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.

724 lines
30 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. extlib.c
  5. Abstract:
  6. This file implements all the library routines operating on
  7. extensible performance libraries.
  8. Author:
  9. JeePang
  10. Revision History:
  11. 09/27/2000 - JeePang - Moved from perflib.c
  12. --*/
  13. #define UNICODE
  14. //
  15. // Include files
  16. //
  17. #pragma warning(disable:4306)
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <ntregapi.h>
  22. #include <ntprfctr.h>
  23. #include <windows.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <winperf.h>
  27. #include <rpc.h>
  28. #include "regrpc.h"
  29. #include "ntconreg.h"
  30. #include "prflbmsg.h" // event log messages
  31. #include "perflib.h"
  32. #pragma warning(default:4306)
  33. // default trusted file list
  34. // all files presume to start with "perf"
  35. // static LONGLONG llTrustedNamePrefix = 0x0066007200650050; // "Perf"
  36. #define NAME_PREFIX L"Perf"
  37. DWORD dwTrustedFileNames[] = {
  38. 0x0053004F, // "OS" for PerfOS.dll
  39. 0x0065004E, // "Ne" for PerfNet.dll
  40. 0x00720050, // "Pr" for PerfProc.dll
  41. 0x00690044 // "Di" for PerfDisk.dll
  42. };
  43. CONST DWORD dwTrustedFileNameCount =
  44. sizeof(dwTrustedFileNames) / sizeof (dwTrustedFileNames[0]);
  45. // there must be at least 8 chars in the name to be checked as trusted by
  46. // default trusted file names are at least 8 chars in length
  47. CONST DWORD dwMinTrustedFileNameLen = 6;
  48. BOOL
  49. ServiceIsTrustedByDefault (
  50. LPCWSTR szServiceName
  51. )
  52. {
  53. BOOL bReturn = FALSE;
  54. DWORD dwNameToTest;
  55. DWORD dwIdx;
  56. if (szServiceName != NULL) {
  57. // check for min size
  58. dwIdx = 0;
  59. while ((dwIdx < dwMinTrustedFileNameLen) && (szServiceName[dwIdx] > 0))
  60. dwIdx++;
  61. if (dwIdx == dwMinTrustedFileNameLen) {
  62. // test first 4 bytes to see if they match
  63. if (!wcsncmp(szServiceName, NAME_PREFIX, sizeof(LONGLONG))) {
  64. // then see if the rest is in this list
  65. dwNameToTest = * ((DWORD *)(szServiceName+4));
  66. for (dwIdx = 0; dwIdx < dwTrustedFileNameCount; dwIdx++) {
  67. if (dwNameToTest == dwTrustedFileNames[dwIdx]) {
  68. // match found
  69. bReturn = TRUE;
  70. break;
  71. } else {
  72. // no match so continue
  73. }
  74. }
  75. } else {
  76. // no match so return false
  77. }
  78. } else {
  79. // the name to be checked is too short so it mustn't be
  80. // a trusted one.
  81. }
  82. } else {
  83. // no string so return false
  84. }
  85. return bReturn;
  86. }
  87. DWORD
  88. CloseExtObjectLibrary (
  89. PEXT_OBJECT pObj,
  90. BOOL bCloseNow
  91. )
  92. /*++
  93. CloseExtObjectLibrary
  94. Closes and unloads the specified performance counter library and
  95. deletes all references to the functions.
  96. The unloader is "lazy" in that it waits for the library to be
  97. inactive for a specified time before unloading. This is due to the
  98. fact that Perflib can not ever be certain that no thread will need
  99. this library from one call to the next. In order to prevent "thrashing"
  100. due to constantly loading and unloading of the library, the unloading
  101. is delayed to make sure it's not really needed.
  102. This function expects locked and exclusive access to the object while
  103. it is opening. This must be provided by the calling function.
  104. Arguments:
  105. pObj -- pointer to the object information structure of the
  106. perf object to close
  107. bCloseNow -- the flag to indicate the library should be closed
  108. immediately. This is the result of the calling function
  109. closing the registry key.
  110. --*/
  111. {
  112. DWORD Status = ERROR_SUCCESS;
  113. LONGLONG TimeoutTime;
  114. if (((dwThreadAndLibraryTimeout == 0) ||
  115. (dwThreadAndLibraryTimeout == INFINITE)) && !bCloseNow) {
  116. return Status;
  117. }
  118. if (pObj->hLibrary != NULL) {
  119. // get current time to test timeout
  120. TimeoutTime = GetTimeAsLongLong();
  121. // timeout time is in ms
  122. TimeoutTime -= dwThreadAndLibraryTimeout;
  123. // don't close the library unless the object hasn't been accessed for
  124. // a while or the caller is closing the key
  125. if ((TimeoutTime > pObj->llLastUsedTime) || bCloseNow) {
  126. // don't toss if this library has the "keep" flag set and this
  127. // isn't a "close now" case
  128. if (!bCloseNow && (pObj->dwFlags & PERF_EO_KEEP_RESIDENT)) {
  129. // keep it loaded until the key is closed.
  130. } else {
  131. // then this is the last one to close the library
  132. // free library
  133. try {
  134. // call close function for this DLL
  135. if (pObj->CloseProc) {
  136. Status = (*pObj->CloseProc)();
  137. }
  138. else {
  139. Status = ERROR_PROC_NOT_FOUND;
  140. }
  141. } except (EXCEPTION_EXECUTE_HANDLER) {
  142. Status = GetExceptionCode();
  143. TRACE((WINPERF_DBG_TRACE_FATAL),
  144. (&PerflibGuid, __LINE__, PERF_CLOSE_EXTOBJLIB,
  145. ARG_TYPE_STR, Status,
  146. // pObj->szCloseProcName,
  147. // STRSIZE(pObj->szCloseProcName), NULL));
  148. TRACE_STR(pObj->szCloseProcName), NULL));
  149. }
  150. FreeLibrary(pObj->hLibrary);
  151. pObj->hLibrary = NULL;
  152. // clear all pointers that are now invalid
  153. pObj->OpenProc = NULL;
  154. pObj->CollectProc = NULL;
  155. pObj->QueryProc = NULL;
  156. pObj->CloseProc = NULL;
  157. InterlockedIncrement((LONG *)&pObj->dwCloseCount);
  158. pObj->llLastUsedTime = 0;
  159. }
  160. }
  161. Status = ERROR_SUCCESS;
  162. } else {
  163. // already closed
  164. Status = ERROR_SUCCESS;
  165. }
  166. PerfpDeleteErrorLogs(&pObj->ErrorLog);
  167. return Status;
  168. }
  169. DWORD
  170. OpenExtObjectLibrary (
  171. PEXT_OBJECT pObj
  172. )
  173. /*++
  174. OpenExtObjectLibrary
  175. Opens the specified library and looks up the functions used by
  176. the performance library. If the library is successfully
  177. loaded and opened then the open procedure is called to initialize
  178. the object.
  179. This function expects locked and exclusive access to the object while
  180. it is opening. This must be provided by the calling function.
  181. Arguments:
  182. pObj -- pointer to the object information structure of the
  183. perf object to close
  184. --*/
  185. {
  186. DWORD FnStatus = ERROR_SUCCESS;
  187. DWORD Status = ERROR_SUCCESS;
  188. DWORD dwOpenEvent = PERFLIB_OPEN_PROC_FAILURE;
  189. DWORD dwType;
  190. DWORD dwSize;
  191. DWORD dwValue;
  192. // variables used for event logging
  193. DWORD dwDataIndex;
  194. WORD wStringIndex;
  195. ULONG_PTR dwRawDataDwords[8];
  196. LPWSTR szMessageArray[8];
  197. HANDLE hPerflibFuncTimer = NULL;
  198. DLL_VALIDATION_DATA CurrentDllData;
  199. OPEN_PROC_WAIT_INFO opwInfo;
  200. UINT nErrorMode;
  201. LPWSTR szServiceName;
  202. DWORD szServiceNameSize;
  203. BOOL bUseTimer;
  204. // check to see if the library has already been opened
  205. if (pObj == NULL) {
  206. return ERROR_INVALID_PARAMETER;
  207. }
  208. if (pObj->dwFlags & PERF_EO_DISABLED) return ERROR_SERVICE_DISABLED;
  209. if (pObj->hLibrary == NULL) {
  210. // library isn't loaded yet, so
  211. // check to see if this function is enabled
  212. szServiceName = pObj->szServiceName;
  213. if (szServiceName == NULL) {
  214. szServiceName = (LPWSTR) &NULL_STRING[0];
  215. }
  216. szServiceNameSize = WSTRSIZE(szServiceName);
  217. dwType = 0;
  218. dwSize = sizeof (dwValue);
  219. dwValue = 0;
  220. Status = PrivateRegQueryValueExW (
  221. pObj->hPerfKey,
  222. DisablePerformanceCounters,
  223. NULL,
  224. &dwType,
  225. (LPBYTE)&dwValue,
  226. &dwSize);
  227. if ((Status == ERROR_SUCCESS) &&
  228. (dwType == REG_DWORD)) {
  229. pObj->dwFlags &= ~PERF_EO_DISABLED;
  230. switch (dwValue) {
  231. case PERFLIB_DISABLE_ALL : // disabled on all platforms
  232. // then DON'T Load this library
  233. pObj->dwFlags |= PERF_EO_DISABLED;
  234. DebugPrint((4, "Perflib:%d %ws disabled\n", __LINE__, szServiceName));
  235. TRACE((WINPERF_DBG_TRACE_INFO),
  236. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  237. ARG_TYPE_WSTR, 0, szServiceName,
  238. szServiceNameSize, NULL));
  239. break;
  240. case PERFLIB_DISABLE_X32 : // disabled only on WIN32 WOW
  241. {
  242. #if _WIN32
  243. NTSTATUS NtStatus;
  244. ULONG_PTR Wow64Info = 0;
  245. NtStatus = NtQueryInformationProcess(
  246. NtCurrentProcess(),
  247. ProcessWow64Information,
  248. &Wow64Info,
  249. sizeof(Wow64Info),
  250. NULL);
  251. if (NT_SUCCESS(NtStatus) && (Wow64Info)) {
  252. pObj->dwFlags |= PERF_EO_DISABLED;
  253. DebugPrint((4, "Perflib:%d X86 %ws disabled in WOW64\n", __LINE__, szServiceName));
  254. TRACE((WINPERF_DBG_TRACE_INFO),
  255. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  256. ARG_TYPE_WSTR, 0, szServiceName,
  257. szServiceNameSize, NULL));
  258. }
  259. #endif
  260. break;
  261. }
  262. case PERFLIB_DISABLE_IA64 : // disabled only on WIN64 native
  263. #if _WIN64
  264. pObj->dwFlags |= PERF_EO_DISABLED;
  265. DebugPrint((4, "Perflib:%d %ws disabled in WIN64\n", __LINE__, szServiceName));
  266. TRACE((WINPERF_DBG_TRACE_INFO),
  267. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  268. ARG_TYPE_WSTR, 0, szServiceName,
  269. szServiceNameSize, NULL));
  270. #endif
  271. break;
  272. // else falls through for _WIN32
  273. }
  274. }
  275. else {
  276. // set the error status & the flag value
  277. Status = ERROR_SUCCESS;
  278. pObj->dwFlags &= ~PERF_EO_DISABLED;
  279. }
  280. if ((Status == ERROR_SUCCESS) &&
  281. (pObj->LibData.FileSize > 0)) {
  282. if (ServiceIsTrustedByDefault(szServiceName)) {
  283. // then set as trusted and continue
  284. pObj->dwFlags |= PERF_EO_TRUSTED;
  285. } else {
  286. // see if this is a trusted file or a file that has been updated
  287. // get the file information
  288. memset (&CurrentDllData, 0, sizeof(CurrentDllData));
  289. Status = GetPerfDllFileInfo (
  290. pObj->szLibraryName,
  291. &CurrentDllData);
  292. if (Status == ERROR_SUCCESS) {
  293. // compare file data to registry data and update flags
  294. if ((pObj->LibData.CreationDate.dwHighDateTime ==
  295. CurrentDllData.CreationDate.dwHighDateTime) &&
  296. ((pObj->LibData.CreationDate.dwLowDateTime >> 25) ==
  297. (CurrentDllData.CreationDate.dwLowDateTime >> 25)) &&
  298. (pObj->LibData.FileSize == CurrentDllData.FileSize)) {
  299. pObj->dwFlags |= PERF_EO_TRUSTED;
  300. } else {
  301. TRACE((WINPERF_DBG_TRACE_WARNING),
  302. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  303. ARG_TYPE_WSTR, 0, szServiceName,
  304. szServiceNameSize, NULL));
  305. if (THROTTLE_PERFDLL(PERFLIB_NOT_TRUSTED_FILE, pObj)) {
  306. // load data for eventlog message
  307. dwDataIndex = wStringIndex = 0;
  308. szMessageArray[wStringIndex++] =
  309. pObj->szLibraryName;
  310. szMessageArray[wStringIndex++] =
  311. szServiceName;
  312. ReportEvent (hEventLog,
  313. EVENTLOG_WARNING_TYPE, // error type
  314. 0, // category (not used)
  315. (DWORD)PERFLIB_NOT_TRUSTED_FILE, // event,
  316. NULL, // SID (not used),
  317. wStringIndex, // number of strings
  318. 0, // sizeof raw data
  319. szMessageArray, // message text array
  320. NULL); // raw data
  321. }
  322. }
  323. }
  324. }
  325. }
  326. if ((Status == ERROR_SUCCESS) && (!(pObj->dwFlags & PERF_EO_DISABLED))) {
  327. // go ahead and load it
  328. nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
  329. // then load library & look up functions
  330. pObj->hLibrary = LoadLibraryExW (pObj->szLibraryName,
  331. NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  332. if (pObj->hLibrary != NULL) {
  333. // lookup function names
  334. pObj->OpenProc = (OPENPROC)GetProcAddress(
  335. pObj->hLibrary, pObj->szOpenProcName);
  336. if (pObj->OpenProc == NULL) {
  337. Status = GetLastError();
  338. TRACE((WINPERF_DBG_TRACE_FATAL),
  339. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  340. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  341. Status, szServiceName, szServiceNameSize,
  342. TRACE_STR(pObj->szOpenProcName), NULL));
  343. if (THROTTLE_PERFDLL(PERFLIB_OPEN_PROC_NOT_FOUND, pObj)) {
  344. WCHAR wszProcName[MAX_PATH+1];
  345. // load data for eventlog message
  346. dwDataIndex = wStringIndex = 0;
  347. dwRawDataDwords[dwDataIndex++] =
  348. (ULONG_PTR)Status;
  349. wcstombs(pObj->szOpenProcName, wszProcName, MAX_PATH);
  350. szMessageArray[wStringIndex++] = &wszProcName[0];
  351. szMessageArray[wStringIndex++] =
  352. pObj->szLibraryName;
  353. szMessageArray[wStringIndex++] =
  354. szServiceName;
  355. ReportEvent (hEventLog,
  356. EVENTLOG_ERROR_TYPE, // error type
  357. 0, // category (not used)
  358. (DWORD)PERFLIB_OPEN_PROC_NOT_FOUND, // event,
  359. NULL, // SID (not used),
  360. wStringIndex, // number of strings
  361. dwDataIndex*sizeof(ULONG_PTR), // sizeof raw data
  362. szMessageArray, // message text array
  363. (LPVOID)&dwRawDataDwords[0]); // raw data
  364. }
  365. DisablePerfLibrary(pObj, PERFLIB_DISABLE_ALL);
  366. }
  367. if (Status == ERROR_SUCCESS) {
  368. if (pObj->dwFlags & PERF_EO_QUERY_FUNC) {
  369. pObj->QueryProc = (QUERYPROC)GetProcAddress (
  370. pObj->hLibrary, pObj->szCollectProcName);
  371. pObj->CollectProc = (COLLECTPROC)pObj->QueryProc;
  372. } else {
  373. pObj->CollectProc = (COLLECTPROC)GetProcAddress (
  374. pObj->hLibrary, pObj->szCollectProcName);
  375. pObj->QueryProc = (QUERYPROC)pObj->CollectProc;
  376. }
  377. if (pObj->CollectProc == NULL) {
  378. Status = GetLastError();
  379. TRACE((WINPERF_DBG_TRACE_FATAL),
  380. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  381. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  382. Status, szServiceName, szServiceNameSize,
  383. TRACE_STR(pObj->szCollectProcName), NULL));
  384. if (THROTTLE_PERFDLL(PERFLIB_COLLECT_PROC_NOT_FOUND, pObj)) {
  385. WCHAR wszProcName[MAX_PATH+1];
  386. // load data for eventlog message
  387. dwDataIndex = wStringIndex = 0;
  388. dwRawDataDwords[dwDataIndex++] =
  389. (ULONG_PTR)Status;
  390. wcstombs(pObj->szCollectProcName,
  391. wszProcName, MAX_PATH);
  392. szMessageArray[wStringIndex++] = &wszProcName[0];
  393. szMessageArray[wStringIndex++] =
  394. pObj->szLibraryName;
  395. szMessageArray[wStringIndex++] =
  396. szServiceName;
  397. ReportEvent (hEventLog,
  398. EVENTLOG_ERROR_TYPE, // error type
  399. 0, // category (not used)
  400. (DWORD)PERFLIB_COLLECT_PROC_NOT_FOUND, // event,
  401. NULL, // SID (not used),
  402. wStringIndex, // number of strings
  403. dwDataIndex*sizeof(ULONG_PTR), // sizeof raw data
  404. szMessageArray, // message text array
  405. (LPVOID)&dwRawDataDwords[0]); // raw data
  406. }
  407. DisablePerfLibrary(pObj, PERFLIB_DISABLE_ALL);
  408. }
  409. }
  410. if (Status == ERROR_SUCCESS) {
  411. pObj->CloseProc = (CLOSEPROC)GetProcAddress (
  412. pObj->hLibrary, pObj->szCloseProcName);
  413. if (pObj->CloseProc == NULL) {
  414. Status = GetLastError();
  415. TRACE((WINPERF_DBG_TRACE_FATAL),
  416. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  417. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  418. Status, szServiceName, szServiceNameSize,
  419. TRACE_STR(pObj->szCloseProcName), NULL));
  420. if (THROTTLE_PERFDLL(PERFLIB_CLOSE_PROC_NOT_FOUND, pObj)) {
  421. WCHAR wszProcName[MAX_PATH+1];
  422. // load data for eventlog message
  423. dwDataIndex = wStringIndex = 0;
  424. dwRawDataDwords[dwDataIndex++] =
  425. (ULONG_PTR)Status;
  426. wcstombs(pObj->szCollectProcName,
  427. wszProcName, MAX_PATH);
  428. szMessageArray[wStringIndex++] = &wszProcName[0];
  429. szMessageArray[wStringIndex++] =
  430. pObj->szLibraryName;
  431. szMessageArray[wStringIndex++] =
  432. szServiceName;
  433. ReportEvent (hEventLog,
  434. EVENTLOG_ERROR_TYPE, // error type
  435. 0, // category (not used)
  436. (DWORD)PERFLIB_CLOSE_PROC_NOT_FOUND, // event,
  437. NULL, // SID (not used),
  438. wStringIndex, // number of strings
  439. dwDataIndex*sizeof(ULONG_PTR), // sizeof raw data
  440. szMessageArray, // message text array
  441. (LPVOID)&dwRawDataDwords[0]); // raw data
  442. }
  443. DisablePerfLibrary(pObj, PERFLIB_DISABLE_ALL);
  444. }
  445. }
  446. bUseTimer = TRUE; // default
  447. if (!(lPerflibConfigFlags & PLCF_NO_DLL_TESTING)) {
  448. if (pObj->dwFlags & PERF_EO_TRUSTED) {
  449. bUseTimer = FALSE; // Trusted DLL's are not timed
  450. }
  451. } else {
  452. // disable DLL testing
  453. bUseTimer = FALSE; // Timing is disabled as well
  454. }
  455. if (Status == ERROR_SUCCESS) {
  456. try {
  457. // start timer
  458. opwInfo.pNext = NULL;
  459. opwInfo.szLibraryName = pObj->szLibraryName;
  460. opwInfo.szServiceName = szServiceName;
  461. opwInfo.dwWaitTime = pObj->dwOpenTimeout;
  462. opwInfo.dwEventMsg = PERFLIB_OPEN_PROC_TIMEOUT;
  463. opwInfo.pData = (LPVOID)pObj;
  464. if (bUseTimer) {
  465. hPerflibFuncTimer = StartPerflibFunctionTimer(&opwInfo);
  466. // if no timer, continue anyway, even though things may
  467. // hang, it's better than not loading the DLL since they
  468. // usually load OK
  469. //
  470. if (hPerflibFuncTimer == NULL) {
  471. // unable to get a timer entry
  472. TRACE((WINPERF_DBG_TRACE_WARNING),
  473. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB, 0, 0, NULL));
  474. }
  475. } else {
  476. hPerflibFuncTimer = NULL;
  477. }
  478. // call open procedure to initialize DLL
  479. if (pObj->OpenProc) {
  480. FnStatus = (*pObj->OpenProc)(pObj->szLinkageString);
  481. }
  482. else {
  483. FnStatus = ERROR_PROC_NOT_FOUND;
  484. dwOpenEvent = PERFLIB_OPEN_PROC_NOT_FOUND;
  485. }
  486. // check the result.
  487. if (FnStatus != ERROR_SUCCESS) {
  488. TRACE((WINPERF_DBG_TRACE_FATAL),
  489. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  490. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  491. FnStatus, szServiceName, szServiceNameSize,
  492. pObj->szLinkageString, (pObj->szLinkageString) ?
  493. WSTRSIZE(pObj->szLinkageString) : 0, NULL));
  494. dwOpenEvent = PERFLIB_OPEN_PROC_FAILURE;
  495. if (FnStatus != ERROR_ACCESS_DENIED) {
  496. pObj->dwOpenFail ++;
  497. }
  498. else { // remember the thread Id
  499. pObj->ThreadId = GetCurrentThreadId();
  500. pObj->dwOpenFail = 0; // usually only 1 type of failure
  501. }
  502. } else {
  503. pObj->ThreadId = 0;
  504. InterlockedIncrement((LONG *)&pObj->dwOpenCount);
  505. }
  506. } except (EXCEPTION_EXECUTE_HANDLER) {
  507. FnStatus = GetExceptionCode();
  508. TRACE((WINPERF_DBG_TRACE_FATAL),
  509. (&PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB,
  510. ARG_DEF(ARG_TYPE_WSTR, 1), FnStatus,
  511. szServiceName, szServiceNameSize, NULL));
  512. dwOpenEvent = PERFLIB_OPEN_PROC_EXCEPTION;
  513. }
  514. if (hPerflibFuncTimer != NULL) {
  515. // kill timer
  516. Status = KillPerflibFunctionTimer (hPerflibFuncTimer);
  517. hPerflibFuncTimer = NULL;
  518. }
  519. if (FnStatus != ERROR_SUCCESS) {
  520. if (dwOpenEvent == PERFLIB_OPEN_PROC_EXCEPTION) {
  521. DisablePerfLibrary(pObj, PERFLIB_DISABLE_ALL);
  522. }
  523. if (THROTTLE_PERFDLL(dwOpenEvent, pObj)) {
  524. // load data for eventlog message
  525. dwDataIndex = wStringIndex = 0;
  526. dwRawDataDwords[dwDataIndex++] =
  527. (ULONG_PTR)FnStatus;
  528. szMessageArray[wStringIndex++] =
  529. szServiceName;
  530. szMessageArray[wStringIndex++] =
  531. pObj->szLibraryName;
  532. ReportEventW (hEventLog,
  533. (WORD)EVENTLOG_ERROR_TYPE, // error type
  534. 0, // category (not used)
  535. dwOpenEvent, // event,
  536. NULL, // SID (not used),
  537. wStringIndex, // number of strings
  538. dwDataIndex*sizeof(ULONG_PTR), // sizeof raw data
  539. szMessageArray, // message text array
  540. (LPVOID)&dwRawDataDwords[0]); // raw data
  541. }
  542. }
  543. }
  544. if (FnStatus != ERROR_SUCCESS) {
  545. // clear fields
  546. pObj->OpenProc = NULL;
  547. pObj->CollectProc = NULL;
  548. pObj->QueryProc = NULL;
  549. pObj->CloseProc = NULL;
  550. if (pObj->hLibrary != NULL) {
  551. FreeLibrary (pObj->hLibrary);
  552. pObj->hLibrary = NULL;
  553. }
  554. Status = FnStatus;
  555. } else {
  556. pObj->llLastUsedTime = GetTimeAsLongLong();
  557. }
  558. } else {
  559. Status = GetLastError();
  560. TRACE((WINPERF_DBG_TRACE_FATAL),
  561. (& PerflibGuid, __LINE__, PERF_OPEN_EXTOBJLIB, ARG_DEF(ARG_TYPE_WSTR, 1), Status,
  562. szServiceName, szServiceNameSize, NULL));
  563. if (Status == ERROR_BAD_EXE_FORMAT) {
  564. // report error event and disable performance counter DLL.
  565. DWORD dwDisable = 0;
  566. DWORD dwEvent = PERFLIB_INVALID_WOW32_PERF_DLL;
  567. #if _WIN64
  568. // Unable to load IA64 version performance counter DLL, this might be the case that
  569. // performance counter DLL is 32-bit version. Disable on WIN64 native case.
  570. //
  571. dwEvent = PERFLIB_INVALID_IA64_PERF_DLL;
  572. dwDisable = PERFLIB_DISABLE_IA64;
  573. #endif
  574. #if _WIN32
  575. // Unable to load WIN32 version performance counter DLL, this might be the case that
  576. // performance counter DLL is 64-bit native version. Disable on WIN32 WOW case.
  577. //
  578. if (dwDisable == PERFLIB_DISABLE_IA64) {
  579. dwDisable = PERFLIB_DISABLE_ALL;
  580. }
  581. else {
  582. dwDisable = PERFLIB_DISABLE_X32;
  583. }
  584. #endif
  585. dwDataIndex = wStringIndex = 0;
  586. dwRawDataDwords[dwDataIndex ++] = (ULONG_PTR) Status;
  587. szMessageArray[wStringIndex ++] = szServiceName;
  588. ReportEventW(hEventLog,
  589. (WORD) EVENTLOG_ERROR_TYPE, // error type
  590. 0, // category (not used)
  591. dwEvent, // event,
  592. NULL, // SID (not used),
  593. wStringIndex, // number of strings
  594. dwDataIndex * sizeof(ULONG_PTR), // sizeof raw data
  595. szMessageArray, // message text array
  596. (LPVOID) & dwRawDataDwords[0]); // raw data
  597. DisablePerfLibrary(pObj, dwDisable);
  598. }
  599. }
  600. SetErrorMode (nErrorMode);
  601. }
  602. } else {
  603. // else already open so bump the ref count
  604. pObj->llLastUsedTime = GetTimeAsLongLong();
  605. }
  606. return Status;
  607. }
  608. #ifdef _WIN64
  609. DWORD
  610. ExtpAlignBuffer(
  611. PCHAR lpLastBuffer,
  612. PCHAR *lpNextBuffer,
  613. DWORD lpBytesLeft
  614. )
  615. {
  616. PCHAR lpAligned;
  617. PCHAR lpBuffer = *lpNextBuffer;
  618. PPERF_OBJECT_TYPE pObject;
  619. if ((ULONG_PTR) lpBuffer & (ULONG_PTR) 0x07) {
  620. DWORD dwAdjust;
  621. lpAligned = ALIGN_ON_QWORD(lpBuffer);
  622. dwAdjust = (DWORD) (lpAligned - (PCHAR)lpBuffer);
  623. if (lpBytesLeft < dwAdjust) // No more room to align
  624. return 0;
  625. lpBytesLeft = lpBytesLeft - dwAdjust;
  626. pObject = (PPERF_OBJECT_TYPE) lpLastBuffer;
  627. while (((PCHAR) pObject + pObject->TotalByteLength) < lpBuffer) {
  628. pObject = (PPERF_OBJECT_TYPE) (((PCHAR) pObject) + pObject->TotalByteLength);
  629. }
  630. if ((PCHAR) pObject < lpBuffer) {
  631. pObject->TotalByteLength += dwAdjust;
  632. }
  633. }
  634. *lpNextBuffer = lpBuffer;
  635. return lpBytesLeft;
  636. }
  637. #endif