ReactOS 0.4.16-dev-715-ga1a169f
stat.cpp
Go to the documentation of this file.
1/***
2*stat64.c - get file status
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* defines _stat64() - get file status
8*
9*******************************************************************************/
10
11#include <ctype.h>
12#include <direct.h>
13#include <errno.h>
14#include <fcntl.h>
18#include <io.h>
19#include <share.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24
25
26
27namespace
28{
30 {
31 typedef int type;
32
33 inline static bool close(_In_ type const fh) throw()
34 {
35 _close(fh);
36 return true;
37 }
38
39 inline static type get_invalid_value() throw()
40 {
41 return -1;
42 }
43 };
44
46 {
47 typedef HANDLE type;
48
49 static bool close(_In_ type const handle) throw()
50 {
51 return ::FindClose(handle) != FALSE;
52 }
53
55 {
57 }
58 };
59
60
61
62 typedef __crt_unique_handle_t<file_handle_traits> scoped_file_handle;
63 typedef __crt_unique_handle_t<find_handle_traits> unique_find_handle;
64}
65
66static bool __cdecl is_slash(wchar_t const c) throw()
67{
68 return c == L'\\' || c == L'/';
69}
70
72{
73 size = 0;
74 _VALIDATE_RETURN_NOEXC(file_info.nFileSizeHigh == 0 && file_info.nFileSizeLow <= LONG_MAX, EOVERFLOW, false);
75
76 size = static_cast<long>(file_info.nFileSizeLow);
77 return true;
78}
79
81{
82 size = 0;
83 _VALIDATE_RETURN_NOEXC(file_info.nFileSizeHigh <= LONG_MAX, EOVERFLOW, false);
84
85 size = static_cast<__int64>(
86 static_cast<unsigned __int64>(file_info.nFileSizeHigh) * 0x100000000ll +
87 static_cast<unsigned __int64>(file_info.nFileSizeLow));
88 return true;
89}
90
91_Success_(return != 0)
92static wchar_t* __cdecl call_wfullpath(
94 wchar_t const* const path,
96 _Inout_ wchar_t** const buffer_result
98{
99 errno_t const saved_errno = errno;
100 errno = 0;
101
102 wchar_t* const result = _wfullpath(buffer, path, buffer_size);
103 if (result != nullptr)
104 {
105 errno = saved_errno;
106 return result;
107 }
108
109 if (errno != ERANGE)
110 return nullptr;
111
112 errno = saved_errno;
113
114 *buffer_result = _wfullpath(nullptr, path, 0);
115 return *buffer_result;
116}
117
118static bool __cdecl has_executable_extension(wchar_t const* const path) throw()
119{
120 if (!path)
121 {
122 return false;
123 }
124
125 wchar_t const* const last_dot = wcsrchr(path, L'.');
126 if (!last_dot)
127 {
128 return false;
129 }
130
131 if (_wcsicmp(last_dot, L".exe") != 0 &&
132 _wcsicmp(last_dot, L".cmd") != 0 &&
133 _wcsicmp(last_dot, L".bat") != 0 &&
134 _wcsicmp(last_dot, L".com") != 0)
135 {
136 return false;
137 }
138
139 return true;
140}
141
142static bool __cdecl is_root_or_empty(wchar_t const* const path) throw()
143{
144 if (!path)
145 {
146 return false;
147 }
148
149 bool const has_drive_letter_and_colon = __ascii_iswalpha(path[0]) && path[1] == L':';
150 wchar_t const* const path_start = has_drive_letter_and_colon
151 ? path + 2
152 : path;
153
154 if (path_start[0] == L'\0')
155 {
156 return true;
157 }
158
159 if (is_slash(path_start[0]) && path_start[1] == L'\0')
160 {
161 return true;
162 }
163
164 return false;
165}
166
167static unsigned short __cdecl convert_to_stat_mode(
168 int const attributes,
169 wchar_t const* const path
170 ) throw()
171{
172 unsigned const os_mode = attributes & 0xff;
173
174 // check to see if this is a directory - note we must make a special
175 // check for the root, which DOS thinks is not a directory:
176 bool const is_directory = (os_mode & FILE_ATTRIBUTE_DIRECTORY) != 0;
177
178 unsigned short stat_mode = is_directory || is_root_or_empty(path)
180 : _S_IFREG;
181
182 // If attribute byte does not have read-only bit, it is read-write:
183 stat_mode |= (os_mode & FILE_ATTRIBUTE_READONLY) != 0
184 ? _S_IREAD
186
187 // See if file appears to be an executable by checking its extension:
189 stat_mode |= _S_IEXEC;
190
191 // propagate user read/write/execute bits to group/other fields:
192 stat_mode |= (stat_mode & 0700) >> 3;
193 stat_mode |= (stat_mode & 0700) >> 6;
194
195 return stat_mode;
196}
197
198// Returns false if and only if the path is invalid.
199static bool __cdecl get_drive_number_from_path(wchar_t const* const path, int& drive_number) throw()
200{
201 drive_number = 0;
202
203 // If path has a drive letter and a colon, return the value of that drive,
204 // as expected from _getdrive(). A = 1, B = 2, etc.
205 // If the path is relative, then use _getdrive() to get the current drive.
206 if (__ascii_iswalpha(path[0]) && path[1] == L':')
207 {
208 // If the path is just a drive letter followed by a colon, it is not a
209 // valid input to the stat functions:
210 if (path[2] == L'\0')
211 {
213 return false;
214 }
215
216 drive_number = __ascii_towlower(path[0]) - L'a' + 1;
217 }
218 else
219 {
221 }
222
223 return true;
224}
225
226static bool __cdecl is_root_unc_name(wchar_t const* const path) throw()
227{
228 // The shortest allowed string is of the form //x/y:
229 if (wcslen(path) < 5)
230 return 0;
231
232 // The string must begin with exactly two consecutive slashes:
233 if (!is_slash(path[0]) || !is_slash(path[1]) || is_slash(path[2]))
234 return 0;
235
236 // Find the slash between the server name and share name:
237 wchar_t const* p = path + 2; // Account for the two slashes
238 while (*++p)
239 {
240 if (is_slash(*p))
241 break;
242 }
243
244 // We reached the end before finding a slash, or the slash is at the end:
245 if (p[0] == L'\0' || p[1] == L'\0')
246 return 0;
247
248 // Is there a further slash?
249 while (*++p)
250 {
251 if (is_slash(*p))
252 break;
253 }
254
255 // Just the final slash (or no final slash):
256 if (p[0] == L'\0' || p[1] == L'\0')
257 return 1;
258
259 return 0;
260}
261
262static bool __cdecl is_usable_drive_or_unc_root(wchar_t const* const path) throw()
263{
264 if (wcspbrk(path, L"./\\") == nullptr)
265 return false;
266
267 wchar_t full_path_buffer[_MAX_PATH];
268 __crt_unique_heap_ptr<wchar_t, __crt_public_free_policy> full_path_pointer;
269 wchar_t* const full_path = call_wfullpath(
270 full_path_buffer,
271 path,
272 _MAX_PATH,
273 full_path_pointer.get_address_of());
274
275 if (full_path == nullptr)
276 return false;
277
278 // Check to see if the path is a root of a directory ("C:\") or a UNC root
279 // directory ("\\server\share\"):
280 if (wcslen(full_path) != 3 && !is_root_unc_name(full_path))
281 return false;
282
283 if (GetDriveTypeW(path) <= 1)
284 return false;
285
286 return true;
287}
288
289template <typename TimeType>
291 FILETIME const file_time,
292 TimeType const fallback_time
293 ) throw()
294{
295 using time_traits = __crt_time_time_t_traits<TimeType>;
296
297 if (file_time.dwLowDateTime == 0 && file_time.dwHighDateTime == 0)
298 {
299 return fallback_time;
300 }
301
302 SYSTEMTIME system_time;
304 if (!FileTimeToSystemTime(&file_time, &system_time) ||
305 !SystemTimeToTzSpecificLocalTime(nullptr, &system_time, &local_time))
306 {
307 // Ignore failures from these APIs, for consistency with the logic below
308 // that ignores failures in the conversion from SYSTEMTIME to time_t.
309 return -1;
310 }
311
312 // If the conversion to time_t fails, it will return -1. We'll use this as
313 // the time_t value instead of failing the entire stat call, to allow callers
314 // to get information about files whose time information is not representable.
315 // (Callers use this API to test for file existence or to get file sizes.)
316 return time_traits::loctotime(
317 local_time.wYear,
318 local_time.wMonth,
319 local_time.wDay,
320 local_time.wHour,
321 local_time.wMinute,
322 local_time.wSecond,
323 -1);
324}
325
326template <typename StatStruct>
328 wchar_t const* const path,
329 StatStruct& result
330 ) throw()
331{
332 using time_traits = __crt_time_time_t_traits<decltype(result.st_mtime)>;
333
335 {
337 return false;
338 }
339
340 // Root directories (such as C:\ or \\server\share\‍) are fabricated:
342 result.st_nlink = 1;
343
344 // Try to get the disk from the name; if there is none, get the current disk:
345 int drive_number{};
347 {
348 return false;
349 }
350
351 result.st_rdev = static_cast<_dev_t>(drive_number - 1);
352 result.st_dev = static_cast<_dev_t>(drive_number - 1); // A=0, B=1, etc.
353
354 result.st_mtime = time_traits::loctotime(1980, 1, 1, 0, 0, 0, -1);
355 result.st_atime = result.st_mtime;
356 result.st_ctime = result.st_mtime;
357 return true;
358}
359
360template <typename StatStruct>
362 wchar_t const* const path,
363 int const fh,
364 HANDLE const handle,
365 StatStruct& result
366 ) throw()
367{
368 using time_type = decltype(result.st_mtime);
369
370 // Figure out what kind of file underlies the file handle:
371 int const file_type = GetFileType(handle) & ~FILE_TYPE_REMOTE;
372
374 {
375 // Okay, it's a disk file; we'll do the normal logic below.
376 }
378 {
379 // We treat pipes and devices similarly: no further information is
380 // available from any API, so we set the fields as reasonably as
381 // possible and return.
382 result.st_mode = file_type == FILE_TYPE_CHAR
383 ? _S_IFCHR
384 : _S_IFIFO;
385
386 result.st_nlink = 1;
387
388 result.st_rdev = static_cast<unsigned>(fh);
389 result.st_dev = static_cast<unsigned>(fh);
390
392 {
393 unsigned long available;
394 if (PeekNamedPipe(handle, nullptr, 0, nullptr, &available, nullptr))
395 {
396 result.st_size = static_cast<_off_t>(available);
397 }
398 }
399
400 return true;
401 }
402 else if (file_type == FILE_TYPE_UNKNOWN)
403 {
404 errno = EBADF;
405 return false;
406 }
407 else
408 {
409 // Per the documentation we should not reach here, but we'll add
410 // this just to be safe:
412 return false;
413 }
414
415 // At this point, we know we have a file on disk. Set the common fields:
416 result.st_nlink = 1;
417
418 if (path)
419 {
420 // Try to get the disk from the name; if there is none, get the current disk:
421 int drive_number{};
423 {
424 return false;
425 }
426
427 result.st_rdev = static_cast<_dev_t>(drive_number - 1);
428 result.st_dev = static_cast<_dev_t>(drive_number - 1); // A=0, B=1, etc.
429 }
430
433 {
435 return false;
436 }
437
438 result.st_mode = convert_to_stat_mode(file_info.dwFileAttributes, path);
439
440 result.st_mtime = convert_filetime_to_time_t(file_info.ftLastWriteTime, static_cast<time_type>(0));
441 result.st_atime = convert_filetime_to_time_t(file_info.ftLastAccessTime, result.st_mtime);
442 result.st_ctime = convert_filetime_to_time_t(file_info.ftCreationTime, result.st_mtime);
443
444 if (!compute_size(file_info, result.st_size))
445 {
446 return false;
447 }
448
449 return true;
450}
451
452template <typename StatStruct>
454 wchar_t const* const path,
455 StatStruct* const result
456 ) throw()
457{
459 *result = StatStruct{};
460
462
463 __crt_unique_handle const file_handle(CreateFileW(
464 path,
467 nullptr,
470 nullptr));
471
472 if (file_handle)
473 {
475 {
476 *result = StatStruct{};
477 return -1;
478 }
479 }
480 else
481 {
483 {
484 *result = StatStruct{};
485 return -1;
486 }
487 }
488
489 return 0;
490}
491
492
493
494template <typename StatStruct>
496 char const* const path,
497 StatStruct* const result
498 ) throw()
499{
500 if (path == nullptr) {
501 return common_stat(static_cast<wchar_t const*>(nullptr), result);
502 }
503
505
507
508 if (cvt != 0) {
509 return -1;
510 }
511
512 return common_stat(wide_path.data(), result);
513}
514
515
516
517extern "C" int __cdecl _stat32(char const* const path, struct _stat32* const result)
518{
519 return common_stat(path, result);
520}
521
522extern "C" int __cdecl _stat32i64(char const* const path, struct _stat32i64* const result)
523{
524 return common_stat(path, result);
525}
526
527extern "C" int __cdecl _stat64(char const* const path, struct _stat64* const result)
528{
529 return common_stat(path, result);
530}
531
532extern "C" int __cdecl _stat64i32(char const* const path, struct _stat64i32* const result)
533{
534 return common_stat(path, result);
535}
536
537extern "C" int __cdecl _wstat32(wchar_t const* const path, struct _stat32* const result)
538{
539 return common_stat(path, result);
540}
541
542extern "C" int __cdecl _wstat32i64(wchar_t const* const path, struct _stat32i64* const result)
543{
544 return common_stat(path, result);
545}
546
547extern "C" int __cdecl _wstat64(wchar_t const* const path, struct _stat64* const result)
548{
549 return common_stat(path, result);
550}
551
552extern "C" int __cdecl _wstat64i32(wchar_t const* const path, struct _stat64i32* const result)
553{
554 return common_stat(path, result);
555}
556
557
558
559template <typename StatStruct>
560static int __cdecl common_fstat(int const fh, StatStruct* const result) throw()
561{
563 *result = StatStruct{};
564
566 _VALIDATE_CLEAR_OSSERR_RETURN(fh >= 0 && fh < _nhandle, EBADF, -1);
568
569 return __acrt_lowio_lock_fh_and_call(fh, [&]()
570 {
571 if ((_osfile(fh) & FOPEN) == 0)
572 {
573 errno = EBADF;
574 _ASSERTE(("Invalid file descriptor. File possibly closed by a different thread",0));
575 return -1;
576 }
577
578 if (!common_stat_handle_file_opened(nullptr, fh, reinterpret_cast<HANDLE>(_osfhnd(fh)), *result))
579 {
580 *result = StatStruct{};
581 return -1;
582 }
583
584 return 0;
585 });
586}
587
588extern "C" int __cdecl _fstat32(int const fh, struct _stat32* const result)
589{
590 return common_fstat(fh, result);
591}
592
593extern "C" int __cdecl _fstat32i64(int const fh, struct _stat32i64* const result)
594{
595 return common_fstat(fh, result);
596}
597
598extern "C" int __cdecl _fstat64(int const fh, struct _stat64* const result)
599{
600 return common_fstat(fh, result);
601}
602
603extern "C" int __cdecl _fstat64i32(int const fh, struct _stat64i32* const result)
604{
605 return common_fstat(fh, result);
606}
#define EINVAL
Definition: acclib.h:90
#define ERANGE
Definition: acclib.h:92
#define EBADF
Definition: acclib.h:82
#define __cdecl
Definition: accygwin.h:79
#define __int64
Definition: basetyps.h:16
#define _CHECK_FH_CLEAR_OSSERR_RETURN(handle, errorcode, retexpr)
void __cdecl __acrt_errno_map_os_error(unsigned long)
Definition: errno.cpp:91
#define _osfhnd(i)
int _nhandle
Definition: ioinit.cpp:34
auto __acrt_lowio_lock_fh_and_call(int const fh, Action &&action) -> decltype(action())
errno_t __acrt_mbs_to_wcs_cp(char const *const null_terminated_input_string, __crt_win32_buffer< wchar_t, ResizePolicy > &win32_buffer, unsigned int const code_page)
unsigned int __acrt_get_utf8_acp_compatibility_codepage()
#define _ASSERTE(expr)
Definition: crtdbg.h:114
_Check_return_ _CRTIMP int __cdecl _getdrive(void)
Definition: getdrive.c:20
result_buffer_count char *const _In_ int const _In_ bool const _In_ unsigned const _In_ STRFLT const _In_ bool const _Inout_ __crt_cached_ptd_host &ptd throw()
Definition: cvt.cpp:119
#define FALSE
Definition: types.h:117
#define _S_IWRITE
Definition: cabinet.h:33
#define _S_IREAD
Definition: cabinet.h:34
static WCHAR available[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2336
#define wcsrchr
Definition: compat.h:16
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
static DOUBLE local_time(DOUBLE time, DateInstance *date)
Definition: date.c:351
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
Definition: fileinfo.c:458
DWORD WINAPI GetFileType(HANDLE hFile)
Definition: fileinfo.c:269
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation, CONST SYSTEMTIME *lpUniversalTime, LPSYSTEMTIME lpLocalTime)
Definition: timezone.c:377
#define EOVERFLOW
Definition: errno.h:82
static char * cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag)
Definition: fcvtbuf.c:45
#define FOPEN
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
long _off_t
Definition: stdio.h:73
_Check_return_ _CRTIMP wchar_t *__cdecl _wfullpath(_Out_writes_opt_z_(_SizeInWords) wchar_t *_FullPath, _In_z_ const wchar_t *_Path, _In_ size_t _SizeInWords)
#define _S_IFCHR
Definition: stat.h:135
#define _S_IFREG
Definition: stat.h:137
#define _S_IFDIR
Definition: stat.h:134
#define _S_IEXEC
Definition: stat.h:140
#define _fstat64i32
Definition: stat.h:269
#define _S_IFIFO
Definition: stat.h:136
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
__forceinline int __CRTDECL __ascii_iswalpha(int const _C)
Definition: ctype.h:170
__forceinline int __CRTDECL __ascii_towlower(int const _C)
Definition: ctype.h:180
#define _VALIDATE_CLEAR_OSSERR_RETURN(expr, errorcode, retexpr)
#define _VALIDATE_RETURN_NOEXC(expr, errorcode, retexpr)
#define LONG_MAX
Definition: intsafe.h:154
__u8 drive_number
Definition: mkdosfs.c:0
#define _MAX_PATH
Definition: utility.h:77
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
__crt_unique_handle_t< file_handle_traits > scoped_file_handle
Definition: stat.cpp:62
__crt_unique_handle_t< find_handle_traits > unique_find_handle
Definition: stat.cpp:63
#define _Out_writes_z_(s)
Definition: no_sal2.h:180
#define _Inout_
Definition: no_sal2.h:162
#define _Success_(c)
Definition: no_sal2.h:84
#define _In_
Definition: no_sal2.h:158
BOOL WINAPI PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage)
Definition: npipe.c:1214
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define L(x)
Definition: ntvdm.h:50
static FILE * file_handle
Definition: regtests2xml.c:45
#define errno
Definition: errno.h:18
_Check_return_opt_ _CRTIMP int __cdecl _close(_In_ int _FileHandle)
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcspbrk(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
unsigned int _dev_t
Definition: types.h:25
#define _osfile(i)
Definition: internal.h:72
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
static bool __cdecl is_slash(wchar_t const c)
Definition: stat.cpp:66
static bool __cdecl is_root_unc_name(wchar_t const *const path)
Definition: stat.cpp:226
static bool __cdecl get_drive_number_from_path(wchar_t const *const path, int &drive_number)
Definition: stat.cpp:199
int __cdecl _fstat64(int const fh, struct _stat64 *const result)
Definition: stat.cpp:598
static bool __cdecl has_executable_extension(wchar_t const *const path)
Definition: stat.cpp:118
static bool __cdecl is_root_or_empty(wchar_t const *const path)
Definition: stat.cpp:142
static bool __cdecl common_stat_handle_file_opened(wchar_t const *const path, int const fh, HANDLE const handle, StatStruct &result)
Definition: stat.cpp:361
static TimeType __cdecl convert_filetime_to_time_t(FILETIME const file_time, TimeType const fallback_time)
Definition: stat.cpp:290
int __cdecl _wstat64(wchar_t const *const path, struct _stat64 *const result)
Definition: stat.cpp:547
static int __cdecl common_stat(wchar_t const *const path, StatStruct *const result)
Definition: stat.cpp:453
wchar_t const *const size_t const buffer_size
Definition: stat.cpp:95
int __cdecl _fstat32i64(int const fh, struct _stat32i64 *const result)
Definition: stat.cpp:593
int __cdecl _wstat64i32(wchar_t const *const path, struct _stat64i32 *const result)
Definition: stat.cpp:552
wchar_t const *const size_t const _Inout_ wchar_t **const buffer_result throw()
Definition: stat.cpp:97
static int __cdecl common_fstat(int const fh, StatStruct *const result)
Definition: stat.cpp:560
static bool __cdecl is_usable_drive_or_unc_root(wchar_t const *const path)
Definition: stat.cpp:262
static bool __cdecl compute_size(BY_HANDLE_FILE_INFORMATION const &file_info, long &size)
Definition: stat.cpp:71
int __cdecl _wstat32i64(wchar_t const *const path, struct _stat32i64 *const result)
Definition: stat.cpp:542
static bool __cdecl common_stat_handle_file_not_opened(wchar_t const *const path, StatStruct &result)
Definition: stat.cpp:327
static unsigned short __cdecl convert_to_stat_mode(int const attributes, wchar_t const *const path)
Definition: stat.cpp:167
int __cdecl _fstat32(int const fh, struct _stat32 *const result)
Definition: stat.cpp:588
int __cdecl _wstat32(wchar_t const *const path, struct _stat32 *const result)
Definition: stat.cpp:537
wchar_t const *const path
Definition: stat.cpp:94
Definition: stat.h:26
Definition: stat.h:70
static bool close(_In_ type const fh)
Definition: stat.cpp:33
static bool close(_In_ type const handle)
Definition: stat.cpp:49
int errno_t
Definition: corecrt.h:615
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FILE_TYPE_UNKNOWN
Definition: winbase.h:284
#define FILE_TYPE_CHAR
Definition: winbase.h:286
#define FILE_TYPE_PIPE
Definition: winbase.h:287
#define FILE_TYPE_DISK
Definition: winbase.h:285
#define const
Definition: zconf.h:233