Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenntapi.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/config/cmapi.c 00005 * PURPOSE: Configuration Manager - Internal Registry APIs 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Eric Kohl 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include "ntoskrnl.h" 00013 #define NDEBUG 00014 #include "debug.h" 00015 00016 BOOLEAN CmBootAcceptFirstTime = TRUE; 00017 BOOLEAN CmFirstTime = TRUE; 00018 00019 /* FUNCTIONS *****************************************************************/ 00020 00021 NTSTATUS 00022 NTAPI 00023 NtCreateKey(OUT PHANDLE KeyHandle, 00024 IN ACCESS_MASK DesiredAccess, 00025 IN POBJECT_ATTRIBUTES ObjectAttributes, 00026 IN ULONG TitleIndex, 00027 IN PUNICODE_STRING Class OPTIONAL, 00028 IN ULONG CreateOptions, 00029 OUT PULONG Disposition OPTIONAL) 00030 { 00031 NTSTATUS Status; 00032 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00033 CM_PARSE_CONTEXT ParseContext = {0}; 00034 HANDLE Handle; 00035 PAGED_CODE(); 00036 DPRINT("NtCreateKey(OB name %wZ)\n", ObjectAttributes->ObjectName); 00037 00038 /* Check for user-mode caller */ 00039 if (PreviousMode != KernelMode) 00040 { 00041 /* Prepare to probe parameters */ 00042 _SEH2_TRY 00043 { 00044 /* Check if we have a class */ 00045 if (Class) 00046 { 00047 /* Probe it */ 00048 ParseContext.Class = ProbeForReadUnicodeString(Class); 00049 ProbeForRead(ParseContext.Class.Buffer, 00050 ParseContext.Class.Length, 00051 sizeof(WCHAR)); 00052 } 00053 00054 /* Probe the key handle */ 00055 ProbeForWriteHandle(KeyHandle); 00056 *KeyHandle = NULL; 00057 00058 /* Probe object attributes */ 00059 ProbeForRead(ObjectAttributes, 00060 sizeof(OBJECT_ATTRIBUTES), 00061 sizeof(ULONG)); 00062 00063 if (Disposition) ProbeForWriteUlong(Disposition); 00064 } 00065 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00066 { 00067 /* Return the exception code */ 00068 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00069 } 00070 _SEH2_END; 00071 } 00072 else 00073 { 00074 /* Save the class directly */ 00075 if (Class) ParseContext.Class = *Class; 00076 } 00077 00078 /* Setup the parse context */ 00079 ParseContext.CreateOperation = TRUE; 00080 ParseContext.CreateOptions = CreateOptions; 00081 00082 /* Do the create */ 00083 Status = ObOpenObjectByName(ObjectAttributes, 00084 CmpKeyObjectType, 00085 PreviousMode, 00086 NULL, 00087 DesiredAccess, 00088 &ParseContext, 00089 &Handle); 00090 00091 _SEH2_TRY 00092 { 00093 /* Return data to user */ 00094 if (NT_SUCCESS(Status)) *KeyHandle = Handle; 00095 if (Disposition) *Disposition = ParseContext.Disposition; 00096 } 00097 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00098 { 00099 /* Get the status */ 00100 Status = _SEH2_GetExceptionCode(); 00101 } 00102 _SEH2_END; 00103 00104 /* Return status */ 00105 return Status; 00106 } 00107 00108 NTSTATUS 00109 NTAPI 00110 NtOpenKey(OUT PHANDLE KeyHandle, 00111 IN ACCESS_MASK DesiredAccess, 00112 IN POBJECT_ATTRIBUTES ObjectAttributes) 00113 { 00114 CM_PARSE_CONTEXT ParseContext = {0}; 00115 HANDLE Handle; 00116 NTSTATUS Status; 00117 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00118 PAGED_CODE(); 00119 DPRINT("NtOpenKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName); 00120 00121 /* Check for user-mode caller */ 00122 if (PreviousMode != KernelMode) 00123 { 00124 /* Prepare to probe parameters */ 00125 _SEH2_TRY 00126 { 00127 /* Probe the key handle */ 00128 ProbeForWriteHandle(KeyHandle); 00129 *KeyHandle = NULL; 00130 00131 /* Probe object attributes */ 00132 ProbeForRead(ObjectAttributes, 00133 sizeof(OBJECT_ATTRIBUTES), 00134 sizeof(ULONG)); 00135 } 00136 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00137 { 00138 /* Return the exception code */ 00139 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00140 } 00141 _SEH2_END; 00142 } 00143 00144 /* Just let the object manager handle this */ 00145 Status = ObOpenObjectByName(ObjectAttributes, 00146 CmpKeyObjectType, 00147 ExGetPreviousMode(), 00148 NULL, 00149 DesiredAccess, 00150 &ParseContext, 00151 &Handle); 00152 00153 /* Only do this if we succeeded */ 00154 if (NT_SUCCESS(Status)) 00155 { 00156 _SEH2_TRY 00157 { 00158 /* Return the handle to caller */ 00159 *KeyHandle = Handle; 00160 } 00161 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00162 { 00163 /* Get the status */ 00164 Status = _SEH2_GetExceptionCode(); 00165 } 00166 _SEH2_END; 00167 } 00168 00169 /* Return status */ 00170 return Status; 00171 } 00172 00173 00174 NTSTATUS 00175 NTAPI 00176 NtDeleteKey(IN HANDLE KeyHandle) 00177 { 00178 PCM_KEY_BODY KeyObject; 00179 NTSTATUS Status; 00180 REG_DELETE_KEY_INFORMATION DeleteKeyInfo; 00181 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00182 PAGED_CODE(); 00183 DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle); 00184 00185 /* Verify that the handle is valid and is a registry key */ 00186 Status = ObReferenceObjectByHandle(KeyHandle, 00187 DELETE, 00188 CmpKeyObjectType, 00189 ExGetPreviousMode(), 00190 (PVOID*)&KeyObject, 00191 NULL); 00192 if (!NT_SUCCESS(Status)) return Status; 00193 00194 /* Setup the callback */ 00195 PostOperationInfo.Object = (PVOID)KeyObject; 00196 DeleteKeyInfo.Object = (PVOID)KeyObject; 00197 Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo); 00198 if (NT_SUCCESS(Status)) 00199 { 00200 /* Check if we are read-only */ 00201 if ((KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY) || 00202 (KeyObject->KeyControlBlock->ParentKcb->ExtFlags & CM_KCB_READ_ONLY_KEY)) 00203 { 00204 /* Fail */ 00205 Status = STATUS_ACCESS_DENIED; 00206 } 00207 else 00208 { 00209 /* Call the internal API */ 00210 Status = CmDeleteKey(KeyObject); 00211 } 00212 00213 /* Do post callback */ 00214 PostOperationInfo.Status = Status; 00215 CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo); 00216 } 00217 00218 /* Dereference the object */ 00219 ObDereferenceObject(KeyObject); 00220 return Status; 00221 } 00222 00223 NTSTATUS 00224 NTAPI 00225 NtEnumerateKey(IN HANDLE KeyHandle, 00226 IN ULONG Index, 00227 IN KEY_INFORMATION_CLASS KeyInformationClass, 00228 OUT PVOID KeyInformation, 00229 IN ULONG Length, 00230 OUT PULONG ResultLength) 00231 { 00232 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00233 NTSTATUS Status; 00234 PCM_KEY_BODY KeyObject; 00235 REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo; 00236 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00237 PAGED_CODE(); 00238 DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n", 00239 KeyHandle, Index, KeyInformationClass, Length); 00240 00241 /* Reject classes we don't know about */ 00242 if ((KeyInformationClass != KeyBasicInformation) && 00243 (KeyInformationClass != KeyNodeInformation) && 00244 (KeyInformationClass != KeyFullInformation)) 00245 { 00246 /* Fail */ 00247 return STATUS_INVALID_PARAMETER; 00248 } 00249 00250 /* Verify that the handle is valid and is a registry key */ 00251 Status = ObReferenceObjectByHandle(KeyHandle, 00252 KEY_ENUMERATE_SUB_KEYS, 00253 CmpKeyObjectType, 00254 ExGetPreviousMode(), 00255 (PVOID*)&KeyObject, 00256 NULL); 00257 if (!NT_SUCCESS(Status)) return Status; 00258 00259 if (PreviousMode != KernelMode) 00260 { 00261 _SEH2_TRY 00262 { 00263 ProbeForWriteUlong(ResultLength); 00264 ProbeForWrite(KeyInformation, 00265 Length, 00266 sizeof(ULONG)); 00267 } 00268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00269 { 00270 /* Dereference and return status */ 00271 ObDereferenceObject(KeyObject); 00272 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00273 } 00274 _SEH2_END; 00275 } 00276 00277 /* Setup the callback */ 00278 PostOperationInfo.Object = (PVOID)KeyObject; 00279 EnumerateKeyInfo.Object = (PVOID)KeyObject; 00280 EnumerateKeyInfo.Index = Index; 00281 EnumerateKeyInfo.KeyInformationClass = KeyInformationClass; 00282 EnumerateKeyInfo.Length = Length; 00283 EnumerateKeyInfo.ResultLength = ResultLength; 00284 00285 /* Do the callback */ 00286 Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo); 00287 if (NT_SUCCESS(Status)) 00288 { 00289 /* Call the internal API */ 00290 Status = CmEnumerateKey(KeyObject->KeyControlBlock, 00291 Index, 00292 KeyInformationClass, 00293 KeyInformation, 00294 Length, 00295 ResultLength); 00296 00297 /* Do the post callback */ 00298 PostOperationInfo.Status = Status; 00299 CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo); 00300 } 00301 00302 /* Dereference and return status */ 00303 ObDereferenceObject(KeyObject); 00304 return Status; 00305 } 00306 00307 NTSTATUS 00308 NTAPI 00309 NtEnumerateValueKey(IN HANDLE KeyHandle, 00310 IN ULONG Index, 00311 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, 00312 OUT PVOID KeyValueInformation, 00313 IN ULONG Length, 00314 OUT PULONG ResultLength) 00315 { 00316 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00317 NTSTATUS Status; 00318 PCM_KEY_BODY KeyObject; 00319 REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo; 00320 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00321 PAGED_CODE(); 00322 DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n", 00323 KeyHandle, Index, KeyValueInformationClass, Length); 00324 00325 /* Reject classes we don't know about */ 00326 if ((KeyValueInformationClass != KeyValueBasicInformation) && 00327 (KeyValueInformationClass != KeyValueFullInformation) && 00328 (KeyValueInformationClass != KeyValuePartialInformation)) 00329 { 00330 /* Fail */ 00331 return STATUS_INVALID_PARAMETER; 00332 } 00333 00334 /* Verify that the handle is valid and is a registry key */ 00335 Status = ObReferenceObjectByHandle(KeyHandle, 00336 KEY_QUERY_VALUE, 00337 CmpKeyObjectType, 00338 ExGetPreviousMode(), 00339 (PVOID*)&KeyObject, 00340 NULL); 00341 if (!NT_SUCCESS(Status)) return Status; 00342 00343 if (PreviousMode != KernelMode) 00344 { 00345 _SEH2_TRY 00346 { 00347 ProbeForWriteUlong(ResultLength); 00348 ProbeForWrite(KeyValueInformation, 00349 Length, 00350 sizeof(ULONG)); 00351 } 00352 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00353 { 00354 /* Dereference and return status */ 00355 ObDereferenceObject(KeyObject); 00356 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00357 } 00358 _SEH2_END; 00359 } 00360 00361 /* Setup the callback */ 00362 PostOperationInfo.Object = (PVOID)KeyObject; 00363 EnumerateValueKeyInfo.Object = (PVOID)KeyObject; 00364 EnumerateValueKeyInfo.Index = Index; 00365 EnumerateValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; 00366 EnumerateValueKeyInfo.KeyValueInformation = KeyValueInformation; 00367 EnumerateValueKeyInfo.Length = Length; 00368 EnumerateValueKeyInfo.ResultLength = ResultLength; 00369 00370 /* Do the callback */ 00371 Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey, 00372 &EnumerateValueKeyInfo); 00373 if (NT_SUCCESS(Status)) 00374 { 00375 /* Call the internal API */ 00376 Status = CmEnumerateValueKey(KeyObject->KeyControlBlock, 00377 Index, 00378 KeyValueInformationClass, 00379 KeyValueInformation, 00380 Length, 00381 ResultLength); 00382 00383 /* Do the post callback */ 00384 PostOperationInfo.Status = Status; 00385 CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo); 00386 } 00387 00388 ObDereferenceObject(KeyObject); 00389 return Status; 00390 } 00391 00392 NTSTATUS 00393 NTAPI 00394 NtQueryKey(IN HANDLE KeyHandle, 00395 IN KEY_INFORMATION_CLASS KeyInformationClass, 00396 OUT PVOID KeyInformation, 00397 IN ULONG Length, 00398 OUT PULONG ResultLength) 00399 { 00400 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00401 NTSTATUS Status; 00402 PCM_KEY_BODY KeyObject; 00403 REG_QUERY_KEY_INFORMATION QueryKeyInfo; 00404 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00405 OBJECT_HANDLE_INFORMATION HandleInfo; 00406 PAGED_CODE(); 00407 DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n", 00408 KeyHandle, KeyInformationClass, Length); 00409 00410 /* Reject invalid classes */ 00411 if ((KeyInformationClass != KeyBasicInformation) && 00412 (KeyInformationClass != KeyNodeInformation) && 00413 (KeyInformationClass != KeyFullInformation) && 00414 (KeyInformationClass != KeyNameInformation) && 00415 (KeyInformationClass != KeyCachedInformation) && 00416 (KeyInformationClass != KeyFlagsInformation)) 00417 { 00418 /* Fail */ 00419 return STATUS_INVALID_PARAMETER; 00420 } 00421 00422 /* Check if just the name is required */ 00423 if (KeyInformationClass == KeyNameInformation) 00424 { 00425 /* Ignore access level */ 00426 Status = ObReferenceObjectByHandle(KeyHandle, 00427 0, 00428 CmpKeyObjectType, 00429 ExGetPreviousMode(), 00430 (PVOID*)&KeyObject, 00431 &HandleInfo); 00432 if (NT_SUCCESS(Status)) 00433 { 00434 /* At least a single bit of access is required */ 00435 if (!HandleInfo.GrantedAccess) 00436 { 00437 /* No such luck */ 00438 ObDereferenceObject(KeyObject); 00439 Status = STATUS_ACCESS_DENIED; 00440 } 00441 } 00442 } 00443 else 00444 { 00445 /* Get a reference */ 00446 Status = ObReferenceObjectByHandle(KeyHandle, 00447 KEY_QUERY_VALUE, 00448 CmpKeyObjectType, 00449 ExGetPreviousMode(), 00450 (PVOID*)&KeyObject, 00451 NULL); 00452 } 00453 00454 /* Quit on failure */ 00455 if (!NT_SUCCESS(Status)) return Status; 00456 00457 if (PreviousMode != KernelMode) 00458 { 00459 _SEH2_TRY 00460 { 00461 ProbeForWriteUlong(ResultLength); 00462 ProbeForWrite(KeyInformation, 00463 Length, 00464 sizeof(ULONG)); 00465 } 00466 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00467 { 00468 /* Dereference and return status */ 00469 ObDereferenceObject(KeyObject); 00470 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00471 } 00472 _SEH2_END; 00473 } 00474 00475 /* Setup the callback */ 00476 PostOperationInfo.Object = (PVOID)KeyObject; 00477 QueryKeyInfo.Object = (PVOID)KeyObject; 00478 QueryKeyInfo.KeyInformationClass = KeyInformationClass; 00479 QueryKeyInfo.KeyInformation = KeyInformation; 00480 QueryKeyInfo.Length = Length; 00481 QueryKeyInfo.ResultLength = ResultLength; 00482 00483 /* Do the callback */ 00484 Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo); 00485 if (NT_SUCCESS(Status)) 00486 { 00487 /* Call the internal API */ 00488 Status = CmQueryKey(KeyObject->KeyControlBlock, 00489 KeyInformationClass, 00490 KeyInformation, 00491 Length, 00492 ResultLength); 00493 00494 /* Do the post callback */ 00495 PostOperationInfo.Status = Status; 00496 CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo); 00497 } 00498 00499 /* Dereference and return status */ 00500 ObDereferenceObject(KeyObject); 00501 return Status; 00502 } 00503 00504 NTSTATUS 00505 NTAPI 00506 NtQueryValueKey(IN HANDLE KeyHandle, 00507 IN PUNICODE_STRING ValueName, 00508 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, 00509 OUT PVOID KeyValueInformation, 00510 IN ULONG Length, 00511 OUT PULONG ResultLength) 00512 { 00513 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00514 NTSTATUS Status; 00515 PCM_KEY_BODY KeyObject; 00516 REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo; 00517 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00518 UNICODE_STRING ValueNameCopy = *ValueName; 00519 PAGED_CODE(); 00520 DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n", 00521 KeyHandle, ValueName, KeyValueInformationClass, Length); 00522 00523 /* Verify that the handle is valid and is a registry key */ 00524 Status = ObReferenceObjectByHandle(KeyHandle, 00525 KEY_QUERY_VALUE, 00526 CmpKeyObjectType, 00527 ExGetPreviousMode(), 00528 (PVOID*)&KeyObject, 00529 NULL); 00530 if (!NT_SUCCESS(Status)) return Status; 00531 00532 if (PreviousMode != KernelMode) 00533 { 00534 _SEH2_TRY 00535 { 00536 ProbeForWriteUlong(ResultLength); 00537 ProbeForWrite(KeyValueInformation, 00538 Length, 00539 sizeof(ULONG)); 00540 } 00541 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00542 { 00543 /* Dereference and return status */ 00544 ObDereferenceObject(KeyObject); 00545 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00546 } 00547 _SEH2_END; 00548 } 00549 00550 /* Make sure the name is aligned properly */ 00551 if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1))) 00552 { 00553 /* It isn't, so we'll fail */ 00554 ObDereferenceObject(KeyObject); 00555 return STATUS_INVALID_PARAMETER; 00556 } 00557 else 00558 { 00559 /* Ignore any null characters at the end */ 00560 while ((ValueNameCopy.Length) && 00561 !(ValueNameCopy.Buffer[ValueNameCopy.Length / sizeof(WCHAR) - 1])) 00562 { 00563 /* Skip it */ 00564 ValueNameCopy.Length -= sizeof(WCHAR); 00565 } 00566 } 00567 00568 /* Setup the callback */ 00569 PostOperationInfo.Object = (PVOID)KeyObject; 00570 QueryValueKeyInfo.Object = (PVOID)KeyObject; 00571 QueryValueKeyInfo.ValueName = &ValueNameCopy; 00572 QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; 00573 QueryValueKeyInfo.Length = Length; 00574 QueryValueKeyInfo.ResultLength = ResultLength; 00575 00576 /* Do the callback */ 00577 Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo); 00578 if (NT_SUCCESS(Status)) 00579 { 00580 /* Call the internal API */ 00581 Status = CmQueryValueKey(KeyObject->KeyControlBlock, 00582 ValueNameCopy, 00583 KeyValueInformationClass, 00584 KeyValueInformation, 00585 Length, 00586 ResultLength); 00587 00588 /* Do the post callback */ 00589 PostOperationInfo.Status = Status; 00590 CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo); 00591 } 00592 00593 /* Dereference and return status */ 00594 ObDereferenceObject(KeyObject); 00595 return Status; 00596 } 00597 00598 NTSTATUS 00599 NTAPI 00600 NtSetValueKey(IN HANDLE KeyHandle, 00601 IN PUNICODE_STRING ValueName, 00602 IN ULONG TitleIndex, 00603 IN ULONG Type, 00604 IN PVOID Data, 00605 IN ULONG DataSize) 00606 { 00607 NTSTATUS Status; 00608 PCM_KEY_BODY KeyObject; 00609 REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo; 00610 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00611 UNICODE_STRING ValueNameCopy = *ValueName; 00612 PAGED_CODE(); 00613 DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n", 00614 KeyHandle, ValueName, TitleIndex, Type, DataSize); 00615 00616 /* Verify that the handle is valid and is a registry key */ 00617 Status = ObReferenceObjectByHandle(KeyHandle, 00618 KEY_SET_VALUE, 00619 CmpKeyObjectType, 00620 ExGetPreviousMode(), 00621 (PVOID*)&KeyObject, 00622 NULL); 00623 if (!NT_SUCCESS(Status)) return Status; 00624 00625 /* Make sure the name is aligned, not too long, and the data under 4GB */ 00626 if ( (ValueNameCopy.Length > 32767) || 00627 ((ValueNameCopy.Length & (sizeof(WCHAR) - 1))) || 00628 (DataSize > 0x80000000)) 00629 { 00630 /* Fail */ 00631 ObDereferenceObject(KeyObject); 00632 return STATUS_INVALID_PARAMETER; 00633 } 00634 00635 /* Ignore any null characters at the end */ 00636 while ((ValueNameCopy.Length) && 00637 !(ValueNameCopy.Buffer[ValueNameCopy.Length / sizeof(WCHAR) - 1])) 00638 { 00639 /* Skip it */ 00640 ValueNameCopy.Length -= sizeof(WCHAR); 00641 } 00642 00643 /* Don't touch read-only keys */ 00644 if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY) 00645 { 00646 /* Fail */ 00647 ObDereferenceObject(KeyObject); 00648 return STATUS_ACCESS_DENIED; 00649 } 00650 00651 /* Setup callback */ 00652 PostOperationInfo.Object = (PVOID)KeyObject; 00653 SetValueKeyInfo.Object = (PVOID)KeyObject; 00654 SetValueKeyInfo.ValueName = ValueName; 00655 SetValueKeyInfo.TitleIndex = TitleIndex; 00656 SetValueKeyInfo.Type = Type; 00657 SetValueKeyInfo.Data = Data; 00658 SetValueKeyInfo.DataSize = DataSize; 00659 00660 /* Do the callback */ 00661 Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo); 00662 if (NT_SUCCESS(Status)) 00663 { 00664 /* Call the internal API */ 00665 Status = CmSetValueKey(KeyObject->KeyControlBlock, 00666 &ValueNameCopy, 00667 Type, 00668 Data, 00669 DataSize); 00670 } 00671 00672 /* Do the post-callback */ 00673 PostOperationInfo.Status = Status; 00674 CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo); 00675 00676 /* Dereference and return status */ 00677 ObDereferenceObject(KeyObject); 00678 return Status; 00679 } 00680 00681 NTSTATUS 00682 NTAPI 00683 NtDeleteValueKey(IN HANDLE KeyHandle, 00684 IN PUNICODE_STRING ValueName) 00685 { 00686 PCM_KEY_BODY KeyObject; 00687 NTSTATUS Status; 00688 REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo; 00689 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00690 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00691 UNICODE_STRING ValueNameCopy = *ValueName; 00692 PAGED_CODE(); 00693 00694 /* Verify that the handle is valid and is a registry key */ 00695 Status = ObReferenceObjectByHandle(KeyHandle, 00696 KEY_SET_VALUE, 00697 CmpKeyObjectType, 00698 PreviousMode, 00699 (PVOID *)&KeyObject, 00700 NULL); 00701 if (!NT_SUCCESS(Status)) return Status; 00702 00703 /* Don't touch read-only keys */ 00704 if (KeyObject->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY) 00705 { 00706 /* Fail */ 00707 ObDereferenceObject(KeyObject); 00708 return STATUS_ACCESS_DENIED; 00709 } 00710 00711 /* Make sure the name is aligned properly */ 00712 if ((ValueNameCopy.Length & (sizeof(WCHAR) - 1))) 00713 { 00714 /* It isn't, so we'll fail */ 00715 ObDereferenceObject(KeyObject); 00716 return STATUS_INVALID_PARAMETER; 00717 } 00718 00719 /* Do the callback */ 00720 DeleteValueKeyInfo.Object = (PVOID)KeyObject; 00721 DeleteValueKeyInfo.ValueName = ValueName; 00722 Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey, 00723 &DeleteValueKeyInfo); 00724 if (NT_SUCCESS(Status)) 00725 { 00726 /* Call the internal API */ 00727 Status = CmDeleteValueKey(KeyObject->KeyControlBlock, ValueNameCopy); 00728 00729 /* Do the post callback */ 00730 PostOperationInfo.Object = (PVOID)KeyObject; 00731 PostOperationInfo.Status = Status; 00732 CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, 00733 &PostOperationInfo); 00734 } 00735 00736 /* Dereference the key body */ 00737 ObDereferenceObject(KeyObject); 00738 return Status; 00739 } 00740 00741 NTSTATUS 00742 NTAPI 00743 NtFlushKey(IN HANDLE KeyHandle) 00744 { 00745 NTSTATUS Status; 00746 PCM_KEY_BODY KeyObject; 00747 PAGED_CODE(); 00748 00749 /* Get the key object */ 00750 Status = ObReferenceObjectByHandle(KeyHandle, 00751 0, 00752 CmpKeyObjectType, 00753 ExGetPreviousMode(), 00754 (PVOID*)&KeyObject, 00755 NULL); 00756 if (!NT_SUCCESS(Status)) return Status; 00757 00758 /* Lock the registry */ 00759 CmpLockRegistry(); 00760 00761 /* Lock the KCB */ 00762 CmpAcquireKcbLockShared(KeyObject->KeyControlBlock); 00763 00764 /* Make sure KCB isn't deleted */ 00765 if (KeyObject->KeyControlBlock->Delete) 00766 { 00767 /* Fail */ 00768 Status = STATUS_KEY_DELETED; 00769 } 00770 else 00771 { 00772 /* Call the internal API */ 00773 Status = CmFlushKey(KeyObject->KeyControlBlock, FALSE); 00774 } 00775 00776 /* Release the locks */ 00777 CmpReleaseKcbLock(KeyObject->KeyControlBlock); 00778 CmpUnlockRegistry(); 00779 00780 /* Dereference the object and return status */ 00781 ObDereferenceObject(KeyObject); 00782 return Status; 00783 } 00784 00785 NTSTATUS 00786 NTAPI 00787 NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, 00788 IN POBJECT_ATTRIBUTES FileObjectAttributes) 00789 { 00790 /* Call the newer API */ 00791 return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, 0, NULL); 00792 } 00793 00794 NTSTATUS 00795 NTAPI 00796 NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes, 00797 IN POBJECT_ATTRIBUTES FileObjectAttributes, 00798 IN ULONG Flags) 00799 { 00800 /* Call the newer API */ 00801 return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL); 00802 } 00803 00804 NTSTATUS 00805 NTAPI 00806 NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey, 00807 IN POBJECT_ATTRIBUTES SourceFile, 00808 IN ULONG Flags, 00809 IN HANDLE TrustClassKey) 00810 { 00811 NTSTATUS Status; 00812 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00813 PCM_KEY_BODY KeyBody = NULL; 00814 PAGED_CODE(); 00815 00816 /* Validate flags */ 00817 if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER; 00818 00819 /* Validate privilege */ 00820 if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode)) 00821 { 00822 /* Fail */ 00823 DPRINT1("Restore Privilege missing!\n"); 00824 return STATUS_PRIVILEGE_NOT_HELD; 00825 } 00826 00827 /* Block APCs */ 00828 KeEnterCriticalRegion(); 00829 00830 /* Check if we have a trust class */ 00831 if (TrustClassKey) 00832 { 00833 /* Reference it */ 00834 Status = ObReferenceObjectByHandle(TrustClassKey, 00835 0, 00836 CmpKeyObjectType, 00837 PreviousMode, 00838 (PVOID *)&KeyBody, 00839 NULL); 00840 } 00841 00842 /* Call the internal API */ 00843 Status = CmLoadKey(TargetKey, SourceFile, Flags, KeyBody); 00844 00845 /* Dereference the trust key, if any */ 00846 if (KeyBody) ObDereferenceObject(KeyBody); 00847 00848 /* Bring back APCs */ 00849 KeLeaveCriticalRegion(); 00850 00851 /* Return status */ 00852 return Status; 00853 } 00854 00855 NTSTATUS 00856 NTAPI 00857 NtNotifyChangeKey(IN HANDLE KeyHandle, 00858 IN HANDLE Event, 00859 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 00860 IN PVOID ApcContext OPTIONAL, 00861 OUT PIO_STATUS_BLOCK IoStatusBlock, 00862 IN ULONG CompletionFilter, 00863 IN BOOLEAN WatchTree, 00864 OUT PVOID Buffer, 00865 IN ULONG Length, 00866 IN BOOLEAN Asynchronous) 00867 { 00868 /* Call the newer API */ 00869 return NtNotifyChangeMultipleKeys(KeyHandle, 00870 0, 00871 NULL, 00872 Event, 00873 ApcRoutine, 00874 ApcContext, 00875 IoStatusBlock, 00876 CompletionFilter, 00877 WatchTree, 00878 Buffer, 00879 Length, 00880 Asynchronous); 00881 } 00882 00883 NTSTATUS 00884 NTAPI 00885 NtInitializeRegistry(IN USHORT Flag) 00886 { 00887 BOOLEAN SetupBoot; 00888 NTSTATUS Status = STATUS_SUCCESS; 00889 PAGED_CODE(); 00890 00891 /* Always do this as kernel mode */ 00892 if (KeGetPreviousMode() == UserMode) return ZwInitializeRegistry(Flag); 00893 00894 /* Enough of the system has booted by now */ 00895 Ki386PerfEnd(); 00896 00897 /* Validate flag */ 00898 if (Flag > CM_BOOT_FLAG_MAX) return STATUS_INVALID_PARAMETER; 00899 00900 /* Check if boot was accepted */ 00901 if ((Flag >= CM_BOOT_FLAG_ACCEPTED) && (Flag <= CM_BOOT_FLAG_MAX)) 00902 { 00903 /* Only allow once */ 00904 if (!CmBootAcceptFirstTime) return STATUS_ACCESS_DENIED; 00905 CmBootAcceptFirstTime = FALSE; 00906 00907 /* Get the control set accepted */ 00908 Flag -= CM_BOOT_FLAG_ACCEPTED; 00909 if (Flag) 00910 { 00911 /* FIXME: Save the last known good boot */ 00912 //Status = CmpSaveBootControlSet(Flag); 00913 00914 /* Notify HAL */ 00915 HalEndOfBoot(); 00916 00917 /* Enable lazy flush */ 00918 CmpHoldLazyFlush = FALSE; 00919 CmpLazyFlush(); 00920 return Status; 00921 } 00922 00923 /* Otherwise, invalid boot */ 00924 return STATUS_INVALID_PARAMETER; 00925 } 00926 00927 /* Check if this was a setup boot */ 00928 SetupBoot = (Flag == CM_BOOT_FLAG_SETUP ? TRUE : FALSE); 00929 00930 /* Make sure we're only called once */ 00931 if (!CmFirstTime) return STATUS_ACCESS_DENIED; 00932 CmFirstTime = FALSE; 00933 00934 /* Acquire registry lock */ 00935 //CmpLockRegistryExclusive(); 00936 00937 /* Initialize the hives and lazy flusher */ 00938 CmpCmdInit(SetupBoot); 00939 00940 /* Save version data */ 00941 CmpSetVersionData(); 00942 00943 /* Release the registry lock */ 00944 //CmpUnlockRegistry(); 00945 return STATUS_SUCCESS; 00946 } 00947 00948 NTSTATUS 00949 NTAPI 00950 NtCompactKeys(IN ULONG Count, 00951 IN PHANDLE KeyArray) 00952 { 00953 UNIMPLEMENTED; 00954 return STATUS_NOT_IMPLEMENTED; 00955 } 00956 00957 NTSTATUS 00958 NTAPI 00959 NtCompressKey(IN HANDLE Key) 00960 { 00961 UNIMPLEMENTED; 00962 return STATUS_NOT_IMPLEMENTED; 00963 } 00964 00965 NTSTATUS 00966 NTAPI 00967 NtLockProductActivationKeys(IN PULONG pPrivateVer, 00968 IN PULONG pSafeMode) 00969 { 00970 UNIMPLEMENTED; 00971 return STATUS_NOT_IMPLEMENTED; 00972 } 00973 00974 NTSTATUS 00975 NTAPI 00976 NtLockRegistryKey(IN HANDLE KeyHandle) 00977 { 00978 UNIMPLEMENTED; 00979 return STATUS_NOT_IMPLEMENTED; 00980 } 00981 00982 NTSTATUS 00983 NTAPI 00984 NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle, 00985 IN ULONG Count, 00986 IN POBJECT_ATTRIBUTES SlaveObjects, 00987 IN HANDLE Event, 00988 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 00989 IN PVOID ApcContext OPTIONAL, 00990 OUT PIO_STATUS_BLOCK IoStatusBlock, 00991 IN ULONG CompletionFilter, 00992 IN BOOLEAN WatchTree, 00993 OUT PVOID Buffer, 00994 IN ULONG Length, 00995 IN BOOLEAN Asynchronous) 00996 { 00997 UNIMPLEMENTED; 00998 return STATUS_NOT_IMPLEMENTED; 00999 } 01000 01001 NTSTATUS 01002 NTAPI 01003 NtQueryMultipleValueKey(IN HANDLE KeyHandle, 01004 IN OUT PKEY_VALUE_ENTRY ValueList, 01005 IN ULONG NumberOfValues, 01006 OUT PVOID Buffer, 01007 IN OUT PULONG Length, 01008 OUT PULONG ReturnLength) 01009 { 01010 UNIMPLEMENTED; 01011 return STATUS_NOT_IMPLEMENTED; 01012 } 01013 01014 NTSTATUS 01015 NTAPI 01016 NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey, 01017 OUT PULONG HandleCount) 01018 { 01019 KPROCESSOR_MODE PreviousMode; 01020 PCM_KEY_BODY KeyBody = NULL; 01021 HANDLE KeyHandle; 01022 NTSTATUS Status; 01023 01024 DPRINT("NtQueryOpenSubKeys()\n"); 01025 01026 PAGED_CODE(); 01027 01028 /* Get the processor mode */ 01029 PreviousMode = KeGetPreviousMode(); 01030 01031 if (PreviousMode != KernelMode) 01032 { 01033 /* Prepare to probe parameters */ 01034 _SEH2_TRY 01035 { 01036 /* Probe target key */ 01037 ProbeForRead(TargetKey, 01038 sizeof(OBJECT_ATTRIBUTES), 01039 sizeof(ULONG)); 01040 01041 /* Probe handle count */ 01042 ProbeForWriteUlong(HandleCount); 01043 } 01044 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01045 { 01046 /* Return the exception code */ 01047 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01048 } 01049 _SEH2_END; 01050 } 01051 01052 /* Open a handle to the key */ 01053 Status = ObOpenObjectByName(TargetKey, 01054 CmpKeyObjectType, 01055 PreviousMode, 01056 NULL, 01057 KEY_READ, 01058 NULL, 01059 &KeyHandle); 01060 if (NT_SUCCESS(Status)) 01061 { 01062 /* Reference the key object */ 01063 Status = ObReferenceObjectByHandle(KeyHandle, 01064 KEY_READ, 01065 CmpKeyObjectType, 01066 PreviousMode, 01067 (PVOID *)&KeyBody, 01068 NULL); 01069 01070 /* Close the handle */ 01071 NtClose(KeyHandle); 01072 } 01073 01074 /* Fail, if the key object could not be referenced */ 01075 if (!NT_SUCCESS(Status)) 01076 return Status; 01077 01078 /* Lock the registry exclusively */ 01079 CmpLockRegistryExclusive(); 01080 01081 /* Fail, if we did not open a hive root key */ 01082 if (KeyBody->KeyControlBlock->KeyCell != 01083 KeyBody->KeyControlBlock->KeyHive->BaseBlock->RootCell) 01084 { 01085 DPRINT("Error: Key is not a hive root key!\n"); 01086 CmpUnlockRegistry(); 01087 ObDereferenceObject(KeyBody); 01088 return STATUS_INVALID_PARAMETER; 01089 } 01090 01091 /* Call the internal API */ 01092 *HandleCount = CmCountOpenSubKeys(KeyBody->KeyControlBlock, 01093 FALSE); 01094 01095 /* Unlock the registry */ 01096 CmpUnlockRegistry(); 01097 01098 /* Dereference the key object */ 01099 ObDereferenceObject(KeyBody); 01100 01101 DPRINT("Done.\n"); 01102 01103 return Status; 01104 } 01105 01106 NTSTATUS 01107 NTAPI 01108 NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey, 01109 IN ULONG BufferLength, 01110 IN PVOID Buffer, 01111 IN PULONG RequiredSize) 01112 { 01113 UNIMPLEMENTED; 01114 return STATUS_NOT_IMPLEMENTED; 01115 } 01116 01117 NTSTATUS 01118 NTAPI 01119 NtRenameKey(IN HANDLE KeyHandle, 01120 IN PUNICODE_STRING ReplacementName) 01121 { 01122 UNIMPLEMENTED; 01123 return STATUS_NOT_IMPLEMENTED; 01124 } 01125 01126 NTSTATUS 01127 NTAPI 01128 NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes, 01129 IN HANDLE Key, 01130 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes) 01131 { 01132 UNIMPLEMENTED; 01133 return STATUS_NOT_IMPLEMENTED; 01134 } 01135 01136 NTSTATUS 01137 NTAPI 01138 NtRestoreKey(IN HANDLE KeyHandle, 01139 IN HANDLE FileHandle, 01140 IN ULONG RestoreFlags) 01141 { 01142 UNIMPLEMENTED; 01143 return STATUS_NOT_IMPLEMENTED; 01144 } 01145 01146 NTSTATUS 01147 NTAPI 01148 NtSaveKey(IN HANDLE KeyHandle, 01149 IN HANDLE FileHandle) 01150 { 01151 UNIMPLEMENTED; 01152 return STATUS_NOT_IMPLEMENTED; 01153 } 01154 01155 NTSTATUS 01156 NTAPI 01157 NtSaveKeyEx(IN HANDLE KeyHandle, 01158 IN HANDLE FileHandle, 01159 IN ULONG Flags) 01160 { 01161 UNIMPLEMENTED; 01162 return STATUS_NOT_IMPLEMENTED; 01163 } 01164 01165 NTSTATUS 01166 NTAPI 01167 NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle, 01168 IN HANDLE LowPrecedenceKeyHandle, 01169 IN HANDLE FileHandle) 01170 { 01171 UNIMPLEMENTED; 01172 return STATUS_NOT_IMPLEMENTED; 01173 } 01174 01175 NTSTATUS 01176 NTAPI 01177 NtSetInformationKey(IN HANDLE KeyHandle, 01178 IN KEY_SET_INFORMATION_CLASS KeyInformationClass, 01179 IN PVOID KeyInformation, 01180 IN ULONG KeyInformationLength) 01181 { 01182 UNIMPLEMENTED; 01183 return STATUS_NOT_IMPLEMENTED; 01184 } 01185 01186 NTSTATUS 01187 NTAPI 01188 NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes) 01189 { 01190 return NtUnloadKey2(KeyObjectAttributes, 0); 01191 } 01192 01193 NTSTATUS 01194 NTAPI 01195 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey, 01196 IN ULONG Flags) 01197 { 01198 #if 0 01199 NTSTATUS Status; 01200 OBJECT_ATTRIBUTES ObjectAttributes; 01201 UNICODE_STRING ObjectName; 01202 CM_PARSE_CONTEXT ParseContext = {0}; 01203 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 01204 PCM_KEY_BODY KeyBody = NULL; 01205 ULONG ParentConv = 0, ChildConv = 0; 01206 HANDLE Handle; 01207 PAGED_CODE(); 01208 01209 /* Validate privilege */ 01210 if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode)) 01211 { 01212 /* Fail */ 01213 DPRINT1("Restore Privilege missing!\n"); 01214 return STATUS_PRIVILEGE_NOT_HELD; 01215 } 01216 01217 /* Check for user-mode caller */ 01218 if (PreviousMode != KernelMode) 01219 { 01220 /* Prepare to probe parameters */ 01221 _SEH2_TRY 01222 { 01223 /* Probe object attributes */ 01224 ProbeForRead(TargetKey, 01225 sizeof(OBJECT_ATTRIBUTES), 01226 sizeof(ULONG)); 01227 01228 ObjectAttributes = *TargetKey; 01229 01230 /* Probe the string */ 01231 ProbeForReadUnicodeString(&TargetKey->ObjectName); 01232 01233 ObjectName = *TargetKey->ObjectName; 01234 01235 ProbeForRead(ObjectName.Buffer, 01236 ObjectName.Length, 01237 sizeof(WCHAR)); 01238 01239 ObjectAttributes.ObjectName = &ObjectName; 01240 } 01241 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01242 { 01243 /* Return the exception code */ 01244 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01245 } 01246 _SEH2_END; 01247 } 01248 else 01249 { 01250 /* Save the target attributes directly */ 01251 ObjectAttributes = *TargetKey; 01252 } 01253 01254 /* Setup the parse context */ 01255 ParseContext.CreateOperation = TRUE; 01256 ParseContext.CreateOptions = REG_OPTION_BACKUP_RESTORE; 01257 01258 /* Do the create */ 01259 Status = ObOpenObjectByName(&ObjectAttributes, 01260 CmpKeyObjectType, 01261 KernelMode, 01262 NULL, 01263 KEY_WRITE, 01264 &ParseContext, 01265 &Handle); 01266 01267 /* Return if failure encountered */ 01268 if (!NT_SUCCESS(Status)) return Status; 01269 01270 /* Reference it */ 01271 Status = ObReferenceObjectByHandle(Handle, 01272 KEY_WRITE, 01273 CmpKeyObjectType, 01274 KernelMode, 01275 (PVOID *)&KeyBody, 01276 NULL); 01277 01278 /* Close the handle */ 01279 ZwClose(Handle); 01280 01281 /* Return if failure encountered */ 01282 if (!NT_SUCCESS(Status)) return Status; 01283 01284 /* Acquire the lock depending on flags */ 01285 if (Flags == REG_FORCE_UNLOAD) 01286 { 01287 /* Lock registry exclusively */ 01288 CmpLockRegistryExclusive(); 01289 } 01290 else 01291 { 01292 /* Lock registry */ 01293 CmpLockRegistry(); 01294 01295 /* Acquire the hive loading lock */ 01296 ExAcquirePushLockExclusive(&CmpLoadHiveLock); 01297 01298 /* Lock parent and child */ 01299 if (KeyBody->KeyControlBlock->ParentKcb) 01300 ParentConv = KeyBody->KeyControlBlock->ParentKcb->ConvKey; 01301 else 01302 ParentConv = KeyBody->KeyControlBlock->ConvKey; 01303 01304 ChildConv = KeyBody->KeyControlBlock->ConvKey; 01305 01306 CmpAcquireTwoKcbLocksExclusiveByKey(ChildConv, ParentConv); 01307 } 01308 01309 /* Check if it's being deleted already */ 01310 if (KeyBody->KeyControlBlock->Delete) 01311 { 01312 /* Return appropriate status */ 01313 Status = STATUS_KEY_DELETED; 01314 goto Quickie; 01315 } 01316 01317 /* Check if it's a readonly key */ 01318 if (KeyBody->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY) 01319 { 01320 /* Return appropriate status */ 01321 Status = STATUS_ACCESS_DENIED; 01322 goto Quickie; 01323 } 01324 01325 /* Call the internal API */ 01326 Status = CmUnloadKey(KeyBody->KeyControlBlock, 01327 Flags); 01328 01329 /* Check if we failed, but really need to succeed */ 01330 if ((Status == STATUS_CANNOT_DELETE) && (Flags == REG_FORCE_UNLOAD)) 01331 { 01332 /* TODO: We should perform another attempt here */ 01333 ASSERT(FALSE); 01334 } 01335 01336 /* If CmUnloadKey failed we need to unlock registry ourselves */ 01337 if (!NT_SUCCESS(Status)) 01338 { 01339 if (Flags != REG_FORCE_UNLOAD) 01340 { 01341 /* Release the hive loading lock */ 01342 ExReleasePushLockExclusive(&CmpLoadHiveLock); 01343 01344 /* Release two KCBs lock */ 01345 CmpReleaseTwoKcbLockByKey(ChildConv, ParentConv); 01346 } 01347 01348 /* Unlock the registry */ 01349 CmpUnlockRegistry(); 01350 } 01351 01352 Quickie: 01353 /* Dereference the key */ 01354 ObDereferenceObject(KeyBody); 01355 01356 /* Return status */ 01357 return Status; 01358 #else 01359 UNIMPLEMENTED; 01360 return STATUS_NOT_IMPLEMENTED; 01361 #endif 01362 } 01363 01364 NTSTATUS 01365 NTAPI 01366 NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey, 01367 IN HANDLE Event) 01368 { 01369 UNIMPLEMENTED; 01370 return STATUS_NOT_IMPLEMENTED; 01371 } 01372 01373 /* EOF */ Generated on Sun May 27 2012 04:37:09 for ReactOS by
1.7.6.1
|