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.

2902 lines
86 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File Name: faxocm.cpp
  4. //
  5. // Abstract: This file implements the OCM setup for fax.
  6. //
  7. // Environment: windows XP / User Mode
  8. //
  9. // Coding Style: Any function, variable, or typedef preceded with the
  10. // "prv_" prefix (short for "local"), implies that
  11. // it is visible only within the scope of this file.
  12. // For functions and variables, it implies they are
  13. // static.
  14. //
  15. // Copyright (c) 2000 Microsoft Corporation
  16. //
  17. // Revision History:
  18. //
  19. // Date: Developer: Comments:
  20. // ----- ---------- ---------
  21. // 15-Mar-2000 Oren Rosenbloom (orenr) Created from old faxocm.cpp by wesx
  22. //////////////////////////////////////////////////////////////////////////////
  23. #include "faxocm.h"
  24. #pragma hdrstop
  25. #include <shellapi.h>
  26. #include <systrayp.h>
  27. /////////////////////////////// Local Defines ////////////////////////////
  28. #define prv_TOTAL_NUM_PROGRESS_BAR_TICKS 12
  29. // These two are defined in %SDXROOT%\SHELL\EXT\SYSTRAY\DLL\systray.h too.
  30. // This is a duplicate definition that has to remain in sync.
  31. // We don't use the systray.h because we have local builds and we're
  32. // not enlisted on the whole project.
  33. #define FAX_STARTUP_TIMER_ID 7
  34. #define FAX_SHUTDOWN_TIMER_ID 99
  35. ///////////////////////////////
  36. // prv_Component_t
  37. //
  38. // Stores the information we
  39. // get from the OC Manager
  40. // for use by the rest of the
  41. // faxocm.dll.
  42. //
  43. typedef struct prv_Component_t
  44. {
  45. DWORD dwExpectedOCManagerVersion;
  46. TCHAR szComponentID[255 + 1];
  47. TCHAR szSubComponentID[255 + 1]; // Needed for prv_dlgOcmWizardPage
  48. HINF hInf;
  49. DWORD dwSetupMode;
  50. DWORDLONG dwlFlags;
  51. UINT uiLanguageID;
  52. TCHAR szSourcePath[_MAX_PATH + _MAX_FNAME + 1];
  53. TCHAR szUnattendFile[_MAX_PATH + _MAX_FNAME + 1];
  54. OCMANAGER_ROUTINES Helpers;
  55. EXTRA_ROUTINES Extras;
  56. HSPFILEQ hQueue;
  57. DWORD dwProductType;
  58. PRODUCT_SKU_TYPE InstalledProductSKU;
  59. DWORD InstalledProductBuild;
  60. } prv_Component_t;
  61. ///////////////////////////////
  62. // prv_GVAR
  63. //
  64. // Global variables visible
  65. // only within this file
  66. // scope.
  67. //
  68. static struct prv_GVAR
  69. {
  70. BOOL bInited;
  71. HINSTANCE hInstance;
  72. DWORD dwCurrentOCManagerVersion;
  73. prv_Component_t Component;
  74. } prv_GVAR =
  75. {
  76. FALSE, // bInited
  77. NULL // hInstance
  78. };
  79. //
  80. // Delay Load support
  81. //
  82. #include <delayimp.h>
  83. EXTERN_C
  84. FARPROC
  85. WINAPI
  86. DelayLoadFailureHook (
  87. UINT unReason,
  88. PDelayLoadInfo pDelayInfo
  89. );
  90. PfnDliHook __pfnDliFailureHook = DelayLoadFailureHook;
  91. //////////////////// Static Function Prototypes //////////////////////////////
  92. static void prv_UpdateProgressBar(DWORD dwNumTicks);
  93. static DWORD prv_GetSectionToProcess(const TCHAR *pszCurrentSection,
  94. TCHAR *pszSectionToProcess,
  95. DWORD dwNumBufChars);
  96. static DWORD prv_ValidateVersion(SETUP_INIT_COMPONENT *pSetupInit);
  97. static DWORD prv_SetSetupData(const TCHAR *pszComponentId,
  98. SETUP_INIT_COMPONENT *pSetupInit);
  99. static DWORD prv_OnPreinitialize(void);
  100. static DWORD prv_OnInitComponent(LPCTSTR pszComponentId,
  101. SETUP_INIT_COMPONENT *pSetupInitComponent);
  102. static DWORD prv_OnExtraRoutines(LPCTSTR pszComponentId,
  103. EXTRA_ROUTINES *pExtraRoutines);
  104. static DWORD prv_OnSetLanguage(UINT uiLanguageID);
  105. static DWORD_PTR prv_OnQueryImage(void);
  106. static DWORD prv_OnSetupRequestPages(LPCTSTR pszComponentId,
  107. WizardPagesType uiType,
  108. PSETUP_REQUEST_PAGES pSetupRequestPages);
  109. static DWORD prv_OnWizardCreated(void);
  110. static DWORD prv_OnQuerySkipPage(void);
  111. static DWORD prv_OnQuerySelStateChange(LPCTSTR pszComponentId,
  112. LPCTSTR pszSubcomponentId,
  113. UINT uiState,
  114. UINT uiFlags);
  115. static DWORD prv_OnCalcDiskSpace(LPCTSTR pszComponentId,
  116. LPCTSTR pszSubcomponentId,
  117. DWORD addComponent,
  118. HDSKSPC dspace);
  119. static DWORD prv_OnQueueFileOps(LPCTSTR pszComponentId,
  120. LPCTSTR pszSubcomponentId,
  121. HSPFILEQ hQueue);
  122. static DWORD prv_OnNotificationFromQueue(void);
  123. static DWORD prv_OnQueryStepCount(LPCTSTR pszComponentId,
  124. LPCTSTR pszSubcomponentId);
  125. static DWORD prv_OnCompleteInstallation(LPCTSTR pszComponentId,
  126. LPCTSTR pszSubcomponentId);
  127. static DWORD prv_OnCleanup(void);
  128. static DWORD prv_OnQueryState(LPCTSTR pszComponentId,
  129. LPCTSTR pszSubcomponentId,
  130. UINT uiState);
  131. static DWORD prv_OnNeedMedia(void);
  132. static DWORD prv_OnAboutToCommitQueue(LPCTSTR pszComponentId,
  133. LPCTSTR pszSubcomponentId);
  134. static DWORD prv_RunExternalProgram(LPCTSTR pszComponent,
  135. DWORD state);
  136. static DWORD prv_EnumSections(HINF hInf,
  137. const TCHAR *component,
  138. const TCHAR *key,
  139. DWORD index,
  140. INFCONTEXT *pic,
  141. TCHAR *name);
  142. static DWORD prv_CleanupNetShares(LPCTSTR pszComponent,
  143. DWORD state);
  144. static DWORD prv_CompleteFaxInstall(const TCHAR *pszSubcomponentId,
  145. const TCHAR *pszInstallSection);
  146. static DWORD prv_CompleteFaxUninstall(const TCHAR *pszSubcomponentId,
  147. const TCHAR *pszUninstallSection);
  148. static DWORD prv_UninstallFax(const TCHAR *pszSubcomponentId,
  149. const TCHAR *pszUninstallSection);
  150. static DWORD prv_NotifyStatusMonitor(WPARAM wParam);
  151. static DWORD prv_ShowUninstalledFaxShortcut(void);
  152. static INT_PTR CALLBACK prv_dlgOcmWizardPage(HWND hwndDlg,
  153. UINT uMsg,
  154. WPARAM wParam,
  155. LPARAM lParam);
  156. ///////////////////////////////
  157. // faxocm_IsInited
  158. //
  159. // Returns TRUE if OCM is
  160. // initialized, FALSE, otherwise
  161. //
  162. // Params:
  163. // - void
  164. // Returns:
  165. // - TRUE if initialized.
  166. // - FALSE otherwise.
  167. //
  168. BOOL faxocm_IsInited(void)
  169. {
  170. return prv_GVAR.bInited;
  171. }
  172. ///////////////////////////////
  173. // faxocm_GetAppInstance
  174. //
  175. // Returns the hInstance of
  176. // this DLL.
  177. //
  178. // Params:
  179. // - void
  180. // Returns:
  181. // - Instance of this DLL.
  182. //
  183. HINSTANCE faxocm_GetAppInstance(void)
  184. {
  185. return prv_GVAR.hInstance;
  186. }
  187. ///////////////////////////////
  188. // faxocm_GetComponentID
  189. //
  190. // Returns the Component ID
  191. // passed to us via the OC
  192. // Manager
  193. //
  194. // Params:
  195. // - pszComponentID - ID of top level component
  196. // - dwNumBufChars - # chars pszComponentID can hold
  197. // Returns:
  198. // - NO_ERROR on success.
  199. // - error code otherwise
  200. //
  201. DWORD faxocm_GetComponentID(TCHAR *pszComponentID,
  202. DWORD dwNumBufChars)
  203. {
  204. DWORD dwReturn = NO_ERROR;
  205. if ((pszComponentID == NULL) ||
  206. (dwNumBufChars == 0))
  207. {
  208. return ERROR_INVALID_PARAMETER;
  209. }
  210. _tcsncpy(pszComponentID, prv_GVAR.Component.szComponentID, dwNumBufChars);
  211. return dwReturn;
  212. }
  213. ///////////////////////////////
  214. // faxocm_GetComponentFileQueue
  215. //
  216. // Returns the file queue
  217. // given to us by the OC Manager
  218. //
  219. // The file queue is used by
  220. // the Setup API functions for
  221. // copying/deleting files.
  222. //
  223. // Params:
  224. // - void
  225. // Returns:
  226. // - Handle to file queue
  227. //
  228. HSPFILEQ faxocm_GetComponentFileQueue(void)
  229. {
  230. return prv_GVAR.Component.hQueue;
  231. }
  232. ///////////////////////////////
  233. // faxocm_GetComponentInfName
  234. //
  235. // Returns the full path to the
  236. // faxsetup.inf file.
  237. //
  238. // Params:
  239. // - buffer to fill with path, must be at least MAX_PATH long
  240. // Returns:
  241. // - NO_ERROR - in case of success
  242. // - Win32 Error code - otherwise
  243. //
  244. BOOL faxocm_GetComponentInfName(TCHAR* szInfFileName)
  245. {
  246. BOOL bRes = TRUE;
  247. DBG_ENTER(_T("faxocm_GetComponentInfName"),bRes);
  248. (*szInfFileName) = NULL;
  249. if (GetWindowsDirectory(szInfFileName,MAX_PATH)==0)
  250. {
  251. CALL_FAIL(SETUP_ERR,TEXT("GetWindowsDirectory"),GetLastError());
  252. bRes = FALSE;
  253. goto exit;
  254. }
  255. if (_tcslen(szInfFileName)+_tcslen(FAX_INF_PATH)>(MAX_PATH-1))
  256. {
  257. VERBOSE(SETUP_ERR,_T("MAX_PATH too short to create INF path"));
  258. bRes = FALSE;
  259. goto exit;
  260. }
  261. _tcscat(szInfFileName,FAX_INF_PATH);
  262. exit:
  263. return bRes;
  264. }
  265. ///////////////////////////////
  266. // faxocm_GetComponentInf
  267. //
  268. // Returns the handle to the
  269. // faxsetup.inf file.
  270. //
  271. // Params:
  272. // - void
  273. // Returns:
  274. // - Handle to faxsetup.inf file
  275. //
  276. HINF faxocm_GetComponentInf(void)
  277. {
  278. return prv_GVAR.Component.hInf;
  279. }
  280. ///////////////////////////////
  281. // faxocm_GetComponentSetupMode
  282. //
  283. // Returns the setup mode as
  284. // given to us by OC Manager.
  285. //
  286. // Params:
  287. // - void.
  288. // Returns:
  289. // - Setup mode as given to us by OC Manager
  290. //
  291. DWORD faxocm_GetComponentSetupMode(void)
  292. {
  293. return prv_GVAR.Component.dwSetupMode;
  294. }
  295. ///////////////////////////////
  296. // faxocm_GetComponentFlags
  297. //
  298. // Returns the flags as
  299. // given to us by OC Manager.
  300. //
  301. // Params:
  302. // - void
  303. // Returns:
  304. // - Flags as given to us by OC Manager
  305. //
  306. DWORDLONG faxocm_GetComponentFlags(void)
  307. {
  308. return prv_GVAR.Component.dwlFlags;
  309. }
  310. ///////////////////////////////
  311. // faxocm_GetComponentLangID
  312. //
  313. // Returns the Language ID
  314. // given to us by OC Manager.
  315. //
  316. // Params:
  317. // - void.
  318. // Returns:
  319. // - Language ID as given to us by OC Manager
  320. //
  321. UINT faxocm_GetComponentLangID(void)
  322. {
  323. return prv_GVAR.Component.uiLanguageID;
  324. }
  325. ///////////////////////////////
  326. // faxocm_GetComponentSourcePath
  327. //
  328. // Returns the Source Path
  329. // given to us by OC Manager.
  330. //
  331. // Params:
  332. // - pszSourcePath - OUT - buffer to hold source path
  333. // - dwNumBufChars - # of characters pszSourcePath can hold.
  334. // Returns:
  335. // - NO_ERROR on success.
  336. // - error code otherwise.
  337. //
  338. DWORD faxocm_GetComponentSourcePath(TCHAR *pszSourcePath,
  339. DWORD dwNumBufChars)
  340. {
  341. DWORD dwReturn = NO_ERROR;
  342. if ((pszSourcePath == NULL) ||
  343. (dwNumBufChars == 0))
  344. {
  345. return ERROR_INVALID_PARAMETER;
  346. }
  347. _tcsncpy(pszSourcePath, prv_GVAR.Component.szSourcePath, dwNumBufChars);
  348. return dwReturn;
  349. }
  350. ///////////////////////////////
  351. // faxocm_GetComponentUnattendFile
  352. //
  353. // Returns the Unattend Path
  354. // given to us by OC Manager.
  355. //
  356. // Params:
  357. // - pszUnattendFile - OUT - buffer to hold unattend path
  358. // - dwNumBufChars - # of characters pszSourcePath can hold.
  359. // Returns:
  360. // - NO_ERROR on success.
  361. // - error code otherwise.
  362. //
  363. DWORD faxocm_GetComponentUnattendFile(TCHAR *pszUnattendFile,
  364. DWORD dwNumBufChars)
  365. {
  366. DWORD dwReturn = NO_ERROR;
  367. if ((pszUnattendFile == NULL) ||
  368. (dwNumBufChars == 0))
  369. {
  370. return ERROR_INVALID_PARAMETER;
  371. }
  372. _tcsncpy(pszUnattendFile, prv_GVAR.Component.szUnattendFile, dwNumBufChars);
  373. return dwReturn;
  374. }
  375. ////////////////////////////////////
  376. // faxocm_GetComponentHelperRoutines
  377. //
  378. // Returns the pointer to the Helper
  379. // data and functions as given to us
  380. // by OC Manager.
  381. //
  382. // Params:
  383. // - void.
  384. // Returns:
  385. // - Ptr to helper routines as given to us by OC Manager.
  386. //
  387. OCMANAGER_ROUTINES* faxocm_GetComponentHelperRoutines(void)
  388. {
  389. return &prv_GVAR.Component.Helpers;
  390. }
  391. ////////////////////////////////////
  392. // faxocm_GetComponentExtraRoutines
  393. //
  394. // Returns the pointer to the Helper
  395. // data and functions as given to us
  396. // by OC Manager.
  397. //
  398. // Params:
  399. // - void
  400. // Returns:
  401. // - Ptr to extra info as given to us by OC Manager.
  402. //
  403. EXTRA_ROUTINES* faxocm_GetComponentExtraRoutines(void)
  404. {
  405. return &prv_GVAR.Component.Extras;
  406. }
  407. ////////////////////////////////////
  408. // faxocm_GetProductType
  409. //
  410. // Returns the product type as given
  411. // to us by OC Manager.
  412. //
  413. // Params:
  414. // - void.
  415. // Returns:
  416. // - Product type as given to us by OC Manager.
  417. //
  418. DWORD faxocm_GetProductType(void)
  419. {
  420. return prv_GVAR.Component.dwProductType;
  421. }
  422. ////////////////////////////////////
  423. // faxocm_GetVersionInfo
  424. //
  425. // Returns the version # as given
  426. // to us by OC Manager.
  427. //
  428. // Params:
  429. // - pdwExpectedOCManagerVersion - OUT - self explanatory.
  430. // - pdwCurrentOCManagerVersion - OUT - self explanatory.
  431. // Returns:
  432. // - void.
  433. //
  434. void faxocm_GetVersionInfo(DWORD *pdwExpectedOCManagerVersion,
  435. DWORD *pdwCurrentOCManagerVersion)
  436. {
  437. if (pdwExpectedOCManagerVersion)
  438. {
  439. *pdwExpectedOCManagerVersion =
  440. prv_GVAR.Component.dwExpectedOCManagerVersion;
  441. }
  442. if (pdwCurrentOCManagerVersion)
  443. {
  444. *pdwCurrentOCManagerVersion = prv_GVAR.dwCurrentOCManagerVersion;
  445. }
  446. return;
  447. }
  448. void faxocm_GetProductInfo(PRODUCT_SKU_TYPE* pInstalledProductSKU,
  449. DWORD* dwInstalledProductBuild)
  450. {
  451. if (pInstalledProductSKU)
  452. {
  453. *pInstalledProductSKU = prv_GVAR.Component.InstalledProductSKU;
  454. }
  455. if (dwInstalledProductBuild)
  456. {
  457. *dwInstalledProductBuild = prv_GVAR.Component.InstalledProductBuild;
  458. }
  459. }
  460. extern "C"
  461. BOOL FaxControl_DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/);
  462. ///////////////////////////////
  463. // DllMain
  464. //
  465. // DLL Entry Point
  466. //
  467. // Params:
  468. // hInstance - Instance handle
  469. // Reason - Reason for the entrypoint being called
  470. // Context - Context record
  471. //
  472. // Returns:
  473. // TRUE - Initialization succeeded
  474. // FALSE - Initialization failed
  475. //
  476. extern "C"
  477. DWORD DllMain(HINSTANCE hInst,
  478. DWORD Reason,
  479. LPVOID Context)
  480. {
  481. DBG_ENTER(_T("DllMain"));
  482. switch (Reason)
  483. {
  484. case DLL_PROCESS_ATTACH:
  485. // initialize our global variables
  486. memset(&prv_GVAR, 0, sizeof(prv_GVAR));
  487. prv_GVAR.hInstance = hInst;
  488. // Initialize Debug Support
  489. //
  490. VERBOSE(DBG_MSG,_T("FxsOcm.dll loaded - DLL_PROCESS_ATTACH"));
  491. DisableThreadLibraryCalls(hInst);
  492. break;
  493. case DLL_PROCESS_DETACH:
  494. // terminate Debug Support
  495. VERBOSE(DBG_MSG,_T("FxsOcm.dll unloaded - DLL_PROCESS_DETACH"));
  496. break;
  497. default:
  498. VERBOSE(DBG_MSG,_T("DllMain, received some weird 'Reason' ")
  499. _T("for this fn, Reason = %lu"), Reason);
  500. break;
  501. }
  502. //
  503. // Pass DllMain call to ATL supplied DllMain
  504. //
  505. return FaxControl_DllMain (hInst, Reason, Context);
  506. }
  507. ///////////////////////////////
  508. // FaxOcmSetupProc
  509. //
  510. // Entry point for OC Manager.
  511. //
  512. // The OC Manager calls this function
  513. // to drive this DLL.
  514. //
  515. // Params:
  516. // - pszComponentId - major component
  517. // - pszSubcomponentId - component found if user presses "Details"
  518. // - uiFunction - what stage of setup we are in.
  519. // - uiParam1 - dependent on uiFunction - could be anything.
  520. // - pParam2 - dependent on uiFunction - could be anything.
  521. //
  522. // Returns:
  523. // DWORD indicating error or success.
  524. //
  525. //
  526. DWORD_PTR FaxOcmSetupProc(IN LPWSTR pszComponentId,
  527. IN LPWSTR pszSubcomponentId,
  528. IN UINT uiFunction,
  529. IN UINT uiParam1,
  530. IN OUT PVOID pParam2)
  531. {
  532. DWORD_PTR rc = 0;
  533. DBG_ENTER( _T("FaxOcmSetupProc"),
  534. _T("%s - %s"),
  535. pszComponentId,
  536. pszSubcomponentId);
  537. VERBOSE(DBG_MSG, _T("FaxOcmSetup proc called with function '%s'"),
  538. fxocDbg_GetOcFunction(uiFunction));
  539. switch(uiFunction)
  540. {
  541. case OC_PREINITIALIZE:
  542. rc = prv_OnPreinitialize();
  543. break;
  544. case OC_INIT_COMPONENT:
  545. rc = prv_OnInitComponent(pszComponentId,
  546. (PSETUP_INIT_COMPONENT) pParam2);
  547. break;
  548. case OC_EXTRA_ROUTINES:
  549. rc = prv_OnExtraRoutines(pszComponentId, (PEXTRA_ROUTINES)pParam2);
  550. break;
  551. case OC_SET_LANGUAGE:
  552. rc = prv_OnSetLanguage(uiParam1);
  553. break;
  554. case OC_QUERY_IMAGE:
  555. // Argh! I hate casting handles to DWORDs
  556. rc = prv_OnQueryImage();
  557. break;
  558. case OC_REQUEST_PAGES:
  559. rc = prv_OnSetupRequestPages(pszComponentId,
  560. (WizardPagesType)uiParam1, (PSETUP_REQUEST_PAGES)pParam2);
  561. break;
  562. case OC_QUERY_CHANGE_SEL_STATE:
  563. rc = prv_OnQuerySelStateChange(pszComponentId,
  564. pszSubcomponentId,
  565. uiParam1,
  566. (UINT)((UINT_PTR)pParam2));
  567. break;
  568. case OC_CALC_DISK_SPACE:
  569. rc = prv_OnCalcDiskSpace(pszComponentId,
  570. pszSubcomponentId,
  571. uiParam1,
  572. pParam2);
  573. // sometimes the OC Manager gives us NULL subcomponent IDs,
  574. // so just ignore them.
  575. if (rc == ERROR_INVALID_PARAMETER)
  576. {
  577. rc = NO_ERROR;
  578. }
  579. break;
  580. case OC_QUEUE_FILE_OPS:
  581. SET_DEBUG_FLUSH(TRUE);
  582. rc = prv_OnQueueFileOps(pszComponentId,
  583. pszSubcomponentId,
  584. (HSPFILEQ)pParam2);
  585. SET_DEBUG_FLUSH(FALSE);
  586. // OC Manager calls us twice on this function. Once with a subcomponent ID
  587. // of NULL, and the second time with a subcomponent ID of "Fax".
  588. // Since we are going to be called a second time with a valid ID (i.e. "Fax")
  589. // disregard the first call and process the second call.
  590. if (rc == ERROR_INVALID_PARAMETER)
  591. {
  592. rc = NO_ERROR;
  593. }
  594. break;
  595. case OC_NOTIFICATION_FROM_QUEUE:
  596. rc = prv_OnNotificationFromQueue();
  597. break;
  598. case OC_QUERY_STEP_COUNT:
  599. rc = prv_OnQueryStepCount(pszComponentId, pszSubcomponentId);
  600. // OC Manager calls us twice on this function. Once with a subcomponent ID
  601. // of NULL, and the second time with a subcomponent ID of "Fax".
  602. // Since we are going to be called a second time with a valid ID (i.e. "Fax")
  603. // disregard the first call and process the second call.
  604. if (rc == ERROR_INVALID_PARAMETER)
  605. {
  606. rc = NO_ERROR;
  607. }
  608. break;
  609. case OC_COMPLETE_INSTALLATION:
  610. SET_DEBUG_FLUSH(TRUE);
  611. rc = prv_OnCompleteInstallation(pszComponentId, pszSubcomponentId);
  612. SET_DEBUG_FLUSH(FALSE);
  613. // OC Manager calls us twice on this function. Once with a subcomponent ID
  614. // of NULL, and the second time with a subcomponent ID of "Fax".
  615. // Since we are going to be called a second time with a valid ID (i.e. "Fax")
  616. // disregard the first call and process the second call.
  617. if (rc == ERROR_INVALID_PARAMETER)
  618. {
  619. rc = NO_ERROR;
  620. }
  621. break;
  622. case OC_CLEANUP:
  623. rc = prv_OnCleanup();
  624. // OC Manager calls us twice on this function. Once with a subcomponent ID
  625. // of NULL, and the second time with a subcomponent ID of "Fax".
  626. // Since we are going to be called a second time with a valid ID (i.e. "Fax")
  627. // disregard the first call and process the second call.
  628. if (rc == ERROR_INVALID_PARAMETER)
  629. {
  630. rc = NO_ERROR;
  631. }
  632. break;
  633. case OC_QUERY_STATE:
  634. rc = prv_OnQueryState(pszComponentId, pszSubcomponentId, uiParam1);
  635. break;
  636. case OC_NEED_MEDIA:
  637. rc = prv_OnNeedMedia();
  638. break;
  639. case OC_ABOUT_TO_COMMIT_QUEUE:
  640. rc = prv_OnAboutToCommitQueue(pszComponentId, pszSubcomponentId);
  641. break;
  642. case OC_QUERY_SKIP_PAGE:
  643. rc = prv_OnQuerySkipPage();
  644. break;
  645. case OC_WIZARD_CREATED:
  646. rc = prv_OnWizardCreated();
  647. break;
  648. default:
  649. rc = NO_ERROR;
  650. break;
  651. }
  652. return rc;
  653. }
  654. ///////////////////////////////
  655. // prv_ValidateVersion
  656. //
  657. // Validates that the version
  658. // of OC Manager this DLL was written
  659. // for is compatible with the version
  660. // of OC Manager that is currently
  661. // driving us.
  662. //
  663. // Params:
  664. // - pSetupInit - setup info as given to us by OC Manager.
  665. //
  666. // Returns:
  667. // - NO_ERROR if success.
  668. // - error code otherwise.
  669. //
  670. static DWORD prv_ValidateVersion(SETUP_INIT_COMPONENT *pSetupInit)
  671. {
  672. DWORD dwReturn = NO_ERROR;
  673. DBG_ENTER(TEXT("prv_ValidateVersion"), dwReturn);
  674. if (OCMANAGER_VERSION <= pSetupInit->OCManagerVersion)
  675. {
  676. // the version we expect is lower or the same than the version
  677. // than OC Manager understands. This means that a newer OC
  678. // Manager should still be able to drive older components, so
  679. // return the version we support to OC Manager, and it will decide
  680. // if it can drive this component or not.
  681. VERBOSE( DBG_MSG,
  682. _T("OC Manager version: 0x%x, ")
  683. _T("FaxOcm Expected Version: 0x%x, seems OK"),
  684. pSetupInit->OCManagerVersion,
  685. OCMANAGER_VERSION);
  686. pSetupInit->ComponentVersion = OCMANAGER_VERSION;
  687. }
  688. else
  689. {
  690. // we were written for a newer version of OC Manager than the
  691. // OC Manager driving this component. Fail.
  692. VERBOSE( SETUP_ERR,
  693. _T("OC Manager version: 0x%x, ")
  694. _T("FaxOcm Expected Version: 0x%x, unsupported, abort."),
  695. pSetupInit->OCManagerVersion,
  696. OCMANAGER_VERSION);
  697. dwReturn = ERROR_CALL_NOT_IMPLEMENTED;
  698. }
  699. return dwReturn;
  700. }
  701. ///////////////////////////////
  702. // prv_SetSetupData
  703. //
  704. // Initialize our global variable containing
  705. // the prv_Component_t information.
  706. //
  707. // Params:
  708. // - pszComponentId - id as it appears in SysOc.inf
  709. // - pSetupInit - OC Manager setup info.
  710. //
  711. // Returns:
  712. // - NO_ERROR if success.
  713. // - error code otherwise.
  714. //
  715. static DWORD prv_SetSetupData(const TCHAR *pszComponentId,
  716. SETUP_INIT_COMPONENT *pSetupInit)
  717. {
  718. DWORD dwReturn = NO_ERROR;
  719. DBG_ENTER(TEXT("prv_SetSetupData"), dwReturn, TEXT("%s"), pszComponentId);
  720. if ((pszComponentId == NULL) ||
  721. (pSetupInit == NULL))
  722. {
  723. return ERROR_INVALID_PARAMETER;
  724. }
  725. if (dwReturn == NO_ERROR)
  726. {
  727. memset(&prv_GVAR.Component, 0, sizeof(prv_GVAR.Component));
  728. prv_GVAR.dwCurrentOCManagerVersion = pSetupInit->OCManagerVersion;
  729. _tcsncpy(prv_GVAR.Component.szComponentID,
  730. pszComponentId,
  731. sizeof(prv_GVAR.Component.szComponentID) / sizeof(TCHAR));
  732. // szSubComponentID will be set in OC_QUERY_STATE, because
  733. // we don't have it now
  734. _tcsncpy(prv_GVAR.Component.szSourcePath,
  735. pSetupInit->SetupData.SourcePath,
  736. sizeof(prv_GVAR.Component.szSourcePath) / sizeof(TCHAR));
  737. _tcsncpy(prv_GVAR.Component.szUnattendFile,
  738. pSetupInit->SetupData.UnattendFile,
  739. sizeof(prv_GVAR.Component.szUnattendFile) / sizeof(TCHAR));
  740. prv_GVAR.Component.hInf = pSetupInit->ComponentInfHandle;
  741. prv_GVAR.Component.dwlFlags = pSetupInit->SetupData.OperationFlags;
  742. prv_GVAR.Component.dwProductType = pSetupInit->SetupData.ProductType;
  743. prv_GVAR.Component.dwSetupMode = pSetupInit->SetupData.SetupMode;
  744. prv_GVAR.Component.dwExpectedOCManagerVersion = OCMANAGER_VERSION;
  745. memcpy(&prv_GVAR.Component.Helpers,
  746. &pSetupInit->HelperRoutines,
  747. sizeof(prv_GVAR.Component.Helpers));
  748. }
  749. return dwReturn;
  750. }
  751. ///////////////////////////////
  752. // prv_GetSectionToProcess
  753. //
  754. // This determines if we are
  755. // clean installing, upgrading,
  756. // uninstalling, etc, and returns
  757. // the correct install section in the
  758. // faxsetup.inf to process.
  759. //
  760. // Params:
  761. // - pszCurrentSection
  762. // - pszSectionToProcess - OUT
  763. // - dwNumBufChars - # of characters pszSectionToProcess can hold.
  764. //
  765. // Returns:
  766. // - NO_ERROR if success.
  767. // - error code otherwise.
  768. //
  769. static DWORD prv_GetSectionToProcess(const TCHAR *pszCurrentSection,
  770. TCHAR *pszSectionToProcess,
  771. DWORD dwNumBufChars)
  772. {
  773. DWORD dwReturn = NO_ERROR;
  774. BOOL bInstall = TRUE;
  775. DBG_ENTER( TEXT("prv_GetSectionToProcess"),
  776. dwReturn,
  777. TEXT("%s"),
  778. pszCurrentSection);
  779. if ((pszCurrentSection == NULL) ||
  780. (pszSectionToProcess == NULL) ||
  781. (dwNumBufChars == 0))
  782. {
  783. return ERROR_INVALID_PARAMETER;
  784. }
  785. const TCHAR *pszInfKeyword = fxState_GetInstallType(pszCurrentSection);
  786. // okay, get that section's value, which will be an install/uninstall
  787. // section in the INF.
  788. if (pszInfKeyword)
  789. {
  790. dwReturn = fxocUtil_GetKeywordValue(pszCurrentSection,
  791. pszInfKeyword,
  792. pszSectionToProcess,
  793. dwNumBufChars);
  794. }
  795. else
  796. {
  797. dwReturn = ::GetLastError();
  798. VERBOSE(SETUP_ERR,
  799. _T("fxState_GetInstallType failed, rc = 0x%lx"),
  800. dwReturn);
  801. }
  802. return dwReturn;
  803. }
  804. ///////////////////////////////
  805. // prv_UpdateProgressBar
  806. //
  807. // Update the progress bar displayed in the
  808. // OC Manager dialog. This simply tells
  809. // the OC Manager to increment the dialog by
  810. // the specified # of ticks.
  811. //
  812. // Params:
  813. // - dwNumTicks - # of ticks to increment by.
  814. //
  815. // Returns:
  816. // - void
  817. //
  818. static void prv_UpdateProgressBar(DWORD dwNumTicks)
  819. {
  820. // update the progress bar based on the number of ticks the caller
  821. // would like to set.
  822. DBG_ENTER(TEXT("prv_UpdateProgressBar"), TEXT("%d"), dwNumTicks);
  823. if (prv_GVAR.Component.Helpers.TickGauge)
  824. {
  825. for (DWORD i = 0; i < dwNumTicks; i++)
  826. {
  827. prv_GVAR.Component.Helpers.TickGauge(
  828. prv_GVAR.Component.Helpers.OcManagerContext);
  829. }
  830. }
  831. }
  832. ///////////////////////////////
  833. // prv_OnPreinitialize()
  834. //
  835. // Handler for OC_PREINITIALIZE
  836. //
  837. // Params:
  838. // Returns:
  839. // - Either OCFLAG_UNICODE or
  840. // OCFLAG_ANSI, depending on
  841. // what this DLL supports.
  842. // This DLL supports both.
  843. static DWORD prv_OnPreinitialize(VOID)
  844. {
  845. return OCFLAG_UNICODE;
  846. }
  847. ///////////////////////////////
  848. // prv_OnInitComponent()
  849. //
  850. // Handler for OC_INIT_COMPONENT
  851. //
  852. // Params:
  853. // - pszComponentId - ID specified in SysOc.inf (probably "Fax")
  854. // - pSetupInitComponent - OC Manager Setup info
  855. //
  856. // Returns:
  857. // - NO_ERROR if success.
  858. // - error code otherwise.
  859. //
  860. static DWORD prv_OnInitComponent(LPCTSTR pszComponentId,
  861. SETUP_INIT_COMPONENT *pSetupInitComponent)
  862. {
  863. BOOL bSuccess = FALSE;
  864. DWORD dwReturn = NO_ERROR;
  865. UINT uiErrorAtLineNumber = 0;
  866. DBG_ENTER(TEXT("prv_OnInitComponent"), dwReturn, TEXT("%s"), pszComponentId);
  867. if ((pszComponentId == NULL) ||
  868. (pSetupInitComponent == NULL))
  869. {
  870. return ERROR_INVALID_PARAMETER;
  871. }
  872. // save the setup data.
  873. if (dwReturn == NO_ERROR)
  874. {
  875. dwReturn = prv_SetSetupData(pszComponentId, pSetupInitComponent);
  876. }
  877. // Initialize debug so that we can get the debug settings specified
  878. // in the faxocm.inf file.
  879. fxocDbg_Init((faxocm_GetComponentInf()));
  880. // Validate the version of OC Manager against the version we expect
  881. if (dwReturn == NO_ERROR)
  882. {
  883. dwReturn = prv_ValidateVersion(pSetupInitComponent);
  884. }
  885. // Notice we do NOT need to call 'SetupOpenAppendInfFile'
  886. // since OC Manager already appends the layout.inf to the hInf
  887. // for us.
  888. bSuccess = ::SetupOpenAppendInfFile(NULL, prv_GVAR.Component.hInf, NULL);
  889. if (!bSuccess)
  890. {
  891. dwReturn = ::GetLastError();
  892. VERBOSE( DBG_MSG,
  893. _T("SetupOpenAppendInfFile failed to append ")
  894. _T("the layout inf to the component Inf"));
  895. }
  896. //
  897. // initialize all the subsystems and Upgrade
  898. //
  899. if (dwReturn == NO_ERROR)
  900. {
  901. fxState_Init();
  902. fxocUtil_Init();
  903. fxocFile_Init();
  904. fxocMapi_Init();
  905. fxocPrnt_Init();
  906. fxocReg_Init();
  907. fxocSvc_Init();
  908. fxUnatnd_Init();
  909. fxocUpg_Init();
  910. }
  911. // set our initialized flag.
  912. if (dwReturn == NO_ERROR)
  913. {
  914. prv_GVAR.bInited = TRUE;
  915. VERBOSE( DBG_MSG,
  916. _T("OnInitComponent, ComponentID: '%s', ")
  917. _T("SourcePath: '%s', Component Inf Handle: 0x%0x"),
  918. prv_GVAR.Component.szComponentID,
  919. prv_GVAR.Component.szSourcePath,
  920. prv_GVAR.Component.hInf);
  921. }
  922. else
  923. {
  924. // XXX - OrenR - 03/23/2000
  925. // We should probably clean up here
  926. prv_GVAR.bInited = FALSE;
  927. VERBOSE( SETUP_ERR,
  928. _T("OnInitComponent, ComponentID: '%s'")
  929. _T("SourcePath: '%s', Component Inf Handle: 0x%0x ")
  930. _T("Failed to Append Layout.inf file, dwReturn = %lu"),
  931. prv_GVAR.Component.szComponentID,
  932. prv_GVAR.Component.szSourcePath,
  933. prv_GVAR.Component.hInf,
  934. dwReturn);
  935. }
  936. // Load product SKU and Version (if exists)
  937. HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP,FALSE,KEY_READ);
  938. if (hKey)
  939. {
  940. // write the SKU into the registry
  941. prv_GVAR.Component.InstalledProductSKU = PRODUCT_SKU_TYPE(GetRegistryDword(hKey,REGVAL_PRODUCT_SKU));
  942. prv_GVAR.Component.InstalledProductBuild = GetRegistryDword(hKey,REGVAL_PRODUCT_BUILD);
  943. RegCloseKey(hKey);
  944. }
  945. else
  946. {
  947. VERBOSE(DBG_MSG,_T("Failed to open fax setup registry, dwReturn = 0x%lx"),GetLastError());
  948. }
  949. // Output to debug our current setup state.
  950. fxState_DumpSetupState();
  951. return dwReturn;
  952. }
  953. ///////////////////////////////
  954. // prv_OnCleanup
  955. //
  956. // Called just before this
  957. // DLL is unloaded
  958. //
  959. // Params:
  960. // Returns:
  961. // - NO_ERROR if success.
  962. // - error code otherwise.
  963. //
  964. static DWORD prv_OnCleanup(void)
  965. {
  966. DWORD dwReturn = NO_ERROR;
  967. DBG_ENTER(TEXT("prv_OnCleanup"), dwReturn);
  968. // terminate the subsystems in reverse order from which they we
  969. // intialized.
  970. fxUnatnd_Term();
  971. fxocSvc_Term();
  972. fxocReg_Term();
  973. fxocPrnt_Term();
  974. fxocMapi_Term();
  975. fxocFile_Term();
  976. fxocUtil_Term();
  977. fxState_Term();
  978. // this closes the log file, so do this last...
  979. fxocDbg_Term();
  980. return dwReturn;
  981. }
  982. ///////////////////////////////
  983. // prv_OnCalcDiskSpace
  984. //
  985. // Handler for OC_CALC_DISK_SPACE
  986. // OC Manager calls this function
  987. // so that it can determine how
  988. // much disk space we require.
  989. //
  990. // Params:
  991. // - pszComponentId - From SysOc.inf (usually "fax")
  992. // - pszSubcomponentId -
  993. // - addComponent - non-zero if installing, 0 if uninstalling
  994. // - dspace - handle to disk space abstraction.
  995. //
  996. // Returns:
  997. // - NO_ERROR if success.
  998. // - error code otherwise.
  999. //
  1000. static DWORD prv_OnCalcDiskSpace(LPCTSTR pszComponentId,
  1001. LPCTSTR pszSubcomponentId,
  1002. DWORD addComponent,
  1003. HDSKSPC dspace)
  1004. {
  1005. DWORD dwReturn = NO_ERROR;
  1006. DBG_ENTER( TEXT("prv_OnCalcDiskSpace"),
  1007. dwReturn,
  1008. TEXT("%s - %s"),
  1009. pszComponentId,
  1010. pszSubcomponentId);
  1011. if (dwReturn == NO_ERROR)
  1012. {
  1013. dwReturn = fxocFile_CalcDiskSpace(pszSubcomponentId,
  1014. addComponent,
  1015. dspace);
  1016. }
  1017. return dwReturn;
  1018. }
  1019. ///////////////////////////////
  1020. // prv_OnQueueFileOps
  1021. //
  1022. // Handler for OC_QUEUE_FILE_OPS
  1023. // This fn will queue all the files
  1024. // specified for copying and deleting
  1025. // in the INF install section.
  1026. //
  1027. // Params:
  1028. // - pszCompnentId
  1029. // - pszSubcomponentId
  1030. // - hQueue - Handle to queue abstraction.
  1031. // Returns:
  1032. // - NO_ERROR if success.
  1033. // - error code otherwise.
  1034. //
  1035. static DWORD prv_OnQueueFileOps(LPCTSTR pszComponentId,
  1036. LPCTSTR pszSubcomponentId,
  1037. HSPFILEQ hQueue)
  1038. {
  1039. DWORD dwReturn = NO_ERROR;
  1040. BOOL bInstallSelected = FALSE;
  1041. BOOL bSelectionStateChanged = FALSE;
  1042. DBG_ENTER( TEXT("prv_OnQueueFileOps"),
  1043. dwReturn,
  1044. TEXT("%s - %s"),
  1045. pszComponentId,
  1046. pszSubcomponentId);
  1047. if ((pszComponentId == NULL) ||
  1048. (pszSubcomponentId == NULL) ||
  1049. (hQueue == NULL))
  1050. {
  1051. return ERROR_INVALID_PARAMETER;
  1052. }
  1053. // save our Queue Handle.
  1054. prv_GVAR.Component.hQueue = hQueue;
  1055. dwReturn = faxocm_HasSelectionStateChanged(pszSubcomponentId,
  1056. &bSelectionStateChanged,
  1057. &bInstallSelected,
  1058. NULL);
  1059. if (dwReturn != NO_ERROR)
  1060. {
  1061. VERBOSE( SETUP_ERR,
  1062. _T("HasSelectionStateChanged failed, rc = 0x%lx"),
  1063. dwReturn);
  1064. return dwReturn;
  1065. }
  1066. // our selection state has changed, install or uninstall based on
  1067. // the current selection state.
  1068. if (bSelectionStateChanged == TRUE)
  1069. {
  1070. TCHAR szSectionToProcess[255 + 1] = {0};
  1071. VERBOSE( DBG_MSG,
  1072. _T("Beginning Queuing of Files: ComponentID: '%s', ")
  1073. _T("SubComponentID: '%s', Selection State has ")
  1074. _T("changed to %lu ==> Installing/Uninstalling"),
  1075. pszComponentId, pszSubcomponentId,
  1076. bInstallSelected);
  1077. if (dwReturn == NO_ERROR)
  1078. {
  1079. dwReturn = prv_GetSectionToProcess(
  1080. pszSubcomponentId,
  1081. szSectionToProcess,
  1082. sizeof(szSectionToProcess) / sizeof(TCHAR));
  1083. if (dwReturn != NO_ERROR)
  1084. {
  1085. VERBOSE(SETUP_ERR,
  1086. _T("Failed to get section to process ")
  1087. _T("rc = 0x%lx"),
  1088. dwReturn);
  1089. }
  1090. }
  1091. if (dwReturn == NO_ERROR)
  1092. {
  1093. if (bInstallSelected)
  1094. {
  1095. //
  1096. // Install
  1097. //
  1098. //
  1099. // Prepare for the Upgrade : Save different Settings
  1100. //
  1101. dwReturn = fxocUpg_SaveSettings();
  1102. if (dwReturn != NO_ERROR)
  1103. {
  1104. VERBOSE(DBG_WARNING,
  1105. _T("Failed to prepare for the Upgrade : save settings during upgrade to Windows-XP Fax. ")
  1106. _T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
  1107. dwReturn);
  1108. dwReturn = NO_ERROR;
  1109. }
  1110. // install files
  1111. dwReturn = fxocFile_Install(pszSubcomponentId,
  1112. szSectionToProcess);
  1113. if (dwReturn != NO_ERROR)
  1114. {
  1115. VERBOSE(DBG_MSG,
  1116. _T("Failed Fax File operations, ")
  1117. _T("for subcomponent '%s', section '%s', ")
  1118. _T("rc = 0x%lx"), pszSubcomponentId,
  1119. szSectionToProcess, dwReturn);
  1120. }
  1121. }
  1122. else
  1123. {
  1124. //
  1125. // Uninstall
  1126. //
  1127. dwReturn = prv_UninstallFax(pszSubcomponentId,
  1128. szSectionToProcess);
  1129. }
  1130. }
  1131. }
  1132. else
  1133. {
  1134. VERBOSE(DBG_MSG,
  1135. _T("End Queuing of Files, ComponentID: '%s', ")
  1136. _T("SubComponentID: '%s', Selection State has NOT ")
  1137. _T("changed, doing nothing, bInstallSelected=%lu"),
  1138. pszComponentId, pszSubcomponentId,
  1139. bInstallSelected);
  1140. }
  1141. return dwReturn;
  1142. }
  1143. ///////////////////////////////
  1144. // prv_OnCompleteInstallation
  1145. //
  1146. // Handler for OC_COMPLETE_INSTALLATION.
  1147. // This is called after the queue is
  1148. // committed. It is here that we
  1149. // make our registery changes, add
  1150. // fax service, and create the fax printer.
  1151. //
  1152. // Params:
  1153. // - pszComponentId
  1154. // - pszSubcomponentId.
  1155. // Returns:
  1156. // - NO_ERROR if success.
  1157. // - error code otherwise.
  1158. //
  1159. static DWORD prv_OnCompleteInstallation(LPCTSTR pszComponentId,
  1160. LPCTSTR pszSubcomponentId)
  1161. {
  1162. BOOL bSelectionStateChanged = FALSE;
  1163. BOOL bInstallSelected = FALSE;
  1164. DWORD dwReturn = NO_ERROR;
  1165. DBG_ENTER( TEXT("prv_OnCompleteInstallation"),
  1166. dwReturn,
  1167. TEXT("%s - %s"),
  1168. pszComponentId,
  1169. pszSubcomponentId);
  1170. // Do post-installation processing in the cleanup section.
  1171. // This way we know all components queued for installation
  1172. // have beein installed before we do our stuff.
  1173. if (!pszSubcomponentId || !*pszSubcomponentId)
  1174. {
  1175. return ERROR_INVALID_PARAMETER;
  1176. }
  1177. dwReturn = faxocm_HasSelectionStateChanged(pszSubcomponentId,
  1178. &bSelectionStateChanged,
  1179. &bInstallSelected,
  1180. NULL);
  1181. if (dwReturn != NO_ERROR)
  1182. {
  1183. VERBOSE(SETUP_ERR,
  1184. _T("HasSelectionStateChanged failed, rc = 0x%lx"),
  1185. dwReturn);
  1186. return dwReturn;
  1187. }
  1188. // if our selection state has changed, then install/uninstall
  1189. if (bSelectionStateChanged)
  1190. {
  1191. TCHAR szSectionToProcess[255 + 1] = {0};
  1192. //
  1193. // Fake report to prevent re-entrancy
  1194. //
  1195. g_InstallReportType = bInstallSelected ? REPORT_FAX_UNINSTALLED : REPORT_FAX_INSTALLED;
  1196. dwReturn = prv_GetSectionToProcess(
  1197. pszSubcomponentId,
  1198. szSectionToProcess,
  1199. sizeof(szSectionToProcess) / sizeof(TCHAR));
  1200. if (dwReturn == NO_ERROR)
  1201. {
  1202. // if the Install checkbox is selected, then install
  1203. if (bInstallSelected)
  1204. {
  1205. dwReturn = prv_CompleteFaxInstall(pszSubcomponentId,
  1206. szSectionToProcess);
  1207. }
  1208. else
  1209. {
  1210. // if the install checkbox is not selected, then uninstall.
  1211. dwReturn = prv_CompleteFaxUninstall(pszSubcomponentId,
  1212. szSectionToProcess);
  1213. }
  1214. }
  1215. else
  1216. {
  1217. VERBOSE(SETUP_ERR,
  1218. _T("Failed to get section to process ")
  1219. _T("rc = 0x%lx"), dwReturn);
  1220. }
  1221. //
  1222. // Report real installation state in case someone asks
  1223. //
  1224. g_InstallReportType = REPORT_FAX_DETECT;
  1225. if (ERROR_SUCCESS == dwReturn)
  1226. {
  1227. //
  1228. // Installation / Uninstallation is successfully complete.
  1229. // Notify the 'Printers and Faxes' folder it should refresh itself.
  1230. //
  1231. RefreshPrintersAndFaxesFolder();
  1232. }
  1233. }
  1234. return dwReturn;
  1235. } // prv_OnCompleteInstallation
  1236. ///////////////////////////////
  1237. // prv_CompleteFaxInstall
  1238. //
  1239. // Called by prv_OnCompleteInstallation
  1240. // this function creates the program
  1241. // groups/shortcuts, registry entries,
  1242. // fax service, fax printer, etc.
  1243. //
  1244. // Params:
  1245. // - pszSubcomponentId
  1246. // - pszSectionToProcess
  1247. //
  1248. static DWORD prv_CompleteFaxInstall(const TCHAR *pszSubcomponentId,
  1249. const TCHAR *pszSectionToProcess)
  1250. {
  1251. DWORD dwReturn = NO_ERROR;
  1252. fxState_UpgradeType_e UpgradeType = FXSTATE_UPGRADE_TYPE_NONE;
  1253. DBG_ENTER( TEXT("prv_CompleteFaxInstall"),
  1254. dwReturn,
  1255. TEXT("%s - %s"),
  1256. pszSubcomponentId,
  1257. pszSectionToProcess);
  1258. if ((pszSubcomponentId == NULL) ||
  1259. (pszSectionToProcess == NULL))
  1260. {
  1261. return ERROR_INVALID_PARAMETER;
  1262. }
  1263. UpgradeType = fxState_IsUpgrade();
  1264. // Create Program Group/Shortcuts
  1265. // We create the shortcuts first because at the very worst case, if we
  1266. // fail everything else, the applications should be somewhat robust enough
  1267. // to be able to correct or notify the user of problems that could not
  1268. // be notified during install.
  1269. VERBOSE(DBG_MSG,_T("Creating program groups and shortcuts..."));
  1270. dwReturn = fxocLink_Install(pszSubcomponentId,pszSectionToProcess);
  1271. if (dwReturn != NO_ERROR)
  1272. {
  1273. VERBOSE(SETUP_ERR,
  1274. _T("Failed to create program ")
  1275. _T("groups/shortcuts for fax. This is a non-fatal ")
  1276. _T("error, continuing fax install...rc=0x%lx"),
  1277. dwReturn);
  1278. dwReturn = NO_ERROR;
  1279. }
  1280. prv_UpdateProgressBar(1);
  1281. // Load the unattended data if applicable
  1282. if ((fxState_IsUnattended()) || (UpgradeType == FXSTATE_UPGRADE_TYPE_WIN9X))
  1283. {
  1284. VERBOSE(DBG_MSG,
  1285. _T("CompleteInstall, state is unattended ")
  1286. _T("or we are upgrading from Win9X, ")
  1287. _T("caching unattended data from INF file"));
  1288. // load our unattended data
  1289. dwReturn = fxUnatnd_LoadUnattendedData();
  1290. if (dwReturn == NO_ERROR)
  1291. {
  1292. // set up the fax printer name
  1293. fxocPrnt_SetFaxPrinterName(fxUnatnd_GetPrinterName());
  1294. fxocPrnt_SetFaxPrinterShared(fxUnatnd_GetIsPrinterShared());
  1295. }
  1296. else
  1297. {
  1298. VERBOSE(SETUP_ERR,
  1299. _T("Failed to load unattended data, ")
  1300. _T("non-fatal error, continuing anyway...")
  1301. _T("rc = 0x%lx"), dwReturn);
  1302. dwReturn = NO_ERROR;
  1303. }
  1304. }
  1305. prv_UpdateProgressBar(1);
  1306. // install the registry settings as specified in the INF file
  1307. VERBOSE(DBG_MSG,_T("Installing Registry..."));
  1308. dwReturn = fxocReg_Install(pszSubcomponentId,pszSectionToProcess);
  1309. if (dwReturn != NO_ERROR)
  1310. {
  1311. VERBOSE(SETUP_ERR,
  1312. _T("Failed to install registry settings ")
  1313. _T("for fax installation. This is a fatal ")
  1314. _T("error, abandoning fax install...rc=0x%lx"),
  1315. dwReturn);
  1316. goto cleanup;
  1317. }
  1318. prv_UpdateProgressBar(1);
  1319. // migrate existing SBS registry
  1320. if (UpgradeType == FXSTATE_UPGRADE_TYPE_W2K)
  1321. {
  1322. VERBOSE(DBG_MSG,_T("Migrating existing registry..."));
  1323. dwReturn = fxocUpg_MoveRegistry();
  1324. if (dwReturn != NO_ERROR)
  1325. {
  1326. VERBOSE(SETUP_ERR,
  1327. _T("Failed to migrate existing registry.")
  1328. _T("This is a non-fatal ")
  1329. _T("error, continuing fax install...rc=0x%lx"),
  1330. dwReturn);
  1331. dwReturn = NO_ERROR;
  1332. }
  1333. }
  1334. prv_UpdateProgressBar(1);
  1335. // Install Fax Printer/Monitor support
  1336. // Create a fax printer and monitor
  1337. VERBOSE(DBG_MSG,_T("Installing Fax Monitor and printer drivers..."));
  1338. dwReturn = fxocPrnt_Install(pszSubcomponentId,pszSectionToProcess);
  1339. if (dwReturn != NO_ERROR)
  1340. {
  1341. VERBOSE(SETUP_ERR,
  1342. _T("Failed to install fax printer drivers and ")
  1343. _T("fax monitor. This is a fatal ")
  1344. _T("error, abandoning fax installation...rc=0x%lx"),
  1345. dwReturn);
  1346. goto cleanup;
  1347. }
  1348. VERBOSE(DBG_MSG,_T("Installing Fax printer..."));
  1349. dwReturn = fxocPrnt_InstallPrinter();
  1350. if (dwReturn != NO_ERROR)
  1351. {
  1352. VERBOSE(SETUP_ERR,
  1353. _T("Failed to install fax printer. This is a fatal ")
  1354. _T("error, abandoning fax installation...rc=0x%lx"),
  1355. dwReturn);
  1356. goto cleanup;
  1357. }
  1358. prv_UpdateProgressBar(1);
  1359. // Create fax directories
  1360. dwReturn = fxocFile_ProcessDirectories(pszSectionToProcess,INF_KEYWORD_CREATEDIR);
  1361. if (dwReturn != NO_ERROR)
  1362. {
  1363. VERBOSE(SETUP_ERR,
  1364. _T("Failed to install create directories ")
  1365. _T("for fax. This is a fatal ")
  1366. _T("error, abandoning fax installation...rc=0x%lx"),
  1367. dwReturn);
  1368. goto cleanup;
  1369. }
  1370. prv_UpdateProgressBar(1);
  1371. // Install Services
  1372. // Install any services as specified in the section of the INF file
  1373. VERBOSE(DBG_MSG,_T("Installing Fax Service..."));
  1374. dwReturn = fxocSvc_Install(pszSubcomponentId,pszSectionToProcess);
  1375. if (dwReturn != NO_ERROR)
  1376. {
  1377. VERBOSE(SETUP_ERR,
  1378. _T("Failed to install fax service. ")
  1379. _T("This is a fatal ")
  1380. _T("error, abandoning fax install...rc=0x%lx"),
  1381. dwReturn);
  1382. goto cleanup;
  1383. }
  1384. // Try installing the fax printer another time.
  1385. // If first attempt succeeded, this will return without doing anything.
  1386. // This is because BrookTrout TSP exposes TAPI devices only when it sees the Fax
  1387. // service installed.
  1388. VERBOSE(DBG_MSG,_T("Installing Fax printer..."));
  1389. dwReturn = fxocPrnt_InstallPrinter();
  1390. if (dwReturn != NO_ERROR)
  1391. {
  1392. VERBOSE(SETUP_ERR,
  1393. _T("Failed to install fax printer. This is a fatal ")
  1394. _T("error, abandoning fax installation...rc=0x%lx"),
  1395. dwReturn);
  1396. goto cleanup;
  1397. }
  1398. prv_UpdateProgressBar(1);
  1399. // Install Exchange Support
  1400. VERBOSE(DBG_MSG,_T("Installing Fax MAPI extension..."));
  1401. dwReturn = fxocMapi_Install(pszSubcomponentId,pszSectionToProcess);
  1402. if (dwReturn != NO_ERROR)
  1403. {
  1404. VERBOSE(SETUP_ERR,
  1405. _T("Failed to install exchange support for ")
  1406. _T("fax. This is a fatal ")
  1407. _T("error, abandoning fax installation...rc=0x%lx"),
  1408. dwReturn);
  1409. goto cleanup;
  1410. }
  1411. prv_UpdateProgressBar(1);
  1412. // Delete Directories at upgrade
  1413. VERBOSE(DBG_MSG, _T("Creating directories..."));
  1414. //
  1415. // At upgrade, before deleting of directories, take care of their content
  1416. //
  1417. dwReturn = fxocUpg_MoveFiles();
  1418. if (dwReturn != NO_ERROR)
  1419. {
  1420. VERBOSE(DBG_WARNING,
  1421. _T("Failed to clear previous fax directories. ")
  1422. _T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
  1423. dwReturn);
  1424. dwReturn = NO_ERROR;
  1425. }
  1426. dwReturn = fxocFile_ProcessDirectories(pszSectionToProcess,INF_KEYWORD_DELDIR);
  1427. if (dwReturn != NO_ERROR)
  1428. {
  1429. VERBOSE(DBG_WARNING,
  1430. _T("Failed to delete directories. ")
  1431. _T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
  1432. dwReturn);
  1433. dwReturn = NO_ERROR;
  1434. }
  1435. prv_UpdateProgressBar(1);
  1436. // create/delete the Shares
  1437. VERBOSE(DBG_MSG, _T("Create shares..."));
  1438. dwReturn = fxocFile_ProcessShares(pszSectionToProcess);
  1439. if (dwReturn != NO_ERROR)
  1440. {
  1441. VERBOSE(SETUP_ERR,
  1442. _T("Failed to install shares ")
  1443. _T("for fax. This is a fatal ")
  1444. _T("error, abandoning fax installation...rc=0x%lx"),
  1445. dwReturn);
  1446. goto cleanup;
  1447. }
  1448. if ((fxState_IsUnattended()) || (UpgradeType == FXSTATE_UPGRADE_TYPE_WIN9X))
  1449. {
  1450. VERBOSE(DBG_MSG, _T("Saving unattended data to registry"));
  1451. //
  1452. // this will read from the unattended file list of the uninstalled fax applications
  1453. // and update the fxocUpg.prvData, which is used later, in fxocUpg_GetUpgradeApp()
  1454. // to decide whether or not to show the "Where Did My Fax Go" shortcut.
  1455. //
  1456. dwReturn = fxUnatnd_SaveUnattendedData();
  1457. if (dwReturn != NO_ERROR)
  1458. {
  1459. VERBOSE(SETUP_ERR,
  1460. _T("Failed to save unattended data")
  1461. _T("to the registry. This is a non-fatal ")
  1462. _T("error, continuing fax install...rc=0x%lx"),
  1463. dwReturn);
  1464. dwReturn = NO_ERROR;
  1465. }
  1466. }
  1467. prv_ShowUninstalledFaxShortcut();
  1468. prv_UpdateProgressBar(1);
  1469. dwReturn = prv_NotifyStatusMonitor(FAX_STARTUP_TIMER_ID);
  1470. if (dwReturn != NO_ERROR)
  1471. {
  1472. VERBOSE(SETUP_ERR,
  1473. _T("Failed to notify Status Monitor.")
  1474. _T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
  1475. dwReturn);
  1476. dwReturn = NO_ERROR;
  1477. }
  1478. prv_UpdateProgressBar(1);
  1479. //
  1480. // Complete the Upgrade : Restore settings that were saved at Preparation stage
  1481. //
  1482. dwReturn = fxocUpg_RestoreSettings();
  1483. if (dwReturn != NO_ERROR)
  1484. {
  1485. VERBOSE(DBG_WARNING,
  1486. _T("Failed to restore previous fax applications settings after their uninstall. ")
  1487. _T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
  1488. dwReturn);
  1489. dwReturn = NO_ERROR;
  1490. }
  1491. prv_UpdateProgressBar(1);
  1492. cleanup:
  1493. if (dwReturn != NO_ERROR)
  1494. {
  1495. VERBOSE(SETUP_ERR,
  1496. _T("Complete Fax Install failed, rc = 0x%lx"),
  1497. dwReturn);
  1498. // now we attemp a rollback, if we're here, things are quite bad as it is.
  1499. // we'll try to remove shortcuts, remove the service, etc.
  1500. // the files will remain on the machine.
  1501. TCHAR szUninstallSection[MAX_PATH] = {0};
  1502. if( fxocUtil_GetUninstallSection(pszSubcomponentId,szUninstallSection,MAX_PATH)==NO_ERROR)
  1503. {
  1504. VERBOSE(DBG_MSG,_T("Performing rollback, using section %s."),szUninstallSection);
  1505. if (prv_UninstallFax(pszSubcomponentId,szUninstallSection)==NO_ERROR)
  1506. {
  1507. VERBOSE(DBG_MSG,_T("Rollback (prv_UninstallFax) successful..."));
  1508. }
  1509. else
  1510. {
  1511. // not setting dwReturn explicitly to preserve to original cause for failure.
  1512. VERBOSE(SETUP_ERR,_T("Rollback (prv_UninstallFax) failed, rc = 0x%lx"),GetLastError());
  1513. }
  1514. if (prv_CompleteFaxUninstall(pszSubcomponentId,szUninstallSection)==NO_ERROR)
  1515. {
  1516. VERBOSE(DBG_MSG,_T("Rollback (prv_CompleteFaxUninstall) successful..."));
  1517. }
  1518. else
  1519. {
  1520. // not setting dwReturn explicitly to preserve to original cause for failure.
  1521. VERBOSE(SETUP_ERR,_T("Rollback (prv_CompleteFaxUninstall) failed, rc = 0x%lx"),GetLastError());
  1522. }
  1523. }
  1524. else
  1525. {
  1526. // not setting dwReturn explicitly to preserve to original cause for failure.
  1527. VERBOSE(SETUP_ERR,_T("fxocUtil_GetUninstallSection failed, rc = 0x%lx"),GetLastError());
  1528. }
  1529. }
  1530. return dwReturn;
  1531. } // prv_CompleteFaxInstall
  1532. ///////////////////////////////
  1533. // prv_CompleteFaxUninstall
  1534. //
  1535. // Called by prv_OnCompleteInstallation
  1536. // to uninstall the fax. Since most
  1537. // of the work is done before we even
  1538. // queue our files to delete, the only
  1539. // thing we really do here is remove the
  1540. // program group/shortcuts.
  1541. //
  1542. // Params:
  1543. // - pszSubcomponentId
  1544. // - pszSectionToProcess
  1545. // Returns:
  1546. // - NO_ERROR on success.
  1547. // - error code otherwise.
  1548. //
  1549. static DWORD prv_CompleteFaxUninstall(const TCHAR *pszSubcomponentId,
  1550. const TCHAR *pszSectionToProcess)
  1551. {
  1552. DWORD dwReturn = NO_ERROR;
  1553. DBG_ENTER( TEXT("prv_CompleteFaxUninstall"),
  1554. dwReturn,
  1555. TEXT("%s - %s"),
  1556. pszSubcomponentId,
  1557. pszSectionToProcess);
  1558. if ((pszSubcomponentId == NULL) ||
  1559. (pszSectionToProcess == NULL))
  1560. {
  1561. return ERROR_INVALID_PARAMETER;
  1562. }
  1563. // Uninstall directories
  1564. if (dwReturn == NO_ERROR)
  1565. {
  1566. dwReturn = fxocFile_ProcessDirectories(pszSectionToProcess,INF_KEYWORD_DELDIR);
  1567. if (dwReturn != NO_ERROR)
  1568. {
  1569. VERBOSE(SETUP_ERR,
  1570. _T("Failed to uninstall directories ")
  1571. _T("This is a non-fatal error, ")
  1572. _T("continuing with uninstall attempt...rc=0x%lx"),
  1573. dwReturn);
  1574. dwReturn = NO_ERROR;
  1575. }
  1576. }
  1577. // uninstall subsystems in the reverse order they were installed in.
  1578. if (dwReturn == NO_ERROR)
  1579. {
  1580. // notice we ignore the return codes, we will attempt to completely
  1581. // uninstall even if something fails to uninstall.
  1582. // Remove Program Group/Shortcuts
  1583. dwReturn = fxocLink_Uninstall(pszSubcomponentId,
  1584. pszSectionToProcess);
  1585. }
  1586. return dwReturn;
  1587. } // prv_CompleteFaxUninstall
  1588. ///////////////////////////////
  1589. // prv_UninstallFax
  1590. //
  1591. // Uninstalls fax from the user's
  1592. // computer. This does everything
  1593. // except the program group delete. It
  1594. // will remove the fax printer,
  1595. // fax service, exchange updates,
  1596. // registry, and file deletion.
  1597. static DWORD prv_UninstallFax(const TCHAR *pszSubcomponentId,
  1598. const TCHAR *pszUninstallSection)
  1599. {
  1600. DWORD dwReturn = NO_ERROR;
  1601. DBG_ENTER( TEXT("prv_UninstallFax"),
  1602. dwReturn,
  1603. TEXT("%s - %s"),
  1604. pszSubcomponentId,
  1605. pszUninstallSection);
  1606. if ((pszSubcomponentId == NULL) ||
  1607. (pszUninstallSection == NULL))
  1608. {
  1609. return ERROR_INVALID_PARAMETER;
  1610. }
  1611. // Notice when we uninstall our files, we want to clean up
  1612. // everything else first, to ensure that we can successfully
  1613. // remove the files.
  1614. // Uninstall shares
  1615. if (dwReturn == NO_ERROR)
  1616. {
  1617. dwReturn = fxocFile_ProcessShares(pszUninstallSection);
  1618. if (dwReturn != NO_ERROR)
  1619. {
  1620. VERBOSE(SETUP_ERR,
  1621. _T("Failed to uninstall shares ")
  1622. _T("This is a non-fatal error, ")
  1623. _T("continuing with uninstall attempt...rc=0x%lx"),
  1624. dwReturn);
  1625. dwReturn = NO_ERROR;
  1626. }
  1627. }
  1628. // Uninstall Fax Printer/Monitor support
  1629. if (dwReturn == NO_ERROR)
  1630. {
  1631. dwReturn = fxocPrnt_Uninstall(pszSubcomponentId,
  1632. pszUninstallSection);
  1633. if (dwReturn != NO_ERROR)
  1634. {
  1635. VERBOSE(SETUP_ERR,
  1636. _T("Failed to uninstall fax printer ")
  1637. _T("and monitor. This is a non-fatal error, ")
  1638. _T("continuing with uninstall attempt...rc=0x%lx"),
  1639. dwReturn);
  1640. dwReturn = NO_ERROR;
  1641. }
  1642. }
  1643. // Uninstall Exchange Support
  1644. if (dwReturn == NO_ERROR)
  1645. {
  1646. fxocMapi_Uninstall(pszSubcomponentId,pszUninstallSection);
  1647. if (dwReturn != NO_ERROR)
  1648. {
  1649. VERBOSE(SETUP_ERR,
  1650. _T("Failed to uninstall fax exchange support")
  1651. _T("This is a non-fatal error, ")
  1652. _T("continuing with uninstall attempt...rc=0x%lx"),
  1653. dwReturn);
  1654. dwReturn = NO_ERROR;
  1655. }
  1656. }
  1657. // we have to tell the status monitor to shut itself down before
  1658. // we shut down the service, since it calls FaxUnregisterEvents...
  1659. if (dwReturn == NO_ERROR)
  1660. {
  1661. dwReturn = prv_NotifyStatusMonitor(FAX_SHUTDOWN_TIMER_ID);
  1662. if (dwReturn != NO_ERROR)
  1663. {
  1664. VERBOSE(SETUP_ERR,
  1665. _T("Failed to notify Status Monitor.")
  1666. _T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
  1667. dwReturn);
  1668. dwReturn = NO_ERROR;
  1669. }
  1670. }
  1671. // Notice we uninstall our service first before uninstalling
  1672. // the files.
  1673. if (dwReturn == NO_ERROR)
  1674. {
  1675. fxocSvc_Uninstall(pszSubcomponentId,
  1676. pszUninstallSection);
  1677. if (dwReturn != NO_ERROR)
  1678. {
  1679. VERBOSE(SETUP_ERR,
  1680. _T("Failed to uninstall fax service. ")
  1681. _T("This is a non-fatal error, ")
  1682. _T("continuing with uninstall attempt...rc=0x%lx"),
  1683. dwReturn);
  1684. dwReturn = NO_ERROR;
  1685. }
  1686. }
  1687. if (dwReturn == NO_ERROR)
  1688. {
  1689. // Uninstall Registry
  1690. fxocReg_Uninstall(pszSubcomponentId,
  1691. pszUninstallSection);
  1692. if (dwReturn != NO_ERROR)
  1693. {
  1694. VERBOSE(SETUP_ERR,
  1695. _T("Failed to uninstall fax registry. ")
  1696. _T("This is a non-fatal error, ")
  1697. _T("continuing with uninstall attempt...rc=0x%lx"),
  1698. dwReturn);
  1699. dwReturn = NO_ERROR;
  1700. }
  1701. }
  1702. if (dwReturn == NO_ERROR)
  1703. {
  1704. // uninstall files
  1705. dwReturn = fxocFile_Uninstall(pszSubcomponentId,
  1706. pszUninstallSection);
  1707. if (dwReturn != NO_ERROR)
  1708. {
  1709. VERBOSE(SETUP_ERR,
  1710. _T("Failed to uninstall fax files. ")
  1711. _T("This is a non-fatal error, ")
  1712. _T("continuing with uninstall attempt...rc=0x%lx"),
  1713. dwReturn);
  1714. dwReturn = NO_ERROR;
  1715. }
  1716. }
  1717. return dwReturn;
  1718. }
  1719. ///////////////////////////////
  1720. // prv_OnNotificationFromQueue
  1721. //
  1722. // Handler for OC_NOTIFICATION_FROM_QUEUE
  1723. //
  1724. // NOTE: although this notification is defined,
  1725. // it is currently unimplemented in oc manager
  1726. //
  1727. static DWORD prv_OnNotificationFromQueue(void)
  1728. {
  1729. return NO_ERROR;
  1730. }
  1731. ///////////////////////////////
  1732. // prv_OnQueryStepCount
  1733. //
  1734. // This query by the OC Manager
  1735. // determines how many "ticks"
  1736. // on the progress bar we would
  1737. // like shown.
  1738. //
  1739. // We only update the progress
  1740. // bar during an install (for
  1741. // no good reason!). It seems
  1742. // that all OC components do this.
  1743. //
  1744. // Params:
  1745. // - pszComponentId
  1746. // - pszSubcomponentId
  1747. // Returns:
  1748. // - NO_ERROR on success
  1749. // - error code otherwise.
  1750. //
  1751. static DWORD prv_OnQueryStepCount(LPCTSTR pszComponentId,
  1752. LPCTSTR pszSubcomponentId)
  1753. {
  1754. DWORD dwErr = 0;
  1755. DWORD dwNumSteps = 0;
  1756. BOOL bInstallSelected = FALSE;
  1757. BOOL bSelectionStateChanged = FALSE;
  1758. DBG_ENTER( TEXT("prv_OnQueryStepCount"),
  1759. dwNumSteps,
  1760. TEXT("%s - %s"),
  1761. pszComponentId,
  1762. pszSubcomponentId);
  1763. if (!pszSubcomponentId || !*pszSubcomponentId)
  1764. {
  1765. return ERROR_INVALID_PARAMETER;
  1766. }
  1767. dwErr = faxocm_HasSelectionStateChanged(pszSubcomponentId,
  1768. &bSelectionStateChanged,
  1769. &bInstallSelected,
  1770. NULL);
  1771. if (dwErr != NO_ERROR)
  1772. {
  1773. VERBOSE(SETUP_ERR,
  1774. _T("HasSelectionStateChanged failed, rc = 0x%lx"),
  1775. dwErr);
  1776. return 0;
  1777. }
  1778. if (bSelectionStateChanged)
  1779. {
  1780. if (bInstallSelected)
  1781. {
  1782. dwNumSteps = prv_TOTAL_NUM_PROGRESS_BAR_TICKS;
  1783. }
  1784. }
  1785. return dwNumSteps;
  1786. }
  1787. ///////////////////////////////
  1788. // prv_OnExtraRoutines
  1789. //
  1790. // OC Manager giving us some
  1791. // extra routines. Save them.
  1792. //
  1793. // Params:
  1794. // - pszComponentId
  1795. // - pExtraRoutines - pointer to extra OC Manager fns.
  1796. // Returns:
  1797. // - NO_ERROR on success.
  1798. // - error code otherwise
  1799. //
  1800. static DWORD prv_OnExtraRoutines(LPCTSTR pszComponentId,
  1801. EXTRA_ROUTINES *pExtraRoutines)
  1802. {
  1803. DWORD dwResult = NO_ERROR;
  1804. DBG_ENTER( TEXT("prv_OnExtraRoutines"),
  1805. dwResult,
  1806. TEXT("%s"),
  1807. pszComponentId);
  1808. if ((pszComponentId == NULL) ||
  1809. (pExtraRoutines == NULL))
  1810. {
  1811. dwResult = ERROR_INVALID_PARAMETER;
  1812. return dwResult;
  1813. }
  1814. memcpy(&prv_GVAR.Component.Extras,
  1815. pExtraRoutines,
  1816. sizeof(prv_GVAR.Component.Extras));
  1817. dwResult = NO_ERROR;
  1818. return dwResult;
  1819. }
  1820. ///////////////////////////////
  1821. // prv_OnSetLanguage
  1822. //
  1823. // Handler for OC_SET_LANGUAGE
  1824. // the OC Manager is requesting
  1825. // we change to the specified language.
  1826. // Since there is no GUI, this is not
  1827. // an issue.
  1828. //
  1829. // Params:
  1830. // Return:
  1831. // - TRUE indicating successfully
  1832. // changed language.
  1833. //
  1834. static DWORD prv_OnSetLanguage(UINT uiLanguageID)
  1835. {
  1836. // return false; // this is what OCGEN returns
  1837. prv_GVAR.Component.uiLanguageID = uiLanguageID;
  1838. return TRUE;
  1839. }
  1840. ///////////////////////////////
  1841. // prv_OnQueryImage
  1842. //
  1843. // Handler for OC_QUERY_IMAGE
  1844. // this returns the handle to the
  1845. // loaded icon for displaying in the
  1846. // Add/Remove dialog.
  1847. //
  1848. // Params:
  1849. // Returns:
  1850. // - HBITMAP - handle to loaded bitmap
  1851. //
  1852. static DWORD_PTR prv_OnQueryImage(void)
  1853. {
  1854. DWORD_PTR dwResult = (DWORD_PTR)INVALID_HANDLE_VALUE;
  1855. DBG_ENTER(TEXT("prv_OnQueryImage"));
  1856. dwResult = (DWORD_PTR) LoadBitmap(faxocm_GetAppInstance(),
  1857. MAKEINTRESOURCE(IDI_FAX_ICON));
  1858. return dwResult;
  1859. }
  1860. ///////////////////////////////
  1861. // prv_OnSetupRequestPages
  1862. //
  1863. // Handler for OC_REQUEST_PAGES.
  1864. // We don't have a GUI, so we
  1865. // return 0 pages.
  1866. //
  1867. // Params:
  1868. // - uiType - specifies a type from the
  1869. // WizardPagesType enumerator.
  1870. // - Pointer to SETUP_REQUEST_PAGES
  1871. // structure.
  1872. // Returns:
  1873. // - 0, no pages to display
  1874. //
  1875. //
  1876. static DWORD prv_OnSetupRequestPages(
  1877. LPCTSTR pszComponentId,
  1878. WizardPagesType uiType,
  1879. PSETUP_REQUEST_PAGES pSetupRequestPages)
  1880. {
  1881. DWORD dwReturn = 0;
  1882. PROPSHEETPAGE psp = {0};
  1883. DBG_ENTER( _T("prv_OnSetupRequestPages"),
  1884. dwReturn,
  1885. _T("%s - %d"),
  1886. pszComponentId,
  1887. uiType);
  1888. // Don't show pages if it's unattended
  1889. if (fxState_IsUnattended())
  1890. {
  1891. dwReturn = 0;
  1892. goto exit;
  1893. }
  1894. // Only show pages in WizPagesEarly
  1895. if (uiType != WizPagesEarly)
  1896. {
  1897. dwReturn = 0;
  1898. goto exit;
  1899. }
  1900. if (!IsFaxShared())
  1901. {
  1902. VERBOSE(DBG_MSG, _T("Sharing not supported in this SKU, don't show wizard page"));
  1903. dwReturn = 0;
  1904. goto exit;
  1905. }
  1906. if (pSetupRequestPages->MaxPages < 1)
  1907. {
  1908. dwReturn = 1;
  1909. goto exit;
  1910. }
  1911. psp.dwSize = sizeof(PROPSHEETPAGE);
  1912. psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  1913. psp.hInstance = faxocm_GetAppInstance();
  1914. psp.pszTemplate = MAKEINTRESOURCE(IDD_OCM_WIZARD_PAGE);
  1915. psp.pfnDlgProc = prv_dlgOcmWizardPage;
  1916. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_WIZARD_PAGE_TITLE);
  1917. psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_WIZARD_PAGE_SUBTITLE);
  1918. pSetupRequestPages->Pages[0] = CreatePropertySheetPage(&psp);
  1919. if (!pSetupRequestPages->Pages[0])
  1920. {
  1921. VERBOSE(SETUP_ERR,_T("CreatePropertySheetPage failed, ec=%d"), GetLastError());
  1922. dwReturn = 0;
  1923. goto exit;
  1924. }
  1925. dwReturn = 1;
  1926. exit:
  1927. return dwReturn;
  1928. }
  1929. ///////////////////////////////
  1930. // prv_OnWizardCreated
  1931. //
  1932. // Handler for OC_WIZARD_CREATED
  1933. // Do nothing.
  1934. //
  1935. static DWORD prv_OnWizardCreated(void)
  1936. {
  1937. return NO_ERROR;
  1938. }
  1939. ///////////////////////////////
  1940. // prv_OnQuerySelStateChange
  1941. //
  1942. // Handle for OC_QUERY_CHANGE_SEL_STATE
  1943. // OC Manager is asking us if it is
  1944. // okay for the user to select/unselect
  1945. // this component from the Add/Remove
  1946. // list. We want to allow the user
  1947. // to NOT install this as well, so
  1948. // always allow the user to change the
  1949. // selection state.
  1950. //
  1951. // Params:
  1952. // - pszComponentId
  1953. // - pszSubcomponentId
  1954. // - uiState - Specifies proposed new selection
  1955. // state. 0 => not selected, 1 => selected.
  1956. // - uiFlags - Could be OCQ_ACTUAL_SELECTION or 0.
  1957. // If it is OCQ_ACTUAL_SELECTION then the user
  1958. // actually selected/deselected the pszSubcomponentId.
  1959. // If it is 0, it is being turned on or off
  1960. // because the parent needs that subcomponent.
  1961. //
  1962. // Returns:
  1963. // - TRUE - allow selection change
  1964. //
  1965. //
  1966. static DWORD prv_OnQuerySelStateChange(LPCTSTR pszComponentId,
  1967. LPCTSTR pszSubcomponentId,
  1968. UINT uiState,
  1969. UINT uiFlags)
  1970. {
  1971. // always allow the user to change the selection state of the component.
  1972. return TRUE;
  1973. }
  1974. ///////////////////////////////
  1975. // prv_OnQueryState
  1976. //
  1977. // Handler for OC_QUERY_STATE
  1978. // OC Manager is asking us if the
  1979. // given subcomponent is installed or
  1980. // not. Since the OC Manager keeps a
  1981. // record of this for itself, we rely
  1982. // on it to keep track of our installed
  1983. // state.
  1984. //
  1985. // Params:
  1986. // - pszComponentId
  1987. // - pszSubcomponentId
  1988. // - uiState - Install state OC Manager thinks we are in.
  1989. // Returns:
  1990. // - SubcompUseOCManagerDefault - use whatever state
  1991. // OC Manager thinks we are in.
  1992. //
  1993. static DWORD prv_OnQueryState(LPCTSTR pszComponentId,
  1994. LPCTSTR pszSubcomponentId,
  1995. UINT uiState)
  1996. {
  1997. DWORD dwState = SubcompOff;
  1998. DBG_ENTER(_T("prv_OnQueryState"));
  1999. // szSubComponentID should've been set during OC_INIT_COMPONENT, but
  2000. // we don't have it there. So set it here.
  2001. _tcsncpy(prv_GVAR.Component.szSubComponentID,
  2002. pszComponentId,
  2003. ARR_SIZE(prv_GVAR.Component.szSubComponentID));
  2004. if (uiState==OCSELSTATETYPE_CURRENT)
  2005. {
  2006. // when asking about the current state, use the default (either user initiated or from answer file)
  2007. dwState = SubcompUseOcManagerDefault;
  2008. }
  2009. else
  2010. {
  2011. HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP, FALSE,KEY_READ);
  2012. if (hKey)
  2013. {
  2014. DWORD dwInstalled = 0;
  2015. if (GetRegistryDwordEx(hKey,REGVAL_FAXINSTALLED,&dwInstalled)==NO_ERROR)
  2016. {
  2017. if (dwInstalled)
  2018. {
  2019. VERBOSE(DBG_MSG,_T("REG_DWORD 'Installed' is set, assume component is installed"));
  2020. dwState = SubcompOn;
  2021. }
  2022. else
  2023. {
  2024. VERBOSE(DBG_MSG,_T("REG_DWORD 'Installed' is zero, assume component is not installed"));
  2025. }
  2026. }
  2027. else
  2028. {
  2029. VERBOSE(DBG_MSG,_T("REG_DWORD 'Installed' does not exist, assume component is not installed"));
  2030. }
  2031. }
  2032. else
  2033. {
  2034. VERBOSE(DBG_MSG,_T("HKLM\\Software\\Microsoft\\Fax\\Setup does not exist, assume component is not installed"));
  2035. }
  2036. if (hKey)
  2037. {
  2038. RegCloseKey(hKey);
  2039. }
  2040. }
  2041. return dwState;
  2042. }
  2043. ///////////////////////////////
  2044. // prv_OnNeedMedia
  2045. //
  2046. // Handler for OC_NEED_MEDIA
  2047. // Allows us to fetch our own
  2048. // media - for example, from the
  2049. // Internet. We don't need anything
  2050. // so just move on.
  2051. //
  2052. // Params:
  2053. // Returns:
  2054. // - FALSE - don't need any media
  2055. //
  2056. //
  2057. static DWORD prv_OnNeedMedia(void)
  2058. {
  2059. return FALSE;
  2060. }
  2061. ///////////////////////////////
  2062. // prv_OnAboutToCommitQueue
  2063. //
  2064. // Handler for OC_ABOUT_TO_COMMIT_QUEUE
  2065. // Tells us that OC Manager is about
  2066. // to commit to queue. We don't really
  2067. // care, do nothing.
  2068. //
  2069. // Params:
  2070. // - pszComponentId
  2071. // - pszSubcomponentId.
  2072. // Returns:
  2073. // - NO_ERROR on success.
  2074. // - error code otherwise.
  2075. //
  2076. static DWORD prv_OnAboutToCommitQueue(LPCTSTR pszComponentId,
  2077. LPCTSTR pszSubcomponentId)
  2078. {
  2079. DWORD dwReturn = NO_ERROR;
  2080. // don't think we need to do anything here yet.
  2081. return dwReturn;
  2082. }
  2083. ///////////////////////////////
  2084. // prv_OnQuerySkipPage
  2085. //
  2086. // Handler for OC_QUERY_SKIP_PAGE
  2087. //
  2088. // Params:
  2089. // Returns:
  2090. //
  2091. //
  2092. static DWORD prv_OnQuerySkipPage(void)
  2093. {
  2094. return FALSE;
  2095. }
  2096. ///////////////////////////////
  2097. // faxocm_HasSelectionStateChanged
  2098. //
  2099. // This fn tells us if our selection
  2100. // state in the Add/Remove programs
  2101. // dialog box has changed since it
  2102. // was started, and it also tells us
  2103. // our current selection state.
  2104. //
  2105. // Params:
  2106. // - pszSubcomponentId
  2107. // - pbCurrentSelected - OUT
  2108. // - pbOriginallySelected - OUT
  2109. // Returns:
  2110. // - TRUE if selection state has changed
  2111. // - FALSE otherwise.
  2112. //
  2113. DWORD faxocm_HasSelectionStateChanged(LPCTSTR pszSubcomponentId,
  2114. BOOL *pbSelectionStateChanged,
  2115. BOOL *pbCurrentlySelected,
  2116. BOOL *pbOriginallySelected)
  2117. {
  2118. DWORD dwReturn = NO_ERROR;
  2119. BOOL bCurrentlySelected = FALSE;
  2120. BOOL bOriginallySelected = FALSE;
  2121. BOOL bSelectionChanged = TRUE;
  2122. PQUERYSELECTIONSTATE_ROUTINEW pQuerySelectionState = NULL;
  2123. DBG_ENTER( TEXT("faxocm_HasSelectionStateChanged"),
  2124. dwReturn,
  2125. TEXT("%s"),
  2126. pszSubcomponentId);
  2127. // if pszSubcomponentId == NULL, we are hosed.
  2128. Assert(pszSubcomponentId != NULL);
  2129. Assert(pbSelectionStateChanged != NULL);
  2130. if ((pszSubcomponentId == NULL) ||
  2131. (pbSelectionStateChanged == NULL))
  2132. {
  2133. SetLastError(ERROR_INVALID_PARAMETER);
  2134. return dwReturn=ERROR_INVALID_PARAMETER;
  2135. }
  2136. pQuerySelectionState = prv_GVAR.Component.Helpers.QuerySelectionState;
  2137. if (pQuerySelectionState)
  2138. {
  2139. // are we currently selected.
  2140. bCurrentlySelected = pQuerySelectionState(
  2141. prv_GVAR.Component.Helpers.OcManagerContext,
  2142. pszSubcomponentId,
  2143. OCSELSTATETYPE_CURRENT);
  2144. bOriginallySelected = pQuerySelectionState(
  2145. prv_GVAR.Component.Helpers.OcManagerContext,
  2146. pszSubcomponentId,
  2147. OCSELSTATETYPE_ORIGINAL);
  2148. if (bOriginallySelected == bCurrentlySelected)
  2149. {
  2150. bSelectionChanged = FALSE;
  2151. }
  2152. else
  2153. {
  2154. bSelectionChanged = TRUE;
  2155. }
  2156. }
  2157. // if we are not in stand alone mode, and we are upgrading the OS, then assume that
  2158. // the selection state has changed. We do this because we would like to force an
  2159. // install of fax during an upgrade from NT or W2K. Currently (as of 05/02/2000)
  2160. // OC Manager reports an upgrade type of WINNT when upgrading from W2K. This is valid
  2161. // because fax is always installed in W2K (the user could not uninstall it), and therefore
  2162. // whenever we upgrade, bSelectionChanged will always be FALSE, which will prevent
  2163. // the new fax from being installed. NOT GOOD. This fixes that.
  2164. if ( (fxState_IsStandAlone() == FALSE) &&
  2165. ((fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_W2K) ||
  2166. (fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_REPAIR) ||
  2167. (fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_XP_DOT_NET)))
  2168. {
  2169. if (bOriginallySelected && bCurrentlySelected)
  2170. {
  2171. // only if Fax was installed and is now marked for installation during OS upgrade
  2172. // we force re-installation.
  2173. // If both were false, this can't return true because it'll cause an uninstall
  2174. // going and we'll try to uninstall a non existing Fax.
  2175. // This happens when upgrading XP build without Fax to another.
  2176. // This causes many setup error (in setupapi logs) and disturbes setup people.
  2177. // this condition takes care of this problem.
  2178. bSelectionChanged = TRUE;
  2179. }
  2180. }
  2181. if (pbCurrentlySelected)
  2182. {
  2183. *pbCurrentlySelected = bCurrentlySelected;
  2184. }
  2185. if (pbOriginallySelected)
  2186. {
  2187. *pbOriginallySelected = bOriginallySelected;
  2188. }
  2189. *pbSelectionStateChanged = bSelectionChanged;
  2190. return dwReturn;
  2191. }
  2192. ///////////////////////////////
  2193. // prv_NotifyStatusMonitor
  2194. //
  2195. // This function notifies the shell
  2196. // to load FXSST.DLL (Status Monitor)
  2197. // It is done by sending a private message
  2198. // to STOBJECT.DLL window.
  2199. //
  2200. //
  2201. // Params:
  2202. // - WPARAM wParam -
  2203. // either FAX_STARTUP_TIMER_ID or
  2204. // FAX_SHUTDOWN_TIMER_ID
  2205. //
  2206. // Returns:
  2207. // - NO_ERROR if notification succeeded
  2208. // - Win32 Error code otherwise.
  2209. //
  2210. static DWORD prv_NotifyStatusMonitor(WPARAM wParam)
  2211. {
  2212. DWORD dwRet = NO_ERROR;
  2213. HWND hWnd = NULL;
  2214. DBG_ENTER(TEXT("prv_NotifyStatusMonitor"),dwRet);
  2215. // We need to send a WM_TIMER to a window identified by the class name SYSTRAY_CLASSNAME
  2216. // The timer ID should be FAX_STARTUP_TIMER_ID
  2217. hWnd = FindWindow(SYSTRAY_CLASSNAME,NULL);
  2218. if (hWnd==NULL)
  2219. {
  2220. dwRet = GetLastError();
  2221. CALL_FAIL(SETUP_ERR,TEXT("FindWindow"),dwRet);
  2222. goto exit;
  2223. }
  2224. SendMessage(hWnd,WM_TIMER,wParam,0);
  2225. exit:
  2226. return dwRet;
  2227. }
  2228. static INT_PTR CALLBACK prv_dlgWhereDidMyFaxGoQuestion
  2229. (
  2230. HWND hwndDlg,
  2231. UINT uMsg,
  2232. WPARAM wParam,
  2233. LPARAM lParam
  2234. )
  2235. /*++
  2236. Routine name : prv_dlgWhereDidMyFaxGoQuestion
  2237. Routine description:
  2238. Dialogs procedure for "Where did my fax go" dialog
  2239. Author:
  2240. Mooly Beery (MoolyB), Mar, 2001
  2241. Arguments:
  2242. hwndDlg [in] - Handle to dialog box
  2243. uMsg [in] - Message
  2244. wParam [in] - First message parameter
  2245. parameter [in] - Second message parameter
  2246. Return Value:
  2247. Standard dialog return value
  2248. --*/
  2249. {
  2250. INT_PTR iRes = IDIGNORE;
  2251. DBG_ENTER(_T("prv_dlgWhereDidMyFaxGoQuestion"));
  2252. switch (uMsg)
  2253. {
  2254. case WM_INITDIALOG:
  2255. SetFocus(hwndDlg);
  2256. break;
  2257. case WM_COMMAND:
  2258. switch(LOWORD(wParam))
  2259. {
  2260. case IDOK:
  2261. if (BST_CHECKED == ::SendMessage (::GetDlgItem (hwndDlg, IDC_REMOVE_LINK), BM_GETCHECK, 0, 0))
  2262. {
  2263. // we should remove the link.
  2264. // we do this by processing our INF in the section that deals
  2265. // with this link. This way we're sure it can be localized at will
  2266. // and we'll always remove the correct link.
  2267. TCHAR szInfFileName[2*MAX_PATH] = {0};
  2268. if (faxocm_GetComponentInfName(szInfFileName))
  2269. {
  2270. _tcscat(szInfFileName,_T(",Fax.UnInstall.PerUser.WhereDidMyFaxGo"));
  2271. if (LPSTR pszInfCommandLine = UnicodeStringToAnsiString(szInfFileName))
  2272. {
  2273. LaunchINFSection(hwndDlg,prv_GVAR.hInstance,pszInfCommandLine,1);
  2274. MemFree(pszInfCommandLine);
  2275. }
  2276. }
  2277. }
  2278. EndDialog (hwndDlg, iRes);
  2279. return TRUE;
  2280. }
  2281. break;
  2282. }
  2283. return FALSE;
  2284. } // prv_dlgWhereDidMyFaxGoQuestion
  2285. ///////////////////////////////////////////////////////////////////////////////////////
  2286. // Function:
  2287. // WhereDidMyFaxGo
  2288. //
  2289. // Purpose:
  2290. // When a machine running SBS5.0 client was upgraded to Windows-XP
  2291. // We show a link called 'Where did my Fax go' in the start menu
  2292. // at the same location where the SBS5.0 shortcuts used to be.
  2293. // When clicking this link it calls this function that raises
  2294. // a dialog to explain to the user where the Windows-XP Fax's
  2295. // shortcuts are, and asks the user whether to delete this link.
  2296. //
  2297. // Params:
  2298. // None
  2299. //
  2300. // Return Value:
  2301. // NO_ERROR - in case of success
  2302. // Win32 Error code otherwise
  2303. //
  2304. // Author:
  2305. // Mooly Beery (MoolyB) 17-Jan-2001
  2306. ///////////////////////////////////////////////////////////////////////////////////////
  2307. DWORD WhereDidMyFaxGo(void)
  2308. {
  2309. DWORD dwRet = NO_ERROR;
  2310. DBG_ENTER(TEXT("WhereDidMyFaxGo"),dwRet);
  2311. HMODULE hFaxRes = LoadLibraryEx(FAX_RES_FILE, NULL, LOAD_LIBRARY_AS_DATAFILE);
  2312. if(!hFaxRes)
  2313. {
  2314. dwRet = GetLastError();
  2315. CALL_FAIL (RESOURCE_ERR, TEXT("LoadLibraryEx(FxsRes.dll)"), dwRet);
  2316. return dwRet;
  2317. }
  2318. INT_PTR iResult = DialogBox (hFaxRes,
  2319. MAKEINTRESOURCE(IDD_WHERE_DID_MY_FAX_GO),
  2320. NULL,
  2321. prv_dlgWhereDidMyFaxGoQuestion);
  2322. if (iResult==-1)
  2323. {
  2324. dwRet = GetLastError();
  2325. CALL_FAIL (RESOURCE_ERR, TEXT("DialogBox(IDD_WHERE_DID_MY_FAX_GO)"), dwRet);
  2326. }
  2327. FreeLibrary(hFaxRes);
  2328. return dwRet;
  2329. }
  2330. DWORD prv_ShowUninstalledFaxShortcut(void)
  2331. /*++
  2332. Routine name : prv_ShowUninstalledFaxShortcut
  2333. Routine description:
  2334. Show Shortcut of "Where Did My Fax Go ? " in the All Programs.
  2335. Author:
  2336. Iv Garber (IvG), Jun, 2001
  2337. Return Value:
  2338. Standard Win32 error code
  2339. --*/
  2340. {
  2341. DBG_ENTER(_T("prv_ShowUninstalledFaxShortcut"));
  2342. //
  2343. // In cases we upgraded from a machine running SBS2000 Client/Server or XP Client and we want to
  2344. // add a 'Where did my Fax go' shortcut.
  2345. // we want to add it to the current user as well as every user.
  2346. //
  2347. if (fxocUpg_GetUpgradeApp() != FXSTATE_NONE)
  2348. {
  2349. //
  2350. // first add the shortcut to the current user.
  2351. //
  2352. TCHAR szInfFileName[2*MAX_PATH] = {0};
  2353. if (faxocm_GetComponentInfName(szInfFileName))
  2354. {
  2355. _tcscat(szInfFileName,_T(",Fax.Install.PerUser.AppUpgrade"));
  2356. if (LPSTR pszInfCommandLine = UnicodeStringToAnsiString(szInfFileName))
  2357. {
  2358. LaunchINFSection(NULL,prv_GVAR.hInstance,pszInfCommandLine,1);
  2359. MemFree(pszInfCommandLine);
  2360. }
  2361. }
  2362. else
  2363. {
  2364. CALL_FAIL(SETUP_ERR,TEXT("faxocm_GetComponentInfName"),GetLastError());
  2365. }
  2366. //
  2367. // now change the PerUserStub to point to the section that creates the link for every user.
  2368. //
  2369. HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_ACTIVE_SETUP_NT, FALSE,KEY_ALL_ACCESS);
  2370. if (hKey)
  2371. {
  2372. if (LPTSTR lptstrPerUser = GetRegistryString(hKey,_T("StubPath"),NULL))
  2373. {
  2374. TCHAR szLocalPerUserStub[MAX_PATH*2] = {0};
  2375. _tcscpy(szLocalPerUserStub,lptstrPerUser);
  2376. _tcscat(szLocalPerUserStub,REGVAL_ACTIVE_SETUP_PER_USER_APP_UPGRADE);
  2377. if (!SetRegistryString(hKey,_T("StubPath"),szLocalPerUserStub))
  2378. {
  2379. CALL_FAIL(SETUP_ERR,TEXT("SetRegistryString"),GetLastError());
  2380. }
  2381. MemFree(lptstrPerUser);
  2382. }
  2383. else
  2384. {
  2385. CALL_FAIL(SETUP_ERR,TEXT("GetRegistryString"),GetLastError());
  2386. }
  2387. RegCloseKey(hKey);
  2388. }
  2389. else
  2390. {
  2391. CALL_FAIL(SETUP_ERR,TEXT("OpenRegistryKey"),GetLastError());
  2392. }
  2393. }
  2394. return NO_ERROR;
  2395. }
  2396. BOOL prv_ShouldShowPage()
  2397. /*++
  2398. Routine name : prv_ShouldShowPage
  2399. Routine description: Checks whether the OCM wizard page should be shown
  2400. Author: Jonathan Barner (jobarner), May 2002
  2401. Arguments: none
  2402. Return value: TRUE - show, FALSE - don't show
  2403. --*/
  2404. {
  2405. BOOL bSelectionStateChanged = FALSE;
  2406. BOOL bInstallSelected = FALSE;
  2407. if (faxocm_HasSelectionStateChanged(prv_GVAR.Component.szSubComponentID,
  2408. &bSelectionStateChanged,
  2409. &bInstallSelected,
  2410. NULL) != NO_ERROR)
  2411. {
  2412. return FALSE;
  2413. }
  2414. return (bSelectionStateChanged && bInstallSelected);
  2415. }
  2416. static INT_PTR CALLBACK prv_dlgOcmWizardPage(HWND hwndDlg,
  2417. UINT uMsg,
  2418. WPARAM wParam,
  2419. LPARAM lParam)
  2420. /*++
  2421. Routine name : prv_dlgOcmWizardPage
  2422. Routine description: Dialog procedure for OCM Wizard page dialog
  2423. Author: Jonathan Barner (jobarner), May 2002
  2424. Arguments and return values: Standard dialog return value
  2425. --*/
  2426. {
  2427. switch (uMsg)
  2428. {
  2429. case WM_INITDIALOG:
  2430. // Set default to "do not share printer"
  2431. CheckRadioButton(hwndDlg, IDC_SHARE_PRINTER, IDC_DO_NOT_SHARE_PRINTER,
  2432. IDC_DO_NOT_SHARE_PRINTER);
  2433. break;
  2434. case WM_NOTIFY:
  2435. switch(((NMHDR FAR*)lParam)->code)
  2436. {
  2437. case PSN_SETACTIVE:
  2438. {
  2439. LONG_PTR lReturn = prv_ShouldShowPage() ? 0 : -1;
  2440. if (lReturn == 0)
  2441. {
  2442. PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
  2443. }
  2444. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, lReturn);
  2445. return TRUE;
  2446. }
  2447. break;
  2448. case PSN_WIZNEXT:
  2449. BOOL fShouldShare = (IsDlgButtonChecked(hwndDlg, IDC_SHARE_PRINTER) == BST_CHECKED);
  2450. fxocPrnt_SetFaxPrinterShared(fShouldShare);
  2451. break;
  2452. }
  2453. break;
  2454. }
  2455. return FALSE;
  2456. } // prv_dlgOcmWizardPage
  2457. LPCTSTR lplpszFaxFolder[][2] = {
  2458. {FAX_QUEUE_DIR, SD_FAX_FOLDERS},
  2459. {FAX_INBOX_DIR, SD_FAX_FOLDERS},
  2460. {FAX_SENTITEMS_DIR, SD_FAX_FOLDERS},
  2461. {FAX_ACTIVITYLOG_DIR, SD_FAX_FOLDERS},
  2462. {FAX_COMMONCOVERPAGES_DIR, SD_COMMON_COVERPAGES}};
  2463. /*++
  2464. Routine description:
  2465. Sets security info on Fax directories under "Documents and settings" tree
  2466. Arguments:
  2467. lpszCommonAppData [in] - name of Common App directory, for example
  2468. C:\Documents and Settings\All Users\Application Data
  2469. Return Value: Win32 Error code
  2470. Notes:
  2471. This function is called after converting the file system from FAT to NTFS
  2472. (during the call to SecureUserProfiles()).
  2473. The security of folders under system32 are handled by convert.exe itself.
  2474. Written by: jobarner, 08/2002
  2475. --*/
  2476. HRESULT SecureFaxServiceDirectories(LPCTSTR lpszCommonAppData)
  2477. {
  2478. DWORD dwRet;
  2479. DWORD ec = ERROR_SUCCESS;
  2480. BOOL bFaxInstalled = FALSE;
  2481. TCHAR szDir[MAX_PATH] = {'\0'};
  2482. int iResult;
  2483. int i;
  2484. DBG_ENTER( _T("SecureFaxServiceDirectories"), ec);
  2485. ec = IsFaxInstalled (&bFaxInstalled);
  2486. if (ec!=ERROR_SUCCESS)
  2487. {
  2488. VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), ec);
  2489. return ec;
  2490. }
  2491. if (!bFaxInstalled)
  2492. {
  2493. VERBOSE(DBG_MSG, _T("Fax is not installed, quitting"));
  2494. return ERROR_SUCCESS;
  2495. }
  2496. for (i=0; i<ARR_SIZE(lplpszFaxFolder); i++)
  2497. {
  2498. iResult = _sntprintf(szDir,
  2499. ARR_SIZE(szDir) -1,
  2500. TEXT("%s\\%s"),
  2501. lpszCommonAppData,
  2502. lplpszFaxFolder[i][0]);
  2503. if (iResult<0)
  2504. {
  2505. VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
  2506. ec = ERROR_INSUFFICIENT_BUFFER;
  2507. }
  2508. else
  2509. {
  2510. dwRet = SetDirSecurity(szDir, lplpszFaxFolder[i][1]);
  2511. if (dwRet!=ERROR_SUCCESS)
  2512. {
  2513. VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
  2514. ec = dwRet;
  2515. }
  2516. }
  2517. }
  2518. return ec;
  2519. }