|
|
//--------------------------------------------------------------
//
// File: bothchar
//
// Contents: Functions that need to be compiled as ascii for
// scanstate and unicode for loadstate.
//
//---------------------------------------------------------------
#include "bothchar.hxx"
//---------------------------------------------------------------
// Constants
UCHAR EMPTY_STRING[] = "";
const UCHAR NEWLINE_SET[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const DWORD VERBOSE_BIT = 0x01; // used with -v flag
const DWORD DEBUGOUTPUT_BIT = 0x02; // used with -v flag
const DWORD VERBOSEREG_BIT = 0x04; // used with -v flag
#define LOADSTATE_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Loadstate")
//---------------------------------------------------------------
// Globals.
TCHAR *DomainName = NULL; TCHAR *UserName = NULL; TCHAR *UserPath = NULL;
//---------------------------------------------------------------
void CStringList::Add( CStringList *pslMore ) { CStringList *b; CStringList *c; CStringList *d;
// Do nothing if there is no list.
if (pslMore == NULL) return;
// Determine some nodes to work with.
b = pslMore->_pslNext; c = pslMore; d = _pslNext;
// Relink the list so head points to b is a list to c points to d is
// a list back to head.
_pslNext = b; c->_pslNext = d; }
//---------------------------------------------------------------
CStringList::CStringList( DWORD dwLen ) { _pslNext = this; if (dwLen == 0) { _ptsString = NULL; _fHead = TRUE; } else { _fHead = FALSE; _ptsString = (TCHAR *) malloc( dwLen*sizeof(TCHAR) ); } }
//---------------------------------------------------------------
CStringList::~CStringList() { CStringList *pslCurrent = _pslNext; CStringList *pslEnd;
// Non header nodes just free their string.
if (_ptsString != NULL) free( _ptsString ); // Header nodes free the list.
if (_fHead) { while (pslCurrent != this) { pslEnd = pslCurrent->_pslNext; delete pslCurrent; pslCurrent = pslEnd; } } }
//---------------------------------------------------------------
DWORD ParseSectionList( INFCONTEXT *pic, TCHAR **pptsLabel, CStringList **pslList ) { DWORD len; BOOL fSuccess; DWORD dwFields; DWORD i; DWORD dwResult = ERROR_SUCCESS; CStringList *pslCurrent;
// Initialize output
*pslList = NULL;
// Query the length of the label name
fSuccess = SetupGetStringField( pic, 0, NULL, 0, &len ); LOG_ASSERT_GLE( fSuccess, dwResult );
// Allocate space
*pptsLabel = (TCHAR *) malloc( len * sizeof(TCHAR) ); LOG_ASSERT_EXPR( *pptsLabel != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY );
// Read the label name
fSuccess = SetupGetStringField( pic, 0, *pptsLabel, len, NULL ); LOG_ASSERT_GLE( fSuccess, dwResult );
// Find out how many fields are on the line.
dwFields = SetupGetFieldCount( pic ); LOG_ASSERT_GLE( dwFields != 0, dwResult );
// Read each field.
for (i = 1; i <= dwFields; i++) { // Query the length of the field
fSuccess = SetupGetStringField( pic, i, NULL, 0, &len ); LOG_ASSERT_GLE( fSuccess, dwResult );
// Allocate a new node.
pslCurrent = new CStringList( len ); LOG_ASSERT_EXPR( pslCurrent != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY); LOG_ASSERT_EXPR( pslCurrent->String() != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY );
// Copy the field into the node.
fSuccess = SetupGetStringField( pic, i, pslCurrent->String(), len, NULL ); LOG_ASSERT_GLE( fSuccess, dwResult );
// Link the node in the list.
if (*pslList == NULL) *pslList = pslCurrent; else (*pslList)->Add( pslCurrent ); }
cleanup: return dwResult; }
/***************************************************************************
ParseRegPath
Read a string field from a line in the rules inf file and parse it into a root, key, and value. All components of the reg path are optional.
root\key [value]
***************************************************************************/
DWORD ParseRegPath( INFCONTEXT *pic, DWORD dwField, TCHAR **pptsRoot, TCHAR **pptsKey, TCHAR **pptsValue ) { TCHAR *ptsBuffer = NULL; TCHAR *ptsStop; TCHAR *ptsStart; TCHAR *bracket; BOOL fSuccess; DWORD dwLen = 0; DWORD dwResult = ERROR_SUCCESS;
//Null out return values in case of later error.
*pptsRoot = NULL; *pptsKey = NULL; *pptsValue = NULL; // Compute the length of the reg path field.
SetupGetStringField( pic, dwField, NULL, 0, &dwLen );
// Allocate a buffer.
ptsBuffer = (TCHAR *) malloc( dwLen*sizeof(TCHAR) ); LOG_ASSERT_EXPR( ptsBuffer != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY );
// Get the whole reg path. The function fails if the field is empty.
fSuccess = SetupGetStringField( pic, dwField, ptsBuffer, dwLen, &dwLen ); if (!fSuccess) { free( ptsBuffer ); return ERROR_SUCCESS; }
// Look for a backslash.
ptsStop = _tcschr( ptsBuffer, TEXT('\\') );
// If there wasn't one, there is no root.
if (ptsStop == NULL) { *pptsRoot = NULL; ptsStart = ptsBuffer; }
// If there was one, copy the root name.
else { *pptsRoot = (TCHAR *) malloc( ((ptsStop - ptsBuffer) + 1) * sizeof(TCHAR) ); LOG_ASSERT_EXPR( *pptsRoot != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY ); _tcsncpy( *pptsRoot, ptsBuffer, ptsStop - ptsBuffer ); (*pptsRoot)[ptsStop - ptsBuffer] = 0; ptsStart = ptsStop + 1; }
// Look for an opening square bracket.
ptsStop = _tcschr( ptsStart, TEXT('[') );
// If there wasn't one, copy the rest of the string to the key name.
if (ptsStop == NULL) { if (ptsStart[0] == 0) *pptsKey = NULL; else { *pptsKey = (TCHAR *) malloc( (dwLen - (ptsStart - ptsBuffer)) * sizeof(TCHAR) ); *pptsValue = NULL; LOG_ASSERT_EXPR( *pptsKey != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY ); _tcscpy( *pptsKey, ptsStart ); } }
// Handle an optional key and a value.
else { // Back up past any intervening white space.
bracket = ptsStop + 1; while (ptsStop != ptsStart && (ptsStop[0] == TEXT(' ') || ptsStop[0] == TEXT('['))) ptsStop -= 1;
// If there are any characters left, copy them to the key.
if (ptsStop != ptsStart) { ptsStop += 1; *pptsKey = (TCHAR *) malloc( ((ptsStop - ptsStart) + 1) * sizeof(TCHAR) ); LOG_ASSERT_EXPR( *pptsKey != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY ); _tcsncpy( *pptsKey, ptsStart, ptsStop - ptsStart ); (*pptsKey)[ptsStop - ptsStart] = 0; } else *pptsKey = NULL;
// Find the closing square bracket.
ptsStart = bracket; bracket = _tcschr( ptsStart, TEXT(']') ); LOG_ASSERT_EXPR( bracket != NULL, IDS_INF_ERROR, dwResult, SPAPI_E_GENERAL_SYNTAX );
// Copy the value name.
*pptsValue = (TCHAR *) malloc( ((bracket - ptsStart) + 1) * sizeof(TCHAR) ); LOG_ASSERT_EXPR( *pptsValue != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY ); _tcsncpy( *pptsValue, ptsStart, bracket - ptsStart ); (*pptsValue)[bracket - ptsStart] = 0; }
cleanup: if (ptsBuffer != NULL) free( ptsBuffer ); return dwResult; }
/***************************************************************************
ParseRule
Read a line from the rules inf file in one of the following formats. When partial paths are specified, compute the full path. Create a rule record from the line.
reg_path2 is optional and reg_path is parsed by the function ParseRegPath into a root, key, and value. reg-path1 = reg_path2
If reg_path2 contains just a leaf name, generate a full path using the path from reg_path1 and replacing its leaf with the leaf from reg_path2.
***************************************************************************/
DWORD ParseRule( INFCONTEXT *pic, HASH_NODE **pphnRule ) { TCHAR *ptsBuffer; DWORD dwReqLen; DWORD dwResult = ERROR_SUCCESS; BOOL fSuccess; TCHAR *ptsLast; TCHAR *ptsTemp;
// Allocate a new rule.
*pphnRule = (HASH_NODE *) malloc( sizeof(HASH_NODE) ); LOG_ASSERT_EXPR( *pphnRule != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY ); (*pphnRule)->dwAction = 0; (*pphnRule)->phnNext = 0; (*pphnRule)->ptsNewValue = NULL; (*pphnRule)->ptsNewKey = NULL; (*pphnRule)->ptsFunction = NULL; (*pphnRule)->ptsFileDest = NULL;
// Get the first reg path.
dwResult = ParseRegPath( pic, 0, &(*pphnRule)->ptsRoot, &(*pphnRule)->ptsKey, &(*pphnRule)->ptsValue ); FAIL_ON_ERROR( dwResult );
// Get the second reg path.
dwResult = ParseRegPath( pic, 1, &ptsBuffer, &(*pphnRule)->ptsNewKey, &(*pphnRule)->ptsNewValue ); FAIL_ON_ERROR( dwResult );
// Get the optional regfile destination
fSuccess = SetupGetStringField( pic, 2, NULL, 0, &dwReqLen ); if ((TRUE == fSuccess) && (dwReqLen > 0)) { (*pphnRule)->ptsFileDest = (TCHAR *)malloc(dwReqLen * sizeof(TCHAR)); LOG_ASSERT_EXPR( (*pphnRule)->ptsFileDest != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY );
fSuccess = SetupGetStringField(pic, 2, (*pphnRule)->ptsFileDest, dwReqLen, NULL); LOG_ASSERT_GLE(fSuccess, dwResult); }
// If the original key ends with a star, remove it and set the recursive
// flag.
if ((*pphnRule)->ptsKey != NULL) { dwReqLen = _tcslen( (*pphnRule)->ptsKey ); if (dwReqLen > 2 && (*pphnRule)->ptsKey[dwReqLen-1] == TEXT('*') && (*pphnRule)->ptsKey[dwReqLen-2] == TEXT('\\')) { (*pphnRule)->dwAction |= recursive_fa; (*pphnRule)->ptsKey[dwReqLen-2] = 0; } // If there is a new key, set the rename_leaf or rename_path flag.
if ((*pphnRule)->ptsNewKey != NULL) if ((*pphnRule)->dwAction & recursive_fa) (*pphnRule)->dwAction |= rename_path_fa; else (*pphnRule)->dwAction |= rename_leaf_fa; }
// If there is a new value, set the rename_value flag.
if ((*pphnRule)->ptsNewValue != NULL) (*pphnRule)->dwAction |= rename_value_fa;
// If the new key did not contain a root, compute a full path for it.
if (ptsBuffer == NULL && (*pphnRule)->ptsKey != NULL && (*pphnRule)->ptsNewKey != NULL) { // Find the last backslash in the key.
ptsLast = (*pphnRule)->ptsKey; do { ptsTemp = _tcschr( ptsLast, TEXT('\\') ); if (ptsTemp != NULL) ptsLast = ptsTemp+1; } while (ptsTemp != NULL);
// Don't do anything if the original key contains just a leaf.
if (ptsLast != (*pphnRule)->ptsKey) {
// Allocate a ptsBuffer to hold the old path and the new leaf.
free( ptsBuffer ); dwReqLen = _tcslen( (*pphnRule)->ptsNewKey ) + (ptsLast - (*pphnRule)->ptsKey) + 2; ptsBuffer = (TCHAR *) malloc( dwReqLen*sizeof(TCHAR) ); LOG_ASSERT_EXPR( ptsBuffer != NULL, IDS_NOT_ENOUGH_MEMORY, dwResult, ERROR_NOT_ENOUGH_MEMORY );
// Copy in the old path and the new leaf.
_tcsncpy( ptsBuffer, (*pphnRule)->ptsKey, (ptsLast - (*pphnRule)->ptsKey) ); _tcscpy( &ptsBuffer[ptsLast-(*pphnRule)->ptsKey], (*pphnRule)->ptsNewKey ); free( (*pphnRule)->ptsNewKey ); (*pphnRule)->ptsNewKey = ptsBuffer; } } else free(ptsBuffer);
// Consider freeing strings on error.
cleanup: if (dwResult != ERROR_SUCCESS) { if (*pphnRule != NULL) { free((*pphnRule)->ptsRoot); free((*pphnRule)->ptsKey); free((*pphnRule)->ptsValue); free((*pphnRule)->ptsNewKey); free((*pphnRule)->ptsNewValue); free((*pphnRule)->ptsFunction); free((*pphnRule)->ptsFileDest); free(*pphnRule); *pphnRule = NULL; } } return dwResult; }
//---------------------------------------------------------------
// This function prints from an ascii format string to a unicode
// win32 file handle. It is not thread safe.
DWORD Win32Printf( HANDLE file, char *format, ... ) { va_list va; DWORD dwWritten; DWORD dwLen; DWORD dwWideLength; WCHAR *pwsBuffer = NULL; const ULONG LINEBUFSIZE = 4096; #ifdef UNICODE
char *pszBuffer; int iCharLen; char szOutputBuffer[LINEBUFSIZE]; #endif
BOOL fSuccess; TCHAR tcsPrintBuffer[LINEBUFSIZE]; TCHAR *ptsFormat;
#ifdef UNICODE
WCHAR wcsFormat[LINEBUFSIZE];
dwWideLength = MultiByteToWideChar(CP_ACP, 0, format, -1, NULL, 0); if (dwWideLength >= LINEBUFSIZE) { pwsBuffer = (WCHAR *)_alloca( dwWideLength * sizeof(WCHAR)); if (pwsBuffer == NULL) return ERROR_NOT_ENOUGH_MEMORY; ptsFormat = pwsBuffer; if (!MultiByteToWideChar( CP_ACP, 0, format, -1, pwsBuffer, dwWideLength )) return GetLastError(); } else { if (!MultiByteToWideChar(CP_ACP, 0, format, -1, wcsFormat, LINEBUFSIZE)) { return GetLastError(); } ptsFormat = wcsFormat; } #else
ptsFormat = format; #endif
va_start( va, format );
// The doc says if wvsprintf fails, return value is less than
// the length of the expected output. Since its hard to know the
// correct output length, always clear the last error and always
// check it.
SetLastError(ERROR_SUCCESS); wvsprintf( tcsPrintBuffer, ptsFormat, va ); va_end(va); if (GetLastError() != ERROR_SUCCESS) return GetLastError();
// When printing to the console or logfile use ascii.
// When printing to the migration file use Unicode.
dwLen = _tcslen(tcsPrintBuffer); if ((file != OutputFile) || OutputAnsi) { #ifdef UNICODE
//Convert to ANSI for output
iCharLen = WideCharToMultiByte(CP_ACP, 0, tcsPrintBuffer, -1, NULL, 0, NULL, NULL); if (iCharLen >= LINEBUFSIZE) { pszBuffer = (char *)_alloca( iCharLen * sizeof(char)); if (pszBuffer == NULL) return ERROR_OUTOFMEMORY; if (!WideCharToMultiByte(CP_ACP, 0, tcsPrintBuffer, -1, pszBuffer, iCharLen, NULL, NULL)) return GetLastError(); pwsBuffer = (WCHAR *)pszBuffer; } else { if (!WideCharToMultiByte(CP_ACP, 0, tcsPrintBuffer, -1, szOutputBuffer, LINEBUFSIZE, NULL, NULL)) return GetLastError(); pwsBuffer = (WCHAR *)szOutputBuffer; } dwWideLength = dwLen; #else
pwsBuffer = (WCHAR *) tcsPrintBuffer; dwWideLength = dwLen; #endif
} else { #ifdef UNICODE
pwsBuffer = tcsPrintBuffer; dwWideLength = dwLen * sizeof(WCHAR); #else
// Allocate a buffer to hold the unicode string.
DEBUG_ASSERT( dwLen < LINEBUFSIZE ); dwWideLength = MultiByteToWideChar( CP_ACP, 0, tcsPrintBuffer, dwLen, NULL, 0 ); pwsBuffer = (WCHAR *) _alloca( dwWideLength*sizeof(WCHAR) ); if (pwsBuffer == NULL) return ERROR_NOT_ENOUGH_MEMORY;
// Convert the buffer to unicode.
dwWideLength = MultiByteToWideChar( CP_ACP, 0, tcsPrintBuffer, dwLen, pwsBuffer, dwWideLength ); if (dwWideLength == 0) return GetLastError(); dwWideLength *= sizeof(WCHAR); #endif
}
// Write the unicode string.
fSuccess = WriteFile( file, pwsBuffer, dwWideLength, &dwWritten, NULL ); if (!fSuccess || dwWideLength != dwWritten) return GetLastError();
if (file == STDERR) { //Also write to the log file for these
fSuccess = WriteFile( LogFile, pwsBuffer, dwWideLength, &dwWritten, NULL ); if (!fSuccess || dwWideLength != dwWritten) { return GetLastError(); } }
return ERROR_SUCCESS; }
//*****************************************************************
//
// Synopsis: Recursive function to make the command line. We have to do
// this because CStringList stores the parameter in reverse
// order.
//
// Parameters: h
// We need to know when we reach the end of the
// CStringList, which is denoted by pointing back to the
// head of the chain. But in a recursive function we lose
// the head of the chain so it is passed in.
//
// History: 11/8/1999 Created by WeiruC.
//
// Return Value: Win32 error code.
//
//*****************************************************************
void MakeCommandLine(CStringList* h, CStringList* command, TCHAR* commandLine) { if (h==NULL || command == NULL || commandLine == NULL) { if (DebugOutput) { Win32Printf(LogFile, "Error: NULL pointer passed to MakeCommandLine\r\n"); } _tcscpy(commandLine, TEXT("")); return; } if(command->Next() != h) { MakeCommandLine(h, command->Next(), commandLine); }
// No sizes of these buffers are passed in, so we must assume that there is enough space
_tcscat(commandLine, TEXT("\"")); _tcscat(commandLine, command->String()); _tcscat(commandLine, TEXT("\"")); _tcscat(commandLine, TEXT(" ")); }
//---------------------------------------------------------------
// This is a variation of strpbrk. It searchs a string that may
// contain nulls for any character in the set. It returns a pointer
// to the first character in the set or null if the string does
// not contain any characters in the set. Since the function
// searchs past nulls in the str parameter, the len parameter
// indicates the actual length of str. The set is an array of
// booleans.
UCHAR *mempbrk( UCHAR *str, DWORD len, const UCHAR set[256] ) { DWORD i;
for (i = 0; i < len; i++) if (set[str[i]] != 0) return &str[i]; return NULL; }
//---------------------------------------------------------------
DWORD WriteKey( HANDLE outfile, DWORD type, TCHAR *rootname, TCHAR *key, TCHAR *value_name, UCHAR *data, DWORD data_len ) { DWORD result = ERROR_SUCCESS; DWORD j; UCHAR *curr; DWORD orig = 0;
// If a string contains an embedded carriage return or linefeed, save
// it as binary and convert it back to a string on read.
if (type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) { curr = mempbrk( data, data_len, NEWLINE_SET ); if (curr != NULL) { if (type == REG_SZ) orig = 0x400000; else if (type == REG_MULTI_SZ) orig = 0x100000; else orig = 0x200000; type = REG_BINARY; } }
if (NULL == rootname) rootname = TEXT(""); if (NULL == key) key = TEXT(""); if (NULL == value_name) value_name = TEXT("");
switch (type) { case REG_DWORD: if (data == NULL) *data = 0; result = Win32Printf( outfile, "%s, \"%s\", \"%s\", 0x10001, 0x%x\r\n", rootname, key, value_name, *((DWORD *) data) ); FAIL_ON_ERROR( result ); break;
case REG_EXPAND_SZ: case REG_SZ: if (data == NULL) data = EMPTY_STRING; result = Win32Printf( outfile, "%s, \"%s\", \"%s\", 0x%x, \"%s\"\r\n", rootname, key, value_name, type == REG_SZ ? FLG_ADDREG_TYPE_SZ : FLG_ADDREG_TYPE_EXPAND_SZ, data ); FAIL_ON_ERROR( result ); break;
case REG_MULTI_SZ:
// Print the start of the line and the first string.
if (data == NULL) data = EMPTY_STRING; result = Win32Printf( outfile, "%s, \"%s\", \"%s\", 0x10000, \"%s\"", rootname, key, value_name, data ); FAIL_ON_ERROR( result );
// Print each remaining string.
curr = data+strlen((char *) data)+1; do { // Print a comma and the current string.
Win32Printf( outfile, ", \"%s\"", curr );
// Skip passed the current string and its null.
curr += strlen((char *) curr)+1; } while ((DWORD) (curr - data) < data_len);
// Print the trailing newline.
result = Win32Printf( outfile, "\r\n" ); FAIL_ON_ERROR( result ); break;
case REG_BINARY: case REG_NONE: default: // Unknown types, just copy the type and treat the data as binary
// Print the start of the line.
result = Win32Printf( outfile, "%s, \"%s\", \"%s\", 0x%x", rootname, key, value_name, ((type == REG_NONE ? 0x800000 : type ) | orig) ); FAIL_ON_ERROR( result );
// Print each byte in hex without the 0x prefix.
for (j = 0; j < data_len; j++) { result = Win32Printf( outfile, ",%x", data[j] ); FAIL_ON_ERROR( result ); if ( (j+1) % 20 == 0) { result = Win32Printf( outfile, "\\\r\n" ); FAIL_ON_ERROR( result ); } }
result = Win32Printf( outfile, "\r\n" ); FAIL_ON_ERROR( result ); break; }
cleanup: return result; }
//---------------------------------------------------------------
//
DWORD LogReadRule( HASH_NODE *phnNode ) { DWORD dwRetval = ERROR_SUCCESS; BOOL fRuleFound = FALSE;
dwRetval = Win32Printf(LogFile, "Read rule: "); FAIL_ON_ERROR( dwRetval );
if (phnNode->dwAction & function_fa ) { dwRetval = Win32Printf(LogFile, "function"); FAIL_ON_ERROR( dwRetval ); fRuleFound = TRUE; } if (phnNode->dwAction & (rename_leaf_fa | rename_path_fa | rename_value_fa)) { dwRetval = Win32Printf(LogFile, "rename" ); FAIL_ON_ERROR( dwRetval ); fRuleFound = TRUE; } if (phnNode->dwAction & file_fa) { dwRetval = Win32Printf(LogFile, "copy file"); FAIL_ON_ERROR( dwRetval ); fRuleFound = TRUE; } if (phnNode->dwAction & delete_fa || phnNode->dwAction & suppress_fa) { dwRetval = Win32Printf(LogFile, "delete" ); FAIL_ON_ERROR( dwRetval ); fRuleFound = TRUE; } // If none of the above, then it must be an addreg
if ( fRuleFound == FALSE ) { dwRetval = Win32Printf(LogFile, "addreg" ); FAIL_ON_ERROR( dwRetval ); }
dwRetval = Win32Printf(LogFile, " %s\\%s ", phnNode->ptsRoot, phnNode->ptsKey); FAIL_ON_ERROR( dwRetval );
if ( phnNode->ptsValue != NULL ) { dwRetval = Win32Printf(LogFile, "[%s] ", phnNode->ptsValue ); FAIL_ON_ERROR( dwRetval ); }
if ( phnNode->ptsNewKey != NULL || phnNode->ptsNewValue != NULL ) { dwRetval = Win32Printf(LogFile, "to "); FAIL_ON_ERROR( dwRetval ); if (phnNode->ptsNewKey != NULL) { dwRetval = Win32Printf(LogFile, "%s ", phnNode->ptsNewKey); FAIL_ON_ERROR( dwRetval ); } if (phnNode->ptsNewValue != NULL) { dwRetval = Win32Printf(LogFile, "[%s]", phnNode->ptsNewValue); FAIL_ON_ERROR( dwRetval ); } }
dwRetval = Win32Printf(LogFile, "\r\n"); FAIL_ON_ERROR( dwRetval );
cleanup: return (dwRetval); } //---------------------------------------------------------------
char *GetValueFromRegistry(const char *lpValue) { HKEY hKey; char *buffer = NULL; DWORD dwDataSize = 0; DWORD result;
result = RegOpenKeyEx( HKEY_CURRENT_USER, LOADSTATE_KEY, 0, KEY_READ, &hKey ); FAIL_ON_ERROR( result );
// Determine size needed
dwDataSize = 0; result = RegQueryValueExA( hKey, lpValue, NULL, NULL, NULL, &dwDataSize); FAIL_ON_ERROR( result ); buffer = (char *)malloc((dwDataSize + 1) * sizeof(char)); if (NULL == buffer) { Win32PrintfResource(Console, IDS_NOT_ENOUGH_MEMORY); goto cleanup; } result = RegQueryValueExA( hKey, lpValue, NULL, NULL, (LPBYTE)buffer, &dwDataSize);
cleanup: if ((ERROR_SUCCESS != result) && (NULL != buffer)) { free(buffer); buffer = NULL; } RegCloseKey(hKey);
return buffer; }
#define MAX_VALUE_LENGTH 255
//---------------------------------------------------------------
DWORD OpenInfsFromRegistry() { HKEY hKey; DWORD dwIndex = 0; char szData[MAX_PATH + 1]; char szValueName[MAX_VALUE_LENGTH]; DWORD dwValueSize; DWORD dwDataSize; DWORD result = ERROR_SUCCESS;
result = RegOpenKeyEx( HKEY_CURRENT_USER, LOADSTATE_KEY, 0, KEY_READ, &hKey ); FAIL_ON_ERROR( result );
do { dwDataSize = MAX_PATH; dwValueSize = MAX_VALUE_LENGTH; result = RegEnumValueA(hKey, dwIndex, szValueName, &dwValueSize, NULL, NULL, (UCHAR *)szData, &dwDataSize);
if (ERROR_NO_MORE_ITEMS != result) { FAIL_ON_ERROR( result );
// If this is an Inf* key, then open the Inf file
if (0 == strncmp(szValueName, "Inf", 3)) { result = OpenInf( szData ); FAIL_ON_ERROR( result ); }
dwIndex++; } } while (ERROR_SUCCESS == result);
cleanup: RegCloseKey(hKey); return result; }
//---------------------------------------------------------------
DWORD ParseParams( int argc, char *argv[], BOOL scan, TCHAR *pszFullLogFilename ) { int i; BOOL cleared_flags = FALSE; DWORD result; char *error; int iarg; BOOL fAppendLog = FALSE; BOOL fLogFile = FALSE; TCHAR *logfile = NULL; TCHAR szArgv[MAX_PATH + 1]; char *lpData;
// Save the OS version.
Win9x = (GetVersion() & 0x80000000);
// Check all the parameters.
for (i = 1; i < argc; i++) { if (argv[i][0] == '/' || argv[i][0] == '-') { switch (tolower(argv[i][1])) { case 'a': OutputAnsi = TRUE; break; case 'f': CopyFiles = TRUE; if (!cleared_flags) { CopyUser = FALSE; CopySystem = FALSE; SchedSystem = FALSE; cleared_flags = TRUE; } break; case 'i': // Verify that there is a file name.
if (i == argc-1) { Win32PrintfResourceA( Console, IDS_INF_REQUIRED ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; }
// Open the inf file.
i += 1; result = OpenInf( argv[i] ); if (result != ERROR_SUCCESS) return result; break; case 'l': // Verify that there is a file name.
if (i == argc-1) { Win32PrintfResourceA( Console, IDS_LOG_REQUIRED ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; }
// Fail if the log file was already specified.
if (fLogFile == TRUE) { Win32PrintfResourceA( Console, IDS_LOG_ONCE ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; }
i += 1; #ifdef _UNICODE
if (0 == MultiByteToWideChar (GetACP(), 0, argv[i], -1, szArgv, MAX_PATH)) { result = GetLastError(); Win32PrintfResourceA( Console, IDS_INVALID_PARAMETER, argv[i] ); return result; } logfile = szArgv; #else
logfile = argv[i]; #endif
fLogFile = TRUE; break; case 'm': ReallyCopyFiles = FALSE; break; case 'p': UserPortion = TRUE; fAppendLog = TRUE;
if (!scan) { if (fLogFile == TRUE) { Win32PrintfResourceA( Console, IDS_LOG_ONCE ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; } lpData = GetValueFromRegistry("Logfile"); #ifdef _UNICODE
if (0 == MultiByteToWideChar (GetACP(), 0, lpData, -1, szArgv, MAX_PATH)) { result = GetLastError(); Win32PrintfResourceA( Console, IDS_INVALID_PARAMETER, lpData); return result; } logfile = szArgv; #else
logfile = lpData; #endif
fLogFile = TRUE;
MigrationPath = GetValueFromRegistry("Store"); if (MigrationPath != NULL) { MultiByteToWideChar(CP_ACP, 0, MigrationPath, -1, wcsMigrationPath, MAX_PATH + 1); }
OpenInfsFromRegistry(); } break; case 'q': // TestMode will:
// - skip version checking the OS
// - not create a user hive with /f (still will with /u)
TestMode = TRUE; break; case 'r': // run once
SchedSystem = TRUE; if (!cleared_flags) { CopyFiles = FALSE; CopySystem = FALSE; CopyUser = FALSE; cleared_flags = TRUE; } break; case 's': CopySystem = TRUE; if (!cleared_flags) { CopyFiles = FALSE; CopyUser = FALSE; SchedSystem = FALSE; cleared_flags = TRUE; } break; case 'u': CopyUser = TRUE; if (!cleared_flags) { CopyFiles = FALSE; CopySystem = FALSE; SchedSystem = FALSE; cleared_flags = TRUE; } break; case 'v': // Verify that there is a verbosity argument
i += 1; if ((i == argc) || (1 != sscanf(argv[i], "%d", &iarg))) { Win32PrintfResourceA( Console, IDS_VERBOSE_FLAG_REQUIRED ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; }
if ( ( iarg & VERBOSE_BIT ) == VERBOSE_BIT ) { Verbose = TRUE; } if ( ( iarg & DEBUGOUTPUT_BIT ) == DEBUGOUTPUT_BIT ) { DebugOutput = TRUE; } if ( ( iarg & VERBOSEREG_BIT ) == VERBOSEREG_BIT ) { VerboseReg = TRUE; } break; case 'x': if (!cleared_flags) { CopyFiles = FALSE; CopySystem = FALSE; CopyUser = FALSE; SchedSystem = FALSE; cleared_flags = TRUE; } break; case '9': Win9x = TRUE; break;
default:
// There should be no other switches defined.
Win32PrintfResourceA( Console, IDS_INVALID_PARAMETER, argv[i] ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; } } else if (MigrationPath != NULL) { // The path to the server should be specified exactly once.
Win32PrintfResourceA( Console, IDS_INVALID_PARAMETER, argv[i] ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; } else { // Save the migration path.
MigrationPath = argv[i]; DWORD ccMigPath; if (!(ccMigPath = MultiByteToWideChar(CP_ACP, 0, MigrationPath, -1, wcsMigrationPath, MAX_PATH + 1))) { Win32PrintfResourceA( Console, IDS_INVALID_PARAMETER, MigrationPath ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; } } }
// Verify that a path was specified.
if (MigrationPath == NULL) { Win32PrintfResourceA( Console, IDS_MISSING_MIGRATION ); PrintHelp( scan ); return ERROR_INVALID_PARAMETER; }
// Open LogFile
if ( fLogFile == FALSE ) { if (scan) logfile = TEXT("scanstate.log"); else logfile = TEXT("loadstate.log"); } if (fAppendLog == FALSE) { // Delete any previous log
DeleteFile( logfile ); } LogFile = CreateFile( logfile, GENERIC_WRITE, 0, NULL, fAppendLog ? OPEN_ALWAYS : CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); if (LogFile == INVALID_HANDLE_VALUE) { result = GetLastError(); Win32PrintfResourceA( Console, IDS_OPEN_LOG_ERROR, logfile ); error = NULL; FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, result, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &error, 0, NULL ); if (error != NULL) { Win32Printf( Console, error ); LocalFree( error ); } return result; } else if (fAppendLog == TRUE) { // Move file pointer to the end of the file,
// so we won't overwrite previous entries
result = SetFilePointer( LogFile, 0, NULL, FILE_END); if ( result == INVALID_SET_FILE_POINTER ) { result = GetLastError(); Win32PrintfResourceA( Console, IDS_OPEN_LOG_ERROR, logfile ); error = NULL; FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, result, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &error, 0, NULL ); if (error != NULL) { Win32Printf( Console, error ); LocalFree( error ); } return result; } }
TCHAR *ptsFileNamePart; result = GetFullPathName( logfile, MAX_PATH, pszFullLogFilename, &ptsFileNamePart); if (0 == result) { return GetLastError(); }
return ERROR_SUCCESS; }
|