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.

1450 lines
33 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. dosmignt.c
  5. Abstract:
  6. handles windows nt side migration of config.sys and autoexec.bat information
  7. gathered during win9x upgrading. migrates environement settings, prompts, and
  8. some doskey information. Also modifies the autoexec.nt and config.nt files.
  9. Author:
  10. Marc R. Whitten (marcw) 15-Feb-1997
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #include "w95upgnt.h"
  15. #define DBG_DOSMIG "Dosmig"
  16. //
  17. // Flag that is set if Doskey /INSERT needs to be set.
  18. //
  19. BOOL g_MigrateDoskeySetting = FALSE;
  20. //
  21. // PoolMem Handle to pool used for dynamic allocations.
  22. //
  23. POOLHANDLE g_Pool = NULL;
  24. //
  25. // Flag that is set if all necessary data has been collected for migration.
  26. //
  27. BOOL g_MigrationPrepared = FALSE;
  28. //
  29. // String that points to the current file being processed.
  30. //
  31. PCTSTR g_CurrentFile = NULL;
  32. PCTSTR g_LastFile = NULL;
  33. //
  34. // Boolean flag indicating wether any changes were made to the flag.
  35. //
  36. BOOL g_FileChanged = FALSE;
  37. //
  38. // The suppression table holds environment variables we want to ignore.
  39. //
  40. HASHTABLE g_SuppressionTable = NULL;
  41. //
  42. // List of path segments.
  43. //
  44. GROWLIST g_PathList = GROWLIST_INIT;
  45. #define STRINGBUFFER(x) ((PTSTR) (x)->Buf)
  46. #define BUFFEREMPTY(x) ((x)->End == 0)
  47. typedef enum {
  48. DOSMIG_UNUSED,
  49. DOSMIG_BAD,
  50. DOSMIG_UNKNOWN,
  51. DOSMIG_USE,
  52. DOSMIG_MIGRATE,
  53. DOSMIG_IGNORE,
  54. DOSMIG_LAST
  55. } DOSMIG_LINETAG, *PDOSMIG_LINETAG;
  56. PCTSTR
  57. pGetFileNameStartFromPath (
  58. IN PCTSTR Line
  59. )
  60. /*++
  61. Routine Description:
  62. This function returns the start of a File name in a(n assumed
  63. wellformed) path.
  64. Arguments:
  65. Line - The String containing the path and filename.
  66. Return Value:
  67. A pointer to the filename portion of the path. Note, this function
  68. assumes that there may be (potentially valuable) arguments after the
  69. file name. The pointer does not, therefore point only
  70. --*/
  71. {
  72. PCTSTR lineStart = Line;
  73. PCTSTR lineEnd = Line;
  74. if (Line == NULL) {
  75. return NULL;
  76. }
  77. while (_istalnum(*lineEnd) ||
  78. *lineEnd == TEXT('_') ||
  79. *lineEnd == TEXT('.') ||
  80. *lineEnd == TEXT('\\') ||
  81. *lineEnd == TEXT(':')) {
  82. if((*lineEnd == TEXT('\\')) || (*lineEnd == TEXT(':'))) {
  83. lineStart = _tcsinc(lineEnd);
  84. }
  85. lineEnd = _tcsinc(lineEnd);
  86. }
  87. return lineStart;
  88. }
  89. LONG
  90. pSaveBufferToAnsiFile (
  91. IN PCTSTR Path,
  92. IN PCTSTR Buffer
  93. )
  94. {
  95. HANDLE fileHandle;
  96. LONG rc = ERROR_SUCCESS;
  97. DWORD amountWritten;
  98. PTSTR savePath = NULL;
  99. BOOL sysFile = TRUE;
  100. PCSTR ansiString = NULL;
  101. DWORD ansiStringLength;
  102. PCTSTR ArgList[1];
  103. PCTSTR Message = NULL;
  104. PCTSTR p;
  105. PCTSTR fileName;
  106. MYASSERT (Path && Buffer);
  107. //
  108. // IF this is a system file (i.e. config.sys or autoexec.bat) redirect the
  109. // file to config.nt or autoexec.nt.
  110. //
  111. p = _tcschr (Path, TEXT('\\'));
  112. if (p) {
  113. p = _tcsinc (p);
  114. } else {
  115. p = Path;
  116. }
  117. fileName = p;
  118. if (StringIMatch (p, TEXT("config.sys"))) {
  119. savePath = JoinPaths(g_System32Dir,TEXT("config.nt"));
  120. } else if (StringIMatch (p, TEXT("autoexec.bat"))) {
  121. savePath = JoinPaths(g_System32Dir,TEXT("autoexec.nt"));
  122. } else {
  123. sysFile = FALSE;
  124. savePath = (PTSTR) Path;
  125. }
  126. //
  127. // If the file was not changed during the migration, do nothing.
  128. //
  129. if (sysFile || g_FileChanged) {
  130. //
  131. // Open a handle to the file to be created.
  132. //
  133. fileHandle = CreateFile(
  134. savePath,
  135. GENERIC_WRITE,
  136. 0,
  137. NULL,
  138. sysFile ? OPEN_ALWAYS : CREATE_ALWAYS,
  139. FILE_ATTRIBUTE_NORMAL,
  140. NULL
  141. );
  142. if (fileHandle == INVALID_HANDLE_VALUE) {
  143. rc = GetLastError();
  144. } else {
  145. //
  146. // Append from the end of the file.
  147. //
  148. SetFilePointer(
  149. fileHandle,
  150. 0,
  151. NULL,
  152. FILE_END
  153. );
  154. ArgList[0] = g_Win95Name;
  155. Message = ParseMessageID (MSG_DMNT_APPENDSTRING, ArgList);
  156. ansiString = CreateDbcs (Message);
  157. ansiStringLength = ByteCountA (ansiString);
  158. WriteFile(
  159. fileHandle,
  160. ansiString,
  161. ansiStringLength,
  162. &amountWritten,
  163. NULL
  164. );
  165. FreeStringResource (Message);
  166. DestroyDbcs (ansiString);
  167. ansiString = CreateDbcs (Buffer);
  168. ansiStringLength = ByteCountA (ansiString);
  169. if (!WriteFile(
  170. fileHandle,
  171. ansiString,
  172. ansiStringLength,
  173. &amountWritten,
  174. NULL
  175. )) {
  176. LOG((LOG_ERROR, "Error writing buffer to file."));
  177. }
  178. DestroyDbcs (ansiString);
  179. //
  180. // Log the file change.
  181. //
  182. LOG ((
  183. LOG_INFORMATION,
  184. "%s was updated with settings from %s",
  185. savePath,
  186. fileName
  187. ));
  188. CloseHandle(fileHandle);
  189. }
  190. if (sysFile) {
  191. FreePathString(savePath);
  192. }
  193. }
  194. return rc;
  195. }
  196. LONG
  197. pTurnInsertModeOn (
  198. HKEY UserKey
  199. )
  200. {
  201. LONG rc;
  202. HKEY key;
  203. DWORD value = 1;
  204. rc = TrackedRegOpenKeyEx (UserKey,S_CONSOLEKEY,0,KEY_ALL_ACCESS,&key);
  205. if (rc == ERROR_SUCCESS) {
  206. rc = RegSetValueEx(
  207. key,
  208. S_INSERTMODEVALUE,
  209. 0,
  210. REG_DWORD,
  211. (PBYTE) &value,
  212. sizeof(DWORD)
  213. );
  214. CloseRegKey(key);
  215. }
  216. return rc;
  217. }
  218. LONG
  219. pTurnAutoParseOff (
  220. HKEY UserKey
  221. )
  222. {
  223. LONG rc;
  224. HKEY key;
  225. PCTSTR valueStr = TEXT("0");
  226. DWORD valueStrBytes = 2*sizeof(TCHAR);
  227. rc = TrackedRegOpenKeyEx(UserKey,S_WINLOGONKEY,0,KEY_ALL_ACCESS,&key);
  228. if (rc == ERROR_SUCCESS) {
  229. rc = RegSetValueEx(
  230. key,
  231. S_AUTOPARSEVALUE,
  232. 0,
  233. REG_SZ,
  234. (PBYTE) valueStr,
  235. valueStrBytes
  236. );
  237. if (rc != ERROR_SUCCESS) {
  238. DEBUGMSG((DBG_WARNING,"DosMig: Unable to Save new ParseAutoexec value. rc: %u (%x)",rc,rc));
  239. }
  240. else {
  241. DEBUGMSG((DBG_DOSMIG,"ParseAutoexec turned off."));
  242. }
  243. CloseRegKey(key);
  244. }
  245. else {
  246. DEBUGMSG((DBG_WARNING,"DosMig: Unable to open %s rc: %u (%x)",S_WINLOGONKEY,rc,rc));
  247. }
  248. return rc;
  249. }
  250. LONG
  251. pMigrateEnvSetting (
  252. IN PCTSTR Setting,
  253. IN PCTSTR EnvValue,
  254. IN BOOL PrependSetPrefix,
  255. IN OUT PGROWBUFFER Buffer, OPTIONAL
  256. OUT PBOOL AppendedToBuffer OPTIONAL
  257. )
  258. {
  259. LONG rc = ERROR_SUCCESS;
  260. GROWBUFFER newSetting = GROWBUF_INIT;
  261. TCHAR currentPath[MAX_CMDLINE];
  262. TCHAR matchBuffer[MEMDB_MAX];
  263. PCTSTR start;
  264. PCTSTR end;
  265. HKEY key;
  266. DWORD sizeNeeded;
  267. DWORD valueType;
  268. PTSTR storage;
  269. BOOL append = FALSE;
  270. PTSTR p;
  271. PTSTR q;
  272. BOOL bRegMigrationSuppressed;
  273. PTSTR expandKey = TEXT("");
  274. if (AppendedToBuffer) {
  275. *AppendedToBuffer = FALSE;
  276. }
  277. //
  278. // Make sure this setting is not suppressed.
  279. //
  280. bRegMigrationSuppressed = HtFindString (g_SuppressionTable, Setting) != NULL;
  281. if (bRegMigrationSuppressed) {
  282. DEBUGMSG ((DBG_DOSMIG, "pMigrateEnvSetting: NOT Migrating %s = %s in registry. Environment variable is suppressed.", Setting, EnvValue));
  283. }
  284. DEBUGMSG((DBG_DOSMIG,"pMigrateEnvSetting: Migrating %s = %s.",Setting,EnvValue));
  285. if (!bRegMigrationSuppressed) {
  286. //
  287. // Attempt to open the registry key.
  288. //
  289. rc = TrackedRegOpenKeyEx(
  290. HKEY_LOCAL_MACHINE,
  291. S_ENVIRONMENTKEY,
  292. 0,
  293. KEY_ALL_ACCESS,
  294. &key
  295. );
  296. if (rc != ERROR_SUCCESS) {
  297. LOG((LOG_ERROR,"Dosmig: Could not open key %s",S_ENVIRONMENTKEY));
  298. return rc;
  299. }
  300. }
  301. start = EnvValue;
  302. do {
  303. //
  304. // Find end of this portion of the environment string.
  305. // this is (1) the first ';' encountered, or (2) the trailing NULL
  306. //
  307. end = _tcschr(start,TEXT(';'));
  308. if (!end) {
  309. end = GetEndOfString(start);
  310. }
  311. //
  312. // save a copy of the currently found path.
  313. //
  314. StringCopyAB(currentPath,start,end);
  315. //
  316. // Look for self-replacement case.
  317. // This is the case where there are multiple statements setting the
  318. // same environment variable like:
  319. // set foo=bar
  320. // set foo=%foo%;bar2
  321. //
  322. wsprintf(matchBuffer,TEXT("%%%s%%"),Setting);
  323. if (!bRegMigrationSuppressed &&
  324. (StringIMatch(currentPath,matchBuffer) ||
  325. (StringIMatch(currentPath,TEXT("%PATH%")) &&
  326. StringIMatch(Setting,TEXT("MIGRATED_PATH"))
  327. ))) {
  328. //
  329. // Get contents of key if it exists.
  330. //
  331. rc = RegQueryValueEx(
  332. key,
  333. Setting,
  334. 0,
  335. &valueType,
  336. NULL,
  337. &sizeNeeded);
  338. if (rc == ERROR_SUCCESS) {
  339. //
  340. // Now, create a temporary duplicate of the key and
  341. //
  342. storage = PoolMemCreateString(g_Pool,sizeNeeded+1);
  343. if (storage != NULL) {
  344. rc = RegQueryValueEx(
  345. key,
  346. Setting,
  347. 0,
  348. &valueType,
  349. (PBYTE) storage,
  350. &sizeNeeded
  351. );
  352. if (rc != ERROR_SUCCESS) {
  353. LOG((LOG_ERROR,"Dosmig: ReqQueryValueEx failure."));
  354. }
  355. //
  356. // Add this to the environment string to be set.
  357. //
  358. if (append) {
  359. GrowBufAppendString (&newSetting,TEXT(";"));
  360. }
  361. GrowBufAppendString (&newSetting,storage);
  362. PoolMemReleaseMemory(g_Pool,storage);
  363. append = TRUE;
  364. }
  365. else {
  366. rc = GetLastError();
  367. DEBUGMSG((DBG_ERROR,"Dosmig: Error! Unable to allocate storage."));
  368. }
  369. }
  370. else {
  371. rc = ERROR_SUCCESS;
  372. }
  373. }
  374. else {
  375. //
  376. // append the massaged path, keep it for later use.
  377. //
  378. if (append) {
  379. GrowBufAppendString (&newSetting,TEXT(";"));
  380. }
  381. //
  382. // Make sure we take care of any DIR moves.
  383. //
  384. ConvertWin9xCmdLine (currentPath, NULL, NULL);
  385. GrowBufAppendString (&newSetting, currentPath);
  386. //
  387. // store the updated path in the given growbuffer
  388. //
  389. if (Buffer) {
  390. if (PrependSetPrefix && !append) {
  391. StringCopy (matchBuffer, TEXT("SET "));
  392. q = GetEndOfString (matchBuffer);
  393. } else {
  394. q = matchBuffer;
  395. }
  396. if (!append) {
  397. wsprintf (q, TEXT("%s=%s"), Setting, currentPath);
  398. } else {
  399. *q++ = TEXT(';');
  400. StringCopy (q, currentPath);
  401. }
  402. GrowBufAppendString (Buffer, matchBuffer);
  403. if (AppendedToBuffer) {
  404. *AppendedToBuffer = TRUE;
  405. }
  406. }
  407. append = TRUE;
  408. }
  409. //
  410. // set start pointer for next iteration of path.
  411. //
  412. start = end;
  413. if (*start == TEXT(';')) {
  414. start = _tcsinc(start);
  415. }
  416. } while (*start);
  417. if (!bRegMigrationSuppressed) {
  418. //
  419. // Save the value we built up into the registry.
  420. //
  421. if (rc == ERROR_SUCCESS && newSetting.Buf && *newSetting.Buf) {
  422. rc = RegSetValueEx(
  423. key,
  424. Setting,
  425. 0,
  426. REG_EXPAND_SZ,
  427. (LPBYTE) newSetting.Buf,
  428. SizeOfString((PCTSTR) newSetting.Buf)
  429. );
  430. if (rc != ERROR_SUCCESS) {
  431. LOG ((LOG_ERROR,"Dosmig: Unexpectedly could not write key into registry."));
  432. }
  433. DEBUGMSG_IF((rc == ERROR_SUCCESS,DBG_DOSMIG,"Saved env setting into registry. (%s)",newSetting.Buf));
  434. }
  435. else if (rc != ERROR_SUCCESS) {
  436. LOG((LOG_ERROR,"Dosmig: Some previous failure prevents writing the migrated env variable to the registry."));
  437. }
  438. //
  439. // Clean up resource usage.
  440. //
  441. CloseRegKey(key);
  442. }
  443. FreeGrowBuffer(&newSetting);
  444. return rc;
  445. }
  446. LONG
  447. pSetPrompt (
  448. IN PCTSTR PromptCommand
  449. )
  450. {
  451. LONG rc = ERROR_SUCCESS;
  452. PCTSTR promptSetting;
  453. promptSetting = SkipSpace(CharCountToPointer((PTSTR)PromptCommand,6));
  454. if (promptSetting && *promptSetting == TEXT('=')) {
  455. promptSetting = SkipSpace(_tcsinc(promptSetting));
  456. }
  457. if (promptSetting) {
  458. DEBUGMSG((DBG_DOSMIG,"Passing prompt statement off to env migration function."));
  459. rc = pMigrateEnvSetting(S_PROMPT,promptSetting, FALSE, NULL, NULL);
  460. }
  461. ELSE_DEBUGMSG((DBG_DOSMIG,"PromptSetting is empty...ignored."));
  462. return rc;
  463. }
  464. BOOL
  465. pIsValidPath (
  466. PCTSTR Path
  467. )
  468. {
  469. PCTSTR currPtr;
  470. if (!Path) {
  471. return FALSE;
  472. }
  473. Path = SkipSpace(Path);
  474. currPtr = Path;
  475. do {
  476. if ((*currPtr == TEXT(',')) ||
  477. (*currPtr == TEXT(';')) ||
  478. (*currPtr == TEXT('<')) ||
  479. (*currPtr == TEXT('>')) ||
  480. (*currPtr == TEXT('|')) ||
  481. (*currPtr == TEXT('?')) ||
  482. (*currPtr == TEXT('*'))
  483. ) {
  484. return FALSE;
  485. }
  486. currPtr = _tcsinc (currPtr);
  487. } while (*currPtr);
  488. if ((*Path==0) || (*(Path+1)==0)) {
  489. return FALSE;
  490. }
  491. currPtr = Path;
  492. while (*currPtr == TEXT('"')) {
  493. currPtr = _tcsinc (currPtr);
  494. }
  495. currPtr = SkipSpace(currPtr);
  496. if (!_istalpha (*currPtr) &&
  497. *currPtr != TEXT('\\') &&
  498. *currPtr != TEXT('%')) {
  499. return FALSE;
  500. }
  501. return TRUE;
  502. }
  503. LONG
  504. pMigratePathSettings (
  505. IN PCTSTR PathSettings
  506. )
  507. {
  508. LONG rc = ERROR_SUCCESS;
  509. PTSTR oldPath;
  510. UINT i;
  511. UINT size;
  512. PTSTR end;
  513. PTSTR p;
  514. MYASSERT (StringIMatchCharCount (PathSettings, TEXT("PATH"), 4));
  515. //
  516. //skip past the 'PATH' portion of this statement.
  517. //
  518. oldPath = PoolMemDuplicateString (g_Pool, PathSettings);
  519. oldPath = CharCountToPointer(oldPath,4);
  520. //
  521. //Look for an '=' sign.
  522. //
  523. p = _tcschr(oldPath,TEXT('='));
  524. if (p) {
  525. //
  526. // Pass the equals sign.
  527. //
  528. oldPath = _tcsinc(p);
  529. }
  530. //
  531. // Skip any white space before the actual beginning of the path.
  532. //
  533. while (*oldPath && iswspace(*oldPath)) {
  534. oldPath = _tcsinc(oldPath);
  535. }
  536. if (*oldPath) {
  537. //
  538. // If there is actually anything to add to the path, add it.
  539. //
  540. p = oldPath;
  541. while (p && *p) {
  542. //
  543. // Look for ';'
  544. //
  545. end = _tcschr (p, TEXT(';'));
  546. if (end) {
  547. *end = 0;
  548. }
  549. //
  550. // Add this path to our path list.
  551. //
  552. size = GrowListGetSize (&g_PathList);
  553. for (i = 0;i < size; i++) {
  554. if (StringIMatch (p, GrowListGetString (&g_PathList, i))) {
  555. DEBUGMSG ((DBG_DOSMIG, "Skipping path %s. It already exists in path.", p));
  556. break;
  557. }
  558. }
  559. if (i == size) {
  560. //
  561. // Path was not found in the list of path segments. Add it now.
  562. //
  563. if (pIsValidPath (p)) {
  564. GrowListAppendString (&g_PathList, p);
  565. }
  566. ELSE_DEBUGMSG ((DBG_DOSMIG, "Skipping path %s. It is invalid.", p));
  567. }
  568. //
  569. // Go to the next path segment.
  570. //
  571. if (end) {
  572. p = _tcsinc(end);
  573. }
  574. else {
  575. p = NULL;
  576. }
  577. }
  578. }
  579. return rc;
  580. }
  581. LONG
  582. pMigrateSetSetting (
  583. IN PCTSTR SetLine,
  584. IN OUT PGROWBUFFER Buffer,
  585. OUT PBOOL AppendedToBuffer
  586. )
  587. {
  588. TCHAR setIdentifier[MEMDB_MAX];
  589. PTSTR idEnd;
  590. PCTSTR start;
  591. PCTSTR end;
  592. MYASSERT (StringIMatchCharCount (SetLine, TEXT("SET"), 3));
  593. if (AppendedToBuffer) {
  594. *AppendedToBuffer = FALSE;
  595. }
  596. //
  597. // First, skip past the set and any whitespace.
  598. //
  599. start = SkipSpace(CharCountToPointer((PWSTR)SetLine,3));
  600. if (!start) {
  601. //
  602. // line is of the form SET
  603. //
  604. return ERROR_SUCCESS;
  605. }
  606. end = _tcschr(start,TEXT('='));
  607. if (!end) {
  608. //
  609. // line is of the form SET dafasdfasdfasdfasd
  610. //
  611. return ERROR_SUCCESS;
  612. }
  613. if (start==end) {
  614. //
  615. // line is of the form SET=
  616. //
  617. return ERROR_SUCCESS;
  618. }
  619. //
  620. // Create an identifier now.
  621. //
  622. StringCopyAB(setIdentifier,start,end);
  623. idEnd = GetEndOfString (setIdentifier);
  624. //
  625. // Shake off any space.
  626. //
  627. idEnd = (PTSTR) SkipSpaceR(setIdentifier,idEnd);
  628. if (!idEnd) {
  629. //
  630. // Line is of the form SET =
  631. //
  632. return ERROR_SUCCESS;
  633. }
  634. idEnd = _tcsinc(idEnd);
  635. *idEnd = TEXT('\0');
  636. if (StringIMatch(setIdentifier,TEXT("PATH"))) {
  637. DEBUGMSG((DBG_DOSMIG,"Env setting is really a path statement. passing off to path migration function."));
  638. //
  639. // This is really a path setting. let the proper function take care of it.
  640. //
  641. start = SkipSpace(CharCountToPointer((PWSTR)SetLine,3));
  642. if(AppendedToBuffer){
  643. *AppendedToBuffer = TRUE;
  644. }
  645. return pMigratePathSettings(start);
  646. }
  647. //
  648. // Now that setIdentifier is well formed, root out the value to be set.
  649. //
  650. //
  651. // Move start to the beginning of the value to be set.
  652. //
  653. start = SkipSpace(_tcsinc(end));
  654. if (!start) {
  655. //
  656. // Line is of the form SET <id>=
  657. // Nothing to do.
  658. //
  659. return ERROR_SUCCESS;
  660. }
  661. //
  662. // Good to go. Let MigrateEnvSetting handle it.
  663. //
  664. DEBUGMSG((DBG_DOSMIG,"handing massaged set statement to env migration function."));
  665. return pMigrateEnvSetting(setIdentifier,start, TRUE, Buffer, AppendedToBuffer);
  666. }
  667. BOOL
  668. pProcessLine (
  669. DWORD Type,
  670. PGROWBUFFER Buffer,
  671. PTSTR Line
  672. )
  673. {
  674. BOOL rSuccess = TRUE;
  675. LONG migrateRc = ERROR_SUCCESS;
  676. PTSTR migrateString;
  677. BOOL bAppendOrigLine;
  678. TCHAR fixedCmdLine[MAX_CMDLINE];
  679. //
  680. // Do type specific massaging of the line
  681. //
  682. switch (Type) {
  683. case DOSMIG_UNKNOWN: case DOSMIG_BAD: case DOSMIG_IGNORE:
  684. g_FileChanged = TRUE;
  685. GrowBufAppendString (Buffer,TEXT("REM "));
  686. //
  687. // intentionally skipped break.
  688. //
  689. case DOSMIG_USE:
  690. //
  691. // Perform path conversion on Line, then write it to the file
  692. //
  693. StackStringCopy (fixedCmdLine, Line);
  694. ConvertWin9xCmdLine (fixedCmdLine, NULL, NULL);
  695. GrowBufAppendString (Buffer, fixedCmdLine);
  696. GrowBufAppendString (Buffer, TEXT("\r\n"));
  697. break;
  698. case DOSMIG_MIGRATE:
  699. DEBUGMSG((DBG_DOSMIG,"Processing a potentially migrateable line. (%s)",Line));
  700. if (IsPatternMatch(TEXT("doskey*"),Line) || IsPatternMatch(TEXT("*\\doskey*"),Line)) {
  701. GrowBufAppendString (Buffer,TEXT("REM "));
  702. }
  703. //
  704. // Skip space and ECHO OFF char (@) if any.
  705. // Also, skip any path portion of the string.
  706. // i.e, convert path/doskey to doskey.
  707. migrateString = (PTSTR) SkipSpace(Line);
  708. if (*migrateString == TEXT('@')) {
  709. migrateString = (PTSTR) _tcsinc(migrateString);
  710. }
  711. migrateString = (PTSTR) pGetFileNameStartFromPath(migrateString);
  712. bAppendOrigLine = TRUE;
  713. //
  714. // Now, attempt to determine what migration case this is.
  715. //
  716. if (IsPatternMatch(TEXT("prompt*"),migrateString)) {
  717. DEBUGMSG((DBG_DOSMIG,"Migrating prompt. (%s)",migrateString));
  718. migrateRc = pSetPrompt(migrateString);
  719. if (migrateRc != ERROR_SUCCESS) {
  720. rSuccess = FALSE;
  721. LOG((LOG_ERROR,"Dosmig: Error trying to Set Prompt."));
  722. }
  723. ELSE_DEBUGMSG((DBG_DOSMIG,"Prompt successfully migrated."));
  724. }
  725. else if (IsPatternMatch(TEXT("doskey *"),migrateString)) {
  726. //
  727. // Doskey migration.
  728. //
  729. if (IsPatternMatch(TEXT("*/I*"),migrateString)) {
  730. g_MigrateDoskeySetting = TRUE;
  731. DEBUGMSG((DBG_DOSMIG,"Insert mode will be enabled for each user. (%s)",migrateString));
  732. }
  733. ELSE_DEBUGMSG((DBG_DOSMIG,"Doskey command found. However, no migrateable doskey settings found. Command ignored."));
  734. }
  735. else if (IsPatternMatch(TEXT("path=*"),migrateString)
  736. || IsPatternMatch(TEXT("path *"),migrateString)) {
  737. //
  738. // PATH migration.
  739. //
  740. DEBUGMSG((DBG_DOSMIG,"Migrating path setting (%s)",migrateString));
  741. migrateRc = pMigratePathSettings(migrateString);
  742. if (migrateRc != ERROR_SUCCESS) {
  743. rSuccess = FALSE;
  744. LOG((LOG_ERROR,"Dosmig: Error trying to migrate path settings."));
  745. }
  746. ELSE_DEBUGMSG((DBG_DOSMIG,"Path successfully migrated."));
  747. }
  748. else if (IsPatternMatch(TEXT("set *"),migrateString)) {
  749. BOOL b;
  750. //
  751. // SET migration.
  752. //
  753. DEBUGMSG((DBG_DOSMIG,"Migrating env variable. (%s)",migrateString));
  754. migrateRc = pMigrateSetSetting(migrateString, Buffer, &b);
  755. bAppendOrigLine = !b;
  756. if (migrateRc != ERROR_SUCCESS) {
  757. rSuccess = FALSE;
  758. LOG((LOG_ERROR,"Dosmig: Error trying to migrate environment setting."));
  759. }
  760. ELSE_DEBUGMSG((DBG_DOSMIG,"Env variable successfully migrated."));
  761. }
  762. ELSE_DEBUGMSG((DBG_DOSMIG,"Dosmig: Line marked for migration doesn't fit any migration rule.\n%s",Line));
  763. if (bAppendOrigLine) {
  764. GrowBufAppendString (Buffer,Line);
  765. }
  766. //
  767. // Last, append a CRLF into the buffer to be written.
  768. //
  769. GrowBufAppendString (Buffer,TEXT("\r\n"));
  770. break;
  771. default:
  772. LOG((LOG_ERROR,"Dosmig: Invalid Type in switch statement."));
  773. break;
  774. }
  775. return rSuccess;
  776. }
  777. BOOL
  778. pNewFile (
  779. DWORD Offset
  780. ) {
  781. TCHAR file[MAX_TCHAR_PATH];
  782. static DWORD curOffset = INVALID_OFFSET;
  783. BOOL rNewFile = FALSE;
  784. if (Offset != curOffset && MemDbBuildKeyFromOffset(Offset,file,1,NULL)) {
  785. //
  786. // if there isn't a current file, or this is a new file, set the current file
  787. // to this file.
  788. //
  789. if (!g_CurrentFile || !StringMatch(file,g_CurrentFile)) {
  790. //
  791. // If this is a genuine new file (i.e. not just the first file, we'll return true.)
  792. //
  793. rNewFile = g_CurrentFile != NULL;
  794. g_LastFile = g_CurrentFile;
  795. g_CurrentFile = PoolMemDuplicateString(g_Pool,file);
  796. }
  797. }
  798. return rNewFile;
  799. }
  800. VOID
  801. pCompletePathProcessing (
  802. VOID
  803. )
  804. {
  805. UINT i;
  806. UINT size;
  807. UINT winDirLen;
  808. GROWBUFFER buf = GROWBUF_INIT;
  809. PTSTR p;
  810. TCHAR pathStatement[2*MAX_TCHAR_PATH];
  811. TCHAR newPath[MAX_TCHAR_PATH];
  812. HKEY key;
  813. DWORD rc;
  814. //
  815. // Make sure %systemroot% and %systemroot%\system32 are in the path.
  816. //
  817. wsprintf (pathStatement, TEXT("PATH=%s"), g_WinDir);
  818. pMigratePathSettings (pathStatement);
  819. wsprintf (pathStatement, TEXT("PATH=%s\\system32"), g_WinDir);
  820. pMigratePathSettings (pathStatement);
  821. wsprintf (pathStatement, TEXT("PATH=%s\\system32\\WBEM"), g_WinDir);
  822. pMigratePathSettings (pathStatement);
  823. winDirLen = CharCount (g_WinDir);
  824. size = GrowListGetSize (&g_PathList);
  825. for (i = 0; i < size; i++) {
  826. p = (PTSTR) GrowListGetString (&g_PathList, i);
  827. if (StringIMatch (TEXT("%PATH%"), p)) {
  828. //
  829. // Skip self-replacement.
  830. //
  831. continue;
  832. }
  833. if (GetFileStatusOnNt (p) & FILESTATUS_DELETED) {
  834. //
  835. // Skip this path portion. The directory was deleted.
  836. //
  837. DEBUGMSG ((DBG_DOSMIG, "Not migrating %s to new %%path%%. Directory was deleted.", p));
  838. continue;
  839. }
  840. //
  841. // See if the path is moved.
  842. //
  843. if (GetFileInfoOnNt (p, newPath, MAX_TCHAR_PATH) & FILESTATUS_MOVED) {
  844. p = newPath;
  845. }
  846. //
  847. // Replace c:\windows with %systemroot%.
  848. //
  849. if (StringIMatchCharCount (g_WinDir, p, winDirLen)) {
  850. GrowBufAppendString (&buf, TEXT("%SYSTEMROOT%"));
  851. GrowBufAppendString (&buf, p + winDirLen);
  852. }
  853. else {
  854. GrowBufAppendString (&buf, p);
  855. }
  856. GrowBufAppendString (&buf, TEXT(";"));
  857. }
  858. if (size) {
  859. //
  860. // Take off trailing ';'.
  861. //
  862. p = GetEndOfString ((PTSTR) buf.Buf);
  863. if (p) {
  864. p--;
  865. *p = 0;
  866. }
  867. //
  868. // Save into registry.
  869. //
  870. key = OpenRegKey (HKEY_LOCAL_MACHINE,S_ENVIRONMENTKEY);
  871. if (key && key != INVALID_HANDLE_VALUE) {
  872. rc = RegSetValueEx (
  873. key,
  874. TEXT("Path"),
  875. 0,
  876. REG_EXPAND_SZ,
  877. (PBYTE) buf.Buf,
  878. SizeOfString((PCTSTR) buf.Buf)
  879. );
  880. if (rc != ERROR_SUCCESS) {
  881. DEBUGMSG ((DBG_WARNING, "Unable to create migrated Path variable."));
  882. }
  883. CloseRegKey (key);
  884. }
  885. ELSE_DEBUGMSG ((DBG_WARNING, "pCompletePathProcessing: Unable to open environment key."));
  886. }
  887. //
  888. // Clean up resources.
  889. //
  890. FreeGrowBuffer (&buf);
  891. }
  892. VOID
  893. pPathListToBuffer(
  894. GROWBUFFER * growBuf
  895. )
  896. {
  897. INT i;
  898. i = GrowListGetSize (&g_PathList);
  899. if(i <= 0){
  900. return;
  901. }
  902. GrowBufAppendString (growBuf, TEXT("\r\nPATH="));
  903. for (--i; i >= 0; i--) {
  904. GrowBufAppendString (growBuf, GrowListGetString (&g_PathList, i));
  905. if(i){
  906. GrowBufAppendString (growBuf, TEXT(";"));
  907. }
  908. }
  909. GrowBufAppendString (growBuf, TEXT("\r\n"));
  910. }
  911. BOOL
  912. pGeneralMigration (
  913. VOID
  914. )
  915. {
  916. BOOL rSuccess = TRUE; // return value.
  917. MEMDB_ENUM eItems; // Enumerator for each dosmig line.
  918. TCHAR lineBuffer[MEMDB_MAX]; // Buffer for the contents of the current line.
  919. GROWBUFFER buffer = GROWBUF_INIT;
  920. TCHAR key[MEMDB_MAX];
  921. DWORD offset;
  922. DWORD value;
  923. INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
  924. PTSTR p = NULL;
  925. TCHAR pathStatement[MAX_PATH];
  926. //
  927. // Assume that there are no doskey settings to migrate.
  928. //
  929. g_MigrateDoskeySetting = FALSE;
  930. //
  931. // Set the change flag to false.
  932. //
  933. g_FileChanged = FALSE;
  934. //
  935. // Read in the suppression table from win95upg.inf and add it the suppression table.
  936. //
  937. g_SuppressionTable = HtAlloc ();
  938. if (InfFindFirstLine (g_WkstaMigInf, S_SUPPRESSED_ENV_VARS, NULL, &is)) {
  939. do {
  940. p = InfGetStringField (&is, 0);
  941. if (p) {
  942. HtAddString (g_SuppressionTable, p);
  943. }
  944. } while (InfFindNextLine (&is));
  945. }
  946. InfCleanUpInfStruct (&is);
  947. //
  948. // Ok, enumerate through each dosmigration line in memdb. These lines are stored
  949. // as following:
  950. //
  951. // DOSMIG LINES\<item>\<field>\<data>
  952. //
  953. // Where
  954. // o item is a 5 digit enumerator string.
  955. // o field is one of either TYPE,TEXT,DESC,or FILE
  956. // o data is the data associated with the field. For TYPE, data contains a string
  957. // representation of the LINETYPE, for TEXT, it contains the actual text of the line
  958. // for DESC, it contains a description supplied by DOSMIG95's parse rules and for FILE
  959. // it contains the originating file (config.sys, autoexec.bat)
  960. //
  961. //
  962. // Add %system32% by default
  963. //
  964. wsprintf (pathStatement, TEXT("PATH=%s\\system32"), g_WinDir);
  965. pMigratePathSettings (pathStatement);
  966. if (MemDbEnumItems(&eItems,MEMDB_CATEGORY_DM_LINES)) {
  967. do {
  968. //
  969. // Get the actual line contents.
  970. //
  971. if (MemDbGetEndpointValueEx(
  972. MEMDB_CATEGORY_DM_LINES,
  973. eItems.szName,
  974. NULL,
  975. lineBuffer
  976. )) {
  977. //
  978. // Get the value and flags from this endpoint.
  979. //
  980. MemDbBuildKey(key,MEMDB_CATEGORY_DM_LINES,eItems.szName,NULL,lineBuffer);
  981. MemDbGetValueAndFlags(key, &offset, &value);
  982. if (pNewFile(offset)) {
  983. //
  984. // the S_ENVVARS entry is a special case and is not an actual file. All of its entries are simply migrated
  985. // into the registry.
  986. //
  987. if (!StringIMatch(g_LastFile,S_ENVVARS)) {
  988. if (_tcsistr(g_LastFile, TEXT("autoexec.bat"))){
  989. //
  990. // Flush PathList to actual buffer
  991. //
  992. pPathListToBuffer(&buffer);
  993. }
  994. pSaveBufferToAnsiFile(g_LastFile,STRINGBUFFER(&buffer));
  995. }
  996. buffer.End = 0;
  997. g_FileChanged = FALSE;
  998. }
  999. rSuccess = pProcessLine(value,&buffer,lineBuffer);
  1000. DEBUGMSG_IF((rSuccess, DBG_DOSMIG,"Line successfully processed. (%s)",lineBuffer));
  1001. if (!rSuccess) {
  1002. LOG ((LOG_ERROR,"Dosmig: Error processing line. (%s)",lineBuffer));
  1003. }
  1004. }
  1005. else {
  1006. LOG((LOG_ERROR,"Dosmig: MemDbGetEndpointValueEx failed trying to retrieve line %s",eItems.szName));
  1007. }
  1008. } while (MemDbEnumNextValue(&eItems) && rSuccess);
  1009. //
  1010. // Get the file name and save the file off.
  1011. //
  1012. if (!StringIMatch(g_CurrentFile,S_ENVVARS)) {
  1013. if (_tcsistr(g_CurrentFile, TEXT("autoexec.bat"))){
  1014. //
  1015. // Flush PathList to actual buffer
  1016. //
  1017. pPathListToBuffer(&buffer);
  1018. }
  1019. pSaveBufferToAnsiFile(g_CurrentFile,STRINGBUFFER(&buffer));
  1020. }
  1021. pCompletePathProcessing ();
  1022. FreeGrowList (&g_PathList);
  1023. }
  1024. ELSE_DEBUGMSG((DBG_DOSMIG,"No lines to migrate..."));
  1025. //
  1026. // Free our growbuffer.
  1027. //
  1028. FreeGrowBuffer(&buffer);
  1029. //
  1030. // Clean up the suppression table.
  1031. //
  1032. HtFree (g_SuppressionTable);
  1033. return rSuccess;
  1034. }
  1035. BOOL
  1036. WINAPI
  1037. DosMigNt_Entry (
  1038. IN HINSTANCE hinstDLL,
  1039. IN DWORD dwReason,
  1040. IN PVOID lpv
  1041. )
  1042. {
  1043. BOOL rSuccess = TRUE;
  1044. switch (dwReason)
  1045. {
  1046. case DLL_PROCESS_ATTACH:
  1047. g_Pool = PoolMemInitNamedPool ("DOS mig - NT side");
  1048. rSuccess = g_Pool != NULL;
  1049. // Set flag to indicate that migration information has not
  1050. // yet been processed.
  1051. g_MigrationPrepared = FALSE;
  1052. break;
  1053. case DLL_PROCESS_DETACH:
  1054. rSuccess = TRUE;
  1055. PoolMemDestroyPool(g_Pool);
  1056. break;
  1057. }
  1058. return rSuccess;
  1059. }
  1060. LONG
  1061. DosMigNt_User (
  1062. IN HKEY User
  1063. )
  1064. {
  1065. LONG rc = ERROR_SUCCESS;
  1066. if (!g_MigrationPrepared) {
  1067. if (pGeneralMigration()) {
  1068. g_MigrationPrepared = TRUE;
  1069. }
  1070. else {
  1071. LOG((LOG_ERROR,"Dosmig: General migration failed"));
  1072. }
  1073. }
  1074. if (g_MigrationPrepared) {
  1075. //
  1076. // Turn off autoexec.bat parsing.
  1077. //
  1078. rc = pTurnAutoParseOff(User);
  1079. if (g_MigrateDoskeySetting) {
  1080. rc = pTurnInsertModeOn(User);
  1081. if (rc != ERROR_SUCCESS) {
  1082. LOG ((LOG_ERROR,"Dosmig: Error attempting to turn insert mode on."));
  1083. }
  1084. }
  1085. }
  1086. return rc;
  1087. }
  1088. LONG
  1089. DosMigNt_System(
  1090. VOID
  1091. )
  1092. {
  1093. if (!g_MigrationPrepared) {
  1094. if (pGeneralMigration()) {
  1095. g_MigrationPrepared = TRUE;
  1096. }
  1097. else {
  1098. LOG((LOG_ERROR,"Dosmig: General migration failed"));
  1099. }
  1100. }
  1101. return ERROR_SUCCESS;
  1102. }