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

2626 lines
78 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. ctrtest.c
  5. Abstract:
  6. Program to test the extensible counter dll's
  7. Author:
  8. Bob Watson (bobw) 8 Feb 99
  9. Revision History:
  10. --*/
  11. #include <windows.h>
  12. #include <process.h>
  13. #include <winperf.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <pdhmsg.h>
  17. #include "strings.h"
  18. #include "ctrtest.h"
  19. ///////////////////////////////////////////////////////////////////////////////////////
  20. //
  21. // Data Structures
  22. //
  23. ///////////////////////////////////////////////////////////////////////////////////////
  24. typedef struct _LOCAL_THREAD_DATA {
  25. DWORD dwNumObjects;
  26. DWORD dwCycleCount;
  27. DWORD dwLoopCount;
  28. BOOL bTestContents;
  29. BOOL bDisplay;
  30. BOOL bStopOnError;
  31. } LOCAL_THREAD_DATA, *PLOCAL_THREAD_DATA;
  32. ///////////////////////////////////////////////////////////////////////////////////////
  33. //
  34. // Globals & Constants
  35. //
  36. ///////////////////////////////////////////////////////////////////////////////////////
  37. HANDLE g_hEvent;
  38. EXT_OBJECT* g_pExtObjects = NULL;
  39. LOCAL_THREAD_DATA g_LTData;
  40. BOOL g_fRand = FALSE;
  41. FILE* g_pOutput = NULL;
  42. LPWSTR* g_pNameTable;
  43. DWORD g_dwLastIndex;
  44. HANDLE g_hTestHeap = NULL;
  45. LONG lEventLogLevel = LOG_DEBUG;
  46. LONG lExtCounterTestLevel = EXT_TEST_ALL;
  47. #define PERFVAL_NOCONFIG 0
  48. #define PERFVAL_PASS 1
  49. #define PERFVAL_FAIL 2
  50. #define PERFVAL_TIMEOUT 3
  51. static const WCHAR cszDefaultLangId[] = {L"009"};
  52. static const WCHAR cszNamesKey[] = {L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"};
  53. static const WCHAR cszLastHelp[] = {L"Last Help"};
  54. static const WCHAR cszLastCounter[] = {L"Last Counter"};
  55. static const WCHAR cszVersionName[] = {L"Version"};
  56. static const WCHAR cszCounterName[] = {L"Counter "};
  57. static const WCHAR cszHelpName[] = {L"Explain "};
  58. static const WCHAR cszCounters[] = {L"Counters"};
  59. static const WCHAR cszNotFound[] = {L"*** NOT FOUND ***"};
  60. LPWSTR szTestErrorMessage = NULL;
  61. #define MAX_BUF_SIZE ((DWORD)(1024 * 1024 * 8))
  62. #define PERFLIB_TIMER_INTERVAL 200 // 200 ms Timer
  63. ///////////////////////////////////////////////////////////////////////////////////////
  64. //
  65. // Code
  66. //
  67. ///////////////////////////////////////////////////////////////////////////////////////
  68. DWORD
  69. InitializeExtObj(EXT_OBJECT* pExtObj)
  70. {
  71. DWORD dwStatus = ERROR_SUCCESS;
  72. BOOL bUseQueryFn = FALSE;
  73. DWORD dwType;
  74. DWORD dwSize;
  75. DWORD dwMemBlockSize = 0; //sizeof(EXT_OBJECT);
  76. DWORD dwOpenTimeout;
  77. DWORD dwCollectTimeout;
  78. DWORD dwObjectArray[MAX_PERF_OBJECTS_IN_QUERY_FUNCTION];
  79. DWORD dwObjIndex = 0;
  80. DWORD dwLinkageStringLen = 0;
  81. DWORD dwFlags = 0;
  82. DWORD dwKeep;
  83. CHAR szOpenProcName[MAX_PATH];
  84. CHAR szCollectProcName[MAX_PATH];
  85. CHAR szCloseProcName[MAX_PATH];
  86. WCHAR szLibraryString[MAX_PATH];
  87. WCHAR szLibraryExpPath[MAX_PATH];
  88. WCHAR mszObjectList[MAX_PATH];
  89. WCHAR szLinkageKeyPath[MAX_PATH];
  90. WCHAR szLinkageString[MAX_PATH];
  91. WCHAR szServicePath[MAX_PATH];
  92. WCHAR szMutexName[MAX_PATH];
  93. WCHAR szPID[32];
  94. LPBYTE szStringBlock;
  95. LPSTR pNextStringA;
  96. LPWSTR pNextStringW;
  97. LPWSTR szThisChar;
  98. LPWSTR szThisObject;
  99. HKEY hServicesKey = NULL;
  100. HKEY hPerfKey = NULL;
  101. LPWSTR szServiceName;
  102. HKEY hKeyLinkage;
  103. HeapValidate (g_hTestHeap, 0, NULL);
  104. if (pExtObj == NULL)
  105. {
  106. dwStatus = ERROR_INVALID_DATA;
  107. }
  108. else
  109. {
  110. // Open the performance subkey
  111. lstrcpyW (szServicePath, cszHklmServicesKey);
  112. dwStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE, szServicePath,
  113. 0, KEY_READ, &hServicesKey);
  114. lstrcpyW (szServicePath, pExtObj->szServiceName);
  115. lstrcatW (szServicePath, cszPerformance);
  116. dwStatus = RegOpenKeyExW (hServicesKey, szServicePath,
  117. 0, KEY_READ, &hPerfKey);
  118. szServiceName = (LPWSTR)pExtObj->szServiceName;
  119. if ( ERROR_SUCCESS != dwStatus )
  120. {
  121. dwStatus = ERROR_INVALID_DATA;
  122. }
  123. // Read the performance DLL name
  124. if (dwStatus == ERROR_SUCCESS)
  125. {
  126. dwType = 0;
  127. dwSize = sizeof(szLibraryString);
  128. memset (szLibraryString, 0, sizeof(szLibraryString));
  129. memset (szLibraryExpPath, 0, sizeof(szLibraryExpPath));
  130. dwStatus = RegQueryValueExW (hPerfKey,
  131. cszDLLValue,
  132. NULL,
  133. &dwType,
  134. (LPBYTE)szLibraryString,
  135. &dwSize);
  136. if (dwStatus == ERROR_SUCCESS)
  137. {
  138. if (dwType == REG_EXPAND_SZ)
  139. {
  140. // expand any environment vars
  141. dwSize = ExpandEnvironmentStringsW(
  142. szLibraryString,
  143. szLibraryExpPath,
  144. MAX_PATH);
  145. if ((dwSize > MAX_PATH) || (dwSize == 0))
  146. {
  147. dwStatus = ERROR_INVALID_DLL;
  148. }
  149. else
  150. {
  151. dwSize += 1;
  152. dwSize *= sizeof(WCHAR);
  153. dwMemBlockSize += DWORD_MULTIPLE(dwSize);
  154. }
  155. }
  156. else if (dwType == REG_SZ)
  157. {
  158. // look for dll and save full file Path
  159. dwSize = SearchPathW (
  160. NULL, // use standard system search path
  161. szLibraryString,
  162. NULL,
  163. MAX_PATH,
  164. szLibraryExpPath,
  165. NULL);
  166. if ((dwSize > MAX_PATH) || (dwSize == 0))
  167. {
  168. dwStatus = ERROR_INVALID_DLL;
  169. }
  170. else
  171. {
  172. dwSize += 1;
  173. dwSize *= sizeof(WCHAR);
  174. dwMemBlockSize += DWORD_MULTIPLE(dwSize);
  175. }
  176. }
  177. else
  178. {
  179. dwStatus = ERROR_INVALID_DLL;
  180. }
  181. }
  182. }
  183. // Open Function
  184. if (dwStatus == ERROR_SUCCESS)
  185. {
  186. dwType = 0;
  187. dwSize = sizeof(szOpenProcName);
  188. memset (szOpenProcName, 0, sizeof(szOpenProcName));
  189. dwStatus = RegQueryValueExA (hPerfKey,
  190. caszOpenValue,
  191. NULL,
  192. &dwType,
  193. (LPBYTE)szOpenProcName,
  194. &dwSize);
  195. }
  196. // Open Timeout
  197. if (dwStatus == ERROR_SUCCESS)
  198. {
  199. // add in size of previous string
  200. // the size value includes the Term. NULL
  201. dwMemBlockSize += DWORD_MULTIPLE(dwSize);
  202. // we have the procedure name so get the timeout value
  203. dwType = 0;
  204. dwSize = sizeof(dwOpenTimeout);
  205. dwStatus = RegQueryValueExW (hPerfKey,
  206. cszOpenTimeout,
  207. NULL,
  208. &dwType,
  209. (LPBYTE)&dwOpenTimeout,
  210. &dwSize);
  211. // if error, then apply default
  212. if ((dwStatus != ERROR_SUCCESS) || (dwType != REG_DWORD))
  213. {
  214. dwOpenTimeout = 10000;
  215. dwStatus = ERROR_SUCCESS;
  216. }
  217. }
  218. // Close Function
  219. if (dwStatus == ERROR_SUCCESS)
  220. {
  221. dwType = 0;
  222. dwSize = sizeof(szCloseProcName);
  223. memset (szCloseProcName, 0, sizeof(szCloseProcName));
  224. dwStatus = RegQueryValueExA (hPerfKey,
  225. caszCloseValue,
  226. NULL,
  227. &dwType,
  228. (LPBYTE)szCloseProcName,
  229. &dwSize);
  230. }
  231. // Collect Function
  232. if (dwStatus == ERROR_SUCCESS)
  233. {
  234. // add in size of previous string
  235. // the size value includes the Term. NULL
  236. dwMemBlockSize += DWORD_MULTIPLE(dwSize);
  237. // try to look up the query function which is the
  238. // preferred interface if it's not found, then
  239. // try the collect function name. If that's not found,
  240. // then bail
  241. dwType = 0;
  242. dwSize = sizeof(szCollectProcName);
  243. memset (szCollectProcName, 0, sizeof(szCollectProcName));
  244. dwStatus = RegQueryValueExA (hPerfKey,
  245. caszQueryValue,
  246. NULL,
  247. &dwType,
  248. (LPBYTE)szCollectProcName,
  249. &dwSize);
  250. if (dwStatus == ERROR_SUCCESS)
  251. {
  252. // add in size of the Query Function Name
  253. // the size value includes the Term. NULL
  254. dwMemBlockSize += DWORD_MULTIPLE(dwSize);
  255. // get next string
  256. bUseQueryFn = TRUE;
  257. // the query function can support a static object list
  258. // so look it up
  259. }
  260. else
  261. {
  262. // the QueryFunction wasn't found so look up the
  263. // Collect Function name instead
  264. dwType = 0;
  265. dwSize = sizeof(szCollectProcName);
  266. memset (szCollectProcName, 0, sizeof(szCollectProcName));
  267. dwStatus = RegQueryValueExA (hPerfKey,
  268. caszCollectValue,
  269. NULL,
  270. &dwType,
  271. (LPBYTE)szCollectProcName,
  272. &dwSize);
  273. if (dwStatus == ERROR_SUCCESS)
  274. {
  275. // add in size of Collect Function Name
  276. // the size value includes the Term. NULL
  277. dwMemBlockSize += DWORD_MULTIPLE(dwSize);
  278. }
  279. }
  280. }
  281. // Collect Timeout
  282. if (dwStatus == ERROR_SUCCESS)
  283. {
  284. // we have the procedure name so get the timeout value
  285. dwType = 0;
  286. dwSize = sizeof(dwCollectTimeout);
  287. dwStatus = RegQueryValueExW (hPerfKey,
  288. cszCollectTimeout,
  289. NULL,
  290. &dwType,
  291. (LPBYTE)&dwCollectTimeout,
  292. &dwSize);
  293. // if error, then apply default
  294. if ((dwStatus != ERROR_SUCCESS) || (dwType != REG_DWORD))
  295. {
  296. dwCollectTimeout = 10000;
  297. dwStatus = ERROR_SUCCESS;
  298. }
  299. }
  300. // Object List
  301. if (dwStatus == ERROR_SUCCESS)
  302. {
  303. dwType = 0;
  304. dwSize = sizeof(mszObjectList);
  305. memset (mszObjectList, 0, sizeof(mszObjectList));
  306. dwStatus = RegQueryValueExW (hPerfKey,
  307. cszObjListValue,
  308. NULL,
  309. &dwType,
  310. (LPBYTE)mszObjectList,
  311. &dwSize);
  312. if (dwStatus == ERROR_SUCCESS)
  313. {
  314. if (dwType != REG_MULTI_SZ)
  315. {
  316. // convert space delimited list to msz
  317. for (szThisChar = mszObjectList; *szThisChar != 0; szThisChar++)
  318. {
  319. if (*szThisChar == L' ') *szThisChar = L'\0';
  320. }
  321. ++szThisChar;
  322. *szThisChar = 0; // add MSZ term Null
  323. }
  324. for (szThisObject = mszObjectList, dwObjIndex = 0;
  325. (*szThisObject != 0) && (dwObjIndex < MAX_PERF_OBJECTS_IN_QUERY_FUNCTION);
  326. szThisObject += lstrlenW(szThisObject) + 1)
  327. {
  328. dwObjectArray[dwObjIndex] = wcstoul(szThisObject, NULL, 10);
  329. dwObjIndex++;
  330. }
  331. if (*szThisObject != 0)
  332. {
  333. // BUGBUG: log error idicating too many object ID's are
  334. // in the list.
  335. }
  336. }
  337. else
  338. {
  339. // reset status since not having this is
  340. // not a showstopper
  341. dwStatus = ERROR_SUCCESS;
  342. }
  343. }
  344. // Keep Resident
  345. if (dwStatus == ERROR_SUCCESS)
  346. {
  347. dwType = 0;
  348. dwKeep = 0;
  349. dwSize = sizeof(dwKeep);
  350. dwStatus = RegQueryValueExW (hPerfKey,
  351. cszKeepResident,
  352. NULL,
  353. &dwType,
  354. (LPBYTE)&dwKeep,
  355. &dwSize);
  356. if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD))
  357. {
  358. if (dwKeep == 1)
  359. {
  360. dwFlags |= PERF_EO_KEEP_RESIDENT;
  361. }
  362. else
  363. {
  364. // no change.
  365. }
  366. }
  367. else
  368. {
  369. // not fatal, just use the defaults.
  370. dwStatus = ERROR_SUCCESS;
  371. }
  372. }
  373. // Linkage
  374. if (dwStatus == ERROR_SUCCESS)
  375. {
  376. memset (szLinkageString, 0, sizeof(szLinkageString));
  377. lstrcpyW (szLinkageKeyPath, szServiceName);
  378. lstrcatW (szLinkageKeyPath, cszLinkageKey);
  379. dwStatus = RegOpenKeyExW (
  380. hServicesKey,
  381. szLinkageKeyPath,
  382. 0L,
  383. KEY_READ,
  384. &hKeyLinkage);
  385. if (dwStatus == ERROR_SUCCESS)
  386. {
  387. // look up export value string
  388. dwSize = sizeof(szLinkageString);
  389. dwType = 0;
  390. dwStatus = RegQueryValueExW (
  391. hKeyLinkage,
  392. cszExportValue,
  393. NULL,
  394. &dwType,
  395. (LPBYTE)&szLinkageString,
  396. &dwSize);
  397. if ((dwStatus != ERROR_SUCCESS) ||
  398. ((dwType != REG_SZ) && (dwType != REG_MULTI_SZ)))
  399. {
  400. // clear buffer
  401. memset (szLinkageString, 0, sizeof(szLinkageString));
  402. dwLinkageStringLen = 0;
  403. // not finding a linkage key is not fatal so correct
  404. // status
  405. dwStatus = ERROR_SUCCESS;
  406. }
  407. else
  408. {
  409. // add size of linkage string to buffer
  410. // the size value includes the Term. NULL
  411. dwLinkageStringLen = dwSize;
  412. dwMemBlockSize += DWORD_MULTIPLE(dwSize);
  413. }
  414. RegCloseKey (hKeyLinkage);
  415. }
  416. else
  417. {
  418. // not finding a linkage key is not fatal so correct
  419. // status
  420. dwStatus = ERROR_SUCCESS;
  421. }
  422. }
  423. if (hServicesKey != NULL)
  424. RegCloseKey (hServicesKey);
  425. if (hPerfKey != NULL)
  426. RegCloseKey (hPerfKey);
  427. // Copy data to Performance Library Data Structure
  428. if (dwStatus == ERROR_SUCCESS)
  429. {
  430. // allocate and initialize a new ext. object block
  431. szStringBlock = (LPBYTE)HeapAlloc(g_hTestHeap, HEAP_ZERO_MEMORY, dwMemBlockSize);
  432. if (szStringBlock != NULL)
  433. {
  434. // copy values to new buffer (all others are NULL)
  435. pNextStringA = (LPSTR)szStringBlock;
  436. // copy Open Procedure Name
  437. pExtObj->szOpenProcName = pNextStringA;
  438. lstrcpyA (pNextStringA, szOpenProcName);
  439. pNextStringA += lstrlenA (pNextStringA) + 1;
  440. pNextStringA = (LPSTR)ALIGN_ON_DWORD(pNextStringA);
  441. pExtObj->dwOpenTimeout = dwOpenTimeout;
  442. // copy collect function or query function, depending
  443. pExtObj->szCollectProcName = pNextStringA;
  444. lstrcpyA (pNextStringA, szCollectProcName);
  445. pNextStringA += lstrlenA (pNextStringA) + 1;
  446. pNextStringA = (LPSTR)ALIGN_ON_DWORD(pNextStringA);
  447. pExtObj->dwCollectTimeout = dwCollectTimeout;
  448. // copy Close Procedure Name
  449. pExtObj->szCloseProcName = pNextStringA;
  450. lstrcpyA (pNextStringA, szCloseProcName);
  451. pNextStringA += lstrlenA (pNextStringA) + 1;
  452. pNextStringA = (LPSTR)ALIGN_ON_DWORD(pNextStringA);
  453. // copy Library path
  454. pNextStringW = (LPWSTR)pNextStringA;
  455. pExtObj->szLibraryName = pNextStringW;
  456. lstrcpyW (pNextStringW, szLibraryExpPath);
  457. pNextStringW += lstrlenW (pNextStringW) + 1;
  458. pNextStringW = (LPWSTR)ALIGN_ON_DWORD(pNextStringW);
  459. // copy Linkage String if there is one
  460. if (*szLinkageString != 0) {
  461. pExtObj->szLinkageString = pNextStringW;
  462. memcpy (pNextStringW, szLinkageString, dwLinkageStringLen);
  463. // length includes extra NULL char and is in BYTES
  464. pNextStringW += (dwLinkageStringLen / sizeof (WCHAR));
  465. pNextStringW = (LPWSTR)ALIGN_ON_DWORD(pNextStringW);
  466. }
  467. // load flags
  468. if (bUseQueryFn) {
  469. dwFlags |= PERF_EO_QUERY_FUNC;
  470. }
  471. pExtObj->dwFlags = dwFlags;
  472. // load Object array
  473. if (dwObjIndex > 0) {
  474. pExtObj->dwNumObjects = dwObjIndex;
  475. memcpy (pExtObj->dwObjList,
  476. dwObjectArray, (dwObjIndex * sizeof(dwObjectArray[0])));
  477. }
  478. pExtObj->llLastUsedTime = 0;
  479. // create Mutex name
  480. lstrcpyW (szMutexName, pExtObj->szServiceName);
  481. lstrcatW (szMutexName, (LPCWSTR)L"_Perf_Library_Lock_PID_");
  482. _ultow ((ULONG)GetCurrentProcessId(), szPID, 16);
  483. lstrcatW (szMutexName, szPID);
  484. pExtObj->hMutex = CreateMutexW (NULL, FALSE, szMutexName);
  485. pExtObj->bValid = TRUE;
  486. } else {
  487. dwStatus = ERROR_OUTOFMEMORY;
  488. }
  489. }
  490. }
  491. HeapValidate (g_hTestHeap, 0, NULL);
  492. if (ERROR_SUCCESS != dwStatus)
  493. {
  494. pExtObj->bValid = FALSE;
  495. }
  496. return dwStatus;
  497. }
  498. DWORD
  499. FinializeExtObj(PEXT_OBJECT pInfo)
  500. {
  501. DWORD dwStatus = ERROR_SUCCESS;
  502. // then close everything
  503. if (pInfo->hMutex != NULL) {
  504. CloseHandle (pInfo->hMutex);
  505. pInfo->hMutex = NULL;
  506. }
  507. if ( NULL != pInfo->szOpenProcName )
  508. HeapFree(g_hTestHeap, 0, pInfo->szOpenProcName);
  509. if ( NULL != pInfo->szServiceName )
  510. HeapFree(g_hTestHeap, 0, pInfo->szServiceName);
  511. if ( NULL != pInfo->szQueryString )
  512. HeapFree(g_hTestHeap, 0, pInfo->szQueryString);
  513. return dwStatus;
  514. }
  515. DWORD
  516. OpenLibrary (
  517. EXT_OBJECT *pExtObj)
  518. {
  519. DWORD dwStatus = ERROR_SUCCESS;
  520. DWORD dwOpenEvent;
  521. UINT nErrorMode;
  522. // check to see if the library has already been opened
  523. LARGE_INTEGER liStartTime, liEndTime, liFreq;
  524. if (pExtObj != NULL)
  525. {
  526. // then load library & look up functions
  527. nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
  528. pExtObj->hLibrary = LoadLibraryExW (pExtObj->szLibraryName,
  529. NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  530. if (pExtObj->hLibrary != NULL) {
  531. // lookup function names
  532. pExtObj->OpenProc = (OPENPROC)GetProcAddress(
  533. pExtObj->hLibrary, pExtObj->szOpenProcName);
  534. if (pExtObj->OpenProc == NULL) {
  535. wprintf ((LPCWSTR)L"\nOpen Procedure \"%s\" not found in \"%s\"",
  536. pExtObj->szOpenProcName, pExtObj->szLibraryName);
  537. }
  538. } else {
  539. // unable to load library
  540. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tLoadLibraryEx Failed for the \"%s\" Performance Library", GetCurrentThreadId(), pExtObj->szServiceName);
  541. dwStatus = GetLastError();
  542. }
  543. if (dwStatus == ERROR_SUCCESS) {
  544. if (pExtObj->dwFlags & PERF_EO_QUERY_FUNC) {
  545. pExtObj->QueryProc = (QUERYPROC)GetProcAddress (
  546. pExtObj->hLibrary, pExtObj->szCollectProcName);
  547. pExtObj->CollectProc = (COLLECTPROC)pExtObj->QueryProc;
  548. } else {
  549. pExtObj->CollectProc = (COLLECTPROC)GetProcAddress (
  550. pExtObj->hLibrary, pExtObj->szCollectProcName);
  551. pExtObj->QueryProc = (QUERYPROC)pExtObj->CollectProc;
  552. }
  553. if (pExtObj->CollectProc == NULL) {
  554. wprintf ((LPCWSTR)L"\nCollect Procedure \"%s\" not found in \"%s\"",
  555. pExtObj->szCollectProcName, pExtObj->szLibraryName);
  556. }
  557. }
  558. if (dwStatus == ERROR_SUCCESS) {
  559. pExtObj->CloseProc = (CLOSEPROC)GetProcAddress (
  560. pExtObj->hLibrary, pExtObj->szCloseProcName);
  561. if (pExtObj->CloseProc == NULL) {
  562. wprintf ((LPCWSTR)L"\nClose Procedure \"%s\" not found in \"%s\"",
  563. pExtObj->szCloseProcName, pExtObj->szLibraryName);
  564. }
  565. }
  566. if (dwStatus == ERROR_SUCCESS) {
  567. __try {
  568. if ((pExtObj->hMutex != NULL) &&
  569. (pExtObj->OpenProc != NULL)){
  570. dwStatus = WaitForSingleObject (
  571. pExtObj->hMutex,
  572. pExtObj->dwOpenTimeout);
  573. if (dwStatus != WAIT_TIMEOUT) {
  574. QueryPerformanceCounter (&liStartTime);
  575. // dwStatus = (*pExtObj->OpenProc)(pExtObj->szLinkageString);
  576. QueryPerformanceCounter (&liEndTime);
  577. // release the lock
  578. ReleaseMutex(pExtObj->hMutex);
  579. if ( dwStatus != ERROR_SUCCESS )
  580. {
  581. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \t%S failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pExtObj->szOpenProcName, pExtObj->szServiceName, dwStatus);
  582. }
  583. } else {
  584. pExtObj->dwLockoutCount++;
  585. }
  586. } else {
  587. dwStatus = ERROR_LOCK_FAILED;
  588. }
  589. // check the result.
  590. if (dwStatus != ERROR_SUCCESS) {
  591. dwOpenEvent = WBEMPERF_OPEN_PROC_FAILURE;
  592. } else {
  593. InterlockedIncrement((LONG *)&pExtObj->dwOpenCount);
  594. pExtObj->llFunctionTime = liEndTime.QuadPart - liStartTime.QuadPart;
  595. pExtObj->llOpenTime += pExtObj->llFunctionTime;
  596. }
  597. } __except (EXCEPTION_EXECUTE_HANDLER) {
  598. dwStatus = GetExceptionCode();
  599. dwOpenEvent = WBEMPERF_OPEN_PROC_EXCEPTION;
  600. }
  601. }
  602. QueryPerformanceFrequency (&liFreq);
  603. pExtObj->llTimeBase = liFreq.QuadPart;
  604. if (dwStatus != ERROR_SUCCESS) {
  605. // clear fields
  606. pExtObj->OpenProc = NULL;
  607. pExtObj->CollectProc = NULL;
  608. pExtObj->QueryProc = NULL;
  609. pExtObj->CloseProc = NULL;
  610. if (pExtObj->hLibrary != NULL) {
  611. FreeLibrary (pExtObj->hLibrary);
  612. pExtObj->hLibrary = NULL;
  613. }
  614. } else {
  615. GetSystemTimeAsFileTime ((FILETIME *)&pExtObj->llLastUsedTime);
  616. }
  617. } // else no buffer returned
  618. return dwStatus;
  619. }
  620. DWORD
  621. ClearSafeBuffer( PSAFE_BUFFER pSafeBufferBlock )
  622. {
  623. DWORD dwStatus = ERROR_SUCCESS;
  624. if (pSafeBufferBlock != NULL)
  625. {
  626. if (pSafeBufferBlock->lpBuffer != NULL)
  627. HeapFree (g_hTestHeap, 0, pSafeBufferBlock->lpBuffer);
  628. pSafeBufferBlock->lpLowGuardPage = NULL;
  629. pSafeBufferBlock->lpHiGuardPage = NULL;
  630. pSafeBufferBlock->lpEndPointer = NULL;
  631. pSafeBufferBlock->lpBuffer = NULL;
  632. pSafeBufferBlock->lpSafeBuffer = NULL;
  633. pSafeBufferBlock->lpCallBuffer = NULL;
  634. }
  635. else
  636. {
  637. dwStatus = ERROR_INVALID_DATA;
  638. }
  639. return dwStatus;
  640. }
  641. DWORD
  642. CreateSafeBuffer( PSAFE_BUFFER pSafeBufferBlock )
  643. {
  644. DWORD dwStatus = ERROR_SUCCESS;
  645. if (NULL == pSafeBufferBlock)
  646. {
  647. dwStatus = ERROR_INVALID_DATA;
  648. }
  649. if (dwStatus == ERROR_SUCCESS)
  650. {
  651. if (pSafeBufferBlock->lpBuffer != NULL)
  652. HeapFree (g_hTestHeap, 0, pSafeBufferBlock->lpBuffer);
  653. pSafeBufferBlock->dwBufSize += pSafeBufferBlock->dwBufSizeIncrement;
  654. pSafeBufferBlock->dwCallBufSize = pSafeBufferBlock->dwBufSize;
  655. pSafeBufferBlock->lpBuffer = HeapAlloc (g_hTestHeap,
  656. HEAP_ZERO_MEMORY,
  657. pSafeBufferBlock->dwBufSize + (2*GUARD_PAGE_SIZE));
  658. if (NULL != pSafeBufferBlock->lpBuffer)
  659. {
  660. // set buffer pointers
  661. pSafeBufferBlock->lpLowGuardPage = pSafeBufferBlock->lpBuffer;
  662. pSafeBufferBlock->lpSafeBuffer = (LPBYTE)pSafeBufferBlock->lpBuffer + GUARD_PAGE_SIZE;
  663. pSafeBufferBlock->lpCallBuffer = pSafeBufferBlock->lpSafeBuffer;
  664. pSafeBufferBlock->lpHiGuardPage = (LPBYTE)pSafeBufferBlock->lpCallBuffer + pSafeBufferBlock->dwBufSize;
  665. pSafeBufferBlock->lpEndPointer = (LPBYTE)pSafeBufferBlock->lpHiGuardPage + GUARD_PAGE_SIZE;
  666. memset (pSafeBufferBlock->lpLowGuardPage, GUARD_PAGE_CHAR, GUARD_PAGE_SIZE);
  667. memset (pSafeBufferBlock->lpHiGuardPage, GUARD_PAGE_CHAR, GUARD_PAGE_SIZE);
  668. }
  669. else
  670. {
  671. dwStatus = ERROR_OUTOFMEMORY;
  672. }
  673. }
  674. if (dwStatus != ERROR_SUCCESS)
  675. {
  676. dwStatus = ClearSafeBuffer( pSafeBufferBlock );
  677. }
  678. return dwStatus;
  679. }
  680. DWORD
  681. CheckGuardBytes( PSAFE_BUFFER pSafeBufferBlock, PEXT_OBJECT pObj )
  682. {
  683. DWORD dwStatus = ERROR_SUCCESS;
  684. LPDWORD lpCheckPointer;
  685. //
  686. // check for buffer corruption here
  687. //
  688. if (lExtCounterTestLevel <= EXT_TEST_BASIC)
  689. {
  690. //
  691. // check 1: bytes left should be the same as
  692. // new data buffer ptr - orig data buffer ptr
  693. //
  694. if (pSafeBufferBlock->dwCallBufSize != (DWORD)((LPBYTE)pSafeBufferBlock->lpCallBuffer - (LPBYTE)pSafeBufferBlock->lpSafeBuffer))
  695. {
  696. pObj->dwBadPointers++;
  697. dwStatus = ERROR_INVALID_DATA;
  698. }
  699. //
  700. // check 2: buffer after ptr should be < hi Guard page ptr
  701. //
  702. if ((dwStatus == ERROR_SUCCESS) &&
  703. ((LPBYTE)pSafeBufferBlock->lpCallBuffer >= (LPBYTE)pSafeBufferBlock->lpHiGuardPage))
  704. {
  705. // see if they exceeded the allocated memory
  706. if ((LPBYTE)pSafeBufferBlock->lpCallBuffer >= (LPBYTE)pSafeBufferBlock->lpEndPointer)
  707. {
  708. // even worse!!
  709. }
  710. pObj->dwBufferSizeErrors++;
  711. dwStatus = ERROR_INVALID_DATA;
  712. }
  713. //
  714. // check 3: check lo guard page for corruption
  715. //
  716. if (dwStatus == ERROR_SUCCESS )
  717. {
  718. for (lpCheckPointer = (LPDWORD)pSafeBufferBlock->lpLowGuardPage;
  719. lpCheckPointer < (LPDWORD)pSafeBufferBlock->lpSafeBuffer;
  720. lpCheckPointer++)
  721. {
  722. if (*lpCheckPointer != GUARD_PAGE_DWORD)
  723. {
  724. pObj->dwLowerGPViolations++;
  725. dwStatus = ERROR_INVALID_DATA;
  726. break;
  727. }
  728. }
  729. }
  730. //
  731. // check 4: check hi guard page for corruption
  732. //
  733. if (dwStatus == ERROR_SUCCESS)
  734. {
  735. for (lpCheckPointer = (LPDWORD)pSafeBufferBlock->lpHiGuardPage;
  736. lpCheckPointer < (LPDWORD)pSafeBufferBlock->lpEndPointer;
  737. lpCheckPointer++)
  738. {
  739. if (*lpCheckPointer != GUARD_PAGE_DWORD)
  740. {
  741. pObj->dwUpperGPViolations++;
  742. dwStatus = ERROR_INVALID_DATA;
  743. break;
  744. }
  745. }
  746. }
  747. }
  748. if (dwStatus != ERROR_SUCCESS)
  749. {
  750. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tGuardbyte violation for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pObj->szServiceName, dwStatus);
  751. }
  752. return dwStatus;
  753. }
  754. DWORD
  755. ValidateBuffer( PSAFE_BUFFER pSafeBufferBlock, EXT_OBJECT *pThisExtObj )
  756. {
  757. DWORD dwStatus = ERROR_SUCCESS;
  758. DWORD dwObjectBufSize;
  759. DWORD dwIndex;
  760. LONG lInstIndex;
  761. PERF_OBJECT_TYPE *pObject, *pNextObject;
  762. PERF_INSTANCE_DEFINITION *pInstance;
  763. PERF_DATA_BLOCK *pPerfData;
  764. BOOL bForeignDataBuffer;
  765. if (NULL == pSafeBufferBlock)
  766. {
  767. dwStatus = ERROR_INVALID_DATA;
  768. }
  769. // Validate the blob size
  770. if ( dwStatus == ERROR_SUCCESS )
  771. {
  772. if (( pSafeBufferBlock->dwCallBufSize < 0 ) ||
  773. ( pSafeBufferBlock->dwCallBufSize > pSafeBufferBlock->dwBufSize ))
  774. {
  775. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tBuffer size parameter does not match the buffer displacement in the data returned for the \"%s\" performance library", GetCurrentThreadId(), pThisExtObj->szServiceName);
  776. pThisExtObj->dwBufferSizeErrors++;
  777. dwStatus = ERROR_INVALID_PARAMETER;
  778. }
  779. }
  780. // Validate the byte alignment
  781. if (dwStatus == ERROR_SUCCESS)
  782. {
  783. if (pSafeBufferBlock->dwCallBufSize & 0x00000007)
  784. {
  785. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tByte Allignment Error in the data returned for the \"%s\" performance library", GetCurrentThreadId(), pThisExtObj->szServiceName);
  786. pThisExtObj->dwAlignmentErrors++;
  787. dwStatus = ERROR_INVALID_DATA;
  788. }
  789. }
  790. if ( dwStatus == ERROR_SUCCESS )
  791. {
  792. dwStatus = CheckGuardBytes( pSafeBufferBlock, pThisExtObj );
  793. }
  794. if ((lExtCounterTestLevel <= EXT_TEST_ALL) && (dwStatus == ERROR_SUCCESS))
  795. {
  796. //
  797. // Internal consistency checks
  798. //
  799. //
  800. // Check 5: Check object length field values
  801. //
  802. // first test to see if this is a foreign
  803. // computer data block or not
  804. //
  805. pPerfData = (PERF_DATA_BLOCK *)pSafeBufferBlock->lpSafeBuffer;
  806. if ((pPerfData->Signature[0] == (WCHAR)'P') &&
  807. (pPerfData->Signature[1] == (WCHAR)'E') &&
  808. (pPerfData->Signature[2] == (WCHAR)'R') &&
  809. (pPerfData->Signature[3] == (WCHAR)'F'))
  810. {
  811. // if this is a foreign computer data block, then the
  812. // first object is after the header
  813. pObject = (PERF_OBJECT_TYPE *) ((LPBYTE)pPerfData + pPerfData->HeaderLength);
  814. bForeignDataBuffer = TRUE;
  815. }
  816. else
  817. {
  818. // otherwise, if this is just a buffer from
  819. // an extensible counter, the object starts
  820. // at the beginning of the buffer
  821. pObject = (PERF_OBJECT_TYPE *)pSafeBufferBlock->lpSafeBuffer;
  822. bForeignDataBuffer = FALSE;
  823. }
  824. // go to where the pointers say the end of the
  825. // buffer is and then see if it's where it
  826. // should be
  827. dwObjectBufSize = 0;
  828. for (dwIndex = 0; dwIndex < pThisExtObj->dwNumObjectsRet; dwIndex++)
  829. {
  830. dwObjectBufSize += pObject->TotalByteLength;
  831. pObject = (PERF_OBJECT_TYPE *)((LPBYTE)pObject +
  832. pObject->TotalByteLength);
  833. }
  834. if (((LPBYTE)pObject != (LPBYTE)pSafeBufferBlock->lpCallBuffer) ||
  835. (dwObjectBufSize > pSafeBufferBlock->dwCallBufSize))
  836. {
  837. // then a length field is incorrect. This is FATAL
  838. // since it can corrupt the rest of the buffer
  839. // and render the buffer unusable.
  840. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tObject in blob overruns the buffer boundary in the data returned for the \"%s\" Performance Library", GetCurrentThreadId(), pThisExtObj->szServiceName);
  841. pThisExtObj->dwObjectSizeErrors++;
  842. dwStatus = ERROR_INVALID_DATA;
  843. }
  844. //
  845. // Test 6: Test instance field size values
  846. //
  847. if (dwStatus == ERROR_SUCCESS)
  848. {
  849. // set object pointer
  850. if (bForeignDataBuffer)
  851. {
  852. pObject = (PERF_OBJECT_TYPE *) (
  853. (LPBYTE)pPerfData + pPerfData->HeaderLength);
  854. }
  855. else
  856. {
  857. // otherwise, if this is just a buffer from
  858. // an extensible counter, the object starts
  859. // at the beginning of the buffer
  860. pObject = (PERF_OBJECT_TYPE *)pSafeBufferBlock->lpSafeBuffer;
  861. }
  862. for (dwIndex = 0; dwIndex < pThisExtObj->dwNumObjectsRet; dwIndex++)
  863. {
  864. pNextObject = (PERF_OBJECT_TYPE *)((LPBYTE)pObject +
  865. pObject->TotalByteLength);
  866. if (pObject->NumInstances != PERF_NO_INSTANCES)
  867. {
  868. pInstance = (PERF_INSTANCE_DEFINITION *)
  869. ((LPBYTE)pObject + pObject->DefinitionLength);
  870. lInstIndex = 0;
  871. while (lInstIndex < pObject->NumInstances)
  872. {
  873. PERF_COUNTER_BLOCK *pCounterBlock;
  874. // NOTE: this does not walk the instance/counter block, nor does it check the validity of the addresses
  875. pCounterBlock = (PERF_COUNTER_BLOCK *)
  876. ((PCHAR) pInstance + pInstance->ByteLength);
  877. pInstance = (PERF_INSTANCE_DEFINITION *)
  878. ((PCHAR) pCounterBlock + pCounterBlock->ByteLength);
  879. lInstIndex++;
  880. }
  881. if ((LPBYTE)pInstance > (LPBYTE)pNextObject)
  882. {
  883. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tInsatnce data overruns the following object data in the data returned for the \"%s\" Performance Library", GetCurrentThreadId(), pThisExtObj->szServiceName);
  884. dwStatus = ERROR_INVALID_DATA;
  885. }
  886. }
  887. if (dwStatus != ERROR_SUCCESS)
  888. {
  889. break;
  890. }
  891. else
  892. {
  893. pObject = pNextObject;
  894. }
  895. }
  896. if (dwStatus != ERROR_SUCCESS)
  897. {
  898. pThisExtObj->dwInstanceSizeErrors++;
  899. }
  900. }
  901. }
  902. return dwStatus;
  903. }
  904. DWORD
  905. ValidateBlob( PSAFE_BUFFER pSafeBufferBlock, EXT_OBJECT *pThisExtObj )
  906. {
  907. DWORD dwStatus = ERROR_SUCCESS;
  908. DWORD nObjIdx, nCtrIdx;
  909. DWORD dwLastId = g_dwLastIndex;
  910. PERF_OBJECT_TYPE * pObjDef = NULL;
  911. PERF_COUNTER_DEFINITION * pCtrDef;
  912. // Validate the data
  913. // =================
  914. if (pSafeBufferBlock->dwBufSize >= MAX_BUF_SIZE) {
  915. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tCollectFunction for %s requires a buffer > %d bytes", GetCurrentThreadId(), pThisExtObj->szServiceName, MAX_BUF_SIZE);
  916. if (pSafeBufferBlock->lpBuffer != NULL) HeapFree (g_hTestHeap, 0, pSafeBufferBlock->lpBuffer);
  917. dwStatus = ERROR_INVALID_PARAMETER;
  918. } else if (pSafeBufferBlock->lpBuffer == NULL) {
  919. dwStatus = ERROR_OUTOFMEMORY;
  920. } else {
  921. // Validate the objects
  922. // ====================
  923. pObjDef = (PERF_OBJECT_TYPE *)pSafeBufferBlock->lpSafeBuffer;
  924. for (nObjIdx = 0; nObjIdx < pThisExtObj->dwNumObjectsRet; nObjIdx++) {
  925. // test object name & help
  926. if ((pObjDef->ObjectNameTitleIndex <= dwLastId) &&
  927. (pObjDef->ObjectNameTitleIndex > 0)) {
  928. if (g_pNameTable[pObjDef->ObjectNameTitleIndex ] == NULL) {
  929. // no string
  930. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Object Name Display String for index %d", GetCurrentThreadId(), pObjDef->ObjectNameTitleIndex );
  931. dwStatus = ERROR_BADKEY;
  932. } else {
  933. // probably ok
  934. }
  935. } else {
  936. // id out of range
  937. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tObject Name Index values are bad or missing", GetCurrentThreadId());
  938. dwStatus = ERROR_BADKEY;
  939. }
  940. if ((pObjDef->ObjectHelpTitleIndex <= dwLastId) &&
  941. (pObjDef->ObjectHelpTitleIndex> 0)) {
  942. if (g_pNameTable[pObjDef->ObjectHelpTitleIndex] == NULL) {
  943. // no string
  944. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Object Help Display String for index %d", GetCurrentThreadId(), pObjDef->ObjectHelpTitleIndex );
  945. dwStatus = ERROR_BADKEY;
  946. } else {
  947. // probably ok
  948. }
  949. } else {
  950. // id out of range
  951. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tObject Help Index values are bad or missing", GetCurrentThreadId());
  952. dwStatus = ERROR_BADKEY;
  953. }
  954. // Validate the counters
  955. // =====================
  956. pCtrDef = FirstCounter (pObjDef);
  957. for (nCtrIdx = 0; nCtrIdx < pObjDef->NumCounters; nCtrIdx++) {
  958. if ((pCtrDef->CounterNameTitleIndex <= dwLastId) &&
  959. (pCtrDef->CounterNameTitleIndex > 0)) {
  960. if ((g_pNameTable[pCtrDef->CounterNameTitleIndex ] == NULL) &&
  961. ((pCtrDef->CounterType & PERF_COUNTER_BASE) == 0)) {
  962. // no string
  963. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Counter Name Display String for index %d", GetCurrentThreadId(), pCtrDef->CounterNameTitleIndex );
  964. dwStatus = ERROR_BADKEY;
  965. } else {
  966. // probably ok
  967. }
  968. } else {
  969. // id out of range
  970. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tCounter Name Index values are bad or missing", GetCurrentThreadId());
  971. dwStatus = ERROR_BADKEY;
  972. }
  973. // test counter defs
  974. if ((pCtrDef->CounterHelpTitleIndex <= dwLastId) &&
  975. (pCtrDef->CounterHelpTitleIndex> 0)) {
  976. if ((g_pNameTable[pCtrDef->CounterHelpTitleIndex] == NULL) &&
  977. ((pCtrDef->CounterType & PERF_COUNTER_BASE) == 0)) {
  978. // no string
  979. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Counter Help Display String for index %d", GetCurrentThreadId(), pCtrDef->CounterHelpTitleIndex );
  980. dwStatus = ERROR_BADKEY;
  981. } else {
  982. // probably ok
  983. }
  984. } else {
  985. // id out of range
  986. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tCounter Help Index values are bad or missing", GetCurrentThreadId());
  987. dwStatus = ERROR_BADKEY;
  988. }
  989. if (nCtrIdx < ( pObjDef->NumCounters - 1 ) )
  990. pCtrDef = NextCounter (pCtrDef);
  991. }
  992. if ( nObjIdx < ( pThisExtObj->dwNumObjectsRet - 1 ) )
  993. pObjDef = NextObject (pObjDef);
  994. }
  995. }
  996. return dwStatus;
  997. }
  998. DWORD
  999. Validate( PSAFE_BUFFER pSafeBufferBlock, EXT_OBJECT *pThisExtObj )
  1000. {
  1001. DWORD dwStatus = ERROR_SUCCESS;
  1002. dwStatus = ValidateBuffer( pSafeBufferBlock, pThisExtObj );
  1003. if (dwStatus == ERROR_SUCCESS)
  1004. {
  1005. dwStatus = ValidateBlob( pSafeBufferBlock, pThisExtObj );
  1006. if ( dwStatus != ERROR_SUCCESS )
  1007. {
  1008. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tBlob Data Validation failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pThisExtObj->szServiceName, dwStatus);
  1009. }
  1010. }
  1011. else
  1012. {
  1013. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tBuffer Validation failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pThisExtObj->szServiceName, dwStatus);
  1014. }
  1015. return dwStatus;
  1016. }
  1017. //***************************************************************************
  1018. //
  1019. // CollectData (LPBYTE pBuffer,
  1020. // LPDWORD pdwBufferSize,
  1021. // LPWSTR pszItemList)
  1022. //
  1023. // Collects data from the perf objects and libraries added to the access
  1024. // object
  1025. //
  1026. // Inputs:
  1027. //
  1028. // pBuffer - pointer to start of data block
  1029. // where data is being collected
  1030. //
  1031. // pdwBufferSize - pointer to size of data buffer
  1032. //
  1033. // pszItemList - string to pass to ext DLL
  1034. //
  1035. // Outputs:
  1036. //
  1037. // *lppDataDefinition - set to location for next Type
  1038. // Definition if successful
  1039. //
  1040. // Returns:
  1041. //
  1042. // 0 if successful, else Win 32 error code of failure
  1043. //
  1044. //
  1045. //***************************************************************************
  1046. //
  1047. DWORD
  1048. CollectData (EXT_OBJECT *pThisExtObj)
  1049. {
  1050. DWORD dwStatus = ERROR_SUCCESS; // Failure code
  1051. SAFE_BUFFER SafeBufferBlock; // Buffer block
  1052. DWORD NumObjectTypes = 0; // Number of object returned from collection function
  1053. LARGE_INTEGER liStartTime, // Collect start time
  1054. liEndTime, // Collect end time
  1055. liFreq; // Timer frequency
  1056. DOUBLE dMs = 0; // Timer data
  1057. memset(&SafeBufferBlock, 0, sizeof(SAFE_BUFFER));
  1058. SafeBufferBlock.dwBufSize = 4098;
  1059. SafeBufferBlock.dwBufSizeIncrement = 1024;
  1060. // Collect the data
  1061. // ================
  1062. dwStatus = ERROR_MORE_DATA;
  1063. while ((dwStatus == ERROR_MORE_DATA) && (SafeBufferBlock.dwBufSize < MAX_BUF_SIZE))
  1064. {
  1065. // allocate a local block of memory to pass to the
  1066. // extensible counter function.
  1067. dwStatus = CreateSafeBuffer( &SafeBufferBlock );
  1068. if ( dwStatus == ERROR_SUCCESS )
  1069. {
  1070. // initialize values to pass to the extensible counter function
  1071. NumObjectTypes = 0;
  1072. if ((pThisExtObj->hMutex != NULL) &&
  1073. (pThisExtObj->CollectProc != NULL))
  1074. {
  1075. dwStatus = WaitForSingleObject ( pThisExtObj->hMutex, pThisExtObj->dwCollectTimeout);
  1076. if (dwStatus != WAIT_TIMEOUT)
  1077. {
  1078. __try
  1079. {
  1080. QueryPerformanceCounter (&liStartTime);
  1081. {
  1082. LPBYTE pBuffer = SafeBufferBlock.lpCallBuffer;
  1083. DWORD dwBufSize = SafeBufferBlock.dwCallBufSize;
  1084. dwStatus = (*pThisExtObj->CollectProc) (
  1085. (LPWSTR)pThisExtObj->szQueryString,
  1086. &pBuffer,
  1087. &dwBufSize,
  1088. &NumObjectTypes);
  1089. SafeBufferBlock.dwCallBufSize = dwBufSize;
  1090. SafeBufferBlock.lpCallBuffer = pBuffer;
  1091. }
  1092. QueryPerformanceCounter (&liEndTime);
  1093. if (( dwStatus != ERROR_SUCCESS ) && ( dwStatus != ERROR_MORE_DATA ))
  1094. {
  1095. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \t%S failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pThisExtObj->szCollectProcName, pThisExtObj->szServiceName, dwStatus);
  1096. }
  1097. }
  1098. __except (EXCEPTION_EXECUTE_HANDLER)
  1099. {
  1100. dwStatus = GetExceptionCode();
  1101. InterlockedIncrement ((LONG *)&pThisExtObj->dwExceptionCount);
  1102. }
  1103. ReleaseMutex (pThisExtObj->hMutex);
  1104. }
  1105. else
  1106. {
  1107. pThisExtObj->dwLockoutCount++;
  1108. }
  1109. }
  1110. else
  1111. {
  1112. dwStatus = ERROR_LOCK_FAILED;
  1113. }
  1114. } // if CreateSafeBuffer()
  1115. } // While
  1116. // Copy the data
  1117. // =============
  1118. if (dwStatus == ERROR_SUCCESS)
  1119. {
  1120. // Validate the collection time
  1121. if (dwStatus == ERROR_SUCCESS)
  1122. {
  1123. liFreq.QuadPart = 0;
  1124. QueryPerformanceFrequency (&liFreq);
  1125. pThisExtObj->llTimeBase = liFreq.QuadPart;
  1126. pThisExtObj->llFunctionTime = liEndTime.QuadPart - liStartTime.QuadPart;
  1127. pThisExtObj->llCollectTime += pThisExtObj->llFunctionTime;
  1128. // check the time spent in this function
  1129. dMs = (DOUBLE)pThisExtObj->llFunctionTime;
  1130. dMs /= (DOUBLE)pThisExtObj->llTimeBase;
  1131. dMs *= 1000.0;
  1132. if (dMs > (DOUBLE)pThisExtObj->dwCollectTimeout)
  1133. {
  1134. dwStatus = ERROR_TIMEOUT;
  1135. }
  1136. }
  1137. // Copy the data
  1138. if (dwStatus == ERROR_SUCCESS)
  1139. {
  1140. // External object data
  1141. GetSystemTimeAsFileTime((FILETIME*)&pThisExtObj->llLastUsedTime);
  1142. pThisExtObj->dwNumObjectsRet = NumObjectTypes;
  1143. pThisExtObj->dwRetBufSize = SafeBufferBlock.dwCallBufSize;
  1144. // increment perf counters
  1145. InterlockedIncrement ((LONG *)&pThisExtObj->dwCollectCount);
  1146. }
  1147. // Validate the data
  1148. if ((dwStatus == ERROR_SUCCESS) &&
  1149. (g_LTData.bTestContents))
  1150. {
  1151. dwStatus = Validate( &SafeBufferBlock, pThisExtObj );
  1152. }
  1153. }
  1154. ClearSafeBuffer(&SafeBufferBlock);
  1155. if ((dwStatus != ERROR_SUCCESS) &&
  1156. (dwStatus != WAIT_TIMEOUT)) // don't count timeouts as function errors
  1157. {
  1158. InterlockedIncrement ((LONG *)&pThisExtObj->dwErrorCount);
  1159. }
  1160. return dwStatus;
  1161. }
  1162. DWORD
  1163. CloseLibrary (
  1164. EXT_OBJECT *pInfo
  1165. )
  1166. {
  1167. DWORD dwStatus = ERROR_SUCCESS;
  1168. if (pInfo != NULL) {
  1169. // if there's a close proc to call, then
  1170. // call close procedure to close anything that may have
  1171. // been allocated by the library
  1172. if ((pInfo->hMutex != NULL) &&
  1173. (pInfo->CloseProc != NULL)){
  1174. dwStatus = WaitForSingleObject (
  1175. pInfo->hMutex,
  1176. pInfo->dwOpenTimeout);
  1177. if (dwStatus != WAIT_TIMEOUT) {
  1178. if (pInfo->CloseProc != NULL) {
  1179. dwStatus = (*pInfo->CloseProc) ();
  1180. if ( dwStatus != ERROR_SUCCESS )
  1181. {
  1182. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \t%S failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pInfo->szCloseProcName, pInfo->szServiceName, dwStatus);
  1183. }
  1184. }
  1185. ReleaseMutex(pInfo->hMutex);
  1186. } else {
  1187. pInfo->dwLockoutCount++;
  1188. }
  1189. } else {
  1190. dwStatus = ERROR_LOCK_FAILED;
  1191. }
  1192. if (pInfo->hLibrary != NULL) {
  1193. FreeLibrary (pInfo->hLibrary);
  1194. pInfo->hLibrary = NULL;
  1195. }
  1196. }
  1197. return dwStatus;
  1198. }
  1199. static
  1200. LPWSTR
  1201. *BuildNameTable(
  1202. LPCWSTR szMachineName,
  1203. LPCWSTR lpszLangIdArg, // unicode value of Language subkey
  1204. PDWORD pdwLastItem, // size of array in elements
  1205. PDWORD pdwIdArray // array for index ID's
  1206. )
  1207. /*++
  1208. BuildNameTable
  1209. Arguments:
  1210. hKeyRegistry
  1211. Handle to an open registry (this can be local or remote.) and
  1212. is the value returned by RegConnectRegistry or a default key.
  1213. lpszLangId
  1214. The unicode id of the language to look up. (default is 409)
  1215. Return Value:
  1216. pointer to an allocated table. (the caller must MemoryFree it when finished!)
  1217. the table is an array of pointers to zero terminated strings. NULL is
  1218. returned if an error occured.
  1219. --*/
  1220. {
  1221. HKEY hKeyRegistry; // handle to registry db with counter names
  1222. LPWSTR *lpReturnValue;
  1223. LPCWSTR lpszLangId;
  1224. LPWSTR *lpCounterId;
  1225. LPWSTR lpCounterNames;
  1226. LPWSTR lpHelpText;
  1227. LPWSTR lpThisName;
  1228. LONG lWin32Status;
  1229. DWORD dwValueType;
  1230. DWORD dwArraySize;
  1231. DWORD dwBufferSize;
  1232. DWORD dwCounterSize;
  1233. DWORD dwHelpSize;
  1234. DWORD dwThisCounter;
  1235. DWORD dwLastId;
  1236. DWORD dwLastHelpId;
  1237. DWORD dwLastCounterIdUsed;
  1238. DWORD dwLastHelpIdUsed;
  1239. HKEY hKeyValue;
  1240. HKEY hKeyNames;
  1241. LPWSTR lpValueNameString;
  1242. WCHAR CounterNameBuffer [50];
  1243. WCHAR HelpNameBuffer [50];
  1244. SetLastError (ERROR_SUCCESS);
  1245. szTestErrorMessage = NULL;
  1246. if (szMachineName != NULL) {
  1247. lWin32Status = RegConnectRegistryW (szMachineName,
  1248. HKEY_LOCAL_MACHINE,
  1249. &hKeyRegistry);
  1250. } else {
  1251. lWin32Status = ERROR_SUCCESS;
  1252. hKeyRegistry = HKEY_LOCAL_MACHINE;
  1253. }
  1254. lpValueNameString = NULL; //initialize to NULL
  1255. lpReturnValue = NULL;
  1256. hKeyValue = NULL;
  1257. hKeyNames = NULL;
  1258. // check for null arguments and insert defaults if necessary
  1259. if (!lpszLangIdArg) {
  1260. lpszLangId = cszDefaultLangId;
  1261. } else {
  1262. lpszLangId = lpszLangIdArg;
  1263. }
  1264. // open registry to get number of items for computing array size
  1265. lWin32Status = RegOpenKeyExW (
  1266. hKeyRegistry,
  1267. cszNamesKey,
  1268. 0L,
  1269. KEY_READ,
  1270. &hKeyValue);
  1271. if (lWin32Status != ERROR_SUCCESS) {
  1272. szTestErrorMessage = (LPWSTR)L"Unable to Open Perflib key";
  1273. goto BNT_BAILOUT;
  1274. }
  1275. // get config info
  1276. dwValueType = 0;
  1277. dwBufferSize = sizeof (pdwIdArray[4]);
  1278. lWin32Status = RegQueryValueExW (
  1279. hKeyValue,
  1280. (LPCWSTR)L"Disable Performance Counters",
  1281. 0L,
  1282. &dwValueType,
  1283. (LPBYTE)&pdwIdArray[4],
  1284. &dwBufferSize);
  1285. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  1286. if (lWin32Status == ERROR_FILE_NOT_FOUND) {
  1287. // this is OK since the value need not be present
  1288. pdwIdArray[4] = (DWORD)-1;
  1289. lWin32Status = ERROR_SUCCESS;
  1290. } else {
  1291. szTestErrorMessage = (LPWSTR)L"Unable to read Disable Performance Counters value";
  1292. goto BNT_BAILOUT;
  1293. }
  1294. }
  1295. dwValueType = 0;
  1296. dwBufferSize = sizeof (pdwIdArray[5]);
  1297. lWin32Status = RegQueryValueExW (
  1298. hKeyValue,
  1299. (LPCWSTR)L"ExtCounterTestLevel",
  1300. 0L,
  1301. &dwValueType,
  1302. (LPBYTE)&pdwIdArray[5],
  1303. &dwBufferSize);
  1304. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  1305. if (lWin32Status == ERROR_FILE_NOT_FOUND) {
  1306. // this is OK since the value need not be present
  1307. pdwIdArray[5] = (DWORD)-1;
  1308. lWin32Status = ERROR_SUCCESS;
  1309. } else {
  1310. szTestErrorMessage = (LPWSTR)L"Unable to read ExCounterTestLevel value";
  1311. goto BNT_BAILOUT;
  1312. }
  1313. }
  1314. dwValueType = 0;
  1315. dwBufferSize = sizeof (pdwIdArray[6]);
  1316. lWin32Status = RegQueryValueExW (
  1317. hKeyValue,
  1318. (LPCWSTR)L"Base Index",
  1319. 0L,
  1320. &dwValueType,
  1321. (LPBYTE)&pdwIdArray[6],
  1322. &dwBufferSize);
  1323. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  1324. szTestErrorMessage = (LPWSTR)L"Unable to read Base Index value";
  1325. goto BNT_BAILOUT;
  1326. }
  1327. // get number of items
  1328. dwBufferSize = sizeof (dwLastHelpId);
  1329. lWin32Status = RegQueryValueExW (
  1330. hKeyValue,
  1331. cszLastHelp,
  1332. 0L,
  1333. &dwValueType,
  1334. (LPBYTE)&dwLastHelpId,
  1335. &dwBufferSize);
  1336. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  1337. szTestErrorMessage = (LPWSTR)L"Unable to read Last Help value";
  1338. goto BNT_BAILOUT;
  1339. }
  1340. pdwIdArray[2] = dwLastHelpId;
  1341. // get number of items
  1342. dwBufferSize = sizeof (dwLastId);
  1343. lWin32Status = RegQueryValueExW (
  1344. hKeyValue,
  1345. cszLastCounter,
  1346. 0L,
  1347. &dwValueType,
  1348. (LPBYTE)&dwLastId,
  1349. &dwBufferSize);
  1350. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  1351. szTestErrorMessage = (LPWSTR)L"Unable to read Last Counter value";
  1352. goto BNT_BAILOUT;
  1353. }
  1354. pdwIdArray[0] = dwLastId;
  1355. if (dwLastId < dwLastHelpId)
  1356. dwLastId = dwLastHelpId;
  1357. dwArraySize = dwLastId * sizeof(LPWSTR);
  1358. // get Perflib system version
  1359. if (szMachineName[0] == 0) {
  1360. hKeyNames = HKEY_PERFORMANCE_DATA;
  1361. } else {
  1362. lWin32Status = RegConnectRegistryW (szMachineName,
  1363. HKEY_PERFORMANCE_DATA,
  1364. &hKeyNames);
  1365. }
  1366. lstrcpyW (CounterNameBuffer, cszCounterName);
  1367. lstrcatW (CounterNameBuffer, lpszLangId);
  1368. lstrcpyW (HelpNameBuffer, cszHelpName);
  1369. lstrcatW (HelpNameBuffer, lpszLangId);
  1370. // get size of counter names and add that to the arrays
  1371. dwBufferSize = 0;
  1372. lWin32Status = RegQueryValueExW (
  1373. hKeyNames,
  1374. CounterNameBuffer,
  1375. 0L,
  1376. &dwValueType,
  1377. NULL,
  1378. &dwBufferSize);
  1379. if (lWin32Status != ERROR_SUCCESS) {
  1380. szTestErrorMessage = (LPWSTR)L"Unable to query counter string size";
  1381. goto BNT_BAILOUT;
  1382. }
  1383. dwCounterSize = dwBufferSize;
  1384. // get size of counter names and add that to the arrays
  1385. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  1386. dwBufferSize = 0;
  1387. lWin32Status = RegQueryValueExW (
  1388. hKeyNames,
  1389. HelpNameBuffer,
  1390. 0L,
  1391. &dwValueType,
  1392. NULL,
  1393. &dwBufferSize);
  1394. if (lWin32Status != ERROR_SUCCESS) {
  1395. szTestErrorMessage = (LPWSTR)L"Unable to query help string size";
  1396. goto BNT_BAILOUT;
  1397. }
  1398. dwHelpSize = dwBufferSize;
  1399. lpReturnValue = (LPWSTR *)HeapAlloc (g_hTestHeap, 0,dwArraySize + dwCounterSize + dwHelpSize);
  1400. if (!lpReturnValue) {
  1401. lWin32Status = ERROR_OUTOFMEMORY;
  1402. szTestErrorMessage = (LPWSTR)L"Unable to allocate name string buffer";
  1403. goto BNT_BAILOUT;
  1404. }
  1405. // initialize pointers into buffer
  1406. lpCounterId = lpReturnValue;
  1407. lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize);
  1408. lpHelpText = (LPWSTR)((LPBYTE)lpCounterNames + dwCounterSize);
  1409. // read counters into memory
  1410. dwBufferSize = dwCounterSize;
  1411. lWin32Status = RegQueryValueExW (
  1412. hKeyNames,
  1413. CounterNameBuffer,
  1414. 0L,
  1415. &dwValueType,
  1416. (LPBYTE)lpCounterNames,
  1417. &dwBufferSize);
  1418. if (lWin32Status != ERROR_SUCCESS) {
  1419. szTestErrorMessage = (LPWSTR)L"Unable to query counter string contents";
  1420. goto BNT_BAILOUT;
  1421. }
  1422. dwBufferSize = dwHelpSize;
  1423. lWin32Status = RegQueryValueExW (
  1424. hKeyNames,
  1425. HelpNameBuffer,
  1426. 0L,
  1427. &dwValueType,
  1428. (LPBYTE)lpHelpText,
  1429. &dwBufferSize);
  1430. if (lWin32Status != ERROR_SUCCESS) {
  1431. szTestErrorMessage = (LPWSTR)L"Unable to query help string contents";
  1432. goto BNT_BAILOUT;
  1433. }
  1434. dwLastCounterIdUsed = 0;
  1435. dwLastHelpIdUsed = 0;
  1436. // load counter array items
  1437. for (lpThisName = lpCounterNames;
  1438. *lpThisName;
  1439. lpThisName += (lstrlenW(lpThisName)+1) ) {
  1440. // first string should be an integer (in decimal unicode digits)
  1441. dwThisCounter = wcstoul (lpThisName, NULL, 10);
  1442. if (dwThisCounter == 0) {
  1443. lWin32Status = ERROR_BADKEY;
  1444. szTestErrorMessage = (LPWSTR)L"Bad counter string entry, CONFIG_String_LastCounter is last valid counter string index";
  1445. goto BNT_BAILOUT; // bad entry
  1446. }
  1447. // point to corresponding counter name
  1448. lpThisName += (lstrlenW(lpThisName)+1);
  1449. // and load array element;
  1450. lpCounterId[dwThisCounter] = lpThisName;
  1451. if (dwThisCounter > dwLastCounterIdUsed) dwLastCounterIdUsed = dwThisCounter;
  1452. }
  1453. pdwIdArray[1] = dwLastCounterIdUsed;
  1454. for (lpThisName = lpHelpText;
  1455. *lpThisName;
  1456. lpThisName += (lstrlenW(lpThisName)+1) ) {
  1457. // first string should be an integer (in decimal unicode digits)
  1458. dwThisCounter = wcstoul (lpThisName, NULL, 10);
  1459. if (dwThisCounter == 0) {
  1460. lWin32Status = ERROR_BADKEY;
  1461. szTestErrorMessage = (LPWSTR)L"Bad help string entry, CONFIG_String_LastHelp is last valid counter string index";
  1462. goto BNT_BAILOUT; // bad entry
  1463. }
  1464. // point to corresponding counter name
  1465. lpThisName += (lstrlenW(lpThisName)+1);
  1466. // and load array element;
  1467. lpCounterId[dwThisCounter] = lpThisName;
  1468. if (dwThisCounter > dwLastHelpIdUsed) dwLastHelpIdUsed= dwThisCounter;
  1469. }
  1470. pdwIdArray[3] = dwLastHelpIdUsed;
  1471. dwLastId = dwLastHelpIdUsed;
  1472. if (dwLastId < dwLastCounterIdUsed) dwLastId = dwLastCounterIdUsed;
  1473. if (pdwLastItem) *pdwLastItem = dwLastId;
  1474. HeapFree (g_hTestHeap, 0, (LPVOID)lpValueNameString);
  1475. RegCloseKey (hKeyValue);
  1476. RegCloseKey (hKeyNames);
  1477. RegCloseKey(hKeyRegistry);
  1478. return lpReturnValue;
  1479. BNT_BAILOUT:
  1480. if (lWin32Status != ERROR_SUCCESS) {
  1481. SetLastError (lWin32Status);
  1482. }
  1483. if (lpValueNameString) {
  1484. HeapFree (g_hTestHeap, 0, (LPVOID)lpValueNameString);
  1485. }
  1486. if (lpReturnValue) {
  1487. HeapFree (g_hTestHeap, 0, (LPVOID)lpValueNameString);
  1488. }
  1489. if (hKeyValue)
  1490. RegCloseKey (hKeyValue);
  1491. if (hKeyNames)
  1492. RegCloseKey (hKeyNames);
  1493. if (hKeyRegistry)
  1494. RegCloseKey(hKeyRegistry);
  1495. return NULL;
  1496. }
  1497. DWORD
  1498. CycleTest (
  1499. DWORD dwThreadId,
  1500. PEXT_OBJECT pObj
  1501. )
  1502. {
  1503. DWORD dwStatus = ERROR_SUCCESS;
  1504. DWORD dwLoopCount = g_LTData.dwLoopCount;
  1505. BOOL bPrintData = g_LTData.bDisplay;
  1506. DOUBLE dMs;
  1507. UNREFERENCED_PARAMETER (dwThreadId);
  1508. // Open the Library
  1509. // ================
  1510. dwStatus = OpenLibrary (pObj);
  1511. if ((dwStatus == ERROR_SUCCESS) &&
  1512. (pObj != NULL)) {
  1513. // an object info block was returned
  1514. dMs = (DOUBLE)pObj->llOpenTime; // ticks used
  1515. dMs /= (DOUBLE)pObj->llTimeBase; // ticks/sec
  1516. dMs *= 1000.0; // ms/Sec
  1517. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_OpenServiceName: \t%s", GetCurrentThreadId(), pObj->szServiceName);
  1518. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_OpenProcTime: \t%12.5f mSec", GetCurrentThreadId(), dMs);
  1519. // fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_OpenProcTimeout: \t%6d.00000 mSec", GetCurrentThreadId(), pObj->dwOpenTimeout);
  1520. // check for timeout
  1521. if (dMs > (DOUBLE)pObj->dwOpenTimeout) {
  1522. dwStatus = ERROR_TIMEOUT;
  1523. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tOpen procedure exceeded timeout", GetCurrentThreadId());
  1524. CloseLibrary (pObj);
  1525. }
  1526. } else {
  1527. // no object block returned
  1528. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tUnable to open the \"%s\" Performance Library", GetCurrentThreadId(), pObj->szServiceName);
  1529. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORCODE:\t0x%8.8x (%dL)", GetCurrentThreadId(), dwStatus, dwStatus);
  1530. }
  1531. // Collect Data for "dwLoopCount" times
  1532. // ====================================
  1533. if (dwStatus == ERROR_SUCCESS)
  1534. {
  1535. HeapValidate (g_hTestHeap, 0, NULL);
  1536. // call collect function
  1537. do
  1538. {
  1539. // get the data again
  1540. dwStatus = CollectData (pObj);
  1541. HeapValidate (g_hTestHeap, 0, NULL);
  1542. } while (--dwLoopCount > 0);
  1543. // Close Library
  1544. // =============
  1545. // Even if we get an error, we should try to close the library
  1546. // ===========================================================
  1547. CloseLibrary (pObj);
  1548. // Report Status
  1549. // =============
  1550. if (dwStatus == ERROR_SUCCESS) {
  1551. // dump collect fn stats.
  1552. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_ServiceName: \t%s", GetCurrentThreadId(), pObj->szServiceName);
  1553. if ((pObj->dwCollectCount > 0) && (pObj->dwNumObjectsRet > 0)){
  1554. // don't compute time if no objects were returned
  1555. dMs = (DOUBLE)pObj->llCollectTime;
  1556. dMs /= (DOUBLE)pObj->llTimeBase;
  1557. dMs *= 1000.0;
  1558. dMs /= (DOUBLE)pObj->dwCollectCount;
  1559. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_AvgCollectProcTime: \t%12.5f mSec", GetCurrentThreadId(), dMs);
  1560. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_CollectProcTimeout: \t%6d.00000 mSec", GetCurrentThreadId(), pObj->dwCollectTimeout);
  1561. }
  1562. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_ObjectsRet: \t%d", GetCurrentThreadId(), pObj->dwNumObjectsRet);
  1563. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_RetBuffSize: \t%d", GetCurrentThreadId(), pObj->dwRetBufSize);
  1564. } else {
  1565. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tCollect procedure returned an error", GetCurrentThreadId());
  1566. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORCODE:\t0x%8.8x (%dL)", GetCurrentThreadId(), dwStatus, dwStatus);
  1567. // output the contents of the info buffer
  1568. if (dwStatus == ERROR_TIMEOUT) {
  1569. // dump collect fn stats.
  1570. dMs = (DOUBLE)pObj->llFunctionTime;
  1571. dMs /= (DOUBLE)pObj->llTimeBase;
  1572. dMs *= 1000.0;
  1573. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectService: \t%s", GetCurrentThreadId(), pObj->szServiceName);
  1574. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectProcTime:\t%12.5f mSec", GetCurrentThreadId(), dMs);
  1575. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectTimeout: \t%6d.00000 mSec", GetCurrentThreadId(), pObj->dwCollectTimeout);
  1576. }
  1577. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectService: \t%s", GetCurrentThreadId(), pObj->szServiceName);
  1578. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectTime: \t%I64u", GetCurrentThreadId(), pObj->llCollectTime);
  1579. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectCount:\t%d", GetCurrentThreadId(), pObj->dwCollectCount);
  1580. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_OpenCount: \t%d", GetCurrentThreadId(), pObj->dwOpenCount);
  1581. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CloseCount: \t%d", GetCurrentThreadId(), pObj->dwCloseCount);
  1582. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_LockoutCount:\t%d", GetCurrentThreadId(), pObj->dwLockoutCount);
  1583. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_ErrorCount: \t%d", GetCurrentThreadId(), pObj->dwErrorCount);
  1584. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_Exceptions: \t%d", GetCurrentThreadId(), pObj->dwExceptionCount);
  1585. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_LowerGPErrs: \t%d", GetCurrentThreadId(), pObj->dwLowerGPViolations);
  1586. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_UpperGPErrs: \t%d", GetCurrentThreadId(), pObj->dwUpperGPViolations);
  1587. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_BadPointers: \t%d", GetCurrentThreadId(), pObj->dwBadPointers);
  1588. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_BufSizeErrs: \t%d", GetCurrentThreadId(), pObj->dwBufferSizeErrors);
  1589. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_AlignErrors: \t%d", GetCurrentThreadId(), pObj->dwAlignmentErrors);
  1590. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_ObjSizeErrs: \t%d", GetCurrentThreadId(), pObj->dwObjectSizeErrors);
  1591. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_InstSizeErrs:\t%d", GetCurrentThreadId(), pObj->dwInstanceSizeErrors);
  1592. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_TimeBase: \t%I64u", GetCurrentThreadId(), pObj->llTimeBase);
  1593. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_FunctionTime:\t%I64u", GetCurrentThreadId(), pObj->llFunctionTime);
  1594. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_ObjectsRet: \t%d", GetCurrentThreadId(), pObj->dwNumObjectsRet);
  1595. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_RetBuffSize: \t%d", GetCurrentThreadId(), pObj->dwRetBufSize);
  1596. }
  1597. }
  1598. HeapValidate (g_hTestHeap, 0, NULL);
  1599. return dwStatus;
  1600. }
  1601. unsigned __stdcall CycleThreadProc( void * lpThreadArg )
  1602. {
  1603. DWORD dwStatus = ERROR_SUCCESS;
  1604. DWORD dwCycleCount = g_LTData.dwCycleCount;
  1605. DWORD dwThreadNum = *((DWORD*)lpThreadArg);
  1606. PEXT_OBJECT pObj = NULL;
  1607. EXT_OBJECT ThreadObj;
  1608. DWORD dwThisThread = GetCurrentThreadId();
  1609. HeapValidate (g_hTestHeap, 0, NULL);
  1610. srand( GetTickCount() );
  1611. do {
  1612. // If the rand flag is set, randomly choose an object to hit
  1613. if (g_fRand)
  1614. {
  1615. pObj = &g_pExtObjects[rand()%g_LTData.dwNumObjects];
  1616. }
  1617. else
  1618. {
  1619. pObj = &g_pExtObjects[dwThreadNum];
  1620. }
  1621. if ( pObj->bValid )
  1622. {
  1623. memcpy(&ThreadObj, pObj, sizeof(EXT_OBJECT));
  1624. dwStatus = CycleTest(dwThisThread, &ThreadObj);
  1625. // What error handling mode are we using?
  1626. if (g_LTData.bStopOnError)
  1627. {
  1628. if (( ERROR_SUCCESS != dwStatus ) &&
  1629. (ERROR_INVALID_DATA != dwStatus))
  1630. {
  1631. SetEvent( g_hEvent );
  1632. }
  1633. else
  1634. {
  1635. if ( WAIT_OBJECT_0 == WaitForSingleObject( g_hEvent, 0 ) )
  1636. break;
  1637. dwStatus = ERROR_SUCCESS;
  1638. }
  1639. }
  1640. }
  1641. } while (--dwCycleCount > 0);
  1642. HeapValidate (g_hTestHeap, 0, NULL);
  1643. return dwStatus;
  1644. }
  1645. DWORD Initialize( WCHAR* szIniFileName, DWORD* pdwThreadCount )
  1646. {
  1647. DWORD dwStatus = ERROR_SUCCESS;
  1648. BOOL bStatus = FALSE;
  1649. WCHAR wcsReturnBuff[256];
  1650. WCHAR wcsKeyName[256];
  1651. DWORD dwCtr = 0;
  1652. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_INI_File_Name:\t%s", szIniFileName);
  1653. fwprintf (g_pOutput, (LPCWSTR)L"\n");
  1654. // LTData
  1655. GetPrivateProfileStringW( L"Main", L"NumObjects", L"0", wcsReturnBuff, 256, szIniFileName );
  1656. g_LTData.dwNumObjects = wcstoul(wcsReturnBuff, NULL, 10);
  1657. GetPrivateProfileStringW( L"Main", L"CycleCount", L"0", wcsReturnBuff, 256, szIniFileName );
  1658. g_LTData.dwCycleCount = wcstoul(wcsReturnBuff, NULL, 10);
  1659. GetPrivateProfileStringW( L"Main", L"LoopCount", L"0", wcsReturnBuff, 256, szIniFileName );
  1660. g_LTData.dwLoopCount = wcstoul(wcsReturnBuff, NULL, 10);
  1661. GetPrivateProfileStringW( L"Main", L"StopOnError", L"0", wcsReturnBuff, 256, szIniFileName );
  1662. g_LTData.bStopOnError = wcstoul(wcsReturnBuff, NULL, 10);
  1663. g_LTData.bDisplay = TRUE;
  1664. g_LTData.bTestContents = TRUE;
  1665. // Other
  1666. GetPrivateProfileStringW( L"Main", L"NumThreads", L"0", wcsReturnBuff, 256, szIniFileName );
  1667. *pdwThreadCount = wcstoul(wcsReturnBuff, NULL, 10);
  1668. if ( *pdwThreadCount < g_LTData.dwNumObjects )
  1669. {
  1670. *pdwThreadCount = g_LTData.dwNumObjects;
  1671. }
  1672. GetPrivateProfileStringW( L"Main", L"Random", L"0", wcsReturnBuff, 256, szIniFileName );
  1673. g_fRand = wcstoul(wcsReturnBuff, NULL, 10);
  1674. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Perf_Objects: \t%d", g_LTData.dwNumObjects);
  1675. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Test_Cycles: \t%d", g_LTData.dwCycleCount);
  1676. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Collects_Per_Cycle:\t%d", g_LTData.dwLoopCount);
  1677. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Display_Results: \t%s", (g_LTData.bDisplay?L"Yes":L"No"));
  1678. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Validate_Data: \t%s", (g_LTData.bTestContents?L"Yes":L"No"));
  1679. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Threads: \t%d", *pdwThreadCount);
  1680. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Randomize_Perf_Objects: \t%s", (g_fRand?L"Yes":L"No"));
  1681. fwprintf (g_pOutput, (LPCWSTR)L"\n");
  1682. g_pExtObjects = (EXT_OBJECT*) HeapAlloc(g_hTestHeap,
  1683. HEAP_ZERO_MEMORY,
  1684. g_LTData.dwNumObjects * sizeof(EXT_OBJECT));
  1685. if ( NULL != g_pExtObjects )
  1686. {
  1687. for( dwCtr = 0; dwCtr < g_LTData.dwNumObjects; dwCtr++ )
  1688. {
  1689. // Service name
  1690. swprintf( wcsKeyName, L"Object%d", dwCtr );
  1691. GetPrivateProfileStringW( L"Main", wcsKeyName, L"PerfProc", wcsReturnBuff, 256, szIniFileName );
  1692. g_pExtObjects[dwCtr].szServiceName = (WCHAR*) HeapAlloc( g_hTestHeap, 0,
  1693. ( wcslen( wcsReturnBuff ) + 1 ) * sizeof(WCHAR) );
  1694. wcscpy( g_pExtObjects[dwCtr].szServiceName, wcsReturnBuff );
  1695. // Query string
  1696. swprintf( wcsKeyName, L"Counter%d", dwCtr );
  1697. GetPrivateProfileStringW( L"Main", wcsKeyName, L"Global", wcsReturnBuff, 256, szIniFileName );
  1698. g_pExtObjects[dwCtr].szQueryString = (WCHAR*) HeapAlloc( g_hTestHeap, 0,
  1699. ( wcslen( wcsReturnBuff ) + 1 ) * sizeof(WCHAR) );
  1700. wcscpy( g_pExtObjects[dwCtr].szQueryString, wcsReturnBuff );
  1701. // At least one object has to succeed
  1702. bStatus = ( ( ERROR_SUCCESS == InitializeExtObj( &g_pExtObjects[dwCtr] )) || bStatus);
  1703. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Perf_Object: \t%s : %s",g_pExtObjects[dwCtr].szServiceName, (g_pExtObjects[dwCtr].bValid?L"Active":L"Inactive"));
  1704. }
  1705. }
  1706. fwprintf (g_pOutput, (LPCWSTR)L"\n");
  1707. if (!bStatus)
  1708. {
  1709. dwStatus = ERROR_INVALID_DATA;
  1710. }
  1711. return dwStatus;
  1712. }
  1713. int
  1714. WriteTestResultHeader()
  1715. {
  1716. OSVERSIONINFOW osInfo;
  1717. WCHAR szMachineName[MAX_PATH];
  1718. DWORD dwSize;
  1719. SYSTEMTIME stStart;
  1720. memset (&osInfo, 0, sizeof(osInfo));
  1721. osInfo.dwOSVersionInfoSize = sizeof(osInfo);
  1722. memset (szMachineName, 0, sizeof(szMachineName));
  1723. memset (&stStart, 0, sizeof(stStart));
  1724. GetVersionExW (&osInfo);
  1725. dwSize = sizeof(szMachineName) / sizeof (szMachineName[0]);
  1726. GetComputerNameW (&szMachineName[0], &dwSize);
  1727. GetLocalTime (&stStart);
  1728. fwprintf (g_pOutput, (LPCWSTR)L"\n[TESTRESULT]");
  1729. fwprintf (g_pOutput, (LPCWSTR)L"\n\tTEST: \tPerf Counter DLL Validation");
  1730. fwprintf (g_pOutput, (LPCWSTR)L"\n\tBUILD: \t%d", osInfo.dwBuildNumber);
  1731. fwprintf (g_pOutput, (LPCWSTR)L"\n\tMACHINE:\t%s", szMachineName);
  1732. fwprintf (g_pOutput, (LPCWSTR)L"\n\t%d:START TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d",
  1733. GetCurrentThreadId(),
  1734. stStart.wMonth, stStart.wDay, stStart.wYear % 100,
  1735. stStart.wHour, stStart.wMinute, stStart.wSecond );
  1736. return 0;
  1737. }
  1738. int
  1739. WriteTestConfigData(
  1740. LPDWORD pdwIdInfo
  1741. )
  1742. {
  1743. fwprintf (g_pOutput, (LPCWSTR)L"\n\t");
  1744. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Perflib_LastCounter:\t%d", pdwIdInfo[0]);
  1745. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_String_LastCounter: \t%d", pdwIdInfo[1]);
  1746. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Perflib_LastHelp: \t%d", pdwIdInfo[2]);
  1747. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_String_LastHelp: \t%d", pdwIdInfo[3]);
  1748. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Disabled: \t%d", pdwIdInfo[4]);
  1749. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_ExtCounterTestLevel:\t%d", pdwIdInfo[5]);
  1750. fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_BaseIndex: \t%d", pdwIdInfo[6]);
  1751. // fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_BaseOsObject : \t%d", pdwIdInfo[7]);
  1752. return 0;
  1753. }
  1754. DWORD
  1755. WriteGroupConfig(
  1756. HKEY hKeyPerfSubKey,
  1757. DWORD *pIds
  1758. )
  1759. {
  1760. DWORD nRetStatus = (int)ERROR_SUCCESS;
  1761. DWORD lStatus;
  1762. DWORD dwData;
  1763. DWORD dwBufferSize;
  1764. DWORD dwValueType;
  1765. WCHAR szStringBuffer[MAX_PATH*2];
  1766. dwBufferSize = sizeof(szStringBuffer);
  1767. dwValueType = 0;
  1768. memset (szStringBuffer, 0, sizeof(szStringBuffer));
  1769. lStatus = RegQueryValueExW (
  1770. hKeyPerfSubKey,
  1771. (LPCWSTR)L"Library",
  1772. 0L,
  1773. &dwValueType,
  1774. (LPBYTE)&szStringBuffer[0],
  1775. &dwBufferSize);
  1776. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ONFIG_Library:\t%s",
  1777. GetCurrentThreadId(),
  1778. (lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
  1779. if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
  1780. dwBufferSize = sizeof(szStringBuffer);
  1781. dwValueType = 0;
  1782. memset (szStringBuffer, 0, sizeof(szStringBuffer));
  1783. lStatus = RegQueryValueExW (
  1784. hKeyPerfSubKey,
  1785. (LPCWSTR)L"Open",
  1786. 0L,
  1787. &dwValueType,
  1788. (LPBYTE)&szStringBuffer[0],
  1789. &dwBufferSize);
  1790. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Open:\t%s",
  1791. GetCurrentThreadId(),
  1792. (lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
  1793. if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
  1794. dwBufferSize = sizeof(szStringBuffer);
  1795. dwValueType = 0;
  1796. memset (szStringBuffer, 0, sizeof(szStringBuffer));
  1797. lStatus = RegQueryValueExW (
  1798. hKeyPerfSubKey,
  1799. (LPCWSTR)L"Collect",
  1800. 0L,
  1801. &dwValueType,
  1802. (LPBYTE)&szStringBuffer[0],
  1803. &dwBufferSize);
  1804. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Collect:\t%s",
  1805. GetCurrentThreadId(),
  1806. (lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
  1807. if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
  1808. dwBufferSize = sizeof(szStringBuffer);
  1809. dwValueType = 0;
  1810. memset (szStringBuffer, 0, sizeof(szStringBuffer));
  1811. lStatus = RegQueryValueExW (
  1812. hKeyPerfSubKey,
  1813. (LPCWSTR)L"Object List",
  1814. 0L,
  1815. &dwValueType,
  1816. (LPBYTE)&szStringBuffer[0],
  1817. &dwBufferSize);
  1818. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Object List:\t%s",
  1819. GetCurrentThreadId(),
  1820. (lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
  1821. dwBufferSize = sizeof(szStringBuffer);
  1822. dwValueType = 0;
  1823. memset (szStringBuffer, 0, sizeof(szStringBuffer));
  1824. lStatus = RegQueryValueExW (
  1825. hKeyPerfSubKey,
  1826. (LPCWSTR)L"Close",
  1827. 0L,
  1828. &dwValueType,
  1829. (LPBYTE)&szStringBuffer[0],
  1830. &dwBufferSize);
  1831. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Close:\t%s",
  1832. GetCurrentThreadId(),
  1833. (lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
  1834. if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
  1835. dwBufferSize = sizeof(dwData);
  1836. dwValueType = 0;
  1837. dwData = 0;
  1838. lStatus = RegQueryValueExW (
  1839. hKeyPerfSubKey,
  1840. (LPCWSTR)L"First Counter",
  1841. 0L,
  1842. &dwValueType,
  1843. (LPBYTE)&dwData,
  1844. &dwBufferSize);
  1845. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_First Counter:\t%d",
  1846. GetCurrentThreadId(),
  1847. (lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
  1848. if (lStatus != ERROR_SUCCESS) {
  1849. if (lStatus == ERROR_FILE_NOT_FOUND) {
  1850. if (!pIds[4]) {
  1851. // then this hasn't been installed yet
  1852. nRetStatus = ERROR_SERVICE_DISABLED;
  1853. } else {
  1854. // then this is a base OS service
  1855. nRetStatus = ERROR_SUCCESS;
  1856. }
  1857. } else {
  1858. // some other error so return
  1859. nRetStatus = lStatus;
  1860. }
  1861. pIds[0] = (DWORD)-1;
  1862. } else {
  1863. pIds[0] = dwData;
  1864. }
  1865. dwBufferSize = sizeof(dwData);
  1866. dwValueType = 0;
  1867. dwData = 0;
  1868. lStatus = RegQueryValueExW (
  1869. hKeyPerfSubKey,
  1870. (LPCWSTR)L"Last Counter",
  1871. 0L,
  1872. &dwValueType,
  1873. (LPBYTE)&dwData,
  1874. &dwBufferSize);
  1875. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Last Counter:\t%d",
  1876. GetCurrentThreadId(),
  1877. (lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
  1878. if (lStatus != ERROR_SUCCESS) {
  1879. if (lStatus == ERROR_FILE_NOT_FOUND) {
  1880. if (!pIds[4]) {
  1881. // then this hasn't been installed yet
  1882. nRetStatus = ERROR_SERVICE_DISABLED;
  1883. } else {
  1884. // then this is a base OS service
  1885. nRetStatus = ERROR_SUCCESS;
  1886. }
  1887. } else {
  1888. // some other error so return
  1889. nRetStatus = lStatus;
  1890. }
  1891. pIds[1] = (DWORD)-1;
  1892. } else {
  1893. pIds[1] = dwData;
  1894. }
  1895. dwBufferSize = sizeof(dwData);
  1896. dwValueType = 0;
  1897. dwData = 0;
  1898. lStatus = RegQueryValueExW (
  1899. hKeyPerfSubKey,
  1900. (LPCWSTR)L"First Help",
  1901. 0L,
  1902. &dwValueType,
  1903. (LPBYTE)&dwData,
  1904. &dwBufferSize);
  1905. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_First Help:\t%d",
  1906. GetCurrentThreadId(),
  1907. (lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
  1908. if (lStatus != ERROR_SUCCESS) {
  1909. if (lStatus == ERROR_FILE_NOT_FOUND) {
  1910. if (!pIds[4]) {
  1911. // then this hasn't been installed yet
  1912. nRetStatus = ERROR_SERVICE_DISABLED;
  1913. } else {
  1914. // then this is a base OS service
  1915. nRetStatus = ERROR_SUCCESS;
  1916. }
  1917. } else {
  1918. // some other error so return
  1919. nRetStatus = lStatus;
  1920. }
  1921. pIds[2] = (DWORD)-1;
  1922. } else {
  1923. pIds[2] = dwData;
  1924. }
  1925. dwBufferSize = sizeof(dwData);
  1926. dwValueType = 0;
  1927. dwData = 0;
  1928. lStatus = RegQueryValueExW (
  1929. hKeyPerfSubKey,
  1930. (LPCWSTR)L"Last Help",
  1931. 0L,
  1932. &dwValueType,
  1933. (LPBYTE)&dwData,
  1934. &dwBufferSize);
  1935. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Last Help:\t%d",
  1936. GetCurrentThreadId(),
  1937. (lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
  1938. if (lStatus != ERROR_SUCCESS) {
  1939. if (lStatus == ERROR_FILE_NOT_FOUND) {
  1940. if (!pIds[4]) {
  1941. // then this hasn't been installed yet
  1942. nRetStatus = ERROR_SERVICE_DISABLED;
  1943. } else {
  1944. // then this is a base OS service
  1945. nRetStatus = ERROR_SUCCESS;
  1946. }
  1947. } else {
  1948. // some other error so return
  1949. nRetStatus = lStatus;
  1950. }
  1951. pIds[3] = (DWORD)-1;
  1952. } else {
  1953. pIds[3] = dwData;
  1954. }
  1955. dwBufferSize = sizeof(dwData);
  1956. dwValueType = 0;
  1957. dwData = 0;
  1958. lStatus = RegQueryValueExW (
  1959. hKeyPerfSubKey,
  1960. (LPCWSTR)L"Open Timeout",
  1961. 0L,
  1962. &dwValueType,
  1963. (LPBYTE)&dwData,
  1964. &dwBufferSize);
  1965. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Open Timeout:\t%d",
  1966. GetCurrentThreadId(),
  1967. (lStatus == ERROR_SUCCESS ? dwData : (DWORD)10000));
  1968. dwBufferSize = sizeof(dwData);
  1969. dwValueType = 0;
  1970. dwData = 0;
  1971. lStatus = RegQueryValueExW (
  1972. hKeyPerfSubKey,
  1973. (LPCWSTR)L"Collect Timeout",
  1974. 0L,
  1975. &dwValueType,
  1976. (LPBYTE)&dwData,
  1977. &dwBufferSize);
  1978. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Collect Timeout:\t%d",
  1979. GetCurrentThreadId(),
  1980. (lStatus == ERROR_SUCCESS ? dwData : (DWORD)10000));
  1981. dwBufferSize = sizeof(dwData);
  1982. dwValueType = 0;
  1983. dwData = 0;
  1984. lStatus = RegQueryValueExW (
  1985. hKeyPerfSubKey,
  1986. (LPCWSTR)L"Disable Performance Counters",
  1987. 0L,
  1988. &dwValueType,
  1989. (LPBYTE)&dwData,
  1990. &dwBufferSize);
  1991. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Disable Performance Counters:\t%d",
  1992. GetCurrentThreadId(),
  1993. (lStatus == ERROR_SUCCESS ? dwData : (DWORD)0));
  1994. if ((lStatus == ERROR_SUCCESS) && (dwData != 0)){
  1995. nRetStatus = ERROR_SERVICE_DISABLED;
  1996. }
  1997. return nRetStatus;
  1998. }
  1999. int
  2000. WriteTestResultTrailer(
  2001. DWORD dwTestResult
  2002. )
  2003. {
  2004. SYSTEMTIME stEnd;
  2005. LPWSTR szResult;
  2006. memset (&stEnd, 0, sizeof(stEnd));
  2007. GetLocalTime (&stEnd);
  2008. switch (dwTestResult) {
  2009. case PERFVAL_PASS:
  2010. szResult = (LPWSTR)L"PASS"; break;
  2011. case PERFVAL_FAIL:
  2012. szResult = (LPWSTR)L"FAIL"; break;
  2013. case PERFVAL_TIMEOUT:
  2014. szResult = (LPWSTR)L"TIMEOUT"; break;
  2015. case PERFVAL_NOCONFIG:
  2016. default:
  2017. szResult = (LPWSTR)L"NOCONFIG"; break;
  2018. }
  2019. fwprintf (g_pOutput, (LPCWSTR)L"\n\n\tRESULT: \t%s", szResult);
  2020. fwprintf (g_pOutput, (LPCWSTR)L"\n\tEND TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d",
  2021. stEnd.wMonth, stEnd.wDay, stEnd.wYear % 100,
  2022. stEnd.wHour, stEnd.wMinute, stEnd.wSecond);
  2023. fwprintf (g_pOutput, (LPCWSTR)L"\n[/TESTRESULT]");
  2024. fwprintf (g_pOutput, (LPCWSTR)L"\n");
  2025. return 0;
  2026. }
  2027. int
  2028. WriteGroupHeader(
  2029. LPCWSTR szGroupName
  2030. )
  2031. {
  2032. SYSTEMTIME stStart;
  2033. memset (&stStart, 0, sizeof(stStart));
  2034. GetLocalTime (&stStart);
  2035. fwprintf (g_pOutput, (LPCWSTR)L"\n\n\t[GROUP: %s]", szGroupName);
  2036. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\tSTART TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d.%3.3d",
  2037. stStart.wMonth, stStart.wDay, stStart.wYear % 100,
  2038. stStart.wHour, stStart.wMinute, stStart.wSecond, stStart.wMilliseconds );
  2039. return 0;
  2040. }
  2041. int
  2042. WriteGroupTrailer(
  2043. DWORD dwTestResult
  2044. )
  2045. {
  2046. LPWSTR szResult;
  2047. SYSTEMTIME stEnd;
  2048. memset (&stEnd, 0, sizeof(stEnd));
  2049. GetLocalTime (&stEnd);
  2050. switch (dwTestResult) {
  2051. case PERFVAL_PASS:
  2052. szResult = (LPWSTR)L"PASS"; break;
  2053. case PERFVAL_FAIL:
  2054. szResult = (LPWSTR)L"FAIL"; break;
  2055. case PERFVAL_TIMEOUT:
  2056. szResult = (LPWSTR)L"TIMEOUT"; break;
  2057. case PERFVAL_NOCONFIG:
  2058. default:
  2059. szResult = (LPWSTR)L"NOCONFIG"; break;
  2060. }
  2061. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\tEND TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d.%3.3d",
  2062. stEnd.wMonth, stEnd.wDay, stEnd.wYear % 100,
  2063. stEnd.wHour, stEnd.wMinute, stEnd.wSecond, stEnd.wMilliseconds );
  2064. fwprintf (g_pOutput, (LPCWSTR)L"\n\t\tRESULT: %s", szResult);
  2065. fwprintf (g_pOutput, (LPCWSTR)L"\n\t[/GROUP]");
  2066. return 0;
  2067. }
  2068. int
  2069. WriteTestError (
  2070. DWORD dwTabLevel,
  2071. DWORD dwStatus
  2072. )
  2073. {
  2074. DWORD dwIndent;
  2075. fwprintf (g_pOutput, (LPCWSTR)L"\n");
  2076. for (dwIndent = 0; dwIndent < dwTabLevel; dwIndent++) {
  2077. fwprintf (g_pOutput, (LPCWSTR)L"\t");
  2078. }
  2079. fwprintf (g_pOutput, (LPCWSTR)L"%d:ERROR: \t%s", GetCurrentThreadId(), (szTestErrorMessage != NULL ? szTestErrorMessage : (LPCWSTR)L"No Error"));
  2080. fwprintf (g_pOutput, (LPCWSTR)L"\n");
  2081. for (dwIndent = 0; dwIndent < dwTabLevel; dwIndent++) {
  2082. fwprintf (g_pOutput, (LPCWSTR)L"\t");
  2083. }
  2084. fwprintf (g_pOutput, (LPCWSTR)L"%d:ERRORCODE:\t0x%8.8x (%d)", GetCurrentThreadId(), dwStatus, dwStatus);
  2085. return 0;
  2086. }
  2087. int
  2088. __cdecl
  2089. wmain(
  2090. int argc,
  2091. WCHAR *argv[]
  2092. )
  2093. {
  2094. DWORD dwStatus;
  2095. DWORD dwLastElement = 0;
  2096. DWORD dwIdArray[8];
  2097. DWORD dwTID = 0;
  2098. DWORD dwObj;
  2099. DWORD dwTestResult = PERFVAL_NOCONFIG;
  2100. DWORD dwThreadCount = 0;
  2101. LOCAL_THREAD_DATA* pCurLTData = NULL;
  2102. HANDLE hThreads[MAXIMUM_WAIT_OBJECTS];
  2103. DWORD dwThisThread;
  2104. WCHAR* pwcsINIFile = L".\\ctrtest.ini";
  2105. BOOL fRand = FALSE;
  2106. int nIndex = 0;
  2107. // Set up environment
  2108. g_hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  2109. if ( NULL == g_hEvent )
  2110. return ERROR_INVALID_ACCESS;
  2111. g_pOutput = stdout;
  2112. g_hTestHeap = HeapCreate (HEAP_GENERATE_EXCEPTIONS, 0x10000, 0);
  2113. if (g_hTestHeap == NULL)
  2114. return (ERROR_OUTOFMEMORY);
  2115. WriteTestResultHeader(g_pOutput);
  2116. memset (&dwIdArray[0], 0, sizeof(dwIdArray));
  2117. g_pNameTable = BuildNameTable (
  2118. (LPCWSTR)L"",
  2119. (LPCWSTR)L"009",
  2120. &dwLastElement, // size of array in elements
  2121. &dwIdArray[0]);
  2122. g_dwLastIndex = dwLastElement;
  2123. WriteTestConfigData(&dwIdArray[0]);
  2124. if (g_pNameTable == NULL) {
  2125. // check for name table errors
  2126. dwStatus = GetLastError(); // so we don't continue
  2127. dwTestResult = PERFVAL_FAIL;
  2128. WriteTestError (1, dwStatus);
  2129. }
  2130. else
  2131. {
  2132. if ( argc > 1 )
  2133. {
  2134. pwcsINIFile = argv[1];
  2135. }
  2136. // Load up object/ctr data
  2137. dwStatus = Initialize( pwcsINIFile, &dwThreadCount );
  2138. if ( ERROR_SUCCESS == dwStatus )
  2139. {
  2140. srand( GetTickCount() );
  2141. // create threads
  2142. for (dwThisThread = 0; dwThisThread < dwThreadCount; dwThisThread++)
  2143. {
  2144. hThreads[dwThisThread] = (HANDLE) _beginthreadex( NULL, 0,
  2145. CycleThreadProc, (void*) &dwThisThread, 0, &dwTID );
  2146. }
  2147. // Let these all run through
  2148. dwStatus = WaitForMultipleObjects (dwThreadCount, hThreads, TRUE, INFINITE);
  2149. if (dwStatus != WAIT_TIMEOUT)
  2150. dwStatus = ERROR_SUCCESS;
  2151. for (dwThisThread = 0; dwThisThread < dwThreadCount; dwThisThread++) {
  2152. CloseHandle (hThreads[dwThisThread]);
  2153. }
  2154. }
  2155. }
  2156. WriteTestResultTrailer(dwTestResult);
  2157. for (dwObj = 0; dwObj < g_LTData.dwNumObjects; dwObj++)
  2158. {
  2159. FinializeExtObj(&g_pExtObjects[dwObj]);
  2160. }
  2161. if ( NULL != g_pNameTable )
  2162. HeapFree(g_hTestHeap, 0, g_pNameTable);
  2163. if ( NULL != g_pExtObjects )
  2164. HeapFree(g_hTestHeap, 0, g_pExtObjects);
  2165. if ( NULL != g_hTestHeap )
  2166. HeapDestroy (g_hTestHeap);
  2167. CloseHandle( g_hEvent );
  2168. return (int)dwStatus;
  2169. }