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.

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