kernel32!GetQueuedCompletionStatus函数分析之返回值得有效性

第一部分://#define STATUS_SUCCESS 0x0返回值为0

} else {

//

// Set the completion status, capture the completion

// information, deallocate the associated IRP, and

// attempt to write the completion information.

//

Status = STATUS_SUCCESS ; //#define STATUS_SUCCESS 0x0返回值为0

try {

MiniPacket = CONTAINING_RECORD(Entry,

IOP_MINI_COMPLETION_PACKET,

ListEntry);

if ( MiniPacket->PacketType == IopCompletionPacketIrp ) {

Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);

LocalApcContext = Irp->Overlay.AsynchronousParameters.UserApcContext;

LocalKeyContext = (PVOID)Irp->Tail.CompletionKey;

LocalIoStatusBlock = Irp->IoStatus;

IoFreeIrp(Irp);

} else {

LocalApcContext = MiniPacket->ApcContext;

LocalKeyContext = (PVOID)MiniPacket->KeyContext;

LocalIoStatusBlock.Status = MiniPacket->IoStatus;

LocalIoStatusBlock.Information = MiniPacket->IoStatusInformation;

IopFreeMiniPacket(MiniPacket);

}

*ApcContext = LocalApcContext;

*KeyContext = LocalKeyContext;

*IoStatusBlock = LocalIoStatusBlock;

} except(ExSystemExceptionFilter ()) {

NOTHING;

}

}

//

// Deference I/O completion object.

//

ObDereferenceObject(IoCompletion);

}

//

// If an exception occurs during the probe of the previous count, then

// always handle the exception and return the exception code as the status

// value.

//

} except(ExSystemExceptionFilter()) {

Status = GetExceptionCode();

}

//

// Return service status.

//

return Status ;

}

第二部分:

BOOL

WINAPI

GetQueuedCompletionStatus(

HANDLE CompletionPort,

LPDWORD lpNumberOfBytesTransferred,

PULONG_PTR lpCompletionKey,

LPOVERLAPPED *lpOverlapped,

DWORD dwMilliseconds

)

{

LARGE_INTEGER TimeOut;

PLARGE_INTEGER pTimeOut;

IO_STATUS_BLOCK IoSb;

NTSTATUS Status;

LPOVERLAPPED LocalOverlapped;

BOOL rv;

pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);

Status = NtRemoveIoCompletion(

CompletionPort,

(PVOID *)lpCompletionKey,

(PVOID *)&LocalOverlapped,

&IoSb,

pTimeOut

);

if ( !NT_SUCCESS(Status) || Status == STATUS_TIMEOUT ) {

*lpOverlapped = NULL;

if ( Status == STATUS_TIMEOUT ) {

SetLastError(WAIT_TIMEOUT);

}

else {

BaseSetLastNTError(Status);

}

rv = FALSE;

}

else {

*lpOverlapped = LocalOverlapped; //lpOverlapped 有非0值

*lpNumberOfBytesTransferred = (DWORD)IoSb.Information;

if ( !NT_SUCCESS(IoSb.Status) ){

BaseSetLastNTError( IoSb.Status );

rv = FALSE;

}

else {

rv = TRUE; //成功。返回1!!!

}

}

return rv;

}

第三部分:

参考:

1: kd> kc

00 nt!NtRemoveIoCompletion

01 nt!_KiSystemService

02 SharedUserData!SystemCallStub

03 ntdll!ZwRemoveIoCompletion

04 kernel32!GetQueuedCompletionStatus

05 RPCRT4!COMMON_ProcessCalls

06 RPCRT4!LOADABLE_TRANSPORT::ProcessIOEvents

07 RPCRT4!ProcessIOEventsWrapper

08 RPCRT4!BaseCachedThreadRoutine

09 RPCRT4!ThreadStartRoutine

0a kernel32!BaseThreadStart

1: kd> p

Breakpoint 40 hit

RPCRT4!COMMON_ProcessCalls+0xe9:

001b:77c66f8d 85c0 test eax,eax

1: kd> r

eax=00000001 ebx=77e47889 ecx=00000000 edx=7ffe0304 esi=77be9fc4 edi=77f6a8dc

eip=77c66f8d esp=00acfef0 ebp=00acff18 iopl=0 nv up ei pl nz na po nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202

RPCRT4!COMMON_ProcessCalls+0xe9:

001b:77c66f8d 85c0 test eax,eax

1: kd> dv

b = 0n1

lpOverlapped = 0x00b002b8

第一种情况:都为0

if (!b && !lpOverlapped)

{

// If lpOverlapped is NULL this mean no IO completed.

第二种情况:b为0,lpOverlapped)不为0。调用GetLastError();,前面有BaseSetLastNTError( IoSb.Status );

if (!b)

{

pBaseOverlapped = FindOverlapped(lpOverlapped);

pRequest = FindRequest(lpOverlapped);

LastError = GetLastError();

第三种情况:成功,有数据完成了。

// here we actually have a completed IO

pBaseOverlapped = FindOverlapped(lpOverlapped);

pRequest = FindRequest(lpOverlapped);