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.

760 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. // Copyright (C) 1991-1994, Microsoft Corporation.
  3. //
  4. // File: assert.cpp
  5. //
  6. // Contents: Debugging output routines
  7. //
  8. // History: 23-Jul-91 KyleP Created.
  9. // 09-Oct-91 KevinRo Major changes and comments added
  10. // 18-Oct-91 vich moved debug print routines out
  11. // 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
  12. // 7-Oct-94 BruceFo Ripped out all kernel, non-FLAT,
  13. // DLL-specific, non-Win32 functionality.
  14. // Now it's basically "print to the
  15. // debugger" code.
  16. // 20-Oct-95 EricB Set component debug level in the
  17. // registry.
  18. //
  19. //----------------------------------------------------------------------------
  20. #include "headers.h"
  21. #pragma hdrstop
  22. #include <shlwapi.h>
  23. #include <objbase.h>
  24. #include <basetyps.h>
  25. #include <tchar.h>
  26. #if DBG==1
  27. #include "malloc.h" // alloca
  28. //
  29. // Globals
  30. //
  31. ULONG g_AdminAssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
  32. BOOL g_fInitializedTickCount = FALSE;
  33. ULONG g_ulTickCountAtStart;
  34. BOOL g_fCritSecInit = FALSE;
  35. CRITICAL_SECTION g_csMessageBuf;
  36. static TCHAR g_szMessageBuf[2048]; // this is the message buffer
  37. DECLARE_HEAPCHECKING;
  38. //
  39. // Forward declration of local functions
  40. //
  41. LPSTR AnsiPathFindFileName(LPSTR pPath);
  42. void InitializeDebugging(void);
  43. void smprintf(ULONG ulCompMask, ULONG cchIndent, LPTSTR pszComp, LPTSTR ppszfmt, va_list pargs);
  44. static int w4smprintf(LPTSTR format, va_list arglist);
  45. //+---------------------------------------------------------------------------
  46. //
  47. // Function: w4dprintf
  48. //
  49. // Synopsis: Calls w4smprintf to output a formatted message.
  50. //
  51. //----------------------------------------------------------------------------
  52. static int __cdecl w4dprintf(LPTSTR format, ...)
  53. {
  54. int ret;
  55. va_list va;
  56. va_start(va, format);
  57. ret = w4smprintf(format, va);
  58. va_end(va);
  59. return ret;
  60. }
  61. //+---------------------------------------------------------------------------
  62. //
  63. // Function: w4smprintf
  64. //
  65. // Synopsis: Calls OutputDebugStringA to output a formatted message.
  66. //
  67. //----------------------------------------------------------------------------
  68. static int w4smprintf(LPTSTR format, va_list arglist)
  69. {
  70. int ret;
  71. EnterCriticalSection(&g_csMessageBuf);
  72. ret = StringCchVPrintf(g_szMessageBuf,
  73. sizeof(g_szMessageBuf)/sizeof(TCHAR),
  74. format,
  75. arglist);
  76. OutputDebugString(g_szMessageBuf);
  77. LeaveCriticalSection(&g_csMessageBuf);
  78. return ret;
  79. }
  80. //+------------------------------------------------------------
  81. // Function: smprintf
  82. //
  83. // Synopsis: Prints debug output using a pointer to the
  84. // variable information. Used primarily by the
  85. // xxDebugOut macros
  86. //
  87. // Arguements:
  88. // ulCompMask -- Component level mask used to determine
  89. // output ability
  90. // pszComp -- String const of component prefix.
  91. // ppszfmt -- Pointer to output format and data
  92. //
  93. //-------------------------------------------------------------
  94. CRITICAL_SECTION g_csDebugPrint;
  95. void smprintf(
  96. ULONG ulCompMask,
  97. ULONG cchIndent,
  98. LPTSTR pszComp,
  99. LPTSTR ppszfmt,
  100. va_list pargs)
  101. {
  102. if (ulCompMask & DEB_FORCE)
  103. {
  104. EnterCriticalSection(&g_csDebugPrint);
  105. if (ulCompMask & DEB_ELAPSEDTIME)
  106. {
  107. ULONG ulTicksNow = GetTickCount();
  108. if (!g_fInitializedTickCount)
  109. {
  110. g_fInitializedTickCount = TRUE;
  111. g_ulTickCountAtStart = ulTicksNow;
  112. }
  113. ULONG ulDelta;
  114. if (g_ulTickCountAtStart > ulTicksNow)
  115. {
  116. ulDelta = ulTicksNow + ((ULONG)-1) - g_ulTickCountAtStart;
  117. }
  118. else
  119. {
  120. ulDelta = ulTicksNow - g_ulTickCountAtStart;
  121. }
  122. w4dprintf(_T("%04u.%03u "), ulDelta / 1000, ulDelta % 1000);
  123. }
  124. if (!(ulCompMask & DEB_NOCOMPNAME))
  125. {
  126. DWORD pid = GetCurrentProcessId();
  127. DWORD tid = GetCurrentThreadId();
  128. w4dprintf(_T("%x.%03x> %s: "), pid, tid, pszComp);
  129. }
  130. if (cchIndent)
  131. {
  132. TCHAR tzFmt[] = _T("%999s");
  133. if(cchIndent > 999)
  134. cchIndent = 999;
  135. if(SUCCEEDED(StringCchPrintf(tzFmt,6,_T("%%%us"), cchIndent)))
  136. {
  137. w4dprintf(tzFmt, _T(""));
  138. }
  139. }
  140. w4smprintf(ppszfmt, pargs);
  141. LeaveCriticalSection(&g_csDebugPrint);
  142. }
  143. }
  144. //+----------------------------------------------------------------------------
  145. //
  146. // Admin debuggging library inititalization.
  147. //
  148. // To set a non-default debug info level outside of the debugger, create the
  149. // below registry key and in it create a value whose name is the component's
  150. // debugging tag name (the "comp" parameter to the DECLARE_INFOLEVEL macro) and
  151. // whose data is the desired infolevel in REG_DWORD format.
  152. //-----------------------------------------------------------------------------
  153. #define CURRENT_VERSION_KEY _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion")
  154. #define ADMINDEBUGKEY _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AdminDebug")
  155. #define ADMINDEBUG _T("AdminDebug")
  156. //+----------------------------------------------------------------------------
  157. // Function: CheckInit
  158. //
  159. // Synopsis: Performs debugging library initialization
  160. // including reading the registry for the desired infolevel
  161. //
  162. //-----------------------------------------------------------------------------
  163. void CheckInit(LPTSTR pInfoLevelString, ULONG * pulInfoLevel)
  164. {
  165. HKEY hKey;
  166. LONG lRet;
  167. DWORD dwSize;
  168. if (!g_fCritSecInit) InitializeDebugging();
  169. *pulInfoLevel = DEF_INFOLEVEL;
  170. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  171. ADMINDEBUGKEY,
  172. 0,
  173. KEY_READ,
  174. &hKey);
  175. if (lRet == ERROR_FILE_NOT_FOUND)
  176. {
  177. HKEY hkCV;
  178. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, CURRENT_VERSION_KEY, 0,
  179. KEY_ALL_ACCESS, &hkCV);
  180. if (lRet == ERROR_SUCCESS)
  181. {
  182. lRet = RegCreateKeyEx(hkCV, ADMINDEBUG, 0, _T(""),
  183. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
  184. RegCloseKey(hkCV);
  185. }
  186. }
  187. if (lRet == ERROR_SUCCESS)
  188. {
  189. dwSize = sizeof(ULONG);
  190. lRet = RegQueryValueEx(hKey, pInfoLevelString, NULL, NULL,
  191. (LPBYTE)pulInfoLevel, &dwSize);
  192. if (lRet != ERROR_SUCCESS)
  193. {
  194. lRet = RegSetValueEx(hKey, pInfoLevelString, 0, REG_DWORD,
  195. (CONST BYTE *)pulInfoLevel, sizeof(ULONG));
  196. }
  197. RegCloseKey(hKey);
  198. }
  199. }
  200. void InitializeDebugging(void)
  201. {
  202. if (g_fCritSecInit) return;
  203. InitializeCriticalSection(&g_csMessageBuf);
  204. InitializeCriticalSection(&g_csDebugPrint);
  205. g_fCritSecInit = TRUE;
  206. }
  207. // Returns a pointer to the last component of a path string.
  208. //
  209. // in:
  210. // path name, either fully qualified or not
  211. //
  212. // returns:
  213. // pointer into the path where the path is. if none is found
  214. // returns a poiter to the start of the path
  215. //
  216. // c:\foo\bar -> bar
  217. // c:\foo -> foo
  218. // c:\foo\ -> c:\foo\ (REVIEW: is this case busted?)
  219. // c:\ -> c:\ (REVIEW: this case is strange)
  220. // c: -> c:
  221. // foo -> foo
  222. LPSTR AnsiPathFindFileName(LPSTR pPath)
  223. {
  224. LPSTR pT;
  225. for (pT = pPath; *pPath; pPath = CharNextA(pPath))
  226. {
  227. if ((pPath[0] == '\\' || pPath[0] == ':')
  228. && pPath[1] && (pPath[1] != '\\'))
  229. pT = pPath + 1;
  230. }
  231. return(LPSTR)pT; // const -> non const
  232. }
  233. /////////////////////////////////////////////////////////////////////////////
  234. /////////////////////////////////////////////////////////////////////////////
  235. ////////////// ASSERT CODE //////////////////////////////////////////////
  236. /////////////////////////////////////////////////////////////////////////////
  237. /////////////////////////////////////////////////////////////////////////////
  238. //+------------------------------------------------------------
  239. // Function: PopUpError
  240. //
  241. // Synopsis: Displays a dialog box using provided text,
  242. // and presents the user with the option to
  243. // continue or cancel.
  244. //
  245. // Arguments:
  246. // szMsg -- The string to display in main body of dialog
  247. // iLine -- Line number of file in error
  248. // szFile -- Filename of file in error
  249. //
  250. // Returns:
  251. // IDCANCEL -- User selected the CANCEL button
  252. // IDOK -- User selected the OK button
  253. //-------------------------------------------------------------
  254. int PopUpError(LPTSTR szMsg, int iLine, LPSTR szFile)
  255. {
  256. //
  257. // Create caption
  258. //
  259. static TCHAR szAssertCaption[128];
  260. //
  261. // get process
  262. //
  263. static CHAR szModuleName[MAX_PATH + 1];
  264. ZeroMemory(szModuleName,sizeof(szModuleName));
  265. LPSTR pszModuleName;
  266. if (GetModuleFileNameA(NULL, szModuleName, MAX_PATH))
  267. {
  268. pszModuleName = szModuleName;
  269. }
  270. else
  271. {
  272. pszModuleName = "Unknown";
  273. }
  274. LPSTR pProcess = AnsiPathFindFileName(pszModuleName);
  275. if(FAILED(StringCchPrintf(szAssertCaption,
  276. sizeof(szAssertCaption)/sizeof(TCHAR),
  277. _T("%hs: Assertion Failed"),
  278. pProcess)))
  279. {
  280. return IDCANCEL;
  281. }
  282. //
  283. // Create details.
  284. //
  285. TCHAR szDetails[1024];
  286. DWORD tid = GetCurrentThreadId();
  287. DWORD pid = GetCurrentProcessId();
  288. if(FAILED(StringCchPrintf(szDetails,sizeof(szDetails)/sizeof(TCHAR), _T(" Assertion:\t %s\n\n") \
  289. _T(" File: \t\t %hs\n") \
  290. _T(" Line: \t\t %d\n\n") \
  291. _T(" Module: \t %hs\n") \
  292. _T(" Thread ID:\t %d.%d\n"),
  293. szMsg, szFile, iLine, pszModuleName, pid, tid)))
  294. {
  295. return IDCANCEL;
  296. }
  297. int id = MessageBox(NULL,
  298. szDetails,
  299. szAssertCaption,
  300. MB_SETFOREGROUND
  301. | MB_DEFAULT_DESKTOP_ONLY
  302. | MB_TASKMODAL
  303. | MB_ICONEXCLAMATION
  304. | MB_OKCANCEL);
  305. //
  306. // If id == 0, then an error occurred. There are two possibilities
  307. // that can cause the error: Access Denied, which means that this
  308. // process does not have access to the default desktop, and everything
  309. // else (usually out of memory).
  310. //
  311. if (0 == id)
  312. {
  313. if (GetLastError() == ERROR_ACCESS_DENIED)
  314. {
  315. //
  316. // Retry this one with the SERVICE_NOTIFICATION flag on. That
  317. // should get us to the right desktop.
  318. //
  319. id = MessageBox(NULL,
  320. szMsg,
  321. szAssertCaption,
  322. MB_SETFOREGROUND
  323. | MB_TASKMODAL
  324. | MB_ICONEXCLAMATION
  325. | MB_OKCANCEL);
  326. }
  327. }
  328. return id;
  329. }
  330. //+---------------------------------------------------------------------------
  331. //
  332. // Function: _asdprintf
  333. //
  334. // Synopsis: Calls smprintf to output a formatted message.
  335. //
  336. // History: 18-Oct-91 vich Created
  337. //
  338. //----------------------------------------------------------------------------
  339. inline void __cdecl _asdprintf(LPTSTR pszfmt, ...)
  340. {
  341. va_list va;
  342. va_start(va, pszfmt);
  343. smprintf(DEB_FORCE, 0, _T("Assert"), pszfmt, va);
  344. va_end(va);
  345. }
  346. //+---------------------------------------------------------------------------
  347. //
  348. // Function: AdminAssertEx, private
  349. //
  350. // Synopsis: Display assertion information
  351. //
  352. // Effects: Called when an assertion is hit.
  353. //
  354. //----------------------------------------------------------------------------
  355. void AdminAssertEx(LPSTR szFile, int iLine, LPTSTR szMessage)
  356. {
  357. if (g_AdminAssertLevel & ASSRT_MESSAGE)
  358. {
  359. DWORD tid = GetCurrentThreadId();
  360. LPSTR pszFileName = AnsiPathFindFileName(szFile);
  361. _asdprintf(_T("%s <%hs, l %u, thread %d>\n"),
  362. szMessage, pszFileName, iLine, tid);
  363. }
  364. if (g_AdminAssertLevel & ASSRT_POPUP)
  365. {
  366. int id = PopUpError(szMessage,iLine,szFile);
  367. if (id == IDCANCEL)
  368. {
  369. DebugBreak();
  370. }
  371. }
  372. else if (g_AdminAssertLevel & ASSRT_BREAK)
  373. {
  374. DebugBreak();
  375. }
  376. }
  377. //____________________________________________________________________________
  378. //____________________________________________________________________________
  379. //________________ _________________________________________
  380. //________________ class CDbg _________________________________________
  381. //________________ _________________________________________
  382. //____________________________________________________________________________
  383. //____________________________________________________________________________
  384. CDbg::CDbg(LPTSTR str)
  385. :
  386. m_InfoLevelString(str),
  387. m_flInfoLevel(DEF_INFOLEVEL),
  388. m_flOutputOptions(0)
  389. {
  390. ULONG flRegistry = 0;
  391. CheckInit(m_InfoLevelString, &flRegistry);
  392. m_flInfoLevel = flRegistry & DEB_FORCE;
  393. m_flOutputOptions = flRegistry & ~DEB_FORCE;
  394. }
  395. CDbg::~CDbg()
  396. {
  397. DEBUG_VERIFY_INSTANCE_COUNT(CAdminManagerAz)
  398. DEBUG_VERIFY_INSTANCE_COUNT(CAdminManagerNode)
  399. DEBUG_VERIFY_INSTANCE_COUNT(CApplicationAz)
  400. DEBUG_VERIFY_INSTANCE_COUNT(CApplicationNode)
  401. DEBUG_VERIFY_INSTANCE_COUNT(CGroupAz)
  402. DEBUG_VERIFY_INSTANCE_COUNT(CGroupNode)
  403. DEBUG_VERIFY_INSTANCE_COUNT(CMachineInfo)
  404. DEBUG_VERIFY_INSTANCE_COUNT(CNewApplicationDlg)
  405. DEBUG_VERIFY_INSTANCE_COUNT(CNewAuthorizationStoreDlg)
  406. DEBUG_VERIFY_INSTANCE_COUNT(CNewScopeDlg)
  407. DEBUG_VERIFY_INSTANCE_COUNT(COperationAz)
  408. DEBUG_VERIFY_INSTANCE_COUNT(COperationNode)
  409. DEBUG_VERIFY_INSTANCE_COUNT(COpenAuthorizationStoreDlg)
  410. DEBUG_VERIFY_INSTANCE_COUNT(CRoleAz)
  411. DEBUG_VERIFY_INSTANCE_COUNT(CRoleComponentDataObject)
  412. DEBUG_VERIFY_INSTANCE_COUNT(CRoleNode)
  413. DEBUG_VERIFY_INSTANCE_COUNT(CRoleRootData)
  414. DEBUG_VERIFY_INSTANCE_COUNT(CRoleSnapinAbout)
  415. DEBUG_VERIFY_INSTANCE_COUNT(CScopeAz)
  416. DEBUG_VERIFY_INSTANCE_COUNT(CScopeNode)
  417. DEBUG_VERIFY_INSTANCE_COUNT(SID_CACHE_ENTRY)
  418. DEBUG_VERIFY_INSTANCE_COUNT(CSidHandler)
  419. DEBUG_VERIFY_INSTANCE_COUNT(CTaskAz)
  420. DEBUG_VERIFY_INSTANCE_COUNT(CTaskNode)
  421. TlsFree(CDbg::s_idxTls);
  422. CDbg::s_idxTls = 0xFFFFFFFF;
  423. extern CRITICAL_SECTION g_csMessageBuf;
  424. extern CRITICAL_SECTION g_csDebugPrint;
  425. DeleteCriticalSection(&g_csMessageBuf);
  426. DeleteCriticalSection(&g_csDebugPrint);
  427. }
  428. void __cdecl CDbg::Trace(LPSTR pszfmt, ...)
  429. {
  430. #ifdef UNICODE
  431. ULONG convert = static_cast<ULONG>(strlen(pszfmt)) + 1;
  432. LPTSTR ptcfmt = NULL;
  433. __try
  434. {
  435. ptcfmt = (PWSTR)alloca(convert * sizeof(WCHAR));
  436. }
  437. __except(EXCEPTION_EXECUTE_HANDLER)
  438. {
  439. ptcfmt = NULL;
  440. }
  441. if(!ptcfmt)
  442. return;
  443. ptcfmt[0] = '\0';
  444. (void) MultiByteToWideChar(CP_ACP, 0, pszfmt, -1, ptcfmt, convert);
  445. #else
  446. LPTSTR ptcfmt = pszfmt;
  447. #endif
  448. if (m_flInfoLevel & DEB_TRACE)
  449. {
  450. va_list va;
  451. va_start (va, pszfmt);
  452. ULONG cchIndent = _GetIndent();
  453. smprintf(DEB_TRACE, cchIndent, m_InfoLevelString, ptcfmt, va);
  454. va_end(va);
  455. }
  456. }
  457. void __cdecl CDbg::Trace(PWSTR pwzfmt, ...)
  458. {
  459. #ifndef UNICODE
  460. int convert = wcslen(pwzfmt) + 1;
  461. LPTSTR ptcfmt = NULL;
  462. __try
  463. {
  464. ptcfmt = (PWSTR)alloca(convert * sizeof(CHAR));
  465. }
  466. __except(EXCEPTION_EXECUTE_HANDLER)
  467. {
  468. ptcfmt = NULL;
  469. }
  470. if(!ptcfmt)
  471. return;
  472. ptcfmt[0] = '\0';
  473. (void) WideCharToMultiByte(CP_ACP, 0, pwzfmt, -1, ptcfmt, convert, NULL, NULL);
  474. #else
  475. LPTSTR ptcfmt = pwzfmt;
  476. #endif
  477. if (m_flInfoLevel & DEB_TRACE)
  478. {
  479. va_list va;
  480. va_start (va, pwzfmt);
  481. ULONG cchIndent = _GetIndent();
  482. smprintf(DEB_TRACE, cchIndent, m_InfoLevelString, ptcfmt, va);
  483. va_end(va);
  484. }
  485. }
  486. void __cdecl CDbg::DebugOut(ULONG fDebugMask, LPSTR pszfmt, ...)
  487. {
  488. #ifdef UNICODE
  489. ULONG convert = static_cast<ULONG>(strlen(pszfmt)) + 1;
  490. LPTSTR ptcfmt = NULL;
  491. __try
  492. {
  493. ptcfmt = (PWSTR)alloca(convert * sizeof(WCHAR));
  494. }
  495. __except(EXCEPTION_EXECUTE_HANDLER)
  496. {
  497. ptcfmt = NULL;
  498. }
  499. if(!ptcfmt)
  500. return;
  501. ptcfmt[0] = '\0';
  502. (void) MultiByteToWideChar(CP_ACP, 0, pszfmt, -1, ptcfmt, convert);
  503. #else
  504. LPTSTR ptcfmt = pszfmt;
  505. #endif
  506. va_list va;
  507. va_start (va, pszfmt);
  508. ULONG cchIndent = _GetIndent();
  509. smprintf(m_flOutputOptions | (m_flInfoLevel & fDebugMask)
  510. | (fDebugMask & DEB_NOCOMPNAME),
  511. cchIndent,
  512. m_InfoLevelString,
  513. ptcfmt,
  514. va);
  515. va_end(va);
  516. }
  517. void __cdecl CDbg::DebugOut(ULONG fDebugMask, PWSTR pwzfmt, ...)
  518. {
  519. #ifndef UNICODE
  520. int convert = wcslen(pwzfmt) + 1;
  521. LPTSTR ptcfmt = NULL;
  522. __try
  523. {
  524. ptcfmt = (PWSTR)alloca(convert * sizeof(CHAR));
  525. }
  526. __except(EXCEPTION_EXECUTE_HANDLER)
  527. {
  528. ptcfmt = NULL;
  529. }
  530. if(!ptcfmt)
  531. return;
  532. ptcfmt[0] = '\0';
  533. (void) WideCharToMultiByte(CP_ACP, 0, pwzfmt, -1, ptcfmt, convert, NULL, NULL);
  534. #else
  535. LPTSTR ptcfmt = pwzfmt;
  536. #endif
  537. va_list va;
  538. va_start (va, pwzfmt);
  539. ULONG cchIndent = _GetIndent();
  540. smprintf(m_flOutputOptions | (m_flInfoLevel & fDebugMask)
  541. | (fDebugMask & DEB_NOCOMPNAME),
  542. cchIndent,
  543. m_InfoLevelString,
  544. ptcfmt,
  545. va);
  546. va_end(va);
  547. }
  548. void CDbg::DebugErrorX(LPSTR file, ULONG line, LONG err)
  549. {
  550. if (m_flInfoLevel & DEB_ERROR)
  551. {
  552. file = AnsiPathFindFileName(file);
  553. this->DebugOut(DEB_ERROR, "error<0x%08x> %hs, l %u\n",
  554. err, file, line);
  555. }
  556. }
  557. void CDbg::DebugErrorL(LPSTR file, ULONG line, LONG err)
  558. {
  559. if (m_flInfoLevel & DEB_ERROR)
  560. {
  561. file = AnsiPathFindFileName(file);
  562. this->DebugOut(DEB_ERROR, "error<%uL> %hs, l %u\n", err, file, line);
  563. }
  564. }
  565. void CDbg::DebugMsg(LPSTR file, ULONG line, LPSTR msg)
  566. {
  567. file = AnsiPathFindFileName(file);
  568. this->DebugOut(DEB_FORCE, "asrt %hs, l %u, <%s>\n", file, line, msg);
  569. }
  570. void CDbg::DebugMsg(LPSTR file, ULONG line, PWSTR msg)
  571. {
  572. file = AnsiPathFindFileName(file);
  573. this->DebugOut(DEB_FORCE, _T("asrt %hs, l %u, <%s>\n"), file, line, msg);
  574. }
  575. void CDbg::AssertEx(LPSTR pszFile, int iLine, LPTSTR pszMsg)
  576. {
  577. #if 0
  578. LPTSTR ptcMsg = NULL;
  579. #ifdef UNICODE
  580. int convert = strlen(pszMsg) + 1;
  581. ptcMsg = (PWSTR)alloca(convert * sizeof(WCHAR));
  582. ptcMsg[0] = '\0';
  583. (void) MultiByteToWideChar(CP_ACP, 0, pszMsg, -1, ptcMsg, convert);
  584. #else
  585. ptcMsg = pszMsg;
  586. #endif
  587. AdminAssertEx(pszFile, iLine, ptcMsg);
  588. #endif //0
  589. AdminAssertEx(pszFile, iLine, pszMsg);
  590. }
  591. ULONG
  592. CDbg::_GetIndent()
  593. {
  594. ULONG cchIndent = 0;
  595. if (s_idxTls != 0xFFFFFFFF)
  596. {
  597. cchIndent = static_cast<ULONG>
  598. (reinterpret_cast<ULONG_PTR>
  599. (TlsGetValue(s_idxTls)));
  600. }
  601. return cchIndent;
  602. }
  603. void CDbg::IncIndent()
  604. {
  605. if (s_idxTls != 0xFFFFFFFF)
  606. {
  607. ULONG_PTR cchIndent = reinterpret_cast<ULONG_PTR>(TlsGetValue(s_idxTls));
  608. cchIndent++;
  609. TlsSetValue(s_idxTls, reinterpret_cast<PVOID>(cchIndent));
  610. }
  611. }
  612. void CDbg::DecIndent()
  613. {
  614. if (s_idxTls != 0xFFFFFFFF)
  615. {
  616. ULONG_PTR cchIndent = reinterpret_cast<ULONG_PTR>(TlsGetValue(s_idxTls));
  617. cchIndent--;
  618. TlsSetValue(s_idxTls, reinterpret_cast<PVOID>(cchIndent));
  619. }
  620. }
  621. #endif // DBG==1