Source code of Windows XP (NT5)
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.

526 lines
13 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. migrate.c
  5. Abstract:
  6. This source file implements the windows 9x DEVUPGRD migration dll.
  7. Author:
  8. Marc R. Whitten (marcw) 07-January-2000
  9. Revision History:
  10. Ovidiu Temereanca (ovidiut) 04-Aug-2000 Fixed bugs and support for INF-less paths
  11. --*/
  12. #include "pch.h"
  13. VENDORINFO g_VendorInfo = {"", "", "", ""};
  14. CHAR g_ProductId [MAX_PATH];
  15. PCSTR g_MigrateInfPath = NULL;
  16. HINF g_MigrateInf = INVALID_HANDLE_VALUE;
  17. HANDLE g_hHeap;
  18. HINSTANCE g_hInst;
  19. TCHAR g_DllDir[MAX_TCHAR_PATH];
  20. #define D_DLLVERSION 2
  21. #undef DEFMAC
  22. #define MEMDB_CATEGORY_DLLENTRIES "MigDllEntries"
  23. #define S_ACTIVE "Active"
  24. #define DBG_MIGDLL "SMIGDLL"
  25. //
  26. // the temp file that records original sources location
  27. //
  28. #define S_MIGRATEDATA "migrate.dat"
  29. #define S_MIGRATEDATW L"migrate.dat"
  30. #define S_SECTION_DATAA "Data"
  31. #define S_SECTION_DATAW L"Data"
  32. #define S_KEY_SOURCESA "Sources"
  33. #define S_KEY_SOURCESW L"Sources"
  34. PCSTR g_WorkingDir = NULL;
  35. PCSTR g_DataFileA = NULL;
  36. PCWSTR g_DataFileW = NULL;
  37. typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID);
  38. INITROUTINE_PROTOTYPE MigUtil_Entry;
  39. POOLHANDLE g_GlobalPool;
  40. #define DEVREGKEY "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup\\UpgradeDrivers"
  41. BOOL
  42. WINAPI
  43. DllMain (
  44. IN HINSTANCE DllInstance,
  45. IN ULONG ReasonForCall,
  46. IN LPVOID Reserved
  47. )
  48. {
  49. PSTR p;
  50. BOOL result = TRUE;
  51. switch (ReasonForCall) {
  52. case DLL_PROCESS_ATTACH:
  53. //
  54. // We don't need DLL_THREAD_ATTACH or DLL_THREAD_DETACH messages
  55. //
  56. DisableThreadLibraryCalls (DllInstance);
  57. //
  58. // Global init
  59. //
  60. g_hHeap = GetProcessHeap();
  61. g_hInst = DllInstance;
  62. //
  63. // Init common controls
  64. //
  65. InitCommonControls();
  66. //
  67. // Get DLL path and strip directory
  68. //
  69. GetModuleFileNameA (DllInstance, g_DllDir, MAX_TCHAR_PATH);
  70. p = strrchr (g_DllDir, '\\');
  71. MYASSERT (p);
  72. if (p) {
  73. *p = 0;
  74. }
  75. if (!MigUtil_Entry (DllInstance, DLL_PROCESS_ATTACH, NULL)) {
  76. return FALSE;
  77. }
  78. //
  79. // Allocate a global pool
  80. //
  81. g_GlobalPool = PoolMemInitNamedPool ("Global Pool");
  82. break;
  83. case DLL_PROCESS_DETACH:
  84. if (g_MigrateInfPath) {
  85. FreePathStringA (g_MigrateInfPath);
  86. g_MigrateInfPath = NULL;
  87. }
  88. if (g_MigrateInf != INVALID_HANDLE_VALUE) {
  89. InfCloseInfFile (g_MigrateInf);
  90. g_MigrateInf = INVALID_HANDLE_VALUE;
  91. }
  92. //
  93. // Free standard pools
  94. //
  95. if (g_GlobalPool) {
  96. PoolMemDestroyPool (g_GlobalPool);
  97. g_GlobalPool = NULL;
  98. }
  99. MigUtil_Entry (DllInstance, DLL_PROCESS_DETACH, NULL);
  100. break;
  101. }
  102. return result;
  103. }
  104. LONG
  105. CALLBACK
  106. QueryVersion (
  107. OUT PCSTR *ProductID,
  108. OUT PUINT DllVersion,
  109. OUT PINT *CodePageArray, OPTIONAL
  110. OUT PCSTR *ExeNamesBuf, OPTIONAL
  111. OUT PVENDORINFO *VendorInfo
  112. )
  113. {
  114. LONG result = ERROR_NOT_INSTALLED;
  115. PCSTR tempStr;
  116. HANDLE h;
  117. //
  118. // Fill the data.
  119. //
  120. tempStr = GetStringResourceA (MSG_PRODUCT_ID);
  121. if (tempStr) {
  122. StringCopyByteCountA (g_ProductId, tempStr, MAX_PATH);
  123. FreeStringResourceA (tempStr);
  124. }
  125. *ProductID = g_ProductId;
  126. *DllVersion = D_DLLVERSION;
  127. *CodePageArray = NULL;
  128. *VendorInfo = &g_VendorInfo;
  129. // now get the VendorInfo data from resources
  130. tempStr = GetStringResourceA (MSG_VI_COMPANY_NAME);
  131. if (tempStr) {
  132. StringCopyByteCountA (g_VendorInfo.CompanyName, tempStr, 256);
  133. FreeStringResourceA (tempStr);
  134. }
  135. tempStr = GetStringResourceA (MSG_VI_SUPPORT_NUMBER);
  136. if (tempStr) {
  137. StringCopyByteCountA (g_VendorInfo.SupportNumber, tempStr, 256);
  138. FreeStringResourceA (tempStr);
  139. }
  140. tempStr = GetStringResourceA (MSG_VI_SUPPORT_URL);
  141. if (tempStr) {
  142. StringCopyByteCountA (g_VendorInfo.SupportUrl, tempStr, 256);
  143. FreeStringResourceA (tempStr);
  144. }
  145. tempStr = GetStringResourceA (MSG_VI_INSTRUCTIONS);
  146. if (tempStr) {
  147. StringCopyByteCountA (g_VendorInfo.InstructionsToUser, tempStr, 1024);
  148. FreeStringResourceA (tempStr);
  149. }
  150. *ExeNamesBuf = NULL;
  151. //
  152. // See if the registry key exists. If it does not, return ERROR_NOT_INSTALLED.
  153. //
  154. h = OpenRegKeyStr (DEVREGKEY);
  155. if (h && h != INVALID_HANDLE_VALUE) {
  156. result = ERROR_SUCCESS;
  157. CloseRegKey (h);
  158. }
  159. return result;
  160. }
  161. LONG
  162. CALLBACK
  163. Initialize9x (
  164. IN PCSTR WorkingDirectory,
  165. IN PCSTR SourceDirectories,
  166. IN PCSTR MediaDir
  167. )
  168. {
  169. //
  170. // remember source directory, so it can be removed on cleanup
  171. //
  172. g_DataFileA = JoinPathsExA (g_GlobalPool, WorkingDirectory, S_MIGRATEDATA);
  173. WritePrivateProfileStringA (S_SECTION_DATAA, S_KEY_SOURCESA, MediaDir, g_DataFileA);
  174. g_WorkingDir = DuplicatePathString (WorkingDirectory, 0);
  175. g_MigrateInfPath = JoinPathsExA (g_GlobalPool, WorkingDirectory, S_MIGRATE_INF);
  176. g_MigrateInf = InfOpenInfFileA (g_MigrateInfPath);
  177. return ERROR_SUCCESS;
  178. }
  179. LONG
  180. CALLBACK
  181. MigrateUser9x (
  182. IN HWND ParentWnd,
  183. IN PCSTR UnattendFile,
  184. IN HKEY UserRegKey,
  185. IN PCSTR UserName,
  186. PVOID Reserved
  187. )
  188. {
  189. return ERROR_SUCCESS;
  190. }
  191. LONG
  192. CALLBACK
  193. MigrateSystem9x (
  194. IN HWND ParentWnd,
  195. IN PCSTR UnattendFile,
  196. PVOID Reserved
  197. )
  198. {
  199. HANDLE h;
  200. REGVALUE_ENUM eValue;
  201. REGTREE_ENUM eTree;
  202. BOOL found;
  203. PSTR value;
  204. PSTR p;
  205. PSTR end;
  206. PSTR dir;
  207. CHAR deviceInf [MEMDB_MAX];
  208. HASHTABLE table;
  209. PSTR pnpId;
  210. DWORD attr;
  211. table = HtAllocWithData (sizeof (PSTR));
  212. if (!table) {
  213. return ERROR_OUTOFMEMORY;
  214. }
  215. __try {
  216. //
  217. // Gather list of pnpids registered on this machine.
  218. //
  219. h = OpenRegKeyStrA (DEVREGKEY);
  220. if (!h || h == INVALID_HANDLE_VALUE) {
  221. return ERROR_NOT_INSTALLED;
  222. }
  223. if (EnumFirstRegValue (&eValue, h)) {
  224. do {
  225. p = GetRegValueStringA (h, eValue.ValueName);
  226. if (!p) {
  227. continue;
  228. }
  229. value = PoolMemDuplicateStringA (g_GlobalPool, p);
  230. MemFree (g_hHeap, 0, p);
  231. if (!value) {
  232. return ERROR_OUTOFMEMORY;
  233. }
  234. HtAddStringAndDataA (table, eValue.ValueName, &value);
  235. } while (EnumNextRegValue (&eValue));
  236. }
  237. CloseRegKey (h);
  238. //
  239. // Now, enumerate the registry.
  240. //
  241. if (EnumFirstRegKeyInTreeA (&eTree, "HKLM\\Enum")) {
  242. do {
  243. //
  244. // For each registry key, look to see if we have a compatible id or hardware id
  245. // that is in our hash table.
  246. //
  247. found = FALSE;
  248. value = GetRegValueStringA (eTree.CurrentKey->KeyHandle, "HardwareId");
  249. if (value) {
  250. if (HtFindStringAndDataA (table, value, &dir)) {
  251. found = TRUE;
  252. pnpId = PoolMemDuplicateStringA (g_GlobalPool, value);
  253. } else {
  254. p = value;
  255. while (p && !found) {
  256. end = _mbschr (p, ',');
  257. if (end) {
  258. *end = 0;
  259. }
  260. if (HtFindStringAndDataA (table, p, &dir)) {
  261. found = TRUE;
  262. pnpId = PoolMemDuplicateStringA (g_GlobalPool, p);
  263. }
  264. else {
  265. p = end;
  266. if (p) {
  267. p++;
  268. }
  269. }
  270. }
  271. }
  272. MemFree (g_hHeap, 0, value);
  273. }
  274. if (!found) {
  275. value = GetRegValueStringA (eTree.CurrentKey->KeyHandle, "CompatibleIds");
  276. if (value) {
  277. if (HtFindStringAndDataA (table, value, &dir)) {
  278. found = TRUE;
  279. pnpId = PoolMemDuplicateStringA (g_GlobalPool, value);
  280. }
  281. p = value;
  282. while (p && !found) {
  283. end = _mbschr (p, ',');
  284. if (end) {
  285. *end = 0;
  286. }
  287. if (HtFindStringAndDataA (table, p, &dir)) {
  288. found = TRUE;
  289. pnpId = PoolMemDuplicateStringA (g_GlobalPool, p);
  290. }
  291. else {
  292. p = end;
  293. if (p) {
  294. p++;
  295. }
  296. }
  297. }
  298. MemFree (g_hHeap, 0, value);
  299. }
  300. }
  301. if (found) {
  302. //
  303. // build path to deviceInf (no OriginalInstallMedia since the directory will be blown away)
  304. //
  305. lstrcpyA (deviceInf, dir);
  306. //
  307. // GUI setup expects a path to the actual INF, not a directory,
  308. // so let's fix it if this is the case
  309. //
  310. attr = GetFileAttributesA (deviceInf);
  311. if (attr == (DWORD)-1) {
  312. //
  313. // invalid path spec; ignore it
  314. //
  315. continue;
  316. }
  317. if (attr & FILE_ATTRIBUTE_DIRECTORY) {
  318. //
  319. // just pick up the first INF
  320. //
  321. HANDLE h;
  322. WIN32_FIND_DATAA fd;
  323. PSTR pattern;
  324. pattern = JoinPathsExA (g_GlobalPool, deviceInf, "*.inf");
  325. h = FindFirstFileA (pattern, &fd);
  326. if (h == INVALID_HANDLE_VALUE) {
  327. //
  328. // no INF found here; skip
  329. //
  330. continue;
  331. }
  332. FindClose (h);
  333. //
  334. // build path to the INF; also handle the case when deviceInf ends with a \
  335. //
  336. pattern = JoinPathsExA (g_GlobalPool, deviceInf, fd.cFileName);
  337. lstrcpyA (deviceInf, pattern);
  338. }
  339. //
  340. // Handle the key (remove the message from the compatibility report).
  341. //
  342. WritePrivateProfileStringA (
  343. "HANDLED",
  344. eTree.FullKeyName,
  345. "REGISTRY",
  346. g_MigrateInfPath
  347. );
  348. //
  349. // Add to the appropriate section of the SIF file.
  350. //
  351. WritePrivateProfileString (
  352. "DeviceDrivers",
  353. pnpId,
  354. deviceInf,
  355. UnattendFile
  356. );
  357. //
  358. // Flush to disk.
  359. //
  360. WritePrivateProfileString (NULL, NULL, NULL, g_MigrateInfPath);
  361. WritePrivateProfileString (NULL, NULL, NULL, UnattendFile);
  362. }
  363. } while (EnumNextRegKeyInTree (&eTree));
  364. }
  365. }
  366. __finally {
  367. //
  368. // Clean up resources.
  369. //
  370. HtFree (table);
  371. }
  372. return ERROR_SUCCESS;
  373. }
  374. LONG
  375. CALLBACK
  376. InitializeNT (
  377. IN PCWSTR WorkingDirectory,
  378. IN PCWSTR SourceDirectories,
  379. PVOID Reserved
  380. )
  381. {
  382. g_DataFileW = JoinPathsExW (g_GlobalPool, WorkingDirectory, S_MIGRATEDATW);
  383. return ERROR_SUCCESS;
  384. }
  385. LONG
  386. CALLBACK
  387. MigrateUserNT (
  388. IN HINF UnattendInfHandle,
  389. IN HKEY UserRegKey,
  390. IN PCWSTR UserName,
  391. PVOID Reserved
  392. )
  393. {
  394. return ERROR_SUCCESS;
  395. }
  396. LONG
  397. CALLBACK
  398. MigrateSystemNT (
  399. IN HINF UnattendInfHandle,
  400. PVOID Reserved
  401. )
  402. {
  403. WCHAR SourceDirectory[MAX_PATH + 2];
  404. //
  405. // remove original sources directories
  406. //
  407. if (GetPrivateProfileStringW (
  408. S_SECTION_DATAW,
  409. S_KEY_SOURCESW,
  410. L"",
  411. SourceDirectory,
  412. MAX_PATH + 2,
  413. g_DataFileW
  414. )) {
  415. RemoveCompleteDirectoryW (SourceDirectory);
  416. }
  417. return ERROR_SUCCESS;
  418. }