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.

884 lines
21 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. client16.c
  5. Abstract:
  6. Support for 16-bit (win31 and win95) fax clients
  7. Environment:
  8. Windows NT fax monitor
  9. Revision History:
  10. 06/02/96 -davidx-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "faxmon.h"
  16. #include "tiffstub.h"
  17. #include "prtcovpg.h"
  18. #include "jobtag.h"
  19. //
  20. // File header for the fax data from downlevel client
  21. //
  22. #define FAX16_SIGNATURE 'NF16'
  23. typedef struct {
  24. WORD Magic; // 'II'
  25. WORD Magic2; // 0x0042
  26. DWORD FirstIFDOffset; // offset to the first IFD
  27. DWORD Fax16Signature; // 'NF16'
  28. DWORD CodePage; // code page use for converting multibyte strings to Unicode
  29. DWORD SenderName; // sender's name string
  30. DWORD SenderFaxNumber; // sender's fax number string
  31. DWORD SenderCompany; // sender's company string
  32. DWORD SenderAddress; // sender's address string
  33. DWORD SenderTitle; // sender's title string
  34. DWORD SenderDepartment; // sender's department string
  35. DWORD SenderOffice; // sender's office location string
  36. DWORD SenderHomePhone; // sender's home phone number string
  37. DWORD SenderOfficePhone; // sender's office phone number string
  38. DWORD RecName; // recipient's name string
  39. DWORD RecFaxNumber; // recipient's fax number string
  40. DWORD RecCompany; // recipient's company string
  41. DWORD RecAddress; // recipient's address string
  42. DWORD RecCity; // recipient's city string
  43. DWORD RecState; // recipient's state string
  44. DWORD RecZip; // recipient's zip code string
  45. DWORD RecCountry; // recipient's country string
  46. DWORD RecTitle; // recipient's title string
  47. DWORD RecDepartment; // recipient's department string
  48. DWORD RecOffice; // recipient's office string
  49. DWORD RecHomePhone; // recipient's home phone number string
  50. DWORD RecOfficePhone; // recipient's office phone number string
  51. DWORD SubjectLine; // subject string
  52. DWORD NoteMessage; // note string
  53. DWORD TimeSent; // time-sent string
  54. DWORD BillingCode; // billing code string
  55. DWORD CoverPageFilename; // cover page filename string
  56. DWORD CoverPageDataSize; // size of embedded cover page file in bytes
  57. DWORD CoverPageData; // offset to beginning of embedded cover page file
  58. DWORD NumberOfPages; // number of pages (not including the cover page)
  59. DWORD EmailNotify; // offset to Email notification address
  60. DWORD Reserved[7]; // reserved - must be 0 for now
  61. //
  62. // String data and embedded cover page file if any
  63. //
  64. } FAX16_TIFF_HEADER, *PFAX16_TIFF_HEADER;
  65. LPWSTR
  66. CopyClientStringToUnicode(
  67. PFAX16_TIFF_HEADER pFax16Hdr,
  68. ULONG_PTR offset
  69. )
  70. /*++
  71. Routine Description:
  72. Copy ANSI string from 16-bit clients to Unicode string
  73. Arguments:
  74. pFax16Hdr - Points to the fax data from downlevel client
  75. offset - Specifies the starting offset for the ANSI string
  76. Return Value:
  77. Pointer to the duplicated Unicode string
  78. NULL if there is an error
  79. --*/
  80. {
  81. LPSTR pAnsiStr;
  82. INT cch;
  83. LPWSTR pUnicodeStr = NULL;
  84. if (offset != 0) {
  85. pAnsiStr = (LPSTR) ((LPBYTE) pFax16Hdr + offset);
  86. cch = strlen(pAnsiStr);
  87. if (pUnicodeStr = MemAllocZ((cch + 1) * sizeof(WCHAR)))
  88. MultiByteToWideChar(pFax16Hdr->CodePage, 0, pAnsiStr, cch, pUnicodeStr, cch);
  89. }
  90. return pUnicodeStr;
  91. }
  92. VOID
  93. FreeCoverPageFields(
  94. PCOVERPAGEFIELDS pCPFields
  95. )
  96. /*++
  97. Routine Description:
  98. Dispose of cover page field information
  99. Arguments:
  100. pCPFields - Points to cover page field information
  101. Return Value:
  102. NONE
  103. --*/
  104. {
  105. if (pCPFields != NULL) {
  106. LPTSTR *ppStr;
  107. LONG_PTR count;
  108. //
  109. // Free individual cover page field strings.
  110. // HACK: We assume all fields between RecName and ToList are LPTSTRs.
  111. //
  112. ppStr = &pCPFields->RecName;
  113. count = (offsetof(COVERPAGEFIELDS, ToList) -
  114. offsetof(COVERPAGEFIELDS, RecName)) / sizeof(LPTSTR);
  115. while (count-- > 0) {
  116. MemFree(*ppStr);
  117. ppStr++;
  118. }
  119. MemFree(pCPFields);
  120. }
  121. }
  122. PCOVERPAGEFIELDS
  123. CollectFax16CoverPageFields(
  124. PFAX16_TIFF_HEADER pFax16Hdr
  125. )
  126. /*++
  127. Routine Description:
  128. Collect cover page field information from 16bit client fax job
  129. Arguments:
  130. pFax16Hdr - Points to the fax data from downlevel client
  131. Return Value:
  132. Pointer to cover page field information
  133. NULL if there is an error
  134. --*/
  135. {
  136. //
  137. // Map fields in FAX16_TIFF_HEADER to fields in COVERPAGEFIELDS.
  138. // HACK: We assume all fields between RecName and NumberOfPages are LPTSTRs.
  139. //
  140. #define NUM_CPFIELDS ((offsetof(COVERPAGEFIELDS, NumberOfPages) - \
  141. offsetof(COVERPAGEFIELDS, RecName)) / sizeof(LPTSTR))
  142. ULONG_PTR strOffsets[NUM_CPFIELDS] = {
  143. pFax16Hdr->RecName,
  144. pFax16Hdr->RecFaxNumber,
  145. pFax16Hdr->RecCompany,
  146. pFax16Hdr->RecAddress,
  147. pFax16Hdr->RecCity,
  148. pFax16Hdr->RecState,
  149. pFax16Hdr->RecZip,
  150. pFax16Hdr->RecCountry,
  151. pFax16Hdr->RecTitle,
  152. pFax16Hdr->RecDepartment,
  153. pFax16Hdr->RecOffice,
  154. pFax16Hdr->RecHomePhone,
  155. pFax16Hdr->RecOfficePhone,
  156. pFax16Hdr->SenderName,
  157. pFax16Hdr->SenderFaxNumber,
  158. pFax16Hdr->SenderCompany,
  159. pFax16Hdr->SenderAddress,
  160. pFax16Hdr->SenderTitle,
  161. pFax16Hdr->SenderDepartment,
  162. pFax16Hdr->SenderOffice,
  163. pFax16Hdr->SenderHomePhone,
  164. pFax16Hdr->SenderOfficePhone,
  165. pFax16Hdr->NoteMessage,
  166. pFax16Hdr->SubjectLine,
  167. pFax16Hdr->TimeSent,
  168. };
  169. PCOVERPAGEFIELDS pCPFields;
  170. LPTSTR *ppStr;
  171. LONG_PTR index;
  172. if ((pCPFields = MemAllocZ(sizeof(COVERPAGEFIELDS))) == NULL)
  173. return NULL;
  174. //
  175. // Convert individual cover page field from ANSI to Unicode string
  176. //
  177. for (index=0, ppStr = &pCPFields->RecName; index < NUM_CPFIELDS; index++, ppStr++) {
  178. if ((strOffsets[index] != 0) &&
  179. (*ppStr = CopyClientStringToUnicode(pFax16Hdr, strOffsets[index])) == NULL)
  180. {
  181. FreeCoverPageFields(pCPFields);
  182. return NULL;
  183. }
  184. }
  185. //
  186. // Number of pages printed
  187. //
  188. if ((pCPFields->NumberOfPages = MemAllocZ(sizeof(TCHAR) * 16)) == NULL) {
  189. FreeCoverPageFields(pCPFields);
  190. return NULL;
  191. }
  192. return pCPFields;
  193. }
  194. BOOL
  195. CollectFax16JobParam(
  196. PFAXPORT pFaxPort,
  197. PCOVERPAGEFIELDS pCPFields,
  198. LPTSTR pBillingCode
  199. )
  200. /*++
  201. Routine Description:
  202. Collect 16-bit client fax job parameters
  203. Arguments:
  204. pFaxPort - Points to a fax port structure
  205. pCPFields - Points to cover page field information
  206. pBillingCode - Points to billing code string from 16-bit client
  207. Return Value:
  208. TRUE if successful, FALSE otherwise
  209. --*/
  210. {
  211. //
  212. // Cover page fields which are passed fax service as parameters
  213. //
  214. LPTSTR pSrcStr[NUM_JOBPARAM_TAGS] = {
  215. pCPFields->RecFaxNumber,
  216. pCPFields->RecName,
  217. pCPFields->SdrFaxNumber,
  218. pCPFields->SdrName,
  219. pCPFields->SdrCompany,
  220. pCPFields->SdrDepartment,
  221. pBillingCode
  222. };
  223. LPTSTR *ppDestStr[NUM_JOBPARAM_TAGS] = {
  224. (LPTSTR *)&pFaxPort->jobParam.RecipientNumber,
  225. (LPTSTR *)&pFaxPort->jobParam.RecipientName,
  226. (LPTSTR *)&pFaxPort->jobParam.Tsid,
  227. (LPTSTR *)&pFaxPort->jobParam.SenderName,
  228. (LPTSTR *)&pFaxPort->jobParam.SenderCompany,
  229. (LPTSTR *)&pFaxPort->jobParam.SenderDept,
  230. (LPTSTR *)&pFaxPort->jobParam.BillingCode
  231. };
  232. INT size, index;
  233. LPTSTR p;
  234. //
  235. // Calculate the total length for all parameters
  236. //
  237. for (index=size=0; index < NUM_JOBPARAM_TAGS; index++) {
  238. if (pSrcStr[index])
  239. size += SizeOfString(pSrcStr[index]);
  240. }
  241. //
  242. // Concatenate all parameters into a single string
  243. //
  244. if (size > 0 && (p = pFaxPort->pParameters = MemAllocZ(size))) {
  245. for (index=0; index < NUM_JOBPARAM_TAGS; index++) {
  246. if (pSrcStr[index]) {
  247. *ppDestStr[index] = p;
  248. _tcscpy(p, pSrcStr[index]);
  249. p += _tcslen(p) + 1;
  250. }
  251. }
  252. }
  253. return (pFaxPort->pParameters != NULL);
  254. }
  255. LPTSTR
  256. GetClientCoverPageFile(
  257. PFAX16_TIFF_HEADER pFax16Hdr
  258. )
  259. /*++
  260. Routine Description:
  261. Return the cover page file associated with a 16-bit client fax job
  262. Arguments:
  263. pFax16Hdr - Points to the fax data from downlevel client
  264. Return Value:
  265. Points to the name of the cover page file
  266. NULL if there is an error
  267. --*/
  268. #define SERVER_CP_DIRECTORY TEXT("\\coverpg\\")
  269. {
  270. LPTSTR pFilename;
  271. if (pFax16Hdr->CoverPageFilename) {
  272. //
  273. // Use server-based cover page file
  274. //
  275. if (pFilename = CopyClientStringToUnicode(pFax16Hdr, pFax16Hdr->CoverPageFilename)) {
  276. LPTSTR pServerDir = NULL, p;
  277. DWORD cb, len;
  278. len = (_tcslen(SERVER_CP_DIRECTORY) + _tcslen(pFilename) + 1) * sizeof(TCHAR);
  279. if (!GetPrinterDriverDirectory(NULL, NULL, 1, NULL, 0, &cb) &&
  280. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  281. (pServerDir = MemAllocZ(cb + len)) &&
  282. GetPrinterDriverDirectory(NULL, NULL, 1, (PBYTE) pServerDir, cb, &cb))
  283. {
  284. //
  285. // Strip off the last component of the driver directory
  286. // which should be w32<arch>.
  287. //
  288. if (p = _tcsrchr(pServerDir, TEXT('\\')))
  289. *p = NUL;
  290. _tcscat(pServerDir, SERVER_CP_DIRECTORY);
  291. _tcscat(pServerDir, pFilename);
  292. MemFree(pFilename);
  293. pFilename = pServerDir;
  294. } else {
  295. MemFree(pServerDir);
  296. MemFree(pFilename);
  297. pFilename = NULL;
  298. }
  299. }
  300. } else if (pFilename = CreateTempFaxFile()) {
  301. //
  302. // Cover page data is embedded in the cover page job
  303. // Create a temporary file and copy cover page data into it
  304. //
  305. HANDLE hFile;
  306. DWORD cbWritten;
  307. BOOL copied = FALSE;
  308. Assert(pFax16Hdr->CoverPageData != 0 && pFax16Hdr->CoverPageDataSize != 0);
  309. hFile = CreateFile(pFilename,
  310. GENERIC_WRITE,
  311. 0,
  312. NULL,
  313. OPEN_ALWAYS | TRUNCATE_EXISTING,
  314. FILE_ATTRIBUTE_NORMAL,
  315. NULL);
  316. if (hFile != INVALID_HANDLE_VALUE) {
  317. copied = WriteFile(hFile,
  318. (LPBYTE) pFax16Hdr + pFax16Hdr->CoverPageData,
  319. pFax16Hdr->CoverPageDataSize,
  320. &cbWritten,
  321. NULL);
  322. CloseHandle(hFile);
  323. }
  324. if (! copied) {
  325. Error(("Failed to copy cover page data to a temporary file\n"));
  326. DeleteFile(pFilename);
  327. MemFree(pFilename);
  328. pFilename = NULL;
  329. }
  330. }
  331. return pFilename;
  332. }
  333. LPTSTR
  334. GetBaseNoteFilename(
  335. VOID
  336. )
  337. /*++
  338. Routine Description:
  339. Get the name of base cover page file in system32 directory
  340. Arguments:
  341. NONE
  342. Return Value:
  343. Pointer to name of base cover page file
  344. NULL if there is an error
  345. --*/
  346. #define BASENOTE_FILENAME TEXT("\\basenote.cov")
  347. {
  348. TCHAR systemDir[MAX_PATH];
  349. LPTSTR pBaseNoteName = NULL;
  350. COVDOCINFO covDocInfo;
  351. if (GetSystemDirectory(systemDir, MAX_PATH) &&
  352. (pBaseNoteName = MemAlloc(SizeOfString(systemDir) + SizeOfString(BASENOTE_FILENAME))))
  353. {
  354. _tcscpy(pBaseNoteName, systemDir);
  355. _tcscat(pBaseNoteName, BASENOTE_FILENAME);
  356. Verbose(("Base cover page filename: %ws\n", pBaseNoteName));
  357. if (PrintCoverPage(NULL, NULL, pBaseNoteName, &covDocInfo) ||
  358. ! (covDocInfo.Flags & COVFP_NOTE) ||
  359. ! (covDocInfo.Flags & COVFP_SUBJECT))
  360. {
  361. Error(("Invalid base cover page file: %ws\n", pBaseNoteName));
  362. MemFree(pBaseNoteName);
  363. pBaseNoteName = NULL;
  364. }
  365. }
  366. return pBaseNoteName;
  367. }
  368. BOOL
  369. ProcessFax16CoverPage(
  370. PFAXPORT pFaxPort,
  371. PFAX16_TIFF_HEADER pFax16Hdr
  372. )
  373. /*++
  374. Routine Description:
  375. Render the cover page for downlevel client into a temporary file
  376. Arguments:
  377. pFaxPort - Points to a fax port structure
  378. pFax16Hdr - Pointer to the fax data from downlevel client
  379. Return Value:
  380. TRUE if successful, FALSE if there is an error
  381. --*/
  382. {
  383. PCOVERPAGEFIELDS pCPFields;
  384. LPTSTR pBillingCode;
  385. INT result = FALSE;
  386. //
  387. // Make sure the recipient's fax number is specified
  388. //
  389. if (pFax16Hdr->RecFaxNumber == 0) {
  390. Error(("No recipient number is specified\n"));
  391. return FALSE;
  392. }
  393. //
  394. // Collect cover page field information and
  395. // assemble fax job parameters and
  396. // create a new temporary file for storing cover page job
  397. //
  398. pBillingCode = CopyClientStringToUnicode(pFax16Hdr, pFax16Hdr->BillingCode);
  399. if ((pCPFields = CollectFax16CoverPageFields(pFax16Hdr)) &&
  400. CollectFax16JobParam(pFaxPort, pCPFields, pBillingCode) &&
  401. (pFaxPort->pFilename = CreateTempFaxFile()))
  402. {
  403. LPTSTR pCPFilename = NULL;
  404. LPTSTR pBaseNoteName = NULL;
  405. DWORD pageCount = pFax16Hdr->NumberOfPages;
  406. BOOL renderCP;
  407. COVDOCINFO covDocInfo;
  408. //
  409. // Check if cover page is requested - either a server cover page filename
  410. // is specified or the cover page data is embedded in the file.
  411. //
  412. renderCP = (pFax16Hdr->CoverPageFilename ||
  413. (pFax16Hdr->CoverPageDataSize && pFax16Hdr->CoverPageData));
  414. ZeroMemory(&covDocInfo, sizeof(covDocInfo));
  415. if (renderCP) {
  416. if (pCPFilename = GetClientCoverPageFile(pFax16Hdr)) {
  417. //
  418. // Find out if the specified cover page contains note/subject fields
  419. //
  420. DWORD ec = PrintCoverPage( NULL, NULL, pCPFilename, &covDocInfo );
  421. if (ec) {
  422. Error(( "Cannot examine cover page: %d\n", ec ));
  423. }
  424. result = TRUE;
  425. pageCount++;
  426. }
  427. } else
  428. result = TRUE;
  429. //
  430. // Calculate the total number of pages including cover page(s)
  431. //
  432. if (((pCPFields->Note &&
  433. !IsEmptyString(pCPFields->Note) &&
  434. !(covDocInfo.Flags & COVFP_NOTE)) ||
  435. (pCPFields->Subject &&
  436. !IsEmptyString(pCPFields->Subject) &&
  437. !(covDocInfo.Flags & COVFP_SUBJECT))) &&
  438. (pBaseNoteName = GetBaseNoteFilename()))
  439. {
  440. renderCP = TRUE;
  441. pageCount++;
  442. }
  443. wsprintf(pCPFields->NumberOfPages, TEXT("%d"), pageCount);
  444. //
  445. // Render the fax cover page(s)
  446. //
  447. if (result && renderCP) {
  448. DOCINFO docinfo;
  449. HDC hdc = NULL;
  450. DEVMODE devmode, *pDevmode;
  451. ZeroMemory(&docinfo, sizeof(docinfo));
  452. docinfo.cbSize = sizeof(docinfo);
  453. docinfo.lpszDocName = TEXT("faxmon");
  454. docinfo.lpszOutput = pFaxPort->pFilename;
  455. renderCP = FALSE;
  456. if (covDocInfo.PaperSize > 0) {
  457. ZeroMemory(&devmode, sizeof(devmode));
  458. _tcsncpy(devmode.dmDeviceName, pFaxPort->pPrinterName, CCHDEVICENAME);
  459. devmode.dmSpecVersion = DM_SPECVERSION;
  460. devmode.dmSize = sizeof(devmode);
  461. devmode.dmFields = DM_PAPERSIZE|DM_ORIENTATION;
  462. devmode.dmPaperSize = covDocInfo.PaperSize;
  463. devmode.dmOrientation = covDocInfo.Orientation;
  464. pDevmode = &devmode;
  465. } else
  466. pDevmode = NULL;
  467. if ((hdc = CreateDC(NULL, pFaxPort->pPrinterName, NULL, pDevmode)) &&
  468. (StartDoc(hdc, &docinfo) > 0))
  469. {
  470. //
  471. // Render the user specified cover page
  472. //
  473. if (pCPFilename) {
  474. if (StartPage(hdc) > 0) {
  475. renderCP = PrintCoverPage(hdc, pCPFields, pCPFilename, &covDocInfo) == 0 ? TRUE : FALSE;
  476. EndPage(hdc);
  477. }
  478. } else
  479. renderCP = TRUE;
  480. //
  481. // Render the extra cover page for note and subject
  482. //
  483. if (pBaseNoteName && renderCP) {
  484. if (StartPage(hdc) > 0) {
  485. renderCP = PrintCoverPage(hdc, pCPFields, pBaseNoteName, &covDocInfo) == 0 ? TRUE : FALSE;
  486. EndPage(hdc);
  487. } else
  488. renderCP = FALSE;
  489. }
  490. if (renderCP)
  491. EndDoc(hdc);
  492. else
  493. AbortDoc(hdc);
  494. }
  495. result = renderCP;
  496. if (hdc)
  497. DeleteDC(hdc);
  498. }
  499. //
  500. // In the embedded cover page data case, we created a temporary
  501. // cover page file earlier. So delete it here.
  502. //
  503. if (pCPFilename && !pFax16Hdr->CoverPageFilename)
  504. DeleteFile(pCPFilename);
  505. MemFree(pCPFilename);
  506. MemFree(pBaseNoteName);
  507. }
  508. FreeCoverPageFields(pCPFields);
  509. MemFree(pBillingCode);
  510. //
  511. // Open the cover page TIFF file if there was no error
  512. //
  513. return result && OpenTempFaxFile(pFaxPort, TRUE);
  514. }
  515. BOOL
  516. ConcatFax16Data(
  517. PFAXPORT pFaxPort,
  518. PFAX16_TIFF_HEADER pFax16Hdr,
  519. DWORD size
  520. )
  521. /*++
  522. Routine Description:
  523. Concatenate the fax data from downlevel client to the end of cover page TIFF file
  524. Arguments:
  525. pFaxPort - Points to a fax port structure
  526. pFax16Hdr - Pointer to the fax data from downlevel client
  527. size - Size of the fax data from downlevel client
  528. Return Value:
  529. TRUE if successful, FALSE otherwise
  530. --*/
  531. {
  532. DWORD bytesWritten;
  533. return (pFax16Hdr->NumberOfPages == 0) ||
  534. (WriteFile(pFaxPort->hFile, pFax16Hdr, size, &bytesWritten, NULL) &&
  535. bytesWritten == size);
  536. }
  537. INT
  538. ProcessDownlevelFaxJob(
  539. PFAXPORT pFaxPort
  540. )
  541. /*++
  542. Routine Description:
  543. Process fax jobs sent from win31 and win95 clients
  544. Arguments:
  545. pFaxPort - Points to a fax port structure
  546. Return Value:
  547. error code FAXERR_*
  548. --*/
  549. {
  550. DWORD fileSize;
  551. LPVOID pFileView = NULL;
  552. HANDLE hFileMap = NULL;
  553. INT result = FAXERR_BAD_DATA16;
  554. LPTSTR pOrigFilename;
  555. //
  556. // Get the size of fax job file
  557. //
  558. FlushFileBuffers(pFaxPort->hFile);
  559. if ((fileSize = GetFileSize(pFaxPort->hFile, NULL)) == 0xffffffff ||
  560. (fileSize < sizeof(DWORD) * 2))
  561. {
  562. return FAXERR_FATAL;
  563. }
  564. //
  565. // Map the fax job data into memory
  566. //
  567. if (hFileMap = CreateFileMapping(pFaxPort->hFile, NULL, PAGE_READONLY, 0, 0, NULL))
  568. pFileView = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, fileSize);
  569. CloseHandle(pFaxPort->hFile);
  570. pFaxPort->hFile = INVALID_HANDLE_VALUE;
  571. pOrigFilename = pFaxPort->pFilename;
  572. pFaxPort->pFilename = NULL;
  573. __try {
  574. PFAX16_TIFF_HEADER pFax16Hdr = pFileView;
  575. //
  576. // Validate the fax data from the downlevel client
  577. //
  578. if (hFileMap != NULL &&
  579. pFileView != NULL &&
  580. ValidTiffFileHeader(pFileView) &&
  581. pFax16Hdr->Fax16Signature == FAX16_SIGNATURE)
  582. {
  583. //
  584. // Render the cover page into a temporary TIFF file
  585. // and concatenate the original TIFF data at the end
  586. //
  587. if (ProcessFax16CoverPage(pFaxPort, pFax16Hdr) &&
  588. ConcatFax16Data(pFaxPort, pFax16Hdr, fileSize))
  589. {
  590. result = FAXERR_NONE;
  591. } else {
  592. Error(("Error processing downlevel fax job\n"));
  593. result = FAXERR_FATAL;
  594. }
  595. } else {
  596. Error(("Bad TIFF file from downlevel fax client\n"));
  597. }
  598. } __except(EXCEPTION_EXECUTE_HANDLER) {
  599. Error(("Access violation while reading downlevel fax job\n"));
  600. }
  601. //
  602. // Perform necessary cleanup before returning to caller
  603. //
  604. if (pFileView)
  605. UnmapViewOfFile(pFileView);
  606. if (hFileMap)
  607. CloseHandle(hFileMap);
  608. DeleteFile(pOrigFilename);
  609. MemFree(pOrigFilename);
  610. return result;
  611. }