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.

1531 lines
39 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1997
  4. *
  5. * TITLE: WiaLog.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: CoopP
  10. *
  11. * DATE: 20 Aug, 1999
  12. *
  13. * DESCRIPTION:
  14. * Class implementation for WIA Logging.
  15. *
  16. *******************************************************************************/
  17. #include "cplusinc.h"
  18. #include "sticomm.h"
  19. static const TCHAR szServiceName[] = TEXT("WIASERVC");
  20. static const TCHAR szDefaultName[] = TEXT("WIASERVC.LOG");
  21. static const TCHAR szDefaultKeyName[] = TEXT("WIASERVC");
  22. static const TCHAR szDefaultDLLName[] = TEXT("noname.dll");
  23. static const TCHAR szOpenedLog[] = TEXT("[%s] Opened log at %s %s");
  24. static const TCHAR szClosedLog[] = TEXT("[%s] Closed log on %s %s");
  25. static const WCHAR szFormatSignature[]= L"F9762DD2679F";
  26. //#define DEBUG_WIALOG
  27. /**************************************************************************\
  28. * CWiaLog::CreateInstance
  29. *
  30. * Create the CWiaLog object.
  31. *
  32. * Arguments:
  33. *
  34. * iid - iid of Logging interface
  35. * ppv - return interface pointer
  36. *
  37. * Return Value:
  38. *
  39. * status
  40. *
  41. * History:
  42. *
  43. * 8/20/1999 Original Version
  44. *
  45. \**************************************************************************/
  46. HRESULT CWiaLog::CreateInstance(const IID& iid, void** ppv)
  47. {
  48. HRESULT hr;
  49. //
  50. // Create the WIA Logging component.
  51. //
  52. CWiaLog* pWiaLog = new CWiaLog();
  53. if (!pWiaLog) {
  54. return E_OUTOFMEMORY;
  55. }
  56. //
  57. // Initialize the WIA logging component.
  58. //
  59. hr = pWiaLog->Initialize();
  60. if (FAILED(hr)) {
  61. delete pWiaLog;
  62. return hr;
  63. }
  64. //
  65. // Get the requested interface from the logging component.
  66. //
  67. hr = pWiaLog->QueryInterface(iid, ppv);
  68. if (FAILED(hr)) {
  69. #ifdef DEBUG_WIALOG
  70. OutputDebugString(TEXT("CWiaLog::CreateInstance, Unkown interface\n"));
  71. #endif
  72. delete pWiaLog;
  73. return hr;
  74. }
  75. #ifdef DEBUG_WIALOG
  76. OutputDebugString(TEXT("CWiaLog::CreateInstance, Created WiaLog\n"));
  77. #endif
  78. return hr;
  79. }
  80. /**************************************************************************\
  81. * QueryInterface
  82. * AddRef
  83. * Release
  84. *
  85. * CWiaLog IUnknown Interface
  86. *
  87. * Arguments:
  88. *
  89. *
  90. *
  91. * Return Value:
  92. *
  93. *
  94. *
  95. * History:
  96. *
  97. * 8/20/1999 Original Version
  98. *
  99. \**************************************************************************/
  100. HRESULT __stdcall CWiaLog::QueryInterface(const IID& iid, void** ppv)
  101. {
  102. if (ppv == NULL)
  103. {
  104. return E_POINTER;
  105. }
  106. *ppv = NULL;
  107. if ((iid == IID_IUnknown) || (iid == IID_IWiaLog)) {
  108. *ppv = (IWiaLog*) this;
  109. } else if (iid == IID_IWiaLogEx) {
  110. *ppv = (IWiaLogEx*) this;
  111. } else {
  112. return E_NOINTERFACE;
  113. }
  114. AddRef();
  115. return S_OK;
  116. }
  117. ULONG __stdcall CWiaLog::AddRef()
  118. {
  119. InterlockedIncrement((long*) &m_cRef);
  120. //DPRINTF(DM_TRACE,TEXT("CWiaLog::AddRef() m_cRef = %d"),m_cRef);
  121. return m_cRef;
  122. }
  123. ULONG __stdcall CWiaLog::Release()
  124. {
  125. ULONG ulRefCount = m_cRef - 1;
  126. if (InterlockedDecrement((long*) &m_cRef) == 0) {
  127. //DPRINTF(DM_TRACE,TEXT("CWiaLog::Release() m_cRef = %d"),m_cRef);
  128. delete this;
  129. return 0;
  130. }
  131. //DPRINTF(DM_TRACE,TEXT("CWiaLog::Release() m_cRef = %d"),m_cRef);
  132. return ulRefCount;
  133. }
  134. /*******************************************************************************
  135. *
  136. * CWiaLog
  137. * ~CWiaLog
  138. *
  139. * CWiaLog Constructor/Initialize/Destructor Methods.
  140. *
  141. * History:
  142. *
  143. * 8/20/1999 Original Version
  144. *
  145. \**************************************************************************/
  146. CWiaLog::CWiaLog():m_cRef(0)
  147. {
  148. m_cRef = 0; // Initialize Reference count to zero
  149. m_pITypeInfo = NULL; // Initialize InfoType to NULL
  150. m_dwReportMode = 0; // Initialize Report Type to zero
  151. m_dwMaxSize = WIA_MAX_LOG_SIZE; // Initialize File Max size to default
  152. m_hLogFile = NULL; // Initialize File handle to NULL
  153. m_lDetail = 0; // Initialize TRACE detail level to zero (off)
  154. m_bLogToDebugger = FALSE; // Initialize Logging to DEBUGGER to FALSE
  155. m_bLoggerInitialized = FALSE; // Initialize Logger to UNINITIALIZED
  156. m_bTruncate = FALSE; // Initialize Truncation to FALSE
  157. m_bClear = TRUE; // Initialize Clear Log file to TRUE (Don't want to make huge log files for no reason :) )
  158. ZeroMemory(m_szLogFilePath, // Initialize Path buffer
  159. sizeof(m_szLogFilePath));
  160. ZeroMemory(m_szModeText, // Initialize formatted mode text buffer
  161. sizeof(m_szModeText));
  162. }
  163. CWiaLog::~CWiaLog()
  164. {
  165. //DPRINTF(DM_TRACE,TEXT("CWiaLog::Destroy"));
  166. if (m_pITypeInfo != NULL) {
  167. m_pITypeInfo->Release();
  168. }
  169. //
  170. // Flush buffers to disk
  171. //
  172. //DPRINTF(DM_TRACE,TEXT("Flushing final buffers"));
  173. FlushFileBuffers(m_hLogFile);
  174. //
  175. // close log file on destruction of log object
  176. //
  177. //DPRINTF(DM_TRACE,TEXT("Closing file handle"));
  178. CloseHandle(m_hLogFile);
  179. //
  180. // mark handle as invalid
  181. //
  182. m_hLogFile = INVALID_HANDLE_VALUE;
  183. }
  184. ////////////////////////////////////////////////////////////////////////////////////
  185. // IWiaLog private methods (exposed to the client) //
  186. ////////////////////////////////////////////////////////////////////////////////////
  187. /**************************************************************************\
  188. * CWiaLog::InitializeLog
  189. *
  190. * Initializes the Logging component
  191. *
  192. * Arguments:
  193. *
  194. * none
  195. *
  196. * Return Value:
  197. *
  198. * status
  199. *
  200. * History:
  201. *
  202. * 8/20/1999 Original Version
  203. *
  204. \**************************************************************************/
  205. HRESULT _stdcall CWiaLog::InitializeLog (LONG hInstance)
  206. {
  207. HRESULT hr = S_OK;
  208. //
  209. // set instance handle
  210. //
  211. m_hInstance = (HINSTANCE) ULongToPtr(hInstance);
  212. //
  213. // set DLL's name
  214. //
  215. if(!FormatDLLName(m_hInstance,m_szFmtDLLName,sizeof(m_szFmtDLLName)/sizeof(m_szFmtDLLName[0]))) {
  216. //
  217. // if this there is no DLL name created, use a default one
  218. //
  219. lstrcpy(m_szFmtDLLName, szDefaultDLLName);
  220. hr = E_INVALIDARG;
  221. }
  222. //
  223. // Create Registry Key name
  224. //
  225. lstrcpyn(m_szKeyName,m_szFmtDLLName, (sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1);
  226. m_szKeyName[(sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1] = TEXT('\0');
  227. //
  228. // open log file
  229. //
  230. if (OpenLogFile()) {
  231. if (m_hLogFile != NULL) {
  232. //
  233. // query logging settings from registry, to
  234. // setup logging system
  235. //
  236. QueryLoggingSettings();
  237. if(m_bTruncate) {
  238. ProcessTruncation();
  239. }
  240. if(m_bClear) {
  241. //
  242. // clear log file
  243. //
  244. ::SetFilePointer(m_hLogFile, 0, NULL, FILE_BEGIN );
  245. ::SetEndOfFile(m_hLogFile );
  246. }
  247. WriteLogSessionHeader();
  248. m_bLoggerInitialized = TRUE;
  249. }
  250. } else {
  251. //
  252. // Log file failed to Open... this is really bad
  253. //
  254. hr = E_FAIL;
  255. }
  256. return hr;
  257. }
  258. /**************************************************************************\
  259. * CWiaLog::InitializeLogEx
  260. *
  261. * Initializes the Logging component.
  262. *
  263. * Arguments:
  264. *
  265. * hInstance - Handle of the caller's HINSTANCE
  266. *
  267. * Return Value:
  268. *
  269. * status
  270. *
  271. * History:
  272. *
  273. * 3/28/2000 Original Version
  274. *
  275. \**************************************************************************/
  276. HRESULT _stdcall CWiaLog::InitializeLogEx(BYTE* hInstance)
  277. {
  278. HRESULT hr = S_OK;
  279. //
  280. // set instance handle
  281. //
  282. m_hInstance = (HINSTANCE) hInstance;
  283. //
  284. // set DLL's name
  285. //
  286. if(!FormatDLLName(m_hInstance,m_szFmtDLLName,sizeof(m_szFmtDLLName)/sizeof(m_szFmtDLLName[0]))) {
  287. //
  288. // if this there is no DLL name created, use a default one
  289. //
  290. lstrcpy(m_szFmtDLLName, szDefaultDLLName);
  291. hr = E_INVALIDARG;
  292. }
  293. //
  294. // Create Registry Key name
  295. //
  296. lstrcpyn(m_szKeyName,m_szFmtDLLName, (sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1);
  297. m_szKeyName[(sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1] = TEXT('\0');
  298. //
  299. // open log file
  300. //
  301. if (OpenLogFile()) {
  302. if (m_hLogFile != NULL) {
  303. //
  304. // query logging settings from registry, to
  305. // setup logging system
  306. //
  307. QueryLoggingSettings();
  308. if(m_bTruncate) {
  309. ProcessTruncation();
  310. }
  311. if(m_bClear) {
  312. //
  313. // clear log file
  314. //
  315. ::SetFilePointer(m_hLogFile, 0, NULL, FILE_BEGIN );
  316. ::SetEndOfFile(m_hLogFile );
  317. }
  318. WriteLogSessionHeader();
  319. m_bLoggerInitialized = TRUE;
  320. }
  321. } else {
  322. //
  323. // Log file failed to Open... this is really bad
  324. //
  325. hr = E_FAIL;
  326. }
  327. return hr;
  328. }
  329. /**************************************************************************\
  330. * Log()
  331. *
  332. * Handles Logging, TRACE,ERROR,and WARNING optional call logging
  333. *
  334. * Arguments:
  335. *
  336. * lFlags - Flag to determine which type of logging to use
  337. * hInstance - Instance of the calling module
  338. * lResID - Resource ID of the wiaservc.dll resource file
  339. * lDetail - Logging detail level
  340. * bstrText - string for display
  341. *
  342. *
  343. * Return Value:
  344. *
  345. * status
  346. *
  347. * History:
  348. *
  349. * 8/20/1999 Original Version
  350. *
  351. \**************************************************************************/
  352. HRESULT __stdcall CWiaLog::Log (LONG lFlags, LONG lResID, LONG lDetail, BSTR bstrText)
  353. {
  354. HRESULT hr = E_FAIL;
  355. //
  356. // check string for 'free signature' and remove signature if it exists.
  357. //
  358. BOOL bFreeString = NeedsToBeFreed(&bstrText);
  359. if (m_bLoggerInitialized) {
  360. // Find another way of updating the settings without querying the
  361. // Registry every time
  362. // QueryLoggingSettings();
  363. /*
  364. //
  365. // NOTE: revisit this, How can you load a string resource ID from the service,
  366. // if you don't have the service's HINSTANCE?????
  367. //
  368. if(lResID != WIALOG_NO_RESOURCE_ID) {
  369. if (lResID < 35000) {
  370. //
  371. // Load the resource string from caller's resource
  372. //
  373. if (LoadString(g_hInstance,lResID,pBuffer, sizeof(pBuffer)) != 0) {
  374. bstrText = SysAllocString(pBuffer);
  375. bFreeString = TRUE;
  376. }
  377. } else {
  378. //
  379. // pull string from service's resource
  380. //
  381. }
  382. }
  383. */
  384. switch (lFlags) {
  385. case WIALOG_ERROR:
  386. if(m_dwReportMode & WIALOG_ERROR)
  387. hr = Error(bstrText);
  388. break;
  389. case WIALOG_WARNING:
  390. if(m_dwReportMode & WIALOG_WARNING)
  391. hr = Warning(bstrText);
  392. break;
  393. case WIALOG_TRACE:
  394. default:
  395. if(m_dwReportMode & WIALOG_TRACE)
  396. hr = Trace(bstrText,lDetail);
  397. break;
  398. }
  399. }
  400. if(bFreeString)
  401. {
  402. SysFreeString(bstrText);
  403. }
  404. return hr;
  405. }
  406. /**************************************************************************\
  407. * LogEx()
  408. *
  409. * Handles Logging, TRACE,ERROR,and WARNING optional call logging. This
  410. * is almost the same as the Log() call, but it contains a MethodId which
  411. * can be used for more specific filtering.
  412. *
  413. * Arguments:
  414. *
  415. * lMethodId - Integer indicating the uniqeu ID associated with the
  416. * calling method.
  417. * lFlags - Flag to determine which type of logging to use
  418. * hInstance - Instance of the calling module
  419. * lResID - Resource ID of the wiaservc.dll resource file
  420. * lDetail - Logging detail level
  421. * bstrText - string for display
  422. *
  423. *
  424. * Return Value:
  425. *
  426. * status
  427. *
  428. * History:
  429. *
  430. * 3/28/2000 Original Version
  431. *
  432. \**************************************************************************/
  433. HRESULT _stdcall CWiaLog::LogEx(LONG lMethodId, LONG lFlags, LONG lResID, LONG lDetail, BSTR bstrText)
  434. {
  435. HRESULT hr = E_FAIL;
  436. //
  437. // check string for 'free signature' and remove signature if it exists.
  438. //
  439. BOOL bFreeString = NeedsToBeFreed(&bstrText);
  440. if (m_bLoggerInitialized) {
  441. switch (lFlags) {
  442. case WIALOG_ERROR:
  443. if(m_dwReportMode & WIALOG_ERROR)
  444. hr = Error(bstrText, lMethodId);
  445. break;
  446. case WIALOG_WARNING:
  447. if(m_dwReportMode & WIALOG_WARNING)
  448. hr = Warning(bstrText, lMethodId);
  449. break;
  450. case WIALOG_TRACE:
  451. default:
  452. if(m_dwReportMode & WIALOG_TRACE)
  453. hr = Trace(bstrText,lDetail, lMethodId);
  454. break;
  455. }
  456. }
  457. if(bFreeString)
  458. {
  459. SysFreeString(bstrText);
  460. }
  461. return hr;
  462. }
  463. /**************************************************************************\
  464. * hResult()
  465. *
  466. * Handles hResult translating for Error call logging
  467. *
  468. * Arguments:
  469. *
  470. * hInstance - Instance of the calling module
  471. * hr - HRESULT to be translated
  472. *
  473. * Return Value:
  474. *
  475. * status
  476. *
  477. * History:
  478. *
  479. * 8/20/1999 Original Version
  480. *
  481. \**************************************************************************/
  482. HRESULT __stdcall CWiaLog::hResult (HRESULT hr)
  483. {
  484. HRESULT hRes = E_FAIL;
  485. if (m_bLoggerInitialized) {
  486. // Find another way of updating the settings without querying the
  487. // Registry every time
  488. // QueryLoggingSettings();
  489. //
  490. // we are initialized, so set the return to S_OK
  491. //
  492. hRes = S_OK;
  493. if (m_dwReportMode & WIALOG_ERROR) {
  494. #define NUM_CHARS_FOR_HRESULT 150
  495. TCHAR szhResultText[NUM_CHARS_FOR_HRESULT];
  496. ULONG ulLen = 0;
  497. memset(szhResultText, 0, sizeof(szhResultText));
  498. ulLen = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
  499. NULL,
  500. hr,
  501. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  502. (LPTSTR)szhResultText,
  503. NUM_CHARS_FOR_HRESULT,
  504. NULL);
  505. if (ulLen) {
  506. szhResultText[NUM_CHARS_FOR_HRESULT - 1] = TEXT('\0');
  507. memset(m_szTextBuffer,0,sizeof(m_szTextBuffer));
  508. ConstructText();
  509. _sntprintf(m_szTextBuffer,
  510. (sizeof(m_szTextBuffer)/sizeof(m_szTextBuffer[0])) - 1,
  511. TEXT("%s HRESULT: %s"),
  512. m_szModeText,
  513. szhResultText);
  514. WriteStringToLog(m_szTextBuffer, FLUSH_STATE);
  515. }
  516. }
  517. }
  518. return hRes;
  519. }
  520. HRESULT _stdcall CWiaLog::hResultEx(LONG lMethodId, HRESULT hr)
  521. {
  522. HRESULT hRes = E_FAIL;
  523. if (m_bLoggerInitialized) {
  524. // Find another way of updating the settings without querying the
  525. // Registry every time
  526. // QueryLoggingSettings();
  527. //
  528. // we are initialized, so set the return to S_OK
  529. //
  530. hRes = S_OK;
  531. if (m_dwReportMode & WIALOG_ERROR) {
  532. #define NUM_CHARS_FOR_HRESULT 150
  533. TCHAR szhResultText[NUM_CHARS_FOR_HRESULT];
  534. ULONG ulLen = 0;
  535. memset(szhResultText, 0, sizeof(szhResultText));
  536. ulLen = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
  537. NULL,
  538. hr,
  539. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  540. (LPTSTR)szhResultText,
  541. NUM_CHARS_FOR_HRESULT,
  542. NULL);
  543. if (ulLen) {
  544. szhResultText[NUM_CHARS_FOR_HRESULT - 1] = TEXT('\0');
  545. memset(m_szTextBuffer,0,sizeof(m_szTextBuffer));
  546. ConstructText();
  547. _sntprintf(m_szTextBuffer,
  548. (sizeof(m_szTextBuffer)/sizeof(m_szTextBuffer[0])) - 1,
  549. TEXT("#0x%08X %s HRESULT: %s"),
  550. lMethodId,
  551. m_szModeText,
  552. szhResultText);
  553. WriteStringToLog(m_szTextBuffer, FLUSH_STATE);
  554. }
  555. }
  556. }
  557. return hRes;
  558. }
  559. HRESULT _stdcall CWiaLog::UpdateSettingsEx(LONG lCount, LONG *plMethodIds)
  560. {
  561. return E_NOTIMPL;
  562. }
  563. HRESULT _stdcall CWiaLog::ExportMappingTableEx(MappingTable **ppTable)
  564. {
  565. return E_NOTIMPL;
  566. }
  567. ////////////////////////////////////////////////////////////////////////////////////
  568. // IWiaLog private methods (not exposed to the client) //
  569. ////////////////////////////////////////////////////////////////////////////////////
  570. /**************************************************************************\
  571. * CWiaLog::Initialize
  572. *
  573. * Initializes the CWiaLog class object (does nothing at the moment)
  574. *
  575. * Arguments:
  576. *
  577. * none
  578. *
  579. * Return Value:
  580. *
  581. * status
  582. *
  583. * History:
  584. *
  585. * 8/20/1999 Original Version
  586. *
  587. \**************************************************************************/
  588. HRESULT CWiaLog::Initialize()
  589. {
  590. //DPRINTF(DM_TRACE,TEXT("CWiaLog::Initialize"));
  591. return S_OK;
  592. }
  593. /**************************************************************************\
  594. * Trace()
  595. *
  596. * Handles Trace call logging
  597. *
  598. * Arguments:
  599. *
  600. * hInstance - Instance of the calling module
  601. * lResID - Resource ID of the wiaservc.dll resource file
  602. * bstrText - string for display
  603. * lDetail - Logging detail level
  604. *
  605. * Return Value:
  606. *
  607. * status
  608. *
  609. * History:
  610. *
  611. * 8/20/1999 Original Version
  612. *
  613. \**************************************************************************/
  614. HRESULT CWiaLog::Trace (BSTR bstrText, LONG lDetail, LONG lMethodId)
  615. {
  616. memset(m_szTextBuffer,0,sizeof(m_szTextBuffer));
  617. //
  618. // Turn off if lDetail level is zero
  619. // TODO: Only don't log if both detail level = 0, and the lMethodId doesn't
  620. // match one in our list
  621. //
  622. if(m_lDetail == 0) {
  623. return S_OK;
  624. }
  625. if (lDetail <= m_lDetail) {
  626. ConstructText();
  627. _sntprintf(m_szTextBuffer,
  628. sizeof(m_szTextBuffer) / sizeof(m_szTextBuffer[0]) - 1,
  629. TEXT("#0x%08X %s TRACE: %ws"),
  630. lMethodId,
  631. m_szModeText,
  632. bstrText);
  633. WriteStringToLog(m_szTextBuffer, FLUSH_STATE);
  634. }
  635. return S_OK;
  636. }
  637. /**************************************************************************\
  638. * Warning()
  639. *
  640. * Handles Warning call logging
  641. *
  642. * Arguments:
  643. *
  644. * hInstance - Instance of the calling module
  645. * lResID - Resource ID of the wiaservc.dll resource file
  646. * bstrText - string for display
  647. *
  648. * Return Value:
  649. *
  650. * status
  651. *
  652. * History:
  653. *
  654. * 8/20/1999 Original Version
  655. *
  656. \**************************************************************************/
  657. HRESULT CWiaLog::Warning(BSTR bstrText, LONG lMethodId)
  658. {
  659. memset(m_szTextBuffer,0,sizeof(m_szTextBuffer));
  660. ConstructText();
  661. _sntprintf(m_szTextBuffer,
  662. sizeof(m_szTextBuffer) / sizeof(m_szTextBuffer[0]) - 1,
  663. TEXT("#0x%08X %s WARNING: %ws"),
  664. lMethodId,
  665. m_szModeText,
  666. bstrText);
  667. WriteStringToLog(m_szTextBuffer, FLUSH_STATE);
  668. return S_OK;
  669. }
  670. /**************************************************************************\
  671. * Error()
  672. *
  673. * Handles Error call logging
  674. *
  675. * Arguments:
  676. *
  677. * hInstance - Instance of the calling module
  678. * lResID - Resource ID of the wiaservc.dll resource file
  679. * bstrText - string for display
  680. *
  681. * Return Value:
  682. *
  683. * status
  684. *
  685. * History:
  686. *
  687. * 8/20/1999 Original Version
  688. *
  689. \**************************************************************************/
  690. HRESULT CWiaLog::Error (BSTR bstrText, LONG lMethodId)
  691. {
  692. memset(m_szTextBuffer,0,sizeof(m_szTextBuffer));
  693. ConstructText();
  694. _sntprintf(m_szTextBuffer,
  695. sizeof(m_szTextBuffer) / sizeof(m_szTextBuffer[0]) - 1,
  696. TEXT("#0x%08X %s ERROR: %ws"),
  697. lMethodId,
  698. m_szModeText,
  699. bstrText);
  700. WriteStringToLog(m_szTextBuffer, FLUSH_STATE);
  701. return S_OK;
  702. }
  703. ////////////////////////////////////////////////////////////////////////////////////
  704. // IWiaLog private helpers (not exposed to the client) //
  705. ////////////////////////////////////////////////////////////////////////////////////
  706. /**************************************************************************\
  707. * OpenLogFile()
  708. *
  709. * Open the log file for logging
  710. *
  711. *
  712. * Arguments:
  713. *
  714. * none
  715. *
  716. * Return Value:
  717. *
  718. * status
  719. *
  720. * History:
  721. *
  722. * 8/23/1999 Original Version
  723. *
  724. \**************************************************************************/
  725. BOOL CWiaLog::OpenLogFile()
  726. {
  727. //
  728. // Open log file
  729. //
  730. DWORD dwLength = 0;
  731. CSimpleString csName;
  732. m_hLogFile = INVALID_HANDLE_VALUE;
  733. //
  734. // Get Windows Directory
  735. //
  736. dwLength = ExpandEnvironmentStrings(TEXT("%USERPROFILE%"), m_szLogFilePath,
  737. sizeof(m_szLogFilePath) /
  738. sizeof(m_szLogFilePath[0]));
  739. if (( dwLength == 0) || !*m_szLogFilePath ) {
  740. //DPRINTF(DM_TRACE,TEXT("Could not GetWindowsDirectory()"));
  741. return FALSE;
  742. }
  743. m_szLogFilePath[(sizeof(m_szLogFilePath)/sizeof(m_szLogFilePath[0]) - 1)] = TEXT('\0');
  744. //
  745. // Add log file name to Windows Directory
  746. //
  747. csName = m_szLogFilePath;
  748. csName += TEXT("\\");
  749. csName += TEXT("wiaservc.log");
  750. //
  751. // Create / open Log file
  752. //
  753. m_hLogFile = ::CreateFile(m_szLogFilePath,
  754. GENERIC_WRITE | GENERIC_READ,
  755. FILE_SHARE_WRITE | FILE_SHARE_READ,
  756. NULL, // security attributes
  757. OPEN_ALWAYS,
  758. FILE_ATTRIBUTE_NORMAL,
  759. NULL); // template file handle
  760. if (m_hLogFile == INVALID_HANDLE_VALUE)
  761. return FALSE;
  762. return TRUE;
  763. }
  764. /**************************************************************************\
  765. * WriteStringToLog()
  766. *
  767. * Writed formatted TEXT to a log file
  768. *
  769. *
  770. * Arguments:
  771. *
  772. * pszTextBuffer - Buffer of TEXT to write to file
  773. * fFlush - TRUE = FLUSH file on write,
  774. * FALSE = DON'T FLUSH file on write
  775. *
  776. * Return Value:
  777. *
  778. * status
  779. *
  780. * History:
  781. *
  782. * 8/23/1999 Original Version
  783. *
  784. \**************************************************************************/
  785. VOID CWiaLog::WriteStringToLog(LPTSTR pszTextBuffer,BOOL fFlush)
  786. {
  787. DWORD dwcbWritten;
  788. BY_HANDLE_FILE_INFORMATION fi;
  789. if (!GetFileInformationByHandle(m_hLogFile,&fi)) {
  790. //DPRINTF(DM_TRACE,TEXT("WIALOG could not get file size for log file. "));
  791. return;
  792. }
  793. //
  794. // check to see if our log file has exceeded it's MAX SIZE
  795. // If it has, reset the file pointer, and start writing from the
  796. // TOP.
  797. //
  798. //if ( fi.nFileSizeHigh !=0 || (fi.nFileSizeLow > m_dwMaxSize) ){
  799. // ::SetFilePointer( m_hLogFile, 0, NULL, FILE_END);
  800. // ::SetEndOfFile( m_hLogFile );
  801. // ::GetFileInformationByHandle(m_hLogFile,&fi);
  802. //}
  803. #ifdef USE_FILE_LOCK
  804. ::LockFile(m_hLogFile,
  805. fi.nFileSizeLow,
  806. fi.nFileSizeHigh,
  807. NUM_BYTES_TO_LOCK_LOW,
  808. NUM_BYTES_TO_LOCK_HIGH);
  809. #endif
  810. ::SetFilePointer( m_hLogFile, 0, NULL, FILE_END);
  811. #ifdef UNICODE
  812. //
  813. // convert to ANSI if we are UNICODE, and write string to log.
  814. //
  815. CHAR buffer[MAX_PATH];
  816. WideCharToMultiByte(CP_ACP,WC_NO_BEST_FIT_CHARS,pszTextBuffer,-1,buffer,MAX_PATH,NULL,NULL);
  817. ::WriteFile(m_hLogFile,
  818. buffer,
  819. lstrlen(pszTextBuffer),
  820. &dwcbWritten,
  821. NULL);
  822. #else
  823. //
  824. // we are ANSI so write string to log.
  825. //
  826. ::WriteFile(m_hLogFile,
  827. pszTextBuffer,
  828. lstrlen(pszTextBuffer),
  829. &dwcbWritten,
  830. NULL);
  831. #endif
  832. ::WriteFile(m_hLogFile,
  833. "\r\n",
  834. 2,
  835. &dwcbWritten,
  836. NULL);
  837. #ifdef USE_FILE_LOCK
  838. ::UnlockFile(m_hLogFile,
  839. fi.nFileSizeLow,
  840. fi.nFileSizeHigh,
  841. NUM_BYTES_TO_LOCK_LOW,
  842. NUM_BYTES_TO_LOCK_HIGH);
  843. #endif
  844. //
  845. // Flush buffers to disk if requested (should always be TRUE on Millenium)
  846. //
  847. if (fFlush) {
  848. FlushFileBuffers(m_hLogFile);
  849. }
  850. //
  851. // Log to a Debugger
  852. //
  853. if (m_bLogToDebugger) {
  854. ::OutputDebugString(pszTextBuffer);
  855. ::OutputDebugString(TEXT("\n"));
  856. }
  857. //
  858. // Log to a Window / UI
  859. //
  860. if (m_bLogToUI) {
  861. //
  862. // Log to some window...or UI
  863. //
  864. }
  865. }
  866. /**************************************************************************\
  867. * FormatStdTime()
  868. *
  869. * Formats the TIME to be added to a LOG file
  870. *
  871. *
  872. * Arguments:
  873. *
  874. * pstNow - System Time NOW
  875. * pchBuffer - buffer for the formatted time
  876. * cbBuffer - Buffer size
  877. *
  878. *
  879. * Return Value:
  880. *
  881. * status
  882. *
  883. * History:
  884. *
  885. * 8/23/1999 Original Version
  886. *
  887. \**************************************************************************/
  888. BOOL CWiaLog::FormatStdTime(const SYSTEMTIME *pstNow,TCHAR *pchBuffer)
  889. {
  890. ::wsprintf(pchBuffer,
  891. TEXT("%02d:%02d:%02d.%03d"),
  892. pstNow->wHour,
  893. pstNow->wMinute,
  894. pstNow->wSecond,
  895. pstNow->wMilliseconds);
  896. return TRUE;
  897. }
  898. /**************************************************************************\
  899. * FormatStdDate()
  900. *
  901. * Formats the DATE to be added to a LOG file
  902. *
  903. *
  904. * Arguments:
  905. *
  906. * pstNow - System TIME NOW
  907. * pchBuffer - buffer for the formatted time
  908. * cbBuffer - Buffer size
  909. *
  910. *
  911. * Return Value:
  912. *
  913. * status
  914. *
  915. * History:
  916. *
  917. * 8/23/1999 Original Version
  918. *
  919. \**************************************************************************/
  920. inline BOOL FormatStdDate(const SYSTEMTIME *pstNow,TCHAR *pchBuffer,INT cchBuffer)
  921. {
  922. return (GetDateFormat(LOCALE_SYSTEM_DEFAULT,
  923. LOCALE_NOUSEROVERRIDE,
  924. pstNow,
  925. NULL,
  926. pchBuffer,
  927. cchBuffer)!= 0);
  928. }
  929. /**************************************************************************\
  930. * WriteLogSessionHeader()
  931. *
  932. * Writes a header to the log file
  933. *
  934. *
  935. * Arguments:
  936. *
  937. * none
  938. *
  939. * Return Value:
  940. *
  941. * void
  942. *
  943. * History:
  944. *
  945. * 8/23/1999 Original Version
  946. *
  947. \**************************************************************************/
  948. VOID CWiaLog::WriteLogSessionHeader()
  949. {
  950. SYSTEMTIME stCurrentTime;
  951. TCHAR szFmtDate[64] = {0};
  952. TCHAR szFmtTime[64] = {0};
  953. TCHAR szTextBuffer[128];
  954. //
  955. // Format TIME and DATE
  956. //
  957. GetLocalTime(&stCurrentTime);
  958. FormatStdDate( &stCurrentTime, szFmtDate, sizeof(szFmtDate) / sizeof(szFmtDate[0]) - 1);
  959. FormatStdTime( &stCurrentTime, szFmtTime);
  960. //
  961. // write formatted data to TEXT buffer
  962. //
  963. _sntprintf(szTextBuffer,
  964. sizeof(szTextBuffer)/sizeof(szTextBuffer[0]),
  965. szOpenedLog,
  966. m_szFmtDLLName,
  967. szFmtDate,
  968. szFmtTime);
  969. szTextBuffer[sizeof(szTextBuffer)/sizeof(szTextBuffer[0]) - 1] = TEXT('\0');
  970. //
  971. // write TEXT buffer to log
  972. //
  973. WriteStringToLog(szTextBuffer, FLUSH_STATE);
  974. }
  975. /**************************************************************************\
  976. * QueryLoggingSettings()
  977. *
  978. * Read the registry and set the logging settings.
  979. *
  980. *
  981. * Arguments:
  982. *
  983. * none
  984. *
  985. * Return Value:
  986. *
  987. * status
  988. *
  989. * History:
  990. *
  991. * 8/23/1999 Original Version
  992. *
  993. \**************************************************************************/
  994. BOOL CWiaLog::QueryLoggingSettings()
  995. {
  996. DWORD dwLevel = 0;
  997. DWORD dwMode = 0;
  998. //
  999. // read settings from the registry
  1000. //
  1001. RegEntry re(REGSTR_PATH_STICONTROL REGSTR_PATH_LOGGING,HKEY_LOCAL_MACHINE);
  1002. if (re.IsValid()) {
  1003. m_dwMaxSize = re.GetNumber(REGSTR_VAL_LOG_MAXSIZE,WIA_MAX_LOG_SIZE);
  1004. }
  1005. //
  1006. // read report mode flags
  1007. //
  1008. re.MoveToSubKey(m_szKeyName);
  1009. if (re.IsValid()) {
  1010. dwLevel = re.GetNumber(REGSTR_VAL_LOG_LEVEL,WIALOG_ERROR)
  1011. & WIALOG_MESSAGE_TYPE_MASK;
  1012. dwMode = re.GetNumber(REGSTR_VAL_LOG_MODE,WIALOG_ADD_THREAD|WIALOG_ADD_MODULE)
  1013. & WIALOG_MESSAGE_FLAGS_MASK;
  1014. m_lDetail = re.GetNumber(REGSTR_VAL_LOG_DETAIL,WIALOG_NO_LEVEL);
  1015. //
  1016. // set truncate log on boot options
  1017. //
  1018. DWORD dwTruncate = -1;
  1019. dwTruncate = re.GetNumber(REGSTR_VAL_LOG_TRUNCATE_ON_BOOT,FALSE);
  1020. if (dwTruncate == 0)
  1021. m_bTruncate = FALSE;
  1022. else
  1023. m_bTruncate = TRUE;
  1024. //
  1025. // set clear log on boot options
  1026. //
  1027. DWORD dwClear = -1;
  1028. dwClear = re.GetNumber(REGSTR_VAL_LOG_CLEARLOG_ON_BOOT,TRUE);
  1029. if (dwClear == 0)
  1030. m_bClear = FALSE;
  1031. else
  1032. m_bClear = TRUE;
  1033. //
  1034. // set debugger logging options
  1035. //
  1036. DWORD dwDebugLogging = -1;
  1037. dwDebugLogging = re.GetNumber(REGSTR_VAL_LOG_TO_DEBUGGER,FALSE);
  1038. if (dwDebugLogging == 0)
  1039. m_bLogToDebugger = FALSE;
  1040. else
  1041. m_bLogToDebugger = TRUE;
  1042. }
  1043. //
  1044. // set report mode
  1045. //
  1046. m_dwReportMode = dwLevel | dwMode;
  1047. //
  1048. // set UI (window) logging options
  1049. //
  1050. if(m_dwReportMode & WIALOG_UI)
  1051. m_bLogToUI = TRUE;
  1052. else
  1053. m_bLogToUI = FALSE;
  1054. return TRUE;
  1055. }
  1056. /**************************************************************************\
  1057. * ConstructText()
  1058. *
  1059. * Constructs TEXT according to Logging settings
  1060. *
  1061. *
  1062. * Arguments:
  1063. *
  1064. * pchBuffer - buffer for the formatted text
  1065. * cbBuffer - Buffer size
  1066. *
  1067. *
  1068. * Return Value:
  1069. *
  1070. * status
  1071. *
  1072. * History:
  1073. *
  1074. * 8/23/1999 Original Version
  1075. *
  1076. \**************************************************************************/
  1077. VOID CWiaLog::ConstructText()
  1078. {
  1079. //
  1080. // set string constructor to zero
  1081. //
  1082. CSimpleString csHeader;
  1083. CSimpleString csBuffer;
  1084. CSimpleString csModeText;
  1085. //
  1086. // add thread id
  1087. //
  1088. if(m_dwReportMode & WIALOG_ADD_THREAD) {
  1089. csBuffer.Format(TEXT("[%08X] "), ::GetCurrentThreadId());
  1090. csModeText += csBuffer;
  1091. csHeader += TEXT("[ Thread ] ");
  1092. }
  1093. //
  1094. // add module name
  1095. //
  1096. if(m_dwReportMode & WIALOG_ADD_MODULE) {
  1097. csBuffer.Format(TEXT("%s "), m_szFmtDLLName);
  1098. csModeText += csBuffer;
  1099. csHeader += TEXT("[ Module ] ");
  1100. }
  1101. //
  1102. // add time
  1103. //
  1104. if(m_dwReportMode & WIALOG_ADD_TIME) {
  1105. SYSTEMTIME stCurrentTime;
  1106. TCHAR szFmtTime[40];
  1107. GetLocalTime(&stCurrentTime);
  1108. FormatStdTime(&stCurrentTime, szFmtTime);
  1109. csBuffer.Format(TEXT(" %s "), szFmtTime);
  1110. csModeText += csBuffer;
  1111. csHeader += TEXT("[ HH:MM:SS.ms ] ");
  1112. }
  1113. //
  1114. // Copy the log text into m_szModeText
  1115. //
  1116. lstrcpyn(m_szModeText, csModeText.String(), sizeof(m_szColumnHeader)/sizeof(m_szColumnHeader[0]));
  1117. m_szModeText[sizeof(m_szModeText)/sizeof(m_szModeText[0]) - 1] = TEXT('\0');
  1118. //
  1119. // add column header if needed
  1120. //
  1121. if(csHeader.Compare(m_szColumnHeader) != 0) {
  1122. lstrcpyn(m_szColumnHeader,csHeader.String(), sizeof(m_szColumnHeader)/sizeof(m_szColumnHeader[0]));
  1123. m_szColumnHeader[sizeof(m_szColumnHeader)/sizeof(m_szColumnHeader[0]) - 1] = TEXT('\0');
  1124. WriteStringToLog(TEXT(" "), FLUSH_STATE);
  1125. WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE);
  1126. WriteStringToLog(m_szColumnHeader, FLUSH_STATE);
  1127. WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE);
  1128. WriteStringToLog(TEXT(" "), FLUSH_STATE);
  1129. }
  1130. }
  1131. /**************************************************************************\
  1132. * FormatDLLName()
  1133. *
  1134. * Formats the DLL name to be added to a LOG file
  1135. *
  1136. *
  1137. * Arguments:
  1138. *
  1139. * hInstance - Instance of the calling DLL
  1140. * pchBuffer - buffer for the formatted name
  1141. * cbBuffer - Buffer size
  1142. *
  1143. *
  1144. * Return Value:
  1145. *
  1146. * status
  1147. *
  1148. * History:
  1149. *
  1150. * 8/23/1999 Original Version
  1151. *
  1152. \**************************************************************************/
  1153. BOOL CWiaLog::FormatDLLName(HINSTANCE hInstance, TCHAR *pchBuffer, INT cchBuffer)
  1154. {
  1155. TCHAR lpfullpath[255];
  1156. TCHAR szModuleName[255]; // We know that the module name has to be <= ModuleFileName, so
  1157. // by having szModuleName be the same size, we are guranteed to have enough
  1158. // room (assuming lpFullPath is large enough for the ModuleFileName).
  1159. DWORD dwLength = 0;
  1160. dwLength = GetModuleFileName(hInstance,lpfullpath,sizeof(lpfullpath)/sizeof(lpfullpath[0]));
  1161. lpfullpath[sizeof(lpfullpath)/sizeof(lpfullpath[0]) - 1] = TEXT('\0');
  1162. if(dwLength == 0)
  1163. return FALSE;
  1164. //
  1165. // extract the file name from the full path
  1166. //
  1167. _tsplitpath(lpfullpath, NULL, NULL, szModuleName, NULL);
  1168. lstrcpyn(pchBuffer, szModuleName, cchBuffer);
  1169. pchBuffer[cchBuffer - 1] = TEXT('\0');
  1170. return TRUE;
  1171. }
  1172. /**************************************************************************\
  1173. * NeedsToBeFreed()
  1174. *
  1175. * Determines if the logger should free the allocated string.
  1176. * If the signature is found, it is stripped off the beginning of the string
  1177. * and the return of TRUE is set.
  1178. *
  1179. * Arguments:
  1180. *
  1181. * pBSTR - buffer for BSTRING
  1182. *
  1183. *
  1184. * Return Value:
  1185. *
  1186. * status
  1187. *
  1188. * History:
  1189. *
  1190. * 8/23/1999 Original Version
  1191. *
  1192. \**************************************************************************/
  1193. BOOL CWiaLog::NeedsToBeFreed(BSTR* pBSTR)
  1194. {
  1195. //
  1196. // NOTE: MAX_SIG_LEN *must* be larger than the string length of
  1197. // the signature!!!
  1198. //
  1199. WCHAR wszSig[MAX_SIG_LEN];
  1200. //
  1201. // check string to see if it is NULL, user may want to use a resource ID instead
  1202. //
  1203. if(*pBSTR == NULL) {
  1204. return FALSE;
  1205. }
  1206. //
  1207. // extract a possible signature from the beginning of the BSTR
  1208. //
  1209. wcsncpy(wszSig, *pBSTR, wcslen(szFormatSignature));
  1210. wszSig[wcslen(szFormatSignature)] = '\0';
  1211. //
  1212. // do they match?
  1213. //
  1214. if(wcscmp(wszSig,szFormatSignature) == 0) {
  1215. //
  1216. // They match, so strip off the signature from the BSTR, and
  1217. // return TRUE, (string can be freed by us).
  1218. //
  1219. wcscpy(*pBSTR,*pBSTR + wcslen(szFormatSignature));
  1220. return TRUE;
  1221. }
  1222. //
  1223. // signature did not match, must not be allocated by US
  1224. //
  1225. return FALSE;
  1226. }
  1227. /**************************************************************************\
  1228. * ProcessTruncation()
  1229. *
  1230. * Determines if the logger should truncate the file.
  1231. * The bottom part of the log file is copied, and copied back to the log file
  1232. * after the file has been truncated.
  1233. *
  1234. *
  1235. * Arguments:
  1236. *
  1237. * none
  1238. *
  1239. *
  1240. * Return Value:
  1241. *
  1242. * void
  1243. *
  1244. * History:
  1245. *
  1246. * 9/09/1999 Original Version
  1247. *
  1248. \**************************************************************************/
  1249. VOID CWiaLog::ProcessTruncation()
  1250. {
  1251. //
  1252. // determine file size
  1253. //
  1254. DWORD dwFileSize = 0;
  1255. BY_HANDLE_FILE_INFORMATION fi;
  1256. if (!GetFileInformationByHandle(m_hLogFile,&fi)) {
  1257. //DPRINTF(DM_TRACE,TEXT("WIALOG could not get file size for log file. "));
  1258. return;
  1259. }
  1260. dwFileSize = fi.nFileSizeLow;
  1261. if (dwFileSize > MAX_TRUNCATE_SIZE) {
  1262. //
  1263. // Allocate a temporary buffer
  1264. //
  1265. BYTE *pBuffer = NULL;
  1266. DWORD dwBytesRead = 0;
  1267. DWORD dwBytesWritten = 0;
  1268. pBuffer = (BYTE*)LocalAlloc(LPTR,MAX_TRUNCATE_SIZE);
  1269. if (pBuffer != NULL) {
  1270. BOOL bRead = FALSE;
  1271. //
  1272. // read buffered data
  1273. //
  1274. ::SetFilePointer(m_hLogFile,dwFileSize - MAX_TRUNCATE_SIZE,NULL,FILE_BEGIN);
  1275. bRead = ::ReadFile(m_hLogFile,(VOID*)pBuffer,MAX_TRUNCATE_SIZE,&dwBytesRead,NULL);
  1276. //
  1277. // nuke existing file
  1278. //
  1279. ::SetFilePointer(m_hLogFile, 0, NULL, FILE_BEGIN );
  1280. ::SetEndOfFile(m_hLogFile );
  1281. if (bRead) {
  1282. //
  1283. // Write buffer to file
  1284. //
  1285. ::WriteFile(m_hLogFile,pBuffer,MAX_TRUNCATE_SIZE,&dwBytesWritten,NULL);
  1286. //
  1287. // Write Truncation Header
  1288. //
  1289. WriteStringToLog(TEXT(" "), FLUSH_STATE);
  1290. WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE);
  1291. TCHAR szHeader[MAX_PATH];
  1292. lstrcpy(szHeader,m_szFmtDLLName);
  1293. lstrcat(szHeader,TEXT(" REQUESTED A FILE TRUNCATION"));
  1294. WriteStringToLog(TEXT(" (Data above this marker is saved from a previous session)"), FLUSH_STATE);
  1295. WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE);
  1296. WriteStringToLog(TEXT(" "), FLUSH_STATE);
  1297. }
  1298. LocalFree(pBuffer);
  1299. }
  1300. } else {
  1301. //
  1302. // File is too small, and does not need to be truncated
  1303. //
  1304. return;
  1305. }
  1306. }