1

The WinApi WriteFile() function seems to accept the STD_xxx_HANDLE constants directly as a first argument. I executed the following:

#include <windows.h>
main() {
    DWORD bw;

    WriteFile( (void *)STD_OUTPUT_HANDLE,       "output", 6, &bw, NULL);
    WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), "output", 6, &bw, NULL);

    WriteFile( (void *)STD_ERROR_HANDLE,        "error", 5, &bw, NULL);
    WriteFile( GetStdHandle(STD_ERROR_HANDLE),  "error", 6, &bw, NULL);
}

The above example writes "output" twice to stdout and "error" twice to stderr. I have tested on Win XP and Win 7 (I have no access to WINE or Win 10).

I can see GetStdHandle() does convert the value (from -11 to 7 in the case of STD_OUTPUT_HANDLE), but either value works the same as a WriteFile() input HANDLE.

Is WriteFile implicitly doing GetStdHandle() when it recognizes a STD_xxx_HANDLE constant as its HANDLE input? I have looked but can't find this documented.

Yes I know if it's not documented, don't do it... I'm simply wondering if I missed something.

Paul Houle
  • 735
  • 9
  • 17
  • 1
    yes, `WriteFile` check `hFile` for `STD_ERROR_HANDLE, STD_OUTPUT_HANDLE, STD_INPUT_HANDLE` and convert it by using `GetStdHandle` – RbMm Jul 22 '19 at 00:12
  • 1
    My guess is that this was added to support some automatic sourcecode-rewriting tool... and now kept forever in order to maintain backward-compatibility – Ben Voigt Jul 22 '19 at 00:35
  • Actually, It doesn't make sense to tangle with this. It's considered an invalid handle in other APIs :) – Strive Sun Jul 23 '19 at 10:38

3 Answers3

1

Surprisingly, this works even on Windows 95 RTM and NT 4 (and XP and 8) so it seems like it is on purpose. I can't tell you why nor how far back in NT 3.x this goes.

But it is undocumented and not really part of the ABI so I would suggest that you continue calling GetStdHandle to avoid a nasty surprise in the future.

Anders
  • 97,548
  • 12
  • 110
  • 164
  • Appreciate the additional research. I have come to my senses and shall continue to religiously perform `GetStdHandle()` mapping, unnecessary though it may be. – Paul Houle Jul 23 '19 at 19:14
0

WriteFile expects a handle. The STD_xxx_HANDLE values are not handles. It is not legal to pass those values to WriteFile. You have to convert them to handles by calling GetStdHandle.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
0

Nope, it's treated as pseudohandles, same as GetCurrentProcess() handle.

Try to peek inside KernelBase.dll, It checks the hFile argument if it's equal to STD_X_HANDLE macros.

If yes, the hFile handles turn into NtCurrentPeb()->ProcessParameter->StandardXxx handle.

And there are other functions that recognized STD_XXX_HANDLE macros. GetFiletype , FlushFileBuffers, CloseHandle, and WaitForSingleObject(Ex)also recognize STD_XXX_HANDLE.

Ex-Kyuto
  • 29
  • 5