-/* $Id: create.c,v 1.25 2001/05/04 01:21:45 rex Exp $
+/* $Id: create.c,v 1.26 2001/06/14 21:05:08 jfilby Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
CHECKPOINT;
ParentFcb = Temp;
}
-
+
+ if( *current != L'\0' ){ //the file name is directory. there will be no last part.
/* searching for last path component */
DPRINT ("search for (%S) in (%S)\n", current, Fcb ? Fcb->PathName : L"");
Status = FindFile (DeviceExt, Fcb, ParentFcb, current, NULL, NULL);
Fcb = ParentFcb;
ParentFcb = Temp;
ParentFcb->ObjectName = &(wcschr (ParentFcb->ObjectName, '\\'))[1];
+ }
}
FileObject->Flags = FileObject->Flags |
-# $Id: Makefile,v 1.43 2001/06/12 17:50:27 chorns Exp $
+# $Id: Makefile,v 1.44 2001/06/14 21:05:07 jfilby Exp $
#
# ReactOS Operating System
#
# Configuration Manager (Registry)
OBJECTS_CM = \
- cm/registry.o
+ cm/registry.o \
+ cm/ntfunc.o \
+ cm/rtlfunc.o \
+ cm/regfile.o \
+ cm/regobj.o
# Debugger Support (Dbg)
OBJECTS_DBG = \
--- /dev/null
+
+#ifndef __INCLUDE_CM_H
+#define __INCLUDE_CM_H
+
+#include <windows.h>
+#include <ddk/ntddk.h>
+#include <internal/config.h>
+#include <internal/ob.h>
+#include <limits.h>
+#include <string.h>
+#include <internal/pool.h>
+#include <internal/registry.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#define KO_MARKED_FOR_DELETE 0x00000001
+
+// BLOCK_OFFSET = offset in file after header block
+typedef DWORD BLOCK_OFFSET;
+
+/* header for registry hive file : */
+typedef struct _HEADER_BLOCK
+{
+ ULONG BlockId; /* ="regf" */
+ ULONG Version; /* file version ?*/
+ ULONG VersionOld; /* file version ?*/
+ FILETIME DateModified; /* please don't replace with LARGE_INTEGER !*/
+ ULONG Unused3; /* registry format version ? */
+ ULONG Unused4; /* registry format version ? */
+ ULONG Unused5; /* registry format version ? */
+ ULONG Unused6; /* registry format version ? */
+ BLOCK_OFFSET RootKeyBlock;
+ ULONG BlockSize;
+ ULONG Unused7;
+ WCHAR FileName[64]; /* end of file name */
+ ULONG Unused8[83];
+ ULONG Checksum;
+} HEADER_BLOCK, *PHEADER_BLOCK;
+
+typedef struct _HEAP_BLOCK
+{
+ ULONG BlockId; /* = "hbin" */
+ BLOCK_OFFSET BlockOffset; /* block offset of this heap */
+ ULONG BlockSize; /* size in bytes, 4k multiple */
+ ULONG Unused1;
+ FILETIME DateModified; /* please don't replace with LARGE_INTEGER !*/
+ ULONG Unused2;
+} HEAP_BLOCK, *PHEAP_BLOCK;
+
+// each sub_block begin with this struct :
+// in a free subblock, higher bit of SubBlockSize is set
+typedef struct _FREE_SUB_BLOCK
+{
+ LONG SubBlockSize;/* <0 if used, >0 if free */
+} FREE_SUB_BLOCK, *PFREE_SUB_BLOCK;
+
+typedef struct _KEY_BLOCK
+{
+ LONG SubBlockSize;
+ USHORT SubBlockId;
+ USHORT Type;
+ FILETIME LastWriteTime; /* please don't replace with LARGE_INTEGER !*/
+ ULONG UnUsed1;
+ BLOCK_OFFSET ParentKeyOffset;
+ ULONG NumberOfSubKeys;
+ ULONG UnUsed2;
+ BLOCK_OFFSET HashTableOffset;
+ ULONG UnUsed3;
+ ULONG NumberOfValues;
+ BLOCK_OFFSET ValuesOffset;
+ BLOCK_OFFSET SecurityKeyOffset;
+ BLOCK_OFFSET ClassNameOffset;
+ ULONG Unused4[5];
+ USHORT NameSize;
+ USHORT ClassSize; /* size of ClassName in bytes */
+ UCHAR Name[0]; /* warning : not zero terminated */
+} KEY_BLOCK, *PKEY_BLOCK;
+
+// hash record :
+// HashValue=four letters of value's name
+typedef struct _HASH_RECORD
+{
+ BLOCK_OFFSET KeyOffset;
+ ULONG HashValue;
+} HASH_RECORD, *PHASH_RECORD;
+
+typedef struct _HASH_TABLE_BLOCK
+{
+ LONG SubBlockSize;
+ USHORT SubBlockId;
+ USHORT HashTableSize;
+ HASH_RECORD Table[0];
+} HASH_TABLE_BLOCK, *PHASH_TABLE_BLOCK;
+
+typedef struct _VALUE_LIST_BLOCK
+{
+ LONG SubBlockSize;
+ BLOCK_OFFSET Values[0];
+} VALUE_LIST_BLOCK, *PVALUE_LIST_BLOCK;
+
+typedef struct _VALUE_BLOCK
+{
+ LONG SubBlockSize;
+ USHORT SubBlockId; // "kv"
+ USHORT NameSize; // length of Name
+ LONG DataSize; // length of datas in the subblock pointed by DataOffset
+ BLOCK_OFFSET DataOffset;// datas are here if high bit of DataSize is set
+ ULONG DataType;
+ USHORT Flags;
+ USHORT Unused1;
+ UCHAR Name[0]; /* warning : not zero terminated */
+} VALUE_BLOCK, *PVALUE_BLOCK;
+
+typedef struct _DATA_BLOCK
+{
+ LONG SubBlockSize;
+ UCHAR Data[0];
+} DATA_BLOCK, *PDATA_BLOCK;
+
+typedef struct _REGISTRY_FILE
+{
+ PWSTR Filename;
+ ULONG FileSize;
+ PFILE_OBJECT FileObject;
+ PHEADER_BLOCK HeaderBlock;
+// ULONG NumberOfBlocks;
+ ULONG BlockListSize;
+ PHEAP_BLOCK *BlockList;
+ ULONG FreeListSize;
+ ULONG FreeListMax;
+ PFREE_SUB_BLOCK *FreeList;
+ BLOCK_OFFSET *FreeListOffset;
+// KSPIN_LOCK RegLock;
+ KSEMAPHORE RegSem;
+
+
+// NTSTATUS (*Extend)(ULONG NewSize);
+// PVOID (*Flush)(VOID);
+} REGISTRY_FILE, *PREGISTRY_FILE;
+
+/* Type defining the Object Manager Key Object */
+typedef struct _KEY_OBJECT
+{
+ CSHORT Type;
+ CSHORT Size;
+
+ ULONG Flags;
+ USHORT NameSize; // length of Name
+ UCHAR *Name;
+ PREGISTRY_FILE RegistryFile;
+ BLOCK_OFFSET BlockOffset;
+ PKEY_BLOCK KeyBlock;
+ struct _KEY_OBJECT *ParentKey;
+ ULONG NumberOfSubKeys; /* subkeys loaded in SubKeys */
+ ULONG SizeOfSubKeys; /* space allocated in SubKeys */
+ struct _KEY_OBJECT **SubKeys; /* list of subkeys loaded */
+} KEY_OBJECT, *PKEY_OBJECT;
+
+
+NTSTATUS CmiObjectParse(PVOID ParsedObject,
+ PVOID *NextObject,
+ PUNICODE_STRING FullPath,
+ PWSTR *Path,
+ POBJECT_TYPE ObjectType,
+ ULONG Attribute);
+
+NTSTATUS CmiObjectCreate(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ struct _OBJECT_ATTRIBUTES* ObjectAttributes);
+void CmiObjectDelete(PVOID DeletedObject);
+
+VOID CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey);
+NTSTATUS CmiRemoveKeyFromList(PKEY_OBJECT NewKey);
+PKEY_OBJECT CmiScanKeyList(PKEY_OBJECT Parent,
+ PCHAR KeyNameBuf,
+ ULONG Attributes);
+
+PREGISTRY_FILE CmiCreateRegistry(PWSTR Filename);
+
+ULONG CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock);
+ULONG CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock);
+ULONG CmiGetMaxValueNameLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock);
+ULONG CmiGetMaxValueDataLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock);
+
+NTSTATUS CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ OUT PKEY_BLOCK *SubKeyBlock,
+ OUT BLOCK_OFFSET *BlockOffset,
+ IN PCHAR KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG Attributes);
+NTSTATUS CmiAddSubKey(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_OBJECT Parent,
+ OUT PKEY_OBJECT SubKey,
+ IN PWSTR NewSubKeyName,
+ IN USHORT NewSubKeyNameSize,
+ IN ULONG TitleIndex,
+ IN PUNICODE_STRING Class,
+ IN ULONG CreateOptions);
+
+NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN PCHAR ValueName,
+ OUT PVALUE_BLOCK *ValueBlock,
+ OUT BLOCK_OFFSET *VBOffset);
+NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN ULONG Index,
+ OUT PVALUE_BLOCK *ValueBlock);
+NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN PCHAR ValueNameBuf,
+ OUT PVALUE_BLOCK *pValueBlock,
+ OUT BLOCK_OFFSET *pVBOffset);
+NTSTATUS CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN PCHAR ValueName);
+
+NTSTATUS CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile,
+ OUT PHASH_TABLE_BLOCK *HashBlock,
+ OUT BLOCK_OFFSET *HBOffset,
+ IN ULONG HashTableSize);
+PKEY_BLOCK CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile,
+ PHASH_TABLE_BLOCK HashBlock,
+ ULONG Index);
+NTSTATUS CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile,
+ PHASH_TABLE_BLOCK HashBlock,
+ PKEY_BLOCK NewKeyBlock,
+ BLOCK_OFFSET NKBOffset);
+
+NTSTATUS CmiAllocateValueBlock(IN PREGISTRY_FILE RegistryFile,
+ OUT PVALUE_BLOCK *ValueBlock,
+ OUT BLOCK_OFFSET *VBOffset,
+ IN PCHAR ValueNameBuf);
+NTSTATUS CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile,
+ PVALUE_BLOCK ValueBlock, BLOCK_OFFSET VBOffset);
+
+NTSTATUS CmiAllocateBlock(PREGISTRY_FILE RegistryFile,
+ PVOID *Block,
+ LONG BlockSize,
+ BLOCK_OFFSET * pBlockOffset);
+NTSTATUS CmiDestroyBlock(PREGISTRY_FILE RegistryFile,
+ PVOID Block,BLOCK_OFFSET Offset);
+PVOID CmiGetBlock(PREGISTRY_FILE RegistryFile,
+ BLOCK_OFFSET BlockOffset,
+ OUT PHEAP_BLOCK * ppHeap);
+VOID CmiLockBlock(PREGISTRY_FILE RegistryFile,
+ PVOID Block);
+VOID CmiReleaseBlock(PREGISTRY_FILE RegistryFile,
+ PVOID Block);
+NTSTATUS
+CmiAddFree(PREGISTRY_FILE RegistryFile,
+ PFREE_SUB_BLOCK FreeBlock,BLOCK_OFFSET FreeOffset);
+
+#endif /*__INCLUDE_CM_H*/
\ No newline at end of file
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/cm/ntfunc.c
+ * PURPOSE: Ntxxx function for registry access
+ * UPDATE HISTORY:
+*/
+
+#include "cm.h"
+
+extern POBJECT_TYPE CmiKeyType;
+extern PREGISTRY_FILE CmiVolatileFile;
+
+
+NTSTATUS STDCALL
+NtCreateKey(OUT PHANDLE KeyHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN ULONG TitleIndex,
+ IN PUNICODE_STRING Class,
+ IN ULONG CreateOptions,
+ OUT PULONG Disposition)
+{
+ NTSTATUS Status;
+ PVOID Object;
+ PKEY_OBJECT key;
+ UNICODE_STRING RemainingPath;
+ PWSTR end;
+// KIRQL OldIrql;
+
+// DPRINT("NtCreateKey (Name %wZ),KeyHandle=%x,Root=%x\n",
+// ObjectAttributes->ObjectName,KeyHandle
+// ,ObjectAttributes->RootDirectory);
+ Status = ObFindObject(ObjectAttributes,&Object,&RemainingPath,CmiKeyType);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+DPRINT("RP=%wZ\n",&RemainingPath);
+ if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] ==0))
+ {
+ /* Fail if the key has been deleted */
+ if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
+ {
+ ObDereferenceObject(Object);
+ return STATUS_UNSUCCESSFUL;
+ }
+ if (Disposition)
+ *Disposition = REG_OPENED_EXISTING_KEY;
+ Status = ObCreateHandle(PsGetCurrentProcess(),
+ Object,
+ DesiredAccess,
+ FALSE,
+ KeyHandle);
+DPRINT("Status=%x\n",Status);
+ ObDereferenceObject(Object);
+ return Status;
+ }
+ /* if RemainingPath contains \ : must return error */
+ if((RemainingPath.Buffer[0])=='\\')
+ end = wcschr((RemainingPath.Buffer)+1, '\\');
+ else
+ end = wcschr((RemainingPath.Buffer), '\\');
+ if (end != NULL)
+ {
+ ObDereferenceObject(Object);
+ return STATUS_UNSUCCESSFUL;
+ }
+ /* because NtCreateKey don't create tree */
+
+DPRINT("NCK %S parent=%x\n",RemainingPath.Buffer,Object);
+ key = ObCreateObject(
+ KeyHandle,
+ DesiredAccess,
+ NULL,
+ CmiKeyType
+ );
+
+ if (key == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ key->ParentKey = Object;
+// if ( (key->ParentKey ==NULL))
+// key->ParentKey = ObjectAttributes->RootDirectory;
+ if (CreateOptions & REG_OPTION_VOLATILE)
+ key->RegistryFile=CmiVolatileFile;
+ else
+ key->RegistryFile=key->ParentKey->RegistryFile;
+ key->Flags = 0;
+ key->NumberOfSubKeys = 0;
+ key->SizeOfSubKeys = 0;
+ key->SubKeys = NULL;
+// KeAcquireSpinLock(&key->RegistryFile->RegLock, &OldIrql);
+ /* add key to subkeys of parent if needed */
+ Status = CmiAddSubKey(key->RegistryFile,
+ key->ParentKey,
+ key,
+ RemainingPath.Buffer,
+ RemainingPath.Length,
+ TitleIndex,
+ Class,
+ CreateOptions);
+ key->Name = key->KeyBlock->Name;
+ key->NameSize = key->KeyBlock->NameSize;
+ if (key->RegistryFile == key->ParentKey->RegistryFile)
+ {
+ key->KeyBlock->ParentKeyOffset = key->ParentKey->BlockOffset;
+ key->KeyBlock->SecurityKeyOffset = key->ParentKey->KeyBlock->SecurityKeyOffset;
+ }
+ else
+ {
+ key->KeyBlock->ParentKeyOffset = -1;
+ key->KeyBlock->SecurityKeyOffset = -1;
+ /* this key must rest in memory unless it is deleted */
+ /* , or file is unloaded*/
+ ObReferenceObjectByPointer(key,
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ UserMode);
+ }
+ CmiAddKeyToList(key->ParentKey,key);
+// KeReleaseSpinLock(&key->RegistryFile->RegLock, OldIrql);
+ ObDereferenceObject(key);
+ ObDereferenceObject(Object);
+ if (Disposition) *Disposition = REG_CREATED_NEW_KEY;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS STDCALL
+NtDeleteKey(IN HANDLE KeyHandle)
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_WRITE,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Set the marked for delete bit in the key object */
+ KeyObject->Flags |= KO_MARKED_FOR_DELETE;
+
+ /* Dereference the object */
+ ObDereferenceObject(KeyObject);
+ if(KeyObject->RegistryFile != KeyObject->ParentKey->RegistryFile)
+ ObDereferenceObject(KeyObject);
+ /* close the handle */
+ ObDeleteHandle(PsGetCurrentProcess(),KeyHandle);
+ /* FIXME: I think that ObDeleteHandle should dereference the object */
+ ObDereferenceObject(KeyObject);
+
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+STDCALL
+NtEnumerateKey (
+ IN HANDLE KeyHandle,
+ IN ULONG Index,
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ OUT PVOID KeyInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ )
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ PREGISTRY_FILE RegistryFile;
+ PKEY_BLOCK KeyBlock, SubKeyBlock;
+ PHASH_TABLE_BLOCK HashTableBlock;
+ PKEY_BASIC_INFORMATION BasicInformation;
+ PKEY_NODE_INFORMATION NodeInformation;
+ PKEY_FULL_INFORMATION FullInformation;
+ PDATA_BLOCK pClassData;
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_ENUMERATE_SUB_KEYS,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Get pointer to KeyBlock */
+ KeyBlock = KeyObject->KeyBlock;
+ RegistryFile = KeyObject->RegistryFile;
+
+ /* Get pointer to SubKey */
+ if(Index >= KeyBlock->NumberOfSubKeys)
+ {
+ if (RegistryFile == CmiVolatileFile)
+ {
+ ObDereferenceObject (KeyObject);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ else
+ {
+ int i;
+ PKEY_OBJECT CurKey=NULL;
+ /* search volatile keys */
+ for (i=0; i < KeyObject->NumberOfSubKeys; i++)
+ {
+ CurKey=KeyObject->SubKeys[i];
+ if (CurKey->RegistryFile == CmiVolatileFile)
+ {
+ if ( Index-- == KeyObject->NumberOfSubKeys) break;
+ }
+ }
+ if(Index >= KeyBlock->NumberOfSubKeys)
+ {
+ ObDereferenceObject (KeyObject);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ SubKeyBlock = CurKey->KeyBlock;
+ }
+ }
+ else
+ {
+ HashTableBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
+ SubKeyBlock = CmiGetKeyFromHashByIndex(RegistryFile,
+ HashTableBlock,
+ Index);
+ }
+ if (SubKeyBlock == NULL)
+ {
+ ObDereferenceObject (KeyObject);
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ Status = STATUS_SUCCESS;
+ switch (KeyInformationClass)
+ {
+ case KeyBasicInformation:
+ /* Check size of buffer */
+ if (Length < sizeof(KEY_BASIC_INFORMATION) +
+ (SubKeyBlock->NameSize ) * sizeof(WCHAR))
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ /* Fill buffer with requested info */
+ BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
+ BasicInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime;
+ BasicInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime;
+ BasicInformation->TitleIndex = Index;
+ BasicInformation->NameLength = (SubKeyBlock->NameSize ) * sizeof(WCHAR);
+ mbstowcs(BasicInformation->Name,
+ SubKeyBlock->Name,
+ SubKeyBlock->NameSize*2);
+// BasicInformation->Name[SubKeyBlock->NameSize] = 0;
+ *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
+ SubKeyBlock->NameSize * sizeof(WCHAR);
+ }
+ break;
+
+ case KeyNodeInformation:
+ /* Check size of buffer */
+ if (Length < sizeof(KEY_NODE_INFORMATION) +
+ (SubKeyBlock->NameSize ) * sizeof(WCHAR) +
+ (SubKeyBlock->ClassSize ))
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ /* Fill buffer with requested info */
+ NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
+ NodeInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime;
+ NodeInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime;
+ NodeInformation->TitleIndex = Index;
+ NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
+ SubKeyBlock->NameSize * sizeof(WCHAR);
+ NodeInformation->ClassLength = SubKeyBlock->ClassSize;
+ NodeInformation->NameLength = (SubKeyBlock->NameSize ) * sizeof(WCHAR);
+ mbstowcs(NodeInformation->Name,
+ SubKeyBlock->Name,
+ SubKeyBlock->NameSize*2);
+// NodeInformation->Name[SubKeyBlock->NameSize] = 0;
+ if (SubKeyBlock->ClassSize != 0)
+ {
+ pClassData=CmiGetBlock(KeyObject->RegistryFile
+ ,SubKeyBlock->ClassNameOffset,NULL);
+ wcsncpy(NodeInformation->Name + SubKeyBlock->NameSize ,
+ (PWCHAR)pClassData->Data,
+ SubKeyBlock->ClassSize);
+ CmiReleaseBlock(RegistryFile, pClassData);
+ }
+ *ResultLength = sizeof(KEY_NODE_INFORMATION) +
+ (SubKeyBlock->NameSize) * sizeof(WCHAR) +
+ (SubKeyBlock->ClassSize );
+ }
+ break;
+
+ case KeyFullInformation:
+ /* check size of buffer */
+ if (Length < sizeof(KEY_FULL_INFORMATION) +
+ SubKeyBlock->ClassSize)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ /* fill buffer with requested info */
+ FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
+ FullInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime;
+ FullInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime;
+ FullInformation->TitleIndex = Index;
+ FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
+ sizeof(WCHAR);
+ FullInformation->ClassLength = SubKeyBlock->ClassSize;
+ FullInformation->SubKeys = SubKeyBlock->NumberOfSubKeys;
+ FullInformation->MaxNameLen =
+ CmiGetMaxNameLength(RegistryFile, SubKeyBlock);
+ FullInformation->MaxClassLen =
+ CmiGetMaxClassLength(RegistryFile, SubKeyBlock);
+ FullInformation->Values = SubKeyBlock->NumberOfValues;
+ FullInformation->MaxValueNameLen =
+ CmiGetMaxValueNameLength(RegistryFile, SubKeyBlock);
+ FullInformation->MaxValueDataLen =
+ CmiGetMaxValueDataLength(RegistryFile, SubKeyBlock);
+ if (SubKeyBlock->ClassSize != 0)
+ {
+ pClassData=CmiGetBlock(KeyObject->RegistryFile
+ ,SubKeyBlock->ClassNameOffset,NULL);
+ wcsncpy(FullInformation->Class,
+ (PWCHAR)pClassData->Data,
+ SubKeyBlock->ClassSize);
+ CmiReleaseBlock(RegistryFile, pClassData);
+ }
+ *ResultLength = sizeof(KEY_FULL_INFORMATION) +
+ SubKeyBlock->ClassSize ;
+ }
+ break;
+ }
+ CmiReleaseBlock(RegistryFile, SubKeyBlock);
+ ObDereferenceObject (KeyObject);
+
+ return Status;
+}
+
+
+NTSTATUS
+STDCALL
+NtEnumerateValueKey (
+ IN HANDLE KeyHandle,
+ IN ULONG Index,
+ IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+ OUT PVOID KeyValueInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ )
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ PREGISTRY_FILE RegistryFile;
+ PKEY_BLOCK KeyBlock;
+ PVALUE_BLOCK ValueBlock;
+ PDATA_BLOCK DataBlock;
+ PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
+ PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
+ PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
+
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_QUERY_VALUE,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Get pointer to KeyBlock */
+ KeyBlock = KeyObject->KeyBlock;
+ RegistryFile = KeyObject->RegistryFile;
+
+ /* Get Value block of interest */
+ Status = CmiGetValueFromKeyByIndex(RegistryFile,
+ KeyBlock,
+ Index,
+ &ValueBlock);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(KeyObject);
+ return Status;
+ }
+ else if (ValueBlock != NULL)
+ {
+ switch (KeyValueInformationClass)
+ {
+ case KeyValueBasicInformation:
+ *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
+ (ValueBlock->NameSize + 1) * sizeof(WCHAR);
+ if (Length < *ResultLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
+ KeyValueInformation;
+ ValueBasicInformation->TitleIndex = 0;
+ ValueBasicInformation->Type = ValueBlock->DataType;
+ ValueBasicInformation->NameLength =
+ (ValueBlock->NameSize + 1) * sizeof(WCHAR);
+ mbstowcs(ValueBasicInformation->Name, ValueBlock->Name
+ ,ValueBlock->NameSize*2);
+ ValueBasicInformation->Name[ValueBlock->NameSize]=0;
+ }
+ break;
+
+ case KeyValuePartialInformation:
+ *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
+ (ValueBlock->DataSize & LONG_MAX);
+ if (Length < *ResultLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
+ KeyValueInformation;
+ ValuePartialInformation->TitleIndex = 0;
+ ValuePartialInformation->Type = ValueBlock->DataType;
+ ValuePartialInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
+ if(ValueBlock->DataSize >0)
+ {
+ DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
+ RtlCopyMemory(ValuePartialInformation->Data,
+ DataBlock->Data,
+ ValueBlock->DataSize & LONG_MAX);
+ CmiReleaseBlock(RegistryFile, DataBlock);
+ }
+ else
+ {
+ RtlCopyMemory(ValuePartialInformation->Data,
+ &ValueBlock->DataOffset,
+ ValueBlock->DataSize & LONG_MAX);
+ }
+ DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
+ }
+ break;
+
+ case KeyValueFullInformation:
+ *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
+ (ValueBlock->NameSize ) * sizeof(WCHAR) + (ValueBlock->DataSize & LONG_MAX);
+ if (Length < *ResultLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
+ KeyValueInformation;
+ ValueFullInformation->TitleIndex = 0;
+ ValueFullInformation->Type = ValueBlock->DataType;
+ ValueFullInformation->DataOffset =
+ (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation
+ + (ValueBlock->NameSize ) * sizeof(WCHAR);
+ ValueFullInformation->DataOffset =
+ (ValueFullInformation->DataOffset +3) &0xfffffffc;
+ ValueFullInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
+ ValueFullInformation->NameLength =
+ (ValueBlock->NameSize ) * sizeof(WCHAR);
+ mbstowcs(ValueFullInformation->Name, ValueBlock->Name
+ ,ValueBlock->NameSize*2);
+ if(ValueBlock->DataSize >0)
+ {
+ DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
+ RtlCopyMemory((char *)(ValueFullInformation)
+ + ValueFullInformation->DataOffset,
+ DataBlock->Data,
+ ValueBlock->DataSize & LONG_MAX);
+ CmiReleaseBlock(RegistryFile, DataBlock);
+ }
+ else
+ {
+ RtlCopyMemory((char *)(ValueFullInformation)
+ + ValueFullInformation->DataOffset,
+ &ValueBlock->DataOffset,
+ ValueBlock->DataSize & LONG_MAX);
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ ObDereferenceObject(KeyObject);
+
+ return Status;
+}
+
+
+NTSTATUS STDCALL
+NtFlushKey(IN HANDLE KeyHandle)
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ PREGISTRY_FILE RegistryFile;
+ WCHAR LogName[MAX_PATH];
+ HANDLE FileHandle;
+// HANDLE FileHandleLog;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+// KIRQL OldIrql;
+ UNICODE_STRING TmpFileName;
+ int i;
+ LARGE_INTEGER fileOffset;
+ DWORD * pEntDword;
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_QUERY_VALUE,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ RegistryFile = KeyObject->RegistryFile;
+// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
+ /* then write changed blocks in .log */
+ wcscpy(LogName,RegistryFile->Filename );
+ wcscat(LogName,L".log");
+ RtlInitUnicodeString (&TmpFileName, LogName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &TmpFileName,
+ 0,
+ NULL,
+ NULL);
+/* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
+ so we can't create log file
+ Status = ZwCreateFile(&FileHandleLog,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ NULL, 0, FILE_ATTRIBUTE_NORMAL,
+ 0, FILE_SUPERSEDE, 0, NULL, 0);
+ Status = ZwWriteFile(FileHandleLog,
+ 0, 0, 0, 0,
+ RegistryFile->HeaderBlock,
+ sizeof(HEADER_BLOCK),
+ 0, 0);
+ for (i=0; i < RegistryFile->BlockListSize ; i++)
+ {
+ if( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
+ > RegistryFile->HeaderBlock->DateModified.dwHighDateTime
+ ||( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
+ == RegistryFile->HeaderBlock->DateModified.dwHighDateTime
+ && RegistryFile->BlockList[i]->DateModified.dwLowDateTime
+ > RegistryFile->HeaderBlock->DateModified.dwLowDateTime)
+ )
+ Status = ZwWriteFile(FileHandleLog,
+ 0, 0, 0, 0,
+ RegistryFile->BlockList[i],
+ RegistryFile->BlockList[i]->BlockSize ,
+ 0, 0);
+ }
+ ZwClose(FileHandleLog);
+END FIXME*/
+ /* update header of registryfile with Version >VersionOld */
+ /* this allow recover if system crash while updating hove file */
+ RtlInitUnicodeString (&TmpFileName, RegistryFile->Filename);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &TmpFileName,
+ 0,
+ NULL,
+ NULL);
+ Status = NtOpenFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ NULL, 0, 0);
+ RegistryFile->HeaderBlock->Version++;
+
+ Status = ZwWriteFile(FileHandle,
+ 0, 0, 0, 0,
+ RegistryFile->HeaderBlock,
+ sizeof(HEADER_BLOCK),
+ 0, 0);
+
+ /* update changed blocks in file */
+ fileOffset.u.HighPart = 0;
+ for (i=0; i < RegistryFile->BlockListSize ; i++)
+ {
+ if( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
+ > RegistryFile->HeaderBlock->DateModified.dwHighDateTime
+ ||( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
+ == RegistryFile->HeaderBlock->DateModified.dwHighDateTime
+ && RegistryFile->BlockList[i]->DateModified.dwLowDateTime
+ > RegistryFile->HeaderBlock->DateModified.dwLowDateTime)
+ )
+ {
+ fileOffset.u.LowPart = RegistryFile->BlockList[i]->BlockOffset+4096;
+ Status = NtWriteFile(FileHandle,
+ 0, 0, 0, 0,
+ RegistryFile->BlockList[i],
+ RegistryFile->BlockList[i]->BlockSize ,
+ &fileOffset, 0);
+ }
+ }
+ /* change version in header */
+ RegistryFile->HeaderBlock->VersionOld = RegistryFile->HeaderBlock->Version;
+ ZwQuerySystemTime((PTIME) &RegistryFile->HeaderBlock->DateModified);
+ /* calculate checksum */
+ RegistryFile->HeaderBlock->Checksum = 0;
+ pEntDword = (DWORD *) RegistryFile->HeaderBlock;
+ for (i=0 ; i <127 ; i++)
+ {
+ RegistryFile->HeaderBlock->Checksum ^= pEntDword[i];
+ }
+ /* write new header */
+ fileOffset.u.LowPart = 0;
+ Status = ZwWriteFile(FileHandle,
+ 0, 0, 0, 0,
+ RegistryFile->HeaderBlock,
+ sizeof(HEADER_BLOCK),
+ &fileOffset, 0);
+ ZwClose(FileHandle);
+// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS STDCALL
+NtOpenKey(OUT PHANDLE KeyHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
+{
+ NTSTATUS Status;
+ PVOID Object;
+ UNICODE_STRING RemainingPath;
+
+ RemainingPath.Buffer=NULL;
+ Status = ObFindObject(ObjectAttributes,&Object,&RemainingPath,CmiKeyType);
+DPRINT("NTOpenKey : after ObFindObject\n");
+DPRINT("RB.B=%x\n",RemainingPath.Buffer);
+ if(RemainingPath.Buffer != 0 && RemainingPath.Buffer[0] !=0)
+ {
+DPRINT("NTOpenKey3 : after ObFindObject\n");
+ ObDereferenceObject(Object);
+DPRINT("RP=%wZ\n",&RemainingPath);
+ return STATUS_UNSUCCESSFUL;
+ }
+DPRINT("NTOpenKey2 : after ObFindObject\n");
+ /* Fail if the key has been deleted */
+ if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
+ {
+ ObDereferenceObject(Object);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = ObCreateHandle(
+ PsGetCurrentProcess(),
+ Object,
+ DesiredAccess,
+ FALSE,
+ KeyHandle
+ );
+ ObDereferenceObject(Object);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+STDCALL
+NtQueryKey (
+ IN HANDLE KeyHandle,
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ OUT PVOID KeyInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ )
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ PREGISTRY_FILE RegistryFile;
+ PKEY_BLOCK KeyBlock;
+ PKEY_BASIC_INFORMATION BasicInformation;
+ PKEY_NODE_INFORMATION NodeInformation;
+ PKEY_FULL_INFORMATION FullInformation;
+ PDATA_BLOCK pClassData;
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_READ,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Get pointer to KeyBlock */
+ KeyBlock = KeyObject->KeyBlock;
+ RegistryFile = KeyObject->RegistryFile;
+
+ Status = STATUS_SUCCESS;
+ switch (KeyInformationClass)
+ {
+ case KeyBasicInformation:
+ /* Check size of buffer */
+ if (Length < sizeof(KEY_BASIC_INFORMATION) +
+ KeyObject->NameSize * sizeof(WCHAR))
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ /* Fill buffer with requested info */
+ BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
+ BasicInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime;
+ BasicInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime;
+ BasicInformation->TitleIndex = 0;
+ BasicInformation->NameLength =
+ (KeyObject->NameSize ) * sizeof(WCHAR);
+ mbstowcs(BasicInformation->Name,
+ KeyObject->Name,
+ KeyObject->NameSize*sizeof(WCHAR));
+ *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
+ KeyObject->NameSize * sizeof(WCHAR);
+ }
+ break;
+
+ case KeyNodeInformation:
+ /* Check size of buffer */
+ if (Length < sizeof(KEY_NODE_INFORMATION) +
+ (KeyObject->NameSize ) * sizeof(WCHAR) +
+ KeyBlock->ClassSize )
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ /* Fill buffer with requested info */
+ NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
+ NodeInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime;
+ NodeInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime;
+ NodeInformation->TitleIndex = 0;
+ NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
+ KeyObject->NameSize * sizeof(WCHAR);
+ NodeInformation->ClassLength = KeyBlock->ClassSize;
+ NodeInformation->NameLength =
+ (KeyObject->NameSize ) * sizeof(WCHAR);
+ mbstowcs(NodeInformation->Name,
+ KeyObject->Name,
+ KeyObject->NameSize*2);
+ if (KeyBlock->ClassSize != 0)
+ {
+ pClassData=CmiGetBlock(KeyObject->RegistryFile
+ ,KeyBlock->ClassNameOffset,NULL);
+ wcsncpy(NodeInformation->Name + (KeyObject->NameSize )*sizeof(WCHAR),
+ (PWCHAR)pClassData->Data,
+ KeyBlock->ClassSize);
+ CmiReleaseBlock(RegistryFile, pClassData);
+ }
+ *ResultLength = sizeof(KEY_NODE_INFORMATION) +
+ (KeyObject->NameSize ) * sizeof(WCHAR) +
+ KeyBlock->ClassSize;
+ }
+ break;
+
+ case KeyFullInformation:
+ /* Check size of buffer */
+ if (Length < sizeof(KEY_FULL_INFORMATION) +
+ KeyBlock->ClassSize )
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ /* Fill buffer with requested info */
+ FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
+ FullInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime;
+ FullInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime;
+ FullInformation->TitleIndex = 0;
+ FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
+ sizeof(WCHAR);
+ FullInformation->ClassLength = KeyBlock->ClassSize;
+ FullInformation->SubKeys = KeyBlock->NumberOfSubKeys;
+ FullInformation->MaxNameLen =
+ CmiGetMaxNameLength(RegistryFile, KeyBlock);
+ FullInformation->MaxClassLen =
+ CmiGetMaxClassLength(RegistryFile, KeyBlock);
+ FullInformation->Values = KeyBlock->NumberOfValues;
+ FullInformation->MaxValueNameLen =
+ CmiGetMaxValueNameLength(RegistryFile, KeyBlock);
+ FullInformation->MaxValueDataLen =
+ CmiGetMaxValueDataLength(RegistryFile, KeyBlock);
+ if (KeyBlock->ClassSize != 0)
+ {
+ pClassData=CmiGetBlock(KeyObject->RegistryFile
+ ,KeyBlock->ClassNameOffset,NULL);
+ wcsncpy(FullInformation->Class,
+ (PWCHAR)pClassData->Data,
+ KeyBlock->ClassSize);
+ CmiReleaseBlock(RegistryFile, pClassData);
+ }
+ *ResultLength = sizeof(KEY_FULL_INFORMATION) +
+ KeyBlock->ClassSize ;
+ }
+ break;
+ }
+ ObDereferenceObject (KeyObject);
+
+ return Status;
+}
+
+
+NTSTATUS
+STDCALL
+NtQueryValueKey (
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName,
+ IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+ OUT PVOID KeyValueInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ )
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ PREGISTRY_FILE RegistryFile;
+ PKEY_BLOCK KeyBlock;
+ PVALUE_BLOCK ValueBlock;
+ PDATA_BLOCK DataBlock;
+ PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
+ PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
+ PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
+ char ValueName2[MAX_PATH];
+
+ wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
+ ValueName2[ValueName->Length>>1]=0;
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_QUERY_VALUE,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Get pointer to KeyBlock */
+ KeyBlock = KeyObject->KeyBlock;
+ RegistryFile = KeyObject->RegistryFile;
+ /* Get Value block of interest */
+ Status = CmiScanKeyForValue(RegistryFile,
+ KeyBlock,
+ ValueName2,
+ &ValueBlock,NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(KeyObject);
+ return Status;
+ }
+ else if (ValueBlock != NULL)
+ {
+ switch (KeyValueInformationClass)
+ {
+ case KeyValueBasicInformation:
+ *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
+ ValueBlock->NameSize * sizeof(WCHAR);
+ if (Length < *ResultLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
+ KeyValueInformation;
+ ValueBasicInformation->TitleIndex = 0;
+ ValueBasicInformation->Type = ValueBlock->DataType;
+ ValueBasicInformation->NameLength =
+ (ValueBlock->NameSize + 1) * sizeof(WCHAR);
+ mbstowcs(ValueBasicInformation->Name, ValueBlock->Name,ValueBlock->NameSize*2);
+ ValueBasicInformation->Name[ValueBlock->NameSize]=0;
+ }
+ break;
+
+ case KeyValuePartialInformation:
+ *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
+ (ValueBlock->DataSize & LONG_MAX);
+ if (Length < *ResultLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
+ KeyValueInformation;
+ ValuePartialInformation->TitleIndex = 0;
+ ValuePartialInformation->Type = ValueBlock->DataType;
+ ValuePartialInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
+ if(ValueBlock->DataSize >0)
+ {
+ DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
+ RtlCopyMemory(ValuePartialInformation->Data,
+ DataBlock->Data,
+ ValueBlock->DataSize & LONG_MAX);
+ CmiReleaseBlock(RegistryFile, DataBlock);
+ }
+ else
+ {
+ RtlCopyMemory(ValuePartialInformation->Data,
+ &ValueBlock->DataOffset,
+ ValueBlock->DataSize & LONG_MAX);
+ }
+ }
+ break;
+
+ case KeyValueFullInformation:
+ *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)
+ + (ValueBlock->NameSize -1) * sizeof(WCHAR)
+ + (ValueBlock->DataSize & LONG_MAX);
+ if (Length < *ResultLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
+ KeyValueInformation;
+ ValueFullInformation->TitleIndex = 0;
+ ValueFullInformation->Type = ValueBlock->DataType;
+ ValueFullInformation->DataOffset =
+ (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation
+ + (ValueBlock->NameSize ) * sizeof(WCHAR);
+ ValueFullInformation->DataOffset =
+ (ValueFullInformation->DataOffset +3) &0xfffffffc;
+ ValueFullInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
+ ValueFullInformation->NameLength =
+ (ValueBlock->NameSize ) * sizeof(WCHAR);
+ mbstowcs(ValueFullInformation->Name, ValueBlock->Name,ValueBlock->NameSize*2);
+ if(ValueBlock->DataSize >0)
+ {
+ DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
+ RtlCopyMemory((char *)(ValueFullInformation)
+ + ValueFullInformation->DataOffset,
+ DataBlock->Data,
+ ValueBlock->DataSize & LONG_MAX);
+ CmiReleaseBlock(RegistryFile, DataBlock);
+ }
+ else
+ {
+ RtlCopyMemory((char *)(ValueFullInformation)
+ + ValueFullInformation->DataOffset,
+ &ValueBlock->DataOffset,
+ ValueBlock->DataSize & LONG_MAX);
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ ObDereferenceObject(KeyObject);
+
+ return Status;
+}
+
+
+NTSTATUS
+STDCALL
+NtSetValueKey (
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName,
+ IN ULONG TitleIndex,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize
+ )
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ PREGISTRY_FILE RegistryFile;
+ PKEY_BLOCK KeyBlock;
+ PVALUE_BLOCK ValueBlock;
+ BLOCK_OFFSET VBOffset;
+ char ValueName2[MAX_PATH];
+ PDATA_BLOCK DataBlock, NewDataBlock;
+ PHEAP_BLOCK pHeap;
+// KIRQL OldIrql;
+
+ wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
+ ValueName2[ValueName->Length>>1]=0;
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_SET_VALUE,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Get pointer to KeyBlock */
+ KeyBlock = KeyObject->KeyBlock;
+ RegistryFile = KeyObject->RegistryFile;
+ Status = CmiScanKeyForValue(RegistryFile,
+ KeyBlock,
+ ValueName2,
+ &ValueBlock, &VBOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (KeyObject);
+ return Status;
+ }
+// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
+ if (ValueBlock == NULL)
+ {
+ Status = CmiAddValueToKey(RegistryFile,
+ KeyBlock,
+ ValueName2,
+ &ValueBlock,
+ &VBOffset);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (KeyObject);
+ return Status;
+ }
+ else
+ {
+ /* FIXME if datasize <=4 then write in valueblock directly */
+ if (DataSize <= 4)
+ {
+ if (( ValueBlock->DataSize <0 )
+ && (DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL)))
+ {
+ CmiDestroyBlock(RegistryFile, DataBlock, ValueBlock->DataOffset);
+ }
+ RtlCopyMemory(&ValueBlock->DataOffset, Data, DataSize);
+ ValueBlock->DataSize = DataSize | 0x80000000;
+ ValueBlock->DataType = Type;
+ memcpy(&ValueBlock->DataOffset, Data, DataSize);
+ }
+ /* If new data size is <= current then overwrite current data */
+ else if (DataSize <= (ValueBlock->DataSize & 0x7fffffff))
+ {
+ DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,&pHeap);
+ RtlCopyMemory(DataBlock->Data, Data, DataSize);
+ ValueBlock->DataSize = DataSize;
+ ValueBlock->DataType = Type;
+ CmiReleaseBlock(RegistryFile, DataBlock);
+ /* update time of heap */
+ if(RegistryFile->Filename)
+ ZwQuerySystemTime((PTIME) &pHeap->DateModified);
+ }
+ else
+ {
+ BLOCK_OFFSET NewOffset;
+ /* Destroy current data block and allocate a new one */
+ if (( ValueBlock->DataSize <0 )
+ && (DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL)))
+ {
+ CmiDestroyBlock(RegistryFile, DataBlock, ValueBlock->DataOffset);
+ }
+ Status = CmiAllocateBlock(RegistryFile,
+ (PVOID *)&NewDataBlock,
+ DataSize,&NewOffset);
+ RtlCopyMemory(&NewDataBlock->Data[0], Data, DataSize);
+ ValueBlock->DataSize = DataSize;
+ ValueBlock->DataType = Type;
+ CmiReleaseBlock(RegistryFile, NewDataBlock);
+ ValueBlock->DataOffset = NewOffset;
+ }
+ /* update time of heap */
+ if(RegistryFile->Filename && CmiGetBlock(RegistryFile, VBOffset,&pHeap))
+ ZwQuerySystemTime((PTIME) &pHeap->DateModified);
+
+ }
+// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
+ ObDereferenceObject (KeyObject);
+
+ return Status;
+}
+
+NTSTATUS
+STDCALL
+NtDeleteValueKey (
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName
+ )
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ PREGISTRY_FILE RegistryFile;
+ PKEY_BLOCK KeyBlock;
+ char ValueName2[MAX_PATH];
+// KIRQL OldIrql;
+
+ wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
+ ValueName2[ValueName->Length>>1]=0;
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_QUERY_VALUE,
+ CmiKeyType,
+ UserMode,
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Get pointer to KeyBlock */
+ KeyBlock = KeyObject->KeyBlock;
+ RegistryFile = KeyObject->RegistryFile;
+// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
+ Status = CmiDeleteValueFromKey(RegistryFile,
+ KeyBlock,
+ ValueName2);
+// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
+ ObDereferenceObject(KeyObject);
+
+ return Status;
+}
+
+NTSTATUS
+STDCALL
+NtLoadKey (
+ PHANDLE KeyHandle,
+ POBJECT_ATTRIBUTES ObjectAttributes
+ )
+{
+ return NtLoadKey2(KeyHandle,
+ ObjectAttributes,
+ 0);
+}
+
+
+NTSTATUS
+STDCALL
+NtLoadKey2 (
+ PHANDLE KeyHandle,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ ULONG Unknown3
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtNotifyChangeKey (
+ IN HANDLE KeyHandle,
+ IN HANDLE Event,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG CompletionFilter,
+ IN BOOLEAN Asynchroneous,
+ OUT PVOID ChangeBuffer,
+ IN ULONG Length,
+ IN BOOLEAN WatchSubtree
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtQueryMultipleValueKey (
+ IN HANDLE KeyHandle,
+ IN PWVALENT ListOfValuesToQuery,
+ IN ULONG NumberOfItems,
+ OUT PVOID MultipleValueInformation,
+ IN ULONG Length,
+ OUT PULONG ReturnLength
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtReplaceKey (
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN HANDLE Key,
+ IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtRestoreKey (
+ IN HANDLE KeyHandle,
+ IN HANDLE FileHandle,
+ IN ULONG RestoreFlags
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtSaveKey (
+ IN HANDLE KeyHandle,
+ IN HANDLE FileHandle
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtSetInformationKey (
+ IN HANDLE KeyHandle,
+ IN CINT KeyInformationClass,
+ IN PVOID KeyInformation,
+ IN ULONG KeyInformationLength
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtUnloadKey (
+ HANDLE KeyHandle
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+NtInitializeRegistry (
+ BOOLEAN SetUpBoot
+ )
+{
+// UNIMPLEMENTED;
+ return STATUS_SUCCESS;
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/cm/regfile.c
+ * PURPOSE: Registry file manipulation routines
+ * UPDATE HISTORY:
+*/
+
+#include "cm.h"
+
+
+#define REG_BLOCK_SIZE 4096
+#define REG_HEAP_BLOCK_DATA_OFFSET 32
+#define REG_HEAP_ID 0x6e696268
+#define REG_INIT_BLOCK_LIST_SIZE 32
+#define REG_INIT_HASH_TABLE_SIZE 3
+#define REG_EXTEND_HASH_TABLE_SIZE 4
+#define REG_VALUE_LIST_BLOCK_MULTIPLE 4
+#define REG_KEY_BLOCK_ID 0x6b6e
+#define REG_HASH_TABLE_BLOCK_ID 0x666c
+#define REG_VALUE_BLOCK_ID 0x6b76
+#define REG_KEY_BLOCK_TYPE 0x20
+#define REG_ROOT_KEY_BLOCK_TYPE 0x2c
+
+
+extern PREGISTRY_FILE CmiVolatileFile;
+
+void CmiCreateDefaultHeaderBlock(PHEADER_BLOCK HeaderBlock)
+{
+ RtlZeroMemory(HeaderBlock, sizeof(HEADER_BLOCK));
+ HeaderBlock->BlockId = 0x66676572;
+ HeaderBlock->DateModified.dwLowDateTime = 0;
+ HeaderBlock->DateModified.dwHighDateTime = 0;
+ HeaderBlock->Version = 1;
+ HeaderBlock->Unused3 = 3;
+ HeaderBlock->Unused5 = 1;
+ HeaderBlock->RootKeyBlock = 0;
+ HeaderBlock->BlockSize = REG_BLOCK_SIZE;
+ HeaderBlock->Unused6 = 1;
+ HeaderBlock->Checksum = 0;
+}
+
+void CmiCreateDefaultHeapBlock(PHEAP_BLOCK HeapBlock)
+{
+ RtlZeroMemory(HeapBlock, sizeof(HEAP_BLOCK));
+ HeapBlock->BlockId = REG_HEAP_ID;
+ HeapBlock->DateModified.dwLowDateTime = 0;
+ HeapBlock->DateModified.dwHighDateTime = 0;
+ HeapBlock->BlockSize = REG_BLOCK_SIZE;
+}
+
+void CmiCreateDefaultRootKeyBlock(PKEY_BLOCK RootKeyBlock)
+{
+ RtlZeroMemory(RootKeyBlock, sizeof(KEY_BLOCK));
+ RootKeyBlock->SubBlockSize=-sizeof(KEY_BLOCK);
+ RootKeyBlock->SubBlockId = REG_KEY_BLOCK_ID;
+ RootKeyBlock->Type = REG_ROOT_KEY_BLOCK_TYPE;
+ ZwQuerySystemTime((PTIME) &RootKeyBlock->LastWriteTime);
+ RootKeyBlock->ParentKeyOffset = 0;
+ RootKeyBlock->NumberOfSubKeys = 0;
+ RootKeyBlock->HashTableOffset = -1;
+ RootKeyBlock->NumberOfValues = 0;
+ RootKeyBlock->ValuesOffset = -1;
+ RootKeyBlock->SecurityKeyOffset = 0;
+ RootKeyBlock->ClassNameOffset = -1;
+ RootKeyBlock->NameSize = 0;
+ RootKeyBlock->ClassSize = 0;
+}
+
+NTSTATUS CmiCreateNewRegFile( HANDLE FileHandle )
+{
+ NTSTATUS Status;
+ PHEADER_BLOCK HeaderBlock;
+ PHEAP_BLOCK HeapBlock;
+ PKEY_BLOCK RootKeyBlock;
+ PFREE_SUB_BLOCK FreeSubBlock;
+
+ IO_STATUS_BLOCK IoStatusBlock;
+ char* tBuf;
+
+ tBuf = (char*) ExAllocatePool(NonPagedPool, 2*REG_BLOCK_SIZE);
+ if( tBuf == NULL )
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ HeaderBlock = (PHEADER_BLOCK)tBuf;
+ HeapBlock = (PHEAP_BLOCK) (tBuf+REG_BLOCK_SIZE);
+ RootKeyBlock = (PKEY_BLOCK) (tBuf+REG_BLOCK_SIZE+REG_HEAP_BLOCK_DATA_OFFSET);
+ FreeSubBlock = (PFREE_SUB_BLOCK) (tBuf+REG_BLOCK_SIZE+REG_HEAP_BLOCK_DATA_OFFSET+sizeof(KEY_BLOCK));
+
+ CmiCreateDefaultHeaderBlock(HeaderBlock);
+ CmiCreateDefaultHeapBlock(HeapBlock);
+ CmiCreateDefaultRootKeyBlock(RootKeyBlock);
+
+ HeapBlock->BlockOffset = 0; //First block.
+ HeaderBlock->RootKeyBlock = REG_HEAP_BLOCK_DATA_OFFSET; //Offset to root key block.
+ //The rest of the block is free
+ FreeSubBlock->SubBlockSize = REG_BLOCK_SIZE-(REG_HEAP_BLOCK_DATA_OFFSET+sizeof(KEY_BLOCK));
+
+ Status = ZwWriteFile( FileHandle, NULL, NULL, NULL,
+ &IoStatusBlock, tBuf, 2*REG_BLOCK_SIZE, 0, NULL );
+
+ ExFreePool( tBuf );
+ return Status;
+}
+
+PREGISTRY_FILE
+CmiCreateRegistry(PWSTR Filename)
+{
+ PREGISTRY_FILE RegistryFile;
+ HANDLE FileHandle;
+ PKEY_BLOCK RootKeyBlock;
+ PHEAP_BLOCK tmpHeap;
+ LARGE_INTEGER fileOffset;
+ PFREE_SUB_BLOCK FreeBlock;
+ DWORD FreeOffset;
+ int i, j;
+ BLOCK_OFFSET BlockOffset;
+
+ RegistryFile = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_FILE));
+ if (Filename != NULL)
+ {
+ UNICODE_STRING TmpFileName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ FILE_STANDARD_INFORMATION fsi;
+ IO_STATUS_BLOCK IoSB;
+
+ /* Duplicate Filename */
+ RegistryFile->Filename = ExAllocatePool(NonPagedPool, MAX_PATH);
+ wcscpy(RegistryFile->Filename , Filename);
+
+ RtlInitUnicodeString (&TmpFileName, Filename);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &TmpFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile( &FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoSB,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN_IF,
+ FILE_NON_DIRECTORY_FILE,
+ NULL,
+ 0 );
+
+ /* FIXME: create directory if IoSB.Status == STATUS_OBJECT_PATH_NOT_FOUND */
+ if( !NT_SUCCESS(Status) )
+ {
+ ExFreePool(RegistryFile->Filename);
+ RegistryFile->Filename = NULL;
+ return NULL;
+ }
+ /*if file did not exist*/
+ if( IoSB.Information == FILE_CREATED ){
+ Status = CmiCreateNewRegFile( FileHandle );
+ if( !NT_SUCCESS(Status) )
+ {
+ ExFreePool(RegistryFile->Filename);
+ RegistryFile->Filename = NULL;
+ return NULL;
+ }
+ }
+
+ RegistryFile->HeaderBlock = (PHEADER_BLOCK)
+ ExAllocatePool(NonPagedPool, sizeof(HEADER_BLOCK));
+
+ fileOffset.u.HighPart = 0;
+ fileOffset.u.LowPart = 0;
+ Status = ZwReadFile(FileHandle,
+ 0, 0, 0, 0,
+ RegistryFile->HeaderBlock,
+ sizeof(HEADER_BLOCK),
+ &fileOffset, 0);
+ ZwQueryInformationFile(FileHandle,&IoSB,&fsi
+ ,sizeof(fsi),FileStandardInformation);
+ RegistryFile->FileSize = fsi.EndOfFile.u.LowPart;
+ RegistryFile->BlockListSize = RegistryFile->FileSize / 4096 -1;
+// RegistryFile->NumberOfBlocks = RegistryFile->BlockListSize;
+ RegistryFile->BlockList = ExAllocatePool(NonPagedPool,
+ sizeof(PHEAP_BLOCK *) * (RegistryFile->BlockListSize ));
+ BlockOffset=0;
+ fileOffset.u.HighPart = 0;
+ fileOffset.u.LowPart = 4096;
+ RegistryFile->BlockList [0]
+ = ExAllocatePool(NonPagedPool,RegistryFile->FileSize-4096);
+ if (RegistryFile->BlockList[0] == NULL)
+ {
+// Status = STATUS_INSUFFICIENT_RESOURCES;
+ DPRINT1("error allocating %d bytes for registry\n"
+ ,RegistryFile->FileSize-4096);
+ ZwClose(FileHandle);
+ return NULL;
+ }
+ Status = ZwReadFile(FileHandle,
+ 0, 0, 0, 0,
+ RegistryFile->BlockList [0],
+ RegistryFile->FileSize-4096,
+ &fileOffset, 0);
+ ZwClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("error %x reading registry file at offset %x\n"
+ ,Status,fileOffset.u.LowPart);
+ return NULL;
+ }
+ RegistryFile->FreeListSize = 0;
+ RegistryFile->FreeListMax = 0;
+ RegistryFile->FreeList = NULL;
+ for(i=0 ; i <RegistryFile->BlockListSize; i++)
+ {
+ tmpHeap = (PHEAP_BLOCK)(((char *)RegistryFile->BlockList [0])+BlockOffset);
+ if (tmpHeap->BlockId != REG_HEAP_ID )
+ {
+ DPRINT1("bad BlockId %x,offset %x\n",tmpHeap->BlockId,fileOffset.u.LowPart);
+ }
+ RegistryFile->BlockList [i]
+ = tmpHeap;
+ if (tmpHeap->BlockSize >4096)
+ {
+ for(j=1;j<tmpHeap->BlockSize/4096;j++)
+ RegistryFile->BlockList[i+j] = RegistryFile->BlockList[i];
+ i = i+j-1;
+ }
+ /* search free blocks and add to list */
+ FreeOffset=REG_HEAP_BLOCK_DATA_OFFSET;
+ while(FreeOffset < tmpHeap->BlockSize)
+ {
+ FreeBlock = (PFREE_SUB_BLOCK)((char *)RegistryFile->BlockList[i]
+ +FreeOffset);
+ if ( FreeBlock->SubBlockSize>0)
+ {
+ CmiAddFree(RegistryFile,FreeBlock
+ ,RegistryFile->BlockList[i]->BlockOffset+FreeOffset);
+ FreeOffset += FreeBlock->SubBlockSize;
+ }
+ else
+ FreeOffset -= FreeBlock->SubBlockSize;
+ }
+ BlockOffset += tmpHeap->BlockSize;
+ }
+ Status = ObReferenceObjectByHandle(FileHandle,
+ FILE_ALL_ACCESS,
+ IoFileObjectType,
+ UserMode,
+ (PVOID*)&RegistryFile->FileObject,
+ NULL);
+ }
+ else
+ {
+ RegistryFile->Filename = NULL;
+ RegistryFile->FileObject = NULL;
+
+ RegistryFile->HeaderBlock = (PHEADER_BLOCK)
+ ExAllocatePool(NonPagedPool, sizeof(HEADER_BLOCK));
+ CmiCreateDefaultHeaderBlock(RegistryFile->HeaderBlock);
+
+ RootKeyBlock = (PKEY_BLOCK) ExAllocatePool(NonPagedPool, sizeof(KEY_BLOCK));
+ CmiCreateDefaultRootKeyBlock(RootKeyBlock);
+
+ RegistryFile->HeaderBlock->RootKeyBlock = (BLOCK_OFFSET) RootKeyBlock;
+ }
+ KeInitializeSemaphore(&RegistryFile->RegSem, 1, 1);
+
+ return RegistryFile;
+}
+
+ULONG
+CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock)
+{
+ ULONG Idx, MaxName;
+ PHASH_TABLE_BLOCK HashBlock;
+ PKEY_BLOCK CurSubKeyBlock;
+
+ MaxName = 0;
+ HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
+ if (HashBlock == 0)
+ {
+ return 0;
+ }
+ for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
+ {
+ if (HashBlock->Table[Idx].KeyOffset != 0)
+ {
+ CurSubKeyBlock = CmiGetBlock(RegistryFile,
+ HashBlock->Table[Idx].KeyOffset,NULL);
+ if (MaxName < CurSubKeyBlock->NameSize)
+ {
+ MaxName = CurSubKeyBlock->NameSize;
+ }
+ CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
+ }
+ }
+
+ CmiReleaseBlock(RegistryFile, HashBlock);
+
+ return MaxName;
+}
+
+ULONG
+CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock)
+{
+ ULONG Idx, MaxClass;
+ PHASH_TABLE_BLOCK HashBlock;
+ PKEY_BLOCK CurSubKeyBlock;
+
+ MaxClass = 0;
+ HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
+ if (HashBlock == 0)
+ {
+ return 0;
+ }
+ for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
+ {
+ if (HashBlock->Table[Idx].KeyOffset != 0)
+ {
+ CurSubKeyBlock = CmiGetBlock(RegistryFile,
+ HashBlock->Table[Idx].KeyOffset,NULL);
+ if (MaxClass < CurSubKeyBlock->ClassSize)
+ {
+ MaxClass = CurSubKeyBlock->ClassSize;
+ }
+ CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
+ }
+ }
+
+ CmiReleaseBlock(RegistryFile, HashBlock);
+
+ return MaxClass;
+}
+
+ULONG
+CmiGetMaxValueNameLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock)
+{
+ ULONG Idx, MaxValueName;
+ PVALUE_LIST_BLOCK ValueListBlock;
+ PVALUE_BLOCK CurValueBlock;
+
+ ValueListBlock = CmiGetBlock(RegistryFile,
+ KeyBlock->ValuesOffset,NULL);
+ MaxValueName = 0;
+ if (ValueListBlock == 0)
+ {
+ return 0;
+ }
+ for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
+ {
+ CurValueBlock = CmiGetBlock(RegistryFile,
+ ValueListBlock->Values[Idx],NULL);
+ if (CurValueBlock != NULL &&
+ MaxValueName < CurValueBlock->NameSize)
+ {
+ MaxValueName = CurValueBlock->NameSize;
+ }
+ CmiReleaseBlock(RegistryFile, CurValueBlock);
+ }
+
+ CmiReleaseBlock(RegistryFile, ValueListBlock);
+
+ return MaxValueName;
+}
+
+ULONG
+CmiGetMaxValueDataLength(PREGISTRY_FILE RegistryFile,
+ PKEY_BLOCK KeyBlock)
+{
+ ULONG Idx, MaxValueData;
+ PVALUE_LIST_BLOCK ValueListBlock;
+ PVALUE_BLOCK CurValueBlock;
+
+ ValueListBlock = CmiGetBlock(RegistryFile,
+ KeyBlock->ValuesOffset,NULL);
+ MaxValueData = 0;
+ if (ValueListBlock == 0)
+ {
+ return 0;
+ }
+ for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
+ {
+ CurValueBlock = CmiGetBlock(RegistryFile,
+ ValueListBlock->Values[Idx],NULL);
+ if (CurValueBlock != NULL &&
+ MaxValueData < (CurValueBlock->DataSize & LONG_MAX) )
+ {
+ MaxValueData = CurValueBlock->DataSize & LONG_MAX;
+ }
+ CmiReleaseBlock(RegistryFile, CurValueBlock);
+ }
+
+ CmiReleaseBlock(RegistryFile, ValueListBlock);
+
+ return MaxValueData;
+}
+
+NTSTATUS
+CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ OUT PKEY_BLOCK *SubKeyBlock,
+ OUT BLOCK_OFFSET *BlockOffset,
+ IN PCHAR KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG Attributes)
+{
+ ULONG Idx;
+ PHASH_TABLE_BLOCK HashBlock;
+ PKEY_BLOCK CurSubKeyBlock;
+ WORD KeyLength = strlen(KeyName);
+
+ HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
+ *SubKeyBlock = NULL;
+ if (HashBlock == NULL)
+ {
+ return STATUS_SUCCESS;
+ }
+// for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
+ for (Idx = 0; Idx < KeyBlock->NumberOfSubKeys
+ && Idx < HashBlock->HashTableSize; Idx++)
+ {
+ if (Attributes & OBJ_CASE_INSENSITIVE)
+ {
+ if (HashBlock->Table[Idx].KeyOffset != 0 &&
+ HashBlock->Table[Idx].KeyOffset != -1 &&
+ !_strnicmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4))
+ {
+ CurSubKeyBlock = CmiGetBlock(RegistryFile,
+ HashBlock->Table[Idx].KeyOffset,NULL);
+ if ( CurSubKeyBlock->NameSize == KeyLength
+ && !_strnicmp(KeyName, CurSubKeyBlock->Name, KeyLength))
+ {
+ *SubKeyBlock = CurSubKeyBlock;
+ *BlockOffset = HashBlock->Table[Idx].KeyOffset;
+ break;
+ }
+ else
+ {
+ CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
+ }
+ }
+ }
+ else
+ {
+ if (HashBlock->Table[Idx].KeyOffset != 0 &&
+ HashBlock->Table[Idx].KeyOffset != -1 &&
+ !strncmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4))
+ {
+ CurSubKeyBlock = CmiGetBlock(RegistryFile,
+ HashBlock->Table[Idx].KeyOffset,NULL);
+ if ( CurSubKeyBlock->NameSize == KeyLength
+ && !_strnicmp(KeyName, CurSubKeyBlock->Name, KeyLength))
+ {
+ *SubKeyBlock = CurSubKeyBlock;
+ *BlockOffset = HashBlock->Table[Idx].KeyOffset;
+ break;
+ }
+ else
+ {
+ CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
+ }
+ }
+ }
+ }
+
+ CmiReleaseBlock(RegistryFile, HashBlock);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CmiAddSubKey(PREGISTRY_FILE RegistryFile,
+ PKEY_OBJECT Parent,
+ PKEY_OBJECT SubKey,
+ PWSTR NewSubKeyName,
+ USHORT NewSubKeyNameSize,
+ ULONG TitleIndex,
+ PUNICODE_STRING Class,
+ ULONG CreateOptions)
+{
+ PKEY_BLOCK KeyBlock = Parent->KeyBlock;
+ NTSTATUS Status;
+ PHASH_TABLE_BLOCK HashBlock, NewHashBlock;
+ PKEY_BLOCK NewKeyBlock;
+ BLOCK_OFFSET NKBOffset;
+ ULONG NewBlockSize;
+ USHORT NameSize;
+
+ if (NewSubKeyName[0] == L'\\')
+ {
+ NewSubKeyName++;
+ NameSize = NewSubKeyNameSize/2-1;
+ }
+ else
+ NameSize = NewSubKeyNameSize/2;
+ Status = STATUS_SUCCESS;
+
+ NewBlockSize = sizeof(KEY_BLOCK) + NameSize;
+ Status = CmiAllocateBlock(RegistryFile, (PVOID) &NewKeyBlock
+ , NewBlockSize,&NKBOffset);
+ if (NewKeyBlock == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NewKeyBlock->SubBlockId = REG_KEY_BLOCK_ID;
+ NewKeyBlock->Type = REG_KEY_BLOCK_TYPE;
+ ZwQuerySystemTime((PTIME) &NewKeyBlock->LastWriteTime);
+ NewKeyBlock->ParentKeyOffset = -1;
+ NewKeyBlock->NumberOfSubKeys = 0;
+ NewKeyBlock->HashTableOffset = -1;
+ NewKeyBlock->NumberOfValues = 0;
+ NewKeyBlock->ValuesOffset = -1;
+ NewKeyBlock->SecurityKeyOffset = -1;
+ NewKeyBlock->NameSize = NameSize;
+ wcstombs(NewKeyBlock->Name,NewSubKeyName,NameSize);
+ NewKeyBlock->ClassNameOffset = -1;
+ if (Class)
+ {
+ PDATA_BLOCK pClass;
+ NewKeyBlock->ClassSize = Class->Length+sizeof(WCHAR);
+ Status = CmiAllocateBlock(RegistryFile
+ ,(PVOID)&pClass
+ ,NewKeyBlock->ClassSize
+ ,&NewKeyBlock->ClassNameOffset );
+ wcsncpy((PWSTR)pClass->Data,Class->Buffer,Class->Length);
+ ( (PWSTR)(pClass->Data))[Class->Length]=0;
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ SubKey->KeyBlock = NewKeyBlock;
+ SubKey->BlockOffset = NKBOffset;
+ /* don't modify hash table if key is volatile and parent is not */
+ if (RegistryFile == CmiVolatileFile && Parent->RegistryFile != RegistryFile)
+ {
+ return Status;
+ }
+ if (KeyBlock->HashTableOffset == -1)
+ {
+ Status = CmiAllocateHashTableBlock(RegistryFile,
+ &HashBlock,
+ &KeyBlock->HashTableOffset,
+ REG_INIT_HASH_TABLE_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
+ if (KeyBlock->NumberOfSubKeys + 1 >= HashBlock->HashTableSize)
+ {
+ BLOCK_OFFSET HTOffset;
+
+ /* Reallocate the hash table block */
+ Status = CmiAllocateHashTableBlock(RegistryFile,
+ &NewHashBlock,
+ &HTOffset,
+ HashBlock->HashTableSize +
+ REG_EXTEND_HASH_TABLE_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ RtlZeroMemory(&NewHashBlock->Table[0],
+ sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize);
+ RtlCopyMemory(&NewHashBlock->Table[0],
+ &HashBlock->Table[0],
+ sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
+ CmiDestroyBlock(RegistryFile, HashBlock
+ , KeyBlock->HashTableOffset);
+ KeyBlock->HashTableOffset = HTOffset;
+ HashBlock = NewHashBlock;
+ }
+ }
+ Status = CmiAddKeyToHashTable(RegistryFile, HashBlock, NewKeyBlock,NKBOffset);
+ if (NT_SUCCESS(Status))
+ {
+ KeyBlock->NumberOfSubKeys++;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN PCHAR ValueName,
+ OUT PVALUE_BLOCK *ValueBlock,
+ OUT BLOCK_OFFSET *VBOffset)
+{
+ ULONG Idx;
+ PVALUE_LIST_BLOCK ValueListBlock;
+ PVALUE_BLOCK CurValueBlock;
+ ValueListBlock = CmiGetBlock(RegistryFile,
+ KeyBlock->ValuesOffset,NULL);
+ *ValueBlock = NULL;
+ if (ValueListBlock == NULL)
+ {
+ return STATUS_SUCCESS;
+ }
+ for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
+ {
+ CurValueBlock = CmiGetBlock(RegistryFile,
+ ValueListBlock->Values[Idx],NULL);
+ /* FIXME : perhaps we must not ignore case if NtCreateKey has not been */
+ /* called with OBJ_CASE_INSENSITIVE flag ? */
+ if (CurValueBlock != NULL &&
+ CurValueBlock->NameSize == strlen(ValueName) &&
+ !_strnicmp(CurValueBlock->Name, ValueName,strlen(ValueName)))
+ {
+ *ValueBlock = CurValueBlock;
+ if(VBOffset) *VBOffset = ValueListBlock->Values[Idx];
+ break;
+ }
+ CmiReleaseBlock(RegistryFile, CurValueBlock);
+ }
+
+ CmiReleaseBlock(RegistryFile, ValueListBlock);
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN ULONG Index,
+ OUT PVALUE_BLOCK *ValueBlock)
+{
+ PVALUE_LIST_BLOCK ValueListBlock;
+ PVALUE_BLOCK CurValueBlock;
+ ValueListBlock = CmiGetBlock(RegistryFile,
+ KeyBlock->ValuesOffset,NULL);
+ *ValueBlock = NULL;
+ if (ValueListBlock == NULL)
+ {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ if (Index >= KeyBlock->NumberOfValues)
+ {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ CurValueBlock = CmiGetBlock(RegistryFile,
+ ValueListBlock->Values[Index],NULL);
+ if (CurValueBlock != NULL)
+ {
+ *ValueBlock = CurValueBlock;
+ }
+ CmiReleaseBlock(RegistryFile, CurValueBlock);
+ CmiReleaseBlock(RegistryFile, ValueListBlock);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN PCHAR ValueNameBuf,
+ OUT PVALUE_BLOCK *pValueBlock,
+ OUT BLOCK_OFFSET *pVBOffset)
+{
+ NTSTATUS Status;
+ PVALUE_LIST_BLOCK ValueListBlock, NewValueListBlock;
+ BLOCK_OFFSET VBOffset;
+ BLOCK_OFFSET VLBOffset;
+ PVALUE_BLOCK NewValueBlock;
+
+ Status = CmiAllocateValueBlock(RegistryFile,
+ &NewValueBlock,
+ &VBOffset,
+ ValueNameBuf);
+ *pVBOffset=VBOffset;
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ ValueListBlock = CmiGetBlock(RegistryFile,
+ KeyBlock->ValuesOffset,NULL);
+ if (ValueListBlock == NULL)
+ {
+ Status = CmiAllocateBlock(RegistryFile,
+ (PVOID) &ValueListBlock,
+ sizeof(BLOCK_OFFSET) * 3,
+ &VLBOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ CmiDestroyValueBlock(RegistryFile,
+ NewValueBlock,VBOffset);
+ return Status;
+ }
+ KeyBlock->ValuesOffset = VLBOffset;
+ }
+ else if ( KeyBlock->NumberOfValues
+ >= -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET))
+ {
+ Status = CmiAllocateBlock(RegistryFile,
+ (PVOID) &NewValueListBlock,
+ sizeof(BLOCK_OFFSET) *
+ (KeyBlock->NumberOfValues +
+ REG_VALUE_LIST_BLOCK_MULTIPLE),&VLBOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ CmiDestroyValueBlock(RegistryFile,
+ NewValueBlock,VBOffset);
+ return Status;
+ }
+ RtlCopyMemory(&NewValueListBlock->Values[0],
+ &ValueListBlock->Values[0],
+ sizeof(BLOCK_OFFSET) * KeyBlock->NumberOfValues);
+ CmiDestroyBlock(RegistryFile, ValueListBlock,KeyBlock->ValuesOffset);
+ KeyBlock->ValuesOffset = VLBOffset;
+ ValueListBlock = NewValueListBlock;
+ }
+ ValueListBlock->Values[KeyBlock->NumberOfValues] = VBOffset;
+ KeyBlock->NumberOfValues++;
+ CmiReleaseBlock(RegistryFile, ValueListBlock);
+ CmiReleaseBlock(RegistryFile, NewValueBlock);
+ *pValueBlock = NewValueBlock;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
+ IN PKEY_BLOCK KeyBlock,
+ IN PCHAR ValueName)
+{
+ ULONG Idx;
+ PVALUE_LIST_BLOCK ValueListBlock;
+ PVALUE_BLOCK CurValueBlock;
+ PHEAP_BLOCK pHeap;
+
+ ValueListBlock = CmiGetBlock(RegistryFile,
+ KeyBlock->ValuesOffset,NULL);
+ if (ValueListBlock == 0)
+ {
+ return STATUS_SUCCESS;
+ }
+ for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
+ {
+ CurValueBlock = CmiGetBlock(RegistryFile,
+ ValueListBlock->Values[Idx],&pHeap);
+ if (CurValueBlock != NULL &&
+ CurValueBlock->NameSize == strlen(ValueName) &&
+ !memcmp(CurValueBlock->Name, ValueName,strlen(ValueName)))
+ {
+ if (KeyBlock->NumberOfValues - 1 < Idx)
+ {
+ RtlCopyMemory(&ValueListBlock->Values[Idx],
+ &ValueListBlock->Values[Idx + 1],
+ sizeof(BLOCK_OFFSET) *
+ (KeyBlock->NumberOfValues - 1 - Idx));
+ }
+ else
+ {
+ RtlZeroMemory(&ValueListBlock->Values[Idx],
+ sizeof(BLOCK_OFFSET));
+ }
+ KeyBlock->NumberOfValues -= 1;
+ CmiDestroyValueBlock(RegistryFile, CurValueBlock, ValueListBlock->Values[Idx]);
+ /* update time of heap */
+ ZwQuerySystemTime((PTIME) &pHeap->DateModified);
+
+ break;
+ }
+ CmiReleaseBlock(RegistryFile, CurValueBlock);
+ }
+
+ CmiReleaseBlock(RegistryFile, ValueListBlock);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile,
+ OUT PHASH_TABLE_BLOCK *HashBlock,
+ OUT BLOCK_OFFSET *HBOffset,
+ IN ULONG HashTableSize)
+{
+ NTSTATUS Status;
+ ULONG NewHashSize;
+ PHASH_TABLE_BLOCK NewHashBlock;
+
+ Status = STATUS_SUCCESS;
+ *HashBlock = NULL;
+ NewHashSize = sizeof(HASH_TABLE_BLOCK) +
+ (HashTableSize - 1) * sizeof(HASH_RECORD);
+ Status = CmiAllocateBlock(RegistryFile,
+ (PVOID*)&NewHashBlock,
+ NewHashSize,HBOffset);
+ if (NewHashBlock == NULL || !NT_SUCCESS(Status) )
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NewHashBlock->SubBlockId = REG_HASH_TABLE_BLOCK_ID;
+ NewHashBlock->HashTableSize = HashTableSize;
+ *HashBlock = NewHashBlock;
+ }
+
+ return Status;
+}
+
+PKEY_BLOCK
+CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile,
+ PHASH_TABLE_BLOCK HashBlock,
+ ULONG Index)
+{
+ PKEY_BLOCK KeyBlock;
+ BLOCK_OFFSET KeyOffset;
+
+ if( HashBlock == NULL)
+ return NULL;
+ if (RegistryFile->Filename == NULL)
+ {
+ KeyBlock = (PKEY_BLOCK) HashBlock->Table[Index].KeyOffset;
+ }
+ else
+ {
+ KeyOffset = HashBlock->Table[Index].KeyOffset;
+ KeyBlock = CmiGetBlock(RegistryFile,KeyOffset,NULL);
+ }
+ CmiLockBlock(RegistryFile, KeyBlock);
+
+ return KeyBlock;
+}
+
+NTSTATUS
+CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile,
+ PHASH_TABLE_BLOCK HashBlock,
+ PKEY_BLOCK NewKeyBlock,
+ BLOCK_OFFSET NKBOffset)
+{
+ ULONG i;
+
+ for (i = 0; i < HashBlock->HashTableSize; i++)
+ {
+ if (HashBlock->Table[i].KeyOffset == 0)
+ {
+ HashBlock->Table[i].KeyOffset = NKBOffset;
+ RtlCopyMemory(&HashBlock->Table[i].HashValue,
+ NewKeyBlock->Name,
+ 4);
+ return STATUS_SUCCESS;
+ }
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
+ PVALUE_BLOCK *ValueBlock,
+ BLOCK_OFFSET *VBOffset,
+ IN PCHAR ValueNameBuf)
+{
+ NTSTATUS Status;
+ ULONG NewValueSize;
+ PVALUE_BLOCK NewValueBlock;
+
+ Status = STATUS_SUCCESS;
+
+ NewValueSize = sizeof(VALUE_BLOCK) + strlen(ValueNameBuf);
+ Status = CmiAllocateBlock(RegistryFile,
+ (PVOID*)&NewValueBlock,
+ NewValueSize,VBOffset);
+ if (NewValueBlock == NULL || !NT_SUCCESS(Status))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NewValueBlock->SubBlockId = REG_VALUE_BLOCK_ID;
+ NewValueBlock->NameSize = strlen(ValueNameBuf);
+ memcpy(NewValueBlock->Name, ValueNameBuf,strlen(ValueNameBuf));
+ NewValueBlock->DataType = 0;
+ NewValueBlock->DataSize = 0;
+ NewValueBlock->DataOffset = 0xffffffff;
+ *ValueBlock = NewValueBlock;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile,
+ PVALUE_BLOCK ValueBlock, BLOCK_OFFSET VBOffset)
+{
+ NTSTATUS Status;
+ PHEAP_BLOCK pHeap;
+ PVOID pBlock;
+
+ /* first, release datas : */
+ if (ValueBlock->DataSize >0)
+ {
+ pBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,&pHeap);
+ Status = CmiDestroyBlock(RegistryFile, pBlock, ValueBlock->DataOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ /* update time of heap */
+ if(RegistryFile->Filename)
+ ZwQuerySystemTime((PTIME) &pHeap->DateModified);
+ }
+
+ Status = CmiDestroyBlock(RegistryFile, ValueBlock, VBOffset);
+ /* update time of heap */
+ if(RegistryFile->Filename && CmiGetBlock(RegistryFile, VBOffset,&pHeap))
+ ZwQuerySystemTime((PTIME) &pHeap->DateModified);
+ return Status;
+}
+
+NTSTATUS
+CmiAddHeap(PREGISTRY_FILE RegistryFile,PVOID *NewBlock,BLOCK_OFFSET *NewBlockOffset)
+{
+ PHEAP_BLOCK tmpHeap;
+ PHEAP_BLOCK * tmpBlockList;
+ PFREE_SUB_BLOCK tmpBlock;
+ tmpHeap=ExAllocatePool(PagedPool, REG_BLOCK_SIZE);
+ tmpHeap->BlockId = REG_HEAP_ID;
+ tmpHeap->BlockOffset = RegistryFile->FileSize - REG_BLOCK_SIZE;
+ RegistryFile->FileSize += REG_BLOCK_SIZE;
+ tmpHeap->BlockSize = REG_BLOCK_SIZE;
+ tmpHeap->Unused1 = 0;
+ ZwQuerySystemTime((PTIME) &tmpHeap->DateModified);
+ tmpHeap->Unused2 = 0;
+ /* increase size of list of blocks */
+ tmpBlockList=ExAllocatePool(NonPagedPool,
+ sizeof(PHEAP_BLOCK *) * (RegistryFile->BlockListSize +1));
+ if (tmpBlockList == NULL)
+ {
+ KeBugCheck(0);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ if(RegistryFile->BlockListSize > 0)
+ {
+ memcpy(tmpBlockList,RegistryFile->BlockList,
+ sizeof(PHEAP_BLOCK *)*(RegistryFile->BlockListSize ));
+ ExFreePool(RegistryFile->BlockList);
+ }
+ RegistryFile->BlockList = tmpBlockList;
+ RegistryFile->BlockList [RegistryFile->BlockListSize++] = tmpHeap;
+ /* initialize a free block in this heap : */
+ tmpBlock = (PFREE_SUB_BLOCK)((char *) tmpHeap + REG_HEAP_BLOCK_DATA_OFFSET);
+ tmpBlock-> SubBlockSize = (REG_BLOCK_SIZE - REG_HEAP_BLOCK_DATA_OFFSET) ;
+ *NewBlock = (PVOID)tmpBlock;
+ if (NewBlockOffset)
+ *NewBlockOffset = tmpHeap->BlockOffset + REG_HEAP_BLOCK_DATA_OFFSET;
+ /* FIXME : set first dword to block_offset of another free bloc */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CmiAllocateBlock(PREGISTRY_FILE RegistryFile,
+ PVOID *Block,
+ LONG BlockSize,
+ BLOCK_OFFSET * pBlockOffset)
+{
+ NTSTATUS Status;
+ PFREE_SUB_BLOCK NewBlock;
+ PHEAP_BLOCK pHeap;
+
+ Status = STATUS_SUCCESS;
+ /* round to 16 bytes multiple */
+ BlockSize = (BlockSize + sizeof(DWORD) + 15) & 0xfffffff0;
+
+ /* Handle volatile files first */
+ if (RegistryFile->Filename == NULL)
+ {
+ NewBlock = ExAllocatePool(NonPagedPool, BlockSize);
+ if (NewBlock == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ RtlZeroMemory(NewBlock, BlockSize);
+ NewBlock->SubBlockSize = BlockSize;
+ CmiLockBlock(RegistryFile, NewBlock);
+ *Block = NewBlock;
+ if (pBlockOffset) *pBlockOffset = (BLOCK_OFFSET)NewBlock;
+ }
+ }
+ else
+ {
+ int i;
+ /* first search in free blocks */
+ NewBlock = NULL;
+ for (i=0 ; i<RegistryFile->FreeListSize ; i++)
+ {
+ if(RegistryFile->FreeList[i]->SubBlockSize >=BlockSize)
+ {
+ NewBlock = RegistryFile->FreeList[i];
+ if(pBlockOffset)
+ *pBlockOffset = RegistryFile->FreeListOffset[i];
+ /* update time of heap */
+ if(RegistryFile->Filename
+ && CmiGetBlock(RegistryFile, RegistryFile->FreeListOffset[i],&pHeap))
+ ZwQuerySystemTime((PTIME) &pHeap->DateModified);
+ if( (i+1) <RegistryFile->FreeListSize)
+ {
+ memmove( &RegistryFile->FreeList[i]
+ ,&RegistryFile->FreeList[i+1]
+ ,sizeof(RegistryFile->FreeList[0])
+ *(RegistryFile->FreeListSize-i-1));
+ memmove( &RegistryFile->FreeListOffset[i]
+ ,&RegistryFile->FreeListOffset[i+1]
+ ,sizeof(RegistryFile->FreeListOffset[0])
+ *(RegistryFile->FreeListSize-i-1));
+ }
+ RegistryFile->FreeListSize--;
+ break;
+ }
+ }
+ /* need to extend hive file : */
+ if (NewBlock == NULL)
+ {
+ /* add a new block : */
+ Status = CmiAddHeap(RegistryFile, (PVOID *)&NewBlock , pBlockOffset);
+ }
+ if (NT_SUCCESS(Status))
+ {
+ *Block = NewBlock;
+ /* split the block in two parts */
+ if(NewBlock->SubBlockSize > BlockSize)
+ {
+ NewBlock = (PFREE_SUB_BLOCK)((char *)NewBlock+BlockSize);
+ NewBlock->SubBlockSize=((PFREE_SUB_BLOCK) (*Block))->SubBlockSize-BlockSize;
+ CmiAddFree(RegistryFile,NewBlock,*pBlockOffset+BlockSize);
+ }
+ else if(NewBlock->SubBlockSize < BlockSize)
+ return STATUS_UNSUCCESSFUL;
+ RtlZeroMemory(*Block, BlockSize);
+ ((PFREE_SUB_BLOCK)(*Block)) ->SubBlockSize = - BlockSize;
+ CmiLockBlock(RegistryFile, *Block);
+ }
+ }
+ return Status;
+}
+
+NTSTATUS
+CmiDestroyBlock(PREGISTRY_FILE RegistryFile,
+ PVOID Block,BLOCK_OFFSET Offset)
+{
+ NTSTATUS Status;
+ PHEAP_BLOCK pHeap;
+
+ Status = STATUS_SUCCESS;
+
+ if (RegistryFile->Filename == NULL)
+ {
+ CmiReleaseBlock(RegistryFile, Block);
+ ExFreePool(Block);
+ }
+ else
+ {
+ PFREE_SUB_BLOCK pFree = Block;
+ if (pFree->SubBlockSize <0)
+ pFree->SubBlockSize = -pFree->SubBlockSize;
+ CmiAddFree(RegistryFile,Block,Offset);
+ CmiReleaseBlock(RegistryFile, Block);
+ /* update time of heap */
+ if(RegistryFile->Filename && CmiGetBlock(RegistryFile, Offset,&pHeap))
+ ZwQuerySystemTime((PTIME) &pHeap->DateModified);
+ /* FIXME : set first dword to block_offset of another free bloc ? */
+ /* FIXME : concatenate with previous and next block if free */
+ }
+
+ return Status;
+}
+
+NTSTATUS
+CmiAddFree(PREGISTRY_FILE RegistryFile,
+ PFREE_SUB_BLOCK FreeBlock,BLOCK_OFFSET FreeOffset)
+{
+ PFREE_SUB_BLOCK *tmpList;
+ BLOCK_OFFSET *tmpListOffset;
+ int minInd,maxInd,medInd;
+ if( (RegistryFile->FreeListSize+1) > RegistryFile->FreeListMax)
+ {
+ tmpList=ExAllocatePool(PagedPool
+ ,sizeof(PFREE_SUB_BLOCK)*(RegistryFile->FreeListMax+32));
+ if (tmpList == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ tmpListOffset=ExAllocatePool(PagedPool
+ ,sizeof(BLOCK_OFFSET *)*(RegistryFile->FreeListMax+32));
+ if (tmpListOffset == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ if (RegistryFile->FreeListMax)
+ {
+ memcpy(tmpList,RegistryFile->FreeList
+ ,sizeof(PFREE_SUB_BLOCK)*(RegistryFile->FreeListMax));
+ memcpy(tmpListOffset,RegistryFile->FreeListOffset
+ ,sizeof(BLOCK_OFFSET *)*(RegistryFile->FreeListMax));
+ ExFreePool(RegistryFile->FreeList);
+ ExFreePool(RegistryFile->FreeListOffset);
+ }
+ RegistryFile->FreeList = tmpList;
+ RegistryFile->FreeListOffset = tmpListOffset;
+ RegistryFile->FreeListMax +=32;
+ }
+ /* add new offset to free list, maintening list in ascending order */
+ if ( RegistryFile->FreeListSize==0
+ || RegistryFile->FreeListOffset[RegistryFile->FreeListSize-1] < FreeOffset)
+ {
+ /* add to end of list : */
+ RegistryFile->FreeList[RegistryFile->FreeListSize] = FreeBlock;
+ RegistryFile->FreeListOffset[RegistryFile->FreeListSize ++] = FreeOffset;
+ }
+ else if (RegistryFile->FreeListOffset[0] > FreeOffset)
+ {
+ /* add to begin of list : */
+ memmove( &RegistryFile->FreeList[1],&RegistryFile->FreeList[0]
+ ,sizeof(RegistryFile->FreeList[0])*RegistryFile->FreeListSize);
+ memmove( &RegistryFile->FreeListOffset[1],&RegistryFile->FreeListOffset[0]
+ ,sizeof(RegistryFile->FreeListOffset[0])*RegistryFile->FreeListSize);
+ RegistryFile->FreeList[0] = FreeBlock;
+ RegistryFile->FreeListOffset[0] = FreeOffset;
+ RegistryFile->FreeListSize ++;
+ }
+ else
+ {
+ /* search where to insert : */
+ minInd=0;
+ maxInd=RegistryFile->FreeListSize-1;
+ while( (maxInd-minInd) >1)
+ {
+ medInd=(minInd+maxInd)/2;
+ if (RegistryFile->FreeListOffset[medInd] > FreeOffset)
+ maxInd=medInd;
+ else
+ minInd=medInd;
+ }
+ /* insert before maxInd : */
+ memmove( &RegistryFile->FreeList[maxInd+1],&RegistryFile->FreeList[maxInd]
+ ,sizeof(RegistryFile->FreeList[0])
+ *(RegistryFile->FreeListSize-minInd));
+ memmove( &RegistryFile->FreeListOffset[maxInd+1]
+ , &RegistryFile->FreeListOffset[maxInd]
+ , sizeof(RegistryFile->FreeListOffset[0])
+ *(RegistryFile->FreeListSize-minInd));
+ RegistryFile->FreeList[maxInd] = FreeBlock;
+ RegistryFile->FreeListOffset[maxInd] = FreeOffset;
+ RegistryFile->FreeListSize ++;
+ }
+ return STATUS_SUCCESS;
+}
+
+PVOID
+CmiGetBlock(PREGISTRY_FILE RegistryFile,
+ BLOCK_OFFSET BlockOffset,
+ OUT PHEAP_BLOCK * ppHeap)
+{
+ if( BlockOffset == 0 || BlockOffset == -1) return NULL;
+
+ if (RegistryFile->Filename == NULL)
+ {
+ return (PVOID)BlockOffset;
+ }
+ else
+ {
+ PHEAP_BLOCK pHeap;
+ pHeap = RegistryFile->BlockList[BlockOffset/4096];
+ if(ppHeap) *ppHeap = pHeap;
+ return ((char *)pHeap
+ +(BlockOffset - pHeap->BlockOffset));
+ }
+}
+
+void
+CmiLockBlock(PREGISTRY_FILE RegistryFile,
+ PVOID Block)
+{
+ if (RegistryFile->Filename != NULL)
+ {
+ /* FIXME : implement */
+ }
+}
+
+void
+CmiReleaseBlock(PREGISTRY_FILE RegistryFile,
+ PVOID Block)
+{
+ if (RegistryFile->Filename != NULL)
+ {
+ /* FIXME : implement */
+ }
+}
-/* $Id: registry.c,v 1.60 2001/06/01 17:12:33 ekohl Exp $
+/* $Id: registry.c,v 1.61 2001/06/14 21:05:07 jfilby Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* Created 22/05/98
*/
-#include <windows.h>
-#include <ddk/ntddk.h>
-#include <internal/config.h>
-#include <internal/ob.h>
-#include <limits.h>
-#include <string.h>
-#include <internal/pool.h>
-#include <internal/registry.h>
-
-#define NDEBUG
-#include <internal/debug.h>
-
-/* ----------------------------------------------------- Typedefs */
-
-#define REG_BLOCK_SIZE 4096
-#define REG_HEAP_BLOCK_DATA_OFFSET 32
-#define REG_HEAP_ID 0x6e696268
-#define REG_INIT_BLOCK_LIST_SIZE 32
-#define REG_INIT_HASH_TABLE_SIZE 3
-#define REG_EXTEND_HASH_TABLE_SIZE 4
-#define REG_VALUE_LIST_BLOCK_MULTIPLE 4
-#define REG_KEY_BLOCK_ID 0x6b6e
-#define REG_HASH_TABLE_BLOCK_ID 0x666c
-#define REG_VALUE_BLOCK_ID 0x6b76
-#define REG_KEY_BLOCK_TYPE 0x20
-#define REG_ROOT_KEY_BLOCK_TYPE 0x2c
+#include "cm.h"
#define REG_ROOT_KEY_NAME L"\\Registry"
#define REG_MACHINE_KEY_NAME L"\\Registry\\Machine"
#define SAM_REG_FILE L"\\SystemRoot\\System32\\Config\\SAM"
#define SEC_REG_FILE L"\\SystemRoot\\System32\\Config\\SECURITY"
-#define KO_MARKED_FOR_DELETE 0x00000001
-
-// BLOCK_OFFSET = offset in file after header block
-typedef DWORD BLOCK_OFFSET;
-
-/* header for registry hive file : */
-typedef struct _HEADER_BLOCK
-{
- ULONG BlockId; /* ="regf" */
- ULONG Version; /* file version ?*/
- ULONG VersionOld; /* file version ?*/
- FILETIME DateModified; /* please don't replace with LARGE_INTEGER !*/
- ULONG Unused3; /* registry format version ? */
- ULONG Unused4; /* registry format version ? */
- ULONG Unused5; /* registry format version ? */
- ULONG Unused6; /* registry format version ? */
- BLOCK_OFFSET RootKeyBlock;
- ULONG BlockSize;
- ULONG Unused7;
- WCHAR FileName[64]; /* end of file name */
- ULONG Unused8[83];
- ULONG Checksum;
-} HEADER_BLOCK, *PHEADER_BLOCK;
-
-typedef struct _HEAP_BLOCK
-{
- ULONG BlockId; /* = "hbin" */
- BLOCK_OFFSET BlockOffset; /* block offset of this heap */
- ULONG BlockSize; /* size in bytes, 4k multiple */
- ULONG Unused1;
- FILETIME DateModified; /* please don't replace with LARGE_INTEGER !*/
- ULONG Unused2;
-} HEAP_BLOCK, *PHEAP_BLOCK;
-
-// each sub_block begin with this struct :
-// in a free subblock, higher bit of SubBlockSize is set
-typedef struct _FREE_SUB_BLOCK
-{
- LONG SubBlockSize;/* <0 if used, >0 if free */
-} FREE_SUB_BLOCK, *PFREE_SUB_BLOCK;
-
-typedef struct _KEY_BLOCK
-{
- LONG SubBlockSize;
- USHORT SubBlockId;
- USHORT Type;
- FILETIME LastWriteTime; /* please don't replace with LARGE_INTEGER !*/
- ULONG UnUsed1;
- BLOCK_OFFSET ParentKeyOffset;
- ULONG NumberOfSubKeys;
- ULONG UnUsed2;
- BLOCK_OFFSET HashTableOffset;
- ULONG UnUsed3;
- ULONG NumberOfValues;
- BLOCK_OFFSET ValuesOffset;
- BLOCK_OFFSET SecurityKeyOffset;
- BLOCK_OFFSET ClassNameOffset;
- ULONG Unused4[5];
- USHORT NameSize;
- USHORT ClassSize; /* size of ClassName in bytes */
- UCHAR Name[0]; /* warning : not zero terminated */
-} KEY_BLOCK, *PKEY_BLOCK;
-
-// hash record :
-// HashValue=four letters of value's name
-typedef struct _HASH_RECORD
-{
- BLOCK_OFFSET KeyOffset;
- ULONG HashValue;
-} HASH_RECORD, *PHASH_RECORD;
-
-typedef struct _HASH_TABLE_BLOCK
-{
- LONG SubBlockSize;
- USHORT SubBlockId;
- USHORT HashTableSize;
- HASH_RECORD Table[0];
-} HASH_TABLE_BLOCK, *PHASH_TABLE_BLOCK;
-
-typedef struct _VALUE_LIST_BLOCK
-{
- LONG SubBlockSize;
- BLOCK_OFFSET Values[0];
-} VALUE_LIST_BLOCK, *PVALUE_LIST_BLOCK;
-
-typedef struct _VALUE_BLOCK
-{
- LONG SubBlockSize;
- USHORT SubBlockId; // "kv"
- USHORT NameSize; // length of Name
- LONG DataSize; // length of datas in the subblock pointed by DataOffset
- BLOCK_OFFSET DataOffset;// datas are here if high bit of DataSize is set
- ULONG DataType;
- USHORT Flags;
- USHORT Unused1;
- UCHAR Name[0]; /* warning : not zero terminated */
-} VALUE_BLOCK, *PVALUE_BLOCK;
-
-typedef struct _DATA_BLOCK
-{
- LONG SubBlockSize;
- UCHAR Data[0];
-} DATA_BLOCK, *PDATA_BLOCK;
-
-typedef struct _REGISTRY_FILE
-{
- PWSTR Filename;
- ULONG FileSize;
- PFILE_OBJECT FileObject;
- PHEADER_BLOCK HeaderBlock;
-// ULONG NumberOfBlocks;
- ULONG BlockListSize;
- PHEAP_BLOCK *BlockList;
- ULONG FreeListSize;
- ULONG FreeListMax;
- PFREE_SUB_BLOCK *FreeList;
- BLOCK_OFFSET *FreeListOffset;
-// KSPIN_LOCK RegLock;
- KSEMAPHORE RegSem;
-
-
-// NTSTATUS (*Extend)(ULONG NewSize);
-// PVOID (*Flush)(VOID);
-} REGISTRY_FILE, *PREGISTRY_FILE;
-
-/* Type defining the Object Manager Key Object */
-typedef struct _KEY_OBJECT
-{
- CSHORT Type;
- CSHORT Size;
-
- ULONG Flags;
- USHORT NameSize; // length of Name
- UCHAR *Name;
- PREGISTRY_FILE RegistryFile;
- BLOCK_OFFSET BlockOffset;
- PKEY_BLOCK KeyBlock;
- struct _KEY_OBJECT *ParentKey;
- ULONG NumberOfSubKeys; /* subkeys loaded in SubKeys */
- ULONG SizeOfSubKeys; /* space allocated in SubKeys */
- struct _KEY_OBJECT **SubKeys; /* list of subkeys loaded */
-} KEY_OBJECT, *PKEY_OBJECT;
-
/* ------------------------------------------------- File Statics */
POBJECT_TYPE CmiKeyType = NULL;
-static PREGISTRY_FILE CmiVolatileFile = NULL;
+PREGISTRY_FILE CmiVolatileFile = NULL;
+KSPIN_LOCK CmiKeyListLock;
+
static PKEY_OBJECT CmiRootKey = NULL;
static PKEY_OBJECT CmiMachineKey = NULL;
static PKEY_OBJECT CmiUserKey = NULL;
-static KSPIN_LOCK CmiKeyListLock;
static GENERIC_MAPPING CmiKeyMapping =
{KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS};
-/* ----------------------------------------- Forward Declarations */
-
-static NTSTATUS CmiObjectParse(PVOID ParsedObject,
- PVOID *NextObject,
- PUNICODE_STRING FullPath,
- PWSTR *Path,
- POBJECT_TYPE ObjectType,
- ULONG Attribute);
-static NTSTATUS CmiObjectCreate(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- struct _OBJECT_ATTRIBUTES* ObjectAttributes);
-
-static VOID CmiObjectDelete(PVOID DeletedObject);
-static VOID CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey);
-static NTSTATUS CmiRemoveKeyFromList(PKEY_OBJECT NewKey);
-static PKEY_OBJECT CmiScanKeyList(PKEY_OBJECT Parent,
- PCHAR KeyNameBuf,
- ULONG Attributes);
-static PREGISTRY_FILE CmiCreateRegistry(PWSTR Filename);
-static ULONG CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock);
-static ULONG CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock);
-static ULONG CmiGetMaxValueNameLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock);
-static ULONG CmiGetMaxValueDataLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock);
-static NTSTATUS CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- OUT PKEY_BLOCK *SubKeyBlock,
- OUT BLOCK_OFFSET *BlockOffset,
- IN PCHAR KeyName,
- IN ACCESS_MASK DesiredAccess,
- IN ULONG Attributes);
-static NTSTATUS CmiAddSubKey(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_OBJECT Parent,
- OUT PKEY_OBJECT SubKey,
- IN PWSTR NewSubKeyName,
- IN USHORT NewSubKeyNameSize,
- IN ULONG TitleIndex,
- IN PUNICODE_STRING Class,
- IN ULONG CreateOptions);
-static NTSTATUS CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN PCHAR ValueName,
- OUT PVALUE_BLOCK *ValueBlock,
- OUT BLOCK_OFFSET *VBOffset);
-static NTSTATUS CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN ULONG Index,
- OUT PVALUE_BLOCK *ValueBlock);
-static NTSTATUS CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN PCHAR ValueNameBuf,
- OUT PVALUE_BLOCK *pValueBlock,
- OUT BLOCK_OFFSET *pVBOffset);
-static NTSTATUS CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN PCHAR ValueName);
-static NTSTATUS CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile,
- OUT PHASH_TABLE_BLOCK *HashBlock,
- OUT BLOCK_OFFSET *HBOffset,
- IN ULONG HashTableSize);
-static PKEY_BLOCK CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile,
- PHASH_TABLE_BLOCK HashBlock,
- ULONG Index);
-static NTSTATUS CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile,
- PHASH_TABLE_BLOCK HashBlock,
- PKEY_BLOCK NewKeyBlock,
- BLOCK_OFFSET NKBOffset);
-static NTSTATUS CmiAllocateValueBlock(IN PREGISTRY_FILE RegistryFile,
- OUT PVALUE_BLOCK *ValueBlock,
- OUT BLOCK_OFFSET *VBOffset,
- IN PCHAR ValueNameBuf);
-static NTSTATUS CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile,
- PVALUE_BLOCK ValueBlock, BLOCK_OFFSET VBOffset);
-static NTSTATUS CmiAllocateBlock(PREGISTRY_FILE RegistryFile,
- PVOID *Block,
- LONG BlockSize,
- BLOCK_OFFSET * pBlockOffset);
-static NTSTATUS CmiDestroyBlock(PREGISTRY_FILE RegistryFile,
- PVOID Block,BLOCK_OFFSET Offset);
-static PVOID CmiGetBlock(PREGISTRY_FILE RegistryFile,
- BLOCK_OFFSET BlockOffset,
- OUT PHEAP_BLOCK * ppHeap);
-static VOID CmiLockBlock(PREGISTRY_FILE RegistryFile,
- PVOID Block);
-static VOID CmiReleaseBlock(PREGISTRY_FILE RegistryFile,
- PVOID Block);
-static NTSTATUS
-CmiAddFree(PREGISTRY_FILE RegistryFile,
- PFREE_SUB_BLOCK FreeBlock,BLOCK_OFFSET FreeOffset);
-
-/* --------------------------------------------- Public Interface */
VOID
CmInitializeRegistry(VOID)
DPRINT("CmShutdownRegistry()...\n");
}
-NTSTATUS STDCALL
-NtCreateKey(OUT PHANDLE KeyHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN ULONG TitleIndex,
- IN PUNICODE_STRING Class,
- IN ULONG CreateOptions,
- OUT PULONG Disposition)
-{
- NTSTATUS Status;
- PVOID Object;
- PKEY_OBJECT key;
- UNICODE_STRING RemainingPath;
- PWSTR end;
-// KIRQL OldIrql;
-
-// DPRINT("NtCreateKey (Name %wZ),KeyHandle=%x,Root=%x\n",
-// ObjectAttributes->ObjectName,KeyHandle
-// ,ObjectAttributes->RootDirectory);
- Status = ObFindObject(ObjectAttributes,&Object,&RemainingPath,CmiKeyType);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-DPRINT("RP=%wZ\n",&RemainingPath);
- if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] ==0))
- {
- /* Fail if the key has been deleted */
- if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
- {
- ObDereferenceObject(Object);
- return STATUS_UNSUCCESSFUL;
- }
- if (Disposition)
- *Disposition = REG_OPENED_EXISTING_KEY;
- Status = ObCreateHandle(PsGetCurrentProcess(),
- Object,
- DesiredAccess,
- FALSE,
- KeyHandle);
-DPRINT("Status=%x\n",Status);
- ObDereferenceObject(Object);
- return Status;
- }
- /* if RemainingPath contains \ : must return error */
- if((RemainingPath.Buffer[0])=='\\')
- end = wcschr((RemainingPath.Buffer)+1, '\\');
- else
- end = wcschr((RemainingPath.Buffer), '\\');
- if (end != NULL)
- {
- ObDereferenceObject(Object);
- return STATUS_UNSUCCESSFUL;
- }
- /* because NtCreateKey don't create tree */
-
-DPRINT("NCK %S parent=%x\n",RemainingPath.Buffer,Object);
- key = ObCreateObject(
- KeyHandle,
- DesiredAccess,
- NULL,
- CmiKeyType
- );
-
- if (key == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
- key->ParentKey = Object;
-// if ( (key->ParentKey ==NULL))
-// key->ParentKey = ObjectAttributes->RootDirectory;
- if (CreateOptions & REG_OPTION_VOLATILE)
- key->RegistryFile=CmiVolatileFile;
- else
- key->RegistryFile=key->ParentKey->RegistryFile;
- key->Flags = 0;
- key->NumberOfSubKeys = 0;
- key->SizeOfSubKeys = 0;
- key->SubKeys = NULL;
-// KeAcquireSpinLock(&key->RegistryFile->RegLock, &OldIrql);
- /* add key to subkeys of parent if needed */
- Status = CmiAddSubKey(key->RegistryFile,
- key->ParentKey,
- key,
- RemainingPath.Buffer,
- RemainingPath.Length,
- TitleIndex,
- Class,
- CreateOptions);
- key->Name = key->KeyBlock->Name;
- key->NameSize = key->KeyBlock->NameSize;
- if (key->RegistryFile == key->ParentKey->RegistryFile)
- {
- key->KeyBlock->ParentKeyOffset = key->ParentKey->BlockOffset;
- key->KeyBlock->SecurityKeyOffset = key->ParentKey->KeyBlock->SecurityKeyOffset;
- }
- else
- {
- key->KeyBlock->ParentKeyOffset = -1;
- key->KeyBlock->SecurityKeyOffset = -1;
- /* this key must rest in memory unless it is deleted */
- /* , or file is unloaded*/
- ObReferenceObjectByPointer(key,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
- }
- CmiAddKeyToList(key->ParentKey,key);
-// KeReleaseSpinLock(&key->RegistryFile->RegLock, OldIrql);
- ObDereferenceObject(key);
- ObDereferenceObject(Object);
- if (Disposition) *Disposition = REG_CREATED_NEW_KEY;
-
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS STDCALL
-NtDeleteKey(IN HANDLE KeyHandle)
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_WRITE,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Set the marked for delete bit in the key object */
- KeyObject->Flags |= KO_MARKED_FOR_DELETE;
-
- /* Dereference the object */
- ObDereferenceObject(KeyObject);
- if(KeyObject->RegistryFile != KeyObject->ParentKey->RegistryFile)
- ObDereferenceObject(KeyObject);
- /* close the handle */
- ObDeleteHandle(PsGetCurrentProcess(),KeyHandle);
- /* FIXME: I think that ObDeleteHandle should dereference the object */
- ObDereferenceObject(KeyObject);
-
-
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-STDCALL
-NtEnumerateKey (
- IN HANDLE KeyHandle,
- IN ULONG Index,
- IN KEY_INFORMATION_CLASS KeyInformationClass,
- OUT PVOID KeyInformation,
- IN ULONG Length,
- OUT PULONG ResultLength
- )
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PREGISTRY_FILE RegistryFile;
- PKEY_BLOCK KeyBlock, SubKeyBlock;
- PHASH_TABLE_BLOCK HashTableBlock;
- PKEY_BASIC_INFORMATION BasicInformation;
- PKEY_NODE_INFORMATION NodeInformation;
- PKEY_FULL_INFORMATION FullInformation;
- PDATA_BLOCK pClassData;
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_ENUMERATE_SUB_KEYS,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Get pointer to KeyBlock */
- KeyBlock = KeyObject->KeyBlock;
- RegistryFile = KeyObject->RegistryFile;
-
- /* Get pointer to SubKey */
- if(Index >= KeyBlock->NumberOfSubKeys)
- {
- if (RegistryFile == CmiVolatileFile)
- {
- ObDereferenceObject (KeyObject);
- return STATUS_NO_MORE_ENTRIES;
- }
- else
- {
- int i;
- PKEY_OBJECT CurKey=NULL;
- /* search volatile keys */
- for (i=0; i < KeyObject->NumberOfSubKeys; i++)
- {
- CurKey=KeyObject->SubKeys[i];
- if (CurKey->RegistryFile == CmiVolatileFile)
- {
- if ( Index-- == KeyObject->NumberOfSubKeys) break;
- }
- }
- if(Index >= KeyBlock->NumberOfSubKeys)
- {
- ObDereferenceObject (KeyObject);
- return STATUS_NO_MORE_ENTRIES;
- }
- SubKeyBlock = CurKey->KeyBlock;
- }
- }
- else
- {
- HashTableBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
- SubKeyBlock = CmiGetKeyFromHashByIndex(RegistryFile,
- HashTableBlock,
- Index);
- }
- if (SubKeyBlock == NULL)
- {
- ObDereferenceObject (KeyObject);
- return STATUS_NO_MORE_ENTRIES;
- }
-
- Status = STATUS_SUCCESS;
- switch (KeyInformationClass)
- {
- case KeyBasicInformation:
- /* Check size of buffer */
- if (Length < sizeof(KEY_BASIC_INFORMATION) +
- (SubKeyBlock->NameSize ) * sizeof(WCHAR))
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- /* Fill buffer with requested info */
- BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
- BasicInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime;
- BasicInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime;
- BasicInformation->TitleIndex = Index;
- BasicInformation->NameLength = (SubKeyBlock->NameSize ) * sizeof(WCHAR);
- mbstowcs(BasicInformation->Name,
- SubKeyBlock->Name,
- SubKeyBlock->NameSize*2);
-// BasicInformation->Name[SubKeyBlock->NameSize] = 0;
- *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
- SubKeyBlock->NameSize * sizeof(WCHAR);
- }
- break;
-
- case KeyNodeInformation:
- /* Check size of buffer */
- if (Length < sizeof(KEY_NODE_INFORMATION) +
- (SubKeyBlock->NameSize ) * sizeof(WCHAR) +
- (SubKeyBlock->ClassSize ))
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- /* Fill buffer with requested info */
- NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
- NodeInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime;
- NodeInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime;
- NodeInformation->TitleIndex = Index;
- NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
- SubKeyBlock->NameSize * sizeof(WCHAR);
- NodeInformation->ClassLength = SubKeyBlock->ClassSize;
- NodeInformation->NameLength = (SubKeyBlock->NameSize ) * sizeof(WCHAR);
- mbstowcs(NodeInformation->Name,
- SubKeyBlock->Name,
- SubKeyBlock->NameSize*2);
-// NodeInformation->Name[SubKeyBlock->NameSize] = 0;
- if (SubKeyBlock->ClassSize != 0)
- {
- pClassData=CmiGetBlock(KeyObject->RegistryFile
- ,SubKeyBlock->ClassNameOffset,NULL);
- wcsncpy(NodeInformation->Name + SubKeyBlock->NameSize ,
- (PWCHAR)pClassData->Data,
- SubKeyBlock->ClassSize);
- CmiReleaseBlock(RegistryFile, pClassData);
- }
- *ResultLength = sizeof(KEY_NODE_INFORMATION) +
- (SubKeyBlock->NameSize) * sizeof(WCHAR) +
- (SubKeyBlock->ClassSize );
- }
- break;
-
- case KeyFullInformation:
- /* check size of buffer */
- if (Length < sizeof(KEY_FULL_INFORMATION) +
- SubKeyBlock->ClassSize)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- /* fill buffer with requested info */
- FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
- FullInformation->LastWriteTime.u.LowPart = SubKeyBlock->LastWriteTime.dwLowDateTime;
- FullInformation->LastWriteTime.u.HighPart = SubKeyBlock->LastWriteTime.dwHighDateTime;
- FullInformation->TitleIndex = Index;
- FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
- sizeof(WCHAR);
- FullInformation->ClassLength = SubKeyBlock->ClassSize;
- FullInformation->SubKeys = SubKeyBlock->NumberOfSubKeys;
- FullInformation->MaxNameLen =
- CmiGetMaxNameLength(RegistryFile, SubKeyBlock);
- FullInformation->MaxClassLen =
- CmiGetMaxClassLength(RegistryFile, SubKeyBlock);
- FullInformation->Values = SubKeyBlock->NumberOfValues;
- FullInformation->MaxValueNameLen =
- CmiGetMaxValueNameLength(RegistryFile, SubKeyBlock);
- FullInformation->MaxValueDataLen =
- CmiGetMaxValueDataLength(RegistryFile, SubKeyBlock);
- if (SubKeyBlock->ClassSize != 0)
- {
- pClassData=CmiGetBlock(KeyObject->RegistryFile
- ,SubKeyBlock->ClassNameOffset,NULL);
- wcsncpy(FullInformation->Class,
- (PWCHAR)pClassData->Data,
- SubKeyBlock->ClassSize);
- CmiReleaseBlock(RegistryFile, pClassData);
- }
- *ResultLength = sizeof(KEY_FULL_INFORMATION) +
- SubKeyBlock->ClassSize ;
- }
- break;
- }
- CmiReleaseBlock(RegistryFile, SubKeyBlock);
- ObDereferenceObject (KeyObject);
-
- return Status;
-}
-
-
-NTSTATUS
-STDCALL
-NtEnumerateValueKey (
- IN HANDLE KeyHandle,
- IN ULONG Index,
- IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
- OUT PVOID KeyValueInformation,
- IN ULONG Length,
- OUT PULONG ResultLength
- )
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PREGISTRY_FILE RegistryFile;
- PKEY_BLOCK KeyBlock;
- PVALUE_BLOCK ValueBlock;
- PDATA_BLOCK DataBlock;
- PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
- PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
- PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
-
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_QUERY_VALUE,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Get pointer to KeyBlock */
- KeyBlock = KeyObject->KeyBlock;
- RegistryFile = KeyObject->RegistryFile;
-
- /* Get Value block of interest */
- Status = CmiGetValueFromKeyByIndex(RegistryFile,
- KeyBlock,
- Index,
- &ValueBlock);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(KeyObject);
- return Status;
- }
- else if (ValueBlock != NULL)
- {
- switch (KeyValueInformationClass)
- {
- case KeyValueBasicInformation:
- *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
- (ValueBlock->NameSize + 1) * sizeof(WCHAR);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
- KeyValueInformation;
- ValueBasicInformation->TitleIndex = 0;
- ValueBasicInformation->Type = ValueBlock->DataType;
- ValueBasicInformation->NameLength =
- (ValueBlock->NameSize + 1) * sizeof(WCHAR);
- mbstowcs(ValueBasicInformation->Name, ValueBlock->Name
- ,ValueBlock->NameSize*2);
- ValueBasicInformation->Name[ValueBlock->NameSize]=0;
- }
- break;
-
- case KeyValuePartialInformation:
- *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
- (ValueBlock->DataSize & LONG_MAX);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
- KeyValueInformation;
- ValuePartialInformation->TitleIndex = 0;
- ValuePartialInformation->Type = ValueBlock->DataType;
- ValuePartialInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
- if(ValueBlock->DataSize >0)
- {
- DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
- RtlCopyMemory(ValuePartialInformation->Data,
- DataBlock->Data,
- ValueBlock->DataSize & LONG_MAX);
- CmiReleaseBlock(RegistryFile, DataBlock);
- }
- else
- {
- RtlCopyMemory(ValuePartialInformation->Data,
- &ValueBlock->DataOffset,
- ValueBlock->DataSize & LONG_MAX);
- }
- DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
- }
- break;
-
- case KeyValueFullInformation:
- *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
- (ValueBlock->NameSize ) * sizeof(WCHAR) + (ValueBlock->DataSize & LONG_MAX);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
- KeyValueInformation;
- ValueFullInformation->TitleIndex = 0;
- ValueFullInformation->Type = ValueBlock->DataType;
- ValueFullInformation->DataOffset =
- (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation
- + (ValueBlock->NameSize ) * sizeof(WCHAR);
- ValueFullInformation->DataOffset =
- (ValueFullInformation->DataOffset +3) &0xfffffffc;
- ValueFullInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
- ValueFullInformation->NameLength =
- (ValueBlock->NameSize ) * sizeof(WCHAR);
- mbstowcs(ValueFullInformation->Name, ValueBlock->Name
- ,ValueBlock->NameSize*2);
- if(ValueBlock->DataSize >0)
- {
- DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
- RtlCopyMemory((char *)(ValueFullInformation)
- + ValueFullInformation->DataOffset,
- DataBlock->Data,
- ValueBlock->DataSize & LONG_MAX);
- CmiReleaseBlock(RegistryFile, DataBlock);
- }
- else
- {
- RtlCopyMemory((char *)(ValueFullInformation)
- + ValueFullInformation->DataOffset,
- &ValueBlock->DataOffset,
- ValueBlock->DataSize & LONG_MAX);
- }
- }
- break;
- }
- }
- else
- {
- Status = STATUS_UNSUCCESSFUL;
- }
- ObDereferenceObject(KeyObject);
-
- return Status;
-}
-
-
-NTSTATUS STDCALL
-NtFlushKey(IN HANDLE KeyHandle)
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PREGISTRY_FILE RegistryFile;
- WCHAR LogName[MAX_PATH];
- HANDLE FileHandle;
-// HANDLE FileHandleLog;
- OBJECT_ATTRIBUTES ObjectAttributes;
-// KIRQL OldIrql;
- UNICODE_STRING TmpFileName;
- int i;
- LARGE_INTEGER fileOffset;
- DWORD * pEntDword;
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_QUERY_VALUE,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- RegistryFile = KeyObject->RegistryFile;
-// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
- /* then write changed blocks in .log */
- wcscpy(LogName,RegistryFile->Filename );
- wcscat(LogName,L".log");
- RtlInitUnicodeString (&TmpFileName, LogName);
- InitializeObjectAttributes(&ObjectAttributes,
- &TmpFileName,
- 0,
- NULL,
- NULL);
-/* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
- so we can't create log file
- Status = ZwCreateFile(&FileHandleLog,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- NULL, 0, FILE_ATTRIBUTE_NORMAL,
- 0, FILE_SUPERSEDE, 0, NULL, 0);
- Status = ZwWriteFile(FileHandleLog,
- 0, 0, 0, 0,
- RegistryFile->HeaderBlock,
- sizeof(HEADER_BLOCK),
- 0, 0);
- for (i=0; i < RegistryFile->BlockListSize ; i++)
- {
- if( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
- > RegistryFile->HeaderBlock->DateModified.dwHighDateTime
- ||( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
- == RegistryFile->HeaderBlock->DateModified.dwHighDateTime
- && RegistryFile->BlockList[i]->DateModified.dwLowDateTime
- > RegistryFile->HeaderBlock->DateModified.dwLowDateTime)
- )
- Status = ZwWriteFile(FileHandleLog,
- 0, 0, 0, 0,
- RegistryFile->BlockList[i],
- RegistryFile->BlockList[i]->BlockSize ,
- 0, 0);
- }
- ZwClose(FileHandleLog);
-END FIXME*/
- /* update header of registryfile with Version >VersionOld */
- /* this allow recover if system crash while updating hove file */
- RtlInitUnicodeString (&TmpFileName, RegistryFile->Filename);
- InitializeObjectAttributes(&ObjectAttributes,
- &TmpFileName,
- 0,
- NULL,
- NULL);
- Status = NtOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- NULL, 0, 0);
- RegistryFile->HeaderBlock->Version++;
-
- Status = ZwWriteFile(FileHandle,
- 0, 0, 0, 0,
- RegistryFile->HeaderBlock,
- sizeof(HEADER_BLOCK),
- 0, 0);
-
- /* update changed blocks in file */
- fileOffset.u.HighPart = 0;
- for (i=0; i < RegistryFile->BlockListSize ; i++)
- {
- if( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
- > RegistryFile->HeaderBlock->DateModified.dwHighDateTime
- ||( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
- == RegistryFile->HeaderBlock->DateModified.dwHighDateTime
- && RegistryFile->BlockList[i]->DateModified.dwLowDateTime
- > RegistryFile->HeaderBlock->DateModified.dwLowDateTime)
- )
- {
- fileOffset.u.LowPart = RegistryFile->BlockList[i]->BlockOffset+4096;
- Status = NtWriteFile(FileHandle,
- 0, 0, 0, 0,
- RegistryFile->BlockList[i],
- RegistryFile->BlockList[i]->BlockSize ,
- &fileOffset, 0);
- }
- }
- /* change version in header */
- RegistryFile->HeaderBlock->VersionOld = RegistryFile->HeaderBlock->Version;
- ZwQuerySystemTime((PTIME) &RegistryFile->HeaderBlock->DateModified);
- /* calculate checksum */
- RegistryFile->HeaderBlock->Checksum = 0;
- pEntDword = (DWORD *) RegistryFile->HeaderBlock;
- for (i=0 ; i <127 ; i++)
- {
- RegistryFile->HeaderBlock->Checksum ^= pEntDword[i];
- }
- /* write new header */
- fileOffset.u.LowPart = 0;
- Status = ZwWriteFile(FileHandle,
- 0, 0, 0, 0,
- RegistryFile->HeaderBlock,
- sizeof(HEADER_BLOCK),
- &fileOffset, 0);
- ZwClose(FileHandle);
-// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS STDCALL
-NtOpenKey(OUT PHANDLE KeyHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
-{
- NTSTATUS Status;
- PVOID Object;
- UNICODE_STRING RemainingPath;
-
- RemainingPath.Buffer=NULL;
- Status = ObFindObject(ObjectAttributes,&Object,&RemainingPath,CmiKeyType);
-DPRINT("NTOpenKey : after ObFindObject\n");
-DPRINT("RB.B=%x\n",RemainingPath.Buffer);
- if(RemainingPath.Buffer != 0 && RemainingPath.Buffer[0] !=0)
- {
-DPRINT("NTOpenKey3 : after ObFindObject\n");
- ObDereferenceObject(Object);
-DPRINT("RP=%wZ\n",&RemainingPath);
- return STATUS_UNSUCCESSFUL;
- }
-DPRINT("NTOpenKey2 : after ObFindObject\n");
- /* Fail if the key has been deleted */
- if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
- {
- ObDereferenceObject(Object);
- return STATUS_UNSUCCESSFUL;
- }
-
- Status = ObCreateHandle(
- PsGetCurrentProcess(),
- Object,
- DesiredAccess,
- FALSE,
- KeyHandle
- );
- ObDereferenceObject(Object);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-STDCALL
-NtQueryKey (
- IN HANDLE KeyHandle,
- IN KEY_INFORMATION_CLASS KeyInformationClass,
- OUT PVOID KeyInformation,
- IN ULONG Length,
- OUT PULONG ResultLength
- )
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PREGISTRY_FILE RegistryFile;
- PKEY_BLOCK KeyBlock;
- PKEY_BASIC_INFORMATION BasicInformation;
- PKEY_NODE_INFORMATION NodeInformation;
- PKEY_FULL_INFORMATION FullInformation;
- PDATA_BLOCK pClassData;
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_READ,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Get pointer to KeyBlock */
- KeyBlock = KeyObject->KeyBlock;
- RegistryFile = KeyObject->RegistryFile;
-
- Status = STATUS_SUCCESS;
- switch (KeyInformationClass)
- {
- case KeyBasicInformation:
- /* Check size of buffer */
- if (Length < sizeof(KEY_BASIC_INFORMATION) +
- KeyObject->NameSize * sizeof(WCHAR))
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- /* Fill buffer with requested info */
- BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
- BasicInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime;
- BasicInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime;
- BasicInformation->TitleIndex = 0;
- BasicInformation->NameLength =
- (KeyObject->NameSize ) * sizeof(WCHAR);
- mbstowcs(BasicInformation->Name,
- KeyObject->Name,
- KeyObject->NameSize*sizeof(WCHAR));
- *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
- KeyObject->NameSize * sizeof(WCHAR);
- }
- break;
-
- case KeyNodeInformation:
- /* Check size of buffer */
- if (Length < sizeof(KEY_NODE_INFORMATION) +
- (KeyObject->NameSize ) * sizeof(WCHAR) +
- KeyBlock->ClassSize )
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- /* Fill buffer with requested info */
- NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
- NodeInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime;
- NodeInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime;
- NodeInformation->TitleIndex = 0;
- NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
- KeyObject->NameSize * sizeof(WCHAR);
- NodeInformation->ClassLength = KeyBlock->ClassSize;
- NodeInformation->NameLength =
- (KeyObject->NameSize ) * sizeof(WCHAR);
- mbstowcs(NodeInformation->Name,
- KeyObject->Name,
- KeyObject->NameSize*2);
- if (KeyBlock->ClassSize != 0)
- {
- pClassData=CmiGetBlock(KeyObject->RegistryFile
- ,KeyBlock->ClassNameOffset,NULL);
- wcsncpy(NodeInformation->Name + (KeyObject->NameSize )*sizeof(WCHAR),
- (PWCHAR)pClassData->Data,
- KeyBlock->ClassSize);
- CmiReleaseBlock(RegistryFile, pClassData);
- }
- *ResultLength = sizeof(KEY_NODE_INFORMATION) +
- (KeyObject->NameSize ) * sizeof(WCHAR) +
- KeyBlock->ClassSize;
- }
- break;
-
- case KeyFullInformation:
- /* Check size of buffer */
- if (Length < sizeof(KEY_FULL_INFORMATION) +
- KeyBlock->ClassSize )
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- /* Fill buffer with requested info */
- FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
- FullInformation->LastWriteTime.u.LowPart = KeyBlock->LastWriteTime.dwLowDateTime;
- FullInformation->LastWriteTime.u.HighPart = KeyBlock->LastWriteTime.dwHighDateTime;
- FullInformation->TitleIndex = 0;
- FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
- sizeof(WCHAR);
- FullInformation->ClassLength = KeyBlock->ClassSize;
- FullInformation->SubKeys = KeyBlock->NumberOfSubKeys;
- FullInformation->MaxNameLen =
- CmiGetMaxNameLength(RegistryFile, KeyBlock);
- FullInformation->MaxClassLen =
- CmiGetMaxClassLength(RegistryFile, KeyBlock);
- FullInformation->Values = KeyBlock->NumberOfValues;
- FullInformation->MaxValueNameLen =
- CmiGetMaxValueNameLength(RegistryFile, KeyBlock);
- FullInformation->MaxValueDataLen =
- CmiGetMaxValueDataLength(RegistryFile, KeyBlock);
- if (KeyBlock->ClassSize != 0)
- {
- pClassData=CmiGetBlock(KeyObject->RegistryFile
- ,KeyBlock->ClassNameOffset,NULL);
- wcsncpy(FullInformation->Class,
- (PWCHAR)pClassData->Data,
- KeyBlock->ClassSize);
- CmiReleaseBlock(RegistryFile, pClassData);
- }
- *ResultLength = sizeof(KEY_FULL_INFORMATION) +
- KeyBlock->ClassSize ;
- }
- break;
- }
- ObDereferenceObject (KeyObject);
-
- return Status;
-}
-
-
-NTSTATUS
-STDCALL
-NtQueryValueKey (
- IN HANDLE KeyHandle,
- IN PUNICODE_STRING ValueName,
- IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
- OUT PVOID KeyValueInformation,
- IN ULONG Length,
- OUT PULONG ResultLength
- )
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PREGISTRY_FILE RegistryFile;
- PKEY_BLOCK KeyBlock;
- PVALUE_BLOCK ValueBlock;
- PDATA_BLOCK DataBlock;
- PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
- PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
- PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
- char ValueName2[MAX_PATH];
-
- wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
- ValueName2[ValueName->Length>>1]=0;
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_QUERY_VALUE,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Get pointer to KeyBlock */
- KeyBlock = KeyObject->KeyBlock;
- RegistryFile = KeyObject->RegistryFile;
- /* Get Value block of interest */
- Status = CmiScanKeyForValue(RegistryFile,
- KeyBlock,
- ValueName2,
- &ValueBlock,NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(KeyObject);
- return Status;
- }
- else if (ValueBlock != NULL)
- {
- switch (KeyValueInformationClass)
- {
- case KeyValueBasicInformation:
- *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
- ValueBlock->NameSize * sizeof(WCHAR);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
- KeyValueInformation;
- ValueBasicInformation->TitleIndex = 0;
- ValueBasicInformation->Type = ValueBlock->DataType;
- ValueBasicInformation->NameLength =
- (ValueBlock->NameSize + 1) * sizeof(WCHAR);
- mbstowcs(ValueBasicInformation->Name, ValueBlock->Name,ValueBlock->NameSize*2);
- ValueBasicInformation->Name[ValueBlock->NameSize]=0;
- }
- break;
-
- case KeyValuePartialInformation:
- *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
- (ValueBlock->DataSize & LONG_MAX);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
- KeyValueInformation;
- ValuePartialInformation->TitleIndex = 0;
- ValuePartialInformation->Type = ValueBlock->DataType;
- ValuePartialInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
- if(ValueBlock->DataSize >0)
- {
- DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
- RtlCopyMemory(ValuePartialInformation->Data,
- DataBlock->Data,
- ValueBlock->DataSize & LONG_MAX);
- CmiReleaseBlock(RegistryFile, DataBlock);
- }
- else
- {
- RtlCopyMemory(ValuePartialInformation->Data,
- &ValueBlock->DataOffset,
- ValueBlock->DataSize & LONG_MAX);
- }
- }
- break;
-
- case KeyValueFullInformation:
- *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)
- + (ValueBlock->NameSize -1) * sizeof(WCHAR)
- + (ValueBlock->DataSize & LONG_MAX);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
- KeyValueInformation;
- ValueFullInformation->TitleIndex = 0;
- ValueFullInformation->Type = ValueBlock->DataType;
- ValueFullInformation->DataOffset =
- (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation
- + (ValueBlock->NameSize ) * sizeof(WCHAR);
- ValueFullInformation->DataOffset =
- (ValueFullInformation->DataOffset +3) &0xfffffffc;
- ValueFullInformation->DataLength = ValueBlock->DataSize & LONG_MAX;
- ValueFullInformation->NameLength =
- (ValueBlock->NameSize ) * sizeof(WCHAR);
- mbstowcs(ValueFullInformation->Name, ValueBlock->Name,ValueBlock->NameSize*2);
- if(ValueBlock->DataSize >0)
- {
- DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL);
- RtlCopyMemory((char *)(ValueFullInformation)
- + ValueFullInformation->DataOffset,
- DataBlock->Data,
- ValueBlock->DataSize & LONG_MAX);
- CmiReleaseBlock(RegistryFile, DataBlock);
- }
- else
- {
- RtlCopyMemory((char *)(ValueFullInformation)
- + ValueFullInformation->DataOffset,
- &ValueBlock->DataOffset,
- ValueBlock->DataSize & LONG_MAX);
- }
- }
- break;
- }
- }
- else
- {
- Status = STATUS_UNSUCCESSFUL;
- }
- ObDereferenceObject(KeyObject);
-
- return Status;
-}
-
-
-NTSTATUS
-STDCALL
-NtSetValueKey (
- IN HANDLE KeyHandle,
- IN PUNICODE_STRING ValueName,
- IN ULONG TitleIndex,
- IN ULONG Type,
- IN PVOID Data,
- IN ULONG DataSize
- )
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PREGISTRY_FILE RegistryFile;
- PKEY_BLOCK KeyBlock;
- PVALUE_BLOCK ValueBlock;
- BLOCK_OFFSET VBOffset;
- char ValueName2[MAX_PATH];
- PDATA_BLOCK DataBlock, NewDataBlock;
- PHEAP_BLOCK pHeap;
-// KIRQL OldIrql;
-
- wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
- ValueName2[ValueName->Length>>1]=0;
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_SET_VALUE,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- return Status;
-
- /* Get pointer to KeyBlock */
- KeyBlock = KeyObject->KeyBlock;
- RegistryFile = KeyObject->RegistryFile;
- Status = CmiScanKeyForValue(RegistryFile,
- KeyBlock,
- ValueName2,
- &ValueBlock, &VBOffset);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject (KeyObject);
- return Status;
- }
-// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
- if (ValueBlock == NULL)
- {
- Status = CmiAddValueToKey(RegistryFile,
- KeyBlock,
- ValueName2,
- &ValueBlock,
- &VBOffset);
- }
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject (KeyObject);
- return Status;
- }
- else
- {
- /* FIXME if datasize <=4 then write in valueblock directly */
- if (DataSize <= 4)
- {
- if (( ValueBlock->DataSize <0 )
- && (DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL)))
- {
- CmiDestroyBlock(RegistryFile, DataBlock, ValueBlock->DataOffset);
- }
- RtlCopyMemory(&ValueBlock->DataOffset, Data, DataSize);
- ValueBlock->DataSize = DataSize | 0x80000000;
- ValueBlock->DataType = Type;
- memcpy(&ValueBlock->DataOffset, Data, DataSize);
- }
- /* If new data size is <= current then overwrite current data */
- else if (DataSize <= (ValueBlock->DataSize & 0x7fffffff))
- {
- DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,&pHeap);
- RtlCopyMemory(DataBlock->Data, Data, DataSize);
- ValueBlock->DataSize = DataSize;
- ValueBlock->DataType = Type;
- CmiReleaseBlock(RegistryFile, DataBlock);
- /* update time of heap */
- if(RegistryFile->Filename)
- ZwQuerySystemTime((PTIME) &pHeap->DateModified);
- }
- else
- {
- BLOCK_OFFSET NewOffset;
- /* Destroy current data block and allocate a new one */
- if (( ValueBlock->DataSize <0 )
- && (DataBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,NULL)))
- {
- CmiDestroyBlock(RegistryFile, DataBlock, ValueBlock->DataOffset);
- }
- Status = CmiAllocateBlock(RegistryFile,
- (PVOID *)&NewDataBlock,
- DataSize,&NewOffset);
- RtlCopyMemory(&NewDataBlock->Data[0], Data, DataSize);
- ValueBlock->DataSize = DataSize;
- ValueBlock->DataType = Type;
- CmiReleaseBlock(RegistryFile, NewDataBlock);
- ValueBlock->DataOffset = NewOffset;
- }
- /* update time of heap */
- if(RegistryFile->Filename && CmiGetBlock(RegistryFile, VBOffset,&pHeap))
- ZwQuerySystemTime((PTIME) &pHeap->DateModified);
-
- }
-// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
- ObDereferenceObject (KeyObject);
-
- return Status;
-}
-
-NTSTATUS
-STDCALL
-NtDeleteValueKey (
- IN HANDLE KeyHandle,
- IN PUNICODE_STRING ValueName
- )
-{
- NTSTATUS Status;
- PKEY_OBJECT KeyObject;
- PREGISTRY_FILE RegistryFile;
- PKEY_BLOCK KeyBlock;
- char ValueName2[MAX_PATH];
-// KIRQL OldIrql;
-
- wcstombs(ValueName2,ValueName->Buffer,ValueName->Length>>1);
- ValueName2[ValueName->Length>>1]=0;
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_QUERY_VALUE,
- CmiKeyType,
- UserMode,
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Get pointer to KeyBlock */
- KeyBlock = KeyObject->KeyBlock;
- RegistryFile = KeyObject->RegistryFile;
-// KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
- Status = CmiDeleteValueFromKey(RegistryFile,
- KeyBlock,
- ValueName2);
-// KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
- ObDereferenceObject(KeyObject);
-
- return Status;
-}
-
-NTSTATUS
-STDCALL
-NtLoadKey (
- PHANDLE KeyHandle,
- POBJECT_ATTRIBUTES ObjectAttributes
- )
-{
- return NtLoadKey2(KeyHandle,
- ObjectAttributes,
- 0);
-}
-
-
-NTSTATUS
-STDCALL
-NtLoadKey2 (
- PHANDLE KeyHandle,
- POBJECT_ATTRIBUTES ObjectAttributes,
- ULONG Unknown3
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtNotifyChangeKey (
- IN HANDLE KeyHandle,
- IN HANDLE Event,
- IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
- IN PVOID ApcContext OPTIONAL,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN ULONG CompletionFilter,
- IN BOOLEAN Asynchroneous,
- OUT PVOID ChangeBuffer,
- IN ULONG Length,
- IN BOOLEAN WatchSubtree
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtQueryMultipleValueKey (
- IN HANDLE KeyHandle,
- IN PWVALENT ListOfValuesToQuery,
- IN ULONG NumberOfItems,
- OUT PVOID MultipleValueInformation,
- IN ULONG Length,
- OUT PULONG ReturnLength
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtReplaceKey (
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN HANDLE Key,
- IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtRestoreKey (
- IN HANDLE KeyHandle,
- IN HANDLE FileHandle,
- IN ULONG RestoreFlags
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtSaveKey (
- IN HANDLE KeyHandle,
- IN HANDLE FileHandle
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtSetInformationKey (
- IN HANDLE KeyHandle,
- IN CINT KeyInformationClass,
- IN PVOID KeyInformation,
- IN ULONG KeyInformationLength
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtUnloadKey (
- HANDLE KeyHandle
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-NtInitializeRegistry (
- BOOLEAN SetUpBoot
- )
-{
-// UNIMPLEMENTED;
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS STDCALL
-RtlCheckRegistryKey(IN ULONG RelativeTo,
- IN PWSTR Path)
-{
- HANDLE KeyHandle;
- NTSTATUS Status;
-
- Status = RtlpGetRegistryHandle(RelativeTo,
- Path,
- FALSE,
- &KeyHandle);
- if (!NT_SUCCESS(Status))
- return Status;
-
- NtClose(KeyHandle);
-
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-STDCALL
-RtlCreateRegistryKey (
- IN ULONG RelativeTo,
- IN PWSTR Path
- )
-{
- HANDLE KeyHandle;
- NTSTATUS Status;
-
- Status = RtlpGetRegistryHandle(RelativeTo,
- Path,
- TRUE,
- &KeyHandle);
- if (!NT_SUCCESS(Status))
- return Status;
-
- NtClose(KeyHandle);
-
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-STDCALL
-RtlDeleteRegistryValue (
- IN ULONG RelativeTo,
- IN PWSTR Path,
- IN PWSTR ValueName
- )
-{
- HANDLE KeyHandle;
- NTSTATUS Status;
- UNICODE_STRING Name;
-
- Status = RtlpGetRegistryHandle(RelativeTo,
- Path,
- TRUE,
- &KeyHandle);
- if (!NT_SUCCESS(Status))
- return Status;
-
- RtlInitUnicodeString(&Name,
- ValueName);
-
- NtDeleteValueKey(KeyHandle,
- &Name);
-
- NtClose(KeyHandle);
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDCALL
-RtlQueryRegistryValues (
- IN ULONG RelativeTo,
- IN PWSTR Path,
- IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
- IN PVOID Context,
- IN PVOID Environment
- )
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS
-STDCALL
-RtlWriteRegistryValue (
- IN ULONG RelativeTo,
- IN PWSTR Path,
- IN PWSTR ValueName,
- IN ULONG ValueType,
- IN PVOID ValueData,
- IN ULONG ValueLength
- )
-{
- HANDLE KeyHandle;
- NTSTATUS Status;
- UNICODE_STRING Name;
-
- Status = RtlpGetRegistryHandle(RelativeTo,
- Path,
- TRUE,
- &KeyHandle);
- if (!NT_SUCCESS(Status))
- return Status;
-
- RtlInitUnicodeString(&Name,
- ValueName);
-
- NtSetValueKey(KeyHandle,
- &Name,
- 0,
- ValueType,
- ValueData,
- ValueLength);
-
- NtClose(KeyHandle);
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS STDCALL
-RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath)
-{
- return STATUS_UNSUCCESSFUL;
-}
-
-/* ------------------------------------------ Private Implementation */
-
-
-NTSTATUS
-RtlpGetRegistryHandle(ULONG RelativeTo,
- PWSTR Path,
- BOOLEAN Create,
- PHANDLE KeyHandle)
-{
- UNICODE_STRING KeyName;
- WCHAR KeyBuffer[MAX_PATH];
- OBJECT_ATTRIBUTES ObjectAttributes;
- NTSTATUS Status;
-
- if (RelativeTo & RTL_REGISTRY_HANDLE)
- {
- *KeyHandle = (HANDLE)Path;
- return STATUS_SUCCESS;
- }
-
- if (RelativeTo & RTL_REGISTRY_OPTIONAL)
- RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
-
- if (RelativeTo >= RTL_REGISTRY_MAXIMUM)
- return STATUS_INVALID_PARAMETER;
-
- KeyName.Length = 0;
- KeyName.MaximumLength = MAX_PATH;
- KeyName.Buffer = KeyBuffer;
- KeyBuffer[0] = 0;
-
- switch (RelativeTo)
- {
- case RTL_REGISTRY_SERVICES:
- RtlAppendUnicodeToString(&KeyName,
- L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
- break;
-
- case RTL_REGISTRY_CONTROL:
- RtlAppendUnicodeToString(&KeyName,
- L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\");
- break;
-
- case RTL_REGISTRY_WINDOWS_NT:
- RtlAppendUnicodeToString(&KeyName,
- L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
- break;
-
- case RTL_REGISTRY_DEVICEMAP:
- RtlAppendUnicodeToString(&KeyName,
- L"\\Registry\\Machine\\Hardware\\DeviceMap\\");
- break;
-
- case RTL_REGISTRY_USER:
- Status = RtlFormatCurrentUserKeyPath(&KeyName);
- if (!NT_SUCCESS(Status))
- return Status;
- break;
- }
-
- if (Path[0] != L'\\')
- RtlAppendUnicodeToString(&KeyName,
- L"\\");
-
- RtlAppendUnicodeToString(&KeyName,
- Path);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- if (Create == TRUE)
- {
- Status = NtCreateKey(KeyHandle,
- KEY_ALL_ACCESS,
- &ObjectAttributes,
- 0,
- NULL,
- 0,
- NULL);
- }
- else
- {
- Status = NtOpenKey(KeyHandle,
- KEY_ALL_ACCESS,
- &ObjectAttributes);
- }
-
- return Status;
-}
-
-static NTSTATUS CmiObjectParse(PVOID ParsedObject,
- PVOID *NextObject,
- PUNICODE_STRING FullPath,
- PWSTR *Path,
- POBJECT_TYPE ObjectType,
- ULONG Attributes)
-{
- CHAR cPath[MAX_PATH];
- PWSTR end;
- PKEY_OBJECT FoundObject;
- PKEY_OBJECT ParsedKey=ParsedObject;
- PKEY_BLOCK SubKeyBlock;
- BLOCK_OFFSET BlockOffset;
- NTSTATUS Status;
- *NextObject = NULL;
- if ((*Path) == NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- if((*Path[0])=='\\')
- {
- end = wcschr((*Path)+1, '\\');
- if (end != NULL)
- *end = 0;
- wcstombs(cPath,(*Path)+1,wcslen((*Path)+1));
- cPath[wcslen( (*Path)+1)]=0;
- }
- else
- {
- end = wcschr((*Path), '\\');
- if (end != NULL)
- *end = 0;
- wcstombs(cPath,(*Path),wcslen((*Path)));
- cPath[wcslen( (*Path))]=0;
- }
-
- FoundObject = CmiScanKeyList(ParsedKey,cPath,Attributes);
- if (FoundObject == NULL)
- {
- Status = CmiScanForSubKey(ParsedKey->RegistryFile,
- ParsedKey->KeyBlock,
- &SubKeyBlock,
- &BlockOffset,
- cPath,
- 0,
- Attributes);
- if(!NT_SUCCESS(Status) || SubKeyBlock == NULL)
- {
- if (end != NULL)
- {
- *end = '\\';
- }
- return STATUS_UNSUCCESSFUL;
- }
- /* Create new key object and put into linked list */
-DPRINT("CmiObjectParse %s\n",cPath);
- FoundObject = ObCreateObject(NULL,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- CmiKeyType);
- if (FoundObject == NULL)
- {
- //FIXME : return the good error code
- return STATUS_UNSUCCESSFUL;
- }
- FoundObject->Flags = 0;
- FoundObject->Name = SubKeyBlock->Name;
- FoundObject->NameSize = SubKeyBlock->NameSize;
- FoundObject->KeyBlock = SubKeyBlock;
- FoundObject->BlockOffset = BlockOffset;
- FoundObject->RegistryFile = ParsedKey->RegistryFile;
- CmiAddKeyToList(ParsedKey,FoundObject);
- }
- else
- ObReferenceObjectByPointer(FoundObject,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
-DPRINT("CmiObjectParse %s\n",FoundObject->Name);
- if (end != NULL)
- {
- *end = '\\';
- *Path = end;
- }
- else
- {
- *Path = NULL;
- }
-
- *NextObject = FoundObject;
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS CmiObjectCreate(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- struct _OBJECT_ATTRIBUTES* ObjectAttributes)
-{
- PKEY_OBJECT pKey=ObjectBody;
- pKey->ParentKey = Parent;
- if (RemainingPath)
- {
- if(RemainingPath[0]== L'\\')
- {
- pKey->Name = (PCHAR) (&RemainingPath[1]);
- pKey->NameSize = wcslen(RemainingPath)-1;
- }
- else
- {
- pKey->Name = (PCHAR) RemainingPath;
- pKey->NameSize = wcslen(RemainingPath);
- }
- }
- else
- pKey->NameSize = 0;
-
- return STATUS_SUCCESS;
-}
-
-static VOID
-CmiObjectDelete(PVOID DeletedObject)
-{
- PKEY_OBJECT KeyObject;
-
-DPRINT("delete object key\n");
- KeyObject = (PKEY_OBJECT) DeletedObject;
- if(!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
- {
- DPRINT1("Key not found in parent list ???\n");
- }
- if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
- {
-DPRINT1("delete really key\n");
- CmiDestroyBlock(KeyObject->RegistryFile,
- KeyObject->KeyBlock,
- KeyObject->BlockOffset);
- }
- else
- {
- CmiReleaseBlock(KeyObject->RegistryFile,
- KeyObject->KeyBlock);
- }
-}
-
-static VOID
-CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey)
-{
- KIRQL OldIrql;
-
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
- if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
- {
- PKEY_OBJECT *tmpSubKeys = ExAllocatePool(PagedPool
- , (ParentKey->NumberOfSubKeys+1) * sizeof(DWORD));
- if(ParentKey->NumberOfSubKeys > 0)
- memcpy(tmpSubKeys,ParentKey->SubKeys
- ,ParentKey->NumberOfSubKeys*sizeof(DWORD));
- if(ParentKey->SubKeys) ExFreePool(ParentKey->SubKeys);
- ParentKey->SubKeys=tmpSubKeys;
- ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys+1;
- }
- /* FIXME : please maintain the list in alphabetic order */
- /* to allow a dichotomic search */
- ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
- ObReferenceObjectByPointer(ParentKey,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
- NewKey->ParentKey = ParentKey;
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-}
-
-static NTSTATUS
-CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
-{
- KIRQL OldIrql;
- PKEY_OBJECT ParentKey;
- DWORD Index;
-
- ParentKey=KeyToRemove->ParentKey;
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
- /* FIXME : if list maintained in alphabetic order, use dichotomic search */
- for (Index=0; Index < ParentKey->NumberOfSubKeys; Index++)
- {
- if(ParentKey->SubKeys[Index] == KeyToRemove)
- {
- if (Index < ParentKey->NumberOfSubKeys-1)
- memmove(&ParentKey->SubKeys[Index]
- ,&ParentKey->SubKeys[Index+1]
- ,(ParentKey->NumberOfSubKeys-Index-1)*sizeof(PKEY_OBJECT));
- ParentKey->NumberOfSubKeys--;
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- ObDereferenceObject(ParentKey);
- return STATUS_SUCCESS;
- }
- }
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return STATUS_UNSUCCESSFUL;
-}
-
-static PKEY_OBJECT
-CmiScanKeyList(PKEY_OBJECT Parent,
- PCHAR KeyName,
- ULONG Attributes)
-{
- KIRQL OldIrql;
- PKEY_OBJECT CurKey;
- DWORD Index;
- WORD NameSize;
- NameSize=strlen(KeyName);
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
- /* FIXME : if list maintained in alphabetic order, use dichotomic search */
- for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
- {
- CurKey=Parent->SubKeys[Index];
- if (Attributes & OBJ_CASE_INSENSITIVE)
- {
- if( NameSize == CurKey->NameSize
- && !_strnicmp(KeyName,CurKey->Name,NameSize))
- {
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return CurKey;
- }
- }
- else
- {
- if( NameSize == CurKey->NameSize
- && !strncmp(KeyName,CurKey->Name,NameSize))
- {
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return CurKey;
- }
- }
- }
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-
- return NULL;
-}
-
-static PREGISTRY_FILE
-CmiCreateRegistry(PWSTR Filename)
-{
- PREGISTRY_FILE RegistryFile;
- PKEY_BLOCK RootKeyBlock;
- HANDLE FileHandle;
- PHEAP_BLOCK tmpHeap;
- LARGE_INTEGER fileOffset;
- PFREE_SUB_BLOCK FreeBlock;
- DWORD FreeOffset;
- int i, j;
- BLOCK_OFFSET BlockOffset;
-
- RegistryFile = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_FILE));
- if (Filename != NULL)
- {
- UNICODE_STRING TmpFileName;
- OBJECT_ATTRIBUTES ObjectAttributes;
- NTSTATUS Status;
- FILE_STANDARD_INFORMATION fsi;
- IO_STATUS_BLOCK IoSB;
-
- /* Duplicate Filename */
- RegistryFile->Filename = ExAllocatePool(NonPagedPool, MAX_PATH);
- wcscpy(RegistryFile->Filename , Filename);
- /* FIXME: if file does not exist, create new file */
- /* else attempt to map the file */
- RtlInitUnicodeString (&TmpFileName, Filename);
- InitializeObjectAttributes(&ObjectAttributes,
- &TmpFileName,
- 0,
- NULL,
- NULL);
- Status = NtOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- NULL, 0, 0);
- /* FIXME: if file does not exist, create new file */
- if( !NT_SUCCESS(Status) )
- {
- ExFreePool(RegistryFile->Filename);
- RegistryFile->Filename = NULL;
- return NULL;
- }
- RegistryFile->HeaderBlock = (PHEADER_BLOCK)
- ExAllocatePool(NonPagedPool, sizeof(HEADER_BLOCK));
- Status = ZwReadFile(FileHandle,
- 0, 0, 0, 0,
- RegistryFile->HeaderBlock,
- sizeof(HEADER_BLOCK),
- 0, 0);
- ZwQueryInformationFile(FileHandle,&IoSB,&fsi
- ,sizeof(fsi),FileStandardInformation);
- RegistryFile->FileSize = fsi.EndOfFile.u.LowPart;
- RegistryFile->BlockListSize = RegistryFile->FileSize / 4096 -1;
-// RegistryFile->NumberOfBlocks = RegistryFile->BlockListSize;
- RegistryFile->BlockList = ExAllocatePool(NonPagedPool,
- sizeof(PHEAP_BLOCK *) * (RegistryFile->BlockListSize ));
- BlockOffset=0;
- fileOffset.u.HighPart = 0;
- fileOffset.u.LowPart = 4096;
- RegistryFile->BlockList [0]
- = ExAllocatePool(NonPagedPool,RegistryFile->FileSize-4096);
- if (RegistryFile->BlockList[0] == NULL)
- {
-// Status = STATUS_INSUFFICIENT_RESOURCES;
- DPRINT1("error allocating %d bytes for registry\n"
- ,RegistryFile->FileSize-4096);
- ZwClose(FileHandle);
- return NULL;
- }
- Status = ZwReadFile(FileHandle,
- 0, 0, 0, 0,
- RegistryFile->BlockList [0],
- RegistryFile->FileSize-4096,
- &fileOffset, 0);
- ZwClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("error %x reading registry file at offset %x\n"
- ,Status,fileOffset.u.LowPart);
- return NULL;
- }
- RegistryFile->FreeListSize = 0;
- RegistryFile->FreeListMax = 0;
- RegistryFile->FreeList = NULL;
- for(i=0 ; i <RegistryFile->BlockListSize; i++)
- {
- tmpHeap = (PHEAP_BLOCK)(((char *)RegistryFile->BlockList [0])+BlockOffset);
- if (tmpHeap->BlockId != 0x6e696268 )
- {
- DPRINT1("bad BlockId %x,offset %x\n",tmpHeap->BlockId,fileOffset.u.LowPart);
- }
- RegistryFile->BlockList [i]
- = tmpHeap;
- if (tmpHeap->BlockSize >4096)
- {
- for(j=1;j<tmpHeap->BlockSize/4096;j++)
- RegistryFile->BlockList[i+j] = RegistryFile->BlockList[i];
- i = i+j-1;
- }
- /* search free blocks and add to list */
- FreeOffset=32;
- while(FreeOffset < tmpHeap->BlockSize)
- {
- FreeBlock = (PFREE_SUB_BLOCK)((char *)RegistryFile->BlockList[i]
- +FreeOffset);
- if ( FreeBlock->SubBlockSize>0)
- {
- CmiAddFree(RegistryFile,FreeBlock
- ,RegistryFile->BlockList[i]->BlockOffset+FreeOffset);
- FreeOffset += FreeBlock->SubBlockSize;
- }
- else
- FreeOffset -= FreeBlock->SubBlockSize;
- }
- BlockOffset += tmpHeap->BlockSize;
- }
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_ALL_ACCESS,
- IoFileObjectType,
- UserMode,
- (PVOID*)&RegistryFile->FileObject,
- NULL);
- }
- else
- {
- RegistryFile->Filename = NULL;
- RegistryFile->FileObject = NULL;
-
- RegistryFile->HeaderBlock = (PHEADER_BLOCK)
- ExAllocatePool(NonPagedPool, sizeof(HEADER_BLOCK));
- RtlZeroMemory(RegistryFile->HeaderBlock, sizeof(HEADER_BLOCK));
- RegistryFile->HeaderBlock->BlockId = 0x66676572;
- RegistryFile->HeaderBlock->DateModified.dwLowDateTime = 0;
- RegistryFile->HeaderBlock->DateModified.dwHighDateTime = 0;
- RegistryFile->HeaderBlock->Version = 1;
- RegistryFile->HeaderBlock->Unused3 = 3;
- RegistryFile->HeaderBlock->Unused5 = 1;
- RegistryFile->HeaderBlock->RootKeyBlock = 0;
- RegistryFile->HeaderBlock->BlockSize = REG_BLOCK_SIZE;
- RegistryFile->HeaderBlock->Unused6 = 1;
- RegistryFile->HeaderBlock->Checksum = 0;
- RootKeyBlock = (PKEY_BLOCK)
- ExAllocatePool(NonPagedPool, sizeof(KEY_BLOCK));
- RtlZeroMemory(RootKeyBlock, sizeof(KEY_BLOCK));
- RootKeyBlock->SubBlockId = REG_KEY_BLOCK_ID;
- RootKeyBlock->Type = REG_ROOT_KEY_BLOCK_TYPE;
- ZwQuerySystemTime((PTIME) &RootKeyBlock->LastWriteTime);
- RootKeyBlock->ParentKeyOffset = 0;
- RootKeyBlock->NumberOfSubKeys = 0;
- RootKeyBlock->HashTableOffset = -1;
- RootKeyBlock->NumberOfValues = 0;
- RootKeyBlock->ValuesOffset = -1;
- RootKeyBlock->SecurityKeyOffset = 0;
- RootKeyBlock->ClassNameOffset = -1;
- RootKeyBlock->NameSize = 0;
- RootKeyBlock->ClassSize = 0;
- RegistryFile->HeaderBlock->RootKeyBlock = (BLOCK_OFFSET) RootKeyBlock;
- }
- KeInitializeSemaphore(&RegistryFile->RegSem, 1, 1);
-
- return RegistryFile;
-}
-
-static ULONG
-CmiGetMaxNameLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock)
-{
- ULONG Idx, MaxName;
- PHASH_TABLE_BLOCK HashBlock;
- PKEY_BLOCK CurSubKeyBlock;
-
- MaxName = 0;
- HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
- if (HashBlock == 0)
- {
- return 0;
- }
- for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
- {
- if (HashBlock->Table[Idx].KeyOffset != 0)
- {
- CurSubKeyBlock = CmiGetBlock(RegistryFile,
- HashBlock->Table[Idx].KeyOffset,NULL);
- if (MaxName < CurSubKeyBlock->NameSize)
- {
- MaxName = CurSubKeyBlock->NameSize;
- }
- CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
- }
- }
-
- CmiReleaseBlock(RegistryFile, HashBlock);
-
- return MaxName;
-}
-
-static ULONG
-CmiGetMaxClassLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock)
-{
- ULONG Idx, MaxClass;
- PHASH_TABLE_BLOCK HashBlock;
- PKEY_BLOCK CurSubKeyBlock;
-
- MaxClass = 0;
- HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
- if (HashBlock == 0)
- {
- return 0;
- }
- for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
- {
- if (HashBlock->Table[Idx].KeyOffset != 0)
- {
- CurSubKeyBlock = CmiGetBlock(RegistryFile,
- HashBlock->Table[Idx].KeyOffset,NULL);
- if (MaxClass < CurSubKeyBlock->ClassSize)
- {
- MaxClass = CurSubKeyBlock->ClassSize;
- }
- CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
- }
- }
-
- CmiReleaseBlock(RegistryFile, HashBlock);
-
- return MaxClass;
-}
-
-static ULONG
-CmiGetMaxValueNameLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock)
-{
- ULONG Idx, MaxValueName;
- PVALUE_LIST_BLOCK ValueListBlock;
- PVALUE_BLOCK CurValueBlock;
-
- ValueListBlock = CmiGetBlock(RegistryFile,
- KeyBlock->ValuesOffset,NULL);
- MaxValueName = 0;
- if (ValueListBlock == 0)
- {
- return 0;
- }
- for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
- {
- CurValueBlock = CmiGetBlock(RegistryFile,
- ValueListBlock->Values[Idx],NULL);
- if (CurValueBlock != NULL &&
- MaxValueName < CurValueBlock->NameSize)
- {
- MaxValueName = CurValueBlock->NameSize;
- }
- CmiReleaseBlock(RegistryFile, CurValueBlock);
- }
-
- CmiReleaseBlock(RegistryFile, ValueListBlock);
-
- return MaxValueName;
-}
-
-static ULONG
-CmiGetMaxValueDataLength(PREGISTRY_FILE RegistryFile,
- PKEY_BLOCK KeyBlock)
-{
- ULONG Idx, MaxValueData;
- PVALUE_LIST_BLOCK ValueListBlock;
- PVALUE_BLOCK CurValueBlock;
-
- ValueListBlock = CmiGetBlock(RegistryFile,
- KeyBlock->ValuesOffset,NULL);
- MaxValueData = 0;
- if (ValueListBlock == 0)
- {
- return 0;
- }
- for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
- {
- CurValueBlock = CmiGetBlock(RegistryFile,
- ValueListBlock->Values[Idx],NULL);
- if (CurValueBlock != NULL &&
- MaxValueData < (CurValueBlock->DataSize & LONG_MAX) )
- {
- MaxValueData = CurValueBlock->DataSize & LONG_MAX;
- }
- CmiReleaseBlock(RegistryFile, CurValueBlock);
- }
-
- CmiReleaseBlock(RegistryFile, ValueListBlock);
-
- return MaxValueData;
-}
-
-static NTSTATUS
-CmiScanForSubKey(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- OUT PKEY_BLOCK *SubKeyBlock,
- OUT BLOCK_OFFSET *BlockOffset,
- IN PCHAR KeyName,
- IN ACCESS_MASK DesiredAccess,
- IN ULONG Attributes)
-{
- ULONG Idx;
- PHASH_TABLE_BLOCK HashBlock;
- PKEY_BLOCK CurSubKeyBlock;
- WORD KeyLength = strlen(KeyName);
-
- HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
- *SubKeyBlock = NULL;
- if (HashBlock == NULL)
- {
- return STATUS_SUCCESS;
- }
-// for (Idx = 0; Idx < HashBlock->HashTableSize; Idx++)
- for (Idx = 0; Idx < KeyBlock->NumberOfSubKeys
- && Idx < HashBlock->HashTableSize; Idx++)
- {
- if (Attributes & OBJ_CASE_INSENSITIVE)
- {
- if (HashBlock->Table[Idx].KeyOffset != 0 &&
- HashBlock->Table[Idx].KeyOffset != -1 &&
- !_strnicmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4))
- {
- CurSubKeyBlock = CmiGetBlock(RegistryFile,
- HashBlock->Table[Idx].KeyOffset,NULL);
- if ( CurSubKeyBlock->NameSize == KeyLength
- && !_strnicmp(KeyName, CurSubKeyBlock->Name, KeyLength))
- {
- *SubKeyBlock = CurSubKeyBlock;
- *BlockOffset = HashBlock->Table[Idx].KeyOffset;
- break;
- }
- else
- {
- CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
- }
- }
- }
- else
- {
- if (HashBlock->Table[Idx].KeyOffset != 0 &&
- HashBlock->Table[Idx].KeyOffset != -1 &&
- !strncmp(KeyName, (PCHAR) &HashBlock->Table[Idx].HashValue, 4))
- {
- CurSubKeyBlock = CmiGetBlock(RegistryFile,
- HashBlock->Table[Idx].KeyOffset,NULL);
- if ( CurSubKeyBlock->NameSize == KeyLength
- && !_strnicmp(KeyName, CurSubKeyBlock->Name, KeyLength))
- {
- *SubKeyBlock = CurSubKeyBlock;
- *BlockOffset = HashBlock->Table[Idx].KeyOffset;
- break;
- }
- else
- {
- CmiReleaseBlock(RegistryFile, CurSubKeyBlock);
- }
- }
- }
- }
-
- CmiReleaseBlock(RegistryFile, HashBlock);
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-CmiAddSubKey(PREGISTRY_FILE RegistryFile,
- PKEY_OBJECT Parent,
- PKEY_OBJECT SubKey,
- PWSTR NewSubKeyName,
- USHORT NewSubKeyNameSize,
- ULONG TitleIndex,
- PUNICODE_STRING Class,
- ULONG CreateOptions)
-{
- PKEY_BLOCK KeyBlock = Parent->KeyBlock;
- NTSTATUS Status;
- PHASH_TABLE_BLOCK HashBlock, NewHashBlock;
- PKEY_BLOCK NewKeyBlock;
- BLOCK_OFFSET NKBOffset;
- ULONG NewBlockSize;
- USHORT NameSize;
-
- if (NewSubKeyName[0] == L'\\')
- {
- NewSubKeyName++;
- NameSize = NewSubKeyNameSize/2-1;
- }
- else
- NameSize = NewSubKeyNameSize/2;
- Status = STATUS_SUCCESS;
-
- NewBlockSize = sizeof(KEY_BLOCK) + NameSize;
- Status = CmiAllocateBlock(RegistryFile, (PVOID) &NewKeyBlock
- , NewBlockSize,&NKBOffset);
- if (NewKeyBlock == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- NewKeyBlock->SubBlockId = REG_KEY_BLOCK_ID;
- NewKeyBlock->Type = REG_KEY_BLOCK_TYPE;
- ZwQuerySystemTime((PTIME) &NewKeyBlock->LastWriteTime);
- NewKeyBlock->ParentKeyOffset = -1;
- NewKeyBlock->NumberOfSubKeys = 0;
- NewKeyBlock->HashTableOffset = -1;
- NewKeyBlock->NumberOfValues = 0;
- NewKeyBlock->ValuesOffset = -1;
- NewKeyBlock->SecurityKeyOffset = -1;
- NewKeyBlock->NameSize = NameSize;
- wcstombs(NewKeyBlock->Name,NewSubKeyName,NameSize);
- NewKeyBlock->ClassNameOffset = -1;
- if (Class)
- {
- PDATA_BLOCK pClass;
- NewKeyBlock->ClassSize = Class->Length+sizeof(WCHAR);
- Status = CmiAllocateBlock(RegistryFile
- ,(PVOID)&pClass
- ,NewKeyBlock->ClassSize
- ,&NewKeyBlock->ClassNameOffset );
- wcsncpy((PWSTR)pClass->Data,Class->Buffer,Class->Length);
- ( (PWSTR)(pClass->Data))[Class->Length]=0;
- }
- }
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- SubKey->KeyBlock = NewKeyBlock;
- SubKey->BlockOffset = NKBOffset;
- /* don't modify hash table if key is volatile and parent is not */
- if (RegistryFile == CmiVolatileFile && Parent->RegistryFile != RegistryFile)
- {
- return Status;
- }
- if (KeyBlock->HashTableOffset == -1)
- {
- Status = CmiAllocateHashTableBlock(RegistryFile,
- &HashBlock,
- &KeyBlock->HashTableOffset,
- REG_INIT_HASH_TABLE_SIZE);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
- else
- {
- HashBlock = CmiGetBlock(RegistryFile, KeyBlock->HashTableOffset,NULL);
- if (KeyBlock->NumberOfSubKeys + 1 >= HashBlock->HashTableSize)
- {
- BLOCK_OFFSET HTOffset;
-
- /* Reallocate the hash table block */
- Status = CmiAllocateHashTableBlock(RegistryFile,
- &NewHashBlock,
- &HTOffset,
- HashBlock->HashTableSize +
- REG_EXTEND_HASH_TABLE_SIZE);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- RtlZeroMemory(&NewHashBlock->Table[0],
- sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize);
- RtlCopyMemory(&NewHashBlock->Table[0],
- &HashBlock->Table[0],
- sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
- CmiDestroyBlock(RegistryFile, HashBlock
- , KeyBlock->HashTableOffset);
- KeyBlock->HashTableOffset = HTOffset;
- HashBlock = NewHashBlock;
- }
- }
- Status = CmiAddKeyToHashTable(RegistryFile, HashBlock, NewKeyBlock,NKBOffset);
- if (NT_SUCCESS(Status))
- {
- KeyBlock->NumberOfSubKeys++;
- }
-
- return Status;
-}
-
-static NTSTATUS
-CmiScanKeyForValue(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN PCHAR ValueName,
- OUT PVALUE_BLOCK *ValueBlock,
- OUT BLOCK_OFFSET *VBOffset)
-{
- ULONG Idx;
- PVALUE_LIST_BLOCK ValueListBlock;
- PVALUE_BLOCK CurValueBlock;
- ValueListBlock = CmiGetBlock(RegistryFile,
- KeyBlock->ValuesOffset,NULL);
- *ValueBlock = NULL;
- if (ValueListBlock == NULL)
- {
- return STATUS_SUCCESS;
- }
- for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
- {
- CurValueBlock = CmiGetBlock(RegistryFile,
- ValueListBlock->Values[Idx],NULL);
- /* FIXME : perhaps we must not ignore case if NtCreateKey has not been */
- /* called with OBJ_CASE_INSENSITIVE flag ? */
- if (CurValueBlock != NULL &&
- CurValueBlock->NameSize == strlen(ValueName) &&
- !_strnicmp(CurValueBlock->Name, ValueName,strlen(ValueName)))
- {
- *ValueBlock = CurValueBlock;
- if(VBOffset) *VBOffset = ValueListBlock->Values[Idx];
- break;
- }
- CmiReleaseBlock(RegistryFile, CurValueBlock);
- }
-
- CmiReleaseBlock(RegistryFile, ValueListBlock);
-
- return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-CmiGetValueFromKeyByIndex(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN ULONG Index,
- OUT PVALUE_BLOCK *ValueBlock)
-{
- PVALUE_LIST_BLOCK ValueListBlock;
- PVALUE_BLOCK CurValueBlock;
- ValueListBlock = CmiGetBlock(RegistryFile,
- KeyBlock->ValuesOffset,NULL);
- *ValueBlock = NULL;
- if (ValueListBlock == NULL)
- {
- return STATUS_NO_MORE_ENTRIES;
- }
- if (Index >= KeyBlock->NumberOfValues)
- {
- return STATUS_NO_MORE_ENTRIES;
- }
- CurValueBlock = CmiGetBlock(RegistryFile,
- ValueListBlock->Values[Index],NULL);
- if (CurValueBlock != NULL)
- {
- *ValueBlock = CurValueBlock;
- }
- CmiReleaseBlock(RegistryFile, CurValueBlock);
- CmiReleaseBlock(RegistryFile, ValueListBlock);
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-CmiAddValueToKey(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN PCHAR ValueNameBuf,
- OUT PVALUE_BLOCK *pValueBlock,
- OUT BLOCK_OFFSET *pVBOffset)
-{
- NTSTATUS Status;
- PVALUE_LIST_BLOCK ValueListBlock, NewValueListBlock;
- BLOCK_OFFSET VBOffset;
- BLOCK_OFFSET VLBOffset;
- PVALUE_BLOCK NewValueBlock;
-
- Status = CmiAllocateValueBlock(RegistryFile,
- &NewValueBlock,
- &VBOffset,
- ValueNameBuf);
- *pVBOffset=VBOffset;
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- ValueListBlock = CmiGetBlock(RegistryFile,
- KeyBlock->ValuesOffset,NULL);
- if (ValueListBlock == NULL)
- {
- Status = CmiAllocateBlock(RegistryFile,
- (PVOID) &ValueListBlock,
- sizeof(BLOCK_OFFSET) * 3,
- &VLBOffset);
- if (!NT_SUCCESS(Status))
- {
- CmiDestroyValueBlock(RegistryFile,
- NewValueBlock,VBOffset);
- return Status;
- }
- KeyBlock->ValuesOffset = VLBOffset;
- }
- else if ( KeyBlock->NumberOfValues
- >= -(ValueListBlock->SubBlockSize-4)/sizeof(BLOCK_OFFSET))
- {
- Status = CmiAllocateBlock(RegistryFile,
- (PVOID) &NewValueListBlock,
- sizeof(BLOCK_OFFSET) *
- (KeyBlock->NumberOfValues +
- REG_VALUE_LIST_BLOCK_MULTIPLE),&VLBOffset);
- if (!NT_SUCCESS(Status))
- {
- CmiDestroyValueBlock(RegistryFile,
- NewValueBlock,VBOffset);
- return Status;
- }
- RtlCopyMemory(&NewValueListBlock->Values[0],
- &ValueListBlock->Values[0],
- sizeof(BLOCK_OFFSET) * KeyBlock->NumberOfValues);
- CmiDestroyBlock(RegistryFile, ValueListBlock,KeyBlock->ValuesOffset);
- KeyBlock->ValuesOffset = VLBOffset;
- ValueListBlock = NewValueListBlock;
- }
- ValueListBlock->Values[KeyBlock->NumberOfValues] = VBOffset;
- KeyBlock->NumberOfValues++;
- CmiReleaseBlock(RegistryFile, ValueListBlock);
- CmiReleaseBlock(RegistryFile, NewValueBlock);
- *pValueBlock = NewValueBlock;
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-CmiDeleteValueFromKey(IN PREGISTRY_FILE RegistryFile,
- IN PKEY_BLOCK KeyBlock,
- IN PCHAR ValueName)
-{
- ULONG Idx;
- PVALUE_LIST_BLOCK ValueListBlock;
- PVALUE_BLOCK CurValueBlock;
- PHEAP_BLOCK pHeap;
-
- ValueListBlock = CmiGetBlock(RegistryFile,
- KeyBlock->ValuesOffset,NULL);
- if (ValueListBlock == 0)
- {
- return STATUS_SUCCESS;
- }
- for (Idx = 0; Idx < KeyBlock->NumberOfValues; Idx++)
- {
- CurValueBlock = CmiGetBlock(RegistryFile,
- ValueListBlock->Values[Idx],&pHeap);
- if (CurValueBlock != NULL &&
- CurValueBlock->NameSize == strlen(ValueName) &&
- !memcmp(CurValueBlock->Name, ValueName,strlen(ValueName)))
- {
- if (KeyBlock->NumberOfValues - 1 < Idx)
- {
- RtlCopyMemory(&ValueListBlock->Values[Idx],
- &ValueListBlock->Values[Idx + 1],
- sizeof(BLOCK_OFFSET) *
- (KeyBlock->NumberOfValues - 1 - Idx));
- }
- else
- {
- RtlZeroMemory(&ValueListBlock->Values[Idx],
- sizeof(BLOCK_OFFSET));
- }
- KeyBlock->NumberOfValues -= 1;
- CmiDestroyValueBlock(RegistryFile, CurValueBlock, ValueListBlock->Values[Idx]);
- /* update time of heap */
- ZwQuerySystemTime((PTIME) &pHeap->DateModified);
-
- break;
- }
- CmiReleaseBlock(RegistryFile, CurValueBlock);
- }
-
- CmiReleaseBlock(RegistryFile, ValueListBlock);
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-CmiAllocateHashTableBlock(IN PREGISTRY_FILE RegistryFile,
- OUT PHASH_TABLE_BLOCK *HashBlock,
- OUT BLOCK_OFFSET *HBOffset,
- IN ULONG HashTableSize)
-{
- NTSTATUS Status;
- ULONG NewHashSize;
- PHASH_TABLE_BLOCK NewHashBlock;
-
- Status = STATUS_SUCCESS;
- *HashBlock = NULL;
- NewHashSize = sizeof(HASH_TABLE_BLOCK) +
- (HashTableSize - 1) * sizeof(HASH_RECORD);
- Status = CmiAllocateBlock(RegistryFile,
- (PVOID*)&NewHashBlock,
- NewHashSize,HBOffset);
- if (NewHashBlock == NULL || !NT_SUCCESS(Status) )
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- NewHashBlock->SubBlockId = REG_HASH_TABLE_BLOCK_ID;
- NewHashBlock->HashTableSize = HashTableSize;
- *HashBlock = NewHashBlock;
- }
-
- return Status;
-}
-
-static PKEY_BLOCK
-CmiGetKeyFromHashByIndex(PREGISTRY_FILE RegistryFile,
- PHASH_TABLE_BLOCK HashBlock,
- ULONG Index)
-{
- PKEY_BLOCK KeyBlock;
- BLOCK_OFFSET KeyOffset;
-
- if( HashBlock == NULL)
- return NULL;
- if (RegistryFile->Filename == NULL)
- {
- KeyBlock = (PKEY_BLOCK) HashBlock->Table[Index].KeyOffset;
- }
- else
- {
- KeyOffset = HashBlock->Table[Index].KeyOffset;
- KeyBlock = CmiGetBlock(RegistryFile,KeyOffset,NULL);
- }
- CmiLockBlock(RegistryFile, KeyBlock);
-
- return KeyBlock;
-}
-
-static NTSTATUS
-CmiAddKeyToHashTable(PREGISTRY_FILE RegistryFile,
- PHASH_TABLE_BLOCK HashBlock,
- PKEY_BLOCK NewKeyBlock,
- BLOCK_OFFSET NKBOffset)
-{
- ULONG i;
-
- for (i = 0; i < HashBlock->HashTableSize; i++)
- {
- if (HashBlock->Table[i].KeyOffset == 0)
- {
- HashBlock->Table[i].KeyOffset = NKBOffset;
- RtlCopyMemory(&HashBlock->Table[i].HashValue,
- NewKeyBlock->Name,
- 4);
- return STATUS_SUCCESS;
- }
- }
- return STATUS_UNSUCCESSFUL;
-}
-
-static NTSTATUS
-CmiAllocateValueBlock(PREGISTRY_FILE RegistryFile,
- PVALUE_BLOCK *ValueBlock,
- BLOCK_OFFSET *VBOffset,
- IN PCHAR ValueNameBuf)
-{
- NTSTATUS Status;
- ULONG NewValueSize;
- PVALUE_BLOCK NewValueBlock;
-
- Status = STATUS_SUCCESS;
-
- NewValueSize = sizeof(VALUE_BLOCK) + strlen(ValueNameBuf);
- Status = CmiAllocateBlock(RegistryFile,
- (PVOID*)&NewValueBlock,
- NewValueSize,VBOffset);
- if (NewValueBlock == NULL || !NT_SUCCESS(Status))
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- NewValueBlock->SubBlockId = REG_VALUE_BLOCK_ID;
- NewValueBlock->NameSize = strlen(ValueNameBuf);
- memcpy(NewValueBlock->Name, ValueNameBuf,strlen(ValueNameBuf));
- NewValueBlock->DataType = 0;
- NewValueBlock->DataSize = 0;
- NewValueBlock->DataOffset = 0xffffffff;
- *ValueBlock = NewValueBlock;
- }
-
- return Status;
-}
-
-static NTSTATUS
-CmiDestroyValueBlock(PREGISTRY_FILE RegistryFile,
- PVALUE_BLOCK ValueBlock, BLOCK_OFFSET VBOffset)
-{
- NTSTATUS Status;
- PHEAP_BLOCK pHeap;
- PVOID pBlock;
-
- /* first, release datas : */
- if (ValueBlock->DataSize >0)
- {
- pBlock = CmiGetBlock(RegistryFile, ValueBlock->DataOffset,&pHeap);
- Status = CmiDestroyBlock(RegistryFile, pBlock, ValueBlock->DataOffset);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- /* update time of heap */
- if(RegistryFile->Filename)
- ZwQuerySystemTime((PTIME) &pHeap->DateModified);
- }
-
- Status = CmiDestroyBlock(RegistryFile, ValueBlock, VBOffset);
- /* update time of heap */
- if(RegistryFile->Filename && CmiGetBlock(RegistryFile, VBOffset,&pHeap))
- ZwQuerySystemTime((PTIME) &pHeap->DateModified);
- return Status;
-}
-
-static NTSTATUS
-CmiAddHeap(PREGISTRY_FILE RegistryFile,PVOID *NewBlock,BLOCK_OFFSET *NewBlockOffset)
-{
- PHEAP_BLOCK tmpHeap;
- PHEAP_BLOCK * tmpBlockList;
- PFREE_SUB_BLOCK tmpBlock;
- tmpHeap=ExAllocatePool(PagedPool, REG_BLOCK_SIZE);
- tmpHeap->BlockId = REG_HEAP_ID;
- tmpHeap->BlockOffset = RegistryFile->FileSize - REG_BLOCK_SIZE;
- RegistryFile->FileSize += REG_BLOCK_SIZE;
- tmpHeap->BlockSize = REG_BLOCK_SIZE;
- tmpHeap->Unused1 = 0;
- ZwQuerySystemTime((PTIME) &tmpHeap->DateModified);
- tmpHeap->Unused2 = 0;
- /* increase size of list of blocks */
- tmpBlockList=ExAllocatePool(NonPagedPool,
- sizeof(PHEAP_BLOCK *) * (RegistryFile->BlockListSize +1));
- if (tmpBlockList == NULL)
- {
- KeBugCheck(0);
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
- if(RegistryFile->BlockListSize > 0)
- {
- memcpy(tmpBlockList,RegistryFile->BlockList,
- sizeof(PHEAP_BLOCK *)*(RegistryFile->BlockListSize ));
- ExFreePool(RegistryFile->BlockList);
- }
- RegistryFile->BlockList = tmpBlockList;
- RegistryFile->BlockList [RegistryFile->BlockListSize++] = tmpHeap;
- /* initialize a free block in this heap : */
- tmpBlock = (PFREE_SUB_BLOCK)((char *) tmpHeap + REG_HEAP_BLOCK_DATA_OFFSET);
- tmpBlock-> SubBlockSize = (REG_BLOCK_SIZE - REG_HEAP_BLOCK_DATA_OFFSET) ;
- *NewBlock = (PVOID)tmpBlock;
- if (NewBlockOffset)
- *NewBlockOffset = tmpHeap->BlockOffset + REG_HEAP_BLOCK_DATA_OFFSET;
- /* FIXME : set first dword to block_offset of another free bloc */
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-CmiAllocateBlock(PREGISTRY_FILE RegistryFile,
- PVOID *Block,
- LONG BlockSize,
- BLOCK_OFFSET * pBlockOffset)
-{
- NTSTATUS Status;
- PFREE_SUB_BLOCK NewBlock;
- PHEAP_BLOCK pHeap;
-
- Status = STATUS_SUCCESS;
- /* round to 16 bytes multiple */
- BlockSize = (BlockSize + sizeof(DWORD) + 15) & 0xfffffff0;
-
- /* Handle volatile files first */
- if (RegistryFile->Filename == NULL)
- {
- NewBlock = ExAllocatePool(NonPagedPool, BlockSize);
- if (NewBlock == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- RtlZeroMemory(NewBlock, BlockSize);
- NewBlock->SubBlockSize = BlockSize;
- CmiLockBlock(RegistryFile, NewBlock);
- *Block = NewBlock;
- if (pBlockOffset) *pBlockOffset = (BLOCK_OFFSET)NewBlock;
- }
- }
- else
- {
- int i;
- /* first search in free blocks */
- NewBlock = NULL;
- for (i=0 ; i<RegistryFile->FreeListSize ; i++)
- {
- if(RegistryFile->FreeList[i]->SubBlockSize >=BlockSize)
- {
- NewBlock = RegistryFile->FreeList[i];
- if(pBlockOffset)
- *pBlockOffset = RegistryFile->FreeListOffset[i];
- /* update time of heap */
- if(RegistryFile->Filename
- && CmiGetBlock(RegistryFile, RegistryFile->FreeListOffset[i],&pHeap))
- ZwQuerySystemTime((PTIME) &pHeap->DateModified);
- if( (i+1) <RegistryFile->FreeListSize)
- {
- memmove( &RegistryFile->FreeList[i]
- ,&RegistryFile->FreeList[i+1]
- ,sizeof(RegistryFile->FreeList[0])
- *(RegistryFile->FreeListSize-i-1));
- memmove( &RegistryFile->FreeListOffset[i]
- ,&RegistryFile->FreeListOffset[i+1]
- ,sizeof(RegistryFile->FreeListOffset[0])
- *(RegistryFile->FreeListSize-i-1));
- }
- RegistryFile->FreeListSize--;
- break;
- }
- }
- /* need to extend hive file : */
- if (NewBlock == NULL)
- {
- /* add a new block : */
- Status = CmiAddHeap(RegistryFile, (PVOID *)&NewBlock , pBlockOffset);
- }
- if (NT_SUCCESS(Status))
- {
- *Block = NewBlock;
- /* split the block in two parts */
- if(NewBlock->SubBlockSize > BlockSize)
- {
- NewBlock = (PFREE_SUB_BLOCK)((char *)NewBlock+BlockSize);
- NewBlock->SubBlockSize=((PFREE_SUB_BLOCK) (*Block))->SubBlockSize-BlockSize;
- CmiAddFree(RegistryFile,NewBlock,*pBlockOffset+BlockSize);
- }
- else if(NewBlock->SubBlockSize < BlockSize)
- return STATUS_UNSUCCESSFUL;
- RtlZeroMemory(*Block, BlockSize);
- ((PFREE_SUB_BLOCK)(*Block)) ->SubBlockSize = - BlockSize;
- CmiLockBlock(RegistryFile, *Block);
- }
- }
- return Status;
-}
-
-static NTSTATUS
-CmiDestroyBlock(PREGISTRY_FILE RegistryFile,
- PVOID Block,BLOCK_OFFSET Offset)
-{
- NTSTATUS Status;
- PHEAP_BLOCK pHeap;
-
- Status = STATUS_SUCCESS;
-
- if (RegistryFile->Filename == NULL)
- {
- CmiReleaseBlock(RegistryFile, Block);
- ExFreePool(Block);
- }
- else
- {
- PFREE_SUB_BLOCK pFree = Block;
- if (pFree->SubBlockSize <0)
- pFree->SubBlockSize = -pFree->SubBlockSize;
- CmiAddFree(RegistryFile,Block,Offset);
- CmiReleaseBlock(RegistryFile, Block);
- /* update time of heap */
- if(RegistryFile->Filename && CmiGetBlock(RegistryFile, Offset,&pHeap))
- ZwQuerySystemTime((PTIME) &pHeap->DateModified);
- /* FIXME : set first dword to block_offset of another free bloc ? */
- /* FIXME : concatenate with previous and next block if free */
- }
-
- return Status;
-}
-
-static NTSTATUS
-CmiAddFree(PREGISTRY_FILE RegistryFile,
- PFREE_SUB_BLOCK FreeBlock,BLOCK_OFFSET FreeOffset)
-{
- PFREE_SUB_BLOCK *tmpList;
- BLOCK_OFFSET *tmpListOffset;
- int minInd,maxInd,medInd;
- if( (RegistryFile->FreeListSize+1) > RegistryFile->FreeListMax)
- {
- tmpList=ExAllocatePool(PagedPool
- ,sizeof(PFREE_SUB_BLOCK)*(RegistryFile->FreeListMax+32));
- if (tmpList == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
- tmpListOffset=ExAllocatePool(PagedPool
- ,sizeof(BLOCK_OFFSET *)*(RegistryFile->FreeListMax+32));
- if (tmpListOffset == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
- if (RegistryFile->FreeListMax)
- {
- memcpy(tmpList,RegistryFile->FreeList
- ,sizeof(PFREE_SUB_BLOCK)*(RegistryFile->FreeListMax));
- memcpy(tmpListOffset,RegistryFile->FreeListOffset
- ,sizeof(BLOCK_OFFSET *)*(RegistryFile->FreeListMax));
- ExFreePool(RegistryFile->FreeList);
- ExFreePool(RegistryFile->FreeListOffset);
- }
- RegistryFile->FreeList = tmpList;
- RegistryFile->FreeListOffset = tmpListOffset;
- RegistryFile->FreeListMax +=32;
- }
- /* add new offset to free list, maintening list in ascending order */
- if ( RegistryFile->FreeListSize==0
- || RegistryFile->FreeListOffset[RegistryFile->FreeListSize-1] < FreeOffset)
- {
- /* add to end of list : */
- RegistryFile->FreeList[RegistryFile->FreeListSize] = FreeBlock;
- RegistryFile->FreeListOffset[RegistryFile->FreeListSize ++] = FreeOffset;
- }
- else if (RegistryFile->FreeListOffset[0] > FreeOffset)
- {
- /* add to begin of list : */
- memmove( &RegistryFile->FreeList[1],&RegistryFile->FreeList[0]
- ,sizeof(RegistryFile->FreeList[0])*RegistryFile->FreeListSize);
- memmove( &RegistryFile->FreeListOffset[1],&RegistryFile->FreeListOffset[0]
- ,sizeof(RegistryFile->FreeListOffset[0])*RegistryFile->FreeListSize);
- RegistryFile->FreeList[0] = FreeBlock;
- RegistryFile->FreeListOffset[0] = FreeOffset;
- RegistryFile->FreeListSize ++;
- }
- else
- {
- /* search where to insert : */
- minInd=0;
- maxInd=RegistryFile->FreeListSize-1;
- while( (maxInd-minInd) >1)
- {
- medInd=(minInd+maxInd)/2;
- if (RegistryFile->FreeListOffset[medInd] > FreeOffset)
- maxInd=medInd;
- else
- minInd=medInd;
- }
- /* insert before maxInd : */
- memmove( &RegistryFile->FreeList[maxInd+1],&RegistryFile->FreeList[maxInd]
- ,sizeof(RegistryFile->FreeList[0])
- *(RegistryFile->FreeListSize-minInd));
- memmove( &RegistryFile->FreeListOffset[maxInd+1]
- , &RegistryFile->FreeListOffset[maxInd]
- , sizeof(RegistryFile->FreeListOffset[0])
- *(RegistryFile->FreeListSize-minInd));
- RegistryFile->FreeList[maxInd] = FreeBlock;
- RegistryFile->FreeListOffset[maxInd] = FreeOffset;
- RegistryFile->FreeListSize ++;
- }
- return STATUS_SUCCESS;
-}
-
-static PVOID
-CmiGetBlock(PREGISTRY_FILE RegistryFile,
- BLOCK_OFFSET BlockOffset,
- OUT PHEAP_BLOCK * ppHeap)
-{
- if( BlockOffset == 0 || BlockOffset == -1) return NULL;
-
- if (RegistryFile->Filename == NULL)
- {
- return (PVOID)BlockOffset;
- }
- else
- {
- PHEAP_BLOCK pHeap;
- pHeap = RegistryFile->BlockList[BlockOffset/4096];
- if(ppHeap) *ppHeap = pHeap;
- return ((char *)pHeap
- +(BlockOffset - pHeap->BlockOffset));
- }
-}
-
-static VOID
-CmiLockBlock(PREGISTRY_FILE RegistryFile,
- PVOID Block)
-{
- if (RegistryFile->Filename != NULL)
- {
- /* FIXME : implement */
- }
-}
-
-static VOID
-CmiReleaseBlock(PREGISTRY_FILE RegistryFile,
- PVOID Block)
-{
- if (RegistryFile->Filename != NULL)
- {
- /* FIXME : implement */
- }
-}
/* EOF */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/cm/regobj.c
+ * PURPOSE: Registry object manipulation routines.
+ * UPDATE HISTORY:
+*/
+
+#include "cm.h"
+
+extern POBJECT_TYPE CmiKeyType;
+extern KSPIN_LOCK CmiKeyListLock;
+
+NTSTATUS CmiObjectParse(PVOID ParsedObject,
+ PVOID *NextObject,
+ PUNICODE_STRING FullPath,
+ PWSTR *Path,
+ POBJECT_TYPE ObjectType,
+ ULONG Attributes)
+{
+ CHAR cPath[MAX_PATH];
+ PWSTR end;
+ PKEY_OBJECT FoundObject;
+ PKEY_OBJECT ParsedKey=ParsedObject;
+ PKEY_BLOCK SubKeyBlock;
+ BLOCK_OFFSET BlockOffset;
+ NTSTATUS Status;
+ *NextObject = NULL;
+ if ((*Path) == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if((*Path[0])=='\\')
+ {
+ end = wcschr((*Path)+1, '\\');
+ if (end != NULL)
+ *end = 0;
+ wcstombs(cPath,(*Path)+1,wcslen((*Path)+1));
+ cPath[wcslen( (*Path)+1)]=0;
+ }
+ else
+ {
+ end = wcschr((*Path), '\\');
+ if (end != NULL)
+ *end = 0;
+ wcstombs(cPath,(*Path),wcslen((*Path)));
+ cPath[wcslen( (*Path))]=0;
+ }
+
+ FoundObject = CmiScanKeyList(ParsedKey,cPath,Attributes);
+ if (FoundObject == NULL)
+ {
+ Status = CmiScanForSubKey(ParsedKey->RegistryFile,
+ ParsedKey->KeyBlock,
+ &SubKeyBlock,
+ &BlockOffset,
+ cPath,
+ 0,
+ Attributes);
+ if(!NT_SUCCESS(Status) || SubKeyBlock == NULL)
+ {
+ if (end != NULL)
+ {
+ *end = '\\';
+ }
+ return STATUS_UNSUCCESSFUL;
+ }
+ /* Create new key object and put into linked list */
+DPRINT("CmiObjectParse %s\n",cPath);
+ FoundObject = ObCreateObject(NULL,
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ CmiKeyType);
+ if (FoundObject == NULL)
+ {
+ //FIXME : return the good error code
+ return STATUS_UNSUCCESSFUL;
+ }
+ FoundObject->Flags = 0;
+ FoundObject->Name = SubKeyBlock->Name;
+ FoundObject->NameSize = SubKeyBlock->NameSize;
+ FoundObject->KeyBlock = SubKeyBlock;
+ FoundObject->BlockOffset = BlockOffset;
+ FoundObject->RegistryFile = ParsedKey->RegistryFile;
+ CmiAddKeyToList(ParsedKey,FoundObject);
+ }
+ else
+ ObReferenceObjectByPointer(FoundObject,
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ UserMode);
+DPRINT("CmiObjectParse %s\n",FoundObject->Name);
+ if (end != NULL)
+ {
+ *end = '\\';
+ *Path = end;
+ }
+ else
+ {
+ *Path = NULL;
+ }
+
+ *NextObject = FoundObject;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS CmiObjectCreate(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ struct _OBJECT_ATTRIBUTES* ObjectAttributes)
+{
+ PKEY_OBJECT pKey=ObjectBody;
+ pKey->ParentKey = Parent;
+ if (RemainingPath)
+ {
+ if(RemainingPath[0]== L'\\')
+ {
+ pKey->Name = (PCHAR) (&RemainingPath[1]);
+ pKey->NameSize = wcslen(RemainingPath)-1;
+ }
+ else
+ {
+ pKey->Name = (PCHAR) RemainingPath;
+ pKey->NameSize = wcslen(RemainingPath);
+ }
+ }
+ else
+ pKey->NameSize = 0;
+
+ return STATUS_SUCCESS;
+}
+
+void
+CmiObjectDelete(PVOID DeletedObject)
+{
+ PKEY_OBJECT KeyObject;
+
+DPRINT("delete object key\n");
+ KeyObject = (PKEY_OBJECT) DeletedObject;
+ if(!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
+ {
+ DPRINT1("Key not found in parent list ???\n");
+ }
+ if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
+ {
+DPRINT1("delete really key\n");
+ CmiDestroyBlock(KeyObject->RegistryFile,
+ KeyObject->KeyBlock,
+ KeyObject->BlockOffset);
+ }
+ else
+ {
+ CmiReleaseBlock(KeyObject->RegistryFile,
+ KeyObject->KeyBlock);
+ }
+}
+
+void
+CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey)
+{
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
+ if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
+ {
+ PKEY_OBJECT *tmpSubKeys = ExAllocatePool(PagedPool
+ , (ParentKey->NumberOfSubKeys+1) * sizeof(DWORD));
+ if(ParentKey->NumberOfSubKeys > 0)
+ memcpy(tmpSubKeys,ParentKey->SubKeys
+ ,ParentKey->NumberOfSubKeys*sizeof(DWORD));
+ if(ParentKey->SubKeys) ExFreePool(ParentKey->SubKeys);
+ ParentKey->SubKeys=tmpSubKeys;
+ ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys+1;
+ }
+ /* FIXME : please maintain the list in alphabetic order */
+ /* to allow a dichotomic search */
+ ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
+ ObReferenceObjectByPointer(ParentKey,
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ UserMode);
+ NewKey->ParentKey = ParentKey;
+ KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+}
+
+NTSTATUS
+CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
+{
+ KIRQL OldIrql;
+ PKEY_OBJECT ParentKey;
+ DWORD Index;
+
+ ParentKey=KeyToRemove->ParentKey;
+ KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
+ /* FIXME : if list maintained in alphabetic order, use dichotomic search */
+ for (Index=0; Index < ParentKey->NumberOfSubKeys; Index++)
+ {
+ if(ParentKey->SubKeys[Index] == KeyToRemove)
+ {
+ if (Index < ParentKey->NumberOfSubKeys-1)
+ memmove(&ParentKey->SubKeys[Index]
+ ,&ParentKey->SubKeys[Index+1]
+ ,(ParentKey->NumberOfSubKeys-Index-1)*sizeof(PKEY_OBJECT));
+ ParentKey->NumberOfSubKeys--;
+ KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+ ObDereferenceObject(ParentKey);
+ return STATUS_SUCCESS;
+ }
+ }
+ KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+ return STATUS_UNSUCCESSFUL;
+}
+
+PKEY_OBJECT
+CmiScanKeyList(PKEY_OBJECT Parent,
+ PCHAR KeyName,
+ ULONG Attributes)
+{
+ KIRQL OldIrql;
+ PKEY_OBJECT CurKey;
+ DWORD Index;
+ WORD NameSize;
+ NameSize=strlen(KeyName);
+ KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
+ /* FIXME : if list maintained in alphabetic order, use dichotomic search */
+ for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
+ {
+ CurKey=Parent->SubKeys[Index];
+ if (Attributes & OBJ_CASE_INSENSITIVE)
+ {
+ if( NameSize == CurKey->NameSize
+ && !_strnicmp(KeyName,CurKey->Name,NameSize))
+ {
+ KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+ return CurKey;
+ }
+ }
+ else
+ {
+ if( NameSize == CurKey->NameSize
+ && !strncmp(KeyName,CurKey->Name,NameSize))
+ {
+ KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+ return CurKey;
+ }
+ }
+ }
+ KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+
+ return NULL;
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/cm/rtlfunc.c
+ * PURPOSE: Rtlxxx function for registry access
+ * UPDATE HISTORY:
+*/
+
+#include "cm.h"
+
+NTSTATUS STDCALL
+RtlCheckRegistryKey(IN ULONG RelativeTo,
+ IN PWSTR Path)
+{
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ Status = RtlpGetRegistryHandle(RelativeTo,
+ Path,
+ FALSE,
+ &KeyHandle);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ NtClose(KeyHandle);
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+STDCALL
+RtlCreateRegistryKey (
+ IN ULONG RelativeTo,
+ IN PWSTR Path
+ )
+{
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+
+ Status = RtlpGetRegistryHandle(RelativeTo,
+ Path,
+ TRUE,
+ &KeyHandle);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ NtClose(KeyHandle);
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+STDCALL
+RtlDeleteRegistryValue (
+ IN ULONG RelativeTo,
+ IN PWSTR Path,
+ IN PWSTR ValueName
+ )
+{
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+
+ Status = RtlpGetRegistryHandle(RelativeTo,
+ Path,
+ TRUE,
+ &KeyHandle);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ RtlInitUnicodeString(&Name,
+ ValueName);
+
+ NtDeleteValueKey(KeyHandle,
+ &Name);
+
+ NtClose(KeyHandle);
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+STDCALL
+RtlQueryRegistryValues (
+ IN ULONG RelativeTo,
+ IN PWSTR Path,
+ IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
+ IN PVOID Context,
+ IN PVOID Environment
+ )
+{
+ UNIMPLEMENTED;
+}
+
+
+NTSTATUS
+STDCALL
+RtlWriteRegistryValue (
+ IN ULONG RelativeTo,
+ IN PWSTR Path,
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength
+ )
+{
+ HANDLE KeyHandle;
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+
+ Status = RtlpGetRegistryHandle(RelativeTo,
+ Path,
+ TRUE,
+ &KeyHandle);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ RtlInitUnicodeString(&Name,
+ ValueName);
+
+ NtSetValueKey(KeyHandle,
+ &Name,
+ 0,
+ ValueType,
+ ValueData,
+ ValueLength);
+
+ NtClose(KeyHandle);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS STDCALL
+RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath)
+{
+ return STATUS_UNSUCCESSFUL;
+}
+
+/* ------------------------------------------ Private Implementation */
+
+
+NTSTATUS
+RtlpGetRegistryHandle(ULONG RelativeTo,
+ PWSTR Path,
+ BOOLEAN Create,
+ PHANDLE KeyHandle)
+{
+ UNICODE_STRING KeyName;
+ WCHAR KeyBuffer[MAX_PATH];
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+
+ if (RelativeTo & RTL_REGISTRY_HANDLE)
+ {
+ *KeyHandle = (HANDLE)Path;
+ return STATUS_SUCCESS;
+ }
+
+ if (RelativeTo & RTL_REGISTRY_OPTIONAL)
+ RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
+
+ if (RelativeTo >= RTL_REGISTRY_MAXIMUM)
+ return STATUS_INVALID_PARAMETER;
+
+ KeyName.Length = 0;
+ KeyName.MaximumLength = MAX_PATH;
+ KeyName.Buffer = KeyBuffer;
+ KeyBuffer[0] = 0;
+
+ switch (RelativeTo)
+ {
+ case RTL_REGISTRY_SERVICES:
+ RtlAppendUnicodeToString(&KeyName,
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+ break;
+
+ case RTL_REGISTRY_CONTROL:
+ RtlAppendUnicodeToString(&KeyName,
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\");
+ break;
+
+ case RTL_REGISTRY_WINDOWS_NT:
+ RtlAppendUnicodeToString(&KeyName,
+ L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
+ break;
+
+ case RTL_REGISTRY_DEVICEMAP:
+ RtlAppendUnicodeToString(&KeyName,
+ L"\\Registry\\Machine\\Hardware\\DeviceMap\\");
+ break;
+
+ case RTL_REGISTRY_USER:
+ Status = RtlFormatCurrentUserKeyPath(&KeyName);
+ if (!NT_SUCCESS(Status))
+ return Status;
+ break;
+ }
+
+ if (Path[0] != L'\\')
+ RtlAppendUnicodeToString(&KeyName,
+ L"\\");
+
+ RtlAppendUnicodeToString(&KeyName,
+ Path);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ if (Create == TRUE)
+ {
+ Status = NtCreateKey(KeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ NULL);
+ }
+ else
+ {
+ Status = NtOpenKey(KeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes);
+ }
+
+ return Status;
+}
-/* $Id: create.c,v 1.43 2001/06/04 11:26:11 chorns Exp $
+/* $Id: create.c,v 1.44 2001/06/14 21:05:07 jfilby Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
{
return (STATUS_UNSUCCESSFUL);
}
-
+
+ Irp->UserIosb = IoStatusBlock; //return iostatus
Irp->AssociatedIrp.SystemBuffer = EaBuffer;
Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
* immediately.
*/
Status = IofCallDriver(FileObject->DeviceObject, Irp );
+
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,