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.

627 lines
19 KiB

  1. #include "pch.h"
  2. #include <ole2.h>
  3. #include "advpub.h"
  4. #include "sdsutils.h"
  5. #include "migrate.h"
  6. #include "utils.h"
  7. BOOL AppendString(LPSTR *lpBuffer, DWORD *lpdwSize, LPCSTR lpStr)
  8. {
  9. DWORD cbBufferUsed = 0;
  10. DWORD dwNewSize = 0;
  11. LPSTR lpTmp = NULL;
  12. DWORD dwLen = 0;
  13. // Sanity check
  14. if (lpStr == NULL || *lpStr == '\0')
  15. return FALSE;
  16. if (*lpBuffer == NULL)
  17. {
  18. // Allocate the buffer.
  19. *lpdwSize = sizeof(char) * MAX_PATH;
  20. *lpBuffer = (char *) LocalAlloc(LPTR, *lpdwSize);
  21. if (*lpBuffer == NULL)
  22. {
  23. #ifdef DEBUG
  24. SetupLogError("IE6: AppendString memory failure\r\n",LogSevInformation);
  25. #endif
  26. return FALSE;
  27. }
  28. }
  29. dwNewSize = lstrlen(lpStr);
  30. // Get the number of bytes used up, excluding the second terminating NULL (-1)
  31. cbBufferUsed = CountMultiStringBytes((LPCSTR)*lpBuffer) - 1;
  32. if ( (*lpdwSize - cbBufferUsed) < (dwNewSize + 2))
  33. {
  34. LPSTR lpNewBuffer = NULL;
  35. DWORD dwTemp = 0;
  36. // Need to reallocate.
  37. dwTemp = *lpdwSize + (max((sizeof(char) * MAX_PATH), dwNewSize+2));
  38. lpNewBuffer = (char *) LocalAlloc(LPTR,dwTemp);
  39. if ( lpNewBuffer == NULL)
  40. {
  41. #ifdef DEBUG
  42. SetupLogError("IE6: AppendString memory failure\r\n",LogSevInformation);
  43. #endif
  44. return FALSE;
  45. }
  46. else
  47. {
  48. // Rearrange the IN pointer to point to the new block.
  49. // Copy over the old info to the new allocated block.
  50. // +1 for the one that we subtracted above.
  51. CopyMemory(lpNewBuffer, *lpBuffer, cbBufferUsed+1);
  52. // Free the old buffer.
  53. LocalFree(*lpBuffer);
  54. // Point to the new buffer.
  55. *lpBuffer = (char *) lpNewBuffer;
  56. *lpdwSize = dwTemp;
  57. }
  58. }
  59. // Append the new string now.
  60. lpTmp = *lpBuffer + cbBufferUsed;
  61. lstrcpy(lpTmp,lpStr);
  62. // Add the second terminating NULL to it now.
  63. lpTmp += (dwNewSize + 1);
  64. *lpTmp = '\0';
  65. return TRUE;
  66. }
  67. // NOTE NOTE: This function is called during the QueryVersion phase. Hence it needs to be small and fast
  68. // So we just do the check for the presence of the "HKLM\S\M\W\CV\Policies\Ratings" key and don't try to
  69. // verify using MSRating API.
  70. #define REGVAL_KEY "Key"
  71. BOOL IsRatingsEnabled()
  72. {
  73. HKEY hKey;
  74. BOOL bRet = FALSE;
  75. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,REGKEY_RATING,KEY_READ,NULL,&hKey) == ERROR_SUCCESS)
  76. {
  77. DWORD dwType;
  78. if (RegQueryValueEx(hKey,REGVAL_KEY,NULL,&dwType, NULL, NULL) == ERROR_SUCCESS
  79. && dwType == REG_BINARY)
  80. {
  81. #ifdef DEBUG
  82. SetupLogError("IE6: Located RATINGS\Key", LogSevInformation);
  83. #endif
  84. // The Ratings key exists and Password has been set. Means Ratings
  85. // is enabled.
  86. bRet = TRUE;
  87. }
  88. RegCloseKey(hKey);
  89. }
  90. return bRet;
  91. }
  92. // Returns the number of used bytes in a double NULL terminated string, including the two NULLS.
  93. DWORD CountMultiStringBytes (LPCSTR lpString)
  94. {
  95. DWORD cbBytes;
  96. LPSTR lpTmp;
  97. DWORD dwLen;
  98. // Sanity check
  99. if (lpString == NULL)
  100. return 0;
  101. // Get to the double \0 termination of lpBuffer
  102. lpTmp = (LPSTR)lpString;
  103. cbBytes = 1;
  104. while (lpTmp && *lpTmp != '\0')
  105. {
  106. dwLen = lstrlen(lpTmp) + 1;
  107. lpTmp = lpTmp + dwLen;
  108. cbBytes += dwLen;
  109. }
  110. return cbBytes;
  111. }
  112. BOOL PathEndsInFile(LPSTR lpPath, LPCSTR lpFile)
  113. {
  114. LPSTR pTmp = lpPath;
  115. // Sanity check
  116. if (lpPath == NULL || lpFile == NULL)
  117. return FALSE;
  118. #ifdef DEBUG
  119. char szDebug[MAX_PATH*3];
  120. wsprintf(szDebug,"IE5 (PathEndsInFile): %s :: %s \r\n", lpPath, lpFile);
  121. SetupLogError(szDebug,LogSevInformation);
  122. #endif
  123. // Point pTmp to the terminating NULL
  124. pTmp = lpPath + lstrlen(lpPath);
  125. while (*pTmp != '\\' && pTmp != lpPath)
  126. {
  127. pTmp = CharPrev(lpPath, pTmp);
  128. }
  129. pTmp = CharNext(pTmp);
  130. #ifdef DEBUG
  131. wsprintf(szDebug,"IE5 (PathEndsInFile): %s :: %s \r\n", pTmp, lpFile);
  132. SetupLogError(szDebug,LogSevInformation);
  133. #endif
  134. return (lstrcmpi(pTmp, lpFile) == 0);
  135. }
  136. // Helper function to get the path for "Ratings.pol" from the MIGRATE.INF
  137. // The path is returned in a buffer allocated by the function.
  138. // **********************************************************************
  139. // *** NOTE *** : It is the caller function responsibilty to free memory.
  140. // **********************************************************************
  141. // Parameters:
  142. // lpOutBuffer: Ptr to variable to hold the new string allocated.
  143. // User can pass in NULL if only interested in existance of Ratings.pol
  144. // and not the actual path to it.
  145. BOOL GetRatingsPathFromMigInf( LPSTR *lpOutBuffer)
  146. {
  147. INFCONTEXT ic;
  148. HINF hInf;
  149. BOOL bFound = FALSE;
  150. LPSTR lpBuf = NULL;
  151. DWORD dwSize, dwNewSize;
  152. if (lpOutBuffer)
  153. *lpOutBuffer = NULL;
  154. dwSize = MAX_PATH;
  155. lpBuf = (char *) LocalAlloc(LPTR, sizeof(char)*dwSize);
  156. if (lpBuf == NULL)
  157. return FALSE;
  158. // Before calling the migration DLL, Setup sets the CurrentDirectory to
  159. // the directory assigned to that migration DLL. Hence can use this.
  160. //hInf = SetupOpenInfFile(cszMIGRATEINF, NULL, INF_STYLE_WIN4, NULL);
  161. hInf = SetupOpenInfFile(g_szMigrateInf, NULL, INF_STYLE_WIN4, NULL);
  162. if (hInf)
  163. {
  164. #ifdef DEBUG
  165. SetupLogError("IE6: Opened Miginf.inf \r\n", LogSevInformation);
  166. #endif
  167. if (SetupFindFirstLine(hInf,cszMIGINF_MIGRATION_PATHS,NULL,&ic))
  168. {
  169. do
  170. {
  171. dwNewSize = 0;
  172. if( SetupGetLineTextA(&ic,hInf,NULL,NULL,lpBuf,dwSize,&dwNewSize) == 0 && dwNewSize > dwSize)
  173. { // Need more buffer space
  174. // Free the old buffer space.
  175. LocalFree(lpBuf);
  176. // Try and allocate a new buffer.
  177. dwSize = dwNewSize;
  178. lpBuf = (char *) LocalAlloc(LPTR, sizeof(char)*dwSize);
  179. if (lpBuf == NULL)
  180. {
  181. // Memory Error - break out.
  182. break;
  183. }
  184. if (!SetupGetLineTextA(&ic,hInf,NULL,NULL,lpBuf,dwSize,&dwNewSize))
  185. {
  186. // The bFound check below takes care of LocalFree(lpBuf);
  187. #ifdef DEBUG
  188. SetupLogError("IE6: Error doing SetupGetTextLineA \r\n", LogSevInformation);
  189. #endif
  190. break; // Failure can't help it.
  191. }
  192. }
  193. // So managed to read out the line. Check if it contains .pol
  194. if (PathEndsInFile(lpBuf,cszRATINGSFILE))
  195. {
  196. if (lpOutBuffer)
  197. {
  198. *lpOutBuffer = lpBuf;
  199. }
  200. else
  201. { // User is not interested in Path. Free the block.
  202. LocalFree(lpBuf);
  203. }
  204. bFound = TRUE;
  205. #ifdef DEBUG
  206. SetupLogError("IE6: Found Ratings.Pol in Migrate.Inf \r\n", LogSevInformation);
  207. #endif
  208. }
  209. }
  210. while (!bFound && SetupFindNextLine(&ic,&ic));
  211. }
  212. SetupCloseInfFile(hInf);
  213. }
  214. if (!bFound)
  215. {
  216. // Free the local buffer.
  217. LocalFree(lpBuf);
  218. }
  219. return bFound;
  220. }
  221. //******************************************************************************
  222. // GenerateFilePaths:
  223. // NOTE NOTE NOTE: The migration DLL remains loaded from the "Initialize9x" phase
  224. // right till the end of the "MigrateSystem9x" phase. And again from "InitializeNT" phase
  225. // right till the end of the "MigrateSystemNT" phase. Hence these paths are usable
  226. // through out.
  227. //*******************************************************************************
  228. void GenerateFilePaths()
  229. {
  230. *g_szMigrateInf = '\0';
  231. *g_szPrivateInf = '\0';
  232. if (g_lpWorkingDir)
  233. {
  234. // generate the path to the Migrate.Inf file
  235. wsprintf(g_szMigrateInf, "%s\\%s", g_lpWorkingDir, cszMIGRATEINF);
  236. #ifdef DEBUG
  237. char szDebug[MAX_PATH];
  238. wsprintf(szDebug,"IE6: g_szMigrateInf: %s \r\n",g_szMigrateInf);
  239. SetupLogError(szDebug,LogSevInformation);
  240. #endif
  241. // generate the path to the Private.Inf file
  242. wsprintf(g_szPrivateInf, "%s\\%s", g_lpWorkingDir, cszPRIVATEINF);
  243. #ifdef DEBUG
  244. wsprintf(szDebug,"IE6: g_szPrivateInf: %s \r\n",g_szPrivateInf);
  245. SetupLogError(szDebug,LogSevInformation);
  246. #endif
  247. }
  248. }
  249. #define IE_KEY "Software\\Microsoft\\Internet Explorer"
  250. #define VERSION_KEY "Version"
  251. BOOL NeedToMigrateIE()
  252. {
  253. BOOL bRet = FALSE;
  254. char szPath[MAX_PATH];
  255. DWORD dwInstalledVer, dwInstalledBuild;
  256. // Currently, the only thing we are interested in are the Ratings settings.
  257. if (IsRatingsEnabled())
  258. {
  259. // Append the "ratings.pol" filename to the list of files needed.
  260. // NOTE: AppendString allocates memory for the 1st parameter. User
  261. // must remember to free it.
  262. bRet |= AppendString(&g_lpNameBuf, &g_dwNameBufSize, cszRATINGSFILE);
  263. }
  264. if (!bRet)
  265. {
  266. GetSystemDirectory(szPath, sizeof(szPath));
  267. AddPath(szPath, "shdocvw.dll");
  268. GetVersionFromFile(szPath, &dwInstalledVer, &dwInstalledBuild, TRUE);
  269. // are running with IE5.5 installed.
  270. bRet = (dwInstalledVer == 0x00050032);
  271. }
  272. // Can add other modules that need to be migrated over here.
  273. // use bRet |= (....) so that you don't stomp previous bRet settings.
  274. return bRet;
  275. }
  276. void MyDelRegTree(HKEY hRoot, LPSTR szSubKey)
  277. {
  278. char szName[MAX_PATH];
  279. DWORD dwIndex;
  280. DWORD dwNameSize;
  281. HKEY hKey;
  282. dwIndex = 0;
  283. dwNameSize = sizeof(szName);
  284. if (RegOpenKeyEx(hRoot, szSubKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  285. {
  286. while (RegEnumKey(hKey, dwIndex, szName, dwNameSize) == ERROR_SUCCESS)
  287. {
  288. MyDelRegTree(hKey,szName);
  289. // dwIndex++; DONT INCR. SINCE WE HAVE DELETED A SUBKEY.
  290. dwNameSize = sizeof(szName);
  291. }
  292. RegCloseKey(hKey);
  293. //Finally delete the named subkey supplied above.
  294. RegDeleteKey(hRoot, szSubKey);
  295. }
  296. }
  297. // Recursively Enum values and subkey and copy them over. And then
  298. // delete all subkeys of the Source key.
  299. void MoveRegBranch(HKEY hFromKey, HKEY hToKey)
  300. {
  301. char szName[MAX_PATH];
  302. char szValue[MAX_PATH];
  303. DWORD dwNameSize;
  304. DWORD dwValueSize;
  305. DWORD dwType;
  306. DWORD dwIndex;
  307. // Enumerate all the values here and copy them over to the right
  308. // location.
  309. dwIndex = 0;
  310. dwNameSize = sizeof(szName);
  311. dwValueSize = sizeof(szValue);
  312. while (RegEnumValue(hFromKey,dwIndex, szName, &dwNameSize, NULL,
  313. &dwType, (LPBYTE)szValue, &dwValueSize) == ERROR_SUCCESS)
  314. {
  315. RegSetValueEx(hToKey,szName,0,dwType,(LPBYTE)szValue, dwValueSize);
  316. // Get ready for the next round.
  317. dwIndex++;
  318. dwNameSize = sizeof(szName);
  319. dwValueSize = sizeof(szValue);
  320. }
  321. // Next Enum all the subkeys under source and move them over.
  322. dwIndex = 0;
  323. dwNameSize = sizeof(szName);
  324. while (RegEnumKey(hFromKey, dwIndex, szName, dwNameSize) == ERROR_SUCCESS)
  325. {
  326. HKEY hFromSubKey = NULL;
  327. HKEY hToSubKey = NULL;
  328. // Open this SubKey that we enumerated.
  329. if (RegOpenKeyEx(hFromKey, szName, 0, KEY_ALL_ACCESS, &hFromSubKey) == ERROR_SUCCESS)
  330. {
  331. // Create the destination subkey.
  332. if (RegCreateKeyEx(hToKey, szName, 0, NULL,REG_OPTION_NON_VOLATILE,
  333. KEY_ALL_ACCESS, NULL, &hToSubKey, NULL) == ERROR_SUCCESS)
  334. {
  335. // Move the subkeys...
  336. MoveRegBranch(hFromSubKey, hToSubKey);
  337. RegCloseKey(hToSubKey);
  338. }
  339. RegCloseKey(hFromSubKey);
  340. }
  341. // Get ready for the next round
  342. dwIndex++;
  343. dwNameSize = sizeof(szName);
  344. }
  345. // Now Delete all the SubKeys. The above recursive call ensures that
  346. // the Subkeys are one-level deep and hence deletable.
  347. dwIndex = 0;
  348. dwNameSize = sizeof(szName);
  349. while (RegEnumKey(hFromKey, dwIndex, szName, dwNameSize) == ERROR_SUCCESS)
  350. {
  351. RegDeleteKey(hFromKey,szName);
  352. // dwIndex++; DONT INCR. SINCE WE HAVE DELETED A SUBKEY.
  353. dwNameSize = sizeof(szName);
  354. }
  355. }
  356. #define REGKEY_DEFAULT ".Default"
  357. #define REGKEY_MIGRATE_HIVE "Software\\Microsoft\\Policies\\Users"
  358. #define REGKEY_MIGRATE_PICSRULES "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Ratings\\PICSRules"
  359. #define REGKEY_RATING_PICSRULES "PICSRules"
  360. BOOL UpgradeRatings()
  361. {
  362. // Real Ratings locations...
  363. // HKLM\S\M\W\CV\Policies\Ratings (called RATING)
  364. // Open HKLM\software\Microsoft\Policies\Users.. This is where NT Setup puts
  365. // the migrated Ratings HIVE.
  366. // Users [FileNamex] gets copied to RATING [FileNamex]
  367. // NOTE: Need to take care of SYSTEM/SYSTEM32.
  368. // Users\.Default branch gets moved to RATING
  369. // Users\S\M\W\CV\Policies\Ratings\PICSRules branch gets moved to RATING.
  370. HKEY hRealRatings = NULL;
  371. HKEY hRealDefault = NULL;
  372. HKEY hRealPicsRules = NULL;
  373. HKEY hMigratedRoot = NULL;
  374. BOOL bRet = FALSE;
  375. // Open the RegKey to the real location of Ratings.
  376. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_RATING, 0, KEY_ALL_ACCESS,
  377. &hRealRatings) != ERROR_SUCCESS)
  378. goto Done;
  379. // Open the RegKey to the real location of .Default
  380. if (RegCreateKeyEx(hRealRatings, REGKEY_DEFAULT, 0,
  381. NULL,REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hRealDefault, NULL) != ERROR_SUCCESS)
  382. goto Done;
  383. // Open the RegKey to the real location of PICSRules
  384. if (RegCreateKeyEx(hRealRatings, REGKEY_RATING_PICSRULES, 0,
  385. NULL,REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hRealPicsRules, NULL) != ERROR_SUCCESS)
  386. goto Done;
  387. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_MIGRATE_HIVE, 0, KEY_ALL_ACCESS, &hMigratedRoot) == ERROR_SUCCESS)
  388. {
  389. HKEY hMigrateSubKey = NULL;
  390. char szName[MAX_PATH];
  391. char szValue[MAX_PATH];
  392. DWORD dwNameSize;
  393. DWORD dwValueSize;
  394. DWORD dwType;
  395. char szNewPath[MAX_PATH];
  396. DWORD dwNewPathSize;
  397. DWORD dwIndex;
  398. // Enumerate all the values here and copy them over to the right
  399. // location. Make sure to replace 'System' with 'System32'
  400. dwIndex = 0;
  401. dwNameSize = sizeof(szName);
  402. dwValueSize = sizeof(szValue);
  403. while (RegEnumValue(hMigratedRoot,dwIndex, szName, &dwNameSize, NULL,
  404. &dwType, (LPBYTE)szValue, &dwValueSize) == ERROR_SUCCESS)
  405. {
  406. // Munge the Value and replace 'System' with System32.
  407. // Return value includes the terminating NULL char, which is
  408. // need by the RegSetValueEx API.
  409. dwNewPathSize = GetFixedPath(szNewPath, MAX_PATH, szValue);
  410. // Set the correct Ratings setting.
  411. RegSetValueEx(hRealRatings,szName,0,dwType,(LPBYTE)szNewPath, dwNewPathSize);
  412. // Get ready for the next round.
  413. dwIndex++;
  414. dwNameSize = sizeof(szName);
  415. dwValueSize = sizeof(szValue);
  416. }
  417. // Now grab Users\.Default and move it to the right location.
  418. if (RegOpenKeyEx(hMigratedRoot, REGKEY_DEFAULT, 0, KEY_ALL_ACCESS, &hMigrateSubKey) == ERROR_SUCCESS)
  419. {
  420. MoveRegBranch(hMigrateSubKey,hRealDefault);
  421. RegCloseKey(hMigrateSubKey);
  422. }
  423. // Now grab Users\...\PICSRules and move it to the right location.
  424. if (RegOpenKeyEx(hMigratedRoot, REGKEY_MIGRATE_PICSRULES, 0, KEY_ALL_ACCESS, &hMigrateSubKey) == ERROR_SUCCESS)
  425. {
  426. MoveRegBranch(hMigrateSubKey,hRealPicsRules);
  427. RegCloseKey(hMigrateSubKey);
  428. }
  429. RegCloseKey(hMigratedRoot);
  430. bRet = TRUE;
  431. }
  432. // Now clean the Migrated Hive.
  433. MyDelRegTree(HKEY_LOCAL_MACHINE, REGKEY_MIGRATE_HIVE);
  434. Done:
  435. if (hRealRatings)
  436. RegCloseKey(hRealRatings);
  437. if (hRealDefault)
  438. RegCloseKey(hRealDefault);
  439. if (hRealPicsRules)
  440. RegCloseKey(hRealPicsRules);
  441. return bRet;
  442. }
  443. // Returns the size of NewPath including the terminating NULL.
  444. DWORD GetFixedPath(LPSTR lpBuf, DWORD dwSize, LPCSTR lpPath)
  445. {
  446. char lpLocalCopy[MAX_PATH], szTemp[5];
  447. char chSave;
  448. DWORD dwCount = 0;
  449. LPSTR pTmp, pTmp2;
  450. if (lpBuf == NULL || lpPath == NULL)
  451. return 0;
  452. // Create a local copy to party on.
  453. lstrcpy(lpLocalCopy, lpPath);
  454. pTmp = lpLocalCopy;
  455. *lpBuf = '\0';
  456. while (*pTmp && dwCount < dwSize)
  457. {
  458. pTmp2 = pTmp;
  459. while(*pTmp2 && *pTmp2 != '\\')
  460. pTmp2 = CharNext(pTmp2);
  461. chSave = *pTmp2;
  462. *pTmp2 = '\0';
  463. if (lstrcmpi(pTmp,"system")==0)
  464. {
  465. dwCount += 8;
  466. if (dwSize <= dwCount)
  467. { //Error
  468. *lpBuf = '\0';
  469. return 0;
  470. }
  471. lstrcat(lpBuf,"system32");
  472. }
  473. else
  474. {
  475. dwCount += lstrlen(pTmp);
  476. if (dwSize <= dwCount)
  477. { // Error
  478. *lpBuf = '\0';
  479. return 0;
  480. }
  481. lstrcat(lpBuf,pTmp);
  482. }
  483. // Append the saved character to Output buffer also.
  484. wsprintf(szTemp,"%c",chSave);
  485. dwCount += lstrlen(szTemp);
  486. if (dwSize <= dwCount)
  487. { // Error
  488. *lpBuf = '\0';
  489. return 0;
  490. }
  491. lstrcat(lpBuf, szTemp);
  492. *pTmp2 = chSave;
  493. pTmp = CharNext(pTmp2);
  494. }
  495. return dwCount;
  496. }
  497. LPWSTR MakeWideStrFromAnsi(LPSTR psz)
  498. {
  499. LPWSTR pwsz;
  500. int i;
  501. // arg checking.
  502. //
  503. if (!psz)
  504. return NULL;
  505. // compute the length of the required BSTR
  506. //
  507. i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  508. if (i <= 0) return NULL;
  509. // allocate the widestr
  510. //
  511. pwsz = (LPWSTR) CoTaskMemAlloc(i * sizeof(WCHAR));
  512. if (!pwsz)
  513. return NULL;
  514. MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i);
  515. pwsz[i - 1] = 0;
  516. return pwsz;
  517. }