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.

555 lines
15 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. common.c
  5. Abstract:
  6. Utility routines used by Lodctr and/or UnLodCtr
  7. Author:
  8. Bob Watson (a-robw) 12 Feb 93
  9. Revision History:
  10. --*/
  11. #define UNICODE 1
  12. #define _UNICODE 1
  13. //
  14. // "C" Include files
  15. //
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <malloc.h>
  20. #include <locale.h>
  21. //
  22. // Windows Include files
  23. //
  24. #include <windows.h>
  25. #include <winperf.h>
  26. #include <tchar.h>
  27. #include <initguid.h>
  28. #include <guiddef.h>
  29. #include "wmistr.h"
  30. #include "evntrace.h"
  31. //
  32. // local include files
  33. //
  34. #define _INIT_WINPERFP_
  35. #include "winperfp.h"
  36. #include "common.h"
  37. //
  38. //
  39. // Text string Constant definitions
  40. //
  41. LPCTSTR NamesKey = (LPCTSTR)TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib");
  42. LPCTSTR DefaultLangId = (LPCTSTR)TEXT("009");
  43. LPCTSTR DefaultLangTag = (LPCTSTR)TEXT("000");
  44. LPCTSTR Counters = (LPCTSTR)TEXT("Counters");
  45. LPCTSTR Help = (LPCTSTR)TEXT("Help");
  46. LPCTSTR VersionStr = (LPCTSTR)TEXT("Version");
  47. LPCTSTR LastHelp = (LPCTSTR)TEXT("Last Help");
  48. LPCTSTR LastCounter = (LPCTSTR)TEXT("Last Counter");
  49. LPCTSTR FirstHelp = (LPCTSTR)TEXT("First Help");
  50. LPCTSTR cszFirstCounter = (LPCTSTR)TEXT("First Counter");
  51. LPCTSTR Busy = (LPCTSTR)TEXT("Updating");
  52. LPCTSTR Slash = (LPCTSTR)TEXT("\\");
  53. LPCTSTR BlankString = (LPCTSTR)TEXT(" ");
  54. LPCTSTR DriverPathRoot = (LPCTSTR)TEXT("SYSTEM\\CurrentControlSet\\Services");
  55. LPCTSTR Performance = (LPCTSTR)TEXT("Performance");
  56. LPCTSTR CounterNameStr = (LPCTSTR)TEXT("Counter ");
  57. LPCTSTR HelpNameStr = (LPCTSTR)TEXT("Explain ");
  58. LPCTSTR AddCounterNameStr = (LPCTSTR)TEXT("Addcounter ");
  59. LPCTSTR AddHelpNameStr = (LPCTSTR)TEXT("Addexplain ");
  60. LPCTSTR szObjectList = (LPCTSTR)TEXT("Object List");
  61. LPCTSTR szLibraryValidationCode = (LPCTSTR)TEXT("Library Validation Code");
  62. BOOLEAN g_bCheckTraceLevel = FALSE;
  63. // Global (to this module) Buffers
  64. //
  65. static TCHAR DisplayStringBuffer[DISP_BUFF_SIZE];
  66. static TCHAR TextFormat[DISP_BUFF_SIZE];
  67. static HANDLE hMod = NULL; // process handle
  68. static DWORD dwLastError = ERROR_SUCCESS;
  69. HANDLE hEventLog = NULL;
  70. HANDLE hLoadPerfMutex = NULL;
  71. //
  72. // local static data
  73. //
  74. static TCHAR cDoubleQuote = TEXT('\"');
  75. BOOL
  76. __stdcall
  77. DllEntryPoint(
  78. IN HANDLE DLLHandle,
  79. IN DWORD Reason,
  80. IN LPVOID ReservedAndUnused
  81. )
  82. {
  83. BOOL bReturn = FALSE;
  84. ReservedAndUnused;
  85. DisableThreadLibraryCalls (DLLHandle);
  86. switch(Reason) {
  87. case DLL_PROCESS_ATTACH:
  88. setlocale(LC_ALL, ".OCP");
  89. hMod = DLLHandle; // use DLL handle , not APP handle
  90. // register eventlog source
  91. hEventLog = RegisterEventSourceW (
  92. NULL, (LPCWSTR)L"LoadPerf");
  93. bReturn = TRUE;
  94. break;
  95. case DLL_PROCESS_DETACH:
  96. if (hEventLog != NULL) {
  97. if (DeregisterEventSource(hEventLog)) {
  98. hEventLog = NULL;
  99. }
  100. }
  101. if (hLoadPerfMutex != NULL) {
  102. CloseHandle(hLoadPerfMutex);
  103. hLoadPerfMutex = NULL;
  104. }
  105. bReturn = TRUE;
  106. break;
  107. case DLL_THREAD_ATTACH:
  108. case DLL_THREAD_DETACH:
  109. bReturn = TRUE;
  110. break;
  111. }
  112. return bReturn;
  113. }
  114. LPCTSTR
  115. GetStringResource (
  116. UINT wStringId
  117. )
  118. /*++
  119. Retrived UNICODE strings from the resource file for display
  120. --*/
  121. {
  122. if (!hMod) {
  123. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  124. }
  125. if (hMod) {
  126. if ((LoadString(hMod, wStringId, DisplayStringBuffer, DISP_BUFF_SIZE)) > 0) {
  127. return (LPTSTR)&DisplayStringBuffer[0];
  128. } else {
  129. dwLastError = GetLastError();
  130. return BlankString;
  131. }
  132. } else {
  133. return BlankString;
  134. }
  135. }
  136. LPCWSTR
  137. GetFormatResource (
  138. UINT wStringId
  139. )
  140. /*++
  141. Returns an ANSI string for use as a format string in a printf fn.
  142. --*/
  143. {
  144. if (!hMod) {
  145. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  146. }
  147. if (hMod) {
  148. if ((LoadStringW(hMod, wStringId, TextFormat, DISP_BUFF_SIZE)) > 0) {
  149. return (LPCTSTR)&TextFormat[0];
  150. } else {
  151. dwLastError = GetLastError();
  152. return BlankString;
  153. }
  154. } else {
  155. return BlankString;
  156. }
  157. }
  158. VOID
  159. DisplayCommandHelp (
  160. UINT iFirstLine,
  161. UINT iLastLine
  162. )
  163. /*++
  164. DisplayCommandHelp
  165. displays usage of command line arguments
  166. Arguments
  167. NONE
  168. Return Value
  169. NONE
  170. --*/
  171. {
  172. UINT iThisLine;
  173. WCHAR StringBuffer[DISP_BUFF_SIZE];
  174. CHAR OemStringBuffer[DISP_BUFF_SIZE];
  175. int nStringBufferLen;
  176. int nOemStringBufferLen;
  177. // clear the buffer
  178. memset (StringBuffer, 0, sizeof(StringBuffer));
  179. if (!hMod) {
  180. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  181. }
  182. if (hMod) {
  183. for (iThisLine = iFirstLine;
  184. iThisLine <= iLastLine;
  185. iThisLine++) {
  186. nStringBufferLen = LoadStringW(hMod, iThisLine, StringBuffer,
  187. DISP_BUFF_SIZE);
  188. if (nStringBufferLen > 0) {
  189. nOemStringBufferLen = sizeof(OemStringBuffer) / sizeof(OemStringBuffer[0]);
  190. WideCharToMultiByte (CP_OEMCP, 0,
  191. StringBuffer, // string to convert
  192. nStringBufferLen +1, // string length + null
  193. OemStringBuffer,
  194. nOemStringBufferLen,
  195. NULL, NULL);
  196. fprintf (stdout, "\n%s", OemStringBuffer);
  197. }
  198. }
  199. } // else do nothing
  200. } // DisplayCommandHelp
  201. BOOL
  202. TrimSpaces (
  203. IN OUT LPTSTR szString
  204. )
  205. /*++
  206. Routine Description:
  207. Trims leading and trailing spaces from szString argument, modifying
  208. the buffer passed in
  209. Arguments:
  210. IN OUT LPTSTR szString
  211. buffer to process
  212. Return Value:
  213. TRUE if string was modified
  214. FALSE if not
  215. --*/
  216. {
  217. LPTSTR szSource;
  218. LPTSTR szDest;
  219. LPTSTR szLast;
  220. BOOL bChars;
  221. szLast = szSource = szDest = szString;
  222. bChars = FALSE;
  223. while (*szSource != 0) {
  224. // skip leading non-space chars
  225. if (!_istspace(*szSource)) {
  226. szLast = szDest;
  227. bChars = TRUE;
  228. }
  229. if (bChars) {
  230. // remember last non-space character
  231. // copy source to destination & increment both
  232. *szDest++ = *szSource++;
  233. } else {
  234. szSource++;
  235. }
  236. }
  237. if (bChars) {
  238. *++szLast = 0; // terminate after last non-space char
  239. } else {
  240. // string was all spaces so return an empty (0-len) string
  241. *szString = 0;
  242. }
  243. return (szLast != szSource);
  244. }
  245. BOOL
  246. IsDelimiter (
  247. IN TCHAR cChar,
  248. IN TCHAR cDelimiter
  249. )
  250. /*++
  251. Routine Description:
  252. compares the characte to the delimiter. If the delimiter is
  253. a whitespace character then any whitespace char will match
  254. otherwise an exact match is required
  255. --*/
  256. {
  257. if (_istspace(cDelimiter)) {
  258. // delimiter is whitespace so any whitespace char will do
  259. return (_istspace(cChar));
  260. } else {
  261. // delimiter is not white space so use an exact match
  262. return (cChar == cDelimiter);
  263. }
  264. }
  265. LPCTSTR
  266. GetItemFromString (
  267. IN LPCTSTR szEntry,
  268. IN DWORD dwItem,
  269. IN TCHAR cDelimiter
  270. )
  271. /*++
  272. Routine Description:
  273. returns nth item from a list delimited by the cDelimiter Char.
  274. Leaves (double)quoted strings intact.
  275. Arguments:
  276. IN LPCTSTR szEntry
  277. Source string returned to parse
  278. IN DWORD dwItem
  279. 1-based index indicating which item to return. (i.e. 1= first item
  280. in list, 2= second, etc.)
  281. IN TCHAR cDelimiter
  282. character used to separate items. Note if cDelimiter is WhiteSpace
  283. (e.g. a tab or a space) then any white space will serve as a delim.
  284. Return Value:
  285. pointer to buffer containing desired entry in string. Note, this
  286. routine may only be called 4 times before the string
  287. buffer is re-used. (i.e. don't use this function more than
  288. 4 times in single function call!!)
  289. --*/
  290. {
  291. static TCHAR szReturnBuffer[4][MAX_PATH];
  292. static LONG dwBuff;
  293. LPTSTR szSource, szDest;
  294. DWORD dwThisItem;
  295. DWORD dwStrLeft;
  296. dwBuff = ++dwBuff % 4; // wrap buffer index
  297. szSource = (LPTSTR)szEntry;
  298. szDest = &szReturnBuffer[dwBuff][0];
  299. // clear previous contents
  300. memset (szDest, 0, (MAX_PATH * sizeof(TCHAR)));
  301. // find desired entry in string
  302. dwThisItem = 1;
  303. while (dwThisItem < dwItem) {
  304. if (*szSource != 0) {
  305. while (!IsDelimiter(*szSource, cDelimiter) && (*szSource != 0)) {
  306. if (*szSource == cDoubleQuote) {
  307. // if this is a quote, then go to the close quote
  308. szSource++;
  309. while ((*szSource != cDoubleQuote) && (*szSource != 0)) szSource++;
  310. }
  311. if (*szSource != 0) szSource++;
  312. }
  313. }
  314. dwThisItem++;
  315. if (*szSource != 0) szSource++;
  316. }
  317. // copy this entry to the return buffer
  318. if (*szSource != 0) {
  319. dwStrLeft = MAX_PATH-1;
  320. while (!IsDelimiter(*szSource, cDelimiter) && (*szSource != 0)) {
  321. if (*szSource == cDoubleQuote) {
  322. // if this is a quote, then go to the close quote
  323. // don't copy quotes!
  324. szSource++;
  325. while ((*szSource != cDoubleQuote) && (*szSource != 0)) {
  326. *szDest++ = *szSource++;
  327. dwStrLeft--;
  328. if (!dwStrLeft) break; // dest is full (except for term NULL
  329. }
  330. if (*szSource != 0) szSource++;
  331. } else {
  332. *szDest++ = *szSource++;
  333. dwStrLeft--;
  334. if (!dwStrLeft) break; // dest is full (except for term NULL
  335. }
  336. }
  337. *szDest = 0;
  338. }
  339. // remove any leading and/or trailing spaces
  340. TrimSpaces (&szReturnBuffer[dwBuff][0]);
  341. return &szReturnBuffer[dwBuff][0];
  342. }
  343. void
  344. ReportLoadPerfEvent(
  345. IN WORD EventType,
  346. IN DWORD EventID,
  347. IN DWORD dwDataCount,
  348. IN DWORD dwData1,
  349. IN DWORD dwData2,
  350. IN DWORD dwData3,
  351. IN WORD wStringCount,
  352. IN LPWSTR szString1,
  353. IN LPWSTR szString2,
  354. IN LPWSTR szString3
  355. )
  356. {
  357. WCHAR szDbg[1024];
  358. DWORD dwData[4];
  359. LPWSTR szMessageArray[4];
  360. BOOL bResult = FALSE;
  361. DWORD dwLastError = GetLastError();
  362. if (dwDataCount > 3) dwDataCount = 3;
  363. if (wStringCount > 3) wStringCount = 3;
  364. if (dwDataCount > 0) dwData[0] = dwData1;
  365. if (dwDataCount > 1) dwData[1] = dwData2;
  366. if (dwDataCount > 2) dwData[2] = dwData3;
  367. dwDataCount *= sizeof(DWORD);
  368. if (wStringCount > 0 && szString1) szMessageArray[0] = szString1;
  369. if (wStringCount > 1 && szString2) szMessageArray[1] = szString2;
  370. if (wStringCount > 2 && szString3) szMessageArray[2] = szString3;
  371. if (hEventLog == NULL) {
  372. hEventLog = RegisterEventSourceW (NULL, (LPCWSTR)L"LoadPerf");
  373. }
  374. if (dwDataCount > 0 && wStringCount > 0) {
  375. bResult = ReportEventW(hEventLog,
  376. EventType, // event type
  377. 0, // category (not used)
  378. EventID, // event,
  379. NULL, // SID (not used),
  380. wStringCount, // number of strings
  381. dwDataCount, // sizeof raw data
  382. szMessageArray, // message text array
  383. (LPVOID) & dwData[0]); // raw data
  384. }
  385. else if (dwDataCount > 0) {
  386. bResult = ReportEventW(hEventLog,
  387. EventType, // event type
  388. 0, // category (not used)
  389. EventID, // event,
  390. NULL, // SID (not used),
  391. 0, // number of strings
  392. dwDataCount, // sizeof raw data
  393. NULL, // message text array
  394. (LPVOID) & dwData[0]); // raw data
  395. }
  396. else if (wStringCount > 0) {
  397. bResult = ReportEventW(hEventLog,
  398. EventType, // event type
  399. 0, // category (not used)
  400. EventID, // event,
  401. NULL, // SID (not used),
  402. wStringCount, // number of strings
  403. 0, // sizeof raw data
  404. szMessageArray, // message text array
  405. NULL); // raw data
  406. }
  407. else {
  408. bResult = ReportEventW(hEventLog,
  409. EventType, // event type
  410. 0, // category (not used)
  411. EventID, // event,
  412. NULL, // SID (not used),
  413. 0, // number of strings
  414. 0, // sizeof raw data
  415. NULL, // message text array
  416. NULL); // raw data
  417. }
  418. if (! bResult) {
  419. swprintf(szDbg,
  420. (LPCWSTR) L"LOADPERF(0x%08X)::(%d,0x%08X,%d)(%d,%d,%d,%d)(%d,%ws,%ws,%ws)\n",
  421. GetCurrentThreadId(),
  422. EventType, EventID, GetLastError(),
  423. dwDataCount, dwData1, dwData2, dwData3,
  424. wStringCount, szString1, szString2, szString3);
  425. OutputDebugString(szDbg);
  426. }
  427. SetLastError(dwLastError);
  428. }
  429. BOOLEAN LoadPerfGrabMutex()
  430. {
  431. BOOLEAN bResult = TRUE;
  432. HANDLE hLocalMutex = NULL;
  433. DWORD dwWaitStatus = 0;
  434. if (hLoadPerfMutex == NULL) {
  435. hLocalMutex = CreateMutex(NULL, TRUE, TEXT("LOADPERF_MUTEX"));
  436. if (hLocalMutex == NULL) {
  437. bResult = FALSE;
  438. }
  439. else {
  440. InterlockedCompareExchangePointer(& hLoadPerfMutex,
  441. hLocalMutex,
  442. NULL);
  443. }
  444. }
  445. if (hLocalMutex == NULL) {
  446. dwWaitStatus = WaitForSingleObject(hLoadPerfMutex, H_MUTEX_TIMEOUT);
  447. if (dwWaitStatus != WAIT_OBJECT_0 && dwWaitStatus != WAIT_ABANDONED) {
  448. SetLastError(dwWaitStatus);
  449. bResult = FALSE;
  450. }
  451. }
  452. if (! bResult) {
  453. TRACE((WINPERF_DBG_TRACE_FATAL),
  454. (& LoadPerfGuid,
  455. __LINE__,
  456. LOADPERF_LOADPERFGRABMUTEX,
  457. 0,
  458. GetLastError(),
  459. NULL));
  460. }
  461. return bResult;
  462. }