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.

2849 lines
82 KiB

  1. /*
  2. Module Name:
  3. faxlog.c
  4. Abstract:
  5. This is the main fax service activity logging implementation.
  6. Author:
  7. Revision History:
  8. --*/
  9. #include "faxsvc.h"
  10. #include <string>
  11. using namespace std;
  12. LOG_STRING_TABLE g_OutboxTable[] =
  13. {
  14. {IDS_JOB_ID, FIELD_TYPE_TEXT, 18, NULL },
  15. {IDS_PARENT_JOB_ID, FIELD_TYPE_TEXT, 18, NULL },
  16. {IDS_SUBMITED, FIELD_TYPE_DATE, 0, NULL },
  17. {IDS_SCHEDULED, FIELD_TYPE_DATE, 0, NULL },
  18. {IDS_STATUS, FIELD_TYPE_TEXT, 255, NULL },
  19. {IDS_ERROR_DESC, FIELD_TYPE_TEXT, 255, NULL },
  20. {IDS_ERROR_CODE, FIELD_TYPE_TEXT, 10, NULL },
  21. {IDS_START_TIME, FIELD_TYPE_DATE, 0, NULL },
  22. {IDS_END_TIME, FIELD_TYPE_DATE, 0, NULL },
  23. {IDS_DEVICE, FIELD_TYPE_TEXT, 255, NULL },
  24. {IDS_DIALED_NUMBER, FIELD_TYPE_TEXT, 255, NULL },
  25. {IDS_CSID, FIELD_TYPE_TEXT, 255, NULL },
  26. {IDS_TSID, FIELD_TYPE_TEXT, 255, NULL },
  27. {IDS_PAGES, FIELD_TYPE_FLOAT, 0, NULL },
  28. {IDS_TOTAL_PAGES, FIELD_TYPE_FLOAT, 0, NULL },
  29. {IDS_FILE_NAME, FIELD_TYPE_TEXT, 255, NULL },
  30. {IDS_DOCUMENT, FIELD_TYPE_TEXT, 255, NULL },
  31. {IDS_FILE_SIZE, FIELD_TYPE_FLOAT, 0, NULL },
  32. {IDS_RETRIES, FIELD_TYPE_FLOAT, 0, NULL },
  33. {IDS_COVER_PAGE, FIELD_TYPE_TEXT, 255, NULL },
  34. {IDS_SUBJECT, FIELD_TYPE_TEXT, 255, NULL },
  35. {IDS_NOTE, FIELD_TYPE_TEXT, 255, NULL },
  36. {IDS_USER_NAME, FIELD_TYPE_TEXT, 255, NULL },
  37. {IDS_SENDER_NAME, FIELD_TYPE_TEXT, 255, NULL },
  38. {IDS_SENDER_FAX_NUMBER, FIELD_TYPE_TEXT, 255, NULL },
  39. {IDS_SENDER_COMPANY, FIELD_TYPE_TEXT, 255, NULL },
  40. {IDS_SENDER_STREET, FIELD_TYPE_TEXT, 255, NULL },
  41. {IDS_SENDER_CITY, FIELD_TYPE_TEXT, 255, NULL },
  42. {IDS_SENDER_ZIP, FIELD_TYPE_TEXT, 255, NULL },
  43. {IDS_SENDER_COUNTRY, FIELD_TYPE_TEXT, 255, NULL },
  44. {IDS_SENDER_TITLE, FIELD_TYPE_TEXT, 255, NULL },
  45. {IDS_SENDER_DEPARTMENT, FIELD_TYPE_TEXT, 255, NULL },
  46. {IDS_SENDER_OFFICE, FIELD_TYPE_TEXT, 255, NULL },
  47. {IDS_SENDER_H_PHONE, FIELD_TYPE_TEXT, 255, NULL },
  48. {IDS_SENDER_O_PHONE, FIELD_TYPE_TEXT, 255, NULL },
  49. {IDS_SENDER_E_MAIL, FIELD_TYPE_TEXT, 255, NULL },
  50. {IDS_RECIPIENT_NAME, FIELD_TYPE_TEXT, 255, NULL },
  51. {IDS_RECIPIENT_FAX_NUMBER, FIELD_TYPE_TEXT, 255, NULL },
  52. {IDS_RECIPIENT_COMPANY, FIELD_TYPE_TEXT, 255, NULL },
  53. {IDS_RECIPIENT_STREET, FIELD_TYPE_TEXT, 255, NULL },
  54. {IDS_RECIPIENT_CITY, FIELD_TYPE_TEXT, 255, NULL },
  55. {IDS_RECIPIENT_ZIP, FIELD_TYPE_TEXT, 255, NULL },
  56. {IDS_RECIPIENT_COUNTRY, FIELD_TYPE_TEXT, 255, NULL },
  57. {IDS_RECIPIENT_TITLE, FIELD_TYPE_TEXT, 255, NULL },
  58. {IDS_RECIPIENT_DEPARTMENT, FIELD_TYPE_TEXT, 255, NULL },
  59. {IDS_RECIPIENT_OFFICE, FIELD_TYPE_TEXT, 255, NULL },
  60. {IDS_RECIPIENT_H_PHONE, FIELD_TYPE_TEXT, 255, NULL },
  61. {IDS_RECIPIENT_O_PHONE, FIELD_TYPE_TEXT, 255, NULL },
  62. {IDS_RECIPIENT_E_MAIL, FIELD_TYPE_TEXT, 255, NULL },
  63. {IDS_BILLING_CODE, FIELD_TYPE_TEXT, 255, NULL }
  64. };
  65. LOG_STRING_TABLE g_InboxTable[] =
  66. {
  67. {IDS_STATUS, FIELD_TYPE_TEXT, 255, NULL },
  68. {IDS_ERROR_DESC, FIELD_TYPE_TEXT, 255, NULL },
  69. {IDS_ERROR_CODE, FIELD_TYPE_TEXT, 10, NULL },
  70. {IDS_START_TIME, FIELD_TYPE_DATE, 0, NULL },
  71. {IDS_END_TIME, FIELD_TYPE_DATE, 0, NULL },
  72. {IDS_DEVICE, FIELD_TYPE_TEXT, 255, NULL },
  73. {IDS_FILE_NAME, FIELD_TYPE_TEXT, 255, NULL },
  74. {IDS_FILE_SIZE, FIELD_TYPE_FLOAT, 0, NULL },
  75. {IDS_CSID, FIELD_TYPE_TEXT, 255, NULL },
  76. {IDS_TSID, FIELD_TYPE_TEXT, 255, NULL },
  77. {IDS_CALLER_ID, FIELD_TYPE_TEXT, 255, NULL },
  78. {IDS_ROUTING_INFO, FIELD_TYPE_TEXT, 255, NULL },
  79. {IDS_PAGES, FIELD_TYPE_FLOAT, 0, NULL }
  80. };
  81. const DWORD gc_dwCountInboxTable = (sizeof(g_InboxTable)/sizeof(g_InboxTable[0]));
  82. const DWORD gc_dwCountOutboxTable = (sizeof(g_OutboxTable)/sizeof(g_OutboxTable[0]));
  83. HANDLE g_hInboxActivityLogFile;
  84. HANDLE g_hOutboxActivityLogFile;
  85. static
  86. wstring
  87. FilteredLogString (LPCWSTR lpcwstrSrc) throw (exception);
  88. static
  89. VOID
  90. GetSchemaFileText(wstring &wstrRes) throw (exception);
  91. static
  92. VOID
  93. GetTableColumnsText(
  94. LPTSTR ptszTableName,
  95. wstring &wstrResult
  96. ) throw (exception);
  97. static
  98. BOOL
  99. GetFaxTimeAsString(
  100. SYSTEMTIME* pFaxTime,
  101. wstring &wstrTime
  102. ) throw (exception);
  103. static
  104. BOOL
  105. GetInboundCommandText(
  106. PJOB_QUEUE lpJobQueue,
  107. LPCFSPI_JOB_STATUS lpcFaxStatus,
  108. wstring &wstrCommandText
  109. ) throw (exception);
  110. static
  111. BOOL
  112. GetOutboundCommandText(
  113. PJOB_QUEUE lpJobQueue,
  114. wstring &wstrCommandText
  115. ) throw (exception);
  116. //
  117. // Important!! - Always lock g_CsInboundActivityLogging and then g_CsOutboundActivityLogging
  118. //
  119. CFaxCriticalSection g_CsInboundActivityLogging;
  120. CFaxCriticalSection g_CsOutboundActivityLogging;
  121. BOOL g_fLogStringTableInit;
  122. static DWORD CreateLogFile(DWORD dwFileType, LPCWSTR lpcwstrDBPath, LPHANDLE phFile);
  123. static BOOL LogFileLimitReached(DWORD dwFileToCheck);
  124. static DWORD LogFileLimitReachAction(DWORD dwFileType);
  125. static DWORD DeleteLogActivityFile(DWORD dwFileType);
  126. static DWORD ReplaceLogActivityFile(DWORD dwFileType);
  127. static LPTSTR BuildFullFileName( LPCTSTR strPath,LPCTSTR strFileName );
  128. static BOOL SetFileToCurrentTime(HANDLE hFile);
  129. //*********************************************************************************
  130. //* Name: LogInboundActivity()
  131. //* Author: Oded Sacher
  132. //* Date: Oct 19, 1999
  133. //*********************************************************************************
  134. //* DESCRIPTION:
  135. //* Inserts new record into the Inbox Activity logging table.
  136. //* Must be called inside critical section CsActivityLogging.
  137. //*
  138. //* PARAMETERS:
  139. //* [IN ] PJOB_QUEUE lpJobQueue
  140. //* pointer to the job queue of the inbound job.
  141. //*
  142. //* [IN ] LPCFSPI_JOB_STATUS lpcFaxStatus
  143. //* The status of the recieved job.
  144. //*
  145. //*
  146. //* RETURN VALUE:
  147. //* TRUE
  148. //* If no error occured.
  149. //* FALSE
  150. //* If an error occured.
  151. //*********************************************************************************
  152. BOOL
  153. LogInboundActivity(
  154. PJOB_QUEUE lpJobQueue,
  155. LPCFSPI_JOB_STATUS lpcFaxStatus
  156. )
  157. {
  158. DWORD dwRes = ERROR_SUCCESS;
  159. DEBUG_FUNCTION_NAME(TEXT("LogInboundActivity"));
  160. wstring wstrText;
  161. DWORD dwBytesWritten;
  162. if (!g_ActivityLoggingConfig.bLogIncoming)
  163. {
  164. //
  165. // Inbound activity logging is disabled
  166. //
  167. return TRUE;
  168. }
  169. Assert (g_hInboxActivityLogFile != INVALID_HANDLE_VALUE);
  170. try
  171. {
  172. if (!GetInboundCommandText(lpJobQueue, lpcFaxStatus, wstrText))
  173. {
  174. DebugPrintEx(DEBUG_ERR,
  175. TEXT("GetInboundCommandText failed )"));
  176. dwRes = ERROR_OUTOFMEMORY;
  177. goto exit;
  178. }
  179. }
  180. catch (exception &ex)
  181. {
  182. dwRes = ERROR_OUTOFMEMORY;
  183. DebugPrintEx(
  184. DEBUG_ERR,
  185. TEXT("GetInboundCommandText caused exception (%S)"),
  186. ex.what());
  187. goto exit;
  188. }
  189. if (LogFileLimitReached(ACTIVITY_LOG_INBOX))
  190. {
  191. //
  192. // Time to take action and replace/remove the old log file
  193. //
  194. DebugPrintEx(DEBUG_MSG,
  195. TEXT("Inbox activity log file has reached it's limit. deleting/renaming the old file")
  196. );
  197. dwRes = LogFileLimitReachAction(ACTIVITY_LOG_INBOX);
  198. if (ERROR_SUCCESS != dwRes)
  199. {
  200. DebugPrintEx(DEBUG_ERR,
  201. TEXT("LogFileLimitReachAction for ACTIVITY_LOG_INBOX failed (ec: %ld). Inbound activity logging will halt"),
  202. dwRes
  203. );
  204. //
  205. // May happen if we couldn't create a new log file
  206. // CreateLogFile() disables logging on failure
  207. //
  208. if (!g_ActivityLoggingConfig.bLogIncoming ||
  209. g_hInboxActivityLogFile == INVALID_HANDLE_VALUE)
  210. {
  211. goto exit;
  212. }
  213. //
  214. // try to continue with the old log file
  215. //
  216. dwRes = ERROR_SUCCESS;
  217. }
  218. }
  219. if (!WriteFile( g_hInboxActivityLogFile,
  220. wstrText.c_str(),
  221. wstrText.length() * sizeof(WCHAR),
  222. &dwBytesWritten,
  223. NULL))
  224. {
  225. dwRes = GetLastError();
  226. DebugPrintEx(DEBUG_ERR,
  227. TEXT("WriteFile failed (ec: %ld)"),
  228. dwRes);
  229. goto exit;
  230. }
  231. Assert (ERROR_SUCCESS == dwRes);
  232. exit:
  233. if (ERROR_SUCCESS != dwRes)
  234. {
  235. SetLastError (dwRes);
  236. return FALSE;
  237. }
  238. return TRUE;
  239. } // LogInboundActivity
  240. //*********************************************************************************
  241. //* Name: LogOutboundActivity()
  242. //* Author: Oded Sacher
  243. //* Date: Oct 19, 1999
  244. //*********************************************************************************
  245. //* DESCRIPTION:
  246. //* Inserts new record into the Outbox Activity logging table.
  247. //* Must be called inside critical section CsActivityLogging..
  248. //*
  249. //* PARAMETERS:
  250. //* [IN ] PJOB_QUEUE lpJobQueue
  251. //* pointer to the job queue of the inbound job.
  252. //*
  253. //*
  254. //* RETURN VALUE:
  255. //* TRUE
  256. //* If no error occured.
  257. //* FALSE
  258. //* If an error occured.
  259. //*********************************************************************************
  260. BOOL
  261. LogOutboundActivity(
  262. PJOB_QUEUE lpJobQueue
  263. )
  264. {
  265. DWORD dwRes = ERROR_SUCCESS;
  266. DEBUG_FUNCTION_NAME(TEXT("LogOutboundActivity"));
  267. wstring wstrText;
  268. DWORD dwBytesWritten;
  269. if (!g_ActivityLoggingConfig.bLogOutgoing)
  270. {
  271. //
  272. // Outbound activity logging is disabled
  273. //
  274. return TRUE;
  275. }
  276. Assert (g_hOutboxActivityLogFile != INVALID_HANDLE_VALUE);
  277. try
  278. {
  279. if (!GetOutboundCommandText(lpJobQueue, wstrText))
  280. {
  281. DebugPrintEx(DEBUG_ERR,
  282. TEXT("GetOutboundCommandText failed )"));
  283. dwRes = ERROR_OUTOFMEMORY;
  284. goto exit;
  285. }
  286. }
  287. catch (exception &ex)
  288. {
  289. dwRes = ERROR_OUTOFMEMORY;
  290. DebugPrintEx(
  291. DEBUG_ERR,
  292. TEXT("GetOutboundCommandText caused exception (%S)"),
  293. ex.what());
  294. goto exit;
  295. }
  296. if (LogFileLimitReached(ACTIVITY_LOG_OUTBOX))
  297. {
  298. //
  299. // Time to take action and replace/remove the old log file
  300. //
  301. DebugPrintEx(DEBUG_MSG,
  302. TEXT("Outbox activity log file has reached it's limit. deleting/renaming the old file")
  303. );
  304. dwRes = LogFileLimitReachAction(ACTIVITY_LOG_OUTBOX);
  305. if (ERROR_SUCCESS != dwRes)
  306. {
  307. DebugPrintEx(DEBUG_ERR,
  308. TEXT("LogFileLimitReachAction for ACTIVITY_LOG_OUTBOX failed (ec: %ld)."),
  309. dwRes
  310. );
  311. //
  312. // May happen if we couldn't create a new log file
  313. // CreateLogFile() disables logging on failure
  314. //
  315. if (!g_ActivityLoggingConfig.bLogOutgoing ||
  316. g_hOutboxActivityLogFile == INVALID_HANDLE_VALUE)
  317. {
  318. goto exit;
  319. }
  320. //
  321. // try to continue with the old log file
  322. //
  323. dwRes = ERROR_SUCCESS;
  324. }
  325. }
  326. if (!WriteFile( g_hOutboxActivityLogFile,
  327. wstrText.c_str(),
  328. wstrText.length() * sizeof(WCHAR),
  329. &dwBytesWritten,
  330. NULL))
  331. {
  332. dwRes = GetLastError();
  333. DebugPrintEx(DEBUG_ERR,
  334. TEXT("WriteFile failed (ec: %ld)"),
  335. dwRes);
  336. goto exit;
  337. }
  338. Assert (ERROR_SUCCESS == dwRes);
  339. exit:
  340. if (ERROR_SUCCESS != dwRes)
  341. {
  342. SetLastError (dwRes);
  343. return FALSE;
  344. }
  345. return TRUE;
  346. } // LogOutboundActivity
  347. //*********************************************************************************
  348. //* Name: GetTableColumnsText()
  349. //* Author: Oded Sacher
  350. //* Date: Oct 19, 1999
  351. //*********************************************************************************
  352. //* DESCRIPTION:
  353. //* Retrieves the first row of the log file (column names).
  354. //*
  355. //* PARAMETERS:
  356. //* [IN] LPTSTR TableName
  357. //* Table name, can be Outbox or Inbox.
  358. //*
  359. //* [IN] wstring &wstrResult
  360. //* Output result string
  361. //*
  362. //* RETURN VALUE:
  363. //* None
  364. //*
  365. //* NOTE: The function might throw STL string exceptions.
  366. //*
  367. //*********************************************************************************
  368. static
  369. VOID
  370. GetTableColumnsText(
  371. LPTSTR ptszTableName,
  372. wstring &wstrResult
  373. ) throw (exception)
  374. {
  375. DEBUG_FUNCTION_NAME(TEXT("GetTableColumnsText"));
  376. PLOG_STRING_TABLE Table = NULL;
  377. DWORD Count = 0;
  378. if (!_tcscmp(ptszTableName, INBOX_TABLE))
  379. {
  380. Table = g_InboxTable;
  381. Count = gc_dwCountInboxTable;
  382. }
  383. else
  384. {
  385. Table = g_OutboxTable;
  386. Count = gc_dwCountOutboxTable;
  387. }
  388. Assert(Table);
  389. for (DWORD Index = 0; Index < Count; Index++)
  390. {
  391. wstrResult += TEXT("\"");
  392. wstrResult += Table[Index].String;
  393. wstrResult += TEXT("\"");
  394. if (Index < Count - 1)
  395. {
  396. wstrResult += TEXT("\t");
  397. }
  398. }
  399. wstrResult += TEXT("\r\n");
  400. DebugPrintEx(DEBUG_MSG,
  401. TEXT("First row (Columns names): %s"),
  402. wstrResult.c_str());
  403. } // GetTableColumnsText
  404. //*********************************************************************************
  405. //* Name: GetSchemaFileText()
  406. //* Author: Oded Sacher
  407. //* Date: Jul 25, 2000
  408. //*********************************************************************************
  409. //* DESCRIPTION:
  410. //* Retrieves the scema.ini text buffer.
  411. //*
  412. //* PARAMETERS:
  413. //* [IN] wstring &wstrRes
  414. //* Output result string
  415. //*
  416. //* RETURN VALUE:
  417. //* None.
  418. //*
  419. //* NOTE: The function might throw STL string exceptions.
  420. //*
  421. //*********************************************************************************
  422. static
  423. VOID
  424. GetSchemaFileText(wstring &wstrRes) throw (exception)
  425. {
  426. DEBUG_FUNCTION_NAME(TEXT("GetSchemaFileText"));
  427. DWORD Index;
  428. //
  429. // Inbox table
  430. //
  431. wstrRes += TEXT("[");
  432. wstrRes += ACTIVITY_LOG_INBOX_FILE;
  433. wstrRes += TEXT("]\r\n");
  434. wstrRes += TEXT("ColNameHeader=True\r\n");
  435. wstrRes += TEXT("Format=TabDelimited\r\n");
  436. wstrRes += TEXT("CharacterSet=1200\r\n");
  437. for (Index = 0; Index < gc_dwCountInboxTable; Index++)
  438. {
  439. TCHAR tszTemp[MAX_PATH * 2] = {0};
  440. if (0 == wcscmp(g_InboxTable[Index].Type, FIELD_TYPE_TEXT))
  441. {
  442. _snwprintf(tszTemp,
  443. ARR_SIZE(tszTemp)-1,
  444. TEXT("Col%ld=%s %s Width %ld\r\n"),
  445. Index + 1,
  446. g_InboxTable[Index].String,
  447. g_InboxTable[Index].Type,
  448. g_InboxTable[Index].Size);
  449. }
  450. else
  451. {
  452. _snwprintf(tszTemp,
  453. ARR_SIZE(tszTemp)-1,
  454. TEXT("Col%ld=%s %s\r\n"),
  455. Index + 1,
  456. g_InboxTable[Index].String,
  457. g_InboxTable[Index].Type);
  458. }
  459. wstrRes += tszTemp;
  460. }
  461. //
  462. // Outbox table
  463. //
  464. wstrRes += TEXT("[");
  465. wstrRes += ACTIVITY_LOG_OUTBOX_FILE;
  466. wstrRes += TEXT("]\r\n");
  467. wstrRes += TEXT("ColNameHeader=True\r\n");
  468. wstrRes += TEXT("Format=TabDelimited\r\n");
  469. wstrRes += TEXT("CharacterSet=1200\r\n");
  470. for (Index = 0; Index < gc_dwCountOutboxTable; Index++)
  471. {
  472. TCHAR tszTemp[MAX_PATH * 2] = {0};
  473. if (0 == wcscmp(g_OutboxTable[Index].Type, FIELD_TYPE_TEXT))
  474. {
  475. _snwprintf(tszTemp,
  476. ARR_SIZE(tszTemp)-1,
  477. TEXT("Col%ld=%s %s Width %ld\r\n"),
  478. Index + 1,
  479. g_OutboxTable[Index].String,
  480. g_OutboxTable[Index].Type,
  481. g_OutboxTable[Index].Size);
  482. }
  483. else
  484. {
  485. _snwprintf(tszTemp,
  486. ARR_SIZE(tszTemp)-1,
  487. TEXT("Col%ld=%s %s\r\n"),
  488. Index + 1,
  489. g_OutboxTable[Index].String,
  490. g_OutboxTable[Index].Type);
  491. }
  492. wstrRes += tszTemp;
  493. }
  494. } // GetSchemaFileText
  495. //*********************************************************************************
  496. //* Name: CreateLogDB()
  497. //* Author: Oded Sacher
  498. //* Date: Oct 19, 1999
  499. //*********************************************************************************
  500. //* DESCRIPTION:
  501. //* Creates the database files. Creates the Schema.ini file.
  502. //*
  503. //* PARAMETERS:
  504. //* [IN] LPCWSTR lpcwstrDBPath
  505. //* Pointer to a NULL terminated string contains the DB path.
  506. //* [OUT] LPHANDLE phInboxFile
  507. //* Adress of a variable to receive the inbox file handle.
  508. //* [OUT] LPHANDLE phOutboxFile
  509. //* Adress of a variable to receive the outbox file handle.
  510. //*
  511. //* RETURN VALUE:
  512. //* Win32 error Code
  513. //*********************************************************************************
  514. DWORD
  515. CreateLogDB (
  516. LPCWSTR lpcwstrDBPath,
  517. LPHANDLE phInboxFile,
  518. LPHANDLE phOutboxFile
  519. )
  520. {
  521. DEBUG_FUNCTION_NAME(TEXT("CreateLogDB"));
  522. DWORD dwRes = ERROR_SUCCESS;
  523. HANDLE hInboxFile = INVALID_HANDLE_VALUE;
  524. HANDLE hOutboxFile = INVALID_HANDLE_VALUE;
  525. HANDLE hSchemaFile = INVALID_HANDLE_VALUE;
  526. WCHAR wszFileName[MAX_PATH] = {0};
  527. DWORD dwBytesWritten;
  528. DWORD ec = ERROR_SUCCESS; // Used for Schema.ini
  529. wstring wstrSchema;
  530. INT iCount = 0;
  531. Assert (lpcwstrDBPath && phInboxFile && phOutboxFile);
  532. if (FALSE == g_fLogStringTableInit)
  533. {
  534. dwRes = InitializeLoggingStringTables();
  535. if (ERROR_SUCCESS != dwRes)
  536. {
  537. DebugPrintEx(DEBUG_ERR,
  538. TEXT("Close connection failed (hr: 0x%08x)"),
  539. dwRes);
  540. return dwRes;
  541. }
  542. g_fLogStringTableInit = TRUE;
  543. }
  544. dwRes = IsValidFaxFolder(lpcwstrDBPath);
  545. if (ERROR_SUCCESS != dwRes)
  546. {
  547. DebugPrintEx(DEBUG_ERR,
  548. TEXT("IsValidFaxFolder failed for folder : %s (ec=%lu)."),
  549. lpcwstrDBPath,
  550. dwRes);
  551. return dwRes;
  552. }
  553. //
  554. // Create the logging files
  555. //
  556. dwRes = CreateLogFile(ACTIVITY_LOG_INBOX,lpcwstrDBPath,&hInboxFile);
  557. if ( ERROR_SUCCESS != dwRes)
  558. {
  559. DebugPrintEx( DEBUG_ERR,
  560. TEXT("CreateLogFile() Failed, for Inbox file. (ec=%ld)"),
  561. dwRes
  562. );
  563. goto exit;
  564. }
  565. dwRes = CreateLogFile(ACTIVITY_LOG_OUTBOX,lpcwstrDBPath,&hOutboxFile);
  566. if ( ERROR_SUCCESS != dwRes)
  567. {
  568. DebugPrintEx( DEBUG_ERR,
  569. TEXT("CreateLogFile() Failed, for Outbox file. (ec=%ld)"),
  570. dwRes
  571. );
  572. goto exit;
  573. }
  574. *phInboxFile = hInboxFile;
  575. *phOutboxFile= hOutboxFile;
  576. Assert (ERROR_SUCCESS == dwRes && ERROR_SUCCESS == ec);
  577. //
  578. // Create the Schema.ini file - Function do not fail if not succeeded
  579. //
  580. iCount = _snwprintf (wszFileName,
  581. MAX_PATH - 1,
  582. TEXT("%s\\%s"),
  583. lpcwstrDBPath,
  584. TEXT("schema.ini"));
  585. if (0 > iCount)
  586. {
  587. //
  588. // path and file name exceeds MAX_PATH
  589. //
  590. DebugPrintEx(
  591. DEBUG_ERR,
  592. TEXT("_snwprintf Failed, File name bigger than MAX_PATH"));
  593. ec = ERROR_BUFFER_OVERFLOW;
  594. goto exit;
  595. }
  596. hSchemaFile = SafeCreateFile(
  597. wszFileName, // file name
  598. GENERIC_WRITE, // access mode
  599. 0, // share mode
  600. NULL, // SD
  601. CREATE_ALWAYS, // how to create
  602. FILE_ATTRIBUTE_NORMAL, // file attributes
  603. NULL);
  604. if (INVALID_HANDLE_VALUE == hSchemaFile)
  605. {
  606. ec = GetLastError();
  607. DebugPrintEx(DEBUG_ERR,
  608. TEXT("CreateFile failed (ec: %ld)"),
  609. ec);
  610. goto exit;
  611. }
  612. try
  613. {
  614. GetSchemaFileText(wstrSchema);
  615. }
  616. catch (exception &ex)
  617. {
  618. dwRes = ERROR_OUTOFMEMORY;
  619. DebugPrintEx(
  620. DEBUG_ERR,
  621. TEXT("GetSchemaFileText caused exception (%S)"),
  622. ex.what());
  623. goto exit;
  624. }
  625. if (!WriteFile( hSchemaFile,
  626. wstrSchema.c_str(),
  627. wstrSchema.length() * sizeof(WCHAR),
  628. &dwBytesWritten,
  629. NULL))
  630. {
  631. ec = GetLastError();
  632. DebugPrintEx(DEBUG_ERR,
  633. TEXT("WriteFile failed (ec: %ld)"),
  634. ec);
  635. goto exit;
  636. }
  637. Assert (ERROR_SUCCESS == dwRes && ERROR_SUCCESS == ec);
  638. exit:
  639. if (ERROR_SUCCESS != dwRes)
  640. {
  641. if (INVALID_HANDLE_VALUE != hOutboxFile)
  642. {
  643. if (!CloseHandle (hOutboxFile))
  644. {
  645. DebugPrintEx(DEBUG_ERR,
  646. TEXT("CloseHandle failed (ec: %ld)"),
  647. GetLastError());
  648. }
  649. }
  650. if (INVALID_HANDLE_VALUE != hInboxFile)
  651. {
  652. if (!CloseHandle (hInboxFile))
  653. {
  654. DebugPrintEx(DEBUG_ERR,
  655. TEXT("CloseHandle failed (ec: %ld)"),
  656. GetLastError());
  657. }
  658. }
  659. }
  660. if (INVALID_HANDLE_VALUE != hSchemaFile)
  661. {
  662. if (!CloseHandle (hSchemaFile))
  663. {
  664. DebugPrintEx(DEBUG_ERR,
  665. TEXT("CloseHandle failed (ec: %ld)"),
  666. GetLastError());
  667. }
  668. }
  669. if (ERROR_SUCCESS != ec)
  670. {
  671. FaxLog(
  672. FAXLOG_CATEGORY_INIT,
  673. FAXLOG_LEVEL_MED,
  674. 2,
  675. MSG_FAX_ACTIVITY_LOG_FAILED_SCHEMA,
  676. wszFileName,
  677. DWORD2DECIMAL(ec)
  678. );
  679. }
  680. return dwRes;
  681. } // CreateLogDB
  682. //*********************************************************************************
  683. //* Name: InitializeLogging()
  684. //* Author: Oded Sacher
  685. //* Date: Jun 26, 2000
  686. //*********************************************************************************
  687. //* DESCRIPTION:
  688. //* Initializes the Activity Logging. Opens the files.
  689. //*
  690. //*
  691. //* PARAMETERS: None
  692. //*
  693. //* RETURN VALUE:
  694. //* Win32 error code.
  695. //*********************************************************************************
  696. DWORD
  697. InitializeLogging(
  698. VOID
  699. )
  700. {
  701. DWORD dwRes = ERROR_SUCCESS;
  702. DEBUG_FUNCTION_NAME(TEXT("InitializeLogging"));
  703. if (!g_ActivityLoggingConfig.lptstrDBPath)
  704. {
  705. //
  706. // Activity logging is off
  707. //
  708. return ERROR_SUCCESS;
  709. }
  710. EnterCriticalSection (&g_CsInboundActivityLogging);
  711. EnterCriticalSection (&g_CsOutboundActivityLogging);
  712. Assert ( (INVALID_HANDLE_VALUE == g_hInboxActivityLogFile) &&
  713. (INVALID_HANDLE_VALUE == g_hOutboxActivityLogFile) );
  714. //
  715. // Create the logging files
  716. //
  717. dwRes = CreateLogDB (g_ActivityLoggingConfig.lptstrDBPath,
  718. &g_hInboxActivityLogFile,
  719. &g_hOutboxActivityLogFile);
  720. if (ERROR_SUCCESS != dwRes)
  721. {
  722. DebugPrintEx(DEBUG_ERR,
  723. TEXT("CreateLogDB failed (hr: 0x%08x)"),
  724. dwRes);
  725. goto exit;
  726. }
  727. Assert (ERROR_SUCCESS == dwRes);
  728. exit:
  729. LeaveCriticalSection (&g_CsOutboundActivityLogging);
  730. LeaveCriticalSection (&g_CsInboundActivityLogging);
  731. return dwRes;
  732. }
  733. //*********************************************************************************
  734. //* Name: GetInboundCommandText()
  735. //* Author: Oded Sacher
  736. //* Date: Oct 19, 1999
  737. //*********************************************************************************
  738. //* DESCRIPTION:
  739. //* Retrieves a buffer with the new inbound record.
  740. //* The function allocates the memory for the string that will contain the record.
  741. //*
  742. //* PARAMETERS:
  743. //* [IN ] PJOB_QUEUE lpJobQueue
  744. //* pointer to the job queue of the inbound job.
  745. //*
  746. //* [IN ] LPCFSPI_JOB_STATUS lpcFaxStatus
  747. //* The status of the recieved job.
  748. //*
  749. //* [OUT] wstring &wstrCommandText
  750. //* String to compose
  751. //*
  752. //* RETURN VALUE:
  753. //* TRUE
  754. //* If no error occured.
  755. //* FALSE
  756. //* If an error occured.
  757. //*
  758. //* NOTE: The function might throw STL string exceptions.
  759. //*
  760. //*********************************************************************************
  761. static
  762. BOOL
  763. GetInboundCommandText(
  764. PJOB_QUEUE lpJobQueue,
  765. LPCFSPI_JOB_STATUS lpcFaxStatus,
  766. wstring &wstrCommandText
  767. ) throw (exception)
  768. {
  769. DEBUG_FUNCTION_NAME(TEXT("GetInboundCommandText"));
  770. BOOL bStartTime;
  771. BOOL bEndTime;
  772. SYSTEMTIME tmStart;
  773. SYSTEMTIME tmEnd;
  774. HINSTANCE hLoadInstance = NULL;
  775. Assert (lpJobQueue->JobEntry);
  776. Assert (lpJobQueue->JobEntry->LineInfo);
  777. bStartTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_START, &tmStart);
  778. if (bStartTime == FALSE)
  779. {
  780. DebugPrintEx( DEBUG_ERR,
  781. TEXT("GetRealFaxTimeAsSystemTime (Start time) Failed (ec: %ld)"),
  782. GetLastError());
  783. }
  784. bEndTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_END, &tmEnd);
  785. if (bEndTime == FALSE)
  786. {
  787. DebugPrintEx( DEBUG_ERR,
  788. TEXT("GetRealFaxTimeAsSystemTime (End time) Failed (ec: %ld)"),
  789. GetLastError());
  790. }
  791. //
  792. // Status
  793. //
  794. wstrCommandText += TEXT("\"");
  795. switch (lpcFaxStatus->dwJobStatus)
  796. {
  797. case FSPI_JS_FAILED:
  798. wstrCommandText += FilteredLogString(GetString(IDS_FAILED_RECEIVE));
  799. break;
  800. case FSPI_JS_COMPLETED:
  801. wstrCommandText += FilteredLogString(GetString(FPS_COMPLETED));
  802. break;
  803. case FSPI_JS_ABORTED:
  804. wstrCommandText += FilteredLogString(GetString(IDS_CANCELED));
  805. break;
  806. default:
  807. ASSERT_FALSE;
  808. }
  809. wstrCommandText += TEXT("\"\t\"");
  810. //
  811. // ErrorDesc
  812. //
  813. wstring wstrErr;
  814. if (lstrlen(lpJobQueue->JobEntry->ExStatusString))
  815. {
  816. //
  817. // The FSP provided extended status string
  818. //
  819. wstrErr = lpJobQueue->JobEntry->ExStatusString;
  820. }
  821. else if (lpcFaxStatus->dwExtendedStatus == 0)
  822. {
  823. //
  824. // No extended status
  825. //
  826. wstrErr = TEXT(" ");
  827. }
  828. else
  829. {
  830. //
  831. // Well known extended status
  832. //
  833. LPTSTR ResStr = MapFSPIJobExtendedStatusToString(lpcFaxStatus->dwExtendedStatus);
  834. if (NULL == ResStr)
  835. {
  836. ASSERT_FALSE;
  837. wstrErr = TEXT(" ");
  838. DebugPrintEx(
  839. DEBUG_ERR,
  840. TEXT("Unexpected extended status. Extended Status: %ld, Provider: %s"),
  841. lpcFaxStatus->dwExtendedStatus,
  842. lpJobQueue->JobEntry->LineInfo->Provider->ImageName);
  843. }
  844. else
  845. {
  846. if (FSPI_ES_PARTIALLY_RECEIVED == lpcFaxStatus->dwExtendedStatus && // This is a partially received fax
  847. lstrlen(lpJobQueue->ExStatusString)) // The original extended status string is not empty)
  848. {
  849. //
  850. // copy both the partially received and original extended status strings
  851. //
  852. wstrErr = ResStr;
  853. wstrErr += TEXT(" - ");
  854. wstrErr += lpJobQueue->ExStatusString;
  855. }
  856. else
  857. {
  858. //
  859. // Copy just the extended status string
  860. //
  861. wstrErr = ResStr;
  862. }
  863. }
  864. }
  865. wstrCommandText += FilteredLogString(wstrErr.c_str());
  866. wstrCommandText += TEXT("\"\t\"");
  867. //
  868. // Error Code
  869. //
  870. if (lpcFaxStatus->dwExtendedStatus == 0)
  871. {
  872. wstrErr = TEXT(" ");
  873. }
  874. else
  875. {
  876. TCHAR tszHexNum [40];
  877. swprintf(tszHexNum, TEXT("0x%08x"), lpcFaxStatus->dwExtendedStatus);
  878. wstrErr = tszHexNum;
  879. }
  880. wstrCommandText += wstrErr;
  881. wstrCommandText += TEXT("\"\t");
  882. //
  883. // StartTime
  884. //
  885. if (bStartTime)
  886. {
  887. wstring wstrTime;
  888. if (!GetFaxTimeAsString (&tmStart, wstrTime))
  889. {
  890. DebugPrintEx(
  891. DEBUG_ERR,
  892. TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
  893. GetLastError());
  894. return FALSE;
  895. }
  896. wstrCommandText += FilteredLogString(wstrTime.c_str());
  897. }
  898. wstrCommandText += TEXT("\t");
  899. //
  900. // EndTime
  901. //
  902. if (bEndTime)
  903. {
  904. wstring wstrTime;
  905. if (!GetFaxTimeAsString (&tmEnd, wstrTime))
  906. {
  907. DebugPrintEx(
  908. DEBUG_ERR,
  909. TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
  910. GetLastError());
  911. return FALSE;
  912. }
  913. wstrCommandText += FilteredLogString(wstrTime.c_str());
  914. }
  915. wstrCommandText += TEXT("\t\"");
  916. //
  917. // Device
  918. //
  919. wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->DeviceName);
  920. wstrCommandText += TEXT("\"\t\"");
  921. //
  922. // File name
  923. //
  924. wstrCommandText += FilteredLogString(lpJobQueue->FileName);
  925. wstrCommandText += TEXT("\"\t");
  926. //
  927. // File size
  928. //
  929. TCHAR tszSize[40];
  930. swprintf(tszSize,TEXT("%ld"), lpJobQueue->FileSize);
  931. wstrCommandText += tszSize;
  932. wstrCommandText += TEXT("\t\"");
  933. //
  934. // CSID
  935. //
  936. wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->Csid);
  937. wstrCommandText += TEXT("\"\t\"");
  938. //
  939. // TSID
  940. //
  941. wstrCommandText += FilteredLogString(lpcFaxStatus->lpwstrRemoteStationId);
  942. wstrCommandText += TEXT("\"\t\"");
  943. //
  944. // Caller ID
  945. //
  946. wstrCommandText += FilteredLogString(lpcFaxStatus->lpwstrCallerId);
  947. wstrCommandText += TEXT("\"\t\"");
  948. //
  949. // Routing information
  950. //
  951. wstrCommandText += FilteredLogString(lpcFaxStatus->lpwstrRoutingInfo);
  952. wstrCommandText += TEXT("\"\t");
  953. //
  954. // Pages
  955. //
  956. TCHAR tszPages[40];
  957. swprintf(tszPages,TEXT("%ld"),lpcFaxStatus->dwPageCount);
  958. wstrCommandText += tszPages;
  959. wstrCommandText += TEXT("\r\n");
  960. DebugPrintEx(DEBUG_MSG,
  961. TEXT("Inbound SQL statement: %s"),
  962. wstrCommandText.c_str());
  963. return TRUE;
  964. } // GetInboundCommandText
  965. //*********************************************************************************
  966. //* Name: GetOutboundCommandText()
  967. //* Author: Oded Sacher
  968. //* Date: Oct 19, 1999
  969. //*********************************************************************************
  970. //* DESCRIPTION:
  971. //* Retrieves a buffer that contains the new outbound record.
  972. //* The function allocates the memory for the buffer that will contain the new record.
  973. //*
  974. //* PARAMETERS:
  975. //* [IN ] PJOB_QUEUE lpJobQueue
  976. //* pointer to the job queue of the inbound job.
  977. //*
  978. //* [OUT] wstring &wstrCommandText
  979. //* String to compose
  980. //*
  981. //* RETURN VALUE:
  982. //* TRUE
  983. //* If no error occured.
  984. //* FALSE
  985. //* If an error occured.
  986. //*
  987. //* NOTE: The function might throw STL string exceptions.
  988. //*
  989. //*********************************************************************************
  990. static
  991. BOOL
  992. GetOutboundCommandText(
  993. PJOB_QUEUE lpJobQueue,
  994. wstring &wstrCommandText
  995. ) throw (exception)
  996. {
  997. DEBUG_FUNCTION_NAME(TEXT("GetOutboundCommandText"));
  998. BOOL bStartTime;
  999. BOOL bEndTime;
  1000. BOOL bOriginalTime;
  1001. BOOL bSubmissionTime;
  1002. SYSTEMTIME tmStart;
  1003. SYSTEMTIME tmEnd;
  1004. SYSTEMTIME tmOriginal;
  1005. SYSTEMTIME tmSubmission;
  1006. HINSTANCE hLoadInstance = NULL;
  1007. Assert (lpJobQueue->lpParentJob->SubmissionTime);
  1008. Assert (lpJobQueue->lpParentJob->OriginalScheduleTime);
  1009. bSubmissionTime = FileTimeToSystemTime ((FILETIME*)&(lpJobQueue->lpParentJob->SubmissionTime), &tmSubmission);
  1010. if (bSubmissionTime == FALSE)
  1011. {
  1012. DebugPrintEx( DEBUG_ERR,
  1013. TEXT("FileTimeToSystemTime (Submission time) Failed (ec: %ld)"),
  1014. GetLastError());
  1015. }
  1016. bOriginalTime = FileTimeToSystemTime ((FILETIME*)&(lpJobQueue->lpParentJob->SubmissionTime), &tmOriginal);
  1017. if (bOriginalTime == FALSE)
  1018. {
  1019. DebugPrintEx( DEBUG_ERR,
  1020. TEXT("FileTimeToSystemTime (Original schduled time) Failed (ec: %ld)"),
  1021. GetLastError());
  1022. }
  1023. if (NULL != lpJobQueue->JobEntry)
  1024. {
  1025. bStartTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_START, &tmStart);
  1026. if (bStartTime == FALSE)
  1027. {
  1028. DebugPrintEx( DEBUG_ERR,
  1029. TEXT("GetRealFaxTimeAsSystemTime (Start time) Failed (ec: %ld)"),
  1030. GetLastError());
  1031. }
  1032. bEndTime = GetRealFaxTimeAsSystemTime (lpJobQueue->JobEntry, FAX_TIME_TYPE_END, &tmEnd);
  1033. if (bEndTime == FALSE)
  1034. {
  1035. DebugPrintEx( DEBUG_ERR,
  1036. TEXT("GetRealFaxTimeAsSystemTime (End time) Failed (ec: %ld)"),
  1037. GetLastError());
  1038. }
  1039. }
  1040. //
  1041. // JobID
  1042. //
  1043. TCHAR tszTemp[100];
  1044. swprintf(tszTemp,TEXT("0x%016I64x"), lpJobQueue->UniqueId);
  1045. wstrCommandText += TEXT("\"");
  1046. wstrCommandText += tszTemp;
  1047. wstrCommandText += TEXT("\"\t\"");
  1048. //
  1049. // Parent JobID
  1050. //
  1051. swprintf(tszTemp,TEXT("0x%016I64x"), lpJobQueue->lpParentJob->UniqueId);
  1052. wstrCommandText += tszTemp;
  1053. wstrCommandText += TEXT("\"\t");
  1054. //
  1055. // Submition time
  1056. //
  1057. if (bSubmissionTime)
  1058. {
  1059. wstring wstrTime;
  1060. if (!GetFaxTimeAsString (&tmSubmission, wstrTime))
  1061. {
  1062. DebugPrintEx(
  1063. DEBUG_ERR,
  1064. TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
  1065. GetLastError());
  1066. return FALSE;
  1067. }
  1068. wstrCommandText += FilteredLogString(wstrTime.c_str());
  1069. }
  1070. wstrCommandText += TEXT("\t");
  1071. //
  1072. // Originaly scheduled time
  1073. //
  1074. if (bOriginalTime)
  1075. {
  1076. wstring wstrTime;
  1077. if (!GetFaxTimeAsString (&tmOriginal, wstrTime))
  1078. {
  1079. DebugPrintEx(
  1080. DEBUG_ERR,
  1081. TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
  1082. GetLastError());
  1083. return FALSE;
  1084. }
  1085. wstrCommandText += FilteredLogString(wstrTime.c_str());
  1086. }
  1087. wstrCommandText += TEXT("\t\"");
  1088. //
  1089. // Status
  1090. //
  1091. if (JS_CANCELED == lpJobQueue->JobStatus)
  1092. {
  1093. wstrCommandText += FilteredLogString(GetString(IDS_CANCELED));
  1094. wstrCommandText += TEXT("\"\t\"");
  1095. //
  1096. // Fill the empty columns with NULL information
  1097. //
  1098. wstrCommandText += TEXT("\"\t\""); // ErrorDesc
  1099. wstrCommandText += TEXT("\"\t"); // Error Code
  1100. wstrCommandText += TEXT("\t"); // StartTime
  1101. wstrCommandText += TEXT("\t\""); // EndTime
  1102. wstrCommandText += TEXT("\"\t\""); // Device
  1103. wstrCommandText += TEXT("\"\t\""); // DialedNumber
  1104. wstrCommandText += TEXT("\"\t\""); // CSID
  1105. wstrCommandText += TEXT("\"\t"); // TSID
  1106. wstrCommandText += TEXT("\t"); // Pages
  1107. }
  1108. else
  1109. {
  1110. // Completed/Failed/Aborted jobs only
  1111. Assert (lpJobQueue->JobEntry);
  1112. Assert (lpJobQueue->JobEntry->LineInfo);
  1113. switch (lpJobQueue->JobEntry->FSPIJobStatus.dwJobStatus)
  1114. {
  1115. case FSPI_JS_FAILED:
  1116. case FSPI_JS_FAILED_NO_RETRY:
  1117. case FSPI_JS_DELETED:
  1118. wstrCommandText += FilteredLogString(GetString(IDS_FAILED_SEND));
  1119. break;
  1120. case FSPI_JS_COMPLETED :
  1121. wstrCommandText += FilteredLogString(GetString(FPS_COMPLETED));
  1122. break;
  1123. case FSPI_JS_ABORTED :
  1124. wstrCommandText += FilteredLogString(GetString(IDS_CANCELED));
  1125. break;
  1126. default:
  1127. DebugPrintEx(
  1128. DEBUG_ERR,
  1129. TEXT("Invalid FSPI_JS status: 0x%08X for JobId: %ld"),
  1130. lpJobQueue->JobStatus,
  1131. lpJobQueue->JobId);
  1132. Assert(FSPI_JS_DELETED == lpJobQueue->JobEntry->FSPIJobStatus.dwJobStatus); // ASSERT_FALSE
  1133. }
  1134. wstrCommandText += TEXT("\"\t\"");
  1135. //
  1136. // ErrorDesc
  1137. //
  1138. wstring wstrErr;
  1139. if (lstrlen(lpJobQueue->JobEntry->ExStatusString))
  1140. {
  1141. //
  1142. // The FSP provided extended status string
  1143. //
  1144. wstrErr = lpJobQueue->JobEntry->ExStatusString;
  1145. }
  1146. else if (lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus == 0)
  1147. {
  1148. //
  1149. // No extended status
  1150. //
  1151. wstrErr = TEXT(" ");
  1152. }
  1153. else
  1154. {
  1155. //
  1156. // Well known extended status
  1157. //
  1158. LPTSTR ResStr = MapFSPIJobExtendedStatusToString(lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus);
  1159. if (NULL == ResStr)
  1160. {
  1161. ASSERT_FALSE;
  1162. wstrErr = TEXT(" ");
  1163. DebugPrintEx(
  1164. DEBUG_ERR,
  1165. TEXT("Unexpected extended status. Extended Status: %ld, Provider: %s"),
  1166. lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus,
  1167. lpJobQueue->JobEntry->LineInfo->Provider->ImageName);
  1168. }
  1169. else
  1170. {
  1171. wstrErr = ResStr;
  1172. }
  1173. }
  1174. wstrCommandText += FilteredLogString(wstrErr.c_str());
  1175. wstrCommandText += TEXT("\"\t\"");
  1176. //
  1177. // Error Code
  1178. //
  1179. if (lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus == 0)
  1180. {
  1181. wstrErr = TEXT(" ");
  1182. }
  1183. else
  1184. {
  1185. swprintf(tszTemp, TEXT("0x%08x"), lpJobQueue->JobEntry->FSPIJobStatus.dwExtendedStatus);
  1186. wstrErr = tszTemp;
  1187. }
  1188. wstrCommandText += wstrErr;
  1189. wstrCommandText += TEXT("\"\t");
  1190. //
  1191. // StartTime
  1192. //
  1193. if (bStartTime)
  1194. {
  1195. wstring wstrTime;
  1196. if (!GetFaxTimeAsString (&tmStart, wstrTime))
  1197. {
  1198. DebugPrintEx(
  1199. DEBUG_ERR,
  1200. TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
  1201. GetLastError());
  1202. return FALSE;
  1203. }
  1204. wstrCommandText += FilteredLogString(wstrTime.c_str());
  1205. }
  1206. wstrCommandText += TEXT("\t");
  1207. //
  1208. // EndTime
  1209. //
  1210. if (bEndTime)
  1211. {
  1212. wstring wstrTime;
  1213. if (!GetFaxTimeAsString (&tmEnd, wstrTime))
  1214. {
  1215. DebugPrintEx(
  1216. DEBUG_ERR,
  1217. TEXT("GetFaxTimeAsString Failed (ec: %ld)"),
  1218. GetLastError());
  1219. return FALSE;
  1220. }
  1221. wstrCommandText += FilteredLogString(wstrTime.c_str());
  1222. }
  1223. wstrCommandText += TEXT("\t\"");
  1224. //
  1225. // Device
  1226. //
  1227. wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->DeviceName);
  1228. wstrCommandText += TEXT("\"\t\"");
  1229. //
  1230. // DialedNumber
  1231. //
  1232. if (wcslen (lpJobQueue->JobEntry->DisplayablePhoneNumber))
  1233. {
  1234. // The canonical number was translated to displayable number
  1235. wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->DisplayablePhoneNumber);
  1236. }
  1237. else
  1238. {
  1239. // The canonical number was not translated
  1240. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrFaxNumber);
  1241. }
  1242. wstrCommandText += TEXT("\"\t\"");
  1243. //
  1244. // CSID
  1245. //
  1246. wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->FSPIJobStatus.lpwstrRemoteStationId);
  1247. wstrCommandText += TEXT("\"\t\"");
  1248. //
  1249. // TSID
  1250. //
  1251. wstrCommandText += FilteredLogString(lpJobQueue->JobEntry->LineInfo->Tsid);
  1252. wstrCommandText += TEXT("\"\t");
  1253. //
  1254. // Pages
  1255. //
  1256. swprintf(tszTemp, TEXT("%ld"),lpJobQueue->JobEntry->FSPIJobStatus.dwPageCount);
  1257. wstrCommandText += tszTemp;
  1258. wstrCommandText += TEXT("\t");
  1259. }
  1260. // Common for Canceled and Failed/Completed/Aborted Jobs
  1261. //
  1262. // Total pages
  1263. //
  1264. swprintf(tszTemp, TEXT("%ld"),lpJobQueue->lpParentJob->PageCount);
  1265. wstrCommandText += tszTemp;
  1266. wstrCommandText += TEXT("\t\"");
  1267. //
  1268. // Queue file name
  1269. //
  1270. wstrCommandText += FilteredLogString(lpJobQueue->QueueFileName);
  1271. wstrCommandText += TEXT("\"\t\"");
  1272. //
  1273. // Document
  1274. //
  1275. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->JobParamsEx.lptstrDocumentName);
  1276. wstrCommandText += TEXT("\"\t");
  1277. //
  1278. // File size
  1279. //
  1280. swprintf(tszTemp, TEXT("%ld"), lpJobQueue->lpParentJob->FileSize);
  1281. wstrCommandText += tszTemp;
  1282. wstrCommandText += TEXT("\t");
  1283. //
  1284. // Retries
  1285. //
  1286. swprintf(tszTemp, TEXT("%d"), lpJobQueue->SendRetries);
  1287. wstrCommandText += tszTemp;
  1288. wstrCommandText += TEXT("\t\"");
  1289. //
  1290. // ServerCoverPage
  1291. //
  1292. if (lpJobQueue->lpParentJob->CoverPageEx.bServerBased == TRUE)
  1293. {
  1294. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->CoverPageEx.lptstrCoverPageFileName);
  1295. }
  1296. else
  1297. {
  1298. wstrCommandText += TEXT(" ");
  1299. }
  1300. wstrCommandText += TEXT("\"\t\"");
  1301. //
  1302. // Cover page subject
  1303. //
  1304. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->CoverPageEx.lptstrSubject);
  1305. wstrCommandText += TEXT("\"\t\"");
  1306. //
  1307. // Cover page note
  1308. //
  1309. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->CoverPageEx.lptstrNote);
  1310. wstrCommandText += TEXT("\"\t\"");
  1311. //
  1312. // User Name
  1313. //
  1314. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->UserName);
  1315. wstrCommandText += TEXT("\"\t\"");
  1316. //
  1317. // Sender Name
  1318. //
  1319. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrName);
  1320. wstrCommandText += TEXT("\"\t\"");
  1321. //
  1322. // Sender FaxNumber
  1323. //
  1324. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrFaxNumber);
  1325. wstrCommandText += TEXT("\"\t\"");
  1326. //
  1327. // Sender Company
  1328. //
  1329. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrCompany);
  1330. wstrCommandText += TEXT("\"\t\"");
  1331. //
  1332. // Sender Street
  1333. //
  1334. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrStreetAddress);
  1335. wstrCommandText += TEXT("\"\t\"");
  1336. //
  1337. // Sender City
  1338. //
  1339. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrCity);
  1340. wstrCommandText += TEXT("\"\t\"");
  1341. //
  1342. // Sender ZipCode
  1343. //
  1344. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrZip);
  1345. wstrCommandText += TEXT("\"\t\"");
  1346. //
  1347. // Sender Country
  1348. //
  1349. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrCountry);
  1350. wstrCommandText += TEXT("\"\t\"");
  1351. //
  1352. // Sender Title
  1353. //
  1354. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrTitle);
  1355. wstrCommandText += TEXT("\"\t\"");
  1356. //
  1357. // Sender Department
  1358. //
  1359. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrDepartment);
  1360. wstrCommandText += TEXT("\"\t\"");
  1361. //
  1362. // Sender Office
  1363. //
  1364. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrOfficeLocation);
  1365. wstrCommandText += TEXT("\"\t\"");
  1366. //
  1367. // Sender HomePhone
  1368. //
  1369. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrHomePhone);
  1370. wstrCommandText += TEXT("\"\t\"");
  1371. //
  1372. // Sender OfficePhone
  1373. //
  1374. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrOfficePhone);
  1375. wstrCommandText += TEXT("\"\t\"");
  1376. //
  1377. // Sender EMail
  1378. //
  1379. wstrCommandText += FilteredLogString(lpJobQueue->lpParentJob->SenderProfile.lptstrEmail);
  1380. wstrCommandText += TEXT("\"\t\"");
  1381. //
  1382. // Recipient Name
  1383. //
  1384. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrName);
  1385. wstrCommandText += TEXT("\"\t\"");
  1386. //
  1387. // Recipient FaxNumber
  1388. //
  1389. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrFaxNumber);
  1390. wstrCommandText += TEXT("\"\t\"");
  1391. //
  1392. // Recipient Company
  1393. //
  1394. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrCompany);
  1395. wstrCommandText += TEXT("\"\t\"");
  1396. //
  1397. // Recipient Street
  1398. //
  1399. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrStreetAddress);
  1400. wstrCommandText += TEXT("\"\t\"");
  1401. //
  1402. // Recipient City
  1403. //
  1404. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrCity);
  1405. wstrCommandText += TEXT("\"\t\"");
  1406. //
  1407. // Recipient ZipCode
  1408. //
  1409. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrZip);
  1410. wstrCommandText += TEXT("\"\t\"");
  1411. //
  1412. // Recipient Country
  1413. //
  1414. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrCountry);
  1415. wstrCommandText += TEXT("\"\t\"");
  1416. //
  1417. // Recipient Title
  1418. //
  1419. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrTitle);
  1420. wstrCommandText += TEXT("\"\t\"");
  1421. //
  1422. // Recipient Department
  1423. //
  1424. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrDepartment);
  1425. wstrCommandText += TEXT("\"\t\"");
  1426. //
  1427. // Recipient Office
  1428. //
  1429. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrOfficeLocation);
  1430. wstrCommandText += TEXT("\"\t\"");
  1431. //
  1432. // Recipient HomePhone
  1433. //
  1434. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrHomePhone);
  1435. wstrCommandText += TEXT("\"\t\"");
  1436. //
  1437. // Recipient OfficePhone
  1438. //
  1439. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrOfficePhone);
  1440. wstrCommandText += TEXT("\"\t\"");
  1441. //
  1442. // Recipient EMail
  1443. //
  1444. wstrCommandText += FilteredLogString(lpJobQueue->RecipientProfile.lptstrEmail);
  1445. wstrCommandText += TEXT("\"\t\"");
  1446. //
  1447. // BillingCode
  1448. //
  1449. wstrCommandText += FilteredLogString(lpJobQueue->SenderProfile.lptstrBillingCode);
  1450. wstrCommandText += TEXT("\"\r\n");
  1451. DebugPrintEx(DEBUG_MSG,
  1452. TEXT("Outboun SQL statement: %s"),
  1453. wstrCommandText.c_str());
  1454. return TRUE;
  1455. } // GetOutboundCommandText
  1456. //*********************************************************************************
  1457. //* Name: InitializeLoggingStringTables()
  1458. //* Author: Oded Sacher
  1459. //* Date: Oct 19, 1999
  1460. //*********************************************************************************
  1461. //* DESCRIPTION:
  1462. //* Initializes the Activity Logging string tables (Inbox and Outbox)
  1463. //*
  1464. //*
  1465. //* PARAMETERS: None
  1466. //*
  1467. //* RETURN VALUE:
  1468. //* Win32 error code.
  1469. //*********************************************************************************
  1470. DWORD
  1471. InitializeLoggingStringTables(
  1472. VOID
  1473. )
  1474. {
  1475. DWORD i;
  1476. DWORD err = ERROR_SUCCESS;
  1477. HINSTANCE hInstance;
  1478. TCHAR Buffer[MAX_PATH];
  1479. DEBUG_FUNCTION_NAME(TEXT("InitializeLoggingStringTables"));
  1480. hInstance = GetResInstance(NULL);
  1481. if(!hInstance)
  1482. {
  1483. return GetLastError();
  1484. }
  1485. for (i=0; i<gc_dwCountInboxTable; i++)
  1486. {
  1487. if (LoadString(hInstance,
  1488. g_InboxTable[i].FieldStringResourceId,
  1489. Buffer,
  1490. sizeof(Buffer)/sizeof(TCHAR)))
  1491. {
  1492. g_InboxTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) );
  1493. if (!g_InboxTable[i].String)
  1494. {
  1495. DebugPrintEx(DEBUG_ERR,
  1496. TEXT("Failed to allocate memory"));
  1497. err = ERROR_OUTOFMEMORY;
  1498. goto CleanUp;
  1499. }
  1500. else
  1501. {
  1502. _tcscpy( g_InboxTable[i].String, Buffer );
  1503. }
  1504. }
  1505. else
  1506. {
  1507. err = GetLastError();
  1508. DebugPrintEx(DEBUG_ERR,
  1509. TEXT("LoadString failed, Code:%d"),err);
  1510. goto CleanUp;
  1511. }
  1512. }
  1513. for (i=0; i<gc_dwCountOutboxTable; i++)
  1514. {
  1515. if (LoadString(hInstance,
  1516. g_OutboxTable[i].FieldStringResourceId,
  1517. Buffer,
  1518. sizeof(Buffer)/sizeof(TCHAR)))
  1519. {
  1520. g_OutboxTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) );
  1521. if (!g_OutboxTable[i].String)
  1522. {
  1523. DebugPrintEx(DEBUG_ERR,
  1524. TEXT("Failed to allocate memory"));
  1525. err = ERROR_OUTOFMEMORY;
  1526. goto CleanUp;
  1527. }
  1528. else
  1529. {
  1530. _tcscpy( g_OutboxTable[i].String, Buffer );
  1531. }
  1532. }
  1533. else
  1534. {
  1535. err = GetLastError();
  1536. DebugPrintEx(DEBUG_ERR,
  1537. TEXT("LoadString failed, Code:%d"),err);
  1538. goto CleanUp;
  1539. }
  1540. }
  1541. Assert (ERROR_SUCCESS == err);
  1542. return ERROR_SUCCESS;
  1543. CleanUp:
  1544. Assert (err != ERROR_SUCCESS);
  1545. for (i=0; i<gc_dwCountInboxTable; i++)
  1546. {
  1547. MemFree (g_InboxTable[i].String);
  1548. g_InboxTable[i].String = NULL;
  1549. }
  1550. for (i=0; i<gc_dwCountOutboxTable; i++)
  1551. {
  1552. MemFree (g_OutboxTable[i].String);
  1553. g_OutboxTable[i].String = NULL;
  1554. }
  1555. return err;
  1556. } // InitializeLoggingStringTables
  1557. //*********************************************************************************
  1558. //* Name: FilteredLogString
  1559. //* Author: Eran Yariv
  1560. //* Date: Feb 19, 2002
  1561. //*********************************************************************************
  1562. //* DESCRIPTION:
  1563. //* This function is used to filter strings that go into the log files.
  1564. //*
  1565. //* PARAMETERS:
  1566. //* [IN] LPCWSTR lpcwstrSrc
  1567. //* The string to filter
  1568. //*
  1569. //*
  1570. //* RETURN VALUE:
  1571. //* Filtered string
  1572. //*
  1573. //* NOTE: The function might throw STL string exceptions.
  1574. //*
  1575. //*********************************************************************************
  1576. static
  1577. wstring
  1578. FilteredLogString (LPCWSTR lpcwstrSrc) throw (exception)
  1579. {
  1580. DEBUG_FUNCTION_NAME(TEXT("FilteredLogString"));
  1581. if (!lpcwstrSrc)
  1582. {
  1583. return EMPTY_LOG_STRING;
  1584. }
  1585. wstring wstrResult = lpcwstrSrc;
  1586. //
  1587. // Replace new lines ('\n') with one space (' ')
  1588. //
  1589. wstring::size_type position;
  1590. while (wstring::npos != (position = wstrResult.find (TEXT('\n'))))
  1591. {
  1592. wstrResult[position] = TEXT(' ');
  1593. }
  1594. //
  1595. // Replace carriage returns ('\r') with one space (' ')
  1596. //
  1597. while (wstring::npos != (position = wstrResult.find (TEXT('\r'))))
  1598. {
  1599. wstrResult[position] = TEXT(' ');
  1600. }
  1601. //
  1602. // Replace double quotes ('"') with single quotes ('\'')
  1603. //
  1604. while (wstring::npos != (position = wstrResult.find (TEXT('"'))))
  1605. {
  1606. wstrResult[position] = TEXT('\'');
  1607. }
  1608. //
  1609. // Replace tabs ('"') with 4 spaces (" ")
  1610. //
  1611. while (wstring::npos != (position = wstrResult.find (TEXT('\t'))))
  1612. {
  1613. wstrResult.replace (position, 1, 4, TEXT(' '));
  1614. }
  1615. return wstrResult;
  1616. } // FilteredLogString
  1617. //*********************************************************************************
  1618. //* Name: GetFaxTimeAsString
  1619. //* Author: Oded Sacher
  1620. //* Date: Oct 19, 1999
  1621. //*********************************************************************************
  1622. //* DESCRIPTION:
  1623. //* This function is used to convert a fax time to a string.
  1624. //*
  1625. //* PARAMETERS:
  1626. //* [IN] SYSTEMTIME* UniversalTime
  1627. //* Fax time
  1628. //*
  1629. //* [OUT] wstring &wstrTime
  1630. //* The output string.
  1631. //*
  1632. //*
  1633. //* RETURN VALUE:
  1634. //* TRUE for success, FALSE otherwise.
  1635. //*
  1636. //* NOTE: The function might throw STL string exceptions.
  1637. //*
  1638. //*********************************************************************************
  1639. static
  1640. BOOL
  1641. GetFaxTimeAsString(
  1642. SYSTEMTIME* UniversalTime,
  1643. wstring &wstrTime) throw (exception)
  1644. {
  1645. DWORD Res;
  1646. SYSTEMTIME LocalTime;
  1647. TIME_ZONE_INFORMATION LocalTimeZone;
  1648. DEBUG_FUNCTION_NAME(TEXT("GetFaxTimeAsString"));
  1649. Res = GetTimeZoneInformation(&LocalTimeZone);
  1650. if (Res == TIME_ZONE_ID_INVALID)
  1651. {
  1652. DebugPrintEx(
  1653. DEBUG_ERR,
  1654. TEXT("Failed to get local time zone info (ec: %ld)"),
  1655. GetLastError());
  1656. return FALSE;
  1657. }
  1658. else
  1659. {
  1660. if (!SystemTimeToTzSpecificLocalTime( &LocalTimeZone, UniversalTime, &LocalTime))
  1661. {
  1662. DebugPrintEx(
  1663. DEBUG_ERR,
  1664. TEXT("Failed to convert universal system time to local system time (ec: %ld)"),
  1665. GetLastError());
  1666. return FALSE;
  1667. }
  1668. }
  1669. TCHAR tszTime[100];
  1670. _stprintf(tszTime,
  1671. TEXT("%d/%d/%d %02d:%02d:%02d"),
  1672. LocalTime.wMonth,
  1673. LocalTime.wDay,
  1674. LocalTime.wYear,
  1675. LocalTime.wHour,
  1676. LocalTime.wMinute,
  1677. LocalTime.wSecond);
  1678. wstrTime = tszTime;
  1679. return TRUE;
  1680. } // GetFaxTimeAsString
  1681. static
  1682. DWORD
  1683. CreateLogFile(DWORD dwFileType,LPCWSTR lpcwstrDBPath, LPHANDLE phFile)
  1684. /*++
  1685. Routine name : CreateLogFile
  1686. Routine description:
  1687. According to the selected dwFileType, this function creates an activity log file
  1688. Author:
  1689. Caliv Nir (t-nicali), Nov, 2001
  1690. Arguments:
  1691. dwFileType [in] - the file to create (inbox or outbox)
  1692. o ACTIVITY_LOG_INBOX for inbox
  1693. o ACTIVITY_LOG_OUTBOX for outbox
  1694. lpcwstrDBPath [in] - the path to the activity logging folder
  1695. phFile [out] - handle to the created log file
  1696. Return Value:
  1697. Win32 Error codes
  1698. Remarks:
  1699. --*/
  1700. {
  1701. HANDLE hFile = INVALID_HANDLE_VALUE;
  1702. WCHAR wszFileName[MAX_PATH] = {0};
  1703. LARGE_INTEGER FileSize= {0};
  1704. DWORD dwBytesWritten;
  1705. DWORD dwFilePointer;
  1706. int Count = 0 ;
  1707. DWORD dwRes = ERROR_SUCCESS;
  1708. DEBUG_FUNCTION_NAME(TEXT("CreateLogFile"));
  1709. Assert (phFile);
  1710. Assert (lpcwstrDBPath);
  1711. Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
  1712. Count = _snwprintf (wszFileName,
  1713. MAX_PATH -1,
  1714. TEXT("%s\\%s"),
  1715. lpcwstrDBPath,
  1716. ((dwFileType == ACTIVITY_LOG_INBOX) ? ACTIVITY_LOG_INBOX_FILE : ACTIVITY_LOG_OUTBOX_FILE)
  1717. );
  1718. if (Count < 0)
  1719. {
  1720. //
  1721. // We already checked for max dir path name.
  1722. //
  1723. DebugPrintEx(
  1724. DEBUG_ERR,
  1725. TEXT("_snwprintf Failed, File name bigger than MAX_PATH"));
  1726. dwRes = ERROR_BUFFER_OVERFLOW;
  1727. goto exit;
  1728. }
  1729. hFile = SafeCreateFile(
  1730. wszFileName, // file name
  1731. GENERIC_WRITE, // access mode
  1732. FILE_SHARE_READ, // share mode
  1733. NULL, // SD
  1734. OPEN_ALWAYS, // how to create
  1735. FILE_ATTRIBUTE_NORMAL, // file attributes
  1736. NULL);
  1737. if (INVALID_HANDLE_VALUE == hFile)
  1738. {
  1739. dwRes = GetLastError();
  1740. DebugPrintEx(DEBUG_ERR,
  1741. TEXT("CreateFile failed (ec: %ld)"),
  1742. dwRes);
  1743. goto exit;
  1744. }
  1745. if (!GetFileSizeEx (hFile, &FileSize))
  1746. {
  1747. dwRes = GetLastError();
  1748. DebugPrintEx(DEBUG_ERR,
  1749. TEXT("GetFileSizeEx failed (ec: %ld)"),
  1750. dwRes);
  1751. goto exit;
  1752. }
  1753. if (0 == FileSize.QuadPart)
  1754. {
  1755. //
  1756. // New file was created, add UNICODE header
  1757. //
  1758. USHORT UnicodeHeader = 0xfeff;
  1759. if (!WriteFile( hFile,
  1760. &UnicodeHeader,
  1761. sizeof(UnicodeHeader),
  1762. &dwBytesWritten,
  1763. NULL))
  1764. {
  1765. dwRes = GetLastError();
  1766. DebugPrintEx(DEBUG_ERR,
  1767. TEXT("WriteFile failed (ec: %ld)"),
  1768. dwRes);
  1769. goto exit;
  1770. }
  1771. //
  1772. // Add the first line (Columns name)
  1773. //
  1774. wstring wstrHeader;
  1775. try
  1776. {
  1777. GetTableColumnsText((dwFileType == ACTIVITY_LOG_INBOX) ? INBOX_TABLE : OUTBOX_TABLE, wstrHeader);
  1778. }
  1779. catch (exception &ex)
  1780. {
  1781. dwRes = ERROR_OUTOFMEMORY;
  1782. DebugPrintEx(
  1783. DEBUG_ERR,
  1784. TEXT("GetTableColumnsText caused exception (%S)"),
  1785. ex.what());
  1786. goto exit;
  1787. }
  1788. if (!WriteFile( hFile,
  1789. wstrHeader.c_str(),
  1790. wstrHeader.length() * sizeof(WCHAR),
  1791. &dwBytesWritten,
  1792. NULL))
  1793. {
  1794. dwRes = GetLastError();
  1795. DebugPrintEx(DEBUG_ERR,
  1796. TEXT("WriteFile failed (ec: %ld)"),
  1797. dwRes);
  1798. goto exit;
  1799. }
  1800. }
  1801. else
  1802. {
  1803. dwFilePointer = SetFilePointer( hFile, // handle to file
  1804. 0, // bytes to move pointer
  1805. NULL, // bytes to move pointer
  1806. FILE_END // starting point
  1807. );
  1808. if (INVALID_SET_FILE_POINTER == dwFilePointer)
  1809. {
  1810. dwRes = GetLastError();
  1811. DebugPrintEx(DEBUG_ERR,
  1812. TEXT("SetFilePointer failed (ec: %ld)"),
  1813. dwRes);
  1814. goto exit;
  1815. }
  1816. }
  1817. *phFile = hFile;
  1818. Assert (ERROR_SUCCESS == dwRes);
  1819. exit:
  1820. if (ERROR_SUCCESS != dwRes)
  1821. {
  1822. //
  1823. // The activity logging will halt because we couldn't complete CreateLogFile().
  1824. //
  1825. if (*phFile != INVALID_HANDLE_VALUE)
  1826. {
  1827. CloseHandle(*phFile);
  1828. *phFile = INVALID_HANDLE_VALUE;
  1829. }
  1830. if (dwFileType == ACTIVITY_LOG_INBOX)
  1831. {
  1832. g_ActivityLoggingConfig.bLogIncoming = FALSE;
  1833. }
  1834. else
  1835. {
  1836. g_ActivityLoggingConfig.bLogOutgoing = FALSE;
  1837. }
  1838. //
  1839. // Post an event log entry
  1840. //
  1841. FaxLog(
  1842. FAXLOG_CATEGORY_INIT,
  1843. (dwFileType == ACTIVITY_LOG_INBOX)?FAXLOG_CATEGORY_INBOUND:FAXLOG_CATEGORY_OUTBOUND,
  1844. 2,
  1845. MSG_LOGGING_NOT_INITIALIZED,
  1846. g_ActivityLoggingConfig.lptstrDBPath,
  1847. DWORD2DECIMAL(dwRes)
  1848. );
  1849. if (INVALID_HANDLE_VALUE != hFile)
  1850. {
  1851. if (!CloseHandle (hFile))
  1852. {
  1853. DebugPrintEx(DEBUG_ERR,
  1854. TEXT("CloseHandle failed (ec: %ld)"),
  1855. GetLastError());
  1856. }
  1857. }
  1858. }
  1859. return dwRes;
  1860. } // CreateLogFile
  1861. static
  1862. BOOL
  1863. LogFileLimitReached(DWORD dwFileToCheck)
  1864. /*++
  1865. Routine name : LogFileLimitReached
  1866. Routine description:
  1867. According to the selected log limit criteria, this function checks to see wheter Activity log file
  1868. have reached it's limit.
  1869. Author:
  1870. Caliv Nir (t-nicali), Nov, 2001
  1871. Arguments:
  1872. dwFileToCheck [in] - the file to be checked (inbox or outbox)
  1873. o ACTIVITY_LOG_INBOX for inbox
  1874. o ACTIVITY_LOG_OUTBOX for outbox
  1875. Return Value:
  1876. TRUE - if the limit have been reached
  1877. Remarks:
  1878. Call this function only if activity logging is enabled for checked the log file !
  1879. --*/
  1880. {
  1881. BOOL bActivityLogEnabled = FALSE;
  1882. HANDLE hLogFile = INVALID_HANDLE_VALUE;
  1883. DEBUG_FUNCTION_NAME(TEXT("LogFileLimitReached"));
  1884. Assert ( (dwFileToCheck==ACTIVITY_LOG_INBOX) || (dwFileToCheck==ACTIVITY_LOG_OUTBOX) );
  1885. Assert ( g_ActivityLoggingConfig.bLogIncoming || g_ActivityLoggingConfig.bLogOutgoing );
  1886. if ( g_ActivityLoggingConfig.dwLogLimitCriteria == ACTIVITY_LOG_LIMIT_CRITERIA_NONE )
  1887. {
  1888. //
  1889. // activity logging limiting is disabled so no limit checking is needed
  1890. //
  1891. goto Exit;
  1892. }
  1893. hLogFile = (dwFileToCheck==ACTIVITY_LOG_INBOX)? g_hInboxActivityLogFile : g_hOutboxActivityLogFile;
  1894. //
  1895. // activity logging is enabled so the handle must be valid
  1896. //
  1897. Assert (hLogFile != INVALID_HANDLE_VALUE);
  1898. if ( g_ActivityLoggingConfig.dwLogLimitCriteria == ACTIVITY_LOG_LIMIT_CRITERIA_SIZE )
  1899. {
  1900. //
  1901. // Checking limit according to file size in Mbytes
  1902. //
  1903. LARGE_INTEGER FileSize = {0};
  1904. //
  1905. // Check the file size
  1906. //
  1907. if( !GetFileSizeEx( hLogFile,&FileSize ) )
  1908. {
  1909. DebugPrintEx(DEBUG_ERR,
  1910. TEXT("GetFileSizeEx failed (ec=%ld))"),
  1911. GetLastError()
  1912. );
  1913. goto Exit;
  1914. }
  1915. //
  1916. // Compare it to limit
  1917. //
  1918. if (FileSize.QuadPart >= ( g_ActivityLoggingConfig.dwLogSizeLimit * 1I64 * 1024I64 * 1024I64 )) // dwLogSizeLimit is in Mbytes
  1919. {
  1920. //
  1921. // File exceeded the given size limit
  1922. //
  1923. return TRUE;
  1924. }
  1925. }
  1926. else
  1927. if ( g_ActivityLoggingConfig.dwLogLimitCriteria == ACTIVITY_LOG_LIMIT_CRITERIA_AGE)
  1928. {
  1929. //
  1930. // Checking limit according to file age in months
  1931. //
  1932. FILETIME FileTimeCreationTime;
  1933. //
  1934. // Check file creation time (the creation time is the first time that something was writen into this file)
  1935. //
  1936. if ( !GetFileTime( hLogFile, // handle to file
  1937. &FileTimeCreationTime, // creation time
  1938. NULL, // last access time
  1939. NULL // last write time
  1940. )
  1941. )
  1942. {
  1943. DebugPrintEx(DEBUG_ERR,
  1944. TEXT("GetFileTime failed (ec=%ld))"),
  1945. GetLastError()
  1946. );
  1947. goto Exit;
  1948. }
  1949. SYSTEMTIME SystemTimeCreationTime = {0};
  1950. if ( !FileTimeToSystemTime( &FileTimeCreationTime, // file time to convert
  1951. &SystemTimeCreationTime // receives system time
  1952. )
  1953. )
  1954. {
  1955. DebugPrintEx(DEBUG_ERR,
  1956. TEXT("FileTimeToSystemTime failed (ec=%ld))"),
  1957. GetLastError()
  1958. );
  1959. goto Exit;
  1960. }
  1961. //
  1962. // Find out current time
  1963. //
  1964. SYSTEMTIME CurrentTime = {0};
  1965. GetSystemTime(&CurrentTime);
  1966. //
  1967. // Calculate monthe diff between current time and the time of the first write to the log file.
  1968. //
  1969. DWORD dwMonthDiff = (CurrentTime.wYear - SystemTimeCreationTime.wYear) * 12 + CurrentTime.wMonth - SystemTimeCreationTime.wMonth;
  1970. if (dwMonthDiff >= g_ActivityLoggingConfig.dwLogAgeLimit)
  1971. {
  1972. //
  1973. // the file reached the age limit
  1974. //
  1975. return TRUE;
  1976. }
  1977. }
  1978. else
  1979. {
  1980. //
  1981. // Bad parameter in g_ActivityLoggingConfig.dwLogLimitCriteria
  1982. //
  1983. ASSERT_FALSE;
  1984. }
  1985. Exit:
  1986. return FALSE;
  1987. } // LogFileLimitReached
  1988. static
  1989. DWORD
  1990. LogFileLimitReachAction(DWORD dwFileType)
  1991. /*++
  1992. Routine name : LogFileLimitReachAction
  1993. Routine description:
  1994. According to the selected log limit reached action criteria, take the action.
  1995. Author:
  1996. Caliv Nir (t-nicali), Nov, 2001
  1997. Arguments:
  1998. dwFileType [in] - the file to handle (inbox or outbox)
  1999. o ACTIVITY_LOG_INBOX for inbox
  2000. o ACTIVITY_LOG_OUTBOX for outbox
  2001. Return Value:
  2002. TRUE - if the limit have been reached
  2003. Remarks:
  2004. Call this function only if activity logging is enabled *and* Limiting the activity files is enabled
  2005. --*/
  2006. {
  2007. HANDLE hLogFile = INVALID_HANDLE_VALUE;
  2008. DWORD dwRes = ERROR_SUCCESS;
  2009. DEBUG_FUNCTION_NAME(TEXT("LogFileLimitReachAction"));
  2010. //
  2011. // Parameter check (Private function)
  2012. //
  2013. Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
  2014. Assert ( (dwFileType==ACTIVITY_LOG_INBOX && g_ActivityLoggingConfig.bLogIncoming) ||
  2015. (dwFileType==ACTIVITY_LOG_OUTBOX && g_ActivityLoggingConfig.bLogOutgoing) );
  2016. Assert ( g_ActivityLoggingConfig.dwLogLimitCriteria != ACTIVITY_LOG_LIMIT_CRITERIA_NONE );
  2017. hLogFile = (dwFileType==ACTIVITY_LOG_INBOX)? g_hInboxActivityLogFile : g_hOutboxActivityLogFile;
  2018. if (g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_DELETE)
  2019. {
  2020. //
  2021. // Delete the log file
  2022. //
  2023. dwRes = DeleteLogActivityFile(dwFileType);
  2024. if (ERROR_SUCCESS != dwRes)
  2025. {
  2026. DebugPrintEx(DEBUG_ERR,
  2027. TEXT("DeleteLogActivityFile failed (ec: %ld)"),
  2028. dwRes);
  2029. goto exit;
  2030. }
  2031. }
  2032. else
  2033. if (g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_COPY)
  2034. {
  2035. //
  2036. // Replace the log file with a fresh copy
  2037. //
  2038. dwRes = ReplaceLogActivityFile(dwFileType);
  2039. if (ERROR_SUCCESS != dwRes)
  2040. {
  2041. DebugPrintEx(DEBUG_ERR,
  2042. TEXT("DeleteLogActivityFile failed (ec: %ld)"),
  2043. dwRes);
  2044. goto exit;
  2045. }
  2046. }
  2047. else
  2048. {
  2049. //
  2050. // Bad parameter in g_ActivityLoggingConfig.dwLimitReachedAction
  2051. //
  2052. ASSERT_FALSE;
  2053. }
  2054. Assert(ERROR_SUCCESS == dwRes);
  2055. exit:
  2056. return dwRes;
  2057. } // LogFileLimitReachAction
  2058. static
  2059. DWORD
  2060. DeleteLogActivityFile(DWORD dwFileType)
  2061. /*++
  2062. Routine name : DeleteLogActivityFile
  2063. Routine description:
  2064. According to dwFileType delete the proper activity log file and create a new one
  2065. Author:
  2066. Caliv Nir (t-nicali), Nov, 2001
  2067. Arguments:
  2068. dwFileType [in] - the file to Delete (inbox or outbox)
  2069. o ACTIVITY_LOG_INBOX for inbox
  2070. o ACTIVITY_LOG_OUTBOX for outbox
  2071. Return Value:
  2072. TRUE - if the limit have been reached
  2073. Remarks:
  2074. Call this function only if activity logging is enabled *and* Limiting the activity files is enabled
  2075. --*/
  2076. {
  2077. LPWSTR strFullFileName = NULL;
  2078. LPHANDLE phFile=NULL;
  2079. DWORD dwRes = ERROR_SUCCESS;
  2080. DEBUG_FUNCTION_NAME(TEXT("DeleteLogActivityFile"));
  2081. Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
  2082. Assert ( g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_DELETE );
  2083. Assert ( (dwFileType==ACTIVITY_LOG_INBOX && g_ActivityLoggingConfig.bLogIncoming) ||
  2084. (dwFileType==ACTIVITY_LOG_OUTBOX && g_ActivityLoggingConfig.bLogOutgoing) );
  2085. Assert ( g_ActivityLoggingConfig.lptstrDBPath );
  2086. strFullFileName = BuildFullFileName(g_ActivityLoggingConfig.lptstrDBPath, ((dwFileType == ACTIVITY_LOG_INBOX)? ACTIVITY_LOG_INBOX_FILE : ACTIVITY_LOG_OUTBOX_FILE) );
  2087. if (NULL == strFullFileName)
  2088. {
  2089. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  2090. DebugPrintEx(DEBUG_ERR,
  2091. TEXT("BuildFullFileName() failed.")
  2092. );
  2093. goto exit;
  2094. }
  2095. phFile = (dwFileType == ACTIVITY_LOG_INBOX) ? &g_hInboxActivityLogFile : &g_hOutboxActivityLogFile ;
  2096. Assert(*phFile);
  2097. if (!CloseHandle(*phFile))
  2098. {
  2099. dwRes = GetLastError();
  2100. DebugPrintEx(DEBUG_ERR,
  2101. TEXT("CloseHandle failed (ec=%ld)."),
  2102. dwRes
  2103. );
  2104. goto exit;
  2105. }
  2106. *phFile = INVALID_HANDLE_VALUE;
  2107. if (!DeleteFile(strFullFileName))
  2108. {
  2109. dwRes = GetLastError();
  2110. DebugPrintEx(DEBUG_ERR,
  2111. TEXT("DeleteFile failed (ec=%ld)."),
  2112. dwRes
  2113. );
  2114. //
  2115. // Try to roll back and use the old file
  2116. //
  2117. }
  2118. //
  2119. // Create new logging file
  2120. //
  2121. dwRes = CreateLogFile(dwFileType,g_ActivityLoggingConfig.lptstrDBPath,phFile);
  2122. if ( ERROR_SUCCESS != dwRes)
  2123. {
  2124. DebugPrintEx( DEBUG_ERR,
  2125. TEXT("CreateLogFile() Failed. (ec=%ld)"),
  2126. dwRes
  2127. );
  2128. goto exit;
  2129. }
  2130. //
  2131. // Because the creation time of the file is important for log limit
  2132. // mechanism, we make sure to update the file creation time that may
  2133. // not be updated (Due to file system caching mechanism for example)
  2134. //
  2135. if (!SetFileToCurrentTime(*phFile))
  2136. {
  2137. DebugPrintEx( DEBUG_ERR,
  2138. TEXT("SetFileToCurrentTime() Failed. (ec=%ld)"),
  2139. dwRes
  2140. );
  2141. }
  2142. DebugPrintEx( DEBUG_MSG,
  2143. TEXT("Activity log file was deleted and replaced with fresh copy.")
  2144. );
  2145. Assert(ERROR_SUCCESS == dwRes);
  2146. exit:
  2147. MemFree(strFullFileName);
  2148. return dwRes;
  2149. } // DeleteLogActivityFile
  2150. static
  2151. DWORD
  2152. ReplaceLogActivityFile(DWORD dwFileType)
  2153. /*++
  2154. Routine name : ReplaceLogActivityFile
  2155. Routine description:
  2156. According to dwFileType copy the proper activity log file and create a new one
  2157. Author:
  2158. Caliv Nir (t-nicali), Nov, 2001
  2159. Arguments:
  2160. dwFileType [in] - the file to Replace (inbox or outbox)
  2161. o ACTIVITY_LOG_INBOX for inbox
  2162. o ACTIVITY_LOG_OUTBOX for outbox
  2163. Return Value:
  2164. Win32 error code
  2165. Remarks:
  2166. Call this function only if activity logging is enabled *and* Limiting the activity files is enabled
  2167. --*/
  2168. {
  2169. SYSTEMTIME LogStartTime = {0};
  2170. SYSTEMTIME LogEndTime = {0};
  2171. FILETIME FirstWriteTime = {0};
  2172. FILETIME LastWriteTime= {0};
  2173. LPWSTR strOldFileName = NULL;
  2174. WCHAR strNewFileName[MAX_PATH] = {0};
  2175. LPWSTR strNameTemplate = NULL;
  2176. LPWSTR strNewFullFileName = NULL;
  2177. LPHANDLE phFile=NULL;
  2178. DWORD dwRes = ERROR_SUCCESS;
  2179. DEBUG_FUNCTION_NAME(TEXT("ReplaceLogActivityFile"));
  2180. Assert ( (dwFileType==ACTIVITY_LOG_INBOX) || (dwFileType==ACTIVITY_LOG_OUTBOX) );
  2181. Assert ( g_ActivityLoggingConfig.dwLimitReachedAction == ACTIVITY_LOG_LIMIT_REACHED_ACTION_COPY );
  2182. Assert ( (dwFileType==ACTIVITY_LOG_INBOX && g_ActivityLoggingConfig.bLogIncoming) ||
  2183. (dwFileType==ACTIVITY_LOG_OUTBOX && g_ActivityLoggingConfig.bLogOutgoing) );
  2184. Assert ( g_ActivityLoggingConfig.lptstrDBPath );
  2185. phFile = (dwFileType == ACTIVITY_LOG_INBOX) ? &g_hInboxActivityLogFile : &g_hOutboxActivityLogFile;
  2186. Assert (INVALID_HANDLE_VALUE != *phFile);
  2187. //
  2188. // find out the file's first and last write time
  2189. //
  2190. if (!GetFileTime( *phFile, // handle to file
  2191. &FirstWriteTime, // creation time
  2192. NULL, // last access time
  2193. &LastWriteTime // last write time
  2194. )
  2195. )
  2196. {
  2197. dwRes = GetLastError();
  2198. DebugPrintEx(DEBUG_ERR,
  2199. TEXT("GetFileTime() failed. (ec=%ld)"),
  2200. dwRes
  2201. );
  2202. goto exit;
  2203. }
  2204. if (!FileTimeToSystemTime( &FirstWriteTime, // file time to convert
  2205. &LogStartTime // receives system time
  2206. )
  2207. )
  2208. {
  2209. dwRes = GetLastError();
  2210. DebugPrintEx(DEBUG_ERR,
  2211. TEXT("FileTimeToSystemTime() failed. (ec=%ld)"),
  2212. dwRes
  2213. );
  2214. goto exit;
  2215. }
  2216. if (!FileTimeToSystemTime( &LastWriteTime, // file time to convert
  2217. &LogEndTime // receives system time
  2218. )
  2219. )
  2220. {
  2221. dwRes = GetLastError();
  2222. DebugPrintEx(DEBUG_ERR,
  2223. TEXT("FileTimeToSystemTime() failed. (ec=%ld)"),
  2224. dwRes
  2225. );
  2226. goto exit;
  2227. }
  2228. //
  2229. // build the current log file name
  2230. //
  2231. strOldFileName = BuildFullFileName(g_ActivityLoggingConfig.lptstrDBPath, ((dwFileType == ACTIVITY_LOG_INBOX)? ACTIVITY_LOG_INBOX_FILE : ACTIVITY_LOG_OUTBOX_FILE) );
  2232. if (NULL == strOldFileName)
  2233. {
  2234. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  2235. DebugPrintEx(DEBUG_ERR,
  2236. TEXT("BuildFullFileName() failed.")
  2237. );
  2238. goto exit;
  2239. }
  2240. //
  2241. // build the copy file name according to the first and last write times
  2242. //
  2243. strNameTemplate = (dwFileType == ACTIVITY_LOG_INBOX) ? ACTIVITY_LOG_INBOX_FILENAME_TEMPLATE : ACTIVITY_LOG_OUTBOX_FILENAME_TEMPLATE;
  2244. _snwprintf ( strNewFileName,
  2245. ARR_SIZE(strNewFileName)-1,
  2246. strNameTemplate, // TEXT("??boxLOG %04d-%02d-%02d through %04d-%02d-%02d.txt") ?? - is "In" or "Out"
  2247. LogStartTime.wYear,
  2248. LogStartTime.wMonth,
  2249. LogStartTime.wDay,
  2250. LogEndTime.wYear,
  2251. LogEndTime.wMonth,
  2252. LogEndTime.wDay
  2253. );
  2254. strNewFullFileName = BuildFullFileName(g_ActivityLoggingConfig.lptstrDBPath,strNewFileName);
  2255. if (NULL == strNewFullFileName)
  2256. {
  2257. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  2258. DebugPrintEx(DEBUG_ERR,
  2259. TEXT("BuildFullFileName() failed.")
  2260. );
  2261. goto exit;
  2262. }
  2263. if ( !CloseHandle(*phFile) )
  2264. {
  2265. dwRes = GetLastError();
  2266. DebugPrintEx(DEBUG_ERR,
  2267. TEXT("CloseHandle() failed. (ec=%ld)"),
  2268. dwRes
  2269. );
  2270. goto exit;
  2271. }
  2272. *phFile = INVALID_HANDLE_VALUE;
  2273. if ( !MoveFile ( strOldFileName, // file name
  2274. strNewFullFileName // new file name
  2275. )
  2276. )
  2277. {
  2278. dwRes = GetLastError();
  2279. DebugPrintEx(DEBUG_ERR,
  2280. TEXT("MoveFileEx() failed. (ec=%ld)"),
  2281. dwRes
  2282. );
  2283. //
  2284. // Try to roll back and use the old file
  2285. //
  2286. }
  2287. //
  2288. // Create the logging file that was renamed
  2289. //
  2290. dwRes = CreateLogFile(dwFileType,g_ActivityLoggingConfig.lptstrDBPath,phFile);
  2291. if ( ERROR_SUCCESS != dwRes)
  2292. {
  2293. DebugPrintEx( DEBUG_ERR,
  2294. TEXT("CreateLogFile() Failed. (ec=%ld)"),
  2295. dwRes
  2296. );
  2297. goto exit;
  2298. }
  2299. //
  2300. // Because the creation time of the file is important for log limit
  2301. // mechanism, we make sure to update the file creation time that may
  2302. // not be updated (Due to file system caching mechanism for example)
  2303. //
  2304. if (!SetFileToCurrentTime(*phFile))
  2305. {
  2306. DebugPrintEx( DEBUG_ERR,
  2307. TEXT("SetFileToCurrentTime() Failed. (ec=%ld)"),
  2308. dwRes
  2309. );
  2310. }
  2311. DebugPrintEx( DEBUG_MSG,
  2312. TEXT("Activity log file was copied and replaced with fresh copy.")
  2313. );
  2314. Assert (ERROR_SUCCESS == dwRes);
  2315. exit:
  2316. MemFree(strOldFileName);
  2317. MemFree(strNewFullFileName);
  2318. return dwRes;
  2319. } // ReplaceLogActivityFile
  2320. static
  2321. LPTSTR
  2322. BuildFullFileName( LPCWSTR strPath,
  2323. LPCWSTR strFileName )
  2324. /*++
  2325. Routine name : BuildFullFileName
  2326. Routine description:
  2327. Utility function to concat path and file name. -> strPath\strFileName
  2328. Author:
  2329. Caliv Nir (t-nicali), Nov, 2001
  2330. Arguments:
  2331. strPath [in] - file path
  2332. strFileName [in] - file name
  2333. Return Value:
  2334. the full file name string
  2335. Remarks:
  2336. Caller must MemFree the return string
  2337. This function works for UNICODE and ANSI (not for MBCS)
  2338. --*/
  2339. {
  2340. LPWSTR strFullFileName = NULL;
  2341. DWORD dwNewNameLen = 0;
  2342. DEBUG_FUNCTION_NAME(TEXT("BuildFullFileName"));
  2343. Assert (strPath && strFileName);
  2344. dwNewNameLen = wcslen(strPath) + wcslen(strFileName) + 2; // sizeof path\fileName and null terminator
  2345. strFullFileName = (LPTSTR)MemAlloc(dwNewNameLen * sizeof(TCHAR));
  2346. if (NULL == strFullFileName)
  2347. {
  2348. DebugPrintEx(DEBUG_ERR,
  2349. TEXT("MemAlloc failed.")
  2350. );
  2351. goto exit;
  2352. }
  2353. strFullFileName[dwNewNameLen-1] = TEXT('\0');
  2354. //
  2355. // Build the full file name
  2356. //
  2357. _snwprintf (strFullFileName,
  2358. dwNewNameLen-1,
  2359. TEXT("%s\\%s"),
  2360. strPath,
  2361. strFileName);
  2362. exit:
  2363. return strFullFileName;
  2364. } // BuildFullFileName
  2365. static
  2366. BOOL
  2367. SetFileToCurrentTime(HANDLE hFile)
  2368. /*++
  2369. Routine name : SetFileToCurrentTime
  2370. Routine description:
  2371. Utility function set the creation time of file into current time
  2372. Author:
  2373. Caliv Nir (t-nicali), Nov, 2001
  2374. Arguments:
  2375. hFile [in] - file handle
  2376. Return Value:
  2377. TRUE if successful, FALSE otherwise
  2378. Remarks:
  2379. hFile - must be a valid file handle
  2380. --*/
  2381. {
  2382. FILETIME ft={0};
  2383. SYSTEMTIME st={0};
  2384. BOOL bRet = TRUE;
  2385. DWORD dwRes;
  2386. DEBUG_FUNCTION_NAME(TEXT("SetFileToCurrentTime"));
  2387. Assert (INVALID_HANDLE_VALUE != hFile);
  2388. //
  2389. // Because the creation time of the file is important for log limit
  2390. // mechanism, we make sure to update the file creation time that may
  2391. // not be updated (Due to file system caching mechanism for example)
  2392. //
  2393. GetSystemTime(&st); // gets current time
  2394. bRet = SystemTimeToFileTime(&st, &ft);
  2395. if (FALSE == bRet) // converts to file time format
  2396. {
  2397. dwRes = GetLastError();
  2398. DebugPrintEx(DEBUG_ERR,
  2399. TEXT("SystemTimeToFileTime failed (ec: %ld)"),
  2400. dwRes);
  2401. goto exit;
  2402. }
  2403. bRet = SetFileTime( hFile, // sets creation time for file
  2404. &ft,
  2405. (LPFILETIME) NULL,
  2406. (LPFILETIME) NULL);
  2407. if (FALSE == bRet)
  2408. {
  2409. dwRes = GetLastError();
  2410. DebugPrintEx(DEBUG_ERR,
  2411. TEXT("SetFileTime failed (ec: %ld)"),
  2412. dwRes);
  2413. goto exit;
  2414. }
  2415. Assert (TRUE == bRet);
  2416. exit:
  2417. return bRet;
  2418. } // SetFileToCurrentTime