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.

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