|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
regutil.c
Abstract:
Utility routines for use by REGINI and REGDMP programs. Author:
Steve Wood (stevewo) 10-Mar-92
Revision History:
--*/
#include "regutil.h"
#define RtlAllocateHeap(x,y,z) malloc(z)
#define RtlFreeHeap(x,y,z) free(z)
UNICODE_STRING RiOnKeyword; UNICODE_STRING RiYesKeyword; UNICODE_STRING RiTrueKeyword; UNICODE_STRING RiOffKeyword; UNICODE_STRING RiNoKeyword; UNICODE_STRING RiFalseKeyword; UNICODE_STRING RiDeleteKeyword; UNICODE_STRING RiRegKeyword; UNICODE_STRING RiRegNoneKeyword; UNICODE_STRING RiRegSzKeyword; UNICODE_STRING RiRegExpandSzKeyword; UNICODE_STRING RiRegDwordKeyword; UNICODE_STRING RiRegBinaryKeyword; UNICODE_STRING RiRegBinaryFileKeyword; UNICODE_STRING RiRegLinkKeyword; UNICODE_STRING RiRegMultiSzKeyword; UNICODE_STRING RiRegMultiSzFileKeyword; UNICODE_STRING RiRegDateKeyword;
void RegInitialize( void ) { RtlInitUnicodeString( &RiOnKeyword, L"ON" ); RtlInitUnicodeString( &RiYesKeyword, L"YES" ); RtlInitUnicodeString( &RiTrueKeyword, L"TRUE" ); RtlInitUnicodeString( &RiOffKeyword, L"OFF" ); RtlInitUnicodeString( &RiNoKeyword, L"NO" ); RtlInitUnicodeString( &RiFalseKeyword, L"FALSE" ); RtlInitUnicodeString( &RiDeleteKeyword, L"DELETE" ); RtlInitUnicodeString( &RiRegKeyword, L"REG_" ); RtlInitUnicodeString( &RiRegNoneKeyword, L"REG_NONE" ); RtlInitUnicodeString( &RiRegSzKeyword, L"REG_SZ" ); RtlInitUnicodeString( &RiRegExpandSzKeyword, L"REG_EXPAND_SZ" ); RtlInitUnicodeString( &RiRegDwordKeyword, L"REG_DWORD" ); RtlInitUnicodeString( &RiRegBinaryKeyword, L"REG_BINARY" ); RtlInitUnicodeString( &RiRegBinaryFileKeyword, L"REG_BINARYFILE" ); RtlInitUnicodeString( &RiRegLinkKeyword, L"REG_LINK" ); RtlInitUnicodeString( &RiRegMultiSzKeyword, L"REG_MULTI_SZ" ); RtlInitUnicodeString( &RiRegMultiSzFileKeyword, L"REG_MULTISZFILE" ); RtlInitUnicodeString( &RiRegDateKeyword, L"REG_DATE" ); }
NTSTATUS RegReadMultiSzFile( IN PUNICODE_STRING FileName, OUT PVOID *ValueBuffer, OUT PULONG ValueLength ) { NTSTATUS Status; UNICODE_STRING NtFileName; PWSTR s; UNICODE_STRING MultiSource; UNICODE_STRING MultiValue; REG_UNICODE_FILE MultiSzFile; ULONG MultiSzFileSize;
FileName->Buffer[ FileName->Length/sizeof(WCHAR) ] = UNICODE_NULL;
RtlDosPathNameToNtPathName_U( FileName->Buffer, &NtFileName, NULL, NULL );
Status = RegLoadAsciiFileAsUnicode( &NtFileName, &MultiSzFile );
if (!NT_SUCCESS( Status )) { return( Status ); }
MultiSzFileSize = (MultiSzFile.EndOfFile - MultiSzFile.NextLine) * sizeof(WCHAR);
*ValueLength = 0; *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, MultiSzFileSize);
MultiSource.Buffer = MultiSzFile.NextLine; if (MultiSzFileSize <= MAXUSHORT) { MultiSource.Length = MultiSource.MaximumLength = (USHORT)MultiSzFileSize; } else { MultiSource.Length = MultiSource.MaximumLength = MAXUSHORT; }
while (RegGetMultiString(&MultiSource, &MultiValue)) { RtlMoveMemory( (PUCHAR)*ValueBuffer + *ValueLength, MultiValue.Buffer, MultiValue.Length ); *ValueLength += MultiValue.Length;
s = MultiSource.Buffer; while ( *s != L'"' && *s != L',' && ((s - MultiSource.Buffer) * sizeof(WCHAR)) < MultiSource.Length ) s++; if ( ((s - MultiSource.Buffer) * sizeof(WCHAR)) == MultiSource.Length || *s == L',' || *s == L';' ) {
((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL; *ValueLength += sizeof(UNICODE_NULL); if ( *s == L';' ) { break; } }
if ( (MultiSzFile.EndOfFile - MultiSource.Buffer) * sizeof(WCHAR) >= MAXUSHORT ) { MultiSource.Length = MultiSource.MaximumLength = MAXUSHORT; } else { MultiSource.Length = MultiSource.MaximumLength = (USHORT)((MultiSzFile.EndOfFile - MultiSource.Buffer) * sizeof(WCHAR)); } }
((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL; *ValueLength += sizeof(UNICODE_NULL);
// Virtual memory for reading of MultiSzFile freed at process
// death?
return( TRUE ); }
NTSTATUS RegReadBinaryFile( IN PUNICODE_STRING FileName, OUT PVOID *ValueBuffer, OUT PULONG ValueLength ) { NTSTATUS Status; UNICODE_STRING NtFileName; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus; HANDLE File; FILE_STANDARD_INFORMATION FileInformation; WCHAR FileNameBuffer[ 256 ]; PWSTR s;
FileName->Buffer[ FileName->Length/sizeof(WCHAR) ] = UNICODE_NULL; wcscpy( FileNameBuffer, L"\\DosDevices\\" ); s = wcscat( FileNameBuffer, FileName->Buffer ); while (*s != UNICODE_NULL) { if (*s == L'/') { *s = L'\\'; } s++; } RtlInitUnicodeString( &NtFileName, FileNameBuffer );
InitializeObjectAttributes( &ObjectAttributes, &NtFileName, OBJ_CASE_INSENSITIVE, (HANDLE)NULL, NULL );
Status = NtOpenFile( &File, SYNCHRONIZE | GENERIC_READ, &ObjectAttributes, &IoStatus, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE ); if (!NT_SUCCESS( Status )) { return( Status ); }
Status = NtQueryInformationFile( File, &IoStatus, (PVOID)&FileInformation, sizeof( FileInformation ), FileStandardInformation ); if (NT_SUCCESS( Status )) { if (FileInformation.EndOfFile.HighPart) { Status = STATUS_BUFFER_OVERFLOW; } } if (!NT_SUCCESS( Status )) { NtClose( File ); return( Status ); }
*ValueLength = FileInformation.EndOfFile.LowPart; *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, *ValueLength ); if (*ValueBuffer == NULL) { Status = STATUS_NO_MEMORY; }
if (NT_SUCCESS( Status )) { Status = NtReadFile( File, NULL, NULL, NULL, &IoStatus, *ValueBuffer, *ValueLength, NULL, NULL );
if (NT_SUCCESS( Status )) { Status = IoStatus.Status;
if (NT_SUCCESS( Status )) { if (IoStatus.Information != *ValueLength) { Status = STATUS_END_OF_FILE; } } }
if (!NT_SUCCESS( Status )) { RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer ); } }
NtClose( File ); return( Status ); }
NTSTATUS RegLoadAsciiFileAsUnicode( IN PUNICODE_STRING FileName, OUT PREG_UNICODE_FILE UnicodeFile ) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus; HANDLE File; FILE_BASIC_INFORMATION FileDateTimeInfo; FILE_STANDARD_INFORMATION FileInformation; ULONG BufferSize, i, i1, LineCount; PVOID BufferBase; PCHAR Src, Src1; PWSTR Dst;
InitializeObjectAttributes( &ObjectAttributes, FileName, OBJ_CASE_INSENSITIVE, (HANDLE)NULL, NULL );
Status = NtOpenFile( &File, SYNCHRONIZE | GENERIC_READ, &ObjectAttributes, &IoStatus, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE ); if (!NT_SUCCESS( Status )) { return( Status ); }
Status = NtQueryInformationFile( File, &IoStatus, (PVOID)&FileInformation, sizeof( FileInformation ), FileStandardInformation ); if (NT_SUCCESS( Status )) { if (FileInformation.EndOfFile.HighPart) { Status = STATUS_BUFFER_OVERFLOW; } } if (!NT_SUCCESS( Status )) { NtClose( File ); return( Status ); }
BufferSize = FileInformation.EndOfFile.LowPart * sizeof( WCHAR ); BufferSize += sizeof( UNICODE_NULL ); BufferBase = NULL; Status = NtAllocateVirtualMemory( NtCurrentProcess(), (PVOID *)&BufferBase, 0, &BufferSize, MEM_COMMIT, PAGE_READWRITE ); if (NT_SUCCESS( Status )) { Src = (PCHAR)BufferBase + ((FileInformation.EndOfFile.LowPart+1) & ~1); Dst = (PWSTR)BufferBase; Status = NtReadFile( File, NULL, NULL, NULL, &IoStatus, Src, FileInformation.EndOfFile.LowPart, NULL, NULL );
if (NT_SUCCESS( Status )) { Status = IoStatus.Status;
if (NT_SUCCESS( Status )) { if (IoStatus.Information != FileInformation.EndOfFile.LowPart) { Status = STATUS_END_OF_FILE; } else { Status = NtQueryInformationFile( File, &IoStatus, (PVOID)&FileDateTimeInfo, sizeof( FileDateTimeInfo ), FileBasicInformation ); } } }
if (!NT_SUCCESS( Status )) { NtFreeVirtualMemory( NtCurrentProcess(), (PVOID *)&BufferBase, &BufferSize, MEM_RELEASE ); } }
NtClose( File ); if (!NT_SUCCESS( Status )) { return( Status ); }
i = 0; while (i < FileInformation.EndOfFile.LowPart) { if (i > 1 && (Src[-2] == ' ' || Src[-2] == '\t') && Src[-1] == '\\' && (*Src == '\r' || *Src == '\n') ) { if (Dst[-1] == L'\\') { --Dst; } while (Dst > (PWSTR)BufferBase) { if (Dst[-1] > L' ') { break; } Dst--; } LineCount = 0; while (i < FileInformation.EndOfFile.LowPart) { if (*Src == '\n') { i++; Src++; LineCount++; } else if (*Src == '\r' && (i+1) < FileInformation.EndOfFile.LowPart && Src[ 1 ] == '\n' ) { i += 2; Src += 2; LineCount++; } else { break; } }
if (LineCount > 1) { *Dst++ = L'\n'; } else { *Dst++ = L' '; while (i < FileInformation.EndOfFile.LowPart && (*Src == ' ' || *Src == '\t')) { i++; Src++; } }
if (i >= FileInformation.EndOfFile.LowPart) { break; } } else if ((*Src == '\r' && Src[1] == '\n') || *Src == '\n') { while (TRUE) { while (i < FileInformation.EndOfFile.LowPart && (*Src == '\r' || *Src == '\n')) { i++; Src++; } Src1 = Src; i1 = i; while (i1 < FileInformation.EndOfFile.LowPart && (*Src1 == ' ' || *Src1 == '\t')) { i1++; Src1++; } if (i1 < FileInformation.EndOfFile.LowPart && (*Src1 == '\r' && Src1[1] == '\n') || *Src1 == '\n' ) { Src = Src1; i = i1; } else { break; } }
*Dst++ = L'\n'; } else { i++; *Dst++ = RtlAnsiCharToUnicodeChar( &Src ); } }
if (NT_SUCCESS( Status )) { *Dst = UNICODE_NULL; UnicodeFile->FileContents = BufferBase; UnicodeFile->EndOfFile = Dst; UnicodeFile->BeginLine = NULL; UnicodeFile->EndOfLine = NULL; UnicodeFile->NextLine = BufferBase; UnicodeFile->LastWriteTime = FileDateTimeInfo.LastWriteTime; } else { NtFreeVirtualMemory( NtCurrentProcess(), (PVOID *)&BufferBase, &BufferSize, MEM_RELEASE ); }
return( Status ); }
BOOLEAN RegGetNextLine( IN OUT PREG_UNICODE_FILE UnicodeFile, OUT PULONG IndentAmount, OUT PWSTR *FirstEqual ) { PWSTR s, s1;
while (TRUE) { if (!(s = UnicodeFile->NextLine)) { return( FALSE ); }
*IndentAmount = 0; while (*s <= L' ') { if (*s == L' ') { *IndentAmount += 1; } else if (*s == L'\t') { *IndentAmount = ((*IndentAmount + 8) - (*IndentAmount % 8) ); }
if (++s >= UnicodeFile->EndOfFile) { return( FALSE ); } }
UnicodeFile->BeginLine = s;
*FirstEqual = NULL; UnicodeFile->NextLine = NULL; while (s < UnicodeFile->EndOfFile) { if (*s == L'=') { if (*FirstEqual == NULL) { *FirstEqual = s; } } else if (*s == L'\n') { s1 = s; while (s > UnicodeFile->BeginLine && s[ -1 ] <= L' ') { s--; } UnicodeFile->EndOfLine = s; do { if (++s1 >= UnicodeFile->EndOfFile) { s1 = NULL; break; } } while (*s1 == L'\r' || *s1 == L'\n');
UnicodeFile->NextLine = s1; break; }
if (++s == UnicodeFile->EndOfFile) { break; } }
if (UnicodeFile->EndOfLine > UnicodeFile->BeginLine) { if (DebugOutput) { fprintf( stderr, "%02u %.*ws\n", *IndentAmount, UnicodeFile->EndOfLine - UnicodeFile->BeginLine, UnicodeFile->BeginLine ); }
return( TRUE ); } }
return( FALSE ); }
void RegDumpKeyValue( FILE *fh, PKEY_VALUE_FULL_INFORMATION KeyValueInformation, ULONG IndentLevel ) { PULONG p; PWSTR pw, pw1; ULONG i, j, k, m, cbPrefix; UNICODE_STRING ValueName; PUCHAR pbyte;
cbPrefix = fprintf( fh, "%.*s", IndentLevel, " " ); ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]); ValueName.Length = (USHORT)KeyValueInformation->NameLength; ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
if (ValueName.Length) { cbPrefix += fprintf( fh, "%wZ ", &ValueName ); } cbPrefix += fprintf( fh, "= " );
if (KeyValueInformation->DataLength == 0) { fprintf( fh, " [no data] \n"); return; }
switch( KeyValueInformation->Type ) { case REG_SZ: case REG_EXPAND_SZ:
if (KeyValueInformation->Type == REG_EXPAND_SZ) { cbPrefix += fprintf( fh, "REG_EXPAND_SZ " ); } pw = (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset); *(PWSTR)((PCHAR)pw + KeyValueInformation->DataLength) = UNICODE_NULL; i = 0; while (*pw) { if ((cbPrefix + wcslen(pw)) > 80) { pw1 = pw; while (*pw1 && *pw1 > L' ') { pw1++; }
if (*pw1) { *pw1++ = UNICODE_NULL; while (*pw1 && *pw1 <= L' ') { pw1++; } } } else { pw1 = NULL; } if (i > 0) { fprintf( fh, " \\\n%.*s", cbPrefix, " " ); }
fprintf( fh, "%ws", pw ); if (!pw1) { break; } i++; pw = pw1; } break;
case REG_BINARY: fprintf( fh, "REG_BINARY 0x%08lx", KeyValueInformation->DataLength ); p = (PULONG)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset); i = (KeyValueInformation->DataLength + 3) / sizeof( ULONG ); if (!SummaryOutput || i <= 8) { for (j=0; j<i; j++) { if ((j % 8) == 0) { fprintf( fh, "\n%.*s", IndentLevel+4, " " ); }
fprintf( fh, "0x%08lx ", *p++ ); } } else { fprintf( fh, " *** value display suppressed ***" ); } fprintf( fh, "\n" ); break;
// case REG_DWORD_LITTLE_ENDIAN:
case REG_DWORD: fprintf( fh, "REG_DWORD 0x%08lx", *((PULONG)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset)) ); break;
case REG_DWORD_BIG_ENDIAN: fprintf( fh, "REG_DWORD_BIG_ENDIAN 0x%08lx", *((PULONG)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset)) ); break;
case REG_LINK: fprintf( fh, "REG_LINK %ws", ((PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset)) ); break;
case REG_MULTI_SZ: cbPrefix += fprintf( fh, "REG_MULTI_SZ " ); pw = (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset); i = 0; if (*pw) while (i < ((KeyValueInformation->DataLength-1) / sizeof(WCHAR))) { if (i > 0) { fprintf( fh, " \\\n%.*s", cbPrefix, " " ); } fprintf(fh, "\"%ws\" ",pw+i); do { ++i; } while ( pw[i] != UNICODE_NULL ); ++i; } break;
case REG_RESOURCE_LIST: case REG_FULL_RESOURCE_DESCRIPTOR: { PCM_RESOURCE_LIST ResourceList = ((PCM_RESOURCE_LIST)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset)); PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor; ULONG k, l, count; PWSTR TypeName; PWSTR FlagName; ULONG Size = KeyValueInformation->DataLength;
if (KeyValueInformation->Type == REG_RESOURCE_LIST) {
fprintf( fh, " REG_RESOURCE_LIST\n");
fprintf( fh, "%.*sNumber of Full resource Descriptors = %d", IndentLevel, " ", ResourceList->Count );
count = ResourceList->Count; FullDescriptor = &ResourceList->List[0];
} else {
fprintf( fh, " REG_FULL_RESOURCE_DESCRIPTOR\n"); count = 1; FullDescriptor = ((PCM_FULL_RESOURCE_DESCRIPTOR) ((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset));
}
for (i=0; i< count; i++) {
fprintf( fh, "\n%.*sPartial List number %d\n", IndentLevel+4, " ", i );
switch(FullDescriptor->InterfaceType) {
case Internal: TypeName = L"Internal"; break; case Isa: TypeName = L"Isa"; break; case Eisa: TypeName = L"Eisa"; break; case MicroChannel: TypeName = L"MicroChannel"; break; case TurboChannel: TypeName = L"TurboChannel"; break; case PCIBus: TypeName = L"PCI"; break; case VMEBus: TypeName = L"VME"; break; case NuBus: TypeName = L"NuBus"; break; case PCMCIABus: TypeName = L"PCMCIA"; break; case CBus: TypeName = L"CBUS"; break; case MPIBus: TypeName = L"MPI"; break;
default: TypeName = L"***invalid bus type***"; break; }
fprintf( fh, "%.*sINTERFACE_TYPE %ws\n", IndentLevel+8, " ", TypeName );
fprintf( fh, "%.*sBUS_NUMBER %d\n", IndentLevel+8, " ", FullDescriptor->BusNumber );
//
// This is a basic test to see if the data format is right.
// We know at least some video resource list are bogus ...
//
if (Size < FullDescriptor->PartialResourceList.Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) ) {
fprintf( fh, "\n%.*s *** !!! Invalid ResourceList !!! *** \n", IndentLevel+8, " ", i );
break; }
Size -= FullDescriptor->PartialResourceList.Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
for (j=0; j<FullDescriptor->PartialResourceList.Count; j++) {
fprintf( fh, "%.*sDescriptor number %d\n", IndentLevel+12, " ", j );
PartialResourceDescriptor = &(FullDescriptor->PartialResourceList.PartialDescriptors[j]);
switch(PartialResourceDescriptor->ShareDisposition) {
case CmResourceShareUndetermined: TypeName = L"CmResourceShareUndetermined"; break; case CmResourceShareDeviceExclusive: TypeName = L"CmResourceDeviceExclusive"; break; case CmResourceShareDriverExclusive: TypeName = L"CmResourceDriverExclusive"; break; case CmResourceShareShared: TypeName = L"CmResourceShared"; break; default: TypeName = L"***invalid share disposition***"; break; }
fprintf( fh, "%.*sShare Disposition %ws\n", IndentLevel+12, " ", TypeName );
FlagName = L"***invalid Flags";
switch(PartialResourceDescriptor->Type) {
case CmResourceTypeNull: TypeName = L"NULL"; FlagName = L"***Unused"; break; case CmResourceTypePort: TypeName = L"PORT"; if (PartialResourceDescriptor->Flags == CM_RESOURCE_PORT_MEMORY) { FlagName = L"CM_RESOURCE_PORT_MEMORY"; } if (PartialResourceDescriptor->Flags == CM_RESOURCE_PORT_IO) { FlagName = L"CM_RESOURCE_PORT_IO"; } break; case CmResourceTypeInterrupt: TypeName = L"INTERRUPT"; if (PartialResourceDescriptor->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) { FlagName = L"CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE"; } if (PartialResourceDescriptor->Flags == CM_RESOURCE_INTERRUPT_LATCHED) { FlagName = L"CM_RESOURCE_INTERRUPT_LATCHED"; } break; case CmResourceTypeMemory: TypeName = L"MEMORY"; if (PartialResourceDescriptor->Flags == CM_RESOURCE_MEMORY_READ_WRITE) { FlagName = L"CM_RESOURCE_MEMORY_READ_WRITE"; } if (PartialResourceDescriptor->Flags == CM_RESOURCE_MEMORY_READ_ONLY) { FlagName = L"CM_RESOURCE_MEMORY_READ_ONLY"; } if (PartialResourceDescriptor->Flags == CM_RESOURCE_MEMORY_WRITE_ONLY) { FlagName = L"CM_RESOURCE_MEMORY_WRITE_ONLY"; } break; case CmResourceTypeDma: TypeName = L"DMA"; FlagName = L"***Unused"; break; case CmResourceTypeDeviceSpecific: TypeName = L"DEVICE SPECIFIC"; FlagName = L"***Unused"; break; default: TypeName = L"***invalid type***"; break; }
fprintf( fh, "%.*sTYPE %ws\n", IndentLevel+12, " ", TypeName );
fprintf( fh, "%.*sFlags %ws\n", IndentLevel+12, " ", FlagName );
switch(PartialResourceDescriptor->Type) {
case CmResourceTypePort: fprintf( fh, "%.*sSTART 0x%08lx LENGTH 0x%08lx\n", IndentLevel+12, " ", PartialResourceDescriptor->u.Port.Start.LowPart, PartialResourceDescriptor->u.Port.Length ); break;
case CmResourceTypeInterrupt: fprintf( fh, "%.*sLEVEL %d VECTOR %d AFFINITY %d\n", IndentLevel+12, " ", PartialResourceDescriptor->u.Interrupt.Level, PartialResourceDescriptor->u.Interrupt.Vector, PartialResourceDescriptor->u.Interrupt.Affinity ); break;
case CmResourceTypeMemory: fprintf( fh, "%.*sSTART 0x%08lx%08lx LENGTH 0x%08lx\n", IndentLevel+12, " ", PartialResourceDescriptor->u.Memory.Start.HighPart, PartialResourceDescriptor->u.Memory.Start.LowPart, PartialResourceDescriptor->u.Memory.Length ); break;
case CmResourceTypeDma: fprintf( fh, "%.*sCHANNEL %d PORT %d\n", IndentLevel+12, " ", PartialResourceDescriptor->u.Dma.Channel, PartialResourceDescriptor->u.Dma.Port ); break;
case CmResourceTypeDeviceSpecific: fprintf( fh, "%.*sDataSize 0x%08lx\n", IndentLevel+12, " ", PartialResourceDescriptor->u.DeviceSpecificData.DataSize );
p = (PULONG)(PartialResourceDescriptor + 1); k = (PartialResourceDescriptor->u.DeviceSpecificData.DataSize + 3) / sizeof( ULONG ); for (l=0; l<k; l++) { if ((l % 8) == 0) { fprintf( fh, "\n%.*s", IndentLevel+12, " " ); }
fprintf( fh, "0x%08lx ", *p++ ); } fprintf( fh, "\n" ); break;
default: fprintf( fh, "%.*s*** Unknown resource list type: %c ****\n", IndentLevel+12, " ", PartialResourceDescriptor->Type ); break; }
fprintf( fh, "\n" ); }
FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) (PartialResourceDescriptor+1); }
break; }
case REG_NONE: default: if (KeyValueInformation->Type == REG_NONE) { fprintf( fh, "REG_NONE\n"); } else { fprintf( fh, "*** Unknown registry type (%08lx)", KeyValueInformation->Type ); } fprintf( fh, "%.*s", IndentLevel, " " ); fprintf( fh, " Length: 0x%lx\n", KeyValueInformation->DataLength ); fprintf( fh, "\n%.*s", IndentLevel, " " ); fprintf( fh, " Data: "); pbyte = ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset); for ( k=0, m=1; k<KeyValueInformation->DataLength; k++,m++) { fprintf( fh, "%02x ", (*pbyte) ); pbyte++;
if (m==8) { fprintf( fh, "\n%.*s", IndentLevel+12, " " ); m=0; } } break; }
fprintf( fh, "\n" ); return; }
//
// Define an upcase macro for temporary use by the upcase routines
//
#define upcase(C) (WCHAR )(((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C)))
BOOLEAN RegGetMultiString( IN OUT PUNICODE_STRING ValueString, OUT PUNICODE_STRING MultiString )
/*++
Routine Description:
This routine parses multi-strings of the form
"foo" "bar" "bletch"
Each time it is called, it strips the first string in quotes from the input string, and returns it as the multi-string.
INPUT ValueString: "foo" "bar" "bletch"
OUTPUT ValueString: "bar" "bletch" MultiString: foo
Arguments:
ValueString - Supplies the string from which the multi-string will be parsed - Returns the remaining string after the multi-string is removed
MultiString - Returns the multi-string removed from ValueString
Return Value:
TRUE - multi-string found and removed.
FALSE - no more multi-strings remaining.
--*/
{ //
// Find the first quote mark.
//
while ((*(ValueString->Buffer) != L'"') && (ValueString->Length > 0)) { ++ValueString->Buffer; ValueString->Length -= sizeof(WCHAR); ValueString->MaximumLength -= sizeof(WCHAR); }
if (ValueString->Length == 0) { return(FALSE); }
//
// We have found the start of the multi-string. Now find the end,
// building up our return MultiString as we go.
//
++ValueString->Buffer; ValueString->Length -= sizeof(WCHAR); ValueString->MaximumLength -= sizeof(WCHAR); MultiString->Buffer = ValueString->Buffer; MultiString->Length = 0; MultiString->MaximumLength = 0; while ((*(ValueString->Buffer) != L'"') && (ValueString->Length > 0)) { ++ValueString->Buffer; ValueString->Length -= sizeof(WCHAR); ValueString->MaximumLength -= sizeof(WCHAR);
MultiString->Length += sizeof(WCHAR); MultiString->MaximumLength += sizeof(WCHAR); }
if (ValueString->Length == 0) { return(FALSE); }
++ValueString->Buffer; ValueString->Length -= sizeof(WCHAR); ValueString->MaximumLength -= sizeof(WCHAR);
return( TRUE );
}
BOOLEAN RegGetKeyValue( IN PUNICODE_STRING InitialKeyValue, IN OUT PREG_UNICODE_FILE UnicodeFile, OUT PULONG ValueType, OUT PVOID *ValueBuffer, OUT PULONG ValueLength ) { ULONG PrefixLength; PWSTR s; PULONG p; ULONG n; NTSTATUS Status; ULONG IndentAmount; PWSTR FirstEqual; UNICODE_STRING KeyValue; UNICODE_STRING MultiValue; BOOLEAN GetDataFromBinaryFile = FALSE; BOOLEAN GetDataFromMultiSzFile = FALSE; BOOLEAN ParseDateTime = FALSE;
KeyValue = *InitialKeyValue; if (RtlPrefixUnicodeString( &RiDeleteKeyword, &KeyValue, TRUE )) { *ValueBuffer = NULL; return( TRUE ); } else if (!RtlPrefixUnicodeString( &RiRegKeyword, &KeyValue, TRUE )) { *ValueType = REG_SZ; PrefixLength = 0; } else if (RtlPrefixUnicodeString( &RiRegNoneKeyword, &KeyValue, TRUE )) { *ValueType = REG_NONE; PrefixLength = RiRegNoneKeyword.Length; } else if (RtlPrefixUnicodeString( &RiRegSzKeyword, &KeyValue, TRUE )) { *ValueType = REG_SZ; PrefixLength = RiRegSzKeyword.Length; } else if (RtlPrefixUnicodeString( &RiRegExpandSzKeyword, &KeyValue, TRUE )) { *ValueType = REG_EXPAND_SZ; PrefixLength = RiRegExpandSzKeyword.Length; } else if (RtlPrefixUnicodeString( &RiRegDwordKeyword, &KeyValue, TRUE )) { *ValueType = REG_DWORD; PrefixLength = RiRegDwordKeyword.Length; } else if (RtlPrefixUnicodeString( &RiRegBinaryFileKeyword, &KeyValue, TRUE )) { *ValueType = REG_BINARY; PrefixLength = RiRegBinaryFileKeyword.Length; GetDataFromBinaryFile = TRUE; } else if (RtlPrefixUnicodeString( &RiRegBinaryKeyword, &KeyValue, TRUE )) { *ValueType = REG_BINARY; PrefixLength = RiRegBinaryKeyword.Length; } else if (RtlPrefixUnicodeString( &RiRegLinkKeyword, &KeyValue, TRUE )) { *ValueType = REG_LINK; PrefixLength = RiRegLinkKeyword.Length; } else if (RtlPrefixUnicodeString( &RiRegMultiSzFileKeyword, &KeyValue, TRUE)) { *ValueType = REG_MULTI_SZ; PrefixLength = RiRegMultiSzFileKeyword.Length; GetDataFromMultiSzFile = TRUE; } else if (RtlPrefixUnicodeString( &RiRegMultiSzKeyword, &KeyValue, TRUE)) { *ValueType = REG_MULTI_SZ; PrefixLength = RiRegMultiSzKeyword.Length; } else if (RtlPrefixUnicodeString( &RiRegDateKeyword, &KeyValue, TRUE )) { *ValueType = REG_BINARY; ParseDateTime = TRUE; PrefixLength = RiRegDateKeyword.Length; } else { return( FALSE ); }
if (*ValueType != REG_NONE) { s = (PWSTR) ((PCHAR)KeyValue.Buffer + PrefixLength); KeyValue.Length -= (USHORT)PrefixLength; while (KeyValue.Length != 0 && *s <= L' ') { s++; KeyValue.Length -= sizeof( WCHAR ); } KeyValue.Buffer = s; } else { *ValueType = REG_SZ; }
if (GetDataFromBinaryFile) { Status = RegReadBinaryFile( &KeyValue, ValueBuffer, ValueLength ); if (NT_SUCCESS( Status )) { return( TRUE ); } else { fprintf( stderr, "REGINI: Unable to read data from %wZ - Status == %lx\n", &KeyValue, Status ); return( FALSE ); } }
if (GetDataFromMultiSzFile) { Status = RegReadMultiSzFile( &KeyValue, ValueBuffer, ValueLength ); if (NT_SUCCESS( Status )) { return( TRUE ); } else { fprintf( stderr, "REGINI: Unable to read data from %wZ - Status == %lx\n", &KeyValue, Status ); return( FALSE ); } }
switch( *ValueType ) { case REG_SZ: case REG_EXPAND_SZ: case REG_LINK: *ValueLength = KeyValue.Length + sizeof( UNICODE_NULL ); *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, *ValueLength ); if (*ValueBuffer == NULL) { return( FALSE ); }
RtlMoveMemory( *ValueBuffer, KeyValue.Buffer, KeyValue.Length ); ((PWSTR)*ValueBuffer)[ KeyValue.Length / sizeof( WCHAR ) ] = UNICODE_NULL; return( TRUE );
case REG_DWORD: *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof( ULONG ) ); if (*ValueBuffer == NULL) { return( FALSE ); }
if (RtlPrefixUnicodeString( &RiTrueKeyword, &KeyValue, TRUE ) || RtlPrefixUnicodeString( &RiYesKeyword, &KeyValue, TRUE ) || RtlPrefixUnicodeString( &RiOnKeyword, &KeyValue, TRUE ) ) { *(PULONG)*ValueBuffer = (ULONG)TRUE; } else if (RtlPrefixUnicodeString( &RiFalseKeyword, &KeyValue, TRUE ) || RtlPrefixUnicodeString( &RiNoKeyword, &KeyValue, TRUE ) || RtlPrefixUnicodeString( &RiOffKeyword, &KeyValue, TRUE ) ) { *(PULONG)*ValueBuffer = (ULONG)FALSE; } else { Status = RtlUnicodeStringToInteger( &KeyValue, 0, (PULONG)*ValueBuffer ); if (!NT_SUCCESS( Status )) { fprintf( stderr, "REGINI: CharToInteger( %wZ ) failed - Status == %lx\n", &KeyValue, Status ); RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer ); return( FALSE ); } }
*ValueLength = sizeof( ULONG ); return( TRUE );
case REG_BINARY: if (ParseDateTime) { #define NUMBER_DATE_TIME_FIELDS 6
ULONG FieldIndexes[ NUMBER_DATE_TIME_FIELDS ] = {1, 2, 0, 3, 4, 7}; //
// Month/Day/Year HH:MM DayOfWeek
//
ULONG CurrentField = 0; PCSHORT Fields; TIME_FIELDS DateTimeFields; UNICODE_STRING Field; ULONG FieldValue;
RtlZeroMemory( &DateTimeFields, sizeof( DateTimeFields ) ); Fields = &DateTimeFields.Year; while (KeyValue.Length) { if (CurrentField >= 7) { return( FALSE ); }
s = KeyValue.Buffer; while (KeyValue.Length && *s == L' ') { KeyValue.Length--; s++; }
Field.Buffer = s; while (KeyValue.Length) { if (CurrentField == (NUMBER_DATE_TIME_FIELDS-1)) { } else if (*s < L'0' || *s > L'9') { break; }
KeyValue.Length--; s++; }
Field.Length = (USHORT)((PCHAR)s - (PCHAR)Field.Buffer); Field.MaximumLength = Field.Length;
if (KeyValue.Length) { KeyValue.Length--; s++; } KeyValue.Buffer = s;
if (CurrentField == (NUMBER_DATE_TIME_FIELDS-1)) { if (Field.Length < 3) { printf( "REGINI: %wZ invalid day of week length\n", &Field ); return FALSE; }
if (DateTimeFields.Year != 0) { printf( "REGINI: Year must be zero to specify day of week\n" ); return FALSE; }
if (!_wcsnicmp( Field.Buffer, L"SUN", 3 )) { FieldValue = 0; } else if (!_wcsnicmp( Field.Buffer, L"MON", 3 )) { FieldValue = 1; } else if (!_wcsnicmp( Field.Buffer, L"TUE", 3 )) { FieldValue = 2; } else if (!_wcsnicmp( Field.Buffer, L"WED", 3 )) { FieldValue = 3; } else if (!_wcsnicmp( Field.Buffer, L"THU", 3 )) { FieldValue = 4; } else if (!_wcsnicmp( Field.Buffer, L"FRI", 3 )) { FieldValue = 5; } else if (!_wcsnicmp( Field.Buffer, L"SAT", 3 )) { FieldValue = 6; } else { printf( "REGINI: %wZ invalid day of week\n", &Field ); return FALSE; } } else { Status = RtlUnicodeStringToInteger( &Field, 10, &FieldValue ); if (!NT_SUCCESS( Status )) { return( FALSE ); } }
Fields[ FieldIndexes[ CurrentField++ ] ] = (CSHORT)FieldValue; }
if (DateTimeFields.Year == 0) { if (DateTimeFields.Day > 5) { printf( "REGINI: Day must be 0 - 5 if year is zero.\n" ); return FALSE; } } else if (DateTimeFields.Year < 100) { DateTimeFields.Year += 1900; }
*ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof( DateTimeFields ) ); *ValueLength = sizeof( DateTimeFields ); RtlMoveMemory( *ValueBuffer, &DateTimeFields, sizeof( DateTimeFields ) ); return TRUE; } else { Status = RtlUnicodeStringToInteger( &KeyValue, 0, ValueLength ); if (!NT_SUCCESS( Status )) { return( FALSE ); } s = KeyValue.Buffer; while (KeyValue.Length != 0 && *s > L' ') { s++; KeyValue.Length -= sizeof( WCHAR ); } KeyValue.Buffer = s; } break;
case REG_MULTI_SZ: *ValueLength = 0; *ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, KeyValue.Length + sizeof( UNICODE_NULL ) ); while (RegGetMultiString(&KeyValue, &MultiValue)) { RtlMoveMemory( (PUCHAR)*ValueBuffer + *ValueLength, MultiValue.Buffer, MultiValue.Length ); *ValueLength += MultiValue.Length; ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL; *ValueLength += sizeof(UNICODE_NULL); } ((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL; *ValueLength += sizeof(UNICODE_NULL);
return( TRUE );
default: return( FALSE ); }
*ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, *ValueLength ); p = *ValueBuffer; n = (*ValueLength + sizeof( ULONG ) - 1) / sizeof( ULONG ); while (n--) { if (KeyValue.Length == 0) { if (!RegGetNextLine( UnicodeFile, &IndentAmount, &FirstEqual )) { RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer ); return( FALSE ); } KeyValue.Buffer = UnicodeFile->BeginLine; KeyValue.Length = (USHORT) ((PCHAR)UnicodeFile->EndOfLine - (PCHAR)UnicodeFile->BeginLine); KeyValue.MaximumLength = KeyValue.Length; }
s = KeyValue.Buffer; while (KeyValue.Length != 0 && *s <= L' ') { s++; KeyValue.Length -= sizeof( WCHAR ); } KeyValue.Buffer = s; if (KeyValue.Length != 0) { Status = RtlUnicodeStringToInteger( &KeyValue, 0, p ); if (!NT_SUCCESS( Status )) { RtlFreeHeap( RtlProcessHeap(), 0, *ValueBuffer ); return( FALSE ); } p++;
s = KeyValue.Buffer; while (KeyValue.Length != 0 && *s > L' ') { s++; KeyValue.Length -= sizeof( WCHAR ); } KeyValue.Buffer = s; } }
return( TRUE ); }
BOOLEAN RtlPrefixUnicodeString( IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive )
/*++
Routine Description:
The RtlPrefixUnicodeString function determines if the String1 counted string parameter is a prefix of the String2 counted string parameter.
The CaseInSensitive parameter specifies if case is to be ignored when doing the comparison.
Arguments:
String1 - Pointer to the first unicode string.
String2 - Pointer to the second unicode string.
CaseInsensitive - TRUE if case should be ignored when doing the comparison.
Return Value:
Boolean value that is TRUE if String1 equals a prefix of String2 and FALSE otherwise.
--*/
{ PWSTR s1, s2; ULONG n; WCHAR c1, c2;
s1 = String1->Buffer; s2 = String2->Buffer; if (String2->Length < String1->Length) { return( FALSE ); }
n = String1->Length / sizeof( c1 ); while (n) { c1 = *s1++; c2 = *s2++;
if (CaseInSensitive) { c1 = upcase(c1); c2 = upcase(c2); } if (c1 != c2) { return( FALSE ); }
n--; }
return( TRUE ); }
|