Hey Dmitry,
I noticed a couple of tests structured like this:
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL); ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* see below */, "expected STATUS_PENDING, got %#x\n", status); ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status); ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information); ... ret = WaitForSingleObject(hfile, 3000);
Technically, the IO_STATUS_BLOCK (hence also the OVERLAPPED) structure is only filled once the I/O Manager completes the read/write IRP -- meaning its contents should only be read _after_ the wait.
So this aspect essentially tests the question of "are ntfs.sys and the cache manager faster to fill the IOSB than the test can read it". That test can be completely valid, especially if it's known that applications do this, however I'm not sure whether that's actually the intention here. (My preference would obviously -- hence this mail -- be to read the result after waiting unless there's a specific reason to do it otherwise. The specifics are kind of up to the FS driver.)
Thanks! -Thomas
Thomas Faber thfabba@gmx.de wrote:
I noticed a couple of tests structured like this:
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL); ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* see below */, "expected STATUS_PENDING, got %#x\n", status); ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status); ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information); ... ret = WaitForSingleObject(hfile, 3000);
Technically, the IO_STATUS_BLOCK (hence also the OVERLAPPED) structure is only filled once the I/O Manager completes the read/write IRP -- meaning its contents should only be read _after_ the wait.
Contents of IO_STATUS_BLOCK/OVERLAPPED are tested only in the cases known to not contain STATUS_PENDING of a being executed operation, which means that the operation has already finished and waiting would return immediately and therefore is not necessary and redundant.
On 2013-09-18 11:31, Dmitry Timoshkov wrote:
Thomas Faber thfabba@gmx.de wrote:
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL); ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* see below */, "expected STATUS_PENDING, got %#x\n", status); ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status); ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information); ... ret = WaitForSingleObject(hfile, 3000);
Technically, the IO_STATUS_BLOCK (hence also the OVERLAPPED) structure is only filled once the I/O Manager completes the read/write IRP -- meaning its contents should only be read _after_ the wait.
Contents of IO_STATUS_BLOCK/OVERLAPPED are tested only in the cases known to not contain STATUS_PENDING of a being executed operation, which means that the operation has already finished and waiting would return immediately and therefore is not necessary and redundant.
Hmm maybe I'm misunderstanding what you're saying, sorry... but I thought the snippet above was a counter-example. It's a pretty straightforward write that's expected to succeed (asynchronously), and it verifies that STATUS_PENDING is returned, but then immediately reads iob.
It's from line 2213ff. The ones at 2364 and 2381 look similar, there might be more.
Am I missing some aspect of the test that makes it different from "simple async write should always return pending"?
Thanks, Thomas