When will be queued a packet to the I/O completion port ?

Dude… it was warnings, directory change notification, Fast I/O for read and write… I already said, I’m totally lost.

I’m not saying the OP hasn’t found some weird edge condition or a bug in some version of Windows handling of some specific IO function code. Heavens knows there are plenty. I’m just saying I have no clue what he’s talking about. The most unfortunate part is that if he can’t explain it to US, he has almost zero chance of explaining it to MSFT in a bug report and thereby getting it fixed.

Peter

@“Peter_Viscarola_(OSR)” about ZwNotifyChangeDirectoryFile - it return STATUS_DATATYPE_MISALIGNMENT if we not pass the DWORD-aligned buffer . this bit confusing, because this is not NT_ERROR status but will be no IOCP notification here, because error from I/O manager. but we can always avoid this error - pass not DWORD-aligned buffer to this api - programmer error. so i mention this situation in vain - it only distracted from the main problem and confused. problem how i final research only in NtLockFile - compare modern IopXxxControlFile and NtLockFile implementation in my cooment and view different - !NT_ERROR(status)

if (FileObject->CompletionContext && ApcContext &&
        !(FileObject->Flags & FO_SKIP_COMPLETION_PORT) &&
        !NT_ERROR(status))

checked in IopXxxControlFile after FastIo return true, but only

if (FileObject->CompletionContext && ApcContext &&
        !(FileObject->Flags & FO_SKIP_COMPLETION_PORT) )

was checked in NtLockFile

early, before win 8 - this error was and in IopXxxControlFile too

when i look wrk source code, how FastIo handled in NtLockFile and NtDeviceIoControlFile - hard was say - are this bug or “by design”. anyway such “design” break general rule - when will be notification to IOCP, so i and asked general question. but after i view, that code code is changed in NtDeviceIoControlFile - check for NT_ERROR(status) added - i understand that was exactly error in xp/2003 and early here. this error is fixed(in win 8 probably) for NtDeviceIoControlFile but MS forget apply same fix for NtLockFile.

we all understand that you are frustrated by the difficulty in explaining the problem that you are looking at. we are also fusterated by our difficulty in understanding what you are trying to say

what is not clear is whether you expect this issue to apply to all kinds of API calls that might result in IOCP completions, or whether you think this is confined to a specific call pattern

I am almost certian that i can explain the correct behaviour to you, since i had exactly this problem before MSFT resolved the problems with Vista / Server 2008 IIRC. But as Peter says it is possible that you have uncovered a specific case that is a bug / flaw

@MBond2 thank, for response

let me summarize.

response for my question: When will be queued a packet to the I/O completion port ?

// status - returned by asynchronous api call 
// (i.e. NtXxx(HANDLE FileHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,IO_STATUS_BLOCK IoStatusBlock,..)
// bSkipOnSuccess = FileObject->Flags & FO_SKIP_COMPLETION_PORT i.e are we set FILE_SKIP_COMPLETION_PORT_ON_SUCCESS on file

bool Will_be_IOCP_Notification(NTSTATUS status, BOOLEAN bSkipOnSuccess = FALSE)
{
	return (status == STATUS_PENDING) || (!NT_ERROR(status) && !bSkipOnSuccess);
}

I hope there is no objection ?


but i was confused by not fixed bug in NtLockFile and WRK-v1.2 source code. early (including win 7) was bug in IopXxxControlFile too, now fixed

the minimal POC - worked on windows 10

VOID WINAPI IoCompletionNT(
								  _In_    NTSTATUS status,
								  _In_    ULONG_PTR dwNumberOfBytesTransfered,
								  _Inout_ PVOID ApcContext
								  )
{
	WCHAR sz[64];
	swprintf_s(sz, L"(%x %p %p)", status, (void*)dwNumberOfBytesTransfered, ApcContext);
	MessageBoxW(0, sz, L"IoCompletionNT", MB_OK);

	delete ApcContext;
}

void PocLockFile()
{
	static UNICODE_STRING ObjectName = RTL_CONSTANT_STRING(L"\\SystemRoot");
	static OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };

	HANDLE hFile;
	IO_STATUS_BLOCK iosb;

	if (0 <= NtOpenFile(&hFile, FILE_READ_DATA, &oa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE))
	{
		if (0 <= RtlSetIoCompletionCallback(hFile, IoCompletionNT, 0))
		{
			if (IO_STATUS_BLOCK* piosb = new IO_STATUS_BLOCK)
			{
				LARGE_INTEGER ByteOffset{}, Length {1};
				NTSTATUS status = NtLockFile(hFile, 0, 0, piosb, piosb, &ByteOffset, &Length, 'keyX', TRUE, TRUE);
				
				if (!Will_be_IOCP_Notification(status))
				{
					WCHAR sz[64];
					swprintf_s(sz, L"[%x, 0, %p]", status, piosb);
					MessageBoxW(0, sz, L"PocLockFile", MB_OK);
					//delete piosb;
				}
			}
		}
		NtClose(hFile);
	}
}

despite NtLockFile return STATUS_INVALID_PARAMETER here and must not be IOCP notification - it was really

of course call Lock on folder no sense, but show POC. more real case, when we do this on file - https://github.com/rbmm/LockFile-Poc/blob/master/NT_Api_poc.cpp


I mentioned also about ZwNotifyChangeDirectoryFile - which can return STATUS_DATATYPE_MISALIGNMENT (this is not NT_ERROR) but we always must avoid this error, by pass correct aligned buffer

You may have found a bug in this seldom used API

byte range locking is an almost useless feature so it would not be surprising that this is less well tested than other calls

also note that the code you posted has very poor style. At least this SAL is wrong

Inout PVOID ApcContext

@MBond2 - yes, i agree that Inout PVOID ApcContext is bad
but i do copy-paste from minwinbase.h

typedef
VOID
(WINAPI *LPOVERLAPPED_COMPLETION_ROUTINE)(
    _In_    DWORD dwErrorCode,
    _In_    DWORD dwNumberOfBytesTransfered,
    _Inout_ LPOVERLAPPED lpOverlapped
    );

so i take documented callback definition for BindIoCompletionCallback and adjust it for not declared in wdk/sdk headers RtlSetIoCompletionCallback
i do copy-paste and simply not and did not pay attention to SAL here. in this sense Inout LPOVERLAPPED lpOverlapped also wrong - this is in-only pointer to structure. PVOID ApcContext also usual pointer to structure which how minimum containing IO_STATUS_BLOCK. but anyway think SAL here oftopic.

about NtLockFile - yes - this is seldom, but when i first look for wrk source code i decide that same bug exist also in NtDeviceIoControlFile. in case fast io used. this bug here (NtDeviceIoControlFile) really exist yet in windows 7 (tested) but in window 8.1 already fixed

leave SAL and style aside. I mention this for the archives so that someone else won’t copy / paste this code and think it is good

I suggest you open a support case with Microsoft. If they agree that this is a real bug, and it actually has an impact on you, they will likely fix it. It will not be a fast process. Microsoft are still working on an issue I raised in SQL Native Client about 18 months ago - and that is just an unhandled exception leaking from C++ code out through a C API and so does not involve the possibility of breaking changes. your issue does involve the possibility of breaking changes for existing software.