Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2738 lines
71 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved
  3. Module Name:
  4. WsbTrace.cpp
  5. Abstract:
  6. These functions are used to provide an ability to trace the flow
  7. of the application for debugging purposes.
  8. Author:
  9. Chuck Bardeen [cbardeen] 29-Oct-1996
  10. Revision History:
  11. Brian Dodd [brian] 09-May-1996 - Added event logging
  12. --*/
  13. #include "stdafx.h"
  14. #include "stdio.h"
  15. #include "aclapi.h"
  16. #undef WsbThrow
  17. #define WsbThrow(hr) throw(hr)
  18. #define WSB_INDENT_STRING OLESTR(" ")
  19. #define WSB_APP_EVENT_LOG OLESTR("\\System32\\config\\AppEvent.evt")
  20. #define WSB_APP_EVENT_LOG_BKUP OLESTR("\\System32\\config\\AppEvent.bkp")
  21. #define WSB_APP_EVENT_LOG_NAME OLESTR("\\AppEvent.evt")
  22. #define WSB_SYS_EVENT_LOG OLESTR("\\System32\\config\\SysEvent.evt")
  23. #define WSB_SYS_EVENT_LOG_BKUP OLESTR("\\System32\\config\\SysEvent.bkp")
  24. #define WSB_SYS_EVENT_LOG_NAME OLESTR("\\SysEvent.evt")
  25. #define WSB_RS_TRACE_FILES OLESTR("Trace\\*.*")
  26. #define WSB_RS_TRACE_PATH OLESTR("Trace\\")
  27. #define BOGUS_TLS_INDEX 0xFFFFFFFF
  28. // Per-thread data:
  29. typedef struct {
  30. ULONG TraceOffCount; // Trace only if this is zero
  31. LONG IndentLevel;
  32. char *LogModule;
  33. DWORD LogModuleLine;
  34. DWORD LogNTBuild;
  35. DWORD LogRSBuild;
  36. } THREAD_DATA;
  37. static DWORD TlsIndex = BOGUS_TLS_INDEX; // Per-thread data index
  38. // The globals that control the tracing
  39. LONGLONG g_WsbTraceModules = WSB_TRACE_BIT_NONE;
  40. IWsbTrace *g_pWsbTrace = 0;
  41. BOOL g_WsbTraceEntryExit = TRUE;
  42. // The globals that control the event logging and printing
  43. WORD g_WsbLogLevel = WSB_LOG_LEVEL_DEFAULT;
  44. BOOL g_WsbLogSnapShotOn = FALSE;
  45. WORD g_WsbLogSnapShotLevel = 0;
  46. OLECHAR g_pWsbLogSnapShotPath[250];
  47. BOOL g_WsbLogSnapShotResetTrace = FALSE;
  48. WORD g_WsbPrintLevel = WSB_LOG_LEVEL_DEFAULT;
  49. //
  50. // WsbTraceCount is a running count of the trace output count: normally we
  51. // use the shared count among the processes, but if we can't get access to
  52. // the shared var., we use this
  53. //
  54. LONG g_WsbTraceCount = 0;
  55. // Helper function
  56. static HRESULT OutputTraceString(ULONG indentLevel, OLECHAR* introString,
  57. OLECHAR* format, va_list vaList);
  58. static HRESULT GetThreadDataPointer(THREAD_DATA** ppTD);
  59. static void SnapShotTraceAndEvent( SYSTEMTIME stime );
  60. void
  61. WsbTraceInit(
  62. void
  63. )
  64. /*++
  65. Routine Description:
  66. Initialize this trace module
  67. Arguments:
  68. None.
  69. Return Value:
  70. None.
  71. --*/
  72. {
  73. // Get an index for the thread local storage
  74. TlsIndex = TlsAlloc();
  75. }
  76. void
  77. WsbTraceCleanupThread(
  78. void
  79. )
  80. /*++
  81. Routine Description:
  82. Cleanup information for this thread (which is going away)
  83. Arguments:
  84. None.
  85. Return Value:
  86. None.
  87. --*/
  88. {
  89. THREAD_DATA* pThreadData = NULL;
  90. if (BOGUS_TLS_INDEX != TlsIndex) {
  91. pThreadData = static_cast<THREAD_DATA*>(TlsGetValue(TlsIndex));
  92. if (pThreadData) {
  93. WsbFree(pThreadData);
  94. TlsSetValue(TlsIndex, NULL);
  95. }
  96. }
  97. }
  98. void
  99. WsbTraceEnter(
  100. OLECHAR* methodName,
  101. OLECHAR* argString,
  102. ...
  103. )
  104. /*++
  105. Routine Description:
  106. This routine prints out trace information indicating that the
  107. method specified has been entered, and the values of its arguements
  108. (if supplied).
  109. Arguments:
  110. methodName - The name of the method that was entered.
  111. argString - A printf style string indicating the number of
  112. arguments and how they should be formatted.
  113. Return Value:
  114. None.
  115. --*/
  116. {
  117. HRESULT hr = S_OK;
  118. OLECHAR tmpString[WSB_TRACE_BUFF_SIZE];
  119. va_list vaList;
  120. try {
  121. THREAD_DATA* pThreadData = NULL;
  122. WsbAffirmHr(GetThreadDataPointer(&pThreadData));
  123. // Make sure we are supposed to trace
  124. WsbAffirm( 0 != g_pWsbTrace, S_OK);
  125. WsbAffirm(0 == pThreadData->TraceOffCount, S_OK);
  126. // Identify the function.
  127. swprintf(tmpString, OLESTR("Enter <%ls> : "), methodName);
  128. // Format & print out
  129. va_start(vaList, argString);
  130. WsbAffirmHr(OutputTraceString(pThreadData->IndentLevel, tmpString,
  131. argString, vaList));
  132. va_end(vaList);
  133. // Increment the indentation level
  134. pThreadData->IndentLevel++;
  135. } WsbCatch (hr);
  136. }
  137. void
  138. WsbTraceExit(
  139. OLECHAR* methodName,
  140. OLECHAR* argString,
  141. ...
  142. )
  143. /*++
  144. Routine Description:
  145. This routine prints out trace information indicating that the
  146. method specified has been exitted, and the values it is returning
  147. (if supplied).
  148. Arguments:
  149. methodName - The name of the method that was exitted.
  150. argString - A printf style string indicating the number of
  151. arguments and how they should be formatted.
  152. Return Value:
  153. None.
  154. --*/
  155. {
  156. HRESULT hr = S_OK;
  157. OLECHAR tmpString[WSB_TRACE_BUFF_SIZE];
  158. va_list vaList;
  159. try {
  160. THREAD_DATA* pThreadData = NULL;
  161. WsbAffirmHr(GetThreadDataPointer(&pThreadData));
  162. // Make sure we are supposed to trace
  163. WsbAffirm( 0 != g_pWsbTrace, S_OK);
  164. WsbAffirm(0 == pThreadData->TraceOffCount, S_OK);
  165. // Decrement the indentation level.
  166. if (pThreadData->IndentLevel > 0) {
  167. pThreadData->IndentLevel--;
  168. } else {
  169. g_pWsbTrace->Print(OLESTR("WARNING: Badly matched TraceIn/TraceOut\r\n"));
  170. }
  171. // Identify the function.
  172. swprintf(tmpString, OLESTR("Exit <%ls> : "), methodName);
  173. // Format & print out
  174. va_start(vaList, argString);
  175. WsbAffirmHr(OutputTraceString(pThreadData->IndentLevel, tmpString,
  176. argString, vaList));
  177. va_end(vaList);
  178. } WsbCatch( hr );
  179. }
  180. void
  181. WsbTracef(
  182. OLECHAR* argString,
  183. ...
  184. )
  185. /*++
  186. Routine Description:
  187. This routine prints out trace information from a printf style string.
  188. A carriage return should be add to the format string if desired.
  189. Arguments:
  190. argString - A printf style string indicating the number of
  191. arguments and how they should be formatted.
  192. Return Value:
  193. None.
  194. --*/
  195. {
  196. HRESULT hr = S_OK;
  197. va_list vaList;
  198. try {
  199. THREAD_DATA* pThreadData = NULL;
  200. WsbAffirmHr(GetThreadDataPointer(&pThreadData));
  201. // Make sure we are supposed to trace
  202. WsbAffirm( 0 != g_pWsbTrace, S_OK);
  203. WsbAffirm(0 == pThreadData->TraceOffCount, S_OK);
  204. // Format & print out
  205. va_start(vaList, argString);
  206. WsbAffirmHr(OutputTraceString(pThreadData->IndentLevel, NULL,
  207. argString, vaList));
  208. va_end(vaList);
  209. } WsbCatch (hr);
  210. }
  211. void
  212. WsbSetEventInfo(
  213. char *fileName,
  214. DWORD lineNo,
  215. DWORD ntBuild,
  216. DWORD rsBuild
  217. )
  218. /*++
  219. Routine Description:
  220. This routine sets information used in logging events.
  221. Arguments:
  222. fileName - The name of the module that logged the event.
  223. lineNo - The source line number of the statement that logged the event
  224. ntBuild - The NT Build version
  225. rsBuild - The RS Build version
  226. Return Value:
  227. None.
  228. Notes:
  229. ntBuild, and rsBuild are passed in with each call to get the build version for
  230. the modules actually logging the event.
  231. --*/
  232. {
  233. THREAD_DATA* pThreadData = NULL;
  234. if (S_OK == GetThreadDataPointer(&pThreadData)) {
  235. pThreadData->LogModule = fileName;
  236. pThreadData->LogModuleLine = lineNo;
  237. pThreadData->LogNTBuild = ntBuild;
  238. pThreadData->LogRSBuild = rsBuild;
  239. }
  240. }
  241. void
  242. WsbTraceAndLogEvent(
  243. DWORD eventId,
  244. DWORD dataSize,
  245. LPVOID data,
  246. ...
  247. )
  248. /*++
  249. Routine Description:
  250. This routine writes a message into the system event log. The message
  251. is also written to the application trace file.
  252. Arguments:
  253. eventId - The message Id to log.
  254. dataSize - Size of arbitrary data.
  255. data - Arbitrary data buffer to display with the message.
  256. Inserts - Message inserts that are merged with the message description specified by
  257. eventId. The number of inserts must match the number specified by the
  258. message description. The last insert must be NULL to indicate the
  259. end of the insert list.
  260. Return Value:
  261. None.
  262. --*/
  263. {
  264. HRESULT hr = S_OK;
  265. try {
  266. va_list vaList;
  267. va_start(vaList, data);
  268. WsbTraceAndLogEventV( eventId, dataSize, data, &vaList );
  269. va_end(vaList);
  270. }
  271. WsbCatch( hr );
  272. }
  273. void
  274. WsbTraceAndLogEventV(
  275. DWORD eventId,
  276. DWORD dataSize,
  277. LPVOID data,
  278. va_list * inserts
  279. )
  280. /*++
  281. Routine Description:
  282. This routine writes a message into the system event log. The message
  283. is also written to the application trace file. The file name and line number is appended
  284. to the log data, if any.
  285. Arguments:
  286. eventId - The message Id to log.
  287. dataSize - Size of arbitrary data.
  288. data - Arbitrary data buffer to display with the message.
  289. inserts - An array of message inserts that are merged with the message description
  290. specified by eventId. The number of inserts must match the number
  291. specified by the message description. The last insert must be NULL,
  292. to indicate the end of the insert list.
  293. Return Value:
  294. None.
  295. --*/
  296. {
  297. HRESULT hr = S_OK;
  298. char *newData = NULL, *fileName;
  299. DWORD newDataSize=0;
  300. OLECHAR ** logString=0;
  301. WORD count=0;
  302. SYSTEMTIME stime;
  303. try {
  304. WsbAssertPointer( inserts );
  305. WORD logType;
  306. const OLECHAR * facilityName = 0;
  307. WORD category = 0;
  308. va_list vaList;
  309. BOOL bLog;
  310. BOOL bSnapShot;
  311. THREAD_DATA* pThreadData = NULL;
  312. // Get space for the passed in data plus the file and line number. If we fail to allocate
  313. // memory for this we just log the data they passed in (without file and line)
  314. GetThreadDataPointer(&pThreadData);
  315. if (pThreadData) {
  316. fileName = strrchr(pThreadData->LogModule, '\\');
  317. } else {
  318. fileName = NULL;
  319. }
  320. if (fileName) {
  321. fileName++; // Point at just the source file name (no path)
  322. int len = strlen(fileName);
  323. newData = (char *) malloc(dataSize + len + 128);
  324. if (newData) {
  325. if (data) {
  326. memcpy(newData, data, dataSize);
  327. }
  328. // Align the record data on even 8 byte boundary for viewing
  329. len = (len>8) ? 16 : 8;
  330. sprintf(&newData[dataSize], "%-*.*s@%7luNt%6luRs%6.6ls", len,
  331. len, fileName, pThreadData->LogModuleLine, pThreadData->LogNTBuild,
  332. RsBuildVersionAsString(pThreadData->LogRSBuild) );
  333. newDataSize = dataSize + strlen(&newData[dataSize]);
  334. }
  335. }
  336. //
  337. // Determine type of event
  338. //
  339. switch ( eventId & 0xc0000000 ) {
  340. case ERROR_SEVERITY_INFORMATIONAL:
  341. logType = EVENTLOG_INFORMATION_TYPE;
  342. bLog = (g_WsbLogLevel >= WSB_LOG_LEVEL_INFORMATION) ? TRUE : FALSE;
  343. bSnapShot = (g_WsbLogSnapShotLevel >= WSB_LOG_LEVEL_INFORMATION) ? TRUE : FALSE;
  344. break;
  345. case ERROR_SEVERITY_WARNING:
  346. logType = EVENTLOG_WARNING_TYPE;
  347. bLog = (g_WsbLogLevel >= WSB_LOG_LEVEL_WARNING) ? TRUE : FALSE;
  348. bSnapShot = (g_WsbLogSnapShotLevel >= WSB_LOG_LEVEL_WARNING) ? TRUE : FALSE;
  349. break;
  350. case ERROR_SEVERITY_ERROR:
  351. logType = EVENTLOG_ERROR_TYPE;
  352. bLog = (g_WsbLogLevel >= WSB_LOG_LEVEL_ERROR) ? TRUE : FALSE;
  353. bSnapShot = (g_WsbLogSnapShotLevel >= WSB_LOG_LEVEL_ERROR) ? TRUE : FALSE;
  354. break;
  355. default:
  356. logType = EVENTLOG_INFORMATION_TYPE;
  357. bLog = (g_WsbLogLevel >= WSB_LOG_LEVEL_COMMENT) ? TRUE : FALSE;
  358. bSnapShot = (g_WsbLogSnapShotLevel >= WSB_LOG_LEVEL_COMMENT) ? TRUE : FALSE;
  359. break;
  360. }
  361. WsbAffirm ( bLog, S_OK );
  362. WsbTracef(OLESTR("\r\n"));
  363. WsbTracef(OLESTR("!!!!! EVENT !!!!! - File: %hs @ Line: %d (%lu-%ls)\r\n"),
  364. (pThreadData ? pThreadData->LogModule : ""),
  365. (pThreadData ? pThreadData->LogModuleLine : 0),
  366. (pThreadData ? pThreadData->LogNTBuild : 0),
  367. RsBuildVersionAsString((pThreadData ? pThreadData->LogRSBuild : 0)) );
  368. //
  369. // Determine source facility and category of message
  370. //
  371. switch ( HRESULT_FACILITY( eventId ) ) {
  372. case WSB_FACILITY_PLATFORM:
  373. facilityName = WSB_FACILITY_PLATFORM_NAME;
  374. category = WSB_CATEGORY_PLATFORM;
  375. break;
  376. case WSB_FACILITY_RMS:
  377. facilityName = WSB_FACILITY_PLATFORM_NAME;
  378. category = WSB_CATEGORY_RMS;
  379. break;
  380. case WSB_FACILITY_HSMENG:
  381. facilityName = WSB_FACILITY_PLATFORM_NAME;
  382. category = WSB_CATEGORY_HSMENG;
  383. break;
  384. case WSB_FACILITY_JOB:
  385. facilityName = WSB_FACILITY_PLATFORM_NAME;
  386. category = WSB_CATEGORY_JOB;
  387. break;
  388. case WSB_FACILITY_HSMTSKMGR:
  389. facilityName = WSB_FACILITY_PLATFORM_NAME;
  390. category = WSB_CATEGORY_HSMTSKMGR;
  391. break;
  392. case WSB_FACILITY_FSA:
  393. facilityName = WSB_FACILITY_PLATFORM_NAME;
  394. category = WSB_CATEGORY_FSA;
  395. break;
  396. case WSB_FACILITY_GUI:
  397. facilityName = WSB_FACILITY_PLATFORM_NAME;
  398. category = WSB_CATEGORY_GUI;
  399. break;
  400. case WSB_FACILITY_MOVER:
  401. facilityName = WSB_FACILITY_PLATFORM_NAME;
  402. category = WSB_CATEGORY_MOVER;
  403. break;
  404. case WSB_FACILITY_LAUNCH:
  405. facilityName = WSB_FACILITY_PLATFORM_NAME;
  406. category = WSB_CATEGORY_LAUNCH;
  407. break;
  408. case WSB_FACILITY_USERLINK:
  409. facilityName = WSB_FACILITY_PLATFORM_NAME;
  410. category = WSB_CATEGORY_USERLINK;
  411. break;
  412. case WSB_FACILITY_TEST:
  413. facilityName = WSB_FACILITY_TEST_NAME;
  414. category = WSB_CATEGORY_TEST;
  415. break;
  416. case HRESULT_FACILITY(FACILITY_NT_BIT):
  417. facilityName = WSB_FACILITY_NTDLL_NAME;
  418. eventId &= ~FACILITY_NT_BIT;
  419. break;
  420. default:
  421. facilityName = WSB_FACILITY_NTDLL_NAME;
  422. break;
  423. }
  424. //
  425. // Trace the message
  426. //
  427. if ( g_pWsbTrace ) {
  428. if ( facilityName ) {
  429. OLECHAR * messageText = 0;
  430. // NOTE: Positional parameters in the inserts are not processed. These
  431. // are done by ReportEvent() only.
  432. vaList = *inserts;
  433. HMODULE hModule;
  434. hModule = LoadLibraryEx( facilityName, NULL, LOAD_LIBRARY_AS_DATAFILE );
  435. if (hModule) {
  436. FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  437. hModule,
  438. eventId,
  439. MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  440. (LPTSTR) &messageText,
  441. 0,
  442. &vaList );
  443. if ( messageText ) {
  444. WsbTracef( OLESTR("%ls"), messageText ); // Format messages come with \n
  445. LocalFree( messageText );
  446. } else {
  447. WsbTracef( OLESTR("!!!!! EVENT !!!!! - Message <0x%08lx> could not be translated.\r\n"), eventId );
  448. }
  449. FreeLibrary(hModule);
  450. } else {
  451. WsbTracef( OLESTR("!!!!! EVENT !!!!! - Could not load facility name DLL %ls. \r\n"), facilityName);
  452. }
  453. } else {
  454. WsbTracef( OLESTR("!!!!! EVENT !!!!! - Message File for <0x%08lx> could not be found.\r\n"), eventId );
  455. }
  456. if ( data && dataSize > 0 )
  457. WsbTraceBufferAsBytes( dataSize, data );
  458. }
  459. // Prepare arguments for ReportEvent
  460. // First count the number of arguments
  461. vaList = *inserts;
  462. for( count = 0; (va_arg( vaList, OLECHAR *)) != NULL; count++ );
  463. if ( count ) {
  464. OLECHAR* tmpArg;
  465. // Allocate a array to hold the string arguments.
  466. //
  467. // IMPORTANT NOTE: Don't try anything fancy here. va_list is different
  468. // on various platforms. We'll need to build the string
  469. // argument required by ReportEvent (too bad ReportEvent
  470. // doesn't take va_list like FormatMessage does.
  471. //
  472. logString = (OLECHAR **)malloc( count*sizeof(OLECHAR *) );
  473. WsbAffirmAlloc( logString );
  474. // load in the strings
  475. vaList = *inserts;
  476. for( count = 0; (tmpArg = va_arg( vaList, OLECHAR *)) != NULL; count++ ) {
  477. logString[count] = tmpArg;
  478. }
  479. }
  480. // Get a handle to the event source
  481. HANDLE hEventSource = RegisterEventSource(NULL, WSB_LOG_SOURCE_NAME );
  482. // Get the time in case we need to snap shot this event's logs and traces
  483. GetLocalTime(&stime);
  484. if (hEventSource != NULL) {
  485. // Write to event log
  486. DWORD recordDataSize = (newData) ? newDataSize : dataSize;
  487. LPVOID recordData = (newData) ? newData : data;
  488. if ( ReportEvent(hEventSource, logType, category, eventId, NULL, count, recordDataSize, (LPCTSTR *)&logString[0], recordData) ) {
  489. WsbTracef( OLESTR("!!!!! EVENT !!!!! - Event <0x%08lx> was logged.\r\n"), eventId );
  490. WsbTracef( OLESTR("\r\n") );
  491. } else {
  492. WsbTracef( OLESTR("!!!!! EVENT !!!!! - Event <0x%08lx> could not be logged due to the following error: %ls\r\n"), eventId, WsbHrAsString(HRESULT_FROM_WIN32(GetLastError())) );
  493. WsbTracef( OLESTR("\r\n") );
  494. }
  495. DeregisterEventSource(hEventSource);
  496. }
  497. try {
  498. HRESULT hr2 = S_OK;
  499. //
  500. // See if we are to take a snap shot of the event and trace logs when an event of this level is logged.
  501. //
  502. if ( (TRUE == bSnapShot) &&
  503. (TRUE == g_WsbLogSnapShotOn) ) {
  504. SnapShotTraceAndEvent(stime);
  505. }
  506. } WsbCatchAndDo(hr, hr=S_OK; );
  507. } WsbCatch( hr );
  508. if (newData) {
  509. free(newData);
  510. }
  511. if (logString) {
  512. free(logString);
  513. }
  514. }
  515. const OLECHAR*
  516. WsbBoolAsString(
  517. BOOL boolean
  518. )
  519. /*++
  520. Routine Description:
  521. This routine provides a string repesentation (e.g. TRUE, FALSE) for
  522. the value of the boolean supplied.
  523. NOTE: This method does not support localization of the strings.
  524. Arguments:
  525. boolean - A boolean value.
  526. Return Value:
  527. A string representation of the value of the boolean.
  528. --*/
  529. {
  530. return(boolean ? OLESTR("TRUE") : OLESTR("FALSE"));
  531. }
  532. const OLECHAR*
  533. WsbLongAsString(
  534. LONG inLong
  535. )
  536. /*++
  537. Routine Description:
  538. This routine provides a string repesentation for the value of the
  539. long supplied.
  540. NOTE: This method shares memory between subsequent calls of the function.
  541. Arguments:
  542. long - A long value
  543. Return Value:
  544. A string representation of the value of the GUID.
  545. --*/
  546. {
  547. static OLECHAR defaultString[40];
  548. swprintf( defaultString, OLESTR("%ld"), inLong );
  549. return(defaultString);
  550. }
  551. const OLECHAR*
  552. WsbFiletimeAsString(
  553. IN BOOL isRelative,
  554. IN FILETIME time
  555. )
  556. /*++
  557. Routine Description:
  558. This routine provides a string repesentation for the value of the
  559. FILETIME supplied.
  560. NOTE: This method shares memory between subsequent calls of the function.
  561. Arguments:
  562. isRelatice - A boolean that indicates whether the time is absolute (e.g 1/1/1987 ...)
  563. or relative (e.g. 1 hour).
  564. time - A FILETIME.
  565. Return Value:
  566. A string representation of the value of the FILETIME.
  567. --*/
  568. {
  569. static OLECHAR defaultString[80];
  570. OLECHAR* tmpString = 0;
  571. HRESULT hr;
  572. hr = WsbFTtoWCS(isRelative, time, &tmpString, sizeof(defaultString));
  573. if (hr == S_OK) {
  574. wcscpy(defaultString, tmpString);
  575. } else {
  576. wcscpy(defaultString, L"BADFILETIME");
  577. }
  578. WsbFree(tmpString);
  579. return(defaultString);
  580. }
  581. const OLECHAR*
  582. WsbGuidAsString(
  583. GUID guid
  584. )
  585. /*++
  586. Routine Description:
  587. This routine provides a string repesentation for the value of the
  588. GUID supplied.
  589. NOTE: This method shares memory between subsequent calls of the function.
  590. Arguments:
  591. guid - A GUID.
  592. Return Value:
  593. A string representation of the value of the GUID.
  594. --*/
  595. {
  596. static OLECHAR defaultString[40];
  597. swprintf( defaultString, OLESTR("{%.8x-%.4x-%.4hx-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}"),
  598. guid.Data1, (UINT)guid.Data2, (UINT)guid.Data3,
  599. (UINT) guid.Data4[0], (UINT) guid.Data4[1],
  600. (UINT) guid.Data4[2], (UINT) guid.Data4[3], (UINT) guid.Data4[4],
  601. (UINT) guid.Data4[5], (UINT) guid.Data4[6], (UINT) guid.Data4[7]);
  602. return(defaultString);
  603. }
  604. HRESULT
  605. WsbSafeGuidAsString(
  606. GUID guid,
  607. CWsbStringPtr &strOut
  608. )
  609. /*++
  610. Routine Description:
  611. This routine provides a string repesentation for the value of the
  612. GUID supplied.
  613. NOTE: This is a MT-safe version of WsbGuidAsString which doesn't use
  614. static memory
  615. Arguments:
  616. guid - A GUID.
  617. strOut - Output string
  618. Return Value:
  619. status (S_OK or E_OUTOFMEMORY)
  620. --*/
  621. {
  622. HRESULT hr = S_OK;
  623. strOut.Free();
  624. strOut = guid;
  625. if ((WCHAR *)strOut == 0)
  626. hr = E_OUTOFMEMORY;
  627. return hr;
  628. }
  629. const OLECHAR*
  630. WsbHrAsString(
  631. HRESULT hr
  632. )
  633. /*++
  634. Routine Description:
  635. This routine provides a string repesentation (e.g. S_OK, E_POINTER) for
  636. the value of the HRESULT supplied.
  637. NOTE: This method shares memory between subsequent calls of the function.
  638. Arguments:
  639. hr - An HRESULT.
  640. Return Value:
  641. A string representation of the value of the HRESULT.
  642. --*/
  643. {
  644. const OLECHAR *returnString = 0;
  645. const OLECHAR *facilityName = 0;
  646. const DWORD cSize = 1024;
  647. DWORD stringSize = (cSize - 20);
  648. static OLECHAR defaultString[cSize];
  649. DWORD lastError;
  650. // Handle a few special cases which are not in the message table resource
  651. switch ( hr ) {
  652. case S_OK:
  653. returnString = OLESTR("Ok"); // This overloads Win32 NO_ERROR.
  654. break;
  655. case S_FALSE:
  656. returnString = OLESTR("False"); // This overloads Win32 ERROR_INVALID_FUNCTION
  657. break;
  658. default:
  659. break;
  660. }
  661. if ( 0 == returnString ) {
  662. returnString = defaultString;
  663. swprintf( defaultString, OLESTR("0x%08lx"), hr );
  664. //
  665. // First, try getting the message from the system
  666. //
  667. if ( 0 == FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
  668. NULL,
  669. hr,
  670. MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  671. defaultString,
  672. stringSize,
  673. NULL ) ) {
  674. lastError = GetLastError(); // For debugging
  675. // Next, try the module executing this code.
  676. if ( 0 == FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  677. NULL,
  678. hr,
  679. MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  680. defaultString,
  681. stringSize,
  682. NULL ) ) {
  683. lastError = GetLastError(); // For debugging
  684. // Finally, try to identify the module based on the facility code
  685. switch ( HRESULT_FACILITY( hr ) ) {
  686. case WSB_FACILITY_PLATFORM:
  687. case WSB_FACILITY_RMS:
  688. case WSB_FACILITY_HSMENG:
  689. case WSB_FACILITY_JOB:
  690. case WSB_FACILITY_HSMTSKMGR:
  691. case WSB_FACILITY_FSA:
  692. case WSB_FACILITY_GUI:
  693. case WSB_FACILITY_MOVER:
  694. case WSB_FACILITY_LAUNCH:
  695. case WSB_FACILITY_USERLINK:
  696. facilityName = WSB_FACILITY_PLATFORM_NAME;
  697. break;
  698. case WSB_FACILITY_TEST:
  699. facilityName = WSB_FACILITY_TEST_NAME;
  700. break;
  701. case HRESULT_FACILITY(FACILITY_NT_BIT):
  702. facilityName = WSB_FACILITY_NTDLL_NAME;
  703. hr &= ~FACILITY_NT_BIT;
  704. break;
  705. default:
  706. facilityName = WSB_FACILITY_NTDLL_NAME;
  707. break;
  708. }
  709. if ( facilityName ) {
  710. HMODULE hModule;
  711. hModule = LoadLibraryEx( facilityName, NULL, LOAD_LIBRARY_AS_DATAFILE );
  712. if (hModule) {
  713. FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  714. hModule,
  715. hr,
  716. MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  717. defaultString,
  718. stringSize,
  719. NULL );
  720. FreeLibrary(hModule);
  721. } else {
  722. WsbTracef( OLESTR("!!!!! EVENT !!!!! - Could not load facility name DLL %ls. \r\n"), facilityName);
  723. }
  724. }
  725. }
  726. }
  727. //
  728. // remove trailing \r\n ( this makes things nice for tracing and asserts )
  729. //
  730. if ( defaultString[ wcslen(defaultString)-1 ] == OLESTR('\n') ) {
  731. defaultString[ wcslen(defaultString)-1 ] = OLESTR('\0');
  732. if ( defaultString[ wcslen(defaultString)-1 ] == OLESTR('\r') ) {
  733. defaultString[ wcslen(defaultString)-1 ] = OLESTR('\0');
  734. swprintf( &defaultString[ wcslen(defaultString) ], OLESTR(" (0x%08lx)"), hr );
  735. }
  736. }
  737. }
  738. return ( returnString );
  739. }
  740. const OLECHAR*
  741. WsbLonglongAsString(
  742. LONGLONG llong
  743. )
  744. /*++
  745. Routine Description:
  746. This routine provides a string repesentation for the value of the
  747. LONGLONG supplied.
  748. NOTE: This method shares memory between subsequent calls of the function.
  749. Arguments:
  750. llong - A LONGLONG value.
  751. Return Value:
  752. A string representation of the value.
  753. --*/
  754. {
  755. static OLECHAR defaultString[128];
  756. OLECHAR* ptr = &defaultString[0];
  757. WsbLLtoWCS(llong, &ptr, 128);
  758. return(defaultString);
  759. }
  760. const OLECHAR*
  761. WsbStringAsString(
  762. OLECHAR* pStr
  763. )
  764. /*++
  765. Routine Description:
  766. This routine provides a string repesentation for the value of the
  767. String supplied.
  768. NOTE: This method shares memory between subsequent calls of the function.
  769. Arguments:
  770. pStr - A string value.
  771. Return Value:
  772. A string representation of the value.
  773. --*/
  774. {
  775. OLECHAR* returnString;
  776. if (0 == pStr) {
  777. returnString = OLESTR("NULL");
  778. } else {
  779. returnString = pStr;
  780. }
  781. return(returnString);
  782. }
  783. const OLECHAR*
  784. WsbPtrToBoolAsString(
  785. BOOL* pBool
  786. )
  787. /*++
  788. Routine Description:
  789. This routine provides a string repesentation for the value of the
  790. pointer to a BOOL supplied.
  791. NOTE: This method does not support localization of the strings.
  792. Arguments:
  793. pBool - A pointer to a BOOL or NULL.
  794. Return Value:
  795. A string representation of the value of the BOOL or "NULL" if the
  796. pointer was null.
  797. --*/
  798. {
  799. OLECHAR* returnString;
  800. if (0 == pBool) {
  801. returnString = OLESTR("NULL");
  802. } else {
  803. returnString = (OLECHAR*) WsbBoolAsString(*pBool);
  804. }
  805. return(returnString);
  806. }
  807. const OLECHAR*
  808. WsbPtrToFiletimeAsString(
  809. IN BOOL isRelative,
  810. IN FILETIME *pTime
  811. )
  812. /*++
  813. Routine Description:
  814. This routine provides a string repesentation for the value of the
  815. FILETIME supplied.
  816. NOTE: This method shares memory between subsequent calls of the function.
  817. Arguments:
  818. iselatice - A boolean that indicates whether the time is absolute (e.g 1/1/1987 ...)
  819. or relative (e.g. 1 hour).
  820. pTime - A pointer to a FILETIME.
  821. Return Value:
  822. A string representation of the value of the FILETIME.
  823. --*/
  824. {
  825. OLECHAR* returnString;
  826. if (0 == pTime) {
  827. returnString = OLESTR("NULL");
  828. } else {
  829. returnString = (OLECHAR*) WsbFiletimeAsString(isRelative, *pTime);
  830. }
  831. return(returnString);
  832. }
  833. const OLECHAR*
  834. WsbPtrToGuidAsString(
  835. GUID* pGuid
  836. )
  837. /*++
  838. Routine Description:
  839. This routine provides a string repesentation for the value of the
  840. pointer to a GUID supplied.
  841. NOTE: This method does not support localization of the strings.
  842. Arguments:
  843. pGuid - A pointer to a GUID or NULL.
  844. Return Value:
  845. A string representation of the value of the GUID or "NULL" if the
  846. pointer was null.
  847. --*/
  848. {
  849. OLECHAR* returnString;
  850. if (0 == pGuid) {
  851. returnString = OLESTR("NULL");
  852. } else {
  853. returnString = (OLECHAR*) WsbGuidAsString(*pGuid);
  854. }
  855. return(returnString);
  856. }
  857. HRESULT
  858. WsbSafePtrToGuidAsString(
  859. GUID* pGuid,
  860. CWsbStringPtr &strOut
  861. )
  862. /*++
  863. Routine Description:
  864. This routine provides a string repesentation for the value of the
  865. pointer to a GUID supplied.
  866. NOTE: This is a MT-safe version of WsbGuidAsString which doesn't use
  867. static memory
  868. Arguments:
  869. pGuid - A pointer to a GUID or NULL.
  870. strOut - Output string
  871. Return Value:
  872. status (S_OK or E_OUTOFMEMORY)
  873. --*/
  874. {
  875. HRESULT hr = S_OK;
  876. if (0 == pGuid) {
  877. strOut = OLESTR("NULL");
  878. if ((WCHAR *)strOut == 0)
  879. hr = E_OUTOFMEMORY;
  880. } else {
  881. hr = WsbSafeGuidAsString(*pGuid, strOut);
  882. }
  883. return hr;
  884. }
  885. const OLECHAR*
  886. WsbPtrToHrAsString(
  887. HRESULT * pHr
  888. )
  889. /*++
  890. Routine Description:
  891. This routine provides a string repesentation for the value of the
  892. pointer to a HRESULT supplied.
  893. NOTE: This method does not support localization of the strings.
  894. Arguments:
  895. pHr - A pointer to an HRESULT.
  896. Return Value:
  897. A string representation of the value of the HRESULT.
  898. --*/
  899. {
  900. OLECHAR* returnString;
  901. if (0 == pHr) {
  902. returnString = OLESTR("NULL");
  903. } else {
  904. returnString = (OLECHAR*) WsbHrAsString(*pHr);
  905. }
  906. return(returnString);
  907. }
  908. const OLECHAR*
  909. WsbPtrToLonglongAsString(
  910. LONGLONG* pLlong
  911. )
  912. /*++
  913. Routine Description:
  914. This routine provides a string repesentation for the value of the
  915. pointer to a LONGLONG supplied.
  916. NOTE: This method does not support localization of the strings.
  917. Arguments:
  918. pLonglong - A pointer to a LONGLONG or NULL.
  919. Return Value:
  920. A string representation of the value of the LONGLONG or "NULL" if the
  921. pointer was null.
  922. --*/
  923. {
  924. OLECHAR* returnString;
  925. if (0 == pLlong) {
  926. returnString = OLESTR("NULL");
  927. } else {
  928. returnString = (OLECHAR*) WsbLonglongAsString(*pLlong);
  929. }
  930. return(returnString);
  931. }
  932. const OLECHAR*
  933. WsbPtrToLongAsString(
  934. LONG* pLong
  935. )
  936. /*++
  937. Routine Description:
  938. This routine provides a string repesentation for the value of the
  939. pointer to a LONG supplied.
  940. NOTE: This method does not support localization of the strings, and
  941. shares memory between subsequent calls of the function.
  942. Arguments:
  943. pLong - A pointer to a LONG or NULL.
  944. Return Value:
  945. A string representation of the value of the LONG or "NULL" if the
  946. pointer was null.
  947. --*/
  948. {
  949. OLECHAR* returnString;
  950. static OLECHAR defaultString[20];
  951. if (0 == pLong) {
  952. returnString = OLESTR("NULL");
  953. } else {
  954. swprintf(defaultString, OLESTR("%ld"), *pLong);
  955. returnString = defaultString;
  956. }
  957. return(returnString);
  958. }
  959. const OLECHAR*
  960. WsbPtrToShortAsString(
  961. SHORT* pShort
  962. )
  963. /*++
  964. Routine Description:
  965. This routine provides a string repesentation for the value of the
  966. pointer to a SHORT supplied.
  967. NOTE: This method does not support localization of the strings, and
  968. shares memory between subsequent calls of the function.
  969. Arguments:
  970. pShort - A pointer to a SHORT or NULL.
  971. Return Value:
  972. A string representation of the value of the SHORT or "NULL" if the
  973. pointer was null.
  974. --*/
  975. {
  976. OLECHAR* returnString;
  977. static OLECHAR defaultString[20];
  978. if (0 == pShort) {
  979. returnString = OLESTR("NULL");
  980. } else {
  981. swprintf(defaultString, OLESTR("%d"), *pShort);
  982. returnString = defaultString;
  983. }
  984. return(returnString);
  985. }
  986. const OLECHAR*
  987. WsbPtrToByteAsString(
  988. BYTE* pByte
  989. )
  990. /*++
  991. Routine Description:
  992. This routine provides a string repesentation for the value of the
  993. pointer to a BYTE supplied.
  994. NOTE: This method does not support localization of the strings, and
  995. shares memory between subsequent calls of the function.
  996. Arguments:
  997. pByte - A pointer to a BYTE or NULL.
  998. Return Value:
  999. A string representation of the value of the BYTE or "NULL" if the
  1000. pointer was null.
  1001. --*/
  1002. {
  1003. OLECHAR* returnString;
  1004. static OLECHAR defaultString[20];
  1005. if (0 == pByte) {
  1006. returnString = OLESTR("NULL");
  1007. } else {
  1008. swprintf(defaultString, OLESTR("%d"), *pByte);
  1009. returnString = defaultString;
  1010. }
  1011. return(returnString);
  1012. }
  1013. const OLECHAR*
  1014. WsbPtrToStringAsString(
  1015. OLECHAR** pString
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This routine provides a string repesentation for the value of the
  1020. pointer to a string supplied.
  1021. NOTE: This method does not support localization ofthe strings.
  1022. Arguments
  1023. pString - A pointer to a OLECHAR* or NULL.
  1024. Return Value:
  1025. The string or "NULL" if the pointer was null.
  1026. --*/
  1027. {
  1028. OLECHAR* returnString;
  1029. if( (0 == pString) || (0 == *pString) ) {
  1030. returnString = OLESTR("NULL");
  1031. } else {
  1032. returnString = *pString;
  1033. }
  1034. return(returnString);
  1035. }
  1036. const OLECHAR*
  1037. WsbPtrToUliAsString(
  1038. ULARGE_INTEGER* pUli
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This routine provides a string repesentation for the value of the
  1043. pointer to a ULARGE_INTEGER supplied.
  1044. NOTE: This method does not support localization of the strings, and
  1045. shares memory between subsequent calls of the function.
  1046. Arguments:
  1047. pUli - A pointer to a ULARGE_INTEGER or NULL.
  1048. Return Value:
  1049. A string representation of the value of the ULARGE_INTEGER or "NULL" if the
  1050. pointer was null.
  1051. --*/
  1052. {
  1053. OLECHAR* returnString;
  1054. if (0 == pUli) {
  1055. returnString = OLESTR("NULL");
  1056. } else {
  1057. returnString = (OLECHAR*) WsbLonglongAsString( pUli->QuadPart );
  1058. }
  1059. return(returnString);
  1060. }
  1061. const OLECHAR*
  1062. WsbPtrToUlongAsString(
  1063. ULONG* pUlong
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. This routine provides a string repesentation for the value of the
  1068. pointer to a ULONG supplied.
  1069. NOTE: This method does not support localization of the strings, and
  1070. shares memory between subsequent calls of the function.
  1071. Arguments:
  1072. pUlong - A pointer to a ULONG or NULL.
  1073. Return Value:
  1074. A string representation of the value of the ULONG or "NULL" if the
  1075. pointer was null.
  1076. --*/
  1077. {
  1078. OLECHAR* returnString;
  1079. static OLECHAR defaultString[20];
  1080. if (0 == pUlong) {
  1081. returnString = OLESTR("NULL");
  1082. } else {
  1083. swprintf(defaultString, OLESTR("%lu"), *pUlong);
  1084. returnString = defaultString;
  1085. }
  1086. return(returnString);
  1087. }
  1088. const OLECHAR*
  1089. WsbPtrToUshortAsString(
  1090. USHORT* pUshort
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. This routine provides a string repesentation for the value of the
  1095. pointer to a USHORT supplied.
  1096. NOTE: This method does not support localization of the strings, and
  1097. shares memory between subsequent calls of the function.
  1098. Arguments:
  1099. pUshort - A pointer to a USHORT or NULL.
  1100. Return Value:
  1101. A string representation of the value of the USHORT or "NULL" if the
  1102. pointer was null.
  1103. --*/
  1104. {
  1105. OLECHAR* returnString;
  1106. static OLECHAR defaultString[20];
  1107. if (0 == pUshort) {
  1108. returnString = OLESTR("NULL");
  1109. } else {
  1110. swprintf(defaultString, OLESTR("%u"), *pUshort);
  1111. returnString = defaultString;
  1112. }
  1113. return(returnString);
  1114. }
  1115. const OLECHAR*
  1116. WsbPtrToPtrAsString(
  1117. void** ppVoid
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. This routine provides a string repesentation for the value of the
  1122. pointer to a ULONG supplied.
  1123. NOTE: This method does not support localization of the strings, and
  1124. shares memory between subsequent calls of the function.
  1125. Arguments:
  1126. pUlong - A pointer to a ULONG or NULL.
  1127. Return Value:
  1128. A string representation of the value of the ULONG or "NULL" if the
  1129. pointer was null.
  1130. --*/
  1131. {
  1132. OLECHAR* returnString;
  1133. static OLECHAR defaultString[20];
  1134. if (0 == ppVoid) {
  1135. returnString = OLESTR("NULL");
  1136. } else {
  1137. swprintf(defaultString, OLESTR("0x%p"), *ppVoid);
  1138. returnString = defaultString;
  1139. }
  1140. return(returnString);
  1141. }
  1142. const OLECHAR*
  1143. WsbAbbreviatePath(
  1144. const OLECHAR* path,
  1145. USHORT length
  1146. )
  1147. /*++
  1148. Routine Description:
  1149. This routine condenses a path from it's original length to the requested
  1150. length by chopping out it's middle characters
  1151. NOTE: This method does not support localization of the strings, and
  1152. shares memory between subsequent calls of the function.
  1153. Arguments:
  1154. path - A pointer to the path
  1155. length - The condensed path length including the \0
  1156. Return Value:
  1157. A string representation of the value of the BYTE or "NULL" if the
  1158. pointer was null. This function also returns "NULL" if the length is less
  1159. than 4 bytes.
  1160. --*/
  1161. {
  1162. HRESULT hr = S_OK;
  1163. OLECHAR* returnString;
  1164. static CWsbStringPtr tmpString;
  1165. returnString = OLESTR("ERROR");
  1166. try {
  1167. //
  1168. // Check to see if we have anything to work with
  1169. //
  1170. if ((0 == path) || (length < 4)) {
  1171. returnString = OLESTR("NULL");
  1172. } else {
  1173. //
  1174. // Get enough space for the return
  1175. //
  1176. USHORT pathlen;
  1177. pathlen = (USHORT)wcslen(path);
  1178. hr = tmpString.Realloc(length);
  1179. if (S_OK != hr) {
  1180. returnString = OLESTR("No memory");
  1181. WsbAffirmHr(hr);
  1182. }
  1183. if (pathlen < length) {
  1184. swprintf(tmpString, OLESTR("%s"), path);
  1185. } else {
  1186. USHORT partlength = (USHORT) ( (length - 4) / 2 );
  1187. wcsncpy(tmpString, path, partlength);
  1188. tmpString[(int) partlength] = L'\0';
  1189. wcscat(tmpString, OLESTR("..."));
  1190. wcscat(tmpString, &(path[pathlen - partlength]));
  1191. }
  1192. returnString = tmpString;
  1193. }
  1194. } WsbCatch(hr);
  1195. return(returnString);
  1196. }
  1197. void WsbTraceBufferAsBytes(
  1198. DWORD size,
  1199. LPVOID data
  1200. )
  1201. /*++
  1202. Routine Description:
  1203. This routine traces an arbitrary size buffer of bytes in hex and asci.
  1204. A similar routine could be written trace a buffer in words.
  1205. Arguments:
  1206. size - The size of buffer to trace.
  1207. data - The data to trace.
  1208. Return Value:
  1209. None.
  1210. --*/
  1211. {
  1212. HRESULT hr = S_OK;
  1213. try {
  1214. // Make sure we are supposed to trace
  1215. WsbAffirm( 0 != g_pWsbTrace, S_OK);
  1216. // Make sure we have something to trace
  1217. WsbAssertPointer( data );
  1218. CWsbStringPtr traceString;
  1219. char *output;
  1220. unsigned char *bufferP = (unsigned char *)data;
  1221. // IMPORTANT NOTE: Changing these may mean the last line processing need to be changed.
  1222. char *beginAsci = " [";
  1223. char *endAsci = "]";
  1224. char *charFmt = "%02x";
  1225. char *addFmt = "%04x:";
  1226. char *between8 = " ";
  1227. char *between4 = " ";
  1228. char noPrintChar = 0x2e;
  1229. const int ll = 16; // IMPORTANT NOTE: line length, a multiple of 8 - if this changes, the last line processing needs to be fixed.
  1230. int lineCount = 0;
  1231. output = (char *)malloc( (/*address*/6+/*data*/(ll*3)+/*asci*/4+ll+3/*between*/+7+1)*sizeof(char) );
  1232. WsbAffirmAlloc( output );
  1233. if ( size > 0 ) {
  1234. unsigned long i, ii, j, k;
  1235. long repeat;
  1236. unsigned char c;
  1237. for ( i = 0; i < size; i++ ) {
  1238. if ( (0 == i % ll) && (i != 0) ) {
  1239. // print asci interpretation
  1240. sprintf( output, beginAsci );
  1241. traceString.Append(output);
  1242. for ( j = 0; j < ll; j++ ) {
  1243. c = bufferP[i-ll+j];
  1244. if ( c < ' ' || c > '~' ) {
  1245. c = noPrintChar;
  1246. }
  1247. sprintf( output, "%c", c );
  1248. traceString.Append(output);
  1249. }
  1250. sprintf( output, endAsci );
  1251. traceString.Append(output);
  1252. WsbTracef( OLESTR("%ls\n"), (WCHAR *) traceString );
  1253. lineCount++;
  1254. // now check if the next line is the same as the one just printed
  1255. repeat = 0;
  1256. ii = i;
  1257. while ( (0 == memcmp( &bufferP[ii-ll], &bufferP[ii], ll )) && (ii+ll < size) ) {
  1258. repeat++;
  1259. ii += ll;
  1260. }
  1261. if ( repeat > 1 ) {
  1262. sprintf( output, " previous line repeats %ld times", repeat);
  1263. traceString = output;
  1264. WsbTracef( OLESTR("%ls\n"), (WCHAR *) traceString );
  1265. lineCount++;
  1266. i = ii;
  1267. }
  1268. }
  1269. if ( 0 == i % ll ) {
  1270. // print address
  1271. sprintf( output, addFmt, i );
  1272. traceString = output;
  1273. }
  1274. // add alignment spacing
  1275. if ( (0 == (i + 8) % ll) ) {
  1276. sprintf( output, between8 );
  1277. traceString.Append(output);
  1278. }
  1279. else if ( 0 == i % 4 ) {
  1280. sprintf( output, between4 );
  1281. traceString.Append(output);
  1282. }
  1283. else {
  1284. sprintf( output, " " );
  1285. traceString.Append(output);
  1286. }
  1287. // print byte in hex
  1288. sprintf( output, charFmt, bufferP[i] );
  1289. traceString.Append(output);
  1290. }
  1291. // handle the last line; i allways > 0 here
  1292. // NOTE: This is only good for upto 16 chars per line.
  1293. if ( i % ll ) {
  1294. k = (ll - (i % ll)) * 3 + ( (i % ll) < 5 ? 1 : 0 )+ ( (i % ll) < 9 ? 2 : 0 )+ ( (i % ll) < 13 ? 1 : 0 );
  1295. for ( j = 0; j < k ; j++ ) {
  1296. sprintf( output, " ");
  1297. traceString.Append(output);
  1298. }
  1299. }
  1300. k = (i % ll) ? (i % ll) : ll ;
  1301. sprintf( output, beginAsci );
  1302. traceString.Append(output);
  1303. for ( j = 0; j < k; j++ ) {
  1304. c = bufferP[i-k+j];
  1305. if ( c < ' ' || c > '~' ) {
  1306. c = noPrintChar;
  1307. }
  1308. sprintf( output, "%c", c );
  1309. traceString.Append(output);
  1310. }
  1311. sprintf( output, endAsci); lineCount++;
  1312. traceString.Append(output);
  1313. WsbTracef( OLESTR("%ls\n"), (WCHAR *) traceString );
  1314. }
  1315. }
  1316. WsbCatch( hr );
  1317. }
  1318. void
  1319. WsbTraceTerminate(
  1320. void
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. Terminate (cleanup) this module because the process is ending
  1325. Arguments:
  1326. None.
  1327. Return Value:
  1328. None.
  1329. --*/
  1330. {
  1331. if (BOGUS_TLS_INDEX != TlsIndex) {
  1332. TlsFree(TlsIndex);
  1333. TlsIndex = BOGUS_TLS_INDEX;
  1334. }
  1335. }
  1336. ULONG
  1337. WsbTraceThreadOff(
  1338. void
  1339. )
  1340. /*++
  1341. Routine Description:
  1342. Increment the trace-off count for this thread
  1343. Arguments:
  1344. None.
  1345. Return Value:
  1346. The final trace-off count.
  1347. --*/
  1348. {
  1349. ULONG count = 0;
  1350. THREAD_DATA* pThreadData = NULL;
  1351. if (S_OK == GetThreadDataPointer(&pThreadData)) {
  1352. count = ++(pThreadData->TraceOffCount);
  1353. }
  1354. return(count);
  1355. }
  1356. ULONG
  1357. WsbTraceThreadOffCount(
  1358. void
  1359. )
  1360. /*++
  1361. Routine Description:
  1362. Return the current trace-off count for this thread
  1363. Arguments:
  1364. None.
  1365. Return Value:
  1366. The current trace-off count.
  1367. --*/
  1368. {
  1369. ULONG count = 0;
  1370. THREAD_DATA* pThreadData = NULL;
  1371. if (S_OK == GetThreadDataPointer(&pThreadData)) {
  1372. count = pThreadData->TraceOffCount;
  1373. }
  1374. return(count);
  1375. }
  1376. ULONG
  1377. WsbTraceThreadOn(
  1378. void
  1379. )
  1380. /*++
  1381. Routine Description:
  1382. Decrement the trace-off count for this thread
  1383. Arguments:
  1384. None.
  1385. Return Value:
  1386. The final trace-off count.
  1387. --*/
  1388. {
  1389. ULONG count = 0;
  1390. THREAD_DATA* pThreadData = NULL;
  1391. if (S_OK == GetThreadDataPointer(&pThreadData)) {
  1392. if (0 < pThreadData->TraceOffCount) {
  1393. pThreadData->TraceOffCount--;
  1394. }
  1395. count = pThreadData->TraceOffCount;
  1396. }
  1397. return(count);
  1398. }
  1399. static HRESULT
  1400. OutputTraceString(
  1401. IN ULONG indentLevel,
  1402. IN OLECHAR* introString,
  1403. IN OLECHAR* format,
  1404. IN va_list vaList
  1405. )
  1406. /*++
  1407. Routine Description:
  1408. Build and output the trace string.
  1409. Arguments:
  1410. indentLevel - Count of indentation strings to output
  1411. introString - String to add before variable list
  1412. vaList - Variable list to format
  1413. Return Value:
  1414. The data pointer.
  1415. --*/
  1416. {
  1417. HRESULT hr = S_OK;
  1418. OLECHAR traceString[WSB_TRACE_BUFF_SIZE];
  1419. try {
  1420. LONG incSize;
  1421. LONG traceSize = 0;
  1422. // Initialize the string
  1423. swprintf(traceString, OLESTR(""));
  1424. // Add indentation
  1425. incSize = wcslen(WSB_INDENT_STRING);
  1426. for(ULONG level = 0; level < indentLevel; level++) {
  1427. if ((traceSize + incSize) < WSB_TRACE_BUFF_SIZE) {
  1428. wcscat(traceString, WSB_INDENT_STRING);
  1429. traceSize += incSize;
  1430. }
  1431. }
  1432. // Add the intro string
  1433. if (introString) {
  1434. incSize = wcslen(introString);
  1435. } else {
  1436. incSize = 0;
  1437. }
  1438. if (incSize && ((traceSize + incSize) < WSB_TRACE_BUFF_SIZE)) {
  1439. wcscat(traceString, introString);
  1440. traceSize += incSize;
  1441. }
  1442. // Format the arguments (leave room for EOL and EOS)
  1443. incSize = _vsnwprintf(&traceString[traceSize],
  1444. (WSB_TRACE_BUFF_SIZE - traceSize - 3), format, vaList);
  1445. if (incSize < 0) {
  1446. // This means we filled the buffer and would have overflowed
  1447. // Need to add EOS
  1448. traceString[WSB_TRACE_BUFF_SIZE - 3] = OLECHAR('\0');
  1449. traceSize = WSB_TRACE_BUFF_SIZE - 3;
  1450. } else {
  1451. traceSize += incSize;
  1452. }
  1453. // Add EOL if needed
  1454. if (introString) {
  1455. wcscat(&traceString[traceSize], OLESTR("\r\n"));
  1456. }
  1457. WsbAffirmHr(g_pWsbTrace->Print(traceString));
  1458. } WsbCatch (hr);
  1459. return(hr);
  1460. }
  1461. static HRESULT
  1462. GetThreadDataPointer(
  1463. OUT THREAD_DATA** ppTD
  1464. )
  1465. /*++
  1466. Routine Description:
  1467. Return a pointer to the data specific to the current thread. This
  1468. function will allocate space for the thread data (and initialize it)
  1469. if needed.
  1470. Arguments:
  1471. ppTD - Pointer to pointer to thread data.
  1472. Return Value:
  1473. The data pointer.
  1474. --*/
  1475. {
  1476. HRESULT hr = E_FAIL;
  1477. THREAD_DATA* pThreadData = NULL;
  1478. // Make sure the TLS index is valid
  1479. if (BOGUS_TLS_INDEX != TlsIndex) {
  1480. // Try to get the data pointer for this thread
  1481. pThreadData = static_cast<THREAD_DATA*>(TlsGetValue(TlsIndex));
  1482. if (pThreadData) {
  1483. hr = S_OK;
  1484. } else {
  1485. // Allocate data for this thread yet
  1486. pThreadData = static_cast<THREAD_DATA*>(WsbAlloc(sizeof(THREAD_DATA)));
  1487. if (pThreadData) {
  1488. if (TlsSetValue(TlsIndex, pThreadData)) {
  1489. // Initialize the data for this thread
  1490. pThreadData->TraceOffCount = 0;
  1491. pThreadData->IndentLevel = 0;
  1492. pThreadData->LogModule = NULL;
  1493. pThreadData->LogModuleLine = 0;
  1494. pThreadData->LogNTBuild = 0;
  1495. pThreadData->LogRSBuild = 0;
  1496. hr = S_OK;
  1497. } else {
  1498. // TlsSetValue failed!
  1499. WsbFree(pThreadData);
  1500. pThreadData = NULL;
  1501. }
  1502. }
  1503. }
  1504. }
  1505. *ppTD = pThreadData;
  1506. return(hr);
  1507. }
  1508. static void
  1509. SnapShotTraceAndEvent(
  1510. SYSTEMTIME stime
  1511. )
  1512. /*++
  1513. Routine Description:
  1514. This routine saves the trace files and event logs
  1515. Arguments:
  1516. Return Value:
  1517. None.
  1518. --*/
  1519. {
  1520. HRESULT hr = S_OK;
  1521. PSID pSystemSID = NULL;
  1522. PSID pAdminSID = NULL;
  1523. PACL pACL = NULL;
  1524. PSECURITY_DESCRIPTOR pSD = NULL;
  1525. #define TRACE_MUTEX_NUM_ACE 2
  1526. EXPLICIT_ACCESS ea[TRACE_MUTEX_NUM_ACE];
  1527. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  1528. SECURITY_ATTRIBUTES sa;
  1529. try {
  1530. OLECHAR dataString[256];
  1531. OLECHAR tmpString[50];
  1532. OLECHAR mutexName[50] = L"WsbTraceSnapShotMutex";
  1533. DWORD sizeGot;
  1534. HANDLE mutexHandle = INVALID_HANDLE_VALUE;
  1535. //
  1536. // The level is one to snap shot and snap shot is on. Now make sure there is a
  1537. // path specified where we are to copy the logs
  1538. //
  1539. WsbAffirm(0 != g_pWsbLogSnapShotPath, E_POINTER);
  1540. WsbAffirm(0 != wcslen(g_pWsbLogSnapShotPath), E_POINTER);
  1541. //
  1542. // Get the system root string from the registry
  1543. //
  1544. WsbAffirmHr(WsbGetRegistryValueString(NULL, WSB_CURRENT_VERSION_REGISTRY_KEY, WSB_SYSTEM_ROOT_REGISTRY_VALUE, dataString, 256, &sizeGot));
  1545. CWsbStringPtr snapShotSubDir;
  1546. CWsbStringPtr snapShotFile;
  1547. snapShotSubDir = g_pWsbLogSnapShotPath;
  1548. //
  1549. // Make sure there is a "\" at the end of the path
  1550. //
  1551. int len;
  1552. len = wcslen(snapShotSubDir);
  1553. if (snapShotSubDir[len] != '\\') {
  1554. snapShotSubDir.Append(L"\\");
  1555. }
  1556. // Build the path to the subdirectory that will contain the logs from the input path
  1557. // and the time of the event.
  1558. swprintf(tmpString, OLESTR("%2.02u.%2.02u-%2.2u.%2.2u.%2.2u.%3.3u"),
  1559. stime.wMonth, stime.wDay,
  1560. stime.wHour, stime.wMinute,
  1561. stime.wSecond, stime.wMilliseconds);
  1562. snapShotSubDir.Append(tmpString);
  1563. //
  1564. // Make sure the subdirectory can be created
  1565. //
  1566. WsbAffirmHr(WsbCreateAllDirectories(snapShotSubDir));
  1567. //
  1568. // Create SD that allows access only to local-system and admin
  1569. // (All RSS process that may be tracing must run as LocalSystem or Admin)
  1570. //
  1571. memset(ea, 0, sizeof(EXPLICIT_ACCESS) * TRACE_MUTEX_NUM_ACE);
  1572. WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 2,
  1573. SECURITY_BUILTIN_DOMAIN_RID,
  1574. DOMAIN_ALIAS_RID_ADMINS,
  1575. 0, 0, 0, 0, 0, 0,
  1576. &pAdminSID) );
  1577. ea[0].grfAccessPermissions = FILE_ALL_ACCESS;
  1578. ea[0].grfAccessMode = SET_ACCESS;
  1579. ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1580. ea[0].Trustee.pMultipleTrustee = NULL;
  1581. ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1582. ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1583. ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1584. ea[0].Trustee.ptstrName = (LPTSTR) pAdminSID;
  1585. WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 1,
  1586. SECURITY_LOCAL_SYSTEM_RID,
  1587. 0, 0, 0, 0, 0, 0, 0,
  1588. &pSystemSID) );
  1589. ea[1].grfAccessPermissions = FILE_ALL_ACCESS;
  1590. ea[1].grfAccessMode = SET_ACCESS;
  1591. ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1592. ea[1].Trustee.pMultipleTrustee = NULL;
  1593. ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1594. ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1595. ea[1].Trustee.TrusteeType = TRUSTEE_IS_USER;
  1596. ea[1].Trustee.ptstrName = (LPTSTR) pSystemSID;
  1597. WsbAffirmNoError(SetEntriesInAcl(TRACE_MUTEX_NUM_ACE, ea, NULL, &pACL));
  1598. pSD = (PSECURITY_DESCRIPTOR) WsbAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
  1599. WsbAffirmPointer(pSD);
  1600. WsbAffirmStatus(InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION));
  1601. WsbAffirmStatus(SetSecurityDescriptorDacl(
  1602. pSD,
  1603. TRUE, // fDaclPresent flag
  1604. pACL,
  1605. FALSE)); // not a default DACL
  1606. sa.nLength = sizeof (SECURITY_ATTRIBUTES);
  1607. sa.lpSecurityDescriptor = pSD;
  1608. sa.bInheritHandle = FALSE;
  1609. //
  1610. // We need to synchronize around the creating of the
  1611. // event backup files and copying them. Since all three
  1612. // services will access this code, use a mutex to
  1613. // synchronize them.
  1614. mutexHandle = CreateMutex(&sa, TRUE, mutexName);
  1615. if (mutexHandle) {
  1616. //
  1617. // Copy the event logs
  1618. // First back them up and then copy the backup file.
  1619. //
  1620. HANDLE eventLogHandle = INVALID_HANDLE_VALUE;
  1621. try {
  1622. CWsbStringPtr computerName;
  1623. CWsbStringPtr logName;
  1624. WsbAffirmHr( WsbGetComputerName( computerName ) );
  1625. //
  1626. // Open the application event log and back it up
  1627. //
  1628. logName = dataString;
  1629. logName.Append(WSB_APP_EVENT_LOG);
  1630. eventLogHandle = OpenEventLog((LPCTSTR)computerName, (LPCTSTR)logName);
  1631. if (INVALID_HANDLE_VALUE != eventLogHandle) {
  1632. logName = dataString;
  1633. logName.Append(WSB_APP_EVENT_LOG_BKUP);
  1634. DeleteFile(logName);
  1635. WsbAffirmStatus(BackupEventLog(eventLogHandle, (LPCTSTR)logName));
  1636. WsbAffirmStatus(CloseEventLog(eventLogHandle));
  1637. snapShotFile = snapShotSubDir;
  1638. snapShotFile.Append(WSB_APP_EVENT_LOG_NAME);
  1639. //
  1640. // Now copy the backup file
  1641. //
  1642. WsbAffirmStatus(CopyFile(logName, snapShotFile, FALSE));
  1643. }
  1644. //
  1645. // Open the system event log and back it up
  1646. //
  1647. logName = dataString;
  1648. logName.Append(WSB_SYS_EVENT_LOG);
  1649. eventLogHandle = OpenEventLog((LPCTSTR)computerName, (LPCTSTR)logName);
  1650. if (INVALID_HANDLE_VALUE != eventLogHandle) {
  1651. logName = dataString;
  1652. logName.Append(WSB_SYS_EVENT_LOG_BKUP);
  1653. DeleteFile(logName);
  1654. WsbAffirmStatus(BackupEventLog(eventLogHandle, (LPCTSTR)logName));
  1655. WsbAffirmStatus(CloseEventLog(eventLogHandle));
  1656. snapShotFile = snapShotSubDir;
  1657. snapShotFile.Append(WSB_SYS_EVENT_LOG_NAME);
  1658. //
  1659. // Now copy the backup file
  1660. //
  1661. WsbAffirmStatus(CopyFile(logName, snapShotFile, FALSE));
  1662. }
  1663. } WsbCatchAndDo(hr,if (INVALID_HANDLE_VALUE != eventLogHandle) {
  1664. CloseEventLog(eventLogHandle);}; hr = S_OK; );
  1665. (void)ReleaseMutex(mutexHandle);
  1666. }
  1667. //
  1668. // Copy the trace files if there are any
  1669. //
  1670. try {
  1671. WIN32_FIND_DATA findData;
  1672. HANDLE handle;
  1673. CWsbStringPtr traceFile;
  1674. CWsbStringPtr searchString;
  1675. BOOL foundFile;
  1676. //
  1677. // Find the file(s)
  1678. //
  1679. WsbAffirmHr(WsbGetMetaDataPath(searchString));
  1680. searchString.Append(WSB_RS_TRACE_FILES);
  1681. handle = FindFirstFile(searchString, &findData);
  1682. snapShotFile = snapShotSubDir;
  1683. snapShotFile.Append(L"\\");
  1684. WsbAffirmHr(WsbGetMetaDataPath(traceFile));
  1685. traceFile.Append(WSB_RS_TRACE_PATH);
  1686. WsbAffirmHr(snapShotFile.Append((OLECHAR *)(findData.cFileName)));
  1687. WsbAffirmHr(traceFile.Append((OLECHAR *)(findData.cFileName)));
  1688. // If we found a file, then remember the scan handle and
  1689. // return the scan item.
  1690. foundFile = TRUE;
  1691. while ((INVALID_HANDLE_VALUE != handle) && (foundFile == TRUE)) {
  1692. if ((FILE_ATTRIBUTE_DIRECTORY & findData.dwFileAttributes) != FILE_ATTRIBUTE_DIRECTORY) {
  1693. WsbAffirmStatus(CopyFile(traceFile, snapShotFile, FALSE));
  1694. }
  1695. foundFile = FindNextFile(handle, &findData);
  1696. snapShotFile = snapShotSubDir;
  1697. snapShotFile.Append(L"\\");
  1698. WsbAffirmHr(WsbGetMetaDataPath(traceFile));
  1699. traceFile.Append(WSB_RS_TRACE_PATH);
  1700. WsbAffirmHr(snapShotFile.Append((OLECHAR *)(findData.cFileName)));
  1701. WsbAffirmHr(traceFile.Append((OLECHAR *)(findData.cFileName)));
  1702. }
  1703. } WsbCatchAndDo(hr, hr = S_OK; );
  1704. }
  1705. WsbCatch( hr );
  1706. if (pAdminSID) {
  1707. FreeSid(pAdminSID);
  1708. }
  1709. if (pSystemSID) {
  1710. FreeSid(pSystemSID);
  1711. }
  1712. if (pACL) {
  1713. LocalFree(pACL);
  1714. }
  1715. if (pSD) {
  1716. WsbFree(pSD);
  1717. }
  1718. }
  1719. #include "winnls.h"
  1720. #include "resource.h"
  1721. #define HIDWORD(_qw) (DWORD)((_qw)>>32)
  1722. #define LODWORD(_qw) (DWORD)(_qw)
  1723. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  1724. LPTSTR AddCommas(DWORD dw, LPTSTR pszResult, int nResLen);
  1725. const int pwOrders[] = {IDS_WSB_BYTES, IDS_WSB_ORDERKB, IDS_WSB_ORDERMB,
  1726. IDS_WSB_ORDERGB, IDS_WSB_ORDERTB, IDS_WSB_ORDERPB, IDS_WSB_ORDEREB};
  1727. HRESULT WsbShortSizeFormat64(__int64 dw64, LPTSTR szBuf)
  1728. /*++
  1729. Routine Description:
  1730. Converts numbers into sort formats
  1731. 532 -> 523 bytes
  1732. 1340 -> 1.3KB
  1733. 23506 -> 23.5KB
  1734. -> 2.4MB
  1735. -> 5.2GB
  1736. Arguments:
  1737. Return Value:
  1738. Note:
  1739. This code is cloned from MS source /shell/shelldll/util.c - AHB
  1740. --*/
  1741. {
  1742. int i;
  1743. UINT wInt, wLen, wDec;
  1744. TCHAR szTemp[10], szOrder[20], szFormat[5];
  1745. HMODULE hModule;
  1746. if (dw64 < 1000) {
  1747. wsprintf(szTemp, TEXT("%d"), LODWORD(dw64));
  1748. i = 0;
  1749. goto AddOrder;
  1750. }
  1751. for (i = 1; i<ARRAYSIZE(pwOrders)-1 && dw64 >= 1000L * 1024L; dw64 >>= 10, i++);
  1752. /* do nothing */
  1753. wInt = LODWORD(dw64 >> 10);
  1754. AddCommas(wInt, szTemp, 10);
  1755. wLen = lstrlen(szTemp);
  1756. if (wLen < 3)
  1757. {
  1758. wDec = LODWORD(dw64 - (__int64)wInt * 1024L) * 1000 / 1024;
  1759. // At this point, wDec should be between 0 and 1000
  1760. // we want get the top one (or two) digits.
  1761. wDec /= 10;
  1762. if (wLen == 2)
  1763. wDec /= 10;
  1764. // Note that we need to set the format before getting the
  1765. // intl char.
  1766. lstrcpy(szFormat, TEXT("%02d"));
  1767. szFormat[2] = (TCHAR)( TEXT('0') + 3 - wLen );
  1768. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
  1769. szTemp+wLen, ARRAYSIZE(szTemp)-wLen);
  1770. wLen = lstrlen(szTemp);
  1771. wLen += wsprintf(szTemp+wLen, szFormat, wDec);
  1772. }
  1773. AddOrder:
  1774. hModule = LoadLibraryEx(WSB_FACILITY_PLATFORM_NAME, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1775. if (hModule) {
  1776. LoadString(hModule,
  1777. pwOrders[i],
  1778. szOrder,
  1779. ARRAYSIZE(szOrder));
  1780. wsprintf(szBuf, szOrder, (LPTSTR)szTemp);
  1781. FreeLibrary(hModule);
  1782. }
  1783. return S_OK;
  1784. }
  1785. LPTSTR AddCommas(DWORD dw, LPTSTR pszResult, int nResLen)
  1786. /*++
  1787. Routine Description:
  1788. Takes a DWORD add commas etc to it and puts the result in the buffer
  1789. Arguments:
  1790. Return Value:
  1791. Note:
  1792. This code is cloned from MS source /shell/shelldll/util.c - AHB
  1793. --*/
  1794. {
  1795. TCHAR szTemp[20]; // more than enough for a DWORD
  1796. TCHAR szSep[5];
  1797. NUMBERFMT nfmt;
  1798. nfmt.NumDigits=0;
  1799. nfmt.LeadingZero=0;
  1800. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep));
  1801. nfmt.Grouping = _tcstol(szSep, NULL, 10);
  1802. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep));
  1803. nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep;
  1804. nfmt.NegativeOrder= 0;
  1805. wsprintf(szTemp, TEXT("%lu"), dw);
  1806. if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, nResLen) == 0)
  1807. lstrcpy(pszResult, szTemp);
  1808. return pszResult;
  1809. }
  1810. void
  1811. WsbTraceAndPrint(
  1812. DWORD eventId,
  1813. ...
  1814. )
  1815. /*++
  1816. Routine Description:
  1817. This routine writes a message into standard output. The message
  1818. is also written to the application trace file.
  1819. Arguments:
  1820. eventId - The message Id to log.
  1821. Inserts - Message inserts that are merged with the message description specified by
  1822. eventId. The number of inserts must match the number specified by the
  1823. message description. The last insert must be NULL to indicate the
  1824. end of the insert list.
  1825. Return Value:
  1826. None.
  1827. --*/
  1828. {
  1829. HRESULT hr = S_OK;
  1830. try {
  1831. va_list vaList;
  1832. va_start(vaList, eventId);
  1833. WsbTraceAndPrintV(eventId, &vaList );
  1834. va_end(vaList);
  1835. } WsbCatch( hr );
  1836. }
  1837. void
  1838. WsbTraceAndPrintV(
  1839. DWORD eventId,
  1840. va_list * inserts
  1841. )
  1842. /*++
  1843. Routine Description:
  1844. This routine writes a message into standard output. The message
  1845. is also written to the application trace file.
  1846. Arguments:
  1847. eventId - The message Id to log.
  1848. inserts - An array of message inserts that are merged with the message description
  1849. specified by eventId. The number of inserts must match the number
  1850. specified by the message description. The last insert must be NULL,
  1851. to indicate the end of the insert list.
  1852. Return Value:
  1853. None.
  1854. --*/
  1855. {
  1856. HRESULT hr = S_OK;
  1857. char *pszMultiByte = NULL;
  1858. try {
  1859. WsbAssertPointer( inserts );
  1860. const OLECHAR * facilityName = 0;
  1861. BOOL bPrint;
  1862. OLECHAR * messageText = 0;
  1863. //
  1864. // Determine type of event
  1865. //
  1866. switch ( eventId & 0xc0000000 ) {
  1867. case ERROR_SEVERITY_INFORMATIONAL:
  1868. bPrint = (g_WsbPrintLevel >= WSB_LOG_LEVEL_INFORMATION) ? TRUE : FALSE;
  1869. break;
  1870. case ERROR_SEVERITY_WARNING:
  1871. bPrint = (g_WsbPrintLevel >= WSB_LOG_LEVEL_WARNING) ? TRUE : FALSE;
  1872. break;
  1873. case ERROR_SEVERITY_ERROR:
  1874. bPrint = (g_WsbPrintLevel >= WSB_LOG_LEVEL_ERROR) ? TRUE : FALSE;
  1875. break;
  1876. default:
  1877. bPrint = (g_WsbPrintLevel >= WSB_LOG_LEVEL_COMMENT) ? TRUE : FALSE;
  1878. break;
  1879. }
  1880. WsbAffirm (bPrint, S_OK);
  1881. //
  1882. // Determine source facility of message
  1883. //
  1884. switch ( HRESULT_FACILITY( eventId ) ) {
  1885. case WSB_FACILITY_PLATFORM:
  1886. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1887. break;
  1888. case WSB_FACILITY_RMS:
  1889. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1890. break;
  1891. case WSB_FACILITY_HSMENG:
  1892. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1893. break;
  1894. case WSB_FACILITY_JOB:
  1895. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1896. break;
  1897. case WSB_FACILITY_HSMTSKMGR:
  1898. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1899. break;
  1900. case WSB_FACILITY_FSA:
  1901. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1902. break;
  1903. case WSB_FACILITY_GUI:
  1904. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1905. break;
  1906. case WSB_FACILITY_MOVER:
  1907. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1908. break;
  1909. case WSB_FACILITY_LAUNCH:
  1910. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1911. break;
  1912. case WSB_FACILITY_USERLINK:
  1913. facilityName = WSB_FACILITY_PLATFORM_NAME;
  1914. break;
  1915. case WSB_FACILITY_CLI:
  1916. facilityName = WSB_FACILITY_CLI_NAME;
  1917. break;
  1918. case WSB_FACILITY_TEST:
  1919. facilityName = WSB_FACILITY_TEST_NAME;
  1920. break;
  1921. case HRESULT_FACILITY(FACILITY_NT_BIT):
  1922. facilityName = WSB_FACILITY_NTDLL_NAME;
  1923. eventId &= ~FACILITY_NT_BIT;
  1924. break;
  1925. default:
  1926. facilityName = WSB_FACILITY_NTDLL_NAME;
  1927. break;
  1928. }
  1929. if ( facilityName ) {
  1930. HMODULE hModule;
  1931. hModule = LoadLibraryEx( facilityName, NULL, LOAD_LIBRARY_AS_DATAFILE );
  1932. if (hModule) {
  1933. //
  1934. // Load and format the message
  1935. //
  1936. FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1937. hModule,
  1938. eventId,
  1939. MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  1940. (LPTSTR) &messageText,
  1941. 0,
  1942. inserts);
  1943. if ( messageText ) {
  1944. //
  1945. // Print the message (Format messages come with \n)
  1946. // Use the WriteConsole/WriteFile to output messages for localiztion support
  1947. //
  1948. // Get console handle
  1949. DWORD fdwMode, dwBytesWritten;
  1950. HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  1951. WsbAffirmHandle(hOutput);
  1952. // Check to see if it's a console handle or not
  1953. // If the user redirected to a file or used a pipe, we need to use different APIs for writing
  1954. if( (GetFileType(hOutput) & FILE_TYPE_CHAR) && GetConsoleMode(hOutput, &fdwMode) ) {
  1955. // Console
  1956. WsbAffirmStatus(WriteConsoleW(hOutput, messageText, (DWORD)wcslen(messageText), &dwBytesWritten, NULL));
  1957. } else {
  1958. // Not a console
  1959. // Get number of chars required for the translation and alloate
  1960. int nCharCount = WideCharToMultiByte(GetConsoleOutputCP(), 0, messageText, -1, 0, 0, 0, 0);
  1961. if (nCharCount == 0) {
  1962. WsbAffirmWin32(GetLastError());
  1963. }
  1964. pszMultiByte = (char *)WsbAlloc(nCharCount);
  1965. // Translate and write, avoid writing the terminating null
  1966. nCharCount = WideCharToMultiByte(GetConsoleOutputCP(), 0, messageText, -1, pszMultiByte, nCharCount, 0, 0);
  1967. if (nCharCount == 0) {
  1968. WsbAffirmWin32(GetLastError());
  1969. }
  1970. WsbAffirmStatus(WriteFile(hOutput, pszMultiByte, nCharCount-1, &dwBytesWritten, 0));
  1971. // Buffer is freed at the end of this functiob to cover for an error case
  1972. }
  1973. //
  1974. // Trace the message
  1975. //
  1976. if ( g_pWsbTrace ) {
  1977. WsbTracef( OLESTR("!!!!! PRINT - Event <0x%08lx> is printed\n"), eventId );
  1978. WsbTracef( OLESTR("%ls"), messageText ); // Format messages come with \n
  1979. }
  1980. LocalFree( messageText );
  1981. } else {
  1982. if ( g_pWsbTrace ) {
  1983. WsbTracef( OLESTR("!!!!! PRINT !!!!! - Message <0x%08lx> could not be translated.\r\n"), eventId );
  1984. }
  1985. }
  1986. FreeLibrary(hModule);
  1987. } else {
  1988. WsbTracef( OLESTR("!!!!! EVENT !!!!! - Could not load facility name DLL %ls. \r\n"), facilityName);
  1989. }
  1990. } else {
  1991. if ( g_pWsbTrace ) {
  1992. WsbTracef( OLESTR("!!!!! PRINT !!!!! - Message File for <0x%08lx> could not be found.\r\n"), eventId );
  1993. }
  1994. }
  1995. } WsbCatch( hr );
  1996. if (pszMultiByte != NULL) {
  1997. WsbFree(pszMultiByte);
  1998. pszMultiByte = NULL;
  1999. }
  2000. }