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.

792 lines
17 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. sendnote.c
  5. Abstract:
  6. Utility program to send fax notes
  7. Environment:
  8. Windows NT fax driver
  9. Revision History:
  10. 02/15/96 -davidx-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "sendnote.h"
  16. #include "tiff.h"
  17. #include "tifflib.h"
  18. #define Align(p, x) (((x) & ((p)-1)) ? (((x) & ~((p)-1)) + p) : (x))
  19. //
  20. // Data structure used to pass parameters to "Select Fax Printer" dialog
  21. //
  22. typedef struct {
  23. LPTSTR pPrinterName;
  24. INT cPrinters;
  25. PRINTER_INFO_2 *pPrinterInfo2;
  26. } DLGPARAM, *PDLGPARAM;
  27. //
  28. // Global instance handle
  29. //
  30. HMODULE ghInstance = NULL;
  31. INT _debugLevel = 0;
  32. //
  33. // Maximum length of message strings
  34. //
  35. #define MAX_MESSAGE_LEN 256
  36. //
  37. // Maximum length for a printer name
  38. //
  39. #define MAX_PRINTER_NAME MAX_PATH
  40. //
  41. // Window NT fax driver name - currently printer driver name cannot be localized
  42. // so it shouldn't be put into the string resource.
  43. //
  44. static TCHAR faxDriverName[] = TEXT("Windows NT Fax Driver");
  45. VOID
  46. InitSelectFaxPrinter(
  47. HWND hDlg,
  48. PDLGPARAM pDlgParam
  49. )
  50. /*++
  51. Routine Description:
  52. Initialize the "Select Fax Printer" dialog
  53. Arguments:
  54. hDlg - Handle to the print setup dialog window
  55. pDlgParam - Points to print setup dialog parameters
  56. Return Value:
  57. NONE
  58. --*/
  59. {
  60. HWND hwndList;
  61. INT selIndex, printerIndex;
  62. //
  63. // Insert all fax printers into a listbox. Note that we've already filtered
  64. // out non-fax printers earlier by setting their pDriverName field to NULL.
  65. //
  66. if (! (hwndList = GetDlgItem(hDlg, IDC_FAXPRINTER_LIST)))
  67. return;
  68. for (printerIndex=0; printerIndex < pDlgParam->cPrinters; printerIndex++) {
  69. if (pDlgParam->pPrinterInfo2[printerIndex].pDriverName) {
  70. selIndex = (INT)SendMessage(hwndList,
  71. LB_ADDSTRING,
  72. 0,
  73. (LPARAM) pDlgParam->pPrinterInfo2[printerIndex].pPrinterName);
  74. if (selIndex != LB_ERR) {
  75. if (SendMessage(hwndList, LB_SETITEMDATA, selIndex, printerIndex) == LB_ERR)
  76. SendMessage(hwndList, LB_DELETESTRING, selIndex, 0);
  77. }
  78. }
  79. }
  80. //
  81. // Select the first fax printer in the list by default
  82. //
  83. SendMessage(hwndList, LB_SETCURSEL, 0, 0);
  84. }
  85. BOOL
  86. GetSelectedFaxPrinter(
  87. HWND hDlg,
  88. PDLGPARAM pDlgParam
  89. )
  90. /*++
  91. Routine Description:
  92. Remember the name of currently selected fax printer
  93. Arguments:
  94. hDlg - Handle to the print setup dialog window
  95. pDlgParam - Points to print setup dialog parameters
  96. Return Value:
  97. TRUE if successful, FALSE otherwise
  98. --*/
  99. {
  100. HWND hwndList;
  101. INT selIndex, printerIndex;
  102. //
  103. // Get current selection index
  104. //
  105. if ((hwndList = GetDlgItem(hDlg, IDC_FAXPRINTER_LIST)) == NULL ||
  106. (selIndex = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0)) == LB_ERR)
  107. {
  108. return FALSE;
  109. }
  110. //
  111. // Retrieve the selected printer index
  112. //
  113. printerIndex = (INT)SendMessage(hwndList, LB_GETITEMDATA, selIndex, 0);
  114. if (printerIndex < 0 || printerIndex >= pDlgParam->cPrinters)
  115. return FALSE;
  116. //
  117. // Remember the selected fax printer name
  118. //
  119. _tcsncpy(pDlgParam->pPrinterName,
  120. pDlgParam->pPrinterInfo2[printerIndex].pPrinterName,
  121. MAX_PRINTER_NAME);
  122. return TRUE;
  123. }
  124. VOID
  125. CenterWindowOnScreen(
  126. HWND hwnd
  127. )
  128. /*++
  129. Routine Description:
  130. Place the specified windows in the center of the screen
  131. Arguments:
  132. hwnd - Specifies a window to be centered
  133. Return Value:
  134. NONE
  135. --*/
  136. {
  137. HWND hwndDesktop;
  138. RECT windowRect, screenRect;
  139. INT windowWidth, windowHeight, screenWidth, screenHeight;
  140. //
  141. // Get screen dimension
  142. //
  143. hwndDesktop = GetDesktopWindow();
  144. GetWindowRect(hwndDesktop, &screenRect);
  145. screenWidth = screenRect.right - screenRect.left;
  146. screenHeight = screenRect.bottom - screenRect.top;
  147. //
  148. // Get window position
  149. //
  150. GetWindowRect(hwnd, &windowRect);
  151. windowWidth = windowRect.right - windowRect.left;
  152. windowHeight = windowRect.bottom - windowRect.top;
  153. //
  154. // Center the window on screen
  155. //
  156. MoveWindow(hwnd,
  157. screenRect.left + (screenWidth - windowWidth) / 2,
  158. screenRect.top + (screenHeight - windowHeight) / 2,
  159. windowWidth,
  160. windowHeight,
  161. FALSE);
  162. }
  163. INT_PTR CALLBACK
  164. SelectPrinterDlgProc(
  165. HWND hDlg,
  166. UINT uMsg,
  167. WPARAM wParam,
  168. LPARAM lParam
  169. )
  170. /*++
  171. Routine Description:
  172. Dialog procedure for handling "Select Fax Printer" dialog
  173. Arguments:
  174. hDlg - Handle to the dialog window
  175. uMsg, wParam, lParam - Dialog message and message parameters
  176. Return Value:
  177. Depends on dialog message
  178. --*/
  179. {
  180. PDLGPARAM pDlgParam;
  181. switch (uMsg) {
  182. case WM_INITDIALOG:
  183. //
  184. // Remember the pointer to DLGPARAM structure
  185. //
  186. pDlgParam = (PDLGPARAM) lParam;
  187. Assert(pDlgParam != NULL);
  188. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  189. CenterWindowOnScreen(hDlg);
  190. InitSelectFaxPrinter(hDlg, pDlgParam);
  191. return TRUE;
  192. case WM_COMMAND:
  193. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  194. case IDC_FAXPRINTER_LIST:
  195. if (GET_WM_COMMAND_CMD(wParam, lParam) != LBN_DBLCLK)
  196. break;
  197. //
  198. // Fall through - double-clicking in the fax printer list
  199. // is treated the same as clicking OK button
  200. //
  201. case IDOK:
  202. //
  203. // User pressed OK to proceed
  204. //
  205. pDlgParam = (PDLGPARAM) GetWindowLongPtr(hDlg, DWLP_USER);
  206. Assert(pDlgParam != NULL);
  207. if (GetSelectedFaxPrinter(hDlg, pDlgParam))
  208. EndDialog(hDlg, IDOK);
  209. else
  210. MessageBeep(MB_OK);
  211. return TRUE;
  212. case IDCANCEL:
  213. //
  214. // User pressed Cancel to dismiss the dialog
  215. //
  216. EndDialog(hDlg, IDCANCEL);
  217. return TRUE;
  218. }
  219. break;
  220. }
  221. return FALSE;
  222. }
  223. VOID
  224. DisplayErrorMessage(
  225. INT errId
  226. )
  227. /*++
  228. Routine Description:
  229. Display an error message dialog
  230. Arguments:
  231. errId - Specifies the resource ID of the error message string
  232. Return Value:
  233. NONE
  234. --*/
  235. {
  236. TCHAR errMsg[MAX_MESSAGE_LEN];
  237. LoadString(ghInstance, errId, errMsg, MAX_MESSAGE_LEN);
  238. MessageBox(NULL, errMsg, NULL, MB_OK | MB_ICONERROR);
  239. }
  240. BOOL
  241. SelectFaxPrinter(
  242. LPTSTR pPrinterName
  243. )
  244. /*++
  245. Routine Description:
  246. Select a fax printer to send note to
  247. Arguments:
  248. pPrinterName - Points to a buffer for storing selected printer name
  249. Return Value:
  250. TRUE if successful, FALSE if there is an error
  251. --*/
  252. {
  253. PRINTER_INFO_2 *pPrinterInfo2;
  254. DWORD index, cPrinters, cFaxPrinters;
  255. DLGPARAM dlgParam;
  256. //
  257. // Enumerate the list of printers available on the system
  258. //
  259. pPrinterInfo2 = MyEnumPrinters(NULL, 2, &cPrinters, PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS);
  260. if (pPrinterInfo2 == NULL || cPrinters == 0) {
  261. MemFree(pPrinterInfo2);
  262. DisplayErrorMessage(IDS_NO_FAX_PRINTER);
  263. return FALSE;
  264. }
  265. //
  266. // Find out how many fax printers there are:
  267. // case 1: no fax printer at all - display an error message
  268. // case 2: only one fax printer - use it
  269. // case 3: more than one fax printer - display a dialog to let user choose one
  270. //
  271. cFaxPrinters = 0;
  272. for (index=0; index < cPrinters; index++) {
  273. if (_tcscmp(pPrinterInfo2[index].pDriverName, faxDriverName) != EQUAL_STRING)
  274. pPrinterInfo2[index].pDriverName = NULL;
  275. else if (cFaxPrinters++ == 0)
  276. _tcsncpy(pPrinterName, pPrinterInfo2[index].pPrinterName, MAX_PRINTER_NAME);
  277. }
  278. switch (cFaxPrinters) {
  279. case 0:
  280. //
  281. // No fax printer is installed - display an error message
  282. //
  283. DisplayErrorMessage(IDS_NO_FAX_PRINTER);
  284. break;
  285. case 1:
  286. //
  287. // Exactly one fax printer is installed - use it
  288. //
  289. break;
  290. default:
  291. //
  292. // More than one fax printer is available - let use choose one
  293. //
  294. dlgParam.pPrinterInfo2 = pPrinterInfo2;
  295. dlgParam.cPrinters = cPrinters;
  296. dlgParam.pPrinterName = pPrinterName;
  297. if (DialogBoxParam(ghInstance,
  298. MAKEINTRESOURCE(IDD_SELECT_FAXPRINTER),
  299. NULL,
  300. SelectPrinterDlgProc,
  301. (LPARAM) &dlgParam) != IDOK)
  302. {
  303. cFaxPrinters = 0;
  304. }
  305. break;
  306. }
  307. pPrinterName[MAX_PRINTER_NAME-1] = NUL;
  308. MemFree(pPrinterInfo2);
  309. return cFaxPrinters > 0;
  310. }
  311. #ifdef FAX_SCAN_ENABLED
  312. #if 0
  313. BOOL
  314. PrintTifFile(
  315. HDC PrinterDC,
  316. LPWSTR FileName
  317. )
  318. {
  319. BOOL Rval = TRUE;
  320. HANDLE hFile;
  321. HANDLE hMap;
  322. DWORD i,j;
  323. INT HorzRes;
  324. INT VertRes;
  325. BOOL Result = FALSE;
  326. DWORD VertResFactor = 1;
  327. PTIFF_HEADER TiffHdr;
  328. DWORD NextIfdSeekPoint;
  329. WORD NumDirEntries = 0;
  330. PTIFF_TAG TiffTags = NULL;
  331. DWORD ImageWidth = 0;
  332. DWORD ImageHeight = 0;
  333. DWORD DataSize = 0;
  334. DWORD DataOffset = 0;
  335. DWORD XRes = 0;
  336. DWORD YRes = 0;
  337. LPBYTE FileBytes;
  338. LPBYTE Bitmap;
  339. LPBYTE dPtr;
  340. LPBYTE sPtr;
  341. INT DestWidth;
  342. INT DestHeight;
  343. FLOAT ScaleX;
  344. FLOAT ScaleY;
  345. FLOAT Scale;
  346. DWORD LineSize;
  347. DWORD dontcare;
  348. PBITMAPINFO SrcBitmapInfo;
  349. SrcBitmapInfo = (PBITMAPINFO) MemAlloc( sizeof(BITMAPINFO) + (sizeof(RGBQUAD)*32) );
  350. if (SrcBitmapInfo == NULL) {
  351. return FALSE;
  352. }
  353. SrcBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  354. SrcBitmapInfo->bmiHeader.biWidth = 0;
  355. SrcBitmapInfo->bmiHeader.biHeight = 0;
  356. SrcBitmapInfo->bmiHeader.biPlanes = 1;
  357. SrcBitmapInfo->bmiHeader.biBitCount = 1;
  358. SrcBitmapInfo->bmiHeader.biCompression = BI_RGB;
  359. SrcBitmapInfo->bmiHeader.biSizeImage = 0;
  360. SrcBitmapInfo->bmiHeader.biXPelsPerMeter = 7874;
  361. SrcBitmapInfo->bmiHeader.biYPelsPerMeter = 7874;
  362. SrcBitmapInfo->bmiHeader.biClrUsed = 0;
  363. SrcBitmapInfo->bmiHeader.biClrImportant = 0;
  364. SrcBitmapInfo->bmiColors[0].rgbBlue = 255;
  365. SrcBitmapInfo->bmiColors[0].rgbGreen = 255;
  366. SrcBitmapInfo->bmiColors[0].rgbRed = 255;
  367. SrcBitmapInfo->bmiColors[0].rgbReserved = 0;
  368. SrcBitmapInfo->bmiColors[1].rgbBlue = 0;
  369. SrcBitmapInfo->bmiColors[1].rgbGreen = 0;
  370. SrcBitmapInfo->bmiColors[1].rgbRed = 0;
  371. SrcBitmapInfo->bmiColors[1].rgbReserved = 0;
  372. HorzRes = GetDeviceCaps( PrinterDC, HORZRES );
  373. VertRes = GetDeviceCaps( PrinterDC, VERTRES );
  374. hFile = CreateFile(
  375. FileName,
  376. GENERIC_READ,
  377. 0,
  378. NULL,
  379. OPEN_EXISTING,
  380. 0,
  381. NULL
  382. );
  383. if (hFile == INVALID_HANDLE_VALUE) {
  384. Rval = FALSE;
  385. goto exit;
  386. }
  387. //
  388. // make sure the file is non-zero length
  389. //
  390. if (GetFileSize(hFile,&dontcare) == 0) {
  391. Rval = FALSE;
  392. goto exit;
  393. }
  394. hMap = CreateFileMapping(
  395. hFile,
  396. NULL,
  397. PAGE_READONLY,
  398. 0,
  399. 0,
  400. NULL
  401. );
  402. if (hMap == NULL) {
  403. Rval = FALSE;
  404. goto exit;
  405. }
  406. FileBytes = MapViewOfFile(
  407. hMap,
  408. FILE_MAP_READ,
  409. 0,
  410. 0,
  411. 0
  412. );
  413. if (FileBytes == NULL) {
  414. Rval = FALSE;
  415. goto exit;
  416. }
  417. TiffHdr = (PTIFF_HEADER) FileBytes;
  418. NextIfdSeekPoint = TiffHdr->IFDOffset;
  419. while (NextIfdSeekPoint) {
  420. NumDirEntries = *(LPWORD)(FileBytes+NextIfdSeekPoint);
  421. TiffTags = (PTIFF_TAG)(FileBytes+NextIfdSeekPoint+sizeof(WORD));
  422. NextIfdSeekPoint = *(LPDWORD)(TiffTags+NumDirEntries);
  423. for (i=0; i<NumDirEntries; i++) {
  424. switch (TiffTags[i].TagId) {
  425. case TIFFTAG_IMAGEWIDTH:
  426. ImageWidth = TiffTags[i].DataOffset;
  427. break;
  428. case TIFFTAG_IMAGELENGTH:
  429. ImageHeight = TiffTags[i].DataOffset;
  430. break;
  431. case TIFFTAG_STRIPBYTECOUNTS:
  432. DataSize = TiffTags[i].DataOffset;
  433. break;
  434. case TIFFTAG_STRIPOFFSETS:
  435. DataOffset = TiffTags[i].DataOffset;
  436. break;
  437. case TIFFTAG_XRESOLUTION:
  438. XRes = *(LPDWORD)(FileBytes+TiffTags[i].DataOffset);
  439. break;
  440. case TIFFTAG_YRESOLUTION:
  441. YRes = *(LPDWORD)(FileBytes+TiffTags[i].DataOffset);
  442. break;
  443. }
  444. }
  445. if (YRes <= 100) {
  446. SrcBitmapInfo->bmiHeader.biYPelsPerMeter /= 2;
  447. VertResFactor = 2;
  448. }
  449. LineSize = ImageWidth / 8;
  450. LineSize += (ImageWidth % 8) ? 1 : 0;
  451. Bitmap = (LPBYTE) VirtualAlloc( NULL, DataSize+(ImageHeight*sizeof(DWORD)), MEM_COMMIT, PAGE_READWRITE );
  452. if (Bitmap) {
  453. sPtr = FileBytes + DataOffset;
  454. dPtr = Bitmap;
  455. for (j=0; j<ImageHeight; j++) {
  456. CopyMemory( dPtr, sPtr, LineSize );
  457. sPtr += LineSize;
  458. dPtr = (LPBYTE) Align( 4, (ULONG_PTR)dPtr+LineSize );
  459. }
  460. StartPage( PrinterDC );
  461. ScaleX = (FLOAT) ImageWidth / (FLOAT) HorzRes;
  462. ScaleY = ((FLOAT) ImageHeight * VertResFactor) / (FLOAT) VertRes;
  463. Scale = ScaleX > ScaleY ? ScaleX : ScaleY;
  464. DestWidth = (int) ((FLOAT) ImageWidth / Scale);
  465. DestHeight = (int) (((FLOAT) ImageHeight * VertResFactor) / Scale);
  466. SrcBitmapInfo->bmiHeader.biWidth = ImageWidth;
  467. SrcBitmapInfo->bmiHeader.biHeight = - (INT) ImageHeight;
  468. StretchDIBits(
  469. PrinterDC,
  470. 0,
  471. 0,
  472. DestWidth,
  473. DestHeight,
  474. 0,
  475. 0,
  476. ImageWidth,
  477. ImageHeight,
  478. Bitmap,
  479. (BITMAPINFO *) &SrcBitmapInfo,
  480. DIB_RGB_COLORS,
  481. SRCCOPY
  482. );
  483. EndPage( PrinterDC );
  484. VirtualFree( Bitmap, 0, MEM_RELEASE );
  485. } else {
  486. Rval = FALSE;
  487. }
  488. }
  489. exit:
  490. if (FileBytes) {
  491. UnmapViewOfFile( FileBytes );
  492. }
  493. if (hMap) {
  494. CloseHandle( hMap );
  495. }
  496. if (hFile) {
  497. CloseHandle( hFile );
  498. }
  499. if (SrcBitmapInfo) {
  500. MemFree( SrcBitmapInfo );
  501. }
  502. return Rval;
  503. }
  504. #endif
  505. #endif
  506. INT
  507. wWinMain(
  508. HINSTANCE hInstance,
  509. HINSTANCE hPrevInstance,
  510. LPTSTR lpCmdLine,
  511. INT nCmdShow
  512. )
  513. /*++
  514. Routine Description:
  515. Application entry point
  516. Arguments:
  517. hInstance - Identifies the current instance of the application
  518. hPrevInstance - Identifies the previous instance of the application
  519. lpCmdLine - Specifies the command line for the application.
  520. nCmdShow - Specifies how the window is to be shown
  521. Return Value:
  522. 0
  523. --*/
  524. {
  525. TCHAR printerName[MAX_PRINTER_NAME];
  526. HDC hdc;
  527. TCHAR sendNote[100];
  528. DOCINFO docInfo = {
  529. sizeof(DOCINFO),
  530. NULL,
  531. NULL,
  532. NULL,
  533. 0,
  534. };
  535. ghInstance = hInstance;
  536. sendNote[0] = TEXT(' ');
  537. LoadString( ghInstance, IDS_SENDNOTE, sendNote, sizeof(sendNote)/sizeof(TCHAR) );
  538. docInfo.lpszDocName = sendNote ;
  539. //
  540. // Check if a printer name is specified on the command line
  541. //
  542. ZeroMemory(printerName, sizeof(printerName));
  543. if (lpCmdLine) {
  544. _tcsncpy(printerName, lpCmdLine, MAX_PRINTER_NAME);
  545. printerName[MAX_PRINTER_NAME-1] = NUL;
  546. }
  547. //
  548. // Select a fax printer to send note to if necessary
  549. //
  550. if (IsEmptyString(printerName) && !SelectFaxPrinter(printerName))
  551. return 0;
  552. Verbose(("Send note to fax printer: %ws\n", printerName));
  553. //
  554. // Set an environment variable so that the driver knows
  555. // the current application is "Send Note" utility.
  556. //
  557. SetEnvironmentVariable(TEXT("NTFaxSendNote"), TEXT("1"));
  558. //
  559. // Create a printer DC and print an empty job
  560. //
  561. if (! (hdc = CreateDC(NULL, printerName, NULL, NULL))) {
  562. DisplayErrorMessage(IDS_CREATEDC_FAILED);
  563. } else {
  564. if (StartDoc(hdc, &docInfo) > 0) {
  565. #ifdef FAX_SCAN_ENABLED
  566. TCHAR FileName[MAX_PATH];
  567. if (GetEnvironmentVariable( TEXT("ScanTifName"), FileName, sizeof(FileName)/sizeof(TCHAR) )) {
  568. PrintTiffFile( hdc, FileName );
  569. DeleteFile( FileName );
  570. }
  571. #endif
  572. EndDoc(hdc);
  573. }
  574. DeleteDC(hdc);
  575. }
  576. return 0;
  577. }