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.

2018 lines
66 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File Name: fxocPrnt.cpp
  4. //
  5. // Abstract: This provides the printer routines used in the FaxOCM
  6. // code base.
  7. //
  8. // Environment: Windows XP / User Mode
  9. //
  10. // Copyright (c) 2000 Microsoft Corporation
  11. //
  12. // Revision History:
  13. //
  14. // Date: Developer: Comments:
  15. // ----- ---------- ---------
  16. // 17-Feb-1996 Wesley Witt (wesw) Created routines originally from util.cpp
  17. // 21-Mar-2000 Oren Rosenbloom (orenr) Cleaned up, renamed, re-organized fns
  18. // 17-Jul-2000 Eran Yariv (erany) Added CoClassInstalled code
  19. // 08-Jan-2001 Mooly Beery (moolyb) Modified CoClassInstaller (wizard integration)
  20. //////////////////////////////////////////////////////////////////////////////
  21. #include "faxocm.h"
  22. #pragma hdrstop
  23. #include <shellapi.h>
  24. #include <winsprlp.h>
  25. #include <setuputil.h>
  26. // W2K Printer defines
  27. #define prv_W2K_FAX_PORT_NAME _T("MSFAX:") // Win2K Fax printer port name
  28. #define prv_W2K_FAX_DRIVER_NAME _T("Windows NT Fax Driver") // Win2K Fax printer driver name
  29. #define prv_W2K_FAX_MONITOR_NAME _T("Windows NT Fax Monitor") // Win2K Fax printer monitor name
  30. #define prv_W9X_PRINTER_DRIVER_FOLDER _T("\\clients\\faxclient\\drivers\\W9X")
  31. #define prv_NT4_PRINTER_DRIVER_FOLDER _T("\\clients\\faxclient\\drivers\\NT4")
  32. #define prv_PRINTER_DRIVER_FOLDER _T("\\clients\\faxclient\\drivers")
  33. #define prv_SYSTEM32_PATH _T("%windir%\\system32")
  34. #define prv_SERVER_SERVICE_NAME _T("LanmanServer")
  35. #define prv_SPOOLER_SERVICE_NAME _T("Spooler")
  36. //////////////////////// Static Function Prototypes /////////////////////////
  37. static DWORD prv_DeleteFaxPrinter(LPCTSTR lpctstrDriverName, LPCTSTR lpctstrPortName);
  38. static DWORD prv_CreatePrintMonitor(const TCHAR *pszMonitorName,
  39. const TCHAR *pszMonitorFile);
  40. static DWORD prv_DeletePrintMonitor(const TCHAR *pszMonitorName);
  41. static DWORD prv_DeleteFaxPrinterDriver(LPTSTR lptstrDriverName,
  42. LPTSTR pEnviroment,
  43. DWORD dwVersionFlag);
  44. static DWORD prv_AddFaxPrinterDriver(LPCTSTR lpctstrDriverSourcePath,LPCTSTR pEnvironment=NULL);
  45. DWORD IsFaxInstalled (LPBOOL lpbInstalled);
  46. static INT_PTR CALLBACK prv_dlgInstallFaxQuestion(HWND, UINT, WPARAM, LPARAM);
  47. ///////////////////////////////
  48. // prv_GVAR
  49. //
  50. //
  51. static struct prv_GVAR
  52. {
  53. TCHAR szFaxPrinterName[255 + 1];
  54. } prv_GVAR;
  55. static bool bIsPnpInstallation = true;
  56. ///////////////////////////////
  57. // fxocPrnt_Init
  58. //
  59. // Initialize the fax printer
  60. // subsystem.
  61. //
  62. // Params:
  63. // - void.
  64. // Returns:
  65. // - NO_ERROR on success.
  66. // - error code otherwise.
  67. //
  68. DWORD fxocPrnt_Init(void)
  69. {
  70. DWORD dwRes = NO_ERROR;
  71. DBG_ENTER(_T("Init Print Module"),dwRes);
  72. return dwRes;
  73. }
  74. ///////////////////////////////
  75. // fxocPrnt_Term
  76. //
  77. // Terminate the fax printer
  78. // subsystem.
  79. //
  80. // Params:
  81. // - void.
  82. // Returns:
  83. // - NO_ERROR on success.
  84. // - error code otherwise.
  85. //
  86. DWORD fxocPrnt_Term(void)
  87. {
  88. DWORD dwRes = NO_ERROR;
  89. DBG_ENTER(_T("Term Print Module"),dwRes);
  90. return dwRes;
  91. }
  92. ///////////////////////////////
  93. // fxocPrnt_Install
  94. //
  95. // Install fax printer monitor and driver(s)
  96. // Note: Doesn't install the actual printer!
  97. //
  98. // Params:
  99. // - pszSubcomponentId
  100. // - pszInstallSection
  101. // Returns:
  102. // - NO_ERROR on success.
  103. // - error code otherwise.
  104. //
  105. DWORD fxocPrnt_Install(const TCHAR *pszSubcomponentId,
  106. const TCHAR *pszInstallSection)
  107. {
  108. DWORD dwReturn = NO_ERROR;
  109. DBG_ENTER( _T("fxocPrnt_Install"),
  110. dwReturn,
  111. _T("%s - %s"),
  112. pszSubcomponentId,
  113. pszInstallSection);
  114. //
  115. // Before we do anything related to the printer, make sure that the 'LanManServer'
  116. // service is started.
  117. // The AddPrinter() code in the spooler service requires the LanManServer (SMB file sharing service)
  118. // service to be running.
  119. // For some reason LanManServer is not running yet when doing a system install (GUI mode) of
  120. // Windows XP Professional (in Server it does).
  121. //
  122. // it's possible that LanmanServer is not installed on Desktop SKUs
  123. if (!IsDesktopSKU())
  124. {
  125. dwReturn = fxocSvc_StartService(prv_SERVER_SERVICE_NAME);
  126. if (dwReturn == NO_ERROR)
  127. {
  128. VERBOSE(DBG_MSG,
  129. _T("Successfully started '%s' service, continuing Printer Install"),
  130. prv_SERVER_SERVICE_NAME);
  131. }
  132. else
  133. {
  134. VERBOSE(SETUP_ERR,
  135. _T("Failed to start '%s' service, rc = 0x%lx, abandoning ")
  136. _T("fax printer installation"),
  137. prv_SERVER_SERVICE_NAME,
  138. dwReturn);
  139. return dwReturn;
  140. }
  141. }
  142. // verify that the spooler is up
  143. dwReturn = fxocSvc_StartService(prv_SPOOLER_SERVICE_NAME);
  144. if (dwReturn == NO_ERROR)
  145. {
  146. VERBOSE(DBG_MSG,
  147. _T("Successfully started '%s' service, continuing Printer Install"),
  148. prv_SPOOLER_SERVICE_NAME);
  149. }
  150. else
  151. {
  152. VERBOSE(SETUP_ERR,
  153. _T("Failed to start '%s' service, rc = 0x%lx, abandoning ")
  154. _T("fax printer installation"),
  155. prv_SPOOLER_SERVICE_NAME,
  156. dwReturn);
  157. return dwReturn;
  158. }
  159. //
  160. // always attemp to remove W2K fax printer
  161. dwReturn = prv_DeleteFaxPrinter(prv_W2K_FAX_DRIVER_NAME, prv_W2K_FAX_PORT_NAME);
  162. if (dwReturn != NO_ERROR)
  163. {
  164. VERBOSE(DBG_MSG,
  165. _T("Failed to delete W2K fax printer, rc = 0x%lx"),
  166. dwReturn);
  167. dwReturn = NO_ERROR;
  168. }
  169. //
  170. // delete the W2K printer driver files
  171. //
  172. dwReturn = prv_DeleteFaxPrinterDriver(prv_W2K_FAX_DRIVER_NAME, NULL, 3);
  173. if (dwReturn != NO_ERROR)
  174. {
  175. VERBOSE(DBG_MSG,
  176. _T("Failed to delete W2K fax drivers, rc = 0x%lx"),
  177. dwReturn);
  178. dwReturn = NO_ERROR;
  179. }
  180. //
  181. // delete the W2K fax print monitor.
  182. //
  183. dwReturn = prv_DeletePrintMonitor(prv_W2K_FAX_MONITOR_NAME);
  184. if (dwReturn != NO_ERROR)
  185. {
  186. VERBOSE(DBG_MSG,
  187. _T("Failed to delete W2K fax monitor, rc = 0x%lx"),
  188. dwReturn);
  189. dwReturn = NO_ERROR;
  190. }
  191. //
  192. // okay lets go and create a fax printer monitor.
  193. //
  194. if (dwReturn == NO_ERROR)
  195. {
  196. // create the print monitor
  197. dwReturn = prv_CreatePrintMonitor(FAX_MONITOR_NAME,
  198. FAX_MONITOR_FILE);
  199. if (dwReturn != NO_ERROR)
  200. {
  201. VERBOSE(SETUP_ERR,
  202. _T("Fax Printer Install, ")
  203. _T("failed to create fax printer monitor, rc=0x%lx"),
  204. dwReturn);
  205. }
  206. }
  207. //
  208. // Copy the fax printer driver files
  209. //
  210. if (dwReturn == NO_ERROR)
  211. {
  212. dwReturn = prv_AddFaxPrinterDriver(prv_SYSTEM32_PATH prv_PRINTER_DRIVER_FOLDER);
  213. if (dwReturn != NO_ERROR)
  214. {
  215. VERBOSE(SETUP_ERR,
  216. _T("Failed to copy Fax Printer Drivers from '%s', ")
  217. _T("attempting to install fax printer anyway..., rc=0x%lx"),
  218. prv_SYSTEM32_PATH,
  219. dwReturn);
  220. dwReturn = NO_ERROR;
  221. }
  222. }
  223. if (IsFaxShared())
  224. {
  225. //
  226. // For SKUs which support fax sharing, let's add the printer drivers for W9X and NT4 too.
  227. //
  228. dwReturn = prv_AddFaxPrinterDriver(prv_SYSTEM32_PATH prv_W9X_PRINTER_DRIVER_FOLDER,W9X_PRINT_ENV);
  229. if (dwReturn != NO_ERROR)
  230. {
  231. VERBOSE(SETUP_ERR,
  232. _T("Failed to copy Fax Printer Drivers for W9X, rc=0x%lx"),
  233. dwReturn);
  234. dwReturn = NO_ERROR;
  235. }
  236. dwReturn = prv_AddFaxPrinterDriver(prv_SYSTEM32_PATH prv_NT4_PRINTER_DRIVER_FOLDER,NT4_PRINT_ENV);
  237. if (dwReturn != NO_ERROR)
  238. {
  239. VERBOSE(SETUP_ERR,
  240. _T("Failed to copy Fax Printer Drivers for NT4, rc=0x%lx"),
  241. dwReturn);
  242. dwReturn = NO_ERROR;
  243. }
  244. }
  245. return dwReturn;
  246. }
  247. ///////////////////////////////
  248. // fxocPrnt_InstallPrinter
  249. //
  250. // Checks whether there are any Fax-capable TAPI devices
  251. // If there are, installs the Fax printer.
  252. //
  253. // Params:
  254. // Returns:
  255. // - NO_ERROR on success.
  256. // - error code otherwise.
  257. //
  258. DWORD fxocPrnt_InstallPrinter()
  259. {
  260. DWORD dwReturn = NO_ERROR;
  261. DWORD dwFaxDevicesCount = 0;
  262. DBG_ENTER( _T("fxocPrnt_InstallPrinter"), dwReturn);
  263. //
  264. // Count the number of Fax-capable modems the system has
  265. //
  266. dwReturn = GetFaxCapableTapiLinesCount(&dwFaxDevicesCount, FAX_MODEM_PROVIDER_NAME);
  267. if (ERROR_SUCCESS != dwReturn)
  268. {
  269. CALL_FAIL (GENERAL_ERR, TEXT("GetFaxCapableTapiLinesCount"), dwReturn);
  270. //
  271. // Assume no fax-capable devices exist
  272. //
  273. dwFaxDevicesCount = 0;
  274. dwReturn = NO_ERROR;
  275. }
  276. //
  277. // We do not create the printer by default unless;
  278. // 1. There are now fax-capable modems in the system or
  279. // 2. a fax printer was already there.
  280. //
  281. // Otherwise, only the monitor and drivers are installed.
  282. // The printer itself will be added either when an FSP / EFSP is registered or
  283. // when a modem is installed.
  284. //
  285. if (dwFaxDevicesCount && (dwReturn == NO_ERROR))
  286. {
  287. TCHAR szFaxPrinterName[255 + 1] = {0};
  288. dwReturn = fxocPrnt_GetFaxPrinterName(szFaxPrinterName,
  289. sizeof(szFaxPrinterName) / sizeof(TCHAR));
  290. if (ERROR_SUCCESS != dwReturn)
  291. {
  292. CALL_FAIL (GENERAL_ERR, TEXT("fxocPrnt_GetFaxPrinterName"), dwReturn);
  293. return dwReturn;
  294. }
  295. //
  296. // Create the fax printer.
  297. //
  298. dwReturn = AddLocalFaxPrinter (szFaxPrinterName, NULL);
  299. if (dwReturn == NO_ERROR)
  300. {
  301. VERBOSE(DBG_MSG,
  302. _T("Fax Printer Install, created fax printer ")
  303. _T("Name = '%s', Driver Name = '%s'"),
  304. szFaxPrinterName,
  305. FAX_DRIVER_NAME);
  306. }
  307. else
  308. {
  309. VERBOSE(SETUP_ERR,
  310. _T("fxocPrnt_Install, ")
  311. _T("failed to create fax printer, rc = 0x%lx"),
  312. dwReturn);
  313. }
  314. }
  315. return dwReturn;
  316. }
  317. ///////////////////////////////
  318. // fxocPrnt_Uninstall
  319. //
  320. // Remove all fax printers on this
  321. // machine.
  322. //
  323. // Params:
  324. // - pszSubcomponentId
  325. // - pszUninstallSection.
  326. // Returns:
  327. // - NO_ERROR on success.
  328. // - error code otherwise.
  329. //
  330. //
  331. DWORD fxocPrnt_Uninstall(const TCHAR *pszSubcomponentId,
  332. const TCHAR *pszUninstallSection)
  333. {
  334. DWORD dwReturn = NO_ERROR;
  335. // before we do anything related to the printer, make sure that the 'Server'
  336. // service is started.
  337. DBG_ENTER( _T("fxocPrnt_Uninstall"),
  338. dwReturn,
  339. _T("%s - %s"),
  340. pszSubcomponentId,
  341. pszUninstallSection);
  342. // it's possible that LanmanServer is not installed on Desktop SKUs
  343. if (!IsDesktopSKU())
  344. {
  345. dwReturn = fxocSvc_StartService(prv_SERVER_SERVICE_NAME);
  346. if (dwReturn == NO_ERROR)
  347. {
  348. VERBOSE(DBG_MSG,
  349. _T("Successfully started '%s' service, continuing Printer uninstall"),
  350. prv_SERVER_SERVICE_NAME);
  351. }
  352. else
  353. {
  354. VERBOSE(SETUP_ERR,
  355. _T("Failed to start '%s' service, rc = 0x%lx, abandoning ")
  356. _T("fax printer uninstall"),
  357. prv_SERVER_SERVICE_NAME,
  358. dwReturn);
  359. return dwReturn;
  360. }
  361. }
  362. // verify that the spooler is up
  363. dwReturn = fxocSvc_StartService(prv_SPOOLER_SERVICE_NAME);
  364. if (dwReturn == NO_ERROR)
  365. {
  366. VERBOSE(DBG_MSG,
  367. _T("Successfully started '%s' service, continuing Printer Install"),
  368. prv_SPOOLER_SERVICE_NAME);
  369. }
  370. else
  371. {
  372. VERBOSE(SETUP_ERR,
  373. _T("Failed to start '%s' service, rc = 0x%lx, abandoning ")
  374. _T("fax printer installation"),
  375. prv_SPOOLER_SERVICE_NAME,
  376. dwReturn);
  377. return dwReturn;
  378. }
  379. // remove the fax printer
  380. prv_DeleteFaxPrinter(FAX_DRIVER_NAME, FAX_MONITOR_PORT_NAME);
  381. // remove fax printer monitor
  382. prv_DeletePrintMonitor(FAX_MONITOR_NAME);
  383. // remove all fax printer drivers
  384. prv_DeleteFaxPrinterDriver(FAX_DRIVER_NAME, NULL, 3);
  385. //
  386. // For SKUs which support fax sharing, remove down-level drivers as well.
  387. //
  388. if (IsFaxShared())
  389. {
  390. prv_DeleteFaxPrinterDriver(FAX_DRIVER_NAME, NT4_PRINT_ENV, 2);
  391. prv_DeleteFaxPrinterDriver(FAX_DRIVER_NAME, W9X_PRINT_ENV, 0);
  392. }
  393. return dwReturn;
  394. }
  395. ///////////////////////////////
  396. // fxocPrnt_SetFaxPrinterName
  397. //
  398. // Sets the name of the fax printer.
  399. // This must be called prior to the
  400. // creation of the fax printer via
  401. // fxocPrnt_Install.
  402. //
  403. // Params:
  404. // - pszFaxPrinterName - new name for fax printer.
  405. // Returns:
  406. // - void.
  407. //
  408. void fxocPrnt_SetFaxPrinterName(const TCHAR* pszFaxPrinterName)
  409. {
  410. DBG_ENTER( _T("fxocPrnt_SetFaxPrinterName"),
  411. _T("%s"),
  412. pszFaxPrinterName);
  413. if (pszFaxPrinterName)
  414. {
  415. _tcsncpy(prv_GVAR.szFaxPrinterName,
  416. pszFaxPrinterName,
  417. sizeof(prv_GVAR.szFaxPrinterName) / sizeof(TCHAR));
  418. }
  419. else
  420. {
  421. memset(prv_GVAR.szFaxPrinterName,
  422. 0,
  423. sizeof(prv_GVAR.szFaxPrinterName));
  424. }
  425. return;
  426. }
  427. void fxocPrnt_SetFaxPrinterShared(BOOL IsFaxPrinterShared)
  428. {
  429. DBG_ENTER( _T("fxocPrnt_SetFaxPrinterShared"),
  430. _T("%d"),
  431. IsFaxPrinterShared);
  432. HKEY hFaxKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP,TRUE,KEY_WRITE);
  433. if (hFaxKey)
  434. {
  435. if (SetRegistryDword(hFaxKey,REGVAL_IS_SHARED_FAX_PRINTER,(IsFaxPrinterShared ? 1 : 0)))
  436. {
  437. VERBOSE(DBG_MSG, TEXT("Fax is installed in a mode that enables sharing"));
  438. }
  439. else
  440. {
  441. VERBOSE(DBG_MSG, TEXT("SetRegistryDword failed (ec=%d)"),GetLastError());
  442. }
  443. RegCloseKey(hFaxKey);
  444. }
  445. else
  446. {
  447. VERBOSE(SETUP_ERR, TEXT("Failed to create REGKEY_FAX_SETUP, printer won't be shared (ec=%d)"),GetLastError());
  448. }
  449. }
  450. ///////////////////////////////
  451. // fxocPrnt_GetFaxPrinterName
  452. //
  453. // Returns the current name of the
  454. // fax printer.
  455. //
  456. // Params:
  457. // - pszFaxPrinterName - OUT
  458. // - dwNumBufChars
  459. // Returns:
  460. // - NO_ERROR on success
  461. // - error code otherwise.
  462. //
  463. DWORD fxocPrnt_GetFaxPrinterName(TCHAR* pszFaxPrinterName,
  464. DWORD dwNumBufChars)
  465. {
  466. DWORD dwReturn = NO_ERROR;
  467. DBG_ENTER( _T("fxocPrnt_GetFaxPrinterName"), dwReturn);
  468. if ((pszFaxPrinterName == NULL) ||
  469. (dwNumBufChars == 0))
  470. {
  471. dwReturn = ERROR_INVALID_PARAMETER;
  472. return dwReturn;
  473. }
  474. if (prv_GVAR.szFaxPrinterName[0] != 0)
  475. {
  476. _tcsncpy(pszFaxPrinterName,
  477. prv_GVAR.szFaxPrinterName,
  478. dwNumBufChars);
  479. }
  480. else
  481. {
  482. //
  483. // nobody set the fax printer name, so return the default
  484. // table.
  485. _tcsncpy(pszFaxPrinterName,
  486. FAX_PRINTER_NAME,
  487. dwNumBufChars);
  488. }
  489. return dwReturn;
  490. } // fxocPrnt_GetFaxPrinterName
  491. LPCTSTR lpctstrDriverFilesW2KandXP[] =
  492. {
  493. FAX_UI_MODULE_NAME, // FXSUI.DLL
  494. FAX_DRV_MODULE_NAME, // FXSDRV.DLL
  495. FAX_WZRD_MODULE_NAME, // FXSWZRD.DLL
  496. FAX_TIFF_MODULE_NAME, // FXSTIFF.DLL
  497. FAX_API_MODULE_NAME, // FXSAPI.DLL
  498. FAX_RES_FILE
  499. };
  500. LPCTSTR lpctstrDriverFilesNT4[] =
  501. {
  502. FAX_NT4_DRV_MODULE_NAME, // FXSDRV4.DLL
  503. FAX_UI_MODULE_NAME, // FXSUI.DLL
  504. FAX_WZRD_MODULE_NAME, // FXSWZRD.DLL
  505. FAX_API_MODULE_NAME, // FXSAPI.DLL
  506. FAX_TIFF_FILE, // FXSTIFF.DLL
  507. FAX_RES_FILE
  508. };
  509. LPCTSTR lpctstrDriverFilesW9X[] =
  510. {
  511. FAX_DRV_WIN9X_32_MODULE_NAME, // FXSDRV32.DLL
  512. FAX_DRV_WIN9X_16_MODULE_NAME, // FXSDRV16.DRV
  513. FAX_API_MODULE_NAME, // FXSAPI.DLL
  514. FAX_DRV_UNIDRV_MODULE_NAME, // UNIDRV.DLL
  515. FAX_DRV_UNIDRV_HELP, // UNIDRV.HLP
  516. FAX_DRV_ICONLIB, // ICONLIB.DLL
  517. FAX_WZRD_MODULE_NAME, // FXSWZRD.DLL
  518. FAX_TIFF_FILE, // FXSTIFF.DLL
  519. FAX_RES_FILE
  520. };
  521. ///////////////////////////////////
  522. // prv_AddFaxPrinterDriver
  523. //
  524. // Add printer driver to the server machine.
  525. // In case of failure, do clean-up and returns FALSE.
  526. // Temp files are deleted allways.
  527. //
  528. // Params:
  529. // - lpctstrDriverSourcePath : The directory where the printer's driver files
  530. // are located (put there by the setup)
  531. // - pEnvironment : for which platform are the drivers added
  532. //
  533. static DWORD prv_AddFaxPrinterDriver(LPCTSTR lpctstrDriverSourcePath,LPCTSTR pEnvironment)
  534. {
  535. DWORD dwReturn = NO_ERROR;
  536. BOOL bSuccess = FALSE;
  537. LPCTSTR* filesToCopy = NULL;
  538. DWORD dwFileCount = 0;
  539. DWORD dwNeededSize = 0;
  540. TCHAR szPrinterDriverDirectory[MAX_PATH] = {0};
  541. TCHAR szSourceDir[MAX_PATH] = {0};
  542. DWORD dwNumChars = 0;
  543. DBG_ENTER( _T("prv_AddFaxPrinterDriver"),
  544. dwReturn,
  545. _T("%s - %s"),
  546. lpctstrDriverSourcePath,
  547. pEnvironment);
  548. if (!GetPrinterDriverDirectory(NULL,
  549. (LPTSTR)pEnvironment,
  550. 1,
  551. (LPBYTE)szPrinterDriverDirectory,
  552. sizeof(szPrinterDriverDirectory),
  553. &dwNeededSize))
  554. {
  555. dwReturn = GetLastError();
  556. VERBOSE(SETUP_ERR,
  557. TEXT("GetPrinterDriverDirectory failed - %d."),
  558. dwReturn);
  559. return dwReturn;
  560. }
  561. bSuccess = TRUE;
  562. VERBOSE(DBG_MSG,
  563. _T("Printer driver directory is %s\n"),
  564. szPrinterDriverDirectory);
  565. if (pEnvironment==NULL)
  566. {
  567. filesToCopy = lpctstrDriverFilesW2KandXP;
  568. dwFileCount = sizeof(lpctstrDriverFilesW2KandXP)/sizeof(LPCTSTR);
  569. }
  570. else if (_tcsicmp(pEnvironment,NT4_PRINT_ENV)==0)
  571. {
  572. filesToCopy = lpctstrDriverFilesNT4;
  573. dwFileCount = sizeof(lpctstrDriverFilesNT4)/sizeof(LPCTSTR);
  574. }
  575. else if (_tcsicmp(pEnvironment,W9X_PRINT_ENV)==0)
  576. {
  577. filesToCopy = lpctstrDriverFilesW9X;
  578. dwFileCount = sizeof(lpctstrDriverFilesW9X)/sizeof(LPCTSTR);
  579. }
  580. if (bSuccess)
  581. {
  582. dwNumChars = ExpandEnvironmentStrings(lpctstrDriverSourcePath,
  583. szSourceDir,
  584. sizeof(szSourceDir) / sizeof(TCHAR));
  585. if (dwNumChars == 0)
  586. {
  587. VERBOSE(SETUP_ERR,
  588. _T("ExpandEnvironmentStrings failed, rc = 0x%lx"),
  589. ::GetLastError());
  590. bSuccess = FALSE;
  591. }
  592. }
  593. if (bSuccess)
  594. {
  595. bSuccess = MultiFileCopy(dwFileCount,
  596. filesToCopy,
  597. szSourceDir,
  598. szPrinterDriverDirectory);
  599. if (!bSuccess)
  600. {
  601. VERBOSE(SETUP_ERR,
  602. _T("MultiFileCopy failed (ec: %ld)"),
  603. GetLastError());
  604. }
  605. }
  606. if (bSuccess)
  607. {
  608. DRIVER_INFO_3 DriverInfo3;
  609. ZeroMemory(&DriverInfo3,sizeof(DRIVER_INFO_3));
  610. // fill DRIVER_INFO_3 depending on pEnv...
  611. bSuccess = FillDriverInfo(&DriverInfo3,pEnvironment);
  612. if (bSuccess)
  613. {
  614. bSuccess = AddPrinterDriverEx(NULL,
  615. 3,
  616. (LPBYTE)&DriverInfo3,
  617. APD_COPY_NEW_FILES|APD_DONT_SET_CHECKPOINT);
  618. if (bSuccess)
  619. {
  620. VERBOSE(DBG_MSG,_T("Successfully added new fax printer drivers"));
  621. }
  622. else
  623. {
  624. VERBOSE(SETUP_ERR,_T("AddPrinterDriverEx failed (ec: %ld)"),GetLastError());
  625. }
  626. }
  627. else
  628. {
  629. VERBOSE(SETUP_ERR,_T("FillDriverInfo failed, try to continue"));
  630. }
  631. }
  632. //
  633. // Delete the temporary fax DLL files.
  634. //
  635. if (!MultiFileDelete(dwFileCount,
  636. filesToCopy,
  637. szPrinterDriverDirectory))
  638. {
  639. VERBOSE(SETUP_ERR,
  640. _T("MultiFileDelete() failed (ec: %ld)"),
  641. GetLastError());
  642. }
  643. if (!bSuccess)
  644. {
  645. dwReturn = ::GetLastError();
  646. }
  647. return dwReturn;
  648. }
  649. ///////////////////////////////
  650. // prv_DeletePrinter
  651. //
  652. // Delete printer by name. The driver name and the port name are just for debug print.
  653. //
  654. // Params:
  655. // - pszPrinterName - name of printer to delete
  656. // - pszFaxDriver - name of associated driver
  657. // - pszPortName - name of associated port.
  658. //
  659. static DWORD prv_DeletePrinter(const TCHAR *pszPrinterName,
  660. const TCHAR *pszFaxDriver,
  661. const TCHAR *pszPortName)
  662. {
  663. DWORD dwReturn = NO_ERROR;
  664. BOOL bSuccess = FALSE;
  665. HANDLE hPrinter = NULL;
  666. PRINTER_DEFAULTS PrinterDefaults =
  667. {
  668. NULL,
  669. NULL,
  670. PRINTER_ALL_ACCESS
  671. };
  672. DBG_ENTER( _T("prv_DeletePrinter"),
  673. dwReturn,
  674. _T("%s - %s - %s"),
  675. pszPrinterName,
  676. pszFaxDriver,
  677. pszPortName);
  678. if ((pszPrinterName == NULL) ||
  679. (pszFaxDriver == NULL) ||
  680. (pszPortName == NULL))
  681. {
  682. dwReturn = ERROR_INVALID_PARAMETER;
  683. return dwReturn;
  684. }
  685. bSuccess = ::OpenPrinter((TCHAR*) pszPrinterName,
  686. &hPrinter,
  687. &PrinterDefaults);
  688. if (bSuccess)
  689. {
  690. VERBOSE(DBG_MSG,
  691. _T("prv_DeletePrinter, deleting ")
  692. _T("printer '%s' with Driver Name = '%s', ")
  693. _T("Port Name = '%s'"),
  694. pszPrinterName,
  695. pszFaxDriver,
  696. pszPortName);
  697. if (!SetPrinter(hPrinter,0,NULL,PRINTER_CONTROL_PURGE))
  698. {
  699. // Don't let a failure here keep us from attempting the delete
  700. VERBOSE(PRINT_ERR,TEXT("SetPrinter failed (purge jobs before uninstall) ec=%d"),GetLastError());
  701. }
  702. bSuccess = ::DeletePrinter(hPrinter);
  703. if (!bSuccess)
  704. {
  705. dwReturn = ::GetLastError();
  706. VERBOSE(SETUP_ERR,
  707. _T("prv_DeletePrinter, failed to delete ")
  708. _T("fax printer '%s', rc = 0x%lx"),
  709. pszPrinterName,
  710. dwReturn);
  711. }
  712. bSuccess = ::ClosePrinter(hPrinter);
  713. if (!bSuccess)
  714. {
  715. dwReturn = ::GetLastError();
  716. VERBOSE(SETUP_ERR,
  717. _T("prv_DeletePrinter, failed to Close ")
  718. _T("fax printer '%s', rc = 0x%lx"),
  719. pszPrinterName,
  720. dwReturn);
  721. }
  722. hPrinter = NULL;
  723. }
  724. return dwReturn;
  725. }
  726. ///////////////////////////////
  727. // prv_DeleteFaxPrinter
  728. //
  729. // Delete fax printer with driver name and port as passed in params
  730. //
  731. // Params:
  732. // LPCTSTR lpctstrDriverName - printer driver name to delete
  733. // LPCTSTR lpctstrPortName - printer port name
  734. //
  735. //
  736. //
  737. static DWORD prv_DeleteFaxPrinter(LPCTSTR lpctstrDriverName, LPCTSTR lpctstrPortName)
  738. {
  739. BOOL bSuccess = FALSE;
  740. DWORD dwReturn = NO_ERROR;
  741. DWORD dwCount = 0;
  742. DWORD i = 0;
  743. PPRINTER_INFO_2 pPrinterInfo = NULL;
  744. DBG_ENTER(_T("prv_DeleteFaxPrinter"),dwReturn);
  745. pPrinterInfo = (PPRINTER_INFO_2) MyEnumPrinters(NULL,
  746. 2,
  747. &dwCount,
  748. PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS);
  749. VERBOSE(DBG_MSG,
  750. _T("DeleteFaxPrinter, found %lu printers installed ")
  751. _T("on this computer"),
  752. dwCount);
  753. if (pPrinterInfo)
  754. {
  755. for (i=0; i < dwCount; i++)
  756. {
  757. // Check if printer has same driver same port name
  758. if (_tcsicmp(pPrinterInfo[i].pDriverName, lpctstrDriverName) == 0 &&
  759. _tcsicmp(pPrinterInfo[i].pPortName, lpctstrPortName) == 0)
  760. {
  761. // We can have a Local printer here or a Printer connection.
  762. // we differentiate between the two by the ServerName field of
  763. // PRINTER_INFO_2
  764. if (pPrinterInfo[i].pServerName==NULL)
  765. {
  766. // this is a local printer.
  767. dwReturn = prv_DeletePrinter(pPrinterInfo[i].pPrinterName,
  768. lpctstrDriverName,
  769. lpctstrPortName);
  770. if (dwReturn != NO_ERROR)
  771. {
  772. VERBOSE(SETUP_ERR,
  773. _T("Failed to delete printer '%s', rc = 0x%lx, ")
  774. _T("continuing anyway..."),
  775. pPrinterInfo[i].pPrinterName,
  776. dwReturn);
  777. dwReturn = NO_ERROR;
  778. }
  779. }
  780. else
  781. {
  782. // this is a printer connection
  783. if (!DeletePrinterConnection(pPrinterInfo[i].pPrinterName))
  784. {
  785. dwReturn = GetLastError();
  786. VERBOSE(SETUP_ERR,
  787. _T("Failed to delete printer connection '%s', rc = 0x%lx, ")
  788. _T("continuing anyway..."),
  789. pPrinterInfo[i].pPrinterName,
  790. dwReturn);
  791. dwReturn = NO_ERROR;
  792. }
  793. }
  794. }
  795. }
  796. MemFree(pPrinterInfo);
  797. }
  798. return dwReturn;
  799. }
  800. ///////////////////////////////
  801. // prv_CreatePrintMonitor
  802. //
  803. // Create the printer monitor
  804. //
  805. // Params:
  806. // - pszMonitorName - name of printer monitor
  807. // - pszMonitorFile - name of print monitor file
  808. // Returns:
  809. // - NO_ERROR on success
  810. // - error code otherwise.
  811. //
  812. static DWORD prv_CreatePrintMonitor(const TCHAR *pszMonitorName,
  813. const TCHAR *pszMonitorFile)
  814. {
  815. BOOL bSuccess = TRUE;
  816. DWORD dwReturn = NO_ERROR;
  817. MONITOR_INFO_2 MonitorInfo;
  818. DBG_ENTER( _T("prv_CreatePrintMonitor"),
  819. dwReturn,
  820. _T("%s - %s"),
  821. pszMonitorName,
  822. pszMonitorFile);
  823. if ((pszMonitorName == NULL) ||
  824. (pszMonitorFile == NULL))
  825. {
  826. dwReturn = ERROR_INVALID_PARAMETER;
  827. return dwReturn;
  828. }
  829. MonitorInfo.pName = (TCHAR*) pszMonitorName;
  830. MonitorInfo.pDLLName = (TCHAR*) pszMonitorFile;
  831. MonitorInfo.pEnvironment = NULL;
  832. bSuccess = ::AddMonitor(NULL, 2, (LPBYTE) &MonitorInfo);
  833. if (bSuccess)
  834. {
  835. VERBOSE(DBG_MSG,
  836. _T("Successfully created fax monitor '%s', ")
  837. _T("File Name '%s'"),
  838. pszMonitorName,
  839. pszMonitorFile);
  840. }
  841. else
  842. {
  843. dwReturn = ::GetLastError();
  844. if (dwReturn == ERROR_PRINT_MONITOR_ALREADY_INSTALLED)
  845. {
  846. VERBOSE(DBG_MSG,
  847. _T("AddMonitor, failed because '%s' monitor already ")
  848. _T("exists. This is fine, let's continue..."),
  849. pszMonitorName);
  850. dwReturn = NO_ERROR;
  851. }
  852. else
  853. {
  854. VERBOSE(SETUP_ERR,
  855. _T("CreatePrinterMonitor, failed to ")
  856. _T("add new print monitor '%s', rc = 0x%lx"),
  857. pszMonitorName,
  858. dwReturn);
  859. }
  860. }
  861. return dwReturn;
  862. }
  863. ///////////////////////////////
  864. // prv_DeletePrintMonitor
  865. //
  866. // Delete the printer monitor
  867. //
  868. // Params:
  869. // - pszMonitorName - name of print monitor to delete
  870. // Returns:
  871. // - NO_ERROR on success
  872. // - error code otherwise.
  873. //
  874. static DWORD prv_DeletePrintMonitor(const TCHAR *pszMonitorName)
  875. {
  876. BOOL bSuccess = TRUE;
  877. DWORD dwReturn = NO_ERROR;
  878. DBG_ENTER( _T("prv_DeletePrintMonitor"),
  879. dwReturn,
  880. _T("%s"),
  881. pszMonitorName);
  882. if (pszMonitorName == NULL)
  883. {
  884. dwReturn = ERROR_INVALID_PARAMETER;
  885. return dwReturn;
  886. }
  887. bSuccess = ::DeleteMonitor(NULL, NULL, (LPTSTR) pszMonitorName);
  888. if (bSuccess)
  889. {
  890. VERBOSE(DBG_MSG,
  891. _T("DeletePrinterMonitor, successfully ")
  892. _T("deleted print monitor name '%s'"),
  893. pszMonitorName);
  894. }
  895. else
  896. {
  897. dwReturn = ::GetLastError();
  898. if (dwReturn != ERROR_UNKNOWN_PRINT_MONITOR)
  899. {
  900. VERBOSE(SETUP_ERR,
  901. _T("DeletePrinterMonitor, failed to ")
  902. _T("remove print monitor '%s', rc = 0x%lx"),
  903. pszMonitorName,
  904. dwReturn);
  905. }
  906. else
  907. {
  908. dwReturn = NO_ERROR;
  909. }
  910. }
  911. return dwReturn;
  912. }
  913. ////////////////////////////
  914. // prv_DeleteFaxPrinterDriver
  915. //
  916. // Delete fax printer driver from current machine
  917. // In case of failure, log it and returns FALSE.
  918. //
  919. // Params:
  920. // - LPTSTR lptstrDriverName - Driver name to delete
  921. // - pEnvironment - for which platform are the drivers deleted
  922. // - DWORD dwVersionFlag - The version of the driver that should be deleted.
  923. // Valid valuse {0,1,2,3} only.
  924. // Returns;
  925. // - Returns ERROR_SUCCESS on success, on failue retuen the error code.
  926. //
  927. static DWORD prv_DeleteFaxPrinterDriver(LPTSTR lptstrDriverName,
  928. LPTSTR pEnviroment,
  929. DWORD dwVersionFlag)
  930. {
  931. BOOL bSuccess = TRUE;
  932. DWORD ec = ERROR_SUCCESS;
  933. DBG_ENTER(_T("prv_DeleteFaxPrinterDriver"),ec);
  934. ASSERTION(dwVersionFlag<=3);
  935. // delete driver.
  936. bSuccess = DeletePrinterDriverEx(NULL,
  937. pEnviroment,
  938. lptstrDriverName,
  939. DPD_DELETE_SPECIFIC_VERSION|DPD_DELETE_ALL_FILES,
  940. dwVersionFlag);
  941. if (!bSuccess)
  942. {
  943. ec = GetLastError();
  944. VERBOSE(DBG_MSG,
  945. TEXT("DeletePrinterDriverEx() for driver %s, version %ld failed (ec: %ld)"),
  946. lptstrDriverName,
  947. dwVersionFlag,
  948. ec);
  949. }
  950. else
  951. {
  952. VERBOSE(DBG_MSG,
  953. TEXT("DeletePrinterDriverEx() for driver %s, version %ld succeeded"),
  954. lptstrDriverName,
  955. dwVersionFlag);
  956. }
  957. return ec;
  958. }
  959. /***************************************************************************************
  960. ** **
  961. ** C o C l a s s I n s t a l l e r s e c t i o n **
  962. ** **
  963. ***************************************************************************************/
  964. #ifdef ENABLE_LOGGING
  965. typedef struct _DIF_DEBUG {
  966. DWORD DifValue;
  967. LPTSTR DifString;
  968. } DIF_DEBUG, *PDIF_DEBUG;
  969. DIF_DEBUG DifDebug[] =
  970. {
  971. { 0, L"" }, // 0x00000000
  972. { DIF_SELECTDEVICE, L"DIF_SELECTDEVICE" }, // 0x00000001
  973. { DIF_INSTALLDEVICE, L"DIF_INSTALLDEVICE" }, // 0x00000002
  974. { DIF_ASSIGNRESOURCES, L"DIF_ASSIGNRESOURCES" }, // 0x00000003
  975. { DIF_PROPERTIES, L"DIF_PROPERTIES" }, // 0x00000004
  976. { DIF_REMOVE, L"DIF_REMOVE" }, // 0x00000005
  977. { DIF_FIRSTTIMESETUP, L"DIF_FIRSTTIMESETUP" }, // 0x00000006
  978. { DIF_FOUNDDEVICE, L"DIF_FOUNDDEVICE" }, // 0x00000007
  979. { DIF_SELECTCLASSDRIVERS, L"DIF_SELECTCLASSDRIVERS" }, // 0x00000008
  980. { DIF_VALIDATECLASSDRIVERS, L"DIF_VALIDATECLASSDRIVERS" }, // 0x00000009
  981. { DIF_INSTALLCLASSDRIVERS, L"DIF_INSTALLCLASSDRIVERS" }, // 0x0000000A
  982. { DIF_CALCDISKSPACE, L"DIF_CALCDISKSPACE" }, // 0x0000000B
  983. { DIF_DESTROYPRIVATEDATA, L"DIF_DESTROYPRIVATEDATA" }, // 0x0000000C
  984. { DIF_VALIDATEDRIVER, L"DIF_VALIDATEDRIVER" }, // 0x0000000D
  985. { DIF_MOVEDEVICE, L"DIF_MOVEDEVICE" }, // 0x0000000E
  986. { DIF_DETECT, L"DIF_DETECT" }, // 0x0000000F
  987. { DIF_INSTALLWIZARD, L"DIF_INSTALLWIZARD" }, // 0x00000010
  988. { DIF_DESTROYWIZARDDATA, L"DIF_DESTROYWIZARDDATA" }, // 0x00000011
  989. { DIF_PROPERTYCHANGE, L"DIF_PROPERTYCHANGE" }, // 0x00000012
  990. { DIF_ENABLECLASS, L"DIF_ENABLECLASS" }, // 0x00000013
  991. { DIF_DETECTVERIFY, L"DIF_DETECTVERIFY" }, // 0x00000014
  992. { DIF_INSTALLDEVICEFILES, L"DIF_INSTALLDEVICEFILES" }, // 0x00000015
  993. { DIF_UNREMOVE, L"DIF_UNREMOVE" }, // 0x00000016
  994. { DIF_SELECTBESTCOMPATDRV, L"DIF_SELECTBESTCOMPATDRV" }, // 0x00000017
  995. { DIF_ALLOW_INSTALL, L"DIF_ALLOW_INSTALL" }, // 0x00000018
  996. { DIF_REGISTERDEVICE, L"DIF_REGISTERDEVICE" }, // 0x00000019
  997. { DIF_NEWDEVICEWIZARD_PRESELECT, L"DIF_NEWDEVICEWIZARD_PRESELECT" }, // 0x0000001A
  998. { DIF_NEWDEVICEWIZARD_SELECT, L"DIF_NEWDEVICEWIZARD_SELECT" }, // 0x0000001B
  999. { DIF_NEWDEVICEWIZARD_PREANALYZE, L"DIF_NEWDEVICEWIZARD_PREANALYZE" }, // 0x0000001C
  1000. { DIF_NEWDEVICEWIZARD_POSTANALYZE, L"DIF_NEWDEVICEWIZARD_POSTANALYZE" }, // 0x0000001D
  1001. { DIF_NEWDEVICEWIZARD_FINISHINSTALL, L"DIF_NEWDEVICEWIZARD_FINISHINSTALL" }, // 0x0000001E
  1002. { DIF_UNUSED1, L"DIF_UNUSED1" }, // 0x0000001F
  1003. { DIF_INSTALLINTERFACES, L"DIF_INSTALLINTERFACES" }, // 0x00000020
  1004. { DIF_DETECTCANCEL, L"DIF_DETECTCANCEL" }, // 0x00000021
  1005. { DIF_REGISTER_COINSTALLERS, L"DIF_REGISTER_COINSTALLERS" }, // 0x00000022
  1006. { DIF_ADDPROPERTYPAGE_ADVANCED, L"DIF_ADDPROPERTYPAGE_ADVANCED" }, // 0x00000023
  1007. { DIF_ADDPROPERTYPAGE_BASIC, L"DIF_ADDPROPERTYPAGE_BASIC" }, // 0x00000024
  1008. { DIF_RESERVED1, L"DIF_RESERVED1" }, // 0x00000025
  1009. { DIF_TROUBLESHOOTER, L"DIF_TROUBLESHOOTER" }, // 0x00000026
  1010. { DIF_POWERMESSAGEWAKE, L"DIF_POWERMESSAGEWAKE" }, // 0x00000027
  1011. { DIF_ADDREMOTEPROPERTYPAGE_ADVANCED, L"DIF_ADDREMOTEPROPERTYPAGE_ADVANCED" } // 0x00000028
  1012. };
  1013. #endif
  1014. /*
  1015. ///////////////////////////////////////////////////////////////////////////////////////
  1016. // Function:
  1017. // SaveDontShowMeThisAgain
  1018. //
  1019. // Purpose:
  1020. // Check if the user checked the 'Don't show me this again'
  1021. // If he did, set the registry key
  1022. //
  1023. // Params:
  1024. // Handle to window
  1025. //
  1026. // Return Value:
  1027. // None
  1028. //
  1029. // Author:
  1030. // Mooly Beery (MoolyB) 17-Jan-2001
  1031. ///////////////////////////////////////////////////////////////////////////////////////
  1032. void SaveDontShowMeThisAgain(HWND hwndDlg)
  1033. {
  1034. DBG_ENTER(_T("SaveDontShowMeThisAgain"));
  1035. //
  1036. // let's save the "Don't show me again" state
  1037. //
  1038. if (BST_CHECKED == ::SendMessage (::GetDlgItem (hwndDlg, IDC_DONT_SHOW), BM_GETCHECK, 0, 0))
  1039. {
  1040. //
  1041. // User pressed the "Don't show me again" checkbox
  1042. //
  1043. HKEY hFaxKey = OpenRegistryKey (HKEY_LOCAL_MACHINE,
  1044. REGKEY_FAX_SETUP,
  1045. TRUE,
  1046. KEY_WRITE);
  1047. if (!hFaxKey)
  1048. {
  1049. CALL_FAIL (GENERAL_ERR, TEXT("OpenRegistryKey(REGKEY_FAX_SETUP)"), GetLastError());
  1050. }
  1051. else
  1052. {
  1053. if (!SetRegistryDword (hFaxKey,
  1054. REGVAL_DONT_UNATTEND_INSTALL,
  1055. 1))
  1056. {
  1057. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryDword(REGVAL_DONT_UNATTEND_INSTALL)"), GetLastError());
  1058. }
  1059. RegCloseKey (hFaxKey);
  1060. }
  1061. }
  1062. }
  1063. */
  1064. /*
  1065. static
  1066. INT_PTR
  1067. CALLBACK
  1068. prv_dlgInstallFaxQuestionPropPage(
  1069. HWND hwndDlg,
  1070. UINT uMsg,
  1071. WPARAM wParam,
  1072. LPARAM lParam
  1073. )
  1074. /*++
  1075. Routine name : prv_dlgInstallFaxQuestionPropPage
  1076. Routine description:
  1077. Dialogs procedure for "Install fax" dialog
  1078. Author:
  1079. Eran Yariv (EranY), Jul, 2000
  1080. Arguments:
  1081. hwndDlg [in] - Handle to dialog box
  1082. uMsg [in] - Message
  1083. wParam [in] - First message parameter
  1084. parameter [in] - Second message parameter
  1085. Return Value:
  1086. Standard dialog return value
  1087. --*/
  1088. /*
  1089. {
  1090. DWORD dwRes = NO_ERROR;
  1091. DBG_ENTER(_T("prv_dlgInstallFaxQuestionPropPage"));
  1092. switch (uMsg)
  1093. {
  1094. case WM_INITDIALOG:
  1095. // no return value here.
  1096. PropSheet_SetWizButtons(GetParent(hwndDlg),PSWIZB_NEXT);
  1097. SetFocus(hwndDlg);
  1098. if (!CheckDlgButton(hwndDlg,IDC_INSTALL_FAX_NOW,BST_CHECKED))
  1099. {
  1100. dwRes = GetLastError();
  1101. CALL_FAIL (GENERAL_ERR, TEXT("CheckDlgButton"), dwRes);
  1102. }
  1103. break;
  1104. case WM_NOTIFY:
  1105. switch (((NMHDR*)lParam)->code)
  1106. {
  1107. case PSN_WIZNEXT:
  1108. SaveDontShowMeThisAgain(hwndDlg);
  1109. //
  1110. // let's get the "Install Fax Now" state
  1111. //
  1112. if (BST_CHECKED == ::SendMessage (::GetDlgItem (hwndDlg, IDC_INSTALL_FAX_NOW), BM_GETCHECK, 0, 0))
  1113. {
  1114. //
  1115. // User pressed the "Install Fax Now" checkbox
  1116. //
  1117. dwRes = InstallFaxUnattended();
  1118. if (dwRes!=ERROR_SUCCESS)
  1119. {
  1120. CALL_FAIL (GENERAL_ERR, TEXT("InstallFaxUnattended"), dwRes);
  1121. }
  1122. }
  1123. return TRUE;
  1124. }
  1125. break;
  1126. }
  1127. return FALSE;
  1128. } // prv_dlgInstallFaxQuestionPropPage
  1129. */
  1130. /*
  1131. static
  1132. INT_PTR
  1133. CALLBACK
  1134. prv_dlgInstallFaxQuestion(
  1135. HWND hwndDlg,
  1136. UINT uMsg,
  1137. WPARAM wParam,
  1138. LPARAM lParam
  1139. )
  1140. /*++
  1141. Routine name : prv_dlgInstallFaxQuestion
  1142. Routine description:
  1143. Dialogs procedure for "Install fax" dialog
  1144. Author:
  1145. Eran Yariv (EranY), Jul, 2000
  1146. Arguments:
  1147. hwndDlg [in] - Handle to dialog box
  1148. uMsg [in] - Message
  1149. wParam [in] - First message parameter
  1150. parameter [in] - Second message parameter
  1151. Return Value:
  1152. Standard dialog return value
  1153. --*/
  1154. /*
  1155. {
  1156. INT_PTR iRes = IDIGNORE;
  1157. DBG_ENTER(_T("prv_dlgInstallFaxQuestion"));
  1158. switch (uMsg)
  1159. {
  1160. case WM_INITDIALOG:
  1161. SetFocus(hwndDlg);
  1162. break;
  1163. case WM_COMMAND:
  1164. switch(LOWORD(wParam))
  1165. {
  1166. case IDC_ANSWER_YES:
  1167. iRes = IDYES;
  1168. break;
  1169. case IDC_ANSWER_NO:
  1170. iRes = IDNO;
  1171. break;
  1172. }
  1173. if (IDIGNORE != iRes)
  1174. {
  1175. SaveDontShowMeThisAgain(hwndDlg);
  1176. EndDialog (hwndDlg, iRes);
  1177. return TRUE;
  1178. }
  1179. break;
  1180. }
  1181. return FALSE;
  1182. } // prv_dlgInstallFaxQuestion
  1183. */
  1184. ///////////////////////////////////////////////////////////////////////////////////////
  1185. // Function:
  1186. // AllowInstallationProposal
  1187. //
  1188. // Purpose:
  1189. // Verify we can propose to the user to install Fax
  1190. // Check if Fax is installed
  1191. // Check if the user has marked the 'don't show this again'
  1192. //
  1193. // Params:
  1194. // None
  1195. //
  1196. // Return Value:
  1197. // true - ok to propose the installation of Fax
  1198. // false - do not propose the Fax installation
  1199. //
  1200. // Author:
  1201. // Mooly Beery (MoolyB) 17-Jan-2001
  1202. ///////////////////////////////////////////////////////////////////////////////////////
  1203. bool AllowInstallationProposal()
  1204. {
  1205. DWORD ec = NO_ERROR;
  1206. BOOL bFaxInstalled = FALSE;
  1207. DBG_ENTER(_T("AllowInstallationProposal"));
  1208. ec = IsFaxInstalled (&bFaxInstalled);
  1209. if (ec!=ERROR_SUCCESS)
  1210. {
  1211. CALL_FAIL (GENERAL_ERR, TEXT("IsFaxInstalled"), ec);
  1212. return false;
  1213. }
  1214. if (bFaxInstalled)
  1215. {
  1216. VERBOSE(DBG_MSG,TEXT("Fax is already installed"));
  1217. return false;
  1218. }
  1219. //
  1220. // Let's find out if we're allowed to add a property page
  1221. //
  1222. BOOL bDontShowThisAgain = FALSE;
  1223. HKEY hFaxKey = OpenRegistryKey (HKEY_LOCAL_MACHINE,
  1224. REGKEY_FAX_SETUP,
  1225. FALSE,
  1226. KEY_READ);
  1227. if (!hFaxKey)
  1228. {
  1229. //
  1230. // No value there
  1231. //
  1232. ec = GetLastError();
  1233. CALL_FAIL (GENERAL_ERR, TEXT("OpenRegistryKey(REGKEY_FAX_SETUP)"), ec);
  1234. // let's go on.
  1235. }
  1236. else
  1237. {
  1238. bDontShowThisAgain = GetRegistryDword (hFaxKey,REGVAL_DONT_UNATTEND_INSTALL);
  1239. RegCloseKey (hFaxKey);
  1240. }
  1241. if (bDontShowThisAgain)
  1242. {
  1243. //
  1244. // User previously checked the "Don't ask me again" checkbox
  1245. //
  1246. VERBOSE (DBG_MSG, TEXT("Used previously checked the \"Don't ask me again\" checkbox"));
  1247. return false;
  1248. }
  1249. return true;
  1250. }
  1251. /*
  1252. ///////////////////////////////////////////////////////////////////////////////////////
  1253. // Function:
  1254. // HandleNonPnpDevices
  1255. //
  1256. // Purpose:
  1257. // Handles DIF_INSTALLDEVICE
  1258. // A new device has finished installing and we check if this is a non PnP device
  1259. // if it is we propose the user to install Fax using a message box.
  1260. //
  1261. // Params:
  1262. // None
  1263. //
  1264. // Return Value:
  1265. // NO_ERROR - everything was ok.
  1266. // Win32 Error code in case if failure.
  1267. //
  1268. // Author:
  1269. // Mooly Beery (MoolyB) 17-Jan-2001
  1270. ///////////////////////////////////////////////////////////////////////////////////////
  1271. DWORD HandleNonPnpDevices()
  1272. {
  1273. DWORD ec = NO_ERROR;
  1274. DBG_ENTER(_T("HandleNonPnpDevices"), ec);
  1275. // if this is a PnP installation don't do anything here
  1276. if (bIsPnpInstallation)
  1277. {
  1278. VERBOSE(DBG_MSG,_T("This is a PnP device installation, exiting"));
  1279. goto exit;
  1280. }
  1281. // if Fax is installed or the user has checked the 'Don't show me this again' do not propose
  1282. if (!AllowInstallationProposal())
  1283. {
  1284. VERBOSE(DBG_MSG,TEXT("Not allowed to install, exit"));
  1285. goto exit;
  1286. }
  1287. //
  1288. // Let's ask the user if he wishes to install a fax now
  1289. //
  1290. INT_PTR iResult = DialogBox (faxocm_GetAppInstance(),
  1291. MAKEINTRESOURCE(IDD_INSTALL_FAX),
  1292. NULL,
  1293. prv_dlgInstallFaxQuestion);
  1294. if (iResult==-1)
  1295. {
  1296. ec = GetLastError();
  1297. CALL_FAIL (RESOURCE_ERR, TEXT("DialogBox(IDD_INSTALL_FAX)"), ec);
  1298. goto exit;
  1299. }
  1300. if (iResult==IDYES)
  1301. {
  1302. //
  1303. // User wishes to install the fax now - do so.
  1304. //
  1305. ec = InstallFaxUnattended();
  1306. if (ec!=ERROR_SUCCESS)
  1307. {
  1308. CALL_FAIL (GENERAL_ERR, TEXT("InstallFaxUnattended"), ec);
  1309. }
  1310. }
  1311. exit:
  1312. return ec;
  1313. }
  1314. ///////////////////////////////////////////////////////////////////////////////////////
  1315. // Function:
  1316. // GetModemDriverInfo
  1317. //
  1318. // Purpose:
  1319. // Gets the modem's selected driver and retrieves the modem's INF
  1320. // filename and section within the INF file
  1321. //
  1322. // Params:
  1323. // IN HDEVINFO hDeviceInfoSet - passed from CoDevice Installer
  1324. // IN PSP_DEVINFO_DATA pDeviceInfoData - passed from CoDevice Installer
  1325. // OUT PSP_DRVINFO_DETAIL_DATA pspDrvInfoDetailData - passes out the driver details
  1326. //
  1327. // Return Value:
  1328. // NO_ERROR - everything was ok.
  1329. // Win32 Error code in case if failure.
  1330. //
  1331. // Caller must call MemFree on returned pointer.
  1332. //
  1333. // Author:
  1334. // Mooly Beery (MoolyB) 28-Mar-2001
  1335. ///////////////////////////////////////////////////////////////////////////////////////
  1336. static DWORD GetModemDriverInfo
  1337. (
  1338. IN HDEVINFO hDeviceInfoSet,
  1339. IN PSP_DEVINFO_DATA pDeviceInfoData,
  1340. OUT PSP_DRVINFO_DETAIL_DATA pspDrvInfoDetailData
  1341. )
  1342. {
  1343. DWORD ec = NO_ERROR;
  1344. DWORD dwRequiredSize = 0;
  1345. SP_DRVINFO_DATA spDrvInfoData;
  1346. DBG_ENTER(_T("GetModemDriverInfo"), ec);
  1347. pspDrvInfoDetailData = NULL;
  1348. spDrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  1349. if (SetupDiGetSelectedDriver(hDeviceInfoSet,pDeviceInfoData,&spDrvInfoData))
  1350. {
  1351. if (!SetupDiGetDriverInfoDetail(hDeviceInfoSet,pDeviceInfoData,&spDrvInfoData,NULL,0,&dwRequiredSize))
  1352. {
  1353. ec = GetLastError();
  1354. if (ec==ERROR_INSUFFICIENT_BUFFER)
  1355. {
  1356. ec = NO_ERROR;
  1357. if (pspDrvInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)MemAlloc(dwRequiredSize))
  1358. {
  1359. pspDrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  1360. if (SetupDiGetDriverInfoDetail(hDeviceInfoSet,pDeviceInfoData,&spDrvInfoData,pspDrvInfoDetailData,dwRequiredSize,NULL))
  1361. {
  1362. VERBOSE(DBG_MSG,_T("Driver Inf Name is: %s"),pspDrvInfoDetailData->InfFileName);
  1363. VERBOSE(DBG_MSG,_T("Driver Section Name is: %s"),pspDrvInfoDetailData->SectionName);
  1364. VERBOSE(DBG_MSG,_T("Driver Description is: %s"),pspDrvInfoDetailData->DrvDescription);
  1365. VERBOSE(DBG_MSG,_T("Driver Hardware ID is: %s"),pspDrvInfoDetailData->HardwareID);
  1366. }
  1367. else
  1368. {
  1369. ec = GetLastError();
  1370. CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetDriverInfoDetail"), ec);
  1371. }
  1372. }
  1373. else
  1374. {
  1375. ec = ERROR_NOT_ENOUGH_MEMORY;
  1376. VERBOSE(GENERAL_ERR, TEXT("MemAlloc failed"));
  1377. }
  1378. }
  1379. else
  1380. {
  1381. ec = GetLastError();
  1382. CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetDriverInfoDetail"), ec);
  1383. }
  1384. }
  1385. else
  1386. {
  1387. ec = ERROR_INVALID_PARAMETER;
  1388. VERBOSE(GENERAL_ERR, TEXT("SetupDiGetDriverInfoDetail should have failed"));
  1389. }
  1390. }
  1391. else
  1392. {
  1393. ec = GetLastError();
  1394. CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetSelectedDriver"), ec);
  1395. }
  1396. return ec;
  1397. }
  1398. ///////////////////////////////////////////////////////////////////////////////////////
  1399. // Function:
  1400. // SearchModemInfFaxSection
  1401. //
  1402. // Purpose:
  1403. // Search the modem's INF to find if a Fax section exists.
  1404. // If a Fax section exists, try to find the InstallFax key
  1405. // If it's there, install Fax unattended.
  1406. //
  1407. // Params:
  1408. // IN HDEVINFO hDeviceInfoSet - passed from CoDevice Installer
  1409. // IN PSP_DEVINFO_DATA pDeviceInfoData - passed from CoDevice Installer
  1410. //
  1411. // Return Value:
  1412. // NO_ERROR - everything was ok.
  1413. // Win32 Error code in case if failure.
  1414. //
  1415. // Author:
  1416. // Mooly Beery (MoolyB) 28-Mar-2001
  1417. ///////////////////////////////////////////////////////////////////////////////////////
  1418. DWORD SearchModemInfFaxSection
  1419. (
  1420. IN HDEVINFO hDeviceInfoSet,
  1421. IN PSP_DEVINFO_DATA pDeviceInfoData
  1422. )
  1423. {
  1424. DWORD ec = NO_ERROR;
  1425. DWORD Size = sizeof(DWORD);
  1426. DWORD Type = 0;
  1427. DWORD Value = 0;
  1428. HKEY hDeviceKey = NULL;
  1429. HKEY hFaxKey = NULL;
  1430. LPTSTR lptstrInstallFax = NULL;
  1431. DBG_ENTER(_T("SearchModemInfFaxSection"), ec);
  1432. // get the device key under HKLM\SYSTEM\CurrentControlSet\Control\Class\ClassGUID\InstanceID
  1433. hDeviceKey = SetupDiOpenDevRegKey(hDeviceInfoSet,pDeviceInfoData,DICS_FLAG_GLOBAL,0,DIREG_DRV,KEY_READ);
  1434. if (hDeviceKey==NULL)
  1435. {
  1436. CALL_FAIL (GENERAL_ERR, TEXT("SetupDiOpenDevRegKey"), ec);
  1437. goto exit;
  1438. }
  1439. // check if the Fax subkey exists.
  1440. hFaxKey = OpenRegistryKey(hDeviceKey,_T("Fax"),FALSE,KEY_READ);
  1441. if (hFaxKey==NULL)
  1442. {
  1443. VERBOSE(DBG_MSG, TEXT("This modem does not have a Fax section, exit..."));
  1444. ec = NO_ERROR;
  1445. goto exit;
  1446. }
  1447. // this modem has a Fax section.
  1448. // let's check if it uses the 'InstallFax' REG_SZ
  1449. lptstrInstallFax = GetRegistryString(hFaxKey,_T("InstallFax"),NULL);
  1450. if (lptstrInstallFax==NULL)
  1451. {
  1452. VERBOSE(DBG_MSG, TEXT("This modem does not have an InstallFax REG_SZ in the Fax section, exit..."));
  1453. ec = NO_ERROR;
  1454. goto exit;
  1455. }
  1456. // check if the InstallFax is 0 (unlikely, but...)
  1457. if (_tcsicmp(lptstrInstallFax,_T("0"))==0)
  1458. {
  1459. VERBOSE(DBG_MSG, TEXT("This modem does has an InstallFax=0 REG_SZ in the Fax section, exit..."));
  1460. ec = NO_ERROR;
  1461. goto exit;
  1462. }
  1463. //if (InSystemSetup(hDeviceInfoSet,pDeviceInfoData))
  1464. {
  1465. // if we're in system setup, we should just notify our component that it should install.
  1466. }
  1467. //else
  1468. {
  1469. // finally, Install Fax.
  1470. ec = InstallFaxUnattended();
  1471. if (ec!=ERROR_SUCCESS)
  1472. {
  1473. CALL_FAIL (GENERAL_ERR, TEXT("InstallFaxUnattended"), ec);
  1474. }
  1475. }
  1476. exit:
  1477. if (hDeviceKey)
  1478. {
  1479. RegCloseKey(hDeviceKey);
  1480. }
  1481. if (hFaxKey)
  1482. {
  1483. RegCloseKey(hFaxKey);
  1484. }
  1485. return ec;
  1486. }
  1487. */
  1488. ///////////////////////////////////////////////////////////////////////////////////////
  1489. // Function:
  1490. // HandleInstallDevice
  1491. //
  1492. // Purpose:
  1493. // Handles DIF_INSTALLDEVICE
  1494. // A new device has finished installing and we're allowed to install a printer
  1495. // if Fax is already on the box
  1496. // In this case we do the following:
  1497. //
  1498. // 1. Check if Fax is installed, it it's not then attemp to install Fax based on INF
  1499. // 2. Check if there's a Fax printer, if there is leave
  1500. // 3. Install a Fax printer
  1501. // 4. Ensure the service is up
  1502. // 5. Leave
  1503. //
  1504. // Params:
  1505. // IN HDEVINFO hDeviceInfoSet - passed from CoDevice Installer
  1506. // IN PSP_DEVINFO_DATA pDeviceInfoData - passed from CoDevice Installer
  1507. //
  1508. // Return Value:
  1509. // NO_ERROR - everything was ok.
  1510. // Win32 Error code in case if failure.
  1511. //
  1512. // Author:
  1513. // Eran Yariv (EranY) 17-Jul-2000
  1514. // Mooly Beery (MoolyB) 08-Jan-2001
  1515. ///////////////////////////////////////////////////////////////////////////////////////
  1516. DWORD HandleInstallDevice
  1517. (
  1518. IN HDEVINFO hDeviceInfoSet,
  1519. IN PSP_DEVINFO_DATA pDeviceInfoData
  1520. )
  1521. {
  1522. DWORD ec = NO_ERROR;
  1523. BOOL bFaxInstalled;
  1524. BOOL bLocalFaxPrinterInstalled;
  1525. DBG_ENTER(_T("HandleInstallDevice"), ec);
  1526. // Now we know a new modem installation succeeded.
  1527. // Let's check if our component is installed.
  1528. //
  1529. ec = IsFaxInstalled(&bFaxInstalled);
  1530. if (ec!=ERROR_SUCCESS)
  1531. {
  1532. CALL_FAIL (GENERAL_ERR, TEXT("IsFaxInstalled"), ec);
  1533. goto exit;
  1534. }
  1535. if (!bFaxInstalled)
  1536. {
  1537. VERBOSE(DBG_MSG,TEXT("Fax is not installed, search modem's INF for Fax section..."));
  1538. /*
  1539. ec = SearchModemInfFaxSection(hDeviceInfoSet,pDeviceInfoData);
  1540. if (ec!=ERROR_SUCCESS)
  1541. {
  1542. CALL_FAIL (GENERAL_ERR, TEXT("SearchModemInfFaxSection"), ec);
  1543. }*/
  1544. goto exit;
  1545. }
  1546. //
  1547. // Let's see if we have a local fax printer
  1548. //
  1549. ec = IsLocalFaxPrinterInstalled (&bLocalFaxPrinterInstalled);
  1550. if (ec!=ERROR_SUCCESS)
  1551. {
  1552. CALL_FAIL (GENERAL_ERR, TEXT("IsLocalFaxPrinterInstalled"), ec);
  1553. goto exit;
  1554. }
  1555. if (bLocalFaxPrinterInstalled)
  1556. {
  1557. VERBOSE(DBG_MSG,TEXT("Fax Printer is installed, exit"));
  1558. goto exit;
  1559. }
  1560. //
  1561. // This is the time to install a local fax printer.
  1562. //
  1563. ec = AddLocalFaxPrinter (FAX_PRINTER_NAME, NULL);
  1564. if (ERROR_SUCCESS != ec)
  1565. {
  1566. CALL_FAIL (GENERAL_ERR, TEXT("AddLocalFaxPrinter"), ec);
  1567. goto exit;
  1568. }
  1569. //
  1570. // Make sure the service is running.
  1571. // This is important because there may have been jobs in the queue that now, when we have
  1572. // a new modem device, can finally be executed.
  1573. //
  1574. if (!EnsureFaxServiceIsStarted (NULL))
  1575. {
  1576. ec = GetLastError ();
  1577. CALL_FAIL (GENERAL_ERR, TEXT("EnsureFaxServiceIsStarted"), ec);
  1578. goto exit;
  1579. }
  1580. exit:
  1581. return ec;
  1582. }
  1583. /*
  1584. ///////////////////////////////////////////////////////////////////////////////////////
  1585. // Function:
  1586. // HandleNewDeviceWizardFinishInstall
  1587. //
  1588. // Purpose:
  1589. // Handles DIF_NEWDEVICEWIZARD_FINISHINSTALL
  1590. // A new device has finished installing and we're allowed to add a property page
  1591. // asking the user to install Fax
  1592. // In this case we do the following:
  1593. //
  1594. // 1. Check if Fax is installed, if it is leave
  1595. // 2. Check if we're allowed to add a property page, if not leave
  1596. // 3. Add a property page to the wizard.
  1597. // 4. Leave
  1598. //
  1599. // Params:
  1600. // See CoClassInstaller documentation in DDK
  1601. //
  1602. // Return Value:
  1603. // NO_ERROR - everything was ok.
  1604. // Win32 Error code in case if failure.
  1605. //
  1606. // Author:
  1607. // Eran Yariv (EranY) 17-Jul-2000
  1608. // Mooly Beery (MoolyB) 08-Jan-2001
  1609. ///////////////////////////////////////////////////////////////////////////////////////
  1610. DWORD HandleNewDeviceWizardFinishInstall
  1611. (
  1612. IN HDEVINFO hDeviceInfoSet,
  1613. IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL
  1614. )
  1615. {
  1616. DWORD ec = NO_ERROR;
  1617. BOOL bFaxInstalled = FALSE;
  1618. TCHAR* WizardTitle = NULL;
  1619. TCHAR* WizardSubTitle = NULL;
  1620. SP_NEWDEVICEWIZARD_DATA nddClassInstallParams = {0};
  1621. DWORD dwClassInstallParamsSize = sizeof(SP_NEWDEVICEWIZARD_DATA);
  1622. HPROPSHEETPAGE hPsp = NULL;
  1623. PROPSHEETPAGE psp = {0};
  1624. DBG_ENTER(_T("HandleNewDeviceWizardFinishInstall"), ec);
  1625. if (!AllowInstallationProposal())
  1626. {
  1627. VERBOSE(DBG_MSG,TEXT("Not allowed to install, exit"));
  1628. goto exit;
  1629. }
  1630. nddClassInstallParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  1631. // get the class install parameters by calling SetupDiGetClassInstallParams
  1632. if (!SetupDiGetClassInstallParams( hDeviceInfoSet,
  1633. pDeviceInfoData,
  1634. (PSP_CLASSINSTALL_HEADER)&nddClassInstallParams,
  1635. dwClassInstallParamsSize,
  1636. NULL))
  1637. {
  1638. ec = GetLastError();
  1639. CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetClassInstallParams"), ec);
  1640. goto exit;
  1641. }
  1642. // check whether NumDynamicPages has reached the max
  1643. if (nddClassInstallParams.NumDynamicPages>=MAX_INSTALLWIZARD_DYNAPAGES)
  1644. {
  1645. VERBOSE (GENERAL_ERR, TEXT("Too many property pages, can't add another one"));
  1646. ec = ERROR_BUFFER_OVERFLOW;
  1647. goto exit;
  1648. }
  1649. // fill in the PROPSHEETPAGE structure
  1650. psp.dwSize = sizeof(PROPSHEETPAGE);
  1651. psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  1652. psp.hInstance = faxocm_GetAppInstance();
  1653. psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALL_FAX_PROP);
  1654. psp.pfnDlgProc = prv_dlgInstallFaxQuestionPropPage;
  1655. WizardTitle = (TCHAR*)MemAlloc(MAX_PATH * sizeof(TCHAR) );
  1656. if(WizardTitle)
  1657. {
  1658. if (!LoadString(psp.hInstance, IDS_NEW_DEVICE_TITLE, WizardTitle, MAX_PATH))
  1659. {
  1660. ec = GetLastError();
  1661. CALL_FAIL (GENERAL_ERR, TEXT("LoadString"), ec);
  1662. WizardTitle[0] = 0;
  1663. }
  1664. else
  1665. {
  1666. psp.pszHeaderTitle = WizardTitle;
  1667. }
  1668. }
  1669. WizardSubTitle = (TCHAR*)MemAlloc(MAX_PATH * sizeof(TCHAR) );
  1670. if(WizardSubTitle)
  1671. {
  1672. if (!LoadString(psp.hInstance, IDS_NEW_DEVICE_SUBTITLE, WizardSubTitle, MAX_PATH))
  1673. {
  1674. ec = GetLastError();
  1675. CALL_FAIL (GENERAL_ERR, TEXT("LoadString"), ec);
  1676. WizardSubTitle[0] = 0;
  1677. }
  1678. else
  1679. {
  1680. psp.pszHeaderSubTitle = WizardSubTitle;
  1681. }
  1682. }
  1683. // add the page and increment the NumDynamicPages counter
  1684. hPsp = CreatePropertySheetPage(&psp);
  1685. if (hPsp==NULL)
  1686. {
  1687. ec = GetLastError();
  1688. CALL_FAIL (GENERAL_ERR, TEXT("CreatePropertySheetPage"), ec);
  1689. goto exit;
  1690. }
  1691. nddClassInstallParams.DynamicPages[nddClassInstallParams.NumDynamicPages++] = hPsp;
  1692. // apply the modified params by calling SetupDiSetClassInstallParams
  1693. if (!SetupDiSetClassInstallParams( hDeviceInfoSet,
  1694. pDeviceInfoData,
  1695. (PSP_CLASSINSTALL_HEADER)&nddClassInstallParams,
  1696. dwClassInstallParamsSize))
  1697. {
  1698. ec = GetLastError();
  1699. CALL_FAIL (GENERAL_ERR, TEXT("LoadString"), ec);
  1700. goto exit;
  1701. }
  1702. exit:
  1703. return ec;
  1704. }
  1705. */
  1706. ///////////////////////////////////////////////////////////////////////////////////////
  1707. // Function:
  1708. // FaxModemCoClassInstaller
  1709. //
  1710. // Purpose:
  1711. // Our Fax CoClassInstaller, handles newly discovered modems
  1712. //
  1713. // Params:
  1714. // See CoClassInstaller documentation in DDK
  1715. //
  1716. // Return Value:
  1717. // NO_ERROR - everything was ok.
  1718. // Win32 Error code in case if failure.
  1719. //
  1720. // Author:
  1721. // Eran Yariv (EranY) 17-Jul-2000
  1722. // Mooly Beery (MoolyB) 08-Jan-2001
  1723. ///////////////////////////////////////////////////////////////////////////////////////
  1724. DWORD CALLBACK FaxModemCoClassInstaller
  1725. (
  1726. IN DI_FUNCTION InstallFunction,
  1727. IN HDEVINFO hDeviceInfoSet,
  1728. IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL,
  1729. IN OUT PCOINSTALLER_CONTEXT_DATA Context
  1730. )
  1731. {
  1732. DWORD ec = NO_ERROR;
  1733. DBG_ENTER(_T("FaxModemCoClassInstaller"), ec, TEXT("Processing %s request"), DifDebug[InstallFunction].DifString);
  1734. // We handle two events:
  1735. //
  1736. // DIF_INSTALLDEVICE
  1737. // A new device has finished installing and we're allowed to install a printer
  1738. // if Fax is already on the box
  1739. // In this case we do the following:
  1740. //
  1741. // 1. Check if Fax is installed, if it's not leave
  1742. // 2. Check if there's a Fax printer, if there is leave
  1743. // 3. Install a Fax printer
  1744. // 4. Ensure the service is up
  1745. // 5. Leave
  1746. //
  1747. // DIF_NEWDEVICEWIZARD_FINISHINSTALL
  1748. // A new device has finished installing and we're allowed to add a property page
  1749. // asking the user to install Fax
  1750. // In this case we do the following:
  1751. //
  1752. // 1. Check if Fax is installed, if it is leave
  1753. // 2. Check if we're allowed to add a property page, if not leave
  1754. // 3. Add a property page to the wizard.
  1755. // 4. Leave
  1756. switch (InstallFunction)
  1757. {
  1758. case DIF_INSTALLWIZARD:
  1759. VERBOSE (DBG_MSG, L"Marking installation as potential non PnP");
  1760. bIsPnpInstallation = false;
  1761. break;
  1762. case DIF_INSTALLDEVICE:
  1763. if (!Context->PostProcessing)
  1764. {
  1765. //
  1766. // The modem device is not installed yet
  1767. //
  1768. VERBOSE (DBG_MSG, L"Pre-installation, waiting for post-installation call");
  1769. ec = ERROR_DI_POSTPROCESSING_REQUIRED;
  1770. return ec;
  1771. }
  1772. if (Context->InstallResult!=NO_ERROR)
  1773. {
  1774. //
  1775. // The modem device had some problems during installation
  1776. //
  1777. VERBOSE (DBG_MSG, L"Previous error causing installation failure, 0x%08x", Context->InstallResult);
  1778. ec = Context->InstallResult;
  1779. return ec;
  1780. }
  1781. if (HandleInstallDevice(hDeviceInfoSet,pDeviceInfoData)!=NO_ERROR)
  1782. {
  1783. CALL_FAIL (GENERAL_ERR, TEXT("HandleInstallDevice"), GetLastError());
  1784. // do not fail the CoClassInstaller
  1785. }
  1786. /* No UI until futher notice
  1787. if (HandleNonPnpDevices()!=NO_ERROR)
  1788. {
  1789. CALL_FAIL (GENERAL_ERR, TEXT("HandleNonPnpDevices"), GetLastError());
  1790. // do not fail the CoClassInstaller
  1791. }
  1792. */
  1793. break;
  1794. case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
  1795. /* No UI until futher notice
  1796. Assert(bIsPnpInstallation);
  1797. if (HandleNewDeviceWizardFinishInstall(hDeviceInfoSet,pDeviceInfoData)!=NO_ERROR)
  1798. {
  1799. CALL_FAIL (GENERAL_ERR, TEXT("HandleNewDeviceWizardFinishInstall"), GetLastError());
  1800. // do not fail the CoClassInstaller
  1801. }
  1802. */
  1803. break;
  1804. default:
  1805. VERBOSE(DBG_MSG,TEXT("We do not handle %s"),DifDebug[InstallFunction].DifString);
  1806. break;
  1807. }
  1808. return ec;
  1809. }