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.

835 lines
22 KiB

  1. //+---------------------------------------------------------------------------
  2. // Copyright (C) 1991, Microsoft Corporation.
  3. //
  4. // File: assert.cxx
  5. //
  6. // Contents: Debugging output routines for idsmgr.dll
  7. //
  8. // Functions: Assert
  9. // PopUpError
  10. //
  11. // History: 23-Jul-91 KyleP Created.
  12. // 09-Oct-91 KevinRo Major changes and comments added
  13. // 18-Oct-91 vich moved debug print routines out
  14. // 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
  15. // 30-Sep-93 KyleP DEVL obsolete
  16. //
  17. //----------------------------------------------------------------------------
  18. #pragma hdrstop
  19. //
  20. // This one file **always** uses debugging options
  21. //
  22. #if DBG == 1
  23. #include <stdarg.h>
  24. #include <stdio.h>
  25. #include <dprintf.h> // w4printf, w4dprintf prototypes
  26. #include <debnot.h>
  27. #include <olesem.hxx>
  28. #include <windows.h>
  29. #include <netevent.h>
  30. #include <stackwlk.hxx>
  31. #include <asrtcfg.h>
  32. #include <memapi.hxx>
  33. unsigned long Win4InfoLevel = DEF_INFOLEVEL;
  34. unsigned long Win4InfoMask = 0xffffffff;
  35. BOOL gAssertOnCreate = TRUE;
  36. int ForceAV();
  37. //+---------------------------------------------------------------------------
  38. //
  39. // Function: _asdprintf
  40. //
  41. // Synopsis: Calls vdprintf to output a formatted message.
  42. //
  43. // History: 18-Oct-91 vich Created
  44. //
  45. //----------------------------------------------------------------------------
  46. inline void __cdecl
  47. _asdprintf(
  48. char const *pszfmt, ...)
  49. {
  50. va_list va;
  51. va_start(va, pszfmt);
  52. vdprintf(DEB_FORCE, "Assert", pszfmt, va);
  53. va_end(va);
  54. }
  55. typedef enum
  56. {
  57. ASSRTCFG_BREAK = 0x01,
  58. ASSRTCFG_POPUP = 0x02,
  59. ASSRTCFG_DEBUGMESSAGE = 0x04,
  60. ASSRTCFG_PRINTSTACK = 0x08,
  61. ASSRTCFG_USEAV = 0x10
  62. } ASSRTCFG;
  63. //+---------------------------------------------------------------------
  64. //
  65. // Class: CAssertInfo
  66. //
  67. // Synopsis: Data type to trake assertion and logging parameters
  68. //
  69. // History: 27-Jan-99 MattSmit Created
  70. //
  71. //----------------------------------------------------------------------
  72. class CAssertInfo : public IAssertConfig
  73. {
  74. public:
  75. CAssertInfo() : _dwFlags(ASSRTCFG_POPUP | ASSRTCFG_DEBUGMESSAGE) {}
  76. //
  77. // IUnknown
  78. //
  79. STDMETHOD(QueryInterface)(REFIID riid, PVOID * ppv)
  80. {
  81. if ((IsEqualIID(riid, IID_IUnknown)) ||
  82. (IsEqualIID(riid, IID_IAssertConfig)))
  83. {
  84. *ppv = this;
  85. AddRef();
  86. return S_OK;
  87. }
  88. else
  89. {
  90. return E_NOINTERFACE;
  91. }
  92. }
  93. STDMETHOD_(ULONG, AddRef)() { return 1;}
  94. STDMETHOD_(ULONG, Release)() { return 1;}
  95. //
  96. // IConfigAssert
  97. //
  98. STDMETHOD(SetBreak)(BOOL f) { SetFlag(f, ASSRTCFG_BREAK); return S_OK;}
  99. STDMETHOD(SetPopup)(BOOL f) { SetFlag(f, ASSRTCFG_POPUP); return S_OK;}
  100. STDMETHOD(SetDebuggerMessage)(BOOL f) { SetFlag(f, ASSRTCFG_DEBUGMESSAGE); return S_OK;}
  101. STDMETHOD(SetPrintStack)(BOOL f) { SetFlag(f, ASSRTCFG_PRINTSTACK); return S_OK;}
  102. STDMETHOD(SetUseAV)(BOOL f) { SetFlag(f, ASSRTCFG_USEAV); return S_OK;}
  103. STDMETHOD(SetLog)(ASSRTLOGINFO *pLogInfo) { _logInfo = *pLogInfo; return S_OK;}
  104. STDMETHOD(SetContextString)(char *psz){ _pszContext = psz; return S_OK;}
  105. STDMETHOD(SetThreshold)(ULONG cTh) { _cThreshold = cTh; return S_OK;}
  106. //
  107. // helpers
  108. //
  109. void Win4AssertEx(char const * szFile, int iLine, char const * szMessage);
  110. int PopUpError(char const *szMsg, int iLine, char const *szFile);
  111. void ComposeErrorMessage(char const *szMsg, int iLine, char const *szFile);
  112. void AppendToFile(char *pszFileName, char const *pwszData);
  113. void FatalErrorHandler(char *errmsg);
  114. void LogAssertionFailure(char const * szMessage);
  115. private:
  116. void SetFlag(BOOL f, DWORD bit)
  117. {
  118. _dwFlags = f ? _dwFlags | bit : _dwFlags & ~bit;
  119. }
  120. char *GetStack();
  121. BOOL GetBreak() {return _dwFlags | ASSRTCFG_BREAK;}
  122. BOOL GetPopup() {return _dwFlags | ASSRTCFG_POPUP;}
  123. BOOL GetDebugMessage() {return _dwFlags | ASSRTCFG_DEBUGMESSAGE;}
  124. void BreakIntoDebugger()
  125. {
  126. if (_dwFlags & ASSRTCFG_USEAV)
  127. ForceAV();
  128. else
  129. DebugBreak();
  130. }
  131. DWORD _dwFlags; // what to do when an assertion fails
  132. ASSRTLOGINFO _logInfo; // if/where to write a log entry
  133. char *_pszContext; // user supplied context string for the log
  134. char _errMessage[128]; // generated error string
  135. ULONG _cThreshold; // number of assertion to ignore
  136. ULONG _cAssrtFail; // number of assertion failures so far
  137. };
  138. CAssertInfo gAssertInfo;
  139. //+---------------------------------------------------------------------------
  140. //
  141. // Method: Win4AssertEx
  142. //
  143. // Synopsis: Called on assertion failure. Takes appropriate action based
  144. // on member variables
  145. //
  146. // History: 27-Jan-99 MattSmit Created
  147. //
  148. //----------------------------------------------------------------------------
  149. void CAssertInfo::Win4AssertEx(
  150. char const * szFile,
  151. int iLine,
  152. char const * szMessage)
  153. {
  154. _cAssrtFail++;
  155. if (_cAssrtFail < _cThreshold)
  156. {
  157. return;
  158. }
  159. ComposeErrorMessage(szMessage, iLine, szFile);
  160. BOOL fBrokeAlready = FALSE;
  161. if (_dwFlags & ASSRTCFG_DEBUGMESSAGE)
  162. {
  163. DWORD tid = GetCurrentThreadId();
  164. _asdprintf("%s\n%s\n", _errMessage, szMessage);
  165. }
  166. if (_logInfo.dwDest & ASSRTLOG_FILE)
  167. {
  168. AppendToFile(_logInfo.pszFileName, szMessage);
  169. }
  170. if (_logInfo.dwDest & ASSRTLOG_NTEVENTLOG)
  171. {
  172. LogAssertionFailure(szMessage);
  173. }
  174. if (_dwFlags & ASSRTCFG_POPUP)
  175. {
  176. int id = PopUpError(szMessage, iLine, szFile);
  177. if (id == IDCANCEL)
  178. {
  179. fBrokeAlready = TRUE;
  180. BreakIntoDebugger();
  181. }
  182. }
  183. if ((_dwFlags & ASSRTCFG_BREAK) && !fBrokeAlready)
  184. {
  185. BreakIntoDebugger();
  186. }
  187. }
  188. //+------------------------------------------------------------
  189. // Method: PopUpError
  190. //
  191. // Synopsis: Displays a dialog box using provided text,
  192. // and presents the user with the option to
  193. // continue or cancel.
  194. //
  195. // Arguments:
  196. // szMsg -- The string to display in main body of dialog
  197. // iLine -- Line number of file in error
  198. // szFile -- Filename of file in error
  199. //
  200. // Returns:
  201. // IDCANCEL -- User selected the CANCEL button
  202. // IDOK -- User selected the OK button
  203. //-------------------------------------------------------------
  204. int CAssertInfo::PopUpError(char const *szMsg, int iLine, char const *szFile)
  205. {
  206. int id;
  207. WCHAR wszWinsta[64];
  208. HWINSTA hWinsta;
  209. DWORD Size;
  210. DWORD dwMessageFlags = MB_SETFOREGROUND | MB_TASKMODAL |
  211. MB_ICONEXCLAMATION | MB_OKCANCEL;
  212. #ifndef _CHICAGO_
  213. hWinsta = GetProcessWindowStation();
  214. Size = sizeof(wszWinsta);
  215. wszWinsta[0] = 0;
  216. if ( hWinsta )
  217. {
  218. (void) GetUserObjectInformation(
  219. hWinsta,
  220. UOI_NAME,
  221. wszWinsta,
  222. Size,
  223. &Size );
  224. }
  225. //
  226. // This makes popups from non-interactive servers/services (including
  227. // rpcss) visible.
  228. //
  229. if ( wszWinsta[0] && (lstrcmpiW(wszWinsta,L"Winsta0") != 0) )
  230. dwMessageFlags |= MB_SERVICE_NOTIFICATION | MB_DEFAULT_DESKTOP_ONLY;
  231. id = MessageBoxA(NULL,(char *) szMsg, (LPSTR) _errMessage,
  232. dwMessageFlags);
  233. #else
  234. id = MessageBox(NULL, (char *) szMsg, (LPSTR) _errMessage,
  235. dwMessageFlags);
  236. #endif
  237. // If id == 0, then an error occurred. There are two possibilities
  238. // that can cause the error: Access Denied, which means that this
  239. // process does not have access to the default desktop, and everything
  240. // else (usually out of memory). Oh well.
  241. return id;
  242. }
  243. //+---------------------------------------------------------------------------
  244. //
  245. // Method: ComposeErrorMessage
  246. //
  247. // Synopsis: Put together a message that contains useful info about the
  248. // context of the error
  249. //
  250. // History: 27-Jan-99 MattSmit Created
  251. //
  252. //----------------------------------------------------------------------------
  253. void CAssertInfo::ComposeErrorMessage(
  254. char const *szMsg,
  255. int iLine,
  256. char const *szFile)
  257. {
  258. static char szModuleName[128];
  259. DWORD tid = GetCurrentThreadId();
  260. DWORD pid = GetCurrentProcessId();
  261. char * pszModuleName;
  262. BOOL bStatus;
  263. if (GetModuleFileNameA(NULL, szModuleName, 128))
  264. {
  265. pszModuleName = strrchr(szModuleName, '\\');
  266. if (!pszModuleName)
  267. {
  268. pszModuleName = szModuleName;
  269. }
  270. else
  271. {
  272. pszModuleName++;
  273. }
  274. }
  275. else
  276. {
  277. pszModuleName = "Unknown";
  278. }
  279. wsprintfA(_errMessage,"Process: %s File: %s line %u, thread id %d.%d",
  280. pszModuleName, szFile, iLine, pid, tid);
  281. }
  282. //+---------------------------------------------------------------------------
  283. //
  284. // Method: AppendToFile
  285. //
  286. // Synopsis: Write assertion failures to a log file.
  287. //
  288. // History: 27-Jan-99 MattSmit Created
  289. //
  290. //----------------------------------------------------------------------------
  291. void CAssertInfo::AppendToFile(char *pszFileName, char const *pwszData)
  292. {
  293. HANDLE hFile = CreateFileA(pszFileName,
  294. GENERIC_WRITE,
  295. 0,
  296. NULL,
  297. OPEN_ALWAYS,
  298. FILE_ATTRIBUTE_NORMAL,
  299. NULL);
  300. if (hFile == INVALID_HANDLE_VALUE)
  301. {
  302. FatalErrorHandler("Could not open log File.");
  303. }
  304. DWORD ret = SetFilePointer(hFile, 0, 0, FILE_END);
  305. if (ret == -1)
  306. {
  307. FatalErrorHandler("Could not set file pointer.");
  308. }
  309. DWORD dwBytesWritten;
  310. BOOL ok = WriteFile(hFile, _errMessage,
  311. lstrlenA(_errMessage),
  312. &dwBytesWritten, NULL);
  313. if (!ok)
  314. {
  315. FatalErrorHandler("Could not write to log File.");
  316. }
  317. ok = WriteFile(hFile, "\n", 1,
  318. &dwBytesWritten, NULL);
  319. if (!ok)
  320. {
  321. FatalErrorHandler("Could not write to log File.");
  322. }
  323. ok = WriteFile(hFile, pwszData,
  324. lstrlenA(pwszData),
  325. &dwBytesWritten, NULL);
  326. if (!ok)
  327. {
  328. FatalErrorHandler("Could not write to log File.");
  329. }
  330. ok = WriteFile(hFile, "\n", 1,
  331. &dwBytesWritten, NULL);
  332. if (!ok)
  333. {
  334. FatalErrorHandler("Could not write to log File.");
  335. }
  336. if (_dwFlags & ASSRTCFG_PRINTSTACK)
  337. {
  338. char *psz = GetStack();
  339. if (psz)
  340. {
  341. ok = WriteFile(hFile, psz,
  342. lstrlenA(psz),
  343. &dwBytesWritten, NULL);
  344. if (!ok)
  345. {
  346. FatalErrorHandler("Could not write to log File.");
  347. }
  348. PrivMemFree(psz);
  349. }
  350. }
  351. if (_pszContext)
  352. {
  353. ok = WriteFile(hFile, pwszData,
  354. lstrlenA(pwszData),
  355. &dwBytesWritten, NULL);
  356. if (!ok)
  357. {
  358. FatalErrorHandler("Could not write to log File.");
  359. }
  360. ok = WriteFile(hFile, "\n", 1,
  361. &dwBytesWritten, NULL);
  362. if (!ok)
  363. {
  364. FatalErrorHandler("Could not write to log File.");
  365. }
  366. }
  367. CloseHandle(hFile);
  368. }
  369. //+---------------------------------------------------------------------------
  370. //
  371. // Function: GetStackExceptionFilter
  372. //
  373. // Synopsis: Walk stack and store in a string variable
  374. //
  375. // History: 27-Jan-99 MattSmit Created
  376. //
  377. //----------------------------------------------------------------------------
  378. LONG GetStackExceptionFilter(LPEXCEPTION_POINTERS lpep, char **ppStack)
  379. {
  380. *ppStack = NULL;
  381. DWORD dwFault = lpep->ExceptionRecord->ExceptionCode;
  382. if (dwFault != 0xceadbeef)
  383. {
  384. return EXCEPTION_CONTINUE_SEARCH;
  385. }
  386. StackWalker resolver(GetCurrentProcess());
  387. Symbol* symbol = resolver.CreateStackTrace(lpep->ContextRecord);
  388. SIZE_T nLen = resolver.GetCallStackSize(symbol);
  389. WCHAR * szStack = new WCHAR[nLen];
  390. if (szStack)
  391. {
  392. resolver.GetCallStack(symbol, nLen, szStack, 20); // No more than 20 lines
  393. *ppStack = (char *) PrivMemAlloc(nLen);
  394. wcstombs(*ppStack, szStack, lstrlenW(szStack));
  395. delete [] szStack;
  396. }
  397. return EXCEPTION_EXECUTE_HANDLER;
  398. }
  399. //+---------------------------------------------------------------------------
  400. //
  401. // Method: GetStack
  402. //
  403. // Synopsis: Throws and exception so the filter can get stack info
  404. //
  405. // History: 27-Jan-99 MattSmit Created
  406. //
  407. //----------------------------------------------------------------------------
  408. char *CAssertInfo::GetStack()
  409. {
  410. char *pStack = NULL;
  411. __try
  412. {
  413. RaiseException(0xceadbeef, 0, 0, NULL);
  414. }
  415. __except(GetStackExceptionFilter(GetExceptionInformation(), &pStack))
  416. {
  417. }
  418. return pStack;
  419. }
  420. //+---------------------------------------------------------------------------
  421. //
  422. // Method: FatalErrorHandler
  423. //
  424. // Synopsis: Called when the assertion code itself cannot allocate
  425. // enough resources to log the assertion failure.
  426. //
  427. // History: 27-Jan-99 MattSmit Created
  428. //
  429. //----------------------------------------------------------------------------
  430. void CAssertInfo::FatalErrorHandler(char *szMessage)
  431. {
  432. BOOL fBrokeAlready = FALSE;
  433. lstrcpyA(_errMessage, "Fatal error while processing assertion failure");
  434. _asdprintf("%s\n%s\n", _errMessage, szMessage);
  435. if (_dwFlags & ASSRTCFG_POPUP)
  436. {
  437. int id = PopUpError(szMessage, __LINE__, __FILE__);
  438. if (id == IDCANCEL)
  439. {
  440. fBrokeAlready = TRUE;
  441. BreakIntoDebugger();
  442. }
  443. }
  444. if (_dwFlags & ASSRTCFG_BREAK && !fBrokeAlready)
  445. {
  446. BreakIntoDebugger();
  447. }
  448. }
  449. //+---------------------------------------------------------------------------
  450. //
  451. // Method: LogAssertionFailure
  452. //
  453. // Synopsis: Write and assertion failure to the NT event log
  454. //
  455. // History: 27-Jan-99 MattSmit Created
  456. //
  457. //----------------------------------------------------------------------------
  458. void CAssertInfo::LogAssertionFailure(char const * szMessage)
  459. {
  460. HANDLE LogHandle;
  461. char const * Strings[3]; // array of message strings.
  462. Strings[0] = _errMessage;
  463. Strings[1] = szMessage;
  464. Strings[2] = _pszContext ? _pszContext : "";
  465. // Get the log handle, then report the event.
  466. LogHandle = RegisterEventSource( NULL, L"DCOM" );
  467. if ( LogHandle )
  468. {
  469. ReportEventA( LogHandle,
  470. EVENTLOG_ERROR_TYPE,
  471. 0, // event category
  472. EVENT_DCOM_ASSERTION_FAILURE,
  473. NULL,
  474. 3, // 3 strings passed
  475. 0, // 0 bytes of binary
  476. Strings, // array of strings
  477. NULL ); // no raw data
  478. // clean up the event log handle
  479. DeregisterEventSource(LogHandle);
  480. }
  481. else
  482. {
  483. FatalErrorHandler("Could not register as event source");
  484. }
  485. }
  486. //+------------------------------------------------------------
  487. // Function: vdprintf
  488. //
  489. // Synopsis: Prints debug output using a pointer to the
  490. // variable information. Used primarily by the
  491. // xxDebugOut macros
  492. //
  493. // Arguements:
  494. // ulCompMask -- Component level mask used to determine
  495. // output ability
  496. // pszComp -- String const of component prefix.
  497. // ppszfmt -- Pointer to output format and data
  498. //
  499. //-------------------------------------------------------------
  500. //
  501. // This semaphore is *outside* vdprintf because the compiler isn't smart
  502. // enough to serialize access for construction if it's function-local and
  503. // protected by a guard variable.
  504. //
  505. // KyleP - 20 May, 1993
  506. //
  507. static COleDebugMutexSem mxs;
  508. STDAPI_(void) vdprintf(
  509. unsigned long ulCompMask,
  510. char const *pszComp,
  511. char const *ppszfmt,
  512. va_list pargs)
  513. {
  514. if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
  515. ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
  516. {
  517. if ((Win4InfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
  518. {
  519. if (! (ulCompMask & DEB_NOCOMPNAME))
  520. {
  521. DWORD tid = GetCurrentThreadId();
  522. DWORD pid = GetCurrentProcessId();
  523. mxs.Request();
  524. #if defined(_CHICAGO_)
  525. //
  526. // Hex Process/Thread ID's are better for Chicago since both
  527. // are memory addresses.
  528. //
  529. w4dprintf( "%08x.%08x> ", pid, tid );
  530. #else
  531. w4dprintf( "%d.%03dp> ", pid, tid );
  532. #endif
  533. w4dprintf("%s: ", pszComp);
  534. w4vdprintf(ppszfmt, pargs);
  535. mxs.Release();
  536. }
  537. }
  538. }
  539. }
  540. //+---------------------------------------------------------------------------
  541. //
  542. // Function: ForceAV
  543. //
  544. // Synopsis: Cause and Access Violation
  545. //
  546. // History: 27-Jan-99 MattSmit Created
  547. //
  548. //----------------------------------------------------------------------------
  549. int ForceAV()
  550. {
  551. return *((int *) 0);
  552. }
  553. //+---------------------------------------------------------------------------
  554. //
  555. // Function: _Win4Assert, private
  556. //
  557. // Synopsis: Display assertion information
  558. //
  559. // Effects: Called when an assertion is hit.
  560. //
  561. // History: 12-Jul-91 AlexT Created.
  562. // 05-Sep-91 AlexT Catch Throws and Catches
  563. // 19-Oct-92 HoiV Added events for TOM
  564. //
  565. //----------------------------------------------------------------------------
  566. STDAPI_(void) Win4AssertEx(
  567. char const * szFile,
  568. int iLine,
  569. char const * szMessage)
  570. {
  571. gAssertInfo.Win4AssertEx(szFile, iLine, szMessage);
  572. }
  573. //+------------------------------------------------------------
  574. // Function: SetWin4InfoLevel(unsigned long ulNewLevel)
  575. //
  576. // Synopsis: Sets the global info level for debugging output
  577. // Returns: Old info level
  578. //
  579. //-------------------------------------------------------------
  580. EXPORTIMP unsigned long APINOT
  581. SetWin4InfoLevel(
  582. unsigned long ulNewLevel)
  583. {
  584. unsigned long ul;
  585. ul = Win4InfoLevel;
  586. Win4InfoLevel = ulNewLevel;
  587. return(ul);
  588. }
  589. //+------------------------------------------------------------
  590. // Function: _SetWin4InfoMask(unsigned long ulNewMask)
  591. //
  592. // Synopsis: Sets the global info mask for debugging output
  593. // Returns: Old info mask
  594. //
  595. //-------------------------------------------------------------
  596. EXPORTIMP unsigned long APINOT
  597. SetWin4InfoMask(
  598. unsigned long ulNewMask)
  599. {
  600. unsigned long ul;
  601. ul = Win4InfoMask;
  602. Win4InfoMask = ulNewMask;
  603. return(ul);
  604. }
  605. //+---------------------------------------------------------------------------
  606. //
  607. // Function: ReadINIFile
  608. //
  609. // Synopsis: Get a paremeter value from the win.ini file
  610. //
  611. // History: 27-Jan-99 MattSmit Created
  612. //
  613. //----------------------------------------------------------------------------
  614. BOOL ReadINIFile(char * pszKey, BOOL * pVal)
  615. {
  616. static char szValue[128];
  617. if (GetProfileStringA("CairOLE Assertions", // section
  618. pszKey, // key
  619. "", // default value
  620. szValue, // return buffer
  621. 128))
  622. {
  623. *pVal = (lstrcmpiA(szValue, "yes") == 0) ;
  624. return TRUE;
  625. }
  626. return FALSE;
  627. }
  628. //+---------------------------------------------------------------------------
  629. //
  630. // Function: AssertDebugInit
  631. //
  632. // Synopsis: Initialize the assertion data structure using the win.ini file
  633. //
  634. // History: 27-Jan-99 MattSmit Created
  635. //
  636. //----------------------------------------------------------------------------
  637. void AssertDebugInit()
  638. {
  639. #define ASSERT_SET(key) \
  640. { \
  641. BOOL val; \
  642. if (ReadINIFile(#key, &val)) \
  643. { \
  644. gAssertInfo.Set##key(val); \
  645. } \
  646. } \
  647. static char szValue[128];
  648. ASSERT_SET(Break);
  649. ASSERT_SET(Popup);
  650. ASSERT_SET(DebuggerMessage);
  651. ASSERT_SET(PrintStack);
  652. ASSERT_SET(UseAV);
  653. ASSRTLOGINFO logInfo;
  654. memset(&logInfo, 0, sizeof(logInfo));
  655. if (GetProfileStringA("CairOLE Assertions", // section
  656. "Log_File", // key
  657. "", // default value
  658. logInfo.pszFileName, // return buffer
  659. MAX_PATH))
  660. {
  661. if (lstrcmpA("", logInfo.pszFileName) != 0)
  662. {
  663. logInfo.dwDest |= ASSRTLOG_FILE;
  664. }
  665. }
  666. if (GetProfileStringA("CairOLE Assertions", // section
  667. "Log_NtEventLog", // key
  668. "", // default value
  669. szValue, // return buffer
  670. 128))
  671. {
  672. logInfo.dwDest |= (lstrcmpiA(szValue, "yes") == 0 )? ASSRTLOG_NTEVENTLOG : 0;
  673. }
  674. if (logInfo.dwDest)
  675. {
  676. gAssertInfo.SetLog(&logInfo);
  677. }
  678. if (GetProfileStringA("CairOLE Assertions", // section
  679. "AssertOnCreate", // key
  680. "", // default value
  681. szValue, // return buffer
  682. 128))
  683. {
  684. gAssertOnCreate = FALSE;
  685. }
  686. }
  687. //+---------------------------------------------------------------------------
  688. //
  689. // Function: CoGetAssertConfig
  690. //
  691. // Synopsis: CI for CAssertInfo. gAssertInfo is a singleton,
  692. // so just to a QI
  693. //
  694. // History: 27-Jan-99 MattSmit Created
  695. //
  696. //----------------------------------------------------------------------------
  697. HRESULT CoGetAssertConfig(REFIID riid, PVOID *ppv)
  698. {
  699. return gAssertInfo.QueryInterface(riid, ppv);
  700. }
  701. #else
  702. int assertDontUseThisName(void)
  703. {
  704. return 1;
  705. }
  706. #endif // DBG == 1