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.

1093 lines
32 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. sndthrd.c
  5. Abstract:
  6. This module:
  7. 1) Verifies a tiff
  8. 2) Enables or disables the FaxRcv Routing Extension
  9. 3) Callback function for the change of state during the RAS connection process
  10. 4) Sends a RAS call
  11. 5) Sends a fax
  12. 6) Receives a fax
  13. 7) Thread to handle the Send logic
  14. Author:
  15. Steven Kehrli (steveke) 11/15/1997
  16. --*/
  17. #ifndef _SNDTHRD_C
  18. #define _SNDTHRD_C
  19. #include <tifflib.h>
  20. #include <tifflibp.h>
  21. #define SUSPECT_RAS_SPEED 28800
  22. #define IMAGEWIDTH_REF 1728
  23. #define IMAGELENGTH_200_REF 2200
  24. #define IMAGELENGTH_100_REF 1100
  25. #define SOFTWARE_REF "Windows NT Fax Server"
  26. UINT
  27. fnVerifyTiff(
  28. LPWSTR szTiffFile,
  29. LPDWORD pdwPages
  30. )
  31. /*++
  32. Routine Description:
  33. Verifies a tiff
  34. Arguments:
  35. szTiffFile - tiff file name
  36. pdwPages - pointer to the number of pages
  37. Return Value:
  38. TRUE on success
  39. --*/
  40. {
  41. HANDLE hTiffFile;
  42. TIFF_INFO TiffInfo;
  43. PTIFF_INSTANCE_DATA pTiffInstanceData;
  44. DWORD IFDOffset;
  45. WORD wNumDirEntries;
  46. PTIFF_TAG pTiffTag;
  47. WORD wIndex;
  48. DWORD ImageLengthRef;
  49. DWORD ImageWidth;
  50. DWORD ImageLength;
  51. DWORD Compression;
  52. DWORD Photometric;
  53. DWORD XResolution;
  54. DWORD YResolution;
  55. LPSTR SoftwareBuffer;
  56. LPSTR Software;
  57. UINT uFlags;
  58. uFlags = ERROR_SUCCESS;
  59. *pdwPages = 0;
  60. // Open the tiff file
  61. hTiffFile = TiffOpen(szTiffFile, &TiffInfo, TRUE, FILLORDER_MSB2LSB);
  62. if (hTiffFile == NULL) {
  63. TiffClose(hTiffFile);
  64. return IDS_TIFF_INVALID_TIFF;
  65. }
  66. pTiffInstanceData = (PTIFF_INSTANCE_DATA) hTiffFile;
  67. // Get the next IFD offset
  68. IFDOffset = pTiffInstanceData->TiffHdr.IFDOffset;
  69. while (IFDOffset) {
  70. // Increment the number of pages
  71. (*pdwPages)++;
  72. // Get the number of tags in this IFD
  73. wNumDirEntries = (WORD) *(LPWORD) (pTiffInstanceData->fPtr + IFDOffset);
  74. // Set the tag pointer
  75. pTiffTag = (PTIFF_TAG) (pTiffInstanceData->fPtr +IFDOffset + sizeof(WORD));
  76. // Get the tiff tags
  77. ImageWidth = -1;
  78. ImageLength = -1;
  79. Compression = -1;
  80. Photometric = -1;
  81. XResolution = -1;
  82. YResolution = -1;
  83. Software = NULL;
  84. for (wIndex = 0; wIndex < wNumDirEntries; wIndex++) {
  85. switch (pTiffTag[wIndex].TagId) {
  86. case TIFFTAG_IMAGEWIDTH:
  87. ImageWidth = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
  88. break;
  89. case TIFFTAG_IMAGELENGTH:
  90. ImageLength = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
  91. break;
  92. case TIFFTAG_COMPRESSION:
  93. Compression = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
  94. break;
  95. case TIFFTAG_PHOTOMETRIC:
  96. Photometric = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
  97. break;
  98. case TIFFTAG_XRESOLUTION:
  99. XResolution = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
  100. break;
  101. case TIFFTAG_YRESOLUTION:
  102. YResolution = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
  103. break;
  104. case TIFFTAG_SOFTWARE:
  105. SoftwareBuffer = (LPSTR) (DWORD UNALIGNED *) (pTiffInstanceData->fPtr + pTiffTag[wIndex].DataOffset);
  106. Software = MemAllocMacro((lstrlenA(SOFTWARE_REF) + 1) * sizeof(CHAR));
  107. lstrcpynA(Software, SoftwareBuffer, (lstrlenA(SOFTWARE_REF) + 1));
  108. break;
  109. }
  110. }
  111. if ((ImageWidth < (IMAGEWIDTH_REF - (IMAGEWIDTH_REF * .1))) || (ImageWidth > (IMAGEWIDTH_REF + (IMAGEWIDTH_REF * .1)))) {
  112. uFlags = IDS_TIFF_INVALID_IMAGEWIDTH;
  113. goto InvalidFax;
  114. }
  115. if (YResolution == 196) {
  116. ImageLengthRef = IMAGELENGTH_200_REF;
  117. }
  118. else if (YResolution == 98) {
  119. ImageLengthRef = IMAGELENGTH_100_REF;
  120. }
  121. else {
  122. uFlags = IDS_TIFF_INVALID_YRESOLUTION;
  123. goto InvalidFax;
  124. }
  125. if ((ImageLength < (ImageLengthRef - (ImageLengthRef * .1))) || (ImageLength > (ImageLengthRef + (ImageLengthRef * .1)))) {
  126. uFlags = IDS_TIFF_INVALID_IMAGELENGTH;
  127. goto InvalidFax;
  128. }
  129. if (Compression != 4) {
  130. uFlags = IDS_TIFF_INVALID_COMPRESSION;
  131. goto InvalidFax;
  132. }
  133. if (Photometric != 0) {
  134. uFlags = IDS_TIFF_INVALID_PHOTOMETRIC;
  135. goto InvalidFax;
  136. }
  137. if (XResolution != 204) {
  138. uFlags = IDS_TIFF_INVALID_XRESOLUTION;
  139. goto InvalidFax;
  140. }
  141. if ((YResolution != 196) && (YResolution != 98)) {
  142. uFlags = IDS_TIFF_INVALID_YRESOLUTION;
  143. goto InvalidFax;
  144. }
  145. if (lstrcmpA(SOFTWARE_REF, Software)) {
  146. uFlags = IDS_TIFF_INVALID_SOFTWARE;
  147. goto InvalidFax;
  148. }
  149. MemFreeMacro(Software);
  150. // Get the next IFD offset
  151. IFDOffset = (DWORD) *(DWORD UNALIGNED *) (pTiffInstanceData->fPtr + (wNumDirEntries * sizeof(TIFF_TAG)) + IFDOffset + sizeof(WORD));
  152. }
  153. TiffClose(hTiffFile);
  154. return ERROR_SUCCESS;
  155. InvalidFax:
  156. if (Software) {
  157. MemFreeMacro(Software);
  158. }
  159. TiffClose(hTiffFile);
  160. return uFlags;
  161. }
  162. VOID
  163. fnEnableFaxRcv(
  164. BOOL bEnable
  165. )
  166. /*++
  167. Routine Description:
  168. Enables or disables the FaxRcv Routing Extension
  169. Arguments:
  170. bEnable - indicates whether to enable or disable the FaxRcv Routing Extension
  171. TRUE enables the FaxRcv Routing Extension
  172. FALSE enables the FaxRcv Routing Extension
  173. Return Value:
  174. None
  175. --*/
  176. {
  177. // hFaxRcvExtKey is the handle to the FaxRcv Extension Registry key
  178. HKEY hFaxRcvExtKey;
  179. // Open the FaxRcv Extension Registry key
  180. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, FAXRCV_EXT_REGKEY, 0, KEY_ALL_ACCESS, &hFaxRcvExtKey) != ERROR_SUCCESS) {
  181. return;
  182. }
  183. // Set the FaxRcv Extension bEnable Registry value
  184. if (RegSetValueEx(hFaxRcvExtKey, BENABLE_EXT_REGVAL, 0, REG_DWORD, (LPBYTE) &bEnable, sizeof(BOOL)) != ERROR_SUCCESS) {
  185. // Close the FaxRcv Extension Registry key
  186. RegCloseKey(hFaxRcvExtKey);
  187. return;
  188. }
  189. // Close the FaxRcv Extension Registry key
  190. RegCloseKey(hFaxRcvExtKey);
  191. }
  192. VOID WINAPI
  193. fnRasDialCallback(
  194. UINT uMsg,
  195. RASCONNSTATE RasConnState,
  196. DWORD dwError
  197. )
  198. /*++
  199. Routine Description:
  200. Callback function for the change of state during the RAS connection process
  201. Arguments:
  202. uMsg - type of event
  203. RasConnState - state
  204. dwError - error
  205. Return Value:
  206. None
  207. --*/
  208. {
  209. static BOOL bError = FALSE;
  210. if ((dwError) && (!bError)) {
  211. bError = TRUE;
  212. // Update the status
  213. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_FAILED, dwError);
  214. SetEvent(g_hRasFailedEvent);
  215. }
  216. else if (RasConnState == RASCS_OpenPort) {
  217. bError = FALSE;
  218. }
  219. else if (RasConnState == RASCS_ConnectDevice) {
  220. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_DIALING, 0);
  221. }
  222. else if (RasConnState == RASCS_Authenticate) {
  223. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_AUTHENTICATING, 0);
  224. }
  225. else if (RasConnState == RASCS_Connected) {
  226. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_CONNECTED, 0);
  227. SetEvent(g_hRasPassedEvent);
  228. }
  229. return;
  230. }
  231. UINT
  232. fnSendRas(
  233. LPHANDLE phFaxStopRasPassFailEvents
  234. )
  235. /*++
  236. Routine Description:
  237. Sends a RAS call
  238. Arguments:
  239. phFaxStopSendPassFailEvents - pointer to the g_hFaxEvent, g_hStopEvent, g_hRasPassedEvent and g_hRasFailedEvent
  240. Return Value:
  241. UINT - resource id
  242. --*/
  243. {
  244. DWORD_PTR dwRslt;
  245. UINT uRslt;
  246. // RasDialParams is the RAS dial params
  247. RASDIALPARAMS RasDialParams;
  248. // hRasConn is the handle to the RAS connection
  249. HRASCONN hRasConn;
  250. // RasConnStatus is the RAS connection status
  251. RASCONNSTATUS RasConnStatus;
  252. // RasStats are the RAS connection statistics
  253. RAS_STATS RasStats;
  254. // RasInfo is the RAS connection info
  255. RAS_INFO RasInfo;
  256. // Initialize hRasConn
  257. hRasConn = NULL;
  258. // Initialize RasDialParams
  259. ZeroMemory(&RasDialParams, sizeof(RASDIALPARAMS));
  260. // Set RasDialParams
  261. RasDialParams.dwSize = sizeof(RASDIALPARAMS);
  262. lstrcpy(RasDialParams.szPhoneNumber, g_szSndNumber);
  263. lstrcpy(RasDialParams.szUserName, g_szRasUserName);
  264. lstrcpy(RasDialParams.szPassword, g_szRasPassword);
  265. lstrcpy(RasDialParams.szDomain, g_szRasDomain);
  266. // Update the status
  267. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_STARTING, (LPARAM) g_szSndNumber);
  268. // Start the RAS session
  269. ResetEvent(g_hRasPassedEvent);
  270. ResetEvent(g_hRasFailedEvent);
  271. dwRslt = g_RasApi.RasDial(NULL, NULL, &RasDialParams, 0, fnRasDialCallback, &hRasConn);
  272. if (dwRslt != 0) {
  273. // Update the status
  274. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_FAILED, dwRslt);
  275. return IDS_STATUS_RAS_FAILED;
  276. }
  277. // Wait for Fax, Stop, RAS Passed or RAS Failed event
  278. dwRslt = WaitForMultipleObjects(4, phFaxStopRasPassFailEvents, FALSE, INFINITE);
  279. switch (dwRslt) {
  280. case WAIT_OBJECT_0:
  281. uRslt = IDS_STATUS_FAXSVC_ENDED;
  282. break;
  283. case (WAIT_OBJECT_0 + 1):
  284. uRslt = IDS_STATUS_ITERATION_STOPPED;
  285. break;
  286. case (WAIT_OBJECT_0 + 2):
  287. uRslt = IDS_STATUS_RAS_PASSED;
  288. break;
  289. case (WAIT_OBJECT_0 + 3):
  290. uRslt = IDS_STATUS_RAS_FAILED;
  291. break;
  292. }
  293. if (uRslt != IDS_STATUS_RAS_PASSED) {
  294. // Update the status
  295. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_STOPPING, 0);
  296. // Stop the RAS session
  297. g_RasApi.RasHangUp(hRasConn);
  298. if (uRslt != IDS_STATUS_RAS_FAILED) {
  299. WaitForSingleObject(g_hRasFailedEvent, INFINITE);
  300. }
  301. return uRslt;
  302. }
  303. // Initialize RasConnStatus
  304. ZeroMemory(&RasConnStatus, sizeof(RASCONNSTATUS));
  305. // Set RasConnStatus
  306. RasConnStatus.dwSize = sizeof(RASCONNSTATUS);
  307. // Get the RAS connection status
  308. g_RasApi.RasGetConnectStatus(hRasConn, &RasConnStatus);
  309. // Initialize RasStats
  310. ZeroMemory(&RasStats, sizeof(RAS_STATS));
  311. // Set RasStats
  312. RasStats.dwSize = sizeof(RAS_STATS);
  313. // Get the connection statistics
  314. g_RasApi.RasGetConnectionStatistics(hRasConn, &RasStats);
  315. // Set the line speed
  316. RasInfo.dwBps = RasStats.dwBps;
  317. // Set the port name
  318. RasInfo.szDeviceName = RasConnStatus.szDeviceName;
  319. // Update the status
  320. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_LINESPEED, (LPARAM) &RasInfo);
  321. if (RasStats.dwBps < SUSPECT_RAS_SPEED) {
  322. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_SPEED_SUSPECT, SUSPECT_RAS_SPEED);
  323. }
  324. else {
  325. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_PASSED, 0);
  326. }
  327. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_STOPPING, 0);
  328. // Stop the RAS session
  329. g_RasApi.RasHangUp(hRasConn);
  330. return IDS_STATUS_RAS_PASSED;
  331. }
  332. UINT
  333. fnSendFax(
  334. FAX_JOB_PARAM FaxJobParams,
  335. LPWSTR szDocumentName,
  336. LPHANDLE phFaxStopSendPassFailEvents,
  337. DWORD dwSendTimeout
  338. )
  339. /*++
  340. Routine Description:
  341. Sends a fax
  342. Arguments:
  343. FaxJobParams - fax job parameters
  344. szDocumentName - name of document to send
  345. phFaxStopSendPassFailEvents - pointer to the g_hFaxEvent, g_hStopEvent, g_hSendPassedEvent and g_hSendFailedEvent
  346. dwSendTimeout - send timeout interval
  347. Return Value:
  348. UINT - resource id
  349. --*/
  350. {
  351. DWORD dwRslt;
  352. UINT uRslt;
  353. // Update the status
  354. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_STARTING, (LPARAM) FaxJobParams.RecipientNumber);
  355. if (!g_bNoCheck) {
  356. // Update the status
  357. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_ID, (LPARAM) FaxJobParams.Tsid);
  358. }
  359. // Send a fax
  360. if (!FaxSendDocument(g_hFaxSvcHandle, szDocumentName, &FaxJobParams, NULL, &g_dwFaxId)) {
  361. return IDS_STATUS_FAX_SEND_FAILED;
  362. }
  363. g_bFaxSndInProgress = TRUE;
  364. g_dwAttempt = 0;
  365. // Wait for Fax, Stop, Send Passed or Send Failed event
  366. dwRslt = WaitForMultipleObjects(4, phFaxStopSendPassFailEvents, FALSE, dwSendTimeout);
  367. g_bFaxSndInProgress = FALSE;
  368. switch (dwRslt) {
  369. case WAIT_TIMEOUT:
  370. uRslt = IDS_STATUS_TIMEOUT_ENDED;
  371. break;
  372. case WAIT_OBJECT_0:
  373. uRslt = IDS_STATUS_FAXSVC_ENDED;
  374. break;
  375. case (WAIT_OBJECT_0 + 1):
  376. uRslt = IDS_STATUS_ITERATION_STOPPED;
  377. break;
  378. case (WAIT_OBJECT_0 + 2):
  379. uRslt = IDS_STATUS_FAX_SEND_PASSED;
  380. break;
  381. case (WAIT_OBJECT_0 + 3):
  382. uRslt = IDS_STATUS_FAX_SEND_FAILED;
  383. break;
  384. }
  385. if (uRslt != IDS_STATUS_FAX_SEND_PASSED) {
  386. if (uRslt == IDS_STATUS_ITERATION_STOPPED) {
  387. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_STOPPING, 0);
  388. }
  389. FaxAbort(g_hFaxSvcHandle, g_dwFaxId);
  390. return uRslt;
  391. }
  392. return IDS_STATUS_FAX_SEND_PASSED;
  393. }
  394. UINT
  395. fnReceiveFax(
  396. LPHANDLE phFaxStopRcvEvents,
  397. DWORD dwReceiveTimeout,
  398. LPWSTR szTsid,
  399. DWORD dwTsidSize,
  400. LPWSTR szCopyTiffFile,
  401. DWORD dwCopyTiffFileSize,
  402. LPWSTR szCopyTiffName,
  403. DWORD dwCopyTiffNameSize
  404. )
  405. /*++
  406. Routine Description:
  407. Receives a fax
  408. Arguments:
  409. phFaxStopRcvEvents - pointer to the g_hFaxEvent, g_hStopEvent and hFaxRcvEvent
  410. dwReceiveTimeout - receive timeout interval
  411. szTsid - TSID of the received fax
  412. dwTsidSize - size of szTsid buffer, in bytes
  413. szCopyTiffFile - name of the copy of the received fax
  414. dwCopyTiffFileSize - size of szCopyTiffFile buffer, in bytes
  415. szCopyTiffName - name of the copy of the received fax
  416. dwCopyTiffNameSize - size of szCopyTiffName buffer, in bytes
  417. Return Value:
  418. UINT - resource id
  419. --*/
  420. {
  421. // hFaxRcvEvent is the handle to the FaxRcv named event
  422. HANDLE hFaxRcvEvent;
  423. // hFaxRcvMutex is the handle to the FaxRcv named mutex
  424. HANDLE hFaxRcvMutex;
  425. // hFaxRcvMap is the handle to the FaxRcv memory map
  426. HANDLE hFaxRcvMap;
  427. // pFaxRcvView is the pointer to the FaxRcv memory map view
  428. LPBYTE pFaxRcvView;
  429. // szTiffFile is the name of the received fax
  430. LPWSTR szTiffFile;
  431. // szFile is the name of the received fax
  432. WCHAR szFile[_MAX_FNAME];
  433. // szExt is the extension of the received fax
  434. WCHAR szExt[_MAX_EXT];
  435. // FaxReceiveInfo is the fax receive info
  436. FAX_RECEIVE_INFO FaxReceiveInfo;
  437. DWORD dwRslt;
  438. UINT uRslt;
  439. UINT_PTR upOffset;
  440. // Update the status
  441. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_WAITING, 0);
  442. // Open FaxRcv named event
  443. hFaxRcvEvent = OpenEvent(SYNCHRONIZE, FALSE, FAXRCV_EVENT);
  444. // Open FaxRcv named mutex
  445. hFaxRcvMutex = OpenMutex(SYNCHRONIZE, FALSE, FAXRCV_MUTEX);
  446. if ((!hFaxRcvEvent) || (!hFaxRcvMutex)) {
  447. if (hFaxRcvEvent) {
  448. CloseHandle(hFaxRcvEvent);
  449. }
  450. if (hFaxRcvMutex) {
  451. CloseHandle(hFaxRcvMutex);
  452. }
  453. return IDS_STATUS_FAXSVC_ENDED;
  454. }
  455. // Update phFaxStopRcvEvents
  456. // hFaxRcvEvent
  457. phFaxStopRcvEvents[2] = hFaxRcvEvent;
  458. // Wait for FaxRcv named mutex
  459. WaitForSingleObject(hFaxRcvMutex, INFINITE);
  460. // Enable the FaxRcv Routing Extension
  461. fnEnableFaxRcv(TRUE);
  462. // Release access to the FaxRcv named mutex
  463. ReleaseMutex(hFaxRcvMutex);
  464. g_bFaxRcvInProgress = TRUE;
  465. // Wait for Fax, Stop or FaxRcv named event
  466. dwRslt = WaitForMultipleObjects(3, phFaxStopRcvEvents, FALSE, dwReceiveTimeout);
  467. g_bFaxRcvInProgress = FALSE;
  468. // Wait for FaxRcv named mutex
  469. WaitForSingleObject(hFaxRcvMutex, INFINITE);
  470. // Disable the FaxRcv Routing Extension
  471. fnEnableFaxRcv(FALSE);
  472. switch (dwRslt) {
  473. case WAIT_TIMEOUT:
  474. uRslt = IDS_STATUS_TIMEOUT_ENDED;
  475. break;
  476. case WAIT_OBJECT_0:
  477. uRslt = IDS_STATUS_FAXSVC_ENDED;
  478. break;
  479. case (WAIT_OBJECT_0 + 1):
  480. uRslt = IDS_STATUS_ITERATION_STOPPED;
  481. break;
  482. case (WAIT_OBJECT_0 + 2):
  483. uRslt = IDS_STATUS_FAX_RECEIVED;
  484. break;
  485. }
  486. if (uRslt != IDS_STATUS_FAX_RECEIVED) {
  487. // Release access to the FaxRcv named mutex
  488. ReleaseMutex(hFaxRcvMutex);
  489. CloseHandle(hFaxRcvEvent);
  490. CloseHandle(hFaxRcvMutex);
  491. return uRslt;
  492. }
  493. // Open FaxRcv memory map
  494. hFaxRcvMap = OpenFileMapping(FILE_MAP_READ, FALSE, FAXRCV_MAP);
  495. if (!hFaxRcvMap) {
  496. // Release access to the FaxRcv named mutex
  497. ReleaseMutex(hFaxRcvMutex);
  498. CloseHandle(hFaxRcvEvent);
  499. CloseHandle(hFaxRcvMutex);
  500. return IDS_STATUS_FAXSVC_ENDED;
  501. }
  502. // Create FaxRcv memory map view
  503. pFaxRcvView = (LPBYTE) MapViewOfFile(hFaxRcvMap, FILE_MAP_READ, 0, 0, 0);
  504. // Set upOffset
  505. upOffset = 0;
  506. // Set szTiffFile
  507. szTiffFile = MemAllocMacro((lstrlen((LPWSTR) ((UINT_PTR) pFaxRcvView + upOffset)) + 1) * sizeof(WCHAR));
  508. lstrcpy(szTiffFile, (LPWSTR) ((UINT_PTR) pFaxRcvView + upOffset));
  509. upOffset += (lstrlen(szTiffFile) + 1) * sizeof(WCHAR);
  510. // Initialize szTsid
  511. ZeroMemory(szTsid, dwTsidSize);
  512. // Set szTsid
  513. lstrcpy(szTsid, (LPWSTR) ((UINT_PTR) pFaxRcvView + upOffset));
  514. upOffset += (lstrlen(szTsid) + 1) * sizeof(WCHAR);
  515. // Set FaxReceiveInfo.dwDeviceId
  516. FaxReceiveInfo.dwDeviceId = (DWORD) *(LPDWORD) ((UINT_PTR) pFaxRcvView + upOffset);
  517. // Close FaxRcv memory map view
  518. UnmapViewOfFile(pFaxRcvView);
  519. // Close FaxRcv memory map
  520. CloseHandle(hFaxRcvMap);
  521. _wsplitpath(szTiffFile, NULL, NULL, szFile, szExt);
  522. // Initialize szCopyTiffFile
  523. ZeroMemory(szCopyTiffFile, dwCopyTiffFileSize * sizeof(WCHAR));
  524. // Set szCopyTiffFile
  525. GetCurrentDirectory(dwCopyTiffFileSize, szCopyTiffFile);
  526. lstrcat(szCopyTiffFile, L"\\");
  527. lstrcat(szCopyTiffFile, (LPWSTR) ((UINT_PTR) szFile + lstrlen(L"Copy of ") * sizeof(WCHAR)));
  528. lstrcat(szCopyTiffFile, szExt);
  529. // Initialize szCopyTiffName
  530. ZeroMemory(szCopyTiffName, dwCopyTiffNameSize);
  531. // Set szCopyTiffName
  532. lstrcpy(szCopyTiffName, (LPWSTR) ((UINT_PTR) szFile + lstrlen(L"Copy of ") * sizeof(WCHAR)));
  533. lstrcat(szCopyTiffName, szExt);
  534. // Set FaxReceiveInfo.szCopyTiffName
  535. FaxReceiveInfo.szCopyTiffName = szCopyTiffName;
  536. // Copy szTiffFile to szCopyTiffFile
  537. CopyFile(szTiffFile, szCopyTiffFile, FALSE);
  538. // Delete the received fax
  539. DeleteFile(szTiffFile);
  540. // Free szTiffFile
  541. MemFreeMacro(szTiffFile);
  542. // Release access to the FaxRcv named mutex
  543. ReleaseMutex(hFaxRcvMutex);
  544. CloseHandle(hFaxRcvEvent);
  545. CloseHandle(hFaxRcvMutex);
  546. // Update the status
  547. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_RECEIVED, (LPARAM) &FaxReceiveInfo);
  548. return IDS_STATUS_FAX_RECEIVED;
  549. }
  550. DWORD WINAPI fnSendProc (LPVOID lpv)
  551. /*++
  552. Routine Description:
  553. Thread to handle the Send logic
  554. Return Value:
  555. DWORD - exit code
  556. --*/
  557. {
  558. // hFaxExitStartEvents is a pointer to the g_hFaxEvent, g_hExitEvent and g_hStartEvent
  559. HANDLE hFaxExitStartEvents[3];
  560. // hFaxStopRasPassFailEvents is a pointer to the g_hFaxEvent, g_hStopEvent, g_hRasPassedEvent and g_hRasFailedEvent
  561. HANDLE hFaxStopRasPassFailEvents[4];
  562. // hFaxStopSendPassFailEvents is a pointer to the g_hFaxEvent, g_hStopEvent, g_hSendPassedEvent and g_hSendFailedEvent
  563. HANDLE hFaxStopSendPassFailEvents[4];
  564. // hFaxStopRcvEvents is a pointer to the g_hFaxEvent, g_hStopEvent and g_hFaxRcvEvent
  565. HANDLE hFaxStopRcvEvents[3];
  566. // dwSendTimeout is the send timeout interval
  567. DWORD dwSendTimeout;
  568. // dwReceiveTimeout is the receive timeout interval
  569. DWORD dwReceiveTimeout;
  570. // szOriginalTiffFile is the name of the original tiff file
  571. LPWSTR szOriginalTiffFile;
  572. // dwNumFaxesToSend is the number of faxes to be sent
  573. DWORD dwNumFaxesToSend;
  574. // dwNumFaxesRemaining is the number of faxes remaining to be sent
  575. DWORD dwNumFaxesRemaining;
  576. // FaxJobParams is the fax job params
  577. FAX_JOB_PARAM FaxJobParams;
  578. // szCopyTiffFile is the name of the copy of the received fax
  579. WCHAR szCopyTiffFile[_MAX_PATH];
  580. // szCopyTiffName is the name of the copy of the received fax
  581. WCHAR szCopyTiffName[_MAX_FNAME + _MAX_EXT];
  582. // szReceivedTsid is the received TSID
  583. WCHAR szReceivedTsid[ENCODE_CHAR_LEN + CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1];
  584. // szEncodedTsid is the encoded TSID
  585. WCHAR szEncodedTsid[ENCODE_CHAR_LEN + CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1];
  586. // szDecodedTsid is the decoded TSID
  587. WCHAR szDecodedTsid[PHONE_NUM_LEN + 1];
  588. DWORD dwPages;
  589. DWORD dwRslt;
  590. UINT uRslt;
  591. // Set hFaxExitStartEvents
  592. // g_hFaxEvent
  593. hFaxExitStartEvents[0] = g_hFaxEvent;
  594. // g_hExitEvent
  595. hFaxExitStartEvents[1] = g_hExitEvent;
  596. // g_hStartEvent
  597. hFaxExitStartEvents[2] = g_hStartEvent;
  598. // Set hFaxStopRasPassFailEvents
  599. // g_hFaxEvent
  600. hFaxStopRasPassFailEvents[0] = g_hFaxEvent;
  601. // g_hStopEvent
  602. hFaxStopRasPassFailEvents[1] = g_hStopEvent;
  603. // g_hPassEvent
  604. hFaxStopRasPassFailEvents[2] = g_hRasPassedEvent;
  605. // g_hFailEvent
  606. hFaxStopRasPassFailEvents[3] = g_hRasFailedEvent;
  607. // Set hFaxStopSendPassFailEvents
  608. // g_hFaxEvent
  609. hFaxStopSendPassFailEvents[0] = g_hFaxEvent;
  610. // g_hStopEvent
  611. hFaxStopSendPassFailEvents[1] = g_hStopEvent;
  612. // g_hSendPassedEvent
  613. hFaxStopSendPassFailEvents[2] = g_hSendPassedEvent;
  614. // g_hSendFailedEvent
  615. hFaxStopSendPassFailEvents[3] = g_hSendFailedEvent;
  616. // Set hFaxStopRcvEvents
  617. // g_hFaxEvent
  618. hFaxStopRcvEvents[0] = g_hFaxEvent;
  619. // g_hStopEvent
  620. hFaxStopRcvEvents[1] = g_hStopEvent;
  621. if (g_bBVT) {
  622. dwSendTimeout = FAXSVC_RETRIES * ((FAXSVC_RETRIES + 1) * FAXSVC_RETRYDELAY) * 60000;
  623. dwReceiveTimeout = dwSendTimeout * 2;
  624. szOriginalTiffFile = FAXBVT_TIF;
  625. dwNumFaxesToSend = FAXBVT_NUM_FAXES;
  626. dwNumFaxesRemaining = dwNumFaxesToSend;
  627. }
  628. else {
  629. dwSendTimeout = INFINITE;
  630. dwReceiveTimeout = INFINITE;
  631. szOriginalTiffFile = FAXWHQL_TIF;
  632. dwNumFaxesToSend = FAXWHQL_NUM_FAXES;
  633. dwNumFaxesRemaining = dwNumFaxesToSend;
  634. }
  635. while (TRUE) {
  636. // Wait for Fax, Exit, or Start event
  637. dwRslt = WaitForMultipleObjects(3, hFaxExitStartEvents, FALSE, INFINITE);
  638. if (dwRslt == WAIT_OBJECT_0) {
  639. SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
  640. continue;
  641. }
  642. else if (dwRslt == (WAIT_OBJECT_0 + 1)) {
  643. return 0;
  644. }
  645. if (g_bSend) {
  646. if (g_bRasEnabled) {
  647. // Send a RAS call
  648. uRslt = fnSendRas(hFaxStopRasPassFailEvents);
  649. if (uRslt != IDS_STATUS_RAS_PASSED) {
  650. switch (uRslt) {
  651. case IDS_STATUS_TIMEOUT_ENDED:
  652. SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
  653. break;
  654. case IDS_STATUS_FAXSVC_ENDED:
  655. SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
  656. break;
  657. case IDS_STATUS_ITERATION_STOPPED:
  658. SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
  659. break;
  660. case IDS_STATUS_RAS_FAILED:
  661. SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
  662. break;
  663. }
  664. dwNumFaxesRemaining = dwNumFaxesToSend;
  665. continue;
  666. }
  667. }
  668. // Encode the TSID
  669. if (!g_bNoCheck) {
  670. fnEncodeTsid(g_szRcvNumber, TX_CONTROL_CHARS, szEncodedTsid);
  671. }
  672. else {
  673. lstrcpy(szEncodedTsid, g_szSndNumber);
  674. }
  675. // Initialize FaxJobParams
  676. ZeroMemory(&FaxJobParams, sizeof(FAX_JOB_PARAM));
  677. // Set FaxJobParams
  678. FaxJobParams.SizeOfStruct = sizeof(FAX_JOB_PARAM);
  679. FaxJobParams.RecipientNumber = g_szSndNumber;
  680. FaxJobParams.RecipientName = g_szSndNumber;
  681. FaxJobParams.Tsid = szEncodedTsid;
  682. FaxJobParams.ScheduleAction = JSA_NOW;
  683. // Send a fax
  684. uRslt = fnSendFax(FaxJobParams, szOriginalTiffFile, hFaxStopSendPassFailEvents, dwSendTimeout);
  685. if (uRslt != IDS_STATUS_FAX_SEND_PASSED) {
  686. switch (uRslt) {
  687. case IDS_STATUS_TIMEOUT_ENDED:
  688. SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
  689. break;
  690. case IDS_STATUS_FAXSVC_ENDED:
  691. SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
  692. break;
  693. case IDS_STATUS_ITERATION_STOPPED:
  694. SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
  695. break;
  696. case IDS_STATUS_FAX_SEND_FAILED:
  697. SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
  698. break;
  699. }
  700. dwNumFaxesRemaining = dwNumFaxesToSend;
  701. continue;
  702. }
  703. }
  704. // Receive a fax
  705. uRslt = fnReceiveFax(hFaxStopRcvEvents, dwReceiveTimeout, szReceivedTsid, sizeof(szReceivedTsid) / sizeof(WCHAR), szCopyTiffFile, sizeof(szCopyTiffFile) / sizeof(WCHAR), szCopyTiffName, sizeof(szCopyTiffName) / sizeof(WCHAR));
  706. if (uRslt != IDS_STATUS_FAX_RECEIVED) {
  707. switch (uRslt) {
  708. case IDS_STATUS_TIMEOUT_ENDED:
  709. SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
  710. break;
  711. case IDS_STATUS_FAXSVC_ENDED:
  712. SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
  713. break;
  714. case IDS_STATUS_ITERATION_STOPPED:
  715. SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
  716. break;
  717. }
  718. if (g_bSend) {
  719. if (uRslt != IDS_STATUS_ITERATION_STOPPED) {
  720. // This iteration failed
  721. SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
  722. }
  723. // Reset the number of faxes remaining to be sent
  724. dwNumFaxesRemaining = dwNumFaxesToSend;
  725. }
  726. continue;
  727. }
  728. if (!g_bNoCheck) {
  729. if (!fnDecodeTsid(szReceivedTsid, g_bSend ? RX_CONTROL_CHARS : TX_CONTROL_CHARS, szDecodedTsid)) {
  730. // Update the status
  731. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_INVALID, 0);
  732. if (g_bSend) {
  733. // This iteration failed
  734. SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
  735. // Reset the number of faxes remaining to be sent
  736. dwNumFaxesRemaining = dwNumFaxesToSend;
  737. }
  738. else {
  739. // Set the g_hStartEvent to start another cycle to receive a fax
  740. SetEvent(g_hStartEvent);
  741. }
  742. continue;
  743. }
  744. // Update the status
  745. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_ID, (LPARAM) szReceivedTsid);
  746. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_VERIFYING, (LPARAM) szCopyTiffName);
  747. // Verify the tiff
  748. uRslt = fnVerifyTiff(szCopyTiffFile, &dwPages);
  749. if ((uRslt == ERROR_SUCCESS) && (((g_bBVT) && (dwPages == FAXBVT_PAGES)) || ((!g_bBVT) && (dwPages == FAXWHQL_PAGES)))) {
  750. // Fax is valid
  751. uRslt = IDS_TIFF_VALID_TIFF;
  752. }
  753. else if (uRslt == ERROR_SUCCESS) {
  754. // Each page is valid, but missing pages
  755. uRslt = IDS_TIFF_INVALID_PAGES;
  756. }
  757. if (uRslt == IDS_TIFF_INVALID_PAGES) {
  758. // Update the status
  759. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, uRslt, dwPages);
  760. }
  761. else {
  762. // Update the status
  763. SendMessage(g_hWndDlg, UM_UPDATE_STATUS, uRslt, 0);
  764. }
  765. }
  766. else {
  767. lstrcpy(szDecodedTsid, szReceivedTsid);
  768. uRslt = IDS_TIFF_VALID_TIFF;
  769. }
  770. if ((g_bSend) && (uRslt == IDS_TIFF_VALID_TIFF)) {
  771. // Decrement the number of faxes remaining to be sent
  772. dwNumFaxesRemaining--;
  773. if (dwNumFaxesRemaining == 0) {
  774. // All faxes have been sent, so this iteration passed
  775. SendMessage(g_hWndDlg, UM_ITERATION_PASSED, 0, 0);
  776. // Reset the number of faxes remaining to be sent
  777. dwNumFaxesRemaining = dwNumFaxesToSend;
  778. }
  779. else {
  780. // There are faxes remaining to be sent, so set the g_hStartEvent to start another cycle to send a fax
  781. SetEvent(g_hStartEvent);
  782. }
  783. continue;
  784. }
  785. else if (g_bSend) {
  786. // This iteration failed
  787. SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
  788. // Reset the number of faxes remaining to be sent
  789. dwNumFaxesRemaining = dwNumFaxesToSend;
  790. continue;
  791. }
  792. else if (uRslt != IDS_TIFF_VALID_TIFF) {
  793. // Set the g_hStartEvent to start another cycle to receive a fax
  794. SetEvent(g_hStartEvent);
  795. continue;
  796. }
  797. if (!g_bSend) {
  798. // Encode the TSID
  799. if (!g_bNoCheck) {
  800. fnEncodeTsid(szDecodedTsid, RX_CONTROL_CHARS, szEncodedTsid);
  801. }
  802. else {
  803. lstrcpy(szEncodedTsid, szDecodedTsid);
  804. }
  805. // Initialize FaxJobParams
  806. ZeroMemory(&FaxJobParams, sizeof(FAX_JOB_PARAM));
  807. // Set FaxJobParams
  808. FaxJobParams.SizeOfStruct = sizeof(FAX_JOB_PARAM);
  809. FaxJobParams.RecipientNumber = szDecodedTsid;
  810. FaxJobParams.RecipientName = szDecodedTsid;
  811. FaxJobParams.Tsid = szEncodedTsid;
  812. FaxJobParams.ScheduleAction = JSA_NOW;
  813. // Send a fax
  814. uRslt = fnSendFax(FaxJobParams, szCopyTiffFile, hFaxStopSendPassFailEvents, dwSendTimeout);
  815. switch (uRslt) {
  816. case IDS_STATUS_TIMEOUT_ENDED:
  817. SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
  818. break;
  819. case IDS_STATUS_FAXSVC_ENDED:
  820. SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
  821. break;
  822. case IDS_STATUS_ITERATION_STOPPED:
  823. SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
  824. break;
  825. case IDS_STATUS_FAX_SEND_PASSED:
  826. case IDS_STATUS_FAX_SEND_FAILED:
  827. break;
  828. }
  829. if ((uRslt == IDS_STATUS_FAX_SEND_PASSED) || (uRslt == IDS_STATUS_FAX_SEND_FAILED)) {
  830. if (g_bBVT) {
  831. SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
  832. SendMessage(GetDlgItem(g_hWndDlg, IDC_EXIT_BUTTON), BM_CLICK, 0, 0);
  833. }
  834. else {
  835. // Set the g_hStartEvent to start another cycle to wait for a fax
  836. SetEvent(g_hStartEvent);
  837. }
  838. }
  839. continue;
  840. }
  841. }
  842. }
  843. #endif