|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
regmigrt.c
Abstract:
Registry migration routines
Author:
Ted Miller (tedm) 12-Apr-1996
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
typedef enum { AddQuotesNone, AddQuotesNormal, AddQuotesOpenNoClose, AddQuotesNoOpenOrClose, } AddQuotesOp;
BOOL RetrieveMessageIntoBufferV( IN UINT MessageId, OUT PTSTR Buffer, IN UINT BufferSizeChars, IN va_list *arglist ) { DWORD d;
d = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM, hInst, MessageId, 0, Buffer, BufferSizeChars, arglist );
if(!d) {
d = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, hInst, MSG_NOT_FOUND, 0, Buffer, BufferSizeChars, (va_list *)&MessageId );
if(!d) {
return FALSE; } } return TRUE; }
DWORD WriteText( IN HANDLE FileHandle, IN UINT MessageId, ... ) { TCHAR Message[2048]; CHAR message[4096]; va_list arglist; DWORD Written; BOOL b;
va_start(arglist,MessageId);
b = RetrieveMessageIntoBufferV( MessageId, Message, sizeof(Message)/sizeof(Message[0]), &arglist );
va_end(arglist);
if(!b) return ERROR_INVALID_PARAMETER;
#ifdef UNICODE
Written = (DWORD)WideCharToMultiByte( CP_ACP, 0, Message, lstrlen(Message), message, sizeof(message), NULL, NULL ); #else
StringCchCopyA(message,sizeof(message),Message); Written = lstrlen(message); #endif
b = WriteFile(FileHandle,message,Written,&Written,NULL);
return(b ? NO_ERROR : GetLastError()); }
DWORD FlushGenInfLineBuf( IN OUT PINFFILEGEN Context, IN HANDLE File ) { CHAR TransBuf[INFLINEBUFLEN*2]; DWORD rc; PVOID Buffer; DWORD Size; BOOL b;
Buffer = TransBuf;
#ifdef UNICODE
Size = WideCharToMultiByte( CP_ACP, 0, Context->LineBuf, Context->LineBufUsed, TransBuf, sizeof(TransBuf), NULL, NULL ); #else
StringCchCopyA(TransBuf,sizeof(TransBuf),Context->LineBuf); Size = Context->LineBufUsed; #endif
if(WriteFile(File,Buffer,Size,&rc,NULL)) { rc = NO_ERROR; Context->LineBufUsed = 0; } else { rc = GetLastError(); }
return(rc); }
DWORD __inline GenInfWriteChar( IN OUT PINFFILEGEN Context, IN HANDLE File, IN TCHAR Char ) { DWORD rc; PVOID Buffer;
Context->LineBuf[Context->LineBufUsed++] = Char;
rc = (Context->LineBufUsed == INFLINEBUFLEN) ? FlushGenInfLineBuf(Context,File) : NO_ERROR;
return(rc); }
DWORD GenInfWriteString( IN OUT PINFFILEGEN Context, IN HANDLE File, IN LPCTSTR String, IN AddQuotesOp AddQuotes ) { DWORD rc; TCHAR CONST *p;
if((AddQuotes == AddQuotesNormal) || (AddQuotes == AddQuotesOpenNoClose)) { rc = GenInfWriteChar(Context,File,TEXT('\"')); if(rc != NO_ERROR) { return(rc); } }
for(p=String; *p; p++) { rc = GenInfWriteChar(Context,File,*p); if(rc != NO_ERROR) { return(rc); }
if((*p == TEXT('\"')) && (AddQuotes != AddQuotesNone)) { rc = GenInfWriteChar(Context,File,TEXT('\"')); if(rc != NO_ERROR) { return(rc); } } }
if(AddQuotes == AddQuotesNormal) { rc = GenInfWriteChar(Context,File,TEXT('\"')); if(rc != NO_ERROR) { return(rc); } }
return(NO_ERROR); }
DWORD CreateAndOpenTempFile( IN LPCTSTR Path, IN LPCTSTR HeaderLine, OPTIONAL OUT HANDLE *Handle, OUT PTSTR Filename ) { HANDLE h; DWORD rc;
//
// Note that this creates the file.
//
if(!GetTempFileName(Path,TEXT("$IF"),0,Filename)) { rc = GetLastError(); goto c0; }
h = CreateFile( Filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if(h == INVALID_HANDLE_VALUE) { rc = GetLastError(); goto c1; }
if(HeaderLine) { rc = WriteText(h,MSG_INF_SINGLELINE,HeaderLine); if(rc != NO_ERROR) { goto c2; } }
*Handle = h; return(NO_ERROR);
c2: CloseHandle(h); c1: DeleteFile(Filename); c0: return(rc); }
DWORD InfCreateSection( IN LPCTSTR SectionName, IN OUT PINFFILEGEN *Context ) { PTSTR Buffer; DWORD rc;
Buffer = MALLOC( (lstrlen(SectionName) + 3)*sizeof(TCHAR) ); if( !Buffer ) { return ERROR_NOT_ENOUGH_MEMORY; } lstrcpy( Buffer, TEXT("[") ); lstrcat( Buffer, SectionName ); lstrcat( Buffer, TEXT("]") );
rc = WriteText((*Context)->FileHandle,MSG_INF_SINGLELINE,Buffer); FREE( Buffer );
return(rc); }
DWORD InfStart( IN LPCTSTR InfName, IN LPCTSTR Directory, OUT PINFFILEGEN *Context ) { TCHAR InfFileName[MAX_PATH]; DWORD d; DWORD rc; PINFFILEGEN context; UCHAR UnicodeMark[2]; PTSTR p; DWORD BytesWritten = 0;
//
// Allocate some context.
//
context = MALLOC(sizeof(INFFILEGEN));
if(!context) { rc = ERROR_NOT_ENOUGH_MEMORY; goto c0; }
ZeroMemory(context,sizeof(INFFILEGEN));
//
// We'll create a unique inf name in the given directory
// to use as the output inf. The directory itself will
// become the oem file root.
//
if(!GetFullPathName(Directory,MAX_PATH,context->FileName,&p)) { rc = GetLastError(); goto c1; }
if (!ConcatenatePaths(context->FileName,InfName,MAX_PATH)) { rc = ERROR_BUFFER_OVERFLOW; goto c1; }
SetFileAttributes(context->FileName, FILE_ATTRIBUTE_NORMAL); DeleteFile(context->FileName);
//
// Create the output file.
//
context->FileHandle = CreateFile( context->FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if(context->FileHandle == INVALID_HANDLE_VALUE) { rc = GetLastError(); goto c1; }
//
// Write out header for inf file.
//
WriteFile(context->FileHandle, INF_FILE_HEADER, strlen(INF_FILE_HEADER), &BytesWritten, NULL);
rc = GetLastError(); if(rc != NO_ERROR) { goto c5; }
*Context = context; return(NO_ERROR);
c5: CloseHandle(context->FileHandle); DeleteFile(context->FileName); c1: FREE(context); c0: return(rc); }
DWORD InfEnd( IN OUT PINFFILEGEN *Context ) { PINFFILEGEN context; DWORD rc; HANDLE h; DWORD Size;
context = *Context; *Context = NULL;
h = context->FileHandle;
rc = NO_ERROR;
CloseHandle(h); if(rc != NO_ERROR) { DeleteFile(context->FileName); } FREE(context); return(rc); }
DWORD pInfRegLineCommon( IN OUT PINFFILEGEN Context, IN HANDLE OutputFile, IN HKEY Key, IN LPCTSTR Subkey, IN LPCTSTR Value OPTIONAL ) { LPCTSTR RootSpec; LPCTSTR SubkeySpec; DWORD rc;
if(Subkey[0] == TEXT('\\')) { Subkey++; }
//
// Figure out the root key spec.
//
switch((ULONG_PTR)Key) {
case (ULONG_PTR)HKEY_LOCAL_MACHINE:
//
// Check for HKEY_CLASSES_ROOT
//
if(_tcsnicmp(Subkey,TEXT("SOFTWARE\\Classes"),16)) { RootSpec = TEXT("HKLM"); SubkeySpec = Subkey; } else { RootSpec = TEXT("HKCR"); SubkeySpec = Subkey+16; if(*SubkeySpec == TEXT('\\')) { SubkeySpec++; } } break;
case (ULONG_PTR)HKEY_CURRENT_USER:
RootSpec = TEXT("HKCU"); SubkeySpec = Subkey; break;
case (ULONG_PTR)HKEY_CLASSES_ROOT:
RootSpec = TEXT("HKCR"); SubkeySpec = Subkey; break;
default: //
// Value we can't express via inf.
// Use HKEY_ROOT but also write out a comment incidating
// that there's a problem
//
RootSpec = TEXT("HKR"); SubkeySpec = Subkey;
Context->SawBogusOp = TRUE; rc = FlushGenInfLineBuf(Context,OutputFile); if(rc != NO_ERROR) { return(rc); }
rc = WriteText(OutputFile,MSG_INF_BAD_REGSPEC_1); if(rc != NO_ERROR) { return(rc); } break; }
rc = GenInfWriteString(Context,OutputFile,RootSpec,AddQuotesNone); if(rc == NO_ERROR) { rc = GenInfWriteChar(Context,OutputFile,TEXT(',')); if(rc == NO_ERROR) { rc = GenInfWriteString(Context,OutputFile,SubkeySpec,AddQuotesNormal); if((rc == NO_ERROR) && Value) { rc = GenInfWriteChar(Context,OutputFile,TEXT(',')); if(rc == NO_ERROR) { rc = GenInfWriteString(Context,OutputFile,Value,AddQuotesNormal); } } } }
return(rc); }
DWORD InfRecordAddReg( IN OUT PINFFILEGEN Context, IN HKEY Key, IN LPCTSTR Subkey, IN LPCTSTR Value, OPTIONAL IN DWORD DataType, IN PVOID Data, IN DWORD DataLength, IN BOOL SetNoClobberFlag ) { DWORD rc; DWORD Flags; PTSTR p; DWORD d; int LineLen; TCHAR NumStr[24];
//
// Figure out flags based on data type.
// The flags dword is built as two halves depending on whether
// data is string or binary in nature.
//
// We do this before we write out the actual line
// since that routine might also write a warning if a bogus root key
// is specified.
//
switch(DataType) {
case REG_SZ: Flags = FLG_ADDREG_TYPE_SZ; break;
case REG_EXPAND_SZ: Flags = FLG_ADDREG_TYPE_EXPAND_SZ; break;
case REG_MULTI_SZ: Flags = FLG_ADDREG_TYPE_MULTI_SZ; break;
case REG_DWORD: Flags = FLG_ADDREG_TYPE_DWORD; break;
//case REG_NONE:
// Flags = FLG_ADDREG_TYPE_NONE;
// break;
case REG_NONE: Flags = FLG_ADDREG_KEYONLY; break;
default: //
// Arbitrary binary data. Better hope the data type doesn't overflow
// 16 bits.
//
if(DataType > 0xffff) { Context->SawBogusOp = TRUE; rc = FlushGenInfLineBuf(Context,Context->FileHandle); if(rc != NO_ERROR) { return(rc); } rc = WriteText(Context->FileHandle,MSG_INF_BAD_REGSPEC_2); if(rc != NO_ERROR) { return(rc); } DataType = REG_BINARY; } Flags = FLG_ADDREG_BINVALUETYPE | (DataType << 16); break; }
rc = pInfRegLineCommon(Context,Context->FileHandle,Key,Subkey,Value); if(rc != NO_ERROR) { return(rc); } if(Flags == FLG_ADDREG_KEYONLY) { rc = GenInfWriteChar(Context,Context->FileHandle,TEXT(',')); if(rc != NO_ERROR) { return(rc); } }
//
// _stprintf(NumStr,TEXT(",%0#10lx"),Flags | 0x00000002); // Force NO_CLOBBER
//
// _stprintf(NumStr,TEXT(",%0#10lx"),Flags);
wsprintf(NumStr, TEXT(",%#08lx"), SetNoClobberFlag? (Flags | 0x00000002) : Flags);
rc = GenInfWriteString(Context,Context->FileHandle,NumStr,AddQuotesNone); if(rc != NO_ERROR) { return(rc); }
//
// Now we need to write out the data itself.
// How we do this is dependent on the data type.
//
switch(DataType) {
case REG_SZ: case REG_EXPAND_SZ: //
// Single string. Ignore data length.
//
rc = GenInfWriteChar(Context,Context->FileHandle,TEXT(',')); if(rc == NO_ERROR) { rc = GenInfWriteString(Context,Context->FileHandle,Data,AddQuotesNormal); } break;
case REG_DWORD: //
// Write out as a dword.
//
wsprintf(NumStr,TEXT(",%u"),*(DWORD UNALIGNED *)Data); rc = GenInfWriteString(Context,Context->FileHandle,NumStr,AddQuotesNone); break;
case REG_MULTI_SZ: //
// Write out each string.
//
for(p=Data; (rc==NO_ERROR) && *p; p+=lstrlen(p)+1) { rc = GenInfWriteChar(Context,Context->FileHandle,TEXT(',')); if(rc == NO_ERROR) { rc = GenInfWriteString(Context,Context->FileHandle,p,AddQuotesNormal); } }
break;
case REG_NONE: //
// Don't create a value entry
//
break;
default: //
// Treat as binary. If we have any data at all start a new line.
//
if(DataLength) { rc = GenInfWriteString(Context,Context->FileHandle,TEXT(",\\\r\n "),AddQuotesNone); }
LineLen = 0; for(d=0; (rc==NO_ERROR) && (d<DataLength); d++) {
if(LineLen == 25) { rc = GenInfWriteString(Context,Context->FileHandle,TEXT(",\\\r\n "),AddQuotesNone); LineLen = 0; }
if(rc == NO_ERROR) { if(LineLen) { rc = GenInfWriteChar(Context,Context->FileHandle,TEXT(',')); } if(rc == NO_ERROR) { wsprintf(NumStr,TEXT("%02x"),((PBYTE)Data)[d]); rc = GenInfWriteString(Context,Context->FileHandle,NumStr,AddQuotesNone); LineLen++; } } }
break; }
if(rc == NO_ERROR) { rc = GenInfWriteString(Context,Context->FileHandle,TEXT("\r\n"),AddQuotesNone); if(rc == NO_ERROR) { rc = FlushGenInfLineBuf(Context,Context->FileHandle); } }
return(rc); }
#if 0
DWORD InfRecordDelReg( IN OUT PINFFILEGEN Context, IN HKEY Key, IN LPCTSTR Subkey, IN LPCTSTR Value OPTIONAL ) { DWORD rc;
rc = pInfRegLineCommon(Context,Context->DelRegFile,Key,Subkey,Value); if(rc == NO_ERROR) { rc = GenInfWriteString(Context,Context->DelRegFile,TEXT("\r\n"),AddQuotesNone); if(rc == NO_ERROR) { rc = FlushGenInfLineBuf(Context,Context->DelRegFile); } }
return(rc); } #endif
|