ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ntapi.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.