uLib  User mode C/C++ extended API library for Win32 programmers.
KernelUtil.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: Kernel32 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> // GetProcDllData()
14 #endif
15 #ifdef __cplusplus // FILETIME comparators...
16 #include <uLib/LargeInt.h>
17 #endif
18 
19 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 // Kernel32 functions
21 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 
23 UINT GlobalPurgeAtom( CSTR Name )
24 {
25  ATOM A; UINT N = 0;
26 
27  while( 0 != (A = GlobalFindAtom( Name ))) {
28  GlobalDeleteAtom( A );
29  N++;
30  }
31  return N;
32 }
33 
34 // Retrieve the name of an atom
35 
36 CSTR GlobalAtomName( ATOM Atom )
37 {
38  static TCHAR buf[ 80 ];
39  if (!GlobalGetAtomName( Atom, buf, dimof(buf) )) buf[0] = 0;
40  return buf;
41 }
42 
43 CSTR LocalAtomName( ATOM Atom )
44 {
45  static TCHAR buf[ 80 ];
46  if (!GetAtomName( Atom, buf, dimof(buf) )) buf[0] = 0;
47  return buf;
48 }
49 
50 //-----------------------------------------------------------------------------
51 // Get real handles for current process and thread.
52 //-----------------------------------------------------------------------------
53 
55 {
56  HANDLE hThread = GetCurrentThread(), hProc = GetCurrentProcess(); // Pseudo
57  // Get a real handle to the thread.
58  DuplicateHandle( hProc, hThread, hProc, &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS );
59  return hThread;
60 }
61 
63 {
64  HANDLE hProc = GetCurrentProcess(); // Pseudo handle
65  // Get a real handle to the process.
66  DuplicateHandle( hProc, hProc, hProc, &hProc, 0, FALSE, DUPLICATE_SAME_ACCESS );
67  return hProc;
68 }
69 
70 //-----------------------------------------------------------------------------
71 // Hnd = CheckHandle( CreateFile( ... ));
72 // Hnd = CloseHandleEx( Hnd );
73 //-----------------------------------------------------------------------------
74 
75 HANDLE CheckHandle( HANDLE Hnd )
76 {
77  return BAD_HANDLE( Hnd ) ? NULL : Hnd;
78 }
79 
80 HANDLE CloseHandleEx( HANDLE Hnd )
81 {
82  if (Hnd == INVALID_HANDLE_VALUE) Hnd = NULL;
83  else if (Hnd != NULL)
84  {
85  #ifdef HAVE_STRUCTURED_EH
86  __try { if (CloseHandle( Hnd )) Hnd = NULL; }
87  __except_execute { Hnd = NULL; }
88  #else
89  if (CloseHandle( Hnd )) Hnd = NULL;
90  #endif
91  }
92  return Hnd;
93 }
94 
95 bool WaitFor( HANDLE hObj, DWORD msWait )
96 {
97  DWORD rc = WaitForSingleObjectEx( hObj, msWait, true );
98  bool ok = (rc == WAIT_OBJECT_0);
99  if (!ok) SetLastError( rc );
100  return ok;
101 }
102 
103 //-----------------------------------------------------------------------------
104 // Additional global heap functions (add-on to the WindowsX macros)
105 // Mostly useful for clipboard operations and DDE.
106 //-----------------------------------------------------------------------------
107 
108 ASTR GlobalAllocStrA( UINT Count )
109 {
110  return (ASTR) GlobalAllocPtr( GHND, Count ); // NOTA BENE: GHND (movable).
111 }
112 WSTR GlobalAllocStrW( UINT Count )
113 {
114  return (WSTR) GlobalAllocPtr( GHND, Count * WCHAR_SIZE );
115 }
116 
118 
119 ASTR GlobalDupStrA( ACSTR Str, bool isMulti )
120 {
121  ASTR pDup = NULL;
122  if (Str)
123  {
124  UINT Len = isMulti ? MultiSzLengthA( Str ) : UINT( 1+strlen( Str ));
125  pDup = GlobalAllocStrA( Len );
126  if (pDup) memcpy( pDup, Str, Len );
127  }
128  return pDup;
129 }
130 //ASTR GlobalDupStrA( ACSTR Str )
131 //{
132 // ASTR pDup = NULL;
133 // if (Str)
134 // {
135 // UINT Len = (UINT) strlen( Str );
136 // pDup = GlobalAllocStrA( Len + 1 );
137 // if (pDup) strcpy( pDup, Str );
138 // }
139 // return pDup;
140 //}
141 
142 WSTR GlobalDupStrW( WCSTR Str, bool isMulti )
143 {
144  WSTR pDup = NULL;
145  if (Str)
146  {
147  UINT Len = isMulti ? MultiSzLengthW( Str ) : UINT( 1+wcslen( Str ));
148  pDup = GlobalAllocStrW( Len );
149  if (pDup) memcpy( pDup, Str, Len * WCHAR_SIZE );
150  }
151  return pDup;
152 }
153 
155 
156 HANDLE GlobalUnlockedHandle( PVOID Ptr, PUINT pCount )
157 {
158  UINT lockCount = 0;
159  HANDLE hMem = GlobalHandle( Ptr );
160  if (hMem)
161  {
162  BOOL locked = TRUE;
163  while( locked )
164  {
165  lockCount++;
166  locked = GlobalUnlock( hMem );
167  if (!locked && GetLastError() != 0) hMem = NULL; // Failure
168  }
169  }
170  if (pCount) *pCount = lockCount;
171  return hMem;
172 }
173 
174 //-----------------------------------------------------------------------------
175 // Memory access check. MSDN: Success does /not/ guarantee accessibility
176 // in a multithreading environment. @sa Intel Asm: VERR and VERW.
177 //-----------------------------------------------------------------------------
178 
179 bool IsBadReadWritePtr( const PVOID address, UINT_PTR size )
180 {
181  return (IsBadReadPtr( address, size ) || IsBadWritePtr( address, size ));
182 }
183 
184 //-----------------------------------------------------------------------------
185 // Simplified CreateProcess..
186 //-----------------------------------------------------------------------------
187 
188 HANDLE Launch( CSTR exePath, CSTR cmdLn, CSTR startDir, int iShow, DWORD Flags )
189 {
190  LPSECURITY_ATTRIBUTES sa = &DefSec;
191  PROCESS_INFORMATION pi = { NULL,NULL, 0,0 };
192  STARTUPINFO si = {
193  sizeof(STARTUPINFO),
194  NULL,NULL,NULL, 0,0,0,0,0,0,0,0,0,0,0, NULL,NULL,NULL
195  };
196  PVOID pEnv = NULL; // NULL = Use environment of the calling process.
197 
198  #if 0 // CreateProcess handles sending the process to the right desktop by default
199  si.lpDesktop = _T("winsta0\\default"); // Memo to self (for the string content)
200  #endif
201  si.wShowWindow = iShow;
202  si.dwFlags = STARTF_USESHOWWINDOW;
203 
204  if (!CreateProcess( exePath, (TSTR)cmdLn, sa,sa, FALSE, Flags, pEnv, startDir, &si,&pi ))
205  {
206  TRACE( DP_ERROR, _F("CreateProcess( %s, %s ) failed: %s\n"), exePath, cmdLn, SysErrorMsg() );
207  pi.hProcess = NULL;
208  }
209  if (pi.hThread) CloseHandle( pi.hThread ); // Not used with Launch.
210  return pi.hProcess;
211 }
212 
213 //-----------------------------------------------------------------------------
214 // CreateCapturedProc - Create a process who's STDIN/OUT/ERR are redirected
215 // to three anonymous pipes. Return handle of the created process, or NULL.
216 //-----------------------------------------------------------------------------
217 
219  IN CSTR cmdLn, // Command line string
220  IN LPSTARTUPINFO si, // STARTUPINFO (less the std handles) for the new proc
221  IN DWORD Flags, // Creation flags for CreateProcess.
222  OPTOUT PHANDLE pRdHnd, // We read child's stdout from here
223  OPTOUT PHANDLE pWrHnd, // We write child's stdin to here
224  OPTOUT PHANDLE pErrHnd, // We read child's stderr from here
225  OPTOUT PHANDLE phThread // If you need the thread handle
226  )
227 {
228  PROCESS_INFORMATION ppi = { 0,0,0,0 };
229  if (si == NULL)
230  SetLastError( ERROR_INVALID_PARAMETER );
231  else
232  {
233  if (pRdHnd) CreatePipe( pRdHnd, &si->hStdOutput, &DefSec, 0 ); // Our read, child's STDOUT
234  if (pWrHnd) CreatePipe( &si->hStdInput, pWrHnd, &DefSec, 0 ); // Our write, child's STDIN
235  if (pErrHnd) CreatePipe( pErrHnd, &si->hStdError, &DefSec, 0 ); // Our read, child's STDERR
236 
237  bool ok = true;
238  if (pRdHnd != NULL) ok = (*pRdHnd != NULL);
239  if ((pWrHnd != NULL) && ok) ok = (*pWrHnd != NULL);
240  if ((pErrHnd != NULL) && ok) ok = (*pErrHnd != NULL);
241  if (ok)
242  {
243  si->dwFlags |= STARTF_USESTDHANDLES;
244  if (CreateProcess( NULL, (TSTR)cmdLn, &DefSec, &DefSec, TRUE, Flags, 0,0, si, &ppi ))
245  {
246  if (phThread) *phThread = ppi.hThread;
247  else CloseHandleEx( ppi.hThread ); // Don't leak a handle we don't return.
248  return ppi.hProcess;
249  }
250  }
251  // Failure
252  if (pErrHnd) {
253  *pErrHnd = CloseHandleEx( *pErrHnd );
254  si->hStdError = CloseHandleEx( si->hStdError );
255  }
256  if (pWrHnd) {
257  *pWrHnd = CloseHandleEx( *pWrHnd );
258  si->hStdInput = CloseHandleEx( si->hStdInput );
259  }
260  if (pRdHnd) {
261  *pRdHnd = CloseHandleEx( *pRdHnd );
262  si->hStdOutput = CloseHandleEx( si->hStdOutput );
263  }
264  if (phThread) *phThread = NULL;
265  }
266  return NULL;
267 }
268 
269 //-----------------------------------------------------------------------------
270 // CreateCapturedProcessEx...
271 //-----------------------------------------------------------------------------
272 
274  OPTIN CSTR ExePath, // Executable path name.
275  OPTIN CSTR CmdLn, // Command line string.
276  OPTIN CSTR EnvStr, // Environment strings (multi-sz).
277  OPTIN CSTR WorkDir, // Working directory.
278  IN LPSTARTUPINFO pSI, // STARTUPINFO (less the std handles) for the new proc.
279  IN DWORD Flags, // Creation flags for CreateProcess.
280  OPTOUT PHANDLE pRdHnd, // We read child's stdout from here.
281  OPTOUT PHANDLE pWrHnd, // We write child's stdin to here.
282  OPTOUT PHANDLE pErrHnd, // We read child's stderr from here.
283  OPTOUT PHANDLE phThread // If you need the thread handle.
284  )
285 {
286  PROCESS_INFORMATION pi = { 0,0,0,0 };
287  if (pSI == NULL)
288  SetLastError( ERROR_INVALID_PARAMETER );
289  else
290  {
291  DWORD err = 0;
292  if (pRdHnd) CreatePipe( pRdHnd, &pSI->hStdOutput, &DefSec, 0 ); // Our read, child's STDOUT
293  if (pWrHnd) CreatePipe( &pSI->hStdInput, pWrHnd, &DefSec, 0 ); // Our write, child's STDIN
294  if (pErrHnd) CreatePipe( pErrHnd, &pSI->hStdError, &DefSec, 0 ); // Our read, child's STDERR
295 
296  bool ok = true;
297  if (pRdHnd != NULL) ok = (*pRdHnd != NULL);
298  if ((pWrHnd != NULL) && ok) ok = (*pWrHnd != NULL);
299  if ((pErrHnd != NULL) && ok) ok = (*pErrHnd != NULL);
300  if (ok)
301  {
302  pSI->dwFlags |= STARTF_USESTDHANDLES;
303 
304  if (CreateProcess( ExePath, TSTR(CmdLn),
305  &DefSec, &DefSec, true, Flags, PVOID(EnvStr), WorkDir, pSI, &pi
306  ))
307  {
308  if (phThread) *phThread = pi.hThread;
309  else CloseHandleEx( pi.hThread ); // Don't leak a handle we don't return.
310  return pi.hProcess;
311  }
312  else err = GetLastError(); // Carry forward..
313  }
314  // Failure
315  if (pErrHnd) {
316  *pErrHnd = CloseHandleEx( *pErrHnd );
317  pSI->hStdError = CloseHandleEx( pSI->hStdError );
318  }
319  if (pWrHnd) {
320  *pWrHnd = CloseHandleEx( *pWrHnd );
321  pSI->hStdInput = CloseHandleEx( pSI->hStdInput );
322  }
323  if (pRdHnd) {
324  *pRdHnd = CloseHandleEx( *pRdHnd );
325  pSI->hStdOutput = CloseHandleEx( pSI->hStdOutput );
326  }
327  if (phThread) *phThread = NULL;
328  if (err) SetLastError( err );
329  }
330  return NULL;
331 }
332 
333 //-----------------------------------------------------------------------------
334 // Do the mentioned closing, and terminate the process..
335 //-----------------------------------------------------------------------------
336 
338  IN HANDLE hProc, // Process handle
339  IN LPSTARTUPINFO pSi, // STARTUPINFO used in CreateCapturedProcess
340  IN PHANDLE pRdHnd, // The inhnd returned from CreateCapturedProcess
341  IN PHANDLE pWrHnd, // The outhnd returned from CreateCapturedProcess
342  IN PHANDLE pErrHnd // The errhnd returned from CreateCapturedProcess
343  )
344 {
345  if (pErrHnd) *pErrHnd = CloseHandleEx( *pErrHnd );
346  if (pWrHnd) *pWrHnd = CloseHandleEx( *pWrHnd );
347  if (pRdHnd) *pRdHnd = CloseHandleEx( *pRdHnd );
348  if (pSi) // pSi == NULL is an error, but let's be lenient..
349  {
350  pSi->hStdError = CloseHandleEx( pSi->hStdError );
351  pSi->hStdOutput = CloseHandleEx( pSi->hStdOutput );
352  pSi->hStdInput = CloseHandleEx( pSi->hStdInput );
353  }
354  return CloseHandleEx( hProc ); // Note: Null-safe.
355 }
356 
358  IN HANDLE hProc, // Process handle
359  IN LPSTARTUPINFO pSi, // STARTUPINFO used in CreateCapturedProcess
360  IN PHANDLE pRdHnd, // The inhnd returned from CreateCapturedProcess
361  IN PHANDLE pWrHnd, // The outhnd returned from CreateCapturedProcess
362  IN PHANDLE pErrHnd, // The errhnd returned from CreateCapturedProcess
363  IN UINT retCode // Return code
364  )
365 {
366  if (hProc && !TerminateProcess( hProc, retCode ))
367  DPrint( DP_ERROR, _F("TerminateProcess(%p): %s\n"), hProc, SysErrorMsg() );
368 
369  return CloseCapturedProcess( hProc, pSi, pRdHnd, pWrHnd, pErrHnd );
370 }
371 
372 //-----------------------------------------------------------------------------
373 // LEGACY: GetOrLoadModule.. (Written before I knew that LoadLibrary does this).
374 //-----------------------------------------------------------------------------
375 
376 HMODULE GetOrLoadModule( CSTR modName )
377 {
378  HMODULE hMod = GetModuleHandle( modName );
379  if (!hMod) hMod = LoadLibrary( modName );
380  return hMod;
381 }
382 
383 //-----------------------------------------------------------------------------
384 // LoadProcLibrary loads a DLL into another process.
385 // It returns the remote DLL handle, or NULL on failure.
386 // Uses a variation of the method invented by Jeff Richter. Clever man :)
387 // NOTE: Anti-virus software (correctly) considers this a generic threat.
388 //-----------------------------------------------------------------------------
389 
390 // TODO: Full test of LoadProcLibrary in x64.
391 
392 #ifdef __GNUC__
393 #pragma GCC diagnostic push
394 #pragma GCC diagnostic ignored "-Wcast-function-type"
395 #endif
396 
397 HMODULE LoadProcLibrary( HANDLE hProc, LPCSTR DllPathName, DWORD msWait )
398 {
399  DWORD err = NO_ERROR;
400  HMODULE hMod = NULL;
401  static HMODULE (WINAPI *_LoadLibrary)( LPCSTR pPathName ) = NULL;
402 
403  // This works because kernel32 is always loaded at the same address in each process.
404  // If that changes, this needs to use NtCreateThread instead, since ntdll is
405  // *guaranteed* to be loaded at the same address in each process.
406 
407  if (!_LoadLibrary)
408  {
409  HMODULE hKernel = GetModuleHandleA( "KERNEL32.DLL" );
410  LITERAL( FARPROC, _LoadLibrary ) = GetProcAddress( hKernel, "LoadLibraryA" );
411  TRACE( DP_DEBUG, _F("kernel32!LoadLibraryA = %p\n"), _LoadLibrary );
412  }
413  if (_LoadLibrary)
414  {
415  PVOID pPath = VirtualAllocEx( hProc, NULL, MAX_PATH, MEM_COMMIT, PAGE_READWRITE );
416  TRACE( DP_DEBUG, _F("VirtualAllocEx[%p] = %p\n"), hProc, pPath );
417  if (!pPath)
418  err = GetLastError();
419  else
420  {
421  SIZE_T cbWr, len = 1+strlen( DllPathName );
422 
423  // Copy LoadLibrary parameter to the other process' memory.
424 
425  TRACE( DP_VERBOSE, _F("WriteProcessMemory [%p,%p] '%s'\n"), hProc, pPath, DllPathName );
426  if (!WriteProcessMemory( hProc, pPath, (PVOID)DllPathName, len, &cbWr ))
427  err = GetLastError();
428  else
429  {
430  // Call LoadLibraryA in the other process.
431  // This works because LoadLibrary has the same signature as ThreadProc.
432 
433  TRACE( DP_VERBOSE, _F("CreateRemoteThread\n") );
434  HANDLE hThr = CreateRemoteThread(
435  hProc, NULL,0, (LPTHREAD_START_ROUTINE)_LoadLibrary, pPath, 0,NULL
436  );
437  if (!hThr) err = GetLastError();
438  else
439  {
440  DWORD_PTR retCode; // 32/64 in case GetExitCodeThread actually fetch 64 bits on x64.
441  TRACE( DP_VERBOSE, _F("WaitForSingleObject( hThr=%p, %lu )\n"), hThr, msWait );
442  DWORD wr = WaitForSingleObject( hThr, msWait );
443  TRACE( DP_DEBUG, _F(" = %lu (%u)\n"), wr, (wr == WAIT_OBJECT_0) );
444  if (wr == WAIT_OBJECT_0)
445  {
446  if (!GetExitCodeThread( hThr, (LPDWORD)&retCode ))
447  {
448  err = GetLastError();
449  retCode = (-1);
450  }
451  } else {
452  err = ERROR_TIMEOUT;
453  retCode = (-1);
454  }
455  // NOTE: This is on the thin ice in x64, since an x64 handle is 64 bits
456  // and GetExitCodeThread officially only return a DWORD, not DWORD_PTR.
457  // Empiric testing indicates that module handles constrain to 32 bits.
458  // However, there's NO guarantee for that. If the module handle is
459  // indeed truncated, the calling process will not be able to /unload/ it.
460  // Amends: GetProcDLLHandle can be used to retrieve the remote handle.
461 
462  hMod = (HMODULE) retCode;
463  CloseHandle( hThr );
464  }
465  }
466  TRACE( DP_VERBOSE, _F("VirtualFreeEx [%p] %p\n"), hProc, pPath );
467  VirtualFreeEx( hProc, pPath, 0, MEM_RELEASE );
468  }
469  }
470  TRACE( DP_DEBUG, _F("hMod = 0x%p\n"), hMod );
471  if (err) SetLastError( err );
472  return hMod;
473 }
474 #ifdef __GNUC__
475 #pragma GCC diagnostic pop
476 #endif
477 
478 //-----------------------------------------------------------------------------
479 // UnloadProcLibrary unloads a DLL from another process.
480 // The DLL handle has to be a *remote handle* (from LoadProcLibrary/GetProcDLLHandle).
481 //-----------------------------------------------------------------------------
482 
483 BOOL UnloadProcLibrary( HANDLE hProc, HMODULE hLib, DWORD msWait )
484 {
485  BOOL ok = FALSE;
486  static BOOL (WINAPI *_FreeLibrary)( HMODULE hLib ) = NULL;
487 
488  // This works because kernel32 is always loaded at the same address in each process.
489  // If that changes, this needs to use the native NtCreateThread instead.
490 
491  if (!_FreeLibrary)
492  {
493  HMODULE hKernel = GetModuleHandleA( "KERNEL32.DLL" );
494  LITERAL( FARPROC,_FreeLibrary ) = GetProcAddress( hKernel, "FreeLibrary" );
495  TRACE( DP_DEBUG, _F("kernel32!FreeLibrary = %p\n"), _FreeLibrary );
496  }
497  if (_FreeLibrary)
498  {
499  // Call FreeLibrary in the other process.
500  // This works because FreeLibrary has the same signature as ThreadProc.
501  HANDLE hThr = CreateRemoteThread(
502  hProc, NULL,0, (LPTHREAD_START_ROUTINE)_FreeLibrary, hLib, 0,NULL
503  );
504  if (hThr)
505  {
506  DWORD_PTR retCode;
507  if (WaitForSingleObject( hThr, msWait ) == WAIT_OBJECT_0)
508  GetExitCodeThread( hThr, (LPDWORD)&retCode );
509  else retCode = 0;
510  ok = (BOOL) retCode;
511  CloseHandle( hThr );
512  }
513  }
514  return ok;
515 }
516 
517 //-----------------------------------------------------------------------------
518 #ifndef NO_NDK_FILES // These two require native data types.
519 
520 SHORT GetProcDLLRefCount( HANDLE hProcess, WCSTR DllName )
521 {
522  SHORT refCount = 0;
523  LDR_MODULE lm;
524  IF_DEBUG( memset( &lm, 0, sizeof(lm) ));
525 
526  if (GetProcDllData( hProcess, DllName, &lm, false ))
527  refCount = lm.LoadCount;
528  return refCount;
529 }
530 
531 HMODULE GetProcDLLHandle( HANDLE hProcess, WCSTR DllName )
532 {
533  HMODULE hDll = NULL;
534  LDR_MODULE lm;
535  IF_DEBUG( memset( &lm, 0, sizeof(lm) ));
536 
537  if (GetProcDllData( hProcess, DllName, &lm, false ))
538  hDll = (HMODULE) lm.BaseAddress;
539  return hDll;
540 }
541 
542 #endif//ndef NO_NDK_FILES
543 //-----------------------------------------------------------------------------
544 BEGIN_NAMESPACE( uLib ) // FILETIME support
545 //-----------------------------------------------------------------------------
546 
547 const FILETIME NullFileTime = {0,0};
548 
549 FILETIME Now( eTimeType Domain )
550 {
551  SYSTEMTIME sysTime;
552  FILETIME result = {0,0};
553 
554  switch( Domain )
555  {
556  case LOCAL_TIME: GetLocalTime( &sysTime ); break;
557  case SYSTEM_TIME: GetSystemTime( &sysTime ); break;
558  default: goto __done;
559  }
560  SystemTimeToFileTime( &sysTime, &result );
561  __done: return result;
562 }
563 
564 FILETIME AddTime( FILETIME Time, SHORT Hr, SHORT Min, SHORT Sec, SHORT mSec )
565 {
566  SYSTEMTIME st;
567  FILETIME result;
568  int ms, add;
569 
570  static const int ms_Sec = 1000;
571  static const int ms_Min = 60*1000; // Take advatage of constant folding
572  static const int ms_Hour = 60*60*1000;
573  static const int ms_Day = 24*60*60*1000;
574 
575  FileTimeToSystemTime( &Time, &st );
576  ms = st.wMilliseconds + (st.wSecond * ms_Sec) + (st.wMinute * ms_Min) + (st.wHour * ms_Hour);
577  add = mSec + (Sec * ms_Sec) + (Min * ms_Min) + (Hr * ms_Hour);
578  ms += add;
579 
580  st.wHour = ms / ms_Hour;
581  ms -= (st.wHour * ms_Hour);
582 
583  st.wMinute = ms / ms_Min;
584  ms -= (st.wMinute * ms_Min);
585 
586  st.wSecond = (ms / ms_Sec);
587  ms -= (st.wSecond * ms_Sec);
588 
589  st.wMilliseconds = ms;
590 
591  SystemTimeToFileTime( &st, &result );
592  return result;
593 }
594 
595 FILETIME AddFiletime( FILETIME Time, const FILETIME Add )
596 // WIP.. Not public yet.
597 {
598  SYSTEMTIME st;
599  FileTimeToSystemTime( &Add, &st );
600 
601  // TODO: Rewrite this to allow adding entire datetime...
602 
603  return AddTime( Time, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds );
604 }
605 
606 FILETIME MakeDateTime( WORD Year, WORD Month, WORD Day, WORD Hr, WORD Min, WORD Sec )
607 {
608  SYSTEMTIME st;
609  FILETIME result;
610 
611  st.wYear = Year;
612  st.wMonth = Month;
613  st.wDay = Day;
614  st.wHour = Hr;
615  st.wMinute = Min;
616  st.wSecond = Sec;
617  st.wDayOfWeek = st.wMilliseconds = 0;
618 
619  SystemTimeToFileTime( &st, &result );
620  return result;
621 }
622 
623 #ifdef __cplusplus // FILETIME comparators...
624 
625 bool operator > ( FILETIME const& A, FILETIME const& B ) // extern "C++"
626 {
627  LargeInt a( A ), b( B );
628  return UINT64( a ) > UINT64( b );
629 }
630 bool operator < ( FILETIME const& A, FILETIME const& B ) // extern "C++"
631 {
632  LargeInt a( A ), b( B );
633  return UINT64( a ) < UINT64( b );
634 }
635 bool operator == ( FILETIME const& A, FILETIME const& B ) // extern "C++"
636 {
637  LargeInt a( A ), b( B );
638  return UINT64( a ) == UINT64( b );
639 }
640 bool operator >= ( FILETIME const& A, FILETIME const& B ) // extern "C++"
641 {
642  return !operator < ( A,B );
643 }
644 bool operator <= ( FILETIME const& A, FILETIME const& B ) // extern "C++"
645 {
646  return !operator > ( A,B );
647 }
648 bool operator != ( FILETIME const& A, FILETIME const& B ) // extern "C++"
649 {
650  return !operator == ( A,B );
651 }
652 
653 #endif
654 //==----------------------------------------------------------------------------
656 //-----------------------------------------------------------------------------
657 // SYSTEMTIME support
658 //-----------------------------------------------------------------------------
659 
660 SYSTEMTIME* SystemTimeToLocalTime( SYSTEMTIME* Time )
661 {
662  TIME_ZONE_INFORMATION tzi;
663  SYSTEMTIME local;
664 
665  if (Time)
666  {
667  DWORD rc = GetTimeZoneInformation( &tzi );
668  _ASSERTE( rc != TIME_ZONE_ID_INVALID );
669  if( SystemTimeToTzSpecificLocalTime( &tzi, Time, &local ))
670  *Time = local;
671  else Time = NULL;
672  }
673  return Time;
674 }
675 
676 SYSTEMTIME* LocalTimeToSystemTime( SYSTEMTIME* Time )
677 {
678  TIME_ZONE_INFORMATION tzi;
679  SYSTEMTIME utc;
680 
681  if (Time)
682  {
683  DWORD rc = GetTimeZoneInformation( &tzi );
684  _ASSERTE( rc != TIME_ZONE_ID_INVALID );
685  if( TzSpecificLocalTimeToSystemTime( &tzi, Time, &utc ))
686  *Time = utc;
687  else Time = NULL;
688  }
689  return Time;
690 }
691 
692 FILETIME FileTimeToLocalTime( FILETIME utc )
693 // It's often more convenient to get the result as a return value.
694 {
695  FILETIME local;
696  if (!FileTimeToLocalFileTime( &utc, &local ))
697  local = uLib::NullFileTime;
698  return local;
699 }
700 
701 //==----------------------------------------------------------------------------
702 
703 static HMODULE GetNtDll()
704 {
705  static HMODULE ntDll;
706  if (!ntDll) ntDll = GetModuleHandle( _T("NTDLL") );
707  return ntDll;
708 }
709 
710 //==----------------------------------------------------------------------------
711 // GetEnvironmentSize
712 //==----------------------------------------------------------------------------
713 
714 bool GetEnvironmentSize( WSTR pwEnv, PUINT pSize, PUINT pUsed )
715 {
716  WSTR pzEnv, pEnv = pwEnv ? pwEnv : GetEnvironmentStringsW();
717  bool ok = (pEnv != NULL);
718  if (pSize) *pSize = 0;
719  if (pUsed) *pUsed = 0;
720  if ( ok )
721  {
722  for( pzEnv = pEnv; *pzEnv; pzEnv = 1 + wcschr( pzEnv, 0 )); // Find the end
723  UINT ccEnv = UINT( (pzEnv - pEnv) + 1 ); // Incl 2nd null
724 
725  MEMORY_BASIC_INFORMATION mbi;
726  ok = (VirtualQuery( pEnv, &mbi, sizeof(mbi) ) > 0);
727  if ( ok )
728  {
729  if (pSize) *pSize = UINT( mbi.RegionSize / WCHAR_SIZE );
730  if (pUsed) *pUsed = ccEnv;
731  }
732  if (!pwEnv) FreeEnvironmentStringsW( pEnv );
733  }
734  return ok;
735 }
736 
737 //==----------------------------------------------------------------------------
738 // Clone/FreeEnvironment
739 //==----------------------------------------------------------------------------
740 
741 // NOTE: While debugging this function, I found a non-compliance in the
742 // environment on Win7 x64. The PATH value was stored *last* in the environment,
743 // not in *sorted order* as it's supposed to be.. This holds ramifications for
744 // Rtl[Get/Set]EnvironmentVariable() implementors.. (E.g: Can't do binary search.)
745 // Caveat Emptor / Love.
746 
747 WSTR CloneEnvironment( OPTOUT PUINT pLength, OPTOUT PUINT pUsed )
748 {
749  static NTSTATUS (NTAPI *_RtlCreateEnvironment)( BOOLEAN Clone, OUT PWSTR* Env );
751  (FARPROC&)_RtlCreateEnvironment = GetProcAddress( GetNtDll(), "RtlCreateEnvironment" );
752 
753  WSTR pwEnv = NULL, pzEnv;
754 
756  SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
757  else
758  {
759  NTSTATUS rc = _RtlCreateEnvironment( true, &pwEnv );
760  if (!NT_SUCCESS( rc ))
761  {
762  pwEnv = NULL;
764  }
765  else
766  {
767  for( pzEnv = pwEnv; *pzEnv; pzEnv = 1 + wcschr( pzEnv, 0 )); // Find the end.
768  UINT_PTR ccUsed = (pzEnv - pwEnv) + 1; // Length incl 2nd null.
769  if (pUsed) *pUsed = (UINT) ccUsed;
770 
771  MEMORY_BASIC_INFORMATION mbi;
772  IF_DEBUG( memset( &mbi, 0, sizeof(mbi) ));
773  if (VirtualQuery( pwEnv, &mbi, sizeof(mbi) ))
774  {
775  UINT ccEnv = UINT( mbi.RegionSize / WCHAR_SIZE );
776  if (pLength) *pLength = ccEnv;
777 
778  #if _DEBUG
779  DPrint( DP_DEBUG,
780  _F("AllocationBase=%#x, BaseAddress=%#x, RegionSize=%lu, State=0x%08X\n"),
781  mbi.AllocationBase, mbi.BaseAddress, mbi.RegionSize, mbi.State
782  );
783  UINT cbUsed = UINT( ccUsed * WCHAR_SIZE );
784  static const UINT MAX_ENV = 32767 * WCHAR_SIZE; // Max permitted env size, says MSDN doc.
785  if (mbi.RegionSize > MAX_ENV) // Ugh, non-compliant environment :/
787  _F("Non-compliant environment size: %lu B (%lu ch)! %lu B used\n"),
788  mbi.RegionSize, ccEnv, cbUsed
789  );
790  #endif
791  }
792  }
793  }
794  return pwEnv;
795 }
796 
798 {
799  static VOID (NTAPI *_RtlDestroyEnvironment)( PWSTR Env );
801  (FARPROC&)_RtlDestroyEnvironment = GetProcAddress( GetNtDll(), "RtlDestroyEnvironment" );
802 
804  SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
805  else
806  {
807  if ( !Env ) SetLastError( ERROR_INVALID_PARAMETER );
808  else
809  {
810  _RtlDestroyEnvironment( Env );
811  #if _DEBUG
812  MEMORY_BASIC_INFORMATION mbi;
813  memset( &mbi, 0, sizeof(mbi) );
814  if (VirtualQuery( Env, &mbi, sizeof(mbi) ))
815  {
816  DPrint( DP_DEBUG,
817  _F("After: AllocationBase=%#x, BaseAddress=%#x, RegionSize=%lu, State=%lu\n"),
818  mbi.AllocationBase, mbi.BaseAddress, mbi.RegionSize, mbi.State
819  );
820  }
821  #endif
822  Env = NULL;
823  }
824  }
825  return Env;
826 }
827 
828 //==----------------------------------------------------------------------------
829 // Set/Get/ModifyEnvironmentVar
830 //==----------------------------------------------------------------------------
831 #ifndef NO_WINTERNAL // UNICODE_STRING
832 
833 // NOTA BENE: RtlSetEnvironmentVariable is quirky, and frequently cause GPF
834 // read exceptions, which it handles internally and returns status zero.
835 // The bug is that it reads one byte /before the beginning of the environment/.
836 // The exceptions are not re-raised, so we cannot provide value added handling.
837 
838 // NOTE: Even though the env block is always UniCode, these functions
839 // work with transmutable strings internally and parameter-wise..
840 
841 bool SetEnvironmentVar( OPTIO WSTR* pwEnv, IN CSTR Name, IN CSTR Value )
842 {
843  static NTSTATUS (NTAPI *_RtlSetEnvironmentVariable)(
844  PWSTR* Environment, PUNICODE_STRING Name, PUNICODE_STRING Value );
845 
847  GetProcAddress( GetNtDll(), "RtlSetEnvironmentVariable" );
848 
849  bool ok = (_RtlSetEnvironmentVariable != NULL);
850  if ( !ok ) SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
851  else
852  {
853  UString uName( Name ), uValue; // Auto-convert..
854  PUNICODE_STRING puVal = NULL;
855  if ( Value )
856  {
857  uValue = Value;
858  puVal = (PUNICODE_STRING) uValue;
859  }
860  NTSTATUS rc = _RtlSetEnvironmentVariable( pwEnv, uName, puVal );
861  ok = NT_SUCCESS( rc );
862  if ( !ok ) SetLastErrorFromNtStatus( rc );
863  }
864  return ok;
865 }
866 
868  OPTIN WSTR pwEnv, IN CSTR Name, OUT TSTR Value, INOUT PUINT ccValBuf )
869 {
870  static NTSTATUS (NTAPI *_RtlQueryEnvironmentVariable)(
871  PWSTR Environment, PUNICODE_STRING Name, PUNICODE_STRING Value );
872 
873  if (!_RtlQueryEnvironmentVariable) (FARPROC&)_RtlQueryEnvironmentVariable =
874  GetProcAddress( GetNtDll(), "RtlQueryEnvironmentVariable_U" ); // N.B: Using _U variant.
875 
876  bool ok = (_RtlQueryEnvironmentVariable != NULL);
877  if ( !ok ) SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
878  else
879  {
880  ok = (ccValBuf != NULL);
881  if ( !ok ) SetLastError( ERROR_INVALID_PARAMETER );
882  else
883  {
884  UString uName( Name ); // Auto-convert..
885  UNICODE_STRING uValue = { 0, USHORT( *ccValBuf * WCHAR_SIZE ), NULL };
886 
887  // Note: RtlQueryEnvironmentVariable_U doesn't touch the Buffer
888  // if MaximumLength is smaller than the actual value length.
889  // Length is not touched if value don't exist, else it is
890  // always set to the actual value size, regardeless of Buffer.
891 
892  #ifdef _UNICODE
893  uValue.Buffer = Value;
894  #else
895  uValue.Buffer = *ccValBuf ? mem_AllocWStr( *ccValBuf ) : NULL;
896  #endif
897  NTSTATUS rc = _RtlQueryEnvironmentVariable( pwEnv, uName, &uValue );
898 
899  // 'rc' may be STATUS_SUCCESS, STATUS_VARIABLE_NOT_FOUND,
900  // STATUS_BUFFER_TOO_SMALL, or STATUS_ACCESS_VIOLATION.
901 
902  UINT ccVal = uValue.Length / WCHAR_SIZE, ccUni = ccVal;
903  if (uValue.MaximumLength > uValue.Length) ++ccUni; // Include NUL.
904 
905  ok = NT_SUCCESS( rc );
906  if ( !ok ) SetLastErrorFromNtStatus( rc );
907  #ifndef _UNICODE
908  else WideCharToMultiByte(
909  CP_ACP, 0, uValue.Buffer, ccUni, Value, *ccValBuf, NULL, NULL
910  );
911  if ( *ccValBuf ) mem_Free( uValue.Buffer );
912  #endif
913  //*ccValBuf = ccVal + 1; // +1 == null terminator
914  if ( ccVal ) ccVal++; // +1 == null terminator
915  *ccValBuf = ccVal;
916  }
917  }
918  return ok;
919 }
920 
922  WSTR* pwEnv, BYTE Option, CSTR Name, CSTR Addendum, TCHAR Sep )
923 {
924  UINT valueLen = 0;
925  if (!IsString( Name ) || !IsString( Addendum ))
926  SetLastError( ERROR_INVALID_PARAMETER );
927  else
928  {
929  UINT addLen = (UINT)_tcslen( Addendum );
930 
931  bool ok = GetEnvironmentVar( *pwEnv, Name, NULL, &valueLen );
932  if (!valueLen ) // Name doesn't exist, so just add it with the Addendum value.
933  {
934  ok = SetEnvironmentVar( pwEnv, Name, Addendum );
935  valueLen = ok ? addLen : 0;
936  }
937  else
938  {
939  // A 2kB fixed buffer would probably suffice, but lets play it safe..
940 
941  UINT bufLen = valueLen + addLen + 2;
942  IF_DEBUG( bufLen = ROUND_UP2( bufLen, 256 ));
943  TSTR valueBuf = mem_AllocStr( bufLen );
944  if ( !valueBuf ) valueLen = 0;
945  else
946  {
947  ok = GetEnvironmentVar( *pwEnv, Name, valueBuf, &valueLen );
948  if ( ok )
949  {
950  valueLen = (Option == MEF_PREPEND)
951  ? PrependString( valueBuf, bufLen, Sep, Addendum )
952  : AppendString( valueBuf, bufLen, Sep, Addendum );
953 
954  #ifndef _UNICODE // DeduplicateCharSeparatedText is non-unicode only..
955  if ( Sep ) valueLen =
956  DeduplicateCharSepText( valueBuf, Sep, false, false );
957  #endif
958 
959  if ( valueLen ) ok = SetEnvironmentVar( pwEnv, Name, valueBuf );
960  if ( !ok ) valueLen = 0;
961  }
962  mem_Free( valueBuf );
963  }
964  }
965  }
966  return valueLen;
967 }
968 
969 #endif//ndef NO_WINTERNAL
970 //==----------------------------------------------------------------------------
971 // DeduplicatePath removes duplicate paths from e.g a PATH variable.
972 // Only the first occurence of each duplicate is retained.
973 //==----------------------------------------------------------------------------
974 
975 #ifndef _UNICODE
977 {
978  return DeduplicateCharSepText( Path, SEMICOLON, false, false );
979 }
980 #endif
981 
982 //==----------------------------------------------------------------------------
983 // PE executable header access
984 //==----------------------------------------------------------------------------
985 
986 #if 0 // old ways..
987  static const WORD PE_SIGN = WORD('EP'); // "PE" (LSBF=0x4550)
988  static const WORD PE_SIGN = *(PWORD)"PE"; // "PE" (LSBF=0x4550)
989 #else // new neat way..
990  static const WORD PE_SIGN = MK_TWOCC("PE"); // LSBF=0x4550
991  static const WORD MZ_SIGN = MK_TWOCC("MZ"); // aka. IMAGE_DOS_SIGNATURE
992 #endif
993 
994 bool ReadNTHeaders( CSTR ExeName, IMAGE_NT_HEADERS* Hdr, bool getOptHdr )
995 {
996  bool ok = false;
997  if (!Hdr) SetLastError( ERROR_INVALID_PARAMETER );
998  else
999  {
1000  IMAGE_DOS_HEADER DosHdr;
1001  #define FHDR_SIZE sizeof(Hdr->FileHeader)
1002  #define OPTHDR_SIZE sizeof(Hdr->OptionalHeader)
1003 
1004  TCHAR name[ MAX_PATH ];
1005  if (!ExeName)
1006  {
1007  GetModuleFileName( NULL, name, dimof(name) );
1008  ExeName = name;
1009  }
1010  HANDLE hFile = CreateFile(
1011  ExeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL
1012  );
1013  ok = (hFile != _BAD_HANDLE);
1014  if (ok)
1015  {
1016  ZeroMemory( &DosHdr, sizeof(DosHdr) );
1017  ok = (BlockRead( hFile, &DosHdr, sizeof(DosHdr) ) == sizeof(DosHdr));
1018  if (ok) ok = (DosHdr.e_magic == MZ_SIGN); // aka. IMAGE_DOS_SIGNATURE
1019  if (ok) ok = (DosHdr.e_lfanew > 0);
1020  if (ok) ok = Seek( hFile, DosHdr.e_lfanew, FILE_BEGIN );
1021  if (ok) ok = (BlockRead( hFile, &Hdr->Signature, 4 ) == 4);
1022  if (ok) ok = (LOWORD( Hdr->Signature ) == PE_SIGN);
1023  if (ok)
1024  {
1025  ok = (BlockRead( hFile, &Hdr->FileHeader, FHDR_SIZE ) == FHDR_SIZE);
1026  if (!ok) memset( &Hdr->FileHeader, 0, FHDR_SIZE );
1027  }
1028  if (ok && getOptHdr)
1029  {
1030  ok = (Hdr->FileHeader.SizeOfOptionalHeader > 0);
1031  if (ok) ok = (BlockRead( hFile, &Hdr->OptionalHeader, OPTHDR_SIZE ) == OPTHDR_SIZE);
1032  if (!ok) memset( &Hdr->OptionalHeader, 0, OPTHDR_SIZE );
1033  }
1034  CloseHandle( hFile );
1035  }
1036  }
1037  return ok;
1038  #undef FHDR_SIZE
1039  #undef OPTHDR_SIZE
1040 }
1041 
1043 {
1044  IMAGE_NT_HEADERS Hdr; IF_DEBUG( memset( &Hdr, 0, sizeof(Hdr) ));
1045  bool ok = ReadNTHeaders( ExeName, &Hdr, false );
1046  return ok ? Hdr.FileHeader.Machine : 0;
1047 }
1048 
1049 bool Is64BitExecutable( CSTR ExeName )
1050 {
1051  IMAGE_NT_HEADERS Hdr; IF_DEBUG( memset( &Hdr, 0, sizeof(Hdr) ));
1052  bool ok = ReadNTHeaders( ExeName, &Hdr, true );
1053  if (ok)
1054  {
1055  ok = (Hdr.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC);
1056  //IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
1057  //IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
1058  }
1059  return ok;
1060 }
1061 
1062 WORD GetInstanceTargetMachine( HINSTANCE hInst )
1063 {
1064  WORD mach = 0; // Return zero on failure
1065  PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER) hInst;
1066  if (pDos->e_lfanew > 0)
1067  {
1068  PIMAGE_NT_HEADERS pHdr = PIMAGE_NT_HEADERS( PBYTE(pDos) + pDos->e_lfanew );
1069  if (LOWORD( pHdr->Signature ) == PE_SIGN) mach = pHdr->FileHeader.Machine;
1070  }
1071  return mach;
1072 }
1073 
1074 bool Is64BitInstance( HINSTANCE hInst )
1075 {
1076  // TODO: Change this to use OptionalHeader.Magic instead of machine Id.
1077  WORD mach = GetInstanceTargetMachine( hInst );
1078  return (mach == IMAGE_FILE_MACHINE_AMD64 || mach == IMAGE_FILE_MACHINE_IA64);
1079 }
1080 
1081 bool Is32BitInstance( HINSTANCE hInst )
1082 {
1083  // TODO: Change this to use OptionalHeader.Magic instead of machine Id.
1084  WORD mach = GetInstanceTargetMachine( hInst );
1085  return (mach == IMAGE_FILE_MACHINE_I386);
1086 }
1087 
1088 // Human readable machine type and subsystem type
1089 // These might belong in a string module, but live here for proximity reasons.
1090 
1091 #ifndef IMAGE_FILE_MACHINE_ALPHA
1092  #define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP
1093  #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64, AXP64
1094 #endif
1095 #ifndef IMAGE_FILE_MACHINE_R3000
1096  #define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian
1097  #define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian
1098  #define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian
1099 #endif
1100 
1102 {
1103  CSTR smach;
1104  switch( Machine )
1105  {
1106  default: smach = _T("Undefined"); break; // Default
1107  case IMAGE_FILE_MACHINE_UNKNOWN: smach = _T("Unknown"); break; // 0
1108  case IMAGE_FILE_MACHINE_I386: smach = _T("32 bit (x86)"); break; // 0x014c // Intel 386.
1109  case IMAGE_FILE_MACHINE_AMD64: smach = _T("64 bit (x64)"); break; // 0x8664 // AMD64 (K8)
1110  case IMAGE_FILE_MACHINE_IA64: smach = _T("64 bit (IA64)"); break; // 0x0200 // Intel 64
1111  #if 1 // PowerPC
1112  case IMAGE_FILE_MACHINE_POWERPC: smach = _T("PowerPC"); break; // 0x01F0 // IBM PowerPC Little-Endian
1113  case IMAGE_FILE_MACHINE_POWERPCFP: smach = _T("PowerPC/FP"); break; // 0x01f1
1114  // Alpha
1115  case IMAGE_FILE_MACHINE_ALPHA: smach = _T("Alpha AXP"); break; // 0x0184 // Alpha_AXP
1116  case IMAGE_FILE_MACHINE_ALPHA64: smach = _T("64 bit (Alpha)"); break; // 0x0284 // ALPHA64, AXP64
1117  #endif
1118  #if 1 // MIPS
1119  case IMAGE_FILE_MACHINE_R3000: smach = _T("Mips R3000"); break; // 0x0162 // MIPS little-endian, 0x160 big-endian
1120  case IMAGE_FILE_MACHINE_R4000: smach = _T("Mips R4000"); break; // 0x0166 // MIPS little-endian
1121  case IMAGE_FILE_MACHINE_R10000: smach = _T("Mips R10000"); break; // 0x0168 // MIPS little-endian
1122  case IMAGE_FILE_MACHINE_WCEMIPSV2: smach = _T("Mips WCEv2"); break; // 0x0169 // MIPS little-endian WCE v2
1123  case IMAGE_FILE_MACHINE_MIPS16: smach = _T("Mips 16"); break; // 0x0266 // MIPS
1124  case IMAGE_FILE_MACHINE_MIPSFPU: smach = _T("Mips/Fpu"); break; // 0x0366 // MIPS
1125  case IMAGE_FILE_MACHINE_MIPSFPU16: smach = _T("Mips/Fpu16"); break; // 0x0466 // MIPS
1126  #endif
1127  #if 0 // Other (mobile devices)
1128  case IMAGE_FILE_MACHINE_SH3: smach = _T("SH3/le"); break; // 0x01a2 // SH3 little-endian
1129  case IMAGE_FILE_MACHINE_SH3DSP: smach = _T("SH3/dsp"); break; // 0x01a3
1130  case IMAGE_FILE_MACHINE_SH3E: smach = _T("SH3E"); break; // 0x01a4 // SH3E little-endian
1131  case IMAGE_FILE_MACHINE_SH4: smach = _T("SH4/le"); break; // 0x01a6 // SH4 little-endian
1132  case IMAGE_FILE_MACHINE_SH5: smach = _T("SH5"); break; // 0x01a8 // SH5
1133  case IMAGE_FILE_MACHINE_ARM: smach = _T("ARM/le"); break; // 0x01c0 // ARM Little-Endian
1134  case IMAGE_FILE_MACHINE_THUMB: smach = _T("Thumb"); break; // 0x01c2
1135  case IMAGE_FILE_MACHINE_AM33: smach = _T("AM33"); break; // 0x01d3
1136  case IMAGE_FILE_MACHINE_TRICORE: smach = _T("TriCore"); break; // 0x0520 // Infineon
1137  case IMAGE_FILE_MACHINE_CEF: smach = _T("CEF"); break; // 0x0CEF
1138  case IMAGE_FILE_MACHINE_EBC: smach = _T("EFI/BC"); break; // 0x0EBC // EFI Byte Code
1139  case IMAGE_FILE_MACHINE_M32R: smach = _T("M32R/le"); break; // 0x9041 // M32R little-endian
1140  case IMAGE_FILE_MACHINE_CEE: smach = _T("CEE"); break; // 0xC0EE
1141  #endif
1142  }
1143  return smach;
1144 }
1145 
1146 #ifndef IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
1147  #define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16
1148 #endif
1149 
1151 {
1152  CSTR ss;
1153  switch( SubSys )
1154  {
1155  default: ss = _T("Undef"); break; // Undefined SubSys code.
1156  case IMAGE_SUBSYSTEM_UNKNOWN: ss = _T("?"); break; //0// Unknown subsystem.
1157  case IMAGE_SUBSYSTEM_NATIVE: ss = _T("Native"); break; //1// Image doesn't require a subsystem.
1158  case IMAGE_SUBSYSTEM_WINDOWS_GUI: ss = _T("GUI"); break; //2// Image runs in the Windows GUI subsystem.
1159  case IMAGE_SUBSYSTEM_WINDOWS_CUI: ss = _T("Con"); break; //3// Image runs in the Windows character subsystem.
1160  case IMAGE_SUBSYSTEM_OS2_CUI: ss = _T("OS2"); break; //5// image runs in the OS/2 character subsystem.
1161  case IMAGE_SUBSYSTEM_POSIX_CUI: ss = _T("Posix"); break; //7// image runs in the Posix character subsystem.
1162  case IMAGE_SUBSYSTEM_NATIVE_WINDOWS: ss = _T("Drv9x"); break; //8// image is a native Win9x driver.
1163  case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: ss = _T("WinCE"); break; //9// Image runs in the Windows CE subsystem.
1164  case IMAGE_SUBSYSTEM_EFI_APPLICATION: ss = _T("EFI App"); break; //10//
1165  case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: ss = _T("EFI Boot"); break; //11//
1166  case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: ss = _T("EFI Drv"); break; //12//
1167  case IMAGE_SUBSYSTEM_EFI_ROM: ss = _T("EFI ROM"); break; //13//
1168  case IMAGE_SUBSYSTEM_XBOX: ss = _T("XBox"); break; //14//
1169  case IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION: ss = _T("Boot"); break; //16//
1170  }
1171  return ss;
1172 }
1173 
1174 // EOF
UINT MultiSzLengthW(WCSTR MultiSz)
Definition: StrFunc.cpp:430
UINT MultiSzLengthA(ACSTR MultiSz)
Definition: StrFunc.cpp:423
HANDLE CloseHandleEx(HANDLE Hnd)
Definition: KernelUtil.cpp:80
_NTFN_EXTERN VOID _RtlDestroyEnvironment(IN PWSTR Environment)
unsigned long DWORD
Definition: Common.h:414
bool ReadNTHeaders(CSTR ExeName, IMAGE_NT_HEADERS *Hdr, bool getOptHdr)
Definition: KernelUtil.cpp:994
PVOID BaseAddress
Definition: NtTypes.h:88
HANDLE CheckHandle(HANDLE Hnd)
Definition: KernelUtil.cpp:75
const char * ACSTR
Definition: Common.h:345
FILETIME AddFiletime(FILETIME Time, const FILETIME Add)
Definition: KernelUtil.cpp:595
UINT DeduplicatePathStr(TSTR Path)
Definition: KernelUtil.cpp:976
bool GetEnvironmentSize(WSTR pwEnv, PUINT pSize, PUINT pUsed)
Definition: KernelUtil.cpp:714
#define CSTR
Definition: Common.h:329
bool IsBadReadWritePtr(const PVOID address, UINT_PTR size)
Definition: KernelUtil.cpp:179
UINT DeduplicateCharSepText(INOUT ASTR Text, CHAR Separator, bool caseSens, bool emitSorted)
CSTR GetMachineStr(WORD Machine)
unsigned short WORD
Definition: Common.h:413
#define IF_DEBUG(code)
Definition: Debug.h:236
HANDLE GetCurrentThreadHandle()
Definition: KernelUtil.cpp:54
bool WaitFor(HANDLE hObj, DWORD msWait)
Definition: KernelUtil.cpp:95
CSTR LocalAtomName(ATOM Atom)
Definition: KernelUtil.cpp:43
bool SetEnvironmentVar(OPTIO WSTR *pwEnv, IN CSTR Name, IN CSTR Value)
Definition: KernelUtil.cpp:841
WSTR CloneEnvironment(OPTOUT PUINT pLength, OPTOUT PUINT pUsed)
Definition: KernelUtil.cpp:747
#define IMAGE_FILE_MACHINE_R10000
#define DP_DEBUG
Definition: Debug.h:85
wchar_t * WSTR
Definition: Common.h:366
#define BEGIN_STRSAFE_OVERRIDE
Definition: StrFunc.h:28
#define TSTR
Definition: Common.h:328
unsigned char * PBYTE
Definition: Common.h:412
#define IMAGE_FILE_MACHINE_ALPHA64
char * ASTR
Definition: Common.h:344
#define dimof(x)
Definition: Common.h:949
#define END_NAMESPACE(name)
Definition: Common.h:225
#define OPTOUT
Definition: Common.h:264
void __cdecl DPrint(int Level, CSTR Fmt,...)
Definition: Debug.cpp:134
FILETIME MakeDateTime(WORD Year, WORD Month, WORD Day, WORD Hr, WORD Min, WORD Sec)
Definition: KernelUtil.cpp:606
HANDLE CreateCapturedProcessEx(OPTIN CSTR ExePath, OPTIN CSTR CmdLn, OPTIN CSTR EnvStr, OPTIN CSTR WorkDir, IN LPSTARTUPINFO pSI, IN DWORD Flags, OPTOUT PHANDLE pRdHnd, OPTOUT PHANDLE pWrHnd, OPTOUT PHANDLE pErrHnd, OPTOUT PHANDLE phThread)
Definition: KernelUtil.cpp:273
CSTR GlobalAtomName(ATOM Atom)
Definition: KernelUtil.cpp:36
HANDLE GetCurrentProcessHandle()
Definition: KernelUtil.cpp:62
#define TRACE(_lvl,...)
Definition: Debug.h:216
UINT GetProcDllData(HANDLE hProcess, WCSTR DllName, OUT PLDR_MODULE pModule, bool Localize)
WORD GetInstanceTargetMachine(HINSTANCE hInst)
#define OPTHDR_SIZE
SHORT LoadCount
Definition: NtTypes.h:94
WORD GetTargetMachine(CSTR ExeName)
bool operator >(FILETIME const &A, FILETIME const &B)
Definition: KernelUtil.cpp:625
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
WSTR FreeEnvironment(WSTR Env)
Definition: KernelUtil.cpp:797
#define IMAGE_FILE_MACHINE_ALPHA
END_STRSAFE_OVERRIDE HANDLE GlobalUnlockedHandle(PVOID Ptr, PUINT pCount)
Definition: KernelUtil.cpp:156
UINT GlobalPurgeAtom(CSTR Name)
Definition: KernelUtil.cpp:23
SHORT GetProcDLLRefCount(HANDLE hProcess, WCSTR DllName)
Definition: KernelUtil.cpp:520
#define __except_execute
Definition: Common.h:647
UINT PrependString(INOUT TSTR String, UINT ccBuf, OPTIN TCHAR Sep, CSTR Prolog)
_NTFN_EXTERN NTSTATUS _RtlSetEnvironmentVariable(IN PWSTR *Environment, IN PUNICODE_STRING Name, IN PUNICODE_STRING Value)
const wchar_t * WCSTR
Definition: Common.h:367
WSTR GlobalAllocStrW(UINT Count)
Definition: KernelUtil.cpp:112
#define IMAGE_FILE_MACHINE_R3000
HMODULE GetOrLoadModule(CSTR modName)
Definition: KernelUtil.cpp:376
UINT AppendString(INOUT TSTR String, UINT ccBuf, OPTIN TCHAR Sep, CSTR Epilog)
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
#define mem_AllocStr
Definition: StrFunc.h:142
void * mem_Free(void *pBlk)
Definition: MemFunc.cpp:124
SYSTEMTIME * SystemTimeToLocalTime(SYSTEMTIME *Time)
Definition: KernelUtil.cpp:660
#define _BAD_HANDLE
Definition: Common.h:997
bool operator >=(FILETIME const &A, FILETIME const &B)
Definition: KernelUtil.cpp:640
BEGIN_STRSAFE_OVERRIDE ASTR GlobalDupStrA(ACSTR Str, bool isMulti)
Definition: KernelUtil.cpp:119
Definition: DynArray.h:18
WSTR mem_AllocWStr(WORD nChar)
Definition: StrFunc.cpp:264
bool SetLastErrorFromNtStatus(NTSTATUS Status)
Definition: Debug.cpp:74
bool operator<=(FILETIME const &A, FILETIME const &B)
Definition: KernelUtil.cpp:644
CSTR SysErrorMsg(DWORD Err=0, TSTR Buf=NULL, UINT Length=0)
Definition: Debug.cpp:39
HANDLE CloseCapturedProcess(IN HANDLE hProc, IN LPSTARTUPINFO pSi, IN PHANDLE pRdHnd, IN PHANDLE pWrHnd, IN PHANDLE pErrHnd)
Definition: KernelUtil.cpp:337
#define OPTIO
Definition: Common.h:265
const FILETIME NullFileTime
Definition: KernelUtil.cpp:547
unsigned __int64 UINT64
Definition: Common.h:400
UTC : GetSystemTime().
Definition: UtilFunc.h:712
SECURITY_ATTRIBUTES DefSec
Definition: Common.cpp:20
UINT ModifyEnvironmentVar(WSTR *pwEnv, BYTE Option, CSTR Name, CSTR Addendum, TCHAR Sep)
Definition: KernelUtil.cpp:921
HMODULE GetProcDLLHandle(HANDLE hProcess, WCSTR DllName)
Definition: KernelUtil.cpp:531
ASTR GlobalAllocStrA(UINT Count)
Definition: KernelUtil.cpp:108
GetLocalTime().
Definition: UtilFunc.h:711
#define DP_ERROR
Definition: Debug.h:82
SYSTEMTIME * LocalTimeToSystemTime(SYSTEMTIME *Time)
Definition: KernelUtil.cpp:676
UINT BlockRead(HANDLE hFile, PVOID Buf, UINT nBytes)
Definition: IoUtil.cpp:417
bool GetEnvironmentVar(OPTIN WSTR pwEnv, IN CSTR Name, OUT TSTR Value, INOUT PUINT ccValBuf)
Definition: KernelUtil.cpp:867
#define MK_TWOCC(S2)
Definition: Common.h:457
Debug and error handling support.
_NTFN_EXTERN NTSTATUS _RtlCreateEnvironment(IN BOOLEAN Clone, OUT PWSTR *Environment)
FILETIME FileTimeToLocalTime(FILETIME utc)
Definition: KernelUtil.cpp:692
CSTR GetSubSystemStr(WORD SubSys)
#define BEGIN_NAMESPACE(name)
Definition: Common.h:224
Common include; Added types, small "ubiquitous" utilities, et c.
bool operator<(FILETIME const &A, FILETIME const &B)
Definition: KernelUtil.cpp:630
FILETIME Now(eTimeType Domain=LOCAL_TIME)
Definition: KernelUtil.cpp:549
bool Is32BitInstance(HINSTANCE hInst)
HMODULE LoadProcLibrary(HANDLE hProc, LPCSTR DllPathName, DWORD msWait)
Definition: KernelUtil.cpp:397
unsigned short * PWORD
Definition: Common.h:413
FILETIME AddTime(IN FILETIME Time, SHORT Hr, SHORT Min, SHORT Sec, SHORT mSec)
#define _F(s)
Definition: Debug.h:49
eTimeType
Definition: UtilFunc.h:709
bool Is64BitInstance(HINSTANCE hInst)
bool operator==(FILETIME const &A, FILETIME const &B)
Definition: KernelUtil.cpp:635
#define BAD_HANDLE(hnd)
Definition: Common.h:1004
WSTR GlobalDupStrW(WCSTR Str, bool isMulti)
Definition: KernelUtil.cpp:142
bool Is64BitExecutable(CSTR ExeName)
#define WCHAR_SIZE
Definition: Common.h:379
#define ROUND_UP2(x, chunk)
Definition: Common.h:984
ModifyEnvironmentVar() prepends the Addendum.
Definition: UtilFunc.h:866
BOOL UnloadProcLibrary(HANDLE hProc, HMODULE hLib, DWORD msWait)
Definition: KernelUtil.cpp:483
#define LITERAL(type, x)
Definition: Common.h:969
#define NT_SUCCESS(Status)
Definition: Common.h:154
#define FHDR_SIZE
#define DP_VERBOSE
Definition: Debug.h:86
HANDLE Launch(CSTR exePath, CSTR cmdLn, CSTR startDir, int iShow, DWORD Flags)
Definition: KernelUtil.cpp:188
#define END_STRSAFE_OVERRIDE
Definition: StrFunc.h:29
HANDLE CreateCapturedProcess(IN CSTR cmdLn, IN LPSTARTUPINFO si, IN DWORD Flags, OPTOUT PHANDLE pRdHnd, OPTOUT PHANDLE pWrHnd, OPTOUT PHANDLE pErrHnd, OPTOUT PHANDLE phThread)
Definition: KernelUtil.cpp:218
bool Seek(HANDLE hFile, LONG Offs, DWORD How)
Definition: IoUtil.cpp:316
#define DP_WARNING
Definition: Debug.h:83
#define SEMICOLON
Definition: Common.h:1223
unsigned char BYTE
Definition: Common.h:412
bool __forceinline IsString(CSTR Str)
Definition: StrFunc.h:84
HANDLE TerminateCapturedProcess(IN HANDLE hProc, IN LPSTARTUPINFO pSi, IN PHANDLE pRdHnd, IN PHANDLE pWrHnd, IN PHANDLE pErrHnd, IN UINT retCode)
Definition: KernelUtil.cpp:357
bool operator !=(FILETIME const &A, FILETIME const &B)
Definition: KernelUtil.cpp:648
#define IMAGE_FILE_MACHINE_R4000
#define OPTIN
Definition: Common.h:263
#define INOUT
Definition: Common.h:262