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.

712 lines
16 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 XP fax driver
  9. Revision History:
  10. 02/15/96 -davidx-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include <windows.h>
  16. #include <windowsx.h>
  17. #include <tchar.h>
  18. #include <faxuiconstants.h>
  19. #include "..\..\..\admin\cfgwzrd\FaxCfgWzExp.h"
  20. #include <faxres.h>
  21. #include <faxutil.h>
  22. #include "sendnote.h"
  23. #include "tiff.h"
  24. #include "faxreg.h"
  25. VOID
  26. DisplayErrorMessage(
  27. INT errId
  28. );
  29. //
  30. // Data structure used to pass parameters to "Select Fax Printer" dialog
  31. //
  32. typedef struct
  33. {
  34. LPTSTR pPrinterName;
  35. INT cPrinters;
  36. INT iSelectedPrinterIndex;
  37. PRINTER_INFO_2 *pPrinterInfo2;
  38. } DLGPARAM, *PDLGPARAM;
  39. //
  40. // Global instance handle
  41. //
  42. HINSTANCE g_hResource = NULL;
  43. HMODULE ghInstance = NULL;
  44. INT _debugLevel = 0;
  45. //
  46. // Maximum length of message strings
  47. //
  48. #define MAX_MESSAGE_LEN 256
  49. //
  50. // Maximum length for a printer name
  51. //
  52. #define MAX_PRINTER_NAME MAX_PATH
  53. //
  54. // Window NT fax driver name - currently printer driver name cannot be localized
  55. // so it shouldn't be put into the string resource.
  56. //
  57. static TCHAR faxDriverName[] = FAX_DRIVER_NAME;
  58. VOID
  59. InitSelectFaxPrinter(
  60. HWND hDlg,
  61. PDLGPARAM pDlgParam
  62. )
  63. /*++
  64. Routine Description:
  65. Initialize the "Select Fax Printer" dialog
  66. Arguments:
  67. hDlg - Handle to the print setup dialog window
  68. pDlgParam - Points to print setup dialog parameters
  69. Return Value:
  70. NONE
  71. --*/
  72. {
  73. HWND hwndList;
  74. INT selIndex, printerIndex;
  75. //
  76. // Insert all fax printers into a listbox. Note that we've already filtered
  77. // out non-fax printers earlier by setting their pDriverName field to NULL.
  78. //
  79. if (!(hwndList = GetDlgItem(hDlg, IDC_FAXPRINTER_LIST)))
  80. {
  81. return;
  82. }
  83. for (printerIndex=0; printerIndex < pDlgParam->cPrinters; printerIndex++)
  84. {
  85. if (pDlgParam->pPrinterInfo2[printerIndex].pDriverName)
  86. {
  87. selIndex = (INT)SendMessage(hwndList,
  88. LB_ADDSTRING,
  89. 0,
  90. (LPARAM) pDlgParam->pPrinterInfo2[printerIndex].pPrinterName);
  91. if (selIndex != LB_ERR)
  92. {
  93. if (SendMessage(hwndList, LB_SETITEMDATA, selIndex, printerIndex) == LB_ERR)
  94. {
  95. SendMessage(hwndList, LB_DELETESTRING, selIndex, 0);
  96. }
  97. }
  98. }
  99. }
  100. //
  101. // Select the first fax printer in the list by default
  102. //
  103. SendMessage(hwndList, LB_SETCURSEL, 0, 0);
  104. }
  105. BOOL
  106. GetSelectedFaxPrinter(
  107. HWND hDlg,
  108. PDLGPARAM pDlgParam
  109. )
  110. /*++
  111. Routine Description:
  112. Remember the name of currently selected fax printer
  113. Arguments:
  114. hDlg - Handle to the print setup dialog window
  115. pDlgParam - Points to print setup dialog parameters
  116. Return Value:
  117. TRUE if successful, FALSE otherwise
  118. --*/
  119. {
  120. HWND hwndList;
  121. INT selIndex, printerIndex;
  122. //
  123. // Get current selection index
  124. //
  125. if ((hwndList = GetDlgItem(hDlg, IDC_FAXPRINTER_LIST)) == NULL ||
  126. (selIndex = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0)) == LB_ERR)
  127. {
  128. return FALSE;
  129. }
  130. //
  131. // Retrieve the selected printer index
  132. //
  133. printerIndex = (INT)SendMessage(hwndList, LB_GETITEMDATA, selIndex, 0);
  134. if (printerIndex < 0 || printerIndex >= pDlgParam->cPrinters)
  135. {
  136. return FALSE;
  137. }
  138. //
  139. // Remember the selected fax printer name
  140. //
  141. _tcsncpy(pDlgParam->pPrinterName,
  142. pDlgParam->pPrinterInfo2[printerIndex].pPrinterName,
  143. MAX_PRINTER_NAME);
  144. pDlgParam->iSelectedPrinterIndex = printerIndex;
  145. return TRUE;
  146. }
  147. VOID
  148. CenterWindowOnScreen(
  149. HWND hwnd
  150. )
  151. /*++
  152. Routine Description:
  153. Place the specified windows in the center of the screen
  154. Arguments:
  155. hwnd - Specifies a window to be centered
  156. Return Value:
  157. NONE
  158. --*/
  159. {
  160. HWND hwndDesktop;
  161. RECT windowRect, screenRect;
  162. INT windowWidth, windowHeight, screenWidth, screenHeight;
  163. //
  164. // Get screen dimension
  165. //
  166. hwndDesktop = GetDesktopWindow();
  167. GetWindowRect(hwndDesktop, &screenRect);
  168. screenWidth = screenRect.right - screenRect.left;
  169. screenHeight = screenRect.bottom - screenRect.top;
  170. //
  171. // Get window position
  172. //
  173. GetWindowRect(hwnd, &windowRect);
  174. windowWidth = windowRect.right - windowRect.left;
  175. windowHeight = windowRect.bottom - windowRect.top;
  176. //
  177. // Center the window on screen
  178. //
  179. MoveWindow(hwnd,
  180. screenRect.left + (screenWidth - windowWidth) / 2,
  181. screenRect.top + (screenHeight - windowHeight) / 2,
  182. windowWidth,
  183. windowHeight,
  184. FALSE);
  185. }
  186. INT_PTR CALLBACK
  187. SelectPrinterDlgProc(
  188. HWND hDlg,
  189. UINT uMsg,
  190. WPARAM wParam,
  191. LPARAM lParam
  192. )
  193. /*++
  194. Routine Description:
  195. Dialog procedure for handling "Select Fax Printer" dialog
  196. Arguments:
  197. hDlg - Handle to the dialog window
  198. uMsg, wParam, lParam - Dialog message and message parameters
  199. Return Value:
  200. Depends on dialog message
  201. --*/
  202. {
  203. PDLGPARAM pDlgParam;
  204. switch (uMsg)
  205. {
  206. case WM_INITDIALOG:
  207. //
  208. // Remember the pointer to DLGPARAM structure
  209. //
  210. pDlgParam = (PDLGPARAM) lParam;
  211. Assert(pDlgParam != NULL);
  212. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  213. CenterWindowOnScreen(hDlg);
  214. InitSelectFaxPrinter(hDlg, pDlgParam);
  215. return TRUE;
  216. case WM_COMMAND:
  217. switch (GET_WM_COMMAND_ID(wParam, lParam))
  218. {
  219. case IDC_FAXPRINTER_LIST:
  220. if (GET_WM_COMMAND_CMD(wParam, lParam) != LBN_DBLCLK)
  221. {
  222. break;
  223. }
  224. //
  225. // Fall through - double-clicking in the fax printer list
  226. // is treated the same as clicking OK button
  227. //
  228. case IDOK:
  229. //
  230. // User pressed OK to proceed
  231. //
  232. pDlgParam = (PDLGPARAM) GetWindowLongPtr(hDlg, DWLP_USER);
  233. Assert(pDlgParam != NULL);
  234. if (GetSelectedFaxPrinter(hDlg, pDlgParam))
  235. {
  236. LPTSTR lptstrServerName = pDlgParam->pPrinterInfo2[pDlgParam->iSelectedPrinterIndex].pServerName;
  237. if (lptstrServerName && // Server name exists and
  238. _tcslen(lptstrServerName) > 0 && // not empty (remote printer) and
  239. !VerifyPrinterIsOnline (pDlgParam->pPrinterName)) // printer is inaccessible.
  240. {
  241. DisplayErrorMessage(IDS_PRINTER_OFFLINE);
  242. }
  243. else
  244. {
  245. //
  246. // All is ok
  247. //
  248. EndDialog (hDlg, IDOK);
  249. }
  250. }
  251. else
  252. {
  253. MessageBeep(MB_OK);
  254. }
  255. return TRUE;
  256. case IDCANCEL:
  257. //
  258. // User pressed Cancel to dismiss the dialog
  259. //
  260. EndDialog(hDlg, IDCANCEL);
  261. return TRUE;
  262. }
  263. break;
  264. case WM_HELP:
  265. WinHelpContextPopup(((LPHELPINFO)lParam)->dwContextId, hDlg);
  266. return TRUE;
  267. case WM_CONTEXTMENU:
  268. WinHelpContextPopup(GetWindowContextHelpId((HWND)wParam), hDlg);
  269. return TRUE;
  270. }
  271. return FALSE;
  272. }
  273. VOID
  274. DisplayErrorMessage(
  275. INT errId
  276. )
  277. /*++
  278. Routine Description:
  279. Display an error message dialog
  280. Arguments:
  281. errId - Specifies the resource ID of the error message string
  282. Return Value:
  283. NONE
  284. --*/
  285. {
  286. TCHAR errMsg[MAX_MESSAGE_LEN];
  287. TCHAR errTitle[MAX_MESSAGE_LEN];
  288. DEBUG_FUNCTION_NAME(TEXT("DisplayErrorMessage"));
  289. if(!LoadString(g_hResource, errId, errMsg, MAX_MESSAGE_LEN))
  290. {
  291. DebugPrintEx(DEBUG_ERR, TEXT("LoadString failed. ec = 0x%X"), GetLastError());
  292. return;
  293. }
  294. if(!LoadString(g_hResource, IDS_SENDNOTE, errTitle, MAX_MESSAGE_LEN))
  295. {
  296. DebugPrintEx(DEBUG_ERR, TEXT("LoadString failed. ec = 0x%X"), GetLastError());
  297. return;
  298. }
  299. AlignedMessageBox(NULL, errMsg, errTitle, MB_OK | MB_ICONERROR);
  300. }
  301. BOOL
  302. SelectFaxPrinter(
  303. LPTSTR pPrinterName
  304. )
  305. /*++
  306. Routine Description:
  307. Select a fax printer to send note to
  308. Arguments:
  309. pPrinterName - Points to a buffer for storing selected printer name
  310. Return Value:
  311. TRUE if successful, FALSE if there is an error
  312. --*/
  313. {
  314. PRINTER_INFO_2 *pPrinterInfo2;
  315. DWORD index, cPrinters, cFaxPrinters;
  316. DLGPARAM dlgParam;
  317. //
  318. // Enumerate the list of printers available on the system
  319. //
  320. pPrinterInfo2 = (PPRINTER_INFO_2) MyEnumPrinters(
  321. NULL,
  322. 2,
  323. &cPrinters,
  324. PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS
  325. );
  326. //
  327. // Find out how many fax printers there are:
  328. // case 1: no fax printer at all - display an error message
  329. // case 2: only one fax printer - use it
  330. // case 3: more than one fax printer - display a dialog to let user choose one
  331. //
  332. cFaxPrinters = 0;
  333. for (index=0; index < cPrinters && pPrinterInfo2; index++)
  334. {
  335. if (_tcscmp(pPrinterInfo2[index].pDriverName, faxDriverName) != EQUAL_STRING)
  336. {
  337. pPrinterInfo2[index].pDriverName = NULL;
  338. }
  339. else if (cFaxPrinters++ == 0)
  340. {
  341. _tcsncpy(pPrinterName, pPrinterInfo2[index].pPrinterName, MAX_PRINTER_NAME);
  342. }
  343. }
  344. switch (cFaxPrinters)
  345. {
  346. case 0:
  347. //
  348. // No fax printer is installed - display an error message
  349. //
  350. if(IsWinXPOS())
  351. {
  352. DisplayErrorMessage(IDS_SENDNOTE_NO_FAX_PRINTER);
  353. }
  354. else
  355. {
  356. //
  357. // Down level client
  358. //
  359. DisplayErrorMessage(IDS_NO_FAX_PRINTER_CONNECTION);
  360. }
  361. break;
  362. case 1:
  363. //
  364. // Exactly one fax printer is installed - use it
  365. //
  366. break;
  367. default:
  368. //
  369. // More than one fax printer is available - let use choose one
  370. //
  371. dlgParam.pPrinterInfo2 = pPrinterInfo2;
  372. dlgParam.cPrinters = cPrinters;
  373. dlgParam.pPrinterName = pPrinterName;
  374. if (DialogBoxParam(g_hResource,
  375. MAKEINTRESOURCE(IDD_SELECT_FAXPRINTER),
  376. NULL,
  377. SelectPrinterDlgProc,
  378. (LPARAM) &dlgParam) != IDOK)
  379. {
  380. cFaxPrinters = 0;
  381. }
  382. break;
  383. }
  384. pPrinterName[MAX_PRINTER_NAME-1] = NUL;
  385. MemFree(pPrinterInfo2);
  386. return cFaxPrinters > 0;
  387. }
  388. BOOL
  389. LaunchConfigWizard(
  390. BOOL bExplicit
  391. )
  392. /*++
  393. Routine name : LaunchConfigWizard
  394. Routine description:
  395. launch Fax Configuration Wizard for Windows XP platform only
  396. Arguments:
  397. bExplicit [in] - TRUE if it's an explicit launch
  398. Return Value:
  399. TRUE if the send wizard should continue.
  400. If FALSE, the user failed to set a dialing location and the client console should quit.
  401. --*/
  402. {
  403. HMODULE hConfigWizModule = NULL;
  404. DEBUG_FUNCTION_NAME(TEXT("LaunchConfigWizard"));
  405. if(!IsWinXPOS())
  406. {
  407. return TRUE;
  408. }
  409. hConfigWizModule = LoadLibrary(FAX_CONFIG_WIZARD_DLL);
  410. if(hConfigWizModule)
  411. {
  412. FAX_CONFIG_WIZARD fpFaxConfigWiz;
  413. BOOL bAbort = FALSE;
  414. fpFaxConfigWiz = (FAX_CONFIG_WIZARD)GetProcAddress(hConfigWizModule,
  415. FAX_CONFIG_WIZARD_PROC);
  416. if(fpFaxConfigWiz)
  417. {
  418. if(!fpFaxConfigWiz(bExplicit, &bAbort))
  419. {
  420. DebugPrintEx(
  421. DEBUG_ERR,
  422. TEXT("FaxConfigWizard() failed with %ld"),
  423. GetLastError());
  424. }
  425. }
  426. else
  427. {
  428. DebugPrintEx(
  429. DEBUG_ERR,
  430. TEXT("GetProcAddress(FaxConfigWizard) failed with %ld"),
  431. GetLastError());
  432. }
  433. if(!FreeLibrary(hConfigWizModule))
  434. {
  435. DebugPrintEx(
  436. DEBUG_ERR,
  437. TEXT("FreeLibrary(FxsCgfWz.dll) failed with %ld"),
  438. GetLastError());
  439. }
  440. if (bAbort)
  441. {
  442. //
  443. // User refused to enter a dialing location - stop the client console.
  444. //
  445. return FALSE;
  446. }
  447. }
  448. else
  449. {
  450. DebugPrintEx(
  451. DEBUG_ERR,
  452. TEXT("LoadLibrary(FxsCgfWz.dll) failed with %ld"),
  453. GetLastError());
  454. }
  455. return TRUE;
  456. } // LaunchConfigWizard
  457. #ifdef UNICODE
  458. INT
  459. wWinMain(
  460. HINSTANCE hInstance,
  461. HINSTANCE hPrevInstance,
  462. LPTSTR lpCmdLine,
  463. INT nCmdShow
  464. )
  465. #else
  466. INT
  467. WinMain(
  468. HINSTANCE hInstance,
  469. HINSTANCE hPrevInstance,
  470. LPTSTR lpCmdLine,
  471. INT nCmdShow
  472. )
  473. #endif
  474. /*++
  475. Routine Description:
  476. Application entry point
  477. Arguments:
  478. hInstance - Identifies the current instance of the application
  479. hPrevInstance - Identifies the previous instance of the application
  480. lpCmdLine - Specifies the command line for the application.
  481. nCmdShow - Specifies how the window is to be shown
  482. Return Value:
  483. 0
  484. --*/
  485. {
  486. TCHAR printerName[MAX_PRINTER_NAME+1];
  487. HDC hdc;
  488. TCHAR sendNote[100];
  489. DOCINFO docInfo =
  490. {
  491. sizeof(DOCINFO),
  492. NULL,
  493. NULL,
  494. NULL,
  495. 0,
  496. };
  497. DEBUG_FUNCTION_NAME(TEXT("WinMain"));
  498. InitCommonControls ();
  499. if(IsRTLUILanguage())
  500. {
  501. //
  502. // Set Right-to-Left layout for RTL languages
  503. //
  504. SetRTLProcessLayout();
  505. }
  506. //
  507. // Implicit launch of fax configuration wizard
  508. //
  509. if (!LaunchConfigWizard(FALSE))
  510. {
  511. //
  512. // User refused to enter a dialing location - stop the client console.
  513. //
  514. DebugPrintEx(
  515. DEBUG_MSG,
  516. TEXT("User refused to enter a dialing location - stop now"));
  517. return 0;
  518. }
  519. ghInstance = hInstance;
  520. g_hResource = GetResInstance(hInstance);
  521. if(!g_hResource)
  522. {
  523. return 0;
  524. }
  525. sendNote[0] = TEXT(' ');
  526. LoadString( g_hResource, IDS_SENDNOTE, sendNote, sizeof(sendNote)/sizeof(sendNote[0]));
  527. docInfo.lpszDocName = sendNote ;
  528. //
  529. // Check if a printer name is specified on the command line
  530. //
  531. ZeroMemory(printerName, sizeof(printerName));
  532. if (lpCmdLine)
  533. {
  534. _tcsncpy(printerName, lpCmdLine, MAX_PRINTER_NAME);
  535. printerName[MAX_PRINTER_NAME-1] = NUL;
  536. }
  537. //
  538. // Select a fax printer to send note to if necessary
  539. //
  540. if (IsEmptyString(printerName) && !SelectFaxPrinter(printerName))
  541. {
  542. goto exit;
  543. }
  544. DebugPrintEx(DEBUG_MSG, TEXT("Send note to fax printer: %ws"), printerName);
  545. //
  546. // Set an environment variable so that the driver knows
  547. // the current application is "Send Note" utility.
  548. //
  549. SetEnvironmentVariable(TEXT("NTFaxSendNote"), TEXT("1"));
  550. //
  551. // Create a printer DC and print an empty job
  552. //
  553. if (! (hdc = CreateDC(NULL, printerName, NULL, NULL)))
  554. {
  555. DisplayErrorMessage(IDS_FAX_ACCESS_FAILED);
  556. }
  557. else
  558. {
  559. if (StartDoc(hdc, &docInfo) > 0)
  560. {
  561. if(EndDoc(hdc) <= 0)
  562. {
  563. DebugPrintEx(DEBUG_ERR, TEXT("EndDoc failed. ec = 0x%X"), GetLastError());
  564. DisplayErrorMessage(IDS_FAX_ACCESS_FAILED);
  565. }
  566. }
  567. else
  568. {
  569. DebugPrintEx(DEBUG_ERR, TEXT("StartDoc failed. ec = 0x%X"), GetLastError());
  570. DisplayErrorMessage(IDS_FAX_ACCESS_FAILED);
  571. }
  572. DeleteDC(hdc);
  573. }
  574. exit:
  575. FreeResInstance();
  576. return 0;
  577. }