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.

1361 lines
35 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. print.c
  5. Abstract:
  6. This module contains the print specific WINFAX API functions.
  7. Author:
  8. Wesley Witt (wesw) 29-Nov-1996
  9. Revision History:
  10. 4-Dec-1999 Danl Use fixed GetFaxPrinterName.
  11. --*/
  12. #include "faxapi.h"
  13. #include "faxreg.h"
  14. #include "faxutil.h"
  15. #pragma hdrstop
  16. #include <mbstring.h>
  17. #define NIL _T('\0')
  18. BOOL
  19. WINAPI
  20. FaxStartPrintJob(
  21. IN LPCTSTR PrinterName,
  22. IN const FAX_PRINT_INFO *PrintInfo,
  23. OUT LPDWORD FaxJobId,
  24. OUT PFAX_CONTEXT_INFO FaxContextInfo
  25. )
  26. /*++
  27. Routine Description:
  28. Starts a print job for the specified printer. This
  29. function provides functionality beyond what the caller
  30. can provide by using StartDoc(). This function disables
  31. the display of the fax send wizard and also passes along
  32. the information that would otherwise be gathered by the
  33. fax wizard ui.
  34. Arguments:
  35. PrinterName - Fax printer name (must be a fax printer)
  36. PrintInfo - Fax print information
  37. FaxJobId - Job id of the resulting print job
  38. FaxContextInfo - context information including hdc
  39. Return Value:
  40. TRUE for success.
  41. FALSE for failure.
  42. --*/
  43. {
  44. return FaxStartPrintJob2 ( PrinterName,
  45. PrintInfo,
  46. 0, // Default resolution
  47. FaxJobId,
  48. FaxContextInfo);
  49. }
  50. #ifdef UNICODE
  51. BOOL
  52. WINAPI
  53. FaxStartPrintJobA(
  54. IN LPCSTR PrinterName,
  55. IN const FAX_PRINT_INFOA *PrintInfo,
  56. OUT LPDWORD FaxJobId,
  57. OUT FAX_CONTEXT_INFOA *FaxContextInfo
  58. )
  59. /*++
  60. Routine Description:
  61. Starts a print job for the specified printer. This
  62. function provides functionality beyond what the caller
  63. can provide by using StartDoc(). This function disables
  64. the display of the fax send wizard and also passes along
  65. the information that would otherwise be gathered by the
  66. fax wizard ui.
  67. Arguments:
  68. PrinterName - Fax printer name (must be a fax printer)
  69. PrintInfo - Fax print information
  70. FaxJobId - Job id of the resulting print job
  71. FaxContextInfo - device context information (hdc, etc.)
  72. Return Value:
  73. TRUE for success.
  74. FALSE for failure.
  75. --*/
  76. {
  77. return FaxStartPrintJob2A ( PrinterName,
  78. PrintInfo,
  79. 0, // Default resolution
  80. FaxJobId,
  81. FaxContextInfo);;
  82. }
  83. #else
  84. BOOL
  85. WINAPI
  86. FaxStartPrintJobW(
  87. IN LPCWSTR PrinterName,
  88. IN const FAX_PRINT_INFOW *PrintInfo,
  89. OUT LPDWORD FaxJobId,
  90. OUT PFAX_CONTEXT_INFOW FaxContextInfo
  91. )
  92. {
  93. UNREFERENCED_PARAMETER(PrinterName);
  94. UNREFERENCED_PARAMETER(PrintInfo);
  95. UNREFERENCED_PARAMETER(FaxJobId);
  96. UNREFERENCED_PARAMETER(FaxContextInfo);
  97. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  98. return FALSE;
  99. }
  100. #endif
  101. PVOID
  102. MyGetJob(
  103. HANDLE hPrinter,
  104. DWORD level,
  105. DWORD jobId
  106. )
  107. /*++
  108. Routine Description:
  109. Wrapper function for spooler API GetJob
  110. Arguments:
  111. hPrinter - Handle to the printer object
  112. level - Level of JOB_INFO structure interested
  113. jobId - Specifies the job ID
  114. Return Value:
  115. Pointer to a JOB_INFO structure, NULL if there is an error
  116. --*/
  117. {
  118. PBYTE pJobInfo = NULL;
  119. DWORD cbNeeded;
  120. if (!GetJob(hPrinter, jobId, level, NULL, 0, &cbNeeded) &&
  121. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  122. (pJobInfo = (PBYTE)MemAlloc(cbNeeded)) &&
  123. GetJob(hPrinter, jobId, level, pJobInfo, cbNeeded, &cbNeeded))
  124. {
  125. return pJobInfo;
  126. }
  127. MemFree(pJobInfo);
  128. return NULL;
  129. }
  130. LPTSTR
  131. GetCpField(
  132. HKEY hKey,
  133. LPTSTR SubKey
  134. )
  135. /*++
  136. Routine Description:
  137. Retrieves the data for a coverpage field from
  138. the registry.
  139. Arguments:
  140. hKey - Registry handle
  141. SubKey - Subkey name
  142. Return Value:
  143. Pointer to the coverpage field data.
  144. --*/
  145. {
  146. LONG rVal;
  147. DWORD RegSize=0;
  148. DWORD RegType;
  149. LPBYTE Buffer;
  150. rVal = RegQueryValueEx( hKey, SubKey, 0, &RegType, NULL, &RegSize );
  151. if (rVal != ERROR_SUCCESS) {
  152. return NULL;
  153. }
  154. Buffer = (LPBYTE) MemAlloc( RegSize );
  155. if (!Buffer) {
  156. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  157. return NULL;
  158. }
  159. rVal = RegQueryValueEx( hKey, SubKey, 0, &RegType, Buffer, &RegSize );
  160. if (rVal != ERROR_SUCCESS) {
  161. MemFree( Buffer );
  162. return NULL;
  163. }
  164. return (LPTSTR) Buffer;
  165. }
  166. BOOL
  167. GetCpFields(
  168. PCOVERPAGEFIELDS CpFields
  169. )
  170. /*++
  171. Routine Description:
  172. Initializes the coverpage field structure and
  173. fills in the sender information from the registry.
  174. This function actually loads only the sender fields.
  175. Arguments:
  176. CpFields - Pointer to a coverpage field structure.
  177. Return Value:
  178. TRUE for success.
  179. FALSE for failure.
  180. --*/
  181. {
  182. HKEY hKey;
  183. LONG rVal;
  184. rVal = RegOpenKey(
  185. HKEY_CURRENT_USER,
  186. REGKEY_FAX_USERINFO,
  187. &hKey
  188. );
  189. if (rVal != ERROR_SUCCESS) {
  190. return FALSE;
  191. }
  192. ZeroMemory( CpFields, sizeof(COVERPAGEFIELDS) );
  193. CpFields->ThisStructSize = sizeof(COVERPAGEFIELDS);
  194. //
  195. // sender fields
  196. //
  197. CpFields->SdrName = GetCpField( hKey, REGVAL_FULLNAME );
  198. CpFields->SdrFaxNumber = GetCpField( hKey, REGVAL_FAX_NUMBER );
  199. CpFields->SdrCompany = GetCpField( hKey, REGVAL_COMPANY );
  200. CpFields->SdrAddress = GetCpField( hKey, REGVAL_ADDRESS );
  201. CpFields->SdrTitle = GetCpField( hKey, REGVAL_TITLE );
  202. CpFields->SdrDepartment = GetCpField( hKey, REGVAL_DEPT );
  203. CpFields->SdrOfficeLocation = GetCpField( hKey, REGVAL_OFFICE );
  204. CpFields->SdrHomePhone = GetCpField( hKey, REGVAL_HOME_PHONE );
  205. CpFields->SdrOfficePhone = GetCpField( hKey, REGVAL_OFFICE_PHONE );
  206. CpFields->SdrEmail = GetCpField( hKey, REGVAL_MAILBOX );
  207. RegCloseKey( hKey );
  208. return TRUE;
  209. }
  210. VOID
  211. FreeCpFields(
  212. PCOVERPAGEFIELDS CpFields
  213. )
  214. /*++
  215. Routine Description:
  216. Frees all memory associated with a coverpage field structure.
  217. Arguments:
  218. CpFields - Pointer to a coverpage field structure.
  219. Return Value:
  220. None.
  221. --*/
  222. {
  223. DWORD i;
  224. LPBYTE *p;
  225. for (i = 0; i < NUM_INSERTION_TAGS; i++) {
  226. p = (LPBYTE *) ((ULONG_PTR)CpFields + sizeof(LPTSTR)*(i+1));
  227. if (p && *p) MemFree( *p );
  228. }
  229. }
  230. BOOL
  231. WINAPI
  232. FaxPrintCoverPage(
  233. IN const FAX_CONTEXT_INFO *FaxContextInfo,
  234. IN const FAX_COVERPAGE_INFO *CoverPageInfo
  235. )
  236. /*++
  237. Routine Description:
  238. Prints a coverpage into the printer DC provided.
  239. Arguments:
  240. FaxContextInfo - contains servername, Printer DC
  241. CoverPageInfo - Cover page information
  242. Return Value:
  243. TRUE for success.
  244. FALSE for failure.
  245. --*/
  246. {
  247. TCHAR CpName[MAX_PATH];
  248. TCHAR Buffer[MAX_PATH];
  249. TCHAR TBuffer[MAX_PATH];
  250. COVERPAGEFIELDS CpFields = {0};
  251. COVDOCINFO CovDocInfo;
  252. DWORD dwDateTimeLen;
  253. DWORD cch;
  254. LPTSTR s;
  255. DWORD ec = 0;
  256. LPCTSTR *src;
  257. LPCTSTR *dst;
  258. DWORD i;
  259. LPCTSTR lpctstrCoverPage,lpctstrServerName;
  260. BOOL retVal = TRUE;
  261. DEBUG_FUNCTION_NAME(TEXT("FaxPrintCoverPage"));
  262. //
  263. // do a little argument validation
  264. //
  265. if (CoverPageInfo == NULL || CoverPageInfo->SizeOfStruct != sizeof(FAX_COVERPAGE_INFOW) ||
  266. FaxContextInfo == NULL || FaxContextInfo->hDC == NULL ||
  267. FaxContextInfo->SizeOfStruct != sizeof (FAX_CONTEXT_INFOW) )
  268. {
  269. DebugPrintEx(DEBUG_ERR,
  270. TEXT("CoverPageInfo is NULL or Size mismatch.")
  271. );
  272. SetLastError( ERROR_INVALID_PARAMETER );
  273. return FALSE;
  274. }
  275. lpctstrCoverPage = CoverPageInfo->CoverPageName;
  276. lpctstrServerName = FaxContextInfo->ServerName;
  277. if (!ValidateCoverpage(lpctstrCoverPage,
  278. lpctstrServerName,
  279. CoverPageInfo->UseServerCoverPage,
  280. CpName,
  281. ARR_SIZE(CpName)))
  282. {
  283. DebugPrintEx(DEBUG_ERR,
  284. TEXT("ValidateCoverpage failed. ec = %ld"),
  285. GetLastError());
  286. retVal = FALSE;
  287. goto exit;
  288. }
  289. //
  290. // get the coverpage fields
  291. //
  292. // Initialize the sender fields of CpFields with sender information from the registry
  293. GetCpFields( &CpFields );
  294. //
  295. // fixup the recipient name
  296. //
  297. if (CoverPageInfo->RecName)
  298. {
  299. if( _tcsncmp(CoverPageInfo->RecName,TEXT("\'"),1) == 0 )
  300. {
  301. // The recipient name is single quouted. Copy only the string inside the quotes.
  302. _tcsncpy(Buffer, _tcsinc(CoverPageInfo->RecName), ARR_SIZE(Buffer)-1);
  303. TCHAR* eos = _tcsrchr(Buffer,TEXT('\0'));
  304. eos = _tcsdec(Buffer,eos);
  305. if( eos )
  306. {
  307. _tcsnset(eos,TEXT('\0'),1);
  308. }
  309. }
  310. else
  311. {
  312. _tcsncpy(Buffer, CoverPageInfo->RecName, ARR_SIZE(Buffer)-1);
  313. }
  314. }
  315. else
  316. {
  317. Buffer[0] = 0;
  318. }
  319. //
  320. // fill in the coverpage fields with the
  321. // data that the caller passed in
  322. //
  323. CpFields.RecName = StringDup(Buffer);
  324. CpFields.RecFaxNumber = StringDup(CoverPageInfo->RecFaxNumber);
  325. CpFields.Subject = StringDup(CoverPageInfo->Subject);
  326. CpFields.Note = StringDup(CoverPageInfo->Note);
  327. CpFields.NumberOfPages = StringDup(_itot( CoverPageInfo->PageCount, Buffer, 10 ));
  328. for (i = 0;
  329. i <= ((LPBYTE)&CoverPageInfo->SdrOfficePhone -(LPBYTE)&CoverPageInfo->RecCompany)/sizeof(LPCTSTR);
  330. i++)
  331. {
  332. src = (LPCTSTR *) ((LPBYTE)&CoverPageInfo->RecCompany + (i*sizeof(LPCTSTR)));
  333. dst = (LPCTSTR *) ((LPBYTE)&CpFields.RecCompany + (i*sizeof(LPCTSTR)));
  334. if (*dst)
  335. {
  336. MemFree ( (LPBYTE) *dst ) ;
  337. }
  338. *dst = (LPCTSTR) StringDup( *src );
  339. }
  340. //
  341. // the time the fax was sent
  342. //
  343. GetLocalTime((LPSYSTEMTIME)&CoverPageInfo->TimeSent);
  344. //
  345. // dwDataTimeLen is the size of s in characters
  346. //
  347. dwDateTimeLen = sizeof(TBuffer) / sizeof (TCHAR);
  348. s = TBuffer;
  349. //
  350. // Get date into s
  351. //
  352. GetY2KCompliantDate( LOCALE_USER_DEFAULT, 0, &CoverPageInfo->TimeSent, s, dwDateTimeLen );
  353. //
  354. // Advance s past the date string and attempt to append time
  355. //
  356. cch = _tcslen( s );
  357. s += cch;
  358. if (++cch < dwDateTimeLen)
  359. {
  360. *s++ = ' ';
  361. //
  362. // DateTimeLen is the decreased by the size of s in characters
  363. //
  364. dwDateTimeLen -= cch;
  365. //
  366. // Get the time here
  367. //
  368. FaxTimeFormat( LOCALE_USER_DEFAULT, 0, &CoverPageInfo->TimeSent, NULL, s, dwDateTimeLen );
  369. }
  370. CpFields.TimeSent = StringDup( TBuffer );
  371. //
  372. // start the coverpage on a new page
  373. //
  374. StartPage( FaxContextInfo->hDC );
  375. //
  376. // print the cover page
  377. //
  378. ec = PrintCoverPage(
  379. FaxContextInfo->hDC,
  380. &CpFields,
  381. CpName,
  382. &CovDocInfo
  383. );
  384. //
  385. // end the page
  386. //
  387. EndPage( FaxContextInfo->hDC );
  388. FreeCpFields( &CpFields );
  389. if (ec != 0)
  390. {
  391. DebugPrintEx(DEBUG_ERR,
  392. TEXT("PrintCoverPage failed. ec = %ld"),
  393. ec);
  394. SetLastError( ec );
  395. retVal = FALSE;
  396. goto exit;
  397. }
  398. exit:
  399. return retVal;
  400. }
  401. #ifdef UNICODE
  402. BOOL
  403. WINAPI
  404. FaxPrintCoverPageA(
  405. IN const FAX_CONTEXT_INFOA *FaxContextInfo,
  406. IN const FAX_COVERPAGE_INFOA *CoverPageInfo
  407. )
  408. /*++
  409. Routine Description:
  410. Prints a coverpage into the printer DC provided.
  411. Arguments:
  412. FaxContextInfo - fax Printer context info (hdc, etc.)
  413. CoverPageInfo - Cover page information
  414. Return Value:
  415. TRUE for success.
  416. FALSE for failure.
  417. --*/
  418. {
  419. //
  420. // assume all fields between Subject and RecName are LPCTSTR's
  421. //
  422. #define COUNT_CP_FIELDS ((LPBYTE) &CoverPageInfoW.Subject - (LPBYTE)&CoverPageInfoW.RecName)/sizeof(LPCTSTR)
  423. DWORD Rval = ERROR_SUCCESS;
  424. FAX_COVERPAGE_INFOW CoverPageInfoW = {0};
  425. FAX_CONTEXT_INFOW ContextInfoW = {0};
  426. LPWSTR ServerName = NULL;
  427. LPWSTR *d;
  428. LPSTR *s;
  429. DWORD i;
  430. DEBUG_FUNCTION_NAME(TEXT("FaxPrintCoverPageA"));
  431. if (!FaxContextInfo || !CoverPageInfo ||
  432. FaxContextInfo->SizeOfStruct != sizeof(FAX_CONTEXT_INFOA) ||
  433. CoverPageInfo->SizeOfStruct != sizeof(FAX_COVERPAGE_INFOA))
  434. {
  435. DebugPrintEx(DEBUG_ERR,
  436. TEXT("CoverPageInfo is NULL or Size mismatch.")
  437. );
  438. SetLastError(ERROR_INVALID_PARAMETER);
  439. return FALSE;
  440. }
  441. ContextInfoW.SizeOfStruct = sizeof(FAX_CONTEXT_INFOW);
  442. ContextInfoW.hDC = FaxContextInfo->hDC;
  443. if (FaxContextInfo->ServerName[0] != (CHAR)'\0')
  444. {
  445. ServerName = AnsiStringToUnicodeString( FaxContextInfo->ServerName );
  446. if (!ServerName && FaxContextInfo->ServerName)
  447. {
  448. Rval = ERROR_OUTOFMEMORY;
  449. goto exit;
  450. }
  451. wcscpy(ContextInfoW.ServerName,ServerName);
  452. }
  453. CoverPageInfoW.SizeOfStruct = sizeof(FAX_COVERPAGE_INFOW);
  454. CoverPageInfoW.UseServerCoverPage = CoverPageInfo->UseServerCoverPage;
  455. CoverPageInfoW.PageCount = CoverPageInfo->PageCount;
  456. CoverPageInfoW.CoverPageName = AnsiStringToUnicodeString( CoverPageInfo->CoverPageName );
  457. if (!CoverPageInfoW.CoverPageName && CoverPageInfo->CoverPageName)
  458. {
  459. Rval = ERROR_OUTOFMEMORY;
  460. goto exit;
  461. }
  462. for (i=0;i<=COUNT_CP_FIELDS;i++)
  463. {
  464. d = (LPWSTR*) ((ULONG_PTR)&CoverPageInfoW.RecName + i*sizeof(LPCWSTR));
  465. s = (LPSTR *) ((LPBYTE)&CoverPageInfo->RecName + i*sizeof(LPSTR));
  466. DebugPrint(( TEXT(" source: 0x%08x --> dest: 0x%08x \n"), s, d));
  467. *d = AnsiStringToUnicodeString( *s );
  468. if (!(*d) && (*s))
  469. {
  470. Rval = ERROR_OUTOFMEMORY;
  471. goto exit;
  472. }
  473. }
  474. CoverPageInfoW.TimeSent = CoverPageInfo->TimeSent;
  475. CoverPageInfoW.PageCount = CoverPageInfo->PageCount;
  476. if (!FaxPrintCoverPageW(
  477. &ContextInfoW,
  478. &CoverPageInfoW
  479. ))
  480. {
  481. Rval = GetLastError();
  482. goto exit;
  483. }
  484. Assert (ERROR_SUCCESS == Rval);
  485. exit:
  486. if (CoverPageInfoW.CoverPageName)
  487. {
  488. MemFree( (LPBYTE) CoverPageInfoW.CoverPageName );
  489. }
  490. if (ServerName)
  491. {
  492. MemFree( (LPBYTE) ServerName );
  493. }
  494. for (i = 0; i < COUNT_CP_FIELDS; i++)
  495. {
  496. d = (LPWSTR *)((ULONG_PTR)&CoverPageInfoW.RecName + i*sizeof(LPWSTR));
  497. if (d && *d)MemFree( (LPBYTE)*d );
  498. }
  499. if (ERROR_SUCCESS != Rval)
  500. {
  501. SetLastError(Rval);
  502. return FALSE;
  503. }
  504. return TRUE;
  505. }
  506. #else
  507. BOOL
  508. WINAPI
  509. FaxPrintCoverPageW(
  510. IN const FAX_CONTEXT_INFOW *FaxContextInfo,
  511. IN const FAX_COVERPAGE_INFOW *CoverPageInfo
  512. )
  513. {
  514. UNREFERENCED_PARAMETER(FaxContextInfo);
  515. UNREFERENCED_PARAMETER(CoverPageInfo);
  516. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  517. return FALSE;
  518. }
  519. #endif
  520. BOOL
  521. WINAPI
  522. FaxStartPrintJob2(
  523. IN LPCTSTR PrinterName,
  524. IN const FAX_PRINT_INFO *PrintInfo,
  525. IN short TiffRes,
  526. OUT LPDWORD FaxJobId,
  527. OUT PFAX_CONTEXT_INFO FaxContextInfo
  528. )
  529. /*++
  530. Routine Description:
  531. Starts a print job for the specified printer. This
  532. function provides functionality beyond what the caller
  533. can provide by using StartDoc(). This function disables
  534. the display of the fax send wizard and also passes along
  535. the information that would otherwise be gathered by the
  536. fax wizard ui.
  537. Arguments:
  538. PrinterName - Fax printer name (must be a fax printer)
  539. PrintInfo - Fax print information
  540. TiffRes - coverpage resolution. 0 for the printer default
  541. FaxJobId - Job id of the resulting print job
  542. FaxContextInfo - context information including hdc
  543. Return Value:
  544. TRUE for success.
  545. FALSE for failure.
  546. --*/
  547. {
  548. HANDLE hPrinter = NULL;
  549. PDEVMODE DevMode = NULL;
  550. PDMPRIVATE DevModePrivate = NULL;
  551. DOCINFO DocInfo;
  552. PJOB_INFO_2 JobInfo = NULL;
  553. PPRINTER_INFO_2 PrinterInfo = NULL;
  554. DWORD dwNeeded = 0;
  555. HDC hDC = NULL;
  556. INT JobId = 0;
  557. LPTSTR strParameters = NULL;
  558. LONG Size;
  559. LPTSTR lptstrFaxPrinterName = NULL;
  560. DEBUG_FUNCTION_NAME(TEXT("FaxStartPrintJob"));
  561. //
  562. // do a little argument validation
  563. //
  564. Assert (TiffRes == 0 || TiffRes == 98 || TiffRes == 196);
  565. if (PrintInfo == NULL || PrintInfo->SizeOfStruct != sizeof(FAX_PRINT_INFOW) ||
  566. !FaxJobId || !FaxContextInfo)
  567. {
  568. DebugPrintEx(DEBUG_ERR,
  569. TEXT("PrintInfo is NULL or Size mismatch.")
  570. );
  571. SetLastError( ERROR_INVALID_PARAMETER );
  572. return FALSE;
  573. }
  574. if (PrintInfo->OutputFileName == NULL &&
  575. (PrintInfo->RecipientNumber == NULL || PrintInfo->RecipientNumber[0] == 0))
  576. {
  577. DebugPrintEx(DEBUG_ERR,
  578. TEXT("No valid recipient number.")
  579. );
  580. SetLastError( ERROR_INVALID_PARAMETER );
  581. return FALSE;
  582. }
  583. if (PrintInfo->Reserved)
  584. {
  585. DebugPrintEx(DEBUG_ERR,
  586. TEXT("Reserved field of FAX_PRINT_INFO should be NULL.")
  587. );
  588. SetLastError( ERROR_INVALID_PARAMETER );
  589. return FALSE;
  590. }
  591. //
  592. // if no printer specified, assume they want a local fax printer
  593. //
  594. if (!PrinterName)
  595. {
  596. lptstrFaxPrinterName = GetFaxPrinterName(NULL); // Need to free this pointer
  597. if (!lptstrFaxPrinterName)
  598. {
  599. DebugPrintEx(DEBUG_ERR,
  600. TEXT("GetFaxPrinterName returned NULL.")
  601. );
  602. SetLastError(ERROR_INVALID_PRINTER_NAME);
  603. goto error_exit;
  604. }
  605. }
  606. else
  607. {
  608. lptstrFaxPrinterName = (LPTSTR)PrinterName;
  609. //
  610. // verify that the printer is a fax printer, the only type allowed
  611. //
  612. if (!IsPrinterFaxPrinter( lptstrFaxPrinterName ))
  613. {
  614. DebugPrintEx(DEBUG_ERR,
  615. TEXT("IsPrinterFaxPrinter failed. Printer name = %s"),
  616. lptstrFaxPrinterName
  617. );
  618. SetLastError( ERROR_INVALID_PRINTER_NAME );
  619. goto error_exit;
  620. }
  621. }
  622. //
  623. // open the printer for normal access (this should always work)
  624. //
  625. if (!OpenPrinter( lptstrFaxPrinterName, &hPrinter, NULL ))
  626. {
  627. DebugPrintEx(DEBUG_ERR,
  628. TEXT("OpenPrinter failed. Printer Name = %s , ec = %ld"),
  629. lptstrFaxPrinterName,
  630. GetLastError());
  631. goto error_exit;
  632. }
  633. //
  634. // get the fax server's name if the fax printer isn't local
  635. //
  636. if (!GetPrinter(hPrinter,2,(LPBYTE)PrinterInfo,0,&dwNeeded))
  637. {
  638. PrinterInfo = (PPRINTER_INFO_2)MemAlloc( dwNeeded );
  639. if (!PrinterInfo)
  640. {
  641. DebugPrintEx(DEBUG_ERR,
  642. TEXT("Cant allocate PPRINTER_INFO_2.")
  643. );
  644. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  645. goto error_exit;
  646. }
  647. }
  648. if (!GetPrinter(hPrinter,2,(LPBYTE)PrinterInfo,dwNeeded,&dwNeeded))
  649. {
  650. DebugPrintEx(DEBUG_ERR,
  651. TEXT("GetPrinter failed. ec = %ld"),
  652. GetLastError());
  653. goto error_exit;
  654. }
  655. if (PrinterInfo->pServerName)
  656. {
  657. if (PrinterInfo->pServerName == _tcsstr (PrinterInfo->pServerName, TEXT("\\\\")))
  658. {
  659. //
  660. // Server name starts with '\\', remove it
  661. //
  662. PrinterInfo->pServerName = _tcsninc (PrinterInfo->pServerName, 2);
  663. }
  664. _tcscpy(FaxContextInfo->ServerName, PrinterInfo->pServerName);
  665. }
  666. else
  667. {
  668. FaxContextInfo->ServerName[0] = NIL;
  669. }
  670. //
  671. // get the required size for the DEVMODE
  672. //
  673. Size = DocumentProperties( NULL, hPrinter, NULL, NULL, NULL, 0 );
  674. if (Size <= 0)
  675. {
  676. DebugPrintEx(DEBUG_ERR,
  677. TEXT("DocumentProperties failed. ec = %ld"),
  678. GetLastError());
  679. goto error_exit;
  680. }
  681. //
  682. // allocate memory for the DEVMODE
  683. //
  684. DevMode = (PDEVMODE) MemAlloc( Size );
  685. if (!DevMode)
  686. {
  687. DebugPrintEx(DEBUG_ERR,
  688. TEXT("Cant allocate DEVMODE.")
  689. );
  690. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  691. goto error_exit;
  692. }
  693. //
  694. // get the default document properties
  695. //
  696. if (DocumentProperties( NULL, hPrinter, NULL, DevMode, NULL, DM_OUT_BUFFER ) != IDOK)
  697. {
  698. DebugPrintEx(DEBUG_ERR,
  699. TEXT("DocumentProperties failed. ec = %ld"),
  700. GetLastError());
  701. goto error_exit;
  702. }
  703. #ifndef WIN95
  704. //
  705. // be sure we are dealing with the correct DEVMODE
  706. //
  707. if (DevMode->dmDriverExtra < sizeof(DMPRIVATE))
  708. {
  709. DebugPrintEx(DEBUG_ERR,
  710. TEXT("Invalid DEVMODE, wrong private data size. DevMode->dmDriverExtra = %ld, sizeof(DMPRIVATE) = %ld"),
  711. DevMode->dmDriverExtra,
  712. sizeof(DMPRIVATE));
  713. SetLastError(ERROR_INVALID_DATA);
  714. goto error_exit;
  715. }
  716. //
  717. // set the private DEVMODE pointer
  718. //
  719. DevModePrivate = (PDMPRIVATE) ((LPBYTE) DevMode + DevMode->dmSize);
  720. //
  721. // set the necessary stuff in the DEVMODE
  722. //
  723. DevModePrivate->sendCoverPage = FALSE;
  724. DevModePrivate->flags |= FAXDM_NO_WIZARD;
  725. DevModePrivate->flags &= ~FAXDM_DRIVER_DEFAULT;
  726. #endif //#ifndef WIN95
  727. //
  728. // Set the necessary reolution
  729. //
  730. if (0 != TiffRes)
  731. {
  732. //
  733. // Set the coverpage resolution to the same value as the body tiff file
  734. //
  735. DevMode->dmYResolution = TiffRes;
  736. }
  737. //
  738. // create the device context
  739. //
  740. hDC = CreateDC( _T("WINSPOOL"), lptstrFaxPrinterName, NULL, DevMode );
  741. if (!hDC)
  742. {
  743. DebugPrintEx(DEBUG_ERR,
  744. TEXT("CreateDC failed. ec = %ld"),
  745. GetLastError());
  746. goto error_exit;
  747. }
  748. //
  749. // set the document information
  750. //
  751. DocInfo.cbSize = sizeof(DOCINFO);
  752. DocInfo.lpszDocName = PrintInfo->DocName;
  753. DocInfo.lpszOutput = PrintInfo->OutputFileName;
  754. DocInfo.lpszDatatype = NULL;
  755. DocInfo.fwType = 0;
  756. //
  757. // start the print job
  758. //
  759. JobId = StartDoc( hDC, &DocInfo );
  760. if (JobId <= 0)
  761. {
  762. DebugPrintEx(DEBUG_ERR,
  763. TEXT("StartDoc failed. ec = %ld"),
  764. GetLastError());
  765. goto error_exit;
  766. }
  767. if (PrintInfo->OutputFileName == NULL)
  768. {
  769. //
  770. // HACK HACK -> pause the print job
  771. //
  772. if (FaxJobId && *FaxJobId == 0xffffffff)
  773. {
  774. SetJob( hPrinter, JobId, 0, NULL, JOB_CONTROL_PAUSE );
  775. }
  776. //
  777. // set the job tags
  778. // this is how we communicate the information to
  779. // the print driver that would otherwise be
  780. // provided by the fax print wizard
  781. //
  782. JobInfo = (PJOB_INFO_2)MyGetJob( hPrinter, 2, JobId );
  783. if (!JobInfo)
  784. {
  785. DebugPrintEx(DEBUG_ERR,
  786. TEXT("MyGetJob failed. ec = %ld"),
  787. GetLastError());
  788. goto error_exit;
  789. }
  790. DWORD dwReceiptFlag = DRT_NONE;
  791. LPTSTR strReceiptAddress = NULL;
  792. if(PrintInfo->DrEmailAddress)
  793. {
  794. dwReceiptFlag = DRT_EMAIL;
  795. strReceiptAddress = LPTSTR(PrintInfo->DrEmailAddress);
  796. }
  797. TCHAR tszNumericData[10] = {0};
  798. if (0 > _sntprintf (tszNumericData,
  799. ARR_SIZE(tszNumericData) -1,
  800. _T("%d"),
  801. dwReceiptFlag))
  802. {
  803. SetLastError(ERROR_BUFFER_OVERFLOW);
  804. DebugPrintEx(DEBUG_ERR,
  805. TEXT("_sntprintf failed. ec = %ld"),
  806. GetLastError());
  807. goto error_exit;
  808. }
  809. FAX_TAG_MAP_ENTRY tagMap[] =
  810. {
  811. //
  812. // Sender info
  813. //
  814. { FAXTAG_NEW_RECORD, FAXTAG_NEW_RECORD_VALUE },
  815. { FAXTAG_BILLING_CODE, LPTSTR(PrintInfo->SenderBillingCode) },
  816. { FAXTAG_RECEIPT_TYPE, tszNumericData },
  817. { FAXTAG_RECEIPT_ADDR, strReceiptAddress },
  818. { FAXTAG_SENDER_NAME, LPTSTR(PrintInfo->SenderName) },
  819. { FAXTAG_SENDER_COMPANY, LPTSTR(PrintInfo->SenderCompany) },
  820. { FAXTAG_SENDER_DEPT, LPTSTR(PrintInfo->SenderDept) },
  821. { FAXTAG_RECIPIENT_COUNT, _T("1") },
  822. //
  823. // Recipient info
  824. //
  825. { FAXTAG_NEW_RECORD, FAXTAG_NEW_RECORD_VALUE },
  826. { FAXTAG_RECIPIENT_NAME, LPTSTR(PrintInfo->RecipientName) },
  827. { FAXTAG_RECIPIENT_NUMBER, LPTSTR(PrintInfo->RecipientNumber) }
  828. };
  829. //
  830. // Call first time to ParamTagToString to find out size of the Parameters string
  831. //
  832. DWORD dwTagCount = sizeof(tagMap)/sizeof(FAX_TAG_MAP_ENTRY);
  833. DWORD dwSize = 0;
  834. ParamTagsToString(tagMap, dwTagCount, NULL, &dwSize);
  835. //
  836. // Allocate the Buffer for the Parameters String
  837. //
  838. strParameters = LPTSTR(MemAlloc(dwSize + sizeof(TCHAR))); // dwSize does not count last NULL
  839. if (!strParameters)
  840. {
  841. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  842. DebugPrintEx(DEBUG_ERR,
  843. _T("strParameters = MemAlloc(%d) failed. ec = %ld"),
  844. dwSize,
  845. GetLastError());
  846. goto error_exit;
  847. }
  848. //
  849. // Get the Parameters string from the ParamTagToString
  850. //
  851. ParamTagsToString(tagMap, dwTagCount, strParameters, &dwSize);
  852. //
  853. // set these fields or the spooler will
  854. // return ACCESS_DENIED for a non-admin client
  855. //
  856. JobInfo->Position = JOB_POSITION_UNSPECIFIED;
  857. JobInfo->pDevMode = NULL;
  858. //
  859. // set our new fax tags
  860. //
  861. JobInfo->pParameters = strParameters;
  862. if (!SetJob( hPrinter, JobId, 2, (LPBYTE) JobInfo, 0 ))
  863. {
  864. DebugPrintEx(DEBUG_ERR,
  865. TEXT("SetJob failed. ec = %ld"),
  866. GetLastError());
  867. goto error_exit;
  868. }
  869. }
  870. //
  871. // clean up and return to the caller
  872. //
  873. ClosePrinter( hPrinter);
  874. MemFree( PrinterInfo);
  875. MemFree( DevMode );
  876. MemFree( strParameters );
  877. MemFree( JobInfo );
  878. if (!PrinterName)
  879. {
  880. MemFree (lptstrFaxPrinterName);
  881. }
  882. if (FaxJobId)
  883. {
  884. *FaxJobId = JobId;
  885. }
  886. FaxContextInfo->hDC = hDC;
  887. return TRUE;
  888. error_exit:
  889. if (hPrinter) {
  890. ClosePrinter( hPrinter);
  891. }
  892. if (PrinterInfo) {
  893. MemFree( PrinterInfo);
  894. }
  895. if (JobId)
  896. {
  897. if (EndDoc( hDC ) <= 0)
  898. {
  899. DebugPrintEx(
  900. DEBUG_ERR,
  901. TEXT("EndDoc failed. (ec: %ld)"),
  902. GetLastError());
  903. }
  904. }
  905. if (hDC)
  906. {
  907. if (!DeleteDC (hDC))
  908. {
  909. DebugPrintEx(
  910. DEBUG_ERR,
  911. TEXT("DeleteDC failed. (ec: %ld)"),
  912. GetLastError());
  913. }
  914. }
  915. if (DevMode) {
  916. MemFree( DevMode );
  917. }
  918. if (strParameters) {
  919. MemFree( strParameters );
  920. }
  921. if (JobInfo) {
  922. MemFree( JobInfo );
  923. }
  924. if (!PrinterName) {
  925. MemFree (lptstrFaxPrinterName);
  926. }
  927. return FALSE;
  928. }
  929. #ifdef UNICODE
  930. BOOL
  931. WINAPI
  932. FaxStartPrintJob2A(
  933. IN LPCSTR PrinterName,
  934. IN const FAX_PRINT_INFOA *PrintInfo,
  935. IN short TiffRes,
  936. OUT LPDWORD JobId,
  937. OUT FAX_CONTEXT_INFOA *FaxContextInfo
  938. )
  939. /*++
  940. Routine Description:
  941. Starts a print job for the specified printer. This
  942. function provides functionality beyond what the caller
  943. can provide by using StartDoc(). This function disables
  944. the display of the fax send wizard and also passes along
  945. the information that would otherwise be gathered by the
  946. fax wizard ui.
  947. Arguments:
  948. PrinterName - Fax printer name (must be a fax printer)
  949. PrintInfo - Fax print information
  950. TiffRes - coverpage resolution. 0 for the printer default
  951. FaxJobId - Job id of the resulting print job
  952. FaxContextInfo - device context information (hdc, etc.)
  953. Return Value:
  954. TRUE for success.
  955. FALSE for failure.
  956. --*/
  957. {
  958. DWORD Rval = ERROR_SUCCESS;
  959. FAX_PRINT_INFOW PrintInfoW;
  960. FAX_CONTEXT_INFOW ContextInfoW;
  961. LPSTR ServerName = NULL;
  962. LPWSTR PrinterNameW = NULL;
  963. DEBUG_FUNCTION_NAME(TEXT("FaxStartPrintJobA"));
  964. if (!PrintInfo || !JobId || !FaxContextInfo ||
  965. (PrintInfo->SizeOfStruct != sizeof(FAX_PRINT_INFOA)))
  966. {
  967. DebugPrintEx(DEBUG_ERR,
  968. TEXT("PrintInfo is NULL or Size mismatch.")
  969. );
  970. SetLastError(ERROR_INVALID_PARAMETER);
  971. return FALSE;
  972. }
  973. if (PrinterName)
  974. {
  975. PrinterNameW = AnsiStringToUnicodeString( PrinterName );
  976. if (!PrinterNameW)
  977. {
  978. SetLastError(ERROR_OUTOFMEMORY);
  979. return FALSE;
  980. }
  981. }
  982. ZeroMemory( &ContextInfoW, sizeof(FAX_CONTEXT_INFOW) );
  983. ContextInfoW.SizeOfStruct = sizeof(FAX_CONTEXT_INFOW) ;
  984. ZeroMemory( &PrintInfoW, sizeof(FAX_PRINT_INFOW) );
  985. PrintInfoW.SizeOfStruct = sizeof(FAX_PRINT_INFOW);
  986. PrintInfoW.DocName = AnsiStringToUnicodeString( PrintInfo->DocName );
  987. if (!PrintInfoW.DocName && PrintInfo->DocName)
  988. {
  989. Rval = ERROR_OUTOFMEMORY;
  990. goto exit;
  991. }
  992. PrintInfoW.RecipientName = AnsiStringToUnicodeString( PrintInfo->RecipientName );
  993. if (!PrintInfoW.RecipientName && PrintInfo->RecipientName)
  994. {
  995. Rval = ERROR_OUTOFMEMORY;
  996. goto exit;
  997. }
  998. PrintInfoW.RecipientNumber = AnsiStringToUnicodeString( PrintInfo->RecipientNumber );
  999. if (!PrintInfoW.RecipientNumber && PrintInfo->RecipientNumber)
  1000. {
  1001. Rval = ERROR_OUTOFMEMORY;
  1002. goto exit;
  1003. }
  1004. PrintInfoW.SenderName = AnsiStringToUnicodeString( PrintInfo->SenderName );
  1005. if (!PrintInfoW.SenderName && PrintInfo->SenderName)
  1006. {
  1007. Rval = ERROR_OUTOFMEMORY;
  1008. goto exit;
  1009. }
  1010. PrintInfoW.SenderCompany = AnsiStringToUnicodeString( PrintInfo->SenderCompany );
  1011. if (!PrintInfoW.SenderCompany && PrintInfo->SenderCompany)
  1012. {
  1013. Rval = ERROR_OUTOFMEMORY;
  1014. goto exit;
  1015. }
  1016. PrintInfoW.SenderDept = AnsiStringToUnicodeString( PrintInfo->SenderDept );
  1017. if (!PrintInfoW.SenderDept && PrintInfo->SenderDept)
  1018. {
  1019. Rval = ERROR_OUTOFMEMORY;
  1020. goto exit;
  1021. }
  1022. PrintInfoW.SenderBillingCode = AnsiStringToUnicodeString( PrintInfo->SenderBillingCode );
  1023. if (!PrintInfoW.SenderBillingCode && PrintInfo->SenderBillingCode)
  1024. {
  1025. Rval = ERROR_OUTOFMEMORY;
  1026. goto exit;
  1027. }
  1028. PrintInfoW.Reserved = AnsiStringToUnicodeString( PrintInfo->Reserved );
  1029. if (!PrintInfoW.Reserved && PrintInfo->Reserved)
  1030. {
  1031. Rval = ERROR_OUTOFMEMORY;
  1032. goto exit;
  1033. }
  1034. PrintInfoW.DrEmailAddress = AnsiStringToUnicodeString( PrintInfo->DrEmailAddress );
  1035. if (!PrintInfoW.DrEmailAddress && PrintInfo->DrEmailAddress)
  1036. {
  1037. Rval = ERROR_OUTOFMEMORY;
  1038. goto exit;
  1039. }
  1040. PrintInfoW.OutputFileName = AnsiStringToUnicodeString( PrintInfo->OutputFileName );
  1041. if (!PrintInfoW.OutputFileName && PrintInfo->OutputFileName)
  1042. {
  1043. Rval = ERROR_OUTOFMEMORY;
  1044. goto exit;
  1045. }
  1046. if (!FaxStartPrintJob2W(
  1047. (LPWSTR) PrinterNameW,
  1048. &PrintInfoW,
  1049. TiffRes,
  1050. JobId,
  1051. &ContextInfoW))
  1052. {
  1053. Rval = GetLastError();
  1054. goto exit;
  1055. }
  1056. ServerName = UnicodeStringToAnsiString( ContextInfoW.ServerName);
  1057. if (ServerName)
  1058. {
  1059. _mbscpy((PUCHAR)FaxContextInfo->ServerName,(PUCHAR)ServerName);
  1060. }
  1061. else
  1062. {
  1063. Rval = ERROR_OUTOFMEMORY;
  1064. goto exit;
  1065. }
  1066. FaxContextInfo->SizeOfStruct = sizeof(FAX_CONTEXT_INFOA);
  1067. FaxContextInfo->hDC = ContextInfoW.hDC;
  1068. Assert (ERROR_SUCCESS == Rval);
  1069. exit:
  1070. MemFree( (LPBYTE) PrinterNameW );
  1071. MemFree( (LPBYTE) PrintInfoW.DocName );
  1072. MemFree( (LPBYTE) PrintInfoW.RecipientName );
  1073. MemFree( (LPBYTE) PrintInfoW.RecipientNumber );
  1074. MemFree( (LPBYTE) PrintInfoW.SenderName );
  1075. MemFree( (LPBYTE) PrintInfoW.SenderCompany );
  1076. MemFree( (LPBYTE) PrintInfoW.SenderDept );
  1077. MemFree( (LPBYTE) PrintInfoW.SenderBillingCode );
  1078. MemFree( (LPBYTE) PrintInfoW.DrEmailAddress );
  1079. MemFree( (LPBYTE) PrintInfoW.OutputFileName );
  1080. MemFree( (LPBYTE) PrintInfoW.Reserved );
  1081. MemFree( (LPBYTE) ServerName );
  1082. if (ERROR_SUCCESS != Rval)
  1083. {
  1084. SetLastError(Rval);
  1085. return FALSE;
  1086. }
  1087. return TRUE;
  1088. }
  1089. #else
  1090. BOOL
  1091. WINAPI
  1092. FaxStartPrintJob2W(
  1093. IN LPCWSTR PrinterName,
  1094. IN const FAX_PRINT_INFOW *PrintInfo,
  1095. IN DWORD TiffRes,
  1096. OUT LPDWORD FaxJobId,
  1097. OUT PFAX_CONTEXT_INFOW FaxContextInfo
  1098. )
  1099. {
  1100. UNREFERENCED_PARAMETER(PrinterName);
  1101. UNREFERENCED_PARAMETER(PrintInfo);
  1102. UNREFERENCED_PARAMETER(TiffRes);
  1103. UNREFERENCED_PARAMETER(FaxJobId);
  1104. UNREFERENCED_PARAMETER(FaxContextInfo);
  1105. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1106. return FALSE;
  1107. }
  1108. #endif