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.

766 lines
22 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. common.c
  5. Abstract:
  6. Utility routines used by Lodctr and/or UnLodCtr
  7. Author:
  8. Bob Watson (a-robw) 12 Feb 93
  9. Revision History:
  10. --*/
  11. #define UNICODE 1
  12. #define _UNICODE 1
  13. //
  14. // "C" Include files
  15. //
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <locale.h>
  20. //
  21. // Windows Include files
  22. //
  23. #include <nt.h>
  24. #include <ntrtl.h>
  25. #include <nturtl.h>
  26. #include <windows.h>
  27. #include <accctrl.h>
  28. #include <aclapi.h>
  29. #include <winperf.h>
  30. #include <tchar.h>
  31. #include <initguid.h>
  32. #include <guiddef.h>
  33. #include "wmistr.h"
  34. #include "evntrace.h"
  35. //
  36. // local include files
  37. //
  38. #define _INIT_WINPERFP_
  39. #include "winperfp.h"
  40. #include "ldprfmsg.h"
  41. #include "common.h"
  42. //
  43. //
  44. // Text string Constant definitions
  45. //
  46. LPCTSTR NamesKey = (LPCTSTR)TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib");
  47. LPCTSTR DefaultLangId = (LPCTSTR)TEXT("009");
  48. LPCTSTR DefaultLangTag = (LPCTSTR)TEXT("000");
  49. LPCTSTR Counters = (LPCTSTR)TEXT("Counters");
  50. LPCTSTR Help = (LPCTSTR)TEXT("Help");
  51. LPCTSTR VersionStr = (LPCTSTR)TEXT("Version");
  52. LPCTSTR LastHelp = (LPCTSTR)TEXT("Last Help");
  53. LPCTSTR LastCounter = (LPCTSTR)TEXT("Last Counter");
  54. LPCTSTR FirstHelp = (LPCTSTR)TEXT("First Help");
  55. LPCTSTR cszFirstCounter = (LPCTSTR)TEXT("First Counter");
  56. LPCTSTR Busy = (LPCTSTR)TEXT("Updating");
  57. LPCTSTR Slash = (LPCTSTR)TEXT("\\");
  58. LPCTSTR BlankString = (LPCTSTR)TEXT(" ");
  59. LPCTSTR DriverPathRoot = (LPCTSTR)TEXT("SYSTEM\\CurrentControlSet\\Services");
  60. LPCTSTR Performance = (LPCTSTR)TEXT("Performance");
  61. LPCTSTR CounterNameStr = (LPCTSTR)TEXT("Counter ");
  62. LPCTSTR HelpNameStr = (LPCTSTR)TEXT("Explain ");
  63. LPCTSTR AddCounterNameStr = (LPCTSTR)TEXT("Addcounter ");
  64. LPCTSTR AddHelpNameStr = (LPCTSTR)TEXT("Addexplain ");
  65. LPCTSTR szObjectList = (LPCTSTR)TEXT("Object List");
  66. LPCTSTR szLibraryValidationCode = (LPCTSTR)TEXT("Library Validation Code");
  67. LPCTSTR szDisplayName = (LPCTSTR) TEXT("DisplayName");
  68. LPCTSTR szPerfIniPath = (LPCTSTR) TEXT("PerfIni");
  69. BOOLEAN g_bCheckTraceLevel = FALSE;
  70. // Global (to this module) Buffers
  71. //
  72. static TCHAR DisplayStringBuffer[DISP_BUFF_SIZE];
  73. static TCHAR TextFormat[DISP_BUFF_SIZE];
  74. static HANDLE hMod = NULL; // process handle
  75. static DWORD dwLastError = ERROR_SUCCESS;
  76. HANDLE hEventLog = NULL;
  77. HANDLE hLoadPerfMutex = NULL;
  78. //
  79. // local static data
  80. //
  81. static TCHAR cDoubleQuote = TEXT('\"');
  82. BOOL
  83. __stdcall
  84. DllEntryPoint(
  85. IN HANDLE DLLHandle,
  86. IN DWORD Reason,
  87. IN LPVOID ReservedAndUnused
  88. )
  89. {
  90. BOOL bReturn = FALSE;
  91. ReservedAndUnused;
  92. DisableThreadLibraryCalls (DLLHandle);
  93. switch(Reason) {
  94. case DLL_PROCESS_ATTACH:
  95. setlocale(LC_ALL, ".OCP");
  96. hMod = DLLHandle; // use DLL handle , not APP handle
  97. // register eventlog source
  98. hEventLog = RegisterEventSourceW (
  99. NULL, (LPCWSTR)L"LoadPerf");
  100. bReturn = TRUE;
  101. break;
  102. case DLL_PROCESS_DETACH:
  103. if (hEventLog != NULL) {
  104. if (DeregisterEventSource(hEventLog)) {
  105. hEventLog = NULL;
  106. }
  107. }
  108. if (hLoadPerfMutex != NULL) {
  109. CloseHandle(hLoadPerfMutex);
  110. hLoadPerfMutex = NULL;
  111. }
  112. bReturn = TRUE;
  113. break;
  114. case DLL_THREAD_ATTACH:
  115. case DLL_THREAD_DETACH:
  116. bReturn = TRUE;
  117. break;
  118. }
  119. return bReturn;
  120. }
  121. LPCTSTR
  122. GetStringResource (
  123. UINT wStringId
  124. )
  125. /*++
  126. Retrived UNICODE strings from the resource file for display
  127. --*/
  128. {
  129. if (!hMod) {
  130. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  131. }
  132. if (hMod) {
  133. if ((LoadString(hMod, wStringId, DisplayStringBuffer, DISP_BUFF_SIZE)) > 0) {
  134. return (LPTSTR)&DisplayStringBuffer[0];
  135. } else {
  136. dwLastError = GetLastError();
  137. return BlankString;
  138. }
  139. } else {
  140. return BlankString;
  141. }
  142. }
  143. LPCWSTR
  144. GetFormatResource (
  145. UINT wStringId
  146. )
  147. /*++
  148. Returns an ANSI string for use as a format string in a printf fn.
  149. --*/
  150. {
  151. if (!hMod) {
  152. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  153. }
  154. if (hMod) {
  155. if ((LoadStringW(hMod, wStringId, TextFormat, DISP_BUFF_SIZE)) > 0) {
  156. return (LPCTSTR)&TextFormat[0];
  157. } else {
  158. dwLastError = GetLastError();
  159. return BlankString;
  160. }
  161. } else {
  162. return BlankString;
  163. }
  164. }
  165. VOID
  166. DisplayCommandHelp (
  167. UINT iFirstLine,
  168. UINT iLastLine
  169. )
  170. /*++
  171. DisplayCommandHelp
  172. displays usage of command line arguments
  173. Arguments
  174. NONE
  175. Return Value
  176. NONE
  177. --*/
  178. {
  179. UINT iThisLine;
  180. WCHAR StringBuffer[DISP_BUFF_SIZE];
  181. CHAR OemStringBuffer[DISP_BUFF_SIZE];
  182. int nStringBufferLen;
  183. int nOemStringBufferLen;
  184. if (! hMod) {
  185. hMod = (HINSTANCE) GetModuleHandle(NULL);
  186. }
  187. if (hMod) {
  188. for (iThisLine = iFirstLine; iThisLine <= iLastLine; iThisLine++) {
  189. ZeroMemory(StringBuffer, DISP_BUFF_SIZE * sizeof(WCHAR));
  190. ZeroMemory(OemStringBuffer, DISP_BUFF_SIZE * sizeof(CHAR));
  191. nStringBufferLen = LoadStringW(
  192. hMod, iThisLine, StringBuffer, DISP_BUFF_SIZE);
  193. if (nStringBufferLen > 0) {
  194. nOemStringBufferLen = DISP_BUFF_SIZE;
  195. WideCharToMultiByte(CP_OEMCP,
  196. 0,
  197. StringBuffer,
  198. nStringBufferLen,
  199. OemStringBuffer,
  200. nOemStringBufferLen,
  201. NULL,
  202. NULL);
  203. fprintf (stdout, "\n%s", OemStringBuffer);
  204. }
  205. }
  206. } // else do nothing
  207. } // DisplayCommandHelp
  208. BOOL
  209. TrimSpaces (
  210. IN OUT LPTSTR szString
  211. )
  212. /*++
  213. Routine Description:
  214. Trims leading and trailing spaces from szString argument, modifying
  215. the buffer passed in
  216. Arguments:
  217. IN OUT LPTSTR szString
  218. buffer to process
  219. Return Value:
  220. TRUE if string was modified
  221. FALSE if not
  222. --*/
  223. {
  224. LPTSTR szSource;
  225. LPTSTR szDest;
  226. LPTSTR szLast;
  227. BOOL bChars;
  228. szLast = szSource = szDest = szString;
  229. bChars = FALSE;
  230. while (*szSource != 0) {
  231. // skip leading non-space chars
  232. if (!_istspace(*szSource)) {
  233. szLast = szDest;
  234. bChars = TRUE;
  235. }
  236. if (bChars) {
  237. // remember last non-space character
  238. // copy source to destination & increment both
  239. *szDest++ = *szSource++;
  240. } else {
  241. szSource++;
  242. }
  243. }
  244. if (bChars) {
  245. *++szLast = 0; // terminate after last non-space char
  246. } else {
  247. // string was all spaces so return an empty (0-len) string
  248. *szString = 0;
  249. }
  250. return (szLast != szSource);
  251. }
  252. BOOL
  253. IsDelimiter (
  254. IN TCHAR cChar,
  255. IN TCHAR cDelimiter
  256. )
  257. /*++
  258. Routine Description:
  259. compares the characte to the delimiter. If the delimiter is
  260. a whitespace character then any whitespace char will match
  261. otherwise an exact match is required
  262. --*/
  263. {
  264. if (_istspace(cDelimiter)) {
  265. // delimiter is whitespace so any whitespace char will do
  266. return (_istspace(cChar));
  267. } else {
  268. // delimiter is not white space so use an exact match
  269. return (cChar == cDelimiter);
  270. }
  271. }
  272. LPCTSTR
  273. GetItemFromString (
  274. IN LPCTSTR szEntry,
  275. IN DWORD dwItem,
  276. IN TCHAR cDelimiter
  277. )
  278. /*++
  279. Routine Description:
  280. returns nth item from a list delimited by the cDelimiter Char.
  281. Leaves (double)quoted strings intact.
  282. Arguments:
  283. IN LPCTSTR szEntry
  284. Source string returned to parse
  285. IN DWORD dwItem
  286. 1-based index indicating which item to return. (i.e. 1= first item
  287. in list, 2= second, etc.)
  288. IN TCHAR cDelimiter
  289. character used to separate items. Note if cDelimiter is WhiteSpace
  290. (e.g. a tab or a space) then any white space will serve as a delim.
  291. Return Value:
  292. pointer to buffer containing desired entry in string. Note, this
  293. routine may only be called 4 times before the string
  294. buffer is re-used. (i.e. don't use this function more than
  295. 4 times in single function call!!)
  296. --*/
  297. {
  298. static TCHAR szReturnBuffer[4][MAX_PATH];
  299. static LONG dwBuff;
  300. LPTSTR szSource, szDest;
  301. DWORD dwThisItem;
  302. DWORD dwStrLeft;
  303. dwBuff = ++dwBuff % 4; // wrap buffer index
  304. szSource = (LPTSTR)szEntry;
  305. szDest = &szReturnBuffer[dwBuff][0];
  306. // clear previous contents
  307. memset (szDest, 0, (MAX_PATH * sizeof(TCHAR)));
  308. // find desired entry in string
  309. dwThisItem = 1;
  310. while (dwThisItem < dwItem) {
  311. if (*szSource != 0) {
  312. while (!IsDelimiter(*szSource, cDelimiter) && (*szSource != 0)) {
  313. if (*szSource == cDoubleQuote) {
  314. // if this is a quote, then go to the close quote
  315. szSource++;
  316. while ((*szSource != cDoubleQuote) && (*szSource != 0)) szSource++;
  317. }
  318. if (*szSource != 0) szSource++;
  319. }
  320. }
  321. dwThisItem++;
  322. if (*szSource != 0) szSource++;
  323. }
  324. // copy this entry to the return buffer
  325. if (*szSource != 0) {
  326. dwStrLeft = MAX_PATH-1;
  327. while (!IsDelimiter(*szSource, cDelimiter) && (*szSource != 0)) {
  328. if (*szSource == cDoubleQuote) {
  329. // if this is a quote, then go to the close quote
  330. // don't copy quotes!
  331. szSource++;
  332. while ((*szSource != cDoubleQuote) && (*szSource != 0)) {
  333. *szDest++ = *szSource++;
  334. dwStrLeft--;
  335. if (!dwStrLeft) break; // dest is full (except for term NULL
  336. }
  337. if (*szSource != 0) szSource++;
  338. } else {
  339. *szDest++ = *szSource++;
  340. dwStrLeft--;
  341. if (!dwStrLeft) break; // dest is full (except for term NULL
  342. }
  343. }
  344. *szDest = 0;
  345. }
  346. // remove any leading and/or trailing spaces
  347. TrimSpaces (&szReturnBuffer[dwBuff][0]);
  348. return &szReturnBuffer[dwBuff][0];
  349. }
  350. void
  351. ReportLoadPerfEvent(
  352. IN WORD EventType,
  353. IN DWORD EventID,
  354. IN DWORD dwDataCount,
  355. IN DWORD dwData1,
  356. IN DWORD dwData2,
  357. IN DWORD dwData3,
  358. IN DWORD dwData4,
  359. IN WORD wStringCount,
  360. IN LPWSTR szString1,
  361. IN LPWSTR szString2,
  362. IN LPWSTR szString3
  363. )
  364. {
  365. DWORD dwData[5];
  366. LPWSTR szMessageArray[4];
  367. BOOL bResult = FALSE;
  368. WORD wLocalStringCount = 0;
  369. DWORD dwLastError = GetLastError();
  370. if (dwDataCount > 4) dwDataCount = 4;
  371. if (wStringCount > 3) wStringCount = 3;
  372. if (dwDataCount > 0) dwData[0] = dwData1;
  373. if (dwDataCount > 1) dwData[1] = dwData2;
  374. if (dwDataCount > 2) dwData[2] = dwData3;
  375. if (dwDataCount > 3) dwData[3] = dwData4;
  376. dwDataCount *= sizeof(DWORD);
  377. if (wStringCount > 0 && szString1) {
  378. szMessageArray[wLocalStringCount] = szString1;
  379. wLocalStringCount ++;
  380. }
  381. if (wStringCount > 1 && szString2) {
  382. szMessageArray[wLocalStringCount] = szString2;
  383. wLocalStringCount ++;
  384. }
  385. if (wStringCount > 2 && szString3) {
  386. szMessageArray[wLocalStringCount] = szString3;
  387. wLocalStringCount ++;
  388. }
  389. if (hEventLog == NULL) {
  390. hEventLog = RegisterEventSourceW (NULL, (LPCWSTR)L"LoadPerf");
  391. }
  392. if (dwDataCount > 0 && wLocalStringCount > 0) {
  393. bResult = ReportEventW(hEventLog,
  394. EventType, // event type
  395. 0, // category (not used)
  396. EventID, // event,
  397. NULL, // SID (not used),
  398. wLocalStringCount, // number of strings
  399. dwDataCount, // sizeof raw data
  400. szMessageArray, // message text array
  401. (LPVOID) & dwData[0]); // raw data
  402. }
  403. else if (dwDataCount > 0) {
  404. bResult = ReportEventW(hEventLog,
  405. EventType, // event type
  406. 0, // category (not used)
  407. EventID, // event,
  408. NULL, // SID (not used),
  409. 0, // number of strings
  410. dwDataCount, // sizeof raw data
  411. NULL, // message text array
  412. (LPVOID) & dwData[0]); // raw data
  413. }
  414. else if (wLocalStringCount > 0) {
  415. bResult = ReportEventW(hEventLog,
  416. EventType, // event type
  417. 0, // category (not used)
  418. EventID, // event,
  419. NULL, // SID (not used),
  420. wLocalStringCount, // number of strings
  421. 0, // sizeof raw data
  422. szMessageArray, // message text array
  423. NULL); // raw data
  424. }
  425. else {
  426. bResult = ReportEventW(hEventLog,
  427. EventType, // event type
  428. 0, // category (not used)
  429. EventID, // event,
  430. NULL, // SID (not used),
  431. 0, // number of strings
  432. 0, // sizeof raw data
  433. NULL, // message text array
  434. NULL); // raw data
  435. }
  436. if (! bResult) {
  437. DbgPrint("LOADPERF(0x%08X)::(%d,0x%08X,%d)(%d,%d,%d,%d,%d)(%d,%ws,%ws,%ws)\n",
  438. GetCurrentThreadId(),
  439. EventType, EventID, GetLastError(),
  440. dwDataCount, dwData1, dwData2, dwData3, dwData4,
  441. wStringCount, szString1, szString2, szString3);
  442. }
  443. SetLastError(dwLastError);
  444. }
  445. BOOLEAN LoadPerfGrabMutex()
  446. {
  447. BOOL bResult = TRUE;
  448. HANDLE hLocalMutex = NULL;
  449. DWORD dwWaitStatus = 0;
  450. SECURITY_ATTRIBUTES SecurityAttributes;
  451. PSECURITY_DESCRIPTOR pSD = NULL;
  452. EXPLICIT_ACCESS ea[3];
  453. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  454. SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY;
  455. PSID psidSystem = NULL;
  456. PSID psidAdmin = NULL;
  457. PSID psidEveryone = NULL;
  458. PACL pAcl = NULL;
  459. if (hLoadPerfMutex == NULL) {
  460. ZeroMemory(& ea, 3 * sizeof(EXPLICIT_ACCESS));
  461. // Get the system sid
  462. //
  463. bResult = AllocateAndInitializeSid(& authNT,
  464. 1,
  465. SECURITY_LOCAL_SYSTEM_RID,
  466. 0, 0, 0, 0, 0, 0, 0,
  467. & psidSystem);
  468. if (! bResult) {
  469. dwWaitStatus = GetLastError();
  470. TRACE((WINPERF_DBG_TRACE_ERROR),
  471. (& LoadPerfGuid,
  472. __LINE__,
  473. LOADPERF_LOADPERFGRABMUTEX,
  474. 0,
  475. dwWaitStatus,
  476. NULL));
  477. goto Cleanup;
  478. }
  479. // Set the access rights for system sid
  480. //
  481. ea[0].grfAccessPermissions = MUTEX_ALL_ACCESS;
  482. ea[0].grfAccessMode = SET_ACCESS;
  483. ea[0].grfInheritance = NO_INHERITANCE;
  484. ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  485. ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  486. ea[0].Trustee.ptstrName = (LPTSTR) psidSystem;
  487. // Get the Admin sid
  488. //
  489. bResult = AllocateAndInitializeSid(& authNT,
  490. 2,
  491. SECURITY_BUILTIN_DOMAIN_RID,
  492. DOMAIN_ALIAS_RID_ADMINS,
  493. 0, 0, 0, 0, 0, 0,
  494. & psidAdmin);
  495. if (! bResult) {
  496. dwWaitStatus = GetLastError();
  497. TRACE((WINPERF_DBG_TRACE_ERROR),
  498. (& LoadPerfGuid,
  499. __LINE__,
  500. LOADPERF_LOADPERFGRABMUTEX,
  501. 0,
  502. dwWaitStatus,
  503. NULL));
  504. goto Cleanup;
  505. }
  506. // Set the access rights for Admin sid
  507. //
  508. ea[1].grfAccessPermissions = MUTEX_ALL_ACCESS;
  509. ea[1].grfAccessMode = SET_ACCESS;
  510. ea[1].grfInheritance = NO_INHERITANCE;
  511. ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  512. ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  513. ea[1].Trustee.ptstrName = (LPTSTR) psidAdmin;
  514. // Get the World sid
  515. //
  516. bResult = AllocateAndInitializeSid(& authWorld,
  517. 1,
  518. SECURITY_WORLD_RID,
  519. 0, 0, 0, 0, 0, 0, 0,
  520. & psidEveryone);
  521. if (! bResult) {
  522. dwWaitStatus = GetLastError();
  523. TRACE((WINPERF_DBG_TRACE_ERROR),
  524. (& LoadPerfGuid,
  525. __LINE__,
  526. LOADPERF_LOADPERFGRABMUTEX,
  527. 0,
  528. dwWaitStatus,
  529. NULL));
  530. goto Cleanup;
  531. }
  532. // Set the access rights for world
  533. //
  534. ea[2].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | MUTEX_MODIFY_STATE;
  535. ea[2].grfAccessMode = SET_ACCESS;
  536. ea[2].grfInheritance = NO_INHERITANCE;
  537. ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  538. ea[2].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  539. ea[2].Trustee.ptstrName = (LPTSTR) psidEveryone;
  540. // Create a new ACL that contains the new ACEs.
  541. //
  542. dwWaitStatus = SetEntriesInAcl(3, ea, NULL, & pAcl);
  543. if (dwWaitStatus != ERROR_SUCCESS) {
  544. bResult = FALSE;
  545. TRACE((WINPERF_DBG_TRACE_ERROR),
  546. (& LoadPerfGuid,
  547. __LINE__,
  548. LOADPERF_LOADPERFGRABMUTEX,
  549. 0,
  550. dwWaitStatus,
  551. NULL));
  552. goto Cleanup;
  553. }
  554. // Initialize a security descriptor.
  555. //
  556. pSD = (PSECURITY_DESCRIPTOR)
  557. LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  558. if (pSD == NULL) {
  559. dwWaitStatus = GetLastError();
  560. bResult = FALSE;
  561. TRACE((WINPERF_DBG_TRACE_ERROR),
  562. (& LoadPerfGuid,
  563. __LINE__,
  564. LOADPERF_LOADPERFGRABMUTEX,
  565. 0,
  566. dwWaitStatus,
  567. NULL));
  568. goto Cleanup;
  569. }
  570. bResult = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
  571. if (! bResult) {
  572. dwWaitStatus = GetLastError();
  573. TRACE((WINPERF_DBG_TRACE_ERROR),
  574. (& LoadPerfGuid,
  575. __LINE__,
  576. LOADPERF_LOADPERFGRABMUTEX,
  577. 0,
  578. dwWaitStatus,
  579. NULL));
  580. goto Cleanup;
  581. }
  582. // Add the ACL to the security descriptor.
  583. //
  584. bResult = SetSecurityDescriptorDacl(pSD, TRUE, pAcl, FALSE);
  585. if (! bResult) {
  586. dwWaitStatus = GetLastError();
  587. TRACE((WINPERF_DBG_TRACE_ERROR),
  588. (& LoadPerfGuid,
  589. __LINE__,
  590. LOADPERF_LOADPERFGRABMUTEX,
  591. 0,
  592. dwWaitStatus,
  593. NULL));
  594. goto Cleanup;
  595. }
  596. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  597. SecurityAttributes.bInheritHandle = TRUE;
  598. SecurityAttributes.lpSecurityDescriptor = pSD;
  599. __try {
  600. hLocalMutex = CreateMutex(& SecurityAttributes,
  601. FALSE,
  602. TEXT("LOADPERF_MUTEX"));
  603. if (hLocalMutex == NULL) {
  604. bResult = FALSE;
  605. dwWaitStatus = GetLastError();
  606. TRACE((WINPERF_DBG_TRACE_ERROR),
  607. (& LoadPerfGuid,
  608. __LINE__,
  609. LOADPERF_LOADPERFGRABMUTEX,
  610. 0,
  611. dwWaitStatus,
  612. NULL));
  613. }
  614. else if (InterlockedCompareExchangePointer(& hLoadPerfMutex,
  615. hLocalMutex,
  616. NULL) != NULL) {
  617. CloseHandle(hLocalMutex);
  618. hLocalMutex = NULL;
  619. }
  620. } __except (EXCEPTION_EXECUTE_HANDLER) {
  621. bResult = FALSE;
  622. dwWaitStatus = GetLastError();
  623. TRACE((WINPERF_DBG_TRACE_FATAL),
  624. (& LoadPerfGuid,
  625. __LINE__,
  626. LOADPERF_LOADPERFGRABMUTEX,
  627. 0,
  628. dwWaitStatus,
  629. NULL));
  630. }
  631. }
  632. __try {
  633. dwWaitStatus = WaitForSingleObject(hLoadPerfMutex, H_MUTEX_TIMEOUT);
  634. } __except (EXCEPTION_EXECUTE_HANDLER) {
  635. bResult = FALSE;
  636. dwWaitStatus = GetLastError();
  637. TRACE((WINPERF_DBG_TRACE_FATAL),
  638. (& LoadPerfGuid,
  639. __LINE__,
  640. LOADPERF_LOADPERFGRABMUTEX,
  641. 0,
  642. dwWaitStatus,
  643. NULL));
  644. }
  645. if (dwWaitStatus != WAIT_OBJECT_0 && dwWaitStatus != WAIT_ABANDONED) {
  646. bResult = FALSE;
  647. TRACE((WINPERF_DBG_TRACE_FATAL),
  648. (& LoadPerfGuid,
  649. __LINE__,
  650. LOADPERF_LOADPERFGRABMUTEX,
  651. 0,
  652. dwWaitStatus,
  653. NULL));
  654. }
  655. Cleanup:
  656. if (psidSystem) FreeSid(psidSystem);
  657. if (psidAdmin) FreeSid(psidAdmin);
  658. if (psidEveryone) FreeSid(psidEveryone);
  659. if (pAcl) LocalFree(pAcl);
  660. if (pSD) LocalFree(pSD);
  661. if (! bResult) SetLastError(dwWaitStatus);
  662. return bResult ? TRUE : FALSE;
  663. }