VOID TestIoCompletion() { OBJECT_ATTRIBUTES obja; UNICODE_STRING ustr; RtlInitUnicodeString(&ustr, L"\\BaseNamedObjects\\TestCompletion"); InitializeObjectAttributes(&obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL); NtCreateIoCompletion(&hObject, IO_COMPLETION_ALL_ACCESS, &obja, 100); }
/* * @implemented */ HANDLE WINAPI CreateIoCompletionPort(IN HANDLE FileHandle, IN HANDLE ExistingCompletionPort, IN ULONG_PTR CompletionKey, IN DWORD NumberOfConcurrentThreads) { NTSTATUS Status; HANDLE NewPort; FILE_COMPLETION_INFORMATION CompletionInformation; IO_STATUS_BLOCK IoStatusBlock; /* Check if this is a new port */ NewPort = ExistingCompletionPort; if (!ExistingCompletionPort) { /* Create it */ Status = NtCreateIoCompletion(&NewPort, IO_COMPLETION_ALL_ACCESS, NULL, NumberOfConcurrentThreads); if (!NT_SUCCESS(Status)) { /* Convert error and fail */ BaseSetLastNTError(Status); return FALSE; } } /* Check if no actual file is being associated with the completion port */ if (FileHandle == INVALID_HANDLE_VALUE) { /* Was there a port already associated? */ if (ExistingCompletionPort) { /* You are not allowed using an old port and dropping the handle */ NewPort = NULL; BaseSetLastNTError(STATUS_INVALID_PARAMETER); } } else { /* We have a file handle, so associated it with this completion port */ CompletionInformation.Port = NewPort; CompletionInformation.Key = (PVOID)CompletionKey; Status = NtSetInformationFile(FileHandle, &IoStatusBlock, &CompletionInformation, sizeof(FILE_COMPLETION_INFORMATION), FileCompletionInformation); if (!NT_SUCCESS(Status)) { /* Convert the error code and close the newly created port, if any */ BaseSetLastNTError(Status); if (!ExistingCompletionPort) NtClose(NewPort); return FALSE; } } /* Return the newly created port, if any */ return NewPort; }