Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

593 lines
18 KiB

  1. /********************************************************************
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. pfrutil.h
  5. Abstract:
  6. PFR utility stuff
  7. Revision History:
  8. DerekM created 05/01/99
  9. ********************************************************************/
  10. #ifndef PFRUTIL_H
  11. #define PFRUTIL_H
  12. // this turns on the manifest mode heap collection
  13. #define MANIFEST_HEAP
  14. // make sure both _DEBUG & DEBUG are defined if one is defined. Otherwise
  15. // the ASSERT macro never does anything
  16. #if defined(_DEBUG) && !defined(DEBUG)
  17. #define DEBUG 1
  18. #endif
  19. #if defined(DEBUG) && !defined(_DEBUG)
  20. #define _DEBUG 1
  21. #endif
  22. #include "dbgtrace.h"
  23. ////////////////////////////////////////////////////////////////////////////
  24. // tracing wrappers
  25. // can't call HRESULT_FROM_WIN32 with a fn as a parameter cuz it is a macro
  26. // and evaluates the expression 3 times. This is a particularlly bad thing
  27. // when u don't look at macros first to see what they do.
  28. inline HRESULT ChangeErrToHR(DWORD dwErr) { return HRESULT_FROM_WIN32(dwErr); }
  29. #if defined(NOTRACE)
  30. #define INIT_TRACING
  31. #define TERM_TRACING
  32. #define USE_TRACING(sz)
  33. #define DBG_MSG(sz)
  34. #define TESTHR(hr, fn) \
  35. hr = (fn);
  36. #define TESTBOOL(hr, fn) \
  37. hr = ((fn) ? NOERROR : HRESULT_FROM_WIN32(GetLastError()));
  38. #define TESTERR(hr, fn) \
  39. SetLastError((fn)); \
  40. hr = HRESULT_FROM_WIN32(GetLastError());
  41. #define VALIDATEPARM(hr, expr) \
  42. hr = ((expr) ? E_INVALIDARG : NOERROR);
  43. #define VALIDATEEXPR(hr, expr, hrErr) \
  44. hr = ((expr) ? (hrErr) : NOERROR);
  45. #else
  46. #define INIT_TRACING \
  47. InitAsyncTrace();
  48. #define TERM_TRACING \
  49. TermAsyncTrace();
  50. #define USE_TRACING(sz) \
  51. TraceQuietEnter(sz); \
  52. TraceFunctEntry(sz); \
  53. DWORD __dwtraceGLE = GetLastError(); \
  54. #define DBG_MSG(sz) \
  55. ErrorTrace(0, sz)
  56. #define TESTHR(hr, fn) \
  57. if (FAILED(hr = (fn))) \
  58. { \
  59. __dwtraceGLE = GetLastError(); \
  60. ErrorTrace(0, "%s failed. Err: 0x%08x", #fn, hr); \
  61. SetLastError(__dwtraceGLE); \
  62. } \
  63. #define TESTBOOL(hr, fn) \
  64. hr = NOERROR; \
  65. if ((fn) == FALSE) \
  66. { \
  67. __dwtraceGLE = GetLastError(); \
  68. hr = HRESULT_FROM_WIN32(__dwtraceGLE); \
  69. ErrorTrace(0, "%s failed. Err: 0x%08x", #fn, __dwtraceGLE); \
  70. SetLastError(__dwtraceGLE); \
  71. }
  72. #define TESTERR(hr, fn) \
  73. SetLastError((fn)); \
  74. if (FAILED(hr = HRESULT_FROM_WIN32(GetLastError()))) \
  75. { \
  76. __dwtraceGLE = GetLastError(); \
  77. ErrorTrace(0, "%s failed. Err: %d", #fn, __dwtraceGLE); \
  78. SetLastError(__dwtraceGLE); \
  79. }
  80. #define VALIDATEPARM(hr, expr) \
  81. if (expr) \
  82. { \
  83. ErrorTrace(0, "Invalid parameters passed to %s", \
  84. ___pszFunctionName); \
  85. SetLastError(ERROR_INVALID_PARAMETER); \
  86. hr = E_INVALIDARG; \
  87. } \
  88. else hr = NOERROR;
  89. #define VALIDATEEXPR(hr, expr, hrErr) \
  90. if (expr) \
  91. { \
  92. ErrorTrace(0, "Expression failure %s", #expr); \
  93. hr = (hrErr); \
  94. } \
  95. else hr = NOERROR;
  96. #endif
  97. ////////////////////////////////////////////////////////////////////////////
  98. // Memory
  99. #if defined(DEBUG) || defined(_DEBUG)
  100. // this structure must ALWAYS be 8 byte aligned. Add padding to the end if
  101. // it isn't.
  102. struct SMyMemDebug
  103. {
  104. __int64 hHeap;
  105. __int64 cb;
  106. DWORD dwTag;
  107. DWORD dwChk;
  108. };
  109. #endif
  110. extern HANDLE g_hPFPrivateHeap;
  111. // **************************************************************************
  112. inline HANDLE MyHeapCreate(SIZE_T cbInitial = 8192, SIZE_T cbMax = 0)
  113. {
  114. return HeapCreate(0, cbInitial, cbMax);
  115. }
  116. // **************************************************************************
  117. inline BOOL MyHeapDestroy(HANDLE hHeap)
  118. {
  119. return HeapDestroy(hHeap);
  120. }
  121. // **************************************************************************
  122. inline LPVOID MyAlloc(SIZE_T cb, HANDLE hHeap = NULL, BOOL fZero = TRUE)
  123. {
  124. #if defined(DEBUG) || defined(_DEBUG)
  125. SMyMemDebug *psmmd;
  126. LPBYTE pb;
  127. cb += (sizeof(SMyMemDebug) + 4);
  128. hHeap = (hHeap != NULL) ? hHeap : GetProcessHeap();
  129. pb = (LPBYTE)HeapAlloc(hHeap, ((fZero) ? HEAP_ZERO_MEMORY : 0), cb);
  130. if (pb != NULL)
  131. {
  132. psmmd = (SMyMemDebug *)pb;
  133. psmmd->hHeap = (__int64)hHeap;
  134. psmmd->cb = (__int64)cb;
  135. psmmd->dwTag = 0xBCBCBCBC;
  136. psmmd->dwChk = 0xBCBCBCBC;
  137. // do this cuz it's easier than figuring out the alignment and
  138. // manually converting it to a 4 byte aligned value
  139. *(pb + cb - 4) = 0xBC;
  140. *(pb + cb - 3) = 0xBC;
  141. *(pb + cb - 2) = 0xBC;
  142. *(pb + cb - 1) = 0xBC;
  143. pb = (PBYTE)pb + sizeof(SMyMemDebug);
  144. }
  145. return pb;
  146. #else
  147. return HeapAlloc(((hHeap != NULL) ? hHeap : GetProcessHeap()),
  148. ((fZero) ? HEAP_ZERO_MEMORY : 0), cb);
  149. #endif
  150. }
  151. // **************************************************************************
  152. inline LPVOID MyReAlloc(LPVOID pv, SIZE_T cb, HANDLE hHeap = NULL,
  153. BOOL fZero = TRUE)
  154. {
  155. #if defined(DEBUG) || defined(_DEBUG)
  156. SMyMemDebug *psmmd;
  157. SIZE_T cbOld;
  158. LPBYTE pbNew;
  159. LPBYTE pb = (LPBYTE)pv;
  160. // if this is NULL, force a call to HeapReAlloc so that it can set the
  161. // proper error for GLE to fetch
  162. if (pv == NULL)
  163. {
  164. SetLastError(0);
  165. return NULL;
  166. }
  167. pb -= sizeof(SMyMemDebug);
  168. hHeap = (hHeap != NULL) ? hHeap : GetProcessHeap();
  169. // wrap this in a try block in case the memory was not allocated
  170. // by us or is corrupted- in which case the following could
  171. // cause an AV.
  172. __try
  173. {
  174. psmmd = (SMyMemDebug *)pb;
  175. cbOld = (SIZE_T)psmmd->cb;
  176. _ASSERT(psmmd->hHeap == (__int64)hHeap);
  177. _ASSERT(psmmd->dwTag == 0xBCBCBCBC);
  178. _ASSERT(psmmd->dwChk == 0xBCBCBCBC);
  179. // do this cuz it's easier than figuring out the alignment and
  180. // manually converting it to a 4 byte aligned value
  181. _ASSERT(*(pb + cbOld - 4) == 0xBC);
  182. _ASSERT(*(pb + cbOld - 3) == 0xBC);
  183. _ASSERT(*(pb + cbOld - 2) == 0xBC);
  184. _ASSERT(*(pb + cbOld - 1) == 0xBC);
  185. if (psmmd->hHeap != (__int64)hHeap)
  186. hHeap = (HANDLE)(DWORD_PTR)psmmd->hHeap;
  187. }
  188. __except(EXCEPTION_EXECUTE_HANDLER)
  189. {
  190. _ASSERT(FALSE);
  191. }
  192. hHeap = *((HANDLE *)pb);
  193. cb += (sizeof(SMyMemDebug) + 4);
  194. pbNew = (LPBYTE)HeapReAlloc(hHeap, ((fZero) ? HEAP_ZERO_MEMORY : 0), pb, cb);
  195. if (pbNew != NULL)
  196. {
  197. psmmd = (SMyMemDebug *)pb;
  198. psmmd->hHeap = (__int64)hHeap;
  199. psmmd->cb = (__int64)cb;
  200. psmmd->dwTag = 0xBCBCBCBC;
  201. psmmd->dwChk = 0xBCBCBCBC;
  202. // do this cuz it's easier than figuring out the alignment and
  203. // manually converting it to a 4 byte aligned value
  204. *(pb + cb - 4) = 0xBC;
  205. *(pb + cb - 3) = 0xBC;
  206. *(pb + cb - 2) = 0xBC;
  207. *(pb + cb - 1) = 0xBC;
  208. pb = (PBYTE)pb + sizeof(SMyMemDebug);
  209. }
  210. return pv;
  211. #else
  212. return HeapReAlloc(((hHeap != NULL) ? hHeap : GetProcessHeap()),
  213. ((fZero) ? HEAP_ZERO_MEMORY : 0), pv, cb);
  214. #endif
  215. }
  216. // **************************************************************************
  217. inline BOOL MyFree(LPVOID pv, HANDLE hHeap = NULL)
  218. {
  219. #if defined(DEBUG) || defined(_DEBUG)
  220. SMyMemDebug *psmmd;
  221. SIZE_T cbOld;
  222. HANDLE hAllocHeap;
  223. LPBYTE pb = (LPBYTE)pv;
  224. // if this is NULL, force a call to HeapFree so that it can set the
  225. // proper error for GLE to fetch
  226. if (pv == NULL)
  227. return TRUE;
  228. pb -= sizeof(SMyMemDebug);
  229. hHeap = (hHeap != NULL) ? hHeap : GetProcessHeap();
  230. // wrap this in a try block in case the memory was not allocated
  231. // by us or is corrupted- in which case the following could
  232. // cause an AV.
  233. __try
  234. {
  235. psmmd = (SMyMemDebug *)pb;
  236. cbOld = (SIZE_T)psmmd->cb;
  237. _ASSERT(psmmd->hHeap == (__int64)hHeap);
  238. _ASSERT(psmmd->dwTag == 0xBCBCBCBC);
  239. _ASSERT(psmmd->dwChk == 0xBCBCBCBC);
  240. // do this cuz it's easier than figuring out the alignment and
  241. // manually converting it to a 4 byte aligned value
  242. _ASSERT(*(pb + cbOld - 4) == 0xBC);
  243. _ASSERT(*(pb + cbOld - 3) == 0xBC);
  244. _ASSERT(*(pb + cbOld - 2) == 0xBC);
  245. _ASSERT(*(pb + cbOld - 1) == 0xBC);
  246. if (psmmd->hHeap != (__int64)hHeap)
  247. hHeap = (HANDLE)(DWORD_PTR)psmmd->hHeap;
  248. }
  249. __except(EXCEPTION_EXECUTE_HANDLER)
  250. {
  251. _ASSERT(FALSE);
  252. }
  253. FillMemory(pb, cbOld, 0xCB);
  254. return HeapFree(hHeap, 0, pb);
  255. #else
  256. return HeapFree(((hHeap != NULL) ? hHeap : GetProcessHeap()), 0, pv);
  257. #endif
  258. }
  259. ////////////////////////////////////////////////////////////////////////////
  260. // useful inlines / defines
  261. // **************************************************************************
  262. inline DWORD MyMax(DWORD a, DWORD b)
  263. {
  264. return (a > b) ? a : b;
  265. }
  266. // **************************************************************************
  267. inline DWORD MyMin(DWORD a, DWORD b)
  268. {
  269. return (a <= b) ? a : b;
  270. }
  271. #define Err2HR(dwErr) HRESULT_FROM_WIN32(dwErr)
  272. #define sizeofSTRW(wsz) sizeof(wsz) / sizeof(WCHAR)
  273. ////////////////////////////////////////////////////////////////////////////
  274. // Files
  275. const WCHAR c_wszDirSuffix[] = L".dir00";
  276. HRESULT OpenFileMapped(LPWSTR wszFile, LPVOID *ppvFile, DWORD *pcbFile);
  277. HRESULT DeleteTempFile(LPWSTR wszFile);
  278. HRESULT MyCallNamedPipe(LPCWSTR wszPipe, LPVOID pvIn, DWORD cbIn,
  279. LPVOID pvOut, DWORD cbOut, DWORD *pcbRead,
  280. DWORD dwWaitPipe, DWORD dwWaitRead = INFINITE);
  281. DWORD CreateTempDirAndFile(LPCWSTR wszTempDir, LPCWSTR wszName,
  282. LPWSTR *pwszPath);
  283. BOOL DeleteTempDirAndFile(LPCWSTR wszPath, BOOL fFilePresent);
  284. #ifdef MANIFEST_HEAP
  285. BOOL DeleteFullAndTriageMiniDumps(LPCWSTR wszPath);
  286. #endif // MANIFEST_HEAP
  287. ////////////////////////////////////////////////////////////////////////////
  288. // Security
  289. BOOL AllocSD(SECURITY_DESCRIPTOR *psd, DWORD dwOLs, DWORD dwAd, DWORD dwWA);
  290. void FreeSD(SECURITY_DESCRIPTOR *psd);
  291. BOOL IsUserAnAdmin(HANDLE hToken);
  292. ////////////////////////////////////////////////////////////////////////////
  293. // Registry
  294. enum EPFORK
  295. {
  296. orkWantWrite = 0x1,
  297. orkUseWOW64 = 0x2,
  298. };
  299. HRESULT OpenRegKey(HKEY hkeyMain, LPCWSTR wszSubKey, DWORD dwOpt, HKEY *phkey);
  300. HRESULT ReadRegEntry(HKEY hkey, LPCWSTR szValName, DWORD *pdwType,
  301. PBYTE pbBuffer, DWORD *pcbBuffer, PBYTE pbDefault,
  302. DWORD cbDefault);
  303. HRESULT ReadRegEntry(HKEY *rghkey, DWORD cKeys, LPCWSTR wszValName,
  304. DWORD *pdwType, PBYTE pbBuffer, DWORD *pcbBuffer,
  305. PBYTE pbDefault, DWORD cbDefault, DWORD *piKey = NULL);
  306. ////////////////////////////////////////////////////////////////////////////
  307. // version info
  308. #define APP_WINCOMP 0x1
  309. #define APP_MSAPP 0x2
  310. DWORD IsMicrosoftApp(LPWSTR wszAppPath, PBYTE pbAppInfo, DWORD cbAppInfo);
  311. ////////////////////////////////////////////////////////////////////////////
  312. // String
  313. WCHAR *MyStrStrIW(const WCHAR *wcs1, const WCHAR *wcs2);
  314. CHAR *MyStrStrIA(const CHAR *cs1, const CHAR *cs2);
  315. HRESULT MyURLEncode(LPWSTR wszDest, DWORD cchDest, LPWSTR wszSrc);
  316. ////////////////////////////////////////////////////////////////////////////
  317. // CPFGenericClassBase
  318. class CPFGenericClassBase
  319. {
  320. public:
  321. // CPFGenericClassBase(void) {}
  322. // virtual ~CPFGenericClassBase(void) {}
  323. void *operator new(size_t size)
  324. {
  325. return MyAlloc(size, NULL, FALSE);
  326. }
  327. void operator delete(void *pvMem)
  328. {
  329. if (pvMem != NULL)
  330. MyFree(pvMem, NULL);
  331. }
  332. };
  333. class CPFPrivHeapGenericClassBase
  334. {
  335. public:
  336. // CPFGenericClassBase(void) {}
  337. // virtual ~CPFGenericClassBase(void) {}
  338. void *operator new(size_t size)
  339. {
  340. return MyAlloc(size, g_hPFPrivateHeap, FALSE);
  341. }
  342. void operator delete(void *pvMem)
  343. {
  344. if (pvMem != NULL)
  345. MyFree(pvMem, g_hPFPrivateHeap);
  346. }
  347. };
  348. ////////////////////////////////////////////////////////////////////////////
  349. // CAutoUnlockCS
  350. // This class wrappers a critical section. It will automatically unlock the
  351. // CS when the class destructs (assuming it is locked)
  352. // NOTE: this object is intended to be used only as a local variable of a
  353. // function, not as a global variable or class member.
  354. class CAutoUnlockCS
  355. {
  356. private:
  357. #if defined(DEBUG) || defined(_DEBUG)
  358. DWORD m_dwOwningThread;
  359. #endif
  360. CRITICAL_SECTION *m_pcs;
  361. DWORD m_cLocks;
  362. public:
  363. CAutoUnlockCS(CRITICAL_SECTION *pcs, BOOL fTakeLock = FALSE)
  364. {
  365. m_pcs = pcs;
  366. m_cLocks = 0;
  367. #if defined(DEBUG) || defined(_DEBUG)
  368. m_dwOwningThread = 0;
  369. #endif
  370. if (fTakeLock)
  371. this->Lock();
  372. }
  373. ~CAutoUnlockCS(void)
  374. {
  375. _ASSERT(m_cLocks <= 1);
  376. if (m_pcs != NULL)
  377. {
  378. #if defined(DEBUG) || defined(_DEBUG)
  379. if (m_cLocks > 0)
  380. _ASSERT(m_dwOwningThread == GetCurrentThreadId());
  381. #endif
  382. while(m_cLocks > 0)
  383. {
  384. LeaveCriticalSection(m_pcs);
  385. m_cLocks--;
  386. }
  387. }
  388. }
  389. void Lock(void)
  390. {
  391. if (m_pcs != NULL)
  392. {
  393. EnterCriticalSection(m_pcs);
  394. m_cLocks++;
  395. #if defined(DEBUG) || defined(_DEBUG)
  396. m_dwOwningThread = GetCurrentThreadId();
  397. #endif
  398. }
  399. }
  400. void Unlock(void)
  401. {
  402. _ASSERT(m_cLocks > 0);
  403. _ASSERT(m_dwOwningThread == GetCurrentThreadId());
  404. if (m_pcs != NULL && m_cLocks > 0)
  405. {
  406. m_cLocks--;
  407. LeaveCriticalSection(m_pcs);
  408. }
  409. #if defined(DEBUG) || defined(_DEBUG)
  410. if (m_cLocks == 0)
  411. m_dwOwningThread = 0;
  412. #endif
  413. }
  414. };
  415. ////////////////////////////////////////////////////////////////////////////
  416. // CAutoUnlockMutex
  417. // This class wrappers a mutex. It will automatically unlock the
  418. // mutex when the class destructs (assuming it is owned)
  419. // NOTE: this object is intended to be used only as a local variable of a
  420. // function, not as a global variable or class member.
  421. class CAutoUnlockMutex
  422. {
  423. private:
  424. #if defined(DEBUG) || defined(_DEBUG)
  425. DWORD m_dwOwningThread;
  426. #endif
  427. HANDLE m_hmut;
  428. DWORD m_cLocks;
  429. public:
  430. CAutoUnlockMutex(HANDLE hmut, BOOL fTakeLock = FALSE)
  431. {
  432. m_hmut = hmut;
  433. m_cLocks = 0;
  434. #if defined(DEBUG) || defined(_DEBUG)
  435. m_dwOwningThread = 0;
  436. #endif
  437. if (fTakeLock)
  438. this->Lock();
  439. }
  440. ~CAutoUnlockMutex(void)
  441. {
  442. _ASSERT(m_cLocks <= 1);
  443. if (m_hmut != NULL)
  444. {
  445. #if defined(DEBUG) || defined(_DEBUG)
  446. if (m_cLocks > 0)
  447. _ASSERT(m_dwOwningThread == GetCurrentThreadId());
  448. #endif
  449. while(m_cLocks > 0)
  450. {
  451. ReleaseMutex(m_hmut);
  452. m_cLocks--;
  453. }
  454. }
  455. }
  456. BOOL Lock(DWORD dwTimeout = INFINITE)
  457. {
  458. if (m_hmut != NULL)
  459. {
  460. if (WaitForSingleObject(m_hmut, dwTimeout) != WAIT_OBJECT_0)
  461. return FALSE;
  462. m_cLocks++;
  463. #if defined(DEBUG) || defined(_DEBUG)
  464. m_dwOwningThread = GetCurrentThreadId();
  465. #endif
  466. }
  467. return TRUE;
  468. }
  469. void Unlock(void)
  470. {
  471. _ASSERT(m_cLocks > 0);
  472. _ASSERT(m_dwOwningThread == GetCurrentThreadId());
  473. if (m_hmut != NULL && m_cLocks > 0)
  474. {
  475. m_cLocks--;
  476. ReleaseMutex(m_hmut);
  477. }
  478. }
  479. };
  480. #endif