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.

486 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation
  6. //
  7. // File: migrate.cpp
  8. // xiaoyuw @ 2001/09
  9. //
  10. //--------------------------------------------------------------------------
  11. #include <stdio.h>
  12. #include <windows.h>
  13. #include <setupapi.h>
  14. #include <shlwapi.h>
  15. // migration DLL version information
  16. typedef struct {
  17. CHAR CompanyName[256];
  18. CHAR SupportNumber[256];
  19. CHAR SupportUrl[256];
  20. CHAR InstructionsToUser[1024];
  21. } VENDORINFO, *PVENDORINFO;
  22. typedef struct {
  23. SIZE_T Size;
  24. PCSTR StaticProductIdentifier;
  25. UINT DllVersion;
  26. PINT CodePageArray;
  27. UINT SourceOs;
  28. UINT TargetOs;
  29. PCSTR * NeededFileList;
  30. PVENDORINFO VendorInfo;
  31. } MIGRATIONINFOA, *PMIGRATIONINFOA;
  32. typedef enum {
  33. OS_WINDOWS9X = 0,
  34. OS_WINDOWSNT4X = 1,
  35. OS_WINDOWS2000 = 2,
  36. OS_WINDOWSWHISTLER = 3
  37. } OS_TYPES, *POS_TYPES;
  38. PMIGRATIONINFOA g_MigrationInfo = NULL;
  39. const char g_szProductId[] = "Microsoft MSI Migration DLL v2.0";
  40. VENDORINFO g_VendorInfo = { "Microsoft", "", "", "" };
  41. // registry keys of note
  42. const char szSideBySideKeyName[] = "Software\\Microsoft\\Windows\\CurrentVersion\\SideBySide";
  43. const char szMigrateStatusKeyName[] = "Software\\Microsoft\\Windows\\CurrentVersion\\SideBySide\\MigrateMsiInstalledAssembly";
  44. const char szRunOnceValueName[] = "Cleanup Msi 2.0 Migration";
  45. const char szRunOnceSetupRegKey[]= "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
  46. const char szRunOnceValueCommandLine[]="reg.exe delete HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SideBySide\\MigrateMsiInstalledAssembly /f";
  47. typedef HRESULT (__stdcall *LPDLLGETVERSION)(DLLVERSIONINFO *);
  48. typedef enum _FUSION_MSI_OS_VERSION
  49. {
  50. E_OS_UNKNOWN,
  51. E_WIN95,
  52. E_WIN_ME,
  53. E_WIN_NT,
  54. E_WIN98,
  55. E_WIN2K,
  56. E_WHISTLER,
  57. E_WIN32_OTHERS
  58. } FUSION_MSI_OS_VERSION;
  59. typedef enum _FUSION_MSI_OS_TYPE
  60. {
  61. E_PERSONAL,
  62. E_PROFESSIONAL,
  63. E_DATA_CENTER,
  64. E_STD_SERVER,
  65. E_ADV_SERVER,
  66. E_WORKSTATION,
  67. E_SERVER
  68. } FUSION_MSI_OS_TYPE;
  69. HRESULT SxspGetOSVersion(FUSION_MSI_OS_VERSION & osv)
  70. {
  71. HRESULT hr = S_OK;
  72. OSVERSIONINFO osvi;
  73. BOOL bOsVersionInfoEx;
  74. osv = E_OS_UNKNOWN;
  75. if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
  76. {
  77. // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
  78. osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  79. if (!GetVersionEx((OSVERSIONINFO *) &osvi))
  80. {
  81. hr = HRESULT_FROM_WIN32(::GetLastError());
  82. goto Exit;
  83. }
  84. }
  85. switch (osvi.dwPlatformId)
  86. {
  87. case VER_PLATFORM_WIN32_NT:
  88. if ( osvi.dwMajorVersion <= 4 )
  89. osv = E_WIN_NT;
  90. else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
  91. osv = E_WIN2K;
  92. else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
  93. osv = E_WHISTLER;
  94. case VER_PLATFORM_WIN32_WINDOWS:
  95. if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
  96. osv = E_WIN95;
  97. else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
  98. osv = E_WIN98;
  99. else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
  100. osv = E_WIN_ME;
  101. break;
  102. case VER_PLATFORM_WIN32s:
  103. osv = E_WIN32_OTHERS;
  104. break;
  105. }
  106. Exit:
  107. return hr;
  108. }
  109. BOOL IsMigrationDone()
  110. {
  111. HKEY hk = NULL;
  112. LONG iRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigrateStatusKeyName, 0, KEY_EXECUTE, &hk);
  113. RegCloseKey(hk);
  114. if (iRet == ERROR_SUCCESS) // the migration is done already
  115. return TRUE; // no further migration
  116. else
  117. return FALSE;
  118. }
  119. /*
  120. BOOL IsW9xOrNT(FUSION_MSI_OS_VERSION &osv)
  121. {
  122. osv = E_OS_UNKNOWN;
  123. if (SUCCEEDED(SxspGetOSVersion(osv)))
  124. {
  125. if ((osv != E_WIN98) && (osv != E_WIN2K))
  126. {
  127. return FALSE;
  128. }
  129. }
  130. else
  131. {
  132. return FALSE;
  133. }
  134. return TRUE;
  135. }
  136. */
  137. /*
  138. BOOL IsMsi20Installed()
  139. {
  140. BOOL fInstalled = FALSE;
  141. HMODULE hMSI = ::LoadLibraryA("MSI");
  142. if (hMSI)
  143. {
  144. LPDLLGETVERSION pfVersion = (LPDLLGETVERSION)::GetProcAddress(hMSI, "DllGetVersion");
  145. if (pfVersion)
  146. {
  147. // MSI detected. Determine version.
  148. DLLVERSIONINFO VersionInfo;
  149. VersionInfo.cbSize = sizeof(DLLVERSIONINFO);
  150. (*pfVersion)(&VersionInfo);
  151. if (VersionInfo.dwMajorVersion < 2)
  152. {
  153. fInstalled = FALSE; // we only deal with Winfuse Assemblise installed using msi2.0.
  154. }
  155. else
  156. {
  157. fInstalled = TRUE;
  158. }
  159. }
  160. ::FreeLibrary(hMSI);
  161. }
  162. return fInstalled;
  163. }
  164. */
  165. void DbgPrintMessageBox(PCSTR pszFunc)
  166. {
  167. #if DBG
  168. CHAR str[256];
  169. sprintf(str, "In %s of migrate.dll", pszFunc);
  170. MessageBox(NULL, str, "migrate", MB_OK);
  171. #endif
  172. }
  173. typedef HRESULT (_stdcall * PFN_MigrateFusionWin32AssemblyToXP)(PCWSTR pszInstallerDir);
  174. LONG MigrateMSIInstalledWin32Assembly()
  175. {
  176. LONG lResult = ERROR_SUCCESS;
  177. PFN_MigrateFusionWin32AssemblyToXP pfMigrateSystemNT;
  178. HMODULE hNTMig = ::LoadLibraryA("fusemig");
  179. if (!hNTMig)
  180. {
  181. // always return success. Its too late for any meaningful
  182. // error recovery
  183. return ERROR_SUCCESS;
  184. }
  185. pfMigrateSystemNT = (PFN_MigrateFusionWin32AssemblyToXP)GetProcAddress(hNTMig, "MsiInstallerDirectoryDirWalk");
  186. if (pfMigrateSystemNT)
  187. {
  188. lResult = (pfMigrateSystemNT)(NULL) & 0X0000FFFF;
  189. }
  190. FreeLibrary(hNTMig);
  191. //
  192. // set the RegKey about the work is done already
  193. //
  194. {
  195. DWORD dwDisposition = 0;
  196. HKEY hkey = NULL;
  197. if ( ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, szSideBySideKeyName, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkey, NULL)){ // create or open
  198. RegCloseKey(hkey);
  199. HKEY hkey2 = NULL;
  200. if ( ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, szMigrateStatusKeyName, 0, NULL, 0, KEY_EXECUTE, NULL, &hkey2, NULL)){ // not care it fails or successes
  201. RegCloseKey(hkey2);
  202. }
  203. }
  204. RegCloseKey(hkey);
  205. }
  206. // return the result from the actual migration call
  207. return lResult;
  208. }
  209. VOID SetRunOnceDeleteMigrationDoneRegKey()
  210. {
  211. // Create if not exist or just open RegKey : HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce\Setup
  212. HKEY hk = NULL;
  213. if ( ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRunOnceSetupRegKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, NULL))
  214. {
  215. // we do not care it success or fail, we could live with it
  216. RegSetValueEx(hk, szRunOnceValueName, 0, REG_SZ, (CONST BYTE *)szRunOnceValueCommandLine,
  217. strlen(szRunOnceValueCommandLine) + 1); // containing the trailing NULL
  218. }
  219. RegCloseKey(hk);
  220. return;
  221. }
  222. ///////////////////////////////////////////////////////////////////////
  223. //
  224. // API of WIN-NT MIGRATION Dll
  225. //
  226. ///////////////////////////////////////////////////////////////////////
  227. LONG CALLBACK QueryMigrationInfoA(PMIGRATIONINFOA * VersionInfo)
  228. {
  229. FUSION_MSI_OS_VERSION osv;
  230. DbgPrintMessageBox("QueryMigrationInfo");
  231. if (IsMigrationDone())
  232. {
  233. return ERROR_NOT_INSTALLED; // no further migration
  234. }
  235. /*
  236. if (IsW9xOrNT(osv) == FALSE) // we only work on w9x and win2K
  237. {
  238. return ERROR_NOT_INSTALLED; // no further migration
  239. }
  240. */
  241. // only work for Win98 and win2k upgrade to winxp !!!
  242. if (VersionInfo != NULL)
  243. {
  244. if (g_MigrationInfo == NULL)
  245. {
  246. g_MigrationInfo = (PMIGRATIONINFOA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIGRATIONINFOA));
  247. if (g_MigrationInfo == NULL)
  248. return ERROR_NOT_ENOUGH_MEMORY;
  249. g_MigrationInfo->Size = sizeof(MIGRATIONINFOA);
  250. g_MigrationInfo->StaticProductIdentifier = g_szProductId;
  251. g_MigrationInfo->DllVersion = 200;
  252. g_MigrationInfo->CodePageArray = NULL;
  253. g_MigrationInfo->SourceOs = (osv == E_WIN98 ? OS_WINDOWS9X : OS_WINDOWS2000);
  254. g_MigrationInfo->TargetOs = OS_WINDOWSWHISTLER;
  255. g_MigrationInfo->NeededFileList = NULL;
  256. g_MigrationInfo->VendorInfo = &g_VendorInfo;
  257. *VersionInfo = g_MigrationInfo;
  258. }
  259. }
  260. return ERROR_SUCCESS;
  261. }
  262. LONG InitializeOnSource()
  263. {
  264. /*
  265. // attempt to load MSI.DLL and grab the version. If this fails, MSI is not
  266. // installed and there is no need for any further migration
  267. if (IsMsi20Installed())
  268. return ERROR_SUCCESS;
  269. else
  270. {
  271. #if DBG
  272. MessageBox(NULL, "MSI version of 2.0 or above is NOT installed, QUIT the migration", "migrate", MB_OK);
  273. #endif
  274. return ERROR_NOT_INSTALLED;
  275. }
  276. */
  277. return ERROR_SUCCESS;
  278. }
  279. ///////////////////////////////////////////////////////////////////////
  280. LONG __stdcall InitializeSrcA(LPCSTR WorkingDirectory, LPCSTR SourceDirectories, LPCSTR MediaDirectory, PVOID Reserved)
  281. {
  282. DbgPrintMessageBox("InitializeSrcA");
  283. return InitializeOnSource();
  284. }
  285. /////////////////////////////////////////////////////////////////////////////
  286. LONG CALLBACK GatherUserSettingsA(LPCSTR AnswerFile, HKEY UserRegKey, LPCSTR UserName, LPVOID Reserved)
  287. {
  288. DbgPrintMessageBox("GatherUserSettingsA");
  289. return ERROR_SUCCESS;
  290. }
  291. LONG CALLBACK GatherSystemSettingsA(LPCSTR AnswerFile, LPVOID Reserved)
  292. {
  293. DbgPrintMessageBox("GatherSystemSettingsA");
  294. return ERROR_SUCCESS;
  295. }
  296. ///////////////////////////////////////////////////////////////////////
  297. // Initialization routine on WinNT. Just stores of the migration
  298. // working directory.
  299. LONG CALLBACK InitializeDstA(LPCSTR WorkingDirectory, LPCSTR SourceDirectories, LPVOID Reserved)
  300. {
  301. DbgPrintMessageBox("InitializeDstA");
  302. return ERROR_SUCCESS;
  303. }
  304. ///////////////////////////////////////////////////////////////////////
  305. LONG CALLBACK ApplyUserSettingsA(
  306. HINF AnswerFileHandle,
  307. HKEY UserRegKey,
  308. LPCSTR UserName,
  309. LPCSTR UserDomain,
  310. LPCSTR FixedUserName,
  311. LPVOID Reserved)
  312. {
  313. DbgPrintMessageBox("ApplyUserSettingsA");
  314. return ERROR_SUCCESS;
  315. }
  316. ///////////////////////////////////////////////////////////////////////
  317. // Called once on NT
  318. LONG CALLBACK ApplySystemSettingsA(HINF UnattendInfHandle, LPVOID Reserved)
  319. {
  320. DbgPrintMessageBox("ApplySystemSettingsA");
  321. LONG lResult = MigrateMSIInstalledWin32Assembly();
  322. SetRunOnceDeleteMigrationDoneRegKey();
  323. return lResult;
  324. }
  325. BOOL
  326. WINAPI
  327. DllMain(
  328. HINSTANCE hinstDLL,
  329. DWORD fdwReason,
  330. LPVOID lpvReserved
  331. )
  332. {
  333. switch (fdwReason)
  334. {
  335. case DLL_PROCESS_ATTACH:
  336. g_MigrationInfo = NULL;
  337. break;
  338. case DLL_PROCESS_DETACH:
  339. if (g_MigrationInfo != NULL)
  340. {
  341. if (lpvReserved != NULL)
  342. {
  343. HeapFree(GetProcessHeap(), 0, g_MigrationInfo);
  344. }
  345. g_MigrationInfo = NULL;
  346. }
  347. break;
  348. }
  349. return TRUE;
  350. }
  351. ///////////////////////////////////////////////////////////////////////
  352. //
  353. // API of WIN9X MIGRATION Dll
  354. //
  355. ///////////////////////////////////////////////////////////////////////
  356. ///////////////////////////////////////////////////////////////////////
  357. // called by setup to extract migration DLL version and support
  358. // information.
  359. LONG CALLBACK QueryVersion(LPCSTR *ProductID, LPUINT DllVersion, LPINT *CodePageArray,
  360. LPCSTR *ExeNamesBuf, PVENDORINFO *VendorInfo)
  361. {
  362. FUSION_MSI_OS_VERSION osv;
  363. DbgPrintMessageBox("QueryVersion");
  364. if (IsMigrationDone())
  365. {
  366. return ERROR_NOT_INSTALLED; // no further migration
  367. }
  368. /*
  369. if (IsW9xOrNT(osv) == FALSE) // we only work on w9x and win2K
  370. {
  371. return ERROR_NOT_INSTALLED; // no further migration
  372. }
  373. */
  374. // product ID information
  375. *ProductID = g_szProductId;
  376. *DllVersion = 200;
  377. // DLL is language independent.
  378. *CodePageArray = NULL;
  379. // no EXE search is required
  380. *ExeNamesBuf = NULL;
  381. // vendor information
  382. *VendorInfo = &g_VendorInfo;
  383. return ERROR_SUCCESS;
  384. }
  385. ///////////////////////////////////////////////////////////////////////
  386. LONG __stdcall Initialize9x(LPCSTR WorkingDirectory, LPCSTR SourceDirectories, LPCSTR MediaDirectory)
  387. {
  388. DbgPrintMessageBox("Initialize9x");
  389. return InitializeOnSource();
  390. }
  391. /////////////////////////////////////////////////////////////////////////////
  392. LONG CALLBACK MigrateUser9x(HWND ParentWnd, LPCSTR AnswerFile, HKEY UserRegKey, LPCSTR UserName, LPVOID Reserved)
  393. {
  394. DbgPrintMessageBox("MigrateUser9x");
  395. return ERROR_SUCCESS;
  396. }
  397. LONG CALLBACK MigrateSystem9x(HWND ParentWnd, LPCSTR AnswerFile, LPVOID Reserved)
  398. {
  399. DbgPrintMessageBox("MigrateSystem9x");
  400. return ERROR_SUCCESS;
  401. }
  402. ///////////////////////////////////////////////////////////////////////
  403. LONG CALLBACK InitializeNT(LPCWSTR WorkingDirectory, LPCWSTR SourceDirectories, LPVOID Reserved)
  404. {
  405. DbgPrintMessageBox("InitializeNT");
  406. return ERROR_SUCCESS;
  407. }
  408. ///////////////////////////////////////////////////////////////////////
  409. LONG CALLBACK MigrateUserNT(HINF AnswerFileHandle, HKEY UserRegKey, LPCWSTR UserName, LPVOID Reserved)
  410. {
  411. DbgPrintMessageBox("MigrateUserNT");
  412. return ERROR_SUCCESS;
  413. }
  414. typedef HRESULT (_stdcall * PFN_MigrateFusionWin32AssemblyToXP)(PCWSTR pszInstallerDir);
  415. ///////////////////////////////////////////////////////////////////////
  416. LONG CALLBACK MigrateSystemNT(HINF UnattendInfHandle, LPVOID Reserved)
  417. {
  418. DbgPrintMessageBox("MigrateSystemNT");
  419. LONG lResult = MigrateMSIInstalledWin32Assembly();
  420. SetRunOnceDeleteMigrationDoneRegKey();
  421. return lResult;
  422. }