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.

1722 lines
50 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. fxocUpgrade.cpp
  5. Abstract:
  6. Implementation of the Upgrade process
  7. Author:
  8. Iv Garber (IvG) Mar, 2001
  9. Revision History:
  10. --*/
  11. #include "faxocm.h"
  12. #pragma hdrstop
  13. #include <setuputil.h>
  14. #include <shlwapi.h> // For SHCopyKey
  15. DWORD g_LastUniqueLineId = 0;
  16. //
  17. // EnumDevicesType is used to call prv_StoreDevices() callback function during the Enumeration of
  18. // Devices in the Registry.
  19. //
  20. typedef enum prv_EnumDevicesType
  21. {
  22. edt_None = 0x00,
  23. edt_PFWDevices = 0x02, // Enumerate W2K Fax Devices
  24. edt_Inbox = 0x04 // Find List of Inbox Folders for W2K Fax
  25. };
  26. //
  27. // Local Static Variable, to store data between OS Manager calls
  28. //
  29. static struct prv_Data
  30. {
  31. DWORD dwFaxInstalledPriorUpgrade; // bit-wise combination of fxState_UpgradeApp_e values to define
  32. // which fax clients were installed on the machine prior to upgrade
  33. //
  34. // data for PFW
  35. //
  36. TCHAR tszCommonCPDir[MAX_PATH]; // Folder for Common Cover Pages
  37. LPTSTR *plptstrInboxFolders; // Array of different Inbox Folders
  38. DWORD dwInboxFoldersCount; // number of Inbox Folders in the plptstrInboxFolders array
  39. } prv_Data =
  40. {
  41. FXSTATE_NONE, // no fax client applications is installed by default
  42. {0}, // tszCommonCPDir
  43. NULL, // plptstrInboxFolders
  44. 0 // dwInboxFoldersCount
  45. };
  46. //
  47. // Internal assisting functions
  48. //
  49. BOOL prv_StoreDevices(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext);
  50. static DWORD prv_MoveCoverPages(LPTSTR lptstrSourceDir, LPTSTR lptstrDestDir, LPTSTR lptstrPrefix);
  51. static DWORD prv_GetPFWCommonCPDir(void);
  52. static DWORD prv_GetSBSServerCPDir(LPTSTR lptstrCPDir) {return NO_ERROR; };
  53. static DWORD prv_SaveArchives(void);
  54. DWORD fxocUpg_WhichFaxWasUninstalled(
  55. DWORD dwFaxAppList
  56. )
  57. /*++
  58. Routine name : fxocUpg_WhichFaxWasUninstalled
  59. Routine description:
  60. Set flags regarding fax applications installed before upgrade. Called from SaveUnattendedData() if
  61. the corresponding data is found in the Answer File.
  62. Author:
  63. Iv Garber (IvG), May, 2001
  64. Arguments:
  65. FaxApp [in] - the combination of the applications that were installed before the upgrade
  66. Return Value:
  67. Standard Win32 error code
  68. --*/
  69. {
  70. DWORD dwReturn = NO_ERROR;
  71. DBG_ENTER(_T("fxocUpg_WhichFaxWasUninstalled"), dwReturn);
  72. prv_Data.dwFaxInstalledPriorUpgrade = dwFaxAppList;
  73. return dwReturn;
  74. }
  75. DWORD fxocUpg_GetUpgradeApp(void)
  76. /*++
  77. Routine name : fxocUpg_GetUpgradeApp
  78. Routine description:
  79. Return type of the upgrade, which indicates which fax applications were installed before the upgrade.
  80. Author:
  81. Iv Garber (IvG), May, 2001
  82. Return Value:
  83. The type of the upgrade
  84. --*/
  85. {
  86. DBG_ENTER(_T("fxocUpg_GetUpgradeApp"), prv_Data.dwFaxInstalledPriorUpgrade);
  87. return prv_Data.dwFaxInstalledPriorUpgrade;
  88. }
  89. DWORD fxocUpg_Init(void)
  90. /*++
  91. Routine name : fxocUpg_Init
  92. Routine description:
  93. checks which Fax applications are installed on the machine,
  94. and set global flags in prv_Data.
  95. Author:
  96. Iv Garber (IvG), May, 2001
  97. Return Value:
  98. DWORD - failure or success
  99. --*/
  100. {
  101. DWORD dwReturn = NO_ERROR;
  102. bool bInstalled = false;
  103. DBG_ENTER(_T("fxocUpg_Init"), dwReturn);
  104. //
  105. // Clear the SBS 5.0 Server flag
  106. //
  107. prv_Data.dwFaxInstalledPriorUpgrade = FXSTATE_NONE;
  108. //
  109. // Check presence of the SBS 5.0 Server
  110. //
  111. dwReturn = WasSBS2000FaxServerInstalled(&bInstalled);
  112. if (dwReturn != NO_ERROR)
  113. {
  114. VERBOSE(DBG_WARNING, _T("CheckInstalledFax() failed, ec=%ld."), dwReturn);
  115. }
  116. if (bInstalled)
  117. {
  118. prv_Data.dwFaxInstalledPriorUpgrade |= FXSTATE_SBS5_SERVER;
  119. }
  120. return dwReturn;
  121. }
  122. DWORD fxocUpg_SaveSettings(void)
  123. /*++
  124. Routine name : fxocUpg_SaveSettings
  125. Routine description:
  126. Save settings of SBS 5.0 Server to allow smooth migration to the Windows XP Fax.
  127. Device Settings should be stored BEFORE handling of the Registry ( which deletes the Devices key )
  128. and BEFORE the Service Start ( which creates new devices and uses settings that are stored here ).
  129. Author:
  130. Iv Garber (IvG), May, 2001
  131. Return Value:
  132. DWORD - failure or success
  133. --*/
  134. {
  135. DWORD dwReturn = NO_ERROR;
  136. DWORD dwEnumType = edt_None;
  137. DBG_ENTER(_T("fxocUpg_SaveSettings"), dwReturn);
  138. //
  139. // Handle Upgrade from W2K/PFW Fax
  140. //
  141. if (fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_W2K)
  142. {
  143. //
  144. // Save its Common CP Dir. This should be done BEFORE Copy/Delete Files of Windows XPFax.
  145. //
  146. dwReturn = prv_GetPFWCommonCPDir();
  147. if (dwReturn != NO_ERROR)
  148. {
  149. VERBOSE(DBG_WARNING, _T("prv_GetPFWCommonCPDir() failed, ec=%ld."), dwReturn);
  150. }
  151. //
  152. // Store Device Settings of PFW -- if SBS 5.0 Server is not present on the machine.
  153. // Also, find Inbox Folders List of the PFW Devices.
  154. //
  155. HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ);
  156. if (!hKey)
  157. {
  158. dwReturn = GetLastError();
  159. VERBOSE(DBG_WARNING, _T("Failed to open Registry for Fax, ec = %ld."), dwReturn);
  160. return dwReturn;
  161. }
  162. if (prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER)
  163. {
  164. //
  165. // Devices already enumerated, through SBS 5.0 Server
  166. // Enumerate only Inbox Folders
  167. //
  168. dwEnumType = edt_Inbox;
  169. }
  170. else
  171. {
  172. //
  173. // Full Enumeration for PFW Devices : Devices Settings + Inbox Folders
  174. //
  175. dwEnumType = edt_PFWDevices | edt_Inbox;
  176. }
  177. dwReturn = EnumerateRegistryKeys(hKey, REGKEY_DEVICES, FALSE, prv_StoreDevices, &dwEnumType);
  178. VERBOSE(DBG_MSG, _T("For PFW, enumerated %ld devices."), dwReturn);
  179. RegCloseKey(hKey);
  180. //
  181. // prv_StoreDevices stored list of PFW's Inbox Folders in prv_Data.
  182. // Now save the Inbox Folders List and SentItems Folder
  183. //
  184. dwReturn = prv_SaveArchives();
  185. if (dwReturn != NO_ERROR)
  186. {
  187. VERBOSE(DBG_WARNING, _T("prv_SaveArchives() failed, ec=%ld."), dwReturn);
  188. }
  189. dwReturn = NO_ERROR;
  190. }
  191. return dwReturn;
  192. }
  193. BOOL
  194. prv_StoreDevices(HKEY hDeviceKey,
  195. LPWSTR lpwstrKeyName,
  196. DWORD dwIndex,
  197. LPVOID lpContextData
  198. )
  199. /*++
  200. Routine name : prv_StoreDevices
  201. Routine description:
  202. Callback function used in enumeration of devices in the registry.
  203. Stores device's data in the Registry, under Setup/Original Setup Data.
  204. Creates List of Inbox Folders ( used for PFW ) and saves it in the prv_Data.
  205. Used when upgrading from PFW/SBS 5.0 Server to Windows XP Fax.
  206. Author:
  207. Iv Garber (IvG), Mar, 2001
  208. Arguments:
  209. hKey [in] - current key
  210. lpwstrKeyName [in] - name of the current key, if exists
  211. dwIndex [in] - count of all the subkeys for the given key / index of the current key
  212. lpContextData [in] - NULL, not used
  213. Return Value:
  214. TRUE if success, FALSE otherwise.
  215. --*/
  216. {
  217. HKEY hSetupKey = NULL;
  218. DWORD dwReturn = NO_ERROR;
  219. DWORD dwNumber = 0;
  220. TCHAR tszNewKeyName[MAX_PATH] = {0};
  221. LPTSTR lptstrString = NULL;
  222. DWORD *pdwEnumType = NULL;
  223. DBG_ENTER(_T("prv_StoreDevices"));
  224. if (lpwstrKeyName == NULL)
  225. {
  226. //
  227. // This is the SubKey we started at ( i.e. Devices )
  228. //
  229. // If InboxFolders should be stored, then allocate
  230. // enough memory for prv_Data.plptstrInboxFolders.
  231. // dwIndex contains TOTAL number of subkeys ( Devices ).
  232. //
  233. pdwEnumType = (DWORD *)lpContextData;
  234. if ( (*pdwEnumType & edt_Inbox) == edt_Inbox )
  235. {
  236. prv_Data.plptstrInboxFolders = (LPTSTR *)MemAlloc(sizeof(LPTSTR) * dwIndex);
  237. if (prv_Data.plptstrInboxFolders)
  238. {
  239. ZeroMemory(prv_Data.plptstrInboxFolders, sizeof(LPTSTR) * dwIndex);
  240. }
  241. else
  242. {
  243. //
  244. // Not enough memory
  245. //
  246. VERBOSE(DBG_WARNING, _T("Not enough memory to store the Inbox Folders."));
  247. }
  248. }
  249. return TRUE;
  250. }
  251. //
  252. // The per Device section
  253. //
  254. //
  255. // Store Device's Inbox Folder
  256. //
  257. if (prv_Data.plptstrInboxFolders)
  258. {
  259. //
  260. // we are here only when lpContextData contains edt_InboxFolders
  261. // and the memory allocation succeded.
  262. //
  263. //
  264. // Open Routing SubKey
  265. //
  266. hSetupKey = OpenRegistryKey(hDeviceKey, REGKEY_PFW_ROUTING, FALSE, KEY_READ);
  267. if (!hSetupKey)
  268. {
  269. //
  270. // Failed to open Routing Subkey
  271. //
  272. dwReturn = GetLastError();
  273. VERBOSE(DBG_WARNING, _T("Failed to open 'Registry' Key for Device #ld, ec = %ld."), dwIndex, dwReturn);
  274. goto ContinueStoreDevice;
  275. }
  276. //
  277. // Take 'Store Directory' Value
  278. //
  279. lptstrString = GetRegistryString(hSetupKey, REGVAL_PFW_INBOXDIR, EMPTY_STRING);
  280. if ((!lptstrString) || (_tcslen(lptstrString) == 0))
  281. {
  282. //
  283. // Failed to take the value
  284. //
  285. dwReturn = GetLastError();
  286. VERBOSE(DBG_WARNING, _T("Failed to get StoreDirectory value for Device #ld, ec = %ld."), dwIndex, dwReturn);
  287. goto ContinueStoreDevice;
  288. }
  289. //
  290. // Check if it is already present
  291. //
  292. DWORD dwI;
  293. for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
  294. {
  295. if (prv_Data.plptstrInboxFolders[dwI])
  296. {
  297. if (_tcscmp(prv_Data.plptstrInboxFolders[dwI], lptstrString) == 0)
  298. {
  299. //
  300. // String found
  301. //
  302. goto ContinueStoreDevice;
  303. }
  304. }
  305. }
  306. //
  307. // String was NOT found between all already registered string, so add it
  308. //
  309. prv_Data.plptstrInboxFolders[dwI] = LPTSTR(MemAlloc(sizeof(TCHAR) * (_tcslen(lptstrString) + 1)));
  310. if (prv_Data.plptstrInboxFolders[dwI])
  311. {
  312. //
  313. // copy string & update the counter
  314. //
  315. _tcscpy(prv_Data.plptstrInboxFolders[dwI], lptstrString);
  316. prv_Data.dwInboxFoldersCount++;
  317. }
  318. else
  319. {
  320. //
  321. // Not enough memory
  322. //
  323. VERBOSE(DBG_WARNING, _T("Not enough memory to store the Inbox Folders."));
  324. }
  325. ContinueStoreDevice:
  326. if (hSetupKey)
  327. {
  328. RegCloseKey(hSetupKey);
  329. hSetupKey = NULL;
  330. }
  331. MemFree(lptstrString);
  332. lptstrString = NULL;
  333. }
  334. //
  335. // Check whether to store Device's Data and how
  336. //
  337. pdwEnumType = (DWORD *)lpContextData;
  338. if ((*pdwEnumType & edt_PFWDevices) == edt_PFWDevices)
  339. {
  340. //
  341. // Store PFW Devices Data
  342. //
  343. lptstrString = REGVAL_PERMANENT_LINEID;
  344. }
  345. else
  346. {
  347. //
  348. // no need to save any Device Data
  349. //
  350. return TRUE;
  351. }
  352. //
  353. // Take Device's Permanent Line Id
  354. //
  355. dwReturn = GetRegistryDwordEx(hDeviceKey, lptstrString, &dwNumber);
  356. if (dwReturn != ERROR_SUCCESS)
  357. {
  358. //
  359. // Cannot find TAPI Permanent LineId --> This is invalid Device Registry
  360. //
  361. return TRUE;
  362. }
  363. VERBOSE(DBG_MSG, _T("Current Tapi Line Id = %ld"), dwNumber);
  364. //
  365. // Create a SubKey Name from it
  366. //
  367. _sntprintf(
  368. tszNewKeyName,
  369. ARR_SIZE(tszNewKeyName) -1,
  370. TEXT("%s\\%010d"),
  371. REGKEY_FAX_SETUP_ORIG,
  372. dwNumber);
  373. hSetupKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, tszNewKeyName, TRUE, 0);
  374. if (!hSetupKey)
  375. {
  376. //
  377. // Failed to create registry key
  378. //
  379. dwReturn = GetLastError();
  380. VERBOSE(DBG_WARNING,
  381. _T("Failed to create a SubKey for the Original Setup Data of the Device, ec = %ld."),
  382. dwReturn);
  383. //
  384. // Continue to the next device
  385. //
  386. return TRUE;
  387. }
  388. //
  389. // Set the Flags for the newly created key
  390. //
  391. dwNumber = GetRegistryDword(hDeviceKey, REGVAL_FLAGS);
  392. SetRegistryDword(hSetupKey, REGVAL_FLAGS, dwNumber);
  393. VERBOSE(DBG_MSG, _T("Flags are : %ld"), dwNumber);
  394. //
  395. // Set the Rings for the newly created key
  396. //
  397. dwNumber = GetRegistryDword(hDeviceKey, REGVAL_RINGS);
  398. SetRegistryDword(hSetupKey, REGVAL_RINGS, dwNumber);
  399. VERBOSE(DBG_MSG, _T("Rings are : %ld"), dwNumber);
  400. //
  401. // Set the TSID for the newly created key
  402. //
  403. lptstrString = GetRegistryString(hDeviceKey, REGVAL_ROUTING_TSID, REGVAL_DEFAULT_TSID);
  404. SetRegistryString(hSetupKey, REGVAL_ROUTING_TSID, lptstrString);
  405. VERBOSE(DBG_MSG, _T("TSID is : %s"), lptstrString);
  406. MemFree(lptstrString);
  407. //
  408. // Set the CSID for the newly created key
  409. //
  410. lptstrString = GetRegistryString(hDeviceKey, REGVAL_ROUTING_CSID, REGVAL_DEFAULT_CSID);
  411. SetRegistryString(hSetupKey, REGVAL_ROUTING_CSID, lptstrString);
  412. VERBOSE(DBG_MSG, _T("CSID is : %s"), lptstrString);
  413. MemFree(lptstrString);
  414. RegCloseKey(hSetupKey);
  415. return TRUE;
  416. }
  417. DWORD fxocUpg_RestoreSettings(void)
  418. /*++
  419. Routine name : fxocUpg_RestoreSettings
  420. Routine description:
  421. Restore settings that were stored at the SaveSettings().
  422. Author:
  423. Iv Garber (IvG), Feb, 2001
  424. Return Value:
  425. DWORD - failure or success
  426. --*/
  427. {
  428. DWORD dwReturn = NO_ERROR;
  429. HANDLE hPrinter = NULL;
  430. DBG_ENTER(_T("fxocUpg_RestoreSettings"), dwReturn);
  431. return dwReturn;
  432. }
  433. DWORD fxocUpg_MoveFiles(void)
  434. /*++
  435. Routine name : fxocUpg_MoveFiles
  436. Routine description:
  437. Move files from the folders that should be deleted.
  438. Should be called BEFORE directories delete.
  439. Author:
  440. Iv Garber (IvG), Feb, 2001
  441. Return Value:
  442. DWORD - failure or success
  443. --*/
  444. {
  445. DWORD dwReturn = NO_ERROR;
  446. TCHAR tszDestination[MAX_PATH] = {0};
  447. LPTSTR lptstrCPDir = NULL;
  448. DBG_ENTER(_T("fxocUpg_MoveFiles"), dwReturn);
  449. if ( (fxState_IsUpgrade() != FXSTATE_UPGRADE_TYPE_W2K) &&
  450. !(prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER) )
  451. {
  452. //
  453. // This is not PFW / SBS 5.0 Server upgrade. Do nothing
  454. //
  455. VERBOSE(DBG_MSG, _T("No need to Move any Files from any Folders."));
  456. return dwReturn;
  457. }
  458. //
  459. // Find Destination Folder : COMMON APP DATA + ServiceCPDir from the Registry
  460. //
  461. if (!GetServerCpDir(NULL, tszDestination, MAX_PATH))
  462. {
  463. dwReturn = GetLastError();
  464. VERBOSE(DBG_WARNING, _T("GetServerCPDir() failed, ec=%ld."), dwReturn);
  465. return dwReturn;
  466. }
  467. if (fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_W2K)
  468. {
  469. //
  470. // PFW Server CP Dir is stored at SaveSettings() in prv_Data.lptstrPFWCommonCPDir
  471. //
  472. dwReturn = prv_MoveCoverPages(prv_Data.tszCommonCPDir, tszDestination, CP_PREFIX_W2K);
  473. if (dwReturn != NO_ERROR)
  474. {
  475. VERBOSE(DBG_WARNING, _T("prv_MoveCoverPages() for Win2K failed, ec = %ld"), dwReturn);
  476. }
  477. }
  478. if (prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER)
  479. {
  480. //
  481. // Get SBS Server CP Dir
  482. //
  483. dwReturn = prv_GetSBSServerCPDir(lptstrCPDir);
  484. if (dwReturn != NO_ERROR)
  485. {
  486. VERBOSE(DBG_WARNING, _T("prv_GetSBSServerCPDir() failed, ec=%ld"), dwReturn);
  487. return dwReturn;
  488. }
  489. //
  490. // Move Cover Pages
  491. //
  492. dwReturn = prv_MoveCoverPages(lptstrCPDir, tszDestination, CP_PREFIX_SBS);
  493. if (dwReturn != NO_ERROR)
  494. {
  495. VERBOSE(DBG_WARNING, _T("prv_MoveCoverPages() for SBS failed, ec = %ld"), dwReturn);
  496. }
  497. MemFree(lptstrCPDir);
  498. }
  499. return dwReturn;
  500. }
  501. static DWORD
  502. prv_MoveCoverPages(
  503. LPTSTR lptstrSourceDir,
  504. LPTSTR lptstrDestDir,
  505. LPTSTR lptstrPrefix
  506. )
  507. /*++
  508. Routine name : prv_MoveCoverPages
  509. Routine description:
  510. Move all the Cover Pages from Source folder to Destination folder
  511. and add a prefix to all the Cover Page names.
  512. Author:
  513. Iv Garber (IvG), Mar, 2001
  514. Arguments:
  515. lptstrSourceDir [IN] - Source Directory where Cover Pages are reside before the upgrade
  516. lptstrDestDir [IN] - where the Cover Pages should reside after the upgrade
  517. lptstrPrefix [IN] - prefix that should be added to the Cover Page file names
  518. Return Value:
  519. Success or Failure Error Code.
  520. --*/
  521. {
  522. DWORD dwReturn = ERROR_SUCCESS;
  523. TCHAR szSearch[MAX_PATH] = {0};
  524. HANDLE hFind = NULL;
  525. WIN32_FIND_DATA FindFileData = {0};
  526. TCHAR szFrom[MAX_PATH] = {0};
  527. TCHAR szTo[MAX_PATH] = {0};
  528. DBG_ENTER(_T("prv_MoveCoverPages"), dwReturn);
  529. if ((!lptstrSourceDir) || (_tcslen(lptstrSourceDir) == 0))
  530. {
  531. //
  532. // we do not know from where to take Cover Pages
  533. //
  534. dwReturn = ERROR_INVALID_PARAMETER;
  535. VERBOSE(DBG_WARNING, _T("SourceDir is NULL. Cannot move Cover Pages. Exiting..."));
  536. return dwReturn;
  537. }
  538. if ((!lptstrDestDir) || (_tcslen(lptstrDestDir) == 0))
  539. {
  540. //
  541. // we do not know where to put the Cover Pages
  542. //
  543. dwReturn = ERROR_INVALID_PARAMETER;
  544. VERBOSE(DBG_WARNING, _T("DestDir is NULL. Cannot move Cover Pages. Exiting..."));
  545. return dwReturn;
  546. }
  547. //
  548. // Find all Cover Page files in the given Source Directory
  549. //
  550. _sntprintf(
  551. szSearch,
  552. ARR_SIZE(szSearch) -1,
  553. _T("%s\\*.cov"),
  554. lptstrSourceDir);
  555. hFind = FindFirstFile(szSearch, &FindFileData);
  556. if (INVALID_HANDLE_VALUE == hFind)
  557. {
  558. dwReturn = GetLastError();
  559. VERBOSE(DBG_WARNING,
  560. _T("FindFirstFile() on %s folder for Cover Pages is failed, ec = %ld"),
  561. lptstrSourceDir,
  562. dwReturn);
  563. return dwReturn;
  564. }
  565. //
  566. // Go for each Cover Page
  567. //
  568. do
  569. {
  570. //
  571. // This is full current Cover Page file name
  572. //
  573. _sntprintf(szFrom, ARR_SIZE(szFrom) -1, _T("%s\\%s"), lptstrSourceDir, FindFileData.cFileName);
  574. //
  575. // This is full new Cover Page file name
  576. //
  577. _sntprintf(szTo, ARR_SIZE(szTo) -1, _T("%s\\%s_%s"), lptstrDestDir, lptstrPrefix, FindFileData.cFileName);
  578. //
  579. // Move the file
  580. //
  581. if (!MoveFile(szFrom, szTo))
  582. {
  583. dwReturn = GetLastError();
  584. VERBOSE(DBG_WARNING, _T("MoveFile() for %s Cover Page failed, ec=%ld"), szFrom, dwReturn);
  585. }
  586. } while(FindNextFile(hFind, &FindFileData));
  587. VERBOSE(DBG_MSG, _T("last call to FindNextFile() returns %ld."), GetLastError());
  588. //
  589. // Close Handle
  590. //
  591. FindClose(hFind);
  592. return dwReturn;
  593. }
  594. static DWORD prv_GetPFWCommonCPDir(
  595. )
  596. /*++
  597. Routine name : prv_GetPFWCommonCPDir
  598. Routine description:
  599. Return Folder for Common Cover Pages used for PFW.
  600. This Folder is equal to : CSIDL_COMMON_DOCUMENTS + Localized Dir
  601. This Localized Dir name we can take from the Resource of Win2K's FaxOcm.Dll.
  602. So, this function should be called BEFORE Copy/Delete Files of Install that will remove old FaxOcm.Dll.
  603. Currently it is called at SaveSettings(), which IS called before CopyFiles.
  604. Author:
  605. Iv Garber (IvG), Mar, 2001
  606. Return Value:
  607. static DWORD -- failure or success
  608. --*/
  609. {
  610. DWORD dwReturn = NO_ERROR;
  611. HMODULE hModule = NULL;
  612. TCHAR tszName[MAX_PATH] = {0};
  613. DBG_ENTER(_T("prv_GetPFWCommonCPDir"), dwReturn);
  614. //
  615. // find full path to FaxOcm.Dll
  616. //
  617. if (!GetSpecialPath(CSIDL_SYSTEM, tszName, ARR_SIZE(tszName)))
  618. {
  619. dwReturn = GetLastError();
  620. VERBOSE(DBG_WARNING, _T("GetSpecialPath(CSIDL_SYSTEM) failed, ec = %ld"), dwReturn);
  621. return dwReturn;
  622. }
  623. if ((_tcslen(tszName) + _tcslen(FAXOCM_NAME) + 1 ) >= ARR_SIZE(tszName)) // 1 for '\'
  624. {
  625. //
  626. // not enough place
  627. //
  628. dwReturn = ERROR_OUTOFMEMORY;
  629. VERBOSE(DBG_WARNING, _T("FaxOcm.Dll path is too long, ec = %ld"), dwReturn);
  630. return dwReturn;
  631. }
  632. _tcscat(tszName, _T("\\"));
  633. _tcscat(tszName, FAXOCM_NAME);
  634. VERBOSE(DBG_MSG, _T("Full Name of FaxOcm is %s"), tszName);
  635. hModule = LoadLibraryEx(tszName, NULL, LOAD_LIBRARY_AS_DATAFILE);
  636. if (!hModule)
  637. {
  638. dwReturn = GetLastError();
  639. VERBOSE(DBG_WARNING, _T("LoadLibrary(%s) failed, ec = %ld."), tszName, dwReturn);
  640. return dwReturn;
  641. }
  642. dwReturn = LoadString(hModule, CPDIR_RESOURCE_ID, tszName, MAX_PATH);
  643. if (dwReturn == 0)
  644. {
  645. //
  646. // Resource string is not found
  647. //
  648. dwReturn = GetLastError();
  649. VERBOSE(DBG_WARNING, _T("LoadString() failed, ec = %ld."), dwReturn);
  650. goto Exit;
  651. }
  652. VERBOSE(DBG_MSG, _T("FaxOcm returned '%s'"), tszName);
  653. //
  654. // Take the Base part of the Folder name
  655. //
  656. if (!GetSpecialPath(CSIDL_COMMON_DOCUMENTS, prv_Data.tszCommonCPDir,ARR_SIZE(prv_Data.tszCommonCPDir)))
  657. {
  658. dwReturn = GetLastError();
  659. VERBOSE(DBG_WARNING, _T("GetSpecialPath(CSIDL_COMMON_DOCUMENTS) failed, ec = %ld"), dwReturn);
  660. prv_Data.tszCommonCPDir[0] = _T('\0');
  661. goto Exit;
  662. }
  663. //
  664. // Combine the full Folder name
  665. //
  666. if ((_tcslen(tszName) + _tcslen(prv_Data.tszCommonCPDir) + 1) >= ARR_SIZE(prv_Data.tszCommonCPDir)) // 1 for '\'
  667. {
  668. //
  669. // not enough place
  670. //
  671. dwReturn = ERROR_OUTOFMEMORY;
  672. VERBOSE(DBG_WARNING, _T("Full path to the Common CP dir for PFW is too long, ec = %ld"), dwReturn);
  673. goto Exit;
  674. }
  675. _tcscat(prv_Data.tszCommonCPDir,_T("\\"));
  676. _tcscat(prv_Data.tszCommonCPDir, tszName);
  677. VERBOSE(DBG_MSG, _T("Full path for Common PFW Cover Pages is '%s'"), prv_Data.tszCommonCPDir);
  678. Exit:
  679. if (hModule)
  680. {
  681. FreeLibrary(hModule);
  682. }
  683. return dwReturn;
  684. }
  685. static DWORD prv_SaveArchives(
  686. )
  687. /*++
  688. Routine name : prv_SaveArchives
  689. Routine description:
  690. Store PFW SentItems & Inbox Archive Folder.
  691. SentItems is taken from Registry : under Fax/Archive Directory.
  692. Inbox Folders List is created by prv_StoreDevices(), that should be called before and that fills
  693. prv_Data.plptstrInboxFolder with an array of Inbox Folders.
  694. This function transforms the data in prv_Data.plptstrInboxFolders into the required format,
  695. and stores in the Registry.
  696. Frees the prv_Data.plptstrInboxFolders.
  697. Author:
  698. Iv Garber (IvG), Mar, 2001
  699. Return Value:
  700. static DWORD -- failure or success
  701. --*/
  702. {
  703. DWORD dwReturn = NO_ERROR;
  704. DWORD dwListLen = 0;
  705. DWORD dwI = 0;
  706. HKEY hFromKey = NULL;
  707. HKEY hToKey = NULL;
  708. LPTSTR lptstrFolder = NULL;
  709. LPTSTR lptstrCursor = NULL;
  710. DBG_ENTER(_T("prv_SaveArchives"), dwReturn);
  711. //
  712. // Open Registry Key to read the ArchiveDirectory value
  713. //
  714. hFromKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ);
  715. if (!hFromKey)
  716. {
  717. dwReturn = GetLastError();
  718. VERBOSE(DBG_WARNING, _T("Failed to open Registry for Fax, ec = %ld."), dwReturn);
  719. goto Exit;
  720. }
  721. //
  722. // Open Registry Key to write the Archive values
  723. //
  724. hToKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAX_SETUP, FALSE, KEY_SET_VALUE);
  725. if (!hToKey)
  726. {
  727. dwReturn = GetLastError();
  728. VERBOSE(DBG_WARNING, _T("Failed to open Registry for Fax/Setup, ec = %ld."), dwReturn);
  729. goto Exit;
  730. }
  731. //
  732. // Read & Write Outgoing Archive Folder
  733. //
  734. lptstrFolder = GetRegistryString(hFromKey, REGVAL_PFW_OUTBOXDIR, EMPTY_STRING);
  735. VERBOSE(DBG_MSG, _T("Outgoing Archive Folder is : %s"), lptstrFolder);
  736. SetRegistryString(hToKey, REGVAL_W2K_SENT_ITEMS, lptstrFolder);
  737. MemFree(lptstrFolder);
  738. lptstrFolder = NULL;
  739. //
  740. // Create valid REG_MULTI_SZ string from List of Inbox Folders
  741. //
  742. if (!prv_Data.plptstrInboxFolders || prv_Data.dwInboxFoldersCount == 0)
  743. {
  744. //
  745. // no Inbox Folders found
  746. //
  747. goto Exit;
  748. }
  749. //
  750. // Calculate the length of the string
  751. //
  752. for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
  753. {
  754. dwListLen += _tcslen(prv_Data.plptstrInboxFolders[dwI]) + 1;
  755. }
  756. //
  757. // Allocate that string
  758. //
  759. lptstrFolder = LPTSTR(MemAlloc((dwListLen + 1) * sizeof(TCHAR)));
  760. if (!lptstrFolder)
  761. {
  762. //
  763. // Not enough memory
  764. //
  765. VERBOSE(DBG_WARNING, _T("Not enough memory to store the Inbox Folders."));
  766. goto Exit;
  767. }
  768. ZeroMemory(lptstrFolder, ((dwListLen + 1) * sizeof(TCHAR)));
  769. lptstrCursor = lptstrFolder;
  770. //
  771. // Fill with the Inbox Folders
  772. //
  773. for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
  774. {
  775. if (prv_Data.plptstrInboxFolders[dwI])
  776. {
  777. _tcscpy(lptstrCursor, prv_Data.plptstrInboxFolders[dwI]);
  778. lptstrCursor += _tcslen(prv_Data.plptstrInboxFolders[dwI]) + 1;
  779. MemFree(prv_Data.plptstrInboxFolders[dwI]);
  780. }
  781. }
  782. MemFree(prv_Data.plptstrInboxFolders);
  783. prv_Data.plptstrInboxFolders = NULL;
  784. prv_Data.dwInboxFoldersCount = 0;
  785. //
  786. // Additional NULL at the end
  787. //
  788. *lptstrCursor = _T('\0');
  789. if (!SetRegistryStringMultiSz(hToKey, REGVAL_W2K_INBOX, lptstrFolder, ((dwListLen + 1) * sizeof(TCHAR))))
  790. {
  791. //
  792. // Failed to store Inbox Folders
  793. //
  794. dwReturn = GetLastError();
  795. VERBOSE(DBG_WARNING, _T("Failed to SetRegistryStringMultiSz() for W2K_Inbox, ec = %ld."), dwReturn);
  796. }
  797. Exit:
  798. if (hFromKey)
  799. {
  800. RegCloseKey(hFromKey);
  801. }
  802. if (hToKey)
  803. {
  804. RegCloseKey(hToKey);
  805. }
  806. MemFree(lptstrFolder);
  807. if (prv_Data.plptstrInboxFolders)
  808. {
  809. for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
  810. {
  811. MemFree(prv_Data.plptstrInboxFolders[dwI]);
  812. }
  813. MemFree(prv_Data.plptstrInboxFolders);
  814. prv_Data.plptstrInboxFolders = NULL;
  815. }
  816. prv_Data.dwInboxFoldersCount = 0;
  817. return dwReturn;
  818. }
  819. /*++
  820. Routine description:
  821. Copy a content of one registry key into another, using shlwapi.dll
  822. Arguments:
  823. hkeyDest [in] - handle for destination registry key
  824. lpszDestSubKeyName [in] - name of destination subkey
  825. hkeySrc [in] - handle for source registry key
  826. lpszSrcSubKeyName [in] - name of source subkey
  827. Return Value: Win32 Error code
  828. Note:
  829. If you already have an open handle to the source\dest, you can provide
  830. them are hKeySrc/hKeyDest, and set the approriate name to "".
  831. --*/
  832. DWORD
  833. CopyRegistrySubkeys2(
  834. HKEY hKeyDest,
  835. LPCTSTR lpszDestSubKeyName,
  836. HKEY hKeySrc,
  837. LPCTSTR lpszSrcSubKeyName
  838. )
  839. {
  840. DWORD ec = ERROR_SUCCESS;
  841. HKEY hKeyDestReal = NULL;
  842. // Create destination Key
  843. hKeyDestReal = OpenRegistryKey(
  844. hKeyDest,
  845. lpszDestSubKeyName,
  846. TRUE, // create
  847. KEY_WRITE);
  848. if (!hKeyDestReal)
  849. {
  850. ec = GetLastError();
  851. goto exit;
  852. }
  853. //
  854. // copy subkeys recursively
  855. //
  856. ec = SHCopyKey(hKeySrc, lpszSrcSubKeyName, hKeyDestReal, 0);
  857. if (ERROR_SUCCESS != ec)
  858. {
  859. goto exit;
  860. }
  861. exit:
  862. if (NULL != hKeyDestReal)
  863. {
  864. RegCloseKey(hKeyDestReal);
  865. }
  866. return ec;
  867. } // FaxCopyRegSubkeys
  868. ///////////////////////////////////////////////////////////////////////////////////////
  869. // Function:
  870. // FixupDevice
  871. //
  872. // Purpose:
  873. // This functions handles the adaptation of a device
  874. // in the registry from the format used in SBS2000 to the format
  875. // used by Server 2003 fax.
  876. //
  877. // Params:
  878. // None
  879. //
  880. // Return Value:
  881. // NO_ERROR - in case of success
  882. // Win32 Error code otherwise
  883. //
  884. // Author:
  885. // Mooly Beery (MoolyB) 18-Dec-2001
  886. ///////////////////////////////////////////////////////////////////////////////////////
  887. BOOL FixupDevice(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext)
  888. {
  889. WCHAR wszDeviceId[32] = {0};
  890. DWORD dwRet = ERROR_SUCCESS;
  891. BOOL bRet = TRUE;
  892. DWORD dwDeviceId = 0;
  893. HKEY hDevices = NULL;
  894. HKEY hDevice = NULL;
  895. DBG_ENTER(_T("FixupDevice"),dwRet);
  896. if (lpwstrKeyName==NULL)
  897. {
  898. goto exit;
  899. }
  900. if (wcscmp(lpwstrKeyName,REGKEY_UNASSOC_EXTENSION_DATA)==0)
  901. {
  902. VERBOSE(DBG_MSG, _T("No migration for UnassociatedExtensionData"));
  903. goto exit;
  904. }
  905. VERBOSE(DBG_MSG, _T("Migrating the %s device"),lpwstrKeyName);
  906. // convert the key name from Hex to Decimal
  907. dwDeviceId = wcstol(lpwstrKeyName,NULL,16);
  908. if (dwDeviceId==0)
  909. {
  910. VERBOSE(SETUP_ERR, _T("converting the device ID to decimal failed"));
  911. bRet = FALSE;
  912. goto exit;
  913. }
  914. if (dwDeviceId>g_LastUniqueLineId)
  915. {
  916. g_LastUniqueLineId = dwDeviceId;
  917. }
  918. if (wsprintf(wszDeviceId,L"%010d",dwDeviceId)==0)
  919. {
  920. VERBOSE(SETUP_ERR, _T("wsprintf failed"));
  921. bRet = FALSE;
  922. goto exit;
  923. }
  924. // create the new device key
  925. hDevices = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_DEVICES,TRUE,KEY_WRITE);
  926. if (hDevices==NULL)
  927. {
  928. VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_FAX_DEVICES failed (ec=%ld)"),GetLastError());
  929. bRet = FALSE;
  930. goto exit;
  931. }
  932. // create a key under HKLM\Sw\Ms\Fax\Devices\wszDeviceId
  933. hDevice = OpenRegistryKey(hDevices,wszDeviceId,TRUE,KEY_WRITE);
  934. if (hDevice==NULL)
  935. {
  936. VERBOSE(SETUP_ERR, _T("OpenRegistryKey %s failed (ec=%ld)"),wszDeviceId,GetLastError());
  937. bRet = FALSE;
  938. goto exit;
  939. }
  940. // set the 'Permanent Lineid' REG_DWORD
  941. if (!SetRegistryDword(hDevice,REGVAL_PERMANENT_LINEID,dwDeviceId))
  942. {
  943. VERBOSE(SETUP_ERR, _T("SetRegistryDword REGVAL_PERMANENT_LINEID failed (ec=%ld)"),GetLastError());
  944. bRet = FALSE;
  945. goto exit;
  946. }
  947. // create an entry under the service GUID for the device.
  948. // and copy the rest of the setting to the new location
  949. dwRet = CopyRegistrySubkeys2(hDevice, REGKEY_FAXSVC_DEVICE_GUID ,hKey,_T(""));
  950. if (dwRet!=ERROR_SUCCESS)
  951. {
  952. VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
  953. goto exit;
  954. }
  955. exit:
  956. if (hDevices)
  957. {
  958. RegCloseKey(hDevices);
  959. }
  960. if (hDevice)
  961. {
  962. RegCloseKey(hDevice);
  963. }
  964. return bRet;
  965. }
  966. ///////////////////////////////////////////////////////////////////////////////////////
  967. // Function:
  968. // FixupDevicesNode
  969. //
  970. // Purpose:
  971. // This functions handles the adaptation of the devices
  972. // in the registry from the format used in SBS2000 to the format
  973. // used by Server 2003 fax.
  974. // Each device is copied but the structure in the registry in
  975. // a little different. specifically, the device data is kept
  976. // under a GUID.
  977. //
  978. // Params:
  979. // None
  980. //
  981. // Return Value:
  982. // NO_ERROR - in case of success
  983. // Win32 Error code otherwise
  984. //
  985. // Author:
  986. // Mooly Beery (MoolyB) 18-Dec-2001
  987. ///////////////////////////////////////////////////////////////////////////////////////
  988. DWORD FixupDevicesNode()
  989. {
  990. HKEY hFax = NULL;
  991. DWORD dwRet = ERROR_SUCCESS;
  992. DBG_ENTER(_T("FixupDevicesNode"),dwRet);
  993. // enumerate all the devices, and for each, move its key under its GUID
  994. dwRet = EnumerateRegistryKeys( HKEY_LOCAL_MACHINE,
  995. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_DEVICES,
  996. FALSE,
  997. FixupDevice,
  998. NULL);
  999. VERBOSE(DBG_MSG, _T("For SBS 5.0 Server, enumerated %ld devices."), dwRet);
  1000. // write the LastUniqueLineId to HKLM\Sw\Ms\Fax.
  1001. hFax = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAXSERVER,TRUE,KEY_WRITE);
  1002. if (hFax==NULL)
  1003. {
  1004. dwRet = GetLastError();
  1005. VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_FAXSERVER failed (ec=%ld)"),dwRet);
  1006. return dwRet;
  1007. }
  1008. if (!SetRegistryDword(hFax,REGVAL_LAST_UNIQUE_LINE_ID,g_LastUniqueLineId+1))
  1009. {
  1010. dwRet = GetLastError();
  1011. VERBOSE(SETUP_ERR, _T("SetRegistryDword REGVAL_LAST_UNIQUE_LINE_ID failed (ec=%ld)"),dwRet);
  1012. return dwRet;
  1013. }
  1014. return ERROR_SUCCESS;
  1015. }
  1016. ///////////////////////////////////////////////////////////////////////////////////////
  1017. // Function:
  1018. // FixupDeviceProvider
  1019. //
  1020. // Purpose:
  1021. // This functions handles the adaptation of a device provider
  1022. // in the registry from the format used in SBS2000 to the format
  1023. // used by Server 2003 fax.
  1024. // The 'Microsoft Modem Device Provider' is not copied.
  1025. //
  1026. // Params:
  1027. // None
  1028. //
  1029. // Return Value:
  1030. // NO_ERROR - in case of success
  1031. // Win32 Error code otherwise
  1032. //
  1033. // Author:
  1034. // Mooly Beery (MoolyB) 18-Dec-2001
  1035. ///////////////////////////////////////////////////////////////////////////////////////
  1036. BOOL FixupDeviceProvider(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext)
  1037. {
  1038. DWORD dwRet = ERROR_SUCCESS;
  1039. BOOL bRet = TRUE;
  1040. HKEY hDeviceProviders = NULL;
  1041. DBG_ENTER(_T("FixupDeviceProvider"),dwRet);
  1042. if (lpwstrKeyName==NULL)
  1043. {
  1044. goto exit;
  1045. }
  1046. if (wcscmp(lpwstrKeyName,REGKEY_MODEM_PROVIDER)==0)
  1047. {
  1048. VERBOSE(DBG_MSG, _T("No migration for the Microsoft Modem Device Provider"));
  1049. goto exit;
  1050. }
  1051. VERBOSE(DBG_MSG, _T("Migrating the %s Device provider"),lpwstrKeyName);
  1052. // create a key under HKLM\Sw\Ms\Fax\Device Providers
  1053. hDeviceProviders = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_DEVICE_PROVIDER_KEY,TRUE,KEY_WRITE);
  1054. if (hDeviceProviders==NULL)
  1055. {
  1056. VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_DEVICE_PROVIDER_KEY failed (ec=%ld)"),GetLastError());
  1057. bRet = FALSE;
  1058. goto exit;
  1059. }
  1060. // create a key under HKLM\Sw\Ms\Fax\Device Providers\name
  1061. dwRet = CopyRegistrySubkeys2(hDeviceProviders,lpwstrKeyName,hKey,_T(""));
  1062. if (dwRet!=ERROR_SUCCESS)
  1063. {
  1064. VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
  1065. goto exit;
  1066. }
  1067. exit:
  1068. if (hDeviceProviders)
  1069. {
  1070. RegCloseKey(hDeviceProviders);
  1071. }
  1072. return bRet;
  1073. }
  1074. ///////////////////////////////////////////////////////////////////////////////////////
  1075. // Function:
  1076. // FixupDeviceProvidersNode
  1077. //
  1078. // Purpose:
  1079. // This functions handles the adaptation of the device providers
  1080. // in the registry from the format used in SBS2000 to the format
  1081. // used by Server 2003 fax.
  1082. // The 'Microsoft Modem Device Provider' is not copied and as for
  1083. // other FSPs, the key under which they are registered is changed
  1084. // to hold the GUID of the FSP.
  1085. //
  1086. // Params:
  1087. // None
  1088. //
  1089. // Return Value:
  1090. // NO_ERROR - in case of success
  1091. // Win32 Error code otherwise
  1092. //
  1093. // Author:
  1094. // Mooly Beery (MoolyB) 18-Dec-2001
  1095. ///////////////////////////////////////////////////////////////////////////////////////
  1096. DWORD FixupDeviceProvidersNode()
  1097. {
  1098. DWORD dwRet = ERROR_SUCCESS;
  1099. DBG_ENTER(_T("FixupDeviceProvidersNode"),dwRet);
  1100. // enumerate the rest of the FSPs, and for each, move its key under its GUID
  1101. dwRet = EnumerateRegistryKeys( HKEY_LOCAL_MACHINE,
  1102. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_DEVICE_PROVIDERS,
  1103. FALSE,
  1104. FixupDeviceProvider,
  1105. NULL);
  1106. VERBOSE(DBG_MSG, _T("For SBS 5.0 Server, enumerated %ld device providers."), dwRet);
  1107. return ERROR_SUCCESS;
  1108. }
  1109. ///////////////////////////////////////////////////////////////////////////////////////
  1110. // Function:
  1111. // FixupRoutingExtension
  1112. //
  1113. // Purpose:
  1114. // This functions handles the adaptation of a routing extension
  1115. // in the registry from the format used in SBS2000 to the format
  1116. // used by Server 2003 fax.
  1117. // The 'Microsoft Routing Extension' is not copied and as for
  1118. // other Routing extensions, they're copied as is.
  1119. //
  1120. // Params:
  1121. // None
  1122. //
  1123. // Return Value:
  1124. // NO_ERROR - in case of success
  1125. // Win32 Error code otherwise
  1126. //
  1127. // Author:
  1128. // Mooly Beery (MoolyB) 18-Dec-2001
  1129. ///////////////////////////////////////////////////////////////////////////////////////
  1130. BOOL FixupRoutingExtension(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext)
  1131. {
  1132. DWORD dwRet = ERROR_SUCCESS;
  1133. BOOL bRet = TRUE;
  1134. HKEY hRoutingExtensions = NULL;
  1135. DBG_ENTER(_T("FixupRoutingExtension"),dwRet);
  1136. if (lpwstrKeyName==NULL)
  1137. {
  1138. goto exit;
  1139. }
  1140. if (wcscmp(lpwstrKeyName,REGKEY_ROUTING_EXTENSION)==0)
  1141. {
  1142. VERBOSE(DBG_MSG, _T("No migration for the Microsoft Routing Extension"));
  1143. goto exit;
  1144. }
  1145. VERBOSE(DBG_MSG, _T("Migrating the %s Routing extension"),lpwstrKeyName);
  1146. // create a key under HKLM\Sw\Ms\Fax\Routing Extensions
  1147. hRoutingExtensions = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_ROUTING_EXTENSION_KEY,TRUE,KEY_WRITE);
  1148. if (hRoutingExtensions==NULL)
  1149. {
  1150. VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_ROUTING_EXTENSIONS failed (ec=%ld)"),GetLastError());
  1151. bRet = FALSE;
  1152. goto exit;
  1153. }
  1154. // create a key under HKLM\Sw\Ms\Fax\Routing Extensions\name
  1155. dwRet = CopyRegistrySubkeys2(hRoutingExtensions,lpwstrKeyName,hKey,_T(""));
  1156. if (dwRet!=ERROR_SUCCESS)
  1157. {
  1158. VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
  1159. goto exit;
  1160. }
  1161. exit:
  1162. if (hRoutingExtensions)
  1163. {
  1164. RegCloseKey(hRoutingExtensions);
  1165. }
  1166. return bRet;
  1167. }
  1168. ///////////////////////////////////////////////////////////////////////////////////////
  1169. // Function:
  1170. // FixupRoutingExtensionsNode
  1171. //
  1172. // Purpose:
  1173. // This functions handles the adaptation of the routing extension
  1174. // in the registry from the format used in SBS2000 to the format
  1175. // used by Server 2003 fax.
  1176. // The 'Microsoft Routing Extension' is not copied to the destination.
  1177. //
  1178. // Params:
  1179. // None
  1180. //
  1181. // Return Value:
  1182. // NO_ERROR - in case of success
  1183. // Win32 Error code otherwise
  1184. //
  1185. // Author:
  1186. // Mooly Beery (MoolyB) 18-Dec-2001
  1187. ///////////////////////////////////////////////////////////////////////////////////////
  1188. DWORD FixupRoutingExtensionsNode()
  1189. {
  1190. DWORD dwRet = ERROR_SUCCESS;
  1191. DBG_ENTER(_T("FixupRoutingExtensionsNode"),dwRet);
  1192. // enumerate the rest of the Routing Extension, and for each decide whether to copy or not.
  1193. dwRet = EnumerateRegistryKeys( HKEY_LOCAL_MACHINE,
  1194. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ROUTING_EXTENSIONS,
  1195. FALSE,
  1196. FixupRoutingExtension,
  1197. NULL);
  1198. VERBOSE(DBG_MSG, _T("For SBS 5.0 Server, enumerated %ld routing extensions."), dwRet);
  1199. return ERROR_SUCCESS;
  1200. }
  1201. struct REG_KEY_PAIR
  1202. {
  1203. LPCTSTR lpctstrSourceKey;
  1204. LPCTSTR lpctstrDestinationKey;
  1205. } g_RegKeyPairs[] =
  1206. {
  1207. { REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ACTIVITY_LOG_CONFIG,
  1208. REGKEY_FAXSERVER _T("\\") REGKEY_ACTIVITY_LOG_CONFIG
  1209. },
  1210. { REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_DEVICES _T("\\") REGKEY_UNASSOC_EXTENSION_DATA,
  1211. REGKEY_FAXSERVER _T("\\") REGKEY_DEVICES _T("\\") REGKEY_UNASSOC_EXTENSION_DATA
  1212. },
  1213. {
  1214. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_LOGGING,
  1215. REGKEY_FAXSERVER _T("\\") REGKEY_LOGGING
  1216. },
  1217. {
  1218. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ARCHIVE_INBOX_CONFIG,
  1219. REGKEY_FAXSERVER _T("\\") REGKEY_ARCHIVE_INBOX_CONFIG
  1220. },
  1221. {
  1222. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_OUTBOUND_ROUTING,
  1223. REGKEY_FAXSERVER _T("\\") REGKEY_OUTBOUND_ROUTING
  1224. },
  1225. {
  1226. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_RECEIPTS_CONFIG,
  1227. REGKEY_FAXSERVER _T("\\") REGKEY_RECEIPTS_CONFIG
  1228. },
  1229. {
  1230. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_SECURITY_CONFIG,
  1231. REGKEY_FAXSERVER _T("\\") REGKEY_SECURITY_CONFIG
  1232. },
  1233. {
  1234. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ARCHIVE_SENTITEMS_CONFIG,
  1235. REGKEY_FAXSERVER _T("\\") REGKEY_ARCHIVE_SENTITEMS_CONFIG
  1236. },
  1237. {
  1238. REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_TAPIDEVICES_CONFIG,
  1239. REGKEY_FAXSERVER _T("\\") REGKEY_TAPIDEVICES_CONFIG
  1240. }
  1241. };
  1242. const INT iCopyKeys = sizeof(g_RegKeyPairs)/sizeof(g_RegKeyPairs[0]);
  1243. LPCTSTR lpctstrValuesToCopy[] =
  1244. {
  1245. REGVAL_BRANDING,
  1246. REGVAL_DIRTYDAYS,
  1247. REGVAL_RETRIES,
  1248. REGVAL_RETRYDELAY,
  1249. REGVAL_SERVERCP,
  1250. REGVAL_STARTCHEAP,
  1251. REGVAL_STOPCHEAP,
  1252. REGVAL_USE_DEVICE_TSID
  1253. };
  1254. const INT iCopyValues = sizeof(lpctstrValuesToCopy)/sizeof(lpctstrValuesToCopy[0]);
  1255. ///////////////////////////////////////////////////////////////////////////////////////
  1256. // Function:
  1257. // fxocUpg_MoveRegistry
  1258. //
  1259. // Purpose:
  1260. // When a machine running SBS2000 server was upgraded to Windows Server 2003
  1261. // we migrate the existing registry from SBS to the fax service.
  1262. // For most registry entries, the existing format is still compatible with
  1263. // the format used by SBS2000 so we just 'move' the registry around from
  1264. // one place to the other.
  1265. // This function is responsible for moving the following subkeys under Fax:
  1266. // ActivityLogging
  1267. // Device Providers\<any other than 'Microsoft Modem Device Provider'>
  1268. // Devices\UnassociatedExtensionData
  1269. // Logging
  1270. // Inbox
  1271. // Outbound Routing
  1272. // Receipts
  1273. // Routing Extensions\<any other than 'Microsoft Routing Extension'>
  1274. // Security
  1275. // SentItems
  1276. // TAPIDevices
  1277. //
  1278. // After moving the registry, some fixup to the registry takes place in order
  1279. // to make modifications from the format used in SBS2000 to the one used
  1280. // in Server 2003 Fax.
  1281. //
  1282. // Params:
  1283. // None
  1284. //
  1285. // Return Value:
  1286. // NO_ERROR - in case of success
  1287. // Win32 Error code otherwise
  1288. //
  1289. // Author:
  1290. // Mooly Beery (MoolyB) 17-Dec-2001
  1291. ///////////////////////////////////////////////////////////////////////////////////////
  1292. DWORD fxocUpg_MoveRegistry(void)
  1293. {
  1294. INT iCount = 0;
  1295. DWORD dwRet = NO_ERROR;
  1296. HKEY hDotNetFax = NULL;
  1297. HKEY hSbsFax = NULL;
  1298. DBG_ENTER(_T("fxocUpg_MoveRegistry"),dwRet);
  1299. if ( !(prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER) )
  1300. {
  1301. VERBOSE(DBG_MSG, _T("SBS2000 was not installed, nothing to migrate"));
  1302. goto exit;
  1303. }
  1304. // Share the printer (unless printer sharing rule was specified in unattended file)
  1305. if (IsFaxShared() && !fxUnatnd_IsPrinterRuleDefined())
  1306. {
  1307. VERBOSE(DBG_MSG, _T("SBS2000 was installed, sharing printer"));
  1308. fxocPrnt_SetFaxPrinterShared(TRUE);
  1309. }
  1310. // first, we copy all the above mentioned registry from HKLM\\Sw\\Ms\\SharedFax to HKLM\\Sw\\Ms\\Fax
  1311. for (iCount=0; iCount<iCopyKeys; iCount++)
  1312. {
  1313. VERBOSE(DBG_MSG,
  1314. _T("Copying %s from %s."),
  1315. g_RegKeyPairs[iCount].lpctstrDestinationKey,
  1316. g_RegKeyPairs[iCount].lpctstrSourceKey );
  1317. dwRet = CopyRegistrySubkeys2(
  1318. HKEY_LOCAL_MACHINE, g_RegKeyPairs[iCount].lpctstrDestinationKey,
  1319. HKEY_LOCAL_MACHINE, g_RegKeyPairs[iCount].lpctstrSourceKey);
  1320. if (dwRet == ERROR_FILE_NOT_FOUND)
  1321. {
  1322. // Some reg keys may not exist. For example, TAPIDevices is created
  1323. // after first use only. So, don't fail on this error.
  1324. VERBOSE(DBG_WARNING, _T("g_RegKeyPairs[iCount].lpctstrSourceKey was not found, continuing"), g_RegKeyPairs[iCount].lpctstrSourceKey);
  1325. }
  1326. else if (dwRet!=ERROR_SUCCESS)
  1327. {
  1328. VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
  1329. goto exit;
  1330. }
  1331. }
  1332. // second, copy specific values
  1333. hDotNetFax = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAXSERVER,TRUE,KEY_WRITE);
  1334. if (hDotNetFax==NULL)
  1335. {
  1336. dwRet = GetLastError();
  1337. VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_FAXSERVER failed (ec=%ld)"),dwRet);
  1338. goto exit;
  1339. }
  1340. hSbsFax = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_SBS2000_FAX_BACKUP,TRUE,KEY_READ);
  1341. if (hSbsFax==NULL)
  1342. {
  1343. dwRet = GetLastError();
  1344. VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_SBS2000_FAX_BACKUP failed (ec=%ld)"),dwRet);
  1345. goto exit;
  1346. }
  1347. for (iCount=0; iCount<iCopyValues; iCount++)
  1348. {
  1349. DWORD dwVal = 0;
  1350. VERBOSE(DBG_MSG,_T("Copying %s."),lpctstrValuesToCopy[iCount]);
  1351. dwVal = GetRegistryDword(hSbsFax,lpctstrValuesToCopy[iCount]);
  1352. if (!SetRegistryDword(hDotNetFax,lpctstrValuesToCopy[iCount],dwVal))
  1353. {
  1354. dwRet = GetLastError();
  1355. VERBOSE(SETUP_ERR, _T("SetRegistryDword %s failed (ec=%ld)"),lpctstrValuesToCopy[iCount],dwRet);
  1356. goto exit;
  1357. }
  1358. }
  1359. // now, we have to fixup items that are not compatible
  1360. dwRet = FixupDeviceProvidersNode();
  1361. if (dwRet!=ERROR_SUCCESS)
  1362. {
  1363. VERBOSE(DBG_WARNING, _T("FixupDeviceProvidersNode() failed, ec = %ld."), dwRet);
  1364. goto exit;
  1365. }
  1366. dwRet = FixupDevicesNode();
  1367. if (dwRet!=ERROR_SUCCESS)
  1368. {
  1369. VERBOSE(DBG_WARNING, _T("FixupDevicesNode() failed, ec = %ld."), dwRet);
  1370. goto exit;
  1371. }
  1372. dwRet = FixupRoutingExtensionsNode();
  1373. if (dwRet!=ERROR_SUCCESS)
  1374. {
  1375. VERBOSE(DBG_WARNING, _T("FixupRoutingExtensionsNode() failed, ec = %ld."), dwRet);
  1376. goto exit;
  1377. }
  1378. // Set security on Inbox, SentItems and ActivityLog dirs
  1379. dwRet = SetDirSecurityFromReg(REGKEY_SOFTWARE TEXT("\\") REGKEY_ACTIVITY_LOG_CONFIG, REGVAL_ACTIVITY_LOG_DB, SD_FAX_FOLDERS);
  1380. if (dwRet!=ERROR_SUCCESS)
  1381. {
  1382. VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
  1383. goto exit;
  1384. }
  1385. dwRet = SetDirSecurityFromReg(REGKEY_SOFTWARE TEXT("\\") REGKEY_ARCHIVE_SENTITEMS_CONFIG, REGVAL_ARCHIVE_FOLDER, SD_FAX_FOLDERS);
  1386. if (dwRet!=ERROR_SUCCESS)
  1387. {
  1388. VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
  1389. goto exit;
  1390. }
  1391. dwRet = SetDirSecurityFromReg(REGKEY_SOFTWARE TEXT("\\") REGKEY_ARCHIVE_INBOX_CONFIG, REGVAL_ARCHIVE_FOLDER, SD_FAX_FOLDERS);
  1392. if (dwRet!=ERROR_SUCCESS)
  1393. {
  1394. VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
  1395. goto exit;
  1396. }
  1397. // last, let's delete the SharedFaxBackup key from the registry.
  1398. if (!DeleteRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_SBS2000_FAX_BACKUP))
  1399. {
  1400. dwRet = GetLastError();
  1401. VERBOSE(DBG_WARNING, _T("DeleteRegistryKey() failed, ec = %ld."), dwRet);
  1402. goto exit;
  1403. }
  1404. exit:
  1405. if (hSbsFax)
  1406. {
  1407. RegCloseKey(hSbsFax);
  1408. }
  1409. if (hDotNetFax)
  1410. {
  1411. RegCloseKey(hDotNetFax);
  1412. }
  1413. return dwRet;
  1414. }