Leaked source code of windows server 2003
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.

1558 lines
59 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. //
  12. // Windows Include files
  13. //
  14. #include <windows.h>
  15. #include "strsafe.h"
  16. #include "stdlib.h"
  17. #include <accctrl.h>
  18. #include <aclapi.h>
  19. #include <winperf.h>
  20. #include <initguid.h>
  21. #include <guiddef.h>
  22. #include "wmistr.h"
  23. #include "evntrace.h"
  24. //
  25. // local include files
  26. //
  27. #define _INIT_WINPERFP_
  28. #include "winperfp.h"
  29. #include "ldprfmsg.h"
  30. #include "common.h"
  31. //
  32. // Text string Constant definitions
  33. //
  34. LPCWSTR NamesKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
  35. LPCWSTR DefaultLangId = L"009";
  36. LPCSTR aszDefaultLangId = "009";
  37. LPCWSTR DefaultLangTag = L"000";
  38. LPCWSTR Counters = L"Counters";
  39. LPCWSTR Help = L"Help";
  40. LPCWSTR VersionStr = L"Version";
  41. LPCWSTR BaseIndex = L"Base Index";
  42. LPCWSTR LastHelp = L"Last Help";
  43. LPCWSTR LastCounter = L"Last Counter";
  44. LPCWSTR FirstHelp = L"First Help";
  45. LPCWSTR FirstCounter = L"First Counter";
  46. LPCWSTR Busy = L"Updating";
  47. LPCWSTR Slash = L"\\";
  48. LPCWSTR BlankString = L" ";
  49. LPCWSTR DriverPathRoot = L"SYSTEM\\CurrentControlSet\\Services";
  50. LPCWSTR Performance = L"Performance";
  51. LPCWSTR CounterNameStr = L"Counter ";
  52. LPCWSTR HelpNameStr = L"Explain ";
  53. LPCWSTR AddCounterNameStr = L"Addcounter ";
  54. LPCWSTR AddHelpNameStr = L"Addexplain ";
  55. LPCWSTR szObjectList = L"Object List";
  56. LPCWSTR szLibraryValidationCode = L"Library Validation Code";
  57. LPCWSTR DisablePerformanceCounters = L"Disable Performance Counters";
  58. LPCWSTR szDisplayName = L"DisplayName";
  59. LPCWSTR szPerfIniPath = L"PerfIniFile";
  60. LPCSTR szInfo = "info";
  61. LPCSTR szSymbolFile = "symbolfile";
  62. LPCSTR szNotFound = "NotFound";
  63. LPCSTR szLanguages = "languages";
  64. LPCWSTR szLangCH = L"004";
  65. LPCWSTR szLangCHT = L"0404";
  66. LPCWSTR szLangCHS = L"0804";
  67. LPCWSTR szLangCHH = L"0C04";
  68. LPCWSTR szLangPT = L"016";
  69. LPCWSTR szLangPT_BR = L"0416";
  70. LPCWSTR szLangPT_PT = L"0816";
  71. LPCWSTR szDatExt = L".DAT";
  72. LPCWSTR szBakExt = L".BAK";
  73. LPCWSTR wszInfo = L"info";
  74. LPCWSTR wszDriverName = L"drivername";
  75. LPCWSTR wszNotFound = L"NotFound";
  76. LPCSTR aszDriverName = "drivername";
  77. BOOLEAN g_bCheckTraceLevel = FALSE;
  78. // Global (to this module) Buffers
  79. //
  80. static HANDLE hMod = NULL; // process handle
  81. HANDLE hEventLog = NULL;
  82. HANDLE hLoadPerfMutex = NULL;
  83. //
  84. // local static data
  85. //
  86. BOOL
  87. __stdcall
  88. DllEntryPoint(
  89. IN HANDLE DLLHandle,
  90. IN DWORD Reason,
  91. IN LPVOID ReservedAndUnused
  92. )
  93. {
  94. BOOL bReturn = FALSE;
  95. ReservedAndUnused;
  96. DisableThreadLibraryCalls(DLLHandle);
  97. switch(Reason) {
  98. case DLL_PROCESS_ATTACH:
  99. hMod = DLLHandle; // use DLL handle , not APP handle
  100. // register eventlog source
  101. hEventLog = RegisterEventSourceW(NULL, (LPCWSTR) L"LoadPerf");
  102. bReturn = TRUE;
  103. break;
  104. case DLL_PROCESS_DETACH:
  105. if (hEventLog != NULL) {
  106. if (DeregisterEventSource(hEventLog)) {
  107. hEventLog = NULL;
  108. }
  109. }
  110. if (hLoadPerfMutex != NULL) {
  111. CloseHandle(hLoadPerfMutex);
  112. hLoadPerfMutex = NULL;
  113. }
  114. bReturn = TRUE;
  115. break;
  116. case DLL_THREAD_ATTACH:
  117. case DLL_THREAD_DETACH:
  118. bReturn = TRUE;
  119. break;
  120. }
  121. return bReturn;
  122. }
  123. LPCWSTR
  124. GetFormatResource(
  125. UINT wStringId
  126. )
  127. /*++
  128. Returns an ANSI string for use as a format string in a printf fn.
  129. --*/
  130. {
  131. LPCWSTR szReturn = BlankString;
  132. static WCHAR TextFormat[DISP_BUFF_SIZE];
  133. if (! hMod) {
  134. hMod = (HINSTANCE) GetModuleHandle(NULL); // get instance ID of this module;
  135. }
  136. if (hMod) {
  137. if ((LoadStringW(hMod, wStringId, TextFormat, DISP_BUFF_SIZE)) > 0) {
  138. szReturn = (LPCWSTR) TextFormat;
  139. }
  140. }
  141. return szReturn;
  142. }
  143. VOID
  144. DisplayCommandHelp(
  145. UINT iFirstLine,
  146. UINT iLastLine
  147. )
  148. /*++
  149. DisplayCommandHelp
  150. displays usage of command line arguments
  151. Arguments
  152. NONE
  153. Return Value
  154. NONE
  155. --*/
  156. {
  157. UINT iThisLine;
  158. WCHAR StringBuffer[DISP_BUFF_SIZE];
  159. CHAR OemStringBuffer[DISP_BUFF_SIZE];
  160. int nStringBufferLen;
  161. int nOemStringBufferLen;
  162. if (! hMod) {
  163. hMod = (HINSTANCE) GetModuleHandle(NULL);
  164. }
  165. if (hMod) {
  166. for (iThisLine = iFirstLine; iThisLine <= iLastLine; iThisLine++) {
  167. ZeroMemory(StringBuffer, DISP_BUFF_SIZE * sizeof(WCHAR));
  168. ZeroMemory(OemStringBuffer, DISP_BUFF_SIZE * sizeof(CHAR));
  169. nStringBufferLen = LoadStringW(hMod, iThisLine, StringBuffer, DISP_BUFF_SIZE);
  170. if (nStringBufferLen > 0) {
  171. nOemStringBufferLen = DISP_BUFF_SIZE;
  172. WideCharToMultiByte(CP_OEMCP,
  173. 0,
  174. StringBuffer,
  175. nStringBufferLen,
  176. OemStringBuffer,
  177. nOemStringBufferLen,
  178. NULL,
  179. NULL);
  180. fprintf(stdout, "\n%s", OemStringBuffer);
  181. }
  182. }
  183. } // else do nothing
  184. } // DisplayCommandHelp
  185. BOOL
  186. TrimSpaces(
  187. LPWSTR szString
  188. )
  189. /*++
  190. Routine Description:
  191. Trims leading and trailing spaces from szString argument, modifying
  192. the buffer passed in
  193. Arguments:
  194. IN OUT LPWSTR szString
  195. buffer to process
  196. Return Value:
  197. TRUE if string was modified
  198. FALSE if not
  199. --*/
  200. {
  201. LPWSTR szSource = szString;
  202. LPWSTR szDest = szString;
  203. LPWSTR szLast = szString;
  204. BOOL bChars = FALSE;
  205. if (szString != NULL) {
  206. while (* szSource != L'\0') {
  207. // skip leading non-space chars
  208. if (! iswspace(* szSource)) {
  209. szLast = szDest;
  210. bChars = TRUE;
  211. }
  212. if (bChars) {
  213. // remember last non-space character
  214. // copy source to destination & increment both
  215. * szDest ++ = * szSource ++;
  216. }
  217. else {
  218. szSource ++;
  219. }
  220. }
  221. if (bChars) {
  222. * ++ szLast = L'\0'; // terminate after last non-space char
  223. }
  224. else {
  225. // string was all spaces so return an empty (0-len) string
  226. * szString = L'\0';
  227. }
  228. }
  229. return (szLast != szSource);
  230. }
  231. BOOL
  232. IsDelimiter(
  233. WCHAR cChar,
  234. WCHAR cDelimiter
  235. )
  236. /*++
  237. Routine Description:
  238. compares the characte to the delimiter. If the delimiter is
  239. a whitespace character then any whitespace char will match
  240. otherwise an exact match is required
  241. --*/
  242. {
  243. if (iswspace(cDelimiter)) {
  244. // delimiter is whitespace so any whitespace char will do
  245. return(iswspace(cChar));
  246. }
  247. else {
  248. // delimiter is not white space so use an exact match
  249. return (cChar == cDelimiter);
  250. }
  251. }
  252. LPCWSTR
  253. GetItemFromString(
  254. LPCWSTR szEntry,
  255. DWORD dwItem,
  256. WCHAR cDelimiter
  257. )
  258. /*++
  259. Routine Description:
  260. returns nth item from a list delimited by the cDelimiter Char.
  261. Leaves (double)quoted strings intact.
  262. Arguments:
  263. IN LPWTSTR szEntry
  264. Source string returned to parse
  265. IN DWORD dwItem
  266. 1-based index indicating which item to return. (i.e. 1= first item
  267. in list, 2= second, etc.)
  268. IN WCHAR cDelimiter
  269. character used to separate items. Note if cDelimiter is WhiteSpace
  270. (e.g. a tab or a space) then any white space will serve as a delim.
  271. Return Value:
  272. pointer to buffer containing desired entry in string. Note, this
  273. routine may only be called 4 times before the string
  274. buffer is re-used. (i.e. don't use this function more than
  275. 4 times in single function call!!)
  276. --*/
  277. {
  278. static WCHAR szReturnBuffer[4][MAX_PATH];
  279. static LONG dwBuff;
  280. LPWSTR szSource, szDest;
  281. DWORD dwThisItem;
  282. DWORD dwStrLeft;
  283. dwBuff = ++ dwBuff % 4; // wrap buffer index
  284. szSource = (LPWSTR) szEntry;
  285. szDest = & szReturnBuffer[dwBuff][0];
  286. // clear previous contents
  287. ZeroMemory(szDest, MAX_PATH * sizeof(WCHAR));
  288. // find desired entry in string
  289. dwThisItem = 1;
  290. while (dwThisItem < dwItem) {
  291. if (* szSource != L'\0') {
  292. while (! IsDelimiter(* szSource, cDelimiter) && (* szSource != L'\0')) {
  293. if (* szSource == cDoubleQuote) {
  294. // if this is a quote, then go to the close quote
  295. szSource ++;
  296. while ((* szSource != cDoubleQuote) && (* szSource != L'\0')) szSource ++;
  297. }
  298. if (* szSource != L'\0') szSource ++;
  299. }
  300. }
  301. dwThisItem ++;
  302. if (* szSource != L'\0') szSource ++;
  303. }
  304. // copy this entry to the return buffer
  305. if (* szSource != L'\0') {
  306. dwStrLeft = MAX_PATH - 1;
  307. while (! IsDelimiter(* szSource, cDelimiter) && (* szSource != L'\0')) {
  308. if (* szSource == cDoubleQuote) {
  309. // if this is a quote, then go to the close quote
  310. // don't copy quotes!
  311. szSource ++;
  312. while ((* szSource != cDoubleQuote) && (* szSource != L'\0')) {
  313. * szDest ++ = * szSource ++;
  314. dwStrLeft --;
  315. if (! dwStrLeft) break; // dest is full (except for term NULL
  316. }
  317. if (* szSource != L'\0') szSource ++;
  318. }
  319. else {
  320. * szDest ++ = * szSource ++;
  321. dwStrLeft --;
  322. if (! dwStrLeft) break; // dest is full (except for term NULL
  323. }
  324. }
  325. * szDest = L'\0';
  326. }
  327. // remove any leading and/or trailing spaces
  328. TrimSpaces(& szReturnBuffer[dwBuff][0]);
  329. return & szReturnBuffer[dwBuff][0];
  330. }
  331. void
  332. ReportLoadPerfEvent(
  333. WORD EventType,
  334. DWORD EventID,
  335. DWORD dwDataCount,
  336. DWORD dwData1,
  337. DWORD dwData2,
  338. DWORD dwData3,
  339. DWORD dwData4,
  340. WORD wStringCount,
  341. LPWSTR szString1,
  342. LPWSTR szString2,
  343. LPWSTR szString3
  344. )
  345. {
  346. DWORD dwData[5];
  347. LPWSTR szMessageArray[4];
  348. BOOL bResult = FALSE;
  349. WORD wLocalStringCount = 0;
  350. DWORD dwLastError = GetLastError();
  351. if (dwDataCount > 4) dwDataCount = 4;
  352. if (wStringCount > 3) wStringCount = 3;
  353. if (dwDataCount > 0) dwData[0] = dwData1;
  354. if (dwDataCount > 1) dwData[1] = dwData2;
  355. if (dwDataCount > 2) dwData[2] = dwData3;
  356. if (dwDataCount > 3) dwData[3] = dwData4;
  357. dwDataCount *= sizeof(DWORD);
  358. if (wStringCount > 0 && szString1) {
  359. szMessageArray[wLocalStringCount] = szString1;
  360. wLocalStringCount ++;
  361. }
  362. if (wStringCount > 1 && szString2) {
  363. szMessageArray[wLocalStringCount] = szString2;
  364. wLocalStringCount ++;
  365. }
  366. if (wStringCount > 2 && szString3) {
  367. szMessageArray[wLocalStringCount] = szString3;
  368. wLocalStringCount ++;
  369. }
  370. if (hEventLog == NULL) {
  371. hEventLog = RegisterEventSourceW(NULL, (LPCWSTR) L"LoadPerf");
  372. }
  373. if (dwDataCount > 0 && wLocalStringCount > 0) {
  374. bResult = ReportEventW(hEventLog,
  375. EventType, // event type
  376. 0, // category (not used)
  377. EventID, // event,
  378. NULL, // SID (not used),
  379. wLocalStringCount, // number of strings
  380. dwDataCount, // sizeof raw data
  381. szMessageArray, // message text array
  382. (LPVOID) & dwData[0]); // raw data
  383. }
  384. else if (dwDataCount > 0) {
  385. bResult = ReportEventW(hEventLog,
  386. EventType, // event type
  387. 0, // category (not used)
  388. EventID, // event,
  389. NULL, // SID (not used),
  390. 0, // number of strings
  391. dwDataCount, // sizeof raw data
  392. NULL, // message text array
  393. (LPVOID) & dwData[0]); // raw data
  394. }
  395. else if (wLocalStringCount > 0) {
  396. bResult = ReportEventW(hEventLog,
  397. EventType, // event type
  398. 0, // category (not used)
  399. EventID, // event,
  400. NULL, // SID (not used),
  401. wLocalStringCount, // number of strings
  402. 0, // sizeof raw data
  403. szMessageArray, // message text array
  404. NULL); // raw data
  405. }
  406. else {
  407. bResult = ReportEventW(hEventLog,
  408. EventType, // event type
  409. 0, // category (not used)
  410. EventID, // event,
  411. NULL, // SID (not used),
  412. 0, // number of strings
  413. 0, // sizeof raw data
  414. NULL, // message text array
  415. NULL); // raw data
  416. }
  417. #if 0
  418. if (! bResult) {
  419. DbgPrint("LOADPERF(%5d,%5d)::(%d,0x%08X,%d)(%d,%d,%d,%d,%d)(%d,\"%ws\",\"%ws\",\"%ws\")\n",
  420. GetCurrentProcessId(), GetCurrentThreadId(),
  421. EventType, EventID, GetLastError(),
  422. dwDataCount, dwData1, dwData2, dwData3, dwData4,
  423. wStringCount, szString1, szString2, szString3);
  424. }
  425. #endif
  426. SetLastError(dwLastError);
  427. }
  428. BOOLEAN LoadPerfGrabMutex()
  429. {
  430. BOOL bResult = TRUE;
  431. HANDLE hLocalMutex = NULL;
  432. DWORD dwWaitStatus = 0;
  433. SECURITY_ATTRIBUTES SecurityAttributes;
  434. PSECURITY_DESCRIPTOR pSD = NULL;
  435. EXPLICIT_ACCESSW ea[3];
  436. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  437. SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY;
  438. PSID psidSystem = NULL;
  439. PSID psidAdmin = NULL;
  440. PSID psidEveryone = NULL;
  441. PACL pAcl = NULL;
  442. if (hLoadPerfMutex == NULL) {
  443. ZeroMemory(ea, 3 * sizeof(EXPLICIT_ACCESS));
  444. // Get the system sid
  445. //
  446. bResult = AllocateAndInitializeSid(& authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, & psidSystem);
  447. if (! bResult) {
  448. dwWaitStatus = GetLastError();
  449. TRACE((WINPERF_DBG_TRACE_ERROR),
  450. (& LoadPerfGuid,
  451. __LINE__,
  452. LOADPERF_LOADPERFGRABMUTEX,
  453. 0,
  454. dwWaitStatus,
  455. NULL));
  456. goto Cleanup;
  457. }
  458. // Set the access rights for system sid
  459. //
  460. ea[0].grfAccessPermissions = MUTEX_ALL_ACCESS;
  461. ea[0].grfAccessMode = SET_ACCESS;
  462. ea[0].grfInheritance = NO_INHERITANCE;
  463. ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  464. ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  465. ea[0].Trustee.ptstrName = (LPWSTR) psidSystem;
  466. // Get the Admin sid
  467. //
  468. bResult = AllocateAndInitializeSid(& authNT,
  469. 2,
  470. SECURITY_BUILTIN_DOMAIN_RID,
  471. DOMAIN_ALIAS_RID_ADMINS,
  472. 0, 0, 0, 0, 0, 0,
  473. & psidAdmin);
  474. if (! bResult) {
  475. dwWaitStatus = GetLastError();
  476. TRACE((WINPERF_DBG_TRACE_ERROR),
  477. (& LoadPerfGuid,
  478. __LINE__,
  479. LOADPERF_LOADPERFGRABMUTEX,
  480. 0,
  481. dwWaitStatus,
  482. NULL));
  483. goto Cleanup;
  484. }
  485. // Set the access rights for Admin sid
  486. //
  487. ea[1].grfAccessPermissions = MUTEX_ALL_ACCESS;
  488. ea[1].grfAccessMode = SET_ACCESS;
  489. ea[1].grfInheritance = NO_INHERITANCE;
  490. ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  491. ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  492. ea[1].Trustee.ptstrName = (LPWSTR) psidAdmin;
  493. // Get the World sid
  494. //
  495. bResult = AllocateAndInitializeSid(& authWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, & psidEveryone);
  496. if (! bResult) {
  497. dwWaitStatus = GetLastError();
  498. TRACE((WINPERF_DBG_TRACE_ERROR),
  499. (& LoadPerfGuid,
  500. __LINE__,
  501. LOADPERF_LOADPERFGRABMUTEX,
  502. 0,
  503. dwWaitStatus,
  504. NULL));
  505. goto Cleanup;
  506. }
  507. // Set the access rights for world
  508. //
  509. ea[2].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | MUTEX_MODIFY_STATE;
  510. ea[2].grfAccessMode = SET_ACCESS;
  511. ea[2].grfInheritance = NO_INHERITANCE;
  512. ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  513. ea[2].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  514. ea[2].Trustee.ptstrName = (LPWSTR) psidEveryone;
  515. // Create a new ACL that contains the new ACEs.
  516. //
  517. dwWaitStatus = SetEntriesInAclW(3, ea, NULL, & pAcl);
  518. if (dwWaitStatus != ERROR_SUCCESS) {
  519. bResult = FALSE;
  520. TRACE((WINPERF_DBG_TRACE_ERROR),
  521. (& LoadPerfGuid,
  522. __LINE__,
  523. LOADPERF_LOADPERFGRABMUTEX,
  524. 0,
  525. dwWaitStatus,
  526. NULL));
  527. goto Cleanup;
  528. }
  529. // Initialize a security descriptor.
  530. //
  531. pSD = (PSECURITY_DESCRIPTOR)
  532. LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  533. if (pSD == NULL) {
  534. dwWaitStatus = GetLastError();
  535. bResult = FALSE;
  536. TRACE((WINPERF_DBG_TRACE_ERROR),
  537. (& LoadPerfGuid,
  538. __LINE__,
  539. LOADPERF_LOADPERFGRABMUTEX,
  540. 0,
  541. dwWaitStatus,
  542. NULL));
  543. goto Cleanup;
  544. }
  545. bResult = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
  546. if (! bResult) {
  547. dwWaitStatus = GetLastError();
  548. TRACE((WINPERF_DBG_TRACE_ERROR),
  549. (& LoadPerfGuid,
  550. __LINE__,
  551. LOADPERF_LOADPERFGRABMUTEX,
  552. 0,
  553. dwWaitStatus,
  554. NULL));
  555. goto Cleanup;
  556. }
  557. // Add the ACL to the security descriptor.
  558. //
  559. bResult = SetSecurityDescriptorDacl(pSD, TRUE, pAcl, FALSE);
  560. if (! bResult) {
  561. dwWaitStatus = GetLastError();
  562. TRACE((WINPERF_DBG_TRACE_ERROR),
  563. (& LoadPerfGuid,
  564. __LINE__,
  565. LOADPERF_LOADPERFGRABMUTEX,
  566. 0,
  567. dwWaitStatus,
  568. NULL));
  569. goto Cleanup;
  570. }
  571. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  572. SecurityAttributes.bInheritHandle = TRUE;
  573. SecurityAttributes.lpSecurityDescriptor = pSD;
  574. __try {
  575. hLocalMutex = CreateMutexW(& SecurityAttributes, FALSE, L"LOADPERF_MUTEX");
  576. if (hLocalMutex == NULL) {
  577. bResult = FALSE;
  578. dwWaitStatus = GetLastError();
  579. TRACE((WINPERF_DBG_TRACE_ERROR),
  580. (& LoadPerfGuid,
  581. __LINE__,
  582. LOADPERF_LOADPERFGRABMUTEX,
  583. 0,
  584. dwWaitStatus,
  585. NULL));
  586. }
  587. else if (InterlockedCompareExchangePointer(& hLoadPerfMutex, hLocalMutex, NULL) != NULL) {
  588. CloseHandle(hLocalMutex);
  589. hLocalMutex = NULL;
  590. }
  591. }
  592. __except (EXCEPTION_EXECUTE_HANDLER) {
  593. bResult = FALSE;
  594. dwWaitStatus = GetLastError();
  595. TRACE((WINPERF_DBG_TRACE_FATAL),
  596. (& LoadPerfGuid,
  597. __LINE__,
  598. LOADPERF_LOADPERFGRABMUTEX,
  599. 0,
  600. dwWaitStatus,
  601. NULL));
  602. }
  603. }
  604. __try {
  605. dwWaitStatus = WaitForSingleObject(hLoadPerfMutex, H_MUTEX_TIMEOUT);
  606. }
  607. __except (EXCEPTION_EXECUTE_HANDLER) {
  608. bResult = FALSE;
  609. dwWaitStatus = GetLastError();
  610. TRACE((WINPERF_DBG_TRACE_FATAL),
  611. (& LoadPerfGuid,
  612. __LINE__,
  613. LOADPERF_LOADPERFGRABMUTEX,
  614. 0,
  615. dwWaitStatus,
  616. NULL));
  617. }
  618. if (dwWaitStatus != WAIT_OBJECT_0 && dwWaitStatus != WAIT_ABANDONED) {
  619. bResult = FALSE;
  620. TRACE((WINPERF_DBG_TRACE_FATAL),
  621. (& LoadPerfGuid,
  622. __LINE__,
  623. LOADPERF_LOADPERFGRABMUTEX,
  624. 0,
  625. dwWaitStatus,
  626. NULL));
  627. }
  628. Cleanup:
  629. if (psidSystem) FreeSid(psidSystem);
  630. if (psidAdmin) FreeSid(psidAdmin);
  631. if (psidEveryone) FreeSid(psidEveryone);
  632. if (pAcl) LocalFree(pAcl);
  633. if (pSD) LocalFree(pSD);
  634. if (! bResult) SetLastError(dwWaitStatus);
  635. return bResult ? TRUE : FALSE;
  636. }
  637. #define LODWORD(ll) ((DWORD) ((LONGLONG) ll & 0x00000000FFFFFFFF))
  638. #define HIDWORD(ll) ((DWORD) (((LONGLONG) ll >> 32) & 0x00000000FFFFFFFF))
  639. #define MAKELONGLONG(low, high) ((LONGLONG) (((DWORD) (low)) | ((LONGLONG) ((DWORD) (high))) << 32))
  640. LPWSTR g_szInfPath = NULL;
  641. LPWSTR
  642. LoadPerfGetLanguage(LPWSTR szLang, BOOL bPrimary)
  643. {
  644. LPWSTR szRtnLang = szLang;
  645. if (bPrimary) {
  646. if (lstrcmpiW(szLang, szLangCHT) == 0 || lstrcmpiW(szLang, szLangCHS) == 0
  647. || lstrcmpiW(szLang, szLangCHH) == 0) {
  648. szRtnLang = (LPWSTR) szLangCH;
  649. }
  650. else if (lstrcmpiW(szLang, szLangPT_PT) == 0 || lstrcmpiW(szLang, szLangPT_BR) == 0) {
  651. szRtnLang = (LPWSTR) szLangPT;
  652. }
  653. }
  654. else if (lstrcmpiW(szLang, szLangCH) == 0) {
  655. DWORD dwLangId = GetUserDefaultUILanguage();
  656. if (dwLangId == 0x0404 || dwLangId == 0x0C04) szRtnLang = (LPWSTR) szLangCHT;
  657. else if (dwLangId == 0x0804) szRtnLang = (LPWSTR) szLangCHS;
  658. else szRtnLang = (LPWSTR) szLangCH;
  659. }
  660. else if (lstrcmpiW(szLang, szLangPT) == 0) {
  661. DWORD dwLangId = GetUserDefaultUILanguage();
  662. if (dwLangId == 0x0416) szRtnLang = (LPWSTR) szLangPT_BR;
  663. else if (dwLangId == 0x0816) szRtnLang = (LPWSTR) szLangPT_PT;
  664. else szRtnLang = (LPWSTR) szLangPT;
  665. }
  666. return szRtnLang;
  667. }
  668. LPWSTR
  669. LoadPerfGetInfPath()
  670. {
  671. LPWSTR szReturn = NULL;
  672. DWORD dwInfPath = 0;
  673. HRESULT hError = S_OK;
  674. if (g_szInfPath == NULL) {
  675. dwInfPath = GetSystemWindowsDirectoryW(NULL, 0);
  676. if (dwInfPath > 0) {
  677. dwInfPath += 6;
  678. if (dwInfPath < MAX_PATH) dwInfPath = MAX_PATH;
  679. g_szInfPath = MemoryAllocate(dwInfPath * sizeof(WCHAR));
  680. if (g_szInfPath != NULL) {
  681. GetSystemWindowsDirectoryW(g_szInfPath, dwInfPath);
  682. hError = StringCchCatW(g_szInfPath, dwInfPath, Slash);
  683. if (SUCCEEDED(hError)) {
  684. hError = StringCchCatW(g_szInfPath, dwInfPath, L"inf");
  685. if (SUCCEEDED(hError)) {
  686. hError = StringCchCatW(g_szInfPath, dwInfPath, Slash);
  687. }
  688. }
  689. if (SUCCEEDED(hError)) {
  690. szReturn = g_szInfPath;
  691. }
  692. else {
  693. SetLastError(HRESULT_CODE(hError));
  694. }
  695. }
  696. else {
  697. SetLastError(ERROR_OUTOFMEMORY);
  698. }
  699. }
  700. else {
  701. SetLastError(ERROR_INVALID_DATA);
  702. }
  703. if (szReturn == NULL) {
  704. MemoryFree(g_szInfPath);
  705. g_szInfPath = NULL;
  706. }
  707. }
  708. else {
  709. szReturn = g_szInfPath;
  710. }
  711. return szReturn;
  712. }
  713. BOOL
  714. LoadPerfGetIncludeFileName(
  715. LPCSTR szIniFile,
  716. DWORD dwFileSize,
  717. DWORD dwUnicode,
  718. LPWSTR * szIncFile,
  719. LPWSTR * szService
  720. )
  721. // Caller LoadPerfBackupIniFile() should free allocated szIncFile and szService.
  722. {
  723. LPSTR szIncName = NULL;
  724. LPSTR szPath = NULL;
  725. LPSTR szDrive = NULL;
  726. LPSTR szDir = NULL;
  727. LPSTR aszIncFile = NULL;
  728. LPSTR aszService = NULL;
  729. DWORD dwSize = 0;
  730. BOOL bReturn = FALSE;
  731. HRESULT hr = S_OK;
  732. if (szIncFile == NULL || szService == NULL) {
  733. SetLastError(ERROR_INVALID_PARAMETER);
  734. return FALSE;
  735. }
  736. * szIncFile = NULL;
  737. * szService = NULL;
  738. dwSize = 6 * dwFileSize;
  739. szIncName = MemoryAllocate(dwSize * sizeof(CHAR));
  740. if (szIncName != NULL) {
  741. LPWSTR wszIniFile = NULL;
  742. szPath = (LPSTR) (szIncName + dwFileSize);
  743. szDrive = (LPSTR) (szPath + dwFileSize);
  744. szDir = (LPSTR) (szDrive + dwFileSize);
  745. aszIncFile = (LPSTR) (szDir + dwFileSize);
  746. aszService = (LPSTR) (aszIncFile + dwFileSize);
  747. if (dwUnicode != 0) {
  748. wszIniFile = LoadPerfMultiByteToWideChar(CP_ACP, (LPSTR) szIniFile);
  749. }
  750. if (wszIniFile == NULL) {
  751. dwSize = GetPrivateProfileStringA(szInfo, aszDriverName, szNotFound, aszService, dwFileSize, szIniFile);
  752. if (lstrcmpiA(aszService, szNotFound) != 0) {
  753. * szService = LoadPerfMultiByteToWideChar(CP_ACP, aszService);
  754. bReturn = TRUE;
  755. }
  756. else {
  757. // name not found, default returned so return NULL string
  758. SetLastError(ERROR_BAD_DRIVER);
  759. }
  760. }
  761. else {
  762. * szService = MemoryAllocate(dwFileSize * sizeof(WCHAR));
  763. if (* szService != NULL) {
  764. dwSize = GetPrivateProfileStringW(
  765. wszInfo, wszDriverName, wszNotFound, * szService, dwFileSize, wszIniFile);
  766. if (lstrcmpiW(* szService, wszNotFound) == 0) {
  767. // name not found, default returned so return NULL string
  768. SetLastError(ERROR_BAD_DRIVER);
  769. }
  770. else {
  771. bReturn = TRUE;
  772. }
  773. }
  774. MemoryFree(wszIniFile);
  775. }
  776. dwSize = GetPrivateProfileStringA(szInfo, szSymbolFile, szNotFound, szIncName, dwFileSize, szIniFile);
  777. if (dwSize == 0 || lstrcmpiA(szIncName, szNotFound) == 0) {
  778. SetLastError(ERROR_BAD_DRIVER);
  779. goto Cleanup;
  780. }
  781. _splitpath(szIniFile, szDrive, szDir, NULL, NULL);
  782. hr = StringCchCopyA(szPath, dwFileSize, szDrive);
  783. if (SUCCEEDED(hr)) {
  784. hr = StringCchCatA(szPath, dwFileSize, szDir);
  785. }
  786. if (FAILED(hr)) {
  787. goto Cleanup;
  788. }
  789. dwSize = SearchPathA(szPath, szIncName, NULL, dwFileSize, aszIncFile, NULL);
  790. if (dwSize == 0) {
  791. dwSize = SearchPathA(NULL, szIncName, NULL, dwFileSize, aszIncFile, NULL);
  792. }
  793. if (dwSize != 0) {
  794. * szIncFile = LoadPerfMultiByteToWideChar(CP_ACP, aszIncFile);
  795. }
  796. bReturn = (dwSize > 0) ? TRUE : FALSE;
  797. }
  798. Cleanup:
  799. TRACE((WINPERF_DBG_TRACE_INFO),
  800. (& LoadPerfGuid,
  801. __LINE__,
  802. LOADPERF_GETINCLUDEFILENAME,
  803. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_STR, 2) | ARG_DEF(ARG_TYPE_STR, 3),
  804. GetLastError(),
  805. TRACE_STR(szIniFile),
  806. TRACE_STR(aszIncFile),
  807. TRACE_STR(aszService),
  808. NULL));
  809. MemoryFree(szIncName);
  810. return bReturn;
  811. }
  812. BOOL
  813. LoadPerfCheckAndCreatePath(
  814. LPWSTR szPath
  815. )
  816. {
  817. BOOL bReturn = CreateDirectoryW(szPath, NULL);
  818. TRACE((WINPERF_DBG_TRACE_INFO),
  819. (& LoadPerfGuid,
  820. __LINE__,
  821. LOADPERF_CHECKANDCREATEPATH,
  822. ARG_DEF(ARG_TYPE_WSTR, 1),
  823. GetLastError(),
  824. TRACE_WSTR(szPath),
  825. NULL));
  826. if (bReturn == FALSE) {
  827. bReturn = (GetLastError() == ERROR_ALREADY_EXISTS) ? (TRUE) : (FALSE);
  828. }
  829. return bReturn;
  830. }
  831. BOOL
  832. LoadPerfCheckAndCopyFile(
  833. LPCWSTR szThisFile,
  834. LPWSTR szBackupFile
  835. )
  836. {
  837. DWORD Status = ERROR_SUCCESS;
  838. BOOL bReturn = FALSE;
  839. HANDLE hFile1 = NULL;
  840. hFile1 = CreateFileW(szThisFile,
  841. GENERIC_READ,
  842. FILE_SHARE_READ | FILE_SHARE_WRITE,
  843. NULL,
  844. OPEN_EXISTING,
  845. FILE_ATTRIBUTE_NORMAL,
  846. NULL);
  847. if (hFile1 == NULL || hFile1 == INVALID_HANDLE_VALUE) {
  848. Status = GetLastError();
  849. }
  850. else {
  851. CloseHandle(hFile1);
  852. bReturn = CopyFileW(szThisFile, szBackupFile, FALSE);
  853. if (bReturn != TRUE) {
  854. Status = GetLastError();
  855. }
  856. }
  857. TRACE((WINPERF_DBG_TRACE_INFO),
  858. (& LoadPerfGuid,
  859. __LINE__,
  860. LOADPERF_GETINCLUDEFILENAME,
  861. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  862. Status,
  863. TRACE_WSTR(szThisFile),
  864. TRACE_WSTR(szBackupFile),
  865. NULL));
  866. return bReturn;
  867. }
  868. void
  869. LoadPerfRemovePreviousIniFile(
  870. LPWSTR szIniName,
  871. LPWSTR szDriverName
  872. )
  873. {
  874. LPWSTR szInfPath = LoadPerfGetInfPath();
  875. LPWSTR szIniPath = NULL;
  876. LPWSTR szIniFile = NULL;
  877. HANDLE hIniFile = NULL;
  878. DWORD Status = ERROR_SUCCESS;
  879. DWORD dwLength;
  880. BOOL bContinue;
  881. BOOL bDelete;
  882. WIN32_FIND_DATAW FindFile;
  883. HRESULT hr = S_OK;
  884. if (szInfPath == NULL) {
  885. Status = ERROR_INVALID_PARAMETER;
  886. goto Cleanup;
  887. }
  888. dwLength = lstrlenW(szInfPath) + lstrlenW(szDriverName) + lstrlenW(szIniName) + 10;
  889. if (dwLength < MAX_PATH) dwLength = MAX_PATH;
  890. szIniPath = MemoryAllocate(2 * dwLength * sizeof(WCHAR));
  891. if (szIniPath == NULL) {
  892. Status = ERROR_OUTOFMEMORY;
  893. goto Cleanup;
  894. }
  895. szIniFile = szIniPath + dwLength;
  896. hr = StringCchPrintfW(szIniPath, dwLength, L"%ws0*", szInfPath);
  897. if (SUCCEEDED(hr)) {
  898. hIniFile = FindFirstFileExW(szIniPath, FindExInfoStandard, & FindFile, FindExSearchLimitToDirectories, NULL, 0);
  899. if (hIniFile == NULL || hIniFile == INVALID_HANDLE_VALUE) {
  900. TRACE((WINPERF_DBG_TRACE_INFO),
  901. (& LoadPerfGuid,
  902. __LINE__,
  903. LOADPERF_GETINCLUDEFILENAME,
  904. ARG_DEF(ARG_TYPE_WSTR, 1),
  905. GetLastError(),
  906. TRACE_WSTR(szIniPath),
  907. NULL));
  908. Status = ERROR_RESOURCE_LANG_NOT_FOUND;
  909. goto Cleanup;
  910. }
  911. }
  912. else {
  913. Status = HRESULT_CODE(hr);
  914. goto Cleanup;
  915. }
  916. bContinue = TRUE;
  917. while (bContinue) {
  918. hr = StringCchPrintfW(szIniFile, dwLength, L"%ws%ws\\%ws\\%ws",
  919. szInfPath, FindFile.cFileName, szDriverName, szIniName);
  920. if (SUCCEEDED(hr)) {
  921. bDelete = DeleteFileW(szIniFile);
  922. dwLength = bDelete ? (ERROR_SUCCESS) : (GetLastError());
  923. TRACE((WINPERF_DBG_TRACE_INFO),
  924. (& LoadPerfGuid,
  925. __LINE__,
  926. LOADPERF_GETINCLUDEFILENAME,
  927. ARG_DEF(ARG_TYPE_WSTR, 1),
  928. dwLength,
  929. TRACE_WSTR(szIniFile),
  930. NULL));
  931. }
  932. bContinue = FindNextFileW(hIniFile, & FindFile);
  933. }
  934. Cleanup:
  935. MemoryFree(szIniPath);
  936. if (hIniFile != NULL && hIniFile != INVALID_HANDLE_VALUE) FindClose(hIniFile);
  937. if (Status != ERROR_SUCCESS) SetLastError(Status);
  938. return;
  939. }
  940. BOOL
  941. LoadPerfBackupIniFile(
  942. LPCWSTR szIniFile,
  943. LPWSTR szLangId,
  944. LPWSTR * szIniName,
  945. LPWSTR * szDriverName,
  946. BOOL bExtFile
  947. )
  948. // Caller InstallPerfDllW() should free allocated szIniName and szDriverName.
  949. // Caller UpdatePerfNameFilesX() passes in NULL szIniName and szDriverName. No need to allocate.
  950. {
  951. BOOL bReturn = TRUE;
  952. LPWSTR szIniFileName = NULL;
  953. LPWSTR szIncFileName = NULL;
  954. LPWSTR szInfPath = NULL;
  955. LPWSTR szIncPath = NULL;
  956. LPWSTR szDriver = NULL;
  957. LPWSTR szIniTarget = NULL;
  958. LPWSTR szIncTarget = NULL;
  959. LPSTR szLangList = NULL;
  960. LPSTR szLang = NULL;
  961. LPSTR aszIniFile = NULL;
  962. DWORD dwFileSize = 0;
  963. DWORD dwSize;
  964. DWORD dwUnicode = 0;
  965. HRESULT hr;
  966. if (szIniFile == NULL || lstrlenW(szIniFile) == 0) return FALSE;
  967. if ((szInfPath = LoadPerfGetInfPath()) == NULL) return FALSE;
  968. if (szIniName != NULL) * szIniName = NULL;
  969. if (szDriverName != NULL) * szDriverName = NULL;
  970. dwFileSize = LoadPerfGetFileSize((LPWSTR) szIniFile, & dwUnicode, TRUE);
  971. if (dwFileSize < SMALL_BUFFER_SIZE) dwFileSize = SMALL_BUFFER_SIZE;
  972. aszIniFile = LoadPerfWideCharToMultiByte(CP_ACP, (LPWSTR) szIniFile);
  973. if (aszIniFile == NULL) return FALSE;
  974. for (szIniFileName = (LPWSTR) szIniFile + lstrlenW(szIniFile) - 1;
  975. szIniFileName != NULL && szIniFileName != szIniFile
  976. && (* szIniFileName) != cNull
  977. && (* szIniFileName) != cBackslash;
  978. szIniFileName --);
  979. if (szIniFileName != NULL && (* szIniFileName) == cBackslash) {
  980. szIniFileName ++;
  981. }
  982. if (szIniFileName != NULL) {
  983. if (szIniName != NULL) {
  984. dwSize = lstrlenW(szIniFileName) + 1;
  985. * szIniName = MemoryAllocate(sizeof(WCHAR) * dwSize);
  986. if (* szIniName != NULL) {
  987. hr = StringCchCopyW(* szIniName, dwSize, szIniFileName);
  988. }
  989. }
  990. szIniTarget = MemoryAllocate(dwFileSize * sizeof(WCHAR));
  991. if (szIniTarget == NULL) {
  992. bReturn = FALSE;
  993. goto Cleanup;
  994. }
  995. }
  996. if (bExtFile) {
  997. bReturn = LoadPerfGetIncludeFileName(aszIniFile, dwFileSize, dwUnicode, & szIncPath, & szDriver);
  998. if (bReturn != TRUE) goto Cleanup;
  999. if (szDriver != NULL) {
  1000. if (szDriverName != NULL) {
  1001. dwSize = lstrlenW(szDriver) + 1;
  1002. * szDriverName = MemoryAllocate(sizeof(WCHAR) * dwSize);
  1003. if (* szDriverName != NULL) {
  1004. hr = StringCchCopyW(* szDriverName, dwSize, szDriver);
  1005. }
  1006. }
  1007. }
  1008. if (szIncPath != NULL) {
  1009. for (szIncFileName = szIncPath + lstrlenW(szIncPath) - 1;
  1010. szIncFileName != NULL && szIncFileName != szIncPath
  1011. && (* szIncFileName) != cNull
  1012. && (* szIncFileName) != cBackslash;
  1013. szIncFileName --);
  1014. if (szIncFileName != NULL && (* szIncFileName) == cBackslash) {
  1015. szIncFileName ++;
  1016. }
  1017. }
  1018. hr = StringCchPrintfW(szIniTarget, dwFileSize, L"%sinc", szInfPath);
  1019. bReturn = LoadPerfCheckAndCreatePath(szIniTarget);
  1020. if (bReturn != TRUE) goto Cleanup;
  1021. hr = StringCchPrintfW(szIniTarget, dwFileSize, L"%sinc%s%ws%s", szInfPath, Slash, szDriver, Slash);
  1022. bReturn = LoadPerfCheckAndCreatePath(szIniTarget);
  1023. if (bReturn != TRUE) goto Cleanup;
  1024. if (szIncFileName != NULL) {
  1025. hr = StringCchCatW(szIniTarget, dwFileSize, szIncFileName);
  1026. bReturn = LoadPerfCheckAndCopyFile(szIncPath, szIniTarget);
  1027. }
  1028. if (bReturn != TRUE) goto Cleanup;
  1029. szLangList = MemoryAllocate(dwFileSize * sizeof(CHAR));
  1030. if (szLangList == NULL) {
  1031. bReturn = FALSE;
  1032. goto Cleanup;
  1033. }
  1034. LoadPerfRemovePreviousIniFile(szIniFileName, szDriver);
  1035. dwSize = GetPrivateProfileStringA(szLanguages, NULL, aszDefaultLangId, szLangList, dwFileSize, aszIniFile);
  1036. for (szLang = szLangList;
  1037. bReturn && szLang != NULL && szLang[0] != '\0';
  1038. szLang += (lstrlenA(szLang) + 1)) {
  1039. LPWSTR szTmpLang = LoadPerfMultiByteToWideChar(CP_ACP, szLang);
  1040. if (szTmpLang != NULL) {
  1041. LPWSTR szThisLang = LoadPerfGetLanguage(szTmpLang, FALSE);
  1042. ZeroMemory(szIniTarget, sizeof(WCHAR) * dwFileSize);
  1043. hr = StringCchPrintfW(szIniTarget, dwFileSize, L"%s%s%s", szInfPath, szThisLang, Slash);
  1044. bReturn = LoadPerfCheckAndCreatePath(szIniTarget);
  1045. if (bReturn != TRUE) goto Cleanup;
  1046. hr = StringCchPrintfW(szIniTarget, dwFileSize, L"%s%s%s%ws%s",
  1047. szInfPath, szThisLang, Slash, szDriver, Slash);
  1048. bReturn = LoadPerfCheckAndCreatePath(szIniTarget);
  1049. if (bReturn) {
  1050. hr = StringCchCatW(szIniTarget, dwFileSize, szIniFileName);
  1051. bReturn = LoadPerfCheckAndCopyFile(szIniFile, szIniTarget);
  1052. }
  1053. MemoryFree(szTmpLang);
  1054. }
  1055. else {
  1056. bReturn = FALSE;
  1057. }
  1058. }
  1059. }
  1060. else if (szLangId != NULL && szIniFileName != NULL) {
  1061. LPWSTR szThisLang = LoadPerfGetLanguage(szLangId, FALSE);
  1062. hr = StringCchPrintfW(szIniTarget, dwFileSize, L"%s%s%s", szInfPath, szThisLang, Slash);
  1063. bReturn = LoadPerfCheckAndCreatePath(szIniTarget);
  1064. if (bReturn) {
  1065. hr = StringCchCatW(szIniTarget, dwFileSize, szIniFileName);
  1066. bReturn = LoadPerfCheckAndCopyFile(szIniFile, szIniTarget);
  1067. }
  1068. }
  1069. else {
  1070. bReturn = FALSE;
  1071. }
  1072. Cleanup:
  1073. MemoryFree(aszIniFile);
  1074. MemoryFree(szIncPath);
  1075. MemoryFree(szDriver);
  1076. MemoryFree(szIniTarget);
  1077. MemoryFree(szLangList);
  1078. return bReturn;
  1079. }
  1080. typedef struct _LOADPERF_LANG_INFO {
  1081. WORD dwLCID;
  1082. int cpAnsi;
  1083. int cpOem;
  1084. int cpMac;
  1085. LPCWSTR szName;
  1086. LPCWSTR szShotName;
  1087. } LOADPERF_LANG_INFO, * PLOADPERF_LANG_INFO;
  1088. const LOADPERF_LANG_INFO LocaleTable[] = {
  1089. { 0x0401, 1256, 720, 10004, L"Arabic (Saudi Arabia)", L"ARA" },
  1090. // { 0x0801, 1256, 720, 10004, L"Arabic (Iraq)", L"ARI" },
  1091. // { 0x0c01, 1256, 720, 10004, L"Arabic (Egypt)", L"ARE" },
  1092. // { 0x1001, 1256, 720, 10004, L"Arabic (Libya)", L"ARL" },
  1093. // { 0x1401, 1256, 720, 10004, L"Arabic (Algeria)", L"ARG" },
  1094. // { 0x1801, 1256, 720, 10004, L"Arabic (Morocco)", L"ARM" },
  1095. // { 0x1c01, 1256, 720, 10004, L"Arabic (Tunisia)", L"ART" },
  1096. // { 0x2001, 1256, 720, 10004, L"Arabic (Oman)", L"ARO" },
  1097. // { 0x2401, 1256, 720, 10004, L"Arabic (Yemen)", L"ARY" },
  1098. // { 0x2801, 1256, 720, 10004, L"Arabic (Syria)", L"ARS" },
  1099. // { 0x2c01, 1256, 720, 10004, L"Arabic (Jordan)", L"ARJ" },
  1100. // { 0x3001, 1256, 720, 10004, L"Arabic (Lebanon)", L"ARB" },
  1101. // { 0x3401, 1256, 720, 10004, L"Arabic (Kuwait)", L"ARK" },
  1102. // { 0x3801, 1256, 720, 10004, L"Arabic (U.A.E.)", L"ARU" },
  1103. // { 0x3c01, 1256, 720, 10004, L"Arabic (Bahrain)", L"ARH" },
  1104. // { 0x4001, 1256, 720, 10004, L"Arabic (Qatar)", L"ARQ" },
  1105. { 0x0402, 1251, 866, 10007, L"Bulgarian (Bulgaria)", L"BGR" },
  1106. // { 0x0403, 1252, 850, 10000, L"Catalan (Spain)", L"CAT" },
  1107. { 0x0404, 950, 950, 10002, L"Chinese(Taiwan) (Taiwan)", L"CHT" },
  1108. { 0x0804, 936, 936, 10008, L"Chinese(PRC) (People's Republic of China)", L"CHS" },
  1109. // { 0x0c04, 936, 936, 10002, L"Chinese(Hong Kong) (Hong Kong)", L"ZHH" },
  1110. // { 0x1004, 936, 936, 10008, L"Chinese(Singapore) (Singapore)", L"ZHI" },
  1111. // { 0x1404, 936, 936, 10002, L"Chinese(Macau) (Macau)", L"ZHM" },
  1112. { 0x0405, 1250, 852, 10029, L"Czech (Czech Republic)", L"CSY" },
  1113. { 0x0406, 1252, 850, 10000, L"Danish (Denmark)", L"DAN" },
  1114. { 0x0407, 1252, 850, 10000, L"German (Germany)", L"DEU" },
  1115. // { 0x0807, 1252, 850, 10000, L"German (Switzerland)", L"DES" },
  1116. // { 0x0c07, 1252, 850, 10000, L"German (Austria)", L"DEA" },
  1117. // { 0x1007, 1252, 850, 10000, L"German (Luxembourg)", L"DEL" },
  1118. // { 0x1407, 1252, 850, 10000, L"German (Liechtenstein)", L"DEC" },
  1119. { 0x0408, 1253, 737, 10006, L"Greek (Greece)", L"ELL" },
  1120. // { 0x2008, 1253, 869, 10006, L"Greek 2 (Greece)", L"ELL" },
  1121. { 0x0409, 1252, 437, 10000, L"English (United States)", L"ENU" },
  1122. // { 0x0809, 1252, 850, 10000, L"English (United Kingdom)", L"ENG" },
  1123. // { 0x0c09, 1252, 850, 10000, L"English (Australia)", L"ENA" },
  1124. // { 0x1009, 1252, 850, 10000, L"English (Canada)", L"ENC" },
  1125. // { 0x1409, 1252, 850, 10000, L"English (New Zealand)", L"ENZ" },
  1126. // { 0x1809, 1252, 850, 10000, L"English (Ireland)", L"ENI" },
  1127. // { 0x1c09, 1252, 437, 10000, L"English (South Africa)", L"ENS" },
  1128. // { 0x2009, 1252, 850, 10000, L"English (Jamaica)", L"ENJ" },
  1129. // { 0x2409, 1252, 850, 10000, L"English (Caribbean)", L"ENB" },
  1130. // { 0x2809, 1252, 850, 10000, L"English (Belize)", L"ENL" },
  1131. // { 0x2c09, 1252, 850, 10000, L"English (Trinidad y Tobago)", L"ENT" },
  1132. // { 0x3009, 1252, 437, 10000, L"English (Zimbabwe)", L"ENW" },
  1133. // { 0x3409, 1252, 437, 10000, L"English (Republic of the Philippines)", L"ENP" },
  1134. // { 0x040a, 1252, 850, 10000, L"Spanish - Traditional Sort (Spain)", L"ESP" },
  1135. // { 0x080a, 1252, 850, 10000, L"Spanish (Mexico)", L"ESM" },
  1136. { 0x0c0a, 1252, 850, 10000, L"Spanish - International Sort (Spain)", L"ESN" },
  1137. // { 0x100a, 1252, 850, 10000, L"Spanish (Guatemala)", L"ESG" },
  1138. // { 0x140a, 1252, 850, 10000, L"Spanish (Costa Rica)", L"ESC" },
  1139. // { 0x180a, 1252, 850, 10000, L"Spanish (Panama)", L"ESA" },
  1140. // { 0x1c0a, 1252, 850, 10000, L"Spanish (Dominican Republic)", L"ESD" },
  1141. // { 0x200a, 1252, 850, 10000, L"Spanish (Venezuela)", L"ESV" },
  1142. // { 0x240a, 1252, 850, 10000, L"Spanish (Colombia)", L"ESO" },
  1143. // { 0x280a, 1252, 850, 10000, L"Spanish (Peru)", L"ESR" },
  1144. // { 0x2c0a, 1252, 850, 10000, L"Spanish (Argentina)", L"ESS" },
  1145. // { 0x300a, 1252, 850, 10000, L"Spanish (Ecuador)", L"ESF" },
  1146. // { 0x340a, 1252, 850, 10000, L"Spanish (Chile)", L"ESL" },
  1147. // { 0x380a, 1252, 850, 10000, L"Spanish (Uruguay)", L"ESY" },
  1148. // { 0x3c0a, 1252, 850, 10000, L"Spanish (Paraguay)", L"ESZ" },
  1149. // { 0x400a, 1252, 850, 10000, L"Spanish (Bolivia)", L"ESB" },
  1150. // { 0x440a, 1252, 850, 10000, L"Spanish (El Salvador)", L"ESE" },
  1151. // { 0x480a, 1252, 850, 10000, L"Spanish (Honduras)", L"ESH" },
  1152. // { 0x4c0a, 1252, 850, 10000, L"Spanish (Nicaragua)", L"ESI" },
  1153. // { 0x500a, 1252, 850, 10000, L"Spanish (Puerto Rico)", L"ESU" },
  1154. { 0x040b, 1252, 850, 10000, L"Finnish (Finland)", L"FIN" },
  1155. { 0x040c, 1252, 850, 10000, L"French (France)", L"FRA" },
  1156. // { 0x080c, 1252, 850, 10000, L"French (Belgium)", L"FRB" },
  1157. // { 0x0c0c, 1252, 850, 10000, L"French (Canada)", L"FRC" },
  1158. // { 0x100c, 1252, 850, 10000, L"French (Switzerland)", L"FRS" },
  1159. // { 0x140c, 1252, 850, 10000, L"French (Luxembourg)", L"FRL" },
  1160. // { 0x180c, 1252, 850, 10000, L"French (Principality of Monaco)", L"FRM" },
  1161. { 0x040d, 1255, 862, 10005, L"Hebrew (Israel)", L"HEB" },
  1162. { 0x040e, 1250, 852, 10029, L"Hungarian (Hungary)", L"HUN" },
  1163. // { 0x040f, 1252, 850, 10079, L"Icelandic (Iceland)", L"ISL" },
  1164. { 0x0410, 1252, 850, 10000, L"Italian (Italy)", L"ITA" },
  1165. // { 0x0810, 1252, 850, 10000, L"Italian (Switzerland)", L"ITS" },
  1166. { 0x0411, 932, 932, 10001, L"Japanese (Japan)", L"JPN" },
  1167. { 0x0412, 949, 949, 10003, L"Korean (Korea)", L"KOR" },
  1168. { 0x0413, 1252, 850, 10000, L"Dutch (Netherlands)", L"NLD" },
  1169. // { 0x0813, 1252, 850, 10000, L"Dutch (Belgium)", L"NLB" },
  1170. { 0x0414, 1252, 850, 10000, L"Norwegian (Bokml) (Norway)", L"NOR" },
  1171. // { 0x0814, 1252, 850, 10000, L"Norwegian (Nynorsk) (Norway)", L"NON" },
  1172. { 0x0415, 1250, 852, 10029, L"Polish (Poland)", L"PLK" },
  1173. { 0x0416, 1252, 850, 10000, L"Portuguese (Brazil)", L"PTB" },
  1174. { 0x0816, 1252, 850, 10000, L"Portuguese (Portugal)", L"PTG" },
  1175. { 0x0418, 1250, 852, 10029, L"Romanian (Romania)", L"ROM" },
  1176. { 0x0419, 1251, 866, 10007, L"Russian (Russia)", L"RUS" },
  1177. { 0x041a, 1250, 852, 10082, L"Croatian (Croatia)", L"HRV" },
  1178. // { 0x081a, 1250, 852, 10029, L"Serbian (Latin) (Serbia)", L"SRL" },
  1179. // { 0x0c1a, 1251, 855, 10007, L"Serbian (Cyrillic) (Serbia)", L"SRB" },
  1180. { 0x041b, 1250, 852, 10029, L"Slovak (Slovakia)", L"SKY" },
  1181. // { 0x041c, 1250, 852, 10029, L"Albanian (Albania)", L"SQI" },
  1182. { 0x041d, 1252, 850, 10000, L"Swedish (Sweden)", L"SVE" },
  1183. // { 0x081d, 1252, 850, 10000, L"Swedish (Finland)", L"SVF" },
  1184. { 0x041e, 874, 874, 10000, L"Thai (Thailand)", L"THA" },
  1185. { 0x041f, 1254, 857, 10081, L"Turkish (Turkey)", L"TRK" },
  1186. // { 0x0420, 1256, 720, 10004, L"Urdu (Islamic Republic of Pakistan)", L"URP" },
  1187. // { 0x0421, 1252, 850, 10000, L"Indonesian (Indonesia)", L"IND" },
  1188. // { 0x0422, 1251, 866, 10017, L"Ukrainian (Ukraine)", L"UKR" },
  1189. // { 0x0423, 1251, 866, 10007, L"Belarusian (Belarus)", L"BEL" },
  1190. { 0x0424, 1250, 852, 10029, L"Slovenian (Slovenia)", L"SLV" },
  1191. { 0x0425, 1257, 775, 10029, L"Estonian (Estonia)", L"ETI" },
  1192. { 0x0426, 1257, 775, 10029, L"Latvian (Latvia)", L"LVI" },
  1193. { 0x0427, 1257, 775, 10029, L"Lithuanian (Lithuania)", L"LTH" }
  1194. // { 0x0827, 1257, 775, 10029, L"Classic Lithuanian (Lithuania)", L"LTC" },
  1195. // { 0x0429, 1256, 720, 10004, L"Farsi (Iran)", L"FAR" },
  1196. // { 0x042a, 1258, 1258, 10000, L"Vietnamese (Viet Nam)", L"VIT" },
  1197. // { 0x042b, 1252, 850, 10000, L"Armenian (Republic of Armenia)", L"HYE" },
  1198. // { 0x042c, 1250, 852, 10029, L"Azeri (Azerbaijan)", L"AZE" },
  1199. // { 0x082c, 1251, 866, 10007, L"Azeri (Azerbaijan)", L"AZE" },
  1200. // { 0x042d, 1252, 850, 10000, L"Basque (Spain)", L"EUQ" },
  1201. // { 0x042f, 1251, 866, 10007, L"Macedonian (Former Yugoslav Republic of Macedonia)", L"MKI" },
  1202. // { 0x0436, 1252, 850, 10000, L"Afrikaans (South Africa)", L"AFK" },
  1203. // { 0x0437, 1252, 850, 10000, L"Georgian (Georgia)", L"KAT" },
  1204. // { 0x0438, 1252, 850, 10079, L"Faeroese (Faeroe Islands)", L"FOS" },
  1205. // { 0x0439, 1252, 850, 10000, L"Hindi (India)", L"HIN" },
  1206. // { 0x043e, 1252, 850, 10000, L"Malay (Malaysia)", L"MSL" },
  1207. // { 0x083e, 1252, 850, 10000, L"Malay (Brunei Darussalam)", L"MSB" },
  1208. // { 0x043f, 1251, 866, 10007, L"Kazak (Kazakstan)", L"KAZ" },
  1209. // { 0x0441, 1252, 437, 10000, L"Swahili (Kenya)", L"SWK" },
  1210. // { 0x0443, 1250, 852, 10029, L"Uzbek (Republic of Uzbekistan)", L"UZB" },
  1211. // { 0x0843, 1251, 866, 10007, L"Uzbek (Republic of Uzbekistan)", L"UZB" },
  1212. // { 0x0444, 1251, 866, 10007, L"Tatar (Tatarstan)", L"TAT" },
  1213. // { 0x0445, 1252, 850, 10000, L"Bengali (India)", L"BEN" },
  1214. // { 0x0446, 1252, 850, 10000, L"Punjabi (India)", L"PAN" },
  1215. // { 0x0447, 1252, 850, 10000, L"Gujarati (India)", L"GUJ" },
  1216. // { 0x0448, 1252, 850, 10000, L"Oriya (India)", L"ORI" },
  1217. // { 0x0449, 1252, 850, 10000, L"Tamil (India)", L"TAM" },
  1218. // { 0x044a, 1252, 850, 10000, L"Telugu (India)", L"TEL" },
  1219. // { 0x044b, 1252, 850, 10000, L"Kannada (India)", L"KAN" },
  1220. // { 0x044c, 1252, 850, 10000, L"Malayalam (India)", L"MAL" },
  1221. // { 0x044d, 1252, 850, 10000, L"Assamese (India)", L"ASM" },
  1222. // { 0x044e, 1252, 850, 10000, L"Marathi (India)", L"MAR" },
  1223. // { 0x044f, 1252, 850, 10000, L"Sanskrit (India)", L"SAN" },
  1224. // { 0x0457, 1252, 850, 10000, L"Konkani (India)", L"KOK" }
  1225. };
  1226. const DWORD dwLocaleSize = sizeof(LocaleTable) / sizeof(LOADPERF_LANG_INFO);
  1227. WORD
  1228. LoadPerfGetLCIDFromString(
  1229. LPWSTR szLangId
  1230. )
  1231. {
  1232. WORD dwLangId = 0;
  1233. DWORD dwLangLen = lstrlenW(szLangId);
  1234. DWORD i;
  1235. WCHAR szDigit;
  1236. for (i = 0; i < dwLangLen; i ++) {
  1237. dwLangId <<= 4;
  1238. szDigit = szLangId[i];
  1239. if (szDigit >= L'0' && szDigit <= L'9') {
  1240. dwLangId += (szDigit - L'0');
  1241. }
  1242. else if (szDigit >= L'a' && szDigit <= L'f') {
  1243. dwLangId += (10 + szDigit - L'a');
  1244. }
  1245. else if (szDigit >= L'A' && szDigit <= L'F') {
  1246. dwLangId += (10 + szDigit - L'A');
  1247. }
  1248. else {
  1249. dwLangId = 0;
  1250. break;
  1251. }
  1252. }
  1253. return dwLangId;
  1254. }
  1255. int
  1256. LoadPerfGetCodePage(
  1257. LPWSTR szLCID
  1258. )
  1259. {
  1260. int CP_Ansi = CP_ACP;
  1261. int CP_Oem = CP_OEMCP;
  1262. int dwStart = 0;
  1263. int dwEnd = dwLocaleSize - 1;
  1264. int dwThis;
  1265. WORD thisLCID;
  1266. WORD thisprimaryLCID;
  1267. WORD primaryLCID;
  1268. thisLCID = LoadPerfGetLCIDFromString(szLCID);
  1269. thisprimaryLCID = PRIMARYLANGID(thisLCID);
  1270. while (dwStart <= dwEnd) {
  1271. dwThis = (dwEnd + dwStart) / 2;
  1272. primaryLCID = PRIMARYLANGID(LocaleTable[dwThis].dwLCID);
  1273. if (LocaleTable[dwThis].dwLCID == thisLCID) {
  1274. CP_Ansi = LocaleTable[dwThis].cpAnsi;
  1275. CP_Oem = LocaleTable[dwThis].cpOem;
  1276. break;
  1277. }
  1278. else if (primaryLCID < thisprimaryLCID) {
  1279. dwStart = dwThis + 1;
  1280. }
  1281. else {
  1282. dwEnd = dwThis - 1;
  1283. }
  1284. }
  1285. if (dwStart > dwEnd) {
  1286. dwStart = 0;
  1287. dwEnd = dwLocaleSize - 1;
  1288. while (dwStart <= dwEnd) {
  1289. dwThis = (dwEnd + dwStart) / 2;
  1290. primaryLCID = PRIMARYLANGID(LocaleTable[dwThis].dwLCID);
  1291. if (primaryLCID == thisprimaryLCID) {
  1292. CP_Ansi = LocaleTable[dwThis].cpAnsi;
  1293. CP_Oem = LocaleTable[dwThis].cpOem;
  1294. break;
  1295. }
  1296. else if (primaryLCID < thisprimaryLCID) {
  1297. dwStart = dwThis + 1;
  1298. }
  1299. else {
  1300. dwEnd = dwThis - 1;
  1301. }
  1302. }
  1303. }
  1304. return CP_Ansi;
  1305. }
  1306. LPSTR
  1307. LoadPerfWideCharToMultiByte(
  1308. UINT CodePage,
  1309. LPWSTR wszString
  1310. )
  1311. {
  1312. // Callers need to free returned string buffer.
  1313. // LoadPerfBackupIniFile()
  1314. // LodctrSetServiceAsTructed()
  1315. // LoadIncludeFile()
  1316. // CreateObjectList()
  1317. // LoadLanguageList()
  1318. LPSTR aszString = NULL;
  1319. int dwValue = WideCharToMultiByte(CodePage, 0, wszString, -1, NULL, 0, NULL, NULL);
  1320. if (dwValue != 0) {
  1321. aszString = MemoryAllocate((dwValue + 1) * sizeof(CHAR));
  1322. if (aszString != NULL) {
  1323. WideCharToMultiByte(CodePage, 0, wszString, -1, aszString, dwValue + 1, NULL, NULL);
  1324. }
  1325. }
  1326. return aszString;
  1327. }
  1328. LPWSTR
  1329. LoadPerfMultiByteToWideChar(
  1330. UINT CodePage,
  1331. LPSTR aszString
  1332. )
  1333. {
  1334. // Callers need to free returned string buffer.
  1335. // UnloadPerfCounterTextStringsA()
  1336. // LoadPerfGetIncludeFileName(), which relies on caller LoadPerfBackupIniFile() to free this.
  1337. // LoadPerfBackupIniFile()
  1338. // BuildLanguageTables()
  1339. // LoadIncludeFile(). The string is part of SYMBOL_TABLE_ENTRY structure and will be freed at the end
  1340. // of LoadPerfInstallPerfDll().
  1341. // GetValue(), which relies on AddEntryToLanguage() (which calls GetValueFromIniKey() then calls GetValue())
  1342. // to free memory lpLocalStringBuff.
  1343. // CreateObjectList()
  1344. // LoadLanguageLists()
  1345. // InstallPerfDllA()
  1346. // LoadPerfCounterTextStringsA()
  1347. // UpdatePerfNameFilesA()
  1348. // SetServiceAsTrustedA()
  1349. LPWSTR wszString = NULL;
  1350. int dwValue = MultiByteToWideChar(CodePage, 0, aszString, -1, NULL, 0);
  1351. if (dwValue != 0) {
  1352. wszString = MemoryAllocate((dwValue + 1) * sizeof(WCHAR));
  1353. if (wszString != NULL) {
  1354. MultiByteToWideChar(CodePage, 0, aszString, -1, wszString, dwValue + 1);
  1355. }
  1356. }
  1357. return wszString;
  1358. }
  1359. DWORD
  1360. LoadPerfGetFileSize(
  1361. LPWSTR szFileName,
  1362. LPDWORD pdwUnicode,
  1363. BOOL bUnicode
  1364. )
  1365. {
  1366. DWORD dwFileSize = 0;
  1367. HANDLE hFile = NULL;
  1368. if (bUnicode) {
  1369. hFile = CreateFileW(
  1370. szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1371. }
  1372. else {
  1373. hFile = CreateFileA(
  1374. (LPSTR) szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1375. }
  1376. if (hFile != NULL && hFile != INVALID_HANDLE_VALUE) {
  1377. dwFileSize = GetFileSize(hFile, NULL);
  1378. if (pdwUnicode != NULL) {
  1379. DWORD dwRead = dwFileSize;
  1380. DWORD dwType = IS_TEXT_UNICODE_NULL_BYTES;
  1381. LPBYTE pBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwFileSize);
  1382. BOOL bResult;
  1383. * pdwUnicode = 0;
  1384. if (pBuffer != NULL) {
  1385. bResult = ReadFile(hFile, (LPVOID) pBuffer, dwFileSize, & dwRead, NULL);
  1386. if (bResult) {
  1387. bResult = IsTextUnicode((LPVOID) pBuffer, dwRead, & dwType);
  1388. * pdwUnicode = bResult ? 1 : 0;
  1389. }
  1390. HeapFree(GetProcessHeap(), 0, pBuffer);
  1391. }
  1392. }
  1393. CloseHandle(hFile);
  1394. }
  1395. return dwFileSize;
  1396. }
  1397. LPCWSTR cszWmiLoadEventName = L"WMI_SysEvent_LodCtr";
  1398. LPCWSTR cszWmiUnloadEventName = L"WMI_SysEvent_UnLodCtr";
  1399. DWORD LoadPerfSignalWmiWithNewData(DWORD dwEventId)
  1400. {
  1401. HANDLE hEvent;
  1402. DWORD dwStatus = ERROR_SUCCESS;
  1403. LPWSTR szEventName = NULL;
  1404. switch (dwEventId) {
  1405. case WMI_LODCTR_EVENT:
  1406. szEventName = (LPWSTR) cszWmiLoadEventName;
  1407. break;
  1408. case WMI_UNLODCTR_EVENT:
  1409. szEventName = (LPWSTR) cszWmiUnloadEventName;
  1410. break;
  1411. default:
  1412. dwStatus = ERROR_INVALID_PARAMETER;
  1413. break;
  1414. }
  1415. if (dwStatus == ERROR_SUCCESS) {
  1416. hEvent = OpenEventW(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, szEventName);
  1417. if (hEvent != NULL) {
  1418. // set event
  1419. SetEvent(hEvent);
  1420. CloseHandle(hEvent);
  1421. }
  1422. else {
  1423. dwStatus = GetLastError();
  1424. }
  1425. }
  1426. return dwStatus;
  1427. }