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.

1576 lines
42 KiB

  1. /*++
  2. Copyright (c) 1999 - 2000 Microsoft Corporation
  3. Module Name:
  4. wizard.c
  5. Abstract:
  6. Fax configuration wizard main function
  7. Environment:
  8. Fax configuration wizard
  9. Revision History:
  10. 03/13/00 -taoyuan-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "faxcfgwz.h"
  16. #include <shfusion.h>
  17. HANDLE g_hFaxSvcHandle = NULL;
  18. LIST_ENTRY g_PageList; // to keep track of the previous page.
  19. BOOL g_bShowDevicePages = TRUE;
  20. BOOL g_bShowUserInfo = TRUE;
  21. WIZARDDATA g_wizData = {0};
  22. extern PPRINTER_NAMES g_pPrinterNames;
  23. extern DWORD g_dwNumPrinters;
  24. const LPCTSTR g_RoutingGuids[RM_COUNT] =
  25. {
  26. REGVAL_RM_FOLDER_GUID, // RM_FOLDER
  27. REGVAL_RM_PRINTING_GUID // RM_PRINT
  28. };
  29. typedef struct _WIZARDPAGEINFO
  30. {
  31. INT pageId; // page dialog id
  32. DLGPROC dlgProc; // page dialog callback function
  33. BOOL bSelected; // Whether this page is selected in the wizard
  34. INT Title; // title id from the resource file
  35. INT SubTitle; // sub title id from the resource file
  36. } WIZARDPAGEINFO, *PWIZARDPAGEINFO;
  37. //
  38. // all configuration pages are false here, they will be initialized by FaxConfigWizard()
  39. //
  40. static WIZARDPAGEINFO g_FaxWizardPage[] =
  41. {
  42. { IDD_CFG_WIZARD_WELCOME, WelcomeDlgProc, TRUE, 0, 0 },
  43. { IDD_WIZARD_USER_INFO, UserInfoDlgProc, FALSE, IDS_WIZ_USER_INFO_TITLE, IDS_WIZ_USER_INFO_SUB },
  44. { IDD_DEVICE_LIMIT_SELECT, DevLimitDlgProc, FALSE, IDS_DEVICE_LIMIT_TITLE, IDS_DEVICE_LIMIT_SUB },
  45. { IDD_ONE_DEVICE_LIMIT, OneDevLimitDlgProc, FALSE, IDS_ONE_DEVICE_TITLE, IDS_ONE_DEVICE_SUB },
  46. { IDD_WIZARD_SEND_SELECT_DEVICES, SendDeviceDlgProc, FALSE, IDS_WIZ_SEND_DEVICE_TITLE, IDS_WIZ_SEND_DEVICE_SUB },
  47. { IDD_WIZARD_SEND_TSID, SendTsidDlgProc, FALSE, IDS_WIZ_SEND_TSID_TITLE, IDS_WIZ_SEND_TSID_SUB },
  48. { IDD_WIZARD_RECV_SELECT_DEVICES, RecvDeviceDlgProc, FALSE, IDS_WIZ_RECV_DEVICE_TITLE, IDS_WIZ_RECV_DEVICE_SUB },
  49. { IDD_WIZARD_RECV_CSID, RecvCsidDlgProc, FALSE, IDS_WIZ_RECV_CSID_TITLE, IDS_WIZ_RECV_CSID_SUB },
  50. { IDD_WIZARD_RECV_ROUTE, RecvRouteDlgProc, FALSE, IDS_WIZ_RECV_ROUTE_TITLE, IDS_WIZ_RECV_ROUTE_SUB },
  51. { IDD_WIZARD_COMPLETE, CompleteDlgProc, TRUE, 0, 0 }
  52. };
  53. #define TIME_TO_WAIT_FOR_CONVERSTION 25000
  54. #define NUM_PAGES (sizeof(g_FaxWizardPage)/sizeof(WIZARDPAGEINFO))
  55. enum WIZARD_PAGE
  56. {
  57. WELCOME = 0,
  58. USER_INFO,
  59. DEV_LIMIT,
  60. ONE_DEV_LIMIT,
  61. SEND_DEVICE,
  62. TSID,
  63. RECV_DEVICE,
  64. CSID,
  65. ROUTE
  66. };
  67. #define TITLE_SIZE 600
  68. BOOL LoadDeviceData();
  69. BOOL SaveDeviceData();
  70. void FreeDeviceData();
  71. DWORD ConvertCpeFilesToCov();
  72. BOOL
  73. FillInPropertyPage(
  74. PROPSHEETPAGE *psp,
  75. PWIZARDPAGEINFO pPageInfo
  76. )
  77. /*++
  78. Routine Description:
  79. Fill out a PROPSHEETPAGE structure with the supplied parameters
  80. Arguments:
  81. psp - Points to the PROPSHEETPAGE structure to be filled out
  82. pData - Pointer to the shared data structure
  83. Return Value:
  84. NONE
  85. --*/
  86. {
  87. LPTSTR pWizardTitle = NULL;
  88. LPTSTR pWizardSubTitle = NULL;
  89. DEBUG_FUNCTION_NAME(TEXT("FillInPropertyPage()"));
  90. Assert(psp);
  91. DebugPrintEx(DEBUG_MSG, TEXT("FillInPropertyPage %d"), pPageInfo->pageId);
  92. psp->dwSize = sizeof(PROPSHEETPAGE);
  93. //
  94. // Don't show titles if it's the first or last page
  95. //
  96. if (0 == pPageInfo->Title && 0 == pPageInfo->SubTitle)
  97. {
  98. psp->dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
  99. }
  100. else
  101. {
  102. psp->dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  103. }
  104. psp->hInstance = g_hResource;
  105. psp->pszTemplate = MAKEINTRESOURCE(pPageInfo->pageId);
  106. psp->pfnDlgProc = pPageInfo->dlgProc;
  107. if (pPageInfo->Title)
  108. {
  109. pWizardTitle = (LPTSTR)MemAlloc(TITLE_SIZE*sizeof(TCHAR));
  110. if(!pWizardTitle)
  111. {
  112. DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed"));
  113. goto error;;
  114. }
  115. if (!LoadString(g_hResource, pPageInfo->Title, pWizardTitle, TITLE_SIZE))
  116. {
  117. DebugPrintEx(DEBUG_ERR,
  118. TEXT("LoadString failed. string ID=%d, error=%d"),
  119. pPageInfo->Title,
  120. GetLastError());
  121. goto error;
  122. }
  123. }
  124. if (pPageInfo->SubTitle)
  125. {
  126. pWizardSubTitle = (LPTSTR)MemAlloc(TITLE_SIZE*sizeof(TCHAR) );
  127. if(!pWizardSubTitle)
  128. {
  129. DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed"));
  130. goto error;
  131. }
  132. ZeroMemory(pWizardSubTitle, TITLE_SIZE*sizeof(TCHAR));
  133. if(IDS_DEVICE_LIMIT_SUB == pPageInfo->SubTitle && g_wizData.dwDeviceLimit != INFINITE)
  134. {
  135. //
  136. // Format limit device selection page subtitle
  137. //
  138. TCHAR tszBuffer[MAX_PATH];
  139. if (!LoadString(g_hResource, pPageInfo->SubTitle, tszBuffer, MAX_PATH))
  140. {
  141. DebugPrintEx(DEBUG_ERR,
  142. TEXT("LoadString failed. string ID=%d, error=%d"),
  143. pPageInfo->SubTitle,
  144. GetLastError());
  145. goto error;
  146. }
  147. _sntprintf(pWizardSubTitle, TITLE_SIZE-1, tszBuffer, g_wizData.dwDeviceLimit);
  148. }
  149. else if (!LoadString(g_hResource, pPageInfo->SubTitle, pWizardSubTitle, TITLE_SIZE))
  150. {
  151. DebugPrintEx(DEBUG_ERR,
  152. TEXT("LoadString failed. string ID=%d, error=%d"),
  153. pPageInfo->SubTitle,
  154. GetLastError());
  155. goto error;
  156. }
  157. }
  158. psp->pszHeaderTitle = pWizardTitle;
  159. psp->pszHeaderSubTitle = pWizardSubTitle;
  160. return TRUE;
  161. error:
  162. MemFree(pWizardTitle);
  163. MemFree(pWizardSubTitle);
  164. return FALSE;
  165. }
  166. BOOL
  167. FaxConfigWizard(
  168. BOOL bExplicitLaunch,
  169. LPBOOL lpbAbort
  170. )
  171. /*++
  172. Routine Description:
  173. Present the Fax Configuration Wizard to the user.
  174. Arguments:
  175. bExplicitLaunch - [in] Fax Config Wizard was launched explicitly
  176. lpbAbort - [out] TRUE if the user refused to enter a dialing location and the calling process should abort.
  177. Return Value:
  178. TRUE if successful, FALSE if there is an error or the user pressed Cancel.
  179. --*/
  180. {
  181. HWND hWnd; // window handle of the calling method
  182. PROPSHEETPAGE psp[NUM_PAGES] = {0};
  183. PROPSHEETPAGE* pspSaved;
  184. PROPSHEETHEADER psh = {0};
  185. BOOL bResult = FALSE;
  186. HDC hdc = NULL;
  187. DWORD i = 0;
  188. DWORD dwPageCount = 0;
  189. LPTSTR lptstrResource = NULL;
  190. BOOL bLinkWindowRegistered = FALSE;
  191. int nRes;
  192. BOOL bSHFusionInitialized = FALSE;
  193. INITCOMMONCONTROLSEX CommonControlsEx = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES };
  194. DEBUG_FUNCTION_NAME(TEXT("FaxConfigWizard()"));
  195. //
  196. // initialize the link list for tracing pages
  197. //
  198. InitializeListHead(&g_PageList);
  199. //
  200. // Enable SHAutoComplete
  201. //
  202. CoInitialize(NULL);
  203. //
  204. // Fusion Initialize
  205. //
  206. if (!SHFusionInitializeFromModuleID(g_hModule, SXS_MANIFEST_RESOURCE_ID))
  207. {
  208. DebugPrintEx(DEBUG_ERR, TEXT("SHFusionInitializeFromModuleID failed."));
  209. }
  210. else
  211. {
  212. bSHFusionInitialized = TRUE;
  213. }
  214. if (!InitCommonControlsEx(&CommonControlsEx))
  215. {
  216. DebugPrintEx(DEBUG_ERR, TEXT("InitCommonControlsEx failed"));
  217. goto exit;
  218. }
  219. hWnd = GetActiveWindow();
  220. g_wizData.hWndParent = hWnd;
  221. //
  222. // On first time, convert CPE files from CSIDL_COMMON_APPDATA\Microsoft\Windows NT\MSFax\Common Coverpages
  223. // to the user personal cover page directory: CSIDL_PERSONAL\Fax\Personal Coverpages
  224. //
  225. if (ConvertCpeFilesToCov() != ERROR_SUCCESS)
  226. {
  227. DebugPrintEx(DEBUG_ERR, TEXT("ConvertCpeFilesToCov failed, continue anyways"));
  228. }
  229. //
  230. // Check if the user has run this wizard before
  231. //
  232. if(!bExplicitLaunch)
  233. {
  234. BOOL bDeviceConfigured = FALSE;
  235. BOOL bExistsPrinterConnection = FALSE;
  236. TCHAR tszPrnName[MAX_PATH];
  237. //
  238. // Is the user info already configured?
  239. //
  240. if(IsUserInfoConfigured())
  241. {
  242. g_bShowUserInfo = FALSE;
  243. }
  244. //
  245. // Are fax devices already configured?
  246. //
  247. if(!FaxGetConfigWizardUsed(&bDeviceConfigured))
  248. {
  249. DebugPrintEx(DEBUG_ERR, TEXT("FaxGetConfigWizardUsed failed. ec = %d"), GetLastError());
  250. goto exit;
  251. }
  252. //
  253. //Are there any printer connections installed?
  254. //
  255. if (GetFirstRemoteFaxPrinterName(tszPrnName,MAX_PATH))
  256. {
  257. bExistsPrinterConnection = TRUE;
  258. }
  259. if(bDeviceConfigured || bExistsPrinterConnection)
  260. {
  261. g_bShowDevicePages = FALSE;
  262. }
  263. }
  264. if(!g_bShowUserInfo && !g_bShowDevicePages)
  265. {
  266. //
  267. // No pages to show - no error
  268. //
  269. bResult = TRUE;
  270. goto exit;
  271. }
  272. //
  273. // We're going to call into the local fax server - connect to it now.
  274. //
  275. if(!Connect())
  276. {
  277. if(bExplicitLaunch)
  278. {
  279. DisplayMessageDialog(hWnd, 0, 0, IDS_ERR_CANT_CONNECT);
  280. }
  281. DebugPrintEx(DEBUG_ERR, TEXT("Can't connect to fax server. ec = %d"), GetLastError());
  282. goto exit;
  283. }
  284. *lpbAbort = FALSE;
  285. if(g_bShowDevicePages)
  286. {
  287. if(FaxAccessCheckEx(g_hFaxSvcHandle, FAX_ACCESS_MANAGE_CONFIG, NULL))
  288. {
  289. //
  290. // IsFaxDeviceInstalled() prompts to install a device if needed
  291. //
  292. if(!IsFaxDeviceInstalled(g_wizData.hWndParent, lpbAbort))
  293. {
  294. g_bShowDevicePages = FALSE;
  295. }
  296. }
  297. else
  298. {
  299. //
  300. // the user has no manage access
  301. //
  302. g_bShowDevicePages = FALSE;
  303. }
  304. }
  305. if (*lpbAbort)
  306. {
  307. //
  308. // the user refused to enter a dialing location and the calling process should abort.
  309. //
  310. DebugPrintEx(DEBUG_MSG,
  311. TEXT("The user refused to enter a dialing location and the calling process should abort"));
  312. return FALSE;
  313. }
  314. if(g_bShowDevicePages)
  315. {
  316. TCHAR tszPrnName[MAX_PATH];
  317. if(GetFirstLocalFaxPrinterName(tszPrnName, MAX_PATH-1))
  318. {
  319. // TODO: suggest install printer
  320. }
  321. }
  322. if(!g_bShowUserInfo && !g_bShowDevicePages)
  323. {
  324. //
  325. // no pages to show - no error
  326. //
  327. bResult = TRUE;
  328. goto exit;
  329. }
  330. //
  331. // Load shared data
  332. //
  333. if(!LoadWizardData())
  334. {
  335. DebugPrintEx(DEBUG_ERR, TEXT("Load data error."));
  336. goto exit;
  337. }
  338. //
  339. // Set page information depending on user selection as well as checking user access right
  340. //
  341. if(g_bShowUserInfo)
  342. {
  343. g_FaxWizardPage[USER_INFO].bSelected = TRUE;
  344. }
  345. if(g_bShowDevicePages)
  346. {
  347. HKEY hRegKey;
  348. DWORD dwDisableRouting = 0;
  349. Assert(g_wizData.dwDeviceCount);
  350. if(1 == g_wizData.dwDeviceLimit)
  351. {
  352. g_FaxWizardPage[ONE_DEV_LIMIT].bSelected = TRUE;
  353. }
  354. else if(g_wizData.dwDeviceLimit < g_wizData.dwDeviceCount)
  355. {
  356. g_FaxWizardPage[DEV_LIMIT].bSelected = TRUE;
  357. }
  358. g_FaxWizardPage[SEND_DEVICE].bSelected = (1 < g_wizData.dwDeviceLimit);
  359. g_FaxWizardPage[TSID].bSelected = TRUE;
  360. g_FaxWizardPage[RECV_DEVICE].bSelected = (1 < g_wizData.dwDeviceLimit);
  361. g_FaxWizardPage[CSID].bSelected = TRUE;
  362. hRegKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAXSERVER, FALSE, KEY_READ);
  363. if(hRegKey)
  364. {
  365. dwDisableRouting = GetRegistryDword(hRegKey, REGVAL_CFGWZRD_DISABLE_ROUTING);
  366. RegCloseKey(hRegKey);
  367. }
  368. g_FaxWizardPage[ROUTE].bSelected = dwDisableRouting ? FALSE : TRUE;
  369. }
  370. //
  371. // Register the link window class
  372. //
  373. bLinkWindowRegistered = LinkWindow_RegisterClass();
  374. if(!bLinkWindowRegistered)
  375. {
  376. DebugPrintEx(DEBUG_ERR, TEXT("LinkWindow_RegisterClass() failed - unable to register link window class"));
  377. }
  378. //
  379. // Fill out one PROPSHEETPAGE structure for every page:
  380. // The first page is a welcome page
  381. // The last page is a complete page
  382. //
  383. pspSaved = psp;
  384. for(i = 0; i < NUM_PAGES; i++)
  385. {
  386. if(g_FaxWizardPage[i].bSelected)
  387. {
  388. if(!FillInPropertyPage(pspSaved++, &g_FaxWizardPage[i]))
  389. {
  390. DebugPrintEx(DEBUG_ERR, TEXT("FillInPropertyPage failed"));
  391. goto exit;
  392. }
  393. dwPageCount++;
  394. }
  395. }
  396. //
  397. // Fill out the PROPSHEETHEADER structure
  398. //
  399. psh.dwSize = sizeof(PROPSHEETHEADER);
  400. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
  401. psh.hwndParent = hWnd;
  402. psh.hInstance = g_hResource;
  403. psh.hIcon = NULL;
  404. psh.pszCaption = TEXT("");
  405. psh.nPages = dwPageCount;
  406. psh.nStartPage = 0;
  407. psh.ppsp = psp;
  408. if(hdc = GetDC(NULL))
  409. {
  410. if(GetDeviceCaps(hdc, BITSPIXEL) >= 8)
  411. {
  412. lptstrResource = MAKEINTRESOURCE(IDB_FAXWIZ_WATERMARK_256);
  413. }
  414. else
  415. {
  416. lptstrResource = MAKEINTRESOURCE(IDB_FAXWIZ_WATERMARK_16);
  417. }
  418. ReleaseDC(NULL,hdc);
  419. hdc = NULL;
  420. }
  421. psh.pszbmHeader = MAKEINTRESOURCE(IDB_CFG_WIZ_BITMAP);
  422. psh.pszbmWatermark = lptstrResource;
  423. //
  424. // Display the wizard pages
  425. //
  426. nRes = (int)PropertySheet(&psh);
  427. if (nRes > 0 && g_wizData.bFinishPressed)
  428. {
  429. //
  430. // Save new settings here
  431. //
  432. if(!SaveWizardData())
  433. {
  434. DisplayMessageDialog(hWnd, MB_ICONERROR, 0, IDS_ERR_NOT_SAVE);
  435. DebugPrintEx(DEBUG_ERR, TEXT("Can't save wizard data."));
  436. goto exit;
  437. }
  438. }
  439. else if(0 == nRes && !bExplicitLaunch) // Cancel
  440. {
  441. if(IDNO == DisplayMessageDialog(hWnd,
  442. MB_YESNO | MB_ICONQUESTION,
  443. 0,
  444. IDS_SHOW_NEXT_TIME))
  445. {
  446. if (g_bShowUserInfo)
  447. {
  448. DWORD dwRes;
  449. HKEY hRegKey = OpenRegistryKey(HKEY_CURRENT_USER,
  450. REGKEY_FAX_SETUP,
  451. TRUE,
  452. KEY_ALL_ACCESS);
  453. if(hRegKey)
  454. {
  455. SetRegistryDword(hRegKey, REGVAL_CFGWZRD_USER_INFO, TRUE);
  456. dwRes = RegCloseKey(hRegKey);
  457. if(ERROR_SUCCESS != dwRes)
  458. {
  459. Assert(FALSE);
  460. DebugPrintEx(DEBUG_ERR, TEXT("RegCloseKey failed: error=%d"), dwRes);
  461. }
  462. }
  463. else
  464. {
  465. DebugPrintEx(DEBUG_ERR,
  466. TEXT("OpenRegistryKey failed: error=%d"),
  467. GetLastError());
  468. }
  469. }
  470. if (g_bShowDevicePages ||
  471. FaxAccessCheckEx(g_hFaxSvcHandle, FAX_ACCESS_MANAGE_CONFIG, NULL))
  472. {
  473. //
  474. // If the user has manage access and does not have a fax device
  475. // it's mean she refused to install it.
  476. // So, we should not disturb her
  477. // with implicit invocation of the Configuration Wizard.
  478. //
  479. if(!FaxSetConfigWizardUsed(g_hFaxSvcHandle, TRUE))
  480. {
  481. DebugPrintEx(DEBUG_ERR, TEXT("FaxSetConfigWizardUsed failed with %d"), GetLastError());
  482. }
  483. }
  484. }
  485. }
  486. else if(nRes < 0)
  487. {
  488. DebugPrintEx(DEBUG_ERR, TEXT("PropertySheet() failed (ec: %ld)"), GetLastError());
  489. }
  490. bResult = TRUE;
  491. exit:
  492. //
  493. // Cleanup properly before exiting
  494. //
  495. for (i = 0; i< dwPageCount; i++)
  496. {
  497. MemFree((PVOID)psp[i].pszHeaderTitle );
  498. MemFree((PVOID)psp[i].pszHeaderSubTitle );
  499. }
  500. FreeWizardData();
  501. ClearPageList();
  502. if( bLinkWindowRegistered )
  503. {
  504. LinkWindow_UnregisterClass( g_hResource );
  505. }
  506. DisConnect();
  507. if (g_pPrinterNames)
  508. {
  509. ReleasePrinterNames (g_pPrinterNames, g_dwNumPrinters);
  510. g_pPrinterNames = NULL;
  511. }
  512. if (bSHFusionInitialized)
  513. {
  514. SHFusionUninitialize();
  515. }
  516. CoUninitialize();
  517. return bResult;
  518. } // FaxConfigWizard
  519. BOOL
  520. LoadWizardData()
  521. /*++
  522. Routine Description:
  523. Load the wizard data from the system.
  524. If there are more than one device, we load the data for the first available device.
  525. Arguments:
  526. Return Value:
  527. TRUE if successful, FALSE if there is an error
  528. --*/
  529. {
  530. DEBUG_FUNCTION_NAME(TEXT("LoadWizardData()"));
  531. if (g_bShowUserInfo)
  532. {
  533. if(!LoadUserInfo())
  534. {
  535. //
  536. // no user info
  537. //
  538. DebugPrintEx(DEBUG_MSG, TEXT("LoadUserInfo: failed: error=%d"), GetLastError());
  539. }
  540. }
  541. //
  542. // get the large fonts for wizard97
  543. //
  544. if(!LoadWizardFont())
  545. {
  546. DebugPrintEx(DEBUG_MSG, TEXT("LoadWizardFont: failed."));
  547. goto error;
  548. }
  549. if (g_bShowDevicePages)
  550. {
  551. if(!LoadDeviceData())
  552. {
  553. DebugPrintEx(DEBUG_MSG, TEXT("LoadDeviceData: failed."));
  554. goto error;
  555. }
  556. }
  557. return TRUE;
  558. error:
  559. FreeWizardData();
  560. return FALSE;
  561. } // LoadWizardData
  562. BOOL
  563. LoadWizardFont()
  564. /*++
  565. Routine Description:
  566. Load the wizard font for the title.
  567. Arguments:
  568. pData - Points to the user mode memory structure
  569. Return Value:
  570. TRUE if successful, FALSE if there is an error
  571. --*/
  572. {
  573. HDC hdc = NULL;
  574. LOGFONT lfTitleFont = {0};
  575. NONCLIENTMETRICS ncm = {0};
  576. TCHAR szFontName[MAX_PATH];
  577. INT iFontSize = 12; // fixed large font size, which is 12
  578. DEBUG_FUNCTION_NAME(TEXT("LoadWizardFont()"));
  579. //
  580. // get the large fonts for wizard97
  581. //
  582. ncm.cbSize = sizeof(ncm);
  583. if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
  584. {
  585. DebugPrintEx(DEBUG_ERR, TEXT("SystemParametersInfo failed. ec = 0x%X"), GetLastError());
  586. goto Error;
  587. }
  588. else
  589. {
  590. CopyMemory((LPVOID* )&lfTitleFont, (LPVOID *)&ncm.lfMessageFont, sizeof(lfTitleFont));
  591. if (!LoadString(g_hResource, IDS_WIZ_LARGE_FONT_NAME, szFontName, MAX_PATH ))
  592. {
  593. DebugPrintEx(DEBUG_ERR,
  594. TEXT("LoadString failed: string ID=%d, error=%d"),
  595. IDS_WIZ_LARGE_FONT_NAME,
  596. GetLastError());
  597. goto Error;
  598. }
  599. lfTitleFont.lfWeight = FW_BOLD;
  600. hdc = GetDC(NULL);
  601. if (!hdc)
  602. {
  603. DebugPrintEx(DEBUG_ERR, TEXT("GetDC() failed (ec: ld)"), GetLastError());
  604. goto Error;
  605. }
  606. lfTitleFont.lfHeight = 0 - (GetDeviceCaps(hdc, LOGPIXELSY) * iFontSize / 72);
  607. g_wizData.hTitleFont = CreateFontIndirect(&lfTitleFont);
  608. if (!g_wizData.hTitleFont)
  609. {
  610. DebugPrintEx(DEBUG_ERR,
  611. TEXT("CreateFontIndirect(&lfTitleFont) failed (ec: %ld)"),
  612. GetLastError());
  613. goto Error;
  614. }
  615. ReleaseDC( NULL, hdc);
  616. hdc = NULL;
  617. }
  618. return TRUE;
  619. Error:
  620. //
  621. // Cleanup properly before exiting
  622. //
  623. if (hdc)
  624. {
  625. ReleaseDC( NULL, hdc);
  626. hdc = NULL;
  627. }
  628. return FALSE;
  629. } // LoadWizardFont
  630. BOOL
  631. SaveWizardData()
  632. /*++
  633. Routine Description:
  634. Save the wizard data to the system.
  635. If there are more than one device, all enabled devices will have the same settings.
  636. Arguments:
  637. pData - Points to the user memory structure
  638. Return Value:
  639. TRUE if successful, FALSE if there is an error
  640. --*/
  641. {
  642. HKEY hRegKey = 0;
  643. DEBUG_FUNCTION_NAME(TEXT("SaveConfigData()"));
  644. if(!g_hFaxSvcHandle)
  645. {
  646. Assert(FALSE);
  647. return FALSE;
  648. }
  649. //
  650. // save user info
  651. //
  652. if (g_bShowUserInfo)
  653. {
  654. if(!SaveUserInfo())
  655. {
  656. DebugPrintEx(DEBUG_ERR, TEXT("SaveUserInfo failed"));
  657. return FALSE;
  658. }
  659. }
  660. //
  661. // save device info
  662. //
  663. if (g_bShowDevicePages)
  664. {
  665. if(!SaveDeviceData())
  666. {
  667. DebugPrintEx(DEBUG_ERR, TEXT("SaveDeviceData failed"));
  668. return FALSE;
  669. }
  670. }
  671. if (g_bShowDevicePages ||
  672. FaxAccessCheckEx(g_hFaxSvcHandle, FAX_ACCESS_MANAGE_CONFIG, NULL))
  673. {
  674. //
  675. // If the user has manage access and does not have a fax device
  676. // it's mean she refused to install it.
  677. // So, we should not disturb her
  678. // with implicit invocation of the Configuration Wizard.
  679. //
  680. if(!FaxSetConfigWizardUsed(g_hFaxSvcHandle, TRUE))
  681. {
  682. DebugPrintEx(DEBUG_ERR, TEXT("FaxSetConfigWizardUsed failed with %d"), GetLastError());
  683. }
  684. }
  685. return TRUE;
  686. } // SaveWizardData
  687. VOID
  688. FreeWizardData()
  689. /*++
  690. Routine Description:
  691. Free the wizard data and release the memory.
  692. Arguments:
  693. pData - Pointer to the receive data structure
  694. Return Value:
  695. None.
  696. --*/
  697. {
  698. DEBUG_FUNCTION_NAME(TEXT("FreeWizardData()"));
  699. if(g_wizData.hTitleFont)
  700. {
  701. DeleteObject(g_wizData.hTitleFont);
  702. }
  703. FreeUserInfo();
  704. FreeDeviceData();
  705. return;
  706. } // FreeWizardData
  707. BOOL
  708. SetLastPage(
  709. INT pageId
  710. )
  711. /*++
  712. Routine Description:
  713. Add one page to the link list to keep track of "go back" information
  714. Arguments:
  715. pageId - Page id of the page to be added.
  716. Return Value:
  717. TRUE if successful, FALSE for failure.
  718. --*/
  719. {
  720. PPAGE_INFO pPageInfo;
  721. DEBUG_FUNCTION_NAME(TEXT("SetLastPage()"));
  722. pPageInfo = (PPAGE_INFO)MemAlloc(sizeof(PAGE_INFO));
  723. if(pPageInfo == NULL)
  724. {
  725. LPCTSTR faxDbgFunction = TEXT("SetLastPage()");
  726. DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed."));
  727. Assert(FALSE);
  728. return FALSE;
  729. }
  730. pPageInfo->pageId = pageId;
  731. //
  732. // add current page as the last page of the list
  733. //
  734. InsertTailList(&g_PageList, &pPageInfo->ListEntry);
  735. return TRUE;
  736. }
  737. BOOL
  738. ClearPageList(
  739. VOID
  740. )
  741. /*++
  742. Routine Description:
  743. Clear the page list and release the allocated memory
  744. Arguments:
  745. None.
  746. Return Value:
  747. True if success, false if fails.
  748. --*/
  749. {
  750. PLIST_ENTRY Last; // the last page information
  751. PPAGE_INFO pPageInfo = NULL;
  752. DEBUG_FUNCTION_NAME(TEXT("ClearPageList()"));
  753. while(!IsListEmpty(&g_PageList))
  754. {
  755. Last = g_PageList.Blink;
  756. pPageInfo = CONTAINING_RECORD( Last, PAGE_INFO, ListEntry );
  757. if(pPageInfo)
  758. {
  759. RemoveEntryList(&pPageInfo->ListEntry);
  760. MemFree(pPageInfo);
  761. }
  762. }
  763. return TRUE;
  764. }
  765. BOOL
  766. RemoveLastPage(
  767. HWND hwnd
  768. )
  769. /*++
  770. Routine Description:
  771. Removes last page from the link list to keep track of "go back" information
  772. Arguments:
  773. hwnd - window handle
  774. Return Value:
  775. TRUE if successful, FALSE for failure.
  776. --*/
  777. {
  778. PPAGE_INFO pPageInfo = NULL;
  779. DEBUG_FUNCTION_NAME(TEXT("RemoveLastPage()"));
  780. Assert(hwnd);
  781. if(!g_PageList.Blink)
  782. {
  783. return FALSE;
  784. }
  785. pPageInfo = CONTAINING_RECORD( g_PageList.Blink, PAGE_INFO, ListEntry );
  786. if(!pPageInfo)
  787. {
  788. return FALSE;
  789. }
  790. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, pPageInfo->pageId);
  791. RemoveEntryList(&pPageInfo->ListEntry);
  792. MemFree(pPageInfo);
  793. return TRUE;
  794. }
  795. BOOL
  796. LoadDeviceData()
  797. /*++
  798. Routine Description:
  799. Load the fax devices information.
  800. If there are more than one device, we load the data for the first available device.
  801. Arguments:
  802. Return Value:
  803. TRUE if successful, FALSE if there is an error
  804. --*/
  805. {
  806. DWORD dwPorts = 0;
  807. BOOL bRes = FALSE;
  808. DWORD dw;
  809. DWORD dwGroups; // group number
  810. DWORD dwGroupIndex;
  811. DWORD dwSndDevIndex=0; // index of the last send enabled device
  812. DWORD dwRcvDevIndex=0; // index of the last receive enabled device
  813. DWORD dwCurrentRM;
  814. LPBYTE pRoutingInfoBuffer;
  815. DWORD dwRoutingInfoBufferSize = 0;
  816. PFAX_PORT_INFO_EX pPortsInfo = NULL; // for FaxEnumPortsEx
  817. PFAX_OUTBOUND_ROUTING_GROUP pFaxRoutingGroup = NULL;
  818. DEBUG_FUNCTION_NAME(TEXT("LoadDeviceData()"));
  819. g_wizData.dwDeviceLimit = GetDeviceLimit();
  820. g_wizData.pdwSendDevOrder = NULL;
  821. g_wizData.szCsid = NULL;
  822. g_wizData.szTsid = NULL;
  823. g_wizData.dwDeviceCount = 0;
  824. g_wizData.pDevInfo = NULL;
  825. if(!FaxEnumPortsEx(g_hFaxSvcHandle, &pPortsInfo, &dwPorts))
  826. {
  827. DebugPrintEx(DEBUG_ERR, TEXT("FaxEnumPortsEx failed: error=%d."), GetLastError());
  828. goto exit;
  829. }
  830. if(!dwPorts)
  831. {
  832. Assert(dwPorts);
  833. DebugPrintEx(DEBUG_ERR, TEXT("No available ports."));
  834. goto exit;
  835. }
  836. g_wizData.dwDeviceCount = dwPorts;
  837. g_wizData.pDevInfo = (PDEVICEINFO)MemAlloc(dwPorts * sizeof(DEVICEINFO));
  838. if(!g_wizData.pDevInfo)
  839. {
  840. Assert(FALSE);
  841. DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc() failed."));
  842. goto exit;
  843. }
  844. ZeroMemory(g_wizData.pDevInfo, dwPorts * sizeof(DEVICEINFO));
  845. //
  846. // pick up the first available device, if no one is available
  847. // choose the first device
  848. //
  849. for(dw = 0; dw < dwPorts; ++dw)
  850. {
  851. //
  852. // copy other device info for each device
  853. //
  854. g_wizData.pDevInfo[dw].bSend = pPortsInfo[dw].bSend;
  855. g_wizData.pDevInfo[dw].ReceiveMode = pPortsInfo[dw].ReceiveMode;
  856. g_wizData.pDevInfo[dw].dwDeviceId = pPortsInfo[dw].dwDeviceID;
  857. g_wizData.pDevInfo[dw].szDeviceName = StringDup(pPortsInfo[dw].lpctstrDeviceName);
  858. if(!g_wizData.pDevInfo[dw].szDeviceName)
  859. {
  860. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed.") );
  861. goto exit;
  862. }
  863. if(pPortsInfo[dw].bSend)
  864. {
  865. dwSndDevIndex = dw;
  866. }
  867. if(FAX_DEVICE_RECEIVE_MODE_OFF != pPortsInfo[dw].ReceiveMode)
  868. {
  869. dwRcvDevIndex = dw;
  870. }
  871. g_wizData.pDevInfo[dw].bSelected = TRUE;
  872. }
  873. //
  874. // Copy TSID
  875. //
  876. g_wizData.szTsid = StringDup(pPortsInfo[dwSndDevIndex].lptstrTsid);
  877. if(!g_wizData.szTsid)
  878. {
  879. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed.") );
  880. goto exit;
  881. }
  882. //
  883. // Copy CSID and rings number
  884. //
  885. g_wizData.dwRingCount = pPortsInfo[dwRcvDevIndex].dwRings;
  886. g_wizData.szCsid = StringDup(pPortsInfo[dwRcvDevIndex].lptstrCsid);
  887. if(!g_wizData.szCsid)
  888. {
  889. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed.") );
  890. goto exit;
  891. }
  892. if (!IsDesktopSKU())
  893. {
  894. //
  895. // get device order
  896. //
  897. if(!FaxEnumOutboundGroups(g_hFaxSvcHandle, &pFaxRoutingGroup, &dwGroups))
  898. {
  899. DebugPrintEx(DEBUG_ERR, TEXT("FaxEnumOutboundGroups failed: error=%d."), GetLastError());
  900. Assert(FALSE);
  901. goto exit;
  902. }
  903. for(dwGroupIndex = 0; dwGroupIndex < dwGroups; dwGroupIndex++)
  904. {
  905. // search the <All Devices> group
  906. if(!lstrcmp(pFaxRoutingGroup[dwGroupIndex].lpctstrGroupName, ROUTING_GROUP_ALL_DEVICES))
  907. {
  908. // device number must be the same as port number
  909. Assert(dwPorts == pFaxRoutingGroup[dwGroupIndex].dwNumDevices);
  910. DebugPrintEx(DEBUG_MSG, TEXT("Total device number is %d."), pFaxRoutingGroup[dwGroupIndex].dwNumDevices);
  911. DebugPrintEx(DEBUG_MSG, TEXT("Group status is %d."), pFaxRoutingGroup[dwGroupIndex].Status);
  912. // collecting device Id
  913. g_wizData.pdwSendDevOrder = MemAlloc(pFaxRoutingGroup[dwGroupIndex].dwNumDevices * sizeof(DWORD));
  914. if(!g_wizData.pdwSendDevOrder)
  915. {
  916. DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed."));
  917. goto exit;
  918. }
  919. memcpy(g_wizData.pdwSendDevOrder,
  920. pFaxRoutingGroup[dwGroupIndex].lpdwDevices,
  921. pFaxRoutingGroup[dwGroupIndex].dwNumDevices * sizeof(DWORD));
  922. break;
  923. }
  924. }
  925. if(!g_wizData.pdwSendDevOrder)
  926. {
  927. DebugPrintEx(DEBUG_ERR, TEXT("No device order information."));
  928. goto exit;
  929. }
  930. }
  931. //
  932. // load routing methods
  933. // the size of each routing methods should not be larger than INFO_SIZE
  934. // fortunately, it is gurranteed by other fax programs
  935. //
  936. for (dwCurrentRM = 0; dwCurrentRM < RM_COUNT; ++dwCurrentRM)
  937. {
  938. LPTSTR lpCurSel;
  939. //
  940. // Check the validity first in the loop,
  941. // then save the routing info
  942. //
  943. lpCurSel = g_wizData.pRouteInfo[dwCurrentRM].tszCurSel;
  944. g_wizData.pRouteInfo[dwCurrentRM].bEnabled = FaxDeviceEnableRoutingMethod(
  945. g_hFaxSvcHandle,
  946. g_wizData.pDevInfo[dwRcvDevIndex].dwDeviceId,
  947. g_RoutingGuids[dwCurrentRM],
  948. QUERY_STATUS );
  949. if(FaxGetExtensionData( g_hFaxSvcHandle,
  950. g_wizData.pDevInfo[dwRcvDevIndex].dwDeviceId,
  951. g_RoutingGuids[dwCurrentRM],
  952. &pRoutingInfoBuffer,
  953. &dwRoutingInfoBufferSize))
  954. {
  955. // only copy the first MAX_PATH - 1 characters
  956. CopyMemory((LPBYTE)lpCurSel,
  957. pRoutingInfoBuffer,
  958. dwRoutingInfoBufferSize < MAX_PATH * sizeof(TCHAR) ?
  959. dwRoutingInfoBufferSize : (MAX_PATH - 1) * sizeof(TCHAR));
  960. FaxFreeBuffer(pRoutingInfoBuffer);
  961. }
  962. }
  963. bRes = TRUE;
  964. exit:
  965. //
  966. // Clean up
  967. //
  968. if(pPortsInfo)
  969. {
  970. FaxFreeBuffer(pPortsInfo);
  971. }
  972. if(pFaxRoutingGroup)
  973. {
  974. FaxFreeBuffer(pFaxRoutingGroup);
  975. }
  976. if(!bRes)
  977. {
  978. FreeDeviceData();
  979. }
  980. return bRes;
  981. } // LoadDeviceData
  982. BOOL
  983. SaveSingleDeviceData (
  984. PDEVICEINFO pDeviceInfo
  985. )
  986. {
  987. BOOL bRes = TRUE;
  988. DWORD dwCurrentRM;
  989. PFAX_PORT_INFO_EX pPortInfo = NULL; // stores device info
  990. DEBUG_FUNCTION_NAME(TEXT("SaveSingleDeviceData"));
  991. if(FaxGetPortEx(g_hFaxSvcHandle, pDeviceInfo->dwDeviceId, &pPortInfo))
  992. {
  993. //
  994. // Save the data to all devices and enable/disable FPF_RECEIVE depending on the data
  995. //
  996. pPortInfo->bSend = pDeviceInfo->bSend;
  997. pPortInfo->ReceiveMode = pDeviceInfo->ReceiveMode;
  998. pPortInfo->lptstrCsid = g_wizData.szCsid;
  999. pPortInfo->lptstrTsid = g_wizData.szTsid;
  1000. pPortInfo->dwRings = g_wizData.dwRingCount;
  1001. if(!FaxSetPortEx(g_hFaxSvcHandle, pDeviceInfo->dwDeviceId, pPortInfo))
  1002. {
  1003. DebugPrintEx(DEBUG_ERR, TEXT("FaxSetPortEx() failed with %d."), GetLastError());
  1004. bRes = FALSE;
  1005. }
  1006. FaxFreeBuffer(pPortInfo);
  1007. }
  1008. else
  1009. {
  1010. DebugPrintEx(DEBUG_ERR, TEXT("FaxGetPortEx() failed with %d."), GetLastError());
  1011. bRes = FALSE;
  1012. }
  1013. //
  1014. // Save routing methods
  1015. //
  1016. for (dwCurrentRM = 0; dwCurrentRM < RM_COUNT; dwCurrentRM++)
  1017. {
  1018. LPTSTR lpCurSel;
  1019. LPCWSTR lpcwstrPrinterPath;
  1020. BOOL bEnabled;
  1021. //
  1022. // Check the validity first in the loop,
  1023. // then save the routing info
  1024. //
  1025. lpCurSel = g_wizData.pRouteInfo[dwCurrentRM].tszCurSel;
  1026. bEnabled = g_wizData.pRouteInfo[dwCurrentRM].bEnabled;
  1027. if ((RM_PRINT == dwCurrentRM) && bEnabled)
  1028. {
  1029. //
  1030. // Attempt to convert printer display name to printer path before we pass it on to the server
  1031. //
  1032. lpcwstrPrinterPath = FindPrinterPathFromName (g_pPrinterNames, g_dwNumPrinters, lpCurSel);
  1033. if (lpcwstrPrinterPath)
  1034. {
  1035. //
  1036. // We have a matching path - replace name with path.
  1037. //
  1038. lstrcpyn (lpCurSel, lpcwstrPrinterPath, MAX_PATH);
  1039. }
  1040. }
  1041. if(!FaxSetExtensionData(g_hFaxSvcHandle,
  1042. pDeviceInfo->dwDeviceId,
  1043. g_RoutingGuids[dwCurrentRM],
  1044. (LPBYTE)lpCurSel,
  1045. MAX_PATH * sizeof(TCHAR)) )
  1046. {
  1047. DebugPrintEx(DEBUG_ERR, TEXT("FaxSetExtensionData() failed with %d."), GetLastError());
  1048. bRes = FALSE;
  1049. }
  1050. if(!FaxDeviceEnableRoutingMethod(g_hFaxSvcHandle,
  1051. pDeviceInfo->dwDeviceId,
  1052. g_RoutingGuids[dwCurrentRM],
  1053. bEnabled ? STATUS_ENABLE : STATUS_DISABLE ) )
  1054. {
  1055. DebugPrintEx(DEBUG_ERR, TEXT("FaxDeviceEnableRoutingMethod() failed with %d."), GetLastError());
  1056. bRes = FALSE;
  1057. }
  1058. }
  1059. return bRes;
  1060. } // SaveSingleDeviceData
  1061. BOOL
  1062. SaveDeviceData()
  1063. /*++
  1064. Routine Description:
  1065. Save the fax devices configuration.
  1066. If there are more than one device, all enabled devices will be set
  1067. to current settings, except whether they are enabled to send/receive faxes.
  1068. Arguments:
  1069. Return Value:
  1070. TRUE if successful, FALSE if there is an error
  1071. --*/
  1072. {
  1073. DWORD dw;
  1074. BOOL bRes = TRUE;
  1075. FAX_OUTBOUND_ROUTING_GROUP outRoutGr = {0};
  1076. DEBUG_FUNCTION_NAME(TEXT("SaveDeviceData"));
  1077. //
  1078. // 1st iteration - save disabled devices only
  1079. //
  1080. for(dw = 0; dw < g_wizData.dwDeviceCount; ++dw)
  1081. {
  1082. if (g_wizData.pDevInfo[dw].bSend || (FAX_DEVICE_RECEIVE_MODE_OFF != g_wizData.pDevInfo[dw].ReceiveMode))
  1083. {
  1084. //
  1085. // Device is active - skip it now
  1086. //
  1087. continue;
  1088. }
  1089. if (!SaveSingleDeviceData(&(g_wizData.pDevInfo[dw])))
  1090. {
  1091. bRes = FALSE;
  1092. }
  1093. }
  1094. //
  1095. // 2nd iteration - save enabled devices only
  1096. //
  1097. for(dw = 0; dw < g_wizData.dwDeviceCount; ++dw)
  1098. {
  1099. if (!g_wizData.pDevInfo[dw].bSend && (FAX_DEVICE_RECEIVE_MODE_OFF == g_wizData.pDevInfo[dw].ReceiveMode))
  1100. {
  1101. //
  1102. // Device is inactive - skip it
  1103. //
  1104. continue;
  1105. }
  1106. if (!SaveSingleDeviceData(&(g_wizData.pDevInfo[dw])))
  1107. {
  1108. bRes = FALSE;
  1109. }
  1110. }
  1111. if (!IsDesktopSKU ())
  1112. {
  1113. //
  1114. // Set device order for send
  1115. //
  1116. outRoutGr.dwSizeOfStruct = sizeof(outRoutGr);
  1117. outRoutGr.lpctstrGroupName = ROUTING_GROUP_ALL_DEVICES;
  1118. outRoutGr.dwNumDevices = g_wizData.dwDeviceCount;
  1119. outRoutGr.lpdwDevices = g_wizData.pdwSendDevOrder;
  1120. outRoutGr.Status = FAX_GROUP_STATUS_ALL_DEV_VALID;
  1121. if(!FaxSetOutboundGroup(g_hFaxSvcHandle, &outRoutGr))
  1122. {
  1123. DebugPrintEx(DEBUG_ERR, TEXT("FaxSetOutboundGroup() failed with %d."), GetLastError());
  1124. bRes = FALSE;
  1125. }
  1126. }
  1127. return bRes;
  1128. } // SaveDeviceData
  1129. void
  1130. FreeDeviceData()
  1131. /*++
  1132. Routine Description:
  1133. Free the devices data and release the memory.
  1134. Arguments:
  1135. Return Value:
  1136. none
  1137. --*/
  1138. {
  1139. DWORD dw;
  1140. DEBUG_FUNCTION_NAME(TEXT("FreeDeviceData()"));
  1141. MemFree(g_wizData.szCsid);
  1142. g_wizData.szCsid = NULL;
  1143. MemFree(g_wizData.szTsid);
  1144. g_wizData.szTsid = NULL;
  1145. MemFree(g_wizData.pdwSendDevOrder);
  1146. g_wizData.pdwSendDevOrder = NULL;
  1147. if (g_wizData.pDevInfo)
  1148. {
  1149. for(dw = 0; dw < g_wizData.dwDeviceCount; ++dw)
  1150. {
  1151. MemFree(g_wizData.pDevInfo[dw].szDeviceName);
  1152. g_wizData.pDevInfo[dw].szDeviceName = NULL;
  1153. }
  1154. MemFree(g_wizData.pDevInfo);
  1155. g_wizData.pDevInfo = NULL;
  1156. }
  1157. } // FreeDeviceData
  1158. ///////////////////////////////////////////////////////////////////////////////////////
  1159. // Function:
  1160. // ConvertCpeFilesToCov
  1161. //
  1162. // Purpose: Convert all of the *.CPE files from CSIDL_COMMON_APPDATA\Microsoft\Windows NT\MSFax\Common Coverpages
  1163. // directory to COV files at CSIDL_PERSONAL\Fax\Personal Coverpages.
  1164. // Mark that the conversion took place in the registry under HKCU so it will happen exactly once per user.
  1165. //
  1166. // Params:
  1167. // None
  1168. //
  1169. // Return Value:
  1170. // Win32 Error code
  1171. //
  1172. // Author:
  1173. //
  1174. ///////////////////////////////////////////////////////////////////////////////////////
  1175. DWORD ConvertCpeFilesToCov()
  1176. {
  1177. DWORD dwErr = ERROR_SUCCESS;
  1178. INT iErr = 0;
  1179. WIN32_FIND_DATA FindFileData;
  1180. HANDLE hFind = INVALID_HANDLE_VALUE;
  1181. TCHAR szServerCpDir[2*MAX_PATH] = {0};
  1182. TCHAR szSearch[MAX_PATH] = {0};
  1183. HKEY hRegKey = NULL;
  1184. DWORD dwConverted = 0;
  1185. DEBUG_FUNCTION_NAME(_T("ConvertCpeFilesToCov"));
  1186. //
  1187. // Check whether this is the first time the current user call to this function
  1188. //
  1189. hRegKey = OpenRegistryKey(
  1190. HKEY_CURRENT_USER,
  1191. REGKEY_FAX_SETUP,
  1192. TRUE,
  1193. KEY_ALL_ACCESS);
  1194. if(hRegKey)
  1195. {
  1196. dwConverted = GetRegistryDword(hRegKey, REGVAL_CPE_CONVERT);
  1197. if (0 == dwConverted)
  1198. {
  1199. SetRegistryDword(hRegKey, REGVAL_CPE_CONVERT, TRUE);
  1200. }
  1201. RegCloseKey(hRegKey);
  1202. }
  1203. if (dwConverted) // We don't have to convert the cpe files, we did already
  1204. return ERROR_SUCCESS;
  1205. //
  1206. // the CPE files are in the server cover page directory
  1207. //
  1208. if ( !GetServerCpDir(NULL,szServerCpDir,ARR_SIZE(szServerCpDir)) )
  1209. {
  1210. dwErr = GetLastError();
  1211. DebugPrintEx(DEBUG_ERR,_T("GetServerCpDir failed (ec=%d)"),dwErr);
  1212. return dwErr;
  1213. }
  1214. //
  1215. // first we're going to convert the CPEs to COV.
  1216. // this is done by running FXSCOVER.EXE /CONVERT <CPE filename>
  1217. //
  1218. _sntprintf(szSearch, ARR_SIZE(szSearch)-1, _T("%s\\*.cpe"), szServerCpDir);
  1219. hFind = FindFirstFile(szSearch, &FindFileData);
  1220. if (hFind==INVALID_HANDLE_VALUE)
  1221. {
  1222. DebugPrintEx(DEBUG_MSG,_T("No CPEs exist in %s, exit function"),szServerCpDir);
  1223. return NO_ERROR;
  1224. }
  1225. //
  1226. // Go for each Cover Page
  1227. //
  1228. do
  1229. {
  1230. //
  1231. // FindFileData.cFileName
  1232. //
  1233. TCHAR szCmdLineParams[MAX_PATH*2] = {0};
  1234. SHELLEXECUTEINFO sei = {0};
  1235. _sntprintf(szCmdLineParams,ARR_SIZE(szCmdLineParams),_T("/CONVERT \"%s\\%s\""),szServerCpDir,FindFileData.cFileName);
  1236. sei.cbSize = sizeof (SHELLEXECUTEINFO);
  1237. sei.fMask = SEE_MASK_NOCLOSEPROCESS;
  1238. sei.lpVerb = TEXT("open");
  1239. sei.lpFile = FAX_COVER_IMAGE_NAME;
  1240. sei.lpParameters = szCmdLineParams;
  1241. sei.lpDirectory = TEXT(".");
  1242. sei.nShow = SW_HIDE;
  1243. //
  1244. // Execute FXSCOVER.EXE and wait for it to end
  1245. //
  1246. if(!ShellExecuteEx(&sei))
  1247. {
  1248. dwErr = GetLastError();
  1249. DebugPrintEx(DEBUG_ERR, TEXT("ShellExecuteEx failed %d"), dwErr);
  1250. break; // don't try to continue with other files
  1251. }
  1252. dwErr = WaitForSingleObject(sei.hProcess, TIME_TO_WAIT_FOR_CONVERSTION);
  1253. CloseHandle(sei.hProcess);
  1254. if (WAIT_OBJECT_0 == dwErr)
  1255. {
  1256. //
  1257. // Shell execute completed successfully
  1258. //
  1259. dwErr = ERROR_SUCCESS;
  1260. continue;
  1261. }
  1262. else
  1263. {
  1264. DebugPrintEx(DEBUG_ERR, TEXT("WaitForSingleObject failed with %d"), dwErr);
  1265. DebugPrintEx(DEBUG_ERR, TEXT("WaitForSingleObject failed GetLastError=%d"), GetLastError());
  1266. break; // don't try to continue with other files
  1267. }
  1268. } while(FindNextFile(hFind, &FindFileData));
  1269. DebugPrintEx(DEBUG_MSG, _T("last call to FindNextFile() returns %ld."), GetLastError());
  1270. //
  1271. // Close Handle
  1272. //
  1273. FindClose(hFind);
  1274. return dwErr;
  1275. }