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.

944 lines
29 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : faxdrv32.c //
  3. // //
  4. // DESCRIPTION : //
  5. // //
  6. // AUTHOR : DanL. //
  7. // //
  8. // HISTORY : //
  9. // Oct 19 1999 DannyL Creation. //
  10. // //
  11. // Copyright (C) 1999 Microsoft Corporation All Rights Reserved //
  12. /////////////////////////////////////////////////////////////////////////////
  13. #include "stdhdr.h"
  14. #include <shellapi.h>
  15. #include "faxdrv32.h"
  16. #include "..\..\faxtiff.h"
  17. #include "tifflib.h"
  18. #include "covpg.h"
  19. #include "faxreg.h"
  20. DBG_DECLARE_MODULE("fxsdrv32");
  21. //
  22. // Defenitions and Macros
  23. //
  24. #define SZ_CONT TEXT("...")
  25. #define SZ_CONT_SIZE (sizeof(SZ_CONT) / sizeof(TCHAR))
  26. #define MAX_TITLE_LEN 128
  27. #define MAX_MESSAGE_LEN 512
  28. //
  29. // Type defenitions
  30. //
  31. typedef struct tagDRIVER_CONTEXT
  32. {
  33. CHAR szPrinterName[MAX_PATH];
  34. CHAR szDocName[MAX_DOC_NAME];
  35. CHAR szTiffName[MAX_PATH];
  36. BOOL bPrintToFile;
  37. CHAR szPrintFile[MAX_PATH];
  38. CHAR szPort[MAX_PORT_NAME];
  39. DEVDATA dvdt;
  40. BOOL bAttachment;
  41. } DRIVER_CONTEXT, *PDRIVER_CONTEXT;
  42. //
  43. // Globals
  44. //
  45. int _debugLevel = 5;
  46. HINSTANCE g_hInstance = NULL;
  47. //
  48. // Prototypes
  49. //
  50. BOOL WINAPI
  51. thunk1632_ThunkConnect32(LPSTR pszDll16,
  52. LPSTR pszDll32,
  53. HINSTANCE hInst,
  54. DWORD dwReason);
  55. /*
  56. - GetServerNameFromPort
  57. -
  58. * Purpose:
  59. * Extract the server name from port name formatted: "\\server\port".
  60. *
  61. * Arguments:
  62. * [in] lpcszPort - Port name.
  63. * [out] lpsz - Server name.
  64. *
  65. * Returns:
  66. * LPTSTR - Server name.
  67. *
  68. * Remarks:
  69. * [N/A].
  70. */
  71. _inline LPSTR GetServerNameFromPort(LPCSTR lpcszPort,LPSTR lpsz)
  72. {
  73. if(!lpsz || !lpcszPort || !_tcscpy(lpsz,lpcszPort+2)) return NULL;
  74. return strtok(lpsz,TEXT("\\"));
  75. }
  76. /*
  77. - CreateTempFaxFile
  78. -
  79. * Purpose:
  80. * Create a temporary file in the system temp directory. The file name is prefixed
  81. * With the specified prefix.
  82. *
  83. * Arguments:
  84. * [in] szPrefix - Prefix for the tmp file.
  85. * [out] szBuffer - Generated tmp file name.
  86. *
  87. * Returns:
  88. * BOOL - TRUE: success , FALSE: failure.
  89. *
  90. * Remarks:
  91. * [N/A]
  92. */
  93. BOOL
  94. CreateTempFaxFile(LPCSTR szPrefix,
  95. CHAR szBuffer[MAX_PATH])
  96. {
  97. CHAR szTempDir[MAX_PATH];
  98. DBG_PROC_ENTRY("CreateTempFaxFile");
  99. //
  100. // Allocate a memory buffer for holding the temporary filename
  101. //
  102. if (!GetTempPath(sizeof(szTempDir),szTempDir)||
  103. !GetTempFileName(szTempDir, szPrefix, 0, szBuffer))
  104. {
  105. RETURN FALSE;
  106. }
  107. RETURN TRUE;
  108. }
  109. /*
  110. - FaxStartDoc
  111. -
  112. * Purpose:
  113. * Start a tiff document for hosting pages.
  114. *
  115. * Arguments:
  116. * [in] dwPtr - Contains a pointer to the driver context
  117. * [in] lpdi - Address of DOCINFO struct given by user in StartDoc.
  118. *
  119. * Returns:
  120. * short - START_DOC_FAIL: Operation failed
  121. * START_DOC_OK: Operation succeded.
  122. * START_DOC_ABORT: User aborted.
  123. *
  124. * Remarks:
  125. * TRUE / FALSE
  126. */
  127. BOOL WINAPI
  128. FaxStartDoc(DWORD dwPtr, LPDOCINFO lpdi)
  129. {
  130. PDRIVER_CONTEXT pdrvctx ;
  131. DWORD dwEnvSize;
  132. DBG_PROC_ENTRY("FaxStartDoc");
  133. //
  134. // Get the pointer to the driver context
  135. //
  136. pdrvctx = (PDRIVER_CONTEXT) dwPtr;
  137. ASSERT(pdrvctx);
  138. SafeStringCopy(pdrvctx->szDocName, !IsBadStringPtr(lpdi->lpszDocName, MAX_DOC_NAME) ? lpdi->lpszDocName : "");
  139. DBG_TRACE1("DocName: %s",pdrvctx->szDocName);
  140. DBG_TRACE1("lpdi->lpszOutput: %s", lpdi->lpszOutput);
  141. DBG_TRACE1("pdrvctx->szPort: %s", pdrvctx->szPort);
  142. //
  143. // Check if printing an attachment
  144. //
  145. dwEnvSize = GetEnvironmentVariable( FAX_ENVVAR_PRINT_FILE, NULL, 0 );
  146. if (dwEnvSize)
  147. {
  148. ASSERT (dwEnvSize < ARR_SIZE(pdrvctx->szPrintFile));
  149. if (0 == GetEnvironmentVariable( FAX_ENVVAR_PRINT_FILE,
  150. pdrvctx->szPrintFile,
  151. ARR_SIZE(pdrvctx->szPrintFile)))
  152. {
  153. DBG_CALL_FAIL("GetEnvironmentVariable",0)
  154. RETURN FALSE;
  155. }
  156. lpdi->lpszOutput = pdrvctx->szPrintFile;
  157. pdrvctx->bAttachment = TRUE;
  158. }
  159. else
  160. {
  161. HANDLE hMutex;
  162. BOOL bSuccess = FALSE;
  163. //
  164. // Check if the printing application is using DDE and did not create new process for printing
  165. // If it so, the environment variable FAX_ENVVAR_PRINT_FILE was not found
  166. //
  167. hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, FAXXP_MEM_MUTEX_NAME);
  168. if (hMutex)
  169. {
  170. if (WaitForSingleObject( hMutex, 1000 * 60 * 5) == WAIT_OBJECT_0)
  171. {
  172. HANDLE hSharedMem;
  173. //
  174. // we own the mutex...make sure we can open the shared memory region.
  175. //
  176. hSharedMem = OpenFileMapping(FILE_MAP_READ, FALSE, FAXXP_MEM_NAME);
  177. if (NULL == hSharedMem)
  178. {
  179. DBG_CALL_FAIL("OpenFileMapping",GetLastError());
  180. }
  181. else
  182. {
  183. //
  184. // we own the mutex and we have the shared memory region open.
  185. //
  186. // check if we are printing to a file.
  187. //
  188. LPTSTR filename;
  189. filename = (LPTSTR)MapViewOfFile(
  190. hSharedMem,
  191. FILE_MAP_READ,
  192. 0,
  193. 0,
  194. 0
  195. );
  196. if (!filename)
  197. {
  198. DBG_CALL_FAIL("MapViewOfFile",GetLastError());
  199. }
  200. else
  201. {
  202. //
  203. // check if this is really the filename we want to print to.
  204. //
  205. if (lpdi->lpszDocName)
  206. {
  207. LPTSTR lptstrSubStr = NULL;
  208. LPTSTR lptstrTmpInputFile = _tcschr(filename, TEXT('\0'));
  209. ASSERT (lptstrTmpInputFile);
  210. lptstrTmpInputFile = _tcsinc(lptstrTmpInputFile);
  211. Assert (_tcsclen(lptstrTmpInputFile));
  212. lptstrSubStr = _tcsstr(lpdi->lpszDocName, lptstrTmpInputFile);
  213. if (lptstrSubStr)
  214. {
  215. //
  216. // We assume the shared memory was pointed to us
  217. //
  218. SafeStringCopy(pdrvctx->szPrintFile ,filename);
  219. lpdi->lpszOutput = pdrvctx->szPrintFile;
  220. pdrvctx->bAttachment = TRUE;
  221. bSuccess = TRUE;
  222. }
  223. }
  224. else
  225. {
  226. //
  227. // To handle the race conditions between two diffrent instances of the printer driver over the shared memory created by PrintRandomDocument().
  228. // We are using now two mechanisms for detecting printing of an attachment using PrintRandomDocument().
  229. // � First we check if an environment variable is set (Set by PrintRandomDocument()). If it is set the driver knows it is an attachment printing.
  230. // � If it is not set, the driver looks for a mutex controlling a shred memory created by PrintRandomDocument(). If it does not exist it is a printing to the fax server.
  231. // � If the shared memory exists, the driver compares the document name in the DOCINFO provided by StartDoc, and the input file name in the shared memory.
  232. // � If there is a match, it is printing of an attachment, else it is a printing to the fax server
  233. // There is still a hole in this implementation, if there is an open instance of the printing application, and the ShellExecuteEx does not create new process for printing, and the printing application does not set the lpszDocName in StartDoc to contain the input file name.
  234. DBG_TRACE("No lpszDocName in DOCINFO - Could not verify the input file name in shared memory");
  235. }
  236. UnmapViewOfFile( filename );
  237. }
  238. if (!CloseHandle( hSharedMem ))
  239. {
  240. DBG_CALL_FAIL("CloseHandle",GetLastError());
  241. // Try to continue...
  242. }
  243. }
  244. ReleaseMutex( hMutex );
  245. }
  246. else
  247. {
  248. //
  249. // Something went wrong with WaitForSingleObject
  250. //
  251. DBG_CALL_FAIL("WaitForSingleObject", GetLastError());
  252. }
  253. if (!CloseHandle( hMutex ))
  254. {
  255. DBG_CALL_FAIL("CloseHandle", GetLastError());
  256. // Try to continue...
  257. }
  258. if (FALSE == bSuccess)
  259. {
  260. RETURN FALSE;
  261. }
  262. }
  263. }
  264. //
  265. // Check if we need to output the job into a file (and not into our -
  266. // printer port).
  267. //
  268. if (lpdi->lpszOutput != NULL &&
  269. (_tcscmp(lpdi->lpszOutput,pdrvctx->szPort) != 0))
  270. {
  271. pdrvctx->bPrintToFile = TRUE;
  272. SafeStringCopy(pdrvctx->szTiffName,lpdi->lpszOutput);
  273. DBG_TRACE("Printing to file ...");
  274. }
  275. else
  276. {
  277. //
  278. // User wants to send the document to the fax.
  279. //
  280. DBG_TRACE("Printing to Fax Server ...");
  281. pdrvctx->bPrintToFile = FALSE;
  282. //
  283. // client 'point and print' setup
  284. //
  285. if (FaxPointAndPrintSetup(pdrvctx->szPort,FALSE, g_hInstance))
  286. {
  287. DBG_TRACE("FaxPointAndPrintSetup succeeded");
  288. }
  289. else
  290. {
  291. DBG_CALL_FAIL("FaxPointAndPrintSetup",GetLastError());
  292. }
  293. if (!CreateTempFaxFile("fax",pdrvctx->szTiffName))
  294. {
  295. DBG_CALL_FAIL("CreateTempFaxFile",GetLastError());
  296. RETURN FALSE;
  297. }
  298. }
  299. pdrvctx->dvdt.hPrinter =CreateFileA(pdrvctx->szTiffName, // pointer to name of the file
  300. GENERIC_WRITE, // access (read-write) mode
  301. FILE_SHARE_READ,// share mode
  302. NULL, // pointer to security attributes
  303. CREATE_ALWAYS, // how to create
  304. FILE_ATTRIBUTE_NORMAL, // file attributes
  305. NULL);// handle to file with attributes to copy
  306. if (pdrvctx->dvdt.hPrinter == INVALID_HANDLE_VALUE)
  307. {
  308. DBG_CALL_FAIL("CreateFileA",GetLastError());
  309. RETURN FALSE;
  310. }
  311. DBG_TRACE1("Fax temporary file name: %s",pdrvctx->szTiffName);
  312. pdrvctx->dvdt.endDevData =
  313. pdrvctx->dvdt.startDevData = &pdrvctx->dvdt;
  314. pdrvctx->dvdt.pageCount = 0;
  315. RETURN TRUE;
  316. }
  317. /*
  318. - FaxAddPage
  319. -
  320. * Purpose:
  321. * Add a page to the tiff document.
  322. *
  323. * Arguments:
  324. * [in] dwPtr - Contains a pointer to the driver context
  325. * [in] lpBitmapData - Buffer of page bitmap.
  326. * [in] dwPxlsWidth - Width of bitmap (units: pixels)
  327. * [in] dwPxlsHeight - Height of bitmap (units: pixels)
  328. *
  329. * Returns:
  330. * BOOL - TRUE: success , FALSE: failure.
  331. *
  332. * Remarks:
  333. * This function uses OutputPageBitmap call from faxdrv\faxtiff.
  334. * In order to reuse the implementation OutputPageBitmap was altered in
  335. * the build context of 95 to redirect the resulted tiff into a file whos
  336. * handle if given in dvdt.hPrinter.
  337. */
  338. BOOL WINAPI
  339. FaxAddPage(DWORD dwPtr,
  340. LPBYTE lpBitmapData,
  341. DWORD dwPxlsWidth,
  342. DWORD dwPxlsHeight)
  343. {
  344. BOOL br = TRUE;
  345. PDRIVER_CONTEXT pdrvctx;
  346. DBG_PROC_ENTRY("FaxAddPage");
  347. DBG_TRACE2("Proportions: %dx%d",dwPxlsWidth,dwPxlsHeight);
  348. //
  349. // Get the pointer to the driver context
  350. //
  351. pdrvctx = (PDRIVER_CONTEXT) dwPtr;
  352. ASSERT(pdrvctx);
  353. //
  354. // Initialize the structure needed by OutputPageBitmap
  355. //
  356. pdrvctx->dvdt.pageCount++;
  357. pdrvctx->dvdt.imageSize.cx = dwPxlsWidth;
  358. pdrvctx->dvdt.imageSize.cy = dwPxlsHeight;
  359. pdrvctx->dvdt.lineOffset = PadBitsToBytes(pdrvctx->dvdt.imageSize.cx, sizeof(DWORD));
  360. //
  361. // Add the bitmap into the tiff document created in FaxStartDoc.
  362. //
  363. if (!OutputPageBitmap(&pdrvctx->dvdt,(PBYTE)lpBitmapData))
  364. {
  365. DBG_CALL_FAIL("OutputPageBitmap",0);
  366. RETURN FALSE;
  367. }
  368. DBG_TRACE1("Page %d added successfully.",pdrvctx->dvdt.pageCount);
  369. RETURN TRUE;
  370. }
  371. /*
  372. - FaxEndDoc
  373. -
  374. * Purpose:
  375. * Finalize creating the tiff document and optionally send it to the
  376. * fax server.
  377. *
  378. * Arguments:
  379. * [in] dwPtr - Contains a pointer to the driver context
  380. * [in] bAbort - Specifies wheather job was finally aborted.
  381. *
  382. * Returns:
  383. * BOOL - TRUE: success , FALSE: failure.
  384. *
  385. * Remarks:
  386. * [N/A]
  387. */
  388. BOOL WINAPI
  389. FaxEndDoc(DWORD dwPtr, BOOL bAbort)
  390. {
  391. BOOL bRc = TRUE;
  392. PDRIVER_CONTEXT pdrvctx;
  393. FAX_SEND_WIZARD_DATA InitialWizardData = {0};
  394. FAX_SEND_WIZARD_DATA WizardDataOutput = {0};
  395. DBG_PROC_ENTRY("FaxEndDoc");
  396. //
  397. // Get the pointer to the driver context
  398. //
  399. pdrvctx = (PDRIVER_CONTEXT) dwPtr;
  400. ASSERT(pdrvctx);
  401. if (pdrvctx->dvdt.hPrinter)
  402. {
  403. //
  404. // Output the tailing IFD.
  405. //
  406. if (!OutputDocTrailer(&pdrvctx->dvdt))
  407. {
  408. DBG_CALL_FAIL("OutputDocTrailer",GetLastError());
  409. bRc = FALSE;
  410. }
  411. //
  412. // Close the tiff file handle.
  413. //
  414. CloseHandle(pdrvctx->dvdt.hPrinter);
  415. pdrvctx->dvdt.hPrinter = NULL;
  416. if (FALSE == bRc)
  417. {
  418. goto Cleanup;
  419. }
  420. }
  421. if (!bAbort && !pdrvctx->bPrintToFile)
  422. {
  423. DWORDLONG dwlParentJobId;
  424. DWORDLONG* pdwlRecipientIds = NULL;
  425. FAX_JOB_PARAM_EX fjp;
  426. CHAR szServerName[MAX_PORT_NAME]="";
  427. HANDLE hFaxServer;
  428. HRESULT hRc;
  429. CHAR lpszServerName[MAX_PORT_NAME]="";
  430. CHAR szCoverPageTiffFile[MAX_PATH] = "";
  431. DWORD dwFlags = FSW_PRINT_PREVIEW_OPTION;
  432. //
  433. // Convert to valid server name.
  434. //
  435. GetServerNameFromPort(pdrvctx->szPort,lpszServerName);
  436. // prepare structures and parameters
  437. WizardDataOutput.dwSizeOfStruct = sizeof(FAX_SEND_WIZARD_DATA);
  438. InitialWizardData.dwSizeOfStruct = sizeof(FAX_SEND_WIZARD_DATA);
  439. InitialWizardData.dwPageCount = pdrvctx->dvdt.pageCount;
  440. InitialWizardData.lptstrPreviewFile = StringDup(pdrvctx->szTiffName);
  441. if (!InitialWizardData.lptstrPreviewFile)
  442. {
  443. DBG_CALL_FAIL("Allocation error",GetLastError());
  444. bRc = FALSE;
  445. goto Cleanup;
  446. }
  447. if (GetEnvironmentVariable(TEXT("NTFaxSendNote"), NULL, 0))
  448. {
  449. dwFlags |= FSW_USE_SEND_WIZARD | FSW_FORCE_COVERPAGE;
  450. }
  451. // If the file mapping succeeded enable the preview option
  452. //
  453. // Launch the FaxSendWizard
  454. //
  455. hRc = FaxSendWizard( (DWORD) NULL,
  456. dwFlags,
  457. lpszServerName,
  458. pdrvctx->szPrinterName,
  459. &InitialWizardData,
  460. szCoverPageTiffFile,
  461. ARR_SIZE(szCoverPageTiffFile),
  462. &WizardDataOutput);
  463. if ( S_FALSE == hRc)
  464. {
  465. bAbort = TRUE;
  466. goto Cleanup;
  467. }
  468. if (FAILED(hRc))
  469. {
  470. DBG_CALL_FAIL("FaxSendWizard", (DWORD)hRc);
  471. bRc = FALSE;
  472. goto Cleanup;
  473. }
  474. //
  475. // Send the tiff ducument to the fax server.
  476. //
  477. //
  478. // Convert to valid server name.
  479. //
  480. GetServerNameFromPort(pdrvctx->szPort,szServerName);
  481. if (!FaxConnectFaxServer(szServerName, // fax server name
  482. &hFaxServer))
  483. {
  484. DBG_CALL_FAIL("FaxConnectFaxServer",GetLastError());
  485. DBG_TRACE1("arg1: %s",NO_NULL_STR(szServerName));
  486. bRc = FALSE;
  487. goto Cleanup;
  488. }
  489. //
  490. // Allocate a buffer for recipient IDs
  491. //
  492. ASSERT(WizardDataOutput.dwNumberOfRecipients);
  493. if (!(pdwlRecipientIds = (DWORDLONG*)MemAlloc(WizardDataOutput.dwNumberOfRecipients * sizeof(DWORDLONG))))
  494. {
  495. DBG_CALL_FAIL("MemAlloc", GetLastError());
  496. FaxClose(hFaxServer);
  497. bRc = FALSE;
  498. goto Cleanup;
  499. }
  500. //
  501. // Initialize a FAX_JOB_PARAM_EX for fax sending from the wizard output.
  502. //
  503. fjp.dwSizeOfStruct = sizeof(fjp);
  504. fjp.dwScheduleAction = WizardDataOutput.dwScheduleAction;
  505. fjp.tmSchedule = WizardDataOutput.tmSchedule;
  506. fjp.dwReceiptDeliveryType = WizardDataOutput.dwReceiptDeliveryType;
  507. fjp.lptstrReceiptDeliveryAddress = WizardDataOutput.szReceiptDeliveryAddress;
  508. fjp.hCall = (HCALL)NULL;
  509. fjp.lptstrDocumentName = pdrvctx->szDocName;
  510. fjp.Priority = WizardDataOutput.Priority;
  511. // setting PageCount=0 means the server will count the number of pages in the job
  512. fjp.dwPageCount = 0;
  513. if (JSA_SPECIFIC_TIME == fjp.dwScheduleAction)
  514. {
  515. //
  516. // Calculate the scheduled time
  517. //
  518. DWORDLONG FileTime;
  519. SYSTEMTIME LocalTime;
  520. INT Minutes;
  521. INT SendMinutes;
  522. //
  523. // Calculate the number of minutes from now to send and add that to the current time.
  524. //
  525. GetLocalTime( &LocalTime );
  526. if (!SystemTimeToFileTime( &LocalTime, (LPFILETIME) &FileTime ))
  527. {
  528. DBG_CALL_FAIL("SystemTimeToFileTime", GetLastError());
  529. FaxClose(hFaxServer);
  530. bRc = FALSE;
  531. goto Cleanup;
  532. }
  533. SendMinutes = (min(23,fjp.tmSchedule.wHour))*60 + min(59,fjp.tmSchedule.wMinute);
  534. Minutes = LocalTime.wHour * 60 + LocalTime.wMinute;
  535. Minutes = SendMinutes - Minutes;
  536. //
  537. // Account for passing midnight
  538. //
  539. if (Minutes < 0)
  540. {
  541. Minutes += 24 * 60;
  542. }
  543. FileTime += (DWORDLONG)(Minutes * 60I64 * 1000I64 * 1000I64 * 10I64);
  544. if (!FileTimeToSystemTime((LPFILETIME) &FileTime, &fjp.tmSchedule ))
  545. {
  546. DBG_CALL_FAIL("FileTimeToSystemTime", GetLastError());
  547. FaxClose(hFaxServer);
  548. bRc = FALSE;
  549. goto Cleanup;
  550. }
  551. }
  552. if(!FaxSendDocumentEx(hFaxServer,
  553. (pdrvctx->dvdt.pageCount > 0)? pdrvctx->szTiffName : NULL,
  554. (WizardDataOutput.lpCoverPageInfo->lptstrCoverPageFileName == NULL)?
  555. NULL:WizardDataOutput.lpCoverPageInfo,
  556. WizardDataOutput.lpSenderInfo,
  557. WizardDataOutput.dwNumberOfRecipients,
  558. WizardDataOutput.lpRecipientsInfo,
  559. &fjp,
  560. &dwlParentJobId,
  561. pdwlRecipientIds))
  562. {
  563. DBG_CALL_FAIL("FaxSendDocumentEx",GetLastError());
  564. bRc = FALSE;
  565. }
  566. FaxClose(hFaxServer);
  567. MemFree (pdwlRecipientIds);
  568. }
  569. //
  570. // Signal the printing application (PrintRandomDocument) that printing is completed or aborted
  571. //
  572. if (TRUE == pdrvctx->bAttachment)
  573. {
  574. HANDLE hEvent;
  575. TCHAR szEventName[FAXXP_ATTACH_EVENT_NAME_LEN] = {0};
  576. LPTSTR lptstrEventName = NULL;
  577. ASSERT(pdrvctx->szPrintFile);
  578. if (TRUE == bAbort)
  579. {
  580. //
  581. // Create the Abort event name
  582. //
  583. _tcscpy (szEventName, pdrvctx->szPrintFile);
  584. _tcscat (szEventName, FAXXP_ATTACH_ABORT_EVENT);
  585. }
  586. else
  587. {
  588. //
  589. // Create the EndDoc event name
  590. //
  591. _tcscpy (szEventName, pdrvctx->szPrintFile);
  592. _tcscat (szEventName, FAXXP_ATTACH_END_DOC_EVENT);
  593. }
  594. lptstrEventName = _tcsrchr(szEventName, TEXT('\\'));
  595. ASSERT (lptstrEventName);
  596. lptstrEventName = _tcsinc(lptstrEventName);
  597. hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, lptstrEventName);
  598. if (NULL == hEvent)
  599. {
  600. DBG_CALL_FAIL("OpenEvent", GetLastError());
  601. DBG_TRACE1("Event name: %s",lptstrEventName);
  602. bRc = FALSE;
  603. }
  604. else
  605. {
  606. if (!SetEvent( hEvent ))
  607. {
  608. DBG_CALL_FAIL("SetEvent", GetLastError());
  609. bRc = FALSE;
  610. }
  611. if (!CloseHandle(hEvent))
  612. {
  613. DBG_CALL_FAIL("CloseHandle", GetLastError());
  614. // Try to continue...
  615. }
  616. }
  617. }
  618. Cleanup:
  619. if (!pdrvctx->bPrintToFile || bAbort)
  620. {
  621. #ifdef DEBUG
  622. if (bAbort)
  623. {
  624. DBG_TRACE("User aborted ...");
  625. }
  626. #endif //DEBUG
  627. //
  628. // Delete temporary file.
  629. //
  630. if (!DeleteFile(pdrvctx->szTiffName))
  631. {
  632. DBG_TRACE1 ("File Name:[%s] not deleted!",pdrvctx->szTiffName);
  633. }
  634. }
  635. *pdrvctx->szTiffName = 0;
  636. MemFree (InitialWizardData.lptstrPreviewFile);
  637. FaxFreeSendWizardData(&WizardDataOutput);
  638. RETURN bRc;
  639. }
  640. /*
  641. - FaxDevInstall
  642. -
  643. * Purpose:
  644. * Complete installation of all client components.
  645. *
  646. * Arguments:
  647. * [in] lpDevName - Device name.
  648. * [in] lpOldPort - Old port name..
  649. * [in] lpNewPort - New port name..
  650. *
  651. * Returns:
  652. * BOOL - TRUE: success , FALSE: failure.
  653. *
  654. * Remarks:
  655. * TBD
  656. */
  657. BOOL WINAPI
  658. FaxDevInstall(LPSTR lpDevName,LPSTR lpOldPort,LPSTR lpNewPort)
  659. {
  660. SDBG_PROC_ENTRY("FaxDevInstall");
  661. // TBD insert install code here
  662. RETURN TRUE;
  663. }
  664. /*
  665. - FaxCreateDriverContext
  666. -
  667. * Purpose:
  668. * Create a new device context, initialize it and return it's pointer
  669. *
  670. * Arguments:
  671. * [in] lpDeviceName - Our device name.
  672. * [in] lpPort - Out device port.
  673. * [in]
  674. * [out] lpDrvContext - Points to the buffer to recieve our 32 bit pointer
  675. *
  676. * Returns:
  677. * BOOL - TRUE: success , FALSE: failure.
  678. *
  679. * Remarks:
  680. * Data which is normally saved and maintained in the uni-driver is kept
  681. * here for the tiff generation and fax sending.
  682. */
  683. BOOL WINAPI
  684. FaxCreateDriverContext(
  685. LPSTR lpDeviceName,
  686. LPSTR lpPort,
  687. LPDEVMODE lpDevMode,
  688. LPDWORD lpDrvContext)
  689. {
  690. PDRIVER_CONTEXT pdrvctx;
  691. DBG_PROC_ENTRY("FaxCreateDriverContext");
  692. DBG_TRACE2("lpDeviceName:%s ,lpPort:%s",lpDeviceName,lpPort);
  693. DBG_TRACE1("lpDevMode: 0x%lx",(ULONG)lpDevMode);
  694. ASSERT(lpDeviceName && lpPort);
  695. //
  696. // Allocate a new driver context structure
  697. //
  698. if (!(pdrvctx = (PDRIVER_CONTEXT)malloc(sizeof(DRIVER_CONTEXT))))
  699. {
  700. DBG_CALL_FAIL("malloc",GetLastError());
  701. RETURN FALSE;
  702. }
  703. DBG_TRACE1("pdrvctx: 0x%lx",(ULONG)pdrvctx);
  704. memset(pdrvctx,0,sizeof(DRIVER_CONTEXT));
  705. //
  706. // Initialize the following fields:
  707. // - szPrinterName: Holds the driver name ('BOSFax')
  708. // - szPort: Holds the port ('\\<Machine Name>\BOSFAX')
  709. //
  710. SafeStringCopy(pdrvctx->szPrinterName, lpDeviceName);
  711. SafeStringCopy(pdrvctx->szPort, lpPort);
  712. if (NULL != lpDevMode)
  713. {
  714. //
  715. // Save the DEVMODE for the use of OutputPageBitmap
  716. //
  717. memcpy(&(pdrvctx->dvdt.dm.dmPublic), lpDevMode, sizeof(pdrvctx->dvdt.dm.dmPublic));
  718. }
  719. DBG_TRACE2("szPrinterName:[%s] szPort:[%s]",NO_NULL_STR(pdrvctx->szPrinterName),NO_NULL_STR(pdrvctx->szPort));
  720. //
  721. // Save our pointer
  722. //
  723. *lpDrvContext = (DWORD) pdrvctx;
  724. RETURN TRUE;
  725. }
  726. /*
  727. - FaxResetDC
  728. -
  729. * Purpose:
  730. * Copies the essential context information from the old DC to the new one.
  731. *
  732. * Arguments:
  733. * [in] pdwOldPtr - Contains the address of a pointer to the old driver context.
  734. * [in] pdwNewPtr - Contains the address of a pointer to the new driver context.
  735. *
  736. * Returns:
  737. * BOOL - TRUE: success , FALSE: failure.
  738. *
  739. * Remarks:
  740. * [N/A]
  741. */
  742. BOOL WINAPI
  743. FaxResetDC(LPDWORD pdwOldPtr, LPDWORD pdwNewPtr)
  744. {
  745. PDRIVER_CONTEXT pOlddrvctx;
  746. PDRIVER_CONTEXT pNewdrvctx;
  747. DWORD dwTemp;
  748. DBG_PROC_ENTRY("FaxResetDC");
  749. //
  750. // Get the pointers to the driver context
  751. //
  752. pOlddrvctx = (PDRIVER_CONTEXT) *pdwOldPtr;
  753. pNewdrvctx = (PDRIVER_CONTEXT) *pdwNewPtr;
  754. ASSERT(pOlddrvctx && pNewdrvctx);
  755. //
  756. // ResetDC is interpreted by GDI to Enable (Create a new DC), Control with RESETDEVICE, and Disable (Delete the old DC).
  757. // We simply copy the new DEVMODE to the old driver context, and switch the driver context pointer.
  758. //
  759. memcpy(&(pOlddrvctx->dvdt.dm.dmPublic), &(pNewdrvctx->dvdt.dm.dmPublic), sizeof(pOlddrvctx->dvdt.dm.dmPublic));
  760. dwTemp = *pdwOldPtr;
  761. *pdwOldPtr = *pdwNewPtr;
  762. *pdwNewPtr = dwTemp;
  763. RETURN TRUE;
  764. }// FaxResetDC
  765. /*
  766. - FaxDisable
  767. -
  768. * Purpose:
  769. * Clean out any leftovers once driver is disabled.
  770. *
  771. * Arguments:
  772. * [in] dwPtr - Contains a pointer to the driver context
  773. *
  774. * Returns:
  775. * BOOL - TRUE: success , FALSE: failure.
  776. *
  777. * Remarks:
  778. * [N/A]
  779. */
  780. BOOL WINAPI
  781. FaxDisable(DWORD dwPtr)
  782. {
  783. PDRIVER_CONTEXT pdrvctx = (PDRIVER_CONTEXT) dwPtr;
  784. DBG_PROC_ENTRY("FaxDisable");
  785. DBG_TRACE1("pdrvctx: 0x%lx", (ULONG)pdrvctx);
  786. ASSERT(pdrvctx);
  787. //
  788. // Check to see if there are any remmenants of an output file
  789. // not fully created
  790. //
  791. if (pdrvctx->dvdt.hPrinter)
  792. {
  793. CloseHandle(pdrvctx->dvdt.hPrinter);
  794. pdrvctx->dvdt.hPrinter = NULL;
  795. DeleteFile(pdrvctx->szTiffName);
  796. }
  797. //
  798. // Free the driver context
  799. //
  800. free(pdrvctx);
  801. RETURN TRUE;
  802. }
  803. //
  804. // REMARK: when returning FALSE, implicitly loaded dlls are not freed !
  805. //
  806. BOOL WINAPI
  807. DllMain(HINSTANCE hInst,
  808. DWORD dwReason,
  809. LPVOID lpvReserved)
  810. {
  811. SDBG_PROC_ENTRY("DllMain");
  812. #ifdef DBG_DEBUG
  813. {
  814. CHAR szModuleName[MAX_PATH]={0};
  815. GetModuleFileName(NULL,szModuleName,ARR_SIZE(szModuleName)-1);
  816. DBG_TRACE2("Module: %s dwReason=%ld",szModuleName,dwReason);
  817. }
  818. #endif //DBG_DEBUG
  819. if( !(thunk1632_ThunkConnect32("fxsdrv", // name of 16-bit DLL
  820. "fxsdrv32",// name of 32-bit DLL
  821. hInst,
  822. dwReason)) )
  823. {
  824. DBG_CALL_FAIL("thunk1632_ThunkConnect32",GetLastError());
  825. goto Error;
  826. }
  827. switch (dwReason)
  828. {
  829. case DLL_PROCESS_ATTACH:
  830. g_hInstance = hInst;
  831. break;
  832. case DLL_THREAD_ATTACH:
  833. break;
  834. case DLL_THREAD_DETACH:
  835. break;
  836. case DLL_PROCESS_DETACH:
  837. HeapCleanup();
  838. break;
  839. }
  840. RETURN TRUE;
  841. Error:
  842. {
  843. // Hack to free implicitly loaded fxsapi.dll in case of failure.
  844. HMODULE hm = GetModuleHandle("FXSAPI.DLL");
  845. if (hm) FreeLibrary(hm);
  846. return FALSE;
  847. }
  848. }