|
|
/*++
Copyright (c) 1997 Microsoft Corporation All rights reserved.
Module Name:
Util.c
Abstract:
Uitility routines for printer migration from Win9x to NT
Author:
Muhunthan Sivapragasam (MuhuntS) 02-Jan-1996
Revision History:
--*/
#include "precomp.h"
VOID DebugMsg( LPCSTR pszFormat, ... ) /*++
Routine Description: On debug builds brings up a message box on severe errors
Arguments: pszFormat : Format string
Return Value: None
--*/ { #if DBG
LPSTR psz; CHAR szMsg[1024]; va_list vargs;
va_start(vargs, pszFormat); vsprintf(szMsg, pszFormat, vargs); va_end(vargs);
#ifdef MYDEBUG
if ( psz = GetStringFromRcFileA(IDS_TITLE) ) {
MessageBoxA(NULL, szMsg, psz, MB_OK); FreeMem(psz); } #else
OutputDebugStringA("Printing Migration : "); OutputDebugStringA(szMsg); OutputDebugStringA("\n"); #endif
#endif
}
VOID LogError( IN LogSeverity Severity, IN UINT uMessageId, ... ) /*++
Routine Description: Logs an error in the setup error log on NT side when something can not be upgraded
Arguments: uMessageId : Id to string in .rc file
Return Value: None
--*/ { LPSTR pszFormat; CHAR szMsg[1024];
va_list vargs;
va_start(vargs, uMessageId);
pszFormat = GetStringFromRcFileA(uMessageId);
if ( pszFormat ) {
wvsprintfA(szMsg, pszFormat, vargs); DebugMsg("%s", szMsg); SetupLogErrorA(szMsg, Severity); }
FreeMem(pszFormat);
va_end(vargs); }
LPSTR ErrorMsg( VOID ) /*++
Routine Description: Returns the error message string from a Win32 error
Arguments: None
Return Value: Pointer to a message string. Caller should free the string
--*/ { DWORD dwLastError; LPSTR pszStr = NULL;
if ( !(dwLastError = GetLastError()) ) dwLastError = STG_E_UNKNOWN;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, dwLastError, 0, (LPSTR)&pszStr, 0, NULL);
return pszStr; }
PVOID AllocMem( IN UINT cbSize ) /*++
Routine Description: Allocate memory from the heap
Arguments: cbSize : Byte count
Return Value: Pointer to the allocated memory
--*/ { return LocalAlloc(LPTR, cbSize); }
VOID FreeMem( IN PVOID p ) /*++
Routine Description: Free memory allocated on the heap
Arguments: p : Pointer to the memory to be freed
Return Value: None
--*/ { LocalFree(p); }
LPSTR AllocStrA( LPCSTR pszStr ) /*++
Routine Description: Allocate memory and make a copy of an ansi string field
Arguments: pszStr : String to copy
Return Value: Pointer to the copied string. Memory is allocated.
--*/ { LPSTR pszRet = NULL;
if ( pszStr && *pszStr ) {
pszRet = AllocMem((strlen(pszStr) + 1) * sizeof(CHAR)); if ( pszRet ) strcpy(pszRet, pszStr); }
return pszRet; }
LPWSTR AllocStrW( LPCWSTR pszStr ) /*++
Routine Description: Allocate memory and make a copy of a unicode string field
Arguments: pszStr : String to copy
Return Value: Pointer to the copied string. Memory is allocated.
--*/ { LPWSTR pszRet = NULL;
if ( pszStr && *pszStr ) {
pszRet = AllocMem((wcslen(pszStr) + 1) * sizeof(WCHAR)); if ( pszRet ) wcscpy(pszRet, pszStr); }
return pszRet; }
LPWSTR AllocStrWFromStrA( LPCSTR pszStr ) /*++
Routine Description: Returns the unicode string for a give ansi string. Memory is allocated.
Arguments: pszStr : Gives the ansi string to copy
Return Value: Pointer to the copied unicode string. Memory is allocated.
--*/ { DWORD dwLen; LPWSTR pszRet = NULL;
if ( pszStr && *pszStr && (dwLen = strlen(pszStr)) && (pszRet = AllocMem((dwLen + 1) * sizeof(WCHAR))) ) {
if ( MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszStr, dwLen, pszRet, dwLen) ) {
pszRet[dwLen] = 0; } else {
FreeMem(pszRet); pszRet = NULL; }
}
return pszRet; }
LPSTR AllocStrAFromStrW( LPCWSTR pszStr ) /*++
Routine Description: Returns the ansi string for a give unicode string. Memory is allocated.
Arguments: pszStr : Gives the ansi string to copy
Return Value: Pointer to the copied ansi string. Memory is allocated.
--*/ { DWORD dwLen; LPSTR pszRet = NULL;
if ( pszStr && *pszStr && (dwLen = wcslen(pszStr)) && (pszRet = AllocMem((dwLen + 1 ) * sizeof(CHAR))) ) {
WideCharToMultiByte(CP_ACP, 0, pszStr, dwLen, pszRet, dwLen, NULL, NULL ); }
return pszRet; }
BOOL WriteToFile( HANDLE hFile, LPCSTR pszFormat, ... ) /*++
Routine Description: Format and write a string to the text file. This is used to write the printing configuration on Win9x
Arguments: hFile : File handle pszFormat : Format string for the message
Return Value: None
--*/ { CHAR szMsg[1024]; va_list vargs; DWORD dwSize, dwWritten; BOOL bRet;
bRet = TRUE;
va_start(vargs, pszFormat); vsprintf(szMsg, pszFormat, vargs); va_end(vargs);
dwSize = strlen(szMsg) * sizeof(CHAR);
if ( !WriteFile(hFile, (LPCVOID)szMsg, dwSize, &dwWritten, NULL) || dwSize != dwWritten ) {
bRet = FALSE; } return bRet; }
VOID WriteString( IN HANDLE hFile, IN OUT LPBOOL pbFail, IN LPCSTR pszStr ) /*++
Routine Description: Writes a string to the upgrade file on Win9x side. Since spooler strings (ex. printer name, driver name) can have space in them we would write all strings with []\n. So we can read strings with space on NT.
Arguments: hFile : File handle pszFormat : Format string for the message pszStr : String to write
Return Value: None
--*/ { DWORD dwLen;
if ( pszStr ) {
dwLen = strlen(pszStr); WriteToFile(hFile, "%3d [%s]\n", dwLen, pszStr); }
}
LPSTR GetStringFromRcFileA( UINT uId ) /*++
Routine Description: Load a string from the .rc file and make a copy of it by doing AllocStr
Arguments: uId : Identifier for the string to be loaded
Return Value: String value loaded, NULL on error. Caller should free the memory
--*/ { CHAR buf[MAX_PATH];
if ( LoadStringA(g_hInst, uId, buf, sizeof(buf) )) return AllocStrA(buf); else return NULL; }
VOID ReadString( IN HANDLE hFile, OUT LPSTR *ppszParam1, OUT LPSTR *ppszParam2 ) { CHAR c; LPSTR pszParameter1; LPSTR pszParameter2; DWORD dwLen; CHAR LineBuffer[MAX_PATH]; DWORD Idx;
//
// Initialize local.
//
c = 0; pszParameter1 = NULL; pszParameter2 = NULL; dwLen = 0; Idx = 0; memset(LineBuffer, 0, sizeof(LineBuffer));
//
// Initialize caller buffer
//
*ppszParam1 = NULL; *ppszParam2 = NULL;
//
// First skip space/\r/\n.
//
c = (CHAR) My_fgetc(hFile); while( (' ' == c) || ('\n' == c) || ('\r' == c) ) { c = (CHAR) My_fgetc(hFile); }
//
// See if it's EOF.
//
if(EOF == c){ //
// End of file.
//
goto ReadString_return; }
//
// Get a line.
//
Idx = 0; while( ('\n' != c) && (EOF != c) ){ LineBuffer[Idx++] = c; c = (CHAR) My_fgetc(hFile); } // while( ('\n' != c) && (EOF != c) )
dwLen = Idx;
//
// See if it's EOF.
//
if(EOF == c){ //
// Illegal migration file.
//
SetupLogError("WIA Migration: ReadString: ERROR!! Illegal migration file.", LogSevError); goto ReadString_return; }
//
// See if it's double quated.
//
if('\"' == LineBuffer[0]){ pszParameter1 = &LineBuffer[1]; Idx = 1; } else { // if('\"' == LineBuffer[0])
//
// There's no '"'. Invalid migration file.
//
SetupLogError("WIA Migration: ReadString: ERROR!! Illegal migration file with no Quote.", LogSevError); goto ReadString_return; } // if('\"' == LineBuffer[0])
//
// Find next '"' and replace with '\0'.
//
for(;'\"' != LineBuffer[Idx]; Idx++); LineBuffer[Idx] = '\0';
//
// Find next (3rd) '"', it's beginning of 2nd parameter.
//
for(;'\"' != LineBuffer[Idx]; Idx++); pszParameter2 = &LineBuffer[++Idx];
//
// Find last '"' and replace with '\0'.
//
for(;'\"' != LineBuffer[Idx]; Idx++); LineBuffer[Idx] = '\0';
//
// Allocate buffer for returning string.
//
*ppszParam1 = AllocStrA(pszParameter1); *ppszParam2 = AllocStrA(pszParameter2);
ReadString_return: return; } // ReadString()
VOID ReadDword( IN HANDLE hFile, IN LPSTR pszLine, IN DWORD dwLineSize, IN LPSTR pszPrefix, OUT LPDWORD pdwValue, IN OUT LPBOOL pbFail ) { LPSTR psz;
if ( *pbFail || My_fgets(pszLine, dwLineSize, hFile) == NULL ) {
*pbFail = TRUE; return; }
//
// First check the prefix matches to make sure we are in the right line
//
for ( psz = (LPSTR)pszLine ; *pszPrefix && *psz == *pszPrefix ; ++psz, ++pszPrefix ) ;
if ( *pszPrefix ) {
*pbFail = TRUE; return; }
//
// Skip spaces
//
while ( *psz && *psz == ' ' ) ++psz;
*pdwValue = atoi(psz); }
VOID ReadDevMode( IN HANDLE hFile, OUT LPDEVMODEA *ppDevMode, IN OUT LPBOOL pbFail ) { LPSTR pszPrefix = "DevMode:"; CHAR c; DWORD dwLen; LPINT ptr;
if ( *pbFail ) return;
// First skip the prefix
//
while ( *pszPrefix && (c = (CHAR) My_fgetc(hFile)) == *pszPrefix++ ) ;
if ( *pszPrefix ) goto Fail;
//
// Skip spaces
//
while ( (c = (CHAR) My_fgetc(hFile)) == ' ' ) ;
//
// Now is the devmode size
//
if ( !isdigit(c) ) goto Fail;
dwLen = c - '0'; while ( isdigit(c = (CHAR) My_fgetc(hFile)) ) dwLen = dwLen * 10 + c - '0';
if ( dwLen == 0 ) return;
if ( c != ' ' ) goto Fail;
//
// Now the devmode is there between []
//
if ( *ppDevMode = (LPDEVMODEA) AllocMem(dwLen) ) {
if ( (c = (CHAR) My_fgetc(hFile)) != '[' ) goto Fail;
if ( dwLen != My_fread((LPVOID)*ppDevMode, dwLen, hFile) ) goto Fail;
//
// Make sure now we have "]\n" to End
//
if ( (CHAR) My_fgetc(hFile) != ']' || (CHAR) My_fgetc(hFile) != '\n' ) {
DebugMsg("Char check fails"); goto Fail; }
return; // Succesful exit
}
Fail: *pbFail = TRUE; }
LONG WriteRegistryToFile( IN HANDLE hFile, IN HKEY hKey, IN LPCSTR pszPath ) { LONG lError; HKEY hSubKey; DWORD dwValueSize; DWORD dwDataSize; DWORD dwSubKeySize; DWORD dwTypeBuffer;
PCHAR pSubKeyBuffer; PCHAR pValueBuffer; PCHAR pDataBuffer;
DWORD Idx; //
// Initialize local.
//
lError = ERROR_SUCCESS; hSubKey = (HKEY)INVALID_HANDLE_VALUE; dwValueSize = 0; dwDataSize = 0; dwSubKeySize = 0; dwTypeBuffer = 0; Idx = 0; pSubKeyBuffer = NULL; pValueBuffer = NULL; pDataBuffer = NULL;
//
// Query necessary buffer size.
//
lError = RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, &dwSubKeySize, NULL, NULL, &dwValueSize, &dwDataSize, NULL, NULL); if(ERROR_SUCCESS != lError){
//
// Unable to retrieve key info.
//
goto WriteRegistryToFile_return;
} // if(ERROR_SUCCESS != lError)
//
// Allocate buffers.
//
dwValueSize = (dwValueSize+1+1) * sizeof(CHAR); dwSubKeySize = (dwSubKeySize+1) * sizeof(CHAR);
pValueBuffer = AllocMem(dwValueSize); pDataBuffer = AllocMem(dwDataSize); pSubKeyBuffer = AllocMem(dwSubKeySize);
if( (NULL == pValueBuffer) || (NULL == pDataBuffer) || (NULL == pSubKeyBuffer) ) {
//
// Insufficient memory.
//
SetupLogError("WIA Migration: WriteRegistryToFile: ERROR!! Unable to allocate buffer.", LogSevError); lError = ERROR_NOT_ENOUGH_MEMORY; goto WriteRegistryToFile_return; } // if(NULL == pDataBuffer)
//
// Indicate beginning of this subkey to the file.
//
WriteToFile(hFile, "\"%s\" = \"BEGIN\"\r\n", pszPath);
//
// Enumerate all values.
//
while(ERROR_SUCCESS == lError){
DWORD dwLocalValueSize; DWORD dwLocalDataSize; //
// Reset buffer and size.
//
dwLocalValueSize = dwValueSize; dwLocalDataSize = dwDataSize; memset(pValueBuffer, 0, dwValueSize); memset(pDataBuffer, 0, dwDataSize);
//
// Acquire registry value/data..
//
lError = RegEnumValueA(hKey, Idx, pValueBuffer, &dwLocalValueSize, NULL, &dwTypeBuffer, pDataBuffer, &dwLocalDataSize); if(ERROR_NO_MORE_ITEMS == lError){ //
// End of data.
//
continue; } // if(ERROR_NO_MORE_ITEMS == lError)
if(ERROR_SUCCESS != lError){ //
// Unable to read registry value.
//
SetupLogError("WIA Migration: WriteRegistryToFile: ERROR!! Unable to acqure registry value/data.", LogSevError); goto WriteRegistryToFile_return; } // if(ERROR_NO_MORE_ITEMS == lError)
//
// Write this value to a file.
//
lError = WriteRegistryValueToFile(hFile, pValueBuffer, dwTypeBuffer, pDataBuffer, dwLocalDataSize); if(ERROR_SUCCESS != lError){ //
// Unable to write to a file.
//
SetupLogError("WIA Migration: WriteRegistryToFile: ERROR!! Unable to write to a file.", LogSevError); goto WriteRegistryToFile_return; } // if(ERROR_SUCCESS != lError)
//
// Goto next value.
//
Idx++; } // while(ERROR_SUCCESS == lError)
//
// Enumerate all sub keys.
//
lError = ERROR_SUCCESS; Idx = 0;
while(ERROR_SUCCESS == lError){
memset(pSubKeyBuffer, 0, dwSubKeySize); lError = RegEnumKeyA(hKey, Idx++, pSubKeyBuffer, dwSubKeySize); if(ERROR_SUCCESS == lError){
//
// There's sub key exists. Spew it to the file and store all the
// values recursively.
//
lError = RegOpenKey(hKey, pSubKeyBuffer, &hSubKey); if(ERROR_SUCCESS != lError){ SetupLogError("WIA Migration: WriteRegistryToFile: ERROR!! Unable to open subkey.", LogSevError); continue; } // if(ERROR_SUCCESS != lError)
//
// Call subkey recursively.
//
lError = WriteRegistryToFile(hFile, hSubKey, pSubKeyBuffer);
} // if(ERROR_SUCCESS == lError)
} // while(ERROR_SUCCESS == lError)
if(ERROR_NO_MORE_ITEMS == lError){ //
// Operation completed as expected.
//
lError = ERROR_SUCCESS;
} // if(ERROR_NO_MORE_ITEMS == lError)
//
// Indicate end of this subkey to the file.
//
WriteToFile(hFile, "\"%s\" = \"END\"\r\n", pszPath);
WriteRegistryToFile_return:
//
// Clean up.
//
if(NULL != pValueBuffer){ FreeMem(pValueBuffer); } // if(NULL != pValueBuffer)
if(NULL != pDataBuffer){ FreeMem(pDataBuffer); } // if(NULL != pDataBuffer)
if(NULL != pSubKeyBuffer){ FreeMem(pSubKeyBuffer); } // if(NULL != pSubKeyBuffer)
return lError; } // WriteRegistryToFile()
LONG WriteRegistryValueToFile( HANDLE hFile, LPSTR pszValue, DWORD dwType, PCHAR pDataBuffer, DWORD dwSize ) {
LONG lError; PCHAR pSpewBuffer; DWORD Idx;
//
// Initialize locals.
//
lError = ERROR_SUCCESS; pSpewBuffer = NULL;
//
// Allocate buffer for actual spew.
//
pSpewBuffer = AllocMem(dwSize*3); if(NULL == pSpewBuffer){ //
// Unable to allocate buffer.
//
lError = ERROR_NOT_ENOUGH_MEMORY; goto WriteRegistryValueToFile_return; } // if(NULL == pSpewBuffer)
for(Idx = 0; Idx < dwSize; Idx++){ wsprintf(pSpewBuffer+Idx*3, "%02x", pDataBuffer[Idx]); *(pSpewBuffer+Idx*3+2) = ','; } // for(Idx = 0; Idx < dwSize; Idx++)
*(pSpewBuffer+dwSize*3-1) = '\0'; WriteToFile(hFile, "\"%s\" = \"%08x:%s\"\r\n", pszValue, dwType, pSpewBuffer); //
// Operation succeeded.
//
lError = ERROR_SUCCESS;
WriteRegistryValueToFile_return:
//
// Clean up.
//
if(NULL != pSpewBuffer){ FreeMem(pSpewBuffer); } // if(NULL != pSpewBuffer)
return lError;
} // WriteRegistryValueToFile()
LONG GetRegData( HKEY hKey, LPSTR pszValue, PCHAR *ppDataBuffer, PDWORD pdwType, PDWORD pdwSize ) {
LONG lError; PCHAR pTempBuffer; DWORD dwRequiredSize; DWORD dwType; //
// Initialize local.
//
lError = ERROR_SUCCESS; pTempBuffer = NULL; dwRequiredSize = 0; dwType = 0; //
// Get required size.
//
lError = RegQueryValueEx(hKey, pszValue, NULL, &dwType, NULL, &dwRequiredSize); if( (ERROR_SUCCESS != lError) || (0 == dwRequiredSize) ) { pTempBuffer = NULL; goto GetRegData_return;
} // if(ERROR_MORE_DATA != lError)
//
// If it doesn't need actual data, just bail out.
//
if(NULL == ppDataBuffer){ lError = ERROR_SUCCESS; goto GetRegData_return; } // if(NULL == ppDataBuffer)
//
// Allocate buffer to receive data.
//
pTempBuffer = AllocMem(dwRequiredSize); if(NULL == pTempBuffer){ //
// Allocation failed.
//
SetupLogError("WIA Migration: GetRegData: ERROR!! Unable to allocate buffer.", LogSevError); lError = ERROR_NOT_ENOUGH_MEMORY; goto GetRegData_return; } // if(NULL == pTempBuffer)
//
// Query the data.
//
lError = RegQueryValueEx(hKey, pszValue, NULL, &dwType, pTempBuffer, &dwRequiredSize); if(ERROR_SUCCESS != lError){ //
// Data acquisition somehow failed. Free buffer.
//
goto GetRegData_return; } // if(ERROR_SUCCESS != lError)
GetRegData_return:
if(ERROR_SUCCESS != lError){ //
// Operation unsuccessful. Free the buffer if allocated.
//
if(NULL != pTempBuffer){ FreeMem(pTempBuffer); pTempBuffer = NULL; } // if(NULL != pTempBuffer)
} // if(ERROR_SUCCESS != lError)
//
// Copy the result.
//
if(NULL != pdwSize){ *pdwSize = dwRequiredSize; } // if(NULL != pdwSize)
if(NULL != ppDataBuffer){ *ppDataBuffer = pTempBuffer; } // if(NULL != ppDataBuffer)
if(NULL != pdwType){ *pdwType = dwType; } // if(NULL != pdwType)
return lError; } // GetRegData()
VOID MyLogError( LPCSTR pszFormat, ... ) { LPSTR psz; CHAR szMsg[1024]; va_list vargs;
if(NULL != pszFormat){ va_start(vargs, pszFormat); vsprintf(szMsg, pszFormat, vargs); va_end(vargs);
SetupLogError(szMsg, LogSevError); } // if(NULL != pszFormat)
} // MyLogError()
|