uLib  User mode C/C++ extended API library for Win32 programmers.
IoUtil.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: I/O utility functions (Migrated from UtilFunc.cpp)
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 
8 #include <uLib/Common.h>
9 #include <uLib/UtilFunc.h>
10 #include <uLib/Debug.h>
11 #include <uLib/StrFunc.h>
12 #ifndef NO_NDK_FILES
13 #include <uLib/NtFunc.h> // GetLdrDllData()
14 #endif
15 #include <uLib/_Internal.h>
16 
17 // TODO: GetFileNameFromHandle() ~ line 830
18 // TODO: GetNtDeviceName() ~ line 990
19 
20 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 // I/O functions
22 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 
24 bool FileExist( CSTR pathName )
25 {
26  DWORD attr = GetFileAttributes( pathName );
27  return (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0);
28 }
29 
30 bool DirExist( CSTR pathName )
31 {
32  DWORD attr = GetFileAttributes( pathName );
33  return (attr != INVALID_FILE_ATTRIBUTES && BITS_SET( FILE_ATTRIBUTE_DIRECTORY, attr ));
34 }
35 
36 //++---------------------------------------------------------------------------
37 
38 bool IsDir( LPWIN32_FIND_DATA pFd )
39 {
40  return (HAVE_BITS( pFd->dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY ));
41 }
42 
43 bool IsSubdirName( CSTR Dir )
44 {
45  if (Dir[0] == DOT)
46  {
47  if (Dir[1] == 0) return false; // "." Current dir
48  // The Dir[2] condition was added to pass ".nitwit" subdirectory names.
49  if (Dir[1] == DOT && Dir[2] == 0) return false; // ".." Parent dir
50  //TRACE( DP_VERBOSE, _F("--> %s\n"), Dir ); // ".dimfuckingunixname" directory detected
51  }
52  return true;
53 }
54 
55 bool IsSubdir( LPWIN32_FIND_DATA pFd )
56 {
57  return IsDir( pFd ) && IsSubdirName( pFd->cFileName );
58 }
59 
60 //++---------------------------------------------------------------------------
61 
62 CSTR GetTempPathName( CSTR Prefix, CSTR dotExt ) // Return full filepath name, with specific ext.
63 {
64  static TCHAR pathname[ MAX_PATH ];
65 
66  UINT ext = UINT( IsString( dotExt ) ? _tcslen( dotExt ) + 1 : 0 );
67  UINT max = dimof(pathname)-14-ext; // Reserve space for GetTempFileName and ext
68  UINT len = GetTempPath( max, pathname );
69  // Single buffer path/name concatenation.
70  UINT rc = GetTempFileName( _T("\\"), Prefix, 0, &pathname[len-1] ); // Direct append
71  if (rc && FileExist( pathname )) DeleteFile( pathname ); // If GetTempFileName created an empty file...
72 
74  TSTR pDot = _tcsrchr( pathname, DOT ); // ".tmp"
75  if (pDot) { if (ext) _tcsecpy( pDot, dotExt ); else *pDot = 0; }
76  else if (ext) _tcscat( pathname, dotExt );
78 
79  return pathname;
80 }
81 
82 //++---------------------------------------------------------------------------
83 
84 bool GetWin32FileData( CSTR PathName, LPWIN32_FIND_DATA pFd )
85 {
86  bool ok = ((pFd != NULL) && IsString( PathName ));
87  if (!ok) SetLastError( ERROR_INVALID_PARAMETER );
88  else {
89  IF_DEBUG( memset( pFd, 0, sizeof(WIN32_FIND_DATA) ));
90  // Now get the WIN32_FIND_DATA.
91  // Note: FindFirstFile doesn't accept a trailing backslash for directories.
92  HANDLE hf = FindFirstFile( WithoutBackslash( PathName ), pFd );
93  ok = (hf != INVALID_HANDLE_VALUE);
94  if (ok) FindClose( hf );
95  }
96  return ok;
97 }
98 
99 //++ SkipNamespacePrefix ++----------------------------------------------------
100 
101 // TEST...
102 // ACSTR pzPath;
103 // pzPath = SkipPathPrefixA( LONG_UNC_PREFIX_A "_Eight" );
104 // pzPath = SkipPathPrefixA( LONG_PATH_PREFIX_A "_Four1" );
105 // pzPath = SkipPathPrefixA( DEVICE_NAME_PREFIX_A "_Four2" );
106 // pzPath = SkipPathPrefixA( UNPARSED_NAME_PREFIX_A "_Four3" );
107 
109 {
110  // With 8-bit chars we can turn this into fast integer comparisons ;)
111 
112  static const EIGHTCC _uncPfx =
113  MK_EIGHTCC( LONG_UNC_PREFIX_A ); // ("\\?\UNC\") Same as "\\?\" but applies to UNC paths.
114  static const FOURCC _knownFcc[3] =
115  {
116  MK_FOURCC( LONG_PATH_PREFIX_A ), // ("\\?\") Disable Win32 name parsing and override the MAX_PATH limit.
117  MK_FOURCC( DEVICE_NAME_PREFIX_A ), // ("\\.\") A device in the Win32 device name space.
118  MK_FOURCC( UNPARSED_NAME_PREFIX_A ), // ("\??\") "Non-parsed" path name (used for symlinks).
119  };
120  union { FOURCC* pfcc; EIGHTCC* pecc; };
121 
122  pfcc = (FOURCC*) PathName;
123  if (*pecc == _uncPfx) PathName += 8;
124  else for( UINT ix = 0; ix < 3; ++ix )
125  if (*pfcc == _knownFcc[ix])
126  {
127  PathName += 4;
128  break;
129  }
130  return PathName;
131 }
132 
134 {
135  #ifdef _UNICODE
136  #define _TraceFmt _F("Skip '%s' prefix --> '%s'\n")
137  #else
138  #define _TraceFmt _F("Skip '%S' prefix --> '%S'\n")
139  #endif
140  struct _pfxRec { CCWSTR Text; WORD Len; }
141  static const knownPfx[] =
142  {
143  { LONG_PATH_PREFIX_W, 4 }, // ("\\?\") Disable Win32 name parsing and override the MAX_PATH limit.
144  { DEVICE_NAME_PREFIX_W, 4 }, // ("\\.\") A device in the Win32 device name space.
145  { UNPARSED_NAME_PREFIX_W, 4 }, // ("\??\") "Non-parsed" path name.
146  { LONG_UNC_PREFIX_W, 8 } // ("\\?\UNC\") Same as "\\?\" but applies to UNC paths.
147  };
148  static const WORD nrPfx = dimof(knownPfx);
149 
150  for( WORD ix = 0; ix < nrPfx; ++ix )
151  if (wcsncmp( PathName, knownPfx[ix].Text, knownPfx[ix].Len ) == 0)
152  {
153  PathName += knownPfx[ix].Len;
154  TRACE( DP_VERBOSE, _TraceFmt, knownPfx[ix].Text, PathName );
155  break;
156  }
157  return PathName;
158  #undef _TraceFmt
159 }
160 
161 //++ GetFileInformationByName ++-----------------------------------------------
162 
163 bool GetFileInformationByName( CSTR FileName, LPBY_HANDLE_FILE_INFORMATION pInfo )
164 {
165  bool ok = false;
166  HANDLE hFile = CheckHandle( CreateFile(
167  FileName, FILE_READ_ATTRIBUTES, FILE_SHARE_ALL, NULL,
168  OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
169  ));
170  if (hFile)
171  {
172  ok = bool_cast( GetFileInformationByHandle( hFile, pInfo ));
173  CloseHandle( hFile );
174  }
175  return ok;
176 }
177 
178 //++ GetVolumeGuidOfShare ++-------------------------------------------------------------
179 
181  IN CSTR ShareName, OUT TSTR VolGuid, WORD ccGuid, OPTOUT TSTR DosDrv, WORD ccDrv )
182 {
183  DWORD error = 0;
184  WCHAR Server[80], Share[80];
185 
186  // Get the volume GUID of a UNC share, suitable for volume mounting.
187 
188  BOOL ok = SplitNetShareName(
189  ShareName, Server, dimof(Server), Share, dimof(Share) );
190  if (ok)
191  {
192  #ifdef _UNICODE
193  #define wzVolGuid VolGuid
194  #else
195  WSTR wzVolGuid = mem_AllocWStr( ccGuid );
196  ok = __ChkOkGetErr( wzVolGuid != NULL, &error );
197  #endif
198  if (ok)
199  {
200  PSHARE_INFO_2 psi = NULL;
201  error = NetShareGetInfo( Server, Share, 2, (PBYTE*)&psi );
202  if (ok = !error) // Assign and check ok after assignment.
203  {
204  #ifdef _UNICODE
205  if (DosDrv) wcsncpyz( DosDrv, psi->shi2_path, ccDrv );
206  #else
207  if (DosDrv) WideCharToMultiByte(
208  CP_ACP,0, psi->shi2_path,-1, DosDrv, ccDrv, NULL, NULL );
209  #endif
210 
211  // TODO: Check that this works with "unmounted" shares as well..
212  // If not, then revise this to work with any defined share.
213 
214  ok = __ChkOkGetErr( GetVolumeNameForVolumeMountPointW(
215  psi->shi2_path, wzVolGuid, ccGuid
216  ), &error );
217  }
218  #ifndef _UNICODE
219  WideCharToMultiByte( CP_ACP,0, wzVolGuid,-1, VolGuid, ccGuid, NULL, NULL );
220  mem_Free( wzVolGuid );
221  #endif
222  if (psi) NetApiBufferFree( psi );
223  }
224  }
225  if (!ok && error) SetLastError( error );
226  return bool_cast( ok );
227 }
228 
229 //++ GetVolumeGuidOfDevice ++------------------------------------------------------------
230 
231 namespace { // Internal callback data
232 struct __gvg_Data {
233  CSTR devName; // in
234  TSTR volGuid, dosDrv; // out
235  WORD ccGuid, ccDrv; // in
236  };
237 } // End internal
238 
239 static bool __gvgmatch_DevMapping( CSTR dosDev, CSTR devName )
240 {
241  TCHAR Mapping[260];
242  DWORD ccRtn = QueryDosDevice( dosDev, Mapping, dimof(Mapping) );
243  return (ccRtn && (_tcsicmp( Mapping, devName ) == 0));
244 }
245 
246 // PS: Don't get cute and try combining these two callbacks,
247 // they have different matching entries..
248 
249 static bool __stdcall __gvgfind_DosVolGuid( TSTR dosDev, PVOID pData )
250 {
251  bool found = false;
252  if (_tcsnicmp( dosDev, _T("Volume"), 6 ) == 0)
253  {
254  __gvg_Data* pd = (__gvg_Data*) pData;
255  found = __gvgmatch_DevMapping( dosDev, pd->devName );
256  if (found) _stprintf_s( pd->volGuid, pd->ccGuid, _T("\\\\?\\%s\\"), dosDev );
257  }
258  return !found;
259 }
260 
261 static bool __stdcall __gvgfind_DosDrive( TSTR dosDev, PVOID pData )
262 {
263  bool found = false;
264  if (dosDev[1] == COLON)
265  {
266  __gvg_Data* pd = (__gvg_Data*) pData;
267  found = __gvgmatch_DevMapping( dosDev, pd->devName );
268  if (found) _stprintf_s( pd->dosDrv, pd->ccDrv, _T("%s\\"), dosDev );
269  }
270  return !found;
271 }
272 
274  IN CSTR DevName, OUT TSTR VolGuid, WORD ccGuid, OPTOUT TSTR DosDrv, WORD ccDrv )
275 {
276  *VolGuid = 0;
277  static const int BufSize = 32*1024;
278  TSTR DevList = mem_AllocStr( BufSize );
279  if (DevList)
280  {
281  DWORD ccDev = QueryDosDevice( NULL, DevList, BufSize ); // The whole device list
282  if (ccDev)
283  {
284  // PONDER: Detect and replace \\.\ prefix in DevName with \Device\ ..?
285 
286  __gvg_Data gvd = { DevName, VolGuid, DosDrv, ccGuid, ccDrv };
287 
288  EnumerateMultiSz( DevList, __gvgfind_DosVolGuid, &gvd );
289  if (!*VolGuid) SetLastError( ERROR_FILE_NOT_FOUND ); //or ERROR_INVALID_NAME ?
290  if (DosDrv) EnumerateMultiSz( DevList, __gvgfind_DosDrive, &gvd );
291  }
292  mem_Free( DevList );
293  }
294  return (*VolGuid != 0);
295 }
296 
297 //++ GetFilePos/SetFilePos ++--------------------------------------------------
298 
299 UINT64 GetFilePos( HANDLE hFile )
300 {
301  LARGE_INTEGER fpos = {{0,0}};
302  fpos.LowPart = SetFilePointer( hFile, 0, &fpos.HighPart, FILE_CURRENT );
303  return fpos.QuadPart;
304 }
305 
306 UINT64 SetFilePos( HANDLE hFile, INT64 Offset, UINT How )
307 {
308  LARGE_INTEGER fpos;
309  fpos.QuadPart = Offset;
310  fpos.LowPart = SetFilePointer( hFile, fpos.LowPart, &fpos.HighPart, How );
311  return fpos.QuadPart;
312 }
313 
314 //++ Seek/Tell ++--------------------------------------------------------------
315 
316 bool Seek( HANDLE hFile, LONG Offs, DWORD How )
317 {
318  return (SetFilePointer( hFile, Offs, NULL, How ) != INVALID_SET_FILE_POINTER);
319 }
320 
321 UINT Tell( HANDLE hFile )
322 {
323  return SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
324 }
325 
326 //++ Get file size as full 64 bit value ++-------------------------------------
327 
328 UINT64 GetFileSize64( HANDLE hFile )
329 {
330  ULARGE_INTEGER fsize;
331  // Symbolic link behavior —> Return the size of the target.
332  fsize.LowPart = GetFileSize( hFile, &fsize.HighPart );
333  return fsize.QuadPart;
334 }
335 
337 {
338  UINT64 size = 0;
339  HANDLE hFile = CheckHandle( CreateFile( FName,
340  FILE_READ_ATTRIBUTES, FILE_SHARE_ALL, NULL, OPEN_EXISTING,
341  FILE_FLAG_BACKUP_SEMANTICS, NULL
342  ));
343  if (hFile)
344  {
345  size = GetFileSize64( hFile );
346  CloseHandle( hFile );
347  }
348  return size;
349 }
350 
351 //++ GetFileSizeByName ++------------------------------------------------------
352 
353 #if (WINVER >= 0x0500) // GetFileAttributesEx arrived in Win2000
355 {
356  ULARGE_INTEGER fsize = {{ 0,0 }};
357  WIN32_FILE_ATTRIBUTE_DATA fa;
358  // Symbolic link behavior —> Return size of the link (0).
359  if (GetFileAttributesEx( FName, GetFileExInfoStandard, &fa ))
360  {
361  fsize.LowPart = fa.nFileSizeLow;
362  fsize.HighPart = fa.nFileSizeHigh;
363  }
364  return fsize.QuadPart;
365 }
366 #else
368 {
369  HANDLE hf;
370  WIN32_FIND_DATA fd;
371  ULARGE_INTEGER fsize = {{ 0,0 }};
372  // Symbolic link behavior —> Return size of the link (0).
373  hf = FindFirstFile( FName, &fd );
374  if (hf) {
375  fsize.LowPart = fd.nFileSizeLow;
376  fsize.HighPart = fd.nFileSizeHigh;
377  FindClose( hf );
378  }
379  return fsize.QuadPart;
380 }
381 #endif //(WINVER >= 0x0500)
382 
383 //++ Open a FS directory ------------------------------------------------------
384 
385 HANDLE OpenDirectory( CSTR DirPath, DWORD Flags )
386 {
387  return CheckHandle( CreateFile(
388  DirPath, GENERIC_RW, FILE_SHARE_RW, NULL,
389  OPEN_EXISTING, Flags | FILE_FLAG_BACKUP_SEMANTICS, NULL
390  ));
391 }
392 
393 //++ IsEndOfFile ++------------------------------------------------------------
394 
395 bool IsEndOfFile( HANDLE hFile )
396 {
397  UINT64 fsize = GetFileSize64( hFile );
398  UINT64 fpos = GetFilePos( hFile );
399  return (fpos >= fsize); // Use >= as a precaution (if FS behaves strange).
400 }
401 
402 //++ PeekFile ++---------------------------------------------------------------
403 
404 UINT PeekFile( HANDLE hFile, PVOID Buf, UINT nBytes )
405 {
406  DWORD cbRd;
407  UINT64 fpos = GetFilePos( hFile );
408  if (DWORD( fpos ) == INVALID_SET_FILE_POINTER && GetLastError() != 0)
409  return 0;
410  if (!ReadFile( hFile, Buf, nBytes, &cbRd, NULL )) cbRd = 0;
411  SetFilePos( hFile, fpos, FILE_BEGIN );
412  return (UINT) cbRd;
413 }
414 
415 //++ BlockRead/BlockWrite ++---------------------------------------------------
416 
417 UINT BlockRead( HANDLE hFile, PVOID Buf, UINT nBytes )
418 {
419  DWORD cbRd;
420  if (!ReadFile( hFile, Buf, nBytes, &cbRd, NULL )) cbRd = 0;
421  return (UINT) cbRd;
422 }
423 UINT BlockWrite( HANDLE hFile, PVOID Buf, UINT nBytes )
424 {
425  DWORD cbWr;
426  if (!WriteFile( hFile, Buf, nBytes, &cbWr, NULL )) cbWr = 0;
427  return (UINT) cbWr;
428 }
429 
430 //++ WriteLine ++--------------------------------------------------------------
431 
432 BOOL WriteLine( HANDLE hFile, CSTR Buf, UINT ccBuf )
433 {
434  DWORD cb;
435  static const TCHAR CrLf[2] = { CR,LF };
436 
437  if (!ccBuf) ccBuf = (UINT)_tcslen( Buf );
438  #ifdef _UNICODE
439  #if 1
440  ccBuf += ccBuf; // We need the byte count, not the string length
441  #else
442  ccBuf *= WCHAR_SIZE; // If or when sizeof(WCHAR) > 2.
443  #endif
444  #endif
445  BOOL ok = WriteFile( hFile, Buf, ccBuf, &cb, NULL );
446  if (ok) ok = WriteFile( hFile, CrLf, sizeof(CrLf), &cb, NULL );
447  return ok;
448 }
449 
450 //++---------------------------------------------------------------------------
451 
452 #if 0 // MEMO - To change behavior of C RTL nnn_s functions...
453 // Simple handler that prints on debugger, and doesn't terminate program.
454 void _dp_InvalidParamHandler(
455  const wchar_t* expression, const wchar_t* function, const wchar_t* file,
456  unsigned int line, uintptr_t _resv
457  )
458 {
459  WCHAR wzBuf[ 512 ];
460  CHAR szBuf[ dimof(wzBuf) ];
461  int len = swprintf( wzBuf, dimof(wzBuf),
462  L"Invalid parameter in function %s."
463  L" File: %s Line: %d\n", function, file, line
464  );
465  WideCharToMultiByte( CP_ACP, 0, wzBuf,len+1, szBuf,dimof(szBuf), NULL, NULL );
466  DPrint( DP_ERROR, szBuf );
467 }
468 _invalid_parameter_handler SetupInvalidParamHandler( bool noAssert )
469 {
470  if (noAssert) _CrtSetReportMode( _CRT_ASSERT, 0 ); // Disable msg box for asserts
471  return _set_invalid_parameter_handler( _dp_InvalidParamHandler );
472 }
473 #endif
474 
475 //++ WriteStr ++---------------------------------------------------------------
476 
477 #define _WRSTR_BUFLEN 512 // Design choice: Same as debugger's buffer size
478 
479 UINT __cdecl WriteStrA( HANDLE hFile, IN const char* Fmt, ... )
480 {
481  char buf[ _WRSTR_BUFLEN ];
482  va_list va;
483  DWORD cbWr;
484 
485  va_start( va, Fmt );
486  int len = vsprintf_s( buf, dimof(buf), Fmt, va );
487  va_end( va );
488  if (!WriteFile( hFile, buf, len, &cbWr, NULL )) cbWr = 0;
489  return cbWr;
490 }
491 
492 UINT __cdecl WriteStrW( HANDLE hFile, const wchar_t* Fmt, ... )
493 {
494  wchar_t buf[ _WRSTR_BUFLEN ];
495  va_list va;
496  DWORD cbWr;
497 
498  va_start( va, Fmt );
499  int len = vswprintf_s( buf, dimof(buf), Fmt, va );
500  va_end( va );
501  if (!WriteFile( hFile, buf, len*sizeof(wchar_t), &cbWr, NULL )) cbWr = 0;
502  else cbWr /= sizeof(wchar_t);
503  return cbWr;
504 }
505 
506 //++ ReadLine ++---------------------------------------------------------------
507 
508 UINT ReadLineA( HANDLE hFile, char* Buffer, UINT BufSize, bool TrimCrLf )
509 {
510  DWORD cbRd;
511  static const char _LF_ = '\n'; // Override global LF (in case of Unicode build).
512  static const char _CR_ = '\r'; // -"- CR
513  UINT len = 0; // Return value
514  DWORD err = 0; // On error
515  LARGE_INTEGER fpos = {{0,0}}; // Remember file position
516 
517  fpos.LowPart = SetFilePointer( hFile, 0, &fpos.HighPart, FILE_CURRENT );
518  if (fpos.LowPart == INVALID_SET_FILE_POINTER) return 0;
519 
520  if (!ReadFile( hFile, Buffer, BufSize, &cbRd, NULL )) {
521  err = GetLastError();
522  // It is not documented whether ReadFile leaves the the file pointer
523  // status quo on all failures, so take the safe road and restore it.
524  // >> SetFilePointer done below!
525  } else {
526  if (cbRd == 0) { // Windows only return EOF as an error if OVERLAPPED!
527  // Make life easier for programmers by translating the EOF condition.
528  Buffer[0] = 0; // Terminate the buffer.
529  err = ERROR_HANDLE_EOF;
530  goto exit_ReadLineA;
531  }
532  Buffer[ cbRd-1 ] = 0; // Terminate the buffer.
533  #ifdef _MBCS // MultiByte build
534  char* end = (char*)_mbschr( (unsigned char*)Buffer, _LF_ );
535  #else
536  char* end = strchr( Buffer, _LF_ );
537  #endif
538  if (!end) {
539  if (IsEndOfFile( hFile )) { // Are we actually at end of file?
540  end = Buffer + cbRd-1;
541  goto readlna_HaveData;
542  } else {
543  err = ERROR_INSUFFICIENT_BUFFER;
544  // Restore file pointer so caller can retry with a bigger buffer.
545  // >> SetFilePointer done below!
546  }
547  } else {
548  *(end+1) = 0; // Terminate after LF. (Safe due to Buffer[cbRd-1] = 0).
549  readlna_HaveData:
550  len = 1 + UINT( end - Buffer ); // Nr of chars incl [CR]LF
551  if (TrimCrLf) {
552  *end-- = 0; // Cut LF
553  if (*end == _CR_) *end = 0; // Cut CR, if any
554  }
555  // Update file pos to next line after CRLF.
556  fpos.QuadPart += len; // SetFilePointer done below!
557  }
558  }
559  SetFilePointer( hFile, fpos.LowPart, &fpos.HighPart, FILE_BEGIN );
560 exit_ReadLineA:
561  if (err) SetLastError( err );
562  return len;
563 }
564 
565 UINT ReadLineW( HANDLE hFile, wchar_t* Buffer, UINT BufLength, bool TrimCrLf )
566 {
567  DWORD cbRd, cchRd, cbBuf;
568  static const wchar_t _LF_ = L'\n'; // Override the global, since this may be a Ansi build.
569  static const wchar_t _CR_ = L'\r'; // -"-
570  UINT len = 0; // Return value
571  DWORD err = 0; // On error
572 
573  LARGE_INTEGER fpos = {{0,0}}; // Remember file position
574  fpos.LowPart = SetFilePointer( hFile, 0, &fpos.HighPart, FILE_CURRENT ); // GetFilePointer
575  if (fpos.LowPart == INVALID_SET_FILE_POINTER) return 0;
576 
577  cbBuf = BufLength * sizeof(wchar_t);
578  if (!ReadFile( hFile, Buffer, cbBuf, &cbRd, NULL )) {
579  err = GetLastError();
580  } else {
581  if (cbRd == 0) {
582  err = ERROR_HANDLE_EOF;
583  Buffer[0] = 0; // Terminate the buffer.
584  goto exit_ReadLineW;
585  }
586  cchRd = cbRd / sizeof(wchar_t);
587  Buffer[ cchRd-1 ] = 0; // Terminate the buffer.
588  wchar_t* end = wcschr( Buffer, _LF_ );
589  if (!end) {
590  if (IsEndOfFile( hFile )) { // Are we actually at end of file?
591  end = Buffer + cchRd-1;
592  goto readlnw_HaveData;
593  } else {
594  err = ERROR_INSUFFICIENT_BUFFER;
595  }
596  } else {
597  *(end+1) = 0; // Terminate after LF. Safe due to Buffer[cbRd-1] = 0.
598  readlnw_HaveData:
599  len = 1 + UINT( end - Buffer ); // Nr of wchars incl CRLF
600  if (TrimCrLf) {
601  *end-- = 0; // Cut LF
602  if (*end == _CR_) *end = 0; // Cut CR, if any
603  }
604  fpos.QuadPart += (len * sizeof(wchar_t)); // Update file pos to next line after CRLF.
605  }
606  }
607  SetFilePointer( hFile, fpos.LowPart, &fpos.HighPart, FILE_BEGIN );
608 exit_ReadLineW:
609  if (err) SetLastError( err );
610  return len;// / sizeof(wchar_t);
611 }
612 
613 //++ GetPathFileName gets a ptr to the filname.ext part of PathName -----------
614 
615 // NOTE: Do not use GetPathFileName for pathnames without a filename part.
616 // If PathName denotes just a directory with no ending BSLASH, you'll get
617 // a pointer to the terminal directory, (if present) which is
618 // probably not what you want.
619 
621 {
622  TSTR fname = PathName ? _tcsrchr( PathName, BSLASH ) : NULL;
623  if (fname) fname++; else fname = PathName;
624  return fname;
625 }
626 
627 //++ GetFullFilePath - Get full path name of the file ++-----------------------
628 
633 
634 // AGH: SearchPath does NOT produce the correct drive char !!
635 
636 //UINT GetFullFilePath( CSTR Name, TSTR pathBuf, UINT bufSize )
637 //{
638 // CSTR pDetail = _tcsrchr( Name, BSLASH );
639 // if (!pDetail) // No backslash, it's a filname only
640 // return SearchPath( NULL, Name, NULL, bufSize, pathBuf, (TSTR*)&pDetail );
641 // else { // The name contains a path spec - Just check file exist
642 // if (!FileExist( Name )) {
643 // SetLastError( ERROR_FILE_NOT_FOUND );
644 // return 0;
645 // }
646 // UINT len = (UINT)_tcslen( Name );
647 // if (len >= bufSize) {
648 // SetLastError( ERROR_INSUFFICIENT_BUFFER );
649 // return 0;
650 // }
651 // _tcsncpyz( pathBuf, Name, dimof(pathBuf) );
652 // return len;
653 // }
654 //}
655 
656 //++ GetFileNameFromHandle ++--------------------------------------------------
657 
658 #if WINVER >= 0x600 // Vista++
659 
660 UINT GetFileNameFromHandle( HANDLE hFile, TSTR Buffer, UINT BufLen )
661 // Alphatest passed
662 {
663  UINT ccName = GetFinalPathNameByHandle( hFile, Buffer, BufLen, VOLUME_NAME_DOS );
664  if (ccName && (BufLen >= ccName))
665  {
666  CSTR pzPath = SkipPathPrefix( Buffer ); // I don't want a leading "\\?\".
667  UINT ccPfix = (UINT) CharIndex( Buffer, pzPath );
668  if (ccPfix)
669  {
670  ccName -= ccPfix;
671  _tcsncpyz( Buffer, pzPath, min_<UINT>( ccName+1, BufLen )); // Remove prefix
672  }
673  Buffer[0] = _totupper( Buffer[0] ); // Upper case drive letter looks better.
674  }
675  return ccName;
676 }
677 
678 #elif !defined( NO_NDK_FILES )
679 
680 // Credits to Mehrdad@stackoverflow.com for pointing out MountPointManager.
681 #include <ddk/MountMgr.h> // Need the MountPointManager here..
682 
684 #pragma warning( disable: 4244 4267 ) // cvt from <larger> to 'USHORT'...
685 
686 UINT GetFileNameFromHandle( HANDLE hFile, TSTR PathName OUT, UINT ccPathName )
687 // Alphatest pending
688 {
689  UINT ccName = 0;
692  {
693  static const USHORT MAX_UNIBUF = (MAX_PATH + 1) * WCHAR_SIZE;
694  // Total buffer size slightly over 2 kB stack space :/
695  BYTE objBuf [ sizeof(OBJECT_NAME_INFORMATION) + MAX_UNIBUF ] = {0}; // OBJECT_NAME_INFORMATION
696  BYTE nameBuf[ sizeof(FILE_NAME_INFORMATION) + MAX_UNIBUF ] = {0}; // FILE_NAME_INFORMATION
697  BYTE trgBuf [ sizeof(MOUNTMGR_TARGET_NAME) + MAX_UNIBUF ] = {0}; // MOUNTMGR_TARGET_NAME
698  BYTE pathBuf[ sizeof(MOUNTMGR_VOLUME_PATHS) + MAX_UNIBUF ] = {0}; // MOUNTMGR_VOLUME_PATHS
699 
700  POBJECT_NAME_INFORMATION objInfo = (POBJECT_NAME_INFORMATION) objBuf;
701  PFILE_NAME_INFORMATION fileInfo = (PFILE_NAME_INFORMATION) nameBuf;
702  PMOUNTMGR_TARGET_NAME trgName = (PMOUNTMGR_TARGET_NAME) trgBuf;
703  PMOUNTMGR_VOLUME_PATHS trgPath = (PMOUNTMGR_VOLUME_PATHS) pathBuf;
704 
705  INIT_PACKED_UNICODE_STRING( &objInfo->Name, sizeof(objBuf) );
706 
707  IO_STATUS_BLOCK ioStat = {0};
708  NTSTATUS rc;
709  ULONG cbData;
710 
711  rc = _NtQueryObject( // Path including disk volume device name.
712  hFile, ObjectNameInformation, objInfo, sizeof(objBuf), &cbData
713  );
714  if (NT_ERROR( rc ))
715  {
717  TRACE( DP_ERROR, _F("NtQueryObject: %s\n"), SysErrorMsg() );
718  }
719  else
720  {
721  rc = _NtQueryInformationFile( // File pathname relative to disk volume.
722  hFile, &ioStat, fileInfo, sizeof(nameBuf), FileNameInformation
723  );
724  if (NT_ERROR( rc ))
725  {
727  TRACE( DP_ERROR, _F("NtQueryInformationFile: %s\n"), SysErrorMsg() );
728  }
729  else if (objInfo->Name.Length <= fileInfo->FileNameLength) // Sanity check
730  {
731  SetLastError( ERROR_INTERNAL_ERROR );
732  TRACE( DP_ERROR, _F("%s. Please contact uLib maintenance.\n"), SysErrorMsg() );
733  }
734  else
735  {
736  trgName->DeviceNameLength = objInfo->Name.Length - fileInfo->FileNameLength;
737  USHORT ccTrg = trgName->DeviceNameLength / WCHAR_SIZE;
738  wcsncpy( trgName->DeviceName, objInfo->Name.Buffer, ccTrg );
739 
740  // PONDER: [MSHDC] "If the user has 'SeChangeNotifyPrivilege'
741  // NtQueryInformationFile returns the full path in all cases."
742  // That would make trgName->DeviceNameLength zero and trgName->DeviceName
743  // blank, which would cause the following code to malfunction...
744  // Hence the ERROR_INTERNAL_ERROR fail-safe above.
745  // TODO: Check if it's true, and if so, FIXME.
746 
747  static CCSTR S_MountMgr = _T("\\\\.\\MountPointManager");
748  HANDLE hMountPointMgr = CheckHandle( CreateFile(
749  S_MountMgr, 0, FILE_SHARE_ALL, NULL, OPEN_EXISTING, 0, NULL
750  ));
751  if (hMountPointMgr)
752  {
753  DWORD cbRtn;
754  BOOL ok = DeviceIoControl(
755  hMountPointMgr, IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
756  trgName, sizeof(trgBuf), trgPath, sizeof(pathBuf),
757  &cbRtn, NULL
758  );
759  TRACE_IF( !ok, DP_ERROR, _F("DeviceIoControl: %s\n"), SysErrorMsg() );
760  if ( ok )
761  {
762  USHORT ccDrv = (trgPath->MultiSzLength / WCHAR_SIZE) - 2; // Exclude 2 NUL chars
763  USHORT ccFile = fileInfo->FileNameLength / WCHAR_SIZE;
764  ccName = ccDrv + ccFile;
765  #ifdef _UNICODE
766  WSTR wzName = wcsnecpy( PathName, trgPath->MultiSz, ccDrv );
767  wcsncpyz( wzName, fileInfo->FileName, ccPathName-ccDrv );
768  #else
769  WideCharToMultiByte( CP_ACP, 0,
770  trgPath->MultiSz, ccDrv, PathName, ccPathName, NULL, NULL
771  );
772  WideCharToMultiByte( CP_ACP, 0,
773  fileInfo->FileName, ccFile, &PathName[ccDrv], ccPathName-ccDrv, NULL, NULL
774  );
775  #endif
776  }
777  CloseHandleEx( hMountPointMgr );
778  }
779  }
780  }
781  }
782  return ccName;
783 }
784 #pragma warning( default: 4244 4267 )
786 
787 #else // WINVER < 0x600 || NO_NDK_FILES // E.g. XP/ReactOS/Wine, or no NDK
788 
789 UINT GetFileNameFromHandle( HANDLE hFile, TSTR Buffer, UINT BufLength )
790 // Alphatest pending
791 {
792  UINT ccPath = 0;
793 
794  // Create a file mapping object and map it
795  // so we can query the name the address belongs to.
796 
797  HANDLE hFileMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
798  if (hFileMap)
799  {
800  PVOID pMem = MapViewOfFile( hFileMap, FILE_MAP_READ, 0, 0, 1 );
801  if (pMem)
802  {
803  // GetMappedFileName returns a /device/ path name from object manager,
804  // e.g. "\Device\HarddiskVolume2\somepath\file.ext", which we translate.
805 
806  if (GetMappedFileName( GetCurrentProcess(), pMem, Buffer, BufLength-1 ))
807  {
808  UINT ccDrvPath = DevicePathToDosPath( Buffer, Buffer, BufLength );
809  ccPath = ccDrvPath ? ccDrvPath : (UINT)_tcslen( Buffer );
810  }
811  UnmapViewOfFile( pMem );
812  }
813  CloseHandle( hFileMap );
814  }
815  return ccPath;
816 }
817 
818 #endif // WINVER < 0x600 || NO_NDK_FILES
819 
820 #ifndef NO_NDK_FILES // Under consideration -- Might migrate to nLib..
821 #ifndef NO_WINTERNAL // UNICODE_STRING
822 //++ GetNtDeviceName ++--------------------------------------------------------
823 
824 // "\Device\Harddisk1" (Harddisk Drive)
825 // "\Device\HarddiskVolume3" (Harddisk Partition)
826 // "\Device\HarddiskVolume3\Temp" (Harddisk Directory)
827 // "\Device\HarddiskVolume3\Temp\transparent.jpeg" (Harddisk File)
828 // "\Device\Harddisk1\DP(1)0-0+6\foto.jpg" (USB stick (Ambiguous))
829 // "\Device\TrueCryptVolumeP\Data\Passwords.txt" (Truecrypt Volume)
830 // "\Device\Floppy0\Autoexec.bat" (Floppy disk)
831 // "\Device\CdRom1\VIDEO_TS\VTS_01_0.VOB" (DVD drive)
832 // "\Device\Serial1" (Real COM port)
833 // "\Device\USBSER000" (Virtual COM port)
834 // "\Device\Mup\ComputerName\C$\Boot.ini" (Network drive share, Windows 7)
835 // "\Device\LanmanRedirector\ComputerName\C$\Boot.ini" (Network drive share, Windwos XP)
836 // "\Device\LanmanRedirector\ComputerName\Shares\Dance.m3u" (Network folder share, Windwos XP)
837 // "\Device\Afd" (Internet socket)
838 // "\Device\Console000F" (Unique name for any Console handle)
839 // "\Device\NamedPipe\Pipename" (Named pipe)
840 // "\BaseNamedObjects\Objectname" (Named mutex, named event, named semaphore)
841 // "\REGISTRY\MACHINE\SOFTWARE\Classes\.txt" (HKEY_CLASSES_ROOT\.txt)
842 
843 #define IsConsoleHandle(h) (( ULONG_PTR(h) & 0x10000003 ) == 0x3 )
844 
845 UINT GetNtDeviceName( HANDLE hObj, TSTR pzNTPath, UINT ccNTPath )
846 // Alphatest ok so far
847 {
848  UINT ccPath = 0;
849  if (pzNTPath) *pzNTPath = 0;
850 
851  if (BAD_HANDLE( hObj )) SetLastError( ERROR_INVALID_HANDLE );
852  else if (!pzNTPath || !ccNTPath) SetLastError( ERROR_INVALID_PARAMETER );
853  else
854  {
855  if (!_NtQueryObject) InitNtFunc();
856 
857  // NtQueryObject() returns STATUS_INVALID_HANDLE for Console handles
858  if (IsConsoleHandle( hObj ))
859  {
860  return _stprintf_s( pzNTPath, ccNTPath, _T("\\Device\\Console%04X"), (DWORD_PTR)hObj );
861  // PONDER: Should this include the \Sessions\x\ component seen on other handles..?
862  }
863 
864  // Native (and kernel) parameters are teeedious.. sigh :/
865  BYTE Buffer[ sizeof(OBJECT_NAME_INFORMATION) + (MAX_PATH+1)*WCHAR_SIZE ];
866  IF_DEBUG( memset( Buffer, 0, sizeof(Buffer) ));
867  POBJECT_NAME_INFORMATION objInfo = (POBJECT_NAME_INFORMATION) Buffer;
868  INIT_PACKED_UNICODE_STRING( &objInfo->Name, sizeof(Buffer) );
869  DWORD cbData = 0;
870 
871  NTSTATUS rc = _NtQueryObject(
872  hObj, ObjectNameInformation, objInfo, sizeof(Buffer), &cbData
873  );
874  if (NT_ERROR( rc )) SetLastErrorFromNtStatus( rc );
875  else if (!objInfo->Name.Length) SetLastError( ERROR_NOT_FOUND );
876  else
877  {
878  ccPath = objInfo->Name.Length / WCHAR_SIZE;
879  objInfo->Name.Buffer[ ccPath ] = 0;
880 
881  #ifdef _UNICODE
882  wcsncpyz( pzNTPath, objInfo->Name.Buffer, ccNTPath );
883  #else
884  WideCharToMultiByte( CP_ACP, 0,
885  objInfo->Name.Buffer, -1, pzNTPath, ccNTPath, NULL, NULL );
886  #endif
887  }
888  }
889  return ccPath;
890 }
891 
892 #endif//ndef NO_WINTERNAL
893 #endif//ndef NO_NDK_FILES
894 
895 #if 1 // PONDER: GetDosNameFromNtDeviceName() could stand an overhaul..
896 // "\Device\HarddiskVolume3" -> "E:"
897 // "\Device\HarddiskVolume3\Temp" -> "E:\Temp"
898 // "\Device\HarddiskVolume3\Temp\transparent.jpeg" -> "E:\Temp\transparent.jpeg"
899 // "\Device\Harddisk1\DP(1)0-0+6\foto.jpg" -> "I:\foto.jpg"
900 // "\Device\TrueCryptVolumeP\Data\Passwords.txt" -> "P:\Data\Passwords.txt"
901 // "\Device\Floppy0\Autoexec.bat" -> "A:\Autoexec.bat"
902 // "\Device\CdRom1\VIDEO_TS\VTS_01_0.VOB" -> "H:\VIDEO_TS\VTS_01_0.VOB"
903 // "\Device\Serial1" -> "COM1"
904 // "\Device\USBSER000" -> "COM4"
905 // "\Device\Mup\ComputerName\C$\Boot.ini" -> "\\ComputerName\C$\Boot.ini"
906 // "\Device\LanmanRedirector\ComputerName\C$\Boot.ini" -> "\\ComputerName\C$\Boot.ini"
907 // "\Device\LanmanRedirector\ComputerName\Shares\Dance.m3u" -> "\\ComputerName\Shares\Dance.m3u"
908 
909 DWORD GetDosNameFromNtDeviceName( CSTR NtName, TSTR DosName, UINT ccDosName )
910 {
911  DWORD err = 0;
912  HKEY hKey;
913  TCHAR szTemp[ MAX_PATH ];
914  TSTR pzCat; // Concatenator
915 
916  if (_tcsnicmp( NtName, _T("\\Device\\Serial"), 14 ) == 0 // e.g. "Serial1"
917  || _tcsnicmp( NtName, _T("\\Device\\UsbSer"), 14 ) == 0) // e.g. "USBSER000"
918  {
919  err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
920  _T("Hardware\\DeviceMap\\SerialComm"),0, KEY_QUERY_VALUE, &hKey );
921  if (!err)
922  {
923  DWORD type, size = sizeof(szTemp);
924  err = RegQueryValueEx( hKey, NtName, 0, &type, (PBYTE)szTemp, &size );
925 
926  if (err) err = ERROR_UNKNOWN_PORT;
927  else _tcsncpyz( DosName, szTemp, ccDosName );
928  RegCloseKey( hKey );
929  }
930  }
931  //"HKLM\HARDWARE\DEVICEMAP\PARALLEL PORTS"
932  //"HKLM\HARDWARE\DEVICEMAP\PARALLEL PORTS\\\Device\Parallel0"
933  else if (_tcsnicmp( NtName, _T("\\Device\\LanmanRedirector\\"), 25 ) == 0) // Win XP
934  {
935  pzCat = _tcsecpy( DosName, _T("\\\\") );
936  _tcsncpyz( pzCat, &NtName[25], ccDosName - 2 );
937  }
938  else if (_tcsnicmp( NtName, _T("\\Device\\Mup\\"), 12 ) == 0) // Win 7
939  {
940  pzCat = _tcsecpy( DosName, _T("\\\\") );
941  _tcsncpyz( pzCat, &NtName[12], ccDosName - 2 );
942  }
943  else
944  {
945  if (!DevicePathToDosPath( NtName, DosName, ccDosName ))
946  {
947  err = GetLastError();
948  // e.g \Device\Harddisk1
949  _tcsncpyz( DosName, NtName, ccDosName );
950  }
951  }
952  return err;
953 }
954 #endif
955 
956 //++ Translate path with device name to absolute path ++-----------------------
957 
958 namespace { // internal
959  struct pfd_Data // internal use with __find_DosDrive.
960  {
961  CSTR pzDev; // in
962  TSTR pzPath; // out
963  UINT ccPath; // in/out
964  bool found; // out
965  };
966 }
967 
969 static bool __stdcall __find_DosDrive( TSTR pzDrv, PVOID pData ) // EnumerateMultiSz
970 {
971  pfd_Data* pd = (pfd_Data*) pData;
972  bool proceed = true;
973  TCHAR szDevice[ MAX_PATH ];
974 
975  // Query the device path of the enumerated DOS drive.
976 
977  UINT ccDevice = QueryDosDevice(
978  WithoutBackslash( pzDrv ), szDevice, dimof(szDevice)
979  );
980  if (ccDevice)
981  {
982  UINT ccCmp = ccDevice - 2; // ccDevice includes *two* NUL chars.
983  CSTR pzSep = &pd->pzDev[ ccCmp ];
984 
985  // Check if the device name matches what we're looking for.
986 
987  if ((*pzSep == BSLASH) && (0 == _tcsnicmp( szDevice, pd->pzDev, ccCmp )))
988  {
989  pd->found = true;
990 
991  // Remove the device name and replace it with the drive letter,
992  // followed by the original file pathname.
993 
994  _tcsncpy( pd->pzPath, pzDrv, 2 ); // "X:"
995  _tcsncpyz( &pd->pzPath[2], pzSep, pd->ccPath - 2 );
996 
997  pd->ccPath = (UINT)_tcslen( pd->pzPath );
998  proceed = false; // Stop enumerating.
999  }
1000  }
1001  return proceed;
1002 }
1004 
1005 // Alphatest passed.
1006 
1007 UINT DevicePathToDosPath( IN CSTR DevPath, OUT TSTR PathBuf, UINT ccPathBuf )
1008 {
1009  UINT ccPath = 0;
1010  TCHAR szDrives[ 128 ] = S_BLANK; // > 26*4
1011 
1012  if (GetLogicalDriveStrings( dimof(szDrives), szDrives ))
1013  {
1014  pfd_Data data = { DevPath, PathBuf, ccPathBuf, false };
1015 
1016  EnumerateMultiSz( szDrives, __find_DosDrive, &data );
1017 
1018  if (data.found) ccPath = data.ccPath;
1019  else SetLastError( ERROR_BAD_PATHNAME );
1020  }
1021  return ccPath;
1022 }
1023 
1024 //++ ChangeDirectory ++--------------------------------------------------------
1025 
1027 {
1028  WORD ccPath = (WORD) GetCurrentDirectory( 0, NULL );
1029  TSTR SaveDir = newStrBuf( ccPath ); // Comply with deleteStr.
1030  if (!SaveDir)
1031  SetLastError( ERROR_OUTOFMEMORY );
1032  else {
1033  BOOL ok = (GetCurrentDirectory( ccPath, SaveDir ) > 0);
1034  if (ok) ok = SetCurrentDirectory( WithBackslash( Dir ));
1035  if (!ok) SaveDir = (TSTR) deleteStr( SaveDir ); // Return NULL to indicate error.
1036  }
1037  return SaveDir;
1038 }
1039 
1041 {
1042  SetCurrentDirectory( oldDir );
1043  return deleteStr( oldDir );
1044 }
1045 
1046 //++ FindMoreFiles ++----------------------------------------------------------
1047 
1048 bool FindMoreFiles( HANDLE hFind, WIN32_FIND_DATA* Found, BYTE nTries, BYTE msWait )
1049 {
1050  UINT nerr = 0;
1051  DWORD err = 0;
1052 try_Find:
1053  if (!FindNextFile( hFind, Found )) {
1054  err = GetLastError();
1055  if (err == ERROR_NO_MORE_FILES) {
1056  done_Files: FindClose( hFind );
1057  if (err) SetLastError( err ); // Re-store error code after closing.
1058  return false;
1059  } else {
1060  DP_StdFailMsg( _T("FindNextFile") );
1061  if (++nerr >= nTries) goto done_Files;
1062  // Allow others a while to finish their work and release the lock.
1063  if (msWait) Sleep( msWait );
1064  goto try_Find;
1065  }
1066  }
1067  return true;
1068 }
1069 
1070 //++ FindCloseEx ++------------------------------------------------------------
1071 
1072 HANDLE FindCloseEx( HANDLE hFind )
1073 {
1074  if (hFind == _BAD_HANDLE) hFind = NULL;
1075  else if (hFind && FindClose( hFind )) hFind = NULL;
1076  return hFind;
1077 }
1078 
1079 #if (WINVER >= 0x0600) // FindFirstStreamW requires Vista.
1080 //++ EnumerateFileStreams ++---------------------------------------------------
1081 
1082 // Alphatest passed: Gives full path from relative input path on current drive.
1083 
1084 UINT EnumerateFileStreams( CSTR FileName, PFnEnumStreams Action, PVOID usrData )
1085 {
1086  UINT nStreams = 0;
1087  WIN32_FIND_STREAM_DATA sd = { 0,0,0 };
1088  static const UINT bufLen = dimof(sd.cStreamName);
1089 
1090  // FindFirstStream/FindNextStream doesn't produce a path name (as was apparently
1091  // intended), so do some value added processing to give the user absolute paths.
1092 
1093  #ifdef _UNICODE
1094  #define wzFile FileName
1095  #else // We need two char conversion buffers, since the APIs are W only.
1096  WSTR wzFile = mem_WDupAStr( FileName, CP_ACP ); // Convert FileName to unicode
1097  TSTR pzStmPath = mem_AllocAStr( bufLen ); // Buffer for the Action call-out
1098  #endif
1099  WSTR wzStmPath = mem_AllocWStr( bufLen ); // Not on stack, for safety's sake.
1100 
1101  // FIXME: GetFullPathName is not good enough for this!
1102  // Use PathIsRelative() to bypass GetFullPathName() when not needed..?
1103 
1104  UINT ccStmPath = GetFullPathNameW( wzFile, MAX_PATH, wzStmPath, NULL );
1105 
1106  UINT ccBufAvail = bufLen - ccStmPath;
1107  WSTR pwzStream = wzStmPath + ccStmPath;
1108  wzStmPath[0] = towupper( wzStmPath[0] ); // Upper case drive letter please..
1109 
1110  HANDLE hStream = CheckHandle( FindFirstStreamW( wzFile, FindStreamInfoStandard, &sd, 0 ));
1111  while( hStream )
1112  {
1113  wcscpy_s( pwzStream, ccBufAvail, sd.cStreamName );
1114  #ifdef _UNICODE
1115  bool proceed = Action( wzStmPath, sd.StreamSize.QuadPart, usrData );
1116  #else
1117  WideCharToMultiByte( CP_ACP, 0, wzStmPath, -1, pzStmPath, bufLen, NULL, NULL );
1118  bool proceed = Action( pzStmPath, sd.StreamSize.QuadPart, usrData );
1119  #endif
1120  ++nStreams;
1121  if (!proceed || !FindNextStreamW( hStream, &sd ))
1122  hStream = FindCloseEx( hStream );
1123  }
1124  mem_Free( wzStmPath );
1125  #ifndef _UNICODE
1126  mem_Free( pzStmPath );
1127  mem_Free( wzFile );
1128  #endif
1129  return nStreams;
1130 }
1131 #endif//(WINVER >= 0x0600)
1132 
1133 //++ LoadAndMapFile ++---------------------------------------------------------
1134 
1135 typedef struct MappedFile* PMappedFile; // HMAPFILE;
1136 struct MappedFile // Internal data struct
1137 {
1138  HANDLE hFile;
1140  HANDLE hMap;
1142  PBYTE pCurr; // 2017 - Used by Peek/Read/WriteMappedFile, et c...
1143 };
1144 
1145 // According to some, it is not necessary to retain the hMap and hFile,
1146 // since the OS will not close those until the last view of it is closed.
1147 // However, my tests showed that the mapping/view fails if the hFile is closed.
1148 // This may be version dependant, and warrant more testing.
1149 // If it's true they can be closed, the brunt of the MappedFile struct can be eliminated.
1150 // LN
1151 
1152 HMAPFILE LoadAndMapFile( CSTR FName, DWORD PageAccess, PBYTE* ppData )
1153 {
1154  DWORD FileAccess, MapAccess, err;
1155  HANDLE hFile, hMap;
1156  PVOID pMap;
1157  UINT64 cbFile;
1158 
1159  PMappedFile pHnd = NULL;
1160  if (ppData) *ppData = NULL;
1161 
1162  #if !ALLOW_EXECUTABLE_FILEMAPPING
1163  // Executable mappings are supported since XP2, but I choose to decline.
1164  // This decision may change in the future (if I or a contributor see fit).
1165 
1166  if (BITS_SET( PAGE_EXECUTE_READ, PageAccess )
1167  || BITS_SET( PAGE_EXECUTE_READWRITE, PageAccess ))
1168  {
1169  err = ERROR_INVALID_PARAMETER;
1170  goto exit_Error; //return NULL;
1171  }
1172  #endif
1173 
1174  FileAccess = GENERIC_READ;
1175  MapAccess = FILE_MAP_READ;
1176 
1177  if (BITS_SET( PAGE_READWRITE, PageAccess )
1178  || BITS_SET( PAGE_WRITECOPY, PageAccess ))
1179  {
1180  FileAccess |= GENERIC_WRITE;
1181  MapAccess |= BITS_SET( PAGE_WRITECOPY, PageAccess ) ? FILE_MAP_COPY : FILE_MAP_WRITE;
1182  }
1183 
1184  // Open the file and map it for reading, et c..
1185 
1186  hFile = CheckHandle( CreateFile(
1187  FName, FileAccess, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL
1188  ));
1189  if (!hFile)
1190  {
1191  err = GetLastError(); // Preserve error code (past the DPrint I/O).
1192  TRACE( DP_ERROR, _F("Can't open '%s': %s\n"), FName, SysErrorMsg( err ));
1193  exit_Error:
1194  SetLastError( err );
1195  goto hmf_Exit; //return NULL;
1196  }
1197  cbFile = GetFileSize64( hFile );
1198 
1199  hMap = CreateFileMapping( hFile, NULL, PageAccess, 0,0, NULL );
1200  if (!hMap)
1201  {
1202  err = GetLastError(); // Preserve error code (past CloseHandle et c..)
1203  TRACE( DP_ERROR, _F("Can't map '%s': %s\n"), FName, SysErrorMsg( err ));
1204  exit_CloseFile:
1205  CloseHandle( hFile );
1206  goto exit_Error;
1207  }
1208 
1209  pMap = MapViewOfFile( hMap, MapAccess, 0,0, 0 );
1210  if (!pMap)
1211  {
1212  err = GetLastError(); // Preserve error code..
1213  TRACE( DP_ERROR, _F("Can't map view of '%s': %s\n"), FName, SysErrorMsg( err ));
1214  CloseHandle( hMap );
1215  goto exit_CloseFile;
1216  }
1217 
1218  // I might consider exposing the handle data at some future time,
1219  // but for now the internal data structure remains opaque.
1220 
1221  pHnd = (PMappedFile) mem_Alloc( sizeof(MappedFile) );
1222  pHnd-> hFile = hFile;
1223  pHnd-> cbFile = cbFile;
1224  pHnd-> hMap = hMap;
1225  pHnd-> pMap = (PBYTE) pMap;
1226  pHnd-> pCurr = (PBYTE) pMap;
1227 
1228  if (ppData) *ppData = (PBYTE) pMap;
1229 
1230 hmf_Exit:
1231  return (HMAPFILE) pHnd; // Return the handle
1232 }
1233 
1235 {
1236  DWORD errCode = 0;
1237  BOOL Ok = (hMap != NULL);
1238  if (!Ok) errCode = ERROR_INVALID_HANDLE;
1239  else
1240  {
1241  PMappedFile pHnd = (PMappedFile) hMap;
1242 
1243  Ok = UnmapViewOfFile( pHnd->pMap );
1244  if (!Ok) errCode = GetLastError();
1245 
1246  pHnd->hMap = CloseHandleEx( pHnd->hMap );
1247  pHnd->hFile = CloseHandleEx( pHnd->hFile );
1248  pHnd = (PMappedFile) mem_Free( pHnd ); // Free the control struct
1249  }
1250  if (errCode) SetLastError( errCode ); // Indicate the primary error
1251  return Ok;
1252 }
1253 
1254 PVOID GetMappedFilePointer( HMAPFILE hMap ) // In case "someone" got sloppy
1255 {
1256  if (hMap) return PMappedFile(hMap)-> pMap;
1257  SetLastError( ERROR_INVALID_HANDLE );
1258  return NULL;
1259 }
1260 
1262 {
1263  if (hMap) return PMappedFile(hMap)-> cbFile;
1264  SetLastError( ERROR_INVALID_HANDLE );
1265  return 0;
1266 }
1267 
1268 // 2017 addendum - Read/Peek/WriteFile facsimiles ...
1269 
1270 size_t PeekMappedFile( HMAPFILE hMapFile, PVOID Buffer, size_t cbRead )
1271 {
1272  if (!cbRead)
1273  SetLastError( ERROR_INVALID_PARAMETER );
1274  else if (!hMapFile) {
1275  SetLastError( ERROR_INVALID_HANDLE );
1276  cbRead = 0;
1277  } else {
1278  PMappedFile pFile = (PMappedFile) hMapFile;
1279  #ifndef HAVE_STRUCTURED_EH
1280  #pragma message("ALERT: PeekMappedFile not using SEH for filemap access.")
1281  memcpy( Buffer, pFile->pCurr, cbRead );
1282  #else
1283  __try { memcpy( Buffer, pFile->pCurr, cbRead ); } // May except..
1285  {
1286  SetLastError( ERROR_READ_FAULT );
1287  cbRead = 0;
1288  }
1289  #endif
1290  }
1291  return cbRead;
1292 }
1293 
1294 size_t ReadMappedFile( HMAPFILE hMapFile, PVOID Buffer, size_t cbRead )
1295 {
1296  cbRead = PeekMappedFile( hMapFile, Buffer, cbRead );
1297  if (cbRead) PMappedFile(hMapFile)->pCurr += cbRead;
1298  return cbRead;
1299 }
1300 
1301 size_t WriteMappedFile( HMAPFILE hMapFile, PVOID Buffer, size_t cbWrite )
1302 {
1303  if (!cbWrite)
1304  SetLastError( ERROR_INVALID_PARAMETER );
1305  else if (!hMapFile) {
1306  SetLastError( ERROR_INVALID_HANDLE );
1307  cbWrite = 0;
1308  } else {
1309  PMappedFile pFile = (PMappedFile) hMapFile;
1310  #ifndef HAVE_STRUCTURED_EH
1311  #pragma message("ALERT: WriteMappedFile not using SEH for filemap access.")
1312  memcpy( pFile->pCurr, Buffer, cbWrite );
1313  pFile->pCurr += cbWrite;
1314  #else
1315  __try
1316  {
1317  memcpy( pFile->pCurr, Buffer, cbWrite ); // May except..
1318  pFile->pCurr += cbWrite; // In which case this is never assigned
1319  }
1321  {
1322  SetLastError( ERROR_WRITE_FAULT );
1323  cbWrite = 0;
1324  }
1325  #endif
1326  }
1327  return cbWrite;
1328 }
1329 
1331 {
1332  PBYTE pData = NULL;
1333  if (hMapFile) pData = PMappedFile(hMapFile)->pCurr;
1334  else SetLastError( ERROR_INVALID_HANDLE );
1335  return pData;
1336 }
1337 
1338 PBYTE SetMappedFilePtr( HMAPFILE hMapFile, INT64 Offset, UINT How )
1339 {
1340  PBYTE pData = NULL; //INVALID_SET_FILE_POINTER;
1341  if (!hMapFile) SetLastError( ERROR_INVALID_HANDLE );
1342  else
1343  {
1344  PMappedFile pFile = (PMappedFile) hMapFile;
1345  INT64 newOffs, fileOffs = (pFile->pCurr - pFile->pMap);
1346 
1347  switch( How )
1348  {
1349  case FILE_BEGIN: newOffs = Offset; break;
1350  case FILE_CURRENT: newOffs = fileOffs + Offset; break;
1351  case FILE_END: newOffs = pFile->cbFile + Offset; break; // NB: Typcally + negative Offset
1352  default:
1353  SetLastError( ERROR_INVALID_PARAMETER );
1354  goto __exit;
1355  }
1356 
1357  if (newOffs < 0 || newOffs > (INT64)pFile->cbFile)
1358  SetLastError( ERROR_SEEK );
1359  else
1360  {
1361  pFile->pCurr = pFile->pMap + newOffs;
1362  pData = pFile->pCurr;
1363  }
1364  }
1365 __exit:
1366  return pData;
1367 }
1368 
1370 {
1371  PBYTE pCurr = GetMappedFilePtr( hMapFile );
1372  return pCurr ? (pCurr - PMappedFile(hMapFile)->pMap) : 0;
1373 }
1374 
1375 UINT64 SetMappedFilePos( HMAPFILE hMapFile, INT64 Offset, UINT How )
1376 {
1377  UINT64 fpos = INVALID_SET_FILE_POINTER;
1378  PBYTE fptr = SetMappedFilePtr( hMapFile, Offset, How );
1379  if (fptr) fpos = (fptr - PMappedFile(hMapFile)->pMap);
1380  return fpos;
1381 }
1382 
1383 // EOF
#define max(a, b)
Definition: Common.h:936
HANDLE CloseHandleEx(HANDLE H)
Definition: KernelUtil.cpp:80
unsigned long DWORD
Definition: Common.h:414
PBYTE SetMappedFilePtr(HMAPFILE hMapFile, INT64 Offset, UINT How)
Definition: IoUtil.cpp:1338
#define DOT
Definition: Common.h:1216
#define HAVE_BITS(var, mask)
Definition: Common.h:1018
HANDLE CheckHandle(HANDLE Hnd)
Definition: KernelUtil.cpp:75
#define FILE_SHARE_RW
Definition: Common.h:1130
PBYTE pMap
Definition: IoUtil.cpp:1141
const char * ACSTR
Definition: Common.h:345
HANDLE OpenDirectory(CSTR DirPath, DWORD Flags)
Definition: IoUtil.cpp:385
DWORD FOURCC
Definition: Common.h:461
bool FindMoreFiles(HANDLE hFind, WIN32_FIND_DATA *Found, BYTE nTries, BYTE msWait)
Definition: IoUtil.cpp:1048
#define CSTR
Definition: Common.h:329
CSTR WithoutBackslash(CSTR PathName)
Definition: StrFunc.cpp:668
CSTR WithBackslash(CSTR PathName)
Definition: StrFunc.cpp:682
PBYTE pCurr
Definition: IoUtil.cpp:1142
#define S_BLANK
Definition: Common.h:1235
unsigned short WORD
Definition: Common.h:413
#define IF_DEBUG(code)
Definition: Debug.h:236
#define INIT_PACKED_UNICODE_STRING(pu, bufsize)
Definition: StrFunc.h:607
bool FileExist(CSTR pathName)
Definition: IoUtil.cpp:24
#define LONG_PATH_PREFIX_A
Definition: UtilFunc.h:2345
#define MK_FOURCC(S4)
Definition: Common.h:466
void * mem_Alloc(size_t Bytes)
Definition: MemFunc.cpp:33
wchar_t * WSTR
Definition: Common.h:366
UINT64 GetFileSize64(HANDLE hFile)
Definition: IoUtil.cpp:328
#define BEGIN_STRSAFE_OVERRIDE
Definition: StrFunc.h:28
#define TSTR
Definition: Common.h:328
unsigned char * PBYTE
Definition: Common.h:412
#define NT_ERROR(Status)
Definition: Common.h:158
UINT BlockWrite(HANDLE hFile, PVOID Buf, UINT nBytes)
Definition: IoUtil.cpp:423
BOOL WriteLine(HANDLE hFile, CSTR Buf, UINT ccBuf)
Definition: IoUtil.cpp:432
#define dimof(x)
Definition: Common.h:949
UINT PeekFile(HANDLE hFile, PVOID Buf, UINT nBytes)
Definition: IoUtil.cpp:404
bool IsSubdirName(CSTR Dir)
Definition: IoUtil.cpp:43
#define OPTOUT
Definition: Common.h:264
void __cdecl DPrint(int Level, CSTR Fmt,...)
Definition: Debug.cpp:134
TSTR newStrBuf(WORD nChar)
Definition: StrFunc.cpp:183
CSTR DoneDirectory(CSTR oldDir)
Definition: IoUtil.cpp:1040
wchar_t *__fastcall wcsncpyz(register wchar_t *Dst, register const wchar_t *Src, size_t Count)
Definition: StrFunc.cpp:142
#define TRACE(_lvl,...)
Definition: Debug.h:216
bool SplitNetShareName(IN CSTR ShareName, OUT WSTR Server, UINT ccServer, OUT WSTR Share, UINT ccShare)
Definition: StrFunc.cpp:634
UINT64 GetFileSize64Ex(CSTR FName)
Definition: IoUtil.cpp:336
WSTR mem_WDupAStr(ACSTR AStr, UINT CodePg=CP_ACP, UINT ccExtra=0)
Definition: StrFunc.cpp:298
size_t PeekMappedFile(HMAPFILE hMapFile, PVOID Buffer, size_t cbRead)
Definition: IoUtil.cpp:1270
HANDLE FindCloseEx(HANDLE hFind)
Definition: IoUtil.cpp:1072
#define EnumerateMultiSz
Definition: StrFunc.h:275
UINT64 GetMappedFilePos(HMAPFILE hMapFile)
Definition: IoUtil.cpp:1369
_NTFN_EXTERN NTSTATUS _NtQueryObject(OPTIN HANDLE Handle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OPTOUT PULONG ReturnLength)
#define LONG_UNC_PREFIX_A
Definition: UtilFunc.h:2346
bool GetFileInformationByName(CSTR FileName, LPBY_HANDLE_FILE_INFORMATION pInfo)
Definition: IoUtil.cpp:163
#define LONG_UNC_PREFIX_W
Definition: UtilFunc.h:2351
#define __except_execute
Definition: Common.h:647
UINT64 SetMappedFilePos(HMAPFILE hMapFile, INT64 Offset, UINT How)
Definition: IoUtil.cpp:1375
HANDLE HMAPFILE
Definition: UtilFunc.h:2732
bool InitNtFunc()
InitNtFunc must be called before any of the NTDLL functions can be used.
Definition: NtFunc.cpp:336
const wchar_t * WCSTR
Definition: Common.h:367
UINT64 cbFile
Definition: IoUtil.cpp:1139
size_t WriteMappedFile(HMAPFILE hMapFile, PVOID Buffer, size_t cbWrite)
Definition: IoUtil.cpp:1301
_NTFN_EXTERN NTSTATUS _NtQueryInformationFile(IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass)
UINT __cdecl WriteStrW(HANDLE hFile, const wchar_t *Fmt,...)
Definition: IoUtil.cpp:492
#define _tcsecpy
Definition: StrFunc.h:74
bool IsEndOfFile(HANDLE hFile)
Definition: IoUtil.cpp:395
UINT ReadLineW(HANDLE hFile, wchar_t *Buffer, UINT BufLength, bool TrimCrLf)
Definition: IoUtil.cpp:565
ASTR mem_AllocAStr(WORD nChar)
Definition: StrFunc.cpp:258
const WCSTR CCWSTR
Definition: Common.h:372
#define TRACE_IF(cond,...)
Definition: Debug.h:227
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
const LPCTSTR CCSTR
Definition: Common.h:335
#define mem_AllocStr
Definition: StrFunc.h:142
#define UNPARSED_NAME_PREFIX_W
Definition: UtilFunc.h:2353
void * mem_Free(void *pBlk)
Definition: MemFunc.cpp:124
#define _BAD_HANDLE
Definition: Common.h:997
QWORD EIGHTCC
Definition: Common.h:470
CSTR GetTempPathName(CSTR Prefix, CSTR dotExt)
Definition: IoUtil.cpp:62
#define LONG_PATH_PREFIX_W
Definition: UtilFunc.h:2350
WSTR mem_AllocWStr(WORD nChar)
Definition: StrFunc.cpp:264
UINT Tell(HANDLE hFile)
Definition: IoUtil.cpp:321
UINT GetNtDeviceName(HANDLE hObj, TSTR pzNTPath, UINT ccNTPath)
Definition: IoUtil.cpp:845
bool(__stdcall * PFnEnumStreams)(CSTR PathName, UINT64 Size, PVOID usrData)
Definition: UtilFunc.h:2667
bool SetLastErrorFromNtStatus(NTSTATUS Status)
Definition: Debug.cpp:74
UINT __cdecl WriteStrA(HANDLE hFile, IN const char *Fmt,...)
Definition: IoUtil.cpp:479
CSTR SysErrorMsg(DWORD Err=0, TSTR Buf=NULL, UINT Length=0)
Definition: Debug.cpp:39
TSTR GetPathFileName(TSTR PathName)
Definition: IoUtil.cpp:620
bool IsDir(LPWIN32_FIND_DATA pFd)
Definition: IoUtil.cpp:38
signed __int64 INT64
Definition: Common.h:401
UINT GetFileNameFromHandle(HANDLE hFile, TSTR Buffer, UINT BufLen)
Definition: IoUtil.cpp:660
#define GENERIC_RW
Definition: Common.h:1128
#define UNPARSED_NAME_PREFIX_A
Definition: UtilFunc.h:2348
unsigned __int64 UINT64
Definition: Common.h:400
#define DEVICE_NAME_PREFIX_A
Definition: UtilFunc.h:2347
PVOID GetMappedFilePointer(HMAPFILE hMap)
Definition: IoUtil.cpp:1254
BOOL UnloadMappedFile(HMAPFILE hMap)
Definition: IoUtil.cpp:1234
bool __forceinline bool_cast(BOOL B52)
Definition: Common.h:767
#define _WRSTR_BUFLEN
Definition: IoUtil.cpp:477
#define DP_ERROR
Definition: Debug.h:82
#define BITS_SET(bits, x)
Definition: Common.h:1016
bool DirExist(CSTR pathName)
Definition: IoUtil.cpp:30
#define CR
Definition: Common.h:1230
UINT EnumerateFileStreams(CSTR FileName, PFnEnumStreams Action, PVOID usrData)
Definition: IoUtil.cpp:1084
UINT ReadLineA(HANDLE hFile, char *Buffer, UINT BufSize, bool TrimCrLf)
Definition: IoUtil.cpp:508
wchar_t *__fastcall wcsnecpy(register wchar_t *Dst, register const wchar_t *Src, size_t N)
Definition: StrFunc.cpp:84
UINT BlockRead(HANDLE hFile, PVOID Buf, UINT nBytes)
Definition: IoUtil.cpp:417
#define FILE_SHARE_ALL
Definition: Common.h:1131
Debug and error handling support.
ACSTR SkipPathPrefixA(ACSTR PathName)
Definition: IoUtil.cpp:108
__inline bool __ChkOkGetErr(BOOL Ok, PDWORD pErr)
Definition: _Internal.h:34
#define COLON
Definition: Common.h:1222
#define DEVICE_NAME_PREFIX_W
Definition: UtilFunc.h:2352
size_t ReadMappedFile(HMAPFILE hMapFile, PVOID Buffer, size_t cbRead)
Definition: IoUtil.cpp:1294
INT_PTR CharIndex(const chrType *Buffer, const chrType *Inside)
Definition: StrFunc.h:93
#define IsConsoleHandle(h)
Definition: IoUtil.cpp:843
DWORD GetDosNameFromNtDeviceName(CSTR NtName, TSTR DosName, UINT ccDosName)
Definition: IoUtil.cpp:909
bool GetVolumeGuidOfDevice(IN CSTR DevName, OUT TSTR VolGuid, WORD ccGuid, OPTOUT TSTR DosDrv, WORD ccDrv)
Definition: IoUtil.cpp:273
#define SkipPathPrefix
Definition: UtilFunc.h:2375
Common include; Added types, small "ubiquitous" utilities, et c.
bool GetWin32FileData(CSTR PathName, LPWIN32_FIND_DATA pFd)
Definition: IoUtil.cpp:84
HMAPFILE LoadAndMapFile(CSTR FName, DWORD PageAccess, PBYTE *ppData)
Definition: IoUtil.cpp:1152
#define BSLASH
Definition: Common.h:1217
#define _TraceFmt
#define _F(s)
Definition: Debug.h:49
UINT64 GetMappedFileSize(HMAPFILE hMap)
Definition: IoUtil.cpp:1261
HANDLE hMap
Definition: IoUtil.cpp:1140
#define BAD_HANDLE(hnd)
Definition: Common.h:1004
bool GetVolumeGuidOfShare(IN CSTR ShareName, OUT TSTR VolGuid, WORD ccGuid, OPTOUT TSTR DosDrv, WORD ccDrv)
Definition: IoUtil.cpp:180
#define WCHAR_SIZE
Definition: Common.h:379
UINT64 GetFilePos(HANDLE hFile)
Definition: IoUtil.cpp:299
CSTR deleteStr(CSTR Dup)
Definition: StrFunc.cpp:191
#define DP_VERBOSE
Definition: Debug.h:86
#define END_STRSAFE_OVERRIDE
Definition: StrFunc.h:29
END_STRSAFE_OVERRIDE UINT DevicePathToDosPath(IN CSTR DevPath, OUT TSTR PathBuf, UINT ccPathBuf)
Definition: IoUtil.cpp:1007
HANDLE hFile
Definition: IoUtil.cpp:1138
UINT64 GetFileSizeByName(CSTR FName)
Definition: IoUtil.cpp:354
bool Seek(HANDLE hFile, LONG Offs, DWORD How)
Definition: IoUtil.cpp:316
#define DP_StdFailMsg(What)
Definition: Debug.h:169
#define LF
Definition: Common.h:1231
CSTR ChangeDirectory(CSTR Dir)
Definition: IoUtil.cpp:1026
unsigned char BYTE
Definition: Common.h:412
bool __forceinline IsString(CSTR Str)
Definition: StrFunc.h:84
PBYTE GetMappedFilePtr(HMAPFILE hMapFile)
Definition: IoUtil.cpp:1330
UINT64 SetFilePos(HANDLE hFile, INT64 Offset, UINT How)
Definition: IoUtil.cpp:306
#define MK_EIGHTCC(S8)
Definition: Common.h:475
#define _tcsncpyz
Definition: StrFunc.h:77
bool IsSubdir(LPWIN32_FIND_DATA pFd)
Definition: IoUtil.cpp:55
WCSTR SkipPathPrefixW(WCSTR PathName)
Definition: IoUtil.cpp:133