2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/ntfunc.c
5 * PURPOSE: Ntxxx function for registry access
11 #include <internal/ob.h>
14 #include <internal/pool.h>
15 #include <internal/registry.h>
18 #include <internal/debug.h>
22 extern POBJECT_TYPE CmiKeyType
;
23 extern PREGISTRY_FILE CmiVolatileFile
;
27 NtCreateKey(OUT PHANDLE KeyHandle
,
28 IN ACCESS_MASK DesiredAccess
,
29 IN POBJECT_ATTRIBUTES ObjectAttributes
,
31 IN PUNICODE_STRING Class
,
32 IN ULONG CreateOptions
,
33 OUT PULONG Disposition
)
38 UNICODE_STRING RemainingPath
;
42 // DPRINT("NtCreateKey (Name %wZ),KeyHandle=%x,Root=%x\n",
43 // ObjectAttributes->ObjectName,KeyHandle
44 // ,ObjectAttributes->RootDirectory);
46 /*FIXME: check for standard handle prefix and adjust objectAttributes accordingly */
48 Status
= ObFindObject(ObjectAttributes
,&Object
,&RemainingPath
,CmiKeyType
);
49 if (!NT_SUCCESS(Status
))
53 DPRINT("RP=%wZ\n",&RemainingPath
);
54 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] ==0))
56 /* Fail if the key has been deleted */
57 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
59 ObDereferenceObject(Object
);
60 return STATUS_UNSUCCESSFUL
;
63 *Disposition
= REG_OPENED_EXISTING_KEY
;
64 Status
= ObCreateHandle(PsGetCurrentProcess(),
69 DPRINT("Status=%x\n",Status
);
70 ObDereferenceObject(Object
);
73 /* if RemainingPath contains \ : must return error */
74 if((RemainingPath
.Buffer
[0])=='\\')
75 end
= wcschr((RemainingPath
.Buffer
)+1, '\\');
77 end
= wcschr((RemainingPath
.Buffer
), '\\');
80 ObDereferenceObject(Object
);
81 return STATUS_UNSUCCESSFUL
;
83 /* because NtCreateKey don't create tree */
85 DPRINT("NCK %S parent=%x\n",RemainingPath
.Buffer
,Object
);
86 Status
= ObCreateObject(KeyHandle
,
92 if (!NT_SUCCESS(Status
))
94 key
->ParentKey
= Object
;
95 // if ( (key->ParentKey ==NULL))
96 // key->ParentKey = ObjectAttributes->RootDirectory;
97 if (CreateOptions
& REG_OPTION_VOLATILE
)
98 key
->RegistryFile
=CmiVolatileFile
;
100 key
->RegistryFile
=key
->ParentKey
->RegistryFile
;
102 key
->NumberOfSubKeys
= 0;
103 key
->SizeOfSubKeys
= 0;
105 // KeAcquireSpinLock(&key->RegistryFile->RegLock, &OldIrql);
106 /* add key to subkeys of parent if needed */
107 Status
= CmiAddSubKey(key
->RegistryFile
,
110 RemainingPath
.Buffer
,
111 RemainingPath
.Length
,
115 key
->Name
= key
->KeyBlock
->Name
;
116 key
->NameSize
= key
->KeyBlock
->NameSize
;
117 if (key
->RegistryFile
== key
->ParentKey
->RegistryFile
)
119 key
->KeyBlock
->ParentKeyOffset
= key
->ParentKey
->BlockOffset
;
120 key
->KeyBlock
->SecurityKeyOffset
= key
->ParentKey
->KeyBlock
->SecurityKeyOffset
;
124 key
->KeyBlock
->ParentKeyOffset
= -1;
125 key
->KeyBlock
->SecurityKeyOffset
= -1;
126 /* this key must rest in memory unless it is deleted */
127 /* , or file is unloaded*/
128 ObReferenceObjectByPointer(key
,
129 STANDARD_RIGHTS_REQUIRED
,
133 CmiAddKeyToList(key
->ParentKey
,key
);
134 // KeReleaseSpinLock(&key->RegistryFile->RegLock, OldIrql);
135 ObDereferenceObject(key
);
136 ObDereferenceObject(Object
);
137 if (Disposition
) *Disposition
= REG_CREATED_NEW_KEY
;
139 if (!NT_SUCCESS(Status
))
144 return STATUS_SUCCESS
;
149 NtDeleteKey(IN HANDLE KeyHandle
)
152 PKEY_OBJECT KeyObject
;
154 /* Verify that the handle is valid and is a registry key */
155 Status
= ObReferenceObjectByHandle(KeyHandle
,
161 if (!NT_SUCCESS(Status
))
166 /* Set the marked for delete bit in the key object */
167 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
169 /* Dereference the object */
170 ObDereferenceObject(KeyObject
);
171 if(KeyObject
->RegistryFile
!= KeyObject
->ParentKey
->RegistryFile
)
172 ObDereferenceObject(KeyObject
);
173 /* close the handle */
174 ObDeleteHandle(PsGetCurrentProcess(),KeyHandle
);
175 /* FIXME: I think that ObDeleteHandle should dereference the object */
176 ObDereferenceObject(KeyObject
);
179 return STATUS_SUCCESS
;
188 IN KEY_INFORMATION_CLASS KeyInformationClass
,
189 OUT PVOID KeyInformation
,
191 OUT PULONG ResultLength
195 PKEY_OBJECT KeyObject
;
196 PREGISTRY_FILE RegistryFile
;
197 PKEY_BLOCK KeyBlock
, SubKeyBlock
;
198 PHASH_TABLE_BLOCK HashTableBlock
;
199 PKEY_BASIC_INFORMATION BasicInformation
;
200 PKEY_NODE_INFORMATION NodeInformation
;
201 PKEY_FULL_INFORMATION FullInformation
;
202 PDATA_BLOCK pClassData
;
204 /* Verify that the handle is valid and is a registry key */
205 Status
= ObReferenceObjectByHandle(KeyHandle
,
206 KEY_ENUMERATE_SUB_KEYS
,
211 if (!NT_SUCCESS(Status
))
216 /* Get pointer to KeyBlock */
217 KeyBlock
= KeyObject
->KeyBlock
;
218 RegistryFile
= KeyObject
->RegistryFile
;
220 /* Get pointer to SubKey */
221 if(Index
>= KeyBlock
->NumberOfSubKeys
)
223 if (RegistryFile
== CmiVolatileFile
)
225 ObDereferenceObject (KeyObject
);
226 return STATUS_NO_MORE_ENTRIES
;
231 PKEY_OBJECT CurKey
=NULL
;
232 /* search volatile keys */
233 for (i
=0; i
< KeyObject
->NumberOfSubKeys
; i
++)
235 CurKey
=KeyObject
->SubKeys
[i
];
236 if (CurKey
->RegistryFile
== CmiVolatileFile
)
238 if ( Index
-- == KeyObject
->NumberOfSubKeys
) break;
241 if(Index
>= KeyBlock
->NumberOfSubKeys
)
243 ObDereferenceObject (KeyObject
);
244 return STATUS_NO_MORE_ENTRIES
;
246 SubKeyBlock
= CurKey
->KeyBlock
;
251 HashTableBlock
= CmiGetBlock(RegistryFile
, KeyBlock
->HashTableOffset
,NULL
);
252 SubKeyBlock
= CmiGetKeyFromHashByIndex(RegistryFile
,
256 if (SubKeyBlock
== NULL
)
258 ObDereferenceObject (KeyObject
);
259 return STATUS_NO_MORE_ENTRIES
;
262 Status
= STATUS_SUCCESS
;
263 switch (KeyInformationClass
)
265 case KeyBasicInformation
:
266 /* Check size of buffer */
267 if (Length
< sizeof(KEY_BASIC_INFORMATION
) +
268 (SubKeyBlock
->NameSize
) * sizeof(WCHAR
))
270 Status
= STATUS_BUFFER_OVERFLOW
;
274 /* Fill buffer with requested info */
275 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
276 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyBlock
->LastWriteTime
.dwLowDateTime
;
277 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyBlock
->LastWriteTime
.dwHighDateTime
;
278 BasicInformation
->TitleIndex
= Index
;
279 BasicInformation
->NameLength
= (SubKeyBlock
->NameSize
) * sizeof(WCHAR
);
280 mbstowcs(BasicInformation
->Name
,
282 SubKeyBlock
->NameSize
*2);
283 // BasicInformation->Name[SubKeyBlock->NameSize] = 0;
284 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
285 SubKeyBlock
->NameSize
* sizeof(WCHAR
);
289 case KeyNodeInformation
:
290 /* Check size of buffer */
291 if (Length
< sizeof(KEY_NODE_INFORMATION
) +
292 (SubKeyBlock
->NameSize
) * sizeof(WCHAR
) +
293 (SubKeyBlock
->ClassSize
))
295 Status
= STATUS_BUFFER_OVERFLOW
;
299 /* Fill buffer with requested info */
300 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
301 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyBlock
->LastWriteTime
.dwLowDateTime
;
302 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyBlock
->LastWriteTime
.dwHighDateTime
;
303 NodeInformation
->TitleIndex
= Index
;
304 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
305 SubKeyBlock
->NameSize
* sizeof(WCHAR
);
306 NodeInformation
->ClassLength
= SubKeyBlock
->ClassSize
;
307 NodeInformation
->NameLength
= (SubKeyBlock
->NameSize
) * sizeof(WCHAR
);
308 mbstowcs(NodeInformation
->Name
,
310 SubKeyBlock
->NameSize
*2);
311 // NodeInformation->Name[SubKeyBlock->NameSize] = 0;
312 if (SubKeyBlock
->ClassSize
!= 0)
314 pClassData
=CmiGetBlock(KeyObject
->RegistryFile
315 ,SubKeyBlock
->ClassNameOffset
,NULL
);
316 wcsncpy(NodeInformation
->Name
+ SubKeyBlock
->NameSize
,
317 (PWCHAR
)pClassData
->Data
,
318 SubKeyBlock
->ClassSize
);
319 CmiReleaseBlock(RegistryFile
, pClassData
);
321 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
322 (SubKeyBlock
->NameSize
) * sizeof(WCHAR
) +
323 (SubKeyBlock
->ClassSize
);
327 case KeyFullInformation
:
328 /* check size of buffer */
329 if (Length
< sizeof(KEY_FULL_INFORMATION
) +
330 SubKeyBlock
->ClassSize
)
332 Status
= STATUS_BUFFER_OVERFLOW
;
336 /* fill buffer with requested info */
337 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
338 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyBlock
->LastWriteTime
.dwLowDateTime
;
339 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyBlock
->LastWriteTime
.dwHighDateTime
;
340 FullInformation
->TitleIndex
= Index
;
341 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
343 FullInformation
->ClassLength
= SubKeyBlock
->ClassSize
;
344 FullInformation
->SubKeys
= SubKeyBlock
->NumberOfSubKeys
;
345 FullInformation
->MaxNameLen
=
346 CmiGetMaxNameLength(RegistryFile
, SubKeyBlock
);
347 FullInformation
->MaxClassLen
=
348 CmiGetMaxClassLength(RegistryFile
, SubKeyBlock
);
349 FullInformation
->Values
= SubKeyBlock
->NumberOfValues
;
350 FullInformation
->MaxValueNameLen
=
351 CmiGetMaxValueNameLength(RegistryFile
, SubKeyBlock
);
352 FullInformation
->MaxValueDataLen
=
353 CmiGetMaxValueDataLength(RegistryFile
, SubKeyBlock
);
354 if (SubKeyBlock
->ClassSize
!= 0)
356 pClassData
=CmiGetBlock(KeyObject
->RegistryFile
357 ,SubKeyBlock
->ClassNameOffset
,NULL
);
358 wcsncpy(FullInformation
->Class
,
359 (PWCHAR
)pClassData
->Data
,
360 SubKeyBlock
->ClassSize
);
361 CmiReleaseBlock(RegistryFile
, pClassData
);
363 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
364 SubKeyBlock
->ClassSize
;
368 CmiReleaseBlock(RegistryFile
, SubKeyBlock
);
369 ObDereferenceObject (KeyObject
);
377 NtEnumerateValueKey (
380 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
381 OUT PVOID KeyValueInformation
,
383 OUT PULONG ResultLength
387 PKEY_OBJECT KeyObject
;
388 PREGISTRY_FILE RegistryFile
;
390 PVALUE_BLOCK ValueBlock
;
391 PDATA_BLOCK DataBlock
;
392 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
393 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
394 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
397 /* Verify that the handle is valid and is a registry key */
398 Status
= ObReferenceObjectByHandle(KeyHandle
,
404 if (!NT_SUCCESS(Status
))
409 /* Get pointer to KeyBlock */
410 KeyBlock
= KeyObject
->KeyBlock
;
411 RegistryFile
= KeyObject
->RegistryFile
;
413 /* Get Value block of interest */
414 Status
= CmiGetValueFromKeyByIndex(RegistryFile
,
418 if (!NT_SUCCESS(Status
))
420 ObDereferenceObject(KeyObject
);
423 else if (ValueBlock
!= NULL
)
425 switch (KeyValueInformationClass
)
427 case KeyValueBasicInformation
:
428 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
429 (ValueBlock
->NameSize
+ 1) * sizeof(WCHAR
);
430 if (Length
< *ResultLength
)
432 Status
= STATUS_BUFFER_OVERFLOW
;
436 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
438 ValueBasicInformation
->TitleIndex
= 0;
439 ValueBasicInformation
->Type
= ValueBlock
->DataType
;
440 ValueBasicInformation
->NameLength
=
441 (ValueBlock
->NameSize
+ 1) * sizeof(WCHAR
);
442 mbstowcs(ValueBasicInformation
->Name
, ValueBlock
->Name
443 ,ValueBlock
->NameSize
*2);
444 ValueBasicInformation
->Name
[ValueBlock
->NameSize
]=0;
448 case KeyValuePartialInformation
:
449 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
450 (ValueBlock
->DataSize
& LONG_MAX
);
451 if (Length
< *ResultLength
)
453 Status
= STATUS_BUFFER_OVERFLOW
;
457 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
459 ValuePartialInformation
->TitleIndex
= 0;
460 ValuePartialInformation
->Type
= ValueBlock
->DataType
;
461 ValuePartialInformation
->DataLength
= ValueBlock
->DataSize
& LONG_MAX
;
462 if(ValueBlock
->DataSize
>0)
464 DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,NULL
);
465 RtlCopyMemory(ValuePartialInformation
->Data
,
467 ValueBlock
->DataSize
& LONG_MAX
);
468 CmiReleaseBlock(RegistryFile
, DataBlock
);
472 RtlCopyMemory(ValuePartialInformation
->Data
,
473 &ValueBlock
->DataOffset
,
474 ValueBlock
->DataSize
& LONG_MAX
);
476 DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,NULL
);
480 case KeyValueFullInformation
:
481 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
482 (ValueBlock
->NameSize
) * sizeof(WCHAR
) + (ValueBlock
->DataSize
& LONG_MAX
);
483 if (Length
< *ResultLength
)
485 Status
= STATUS_BUFFER_OVERFLOW
;
489 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
491 ValueFullInformation
->TitleIndex
= 0;
492 ValueFullInformation
->Type
= ValueBlock
->DataType
;
493 ValueFullInformation
->DataOffset
=
494 (DWORD
)ValueFullInformation
->Name
- (DWORD
)ValueFullInformation
495 + (ValueBlock
->NameSize
) * sizeof(WCHAR
);
496 ValueFullInformation
->DataOffset
=
497 (ValueFullInformation
->DataOffset
+3) &0xfffffffc;
498 ValueFullInformation
->DataLength
= ValueBlock
->DataSize
& LONG_MAX
;
499 ValueFullInformation
->NameLength
=
500 (ValueBlock
->NameSize
) * sizeof(WCHAR
);
501 mbstowcs(ValueFullInformation
->Name
, ValueBlock
->Name
502 ,ValueBlock
->NameSize
*2);
503 if(ValueBlock
->DataSize
>0)
505 DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,NULL
);
506 RtlCopyMemory((char *)(ValueFullInformation
)
507 + ValueFullInformation
->DataOffset
,
509 ValueBlock
->DataSize
& LONG_MAX
);
510 CmiReleaseBlock(RegistryFile
, DataBlock
);
514 RtlCopyMemory((char *)(ValueFullInformation
)
515 + ValueFullInformation
->DataOffset
,
516 &ValueBlock
->DataOffset
,
517 ValueBlock
->DataSize
& LONG_MAX
);
525 Status
= STATUS_UNSUCCESSFUL
;
527 ObDereferenceObject(KeyObject
);
534 NtFlushKey(IN HANDLE KeyHandle
)
537 PKEY_OBJECT KeyObject
;
538 PREGISTRY_FILE RegistryFile
;
539 WCHAR LogName
[MAX_PATH
];
541 // HANDLE FileHandleLog;
542 OBJECT_ATTRIBUTES ObjectAttributes
;
544 UNICODE_STRING TmpFileName
;
546 LARGE_INTEGER fileOffset
;
548 /* Verify that the handle is valid and is a registry key */
549 Status
= ObReferenceObjectByHandle(KeyHandle
,
555 if (!NT_SUCCESS(Status
))
559 RegistryFile
= KeyObject
->RegistryFile
;
560 // KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
561 /* then write changed blocks in .log */
562 wcscpy(LogName
,RegistryFile
->Filename
);
563 wcscat(LogName
,L
".log");
564 RtlInitUnicodeString (&TmpFileName
, LogName
);
565 InitializeObjectAttributes(&ObjectAttributes
,
570 /* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
571 so we can't create log file
572 Status = ZwCreateFile(&FileHandleLog,
575 NULL, 0, FILE_ATTRIBUTE_NORMAL,
576 0, FILE_SUPERSEDE, 0, NULL, 0);
577 Status = ZwWriteFile(FileHandleLog,
579 RegistryFile->HeaderBlock,
580 sizeof(HEADER_BLOCK),
582 for (i=0; i < RegistryFile->BlockListSize ; i++)
584 if( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
585 > RegistryFile->HeaderBlock->DateModified.dwHighDateTime
586 ||( RegistryFile->BlockList[i]->DateModified.dwHighDateTime
587 == RegistryFile->HeaderBlock->DateModified.dwHighDateTime
588 && RegistryFile->BlockList[i]->DateModified.dwLowDateTime
589 > RegistryFile->HeaderBlock->DateModified.dwLowDateTime)
591 Status = ZwWriteFile(FileHandleLog,
593 RegistryFile->BlockList[i],
594 RegistryFile->BlockList[i]->BlockSize ,
597 ZwClose(FileHandleLog);
599 /* update header of registryfile with Version >VersionOld */
600 /* this allow recover if system crash while updating hove file */
601 RtlInitUnicodeString (&TmpFileName
, RegistryFile
->Filename
);
602 InitializeObjectAttributes(&ObjectAttributes
,
607 Status
= NtOpenFile(&FileHandle
,
611 RegistryFile
->HeaderBlock
->Version
++;
613 Status
= ZwWriteFile(FileHandle
,
615 RegistryFile
->HeaderBlock
,
616 sizeof(HEADER_BLOCK
),
619 /* update changed blocks in file */
620 fileOffset
.u
.HighPart
= 0;
621 for (i
=0; i
< RegistryFile
->BlockListSize
; i
++)
623 if( RegistryFile
->BlockList
[i
]->DateModified
.dwHighDateTime
624 > RegistryFile
->HeaderBlock
->DateModified
.dwHighDateTime
625 ||( RegistryFile
->BlockList
[i
]->DateModified
.dwHighDateTime
626 == RegistryFile
->HeaderBlock
->DateModified
.dwHighDateTime
627 && RegistryFile
->BlockList
[i
]->DateModified
.dwLowDateTime
628 > RegistryFile
->HeaderBlock
->DateModified
.dwLowDateTime
)
631 fileOffset
.u
.LowPart
= RegistryFile
->BlockList
[i
]->BlockOffset
+4096;
632 Status
= NtWriteFile(FileHandle
,
634 RegistryFile
->BlockList
[i
],
635 RegistryFile
->BlockList
[i
]->BlockSize
,
639 /* change version in header */
640 RegistryFile
->HeaderBlock
->VersionOld
= RegistryFile
->HeaderBlock
->Version
;
641 ZwQuerySystemTime((PTIME
) &RegistryFile
->HeaderBlock
->DateModified
);
642 /* calculate checksum */
643 RegistryFile
->HeaderBlock
->Checksum
= 0;
644 pEntDword
= (DWORD
*) RegistryFile
->HeaderBlock
;
645 for (i
=0 ; i
<127 ; i
++)
647 RegistryFile
->HeaderBlock
->Checksum
^= pEntDword
[i
];
649 /* write new header */
650 fileOffset
.u
.LowPart
= 0;
651 Status
= ZwWriteFile(FileHandle
,
653 RegistryFile
->HeaderBlock
,
654 sizeof(HEADER_BLOCK
),
657 // KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
658 return STATUS_SUCCESS
;
663 NtOpenKey(OUT PHANDLE KeyHandle
,
664 IN ACCESS_MASK DesiredAccess
,
665 IN POBJECT_ATTRIBUTES ObjectAttributes
)
669 UNICODE_STRING RemainingPath
;
671 RemainingPath
.Buffer
=NULL
;
672 Status
= ObFindObject(ObjectAttributes
,&Object
,&RemainingPath
,CmiKeyType
);
673 DPRINT("NTOpenKey : after ObFindObject\n");
674 DPRINT("RB.B=%x\n",RemainingPath
.Buffer
);
675 if(RemainingPath
.Buffer
!= 0 && RemainingPath
.Buffer
[0] !=0)
677 DPRINT("NTOpenKey3 : after ObFindObject\n");
678 ObDereferenceObject(Object
);
679 DPRINT("RP=%wZ\n",&RemainingPath
);
680 return STATUS_UNSUCCESSFUL
;
682 DPRINT("NTOpenKey2 : after ObFindObject\n");
683 /* Fail if the key has been deleted */
684 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
686 ObDereferenceObject(Object
);
687 return STATUS_UNSUCCESSFUL
;
690 Status
= ObCreateHandle(
691 PsGetCurrentProcess(),
697 ObDereferenceObject(Object
);
698 if (!NT_SUCCESS(Status
))
703 return STATUS_SUCCESS
;
711 IN KEY_INFORMATION_CLASS KeyInformationClass
,
712 OUT PVOID KeyInformation
,
714 OUT PULONG ResultLength
718 PKEY_OBJECT KeyObject
;
719 PREGISTRY_FILE RegistryFile
;
721 PKEY_BASIC_INFORMATION BasicInformation
;
722 PKEY_NODE_INFORMATION NodeInformation
;
723 PKEY_FULL_INFORMATION FullInformation
;
724 PDATA_BLOCK pClassData
;
726 /* Verify that the handle is valid and is a registry key */
727 Status
= ObReferenceObjectByHandle(KeyHandle
,
733 if (!NT_SUCCESS(Status
))
738 /* Get pointer to KeyBlock */
739 KeyBlock
= KeyObject
->KeyBlock
;
740 RegistryFile
= KeyObject
->RegistryFile
;
742 Status
= STATUS_SUCCESS
;
743 switch (KeyInformationClass
)
745 case KeyBasicInformation
:
746 /* Check size of buffer */
747 if (Length
< sizeof(KEY_BASIC_INFORMATION
) +
748 KeyObject
->NameSize
* sizeof(WCHAR
))
750 Status
= STATUS_BUFFER_OVERFLOW
;
754 /* Fill buffer with requested info */
755 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
756 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyBlock
->LastWriteTime
.dwLowDateTime
;
757 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyBlock
->LastWriteTime
.dwHighDateTime
;
758 BasicInformation
->TitleIndex
= 0;
759 BasicInformation
->NameLength
=
760 (KeyObject
->NameSize
) * sizeof(WCHAR
);
761 mbstowcs(BasicInformation
->Name
,
763 KeyObject
->NameSize
*sizeof(WCHAR
));
764 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
765 KeyObject
->NameSize
* sizeof(WCHAR
);
769 case KeyNodeInformation
:
770 /* Check size of buffer */
771 if (Length
< sizeof(KEY_NODE_INFORMATION
) +
772 (KeyObject
->NameSize
) * sizeof(WCHAR
) +
773 KeyBlock
->ClassSize
)
775 Status
= STATUS_BUFFER_OVERFLOW
;
779 /* Fill buffer with requested info */
780 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
781 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyBlock
->LastWriteTime
.dwLowDateTime
;
782 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyBlock
->LastWriteTime
.dwHighDateTime
;
783 NodeInformation
->TitleIndex
= 0;
784 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
785 KeyObject
->NameSize
* sizeof(WCHAR
);
786 NodeInformation
->ClassLength
= KeyBlock
->ClassSize
;
787 NodeInformation
->NameLength
=
788 (KeyObject
->NameSize
) * sizeof(WCHAR
);
789 mbstowcs(NodeInformation
->Name
,
791 KeyObject
->NameSize
*2);
792 if (KeyBlock
->ClassSize
!= 0)
794 pClassData
=CmiGetBlock(KeyObject
->RegistryFile
795 ,KeyBlock
->ClassNameOffset
,NULL
);
796 wcsncpy(NodeInformation
->Name
+ (KeyObject
->NameSize
)*sizeof(WCHAR
),
797 (PWCHAR
)pClassData
->Data
,
798 KeyBlock
->ClassSize
);
799 CmiReleaseBlock(RegistryFile
, pClassData
);
801 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
802 (KeyObject
->NameSize
) * sizeof(WCHAR
) +
807 case KeyFullInformation
:
808 /* Check size of buffer */
809 if (Length
< sizeof(KEY_FULL_INFORMATION
) +
810 KeyBlock
->ClassSize
)
812 Status
= STATUS_BUFFER_OVERFLOW
;
816 /* Fill buffer with requested info */
817 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
818 FullInformation
->LastWriteTime
.u
.LowPart
= KeyBlock
->LastWriteTime
.dwLowDateTime
;
819 FullInformation
->LastWriteTime
.u
.HighPart
= KeyBlock
->LastWriteTime
.dwHighDateTime
;
820 FullInformation
->TitleIndex
= 0;
821 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
823 FullInformation
->ClassLength
= KeyBlock
->ClassSize
;
824 FullInformation
->SubKeys
= KeyBlock
->NumberOfSubKeys
;
825 FullInformation
->MaxNameLen
=
826 CmiGetMaxNameLength(RegistryFile
, KeyBlock
);
827 FullInformation
->MaxClassLen
=
828 CmiGetMaxClassLength(RegistryFile
, KeyBlock
);
829 FullInformation
->Values
= KeyBlock
->NumberOfValues
;
830 FullInformation
->MaxValueNameLen
=
831 CmiGetMaxValueNameLength(RegistryFile
, KeyBlock
);
832 FullInformation
->MaxValueDataLen
=
833 CmiGetMaxValueDataLength(RegistryFile
, KeyBlock
);
834 if (KeyBlock
->ClassSize
!= 0)
836 pClassData
=CmiGetBlock(KeyObject
->RegistryFile
837 ,KeyBlock
->ClassNameOffset
,NULL
);
838 wcsncpy(FullInformation
->Class
,
839 (PWCHAR
)pClassData
->Data
,
840 KeyBlock
->ClassSize
);
841 CmiReleaseBlock(RegistryFile
, pClassData
);
843 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
844 KeyBlock
->ClassSize
;
848 ObDereferenceObject (KeyObject
);
858 IN PUNICODE_STRING ValueName
,
859 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
860 OUT PVOID KeyValueInformation
,
862 OUT PULONG ResultLength
866 PKEY_OBJECT KeyObject
;
867 PREGISTRY_FILE RegistryFile
;
869 PVALUE_BLOCK ValueBlock
;
870 PDATA_BLOCK DataBlock
;
871 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
872 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
873 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
874 char ValueName2
[MAX_PATH
];
876 wcstombs(ValueName2
,ValueName
->Buffer
,ValueName
->Length
>>1);
877 ValueName2
[ValueName
->Length
>>1]=0;
879 /* Verify that the handle is valid and is a registry key */
880 Status
= ObReferenceObjectByHandle(KeyHandle
,
886 if (!NT_SUCCESS(Status
))
891 /* Get pointer to KeyBlock */
892 KeyBlock
= KeyObject
->KeyBlock
;
893 RegistryFile
= KeyObject
->RegistryFile
;
894 /* Get Value block of interest */
895 Status
= CmiScanKeyForValue(RegistryFile
,
899 if (!NT_SUCCESS(Status
))
901 ObDereferenceObject(KeyObject
);
904 else if (ValueBlock
!= NULL
)
906 switch (KeyValueInformationClass
)
908 case KeyValueBasicInformation
:
909 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
910 ValueBlock
->NameSize
* sizeof(WCHAR
);
911 if (Length
< *ResultLength
)
913 Status
= STATUS_BUFFER_OVERFLOW
;
917 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
919 ValueBasicInformation
->TitleIndex
= 0;
920 ValueBasicInformation
->Type
= ValueBlock
->DataType
;
921 ValueBasicInformation
->NameLength
=
922 (ValueBlock
->NameSize
+ 1) * sizeof(WCHAR
);
923 mbstowcs(ValueBasicInformation
->Name
, ValueBlock
->Name
,ValueBlock
->NameSize
*2);
924 ValueBasicInformation
->Name
[ValueBlock
->NameSize
]=0;
928 case KeyValuePartialInformation
:
929 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
930 (ValueBlock
->DataSize
& LONG_MAX
);
931 if (Length
< *ResultLength
)
933 Status
= STATUS_BUFFER_OVERFLOW
;
937 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
939 ValuePartialInformation
->TitleIndex
= 0;
940 ValuePartialInformation
->Type
= ValueBlock
->DataType
;
941 ValuePartialInformation
->DataLength
= ValueBlock
->DataSize
& LONG_MAX
;
942 if(ValueBlock
->DataSize
>0)
944 DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,NULL
);
945 RtlCopyMemory(ValuePartialInformation
->Data
,
947 ValueBlock
->DataSize
& LONG_MAX
);
948 CmiReleaseBlock(RegistryFile
, DataBlock
);
952 RtlCopyMemory(ValuePartialInformation
->Data
,
953 &ValueBlock
->DataOffset
,
954 ValueBlock
->DataSize
& LONG_MAX
);
959 case KeyValueFullInformation
:
960 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
)
961 + (ValueBlock
->NameSize
-1) * sizeof(WCHAR
)
962 + (ValueBlock
->DataSize
& LONG_MAX
);
963 if (Length
< *ResultLength
)
965 Status
= STATUS_BUFFER_OVERFLOW
;
969 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
971 ValueFullInformation
->TitleIndex
= 0;
972 ValueFullInformation
->Type
= ValueBlock
->DataType
;
973 ValueFullInformation
->DataOffset
=
974 (DWORD
)ValueFullInformation
->Name
- (DWORD
)ValueFullInformation
975 + (ValueBlock
->NameSize
) * sizeof(WCHAR
);
976 ValueFullInformation
->DataOffset
=
977 (ValueFullInformation
->DataOffset
+3) &0xfffffffc;
978 ValueFullInformation
->DataLength
= ValueBlock
->DataSize
& LONG_MAX
;
979 ValueFullInformation
->NameLength
=
980 (ValueBlock
->NameSize
) * sizeof(WCHAR
);
981 mbstowcs(ValueFullInformation
->Name
, ValueBlock
->Name
,ValueBlock
->NameSize
*2);
982 if(ValueBlock
->DataSize
>0)
984 DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,NULL
);
985 RtlCopyMemory((char *)(ValueFullInformation
)
986 + ValueFullInformation
->DataOffset
,
988 ValueBlock
->DataSize
& LONG_MAX
);
989 CmiReleaseBlock(RegistryFile
, DataBlock
);
993 RtlCopyMemory((char *)(ValueFullInformation
)
994 + ValueFullInformation
->DataOffset
,
995 &ValueBlock
->DataOffset
,
996 ValueBlock
->DataSize
& LONG_MAX
);
1004 Status
= STATUS_UNSUCCESSFUL
;
1006 ObDereferenceObject(KeyObject
);
1015 IN HANDLE KeyHandle
,
1016 IN PUNICODE_STRING ValueName
,
1017 IN ULONG TitleIndex
,
1024 PKEY_OBJECT KeyObject
;
1025 PREGISTRY_FILE RegistryFile
;
1026 PKEY_BLOCK KeyBlock
;
1027 PVALUE_BLOCK ValueBlock
;
1028 BLOCK_OFFSET VBOffset
;
1029 char ValueName2
[MAX_PATH
];
1030 PDATA_BLOCK DataBlock
, NewDataBlock
;
1034 wcstombs(ValueName2
,ValueName
->Buffer
,ValueName
->Length
>>1);
1035 ValueName2
[ValueName
->Length
>>1]=0;
1037 /* Verify that the handle is valid and is a registry key */
1038 Status
= ObReferenceObjectByHandle(KeyHandle
,
1042 (PVOID
*)&KeyObject
,
1044 if (!NT_SUCCESS(Status
))
1047 /* Get pointer to KeyBlock */
1048 KeyBlock
= KeyObject
->KeyBlock
;
1049 RegistryFile
= KeyObject
->RegistryFile
;
1050 Status
= CmiScanKeyForValue(RegistryFile
,
1053 &ValueBlock
, &VBOffset
);
1054 if (!NT_SUCCESS(Status
))
1056 ObDereferenceObject (KeyObject
);
1059 // KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
1060 if (ValueBlock
== NULL
)
1062 Status
= CmiAddValueToKey(RegistryFile
,
1068 if (!NT_SUCCESS(Status
))
1070 ObDereferenceObject (KeyObject
);
1075 /* FIXME if datasize <=4 then write in valueblock directly */
1078 if (( ValueBlock
->DataSize
<0 )
1079 && (DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,NULL
)))
1081 CmiDestroyBlock(RegistryFile
, DataBlock
, ValueBlock
->DataOffset
);
1083 RtlCopyMemory(&ValueBlock
->DataOffset
, Data
, DataSize
);
1084 ValueBlock
->DataSize
= DataSize
| 0x80000000;
1085 ValueBlock
->DataType
= Type
;
1086 memcpy(&ValueBlock
->DataOffset
, Data
, DataSize
);
1088 /* If new data size is <= current then overwrite current data */
1089 else if (DataSize
<= (ValueBlock
->DataSize
& 0x7fffffff))
1091 DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,&pHeap
);
1092 RtlCopyMemory(DataBlock
->Data
, Data
, DataSize
);
1093 ValueBlock
->DataSize
= DataSize
;
1094 ValueBlock
->DataType
= Type
;
1095 CmiReleaseBlock(RegistryFile
, DataBlock
);
1096 /* update time of heap */
1097 if(RegistryFile
->Filename
)
1098 ZwQuerySystemTime((PTIME
) &pHeap
->DateModified
);
1102 BLOCK_OFFSET NewOffset
;
1103 /* Destroy current data block and allocate a new one */
1104 if (( ValueBlock
->DataSize
<0 )
1105 && (DataBlock
= CmiGetBlock(RegistryFile
, ValueBlock
->DataOffset
,NULL
)))
1107 CmiDestroyBlock(RegistryFile
, DataBlock
, ValueBlock
->DataOffset
);
1109 Status
= CmiAllocateBlock(RegistryFile
,
1110 (PVOID
*)&NewDataBlock
,
1111 DataSize
,&NewOffset
);
1112 RtlCopyMemory(&NewDataBlock
->Data
[0], Data
, DataSize
);
1113 ValueBlock
->DataSize
= DataSize
;
1114 ValueBlock
->DataType
= Type
;
1115 CmiReleaseBlock(RegistryFile
, NewDataBlock
);
1116 ValueBlock
->DataOffset
= NewOffset
;
1118 /* update time of heap */
1119 if(RegistryFile
->Filename
&& CmiGetBlock(RegistryFile
, VBOffset
,&pHeap
))
1120 ZwQuerySystemTime((PTIME
) &pHeap
->DateModified
);
1123 // KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
1124 ObDereferenceObject (KeyObject
);
1132 IN HANDLE KeyHandle
,
1133 IN PUNICODE_STRING ValueName
1137 PKEY_OBJECT KeyObject
;
1138 PREGISTRY_FILE RegistryFile
;
1139 PKEY_BLOCK KeyBlock
;
1140 char ValueName2
[MAX_PATH
];
1143 wcstombs(ValueName2
,ValueName
->Buffer
,ValueName
->Length
>>1);
1144 ValueName2
[ValueName
->Length
>>1]=0;
1146 /* Verify that the handle is valid and is a registry key */
1147 Status
= ObReferenceObjectByHandle(KeyHandle
,
1151 (PVOID
*)&KeyObject
,
1153 if (!NT_SUCCESS(Status
))
1158 /* Get pointer to KeyBlock */
1159 KeyBlock
= KeyObject
->KeyBlock
;
1160 RegistryFile
= KeyObject
->RegistryFile
;
1161 // KeAcquireSpinLock(&RegistryFile->RegLock, &OldIrql);
1162 Status
= CmiDeleteValueFromKey(RegistryFile
,
1165 // KeReleaseSpinLock(&RegistryFile->RegLock, OldIrql);
1166 ObDereferenceObject(KeyObject
);
1175 POBJECT_ATTRIBUTES ObjectAttributes
1178 return NtLoadKey2(KeyHandle
,
1188 POBJECT_ATTRIBUTES ObjectAttributes
,
1199 IN HANDLE KeyHandle
,
1201 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1202 IN PVOID ApcContext OPTIONAL
,
1203 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1204 IN ULONG CompletionFilter
,
1205 IN BOOLEAN Asynchroneous
,
1206 OUT PVOID ChangeBuffer
,
1208 IN BOOLEAN WatchSubtree
1217 NtQueryMultipleValueKey (
1218 IN HANDLE KeyHandle
,
1219 IN PWVALENT ListOfValuesToQuery
,
1220 IN ULONG NumberOfItems
,
1221 OUT PVOID MultipleValueInformation
,
1223 OUT PULONG ReturnLength
1233 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1235 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
1245 IN HANDLE KeyHandle
,
1246 IN HANDLE FileHandle
,
1247 IN ULONG RestoreFlags
1257 IN HANDLE KeyHandle
,
1258 IN HANDLE FileHandle
1267 NtSetInformationKey (
1268 IN HANDLE KeyHandle
,
1269 IN CINT KeyInformationClass
,
1270 IN PVOID KeyInformation
,
1271 IN ULONG KeyInformationLength
1290 NtInitializeRegistry (
1295 return STATUS_SUCCESS
;