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.

5877 lines
222 KiB

  1. /*++
  2. Copyright (c) 1991-1999 Microsoft Corporation
  3. Module Name:
  4. lodctr.c
  5. Abstract:
  6. Program to read the contents of the file specified in the command line
  7. and update the registry accordingly
  8. Author:
  9. Bob Watson (a-robw) 10 Feb 93
  10. Revision History:
  11. a-robw 25-Feb-93 revised calls to make it compile as a UNICODE or
  12. an ANSI app.
  13. Bob Watson (bobw) 10 Mar 99 added event log messages
  14. --*/
  15. //
  16. // Windows Include files
  17. //
  18. #include <windows.h>
  19. #include "strsafe.h"
  20. #include "stdlib.h"
  21. #define __LOADPERF__
  22. #include <loadperf.h>
  23. #include <winperf.h>
  24. #include "wmistr.h"
  25. #include "evntrace.h"
  26. //
  27. // application include files
  28. //
  29. #include "winperfp.h"
  30. #include "common.h"
  31. #include "lodctr.h"
  32. #include "ldprfmsg.h"
  33. typedef struct _DllValidationData {
  34. FILETIME CreationDate;
  35. LONGLONG FileSize;
  36. } DllValidationData, * pDllValidationData;
  37. #define OLD_VERSION 0x010000
  38. #define MAX_GUID_TABLE_SIZE 16
  39. #define tohexdigit(x) ((CHAR) (((x) < 10) ? ((x) + L'0') : ((x) + L'a' - 10)))
  40. // string constants
  41. LPCWSTR szDataFileRoot = L"%systemroot%\\system32\\Perf";
  42. LPCSTR szMofFileName = "MofFile";
  43. LPCWSTR szName = L"_NAME";
  44. LPCWSTR szHelp = L"_HELP";
  45. LPCWSTR sz_DFormat = L" %d";
  46. LPCWSTR szDFormat = L"%d";
  47. LPCSTR szText = "text";
  48. LPCWSTR wszText = L"text";
  49. LPCSTR szObjects = "objects";
  50. LPCWSTR MapFileName = L"Perflib Busy";
  51. LPCWSTR szPerflib = L"Perflib";
  52. LPCWSTR cszLibrary = L"Library";
  53. LPCSTR caszOpen = "Open";
  54. LPCSTR caszCollect = "Collect";
  55. LPCSTR caszClose = "Close";
  56. LPCSTR szTrusted = "Trusted";
  57. int __cdecl
  58. My_vfwprintf(
  59. FILE * str,
  60. const wchar_t * format,
  61. va_list argptr
  62. );
  63. __inline
  64. void __cdecl
  65. OUTPUT_MESSAGE(
  66. BOOL bQuietMode,
  67. const WCHAR * format,
  68. ...
  69. )
  70. {
  71. va_list args;
  72. va_start(args, format);
  73. if (! bQuietMode) {
  74. My_vfwprintf(stdout, format, args);
  75. }
  76. va_end(args);
  77. }
  78. LPWSTR
  79. * BuildNameTable(
  80. HKEY hKeyRegistry, // handle to registry db with counter names
  81. LPWSTR lpszLangId, // unicode value of Language subkey
  82. PDWORD pdwLastItem // size of array in elements
  83. )
  84. /*++
  85. BuildNameTable
  86. Arguments:
  87. hKeyRegistry
  88. Handle to an open registry (this can be local or remote.) and
  89. is the value returned by RegConnectRegistry or a default key.
  90. lpszLangId
  91. The unicode id of the language to look up. (default is 409)
  92. Return Value:
  93. pointer to an allocated table. (the caller must MemoryFree it when finished!)
  94. the table is an array of pointers to zero terminated strings. NULL is
  95. returned if an error occured.
  96. --*/
  97. {
  98. LPWSTR * lpReturnValue = NULL;
  99. LPWSTR * lpCounterId;
  100. LPWSTR lpCounterNames;
  101. LPWSTR lpHelpText;
  102. LPWSTR lpThisName;
  103. LONG lWin32Status;
  104. DWORD dwLastError;
  105. DWORD dwValueType;
  106. DWORD dwArraySize;
  107. DWORD dwBufferSize;
  108. DWORD dwCounterSize;
  109. DWORD dwHelpSize;
  110. DWORD dwThisCounter;
  111. DWORD dwLastId;
  112. DWORD dwLastHelpId;
  113. DWORD dwLastCounterId;
  114. DWORD dwLastCounterIdUsed;
  115. DWORD dwLastHelpIdUsed;
  116. HKEY hKeyValue = NULL;
  117. HKEY hKeyNames = NULL;
  118. LPWSTR CounterNameBuffer = NULL;
  119. LPWSTR HelpNameBuffer = NULL;
  120. HRESULT hr;
  121. // check for null arguments and insert defaults if necessary
  122. if (lpszLangId == NULL) {
  123. lpszLangId = (LPWSTR) DefaultLangId;
  124. }
  125. // open registry to get number of items for computing array size
  126. __try {
  127. lWin32Status = RegOpenKeyExW(hKeyRegistry, NamesKey, RESERVED, KEY_READ, & hKeyValue);
  128. }
  129. __except (EXCEPTION_EXECUTE_HANDLER) {
  130. lWin32Status = GetExceptionCode();
  131. }
  132. if (lWin32Status != ERROR_SUCCESS) {
  133. ReportLoadPerfEvent(
  134. EVENTLOG_ERROR_TYPE, // error type
  135. (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event,
  136. 2, lWin32Status, __LINE__, 0, 0,
  137. 1, (LPWSTR) NamesKey, NULL, NULL);
  138. TRACE((WINPERF_DBG_TRACE_ERROR),
  139. (& LoadPerfGuid,
  140. __LINE__,
  141. LOADPERF_LODCTR_BUILDNAMETABLE,
  142. ARG_DEF(ARG_TYPE_WSTR, 1),
  143. lWin32Status,
  144. TRACE_WSTR(NamesKey),
  145. NULL));
  146. goto BNT_BAILOUT;
  147. }
  148. // get number of items
  149. dwBufferSize = sizeof(dwLastHelpId);
  150. __try {
  151. lWin32Status = RegQueryValueExW(hKeyValue,
  152. LastHelp,
  153. RESERVED,
  154. & dwValueType,
  155. (LPBYTE) & dwLastHelpId,
  156. & dwBufferSize);
  157. }
  158. __except (EXCEPTION_EXECUTE_HANDLER) {
  159. lWin32Status = GetExceptionCode();
  160. }
  161. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  162. ReportLoadPerfEvent(
  163. EVENTLOG_ERROR_TYPE, // error type
  164. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  165. 2, lWin32Status, __LINE__, 0, 0,
  166. 1, (LPWSTR) LastHelp, NULL, NULL);
  167. TRACE((WINPERF_DBG_TRACE_ERROR),
  168. (& LoadPerfGuid,
  169. __LINE__,
  170. LOADPERF_LODCTR_BUILDNAMETABLE,
  171. ARG_DEF(ARG_TYPE_WSTR, 1),
  172. lWin32Status,
  173. TRACE_WSTR(LastHelp),
  174. NULL));
  175. goto BNT_BAILOUT;
  176. }
  177. // get number of items
  178. dwBufferSize = sizeof(dwLastId);
  179. __try {
  180. lWin32Status = RegQueryValueExW(hKeyValue,
  181. LastCounter,
  182. RESERVED,
  183. & dwValueType,
  184. (LPBYTE) & dwLastCounterId,
  185. & dwBufferSize);
  186. }
  187. __except (EXCEPTION_EXECUTE_HANDLER) {
  188. lWin32Status = GetExceptionCode();
  189. }
  190. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  191. ReportLoadPerfEvent(
  192. EVENTLOG_ERROR_TYPE, // error type
  193. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  194. 2, lWin32Status, __LINE__, 0, 0,
  195. 1, (LPWSTR) LastCounter, NULL, NULL);
  196. TRACE((WINPERF_DBG_TRACE_ERROR),
  197. (& LoadPerfGuid,
  198. __LINE__,
  199. LOADPERF_LODCTR_BUILDNAMETABLE,
  200. ARG_DEF(ARG_TYPE_WSTR, 1),
  201. lWin32Status,
  202. TRACE_WSTR(LastCounter),
  203. NULL));
  204. goto BNT_BAILOUT;
  205. }
  206. dwLastId = (dwLastCounterId < dwLastHelpId) ? (dwLastHelpId) : (dwLastCounterId);
  207. // compute size of pointer array
  208. dwArraySize = (dwLastId + 1) * sizeof(LPWSTR);
  209. TRACE((WINPERF_DBG_TRACE_INFO),
  210. (& LoadPerfGuid,
  211. __LINE__,
  212. LOADPERF_LODCTR_BUILDNAMETABLE,
  213. 0,
  214. lWin32Status,
  215. TRACE_DWORD(dwLastCounterId),
  216. TRACE_DWORD(dwLastHelpId),
  217. NULL));
  218. hKeyNames = HKEY_PERFORMANCE_DATA;
  219. dwBufferSize = lstrlenW(CounterNameStr) + lstrlenW(HelpNameStr) + lstrlenW(lpszLangId) + 1;
  220. if (dwBufferSize < MAX_PATH) dwBufferSize = MAX_PATH;
  221. CounterNameBuffer = MemoryAllocate(2 * dwBufferSize * sizeof(WCHAR));
  222. if (CounterNameBuffer == NULL) {
  223. lWin32Status = ERROR_OUTOFMEMORY;
  224. SetLastError(lWin32Status);
  225. ReportLoadPerfEvent(
  226. EVENTLOG_ERROR_TYPE, // error type
  227. (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event,
  228. 1, __LINE__, 0, 0, 0,
  229. 0, NULL, NULL, NULL);
  230. TRACE((WINPERF_DBG_TRACE_ERROR),
  231. (& LoadPerfGuid,
  232. __LINE__,
  233. LOADPERF_LODCTR_BUILDNAMETABLE,
  234. 0,
  235. ERROR_OUTOFMEMORY,
  236. NULL));
  237. goto BNT_BAILOUT;
  238. }
  239. HelpNameBuffer = CounterNameBuffer + dwBufferSize;
  240. hr = StringCchPrintfW(CounterNameBuffer, dwBufferSize, L"%ws%ws", CounterNameStr, lpszLangId);
  241. hr = StringCchPrintfW(HelpNameBuffer, dwBufferSize, L"%ws%ws", HelpNameStr, lpszLangId);
  242. // get size of counter names and add that to the arrays
  243. dwBufferSize = 0;
  244. __try {
  245. lWin32Status = RegQueryValueExW(hKeyNames,
  246. CounterNameBuffer,
  247. RESERVED,
  248. & dwValueType,
  249. NULL,
  250. & dwBufferSize);
  251. }
  252. __except (EXCEPTION_EXECUTE_HANDLER) {
  253. lWin32Status = GetExceptionCode();
  254. }
  255. if (lWin32Status != ERROR_SUCCESS) {
  256. ReportLoadPerfEvent(
  257. EVENTLOG_WARNING_TYPE, // error type
  258. (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event,
  259. 2, lWin32Status, __LINE__, 0, 0,
  260. 1, (LPWSTR) lpszLangId, NULL, NULL);
  261. TRACE((WINPERF_DBG_TRACE_ERROR),
  262. (& LoadPerfGuid,
  263. __LINE__,
  264. LOADPERF_LODCTR_BUILDNAMETABLE,
  265. ARG_DEF(ARG_TYPE_WSTR, 1),
  266. lWin32Status,
  267. TRACE_WSTR(Counters),
  268. NULL));
  269. goto BNT_BAILOUT;
  270. }
  271. dwCounterSize = dwBufferSize;
  272. // get size of counter names and add that to the arrays
  273. dwBufferSize = 0;
  274. __try {
  275. lWin32Status = RegQueryValueExW(hKeyNames,
  276. HelpNameBuffer,
  277. RESERVED,
  278. & dwValueType,
  279. NULL,
  280. & dwBufferSize);
  281. }
  282. __except (EXCEPTION_EXECUTE_HANDLER) {
  283. lWin32Status = GetExceptionCode();
  284. }
  285. if (lWin32Status != ERROR_SUCCESS) {
  286. ReportLoadPerfEvent(
  287. EVENTLOG_ERROR_TYPE, // error type
  288. (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event,
  289. 2, lWin32Status, __LINE__, 0, 0,
  290. 1, (LPWSTR) lpszLangId, NULL, NULL);
  291. TRACE((WINPERF_DBG_TRACE_ERROR),
  292. (& LoadPerfGuid,
  293. __LINE__,
  294. LOADPERF_LODCTR_BUILDNAMETABLE,
  295. ARG_DEF(ARG_TYPE_WSTR, 1),
  296. lWin32Status,
  297. TRACE_WSTR(Help),
  298. NULL));
  299. goto BNT_BAILOUT;
  300. }
  301. dwHelpSize = dwBufferSize;
  302. lpReturnValue = MemoryAllocate(dwArraySize + dwCounterSize + dwHelpSize);
  303. if (lpReturnValue == NULL) {
  304. lWin32Status = ERROR_OUTOFMEMORY;
  305. SetLastError(lWin32Status);
  306. ReportLoadPerfEvent(
  307. EVENTLOG_ERROR_TYPE, // error type
  308. (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event,
  309. 1, __LINE__, 0, 0, 0,
  310. 0, NULL, NULL, NULL);
  311. TRACE((WINPERF_DBG_TRACE_ERROR),
  312. (& LoadPerfGuid,
  313. __LINE__,
  314. LOADPERF_LODCTR_BUILDNAMETABLE,
  315. 0,
  316. ERROR_OUTOFMEMORY,
  317. NULL));
  318. goto BNT_BAILOUT;
  319. }
  320. // initialize pointers into buffer
  321. lpCounterId = lpReturnValue;
  322. lpCounterNames = (LPWSTR) ((LPBYTE) lpCounterId + dwArraySize);
  323. lpHelpText = (LPWSTR) ((LPBYTE) lpCounterNames + dwCounterSize);
  324. // read counters into memory
  325. dwBufferSize = dwCounterSize;
  326. __try {
  327. lWin32Status = RegQueryValueExW(hKeyNames,
  328. CounterNameBuffer,
  329. RESERVED,
  330. & dwValueType,
  331. (LPVOID) lpCounterNames,
  332. & dwBufferSize);
  333. }
  334. __except (EXCEPTION_EXECUTE_HANDLER) {
  335. lWin32Status = GetExceptionCode();
  336. }
  337. if (lWin32Status != ERROR_SUCCESS) {
  338. ReportLoadPerfEvent(
  339. EVENTLOG_WARNING_TYPE, // error type
  340. (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event,
  341. 2, lWin32Status, __LINE__, 0, 0,
  342. 1, (LPWSTR) lpszLangId, NULL, NULL);
  343. TRACE((WINPERF_DBG_TRACE_ERROR),
  344. (& LoadPerfGuid,
  345. __LINE__,
  346. LOADPERF_LODCTR_BUILDNAMETABLE,
  347. ARG_DEF(ARG_TYPE_WSTR, 1),
  348. lWin32Status,
  349. TRACE_WSTR(Counters),
  350. NULL));
  351. goto BNT_BAILOUT;
  352. }
  353. dwBufferSize = dwHelpSize;
  354. __try {
  355. lWin32Status = RegQueryValueExW(hKeyNames,
  356. HelpNameBuffer,
  357. RESERVED,
  358. & dwValueType,
  359. (LPVOID) lpHelpText,
  360. & dwBufferSize);
  361. }
  362. __except (EXCEPTION_EXECUTE_HANDLER) {
  363. lWin32Status = GetExceptionCode();
  364. }
  365. if (lWin32Status != ERROR_SUCCESS) {
  366. ReportLoadPerfEvent(
  367. EVENTLOG_ERROR_TYPE, // error type
  368. (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event,
  369. 2, lWin32Status, __LINE__, 0, 0,
  370. 1, (LPWSTR) lpszLangId, NULL, NULL);
  371. TRACE((WINPERF_DBG_TRACE_ERROR),
  372. (& LoadPerfGuid,
  373. __LINE__,
  374. LOADPERF_LODCTR_BUILDNAMETABLE,
  375. ARG_DEF(ARG_TYPE_WSTR, 1),
  376. lWin32Status,
  377. TRACE_WSTR(Help),
  378. NULL));
  379. goto BNT_BAILOUT;
  380. }
  381. dwLastCounterIdUsed = 0;
  382. dwLastHelpIdUsed = 0;
  383. // load counter array items
  384. for (lpThisName = lpCounterNames; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1) ) {
  385. // first string should be an integer (in decimal unicode digits)
  386. dwThisCounter = wcstoul(lpThisName, NULL, 10);
  387. if (dwThisCounter == 0 || dwThisCounter > dwLastId) {
  388. lWin32Status = ERROR_INVALID_DATA;
  389. SetLastError(lWin32Status);
  390. ReportLoadPerfEvent(
  391. EVENTLOG_ERROR_TYPE, // error type
  392. (DWORD) LDPRFMSG_REGISTRY_COUNTER_STRINGS_CORRUPT, // event,
  393. 4, dwThisCounter, dwLastCounterId, dwLastId, __LINE__,
  394. 1, lpThisName, NULL, NULL);
  395. TRACE((WINPERF_DBG_TRACE_ERROR),
  396. (& LoadPerfGuid,
  397. __LINE__,
  398. LOADPERF_LODCTR_BUILDNAMETABLE,
  399. ARG_DEF(ARG_TYPE_WSTR, 1),
  400. lWin32Status,
  401. TRACE_WSTR(lpThisName),
  402. TRACE_DWORD(dwThisCounter),
  403. TRACE_DWORD(dwLastId),
  404. NULL));
  405. goto BNT_BAILOUT; // bad entry
  406. }
  407. // point to corresponding counter name
  408. lpThisName += (lstrlenW(lpThisName) + 1);
  409. // and load array element;
  410. lpCounterId[dwThisCounter] = lpThisName;
  411. if (dwThisCounter > dwLastCounterIdUsed) dwLastCounterIdUsed = dwThisCounter;
  412. }
  413. for (lpThisName = lpHelpText; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1) ) {
  414. // first string should be an integer (in decimal unicode digits)
  415. dwThisCounter = wcstoul(lpThisName, NULL, 10);
  416. if (dwThisCounter == 0 || dwThisCounter > dwLastId) {
  417. lWin32Status = ERROR_INVALID_DATA;
  418. SetLastError(lWin32Status);
  419. ReportLoadPerfEvent(
  420. EVENTLOG_ERROR_TYPE, // error type
  421. (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT, // event,
  422. 4, dwThisCounter, dwLastHelpId, dwLastId, __LINE__,
  423. 1, lpThisName, NULL, NULL);
  424. TRACE((WINPERF_DBG_TRACE_ERROR),
  425. (& LoadPerfGuid,
  426. __LINE__,
  427. LOADPERF_LODCTR_BUILDNAMETABLE,
  428. ARG_DEF(ARG_TYPE_WSTR, 1),
  429. lWin32Status,
  430. TRACE_WSTR(lpThisName),
  431. TRACE_DWORD(dwThisCounter),
  432. TRACE_DWORD(dwLastId),
  433. NULL));
  434. goto BNT_BAILOUT; // bad entry
  435. }
  436. // point to corresponding counter name
  437. lpThisName += (lstrlenW(lpThisName) + 1);
  438. // and load array element;
  439. lpCounterId[dwThisCounter] = lpThisName;
  440. if (dwThisCounter > dwLastHelpIdUsed) dwLastHelpIdUsed= dwThisCounter;
  441. }
  442. TRACE((WINPERF_DBG_TRACE_INFO),
  443. (& LoadPerfGuid,
  444. __LINE__,
  445. LOADPERF_LODCTR_BUILDNAMETABLE,
  446. ARG_DEF(ARG_TYPE_WSTR, 1),
  447. lWin32Status,
  448. TRACE_WSTR(lpszLangId),
  449. TRACE_DWORD(dwLastCounterIdUsed),
  450. TRACE_DWORD(dwLastHelpIdUsed),
  451. TRACE_DWORD(dwLastId),
  452. NULL));
  453. // check the registry for consistency
  454. // the last help string index should be the last ID used
  455. if (dwLastCounterIdUsed > dwLastId) {
  456. lWin32Status = ERROR_INVALID_DATA;
  457. SetLastError(lWin32Status);
  458. ReportLoadPerfEvent(
  459. EVENTLOG_ERROR_TYPE, // error type
  460. (DWORD) LDPRFMSG_REGISTRY_INDEX_CORRUPT, // event,
  461. 3, dwLastId, dwLastCounterIdUsed, __LINE__, 0,
  462. 0, NULL, NULL, NULL);
  463. goto BNT_BAILOUT; // bad registry
  464. }
  465. if (dwLastHelpIdUsed > dwLastId) {
  466. lWin32Status = ERROR_INVALID_DATA;
  467. SetLastError(lWin32Status);
  468. ReportLoadPerfEvent(
  469. EVENTLOG_ERROR_TYPE, // error type
  470. (DWORD) LDPRFMSG_REGISTRY_INDEX_CORRUPT, // event,
  471. 3, dwLastId, dwLastHelpIdUsed, __LINE__, 0,
  472. 0, NULL, NULL, NULL);
  473. goto BNT_BAILOUT; // bad registry
  474. }
  475. if (pdwLastItem) * pdwLastItem = dwLastId;
  476. BNT_BAILOUT:
  477. if (hKeyValue) RegCloseKey (hKeyValue);
  478. if (hKeyNames && hKeyNames != HKEY_PERFORMANCE_DATA) RegCloseKey (hKeyNames);
  479. MemoryFree(CounterNameBuffer);
  480. if (lWin32Status != ERROR_SUCCESS) {
  481. dwLastError = GetLastError();
  482. MemoryFree(lpReturnValue);
  483. lpReturnValue = NULL;
  484. }
  485. return lpReturnValue;
  486. }
  487. BOOL
  488. MakeBackupCopyOfLanguageFiles(
  489. LPCWSTR szLangId
  490. )
  491. {
  492. LPWSTR szOldFileName = NULL;
  493. LPWSTR szTmpFileName = NULL;
  494. LPWSTR szNewFileName = NULL;
  495. BOOL bStatus = FALSE;
  496. DWORD dwStatus;
  497. HANDLE hOutFile;
  498. HRESULT hr;
  499. UNREFERENCED_PARAMETER(szLangId);
  500. szOldFileName = MemoryAllocate((MAX_PATH + 1) * sizeof(WCHAR));
  501. szTmpFileName = MemoryAllocate((MAX_PATH + 1) * sizeof(WCHAR));
  502. szNewFileName = MemoryAllocate((MAX_PATH + 1) * sizeof(WCHAR));
  503. if (szOldFileName == NULL || szTmpFileName == NULL || szNewFileName == NULL) {
  504. dwStatus = ERROR_OUTOFMEMORY;
  505. goto Cleanup;
  506. }
  507. ExpandEnvironmentStringsW(szDataFileRoot, szOldFileName, MAX_PATH);
  508. hr = StringCchPrintfW(szNewFileName, MAX_PATH + 1, L"%wsStringBackup.INI", szOldFileName);
  509. hr = StringCchPrintfW(szTmpFileName, MAX_PATH + 1, L"%wsStringBackup.TMP", szOldFileName);
  510. // see if the file already exists
  511. hOutFile = CreateFileW(szTmpFileName,
  512. GENERIC_READ,
  513. 0, // no sharing
  514. NULL, // default security
  515. OPEN_EXISTING,
  516. FILE_ATTRIBUTE_NORMAL,
  517. NULL);
  518. if (hOutFile != INVALID_HANDLE_VALUE) {
  519. CloseHandle(hOutFile);
  520. bStatus = DeleteFileW(szTmpFileName);
  521. }
  522. // create backup of file
  523. //
  524. dwStatus = BackupPerfRegistryToFileW(szTmpFileName, NULL);
  525. if (dwStatus == ERROR_SUCCESS) {
  526. bStatus = CopyFileW(szTmpFileName, szNewFileName, FALSE);
  527. if (bStatus) {
  528. DeleteFileW(szTmpFileName);
  529. }
  530. }
  531. else {
  532. bStatus = FALSE;
  533. }
  534. Cleanup:
  535. TRACE((WINPERF_DBG_TRACE_INFO),
  536. (& LoadPerfGuid,
  537. __LINE__,
  538. LOADPERF_MAKEBACKUPCOPYOFLANGUAGEFILES,
  539. ARG_DEF(ARG_TYPE_WSTR, 1),
  540. GetLastError(),
  541. TRACE_WSTR(szNewFileName),
  542. NULL));
  543. MemoryFree(szOldFileName);
  544. MemoryFree(szTmpFileName);
  545. MemoryFree(szNewFileName);
  546. if (! bStatus) SetLastError(dwStatus);
  547. return bStatus;
  548. }
  549. BOOL
  550. GetFileFromCommandLine(
  551. LPWSTR lpCommandLine,
  552. LPWSTR * lpFileName,
  553. DWORD dwFileName,
  554. DWORD_PTR * pdwFlags
  555. )
  556. /*++
  557. GetFileFromCommandLine
  558. parses the command line to retrieve the ini filename that should be
  559. the first and only argument.
  560. Arguments
  561. lpCommandLine pointer to command line (returned by GetCommandLine)
  562. lpFileName pointer to buffer that will recieve address of the
  563. validated filename entered on the command line
  564. pdwFlags pointer to dword containing flag bits
  565. Return Value
  566. TRUE if a valid filename was returned
  567. FALSE if the filename is not valid or missing
  568. error is returned in GetLastError
  569. --*/
  570. {
  571. INT iNumArgs;
  572. LPWSTR lpExeName = NULL;
  573. LPWSTR lpCmdLineName = NULL;
  574. LPWSTR lpIniFileName = NULL;
  575. LPWSTR lpMofFlag = NULL;
  576. HANDLE hFileHandle;
  577. DWORD lStatus = ERROR_SUCCESS;
  578. BOOL bReturn = FALSE;
  579. DWORD NameBuffer;
  580. DWORD dwCpuArg, dwIniArg;
  581. HRESULT hr;
  582. // check for valid arguments
  583. if (lpCommandLine == NULL || lpFileName == NULL || pdwFlags == NULL) {
  584. lStatus = ERROR_INVALID_PARAMETER;
  585. goto Cleanup;
  586. }
  587. // allocate memory for parsing operation
  588. NameBuffer = lstrlenW(lpCommandLine);
  589. if (NameBuffer < MAX_PATH) NameBuffer = MAX_PATH;
  590. lpExeName = MemoryAllocate(4 * NameBuffer * sizeof(WCHAR));
  591. if (lpExeName == NULL) {
  592. lStatus = (ERROR_OUTOFMEMORY);
  593. goto Cleanup;
  594. }
  595. lpCmdLineName = (LPWSTR) (lpExeName + NameBuffer);
  596. lpIniFileName = (LPWSTR) (lpCmdLineName + NameBuffer);
  597. lpMofFlag = (LPWSTR) (lpIniFileName + NameBuffer);
  598. // check for mof Flag
  599. hr = StringCchCopyW(lpMofFlag, NameBuffer, GetItemFromString(lpCommandLine, 2, cSpace));
  600. * pdwFlags |= LOADPERF_FLAGS_LOAD_REGISTRY_ONLY; // default unless a switch is found
  601. if (lpMofFlag[0] == cHyphen || lpMofFlag[0] == cSlash) {
  602. if (lpMofFlag[1] == cQuestion) {
  603. // ask for usage
  604. goto Cleanup;
  605. }
  606. else if (lpMofFlag[1] == cM || lpMofFlag[1] == cm) {
  607. // ignore MOF flag. LODCTR only used to update perfromance registry, no MOF.
  608. //
  609. }
  610. dwCpuArg = 3;
  611. dwIniArg = 4;
  612. }
  613. else {
  614. dwCpuArg = 2;
  615. dwIniArg = 3;
  616. }
  617. // Get INI File name
  618. hr = StringCchCopyW(lpCmdLineName, NameBuffer, GetItemFromString(lpCommandLine, dwIniArg, cSpace));
  619. if (lstrlenW(lpCmdLineName) == 0) {
  620. // then no computer name was specified so try to get the
  621. // ini file from the 2nd entry
  622. hr = StringCchCopyW(lpCmdLineName, NameBuffer, GetItemFromString(lpCommandLine, dwCpuArg, cSpace));
  623. if (lstrlenW(lpCmdLineName) == 0) {
  624. // no ini file found
  625. iNumArgs = 1;
  626. }
  627. else {
  628. // fill in a blank computer name
  629. iNumArgs = 2;
  630. }
  631. }
  632. else {
  633. // the computer name must be present so fetch it
  634. hr = StringCchCopyW(lpMofFlag, NameBuffer, GetItemFromString(lpCommandLine, dwCpuArg, cSpace));
  635. iNumArgs = 3;
  636. }
  637. if (iNumArgs != 2 && iNumArgs != 3) {
  638. // wrong number of arguments
  639. lStatus = ERROR_INVALID_PARAMETER;
  640. goto Cleanup;
  641. }
  642. if (SearchPathW(NULL, lpCmdLineName, NULL, FILE_NAME_BUFFER_SIZE, lpIniFileName, NULL) > 0) {
  643. hFileHandle = CreateFileW(lpIniFileName,
  644. GENERIC_READ,
  645. FILE_SHARE_READ,
  646. NULL,
  647. OPEN_EXISTING,
  648. FILE_ATTRIBUTE_NORMAL,
  649. NULL);
  650. if (hFileHandle != NULL && hFileHandle != INVALID_HANDLE_VALUE) {
  651. CloseHandle(hFileHandle);
  652. // file exists, so return name and success
  653. hr = StringCchCopyW(* lpFileName, dwFileName, lpIniFileName);
  654. bReturn = TRUE;
  655. }
  656. else {
  657. // filename was on command line, but not valid so return
  658. // false, but send name back for error message
  659. hr = StringCchCopyW(* lpFileName, dwFileName, lpIniFileName);
  660. lStatus = GetLastError();
  661. }
  662. }
  663. else {
  664. hr = StringCchCopyW(* lpFileName, dwFileName, lpCmdLineName);
  665. lStatus = ERROR_OPEN_FAILED;
  666. }
  667. Cleanup:
  668. MemoryFree(lpExeName);
  669. if (! bReturn) SetLastError(lStatus);
  670. return bReturn;
  671. }
  672. BOOL
  673. LodctrSetSericeAsTrusted(
  674. LPCWSTR lpIniFile,
  675. LPCWSTR szMachineName,
  676. LPCWSTR szServiceName
  677. )
  678. {
  679. DWORD dwRetSize;
  680. DWORD dwStatus;
  681. BOOL bReturn = FALSE;
  682. LPSTR aszIniFile = LoadPerfWideCharToMultiByte(CP_ACP, (LPWSTR) lpIniFile);
  683. LPSTR szParam = NULL;
  684. if (aszIniFile != NULL) {
  685. DWORD dwFileSize = LoadPerfGetFileSize((LPWSTR) lpIniFile, NULL, TRUE);
  686. if (dwFileSize < SMALL_BUFFER_SIZE) dwFileSize = SMALL_BUFFER_SIZE;
  687. szParam = MemoryAllocate(dwFileSize * sizeof(CHAR));
  688. if (szParam != NULL) {
  689. dwRetSize = GetPrivateProfileStringA(szInfo, szTrusted, szNotFound, szParam, dwFileSize, aszIniFile);
  690. if (lstrcmpiA(szParam, szNotFound) != 0) {
  691. // Trusted string found so set
  692. dwStatus = SetServiceAsTrustedW(NULL, szServiceName);
  693. if (dwStatus != ERROR_SUCCESS) {
  694. SetLastError(dwStatus);
  695. }
  696. else {
  697. bReturn = TRUE;
  698. }
  699. }
  700. else {
  701. // Service is not trusted to have a good Perf DLL
  702. SetLastError(ERROR_SUCCESS);
  703. }
  704. MemoryFree(szParam);
  705. }
  706. else {
  707. SetLastError(ERROR_OUTOFMEMORY);
  708. }
  709. MemoryFree(aszIniFile);
  710. }
  711. else {
  712. SetLastError(ERROR_OUTOFMEMORY);
  713. }
  714. return bReturn;
  715. }
  716. BOOL
  717. BuildLanguageTables(
  718. DWORD dwMode,
  719. LPWSTR lpIniFile,
  720. LPWSTR lpDriverName,
  721. PLANGUAGE_LIST_ELEMENT * pFirstElem
  722. )
  723. /*++
  724. BuildLanguageTables
  725. Creates a list of structures that will hold the text for
  726. each supported language
  727. Arguments
  728. lpIniFile
  729. Filename with data
  730. pFirstElem
  731. pointer to first list entry
  732. ReturnValue
  733. TRUE if all OK
  734. FALSE if not
  735. --*/
  736. {
  737. LPSTR lpEnumeratedLangs = NULL;
  738. LPSTR lpThisLang = NULL;
  739. LPWSTR lpSrchPath = NULL;
  740. LPSTR lpIniPath = NULL;
  741. LPWSTR lpInfPath = LoadPerfGetInfPath();
  742. HANDLE hFile = NULL;
  743. WIN32_FIND_DATAW FindFile;
  744. PLANGUAGE_LIST_ELEMENT pThisElem;
  745. DWORD dwSize;
  746. BOOL bReturn = FALSE;
  747. DWORD dwStatus = ERROR_SUCCESS;
  748. BOOL bFind = TRUE;
  749. DWORD dwPathSize = 0;
  750. DWORD dwFileSize = 0;
  751. LPSTR aszIniFile = NULL;
  752. HRESULT hr;
  753. BOOL bLocalizedBuild = (GetSystemDefaultUILanguage() != 0x0409) ? TRUE : FALSE;
  754. if (lpIniFile == NULL || pFirstElem == NULL || lpInfPath == NULL) {
  755. dwStatus = ERROR_INVALID_PARAMETER;
  756. goto Cleanup;
  757. }
  758. dwPathSize = lstrlenW(lpInfPath) + lstrlenW(lpIniFile) + 6; // "0404\"
  759. if (dwPathSize < MAX_PATH) dwPathSize = MAX_PATH;
  760. lpSrchPath = MemoryAllocate(sizeof(WCHAR) * dwPathSize + sizeof(CHAR) * dwPathSize);
  761. if (lpSrchPath == NULL) {
  762. dwStatus = ERROR_OUTOFMEMORY;
  763. goto Cleanup;
  764. }
  765. lpIniPath = (LPSTR) (((LPWSTR) lpSrchPath) + dwPathSize);
  766. if (! (dwMode & LODCTR_UPNF_NOBACKUP)) {
  767. hr = StringCchPrintfW(lpSrchPath, dwPathSize, L"%ws0*", lpInfPath);
  768. hFile = FindFirstFileExW(lpSrchPath,
  769. FindExInfoStandard,
  770. & FindFile,
  771. FindExSearchLimitToDirectories,
  772. NULL,
  773. 0);
  774. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
  775. dwStatus = ERROR_RESOURCE_LANG_NOT_FOUND;
  776. goto Cleanup;
  777. }
  778. }
  779. bFind = TRUE;
  780. while (bFind) {
  781. ZeroMemory(lpIniPath, dwPathSize * sizeof(CHAR));
  782. if (dwMode & LODCTR_UPNF_NOBACKUP) {
  783. hr = StringCchPrintfA(lpIniPath, dwPathSize, "%ws", lpIniFile);
  784. }
  785. else {
  786. hr = StringCchPrintfA(lpIniPath, dwPathSize, "%ws%ws%ws%ws%ws%ws",
  787. lpInfPath, FindFile.cFileName, Slash, lpDriverName, Slash, lpIniFile);
  788. }
  789. if (lpEnumeratedLangs == NULL) {
  790. dwFileSize = LoadPerfGetFileSize((LPWSTR) lpIniPath, NULL, FALSE);
  791. if (dwFileSize < SMALL_BUFFER_SIZE) dwFileSize = SMALL_BUFFER_SIZE;
  792. lpEnumeratedLangs = MemoryAllocate(dwFileSize * sizeof(CHAR));
  793. if (lpEnumeratedLangs == NULL) {
  794. dwStatus = ERROR_OUTOFMEMORY;
  795. goto Cleanup;
  796. }
  797. }
  798. else {
  799. ZeroMemory(lpEnumeratedLangs, dwFileSize * sizeof(CHAR));
  800. }
  801. dwSize = GetPrivateProfileStringA(szLanguages,
  802. NULL, // return all values in multi-sz string
  803. aszDefaultLangId, // english as the default
  804. lpEnumeratedLangs,
  805. dwFileSize,
  806. lpIniPath);
  807. if (dwSize == 0) {
  808. dwStatus = ERROR_RESOURCE_LANG_NOT_FOUND;
  809. goto Cleanup;
  810. }
  811. for (lpThisLang = lpEnumeratedLangs;
  812. lpThisLang != NULL && * lpThisLang != '\0';
  813. lpThisLang += (lstrlenA(lpThisLang) + 1)) {
  814. LPWSTR wszAllocLang = LoadPerfMultiByteToWideChar(CP_ACP, lpThisLang);
  815. LPWSTR wszThisLang = NULL;
  816. if (wszAllocLang == NULL) continue;
  817. if ((! bLocalizedBuild) && (LoadPerfGetLCIDFromString(wszAllocLang) == 0x0004)) {
  818. // Asshume that this is MUI build, so we should not use generic "004" LangId.
  819. // Instead, we should use "0804" or "0404" to separate CHT and CHS cases.
  820. //
  821. wszThisLang = FindFile.cFileName;
  822. }
  823. else {
  824. wszThisLang = wszAllocLang;
  825. }
  826. for (pThisElem = * pFirstElem; pThisElem != NULL; pThisElem = pThisElem->pNextLang) {
  827. if (lstrcmpiW(pThisElem->LangId, wszThisLang) == 0) {
  828. break;
  829. }
  830. }
  831. if (pThisElem != NULL) {
  832. // already support this language in INI file
  833. //
  834. continue;
  835. }
  836. pThisElem = MemoryAllocate(sizeof(LANGUAGE_LIST_ELEMENT) + (lstrlenW(wszThisLang) + 1) * sizeof(WCHAR));
  837. if (pThisElem == NULL) {
  838. dwStatus = ERROR_OUTOFMEMORY;
  839. continue;
  840. }
  841. // The following code is to build pFirstElem list. pFirstElem list will be returned back
  842. // to LoadPerfInstallPerfDll() function (LangList), then uses in UpdateRegistry().
  843. // Allocated memory will be freed at the end of LoadPerfInstallPerfDll().
  844. //
  845. pThisElem->pNextLang = * pFirstElem;
  846. * pFirstElem = pThisElem;
  847. pThisElem->LangId = (LPWSTR) (((LPBYTE) pThisElem) + sizeof(LANGUAGE_LIST_ELEMENT));
  848. hr = StringCchCopyW(pThisElem->LangId, lstrlenW(wszThisLang) + 1, wszThisLang);
  849. pThisElem->dwLangId = LoadPerfGetLCIDFromString(pThisElem->LangId);
  850. pThisElem->pFirstName = NULL;
  851. pThisElem->pThisName = NULL;
  852. pThisElem->dwNumElements = 0;
  853. pThisElem->NameBuffer = NULL;
  854. pThisElem->HelpBuffer = NULL;
  855. pThisElem->dwNameBuffSize = 0;
  856. pThisElem->dwHelpBuffSize = 0;
  857. TRACE((WINPERF_DBG_TRACE_INFO),
  858. (& LoadPerfGuid,
  859. __LINE__,
  860. LOADPERF_BUILDLANGUAGETABLES,
  861. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  862. ERROR_SUCCESS,
  863. TRACE_WSTR(lpIniFile),
  864. TRACE_WSTR(pThisElem->LangId),
  865. NULL));
  866. MemoryFree(wszAllocLang);
  867. }
  868. if (dwMode & LODCTR_UPNF_NOBACKUP) {
  869. bFind = FALSE;
  870. }
  871. else {
  872. bFind = FindNextFileW(hFile, & FindFile);
  873. }
  874. }
  875. if (* pFirstElem == NULL) {
  876. // then no languages were found
  877. dwStatus = ERROR_RESOURCE_LANG_NOT_FOUND;
  878. }
  879. else {
  880. bReturn = TRUE;
  881. }
  882. Cleanup:
  883. if (hFile != NULL && hFile != INVALID_HANDLE_VALUE) FindClose(hFile);
  884. MemoryFree(lpSrchPath);
  885. MemoryFree(lpEnumeratedLangs);
  886. if (! bReturn) {
  887. TRACE((WINPERF_DBG_TRACE_ERROR),
  888. (& LoadPerfGuid,
  889. __LINE__,
  890. LOADPERF_BUILDLANGUAGETABLES,
  891. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  892. dwStatus,
  893. TRACE_WSTR(lpIniFile),
  894. TRACE_WSTR(lpDriverName),
  895. NULL));
  896. SetLastError(dwStatus);
  897. }
  898. return bReturn;
  899. }
  900. BOOL
  901. LoadIncludeFile(
  902. BOOL bQuietMode,
  903. DWORD dwMode,
  904. LPWSTR lpIniFile,
  905. LPWSTR lpDriverName,
  906. PSYMBOL_TABLE_ENTRY * pTable
  907. )
  908. /*++
  909. LoadIncludeFile
  910. Reads the include file that contains symbolic name definitions and
  911. loads a table with the values defined
  912. Arguments
  913. lpIniFile
  914. Ini file with include file name
  915. pTable
  916. address of pointer to table structure created
  917. Return Value
  918. TRUE if table read or if no table defined
  919. FALSE if error encountere reading table
  920. --*/
  921. {
  922. INT iNumArgs;
  923. DWORD dwSize;
  924. DWORD dwFileSize;
  925. BOOL bReUse;
  926. PSYMBOL_TABLE_ENTRY pThisSymbol = NULL;
  927. LPWSTR szInfPath = LoadPerfGetInfPath();
  928. LPSTR lpIncludeFileName = NULL;
  929. LPSTR lpIncludeFile = NULL;
  930. LPSTR lpIniPath = NULL;
  931. LPSTR lpLineBuffer = NULL;
  932. LPSTR lpAnsiSymbol = NULL;
  933. LPSTR aszIniFile = NULL;
  934. FILE * fIncludeFile = NULL;
  935. DWORD dwLen;
  936. BOOL bReturn = FALSE;
  937. DWORD dwStatus = ERROR_SUCCESS;
  938. HRESULT hr;
  939. if (pTable == NULL || szInfPath == NULL || lpIniFile == NULL) {
  940. dwStatus = ERROR_INVALID_PARAMETER;
  941. goto Cleanup;
  942. }
  943. aszIniFile = LoadPerfWideCharToMultiByte(CP_ACP, lpIniFile);
  944. if (aszIniFile == NULL) {
  945. dwStatus = ERROR_OUTOFMEMORY;
  946. goto Cleanup;
  947. }
  948. dwFileSize = LoadPerfGetFileSize(lpIniFile, NULL, TRUE);
  949. if (dwFileSize < SMALL_BUFFER_SIZE) dwFileSize = SMALL_BUFFER_SIZE;
  950. lpIncludeFileName = MemoryAllocate(3 * dwFileSize * sizeof (CHAR));
  951. if (lpIncludeFileName == NULL) {
  952. ReportLoadPerfEvent(
  953. EVENTLOG_ERROR_TYPE, // error type
  954. (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event,
  955. 1, __LINE__, 0, 0, 0,
  956. 0, NULL, NULL, NULL);
  957. dwStatus = ERROR_OUTOFMEMORY;
  958. goto Cleanup;
  959. }
  960. lpLineBuffer = (LPSTR) (lpIncludeFileName + dwFileSize);
  961. lpAnsiSymbol = (LPSTR) (lpLineBuffer + dwFileSize);
  962. // get name of include file (if present)
  963. dwSize = GetPrivateProfileStringA(szInfo,
  964. szSymbolFile,
  965. szNotFound,
  966. lpIncludeFileName,
  967. dwFileSize,
  968. aszIniFile);
  969. TRACE((WINPERF_DBG_TRACE_INFO),
  970. (& LoadPerfGuid,
  971. __LINE__,
  972. LOADPERF_LOADINCLUDEFILE,
  973. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  974. ERROR_SUCCESS,
  975. TRACE_STR(aszIniFile),
  976. TRACE_STR(lpIncludeFileName),
  977. NULL));
  978. if (lstrcmpiA(lpIncludeFileName, szNotFound) == 0) {
  979. // no symbol file defined
  980. * pTable = NULL;
  981. dwStatus = ERROR_INVALID_DATA;
  982. bReturn = TRUE;
  983. goto Cleanup;
  984. }
  985. dwSize = lstrlenW(szInfPath) + lstrlenW(lpDriverName) + 10;
  986. if (dwSize < (DWORD) (lstrlenW(lpIniFile) + 1)) dwSize = lstrlenW(lpIniFile) + 1;
  987. if (dwSize < MAX_PATH) dwSize = MAX_PATH;
  988. lpIniPath = MemoryAllocate(2 * dwSize * sizeof(CHAR));
  989. if (lpIniPath == NULL) {
  990. dwStatus = ERROR_OUTOFMEMORY;
  991. goto Cleanup;
  992. }
  993. lpIncludeFile = (LPSTR) (lpIniPath + dwSize);
  994. // if here, then a symbol file was defined and is now stored in
  995. // lpIncludeFileName
  996. // get path for the ini file and search that first
  997. if (dwMode & LODCTR_UPNF_NOBACKUP) {
  998. DWORD dwPathSize = lstrlenW(lpIniFile) + 1;
  999. LPSTR szDrive = NULL;
  1000. LPSTR szDir = NULL;
  1001. if (dwPathSize < MAX_PATH) dwPathSize = MAX_PATH;
  1002. szDrive = MemoryAllocate(2 * dwPathSize * sizeof(CHAR));
  1003. if (szDrive == NULL) {
  1004. dwStatus = ERROR_OUTOFMEMORY;
  1005. goto Cleanup;
  1006. }
  1007. szDir = (LPSTR) (szDrive + dwPathSize);
  1008. _splitpath(aszIniFile, szDrive, szDir, NULL, NULL);
  1009. hr = StringCchPrintfA(lpIniPath, dwSize, "%s%s", szDrive, szDir);
  1010. MemoryFree(szDrive);
  1011. }
  1012. else {
  1013. hr = StringCchPrintfA(lpIniPath, dwSize, "%wsinc%ws%ws", szInfPath, Slash, lpDriverName);
  1014. }
  1015. dwLen = SearchPathA(lpIniPath, lpIncludeFileName, NULL, dwSize, lpIncludeFile, NULL);
  1016. if (dwLen == 0) {
  1017. // include file not found with the ini file so search the std. path
  1018. dwLen = SearchPathA(NULL, lpIncludeFileName, NULL, dwSize, lpIncludeFile, NULL);
  1019. }
  1020. if (dwLen > 0) {
  1021. // file name expanded and found so open
  1022. fIncludeFile = fopen(lpIncludeFile, "rt");
  1023. if (fIncludeFile == NULL) {
  1024. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_OPEN_INCLUDE), lpIncludeFileName);
  1025. * pTable = NULL;
  1026. dwStatus = ERROR_OPEN_FAILED;
  1027. TRACE((WINPERF_DBG_TRACE_INFO),
  1028. (& LoadPerfGuid,
  1029. __LINE__,
  1030. LOADPERF_LOADINCLUDEFILE,
  1031. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  1032. ERROR_OPEN_FAILED,
  1033. TRACE_STR(aszIniFile),
  1034. TRACE_STR(lpIncludeFile),
  1035. NULL));
  1036. goto Cleanup;
  1037. }
  1038. }
  1039. else {
  1040. // unable to find the include filename
  1041. // error is already in GetLastError
  1042. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_OPEN_INCLUDE), lpIncludeFileName);
  1043. * pTable = NULL;
  1044. dwStatus = ERROR_BAD_PATHNAME;
  1045. TRACE((WINPERF_DBG_TRACE_INFO),
  1046. (& LoadPerfGuid,
  1047. __LINE__,
  1048. LOADPERF_LOADINCLUDEFILE,
  1049. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  1050. ERROR_BAD_PATHNAME,
  1051. TRACE_STR(aszIniFile),
  1052. TRACE_STR(lpIncludeFileName),
  1053. NULL));
  1054. goto Cleanup;
  1055. }
  1056. //
  1057. // read ANSI Characters from include file
  1058. //
  1059. bReUse = FALSE;
  1060. while (fgets(lpLineBuffer, dwFileSize, fIncludeFile) != NULL) {
  1061. if (strlen(lpLineBuffer) > 8) {
  1062. if (! bReUse) {
  1063. // Build pTable list here. pTable list will be returned back to LoadPerfInstallPerfDll(),
  1064. // used in UpdateRegistry(), then freed at the end of LoadPerfInstallPerfDll().
  1065. //
  1066. if (* pTable) {
  1067. // then add to list
  1068. pThisSymbol->pNext = MemoryAllocate(sizeof(SYMBOL_TABLE_ENTRY));
  1069. pThisSymbol = pThisSymbol->pNext;
  1070. }
  1071. else { // allocate first element
  1072. * pTable = MemoryAllocate(sizeof(SYMBOL_TABLE_ENTRY));
  1073. pThisSymbol = * pTable;
  1074. }
  1075. if (pThisSymbol == NULL) {
  1076. dwStatus = ERROR_OUTOFMEMORY;
  1077. goto Cleanup;
  1078. }
  1079. }
  1080. // all the memory is allocated so load the fields
  1081. pThisSymbol->pNext = NULL;
  1082. iNumArgs = sscanf(lpLineBuffer, "#define %s %d", lpAnsiSymbol, & pThisSymbol->Value);
  1083. if (iNumArgs != 2) {
  1084. pThisSymbol->SymbolName = LoadPerfMultiByteToWideChar(CP_ACP, "");
  1085. pThisSymbol->Value = (DWORD) -1L;
  1086. bReUse = TRUE;
  1087. }
  1088. else {
  1089. pThisSymbol->SymbolName = LoadPerfMultiByteToWideChar(CP_ACP, lpAnsiSymbol);
  1090. TRACE((WINPERF_DBG_TRACE_INFO),
  1091. (& LoadPerfGuid,
  1092. __LINE__,
  1093. LOADPERF_LOADINCLUDEFILE,
  1094. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1095. ERROR_SUCCESS,
  1096. TRACE_STR(lpIncludeFileName),
  1097. TRACE_WSTR(pThisSymbol->SymbolName),
  1098. TRACE_DWORD(pThisSymbol->Value),
  1099. NULL));
  1100. bReUse = FALSE;
  1101. }
  1102. }
  1103. }
  1104. bReturn = TRUE;
  1105. Cleanup:
  1106. MemoryFree(aszIniFile);
  1107. MemoryFree(lpIncludeFileName);
  1108. MemoryFree(lpIniPath);
  1109. if (fIncludeFile != NULL) fclose(fIncludeFile);
  1110. if (! bReturn) {
  1111. TRACE((WINPERF_DBG_TRACE_ERROR),
  1112. (& LoadPerfGuid,
  1113. __LINE__,
  1114. LOADPERF_LOADINCLUDEFILE,
  1115. ARG_DEF(ARG_TYPE_WSTR, 1),
  1116. GetLastError(),
  1117. TRACE_WSTR(lpIniFile),
  1118. NULL));
  1119. SetLastError(dwStatus);
  1120. }
  1121. return bReturn;
  1122. }
  1123. BOOL
  1124. ParseTextId(
  1125. LPWSTR lpTextId,
  1126. PSYMBOL_TABLE_ENTRY pFirstSymbol,
  1127. PDWORD pdwOffset,
  1128. LPWSTR * lpLangId,
  1129. PDWORD pdwType
  1130. )
  1131. /*++
  1132. ParseTextId
  1133. decodes Text Id key from .INI file
  1134. syntax for this process is:
  1135. {<DecimalNumber>} {"NAME"}
  1136. {<SymbolInTable>}_<LangIdString>_{"HELP"}
  1137. e.g. 0_009_NAME
  1138. OBJECT_1_009_HELP
  1139. Arguments
  1140. lpTextId
  1141. string to decode
  1142. pFirstSymbol
  1143. pointer to first entry in symbol table (NULL if no table)
  1144. pdwOffset
  1145. address of DWORD to recive offest value
  1146. lpLangId
  1147. address of pointer to Language Id string
  1148. (NOTE: this will point into the string lpTextID which will be
  1149. modified by this routine)
  1150. pdwType
  1151. pointer to dword that will recieve the type of string i.e.
  1152. HELP or NAME
  1153. Return Value
  1154. TRUE text Id decoded successfully
  1155. FALSE unable to decode string
  1156. NOTE: the string in lpTextID will be modified by this procedure
  1157. --*/
  1158. {
  1159. BOOL bReturn = FALSE;
  1160. DWORD Status = ERROR_SUCCESS;
  1161. LPWSTR lpThisChar;
  1162. PSYMBOL_TABLE_ENTRY pThisSymbol;
  1163. // check for valid return arguments
  1164. if (pdwOffset == NULL || lpLangId == NULL || pdwType == NULL) {
  1165. Status = ERROR_INVALID_PARAMETER;
  1166. goto Cleanup;
  1167. }
  1168. // search string from right to left in order to identify the
  1169. // components of the string.
  1170. lpThisChar = lpTextId + lstrlenW(lpTextId); // point to end of string
  1171. while (lpThisChar > lpTextId && * lpThisChar != cUnderscore) {
  1172. lpThisChar --;
  1173. }
  1174. if (lpThisChar <= lpTextId) {
  1175. // underscore not found in string
  1176. Status = ERROR_INVALID_DATA;
  1177. goto Cleanup;
  1178. }
  1179. // first underscore found
  1180. if (lstrcmpiW(lpThisChar, szName) == 0) {
  1181. // name found, so set type
  1182. * pdwType = TYPE_NAME;
  1183. }
  1184. else if (lstrcmpiW(lpThisChar, szHelp) == 0) {
  1185. // help text found, so set type
  1186. * pdwType = TYPE_HELP;
  1187. }
  1188. else {
  1189. // bad format
  1190. Status = ERROR_INVALID_DATA;
  1191. goto Cleanup;
  1192. }
  1193. // set the current underscore to \0 and look for language ID
  1194. * lpThisChar-- = L'\0';
  1195. while (lpThisChar > lpTextId && * lpThisChar != cUnderscore) {
  1196. lpThisChar --;
  1197. }
  1198. if (lpThisChar <= lpTextId) {
  1199. // underscore not found in string
  1200. Status = ERROR_INVALID_DATA;
  1201. goto Cleanup;
  1202. }
  1203. // set lang ID string pointer to current char ('_') + 1
  1204. * lpLangId = lpThisChar + 1;
  1205. // set this underscore to a NULL and try to decode the remaining text
  1206. * lpThisChar = L'\0';
  1207. // see if the first part of the string is a decimal digit
  1208. if (swscanf(lpTextId, sz_DFormat, pdwOffset) != 1) {
  1209. // it's not a digit, so try to decode it as a symbol in the
  1210. // loaded symbol table
  1211. for (pThisSymbol=pFirstSymbol;
  1212. pThisSymbol != NULL && * pThisSymbol->SymbolName != L'\0';
  1213. pThisSymbol = pThisSymbol->pNext) {
  1214. if (lstrcmpiW(lpTextId, pThisSymbol->SymbolName) == 0) {
  1215. // a matching symbol was found, so insert it's value
  1216. // and return (that's all that needs to be done
  1217. * pdwOffset = pThisSymbol->Value;
  1218. bReturn = TRUE;
  1219. break;
  1220. }
  1221. }
  1222. if (! bReturn) {
  1223. // if here, then no matching symbol was found, and it's not
  1224. // a number, so return an error
  1225. Status = ERROR_BAD_TOKEN_TYPE;
  1226. }
  1227. }
  1228. else {
  1229. // symbol was prefixed with a decimal number
  1230. bReturn = TRUE;
  1231. }
  1232. Cleanup:
  1233. if (! bReturn) {
  1234. SetLastError(Status);
  1235. }
  1236. return bReturn;
  1237. }
  1238. PLANGUAGE_LIST_ELEMENT
  1239. FindLanguage(
  1240. PLANGUAGE_LIST_ELEMENT pFirstLang,
  1241. LPCWSTR pLangId
  1242. )
  1243. /*++
  1244. FindLanguage
  1245. searchs the list of languages and returns a pointer to the language
  1246. list entry that matches the pLangId string argument
  1247. Arguments
  1248. pFirstLang
  1249. pointer to first language list element
  1250. pLangId
  1251. pointer to text string with language ID to look up
  1252. Return Value
  1253. Pointer to matching language list entry
  1254. or NULL if no match
  1255. --*/
  1256. {
  1257. PLANGUAGE_LIST_ELEMENT pRtnLang = NULL;
  1258. PLANGUAGE_LIST_ELEMENT pThisLang;
  1259. DWORD dwLang = LoadPerfGetLCIDFromString((LPWSTR) pLangId);
  1260. DWORD dwSubLang;
  1261. for (pThisLang = pFirstLang; pThisLang; pThisLang = pThisLang->pNextLang) {
  1262. if (pThisLang->dwLangId == dwLang) {
  1263. // match found so return pointer
  1264. pRtnLang = pThisLang;
  1265. break;
  1266. }
  1267. }
  1268. if (pRtnLang == NULL) {
  1269. dwSubLang = (dwLang == PRIMARYLANGID(GetUserDefaultUILanguage()))
  1270. ? (GetUserDefaultUILanguage()) : (PRIMARYLANGID(dwLang));
  1271. if (dwSubLang != dwLang) {
  1272. for (pThisLang = pFirstLang; pThisLang; pThisLang = pThisLang->pNextLang) {
  1273. if (pThisLang->dwLangId == dwSubLang) {
  1274. // match found so return pointer
  1275. pRtnLang = pThisLang;
  1276. break;
  1277. }
  1278. }
  1279. }
  1280. }
  1281. return pRtnLang;
  1282. }
  1283. BOOL
  1284. GetValueW(
  1285. PLANGUAGE_LIST_ELEMENT pLang,
  1286. LPWSTR lpLocalSectionBuff,
  1287. LPWSTR * lpLocalStringBuff
  1288. )
  1289. {
  1290. LPWSTR lpPosition;
  1291. LPWSTR szThisLang = LoadPerfGetLanguage(pLang->LangId, FALSE);
  1292. BOOL bReturn = FALSE;
  1293. DWORD dwSize;
  1294. HRESULT hr;
  1295. if (lpLocalStringBuff != NULL && szThisLang != NULL) {
  1296. * lpLocalStringBuff = NULL;
  1297. lpPosition = wcschr(lpLocalSectionBuff, wEquals);
  1298. if (lpPosition) {
  1299. lpPosition ++;
  1300. // make sure the "=" isn't the last char
  1301. dwSize = (* lpPosition != L'\0') ? (lstrlenW(lpPosition) + 1) : (2);
  1302. * lpLocalStringBuff = MemoryAllocate(dwSize * sizeof(WCHAR));
  1303. if (* lpLocalStringBuff != NULL) {
  1304. hr = (* lpPosition != L'\0')
  1305. ? StringCchCopyW(* lpLocalStringBuff, dwSize, lpPosition)
  1306. : StringCchCopyW(* lpLocalStringBuff, dwSize, L" ");
  1307. bReturn = TRUE;
  1308. }
  1309. else {
  1310. SetLastError(ERROR_OUTOFMEMORY);
  1311. }
  1312. }
  1313. else {
  1314. //ErrorFinfing the "="
  1315. // bad format
  1316. SetLastError(ERROR_INVALID_DATA);
  1317. }
  1318. }
  1319. return bReturn;
  1320. }
  1321. BOOL
  1322. GetValueFromIniKeyW(
  1323. PLANGUAGE_LIST_ELEMENT pLang,
  1324. LPWSTR lpValueKey,
  1325. LPWSTR lpTextSection,
  1326. DWORD * pdwLastReadOffset,
  1327. DWORD dwTryCount,
  1328. LPWSTR * lpLocalStringBuff
  1329. )
  1330. {
  1331. LPWSTR lpLocalSectionBuff;
  1332. DWORD dwIndex;
  1333. DWORD dwLastReadOffset;
  1334. BOOL bRetVal = FALSE;
  1335. if (lpTextSection != NULL && lpValueKey != NULL ) {
  1336. dwLastReadOffset = * pdwLastReadOffset;
  1337. lpLocalSectionBuff = lpTextSection;
  1338. lpLocalSectionBuff += dwLastReadOffset;
  1339. while(* lpLocalSectionBuff != L'\0') {
  1340. dwLastReadOffset += (lstrlenW(lpTextSection + dwLastReadOffset) + 1);
  1341. lpLocalSectionBuff = lpTextSection + dwLastReadOffset;
  1342. * pdwLastReadOffset = dwLastReadOffset;
  1343. }
  1344. // search next N entries in buffer for entry
  1345. // this should usually work since the file
  1346. // is scanned sequentially so it's tried first
  1347. for (dwIndex = 0; dwIndex < dwTryCount; dwIndex ++) {
  1348. // see if this is the correct entry
  1349. // and return it if it is
  1350. if (wcsstr(lpLocalSectionBuff, lpValueKey)) {
  1351. bRetVal = GetValueW(pLang, lpLocalSectionBuff, lpLocalStringBuff);
  1352. //Set the lastReadOffset First
  1353. dwLastReadOffset += (lstrlenW(lpTextSection + dwLastReadOffset) + 1);
  1354. * pdwLastReadOffset = dwLastReadOffset;
  1355. break; // out of the for loop
  1356. }
  1357. else {
  1358. // this isn't the correct one so go to the next
  1359. // entry in the file
  1360. dwLastReadOffset += (lstrlenW(lpTextSection + dwLastReadOffset) + 1);
  1361. lpLocalSectionBuff = lpTextSection + dwLastReadOffset;
  1362. * pdwLastReadOffset = dwLastReadOffset;
  1363. }
  1364. }
  1365. if (! bRetVal) {
  1366. //Cannont Find the key using lastReadOffset
  1367. //try again from the beggining of the Array
  1368. dwLastReadOffset = 0;
  1369. lpLocalSectionBuff = lpTextSection;
  1370. * pdwLastReadOffset = dwLastReadOffset;
  1371. while (* lpLocalSectionBuff != L'\0') {
  1372. if (wcsstr(lpLocalSectionBuff, lpValueKey)) {
  1373. bRetVal = GetValueW(pLang, lpLocalSectionBuff, lpLocalStringBuff);
  1374. break;
  1375. }
  1376. else {
  1377. // go to the next entry
  1378. dwLastReadOffset += (lstrlenW(lpTextSection + dwLastReadOffset) + 1);
  1379. lpLocalSectionBuff = lpTextSection + dwLastReadOffset;
  1380. * pdwLastReadOffset = dwLastReadOffset;
  1381. }
  1382. }
  1383. }
  1384. }
  1385. return bRetVal;
  1386. }
  1387. BOOL
  1388. GetValueA(
  1389. PLANGUAGE_LIST_ELEMENT pLang,
  1390. LPSTR lpLocalSectionBuff,
  1391. LPWSTR * lpLocalStringBuff
  1392. )
  1393. {
  1394. LPSTR lpPosition;
  1395. LPWSTR szThisLang = LoadPerfGetLanguage(pLang->LangId, FALSE);
  1396. BOOL bReturn = FALSE;
  1397. if (lpLocalStringBuff != NULL && szThisLang != NULL) {
  1398. * lpLocalStringBuff = NULL;
  1399. lpPosition = strchr(lpLocalSectionBuff, cEquals);
  1400. if (lpPosition) {
  1401. lpPosition ++;
  1402. // make sure the "=" isn't the last char
  1403. if (* lpPosition != '\0') {
  1404. //Found the "equals" sign
  1405. * lpLocalStringBuff = LoadPerfMultiByteToWideChar(LoadPerfGetCodePage(szThisLang), lpPosition);
  1406. }
  1407. else {
  1408. // empty string, return a pseudo blank string
  1409. * lpLocalStringBuff = LoadPerfMultiByteToWideChar(LoadPerfGetCodePage(szThisLang), " ");
  1410. }
  1411. bReturn = TRUE;
  1412. }
  1413. else {
  1414. //ErrorFinfing the "="
  1415. // bad format
  1416. SetLastError(ERROR_INVALID_DATA);
  1417. }
  1418. }
  1419. return bReturn;
  1420. }
  1421. BOOL
  1422. GetValueFromIniKeyA(
  1423. PLANGUAGE_LIST_ELEMENT pLang,
  1424. LPSTR lpValueKey,
  1425. LPSTR lpTextSection,
  1426. DWORD * pdwLastReadOffset,
  1427. DWORD dwTryCount,
  1428. LPWSTR * lpLocalStringBuff
  1429. )
  1430. {
  1431. LPSTR lpLocalSectionBuff;
  1432. DWORD dwIndex;
  1433. DWORD dwLastReadOffset;
  1434. BOOL bRetVal = FALSE;
  1435. if (lpTextSection != NULL && lpValueKey != NULL ) {
  1436. dwLastReadOffset = * pdwLastReadOffset;
  1437. lpLocalSectionBuff = lpTextSection;
  1438. lpLocalSectionBuff += dwLastReadOffset;
  1439. while(! (* lpLocalSectionBuff)) {
  1440. dwLastReadOffset += (lstrlenA(lpTextSection + dwLastReadOffset) + 1);
  1441. lpLocalSectionBuff = lpTextSection + dwLastReadOffset;
  1442. * pdwLastReadOffset = dwLastReadOffset;
  1443. }
  1444. // search next N entries in buffer for entry
  1445. // this should usually work since the file
  1446. // is scanned sequentially so it's tried first
  1447. for (dwIndex = 0; dwIndex < dwTryCount; dwIndex++) {
  1448. // see if this is the correct entry
  1449. // and return it if it is
  1450. if (strstr(lpLocalSectionBuff, lpValueKey)) {
  1451. bRetVal = GetValueA(pLang, lpLocalSectionBuff, lpLocalStringBuff);
  1452. //Set the lastReadOffset First
  1453. dwLastReadOffset += (lstrlenA(lpTextSection + dwLastReadOffset) + 1);
  1454. * pdwLastReadOffset = dwLastReadOffset;
  1455. break; // out of the for loop
  1456. }
  1457. else {
  1458. // this isn't the correct one so go to the next
  1459. // entry in the file
  1460. dwLastReadOffset += (lstrlenA(lpTextSection + dwLastReadOffset) + 1);
  1461. lpLocalSectionBuff = lpTextSection + dwLastReadOffset;
  1462. * pdwLastReadOffset = dwLastReadOffset;
  1463. }
  1464. }
  1465. if (! bRetVal) {
  1466. //Cannont Find the key using lastReadOffset
  1467. //try again from the beggining of the Array
  1468. dwLastReadOffset = 0;
  1469. lpLocalSectionBuff = lpTextSection;
  1470. * pdwLastReadOffset = dwLastReadOffset;
  1471. while (* lpLocalSectionBuff != '\0') {
  1472. if (strstr(lpLocalSectionBuff, lpValueKey)) {
  1473. bRetVal = GetValueA(pLang, lpLocalSectionBuff, lpLocalStringBuff);
  1474. break;
  1475. }
  1476. else {
  1477. // go to the next entry
  1478. dwLastReadOffset += (lstrlenA(lpTextSection + dwLastReadOffset) + 1);
  1479. lpLocalSectionBuff = lpTextSection + dwLastReadOffset;
  1480. * pdwLastReadOffset = dwLastReadOffset;
  1481. }
  1482. }
  1483. }
  1484. }
  1485. return bRetVal;
  1486. }
  1487. BOOL
  1488. AddEntryToLanguage(
  1489. PLANGUAGE_LIST_ELEMENT pLang,
  1490. LPWSTR lpValueKey,
  1491. LPWSTR lpTextSection,
  1492. DWORD dwUnicode,
  1493. DWORD * pdwLastReadOffset,
  1494. DWORD dwTryCount,
  1495. DWORD dwType,
  1496. DWORD dwOffset,
  1497. DWORD dwFileSize
  1498. )
  1499. /*++
  1500. AddEntryToLanguage
  1501. Add a text entry to the list of text entries for the specified language
  1502. Arguments
  1503. pLang
  1504. pointer to language structure to update
  1505. lpValueKey
  1506. value key to look up in .ini file
  1507. dwOffset
  1508. numeric offset of name in registry
  1509. lpIniFile
  1510. ini file
  1511. Return Value
  1512. TRUE if added successfully
  1513. FALSE if error
  1514. (see GetLastError for status)
  1515. --*/
  1516. {
  1517. LPWSTR lpLocalStringBuff = NULL;
  1518. LPSTR aszValueKey = (LPSTR) lpValueKey;
  1519. LPSTR aszTextSection = (LPSTR) lpTextSection;
  1520. DWORD dwBufferSize = 0;
  1521. DWORD dwStatus = ERROR_SUCCESS;
  1522. BOOL bRetVal;
  1523. BOOL bReturn = FALSE;
  1524. HRESULT hr;
  1525. if ((dwType == TYPE_NAME && dwOffset < FIRST_EXT_COUNTER_INDEX)
  1526. || (dwType == TYPE_HELP && dwOffset < FIRST_EXT_HELP_INDEX)) {
  1527. ReportLoadPerfEvent(
  1528. EVENTLOG_ERROR_TYPE,
  1529. (DWORD) LDPRFMSG_CORRUPT_INDEX,
  1530. 3, dwOffset, dwType, __LINE__, 0,
  1531. 1, lpValueKey, NULL, NULL);
  1532. if (dwUnicode == 0) {
  1533. TRACE((WINPERF_DBG_TRACE_ERROR),
  1534. (& LoadPerfGuid,
  1535. __LINE__,
  1536. LOADPERF_ADDENTRYTOLANGUAGE,
  1537. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  1538. ERROR_BADKEY,
  1539. TRACE_STR(aszTextSection),
  1540. TRACE_STR(aszValueKey),
  1541. TRACE_DWORD(dwType),
  1542. TRACE_DWORD(dwOffset),
  1543. NULL));
  1544. }
  1545. else {
  1546. TRACE((WINPERF_DBG_TRACE_ERROR),
  1547. (& LoadPerfGuid,
  1548. __LINE__,
  1549. LOADPERF_ADDENTRYTOLANGUAGE,
  1550. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1551. ERROR_BADKEY,
  1552. TRACE_WSTR(lpTextSection),
  1553. TRACE_WSTR(lpValueKey),
  1554. TRACE_DWORD(dwType),
  1555. TRACE_DWORD(dwOffset),
  1556. NULL));
  1557. }
  1558. dwStatus = ERROR_BADKEY;
  1559. goto Cleanup;
  1560. }
  1561. if (lpValueKey != NULL) {
  1562. if (dwUnicode == 0) {
  1563. bRetVal = GetValueFromIniKeyA(pLang,
  1564. aszValueKey,
  1565. aszTextSection,
  1566. pdwLastReadOffset,
  1567. dwTryCount,
  1568. & lpLocalStringBuff);
  1569. }
  1570. else {
  1571. bRetVal = GetValueFromIniKeyW(pLang,
  1572. lpValueKey,
  1573. lpTextSection,
  1574. pdwLastReadOffset,
  1575. dwTryCount,
  1576. & lpLocalStringBuff);
  1577. }
  1578. if (! bRetVal || lpLocalStringBuff == NULL) {
  1579. DWORD dwLastReadOffset = * pdwLastReadOffset;
  1580. if (dwUnicode == 0) {
  1581. TRACE((WINPERF_DBG_TRACE_ERROR),
  1582. (& LoadPerfGuid,
  1583. __LINE__,
  1584. LOADPERF_ADDENTRYTOLANGUAGE,
  1585. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  1586. ERROR_BADKEY,
  1587. TRACE_STR(aszTextSection),
  1588. TRACE_STR(aszValueKey),
  1589. TRACE_DWORD(dwLastReadOffset),
  1590. NULL));
  1591. }
  1592. else {
  1593. TRACE((WINPERF_DBG_TRACE_ERROR),
  1594. (& LoadPerfGuid,
  1595. __LINE__,
  1596. LOADPERF_ADDENTRYTOLANGUAGE,
  1597. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1598. ERROR_BADKEY,
  1599. TRACE_WSTR(lpTextSection),
  1600. TRACE_WSTR(lpValueKey),
  1601. TRACE_DWORD(dwLastReadOffset),
  1602. NULL));
  1603. }
  1604. dwStatus = ERROR_BADKEY;
  1605. goto Cleanup;
  1606. }
  1607. else if (lstrcmpiW(lpLocalStringBuff, wszNotFound) == 0) {
  1608. if (dwUnicode == 0) {
  1609. TRACE((WINPERF_DBG_TRACE_ERROR),
  1610. (& LoadPerfGuid,
  1611. __LINE__,
  1612. LOADPERF_ADDENTRYTOLANGUAGE,
  1613. ARG_DEF(ARG_TYPE_STR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  1614. ERROR_BADKEY,
  1615. TRACE_STR(aszTextSection),
  1616. TRACE_STR(aszValueKey),
  1617. NULL));
  1618. }
  1619. else {
  1620. TRACE((WINPERF_DBG_TRACE_ERROR),
  1621. (& LoadPerfGuid,
  1622. __LINE__,
  1623. LOADPERF_ADDENTRYTOLANGUAGE,
  1624. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1625. ERROR_BADKEY,
  1626. TRACE_WSTR(lpTextSection),
  1627. TRACE_WSTR(lpValueKey),
  1628. NULL));
  1629. }
  1630. dwStatus = ERROR_BADKEY;
  1631. goto Cleanup;
  1632. }
  1633. }
  1634. else {
  1635. dwBufferSize = lstrlenW(lpTextSection) + 1;
  1636. lpLocalStringBuff = MemoryAllocate(dwBufferSize * sizeof(WCHAR));
  1637. if (!lpLocalStringBuff) {
  1638. dwStatus = ERROR_OUTOFMEMORY;
  1639. goto Cleanup;
  1640. }
  1641. hr = StringCchCopyW(lpLocalStringBuff, dwBufferSize, lpTextSection);
  1642. }
  1643. // key found, so load structure
  1644. if (! pLang->pThisName) {
  1645. // this is the first
  1646. pLang->pThisName = MemoryAllocate(sizeof(NAME_ENTRY) +
  1647. (lstrlenW(lpLocalStringBuff) + 1) * sizeof (WCHAR));
  1648. if (!pLang->pThisName) {
  1649. dwStatus = ERROR_OUTOFMEMORY;
  1650. goto Cleanup;
  1651. }
  1652. else {
  1653. pLang->pFirstName = pLang->pThisName;
  1654. }
  1655. }
  1656. else {
  1657. pLang->pThisName->pNext = MemoryAllocate(sizeof(NAME_ENTRY) +
  1658. (lstrlenW(lpLocalStringBuff) + 1) * sizeof (WCHAR));
  1659. if (!pLang->pThisName->pNext) {
  1660. dwStatus = ERROR_OUTOFMEMORY;
  1661. goto Cleanup;
  1662. }
  1663. else {
  1664. pLang->pThisName = pLang->pThisName->pNext;
  1665. }
  1666. }
  1667. // pLang->pThisName now points to an uninitialized structre
  1668. pLang->pThisName->pNext = NULL;
  1669. pLang->pThisName->dwOffset = dwOffset;
  1670. pLang->pThisName->dwType = dwType;
  1671. pLang->pThisName->lpText = (LPWSTR) & (pLang->pThisName[1]);
  1672. hr = StringCchCopyW(pLang->pThisName->lpText, lstrlenW(lpLocalStringBuff) + 1, lpLocalStringBuff);
  1673. bReturn = TRUE;
  1674. Cleanup:
  1675. MemoryFree(lpLocalStringBuff);
  1676. SetLastError(dwStatus);
  1677. return (bReturn);
  1678. }
  1679. BOOL
  1680. CreateObjectList(
  1681. LPWSTR lpIniFile,
  1682. DWORD dwFirstDriverCounter,
  1683. PSYMBOL_TABLE_ENTRY pFirstSymbol,
  1684. LPWSTR lpszObjectList,
  1685. DWORD dwObjectList,
  1686. LPDWORD pdwObjectGuidTableEntries
  1687. )
  1688. {
  1689. WCHAR szDigits[32];
  1690. LPWSTR szLangId;
  1691. LPWSTR szTempString;
  1692. LPSTR szGuidStringBuffer;
  1693. LPSTR szThisKey;
  1694. DWORD dwSize;
  1695. DWORD dwObjectCount = 0;
  1696. DWORD dwId;
  1697. DWORD dwType;
  1698. DWORD dwObjectGuidIndex = 0;
  1699. DWORD dwObjects[MAX_PERF_OBJECTS_IN_QUERY_FUNCTION];
  1700. DWORD dwBufferSize = 0;
  1701. LPSTR szObjectSectionEntries = NULL;
  1702. BOOL bResult = FALSE;
  1703. DWORD dwStatus = ERROR_SUCCESS;
  1704. LPSTR aszIniFile = NULL;
  1705. HRESULT hr;
  1706. if (lpIniFile == NULL) {
  1707. dwStatus = ERROR_INVALID_PARAMETER;
  1708. goto Cleanup;
  1709. }
  1710. aszIniFile = LoadPerfWideCharToMultiByte(CP_ACP, lpIniFile);
  1711. if (aszIniFile == NULL) {
  1712. dwStatus = ERROR_OUTOFMEMORY;
  1713. goto Cleanup;
  1714. }
  1715. dwBufferSize = LoadPerfGetFileSize(lpIniFile, NULL, TRUE);
  1716. if (dwBufferSize != 0xFFFFFFFF) {
  1717. dwBufferSize *= sizeof(WCHAR);
  1718. }
  1719. else {
  1720. dwBufferSize = 0;
  1721. }
  1722. if (dwBufferSize < SMALL_BUFFER_SIZE) {
  1723. dwBufferSize = SMALL_BUFFER_SIZE;
  1724. }
  1725. szObjectSectionEntries = MemoryAllocate(dwBufferSize * sizeof(CHAR));
  1726. if (szObjectSectionEntries == NULL) {
  1727. dwStatus = ERROR_OUTOFMEMORY;
  1728. goto Cleanup;
  1729. }
  1730. dwSize = GetPrivateProfileStringA(
  1731. szObjects,
  1732. NULL,
  1733. szNotFound,
  1734. szObjectSectionEntries,
  1735. dwBufferSize,
  1736. aszIniFile);
  1737. * lpszObjectList = L'\0';
  1738. dwObjectCount = 0;
  1739. if (lstrcmpiA(szObjectSectionEntries, szNotFound) != 0) {
  1740. // then some entries were found so read each one, compute the
  1741. // index value and save in the string buffer passed by the caller
  1742. for (szThisKey = szObjectSectionEntries; * szThisKey != '\0'; szThisKey += (lstrlenA(szThisKey) + 1)) {
  1743. // ParstTextId modifies the string so we need to make a work copy
  1744. szTempString = LoadPerfMultiByteToWideChar(CP_ACP, szThisKey);
  1745. if(szTempString == NULL) continue;
  1746. if (ParseTextId(szTempString, pFirstSymbol, & dwId, & szLangId, & dwType)) {
  1747. // then dwID is the id of an object supported by this DLL
  1748. for (dwSize = 0; dwSize < dwObjectCount; dwSize ++) {
  1749. if ((dwId + dwFirstDriverCounter) == dwObjects[dwSize]) {
  1750. break;
  1751. }
  1752. }
  1753. if (dwSize >= dwObjectCount) {
  1754. if (dwObjectCount < MAX_PERF_OBJECTS_IN_QUERY_FUNCTION) {
  1755. if (dwObjectCount != 0) {
  1756. hr = StringCchCatW(lpszObjectList, dwObjectList, BlankString);
  1757. }
  1758. dwObjects[dwObjectCount] = dwId + dwFirstDriverCounter;
  1759. _ultow((dwId + dwFirstDriverCounter), szDigits, 10);
  1760. hr = StringCchCatW(lpszObjectList, dwObjectList, szDigits);
  1761. dwObjectCount ++;
  1762. }
  1763. else {
  1764. // Too manu objects defined in INI file. Ignore.
  1765. continue;
  1766. }
  1767. }
  1768. //
  1769. // now see if this object has a GUID string
  1770. //
  1771. szGuidStringBuffer = MemoryAllocate(dwBufferSize * sizeof(CHAR));
  1772. if (szGuidStringBuffer == NULL) {
  1773. MemoryFree(szTempString);
  1774. continue;
  1775. }
  1776. MemoryFree(szGuidStringBuffer);
  1777. }
  1778. MemoryFree(szTempString);
  1779. }
  1780. // save size of Guid Table
  1781. * pdwObjectGuidTableEntries = dwObjectGuidIndex;
  1782. }
  1783. else {
  1784. // log message that object list is not used
  1785. TRACE((WINPERF_DBG_TRACE_WARNING),
  1786. (& LoadPerfGuid,
  1787. __LINE__,
  1788. LOADPERF_CREATEOBJECTLIST,
  1789. ARG_DEF(ARG_TYPE_WSTR, 1),
  1790. ERROR_SUCCESS,
  1791. TRACE_WSTR(lpIniFile),
  1792. TRACE_DWORD(dwFirstDriverCounter),
  1793. NULL));
  1794. }
  1795. bResult = TRUE;
  1796. Cleanup:
  1797. MemoryFree(szObjectSectionEntries);
  1798. MemoryFree(aszIniFile);
  1799. if (! bResult) SetLastError(dwStatus);
  1800. return bResult;
  1801. }
  1802. BOOL
  1803. LoadLanguageLists(
  1804. BOOL bQuietMode,
  1805. LPWSTR lpIniFile,
  1806. LPWSTR lpDriverName,
  1807. DWORD dwMode,
  1808. DWORD dwFirstCounter,
  1809. DWORD dwFirstHelp,
  1810. PSYMBOL_TABLE_ENTRY pFirstSymbol,
  1811. PLANGUAGE_LIST_ELEMENT pFirstLang
  1812. )
  1813. /*++
  1814. LoadLanguageLists
  1815. Reads in the name and explain text definitions from the ini file and
  1816. builds a list of these items for each of the supported languages and
  1817. then combines all the entries into a sorted MULTI_SZ string buffer.
  1818. Arguments
  1819. lpIniFile
  1820. file containing the definitions to add to the registry
  1821. dwFirstCounter
  1822. starting counter name index number
  1823. dwFirstHelp
  1824. starting help text index number
  1825. pFirstLang
  1826. pointer to first element in list of language elements
  1827. Return Value
  1828. TRUE if all is well
  1829. FALSE if not
  1830. error is returned in GetLastError
  1831. --*/
  1832. {
  1833. LPSTR lpTextIdArray = NULL;
  1834. LPWSTR lpLocalKey = NULL;
  1835. LPWSTR lpThisLocalKey = NULL;
  1836. LPSTR lpThisIniFile = NULL;
  1837. LPWSTR lpwThisIniFile = NULL;
  1838. LPSTR lpThisKey = NULL;
  1839. LPSTR lpTextSectionArray = NULL;
  1840. LPWSTR lpInfPath = LoadPerfGetInfPath();
  1841. DWORD dwSize;
  1842. LPWSTR lpLang;
  1843. DWORD dwOffset;
  1844. DWORD dwType;
  1845. DWORD dwUnicode;
  1846. PLANGUAGE_LIST_ELEMENT pThisLang;
  1847. DWORD dwBufferSize;
  1848. DWORD dwPathSize;
  1849. DWORD dwSuccessCount = 0;
  1850. DWORD dwErrorCount = 0;
  1851. DWORD dwLastReadOffset = 0;
  1852. DWORD dwTryCount = 4; // Init this value with 4
  1853. // (at least 4 times to try maching Key and Value)
  1854. HRESULT hr;
  1855. pThisLang = pFirstLang;
  1856. while (pThisLang != NULL) {
  1857. // if you have more languages then increase this try limit to
  1858. // 4 + No. of langs
  1859. dwTryCount ++;
  1860. pThisLang = pThisLang->pNextLang;
  1861. }
  1862. if (lpIniFile == NULL || lpInfPath == NULL) {
  1863. dwErrorCount = 1;
  1864. SetLastError(ERROR_INVALID_PARAMETER);
  1865. goto Cleanup;
  1866. }
  1867. dwPathSize = lstrlenW(lpInfPath) + lstrlenW(lpDriverName) + lstrlenW(lpIniFile) + 10;
  1868. if (dwPathSize < MAX_PATH) dwPathSize = MAX_PATH;
  1869. TRACE((WINPERF_DBG_TRACE_INFO),
  1870. (& LoadPerfGuid,
  1871. __LINE__,
  1872. LOADPERF_LOADLANGUAGELISTS,
  1873. ARG_DEF(ARG_TYPE_WSTR, 1),
  1874. ERROR_SUCCESS,
  1875. TRACE_WSTR(lpIniFile),
  1876. TRACE_DWORD(dwFirstCounter),
  1877. TRACE_DWORD(dwFirstHelp),
  1878. NULL));
  1879. for (pThisLang = pFirstLang; pThisLang != NULL; pThisLang = pThisLang->pNextLang) {
  1880. WORD wLangTable = LoadPerfGetLCIDFromString(pThisLang->LangId);
  1881. WORD wLangId;
  1882. BOOL bAddEntry;
  1883. if (dwMode & LODCTR_UPNF_NOBACKUP) {
  1884. lpThisIniFile = LoadPerfWideCharToMultiByte(CP_ACP, lpIniFile);
  1885. if (lpThisIniFile == NULL) {
  1886. continue;
  1887. }
  1888. }
  1889. else {
  1890. LPWSTR szThisLang = LoadPerfGetLanguage(pThisLang->LangId, FALSE);
  1891. lpThisIniFile = MemoryAllocate(dwPathSize * sizeof(CHAR));
  1892. if (lpThisIniFile == NULL) {
  1893. continue;
  1894. }
  1895. hr = StringCchPrintfA(lpThisIniFile, dwPathSize, "%ws%ws%ws%ws%ws%ws",
  1896. lpInfPath, szThisLang, Slash, lpDriverName, Slash, lpIniFile);
  1897. }
  1898. lpwThisIniFile = LoadPerfMultiByteToWideChar(CP_ACP, lpThisIniFile);
  1899. dwBufferSize = LoadPerfGetFileSize((LPWSTR) lpThisIniFile, & dwUnicode, FALSE);
  1900. if (dwBufferSize == 0) {
  1901. if (! (dwMode & LODCTR_UPNF_NOBACKUP)) {
  1902. ZeroMemory(lpThisIniFile, dwPathSize * sizeof(CHAR));
  1903. hr = StringCchPrintfA(lpThisIniFile, dwPathSize, "%ws%ws%ws%ws%ws%ws",
  1904. lpInfPath, DefaultLangId, Slash, lpDriverName, Slash, lpIniFile);
  1905. dwBufferSize = LoadPerfGetFileSize((LPWSTR) lpThisIniFile, & dwUnicode, FALSE);
  1906. }
  1907. }
  1908. if (dwBufferSize == 0xFFFFFFFF) {
  1909. dwBufferSize = 0;
  1910. }
  1911. if(dwBufferSize < SMALL_BUFFER_SIZE) dwBufferSize = SMALL_BUFFER_SIZE;
  1912. lpTextIdArray = MemoryAllocate(dwBufferSize * sizeof(CHAR));
  1913. lpTextSectionArray = MemoryAllocate(dwBufferSize * sizeof(WCHAR));
  1914. if (lpTextIdArray == NULL || lpTextSectionArray == NULL) {
  1915. TRACE((WINPERF_DBG_TRACE_INFO),
  1916. (& LoadPerfGuid,
  1917. __LINE__,
  1918. LOADPERF_LOADLANGUAGELISTS,
  1919. ARG_DEF(ARG_TYPE_WSTR, 1),
  1920. ERROR_OUTOFMEMORY,
  1921. TRACE_WSTR(lpIniFile),
  1922. TRACE_DWORD(dwFirstCounter),
  1923. TRACE_DWORD(dwFirstHelp),
  1924. NULL));
  1925. dwErrorCount = 1;
  1926. SetLastError(ERROR_OUTOFMEMORY);
  1927. goto Cleanup;
  1928. }
  1929. // get list of text keys to look up
  1930. dwSize = GetPrivateProfileStringA(szText, // [text] section of .INI file
  1931. NULL, // return all keys
  1932. szNotFound,
  1933. lpTextIdArray, // return buffer
  1934. dwBufferSize,
  1935. lpThisIniFile); // .INI file name
  1936. if ((lstrcmpiA(lpTextIdArray, szNotFound)) == 0) {
  1937. // key not found, default returned
  1938. TRACE((WINPERF_DBG_TRACE_INFO),
  1939. (& LoadPerfGuid,
  1940. __LINE__,
  1941. LOADPERF_LOADLANGUAGELISTS,
  1942. ARG_DEF(ARG_TYPE_WSTR, 1),
  1943. ERROR_NO_SUCH_GROUP,
  1944. TRACE_WSTR(lpIniFile),
  1945. TRACE_DWORD(dwFirstCounter),
  1946. TRACE_DWORD(dwFirstHelp),
  1947. NULL));
  1948. dwErrorCount ++;
  1949. SetLastError(ERROR_NO_SUCH_GROUP);
  1950. goto Cleanup;
  1951. }
  1952. // get the the [text] section from the ini file
  1953. if (dwUnicode == 0) {
  1954. dwSize = GetPrivateProfileSectionA(szText, // [text] section of .INI file
  1955. lpTextSectionArray, // return buffer
  1956. dwBufferSize * sizeof(WCHAR),
  1957. lpThisIniFile); // .INI file name
  1958. }
  1959. else {
  1960. dwSize = GetPrivateProfileSectionW(wszText, // [text] section of .INI file
  1961. (LPWSTR) lpTextSectionArray, // return buffer
  1962. dwBufferSize,
  1963. lpwThisIniFile); // .INI file name
  1964. }
  1965. // do each key returned
  1966. dwLastReadOffset = 0;
  1967. for (lpThisKey = lpTextIdArray;
  1968. lpThisKey != NULL && * lpThisKey != '\0';
  1969. lpThisKey += (lstrlenA(lpThisKey) + 1)) {
  1970. lpLocalKey = LoadPerfMultiByteToWideChar(CP_ACP, lpThisKey);
  1971. lpThisLocalKey = LoadPerfMultiByteToWideChar(CP_ACP, lpThisKey);
  1972. if (lpLocalKey == NULL || lpThisLocalKey == NULL) {
  1973. MemoryFree(lpLocalKey);
  1974. MemoryFree(lpThisLocalKey);
  1975. lpLocalKey = lpThisLocalKey = NULL;
  1976. continue;
  1977. }
  1978. // parse key to see if it's in the correct format
  1979. if (ParseTextId(lpLocalKey, pFirstSymbol, & dwOffset, & lpLang, & dwType)) {
  1980. // so get pointer to language entry structure
  1981. bAddEntry = FALSE;
  1982. wLangId = LoadPerfGetLCIDFromString(lpLang);
  1983. if (wLangId == wLangTable) {
  1984. bAddEntry = TRUE;
  1985. }
  1986. else if (PRIMARYLANGID(wLangTable) == wLangId) {
  1987. bAddEntry = TRUE;
  1988. }
  1989. else if (PRIMARYLANGID(wLangId) == wLangTable) {
  1990. bAddEntry = (GetUserDefaultUILanguage() == wLangId) ? TRUE : FALSE;
  1991. }
  1992. if (bAddEntry) {
  1993. if (! AddEntryToLanguage(pThisLang,
  1994. (dwUnicode == 0) ? ((LPWSTR) lpThisKey) : (lpThisLocalKey),
  1995. (LPWSTR) lpTextSectionArray,
  1996. dwUnicode,
  1997. & dwLastReadOffset,
  1998. dwTryCount,
  1999. dwType,
  2000. (dwOffset + ((dwType == TYPE_NAME)
  2001. ? dwFirstCounter
  2002. : dwFirstHelp)),
  2003. dwBufferSize)) {
  2004. OUTPUT_MESSAGE(bQuietMode,
  2005. GetFormatResource(LC_ERRADDTOLANG),
  2006. lpLocalKey,
  2007. lpLang,
  2008. GetLastError());
  2009. dwErrorCount ++;
  2010. }
  2011. else {
  2012. dwSuccessCount ++;
  2013. }
  2014. TRACE((WINPERF_DBG_TRACE_INFO),
  2015. (& LoadPerfGuid,
  2016. __LINE__,
  2017. LOADPERF_LOADLANGUAGELISTS,
  2018. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2019. ERROR_SUCCESS,
  2020. TRACE_WSTR(lpLocalKey),
  2021. TRACE_WSTR(lpLang),
  2022. TRACE_DWORD(dwOffset),
  2023. TRACE_DWORD(dwType),
  2024. NULL));
  2025. }
  2026. }
  2027. else { // unable to parse ID string
  2028. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_BAD_KEY), lpLocalKey);
  2029. TRACE((WINPERF_DBG_TRACE_ERROR),
  2030. (& LoadPerfGuid,
  2031. __LINE__,
  2032. LOADPERF_LOADLANGUAGELISTS,
  2033. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2034. ERROR_BADKEY,
  2035. TRACE_WSTR(lpLocalKey),
  2036. TRACE_WSTR(lpLang),
  2037. NULL));
  2038. }
  2039. MemoryFree(lpLocalKey);
  2040. MemoryFree(lpThisLocalKey);
  2041. lpLocalKey = lpThisLocalKey = NULL;
  2042. }
  2043. MemoryFree(lpTextIdArray);
  2044. MemoryFree(lpTextSectionArray);
  2045. lpTextIdArray = lpTextSectionArray = NULL;
  2046. }
  2047. Cleanup:
  2048. MemoryFree(lpwThisIniFile);
  2049. MemoryFree(lpThisIniFile);
  2050. MemoryFree(lpTextIdArray);
  2051. MemoryFree(lpLocalKey);
  2052. MemoryFree(lpThisLocalKey);
  2053. MemoryFree(lpTextSectionArray);
  2054. return (BOOL) (dwErrorCount == 0);
  2055. }
  2056. BOOL
  2057. SortLanguageTables(
  2058. PLANGUAGE_LIST_ELEMENT pFirstLang,
  2059. PDWORD pdwLastName,
  2060. PDWORD pdwLastHelp
  2061. )
  2062. /*++
  2063. SortLangageTables
  2064. walks list of languages loaded, allocates and loads a sorted multi_SZ
  2065. buffer containing new entries to be added to current names/help text
  2066. Arguments
  2067. pFirstLang
  2068. pointer to first element in list of languages
  2069. ReturnValue
  2070. TRUE everything done as expected
  2071. FALSE error occurred, status in GetLastError
  2072. --*/
  2073. {
  2074. PLANGUAGE_LIST_ELEMENT pThisLang;
  2075. BOOL bSorted;
  2076. LPWSTR pNameBufPos, pHelpBufPos;
  2077. PNAME_ENTRY pThisName, pPrevName;
  2078. DWORD dwHelpSize, dwNameSize, dwSize;
  2079. DWORD dwCurrentLastName;
  2080. DWORD dwCurrentLastHelp;
  2081. BOOL bReturn = FALSE;
  2082. DWORD dwStatus = ERROR_SUCCESS;
  2083. HRESULT hr;
  2084. if (pdwLastName == NULL || pdwLastHelp == NULL) {
  2085. TRACE((WINPERF_DBG_TRACE_INFO),
  2086. (& LoadPerfGuid,
  2087. __LINE__,
  2088. LOADPERF_SORTLANGUAGETABLES,
  2089. 0,
  2090. ERROR_BAD_ARGUMENTS,
  2091. NULL));
  2092. dwStatus = ERROR_BAD_ARGUMENTS;
  2093. goto Cleanup;
  2094. }
  2095. for (pThisLang = pFirstLang; pThisLang != NULL; pThisLang = pThisLang->pNextLang) {
  2096. // do each language in list
  2097. // sort elements in list by value (offset) so that lowest is first
  2098. if (pThisLang->pFirstName == NULL) {
  2099. // no elements in this list, continue the next one
  2100. continue;
  2101. }
  2102. bSorted = FALSE;
  2103. while (!bSorted) {
  2104. // point to start of list
  2105. pPrevName = pThisLang->pFirstName;
  2106. if (pPrevName) {
  2107. pThisName = pPrevName->pNext;
  2108. }
  2109. else {
  2110. break; // no elements in this list
  2111. }
  2112. if (!pThisName) {
  2113. break; // only one element in the list
  2114. }
  2115. bSorted = TRUE; // assume that it's sorted
  2116. // go until end of list
  2117. while (pThisName->pNext) {
  2118. if (pThisName->dwOffset > pThisName->pNext->dwOffset) {
  2119. // switch 'em
  2120. PNAME_ENTRY pA, pB;
  2121. pPrevName->pNext = pThisName->pNext;
  2122. pA = pThisName->pNext;
  2123. pB = pThisName->pNext->pNext;
  2124. pThisName->pNext = pB;
  2125. pA->pNext = pThisName;
  2126. pThisName = pA;
  2127. bSorted = FALSE;
  2128. }
  2129. //move to next entry
  2130. pPrevName = pThisName;
  2131. pThisName = pThisName->pNext;
  2132. }
  2133. // if bSorted = TRUE , then we walked all the way down
  2134. // the list without changing anything so that's the end.
  2135. }
  2136. // with the list sorted, build the MULTI_SZ strings for the
  2137. // help and name text strings
  2138. // compute buffer size
  2139. dwNameSize = dwHelpSize = 0;
  2140. dwCurrentLastName = 0;
  2141. dwCurrentLastHelp = 0;
  2142. for (pThisName = pThisLang->pFirstName; pThisName != NULL; pThisName = pThisName->pNext) {
  2143. // compute buffer requirements for this entry
  2144. dwSize = SIZE_OF_OFFSET_STRING;
  2145. dwSize += lstrlenW(pThisName->lpText);
  2146. dwSize += 1; // null
  2147. dwSize *= sizeof(WCHAR); // adjust for character size
  2148. // add to appropriate size register
  2149. if (pThisName->dwType == TYPE_NAME) {
  2150. dwNameSize += dwSize;
  2151. if (pThisName->dwOffset > dwCurrentLastName) {
  2152. dwCurrentLastName = pThisName->dwOffset;
  2153. }
  2154. }
  2155. else if (pThisName->dwType == TYPE_HELP) {
  2156. dwHelpSize += dwSize;
  2157. if (pThisName->dwOffset > dwCurrentLastHelp) {
  2158. dwCurrentLastHelp = pThisName->dwOffset;
  2159. }
  2160. }
  2161. }
  2162. // allocate buffers for the Multi_SZ strings
  2163. pThisLang->NameBuffer = MemoryAllocate(dwNameSize);
  2164. pThisLang->HelpBuffer = MemoryAllocate(dwHelpSize);
  2165. if (!pThisLang->NameBuffer || !pThisLang->HelpBuffer) {
  2166. TRACE((WINPERF_DBG_TRACE_INFO),
  2167. (& LoadPerfGuid,
  2168. __LINE__,
  2169. LOADPERF_SORTLANGUAGETABLES,
  2170. ARG_DEF(ARG_TYPE_WSTR, 1),
  2171. ERROR_OUTOFMEMORY,
  2172. TRACE_WSTR(pThisLang->LangId),
  2173. TRACE_DWORD(pThisLang->dwNumElements),
  2174. TRACE_DWORD(dwCurrentLastName),
  2175. TRACE_DWORD(dwCurrentLastHelp),
  2176. NULL));
  2177. dwStatus = ERROR_OUTOFMEMORY;
  2178. goto Cleanup;
  2179. }
  2180. // fill in buffers with sorted strings
  2181. pNameBufPos = (LPWSTR) pThisLang->NameBuffer;
  2182. pHelpBufPos = (LPWSTR) pThisLang->HelpBuffer;
  2183. for (pThisName = pThisLang->pFirstName; pThisName != NULL; pThisName = pThisName->pNext) {
  2184. if (pThisName->dwType == TYPE_NAME) {
  2185. // load number as first 0-term. string
  2186. hr = StringCchPrintfW(pNameBufPos, dwNameSize, szDFormat, pThisName->dwOffset);
  2187. dwSize = lstrlenW(pNameBufPos) + 1;
  2188. dwNameSize -= dwSize;
  2189. pNameBufPos += dwSize; // save NULL term.
  2190. // load the text to match
  2191. hr = StringCchCopyW(pNameBufPos, dwNameSize, pThisName->lpText);
  2192. dwSize = lstrlenW(pNameBufPos) + 1;
  2193. dwNameSize -= dwSize;
  2194. pNameBufPos += dwSize;
  2195. }
  2196. else if (pThisName->dwType == TYPE_HELP) {
  2197. // load number as first 0-term. string
  2198. hr = StringCchPrintfW(pHelpBufPos, dwHelpSize, szDFormat, pThisName->dwOffset);
  2199. dwSize = lstrlenW(pHelpBufPos) + 1;
  2200. dwHelpSize -= dwSize;
  2201. pHelpBufPos += dwSize; // save NULL term.
  2202. // load the text to match
  2203. hr = StringCchCopyW(pHelpBufPos, dwHelpSize, pThisName->lpText);
  2204. dwSize = lstrlenW(pHelpBufPos) + 1;
  2205. dwHelpSize -= dwSize;
  2206. pHelpBufPos += dwSize;
  2207. }
  2208. }
  2209. // add additional NULL at end of string to terminate MULTI_SZ
  2210. * pHelpBufPos = L'\0';
  2211. * pNameBufPos = L'\0';
  2212. // compute size of MULTI_SZ strings
  2213. pThisLang->dwNameBuffSize = (DWORD) ((PBYTE) pNameBufPos - (PBYTE) pThisLang->NameBuffer) + sizeof(WCHAR);
  2214. pThisLang->dwHelpBuffSize = (DWORD) ((PBYTE) pHelpBufPos - (PBYTE) pThisLang->HelpBuffer) + sizeof(WCHAR);
  2215. if (* pdwLastName < dwCurrentLastName) {
  2216. * pdwLastName = dwCurrentLastName;
  2217. }
  2218. if (* pdwLastHelp < dwCurrentLastHelp) {
  2219. * pdwLastHelp = dwCurrentLastHelp;
  2220. }
  2221. TRACE((WINPERF_DBG_TRACE_INFO),
  2222. (& LoadPerfGuid,
  2223. __LINE__,
  2224. LOADPERF_SORTLANGUAGETABLES,
  2225. ARG_DEF(ARG_TYPE_WSTR, 1),
  2226. ERROR_SUCCESS,
  2227. TRACE_WSTR(pThisLang->LangId),
  2228. TRACE_DWORD(pThisLang->dwNumElements),
  2229. TRACE_DWORD(dwCurrentLastName),
  2230. TRACE_DWORD(dwCurrentLastHelp),
  2231. NULL));
  2232. }
  2233. dwCurrentLastName = * pdwLastName;
  2234. dwCurrentLastHelp = * pdwLastHelp;
  2235. TRACE((WINPERF_DBG_TRACE_INFO),
  2236. (& LoadPerfGuid,
  2237. __LINE__,
  2238. LOADPERF_SORTLANGUAGETABLES,
  2239. 0,
  2240. ERROR_SUCCESS,
  2241. TRACE_DWORD(dwCurrentLastName),
  2242. TRACE_DWORD(dwCurrentLastHelp),
  2243. NULL));
  2244. if (dwCurrentLastHelp != dwCurrentLastName + 1) {
  2245. TRACE((WINPERF_DBG_TRACE_WARNING),
  2246. (& LoadPerfGuid,
  2247. __LINE__,
  2248. LOADPERF_SORTLANGUAGETABLES,
  2249. 0,
  2250. ERROR_SUCCESS,
  2251. TRACE_DWORD(dwCurrentLastName),
  2252. TRACE_DWORD(dwCurrentLastHelp),
  2253. NULL));
  2254. dwCurrentLastHelp = dwCurrentLastName + 1;
  2255. * pdwLastHelp = dwCurrentLastHelp;
  2256. }
  2257. bReturn = TRUE;
  2258. Cleanup:
  2259. if (! bReturn) {
  2260. SetLastError(dwStatus);
  2261. }
  2262. return bReturn;
  2263. }
  2264. BOOL
  2265. GetInstalledLanguageList(
  2266. HKEY hPerflibRoot,
  2267. LPWSTR * mszLangList
  2268. )
  2269. /*++
  2270. returns a list of language sub keys found under the perflib key
  2271. GetInstalledLanguageList() build mszLandList MULTI_SZ string from performance registry setting.
  2272. Caller UpdateRegistry() should free the memory.
  2273. --*/
  2274. {
  2275. BOOL bReturn = TRUE;
  2276. LONG lStatus;
  2277. DWORD dwIndex = 0;
  2278. LPWSTR szBuffer;
  2279. DWORD dwBufSize = MAX_PATH;
  2280. LPWSTR szRetBuffer = NULL;
  2281. LPWSTR szTmpBuffer;
  2282. DWORD dwAllocSize = MAX_PATH;
  2283. DWORD dwRetBufSize = 0;
  2284. DWORD dwLastBufSize = 0;
  2285. LPWSTR szNextString;
  2286. HRESULT hr;
  2287. dwBufSize = MAX_PATH;
  2288. szBuffer = MemoryAllocate(dwBufSize * sizeof(WCHAR));
  2289. dwAllocSize = MAX_PATH;
  2290. szRetBuffer = MemoryAllocate(dwAllocSize * sizeof(WCHAR));
  2291. if (szBuffer == NULL || szRetBuffer == NULL) {
  2292. SetLastError(ERROR_OUTOFMEMORY);
  2293. bReturn = FALSE;
  2294. }
  2295. if (bReturn) {
  2296. while ((lStatus = RegEnumKeyExW(hPerflibRoot, dwIndex, szBuffer, & dwBufSize, NULL, NULL, NULL, NULL))
  2297. == ERROR_SUCCESS) {
  2298. TRACE((WINPERF_DBG_TRACE_INFO),
  2299. (& LoadPerfGuid,
  2300. __LINE__,
  2301. LOADPERF_GETINSTALLEDLANGUAGELIST,
  2302. ARG_DEF(ARG_TYPE_WSTR, 1),
  2303. ERROR_SUCCESS,
  2304. TRACE_WSTR(szBuffer),
  2305. TRACE_DWORD(dwIndex),
  2306. TRACE_DWORD(dwLastBufSize),
  2307. TRACE_DWORD(dwRetBufSize),
  2308. NULL));
  2309. dwRetBufSize += (lstrlenW(szBuffer) + 1);
  2310. if (dwRetBufSize >= dwAllocSize) {
  2311. szTmpBuffer = szRetBuffer;
  2312. dwAllocSize = dwRetBufSize + MAX_PATH;
  2313. szRetBuffer = MemoryResize(szTmpBuffer, dwAllocSize * sizeof(WCHAR));
  2314. }
  2315. if (szRetBuffer == NULL) {
  2316. MemoryFree(szTmpBuffer);
  2317. bReturn = FALSE;
  2318. TRACE((WINPERF_DBG_TRACE_INFO),
  2319. (& LoadPerfGuid,
  2320. __LINE__,
  2321. LOADPERF_GETINSTALLEDLANGUAGELIST,
  2322. ARG_DEF(ARG_TYPE_WSTR, 1),
  2323. ERROR_OUTOFMEMORY,
  2324. TRACE_WSTR(szBuffer),
  2325. TRACE_DWORD(dwIndex),
  2326. TRACE_DWORD(dwLastBufSize),
  2327. TRACE_DWORD(dwRetBufSize),
  2328. NULL));
  2329. SetLastError(ERROR_OUTOFMEMORY);
  2330. break;
  2331. }
  2332. szNextString = (LPWSTR) (szRetBuffer + dwLastBufSize);
  2333. hr = StringCchCopyW(szNextString, dwAllocSize - dwLastBufSize, szBuffer);
  2334. dwLastBufSize = dwRetBufSize;
  2335. dwIndex ++;
  2336. dwBufSize = MAX_PATH;
  2337. RtlZeroMemory(szBuffer, dwBufSize * sizeof(WCHAR));
  2338. }
  2339. }
  2340. if (bReturn) {
  2341. WCHAR szLangId[8];
  2342. DWORD dwSubLangId = GetUserDefaultUILanguage();
  2343. DWORD dwLangId = PRIMARYLANGID(dwSubLangId);
  2344. BOOL bFound = FALSE;
  2345. bFound = FALSE;
  2346. for (szNextString = szRetBuffer; * szNextString != L'\0'; szNextString += (lstrlenW(szNextString) + 1)) {
  2347. if (lstrcmpiW(szNextString, DefaultLangId) == 0) {
  2348. bFound = TRUE;
  2349. break;
  2350. }
  2351. }
  2352. if (! bFound) {
  2353. TRACE((WINPERF_DBG_TRACE_INFO),
  2354. (& LoadPerfGuid,
  2355. __LINE__,
  2356. LOADPERF_GETINSTALLEDLANGUAGELIST,
  2357. ARG_DEF(ARG_TYPE_WSTR, 1),
  2358. ERROR_SUCCESS,
  2359. TRACE_WSTR(DefaultLangId),
  2360. TRACE_DWORD(dwIndex),
  2361. TRACE_DWORD(dwLastBufSize),
  2362. TRACE_DWORD(dwRetBufSize),
  2363. NULL));
  2364. dwRetBufSize += (lstrlenW(DefaultLangId) + 1);
  2365. if (dwRetBufSize >= dwAllocSize) {
  2366. szTmpBuffer = szRetBuffer;
  2367. dwAllocSize = dwRetBufSize + MAX_PATH;
  2368. szRetBuffer = MemoryResize(szTmpBuffer, dwAllocSize * sizeof(WCHAR));
  2369. }
  2370. if (szRetBuffer == NULL) {
  2371. MemoryFree(szTmpBuffer);
  2372. bReturn = FALSE;
  2373. TRACE((WINPERF_DBG_TRACE_INFO),
  2374. (& LoadPerfGuid,
  2375. __LINE__,
  2376. LOADPERF_GETINSTALLEDLANGUAGELIST,
  2377. ARG_DEF(ARG_TYPE_WSTR, 1),
  2378. ERROR_OUTOFMEMORY,
  2379. TRACE_WSTR(DefaultLangId),
  2380. TRACE_DWORD(dwIndex),
  2381. TRACE_DWORD(dwLastBufSize),
  2382. TRACE_DWORD(dwRetBufSize),
  2383. NULL));
  2384. SetLastError(ERROR_OUTOFMEMORY);
  2385. }
  2386. else {
  2387. szNextString = (LPWSTR) (szRetBuffer + dwLastBufSize);
  2388. hr = StringCchCopyW(szNextString, dwAllocSize - dwLastBufSize, DefaultLangId);
  2389. dwLastBufSize = dwRetBufSize;
  2390. dwIndex ++;
  2391. }
  2392. }
  2393. if (dwLangId != 0x009) {
  2394. WCHAR nDigit;
  2395. DWORD dwThisLang;
  2396. ZeroMemory(szLangId, 8 * sizeof(WCHAR));
  2397. nDigit = (WCHAR) (dwLangId >> 8);
  2398. szLangId[0] = tohexdigit(nDigit);
  2399. nDigit = (WCHAR) (dwLangId & 0XF0) >> 4;
  2400. szLangId[1] = tohexdigit(nDigit);
  2401. nDigit = (WCHAR) (dwLangId & 0xF);
  2402. szLangId[2] = tohexdigit(nDigit);
  2403. bFound = FALSE;
  2404. for (szNextString = szRetBuffer; * szNextString != L'\0'; szNextString += (lstrlenW(szNextString) + 1)) {
  2405. dwThisLang = LoadPerfGetLCIDFromString(szNextString);
  2406. if (dwThisLang == dwSubLangId || PRIMARYLANGID(dwThisLang) == dwLangId) {
  2407. bFound = TRUE;
  2408. break;
  2409. }
  2410. }
  2411. if (! bFound) {
  2412. TRACE((WINPERF_DBG_TRACE_INFO),
  2413. (& LoadPerfGuid,
  2414. __LINE__,
  2415. LOADPERF_GETINSTALLEDLANGUAGELIST,
  2416. ARG_DEF(ARG_TYPE_WSTR, 1),
  2417. ERROR_SUCCESS,
  2418. TRACE_WSTR(szLangId),
  2419. TRACE_DWORD(dwIndex),
  2420. TRACE_DWORD(dwLastBufSize),
  2421. TRACE_DWORD(dwRetBufSize),
  2422. NULL));
  2423. dwRetBufSize += (lstrlenW(szLangId) + 1);
  2424. if (dwRetBufSize >= dwAllocSize) {
  2425. szTmpBuffer = szRetBuffer;
  2426. dwAllocSize = dwRetBufSize + MAX_PATH;
  2427. szRetBuffer = MemoryResize(szTmpBuffer, dwAllocSize * sizeof(WCHAR));
  2428. }
  2429. if (szRetBuffer == NULL) {
  2430. MemoryFree(szTmpBuffer);
  2431. bReturn = FALSE;
  2432. TRACE((WINPERF_DBG_TRACE_INFO),
  2433. (& LoadPerfGuid,
  2434. __LINE__,
  2435. LOADPERF_GETINSTALLEDLANGUAGELIST,
  2436. ARG_DEF(ARG_TYPE_WSTR, 1),
  2437. ERROR_OUTOFMEMORY,
  2438. TRACE_WSTR(szLangId),
  2439. TRACE_DWORD(dwIndex),
  2440. TRACE_DWORD(dwLastBufSize),
  2441. TRACE_DWORD(dwRetBufSize),
  2442. NULL));
  2443. SetLastError(ERROR_OUTOFMEMORY);
  2444. }
  2445. else {
  2446. szNextString = (LPWSTR) (szRetBuffer + dwLastBufSize);
  2447. hr = StringCchCopyW(szNextString, dwAllocSize - dwLastBufSize, szLangId);
  2448. dwLastBufSize = dwRetBufSize;
  2449. dwIndex ++;
  2450. }
  2451. }
  2452. }
  2453. }
  2454. if (bReturn) {
  2455. // add terminating null char
  2456. dwRetBufSize ++;
  2457. if (dwRetBufSize > dwAllocSize) {
  2458. szTmpBuffer = szRetBuffer;
  2459. dwAllocSize = dwRetBufSize;
  2460. szRetBuffer = MemoryResize(szTmpBuffer, dwRetBufSize * sizeof(WCHAR));
  2461. if (szRetBuffer == NULL) {
  2462. MemoryFree(szTmpBuffer);
  2463. SetLastError(ERROR_OUTOFMEMORY);
  2464. bReturn = FALSE;
  2465. }
  2466. }
  2467. if (szRetBuffer != NULL) {
  2468. szNextString = (LPWSTR) (szRetBuffer + dwLastBufSize);
  2469. * szNextString = L'\0';
  2470. }
  2471. }
  2472. if (bReturn) {
  2473. * mszLangList = szRetBuffer;
  2474. }
  2475. else {
  2476. * mszLangList = NULL;
  2477. MemoryFree(szRetBuffer);
  2478. }
  2479. MemoryFree(szBuffer);
  2480. return bReturn;
  2481. }
  2482. BOOL
  2483. CheckNameTable(
  2484. LPWSTR lpNameStr,
  2485. LPWSTR lpHelpStr,
  2486. LPDWORD pdwLastCounter,
  2487. LPDWORD pdwLastHelp,
  2488. BOOL bUpdate
  2489. )
  2490. {
  2491. BOOL bResult = TRUE;
  2492. BOOL bChanged = FALSE;
  2493. LPWSTR lpThisId;
  2494. DWORD dwThisId;
  2495. DWORD dwLastCounter = * pdwLastCounter;
  2496. DWORD dwLastHelp = * pdwLastHelp;
  2497. DWORD dwLastId = (dwLastCounter > dwLastHelp)
  2498. ? (dwLastCounter) : (dwLastHelp);
  2499. TRACE((WINPERF_DBG_TRACE_INFO),
  2500. (& LoadPerfGuid,
  2501. __LINE__,
  2502. LOADPERF_CHECKNAMETABLE,
  2503. 0,
  2504. ERROR_SUCCESS,
  2505. TRACE_DWORD(dwLastCounter),
  2506. TRACE_DWORD(dwLastHelp),
  2507. NULL));
  2508. for (lpThisId = lpNameStr; * lpThisId != L'\0'; lpThisId += (lstrlenW(lpThisId) + 1)) {
  2509. dwThisId = wcstoul(lpThisId, NULL, 10);
  2510. if ((dwThisId == 0) || (dwThisId != 1 && dwThisId % 2 != 0)) {
  2511. ReportLoadPerfEvent(
  2512. EVENTLOG_ERROR_TYPE, // error type
  2513. (DWORD) LDPRFMSG_REGISTRY_COUNTER_STRINGS_CORRUPT,
  2514. 4, dwThisId, dwLastCounter, dwLastId, __LINE__,
  2515. 1, lpThisId, NULL, NULL);
  2516. TRACE((WINPERF_DBG_TRACE_ERROR),
  2517. (& LoadPerfGuid,
  2518. __LINE__,
  2519. LOADPERF_CHECKNAMETABLE,
  2520. ARG_DEF(ARG_TYPE_WSTR, 1),
  2521. ERROR_BADKEY,
  2522. TRACE_WSTR(lpThisId),
  2523. TRACE_DWORD(dwThisId),
  2524. TRACE_DWORD(dwLastCounter),
  2525. TRACE_DWORD(dwLastHelp),
  2526. NULL));
  2527. SetLastError(ERROR_BADKEY);
  2528. bResult = FALSE;
  2529. break;
  2530. }
  2531. else if (dwThisId > dwLastId || dwThisId > dwLastCounter) {
  2532. if (bUpdate) {
  2533. ReportLoadPerfEvent(
  2534. EVENTLOG_ERROR_TYPE, // error type
  2535. (DWORD) LDPRFMSG_REGISTRY_COUNTER_STRINGS_CORRUPT,
  2536. 4, dwThisId, dwLastCounter, dwLastId, __LINE__,
  2537. 1, lpThisId, NULL, NULL);
  2538. TRACE((WINPERF_DBG_TRACE_ERROR),
  2539. (& LoadPerfGuid,
  2540. __LINE__,
  2541. LOADPERF_CHECKNAMETABLE,
  2542. ARG_DEF(ARG_TYPE_WSTR, 1),
  2543. ERROR_BADKEY,
  2544. TRACE_WSTR(lpThisId),
  2545. TRACE_DWORD(dwThisId),
  2546. TRACE_DWORD(dwLastCounter),
  2547. TRACE_DWORD(dwLastHelp),
  2548. NULL));
  2549. SetLastError(ERROR_BADKEY);
  2550. bResult = FALSE;
  2551. break;
  2552. }
  2553. else {
  2554. bChanged = TRUE;
  2555. if (dwThisId > dwLastCounter) dwLastCounter = dwThisId;
  2556. if (dwLastCounter > dwLastId) dwLastId = dwLastCounter;
  2557. }
  2558. }
  2559. lpThisId += (lstrlenW(lpThisId) + 1);
  2560. }
  2561. if (! bResult) goto Cleanup;
  2562. for (lpThisId = lpHelpStr; * lpThisId != L'\0'; lpThisId += (lstrlenW(lpThisId) + 1)) {
  2563. dwThisId = wcstoul(lpThisId, NULL, 10);
  2564. if ((dwThisId == 0) || (dwThisId != 1 && dwThisId % 2 == 0)) {
  2565. ReportLoadPerfEvent(
  2566. EVENTLOG_ERROR_TYPE, // error type
  2567. (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT,
  2568. 4, dwThisId, dwLastHelp, dwLastId, __LINE__,
  2569. 1, lpThisId, NULL, NULL);
  2570. TRACE((WINPERF_DBG_TRACE_ERROR),
  2571. (& LoadPerfGuid,
  2572. __LINE__,
  2573. LOADPERF_CHECKNAMETABLE,
  2574. ARG_DEF(ARG_TYPE_WSTR, 1),
  2575. ERROR_BADKEY,
  2576. TRACE_WSTR(lpThisId),
  2577. TRACE_DWORD(dwThisId),
  2578. TRACE_DWORD(dwLastCounter),
  2579. TRACE_DWORD(dwLastHelp),
  2580. NULL));
  2581. SetLastError(ERROR_BADKEY);
  2582. bResult = FALSE;
  2583. break;
  2584. }
  2585. else if (dwThisId > dwLastId || dwThisId > dwLastHelp) {
  2586. if (bUpdate) {
  2587. ReportLoadPerfEvent(
  2588. EVENTLOG_ERROR_TYPE, // error type
  2589. (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT,
  2590. 4, dwThisId, dwLastHelp, dwLastId, __LINE__,
  2591. 1, lpThisId, NULL, NULL);
  2592. TRACE((WINPERF_DBG_TRACE_ERROR),
  2593. (& LoadPerfGuid,
  2594. __LINE__,
  2595. LOADPERF_CHECKNAMETABLE,
  2596. ARG_DEF(ARG_TYPE_WSTR, 1),
  2597. ERROR_BADKEY,
  2598. TRACE_WSTR(lpThisId),
  2599. TRACE_DWORD(dwThisId),
  2600. TRACE_DWORD(dwLastCounter),
  2601. TRACE_DWORD(dwLastHelp),
  2602. NULL));
  2603. SetLastError(ERROR_BADKEY);
  2604. bResult = FALSE;
  2605. break;
  2606. }
  2607. else {
  2608. bChanged = TRUE;
  2609. if (dwThisId > dwLastHelp) dwLastHelp = dwThisId;
  2610. if (dwLastHelp > dwLastId) dwLastId = dwLastHelp;
  2611. }
  2612. }
  2613. lpThisId += (lstrlenW(lpThisId) + 1);
  2614. }
  2615. Cleanup:
  2616. if (bResult) {
  2617. if (bChanged) {
  2618. ReportLoadPerfEvent(
  2619. EVENTLOG_WARNING_TYPE,
  2620. (DWORD) LDPRFMSG_CORRUPT_PERFLIB_INDEX,
  2621. 4, * pdwLastCounter, * pdwLastHelp, dwLastCounter, dwLastHelp,
  2622. 0, NULL, NULL, NULL);
  2623. * pdwLastCounter = dwLastCounter;
  2624. * pdwLastHelp = dwLastHelp;
  2625. }
  2626. }
  2627. TRACE((WINPERF_DBG_TRACE_INFO),
  2628. (& LoadPerfGuid,
  2629. __LINE__,
  2630. LOADPERF_CHECKNAMETABLE,
  2631. 0,
  2632. GetLastError(),
  2633. TRACE_DWORD(dwLastCounter),
  2634. TRACE_DWORD(dwLastHelp),
  2635. NULL));
  2636. return bResult;
  2637. }
  2638. BOOL
  2639. UpdateEachLanguage(
  2640. BOOL bQuietMode,
  2641. HKEY hPerflibRoot,
  2642. LPWSTR mszInstalledLangList,
  2643. LPDWORD pdwLastCounter,
  2644. LPDWORD pdwLastHelp,
  2645. PLANGUAGE_LIST_ELEMENT pFirstLang,
  2646. DWORD dwMode,
  2647. BOOL bUpdate
  2648. )
  2649. /*++
  2650. UpdateEachLanguage
  2651. Goes through list of languages and adds the sorted MULTI_SZ strings
  2652. to the existing counter and explain text in the registry.
  2653. Also updates the "Last Counter and Last Help" values
  2654. Arguments
  2655. hPerflibRoot handle to Perflib key in the registry
  2656. mszInstalledLangList
  2657. MSZ string of installed language keys
  2658. pFirstLanguage pointer to first language entry
  2659. Return Value
  2660. TRUE all went as planned
  2661. FALSE an error occured, use GetLastError to find out what it was.
  2662. --*/
  2663. {
  2664. PLANGUAGE_LIST_ELEMENT pThisLang;
  2665. LPWSTR pHelpBuffer = NULL;
  2666. LPWSTR pNameBuffer = NULL;
  2667. LPWSTR pNewName = NULL;
  2668. LPWSTR pNewHelp = NULL;
  2669. DWORD dwLastCounter = * pdwLastCounter;
  2670. DWORD dwLastHelp = * pdwLastHelp;
  2671. DWORD dwBufferSize;
  2672. DWORD dwValueType;
  2673. DWORD dwCounterSize;
  2674. DWORD dwHelpSize;
  2675. HKEY hKeyThisLang = NULL;
  2676. LONG lStatus;
  2677. LPWSTR CounterNameBuffer = NULL;
  2678. LPWSTR HelpNameBuffer = NULL;
  2679. LPWSTR AddCounterNameBuffer = NULL;
  2680. LPWSTR AddHelpNameBuffer = NULL;
  2681. LPWSTR szThisLang;
  2682. BOOL bResult = TRUE;
  2683. HRESULT hr;
  2684. if (bUpdate && ((dwMode & LODCTR_UPNF_REPAIR) == 0)) {
  2685. // this isn't possible on 3.1
  2686. MakeBackupCopyOfLanguageFiles(NULL);
  2687. }
  2688. CounterNameBuffer = MemoryAllocate(4 * MAX_PATH * sizeof(WCHAR));
  2689. if (CounterNameBuffer == NULL) {
  2690. lStatus = ERROR_OUTOFMEMORY;
  2691. goto Cleanup;
  2692. }
  2693. HelpNameBuffer = CounterNameBuffer + MAX_PATH;
  2694. AddCounterNameBuffer = HelpNameBuffer + MAX_PATH;
  2695. AddHelpNameBuffer = AddCounterNameBuffer + MAX_PATH;
  2696. for (szThisLang = mszInstalledLangList; *szThisLang != L'\0'; szThisLang += (lstrlenW(szThisLang) + 1)) {
  2697. TRACE((WINPERF_DBG_TRACE_INFO),
  2698. (& LoadPerfGuid,
  2699. __LINE__,
  2700. LOADPERF_UPDATEEACHLANGUAGE,
  2701. ARG_DEF(ARG_TYPE_WSTR, 1),
  2702. ERROR_SUCCESS,
  2703. TRACE_WSTR(szThisLang),
  2704. NULL));
  2705. hr = StringCchPrintfW(CounterNameBuffer, MAX_PATH, L"%ws%ws", CounterNameStr, szThisLang);
  2706. hr = StringCchPrintfW(HelpNameBuffer, MAX_PATH, L"%ws%ws", HelpNameStr, szThisLang);
  2707. hr = StringCchPrintfW(AddCounterNameBuffer, MAX_PATH, L"%ws%ws", AddCounterNameStr, szThisLang);
  2708. hr = StringCchPrintfW(AddHelpNameBuffer, MAX_PATH, L"%ws%ws", AddHelpNameStr, szThisLang);
  2709. // make sure this language is loaded
  2710. __try {
  2711. lStatus = RegOpenKeyExW(hPerflibRoot, szThisLang, RESERVED, KEY_READ, & hKeyThisLang);
  2712. }
  2713. __except (EXCEPTION_EXECUTE_HANDLER) {
  2714. lStatus = GetExceptionCode();
  2715. TRACE((WINPERF_DBG_TRACE_ERROR),
  2716. (& LoadPerfGuid,
  2717. __LINE__,
  2718. LOADPERF_UPDATEEACHLANGUAGE,
  2719. ARG_DEF(ARG_TYPE_WSTR, 1),
  2720. lStatus,
  2721. TRACE_WSTR(szThisLang),
  2722. NULL));
  2723. }
  2724. // we just need the open status, not the key handle so
  2725. // close this handle and set the one we need.
  2726. if (lStatus == ERROR_SUCCESS) {
  2727. RegCloseKey(hKeyThisLang);
  2728. }
  2729. else if (lStatus == ERROR_FILE_NOT_FOUND) {
  2730. // Somehow language subkey is not there under
  2731. // "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PERFLIB".
  2732. // This should be a rare case, but seems like a common scenario during upgrade
  2733. // from NT4 to XP and .NET server.
  2734. // We should still treat this as success and try update it.
  2735. //
  2736. lStatus = ERROR_SUCCESS;
  2737. }
  2738. hKeyThisLang = HKEY_PERFORMANCE_DATA;
  2739. if (bUpdate) {
  2740. // look up the new strings to add
  2741. pThisLang = FindLanguage(pFirstLang, szThisLang);
  2742. if (pThisLang == NULL) {
  2743. // try default language if available
  2744. pThisLang = FindLanguage(pFirstLang, DefaultLangTag);
  2745. }
  2746. else if (pThisLang->NameBuffer == NULL || pThisLang->HelpBuffer == NULL) {
  2747. TRACE((WINPERF_DBG_TRACE_WARNING),
  2748. (& LoadPerfGuid,
  2749. __LINE__,
  2750. LOADPERF_UPDATEEACHLANGUAGE,
  2751. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2752. LDPRFMSG_CORRUPT_INCLUDE_FILE,
  2753. TRACE_WSTR(pThisLang->LangId),
  2754. TRACE_WSTR(szThisLang),
  2755. NULL));
  2756. pThisLang = FindLanguage(pFirstLang, DefaultLangTag);
  2757. }
  2758. if (pThisLang == NULL) {
  2759. // try english language if available
  2760. pThisLang = FindLanguage(pFirstLang, DefaultLangId);
  2761. }
  2762. else if (pThisLang->NameBuffer == NULL || pThisLang->HelpBuffer == NULL) {
  2763. TRACE((WINPERF_DBG_TRACE_WARNING),
  2764. (& LoadPerfGuid,
  2765. __LINE__,
  2766. LOADPERF_UPDATEEACHLANGUAGE,
  2767. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2768. LDPRFMSG_CORRUPT_INCLUDE_FILE,
  2769. TRACE_WSTR(pThisLang->LangId),
  2770. TRACE_WSTR(szThisLang),
  2771. NULL));
  2772. pThisLang = FindLanguage(pFirstLang, DefaultLangId);
  2773. }
  2774. if (pThisLang == NULL) {
  2775. // unable to add this language so continue
  2776. lStatus = ERROR_NO_MATCH;
  2777. TRACE((WINPERF_DBG_TRACE_ERROR),
  2778. (& LoadPerfGuid,
  2779. __LINE__,
  2780. LOADPERF_UPDATEEACHLANGUAGE,
  2781. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_WSTR, 3),
  2782. lStatus,
  2783. TRACE_WSTR(szThisLang),
  2784. TRACE_WSTR(DefaultLangTag),
  2785. TRACE_WSTR(DefaultLangId),
  2786. TRACE_DWORD(dwLastCounter),
  2787. TRACE_DWORD(dwLastHelp),
  2788. NULL));
  2789. }
  2790. else {
  2791. if (pThisLang->NameBuffer == NULL || pThisLang->HelpBuffer == NULL) {
  2792. ReportLoadPerfEvent(
  2793. EVENTLOG_WARNING_TYPE, // error type
  2794. (DWORD) LDPRFMSG_CORRUPT_INCLUDE_FILE, // event,
  2795. 1, __LINE__, 0, 0, 0,
  2796. 1, pThisLang->LangId, NULL, NULL);
  2797. TRACE((WINPERF_DBG_TRACE_WARNING),
  2798. (& LoadPerfGuid,
  2799. __LINE__,
  2800. LOADPERF_UPDATEEACHLANGUAGE,
  2801. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2802. LDPRFMSG_CORRUPT_INCLUDE_FILE,
  2803. TRACE_WSTR(pThisLang->LangId),
  2804. TRACE_WSTR(szThisLang),
  2805. NULL));
  2806. lStatus = LDPRFMSG_CORRUPT_INCLUDE_FILE;
  2807. }
  2808. TRACE((WINPERF_DBG_TRACE_INFO),
  2809. (& LoadPerfGuid,
  2810. __LINE__,
  2811. LOADPERF_UPDATEEACHLANGUAGE,
  2812. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2813. lStatus,
  2814. TRACE_WSTR(pThisLang->LangId),
  2815. TRACE_WSTR(szThisLang),
  2816. TRACE_DWORD(dwLastCounter),
  2817. TRACE_DWORD(dwLastHelp),
  2818. NULL));
  2819. }
  2820. }
  2821. if (lStatus == ERROR_SUCCESS) {
  2822. // get size of counter names
  2823. dwBufferSize = 0;
  2824. __try {
  2825. lStatus = RegQueryValueExW(hKeyThisLang,
  2826. CounterNameBuffer,
  2827. RESERVED,
  2828. & dwValueType,
  2829. NULL,
  2830. & dwBufferSize);
  2831. }
  2832. __except (EXCEPTION_EXECUTE_HANDLER) {
  2833. lStatus = GetExceptionCode();
  2834. }
  2835. if (lStatus != ERROR_SUCCESS) {
  2836. // this means the language is not installed in the system.
  2837. continue;
  2838. }
  2839. dwCounterSize = dwBufferSize;
  2840. // get size of help text
  2841. dwBufferSize = 0;
  2842. __try {
  2843. lStatus = RegQueryValueExW(hKeyThisLang,
  2844. HelpNameBuffer,
  2845. RESERVED,
  2846. & dwValueType,
  2847. NULL,
  2848. & dwBufferSize);
  2849. }
  2850. __except (EXCEPTION_EXECUTE_HANDLER) {
  2851. lStatus = GetExceptionCode();
  2852. }
  2853. if (lStatus != ERROR_SUCCESS) {
  2854. // this means the language is not installed in the system.
  2855. continue;
  2856. }
  2857. dwHelpSize = dwBufferSize;
  2858. // allocate new buffers
  2859. if (bUpdate) {
  2860. dwCounterSize += pThisLang->dwNameBuffSize;
  2861. dwHelpSize += pThisLang->dwHelpBuffSize;
  2862. }
  2863. pNameBuffer = MemoryAllocate(dwCounterSize);
  2864. pHelpBuffer = MemoryAllocate(dwHelpSize);
  2865. if (pNameBuffer == NULL || pHelpBuffer== NULL) {
  2866. lStatus = ERROR_OUTOFMEMORY;
  2867. TRACE((WINPERF_DBG_TRACE_ERROR),
  2868. (& LoadPerfGuid,
  2869. __LINE__,
  2870. LOADPERF_UPDATEEACHLANGUAGE,
  2871. 0,
  2872. ERROR_OUTOFMEMORY,
  2873. NULL));
  2874. bResult = FALSE;
  2875. goto Cleanup;
  2876. }
  2877. // load current buffers into memory
  2878. // read counter names into buffer. Counter names will be stored as
  2879. // a MULTI_SZ string in the format of "###" "Name"
  2880. dwBufferSize = dwCounterSize;
  2881. __try {
  2882. lStatus = RegQueryValueExW(hKeyThisLang,
  2883. CounterNameBuffer,
  2884. RESERVED,
  2885. & dwValueType,
  2886. (LPVOID) pNameBuffer,
  2887. & dwBufferSize);
  2888. }
  2889. __except (EXCEPTION_EXECUTE_HANDLER) {
  2890. lStatus = GetExceptionCode();
  2891. }
  2892. if (lStatus != ERROR_SUCCESS) {
  2893. // this means the language is not installed in the system.
  2894. continue;
  2895. }
  2896. if (bUpdate) {
  2897. // set pointer to location in buffer where new string should be
  2898. // appended: end of buffer - 1 (second null at end of MULTI_SZ
  2899. pNewName = (LPWSTR) ((PBYTE) pNameBuffer + dwBufferSize - sizeof(WCHAR));
  2900. // adjust buffer length to take into account 2nd null from 1st
  2901. // buffer that has been overwritten
  2902. dwCounterSize -= sizeof(WCHAR);
  2903. }
  2904. // read explain text into buffer. Counter names will be stored as
  2905. // a MULTI_SZ string in the format of "###" "Text..."
  2906. dwBufferSize = dwHelpSize;
  2907. __try {
  2908. lStatus = RegQueryValueExW(hKeyThisLang,
  2909. HelpNameBuffer,
  2910. RESERVED,
  2911. & dwValueType,
  2912. (LPVOID) pHelpBuffer,
  2913. & dwBufferSize);
  2914. }
  2915. __except (EXCEPTION_EXECUTE_HANDLER) {
  2916. lStatus = GetExceptionCode();
  2917. }
  2918. if (lStatus != ERROR_SUCCESS) {
  2919. ReportLoadPerfEvent(
  2920. EVENTLOG_ERROR_TYPE, // error type
  2921. (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event,
  2922. 2, lStatus, __LINE__, 0, 0,
  2923. 1, szThisLang, NULL, NULL);
  2924. TRACE((WINPERF_DBG_TRACE_ERROR),
  2925. (& LoadPerfGuid,
  2926. __LINE__,
  2927. LOADPERF_UPDATEEACHLANGUAGE,
  2928. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2929. lStatus,
  2930. TRACE_WSTR(szThisLang),
  2931. TRACE_WSTR(Help),
  2932. NULL));
  2933. bResult = FALSE;
  2934. goto Cleanup;
  2935. }
  2936. if (bUpdate) {
  2937. // set pointer to location in buffer where new string should be
  2938. // appended: end of buffer - 1 (second null at end of MULTI_SZ
  2939. pNewHelp = (LPWSTR) ((PBYTE)pHelpBuffer + dwBufferSize - sizeof(WCHAR));
  2940. // adjust buffer length to take into account 2nd null from 1st
  2941. // buffer that has been overwritten
  2942. dwHelpSize -= sizeof(WCHAR);
  2943. }
  2944. if (bUpdate) {
  2945. // append new strings to end of current strings
  2946. memcpy(pNewHelp, pThisLang->HelpBuffer, pThisLang->dwHelpBuffSize);
  2947. memcpy(pNewName, pThisLang->NameBuffer, pThisLang->dwNameBuffSize);
  2948. }
  2949. if (! CheckNameTable(pNameBuffer, pHelpBuffer, & dwLastCounter, & dwLastHelp, bUpdate)) {
  2950. bResult = FALSE;
  2951. goto Cleanup;
  2952. }
  2953. if (bUpdate) {
  2954. // write to the file thru PerfLib
  2955. dwBufferSize = dwCounterSize;
  2956. __try {
  2957. lStatus = RegQueryValueExW(hKeyThisLang,
  2958. AddCounterNameBuffer,
  2959. RESERVED,
  2960. & dwValueType,
  2961. (LPVOID) pNameBuffer,
  2962. & dwBufferSize);
  2963. }
  2964. __except (EXCEPTION_EXECUTE_HANDLER) {
  2965. lStatus = GetExceptionCode();
  2966. }
  2967. if (lStatus != ERROR_SUCCESS) {
  2968. ReportLoadPerfEvent(
  2969. EVENTLOG_ERROR_TYPE, // error type
  2970. (DWORD) LDPRFMSG_UNABLE_UPDATE_COUNTER_STRINGS, // event,
  2971. 2, lStatus, __LINE__, 0, 0,
  2972. 1, pThisLang->LangId, NULL, NULL);
  2973. TRACE((WINPERF_DBG_TRACE_ERROR),
  2974. (& LoadPerfGuid,
  2975. __LINE__,
  2976. LOADPERF_UPDATEEACHLANGUAGE,
  2977. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  2978. lStatus,
  2979. TRACE_WSTR(pThisLang->LangId),
  2980. TRACE_WSTR(AddCounterNameBuffer),
  2981. NULL));
  2982. bResult = FALSE;
  2983. goto Cleanup;
  2984. }
  2985. dwBufferSize = dwHelpSize;
  2986. __try {
  2987. lStatus = RegQueryValueExW(hKeyThisLang,
  2988. AddHelpNameBuffer,
  2989. RESERVED,
  2990. & dwValueType,
  2991. (LPVOID) pHelpBuffer,
  2992. & dwBufferSize);
  2993. }
  2994. __except (EXCEPTION_EXECUTE_HANDLER) {
  2995. lStatus = GetExceptionCode();
  2996. }
  2997. if (lStatus != ERROR_SUCCESS) {
  2998. ReportLoadPerfEvent(
  2999. EVENTLOG_ERROR_TYPE, // error type
  3000. (DWORD) LDPRFMSG_UNABLE_UPDATE_HELP_STRINGS, // event,
  3001. 2, lStatus, __LINE__, 0, 0,
  3002. 1, pThisLang->LangId, NULL, NULL);
  3003. TRACE((WINPERF_DBG_TRACE_ERROR),
  3004. (& LoadPerfGuid,
  3005. __LINE__,
  3006. LOADPERF_UPDATEEACHLANGUAGE,
  3007. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3008. lStatus,
  3009. TRACE_WSTR(pThisLang->LangId),
  3010. TRACE_WSTR(AddHelpNameBuffer),
  3011. NULL));
  3012. bResult = FALSE;
  3013. goto Cleanup;
  3014. }
  3015. }
  3016. MemoryFree(pNameBuffer);
  3017. MemoryFree(pHelpBuffer);
  3018. pNameBuffer = NULL;
  3019. pHelpBuffer = NULL;
  3020. }
  3021. else {
  3022. OUTPUT_MESSAGE(bQuietMode, GetFormatResource (LC_UNABLEOPENLANG), szThisLang);
  3023. }
  3024. }
  3025. Cleanup:
  3026. MemoryFree(pNameBuffer);
  3027. MemoryFree(pHelpBuffer);
  3028. MemoryFree(CounterNameBuffer);
  3029. if (! bResult) {
  3030. SetLastError(lStatus);
  3031. }
  3032. else if (! bUpdate) {
  3033. * pdwLastCounter = dwLastCounter;
  3034. * pdwLastHelp = dwLastHelp;
  3035. }
  3036. return bResult;
  3037. }
  3038. BOOL
  3039. UpdateRegistry(
  3040. BOOL bQuietMode,
  3041. DWORD dwMode,
  3042. LPWSTR lpDriverName,
  3043. LPWSTR lpIniFile,
  3044. LPWSTR lp009IniFile,
  3045. PLANG_ENTRY pLanguages,
  3046. PSERVICE_ENTRY pService,
  3047. PLANGUAGE_LIST_ELEMENT pFirstLang,
  3048. PSYMBOL_TABLE_ENTRY pFirstSymbol,
  3049. LPDWORD pdwObjectGuidTableSize,
  3050. LPDWORD pdwIndexValues
  3051. )
  3052. /*++
  3053. UpdateRegistry
  3054. - checks, and if not busy, sets the "busy" key in the registry
  3055. - Reads in the text and help definitions from the .ini file
  3056. - Reads in the current contents of the HELP and COUNTER names
  3057. - Builds a sorted MULTI_SZ struct containing the new definitions
  3058. - Appends the new MULTI_SZ to the current as read from the registry
  3059. - loads the new MULTI_SZ string into the registry
  3060. - updates the keys in the driver's entry and Perflib's entry in the
  3061. registry (e.g. first, last, etc)
  3062. - deletes the DisablePerformanceCounters value if it's present in
  3063. order to re-enable the perf counter DLL
  3064. - clears the "busy" key
  3065. Arguments
  3066. lpIniFile
  3067. pathname to .ini file conatining definitions
  3068. hKeyMachine
  3069. handle to HKEY_LOCAL_MACHINE in registry on system to
  3070. update counters for.
  3071. lpDriverName
  3072. Name of device driver to load counters for
  3073. pFirstLang
  3074. pointer to first element in language structure list
  3075. pFirstSymbol
  3076. pointer to first element in symbol definition list
  3077. Return Value
  3078. TRUE if registry updated successfully
  3079. FALSE if registry not updated
  3080. (This routine will print an error message to stdout if an error
  3081. is encountered).
  3082. --*/
  3083. {
  3084. HKEY hDriverPerf = NULL;
  3085. HKEY hPerflib = NULL;
  3086. LPWSTR lpDriverKeyPath;
  3087. HKEY hKeyMachine = NULL;
  3088. DWORD dwType;
  3089. DWORD dwSize;
  3090. DWORD dwFirstDriverCounter;
  3091. DWORD dwFirstDriverHelp;
  3092. DWORD dwLastDriverCounter;
  3093. DWORD dwLastPerflibCounter;
  3094. DWORD dwLastPerflibHelp;
  3095. DWORD dwPerflibBaseIndex;
  3096. DWORD dwLastCounter;
  3097. DWORD dwLastHelp;
  3098. BOOL bStatus = FALSE;
  3099. LONG lStatus = ERROR_SUCCESS;
  3100. LPWSTR lpszObjectList = NULL;
  3101. DWORD dwObjectList = 0;
  3102. LPWSTR mszLangList = NULL;
  3103. DWORD dwWaitStatus;
  3104. HANDLE hLocalMutex = NULL;
  3105. HRESULT hr;
  3106. SetLastError(ERROR_SUCCESS);
  3107. if (! (dwMode & LODCTR_UPNF_NOINI)) {
  3108. dwObjectList = LoadPerfGetFileSize(lp009IniFile, NULL, TRUE);
  3109. if (dwObjectList == 0xFFFFFFFF) {
  3110. dwObjectList = 0;
  3111. }
  3112. }
  3113. if (dwObjectList < SMALL_BUFFER_SIZE) {
  3114. dwObjectList = SMALL_BUFFER_SIZE;
  3115. }
  3116. // allocate temporary buffers
  3117. dwSize = lstrlenW(DriverPathRoot) + lstrlenW(Slash) + lstrlenW(lpDriverName)
  3118. + lstrlenW(Slash) + lstrlenW(Performance) + 1;
  3119. if (dwSize < MAX_PATH) dwSize = MAX_PATH;
  3120. lpDriverKeyPath = MemoryAllocate(dwSize * sizeof(WCHAR));
  3121. lpszObjectList = MemoryAllocate(dwObjectList * sizeof(WCHAR));
  3122. if (lpDriverKeyPath == NULL || lpszObjectList == NULL) {
  3123. lStatus = ERROR_OUTOFMEMORY;
  3124. goto UpdateRegExit;
  3125. }
  3126. // build driver key path string
  3127. hr = StringCchPrintfW(lpDriverKeyPath, dwSize, L"%ws%ws%ws%ws%ws",
  3128. DriverPathRoot, Slash, lpDriverName, Slash, Performance);
  3129. // check if we need to connect to remote machine
  3130. hKeyMachine = HKEY_LOCAL_MACHINE;
  3131. // open keys to registry
  3132. // open key to driver's performance key
  3133. __try {
  3134. lStatus = RegOpenKeyExW(hKeyMachine, lpDriverKeyPath, RESERVED, KEY_WRITE | KEY_READ, & hDriverPerf);
  3135. }
  3136. __except (EXCEPTION_EXECUTE_HANDLER) {
  3137. lStatus = GetExceptionCode();
  3138. }
  3139. if (lStatus != ERROR_SUCCESS) {
  3140. ReportLoadPerfEvent(
  3141. EVENTLOG_ERROR_TYPE, // error type
  3142. (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event,
  3143. 2, lStatus, __LINE__, 0, 0,
  3144. 1, (LPWSTR) lpDriverKeyPath, NULL, NULL);
  3145. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_OPEN_DRIVERPERF1), lpDriverKeyPath);
  3146. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_OPEN_DRIVERPERF2), lStatus);
  3147. TRACE((WINPERF_DBG_TRACE_ERROR),
  3148. (& LoadPerfGuid,
  3149. __LINE__,
  3150. LOADPERF_UPDATEREGISTRY,
  3151. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3152. lStatus,
  3153. TRACE_WSTR(lpIniFile),
  3154. TRACE_WSTR(lpDriverName),
  3155. NULL));
  3156. goto UpdateRegExit;
  3157. }
  3158. // open key to perflib's "root" key
  3159. __try {
  3160. lStatus = RegOpenKeyExW(hKeyMachine, NamesKey, RESERVED, KEY_WRITE | KEY_READ, & hPerflib);
  3161. }
  3162. __except (EXCEPTION_EXECUTE_HANDLER) {
  3163. lStatus = GetExceptionCode();
  3164. }
  3165. if (lStatus != ERROR_SUCCESS) {
  3166. ReportLoadPerfEvent(
  3167. EVENTLOG_ERROR_TYPE, // error type
  3168. (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event,
  3169. 2, lStatus, __LINE__, 0, 0,
  3170. 1, (LPWSTR) NamesKey, NULL, NULL);
  3171. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_OPEN_PERFLIB), lStatus);
  3172. TRACE((WINPERF_DBG_TRACE_ERROR),
  3173. (& LoadPerfGuid,
  3174. __LINE__,
  3175. LOADPERF_UPDATEREGISTRY,
  3176. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3177. lStatus,
  3178. TRACE_WSTR(lpDriverName),
  3179. TRACE_WSTR(NamesKey),
  3180. NULL));
  3181. goto UpdateRegExit;
  3182. }
  3183. // get "LastCounter" values from PERFLIB
  3184. dwType = 0;
  3185. dwLastPerflibCounter = 0;
  3186. dwSize = sizeof(dwLastPerflibCounter);
  3187. __try {
  3188. lStatus = RegQueryValueExW(hPerflib,
  3189. LastCounter,
  3190. RESERVED,
  3191. & dwType,
  3192. (LPBYTE) & dwLastPerflibCounter,
  3193. & dwSize);
  3194. }
  3195. __except (EXCEPTION_EXECUTE_HANDLER) {
  3196. lStatus = GetExceptionCode();
  3197. }
  3198. if (lStatus != ERROR_SUCCESS) {
  3199. // this request should always succeed, if not then worse things
  3200. // will happen later on, so quit now and avoid the trouble.
  3201. ReportLoadPerfEvent(
  3202. EVENTLOG_ERROR_TYPE, // error type
  3203. (DWORD) LDPRFMSG_UNABLE_QUERY_VALUE, // event,
  3204. 2, lStatus, __LINE__, 0, 0,
  3205. 2, (LPWSTR) LastCounter, (LPWSTR) NamesKey, NULL);
  3206. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_READLASTPERFLIB), lStatus);
  3207. TRACE((WINPERF_DBG_TRACE_ERROR),
  3208. (& LoadPerfGuid,
  3209. __LINE__,
  3210. LOADPERF_UPDATEREGISTRY,
  3211. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3212. lStatus,
  3213. TRACE_WSTR(NamesKey),
  3214. TRACE_WSTR(LastCounter),
  3215. NULL));
  3216. goto UpdateRegExit;
  3217. }
  3218. // get "LastHelp" value now
  3219. dwType = 0;
  3220. dwLastPerflibHelp = 0;
  3221. dwSize = sizeof(dwLastPerflibHelp);
  3222. __try {
  3223. lStatus = RegQueryValueExW(hPerflib,
  3224. LastHelp,
  3225. RESERVED,
  3226. & dwType,
  3227. (LPBYTE) & dwLastPerflibHelp,
  3228. & dwSize);
  3229. }
  3230. __except (EXCEPTION_EXECUTE_HANDLER) {
  3231. lStatus = GetExceptionCode();
  3232. }
  3233. if (lStatus != ERROR_SUCCESS) {
  3234. // this request should always succeed, if not then worse things
  3235. // will happen later on, so quit now and avoid the trouble.
  3236. ReportLoadPerfEvent(
  3237. EVENTLOG_ERROR_TYPE, // error type
  3238. (DWORD) LDPRFMSG_UNABLE_QUERY_VALUE, // event,
  3239. 2, lStatus, __LINE__, 0, 0,
  3240. 2, (LPWSTR) LastHelp, (LPWSTR) NamesKey, NULL);
  3241. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_READLASTPERFLIB), lStatus);
  3242. TRACE((WINPERF_DBG_TRACE_ERROR),
  3243. (& LoadPerfGuid,
  3244. __LINE__,
  3245. LOADPERF_UPDATEREGISTRY,
  3246. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3247. lStatus,
  3248. TRACE_WSTR(NamesKey),
  3249. TRACE_WSTR(LastHelp),
  3250. NULL));
  3251. goto UpdateRegExit;
  3252. }
  3253. // get "Base Index" value now
  3254. dwType = 0;
  3255. dwPerflibBaseIndex = 0;
  3256. dwSize = sizeof(dwPerflibBaseIndex);
  3257. __try {
  3258. lStatus = RegQueryValueExW(hPerflib,
  3259. BaseIndex,
  3260. RESERVED,
  3261. & dwType,
  3262. (LPBYTE) & dwPerflibBaseIndex,
  3263. & dwSize);
  3264. }
  3265. __except (EXCEPTION_EXECUTE_HANDLER) {
  3266. lStatus = GetExceptionCode();
  3267. }
  3268. if (lStatus != ERROR_SUCCESS) {
  3269. // this request should always succeed, if not then worse things
  3270. // will happen later on, so quit now and avoid the trouble.
  3271. ReportLoadPerfEvent(
  3272. EVENTLOG_ERROR_TYPE, // error type
  3273. (DWORD) LDPRFMSG_UNABLE_QUERY_VALUE, // event,
  3274. 2, lStatus, __LINE__, 0, 0,
  3275. 2, (LPWSTR) BaseIndex, (LPWSTR) NamesKey, NULL);
  3276. OUTPUT_MESSAGE(bQuietMode, GetFormatResource (LC_ERR_READLASTPERFLIB), lStatus);
  3277. TRACE((WINPERF_DBG_TRACE_ERROR),
  3278. (& LoadPerfGuid,
  3279. __LINE__,
  3280. LOADPERF_UPDATEREGISTRY,
  3281. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3282. lStatus,
  3283. TRACE_WSTR(NamesKey),
  3284. TRACE_WSTR(BaseIndex),
  3285. NULL));
  3286. goto UpdateRegExit;
  3287. }
  3288. // see if this driver's counter names have already been installed
  3289. // by checking to see if LastCounter's value is less than Perflib's
  3290. // Last Counter
  3291. dwType = 0;
  3292. dwLastDriverCounter = 0;
  3293. dwSize = sizeof(dwLastDriverCounter);
  3294. __try {
  3295. lStatus = RegQueryValueExW(hDriverPerf,
  3296. LastCounter,
  3297. RESERVED,
  3298. & dwType,
  3299. (LPBYTE) & dwLastDriverCounter,
  3300. & dwSize);
  3301. }
  3302. __except (EXCEPTION_EXECUTE_HANDLER) {
  3303. lStatus = GetExceptionCode();
  3304. }
  3305. if (lStatus == ERROR_SUCCESS) {
  3306. // if key found, then compare with perflib value and exit this
  3307. // procedure if the driver's last counter is <= to perflib's last
  3308. //
  3309. // if key not found, then continue with installation
  3310. // on the assumption that the counters have not been installed
  3311. if (dwLastDriverCounter <= dwLastPerflibCounter) {
  3312. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_ALREADY_IN), lpDriverName);
  3313. lStatus = ERROR_ALREADY_EXISTS;
  3314. goto UpdateRegExit;
  3315. }
  3316. }
  3317. TRACE((WINPERF_DBG_TRACE_INFO),
  3318. (& LoadPerfGuid,
  3319. __LINE__,
  3320. LOADPERF_UPDATEREGISTRY,
  3321. ARG_DEF(ARG_TYPE_WSTR, 1),
  3322. lStatus,
  3323. TRACE_WSTR(lpDriverName),
  3324. TRACE_DWORD(dwLastPerflibCounter),
  3325. TRACE_DWORD(dwLastPerflibHelp),
  3326. TRACE_DWORD(dwPerflibBaseIndex),
  3327. NULL));
  3328. // set the "busy" indicator under the PERFLIB key
  3329. dwSize = (lstrlenW(lpDriverName) + 1) * sizeof(WCHAR);
  3330. __try {
  3331. lStatus = RegSetValueExW(hPerflib,
  3332. Busy,
  3333. RESERVED,
  3334. REG_SZ,
  3335. (LPBYTE) lpDriverName,
  3336. dwSize);
  3337. }
  3338. __except (EXCEPTION_EXECUTE_HANDLER) {
  3339. lStatus = GetExceptionCode();
  3340. }
  3341. if (lStatus != ERROR_SUCCESS) {
  3342. OUTPUT_MESSAGE(bQuietMode, GetFormatResource (LC_ERR_UNABLESETBUSY), lStatus);
  3343. TRACE((WINPERF_DBG_TRACE_ERROR),
  3344. (& LoadPerfGuid,
  3345. __LINE__,
  3346. LOADPERF_UPDATEREGISTRY,
  3347. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3348. lStatus,
  3349. TRACE_WSTR(NamesKey),
  3350. TRACE_WSTR(Busy),
  3351. NULL));
  3352. goto UpdateRegExit;
  3353. }
  3354. dwLastCounter = dwLastPerflibCounter;
  3355. dwLastHelp = dwLastPerflibHelp;
  3356. // get the list of installed languages on this machine
  3357. bStatus = GetInstalledLanguageList(hPerflib, & mszLangList);
  3358. if (! bStatus) {
  3359. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_UPDATELANG), GetLastError());
  3360. lStatus = GetLastError();
  3361. goto UpdateRegExit;
  3362. }
  3363. bStatus = UpdateEachLanguage(bQuietMode,
  3364. hPerflib,
  3365. mszLangList,
  3366. & dwLastCounter,
  3367. & dwLastHelp,
  3368. pFirstLang,
  3369. dwMode,
  3370. FALSE);
  3371. if (! bStatus) {
  3372. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_UPDATELANG), GetLastError());
  3373. lStatus = GetLastError();
  3374. goto UpdateRegExit;
  3375. }
  3376. // increment (by 2) the last counters so they point to the first
  3377. // unused index after the existing names and then
  3378. // set the first driver counters
  3379. bStatus = FALSE;
  3380. dwFirstDriverCounter = dwLastCounter + 2;
  3381. dwFirstDriverHelp = dwLastHelp + 2;
  3382. if (dwFirstDriverHelp != dwFirstDriverCounter + 1) {
  3383. TRACE((WINPERF_DBG_TRACE_WARNING),
  3384. (& LoadPerfGuid,
  3385. __LINE__,
  3386. LOADPERF_UPDATEREGISTRY,
  3387. ARG_DEF(ARG_TYPE_WSTR, 1),
  3388. lStatus,
  3389. TRACE_WSTR(lpDriverName),
  3390. TRACE_DWORD(dwPerflibBaseIndex),
  3391. TRACE_DWORD(dwFirstDriverCounter),
  3392. TRACE_DWORD(dwFirstDriverHelp),
  3393. NULL));
  3394. dwFirstDriverHelp = dwFirstDriverCounter + 1;
  3395. }
  3396. if ((dwPerflibBaseIndex < PERFLIB_BASE_INDEX)
  3397. || (dwFirstDriverCounter < dwPerflibBaseIndex)
  3398. || (dwFirstDriverHelp < dwPerflibBaseIndex)) {
  3399. // potential CounterIndex/HelpIndex overlap with Base counters,
  3400. //
  3401. ReportLoadPerfEvent(
  3402. EVENTLOG_ERROR_TYPE, // error type
  3403. (DWORD) LDPRFMSG_REGISTRY_BASEINDEX_CORRUPT, // event,
  3404. 4, dwPerflibBaseIndex, dwFirstDriverCounter, dwFirstDriverHelp, __LINE__,
  3405. 1, lpDriverName, NULL, NULL);
  3406. lStatus = ERROR_BADKEY;
  3407. TRACE((WINPERF_DBG_TRACE_ERROR),
  3408. (& LoadPerfGuid,
  3409. __LINE__,
  3410. LOADPERF_UPDATEREGISTRY,
  3411. ARG_DEF(ARG_TYPE_WSTR, 1),
  3412. lStatus,
  3413. TRACE_WSTR(lpDriverName),
  3414. TRACE_DWORD(dwPerflibBaseIndex),
  3415. TRACE_DWORD(dwFirstDriverCounter),
  3416. TRACE_DWORD(dwFirstDriverHelp),
  3417. NULL));
  3418. goto UpdateRegExit;
  3419. }
  3420. // load .INI file definitions into language tables
  3421. if (dwMode & LODCTR_UPNF_NOINI) {
  3422. PLANGUAGE_LIST_ELEMENT pThisLang = NULL;
  3423. PLANG_ENTRY pLangEntry = NULL;
  3424. PLANG_ENTRY p009LangEntry = NULL;
  3425. DWORD dwErrorCount = 0;
  3426. DWORD dwIndex;
  3427. DWORD dwNewIndex;
  3428. for (pThisLang = pFirstLang; pThisLang != NULL; pThisLang = pThisLang->pNextLang) {
  3429. TRACE((WINPERF_DBG_TRACE_INFO),
  3430. (& LoadPerfGuid,
  3431. __LINE__,
  3432. LOADPERF_LOADLANGUAGELISTS,
  3433. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3434. ERROR_SUCCESS,
  3435. TRACE_WSTR(lpDriverName),
  3436. TRACE_WSTR(pThisLang->LangId),
  3437. TRACE_DWORD(dwFirstDriverCounter),
  3438. TRACE_DWORD(dwFirstDriverHelp),
  3439. NULL));
  3440. for (pLangEntry = pLanguages; pLangEntry != NULL; pLangEntry = pLangEntry->pNext) {
  3441. if (lstrcmpiW(pThisLang->LangId, pLangEntry->szLang) == 0) {
  3442. break;
  3443. }
  3444. else if (lstrcmpiW(pLangEntry->szLang, DefaultLangId) == 0) {
  3445. p009LangEntry = pLangEntry;
  3446. }
  3447. }
  3448. if (pLangEntry == NULL) {
  3449. pLangEntry = p009LangEntry;
  3450. }
  3451. else if (pLangEntry->lpText == NULL) {
  3452. // no text for selected language, use 009 ones.
  3453. //
  3454. pLangEntry = p009LangEntry;
  3455. }
  3456. if (pLangEntry == NULL) {
  3457. dwErrorCount ++;
  3458. continue;
  3459. }
  3460. else if (pLangEntry->lpText == NULL) {
  3461. dwErrorCount ++;
  3462. continue;
  3463. }
  3464. TRACE((WINPERF_DBG_TRACE_INFO),
  3465. (& LoadPerfGuid,
  3466. __LINE__,
  3467. LOADPERF_LOADLANGUAGELISTS,
  3468. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3469. ERROR_SUCCESS,
  3470. TRACE_WSTR(lpDriverName),
  3471. TRACE_WSTR(pLangEntry->szLang),
  3472. TRACE_DWORD(pService->dwFirstCounter),
  3473. TRACE_DWORD(pService->dwFirstHelp),
  3474. TRACE_DWORD(pService->dwLastCounter),
  3475. TRACE_DWORD(pService->dwLastHelp),
  3476. TRACE_DWORD(pLangEntry->dwLastCounter),
  3477. TRACE_DWORD(pLangEntry->dwLastHelp),
  3478. NULL));
  3479. for (dwIndex = pService->dwFirstCounter; dwIndex <= pService->dwLastHelp; dwIndex ++) {
  3480. if (dwIndex > pLangEntry->dwLastHelp) {
  3481. dwErrorCount ++;
  3482. break;
  3483. }
  3484. dwNewIndex = dwIndex + dwFirstDriverCounter
  3485. - pService->dwFirstCounter;
  3486. dwType = (((dwIndex - pService->dwFirstCounter) % 2) == 0)
  3487. ? (TYPE_NAME) : (TYPE_HELP);
  3488. if (pLangEntry->lpText[dwIndex] != NULL) {
  3489. __try {
  3490. TRACE((WINPERF_DBG_TRACE_INFO),
  3491. (& LoadPerfGuid,
  3492. __LINE__,
  3493. LOADPERF_LOADLANGUAGELISTS,
  3494. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_WSTR, 3),
  3495. ERROR_SUCCESS,
  3496. TRACE_WSTR(lpDriverName),
  3497. TRACE_WSTR(pThisLang->LangId),
  3498. TRACE_WSTR(pLangEntry->lpText[dwIndex]),
  3499. TRACE_DWORD(dwIndex),
  3500. TRACE_DWORD(dwNewIndex),
  3501. TRACE_DWORD(dwType),
  3502. NULL));
  3503. bStatus = AddEntryToLanguage(pThisLang,
  3504. NULL,
  3505. pLangEntry->lpText[dwIndex],
  3506. 0,
  3507. NULL,
  3508. 0,
  3509. dwType,
  3510. dwNewIndex,
  3511. 0);
  3512. }
  3513. __except (EXCEPTION_EXECUTE_HANDLER) {
  3514. lStatus = GetExceptionCode();
  3515. TRACE((WINPERF_DBG_TRACE_ERROR),
  3516. (& LoadPerfGuid,
  3517. __LINE__,
  3518. LOADPERF_UPDATEREGISTRY,
  3519. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3520. lStatus,
  3521. TRACE_WSTR(lpDriverName),
  3522. TRACE_WSTR(pThisLang->LangId),
  3523. TRACE_DWORD(dwType),
  3524. TRACE_DWORD(dwIndex),
  3525. TRACE_DWORD(dwNewIndex),
  3526. NULL));
  3527. bStatus = FALSE;
  3528. SetLastError(lStatus);
  3529. }
  3530. if (! bStatus) {
  3531. OUTPUT_MESSAGE(bQuietMode,
  3532. GetFormatResource(LC_ERRADDTOLANG),
  3533. pLangEntry->lpText[dwIndex],
  3534. pThisLang->LangId,
  3535. GetLastError());
  3536. lStatus = GetLastError();
  3537. dwErrorCount ++;
  3538. }
  3539. }
  3540. else {
  3541. TRACE((WINPERF_DBG_TRACE_INFO),
  3542. (& LoadPerfGuid,
  3543. __LINE__,
  3544. LOADPERF_LOADLANGUAGELISTS,
  3545. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3546. ERROR_SUCCESS,
  3547. TRACE_WSTR(lpDriverName),
  3548. TRACE_WSTR(pThisLang->LangId),
  3549. TRACE_DWORD(dwIndex),
  3550. TRACE_DWORD(dwNewIndex),
  3551. TRACE_DWORD(dwType),
  3552. NULL));
  3553. }
  3554. }
  3555. }
  3556. bStatus = (dwErrorCount == 0) ? (TRUE) : (FALSE);
  3557. if (! bStatus) {
  3558. goto UpdateRegExit;
  3559. }
  3560. }
  3561. else {
  3562. bStatus = LoadLanguageLists(bQuietMode,
  3563. lpIniFile,
  3564. lpDriverName,
  3565. dwMode,
  3566. dwFirstDriverCounter,
  3567. dwFirstDriverHelp,
  3568. pFirstSymbol,
  3569. pFirstLang);
  3570. if (! bStatus) {
  3571. // error message is displayed by LoadLanguageLists so just abort
  3572. // error is in GetLastError already
  3573. lStatus = GetLastError();
  3574. goto UpdateRegExit;
  3575. }
  3576. }
  3577. if (dwMode & LODCTR_UPNF_NOINI) {
  3578. WCHAR szDigits[32];
  3579. DWORD dwObjectId;
  3580. for (dwObjectId = 0; dwObjectId < pService->dwNumObjects; dwObjectId ++) {
  3581. ZeroMemory(szDigits, sizeof(WCHAR) * 32);
  3582. _ultow((dwFirstDriverCounter + pService->dwObjects[dwObjectId]), szDigits,
  3583. 10);
  3584. if (dwObjectId > 0) {
  3585. hr = StringCchCatW(lpszObjectList, dwObjectList, BlankString);
  3586. hr = StringCchCatW(lpszObjectList, dwObjectList, szDigits);
  3587. }
  3588. else {
  3589. hr = StringCchCopyW(lpszObjectList, dwObjectList, szDigits);
  3590. }
  3591. }
  3592. }
  3593. else {
  3594. bStatus = CreateObjectList(lp009IniFile,
  3595. dwFirstDriverCounter,
  3596. pFirstSymbol,
  3597. lpszObjectList,
  3598. dwObjectList,
  3599. pdwObjectGuidTableSize);
  3600. if (! bStatus) {
  3601. // error message is displayed by CreateObjectList so just abort
  3602. // error is in GetLastError already
  3603. lStatus = GetLastError();
  3604. goto UpdateRegExit;
  3605. }
  3606. }
  3607. // all the symbols and definitions have been loaded into internal
  3608. // tables. so now they need to be sorted and merged into a multiSZ string
  3609. // this routine also updates the "last" counters
  3610. bStatus = SortLanguageTables(pFirstLang, & dwLastCounter, & dwLastHelp);
  3611. if (! bStatus) {
  3612. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_UNABLESORTTABLES), GetLastError());
  3613. lStatus = GetLastError();
  3614. goto UpdateRegExit;
  3615. }
  3616. if (dwLastCounter < dwLastPerflibCounter || dwLastHelp < dwLastPerflibHelp) {
  3617. // potential CounterIndex/HelpIndex overlap with Base counters,
  3618. //
  3619. ReportLoadPerfEvent(
  3620. EVENTLOG_ERROR_TYPE, // error type
  3621. (DWORD) LDPRFMSG_REGISTRY_BASEINDEX_CORRUPT, // event,
  3622. 4, dwLastPerflibCounter, dwLastCounter, dwLastHelp, __LINE__,
  3623. 1 , lpDriverName, NULL, NULL);
  3624. bStatus = FALSE;
  3625. lStatus = ERROR_BADKEY;
  3626. TRACE((WINPERF_DBG_TRACE_ERROR),
  3627. (& LoadPerfGuid,
  3628. __LINE__,
  3629. LOADPERF_UPDATEREGISTRY,
  3630. ARG_DEF(ARG_TYPE_WSTR, 1),
  3631. lStatus,
  3632. TRACE_WSTR(lpDriverName),
  3633. TRACE_DWORD(dwLastPerflibCounter),
  3634. TRACE_DWORD(dwLastPerflibHelp),
  3635. TRACE_DWORD(dwLastCounter),
  3636. TRACE_DWORD(dwLastHelp),
  3637. NULL));
  3638. goto UpdateRegExit;
  3639. }
  3640. bStatus = UpdateEachLanguage(bQuietMode,
  3641. hPerflib,
  3642. mszLangList,
  3643. & dwLastCounter,
  3644. & dwLastHelp,
  3645. pFirstLang,
  3646. dwMode,
  3647. TRUE);
  3648. if (! bStatus) {
  3649. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_ERR_UPDATELANG), GetLastError());
  3650. lStatus = GetLastError();
  3651. goto UpdateRegExit;
  3652. }
  3653. bStatus = FALSE;
  3654. dwLastPerflibCounter = dwLastCounter;
  3655. dwLastPerflibHelp = dwLastHelp;
  3656. TRACE((WINPERF_DBG_TRACE_INFO),
  3657. (& LoadPerfGuid,
  3658. __LINE__,
  3659. LOADPERF_UPDATEREGISTRY,
  3660. ARG_DEF(ARG_TYPE_WSTR, 1),
  3661. lStatus,
  3662. TRACE_WSTR(lpDriverName),
  3663. TRACE_DWORD(dwFirstDriverCounter),
  3664. TRACE_DWORD(dwFirstDriverHelp),
  3665. TRACE_DWORD(dwLastPerflibCounter),
  3666. TRACE_DWORD(dwLastPerflibHelp),
  3667. NULL));
  3668. if (dwLastCounter < dwFirstDriverCounter) {
  3669. ReportLoadPerfEvent(
  3670. EVENTLOG_ERROR_TYPE, // error type
  3671. (DWORD) LDPRFMSG_CORRUPT_INDEX_RANGE, // event,
  3672. 3, dwFirstDriverCounter, dwLastCounter, __LINE__, 0,
  3673. 2, (LPWSTR) Counters, (LPWSTR) lpDriverKeyPath, NULL);
  3674. lStatus = ERROR_BADKEY;
  3675. goto UpdateRegExit;
  3676. }
  3677. if (dwLastHelp < dwFirstDriverHelp) {
  3678. ReportLoadPerfEvent(
  3679. EVENTLOG_ERROR_TYPE, // error type
  3680. (DWORD) LDPRFMSG_CORRUPT_INDEX_RANGE, // event,
  3681. 3, dwFirstDriverHelp, dwLastHelp, __LINE__, 0,
  3682. 2, (LPWSTR) Help, (LPWSTR) lpDriverKeyPath, NULL);
  3683. lStatus = ERROR_BADKEY;
  3684. goto UpdateRegExit;
  3685. }
  3686. // update last counters for driver and perflib
  3687. // perflib...
  3688. __try {
  3689. lStatus = RegSetValueExW(hPerflib,
  3690. LastCounter,
  3691. RESERVED,
  3692. REG_DWORD,
  3693. (LPBYTE) & dwLastPerflibCounter,
  3694. sizeof(DWORD));
  3695. }
  3696. __except (EXCEPTION_EXECUTE_HANDLER) {
  3697. lStatus = GetExceptionCode();
  3698. }
  3699. if (lStatus != ERROR_SUCCESS) {
  3700. ReportLoadPerfEvent(
  3701. EVENTLOG_ERROR_TYPE, // error type
  3702. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  3703. 3, lStatus, dwLastPerflibCounter, __LINE__, 0,
  3704. 2, (LPWSTR) LastCounter, (LPWSTR) NamesKey, NULL);
  3705. OUTPUT_MESSAGE(bQuietMode, GetFormatResource (LC_UNABLESETVALUE), LastCounter, szPerflib);
  3706. TRACE((WINPERF_DBG_TRACE_ERROR),
  3707. (& LoadPerfGuid,
  3708. __LINE__,
  3709. LOADPERF_UPDATEREGISTRY,
  3710. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3711. lStatus,
  3712. TRACE_WSTR(NamesKey),
  3713. TRACE_WSTR(LastCounter),
  3714. TRACE_DWORD(dwLastPerflibCounter),
  3715. NULL));
  3716. }
  3717. __try {
  3718. lStatus = RegSetValueExW(hPerflib,
  3719. LastHelp,
  3720. RESERVED,
  3721. REG_DWORD,
  3722. (LPBYTE) & dwLastPerflibHelp,
  3723. sizeof(DWORD));
  3724. }
  3725. __except (EXCEPTION_EXECUTE_HANDLER) {
  3726. lStatus = GetExceptionCode();
  3727. }
  3728. if (lStatus != ERROR_SUCCESS) {
  3729. ReportLoadPerfEvent(
  3730. EVENTLOG_ERROR_TYPE, // error type
  3731. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  3732. 3, lStatus, dwLastPerflibHelp, __LINE__, 0,
  3733. 2, (LPWSTR) LastHelp, (LPWSTR) NamesKey, NULL);
  3734. OUTPUT_MESSAGE(bQuietMode, GetFormatResource (LC_UNABLESETVALUE), LastHelp, szPerflib);
  3735. TRACE((WINPERF_DBG_TRACE_ERROR),
  3736. (& LoadPerfGuid,
  3737. __LINE__,
  3738. LOADPERF_UPDATEREGISTRY,
  3739. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3740. lStatus,
  3741. TRACE_WSTR(NamesKey),
  3742. TRACE_WSTR(LastHelp),
  3743. TRACE_DWORD(dwLastPerflibHelp),
  3744. NULL));
  3745. }
  3746. // and the driver
  3747. __try {
  3748. lStatus = RegSetValueExW(hDriverPerf,
  3749. LastCounter,
  3750. RESERVED,
  3751. REG_DWORD,
  3752. (LPBYTE) & dwLastPerflibCounter,
  3753. sizeof(DWORD));
  3754. }
  3755. __except (EXCEPTION_EXECUTE_HANDLER) {
  3756. lStatus = GetExceptionCode();
  3757. }
  3758. if (lStatus != ERROR_SUCCESS) {
  3759. ReportLoadPerfEvent(
  3760. EVENTLOG_ERROR_TYPE, // error type
  3761. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  3762. 3, lStatus, dwLastPerflibCounter, __LINE__, 0,
  3763. 2, (LPWSTR) LastCounter, (LPWSTR) lpDriverKeyPath, NULL);
  3764. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_UNABLESETVALUE), LastCounter, lpDriverName);
  3765. TRACE((WINPERF_DBG_TRACE_ERROR),
  3766. (& LoadPerfGuid,
  3767. __LINE__,
  3768. LOADPERF_UPDATEREGISTRY,
  3769. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3770. lStatus,
  3771. TRACE_WSTR(lpDriverName),
  3772. TRACE_WSTR(LastCounter),
  3773. TRACE_DWORD(dwLastPerflibCounter),
  3774. NULL));
  3775. }
  3776. __try {
  3777. lStatus = RegSetValueExW(hDriverPerf,
  3778. LastHelp,
  3779. RESERVED,
  3780. REG_DWORD,
  3781. (LPBYTE) & dwLastPerflibHelp,
  3782. sizeof(DWORD));
  3783. }
  3784. __except (EXCEPTION_EXECUTE_HANDLER) {
  3785. lStatus = GetExceptionCode();
  3786. }
  3787. if (lStatus != ERROR_SUCCESS) {
  3788. ReportLoadPerfEvent(
  3789. EVENTLOG_ERROR_TYPE, // error type
  3790. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  3791. 3, lStatus, dwLastPerflibHelp, __LINE__, 0,
  3792. 2, (LPWSTR) LastHelp, (LPWSTR) lpDriverKeyPath, NULL);
  3793. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_UNABLESETVALUE), LastHelp, lpDriverName);
  3794. TRACE((WINPERF_DBG_TRACE_ERROR),
  3795. (& LoadPerfGuid,
  3796. __LINE__,
  3797. LOADPERF_UPDATEREGISTRY,
  3798. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3799. lStatus,
  3800. TRACE_WSTR(lpDriverName),
  3801. TRACE_WSTR(LastHelp),
  3802. TRACE_DWORD(dwLastPerflibHelp),
  3803. NULL));
  3804. }
  3805. __try {
  3806. lStatus = RegSetValueExW(hDriverPerf,
  3807. FirstCounter,
  3808. RESERVED,
  3809. REG_DWORD,
  3810. (LPBYTE) & dwFirstDriverCounter,
  3811. sizeof(DWORD));
  3812. }
  3813. __except (EXCEPTION_EXECUTE_HANDLER) {
  3814. lStatus = GetExceptionCode();
  3815. }
  3816. if (lStatus != ERROR_SUCCESS) {
  3817. ReportLoadPerfEvent(
  3818. EVENTLOG_ERROR_TYPE, // error type
  3819. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  3820. 3, lStatus, dwFirstDriverCounter, __LINE__, 0,
  3821. 2, (LPWSTR) FirstCounter, (LPWSTR) lpDriverKeyPath, NULL);
  3822. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_UNABLESETVALUE), FirstCounter, lpDriverName);
  3823. TRACE((WINPERF_DBG_TRACE_ERROR),
  3824. (& LoadPerfGuid,
  3825. __LINE__,
  3826. LOADPERF_UPDATEREGISTRY,
  3827. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3828. lStatus,
  3829. TRACE_WSTR(lpDriverName),
  3830. TRACE_WSTR(FirstCounter),
  3831. TRACE_DWORD(dwFirstDriverCounter),
  3832. NULL));
  3833. }
  3834. __try {
  3835. lStatus = RegSetValueExW(hDriverPerf,
  3836. FirstHelp,
  3837. RESERVED,
  3838. REG_DWORD,
  3839. (LPBYTE) & dwFirstDriverHelp,
  3840. sizeof(DWORD));
  3841. }
  3842. __except (EXCEPTION_EXECUTE_HANDLER) {
  3843. lStatus = GetExceptionCode();
  3844. }
  3845. if (lStatus != ERROR_SUCCESS) {
  3846. ReportLoadPerfEvent(
  3847. EVENTLOG_ERROR_TYPE, // error type
  3848. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  3849. 3, lStatus, dwFirstDriverHelp, __LINE__, 0,
  3850. 2, (LPWSTR) FirstHelp, (LPWSTR) lpDriverKeyPath, NULL);
  3851. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_UNABLESETVALUE), FirstHelp, lpDriverName);
  3852. TRACE((WINPERF_DBG_TRACE_ERROR),
  3853. (& LoadPerfGuid,
  3854. __LINE__,
  3855. LOADPERF_UPDATEREGISTRY,
  3856. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3857. lStatus,
  3858. TRACE_WSTR(lpDriverName),
  3859. TRACE_WSTR(FirstHelp),
  3860. TRACE_DWORD(dwFirstDriverHelp),
  3861. NULL));
  3862. }
  3863. if (*lpszObjectList != L'\0') {
  3864. __try {
  3865. lStatus = RegSetValueExW(hDriverPerf,
  3866. szObjectList,
  3867. RESERVED,
  3868. REG_SZ,
  3869. (LPBYTE) lpszObjectList,
  3870. (lstrlenW(lpszObjectList) + 1) * sizeof (WCHAR));
  3871. }
  3872. __except (EXCEPTION_EXECUTE_HANDLER) {
  3873. lStatus = GetExceptionCode();
  3874. }
  3875. if (lStatus != ERROR_SUCCESS) {
  3876. ReportLoadPerfEvent(
  3877. EVENTLOG_ERROR_TYPE, // error type
  3878. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  3879. 2, lStatus, __LINE__, 0, 0,
  3880. 2, (LPWSTR) szObjectList, (LPWSTR) lpDriverKeyPath, NULL);
  3881. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_UNABLESETVALUE), szObjectList, lpDriverName);
  3882. TRACE((WINPERF_DBG_TRACE_ERROR),
  3883. (& LoadPerfGuid,
  3884. __LINE__,
  3885. LOADPERF_UPDATEREGISTRY,
  3886. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3887. lStatus,
  3888. TRACE_WSTR(lpDriverName),
  3889. TRACE_WSTR(szObjectList),
  3890. NULL));
  3891. }
  3892. }
  3893. bStatus = TRUE;
  3894. pdwIndexValues[0] = dwFirstDriverCounter; // first Counter
  3895. pdwIndexValues[1] = dwLastPerflibCounter; // last Counter
  3896. pdwIndexValues[2] = dwFirstDriverHelp; // first Help
  3897. pdwIndexValues[3] = dwLastPerflibHelp; // last Help
  3898. // remove "DisablePerformanceCounter" value so perf counters are re-enabled.
  3899. lStatus = RegDeleteValueW(hDriverPerf, DisablePerformanceCounters);
  3900. UpdateRegExit:
  3901. if (hPerflib != NULL && hPerflib != INVALID_HANDLE_VALUE) {
  3902. DWORD lTmpStatus = ERROR_SUCCESS;
  3903. __try {
  3904. lTmpStatus = RegDeleteValueW(hPerflib, Busy);
  3905. }
  3906. __except (EXCEPTION_EXECUTE_HANDLER) {
  3907. lTmpStatus = GetExceptionCode();
  3908. }
  3909. if (lTmpStatus != ERROR_SUCCESS) {
  3910. TRACE((WINPERF_DBG_TRACE_ERROR),
  3911. (& LoadPerfGuid,
  3912. __LINE__,
  3913. LOADPERF_UPDATEREGISTRY,
  3914. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  3915. lTmpStatus,
  3916. TRACE_WSTR(lpDriverName),
  3917. TRACE_WSTR(Busy),
  3918. NULL));
  3919. }
  3920. }
  3921. // MemoryFree temporary buffers
  3922. // free any guid string buffers here
  3923. // TODO: add this code
  3924. MemoryFree(lpDriverKeyPath);
  3925. MemoryFree(lpszObjectList);
  3926. MemoryFree(mszLangList);
  3927. if (hDriverPerf != NULL && hDriverPerf != INVALID_HANDLE_VALUE) RegCloseKey(hDriverPerf);
  3928. if (hPerflib != NULL && hPerflib != INVALID_HANDLE_VALUE) RegCloseKey(hPerflib);
  3929. if (hKeyMachine != NULL && hKeyMachine != HKEY_LOCAL_MACHINE) RegCloseKey(hKeyMachine);
  3930. if (! bStatus) SetLastError(lStatus);
  3931. return bStatus;
  3932. }
  3933. DWORD
  3934. LoadPerfInstallPerfDll(
  3935. DWORD dwMode,
  3936. LPCWSTR szComputerName,
  3937. LPWSTR lpDriverName,
  3938. LPCWSTR lpIniFile,
  3939. PLANG_ENTRY pLanguages,
  3940. PSERVICE_ENTRY pService,
  3941. ULONG_PTR dwFlags
  3942. )
  3943. {
  3944. LPWSTR lp009IniFile = NULL;
  3945. LPWSTR lpInfPath = NULL;
  3946. DWORD dwObjectGuidTableSize = 0;
  3947. DWORD dwObjectIndex;
  3948. PLANGUAGE_LIST_ELEMENT LangList = NULL;
  3949. PLANGUAGE_LIST_ELEMENT pThisElem = NULL;
  3950. PSYMBOL_TABLE_ENTRY SymbolTable = NULL;
  3951. DWORD ErrorCode = ERROR_SUCCESS;
  3952. DWORD dwIndexValues[4] = {0,0,0,0};
  3953. HKEY hKeyMachine = HKEY_LOCAL_MACHINE;
  3954. HKEY hKeyDriver = NULL;
  3955. BOOL bResult = TRUE;
  3956. BOOL bQuietMode = (BOOL) ((dwFlags & LOADPERF_FLAGS_DISPLAY_USER_MSGS) == 0);
  3957. LPWSTR szServiceName = NULL;
  3958. LPWSTR szServiceDisplayName = NULL;
  3959. DWORD dwSize;
  3960. HRESULT hr;
  3961. if (lpDriverName == NULL) {
  3962. ErrorCode = ERROR_BAD_DRIVER;
  3963. goto EndOfMain;
  3964. }
  3965. else if (* lpDriverName == L'\0') {
  3966. ErrorCode = ERROR_BAD_DRIVER;
  3967. goto EndOfMain;
  3968. }
  3969. else if (dwMode & LODCTR_UPNF_NOINI) {
  3970. if (pLanguages == NULL || pService == NULL) {
  3971. ErrorCode = ERROR_INVALID_PARAMETER;
  3972. goto EndOfMain;
  3973. }
  3974. }
  3975. else if (dwMode & LODCTR_UPNF_NOBACKUP) {
  3976. if (lpIniFile == NULL) {
  3977. ErrorCode = ERROR_INVALID_PARAMETER;
  3978. goto EndOfMain;
  3979. }
  3980. else if (* lpIniFile == L'\0') {
  3981. ErrorCode = ERROR_INVALID_PARAMETER;
  3982. goto EndOfMain;
  3983. }
  3984. else {
  3985. lp009IniFile = MemoryAllocate((lstrlenW(lpIniFile) + 1) * sizeof(WCHAR));
  3986. if (lp009IniFile == NULL) {
  3987. ErrorCode = ERROR_OUTOFMEMORY;
  3988. goto EndOfMain;
  3989. }
  3990. hr = StringCchCopyW(lp009IniFile, lstrlenW(lpIniFile) + 1, lpIniFile);
  3991. }
  3992. }
  3993. else if (lpIniFile != NULL && lpIniFile[0] != L'\0') {
  3994. lpInfPath = LoadPerfGetInfPath();
  3995. if (lpInfPath == NULL) {
  3996. ErrorCode = GetLastError();
  3997. goto EndOfMain;
  3998. }
  3999. dwSize = lstrlenW(lpInfPath) + lstrlenW(DefaultLangId) + lstrlenW(Slash)
  4000. + lstrlenW(lpDriverName) + lstrlenW(Slash) + lstrlenW(lpIniFile) + 1;
  4001. if (dwSize < MAX_PATH) dwSize = MAX_PATH;
  4002. lp009IniFile = MemoryAllocate(dwSize * sizeof(WCHAR));
  4003. if (lp009IniFile == NULL) {
  4004. ErrorCode = ERROR_OUTOFMEMORY;
  4005. goto EndOfMain;
  4006. }
  4007. hr = StringCchPrintfW(lp009IniFile, dwSize, L"%ws%ws%ws%ws%ws%ws",
  4008. lpInfPath, DefaultLangId, Slash, lpDriverName, Slash, lpIniFile);
  4009. }
  4010. else { // lpIniFile == NULL
  4011. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_NO_INIFILE), lpIniFile);
  4012. ErrorCode = ERROR_OPEN_FAILED;
  4013. goto EndOfMain;
  4014. }
  4015. //
  4016. // Set the table size to the max first after we have passed the above
  4017. //
  4018. dwObjectGuidTableSize = MAX_GUID_TABLE_SIZE;
  4019. hKeyMachine = HKEY_LOCAL_MACHINE;
  4020. dwSize = lstrlenW(DriverPathRoot) + lstrlenW(Slash) + lstrlenW(lpDriverName) + 1;
  4021. if (dwSize < MAX_PATH) dwSize = MAX_PATH;
  4022. szServiceName = MemoryAllocate(2 * dwSize * sizeof(WCHAR));
  4023. if (szServiceName == NULL) {
  4024. ErrorCode = ERROR_OUTOFMEMORY;
  4025. goto EndOfMain;
  4026. }
  4027. szServiceDisplayName = szServiceName + dwSize;
  4028. hr = StringCchPrintfW(szServiceName, dwSize, L"%ws%ws%ws", DriverPathRoot, Slash, lpDriverName);
  4029. ErrorCode = RegOpenKeyExW(hKeyMachine, szServiceName, RESERVED, KEY_READ | KEY_WRITE, & hKeyDriver);
  4030. if (ErrorCode == ERROR_SUCCESS) {
  4031. DWORD dwType = 0;
  4032. DWORD dwBufferSize = dwSize * sizeof(WCHAR);
  4033. __try {
  4034. ErrorCode = RegQueryValueExW(hKeyDriver,
  4035. szDisplayName,
  4036. RESERVED,
  4037. & dwType,
  4038. (LPBYTE) szServiceDisplayName,
  4039. & dwBufferSize);
  4040. }
  4041. __except (EXCEPTION_EXECUTE_HANDLER) {
  4042. ErrorCode = GetExceptionCode();
  4043. }
  4044. }
  4045. if (ErrorCode != ERROR_SUCCESS) {
  4046. hr = StringCchCopyW(szServiceDisplayName, dwSize, lpDriverName);
  4047. }
  4048. if ((! (dwMode & LODCTR_UPNF_REPAIR)) && (hKeyDriver != NULL)) {
  4049. HKEY hKeyDriverPerf = NULL;
  4050. __try {
  4051. ErrorCode = RegOpenKeyExW(hKeyDriver, Performance, RESERVED, KEY_READ | KEY_WRITE, & hKeyDriverPerf);
  4052. }
  4053. __except(EXCEPTION_EXECUTE_HANDLER) {
  4054. ErrorCode = GetExceptionCode();
  4055. }
  4056. if (ErrorCode == ERROR_SUCCESS) {
  4057. LPWSTR szIniName = (LPWSTR) lpIniFile;
  4058. if (dwMode & LODCTR_UPNF_NOBACKUP) {
  4059. for (szIniName = (LPWSTR) lpIniFile + lstrlenW(lpIniFile) - 1;
  4060. szIniName != NULL && szIniName != lpIniFile
  4061. && (* szIniName) != cNull
  4062. && (* szIniName) != cBackslash;
  4063. szIniName --);
  4064. if (szIniName != NULL && (* szIniName) == cBackslash) {
  4065. szIniName ++;
  4066. }
  4067. else {
  4068. szIniName = (LPWSTR) lpIniFile;
  4069. }
  4070. }
  4071. __try {
  4072. ErrorCode = RegSetValueExW(hKeyDriverPerf,
  4073. szPerfIniPath,
  4074. RESERVED,
  4075. REG_SZ,
  4076. (LPBYTE) szIniName,
  4077. sizeof(WCHAR) * lstrlenW(lpIniFile));
  4078. }
  4079. __except(EXCEPTION_EXECUTE_HANDLER) {
  4080. ErrorCode = GetExceptionCode();
  4081. }
  4082. TRACE((WINPERF_DBG_TRACE_ERROR),
  4083. (& LoadPerfGuid,
  4084. __LINE__,
  4085. LOADPERF_INSTALLPERFDLL,
  4086. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2)
  4087. | ARG_DEF(ARG_TYPE_WSTR, 3),
  4088. ErrorCode,
  4089. TRACE_WSTR(lpIniFile),
  4090. TRACE_WSTR(lp009IniFile),
  4091. TRACE_WSTR(szIniName),
  4092. NULL));
  4093. RegCloseKey(hKeyDriverPerf);
  4094. }
  4095. }
  4096. if (hKeyDriver != NULL && hKeyDriver != HKEY_LOCAL_MACHINE) {
  4097. RegCloseKey(hKeyDriver);
  4098. }
  4099. if (hKeyMachine != NULL && hKeyMachine != HKEY_LOCAL_MACHINE) {
  4100. RegCloseKey(hKeyMachine);
  4101. }
  4102. ErrorCode = ERROR_SUCCESS;
  4103. if (dwMode & LODCTR_UPNF_NOINI) {
  4104. PLANG_ENTRY pThisLang = pLanguages;
  4105. while (pThisLang != NULL) {
  4106. // This is to build LangList. UpdateRegistry() takes LangList as a parameter and uses it.
  4107. // Memory will be freed at the end of LoadPerfInstallPerfDll().
  4108. //
  4109. pThisElem = MemoryAllocate(sizeof(LANGUAGE_LIST_ELEMENT)
  4110. + sizeof(WCHAR) * (lstrlenW(pThisLang->szLang) + 1));
  4111. if (pThisElem == NULL) {
  4112. ErrorCode = ERROR_OUTOFMEMORY;
  4113. goto EndOfMain;
  4114. }
  4115. pThisElem->pNextLang = LangList;
  4116. LangList = pThisElem;
  4117. pThisElem->LangId = (LPWSTR)
  4118. (((LPBYTE) pThisElem) + sizeof(LANGUAGE_LIST_ELEMENT));
  4119. hr = StringCchCopyW(pThisElem->LangId, lstrlenW(pThisLang->szLang) + 1, pThisLang->szLang);
  4120. pThisElem->dwLangId = LoadPerfGetLCIDFromString(pThisElem->LangId);
  4121. pThisElem->pFirstName = NULL;
  4122. pThisElem->pThisName = NULL;
  4123. pThisElem->dwNumElements = 0;
  4124. pThisElem->NameBuffer = NULL;
  4125. pThisElem->HelpBuffer = NULL;
  4126. pThisElem->dwNameBuffSize = 0;
  4127. pThisElem->dwHelpBuffSize = 0;
  4128. pThisLang = pThisLang->pNext;
  4129. }
  4130. }
  4131. else {
  4132. bResult = BuildLanguageTables(dwMode, (LPWSTR) lpIniFile, lpDriverName, & LangList);
  4133. dwSize = bResult ? 1 : 0;
  4134. TRACE((WINPERF_DBG_TRACE_ERROR),
  4135. (& LoadPerfGuid,
  4136. __LINE__,
  4137. LOADPERF_INSTALLPERFDLL,
  4138. ARG_DEF(ARG_TYPE_WSTR, 1),
  4139. GetLastError(),
  4140. TRACE_WSTR(lpIniFile),
  4141. TRACE_DWORD(dwSize),
  4142. NULL));
  4143. if (! bResult) {
  4144. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_LANGLIST_ERR), lpIniFile);
  4145. ErrorCode = GetLastError();
  4146. goto EndOfMain;
  4147. }
  4148. bResult = LoadIncludeFile(bQuietMode, dwMode, (LPWSTR) lp009IniFile, lpDriverName, & SymbolTable);
  4149. dwSize = bResult ? 1 : 0;
  4150. TRACE((WINPERF_DBG_TRACE_ERROR),
  4151. (& LoadPerfGuid,
  4152. __LINE__,
  4153. LOADPERF_INSTALLPERFDLL,
  4154. ARG_DEF(ARG_TYPE_WSTR, 1),
  4155. GetLastError(),
  4156. TRACE_WSTR(lp009IniFile),
  4157. TRACE_DWORD(dwSize),
  4158. NULL));
  4159. if (! bResult) {
  4160. // open errors displayed in routine
  4161. ErrorCode = GetLastError();
  4162. goto EndOfMain;
  4163. }
  4164. }
  4165. if (LangList != NULL) {
  4166. bResult = UpdateRegistry(bQuietMode,
  4167. dwMode,
  4168. lpDriverName,
  4169. (LPWSTR) lpIniFile,
  4170. lp009IniFile,
  4171. pLanguages,
  4172. pService,
  4173. LangList,
  4174. SymbolTable,
  4175. & dwObjectGuidTableSize,
  4176. (LPDWORD) dwIndexValues);
  4177. dwSize = bResult ? 1 : 0;
  4178. TRACE((WINPERF_DBG_TRACE_ERROR),
  4179. (& LoadPerfGuid,
  4180. __LINE__,
  4181. LOADPERF_LOADINCLUDEFILE,
  4182. ARG_DEF(ARG_TYPE_WSTR, 1),
  4183. GetLastError(),
  4184. TRACE_WSTR(lpIniFile),
  4185. TRACE_DWORD(dwSize),
  4186. NULL));
  4187. if (! bResult) {
  4188. ErrorCode = GetLastError();
  4189. goto EndOfMain;
  4190. }
  4191. }
  4192. else {
  4193. bResult = FALSE;
  4194. ErrorCode = ERROR_INVALID_DATA;
  4195. goto EndOfMain;
  4196. }
  4197. LodctrSetSericeAsTrusted(lp009IniFile, NULL, lpDriverName);
  4198. // signal WMI with this change, ignore WMI return error.
  4199. LoadPerfSignalWmiWithNewData (WMI_LODCTR_EVENT);
  4200. EndOfMain:
  4201. if ((dwMode & LODCTR_UPNF_REPAIR) == 0) {
  4202. if (ErrorCode != ERROR_SUCCESS) {
  4203. if (ErrorCode == ERROR_ALREADY_EXISTS) {
  4204. ReportLoadPerfEvent(
  4205. EVENTLOG_INFORMATION_TYPE, // error type
  4206. (DWORD) LDPRFMSG_ALREADY_EXIST, // event,
  4207. 1, __LINE__, 0, 0, 0,
  4208. 2, (LPWSTR) lpDriverName, (LPWSTR) szServiceDisplayName, NULL);
  4209. ErrorCode = ERROR_SUCCESS;
  4210. }
  4211. else if (lpDriverName != NULL) {
  4212. ReportLoadPerfEvent(
  4213. EVENTLOG_ERROR_TYPE, // error type
  4214. (DWORD) LDPRFMSG_LOAD_FAILURE, // event,
  4215. 2, ErrorCode, __LINE__, 0, 0,
  4216. 2, (LPWSTR) lpDriverName, (szServiceDisplayName != NULL) ? (szServiceDisplayName) : (lpDriverName), NULL);
  4217. }
  4218. else if (lpIniFile != NULL) {
  4219. ReportLoadPerfEvent(
  4220. EVENTLOG_ERROR_TYPE, // error type
  4221. (DWORD) LDPRFMSG_LOAD_FAILURE, // event,
  4222. 2, ErrorCode, __LINE__, 0, 0,
  4223. 2, (LPWSTR) lpIniFile, (LPWSTR) lpIniFile, NULL);
  4224. }
  4225. else {
  4226. ReportLoadPerfEvent(
  4227. EVENTLOG_ERROR_TYPE, // error type
  4228. (DWORD) LDPRFMSG_LOAD_FAILURE, // event,
  4229. 2, ErrorCode, __LINE__, 0, 0,
  4230. 0, NULL, NULL, NULL);
  4231. }
  4232. }
  4233. else {
  4234. // log success message
  4235. ReportLoadPerfEvent(
  4236. EVENTLOG_INFORMATION_TYPE, // error type
  4237. (DWORD) LDPRFMSG_LOAD_SUCCESS, // event,
  4238. 4, dwIndexValues[0], dwIndexValues[1], dwIndexValues[2], dwIndexValues[3],
  4239. 2, (LPWSTR) lpDriverName, (LPWSTR) szServiceDisplayName, NULL);
  4240. }
  4241. }
  4242. else if (ErrorCode != ERROR_SUCCESS) {
  4243. ReportLoadPerfEvent(
  4244. EVENTLOG_ERROR_TYPE, // error type
  4245. (DWORD) LDPRFMSG_LOAD_FAILURE, // event,
  4246. 2, ErrorCode, __LINE__, 0, 0,
  4247. 1, (LPWSTR) lpDriverName, (szServiceDisplayName != NULL) ? (szServiceDisplayName) : (lpDriverName), NULL);
  4248. }
  4249. TRACE((WINPERF_DBG_TRACE_INFO),
  4250. (& LoadPerfGuid,
  4251. __LINE__,
  4252. LOADPERF_INSTALLPERFDLL,
  4253. ARG_DEF(ARG_TYPE_WSTR, 1),
  4254. ErrorCode,
  4255. TRACE_WSTR(lpDriverName),
  4256. NULL));
  4257. while (LangList != NULL) {
  4258. PLANGUAGE_LIST_ELEMENT pTmpLang = LangList;
  4259. PNAME_ENTRY pThisName = pTmpLang->pFirstName;
  4260. while (pThisName != NULL) {
  4261. PNAME_ENTRY pTmpName = pThisName;
  4262. pThisName = pTmpName->pNext;
  4263. MemoryFree(pTmpName);
  4264. }
  4265. MemoryFree(pTmpLang->NameBuffer);
  4266. MemoryFree(pTmpLang->HelpBuffer);
  4267. LangList = LangList->pNextLang;
  4268. MemoryFree(pTmpLang);
  4269. }
  4270. while (SymbolTable != NULL) {
  4271. PSYMBOL_TABLE_ENTRY pThisSym = SymbolTable;
  4272. SymbolTable = pThisSym->pNext;
  4273. MemoryFree(pThisSym->SymbolName);
  4274. MemoryFree(pThisSym);
  4275. }
  4276. MemoryFree(lp009IniFile);
  4277. MemoryFree(szServiceName);
  4278. return (ErrorCode);
  4279. }
  4280. LOADPERF_FUNCTION
  4281. InstallPerfDllW(
  4282. IN LPCWSTR szComputerName,
  4283. IN LPCWSTR lpIniFile,
  4284. IN ULONG_PTR dwFlags
  4285. )
  4286. {
  4287. DWORD lStatus = ERROR_SUCCESS;
  4288. LPWSTR szIniName = NULL;
  4289. LPWSTR szDriverName = NULL;
  4290. DWORD dwMode = 0;
  4291. DBG_UNREFERENCED_PARAMETER(szComputerName);
  4292. WinPerfStartTrace(NULL);
  4293. if (LoadPerfGrabMutex() == FALSE) {
  4294. return GetLastError();
  4295. }
  4296. if (lpIniFile == NULL) {
  4297. lStatus = ERROR_INVALID_PARAMETER;
  4298. }
  4299. else {
  4300. __try {
  4301. DWORD dwName = lstrlenW(lpIniFile);
  4302. if (dwName == 0) lStatus = ERROR_INVALID_PARAMETER;
  4303. }
  4304. __except(EXCEPTION_EXECUTE_HANDLER) {
  4305. lStatus = ERROR_INVALID_PARAMETER;
  4306. }
  4307. }
  4308. if (lStatus == ERROR_SUCCESS) {
  4309. TRACE((WINPERF_DBG_TRACE_INFO),
  4310. (& LoadPerfGuid,
  4311. __LINE__,
  4312. LOADPERF_INSTALLPERFDLL,
  4313. ARG_DEF(ARG_TYPE_WSTR, 1),
  4314. ERROR_SUCCESS,
  4315. TRACE_WSTR(lpIniFile),
  4316. NULL));
  4317. #if 0
  4318. if (LoadPerfBackupIniFile(lpIniFile, NULL, & szIniName, & szDriverName, TRUE) == FALSE) {
  4319. dwMode |= LODCTR_UPNF_NOBACKUP;
  4320. MemoryFree(szIniName);
  4321. szIniName = (LPWSTR) lpIniFile;
  4322. }
  4323. #else
  4324. // ignore LoadPerfBackupIniFile return code and use input .INI and .H files instead.
  4325. //
  4326. LoadPerfBackupIniFile(lpIniFile, NULL, & szIniName, & szDriverName, TRUE);
  4327. dwMode |= LODCTR_UPNF_NOBACKUP;
  4328. MemoryFree(szIniName);
  4329. szIniName = (LPWSTR) lpIniFile;
  4330. #endif
  4331. // Ignore szComputerName parameter. LOADPERF can only update local performance registry.
  4332. // No remote installation support.
  4333. //
  4334. lStatus = LoadPerfInstallPerfDll(dwMode, NULL, szDriverName, szIniName, NULL, NULL, dwFlags);
  4335. if (szIniName != lpIniFile) MemoryFree(szIniName);
  4336. MemoryFree(szDriverName);
  4337. }
  4338. ReleaseMutex(hLoadPerfMutex);
  4339. return lStatus;
  4340. }
  4341. LOADPERF_FUNCTION
  4342. InstallPerfDllA(
  4343. IN LPCSTR szComputerName,
  4344. IN LPCSTR szIniFile,
  4345. IN ULONG_PTR dwFlags
  4346. )
  4347. {
  4348. LPWSTR lpWideFileName = NULL;
  4349. DWORD lReturn = ERROR_SUCCESS;
  4350. DBG_UNREFERENCED_PARAMETER(szComputerName);
  4351. if (szIniFile != NULL) {
  4352. __try {
  4353. lpWideFileName = LoadPerfMultiByteToWideChar(CP_ACP, (LPSTR) szIniFile);
  4354. if (lpWideFileName == NULL) {
  4355. lReturn = ERROR_OUTOFMEMORY;
  4356. }
  4357. }
  4358. __except(EXCEPTION_EXECUTE_HANDLER) {
  4359. lReturn = ERROR_INVALID_PARAMETER;
  4360. }
  4361. }
  4362. else {
  4363. lReturn = ERROR_INVALID_PARAMETER;
  4364. }
  4365. if (lReturn == ERROR_SUCCESS) {
  4366. // Ignore szComputerName parameter. LOADPERF can only update local performance registry.
  4367. // No remote installation support.
  4368. //
  4369. lReturn = InstallPerfDllW(NULL, lpWideFileName, dwFlags);
  4370. }
  4371. MemoryFree(lpWideFileName);
  4372. return lReturn;
  4373. }
  4374. LOADPERF_FUNCTION
  4375. LoadPerfCounterTextStringsW(
  4376. IN LPWSTR lpCommandLine,
  4377. IN BOOL bQuietMode
  4378. )
  4379. /*++
  4380. LoadPerfCounterTexStringsW
  4381. loads the perf counter strings into the registry and updates
  4382. the perf counter text registry values
  4383. Arguments
  4384. command line string in the following format:
  4385. "/?" displays the usage text
  4386. "file.ini" loads the perf strings found in file.ini
  4387. "\\machine file.ini" loads the perf strings found onto machine
  4388. ReturnValue
  4389. 0 (ERROR_SUCCESS) if command was processed
  4390. Non-Zero if command error was detected.
  4391. --*/
  4392. {
  4393. LPWSTR lpIniFile = NULL;
  4394. DWORD ErrorCode = ERROR_SUCCESS;
  4395. ULONG_PTR dwFlags = 0;
  4396. WinPerfStartTrace(NULL);
  4397. if (lpCommandLine == NULL) {
  4398. ErrorCode = ERROR_INVALID_PARAMETER;
  4399. }
  4400. else {
  4401. __try {
  4402. DWORD dwSize = lstrlenW(lpCommandLine);
  4403. if (dwSize == 0) ErrorCode = ERROR_INVALID_PARAMETER;
  4404. }
  4405. __except(EXCEPTION_EXECUTE_HANDLER) {
  4406. ErrorCode = ERROR_INVALID_PARAMETER;
  4407. }
  4408. }
  4409. if (ErrorCode != ERROR_SUCCESS) goto Cleanup;
  4410. dwFlags |= (bQuietMode ? 0 : LOADPERF_FLAGS_DISPLAY_USER_MSGS);
  4411. lpIniFile = MemoryAllocate(MAX_PATH * sizeof(WCHAR));
  4412. if (lpIniFile == NULL) {
  4413. ErrorCode = ERROR_OUTOFMEMORY;
  4414. goto Cleanup;
  4415. }
  4416. // init last error value
  4417. SetLastError(ERROR_SUCCESS);
  4418. // read command line to determine what to do
  4419. if (GetFileFromCommandLine(lpCommandLine, & lpIniFile, MAX_PATH, & dwFlags)) {
  4420. dwFlags |= LOADPERF_FLAGS_LOAD_REGISTRY_ONLY; // don't do mof's even if they want
  4421. // call installation function
  4422. // LOADPERF can only update local performance registry. No remote installation support.
  4423. //
  4424. ErrorCode = InstallPerfDllW(NULL, lpIniFile, dwFlags);
  4425. }
  4426. else {
  4427. DWORD dwError = GetLastError();
  4428. if (dwError == ERROR_OPEN_FAILED) {
  4429. OUTPUT_MESSAGE(bQuietMode, GetFormatResource(LC_NO_INIFILE), lpIniFile);
  4430. }
  4431. else {
  4432. //Incorrect Command Format
  4433. // display command line usage
  4434. if (! bQuietMode) {
  4435. DisplayCommandHelp(LC_FIRST_CMD_HELP, LC_LAST_CMD_HELP);
  4436. }
  4437. }
  4438. ErrorCode = ERROR_INVALID_PARAMETER;
  4439. }
  4440. Cleanup:
  4441. MemoryFree(lpIniFile);
  4442. return (ErrorCode);
  4443. }
  4444. LOADPERF_FUNCTION
  4445. LoadPerfCounterTextStringsA(
  4446. IN LPSTR lpAnsiCommandLine,
  4447. IN BOOL bQuietMode
  4448. )
  4449. {
  4450. LPWSTR lpWideCommandLine = NULL;
  4451. DWORD lReturn = ERROR_SUCCESS;
  4452. if (lpAnsiCommandLine == NULL) {
  4453. lReturn = ERROR_INVALID_PARAMETER;
  4454. }
  4455. else {
  4456. __try {
  4457. DWORD dwSize = lstrlenA(lpAnsiCommandLine);
  4458. if (dwSize == 0) {
  4459. lReturn = ERROR_INVALID_PARAMETER;
  4460. }
  4461. else {
  4462. lpWideCommandLine = LoadPerfMultiByteToWideChar(CP_ACP, lpAnsiCommandLine);
  4463. if (lpWideCommandLine == NULL) lReturn = ERROR_OUTOFMEMORY;
  4464. }
  4465. }
  4466. __except(EXCEPTION_EXECUTE_HANDLER) {
  4467. lReturn = ERROR_INVALID_PARAMETER;
  4468. }
  4469. }
  4470. if (lReturn == ERROR_SUCCESS) {
  4471. lReturn = LoadPerfCounterTextStringsW(lpWideCommandLine, bQuietMode);
  4472. }
  4473. MemoryFree(lpWideCommandLine);
  4474. return lReturn;
  4475. }
  4476. LOADPERF_FUNCTION
  4477. UpdatePerfNameFilesX(
  4478. LPCWSTR szNewCtrFilePath, // data file with new base counter strings
  4479. LPCWSTR szNewHlpFilePath, // data file with new base counter strings
  4480. LPWSTR szLanguageID, // Lang ID to update
  4481. ULONG_PTR dwFlags // flags
  4482. )
  4483. {
  4484. DWORD dwReturn = ERROR_SUCCESS;
  4485. LPWSTR szCtrNameIn = NULL;
  4486. LPWSTR szHlpNameIn = NULL;
  4487. BOOL bAllocCtrString = FALSE;
  4488. LPWSTR szNewCtrStrings = NULL;
  4489. LPWSTR szNewHlpStrings = NULL;
  4490. LPWSTR szNewCtrMSZ = NULL;
  4491. LPWSTR szNewHlpMSZ = NULL;
  4492. DWORD dwLength = 0;
  4493. LPWSTR * pszNewNameTable = NULL;
  4494. LPWSTR * pszOldNameTable = NULL;
  4495. LPWSTR lpThisName;
  4496. LPWSTR szThisCtrString = NULL;
  4497. LPWSTR szThisHlpString = NULL;
  4498. LPWSTR szLangSection = NULL;
  4499. DWORD dwOldLastEntry = 0;
  4500. DWORD dwNewLastEntry = 0;
  4501. DWORD dwStringSize;
  4502. DWORD dwHlpFileSize = 0;
  4503. DWORD dwCtrFileSize = 0;
  4504. DWORD dwThisCounter;
  4505. DWORD dwSize;
  4506. DWORD dwLastBaseValue = 0;
  4507. DWORD dwType;
  4508. DWORD dwIndex;
  4509. HANDLE hCtrFileIn = INVALID_HANDLE_VALUE;
  4510. HANDLE hCtrFileMap = NULL;
  4511. HANDLE hHlpFileIn = INVALID_HANDLE_VALUE;
  4512. HANDLE hHlpFileMap = NULL;
  4513. HKEY hKeyPerflib;
  4514. HRESULT hr;
  4515. WinPerfStartTrace(NULL);
  4516. if (LoadPerfGrabMutex() == FALSE) {
  4517. return GetLastError();
  4518. }
  4519. if ((! (dwFlags & LODCTR_UPNF_RESTORE)) && (! (dwFlags & LODCTR_UPNF_REPAIR))) {
  4520. if (LoadPerfBackupIniFile(szNewCtrFilePath, szLanguageID, NULL, NULL, FALSE) == FALSE) {
  4521. dwReturn = ERROR_INVALID_PARAMETER;
  4522. }
  4523. if (LoadPerfBackupIniFile(szNewHlpFilePath, szLanguageID, NULL, NULL, FALSE) == FALSE) {
  4524. dwReturn = ERROR_INVALID_PARAMETER;
  4525. }
  4526. }
  4527. if (szNewCtrFilePath == NULL) dwReturn = ERROR_INVALID_PARAMETER;
  4528. if ((szNewHlpFilePath == NULL) && !(dwFlags & LODCTR_UPNF_RESTORE)) dwReturn = ERROR_INVALID_PARAMETER;
  4529. if (szLanguageID == NULL) dwReturn = ERROR_INVALID_PARAMETER;
  4530. if (dwReturn == ERROR_SUCCESS) {
  4531. TRACE((WINPERF_DBG_TRACE_INFO),
  4532. (& LoadPerfGuid,
  4533. __LINE__,
  4534. LOADPERF_UPDATEPERFNAMEFILES,
  4535. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  4536. ERROR_SUCCESS,
  4537. TRACE_WSTR(szNewCtrFilePath),
  4538. TRACE_WSTR(szLanguageID),
  4539. NULL));
  4540. }
  4541. if ((dwReturn == ERROR_SUCCESS) && ! (dwFlags & LODCTR_UPNF_RESTORE)) {
  4542. if (dwFlags & LODCTR_UPNF_REPAIR) {
  4543. dwLength = lstrlenW(szNewCtrFilePath);
  4544. }
  4545. else {
  4546. // save the original files, unless it's a restoration
  4547. MakeBackupCopyOfLanguageFiles(szLanguageID);
  4548. dwLength = lstrlenW(szNewCtrFilePath);
  4549. if (dwLength > 0) dwLength = lstrlenW(szNewHlpFilePath);
  4550. }
  4551. }
  4552. else {
  4553. dwLength = 0;
  4554. SetLastError(dwReturn);
  4555. }
  4556. if (dwLength > 0) {
  4557. // create input filenames
  4558. dwSize = lstrlenW(szNewCtrFilePath) + lstrlenW(szNewHlpFilePath) + 1;
  4559. if (dwSize < MAX_PATH) dwSize = MAX_PATH;
  4560. szCtrNameIn = MemoryAllocate(dwSize * sizeof(WCHAR));
  4561. szHlpNameIn = MemoryAllocate(dwSize * sizeof(WCHAR));
  4562. if (szCtrNameIn != NULL && szHlpNameIn != NULL) {
  4563. if (! (dwFlags & LODCTR_UPNF_REPAIR)) {
  4564. DWORD dwTmp = dwSize;
  4565. dwReturn = ERROR_SUCCESS;
  4566. dwLength = ExpandEnvironmentStringsW(szNewCtrFilePath, szCtrNameIn, dwSize);
  4567. while (dwReturn == ERROR_SUCCESS && dwLength > dwSize) {
  4568. dwSize = dwLength;
  4569. MemoryFree(szCtrNameIn);
  4570. szCtrNameIn = MemoryAllocate(dwLength * sizeof(WCHAR));
  4571. if (szCtrNameIn == NULL) {
  4572. dwReturn = ERROR_OUTOFMEMORY;
  4573. }
  4574. else {
  4575. dwLength = ExpandEnvironmentStringsW(szNewCtrFilePath, szCtrNameIn, dwSize);
  4576. }
  4577. }
  4578. if (dwReturn == ERROR_SUCCESS) {
  4579. dwSize = dwTmp;
  4580. dwLength = ExpandEnvironmentStringsW(szNewHlpFilePath, szHlpNameIn, dwSize);
  4581. while (dwReturn == ERROR_SUCCESS && dwLength > dwSize) {
  4582. dwSize = dwLength;
  4583. MemoryFree(szHlpNameIn);
  4584. szHlpNameIn = MemoryAllocate(dwLength * sizeof(WCHAR));
  4585. if (szHlpNameIn == NULL) {
  4586. dwReturn = ERROR_OUTOFMEMORY;
  4587. }
  4588. else {
  4589. dwLength = ExpandEnvironmentStringsW(szNewHlpFilePath, szHlpNameIn, dwSize);
  4590. }
  4591. }
  4592. }
  4593. }
  4594. else {
  4595. hr = StringCchCopyW(szCtrNameIn, dwSize, szNewCtrFilePath);
  4596. hr = StringCchCopyW(szHlpNameIn, dwSize, szNewHlpFilePath);
  4597. }
  4598. }
  4599. else {
  4600. dwReturn = ERROR_OUTOFMEMORY;
  4601. }
  4602. if (dwReturn == ERROR_SUCCESS) {
  4603. // open and map new files
  4604. hCtrFileIn = CreateFileW(szCtrNameIn,
  4605. GENERIC_READ,
  4606. FILE_SHARE_READ,
  4607. NULL,
  4608. OPEN_EXISTING,
  4609. FILE_ATTRIBUTE_NORMAL,
  4610. NULL);
  4611. if (hCtrFileIn != INVALID_HANDLE_VALUE) {
  4612. // map file
  4613. dwCtrFileSize = GetFileSize(hCtrFileIn, NULL);
  4614. if (dwCtrFileSize == 0xFFFFFFFF){
  4615. dwReturn =GetLastError();
  4616. }
  4617. else {
  4618. hCtrFileMap = CreateFileMappingW(hCtrFileIn, NULL, PAGE_READONLY, 0, 0, NULL);
  4619. if (hCtrFileMap != NULL) {
  4620. szNewCtrStrings = (LPWSTR) MapViewOfFileEx(hCtrFileMap, FILE_MAP_READ, 0, 0, 0, NULL);
  4621. if (szNewCtrStrings == NULL) {
  4622. dwReturn = GetLastError();
  4623. }
  4624. }
  4625. else {
  4626. dwReturn = GetLastError();
  4627. }
  4628. }
  4629. }
  4630. else {
  4631. dwReturn = GetLastError();
  4632. }
  4633. }
  4634. if (dwReturn == ERROR_SUCCESS) {
  4635. // open and map new files
  4636. hHlpFileIn = CreateFileW(szHlpNameIn,
  4637. GENERIC_READ,
  4638. FILE_SHARE_READ,
  4639. NULL,
  4640. OPEN_EXISTING,
  4641. FILE_ATTRIBUTE_NORMAL,
  4642. NULL);
  4643. if (hHlpFileIn != INVALID_HANDLE_VALUE) {
  4644. // map file
  4645. dwHlpFileSize = GetFileSize(hHlpFileIn, NULL);
  4646. if (dwHlpFileSize == 0xFFFFFFFF){
  4647. dwReturn = GetLastError();
  4648. }
  4649. else {
  4650. hHlpFileMap = CreateFileMappingW(hHlpFileIn, NULL, PAGE_READONLY, 0, 0, NULL);
  4651. if (hHlpFileMap != NULL) {
  4652. szNewHlpStrings = (LPWSTR)MapViewOfFileEx(hHlpFileMap, FILE_MAP_READ, 0, 0, 0, NULL);
  4653. if (szNewHlpStrings == NULL) {
  4654. dwReturn = GetLastError();
  4655. }
  4656. }
  4657. else {
  4658. dwReturn = GetLastError();
  4659. }
  4660. }
  4661. }
  4662. else {
  4663. dwReturn = GetLastError();
  4664. }
  4665. }
  4666. }
  4667. else if (dwFlags & LODCTR_UPNF_RESTORE) {
  4668. dwSize = lstrlenW(szNewCtrFilePath) + 1;
  4669. if (dwSize < MAX_PATH) dwSize = MAX_PATH;
  4670. szCtrNameIn = MemoryAllocate(dwSize * sizeof (WCHAR));
  4671. if (szCtrNameIn != NULL) {
  4672. dwReturn = ERROR_SUCCESS;
  4673. dwLength = ExpandEnvironmentStringsW(szNewCtrFilePath, szCtrNameIn, dwSize);
  4674. while (dwReturn == ERROR_SUCCESS && dwLength > dwSize) {
  4675. dwSize = dwLength;
  4676. MemoryFree(szCtrNameIn);
  4677. szCtrNameIn = MemoryAllocate(dwLength * sizeof(WCHAR));
  4678. if (szCtrNameIn == NULL) {
  4679. dwReturn = ERROR_OUTOFMEMORY;
  4680. }
  4681. else {
  4682. dwLength = ExpandEnvironmentStringsW(szNewCtrFilePath, szCtrNameIn, dwSize);
  4683. }
  4684. }
  4685. }
  4686. if (szCtrNameIn != NULL) {
  4687. dwNewLastEntry = GetPrivateProfileIntW((LPCWSTR) L"Perflib", (LPCWSTR) L"Last Help", -1, szCtrNameIn);
  4688. if (dwNewLastEntry != (DWORD) -1) {
  4689. // get the input file size
  4690. hCtrFileIn = CreateFileW(szCtrNameIn,
  4691. GENERIC_READ,
  4692. FILE_SHARE_READ,
  4693. NULL,
  4694. OPEN_EXISTING,
  4695. FILE_ATTRIBUTE_NORMAL,
  4696. NULL);
  4697. if (hCtrFileIn != INVALID_HANDLE_VALUE) {
  4698. // map file
  4699. dwCtrFileSize = GetFileSize(hCtrFileIn, NULL);
  4700. }
  4701. else {
  4702. dwCtrFileSize = 64 * LOADPERF_BUFF_SIZE; // assign 64k if unable to read it
  4703. }
  4704. // load new values from ini file
  4705. bAllocCtrString = TRUE;
  4706. szNewCtrStrings = (LPWSTR) MemoryAllocate(dwCtrFileSize * sizeof(WCHAR));
  4707. if (szNewCtrStrings) {
  4708. dwLength = lstrlenW(szLanguageID) + 16;
  4709. szLangSection = MemoryAllocate(dwLength * sizeof(WCHAR));
  4710. if (szLangSection == NULL) {
  4711. dwReturn = ERROR_OUTOFMEMORY;
  4712. }
  4713. else {
  4714. hr = StringCchPrintfW(szLangSection, dwLength, L"Perfstrings_%ws", szLanguageID);
  4715. dwSize = GetPrivateProfileSectionW(szLangSection,
  4716. szNewCtrStrings,
  4717. dwCtrFileSize,
  4718. szCtrNameIn);
  4719. if (dwSize == 0) {
  4720. hr = StringCchCopyW(szLangSection, dwLength, (LPCWSTR) L"Perfstrings_009");
  4721. dwSize = GetPrivateProfileSectionW(szLangSection,
  4722. szNewCtrStrings,
  4723. dwCtrFileSize,
  4724. szCtrNameIn);
  4725. }
  4726. if (dwSize == 0) {
  4727. dwReturn = ERROR_FILE_INVALID;
  4728. }
  4729. else {
  4730. // set file sizes
  4731. dwHlpFileSize = 0;
  4732. dwCtrFileSize = (dwSize + 2) * sizeof(WCHAR);
  4733. }
  4734. }
  4735. }
  4736. else {
  4737. dwReturn = ERROR_OUTOFMEMORY;
  4738. }
  4739. }
  4740. else {
  4741. // unable to open input file or file is invalid
  4742. dwReturn = ERROR_FILE_INVALID;
  4743. }
  4744. }
  4745. else if (dwReturn == ERROR_SUCCESS) {
  4746. dwReturn = ERROR_OUTOFMEMORY;
  4747. }
  4748. }
  4749. if ((dwReturn == ERROR_SUCCESS) && (! (dwFlags & LODCTR_UPNF_RESTORE))) {
  4750. if (! (dwFlags & LODCTR_UPNF_REPAIR)) {
  4751. // build name table of current strings
  4752. pszOldNameTable = BuildNameTable(HKEY_LOCAL_MACHINE, szLanguageID, & dwOldLastEntry);
  4753. if (pszOldNameTable == NULL) {
  4754. dwReturn = GetLastError();
  4755. }
  4756. }
  4757. else {
  4758. dwOldLastEntry = 0;
  4759. }
  4760. dwNewLastEntry = (dwOldLastEntry == 0) ? (PERFLIB_BASE_INDEX) : (dwOldLastEntry);
  4761. }
  4762. else if (dwFlags & LODCTR_UPNF_RESTORE) {
  4763. dwOldLastEntry = dwNewLastEntry;
  4764. }
  4765. if (dwReturn == ERROR_SUCCESS) {
  4766. // build name table of new strings
  4767. pszNewNameTable = (LPWSTR *) MemoryAllocate((dwNewLastEntry + 2) * sizeof(LPWSTR));// allow for index offset
  4768. if (pszNewNameTable != NULL) {
  4769. for (lpThisName = szNewCtrStrings; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1)) {
  4770. // first string should be an integer (in decimal unicode digits)
  4771. dwThisCounter = wcstoul(lpThisName, NULL, 10);
  4772. if (dwThisCounter == 0 || dwThisCounter > dwNewLastEntry) {
  4773. ReportLoadPerfEvent(
  4774. EVENTLOG_WARNING_TYPE, // error type
  4775. (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT, // event,
  4776. 4, dwThisCounter, dwNewLastEntry, dwNewLastEntry, __LINE__,
  4777. 1, lpThisName, NULL, NULL);
  4778. TRACE((WINPERF_DBG_TRACE_ERROR),
  4779. (& LoadPerfGuid,
  4780. __LINE__,
  4781. LOADPERF_UPDATEPERFNAMEFILES,
  4782. ARG_DEF(ARG_TYPE_WSTR, 1),
  4783. ERROR_INVALID_DATA,
  4784. TRACE_WSTR(lpThisName),
  4785. TRACE_DWORD(dwThisCounter),
  4786. TRACE_DWORD(dwNewLastEntry),
  4787. NULL));
  4788. continue; // bad entry, try next
  4789. }
  4790. // point to corresponding counter name
  4791. if (dwFlags & LODCTR_UPNF_RESTORE) {
  4792. // point to string that follows the "=" char
  4793. lpThisName = wcschr(lpThisName, L'=');
  4794. if (lpThisName != NULL) {
  4795. lpThisName ++;
  4796. }
  4797. else {
  4798. continue;
  4799. }
  4800. }
  4801. else {
  4802. // string is next in MSZ
  4803. lpThisName += (lstrlenW(lpThisName) + 1);
  4804. }
  4805. // and load array element;
  4806. pszNewNameTable[dwThisCounter] = lpThisName;
  4807. }
  4808. if (dwReturn == ERROR_SUCCESS && (! (dwFlags & LODCTR_UPNF_RESTORE))) {
  4809. for (lpThisName = szNewHlpStrings; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1)) {
  4810. // first string should be an integer (in decimal unicode digits)
  4811. dwThisCounter = wcstoul(lpThisName, NULL, 10);
  4812. if (dwThisCounter == 0 || dwThisCounter > dwNewLastEntry) {
  4813. ReportLoadPerfEvent(
  4814. EVENTLOG_WARNING_TYPE, // error type
  4815. (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT, // event,
  4816. 4, dwThisCounter, dwNewLastEntry, dwNewLastEntry, __LINE__,
  4817. 1, lpThisName, NULL, NULL);
  4818. TRACE((WINPERF_DBG_TRACE_ERROR),
  4819. (& LoadPerfGuid,
  4820. __LINE__,
  4821. LOADPERF_UPDATEPERFNAMEFILES,
  4822. ARG_DEF(ARG_TYPE_WSTR, 1),
  4823. ERROR_INVALID_DATA,
  4824. TRACE_WSTR(lpThisName),
  4825. TRACE_DWORD(dwThisCounter),
  4826. TRACE_DWORD(dwNewLastEntry),
  4827. NULL));
  4828. continue; // bad entry, try next
  4829. }
  4830. // point to corresponding counter name
  4831. lpThisName += (lstrlenW(lpThisName) + 1);
  4832. // and load array element;
  4833. pszNewNameTable[dwThisCounter] = lpThisName;
  4834. }
  4835. }
  4836. if (dwReturn == ERROR_SUCCESS) {
  4837. // allocate string buffers for the resulting string
  4838. // we want to make sure there's plenty of room so we'll make it
  4839. // the size of the input file + the current buffer
  4840. dwStringSize = dwHlpFileSize;
  4841. dwStringSize += dwCtrFileSize;
  4842. if (pszOldNameTable != NULL) {
  4843. dwStringSize += MemorySize(pszOldNameTable);
  4844. }
  4845. szNewCtrMSZ = MemoryAllocate(dwStringSize * sizeof(WCHAR));
  4846. szNewHlpMSZ = MemoryAllocate(dwStringSize * sizeof(WCHAR));
  4847. if (szNewCtrMSZ == NULL || szNewHlpMSZ == NULL) {
  4848. dwReturn = ERROR_OUTOFMEMORY;
  4849. }
  4850. }
  4851. }
  4852. else {
  4853. dwReturn = ERROR_OUTOFMEMORY;
  4854. }
  4855. }
  4856. if (dwReturn == ERROR_SUCCESS) {
  4857. // write new strings into registry
  4858. __try {
  4859. dwReturn = RegOpenKeyExW(HKEY_LOCAL_MACHINE, NamesKey, RESERVED, KEY_READ, & hKeyPerflib);
  4860. }
  4861. __except (EXCEPTION_EXECUTE_HANDLER) {
  4862. dwReturn = GetExceptionCode();
  4863. }
  4864. dwSize = sizeof(dwLastBaseValue);
  4865. dwLastBaseValue = 0;
  4866. if (dwReturn == ERROR_SUCCESS) {
  4867. __try {
  4868. dwReturn = RegQueryValueExW(hKeyPerflib,
  4869. BaseIndex,
  4870. RESERVED,
  4871. & dwType,
  4872. (LPBYTE) & dwLastBaseValue,
  4873. & dwSize);
  4874. }
  4875. __except (EXCEPTION_EXECUTE_HANDLER) {
  4876. dwReturn = GetExceptionCode();
  4877. }
  4878. if (dwLastBaseValue == 0) {
  4879. dwReturn = ERROR_BADDB;
  4880. }
  4881. TRACE((WINPERF_DBG_TRACE_INFO),
  4882. (& LoadPerfGuid,
  4883. __LINE__,
  4884. LOADPERF_UPDATEPERFNAMEFILES,
  4885. ARG_DEF(ARG_TYPE_WSTR, 1),
  4886. dwReturn,
  4887. TRACE_WSTR(BaseIndex),
  4888. TRACE_DWORD(dwLastBaseValue),
  4889. NULL));
  4890. RegCloseKey(hKeyPerflib);
  4891. }
  4892. }
  4893. else {
  4894. TRACE((WINPERF_DBG_TRACE_ERROR),
  4895. (& LoadPerfGuid,
  4896. __LINE__,
  4897. LOADPERF_UPDATEPERFNAMEFILES,
  4898. ARG_DEF(ARG_TYPE_WSTR, 1),
  4899. dwReturn,
  4900. TRACE_WSTR(NamesKey),
  4901. NULL));
  4902. }
  4903. if (dwReturn == ERROR_SUCCESS) {
  4904. DWORD dwLoopLimit;
  4905. // the strings should be mapped by now
  4906. // pszNewNameTable contains the new strings from the
  4907. // source path and pszOldNameTable contains the strings
  4908. // from the original system. The merge will consist of
  4909. // taking all base values from the new table and the
  4910. // extended values from the old table.
  4911. dwIndex = 1;
  4912. szThisCtrString = szNewCtrMSZ;
  4913. szThisHlpString = szNewHlpMSZ;
  4914. dwCtrFileSize = dwStringSize;
  4915. dwHlpFileSize = dwStringSize;
  4916. // index 1 is a special case and belongs in the counter string
  4917. // after that even numbers (starting w/ #2) go into the counter string
  4918. // and odd numbers (starting w/ #3) go into the help string
  4919. hr = StringCchPrintfW(szThisCtrString, dwCtrFileSize, L"%d", dwIndex);
  4920. dwCtrFileSize -= (lstrlenW(szThisCtrString) + 1);
  4921. szThisCtrString += (lstrlenW(szThisCtrString) + 1);
  4922. hr = StringCchPrintfW(szThisCtrString, dwCtrFileSize, L"%ws", pszNewNameTable[dwIndex]);
  4923. dwCtrFileSize -= (lstrlenW(szThisCtrString) + 1);
  4924. szThisCtrString += (lstrlenW(szThisCtrString) + 1);
  4925. dwIndex ++;
  4926. if (dwFlags & LODCTR_UPNF_RESTORE) {
  4927. // restore ALL strings from the input file only if this
  4928. // is a restoration
  4929. dwLoopLimit = dwOldLastEntry;
  4930. }
  4931. else {
  4932. // only update the system counters from the input file
  4933. dwLoopLimit = dwLastBaseValue;
  4934. }
  4935. TRACE((WINPERF_DBG_TRACE_INFO),
  4936. (& LoadPerfGuid,
  4937. __LINE__,
  4938. LOADPERF_UPDATEPERFNAMEFILES,
  4939. 0,
  4940. ERROR_SUCCESS,
  4941. TRACE_DWORD(dwOldLastEntry),
  4942. TRACE_DWORD(dwLastBaseValue),
  4943. NULL));
  4944. for (/*dwIndex from above*/; dwIndex <= dwLoopLimit; dwIndex++) {
  4945. if (pszNewNameTable[dwIndex] != NULL) {
  4946. TRACE((WINPERF_DBG_TRACE_INFO),
  4947. (& LoadPerfGuid,
  4948. __LINE__,
  4949. LOADPERF_UPDATEPERFNAMEFILES,
  4950. ARG_DEF(ARG_TYPE_WSTR, 1),
  4951. ERROR_SUCCESS,
  4952. TRACE_WSTR(pszNewNameTable[dwIndex]),
  4953. TRACE_DWORD(dwIndex),
  4954. NULL));
  4955. if (dwIndex & 0x01) {
  4956. // then it's a help string
  4957. hr = StringCchPrintfW(szThisHlpString, dwHlpFileSize, L"%d", dwIndex);
  4958. dwHlpFileSize -= (lstrlenW(szThisHlpString) + 1);
  4959. szThisHlpString += (lstrlenW(szThisHlpString) + 1);
  4960. hr = StringCchPrintfW(szThisHlpString, dwHlpFileSize, L"%ws", pszNewNameTable[dwIndex]);
  4961. dwHlpFileSize -= (lstrlenW(szThisHlpString) + 1);
  4962. szThisHlpString += (lstrlenW(szThisHlpString) + 1);
  4963. }
  4964. else {
  4965. // it's a counter string
  4966. hr = StringCchPrintfW(szThisCtrString, dwCtrFileSize, L"%d", dwIndex);
  4967. dwCtrFileSize -= (lstrlenW(szThisCtrString) + 1);
  4968. szThisCtrString += (lstrlenW(szThisCtrString) + 1);
  4969. hr = StringCchPrintfW(szThisCtrString, dwCtrFileSize, L"%ws", pszNewNameTable[dwIndex]);
  4970. dwCtrFileSize -= (lstrlenW(szThisCtrString) + 1);
  4971. szThisCtrString += (lstrlenW(szThisCtrString) + 1);
  4972. }
  4973. } // else just skip it
  4974. }
  4975. for (/*dwIndex from last run */;dwIndex <= dwOldLastEntry; dwIndex++) {
  4976. if (pszOldNameTable[dwIndex] != NULL) {
  4977. TRACE((WINPERF_DBG_TRACE_INFO),
  4978. (& LoadPerfGuid,
  4979. __LINE__,
  4980. LOADPERF_UPDATEPERFNAMEFILES,
  4981. ARG_DEF(ARG_TYPE_WSTR, 1),
  4982. ERROR_SUCCESS,
  4983. TRACE_WSTR(pszOldNameTable[dwIndex]),
  4984. TRACE_DWORD(dwIndex),
  4985. NULL));
  4986. if (dwIndex & 0x01) {
  4987. // then it's a help string
  4988. hr = StringCchPrintfW(szThisHlpString, dwHlpFileSize, L"%d", dwIndex);
  4989. dwHlpFileSize -= (lstrlenW(szThisHlpString) + 1);
  4990. szThisHlpString += (lstrlenW(szThisHlpString) + 1);
  4991. hr = StringCchPrintfW(szThisHlpString, dwHlpFileSize, L"%ws", pszOldNameTable[dwIndex]);
  4992. dwHlpFileSize -= (lstrlenW(szThisHlpString) + 1);
  4993. szThisHlpString += (lstrlenW(szThisHlpString) + 1);
  4994. } else {
  4995. // it's a counter string
  4996. hr = StringCchPrintfW(szThisCtrString, dwCtrFileSize, L"%d", dwIndex);
  4997. dwCtrFileSize -= (lstrlenW(szThisCtrString) + 1);
  4998. szThisCtrString += (lstrlenW(szThisCtrString) + 1);
  4999. hr = StringCchPrintfW(szThisCtrString, dwCtrFileSize, L"%ws", pszOldNameTable[dwIndex]);
  5000. dwCtrFileSize -= (lstrlenW(szThisCtrString) + 1);
  5001. szThisCtrString += (lstrlenW(szThisCtrString) + 1);
  5002. }
  5003. } // else just skip it
  5004. }
  5005. // terminate the MSZ
  5006. * szThisCtrString ++ = L'\0';
  5007. * szThisHlpString ++ = L'\0';
  5008. }
  5009. // close mapped memory sections:
  5010. if (bAllocCtrString) {
  5011. MemoryFree(szNewCtrStrings);
  5012. MemoryFree(szNewHlpStrings);
  5013. }
  5014. else {
  5015. if (szNewCtrStrings != NULL) UnmapViewOfFile(szNewCtrStrings);
  5016. if (szNewHlpStrings != NULL) UnmapViewOfFile(szNewHlpStrings);
  5017. }
  5018. if (hCtrFileMap != NULL) CloseHandle(hCtrFileMap);
  5019. if (hCtrFileIn != NULL) CloseHandle(hCtrFileIn);
  5020. if (hHlpFileMap != NULL) CloseHandle(hHlpFileMap);
  5021. if (hHlpFileIn != NULL) CloseHandle(hHlpFileIn);
  5022. if (dwReturn == ERROR_SUCCESS) {
  5023. // write new values to registry
  5024. LPWSTR AddCounterNameBuffer = NULL;
  5025. LPWSTR AddHelpNameBuffer = NULL;
  5026. dwLength = lstrlenW(AddCounterNameStr) + lstrlenW(AddHelpNameStr) + lstrlenW(szLanguageID) + 1;
  5027. AddCounterNameBuffer = MemoryAllocate(2 * dwLength * sizeof(WCHAR));
  5028. if (AddCounterNameBuffer != NULL) {
  5029. AddHelpNameBuffer = AddCounterNameBuffer + dwLength;
  5030. hr = StringCchPrintfW(AddCounterNameBuffer, dwLength, L"%ws%ws", AddCounterNameStr, szLanguageID);
  5031. hr = StringCchPrintfW(AddHelpNameBuffer, dwLength, L"%ws%ws", AddHelpNameStr, szLanguageID);
  5032. // because these are perf counter strings, RegQueryValueEx
  5033. // is used instead of RegSetValueEx as one might expect.
  5034. dwSize = (DWORD)((DWORD_PTR)szThisCtrString - (DWORD_PTR)szNewCtrMSZ);
  5035. __try {
  5036. dwReturn = RegQueryValueExW(HKEY_PERFORMANCE_DATA,
  5037. AddCounterNameBuffer,
  5038. RESERVED,
  5039. & dwType,
  5040. (LPVOID) szNewCtrMSZ,
  5041. & dwSize);
  5042. }
  5043. __except (EXCEPTION_EXECUTE_HANDLER) {
  5044. dwReturn = GetExceptionCode();
  5045. }
  5046. if (dwReturn != ERROR_SUCCESS) {
  5047. TRACE((WINPERF_DBG_TRACE_ERROR),
  5048. (& LoadPerfGuid,
  5049. __LINE__,
  5050. LOADPERF_UPDATEPERFNAMEFILES,
  5051. ARG_DEF(ARG_TYPE_WSTR, 1),
  5052. dwReturn,
  5053. TRACE_WSTR(AddCounterNameBuffer),
  5054. TRACE_DWORD(dwSize),
  5055. NULL));
  5056. }
  5057. dwSize = (DWORD) ((DWORD_PTR) szThisHlpString - (DWORD_PTR) szNewHlpMSZ);
  5058. __try {
  5059. dwReturn = RegQueryValueExW(HKEY_PERFORMANCE_DATA,
  5060. AddHelpNameBuffer,
  5061. RESERVED,
  5062. & dwType,
  5063. (LPVOID) szNewHlpMSZ,
  5064. & dwSize);
  5065. }
  5066. __except (EXCEPTION_EXECUTE_HANDLER) {
  5067. dwReturn = GetExceptionCode();
  5068. }
  5069. if (dwReturn != ERROR_SUCCESS) {
  5070. TRACE((WINPERF_DBG_TRACE_ERROR),
  5071. (& LoadPerfGuid,
  5072. __LINE__,
  5073. LOADPERF_UPDATEPERFNAMEFILES,
  5074. ARG_DEF(ARG_TYPE_WSTR, 1),
  5075. dwReturn,
  5076. TRACE_WSTR(AddHelpNameBuffer),
  5077. TRACE_DWORD(dwSize),
  5078. NULL));
  5079. }
  5080. MemoryFree(AddCounterNameBuffer);
  5081. }
  5082. else {
  5083. dwReturn = ERROR_OUTOFMEMORY;
  5084. }
  5085. }
  5086. MemoryFree(szCtrNameIn);
  5087. MemoryFree(szHlpNameIn);
  5088. MemoryFree(pszNewNameTable);
  5089. MemoryFree(pszOldNameTable);
  5090. MemoryFree(szNewCtrMSZ);
  5091. MemoryFree(szNewHlpMSZ);
  5092. MemoryFree(szLangSection);
  5093. ReleaseMutex(hLoadPerfMutex);
  5094. return dwReturn;
  5095. }
  5096. // exported version of the above function
  5097. LOADPERF_FUNCTION
  5098. UpdatePerfNameFilesW(
  5099. IN LPCWSTR szNewCtrFilePath, // data file with new base counter strings
  5100. IN LPCWSTR szNewHlpFilePath, // data file with new base counter strings
  5101. IN LPWSTR szLanguageID, // Lang ID to update
  5102. IN ULONG_PTR dwFlags // flags
  5103. )
  5104. {
  5105. DWORD dwStatus = ERROR_SUCCESS;
  5106. DWORD dwSize;
  5107. if (szNewCtrFilePath != NULL) {
  5108. __try {
  5109. dwSize = lstrlenW(szNewCtrFilePath);
  5110. if (dwSize == 0) dwStatus = ERROR_INVALID_PARAMETER;
  5111. }
  5112. __except(EXCEPTION_EXECUTE_HANDLER) {
  5113. dwStatus = ERROR_INVALID_PARAMETER;
  5114. }
  5115. }
  5116. else {
  5117. dwStatus = ERROR_INVALID_PARAMETER;
  5118. }
  5119. if (szNewHlpFilePath != NULL) {
  5120. __try {
  5121. dwSize = lstrlenW(szNewHlpFilePath);
  5122. if (dwSize == 0) dwStatus = ERROR_INVALID_PARAMETER;
  5123. }
  5124. __except(EXCEPTION_EXECUTE_HANDLER) {
  5125. dwStatus = ERROR_INVALID_PARAMETER;
  5126. }
  5127. }
  5128. else if (! (dwFlags & LODCTR_UPNF_RESTORE)) {
  5129. // this parameter can only be NULL if this flag bit is set.
  5130. dwStatus = ERROR_INVALID_PARAMETER;
  5131. }
  5132. if (szLanguageID != NULL) {
  5133. __try {
  5134. dwSize = lstrlenW(szLanguageID);
  5135. if (dwSize == 0) dwStatus = ERROR_INVALID_PARAMETER;
  5136. }
  5137. __except(EXCEPTION_EXECUTE_HANDLER) {
  5138. dwStatus = ERROR_INVALID_PARAMETER;
  5139. }
  5140. }
  5141. else {
  5142. dwStatus = ERROR_INVALID_PARAMETER;
  5143. }
  5144. if (dwStatus == ERROR_SUCCESS) {
  5145. dwStatus = UpdatePerfNameFilesX(szNewCtrFilePath, // data file with new base counter strings
  5146. szNewHlpFilePath, // data file with new base counter strings
  5147. szLanguageID, // Lang ID to update
  5148. dwFlags); // flags
  5149. }
  5150. return dwStatus;
  5151. }
  5152. LOADPERF_FUNCTION
  5153. UpdatePerfNameFilesA(
  5154. IN LPCSTR szNewCtrFilePath, // data file with new base counter strings
  5155. IN LPCSTR szNewHlpFilePath, // data file with new base counter strings
  5156. IN LPSTR szLanguageID, // Lang ID to update
  5157. IN ULONG_PTR dwFlags // flags
  5158. )
  5159. {
  5160. DWORD dwError = ERROR_SUCCESS;
  5161. LPWSTR wszNewCtrFilePath = NULL;
  5162. LPWSTR wszNewHlpFilePath = NULL;
  5163. LPWSTR wszLanguageID = NULL;
  5164. DWORD dwLength;
  5165. if (szNewCtrFilePath != NULL) {
  5166. __try {
  5167. dwLength = lstrlenA(szNewCtrFilePath);
  5168. if (dwLength == 0) {
  5169. dwError = ERROR_INVALID_PARAMETER;
  5170. }
  5171. else {
  5172. wszNewCtrFilePath = LoadPerfMultiByteToWideChar(CP_ACP, (LPSTR) szNewCtrFilePath);
  5173. }
  5174. }
  5175. __except(EXCEPTION_EXECUTE_HANDLER) {
  5176. dwError = ERROR_INVALID_PARAMETER;
  5177. }
  5178. }
  5179. else {
  5180. dwError = ERROR_INVALID_PARAMETER;
  5181. }
  5182. if (szNewHlpFilePath != NULL) {
  5183. __try {
  5184. dwLength = lstrlenA(szNewHlpFilePath);
  5185. if (dwLength == 0) {
  5186. dwError = ERROR_INVALID_PARAMETER;
  5187. }
  5188. else {
  5189. wszNewHlpFilePath = LoadPerfMultiByteToWideChar(CP_ACP, (LPSTR) szNewHlpFilePath);
  5190. }
  5191. }
  5192. __except(EXCEPTION_EXECUTE_HANDLER) {
  5193. dwError = ERROR_INVALID_PARAMETER;
  5194. }
  5195. }
  5196. else if (! (dwFlags & LODCTR_UPNF_RESTORE)) {
  5197. // this parameter can only be NULL if this flag bit is set.
  5198. dwError = ERROR_INVALID_PARAMETER;
  5199. }
  5200. if (szLanguageID != NULL) {
  5201. __try {
  5202. dwLength = lstrlenA(szLanguageID);
  5203. if (dwLength == 0) {
  5204. dwError = ERROR_INVALID_PARAMETER;
  5205. }
  5206. else {
  5207. wszLanguageID = LoadPerfMultiByteToWideChar(CP_ACP, (LPSTR) szLanguageID);
  5208. }
  5209. }
  5210. __except(EXCEPTION_EXECUTE_HANDLER) {
  5211. dwError = ERROR_INVALID_PARAMETER;
  5212. }
  5213. }
  5214. else {
  5215. dwError = ERROR_INVALID_PARAMETER;
  5216. }
  5217. if (dwError == ERROR_SUCCESS) {
  5218. if (wszNewCtrFilePath == NULL || wszLanguageID == NULL) {
  5219. dwError = ERROR_OUTOFMEMORY;
  5220. }
  5221. else if (szNewHlpFilePath != NULL && wszNewHlpFilePath == NULL) {
  5222. dwError = ERROR_OUTOFMEMORY;
  5223. }
  5224. if (dwError == ERROR_SUCCESS) {
  5225. dwError = UpdatePerfNameFilesX(wszNewCtrFilePath, wszNewHlpFilePath, wszLanguageID, dwFlags);
  5226. }
  5227. }
  5228. MemoryFree(wszNewCtrFilePath);
  5229. MemoryFree(wszNewHlpFilePath);
  5230. MemoryFree(wszLanguageID);
  5231. return dwError;
  5232. }
  5233. LOADPERF_FUNCTION
  5234. SetServiceAsTrustedW(
  5235. IN LPCWSTR szMachineName, // reserved, MBZ
  5236. IN LPCWSTR szServiceName
  5237. )
  5238. {
  5239. HKEY hKeyService_Perf = NULL;
  5240. DWORD dwReturn = ERROR_SUCCESS;
  5241. HKEY hKeyLM = HKEY_LOCAL_MACHINE; // until remote machine access is supported
  5242. LPWSTR szPerfKeyString = NULL;
  5243. LPWSTR szLibName = NULL;
  5244. LPWSTR szExpLibName = NULL;
  5245. LPWSTR szFullPathName = NULL;
  5246. DWORD dwSize, dwType;
  5247. HANDLE hFile;
  5248. DllValidationData dvdLibrary;
  5249. LARGE_INTEGER liSize;
  5250. BOOL bStatus;
  5251. HRESULT hr;
  5252. WinPerfStartTrace(NULL);
  5253. if (szMachineName != NULL) {
  5254. // reserved for future use
  5255. dwReturn = ERROR_INVALID_PARAMETER;
  5256. }
  5257. else if (szServiceName == NULL) {
  5258. dwReturn = ERROR_INVALID_PARAMETER;
  5259. }
  5260. else {
  5261. __try {
  5262. dwSize = lstrlenW(szServiceName);
  5263. if (dwSize == 0) dwReturn = ERROR_INVALID_PARAMETER;
  5264. }
  5265. __except(EXCEPTION_EXECUTE_HANDLER) {
  5266. dwReturn = ERROR_INVALID_PARAMETER;
  5267. }
  5268. }
  5269. if (dwReturn != ERROR_SUCCESS) goto Cleanup;
  5270. szPerfKeyString = MemoryAllocate(sizeof(WCHAR) * SMALL_BUFFER_SIZE * 4);
  5271. if (szPerfKeyString == NULL) {
  5272. dwReturn = ERROR_OUTOFMEMORY;
  5273. goto Cleanup;
  5274. }
  5275. szLibName = (LPWSTR) (szPerfKeyString + SMALL_BUFFER_SIZE);
  5276. szExpLibName = (LPWSTR) (szLibName + SMALL_BUFFER_SIZE);
  5277. szFullPathName = (LPWSTR) (szExpLibName + SMALL_BUFFER_SIZE);
  5278. // build path to performance subkey
  5279. hr = StringCchPrintfW(szPerfKeyString,
  5280. SMALL_BUFFER_SIZE,
  5281. L"%ws%ws%ws%ws%ws",
  5282. DriverPathRoot,
  5283. Slash,
  5284. szServiceName,
  5285. Slash,
  5286. Performance);
  5287. // open performance key under the service key
  5288. __try {
  5289. dwReturn = RegOpenKeyExW(hKeyLM, szPerfKeyString, 0L, KEY_READ | KEY_WRITE, & hKeyService_Perf);
  5290. }
  5291. __except (EXCEPTION_EXECUTE_HANDLER) {
  5292. dwReturn = GetExceptionCode();
  5293. }
  5294. if (dwReturn == ERROR_SUCCESS) {
  5295. // get library name
  5296. dwType = 0;
  5297. dwSize = SMALL_BUFFER_SIZE * sizeof(WCHAR);
  5298. __try {
  5299. dwReturn = RegQueryValueExW(hKeyService_Perf, cszLibrary, NULL, & dwType, (LPBYTE) szLibName, & dwSize);
  5300. }
  5301. __except (EXCEPTION_EXECUTE_HANDLER) {
  5302. dwReturn = GetExceptionCode();
  5303. }
  5304. if (dwReturn == ERROR_SUCCESS) {
  5305. // expand path name if necessary
  5306. if (dwType == REG_EXPAND_SZ) {
  5307. dwSize = ExpandEnvironmentStringsW(szLibName, szExpLibName, SMALL_BUFFER_SIZE);
  5308. }
  5309. else {
  5310. hr = StringCchCopyW(szExpLibName, SMALL_BUFFER_SIZE, szLibName);
  5311. // dwSize is same as returned from Fn Call.
  5312. }
  5313. if (dwSize != 0) {
  5314. // find DLL file
  5315. dwSize = SearchPathW(NULL, szExpLibName, NULL, SMALL_BUFFER_SIZE, szFullPathName, NULL);
  5316. if (dwSize > 0) {
  5317. hFile = CreateFileW(szFullPathName,
  5318. GENERIC_READ,
  5319. FILE_SHARE_READ | FILE_SHARE_WRITE,
  5320. NULL,
  5321. OPEN_EXISTING,
  5322. FILE_ATTRIBUTE_NORMAL,
  5323. NULL);
  5324. if (hFile != INVALID_HANDLE_VALUE) {
  5325. // read file date/time & size
  5326. bStatus = GetFileTime(hFile, & dvdLibrary.CreationDate, NULL, NULL);
  5327. if (bStatus) {
  5328. WORD dateCreate;
  5329. WORD timeCreate;
  5330. FileTimeToDosDateTime(& dvdLibrary.CreationDate, & dateCreate, & timeCreate);
  5331. DosDateTimeToFileTime(dateCreate, timeCreate, & dvdLibrary.CreationDate);
  5332. liSize.LowPart = GetFileSize( hFile, (DWORD *) & liSize.HighPart);
  5333. dvdLibrary.FileSize = liSize.QuadPart;
  5334. // set registry value
  5335. __try {
  5336. dwReturn = RegSetValueExW(hKeyService_Perf,
  5337. szLibraryValidationCode,
  5338. 0L,
  5339. REG_BINARY,
  5340. (LPBYTE) & dvdLibrary,
  5341. sizeof(dvdLibrary));
  5342. }
  5343. __except (EXCEPTION_EXECUTE_HANDLER) {
  5344. dwReturn = GetExceptionCode();
  5345. }
  5346. TRACE((WINPERF_DBG_TRACE_INFO),
  5347. (& LoadPerfGuid,
  5348. __LINE__,
  5349. LOADPERF_SETSERVICEASTRUSTED,
  5350. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_WSTR, 3),
  5351. dwReturn,
  5352. TRACE_WSTR(szServiceName),
  5353. TRACE_WSTR(szExpLibName),
  5354. TRACE_WSTR(szLibraryValidationCode),
  5355. NULL));
  5356. }
  5357. else {
  5358. dwReturn = GetLastError();
  5359. }
  5360. CloseHandle (hFile);
  5361. }
  5362. else {
  5363. dwReturn = GetLastError();
  5364. }
  5365. }
  5366. else {
  5367. dwReturn = ERROR_FILE_NOT_FOUND;
  5368. }
  5369. }
  5370. else {
  5371. // unable to expand environment strings
  5372. dwReturn = GetLastError();
  5373. }
  5374. }
  5375. else {
  5376. TRACE((WINPERF_DBG_TRACE_ERROR),
  5377. (& LoadPerfGuid,
  5378. __LINE__,
  5379. LOADPERF_SETSERVICEASTRUSTED,
  5380. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  5381. dwReturn,
  5382. TRACE_WSTR(szServiceName),
  5383. TRACE_WSTR(cszLibrary),
  5384. NULL));
  5385. }
  5386. // close key
  5387. RegCloseKey (hKeyService_Perf);
  5388. }
  5389. if (dwReturn == ERROR_SUCCESS) {
  5390. TRACE((WINPERF_DBG_TRACE_INFO),
  5391. (& LoadPerfGuid,
  5392. __LINE__,
  5393. LOADPERF_SETSERVICEASTRUSTED,
  5394. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  5395. ERROR_SUCCESS,
  5396. TRACE_WSTR(szServiceName),
  5397. TRACE_WSTR(Performance),
  5398. NULL));
  5399. }
  5400. else {
  5401. TRACE((WINPERF_DBG_TRACE_ERROR),
  5402. (& LoadPerfGuid,
  5403. __LINE__,
  5404. LOADPERF_SETSERVICEASTRUSTED,
  5405. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  5406. dwReturn,
  5407. TRACE_WSTR(szServiceName),
  5408. TRACE_WSTR(Performance),
  5409. NULL));
  5410. }
  5411. Cleanup:
  5412. MemoryFree(szPerfKeyString);
  5413. return dwReturn;
  5414. }
  5415. LOADPERF_FUNCTION
  5416. SetServiceAsTrustedA(
  5417. IN LPCSTR szMachineName, // reserved, MBZ
  5418. IN LPCSTR szServiceName
  5419. )
  5420. {
  5421. LPWSTR lpWideServiceName = NULL;
  5422. DWORD lReturn = ERROR_SUCCESS;
  5423. if (szMachineName != NULL) {
  5424. // reserved for future use
  5425. lReturn = ERROR_INVALID_PARAMETER;
  5426. }
  5427. else if (szServiceName == NULL) {
  5428. lReturn = ERROR_INVALID_PARAMETER;
  5429. }
  5430. else {
  5431. __try {
  5432. DWORD dwStrLen = lstrlenA(szServiceName);
  5433. if (dwStrLen == 0) lReturn = ERROR_INVALID_PARAMETER;
  5434. }
  5435. __except(EXCEPTION_EXECUTE_HANDLER) {
  5436. lReturn = ERROR_INVALID_PARAMETER;
  5437. }
  5438. }
  5439. if (lReturn == ERROR_SUCCESS) {
  5440. //length of string including terminator
  5441. lpWideServiceName = LoadPerfMultiByteToWideChar(CP_ACP, (LPSTR) szServiceName);
  5442. if (lpWideServiceName != NULL) {
  5443. lReturn = SetServiceAsTrustedW(NULL, lpWideServiceName);
  5444. }
  5445. else {
  5446. lReturn = ERROR_OUTOFMEMORY;
  5447. }
  5448. }
  5449. MemoryFree(lpWideServiceName);
  5450. return lReturn;
  5451. }
  5452. int __cdecl
  5453. My_vfwprintf(
  5454. FILE * str,
  5455. const wchar_t * format,
  5456. va_list argptr
  5457. )
  5458. {
  5459. HANDLE hOut;
  5460. int iReturn = 0;
  5461. HRESULT hr;
  5462. static WCHAR szBufferMessage[LOADPERF_BUFF_SIZE];
  5463. if (str == stderr) {
  5464. hOut = GetStdHandle(STD_ERROR_HANDLE);
  5465. }
  5466. else {
  5467. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  5468. }
  5469. if ((GetFileType(hOut) & ~ FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) {
  5470. hr = StringCchVPrintfW(szBufferMessage, LOADPERF_BUFF_SIZE, format, argptr);
  5471. if (SUCCEEDED(hr)) {
  5472. iReturn = lstrlenW(szBufferMessage);
  5473. WriteConsoleW(hOut, szBufferMessage, iReturn, & iReturn, NULL);
  5474. }
  5475. else {
  5476. iReturn = -1;
  5477. }
  5478. }
  5479. else {
  5480. iReturn = vfwprintf(str, format, argptr);
  5481. }
  5482. return iReturn;
  5483. }