1451 lines
33 KiB
C
1451 lines
33 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dosmignt.c
|
|
|
|
Abstract:
|
|
|
|
handles windows nt side migration of config.sys and autoexec.bat information
|
|
gathered during win9x upgrading. migrates environement settings, prompts, and
|
|
some doskey information. Also modifies the autoexec.nt and config.nt files.
|
|
|
|
Author:
|
|
|
|
Marc R. Whitten (marcw) 15-Feb-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "pch.h"
|
|
#include "w95upgnt.h"
|
|
|
|
#define DBG_DOSMIG "Dosmig"
|
|
|
|
|
|
//
|
|
// Flag that is set if Doskey /INSERT needs to be set.
|
|
//
|
|
BOOL g_MigrateDoskeySetting = FALSE;
|
|
|
|
//
|
|
// PoolMem Handle to pool used for dynamic allocations.
|
|
//
|
|
POOLHANDLE g_Pool = NULL;
|
|
|
|
//
|
|
// Flag that is set if all necessary data has been collected for migration.
|
|
//
|
|
BOOL g_MigrationPrepared = FALSE;
|
|
|
|
//
|
|
// String that points to the current file being processed.
|
|
//
|
|
PCTSTR g_CurrentFile = NULL;
|
|
PCTSTR g_LastFile = NULL;
|
|
|
|
//
|
|
// Boolean flag indicating wether any changes were made to the flag.
|
|
//
|
|
BOOL g_FileChanged = FALSE;
|
|
|
|
|
|
//
|
|
// The suppression table holds environment variables we want to ignore.
|
|
//
|
|
HASHTABLE g_SuppressionTable = NULL;
|
|
|
|
//
|
|
// List of path segments.
|
|
//
|
|
GROWLIST g_PathList = GROWLIST_INIT;
|
|
|
|
|
|
|
|
#define STRINGBUFFER(x) ((PTSTR) (x)->Buf)
|
|
#define BUFFEREMPTY(x) ((x)->End == 0)
|
|
|
|
typedef enum {
|
|
|
|
DOSMIG_UNUSED,
|
|
DOSMIG_BAD,
|
|
DOSMIG_UNKNOWN,
|
|
DOSMIG_USE,
|
|
DOSMIG_MIGRATE,
|
|
DOSMIG_IGNORE,
|
|
DOSMIG_LAST
|
|
|
|
} DOSMIG_LINETAG, *PDOSMIG_LINETAG;
|
|
|
|
|
|
|
|
|
|
|
|
PCTSTR
|
|
pGetFileNameStartFromPath (
|
|
IN PCTSTR Line
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the start of a File name in a(n assumed
|
|
wellformed) path.
|
|
|
|
Arguments:
|
|
|
|
Line - The String containing the path and filename.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the filename portion of the path. Note, this function
|
|
assumes that there may be (potentially valuable) arguments after the
|
|
file name. The pointer does not, therefore point only
|
|
|
|
--*/
|
|
{
|
|
PCTSTR lineStart = Line;
|
|
PCTSTR lineEnd = Line;
|
|
|
|
if (Line == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
while (_istalnum(*lineEnd) ||
|
|
*lineEnd == TEXT('_') ||
|
|
*lineEnd == TEXT('.') ||
|
|
*lineEnd == TEXT('\\') ||
|
|
*lineEnd == TEXT(':')) {
|
|
|
|
if((*lineEnd == TEXT('\\')) || (*lineEnd == TEXT(':'))) {
|
|
|
|
lineStart = _tcsinc(lineEnd);
|
|
|
|
}
|
|
lineEnd = _tcsinc(lineEnd);
|
|
}
|
|
|
|
return lineStart;
|
|
}
|
|
|
|
LONG
|
|
pSaveBufferToAnsiFile (
|
|
IN PCTSTR Path,
|
|
IN PCTSTR Buffer
|
|
)
|
|
{
|
|
HANDLE fileHandle;
|
|
LONG rc = ERROR_SUCCESS;
|
|
DWORD amountWritten;
|
|
PTSTR savePath = NULL;
|
|
BOOL sysFile = TRUE;
|
|
PCSTR ansiString = NULL;
|
|
DWORD ansiStringLength;
|
|
PCTSTR ArgList[1];
|
|
PCTSTR Message = NULL;
|
|
PCTSTR p;
|
|
PCTSTR fileName;
|
|
|
|
MYASSERT (Path && Buffer);
|
|
|
|
//
|
|
// IF this is a system file (i.e. config.sys or autoexec.bat) redirect the
|
|
// file to config.nt or autoexec.nt.
|
|
//
|
|
p = _tcschr (Path, TEXT('\\'));
|
|
if (p) {
|
|
p = _tcsinc (p);
|
|
} else {
|
|
p = Path;
|
|
}
|
|
|
|
fileName = p;
|
|
|
|
if (StringIMatch (p, TEXT("config.sys"))) {
|
|
|
|
savePath = JoinPaths(g_System32Dir,TEXT("config.nt"));
|
|
|
|
} else if (StringIMatch (p, TEXT("autoexec.bat"))) {
|
|
|
|
savePath = JoinPaths(g_System32Dir,TEXT("autoexec.nt"));
|
|
|
|
} else {
|
|
sysFile = FALSE;
|
|
savePath = (PTSTR) Path;
|
|
}
|
|
|
|
//
|
|
// If the file was not changed during the migration, do nothing.
|
|
//
|
|
if (sysFile || g_FileChanged) {
|
|
|
|
//
|
|
// Open a handle to the file to be created.
|
|
//
|
|
fileHandle = CreateFile(
|
|
savePath,
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
sysFile ? OPEN_ALWAYS : CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if (fileHandle == INVALID_HANDLE_VALUE) {
|
|
|
|
rc = GetLastError();
|
|
|
|
} else {
|
|
|
|
//
|
|
// Append from the end of the file.
|
|
//
|
|
|
|
SetFilePointer(
|
|
fileHandle,
|
|
0,
|
|
NULL,
|
|
FILE_END
|
|
);
|
|
|
|
|
|
ArgList[0] = g_Win95Name;
|
|
|
|
|
|
|
|
Message = ParseMessageID (MSG_DMNT_APPENDSTRING, ArgList);
|
|
|
|
|
|
ansiString = CreateDbcs (Message);
|
|
ansiStringLength = ByteCountA (ansiString);
|
|
|
|
WriteFile(
|
|
fileHandle,
|
|
ansiString,
|
|
ansiStringLength,
|
|
&amountWritten,
|
|
NULL
|
|
);
|
|
|
|
FreeStringResource (Message);
|
|
DestroyDbcs (ansiString);
|
|
|
|
ansiString = CreateDbcs (Buffer);
|
|
ansiStringLength = ByteCountA (ansiString);
|
|
|
|
if (!WriteFile(
|
|
fileHandle,
|
|
ansiString,
|
|
ansiStringLength,
|
|
&amountWritten,
|
|
NULL
|
|
)) {
|
|
|
|
LOG((LOG_ERROR, "Error writing buffer to file."));
|
|
}
|
|
|
|
DestroyDbcs (ansiString);
|
|
|
|
//
|
|
// Log the file change.
|
|
//
|
|
LOG ((
|
|
LOG_INFORMATION,
|
|
"%s was updated with settings from %s",
|
|
savePath,
|
|
fileName
|
|
));
|
|
|
|
|
|
CloseHandle(fileHandle);
|
|
}
|
|
|
|
if (sysFile) {
|
|
|
|
FreePathString(savePath);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return rc;
|
|
}
|
|
|
|
LONG
|
|
pTurnInsertModeOn (
|
|
HKEY UserKey
|
|
)
|
|
{
|
|
LONG rc;
|
|
HKEY key;
|
|
DWORD value = 1;
|
|
|
|
rc = TrackedRegOpenKeyEx (UserKey,S_CONSOLEKEY,0,KEY_ALL_ACCESS,&key);
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
|
|
rc = RegSetValueEx(
|
|
key,
|
|
S_INSERTMODEVALUE,
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE) &value,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
CloseRegKey(key);
|
|
}
|
|
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
LONG
|
|
pTurnAutoParseOff (
|
|
HKEY UserKey
|
|
)
|
|
{
|
|
LONG rc;
|
|
HKEY key;
|
|
PCTSTR valueStr = TEXT("0");
|
|
DWORD valueStrBytes = 2*sizeof(TCHAR);
|
|
|
|
rc = TrackedRegOpenKeyEx(UserKey,S_WINLOGONKEY,0,KEY_ALL_ACCESS,&key);
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
|
|
rc = RegSetValueEx(
|
|
key,
|
|
S_AUTOPARSEVALUE,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE) valueStr,
|
|
valueStrBytes
|
|
);
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
DEBUGMSG((DBG_WARNING,"DosMig: Unable to Save new ParseAutoexec value. rc: %u (%x)",rc,rc));
|
|
}
|
|
else {
|
|
DEBUGMSG((DBG_DOSMIG,"ParseAutoexec turned off."));
|
|
}
|
|
|
|
CloseRegKey(key);
|
|
}
|
|
else {
|
|
DEBUGMSG((DBG_WARNING,"DosMig: Unable to open %s rc: %u (%x)",S_WINLOGONKEY,rc,rc));
|
|
}
|
|
|
|
|
|
return rc;
|
|
}
|
|
|
|
LONG
|
|
pMigrateEnvSetting (
|
|
IN PCTSTR Setting,
|
|
IN PCTSTR EnvValue,
|
|
IN BOOL PrependSetPrefix,
|
|
IN OUT PGROWBUFFER Buffer, OPTIONAL
|
|
OUT PBOOL AppendedToBuffer OPTIONAL
|
|
)
|
|
{
|
|
LONG rc = ERROR_SUCCESS;
|
|
GROWBUFFER newSetting = GROWBUF_INIT;
|
|
TCHAR currentPath[MAX_CMDLINE];
|
|
TCHAR matchBuffer[MEMDB_MAX];
|
|
PCTSTR start;
|
|
PCTSTR end;
|
|
HKEY key;
|
|
DWORD sizeNeeded;
|
|
DWORD valueType;
|
|
PTSTR storage;
|
|
BOOL append = FALSE;
|
|
PTSTR p;
|
|
PTSTR q;
|
|
BOOL bRegMigrationSuppressed;
|
|
PTSTR expandKey = TEXT("");
|
|
|
|
|
|
if (AppendedToBuffer) {
|
|
*AppendedToBuffer = FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure this setting is not suppressed.
|
|
//
|
|
bRegMigrationSuppressed = HtFindString (g_SuppressionTable, Setting) != NULL;
|
|
if (bRegMigrationSuppressed) {
|
|
DEBUGMSG ((DBG_DOSMIG, "pMigrateEnvSetting: NOT Migrating %s = %s in registry. Environment variable is suppressed.", Setting, EnvValue));
|
|
}
|
|
|
|
DEBUGMSG((DBG_DOSMIG,"pMigrateEnvSetting: Migrating %s = %s.",Setting,EnvValue));
|
|
|
|
if (!bRegMigrationSuppressed) {
|
|
//
|
|
// Attempt to open the registry key.
|
|
//
|
|
rc = TrackedRegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
S_ENVIRONMENTKEY,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&key
|
|
);
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
LOG((LOG_ERROR,"Dosmig: Could not open key %s",S_ENVIRONMENTKEY));
|
|
return rc;
|
|
|
|
}
|
|
}
|
|
|
|
start = EnvValue;
|
|
|
|
do {
|
|
|
|
//
|
|
// Find end of this portion of the environment string.
|
|
// this is (1) the first ';' encountered, or (2) the trailing NULL
|
|
//
|
|
end = _tcschr(start,TEXT(';'));
|
|
if (!end) {
|
|
end = GetEndOfString(start);
|
|
}
|
|
|
|
//
|
|
// save a copy of the currently found path.
|
|
//
|
|
StringCopyAB(currentPath,start,end);
|
|
|
|
//
|
|
// Look for self-replacement case.
|
|
// This is the case where there are multiple statements setting the
|
|
// same environment variable like:
|
|
// set foo=bar
|
|
// set foo=%foo%;bar2
|
|
//
|
|
wsprintf(matchBuffer,TEXT("%%%s%%"),Setting);
|
|
if (!bRegMigrationSuppressed &&
|
|
(StringIMatch(currentPath,matchBuffer) ||
|
|
(StringIMatch(currentPath,TEXT("%PATH%")) &&
|
|
StringIMatch(Setting,TEXT("MIGRATED_PATH"))
|
|
))) {
|
|
|
|
//
|
|
// Get contents of key if it exists.
|
|
//
|
|
rc = RegQueryValueEx(
|
|
key,
|
|
Setting,
|
|
0,
|
|
&valueType,
|
|
NULL,
|
|
&sizeNeeded);
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Now, create a temporary duplicate of the key and
|
|
//
|
|
storage = PoolMemCreateString(g_Pool,sizeNeeded+1);
|
|
|
|
if (storage != NULL) {
|
|
|
|
rc = RegQueryValueEx(
|
|
key,
|
|
Setting,
|
|
0,
|
|
&valueType,
|
|
(PBYTE) storage,
|
|
&sizeNeeded
|
|
);
|
|
if (rc != ERROR_SUCCESS) {
|
|
LOG((LOG_ERROR,"Dosmig: ReqQueryValueEx failure."));
|
|
}
|
|
|
|
//
|
|
// Add this to the environment string to be set.
|
|
//
|
|
if (append) {
|
|
GrowBufAppendString (&newSetting,TEXT(";"));
|
|
}
|
|
|
|
GrowBufAppendString (&newSetting,storage);
|
|
PoolMemReleaseMemory(g_Pool,storage);
|
|
append = TRUE;
|
|
|
|
}
|
|
else {
|
|
rc = GetLastError();
|
|
DEBUGMSG((DBG_ERROR,"Dosmig: Error! Unable to allocate storage."));
|
|
}
|
|
}
|
|
else {
|
|
|
|
rc = ERROR_SUCCESS;
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
|
|
|
|
//
|
|
// append the massaged path, keep it for later use.
|
|
//
|
|
|
|
if (append) {
|
|
GrowBufAppendString (&newSetting,TEXT(";"));
|
|
}
|
|
|
|
//
|
|
// Make sure we take care of any DIR moves.
|
|
//
|
|
ConvertWin9xCmdLine (currentPath, NULL, NULL);
|
|
GrowBufAppendString (&newSetting, currentPath);
|
|
|
|
//
|
|
// store the updated path in the given growbuffer
|
|
//
|
|
if (Buffer) {
|
|
if (PrependSetPrefix && !append) {
|
|
StringCopy (matchBuffer, TEXT("SET "));
|
|
q = GetEndOfString (matchBuffer);
|
|
} else {
|
|
q = matchBuffer;
|
|
}
|
|
if (!append) {
|
|
wsprintf (q, TEXT("%s=%s"), Setting, currentPath);
|
|
} else {
|
|
*q++ = TEXT(';');
|
|
StringCopy (q, currentPath);
|
|
}
|
|
|
|
GrowBufAppendString (Buffer, matchBuffer);
|
|
if (AppendedToBuffer) {
|
|
*AppendedToBuffer = TRUE;
|
|
}
|
|
}
|
|
|
|
append = TRUE;
|
|
}
|
|
|
|
//
|
|
// set start pointer for next iteration of path.
|
|
//
|
|
start = end;
|
|
if (*start == TEXT(';')) {
|
|
start = _tcsinc(start);
|
|
}
|
|
|
|
} while (*start);
|
|
|
|
|
|
if (!bRegMigrationSuppressed) {
|
|
//
|
|
// Save the value we built up into the registry.
|
|
//
|
|
if (rc == ERROR_SUCCESS && newSetting.Buf && *newSetting.Buf) {
|
|
|
|
rc = RegSetValueEx(
|
|
key,
|
|
Setting,
|
|
0,
|
|
REG_EXPAND_SZ,
|
|
(LPBYTE) newSetting.Buf,
|
|
SizeOfString((PCTSTR) newSetting.Buf)
|
|
);
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
LOG ((LOG_ERROR,"Dosmig: Unexpectedly could not write key into registry."));
|
|
}
|
|
DEBUGMSG_IF((rc == ERROR_SUCCESS,DBG_DOSMIG,"Saved env setting into registry. (%s)",newSetting.Buf));
|
|
}
|
|
else if (rc != ERROR_SUCCESS) {
|
|
LOG((LOG_ERROR,"Dosmig: Some previous failure prevents writing the migrated env variable to the registry."));
|
|
}
|
|
|
|
//
|
|
// Clean up resource usage.
|
|
//
|
|
CloseRegKey(key);
|
|
}
|
|
|
|
FreeGrowBuffer(&newSetting);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
LONG
|
|
pSetPrompt (
|
|
IN PCTSTR PromptCommand
|
|
)
|
|
{
|
|
LONG rc = ERROR_SUCCESS;
|
|
|
|
PCTSTR promptSetting;
|
|
|
|
|
|
promptSetting = SkipSpace(CharCountToPointer((PTSTR)PromptCommand,6));
|
|
if (promptSetting && *promptSetting == TEXT('=')) {
|
|
promptSetting = SkipSpace(_tcsinc(promptSetting));
|
|
}
|
|
|
|
if (promptSetting) {
|
|
DEBUGMSG((DBG_DOSMIG,"Passing prompt statement off to env migration function."));
|
|
rc = pMigrateEnvSetting(S_PROMPT,promptSetting, FALSE, NULL, NULL);
|
|
}
|
|
ELSE_DEBUGMSG((DBG_DOSMIG,"PromptSetting is empty...ignored."));
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
pIsValidPath (
|
|
PCTSTR Path
|
|
)
|
|
{
|
|
PCTSTR currPtr;
|
|
|
|
if (!Path) {
|
|
return FALSE;
|
|
}
|
|
|
|
Path = SkipSpace(Path);
|
|
|
|
currPtr = Path;
|
|
|
|
do {
|
|
if ((*currPtr == TEXT(',')) ||
|
|
(*currPtr == TEXT(';')) ||
|
|
(*currPtr == TEXT('<')) ||
|
|
(*currPtr == TEXT('>')) ||
|
|
(*currPtr == TEXT('|')) ||
|
|
(*currPtr == TEXT('?')) ||
|
|
(*currPtr == TEXT('*'))
|
|
) {
|
|
return FALSE;
|
|
}
|
|
currPtr = _tcsinc (currPtr);
|
|
} while (*currPtr);
|
|
|
|
if ((*Path==0) || (*(Path+1)==0)) {
|
|
return FALSE;
|
|
}
|
|
|
|
currPtr = Path;
|
|
while (*currPtr == TEXT('"')) {
|
|
currPtr = _tcsinc (currPtr);
|
|
}
|
|
|
|
currPtr = SkipSpace(currPtr);
|
|
|
|
if (!_istalpha (*currPtr) &&
|
|
*currPtr != TEXT('\\') &&
|
|
*currPtr != TEXT('%')) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
LONG
|
|
pMigratePathSettings (
|
|
IN PCTSTR PathSettings
|
|
)
|
|
{
|
|
LONG rc = ERROR_SUCCESS;
|
|
PTSTR oldPath;
|
|
UINT i;
|
|
UINT size;
|
|
PTSTR end;
|
|
PTSTR p;
|
|
|
|
|
|
MYASSERT (StringIMatchCharCount (PathSettings, TEXT("PATH"), 4));
|
|
|
|
//
|
|
//skip past the 'PATH' portion of this statement.
|
|
//
|
|
oldPath = PoolMemDuplicateString (g_Pool, PathSettings);
|
|
oldPath = CharCountToPointer(oldPath,4);
|
|
|
|
//
|
|
//Look for an '=' sign.
|
|
//
|
|
p = _tcschr(oldPath,TEXT('='));
|
|
if (p) {
|
|
|
|
//
|
|
// Pass the equals sign.
|
|
//
|
|
oldPath = _tcsinc(p);
|
|
}
|
|
|
|
//
|
|
// Skip any white space before the actual beginning of the path.
|
|
//
|
|
while (*oldPath && iswspace(*oldPath)) {
|
|
oldPath = _tcsinc(oldPath);
|
|
}
|
|
|
|
if (*oldPath) {
|
|
//
|
|
// If there is actually anything to add to the path, add it.
|
|
//
|
|
p = oldPath;
|
|
while (p && *p) {
|
|
|
|
//
|
|
// Look for ';'
|
|
//
|
|
end = _tcschr (p, TEXT(';'));
|
|
if (end) {
|
|
*end = 0;
|
|
}
|
|
|
|
//
|
|
// Add this path to our path list.
|
|
//
|
|
size = GrowListGetSize (&g_PathList);
|
|
for (i = 0;i < size; i++) {
|
|
if (StringIMatch (p, GrowListGetString (&g_PathList, i))) {
|
|
DEBUGMSG ((DBG_DOSMIG, "Skipping path %s. It already exists in path.", p));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == size) {
|
|
//
|
|
// Path was not found in the list of path segments. Add it now.
|
|
//
|
|
|
|
if (pIsValidPath (p)) {
|
|
GrowListAppendString (&g_PathList, p);
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_DOSMIG, "Skipping path %s. It is invalid.", p));
|
|
}
|
|
|
|
//
|
|
// Go to the next path segment.
|
|
//
|
|
if (end) {
|
|
p = _tcsinc(end);
|
|
}
|
|
else {
|
|
p = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
LONG
|
|
pMigrateSetSetting (
|
|
IN PCTSTR SetLine,
|
|
IN OUT PGROWBUFFER Buffer,
|
|
OUT PBOOL AppendedToBuffer
|
|
)
|
|
{
|
|
TCHAR setIdentifier[MEMDB_MAX];
|
|
PTSTR idEnd;
|
|
PCTSTR start;
|
|
PCTSTR end;
|
|
|
|
MYASSERT (StringIMatchCharCount (SetLine, TEXT("SET"), 3));
|
|
|
|
if (AppendedToBuffer) {
|
|
*AppendedToBuffer = FALSE;
|
|
}
|
|
//
|
|
// First, skip past the set and any whitespace.
|
|
//
|
|
start = SkipSpace(CharCountToPointer((PWSTR)SetLine,3));
|
|
|
|
if (!start) {
|
|
|
|
//
|
|
// line is of the form SET
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
end = _tcschr(start,TEXT('='));
|
|
|
|
if (!end) {
|
|
//
|
|
// line is of the form SET dafasdfasdfasdfasd
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
if (start==end) {
|
|
|
|
//
|
|
// line is of the form SET=
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Create an identifier now.
|
|
//
|
|
StringCopyAB(setIdentifier,start,end);
|
|
idEnd = GetEndOfString (setIdentifier);
|
|
|
|
//
|
|
// Shake off any space.
|
|
//
|
|
idEnd = (PTSTR) SkipSpaceR(setIdentifier,idEnd);
|
|
|
|
if (!idEnd) {
|
|
//
|
|
// Line is of the form SET =
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
idEnd = _tcsinc(idEnd);
|
|
*idEnd = TEXT('\0');
|
|
|
|
if (StringIMatch(setIdentifier,TEXT("PATH"))) {
|
|
|
|
DEBUGMSG((DBG_DOSMIG,"Env setting is really a path statement. passing off to path migration function."));
|
|
|
|
//
|
|
// This is really a path setting. let the proper function take care of it.
|
|
//
|
|
start = SkipSpace(CharCountToPointer((PWSTR)SetLine,3));
|
|
if(AppendedToBuffer){
|
|
*AppendedToBuffer = TRUE;
|
|
}
|
|
return pMigratePathSettings(start);
|
|
}
|
|
|
|
//
|
|
// Now that setIdentifier is well formed, root out the value to be set.
|
|
//
|
|
|
|
//
|
|
// Move start to the beginning of the value to be set.
|
|
//
|
|
start = SkipSpace(_tcsinc(end));
|
|
|
|
if (!start) {
|
|
//
|
|
// Line is of the form SET <id>=
|
|
// Nothing to do.
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Good to go. Let MigrateEnvSetting handle it.
|
|
//
|
|
DEBUGMSG((DBG_DOSMIG,"handing massaged set statement to env migration function."));
|
|
return pMigrateEnvSetting(setIdentifier,start, TRUE, Buffer, AppendedToBuffer);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
pProcessLine (
|
|
DWORD Type,
|
|
PGROWBUFFER Buffer,
|
|
PTSTR Line
|
|
)
|
|
{
|
|
|
|
BOOL rSuccess = TRUE;
|
|
LONG migrateRc = ERROR_SUCCESS;
|
|
PTSTR migrateString;
|
|
BOOL bAppendOrigLine;
|
|
TCHAR fixedCmdLine[MAX_CMDLINE];
|
|
|
|
|
|
//
|
|
// Do type specific massaging of the line
|
|
//
|
|
switch (Type) {
|
|
|
|
case DOSMIG_UNKNOWN: case DOSMIG_BAD: case DOSMIG_IGNORE:
|
|
|
|
g_FileChanged = TRUE;
|
|
|
|
GrowBufAppendString (Buffer,TEXT("REM "));
|
|
|
|
//
|
|
// intentionally skipped break.
|
|
//
|
|
|
|
case DOSMIG_USE:
|
|
|
|
//
|
|
// Perform path conversion on Line, then write it to the file
|
|
//
|
|
|
|
StackStringCopy (fixedCmdLine, Line);
|
|
ConvertWin9xCmdLine (fixedCmdLine, NULL, NULL);
|
|
|
|
GrowBufAppendString (Buffer, fixedCmdLine);
|
|
GrowBufAppendString (Buffer, TEXT("\r\n"));
|
|
|
|
break;
|
|
|
|
case DOSMIG_MIGRATE:
|
|
|
|
|
|
|
|
DEBUGMSG((DBG_DOSMIG,"Processing a potentially migrateable line. (%s)",Line));
|
|
|
|
if (IsPatternMatch(TEXT("doskey*"),Line) || IsPatternMatch(TEXT("*\\doskey*"),Line)) {
|
|
GrowBufAppendString (Buffer,TEXT("REM "));
|
|
}
|
|
|
|
//
|
|
// Skip space and ECHO OFF char (@) if any.
|
|
// Also, skip any path portion of the string.
|
|
// i.e, convert path/doskey to doskey.
|
|
|
|
migrateString = (PTSTR) SkipSpace(Line);
|
|
|
|
if (*migrateString == TEXT('@')) {
|
|
migrateString = (PTSTR) _tcsinc(migrateString);
|
|
}
|
|
|
|
migrateString = (PTSTR) pGetFileNameStartFromPath(migrateString);
|
|
|
|
bAppendOrigLine = TRUE;
|
|
|
|
//
|
|
// Now, attempt to determine what migration case this is.
|
|
//
|
|
if (IsPatternMatch(TEXT("prompt*"),migrateString)) {
|
|
|
|
DEBUGMSG((DBG_DOSMIG,"Migrating prompt. (%s)",migrateString));
|
|
migrateRc = pSetPrompt(migrateString);
|
|
if (migrateRc != ERROR_SUCCESS) {
|
|
rSuccess = FALSE;
|
|
LOG((LOG_ERROR,"Dosmig: Error trying to Set Prompt."));
|
|
}
|
|
ELSE_DEBUGMSG((DBG_DOSMIG,"Prompt successfully migrated."));
|
|
}
|
|
else if (IsPatternMatch(TEXT("doskey *"),migrateString)) {
|
|
|
|
//
|
|
// Doskey migration.
|
|
//
|
|
|
|
if (IsPatternMatch(TEXT("*/I*"),migrateString)) {
|
|
g_MigrateDoskeySetting = TRUE;
|
|
DEBUGMSG((DBG_DOSMIG,"Insert mode will be enabled for each user. (%s)",migrateString));
|
|
}
|
|
ELSE_DEBUGMSG((DBG_DOSMIG,"Doskey command found. However, no migrateable doskey settings found. Command ignored."));
|
|
|
|
}
|
|
else if (IsPatternMatch(TEXT("path=*"),migrateString)
|
|
|| IsPatternMatch(TEXT("path *"),migrateString)) {
|
|
|
|
//
|
|
// PATH migration.
|
|
//
|
|
|
|
DEBUGMSG((DBG_DOSMIG,"Migrating path setting (%s)",migrateString));
|
|
migrateRc = pMigratePathSettings(migrateString);
|
|
if (migrateRc != ERROR_SUCCESS) {
|
|
rSuccess = FALSE;
|
|
LOG((LOG_ERROR,"Dosmig: Error trying to migrate path settings."));
|
|
}
|
|
ELSE_DEBUGMSG((DBG_DOSMIG,"Path successfully migrated."));
|
|
|
|
}
|
|
else if (IsPatternMatch(TEXT("set *"),migrateString)) {
|
|
|
|
BOOL b;
|
|
//
|
|
// SET migration.
|
|
//
|
|
DEBUGMSG((DBG_DOSMIG,"Migrating env variable. (%s)",migrateString));
|
|
migrateRc = pMigrateSetSetting(migrateString, Buffer, &b);
|
|
bAppendOrigLine = !b;
|
|
|
|
if (migrateRc != ERROR_SUCCESS) {
|
|
rSuccess = FALSE;
|
|
LOG((LOG_ERROR,"Dosmig: Error trying to migrate environment setting."));
|
|
}
|
|
ELSE_DEBUGMSG((DBG_DOSMIG,"Env variable successfully migrated."));
|
|
}
|
|
ELSE_DEBUGMSG((DBG_DOSMIG,"Dosmig: Line marked for migration doesn't fit any migration rule.\n%s",Line));
|
|
|
|
if (bAppendOrigLine) {
|
|
GrowBufAppendString (Buffer,Line);
|
|
}
|
|
//
|
|
// Last, append a CRLF into the buffer to be written.
|
|
//
|
|
GrowBufAppendString (Buffer,TEXT("\r\n"));
|
|
|
|
break;
|
|
default:
|
|
LOG((LOG_ERROR,"Dosmig: Invalid Type in switch statement."));
|
|
break;
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
pNewFile (
|
|
DWORD Offset
|
|
) {
|
|
|
|
TCHAR file[MAX_TCHAR_PATH];
|
|
static DWORD curOffset = INVALID_OFFSET;
|
|
|
|
BOOL rNewFile = FALSE;
|
|
|
|
|
|
if (Offset != curOffset && MemDbBuildKeyFromOffset(Offset,file,1,NULL)) {
|
|
|
|
//
|
|
// if there isn't a current file, or this is a new file, set the current file
|
|
// to this file.
|
|
//
|
|
|
|
if (!g_CurrentFile || !StringMatch(file,g_CurrentFile)) {
|
|
|
|
//
|
|
// If this is a genuine new file (i.e. not just the first file, we'll return true.)
|
|
//
|
|
rNewFile = g_CurrentFile != NULL;
|
|
|
|
g_LastFile = g_CurrentFile;
|
|
g_CurrentFile = PoolMemDuplicateString(g_Pool,file);
|
|
}
|
|
}
|
|
|
|
return rNewFile;
|
|
}
|
|
|
|
VOID
|
|
pCompletePathProcessing (
|
|
VOID
|
|
)
|
|
{
|
|
UINT i;
|
|
UINT size;
|
|
UINT winDirLen;
|
|
GROWBUFFER buf = GROWBUF_INIT;
|
|
PTSTR p;
|
|
TCHAR pathStatement[2*MAX_TCHAR_PATH];
|
|
TCHAR newPath[MAX_TCHAR_PATH];
|
|
HKEY key;
|
|
DWORD rc;
|
|
|
|
|
|
//
|
|
// Make sure %systemroot% and %systemroot%\system32 are in the path.
|
|
//
|
|
wsprintf (pathStatement, TEXT("PATH=%s"), g_WinDir);
|
|
pMigratePathSettings (pathStatement);
|
|
|
|
wsprintf (pathStatement, TEXT("PATH=%s\\system32"), g_WinDir);
|
|
pMigratePathSettings (pathStatement);
|
|
|
|
wsprintf (pathStatement, TEXT("PATH=%s\\system32\\WBEM"), g_WinDir);
|
|
pMigratePathSettings (pathStatement);
|
|
|
|
|
|
|
|
winDirLen = CharCount (g_WinDir);
|
|
size = GrowListGetSize (&g_PathList);
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
|
|
|
|
p = (PTSTR) GrowListGetString (&g_PathList, i);
|
|
|
|
if (StringIMatch (TEXT("%PATH%"), p)) {
|
|
//
|
|
// Skip self-replacement.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
if (GetFileStatusOnNt (p) & FILESTATUS_DELETED) {
|
|
|
|
//
|
|
// Skip this path portion. The directory was deleted.
|
|
//
|
|
DEBUGMSG ((DBG_DOSMIG, "Not migrating %s to new %%path%%. Directory was deleted.", p));
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// See if the path is moved.
|
|
//
|
|
if (GetFileInfoOnNt (p, newPath, MAX_TCHAR_PATH) & FILESTATUS_MOVED) {
|
|
|
|
p = newPath;
|
|
}
|
|
|
|
//
|
|
// Replace c:\windows with %systemroot%.
|
|
//
|
|
if (StringIMatchCharCount (g_WinDir, p, winDirLen)) {
|
|
|
|
GrowBufAppendString (&buf, TEXT("%SYSTEMROOT%"));
|
|
GrowBufAppendString (&buf, p + winDirLen);
|
|
}
|
|
else {
|
|
|
|
GrowBufAppendString (&buf, p);
|
|
}
|
|
|
|
GrowBufAppendString (&buf, TEXT(";"));
|
|
}
|
|
|
|
|
|
|
|
if (size) {
|
|
|
|
|
|
//
|
|
// Take off trailing ';'.
|
|
//
|
|
p = GetEndOfString ((PTSTR) buf.Buf);
|
|
if (p) {
|
|
p--;
|
|
*p = 0;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Save into registry.
|
|
//
|
|
key = OpenRegKey (HKEY_LOCAL_MACHINE,S_ENVIRONMENTKEY);
|
|
if (key && key != INVALID_HANDLE_VALUE) {
|
|
|
|
rc = RegSetValueEx (
|
|
key,
|
|
TEXT("Path"),
|
|
0,
|
|
REG_EXPAND_SZ,
|
|
(PBYTE) buf.Buf,
|
|
SizeOfString((PCTSTR) buf.Buf)
|
|
);
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
DEBUGMSG ((DBG_WARNING, "Unable to create migrated Path variable."));
|
|
}
|
|
|
|
CloseRegKey (key);
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_WARNING, "pCompletePathProcessing: Unable to open environment key."));
|
|
}
|
|
|
|
//
|
|
// Clean up resources.
|
|
//
|
|
FreeGrowBuffer (&buf);
|
|
}
|
|
|
|
VOID
|
|
pPathListToBuffer(
|
|
GROWBUFFER * growBuf
|
|
)
|
|
{
|
|
INT i;
|
|
|
|
i = GrowListGetSize (&g_PathList);
|
|
if(i <= 0){
|
|
return;
|
|
}
|
|
|
|
GrowBufAppendString (growBuf, TEXT("\r\nPATH="));
|
|
for (--i; i >= 0; i--) {
|
|
GrowBufAppendString (growBuf, GrowListGetString (&g_PathList, i));
|
|
if(i){
|
|
GrowBufAppendString (growBuf, TEXT(";"));
|
|
}
|
|
}
|
|
GrowBufAppendString (growBuf, TEXT("\r\n"));
|
|
}
|
|
|
|
BOOL
|
|
pGeneralMigration (
|
|
VOID
|
|
)
|
|
{
|
|
BOOL rSuccess = TRUE; // return value.
|
|
MEMDB_ENUM eItems; // Enumerator for each dosmig line.
|
|
TCHAR lineBuffer[MEMDB_MAX]; // Buffer for the contents of the current line.
|
|
GROWBUFFER buffer = GROWBUF_INIT;
|
|
TCHAR key[MEMDB_MAX];
|
|
DWORD offset;
|
|
DWORD value;
|
|
INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
|
|
PTSTR p = NULL;
|
|
TCHAR pathStatement[MAX_PATH];
|
|
|
|
|
|
//
|
|
// Assume that there are no doskey settings to migrate.
|
|
//
|
|
g_MigrateDoskeySetting = FALSE;
|
|
|
|
|
|
//
|
|
// Set the change flag to false.
|
|
//
|
|
g_FileChanged = FALSE;
|
|
|
|
|
|
//
|
|
// Read in the suppression table from win95upg.inf and add it the suppression table.
|
|
//
|
|
g_SuppressionTable = HtAlloc ();
|
|
|
|
if (InfFindFirstLine (g_WkstaMigInf, S_SUPPRESSED_ENV_VARS, NULL, &is)) {
|
|
do {
|
|
|
|
p = InfGetStringField (&is, 0);
|
|
if (p) {
|
|
HtAddString (g_SuppressionTable, p);
|
|
}
|
|
} while (InfFindNextLine (&is));
|
|
}
|
|
|
|
InfCleanUpInfStruct (&is);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Ok, enumerate through each dosmigration line in memdb. These lines are stored
|
|
// as following:
|
|
//
|
|
// DOSMIG LINES\<item>\<field>\<data>
|
|
//
|
|
// Where
|
|
// o item is a 5 digit enumerator string.
|
|
// o field is one of either TYPE,TEXT,DESC,or FILE
|
|
// o data is the data associated with the field. For TYPE, data contains a string
|
|
// representation of the LINETYPE, for TEXT, it contains the actual text of the line
|
|
// for DESC, it contains a description supplied by DOSMIG95's parse rules and for FILE
|
|
// it contains the originating file (config.sys, autoexec.bat)
|
|
//
|
|
|
|
//
|
|
// Add %system32% by default
|
|
//
|
|
wsprintf (pathStatement, TEXT("PATH=%s\\system32"), g_WinDir);
|
|
pMigratePathSettings (pathStatement);
|
|
|
|
if (MemDbEnumItems(&eItems,MEMDB_CATEGORY_DM_LINES)) {
|
|
|
|
do {
|
|
|
|
//
|
|
// Get the actual line contents.
|
|
//
|
|
if (MemDbGetEndpointValueEx(
|
|
MEMDB_CATEGORY_DM_LINES,
|
|
eItems.szName,
|
|
NULL,
|
|
lineBuffer
|
|
)) {
|
|
|
|
|
|
//
|
|
// Get the value and flags from this endpoint.
|
|
//
|
|
MemDbBuildKey(key,MEMDB_CATEGORY_DM_LINES,eItems.szName,NULL,lineBuffer);
|
|
MemDbGetValueAndFlags(key, &offset, &value);
|
|
|
|
|
|
if (pNewFile(offset)) {
|
|
|
|
//
|
|
// the S_ENVVARS entry is a special case and is not an actual file. All of its entries are simply migrated
|
|
// into the registry.
|
|
//
|
|
if (!StringIMatch(g_LastFile,S_ENVVARS)) {
|
|
if (_tcsistr(g_LastFile, TEXT("autoexec.bat"))){
|
|
//
|
|
// Flush PathList to actual buffer
|
|
//
|
|
pPathListToBuffer(&buffer);
|
|
}
|
|
pSaveBufferToAnsiFile(g_LastFile,STRINGBUFFER(&buffer));
|
|
}
|
|
buffer.End = 0;
|
|
g_FileChanged = FALSE;
|
|
}
|
|
|
|
rSuccess = pProcessLine(value,&buffer,lineBuffer);
|
|
DEBUGMSG_IF((rSuccess, DBG_DOSMIG,"Line successfully processed. (%s)",lineBuffer));
|
|
if (!rSuccess) {
|
|
LOG ((LOG_ERROR,"Dosmig: Error processing line. (%s)",lineBuffer));
|
|
}
|
|
|
|
}
|
|
else {
|
|
LOG((LOG_ERROR,"Dosmig: MemDbGetEndpointValueEx failed trying to retrieve line %s",eItems.szName));
|
|
}
|
|
|
|
} while (MemDbEnumNextValue(&eItems) && rSuccess);
|
|
|
|
|
|
//
|
|
// Get the file name and save the file off.
|
|
//
|
|
if (!StringIMatch(g_CurrentFile,S_ENVVARS)) {
|
|
if (_tcsistr(g_CurrentFile, TEXT("autoexec.bat"))){
|
|
//
|
|
// Flush PathList to actual buffer
|
|
//
|
|
pPathListToBuffer(&buffer);
|
|
}
|
|
pSaveBufferToAnsiFile(g_CurrentFile,STRINGBUFFER(&buffer));
|
|
}
|
|
|
|
pCompletePathProcessing ();
|
|
FreeGrowList (&g_PathList);
|
|
|
|
}
|
|
ELSE_DEBUGMSG((DBG_DOSMIG,"No lines to migrate..."));
|
|
|
|
//
|
|
// Free our growbuffer.
|
|
//
|
|
FreeGrowBuffer(&buffer);
|
|
|
|
//
|
|
// Clean up the suppression table.
|
|
//
|
|
HtFree (g_SuppressionTable);
|
|
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DosMigNt_Entry (
|
|
IN HINSTANCE hinstDLL,
|
|
IN DWORD dwReason,
|
|
IN PVOID lpv
|
|
)
|
|
{
|
|
BOOL rSuccess = TRUE;
|
|
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
g_Pool = PoolMemInitNamedPool ("DOS mig - NT side");
|
|
rSuccess = g_Pool != NULL;
|
|
|
|
// Set flag to indicate that migration information has not
|
|
// yet been processed.
|
|
g_MigrationPrepared = FALSE;
|
|
|
|
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
rSuccess = TRUE;
|
|
PoolMemDestroyPool(g_Pool);
|
|
break;
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
LONG
|
|
DosMigNt_User (
|
|
IN HKEY User
|
|
)
|
|
{
|
|
LONG rc = ERROR_SUCCESS;
|
|
|
|
if (!g_MigrationPrepared) {
|
|
if (pGeneralMigration()) {
|
|
g_MigrationPrepared = TRUE;
|
|
}
|
|
else {
|
|
LOG((LOG_ERROR,"Dosmig: General migration failed"));
|
|
}
|
|
}
|
|
|
|
if (g_MigrationPrepared) {
|
|
//
|
|
// Turn off autoexec.bat parsing.
|
|
//
|
|
rc = pTurnAutoParseOff(User);
|
|
|
|
if (g_MigrateDoskeySetting) {
|
|
rc = pTurnInsertModeOn(User);
|
|
if (rc != ERROR_SUCCESS) {
|
|
LOG ((LOG_ERROR,"Dosmig: Error attempting to turn insert mode on."));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
LONG
|
|
DosMigNt_System(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
|
|
if (!g_MigrationPrepared) {
|
|
if (pGeneralMigration()) {
|
|
g_MigrationPrepared = TRUE;
|
|
}
|
|
else {
|
|
LOG((LOG_ERROR,"Dosmig: General migration failed"));
|
|
}
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|