Well, this may do what you want. Use at your own risk, given that it's
undocumented and subject to change (however it's been the same since NT 3.1,
as far as I know).
One other caveat -- NtQueryInformationFile will fail (STATUS_INVALID_HANDLE)
on console handles, as those aren't real file handles (instead something
internal to kernel32/basesrv), so this example would only provide meaningful
results if you had redirected standard file handles.
You would be looking for either of the synchronous I/O flags (difference
being one has the kernel do an alertable wait and one has the kernel do a
nonalertable wait).
If I redirect stdin and stdout but not stderr, this is the output I see:
"File mode is 20
File mode is 20
Error c0000008"
If you aren't linking to ntdll.lib (supplied with the DDK) then you will
need to create your own import library for ntdll or dynamic link to it using
LoadLibrary/GetProcAddress - the SDK supplies no import library for ntdll.
--
#define NTSYSAPI DECLSPEC_IMPORT
#define NTAPI __stdcall
typedef LONG NTSTATUS;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
#if defined(_WIN64)
typedef struct _IO_STATUS_BLOCK32 {
NTSTATUS Status;
ULONG Information;
} IO_STATUS_BLOCK32, *PIO_STATUS_BLOCK32;
#endif
typedef enum _FILE_INFORMATION_CLASS { // Query Set File/Directory
FileModeInformation = 16 // Y Y F
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _FILE_MODE_INFORMATION { // Information Class 16
ULONG Mode;
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
enum {
FILE_SYNCHRONOUS_IO_ALERT = 0x00000010,
FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020
};
// NtQueryInformationFile retrieves information about a file object.
NTSYSAPI
NTSTATUS
NTAPI
NtQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN FILE_INFORMATION_CLASS FileInformationClass
);
VOID ShowFileMode(HANDLE File)
{
IO_STATUS_BLOCK IoStatusBlock;
FILE_MODE_INFORMATION Mode;
NTSTATUS Status;
if(NT_SUCCESS(Status = NtQueryInformationFile(File, &IoStatusBlock, &Mode,
sizeof(FILE_MODE_INFORMATION), FileModeInformation)))
{
wprintf(L"File mode is %lx\n", Mode.Mode);
}
else
{
wprintf(L"Error %lx\n", Status);
}
}
int __cdecl wmain(int ac, wchar_t** av)
{
ShowFileMode((HANDLE)_get_osfhandle(_fileno(stdin)));
ShowFileMode((HANDLE)_get_osfhandle(_fileno(stdout)));
ShowFileMode((HANDLE)_get_osfhandle(_fileno(stderr)));
return 0;
}
Post by rcgaffI realized I had posted a similar question below and received the same
response on using native calls.
This relates to a Linux/Unix application that is being ported to Windows.
There is a pool of Handles of different types that a handler thread must sort
out and handle appropriately. One of the issues is redirected stdin, which
for which Windows opens the file for synchronous I/O, whereas other files in
the pool were opened with Overlapped I/O.
Certainly if this was a new design it would be easy to handle this, but the
fact that we are trying to drop minimally invasive Windows code into an
existing framework limits flexibility.
Thanks for your help!
Bob
--
Bob Gaffaney
Post by SkywingYou have to use native, undocumented system calls to determine this if you
are just handed a handle.
What are you trying to accomplish? There is possibly a better way that
doesn't involve querying this information.
Post by rcgaffThere must be a way to discover, given a handle, if that handle was opened
for Overlapped IO - surely lower level routines have to know this information.
But I can't find any Win32 API to get this information. Any clues?
Bob