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.

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