void UnBindSocketIOCP(SOCKET sk)
{
/*反编译CreateIoCompletionPort 得知,用NtSetInformationFile可以
FileInformation.hIocp = (int)IoCompletionHandle;
FileInformation.nCompKey = CompletionKey;
nRet = NtSetInformationFile(FileHandle, &IoStatusBlock, &FileInformation, 8u, FileCompletionInformation);
if ( nRet >= 0 )
return IoCompletionHandle;
BaseSetLastNTError(nRet);
微软说的FILE_COMPLETION_INFORMATION结构用于替换端口中端口句柄集的完成信息。
完成信息将替换为 ZwSetInformationFile 例程,
并将 FileInformationClass 参数设置为 FileReplaceCompletionInformation。
FILE_COMPLETION_INFORMATION的端口和键成员设置为其新值。 若要删除文件句柄的现有完成端口,
请将 port 设置为 NULL。
此结构可从 Windows 8.1 开始使用。
*/
MY_IO_STATUS_BLOCK IoStatusBlock = {};
MY_FILE_COMPLETION_INFORMATION FileInformation = {};
FileInformation.Port = (HANDLE)NULL;
FileInformation.Key = 0;
const int _FileCompletionInformation = 30;
const int _FileReplaceCompletionInformation = 61;
LONG nRet = My_NtSetInformationFile((HANDLE)sk, &IoStatusBlock, &FileInformation, sizeof(FileInformation), _FileReplaceCompletionInformation);
Debug_ViewA("nRet=%x", nRet);
}
[注意]Win7 XP 调用这个方法nRet=0xC0000003
C0000003 STATUS_INVALID_INFO_CLASS
关于为什么要取消iocp绑定的原因:比如原accept socket 采用了iocp方式,而后续需要进行传递给其他的框架使用,而那个框架可能不是基于iocp的方式,那么就遇到此问题
解决这个问题当然是取消iocp最有效,如果无法取消iocp 就利用Overlapped结构中增加一些特殊标记来从原来的框架中再次分离socket
如果非要在xp上取消iocp ,可以自己写驱动来做这件事
else if (FileInformationClass == FileCompletionInformation) {
PFILE_COMPLETION_INFORMATION completion = irp->AssociatedIrp.SystemBuffer;
PIO_COMPLETION_CONTEXT context;
PVOID portObject;
//
// It is an error if this file object already has an LPC port associated
// with it.
//
if (fileObject->CompletionContext || fileObject->Flags & FO_SYNCHRONOUS_IO) {
status = STATUS_INVALID_PARAMETER;
} else {
//
// Attempt to reference the port object by its handle and convert it
// into a pointer to the port object itself.
//
status = ObReferenceObjectByHandle( completion->Port,
IO_COMPLETION_MODIFY_STATE,
IoCompletionObjectType,
requestorMode,
(PVOID *) &portObject,
NULL );
if (NT_SUCCESS( status )) {
//
// Allocate the memory to be associated w/this file object
//
context = ExAllocatePoolWithTag( PagedPool,
sizeof( IO_COMPLETION_CONTEXT ),
'cCoI' );
if (!context) {
ObDereferenceObject( portObject );
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
//
// Everything was successful. Capture the completion port
// and the key.
//
context->Port = portObject;
context->Key = completion->Key;
if (!InterlockedCompareExchangePointer( &fileObject->CompletionContext, context, NULL )) {
status = STATUS_SUCCESS;
} else {
//
// Someone set the completion context after the check.
// Simply drop everything on the floor and return an
// error.
//
ExFreePool( context );
ObDereferenceObject( portObject );
status = STATUS_INVALID_PARAMETER;
}
}
}
}