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

cmparse.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/cmparse.c
00005  * PURPOSE:         Configuration Manager - Object Manager Parse Interface
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include "ntoskrnl.h"
00012 #define NDEBUG
00013 #include "debug.h"
00014 
00015 /* GLOBALS *******************************************************************/
00016 
00017 /* FUNCTIONS *****************************************************************/
00018 
00019 BOOLEAN
00020 NTAPI
00021 CmpGetNextName(IN OUT PUNICODE_STRING RemainingName,
00022                OUT PUNICODE_STRING NextName,
00023                OUT PBOOLEAN LastName)
00024 {
00025     BOOLEAN NameValid = TRUE;
00026 
00027     /* Check if there's nothing left in the name */
00028     if (!(RemainingName->Buffer) ||
00029         (!RemainingName->Length) ||
00030         !(*RemainingName->Buffer))
00031     {
00032         /* Clear the next name and set this as last */
00033         *LastName = TRUE;
00034         NextName->Buffer = NULL;
00035         NextName->Length = 0;
00036         return TRUE;
00037     }
00038 
00039     /* Check if we have a path separator */
00040     if (*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR)
00041     {
00042         /* Skip it */
00043         RemainingName->Buffer++;
00044         RemainingName->Length -= sizeof(WCHAR);
00045         RemainingName->MaximumLength -= sizeof(WCHAR);
00046     }
00047 
00048     /* Start loop at where the current buffer is */
00049     NextName->Buffer = RemainingName->Buffer;
00050     while (TRUE)
00051     {
00052         /* Break out if we ran out or hit a path separator */
00053         if (!(RemainingName->Length) ||
00054             (*RemainingName->Buffer == OBJ_NAME_PATH_SEPARATOR))
00055         {
00056             break;
00057         }
00058 
00059         /* Move to the next character */
00060         RemainingName->Buffer++;
00061         RemainingName->Length -= sizeof(WCHAR);
00062         RemainingName->MaximumLength -= sizeof(WCHAR);
00063     }
00064 
00065     /* See how many chars we parsed and validate the length */
00066     NextName->Length = (USHORT)((ULONG_PTR)RemainingName->Buffer -
00067                                 (ULONG_PTR)NextName->Buffer);
00068     if (NextName->Length > 512) NameValid = FALSE;
00069     NextName->MaximumLength = NextName->Length;
00070 
00071     /* If there's nothing left, we're last */
00072     *LastName = !RemainingName->Length;
00073     return NameValid;
00074 }
00075 
00076 BOOLEAN
00077 NTAPI
00078 CmpGetSymbolicLink(IN PHHIVE Hive,
00079                    IN OUT PUNICODE_STRING ObjectName,
00080                    IN OUT PCM_KEY_CONTROL_BLOCK SymbolicKcb,
00081                    IN PUNICODE_STRING RemainingName OPTIONAL)
00082 {
00083     HCELL_INDEX LinkCell = HCELL_NIL;
00084     PCM_KEY_VALUE LinkValue = NULL;
00085     PWSTR LinkName = NULL;
00086     BOOLEAN LinkNameAllocated = FALSE;
00087     PWSTR NewBuffer;
00088     ULONG Length = 0;
00089     ULONG ValueLength = 0;
00090     BOOLEAN Result = FALSE;
00091     HCELL_INDEX CellToRelease = HCELL_NIL;
00092     PCM_KEY_NODE Node;
00093     UNICODE_STRING NewObjectName;
00094 
00095     /* Make sure we're not being deleted */
00096     if (SymbolicKcb->Delete) return FALSE;
00097 
00098     /* Get the key node */
00099     Node = (PCM_KEY_NODE)HvGetCell(SymbolicKcb->KeyHive, SymbolicKcb->KeyCell);
00100     if (!Node) goto Exit;
00101 
00102     /* Find the symbolic link key */
00103     LinkCell = CmpFindValueByName(Hive, Node, &CmSymbolicLinkValueName);
00104     HvReleaseCell(SymbolicKcb->KeyHive, SymbolicKcb->KeyCell);
00105     if (LinkCell == HCELL_NIL) goto Exit;
00106 
00107     /* Get the value cell */
00108     LinkValue = (PCM_KEY_VALUE)HvGetCell(Hive, LinkCell);
00109     if (!LinkValue) goto Exit;
00110 
00111     /* Make sure it's a registry link */
00112     if (LinkValue->Type != REG_LINK) goto Exit;
00113 
00114     /* Now read the value data */
00115     if (!CmpGetValueData(Hive,
00116                          LinkValue,
00117                          &ValueLength,
00118                          (PVOID)&LinkName,
00119                          &LinkNameAllocated,
00120                          &CellToRelease))
00121     {
00122         /* Fail */
00123         goto Exit;
00124     }
00125 
00126     /* Get the length */
00127     Length = ValueLength + sizeof(WCHAR);
00128 
00129     /* Make sure we start with a slash */
00130     if (*LinkName != OBJ_NAME_PATH_SEPARATOR) goto Exit;
00131 
00132     /* Add the remaining name if needed */
00133     if (RemainingName) Length += RemainingName->Length + sizeof(WCHAR);
00134     
00135     /* Check for overflow */
00136     if (Length > 0xFFFF) goto Exit;
00137 
00138     /* Check if we need a new buffer */
00139     if (Length > ObjectName->MaximumLength)
00140     {
00141         /* We do -- allocate one */
00142         NewBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
00143         if (!NewBuffer) goto Exit;
00144         
00145         /* Setup the new string and copy the symbolic target */
00146         NewObjectName.Buffer = NewBuffer;
00147         NewObjectName.MaximumLength = (USHORT)Length;
00148         NewObjectName.Length = (USHORT)ValueLength;
00149         RtlCopyMemory(NewBuffer, LinkName, ValueLength);
00150 
00151         /* Check if we need to add anything else */
00152         if (RemainingName)
00153         {
00154             /* Add the remaining name */
00155             NewBuffer[ValueLength / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
00156             NewObjectName.Length += sizeof(WCHAR);
00157             RtlAppendUnicodeStringToString(&NewObjectName, RemainingName);
00158         }
00159 
00160         /* Free the old buffer */
00161         ExFreePool(ObjectName->Buffer);
00162         *ObjectName = NewObjectName;
00163     }
00164     else
00165     {
00166         /* The old name is large enough -- update the length */
00167         ObjectName->Length = (USHORT)ValueLength;
00168         if (RemainingName)
00169         {
00170             /* Copy the remaining name inside */
00171             RtlMoveMemory(&ObjectName->Buffer[(ValueLength / sizeof(WCHAR)) + 1],
00172                           RemainingName->Buffer,
00173                           RemainingName->Length);
00174 
00175             /* Add the slash and update the length */
00176             ObjectName->Buffer[ValueLength / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
00177             ObjectName->Length += RemainingName->Length + sizeof(WCHAR);
00178         }
00179 
00180         /* Copy the symbolic link target name */
00181         RtlCopyMemory(ObjectName->Buffer, LinkName, ValueLength);
00182     }
00183 
00184     /* Null-terminate the whole thing */
00185     ObjectName->Buffer[ObjectName->Length / sizeof(WCHAR)] = UNICODE_NULL;
00186     Result = TRUE;
00187 
00188 Exit:
00189     /* Free the link name */
00190     if (LinkNameAllocated) ExFreePool(LinkName);
00191 
00192     /* Check if we had a value cell */
00193     if (LinkValue)
00194     {
00195         /* Release it */
00196         ASSERT(LinkCell != HCELL_NIL);
00197         HvReleaseCell(Hive, LinkCell);
00198     }
00199 
00200     /* Check if we had an active cell and release it, then return the result */
00201     if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
00202     return Result;
00203 }
00204 
00205 NTSTATUS
00206 NTAPI
00207 CmpDoCreateChild(IN PHHIVE Hive,
00208                  IN HCELL_INDEX ParentCell,
00209                  IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
00210                  IN PACCESS_STATE AccessState,
00211                  IN PUNICODE_STRING Name,
00212                  IN KPROCESSOR_MODE AccessMode,
00213                  IN PCM_PARSE_CONTEXT ParseContext,
00214                  IN PCM_KEY_CONTROL_BLOCK ParentKcb,
00215                  IN ULONG Flags,
00216                  OUT PHCELL_INDEX KeyCell,
00217                  OUT PVOID *Object)
00218 {
00219     NTSTATUS Status = STATUS_SUCCESS;
00220     PCM_KEY_BODY KeyBody;
00221     HCELL_INDEX ClassCell = HCELL_NIL;
00222     PCM_KEY_NODE KeyNode;
00223     PCELL_DATA CellData;
00224     ULONG StorageType;
00225     LARGE_INTEGER SystemTime;
00226     PCM_KEY_CONTROL_BLOCK Kcb;
00227     PSECURITY_DESCRIPTOR NewDescriptor;
00228 
00229     /* Get the storage type */
00230     StorageType = Stable;
00231     if (Flags & REG_OPTION_VOLATILE) StorageType = Volatile;
00232 
00233     /* Allocate the child */
00234     *KeyCell = HvAllocateCell(Hive,
00235                               FIELD_OFFSET(CM_KEY_NODE, Name) +
00236                               CmpNameSize(Hive, Name),
00237                               StorageType,
00238                               HCELL_NIL);
00239     if (*KeyCell == HCELL_NIL)
00240     {
00241         /* Fail */
00242         Status = STATUS_INSUFFICIENT_RESOURCES;
00243         goto Quickie;
00244     }
00245 
00246     /* Get the key node */
00247     KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, *KeyCell);
00248     if (!KeyNode)
00249     {
00250         /* Fail, this should never happen */
00251         ASSERT(FALSE);
00252         Status = STATUS_INSUFFICIENT_RESOURCES;
00253         goto Quickie;
00254     }
00255 
00256     /* Release the cell */
00257     HvReleaseCell(Hive, *KeyCell);
00258 
00259     /* Check if we have a class name */
00260     if (ParseContext->Class.Length > 0)
00261     {
00262         /* Allocate a class cell */
00263         ClassCell = HvAllocateCell(Hive,
00264                                    ParseContext->Class.Length,
00265                                    StorageType,
00266                                    HCELL_NIL);
00267         if (ClassCell == HCELL_NIL)
00268         {
00269             /* Fail */
00270             Status = STATUS_INSUFFICIENT_RESOURCES;
00271             goto Quickie;
00272         }
00273     }
00274 
00275     /* Allocate the Cm Object */
00276     Status = ObCreateObject(AccessMode,
00277                             CmpKeyObjectType,
00278                             NULL,
00279                             AccessMode,
00280                             NULL,
00281                             sizeof(CM_KEY_BODY),
00282                             0,
00283                             0,
00284                             Object);
00285     if (!NT_SUCCESS(Status)) goto Quickie;
00286     
00287     /* Setup the key body */
00288     KeyBody = (PCM_KEY_BODY)(*Object);
00289     KeyBody->Type = '20yk';
00290     KeyBody->KeyControlBlock = NULL;
00291 
00292     /* Check if we had a class */
00293     if (ParseContext->Class.Length > 0)
00294     {
00295         /* Get the class cell */
00296         CellData = HvGetCell(Hive, ClassCell);
00297         if (!CellData)
00298         {
00299             /* Fail, this should never happen */
00300             ASSERT(FALSE);
00301             Status = STATUS_INSUFFICIENT_RESOURCES;
00302             ObDereferenceObject(*Object);
00303             goto Quickie;
00304         }
00305 
00306         /* Release the cell */
00307         HvReleaseCell(Hive, ClassCell);
00308 
00309         /* Copy the class data */
00310         RtlCopyMemory(&CellData->u.KeyString[0],
00311                       ParseContext->Class.Buffer,
00312                       ParseContext->Class.Length);
00313     }
00314 
00315     /* Fill out the key node */
00316     KeyNode->Signature = CM_KEY_NODE_SIGNATURE;
00317     KeyNode->Flags = Flags &~ REG_OPTION_CREATE_LINK;
00318     KeQuerySystemTime(&SystemTime);
00319     KeyNode->LastWriteTime = SystemTime;
00320     KeyNode->Spare = 0;
00321     KeyNode->Parent = ParentCell;
00322     KeyNode->SubKeyCounts[Stable] = 0;
00323     KeyNode->SubKeyCounts[Volatile] = 0;
00324     KeyNode->SubKeyLists[Stable] = HCELL_NIL;
00325     KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
00326     KeyNode->ValueList.Count = 0;
00327     KeyNode->ValueList.List = HCELL_NIL;
00328     KeyNode->Security = HCELL_NIL;
00329     KeyNode->Class = ClassCell;
00330     KeyNode->ClassLength = ParseContext->Class.Length;
00331     KeyNode->MaxValueDataLen = 0;
00332     KeyNode->MaxNameLen = 0;
00333     KeyNode->MaxValueNameLen = 0;
00334     KeyNode->MaxClassLen = 0;
00335     KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, Name);
00336     if (KeyNode->NameLength < Name->Length) KeyNode->Flags |= KEY_COMP_NAME;
00337     
00338     /* Create the KCB */
00339     Kcb = CmpCreateKeyControlBlock(Hive,
00340                                    *KeyCell,
00341                                    KeyNode,
00342                                    ParentKcb,
00343                                    0, // CMP_LOCK_HASHES_FOR_KCB,
00344                                    Name);
00345     if (!Kcb)
00346     {
00347         /* Fail */
00348         ObDereferenceObjectDeferDelete(*Object);
00349         Status = STATUS_INSUFFICIENT_RESOURCES;
00350         goto Quickie;
00351     }
00352     
00353     /* Sanity check */
00354     ASSERT(Kcb->RefCount == 1);
00355 
00356     /* Now fill out the Cm object */
00357     KeyBody->NotifyBlock = NULL;
00358     KeyBody->ProcessID = PsGetCurrentProcessId();
00359     KeyBody->KeyControlBlock = Kcb;
00360     
00361     /* Link it with the KCB */
00362     EnlistKeyBodyWithKCB(KeyBody, 0);
00363 
00364     /* Assign security */
00365     Status = SeAssignSecurity(ParentDescriptor,
00366                               AccessState->SecurityDescriptor,
00367                               &NewDescriptor,
00368                               TRUE,
00369                               &AccessState->SubjectSecurityContext,
00370                               &CmpKeyObjectType->TypeInfo.GenericMapping,
00371                               CmpKeyObjectType->TypeInfo.PoolType);
00372     if (NT_SUCCESS(Status))
00373     {
00374         Status = CmpSecurityMethod(*Object,
00375                                    AssignSecurityDescriptor,
00376                                    NULL,
00377                                    NewDescriptor,
00378                                    NULL,
00379                                    NULL,
00380                                    CmpKeyObjectType->TypeInfo.PoolType,
00381                                    &CmpKeyObjectType->TypeInfo.GenericMapping);
00382     }
00383 
00384 Quickie:
00385     /* Check if we got here because of failure */
00386     if (!NT_SUCCESS(Status))
00387     {
00388         /* Free any cells we might've allocated */
00389         if (ParseContext->Class.Length > 0) HvFreeCell(Hive, ClassCell);
00390         HvFreeCell(Hive, *KeyCell);
00391     }
00392 
00393     /* Return status */
00394     return Status;
00395 }
00396 
00397 NTSTATUS
00398 NTAPI
00399 CmpDoCreate(IN PHHIVE Hive,
00400             IN HCELL_INDEX Cell,
00401             IN PACCESS_STATE AccessState,
00402             IN PUNICODE_STRING Name,
00403             IN KPROCESSOR_MODE AccessMode,
00404             IN PCM_PARSE_CONTEXT ParseContext,
00405             IN PCM_KEY_CONTROL_BLOCK ParentKcb,
00406             OUT PVOID *Object)
00407 {
00408     NTSTATUS Status;
00409     PCELL_DATA CellData;
00410     HCELL_INDEX KeyCell;
00411     ULONG ParentType;
00412     PCM_KEY_BODY KeyBody;
00413     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
00414     LARGE_INTEGER TimeStamp;
00415     PCM_KEY_NODE KeyNode;
00416 
00417     /* Check if the parent is being deleted */
00418     if (ParentKcb->Delete)
00419     {
00420         /* It has, quit */
00421         ASSERT(FALSE);
00422         Status = STATUS_OBJECT_NAME_NOT_FOUND;
00423         goto Exit;
00424     }
00425 
00426     /* Get the parent node */
00427     KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
00428     if (!KeyNode)
00429     {
00430         /* Fail */
00431         ASSERT(FALSE);
00432         Status = STATUS_INSUFFICIENT_RESOURCES;
00433         goto Exit;
00434     }
00435 
00436     /* Make sure nobody added us yet */
00437     if (CmpFindSubKeyByName(Hive, KeyNode, Name) != HCELL_NIL)
00438     {
00439         /* Fail */
00440         ASSERT(FALSE);
00441         Status = STATUS_REPARSE;
00442         goto Exit;
00443     }
00444 
00445     /* Sanity check */
00446     ASSERT(Cell == ParentKcb->KeyCell);
00447 
00448     /* Get the parent type */
00449     ParentType = HvGetCellType(Cell);
00450     if ((ParentType == Volatile) &&
00451         !(ParseContext->CreateOptions & REG_OPTION_VOLATILE))
00452     {
00453         /* Children of volatile parents must also be volatile */
00454         //ASSERT(FALSE);
00455         Status = STATUS_CHILD_MUST_BE_VOLATILE;
00456         goto Exit;
00457     }
00458 
00459     /* Don't allow children under symlinks */
00460     if (ParentKcb->Flags & KEY_SYM_LINK)
00461     {
00462         /* Fail */
00463         ASSERT(FALSE);
00464         Status = STATUS_ACCESS_DENIED;
00465         goto Exit;
00466     }
00467 
00468     /* Make the cell dirty for now */
00469     HvMarkCellDirty(Hive, Cell, FALSE);
00470 
00471     /* Do the actual create operation */
00472     Status = CmpDoCreateChild(Hive,
00473                               Cell,
00474                               SecurityDescriptor,
00475                               AccessState,
00476                               Name,
00477                               AccessMode,
00478                               ParseContext,
00479                               ParentKcb,
00480                               ParseContext->CreateOptions, // WRONG!
00481                               &KeyCell,
00482                               Object);
00483     if (NT_SUCCESS(Status))
00484     {
00485         /* Get the key body */
00486         KeyBody = (PCM_KEY_BODY)(*Object);
00487 
00488         /* Now add the subkey */
00489         if (!CmpAddSubKey(Hive, Cell, KeyCell))
00490         {
00491             /* Failure! We don't handle this yet! */
00492             ASSERT(FALSE);
00493         }
00494 
00495         /* Get the key node */
00496         KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
00497         if (!KeyNode)
00498         {
00499             /* Fail, this shouldn't happen */
00500             ASSERT(FALSE);
00501         }
00502 
00503         /* Sanity checks */
00504         ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
00505         ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
00506         ASSERT(KeyBody->KeyControlBlock->ParentKcb == ParentKcb);
00507         ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
00508 
00509         /* Update the timestamp */
00510         KeQuerySystemTime(&TimeStamp);
00511         KeyNode->LastWriteTime = TimeStamp;
00512         KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
00513 
00514         /* Check if we need to update name maximum */
00515         if (KeyNode->MaxNameLen < Name->Length)
00516         {
00517             /* Do it */
00518             KeyNode->MaxNameLen = Name->Length;
00519             KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name->Length;
00520         }
00521 
00522         /* Check if we need toupdate class length maximum */
00523         if (KeyNode->MaxClassLen < ParseContext->Class.Length)
00524         {
00525             /* Update it */
00526             KeyNode->MaxClassLen = ParseContext->Class.Length;
00527         }
00528 
00529         /* Check if we're creating a symbolic link */
00530         if (ParseContext->CreateOptions & REG_OPTION_CREATE_LINK)
00531         {
00532             /* Get the cell data */
00533             CellData = HvGetCell(Hive, KeyCell);
00534             if (!CellData)
00535             {
00536                 /* This shouldn't happen */
00537                 ASSERT(FALSE);
00538             }
00539 
00540             /* Update the flags */
00541             CellData->u.KeyNode.Flags |= KEY_SYM_LINK;
00542             KeyBody->KeyControlBlock->Flags = CellData->u.KeyNode.Flags;
00543             HvReleaseCell(Hive, KeyCell);
00544         }
00545     }
00546 
00547 Exit:
00548     /* Release the flusher lock and return status */
00549     return Status;
00550 }
00551 
00552 NTSTATUS
00553 NTAPI
00554 CmpDoOpen(IN PHHIVE Hive,
00555           IN HCELL_INDEX Cell,
00556           IN PCM_KEY_NODE Node,
00557           IN PACCESS_STATE AccessState,
00558           IN KPROCESSOR_MODE AccessMode,
00559           IN ULONG Attributes,
00560           IN PCM_PARSE_CONTEXT Context OPTIONAL,
00561           IN ULONG ControlFlags,
00562           IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb,
00563           IN PUNICODE_STRING KeyName,
00564           OUT PVOID *Object)
00565 {
00566     NTSTATUS Status;
00567     PCM_KEY_BODY KeyBody = NULL;
00568     PCM_KEY_CONTROL_BLOCK Kcb = NULL;
00569 
00570     /* Make sure the hive isn't locked */
00571     if ((Hive->HiveFlags & HIVE_IS_UNLOADING) &&
00572         (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()))
00573     {
00574         /* It is, don't touch it */
00575         return STATUS_OBJECT_NAME_NOT_FOUND;
00576     }
00577 
00578     /* Check if we have a context */
00579     if (Context)
00580     {
00581         /* Check if this is a link create (which shouldn't be an open) */
00582         if (Context->CreateLink)
00583         {
00584             return STATUS_ACCESS_DENIED;
00585         }
00586 
00587         /* Check if this is symlink create attempt */
00588         if (Context->CreateOptions & REG_OPTION_CREATE_LINK)
00589         {
00590             /* Key already exists */
00591             return STATUS_OBJECT_NAME_COLLISION;
00592         }
00593 
00594         /* Set the disposition */
00595         Context->Disposition = REG_OPENED_EXISTING_KEY;
00596     }
00597 
00598     /* Do this in the registry lock */
00599     CmpLockRegistry();
00600 
00601     /* If we have a KCB, make sure it's locked */
00602     //ASSERT(CmpIsKcbLockedExclusive(*CachedKcb));
00603 
00604     /* Check if caller doesn't want to create a KCB */
00605     if (ControlFlags & CMP_OPEN_KCB_NO_CREATE)
00606     {
00607         /* Check if this is a symlink */
00608         if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
00609         {
00610             /* This case for a cached KCB is not implemented yet */
00611             ASSERT(FALSE);
00612         }
00613 
00614         /* The caller wants to open a cached KCB */
00615         if (!CmpReferenceKeyControlBlock(*CachedKcb))
00616         {
00617             /* Release the registry lock */
00618             CmpUnlockRegistry();
00619 
00620             /* Return failure code */
00621             return STATUS_INSUFFICIENT_RESOURCES;
00622         }
00623 
00624         /* Our kcb is that one */
00625         Kcb = *CachedKcb;
00626     }
00627     else
00628     {
00629         /* Check if this is a symlink */
00630         if ((Node->Flags & KEY_SYM_LINK) && !(Attributes & OBJ_OPENLINK))
00631         {
00632             /* Create the KCB for the symlink */
00633             Kcb = CmpCreateKeyControlBlock(Hive,
00634                                            Cell,
00635                                            Node,
00636                                            *CachedKcb,
00637                                            0,
00638                                            KeyName);
00639             if (!Kcb)
00640             {
00641                 /* Release registry lock and return failure */
00642                 CmpUnlockRegistry();
00643                 return STATUS_INSUFFICIENT_RESOURCES;
00644             }
00645 
00646             /* Make sure it's also locked, and set the pointer */
00647             //ASSERT(CmpIsKcbLockedExclusive(Kcb));
00648             *CachedKcb = Kcb;
00649 
00650             /* Release the registry lock */
00651             CmpUnlockRegistry();
00652 
00653             /* Return reparse required */
00654             return STATUS_REPARSE;
00655         }
00656 
00657         /* Create the KCB. FIXME: Use lock flag */
00658         Kcb = CmpCreateKeyControlBlock(Hive,
00659                                        Cell,
00660                                        Node,
00661                                        *CachedKcb,
00662                                        0,
00663                                        KeyName);
00664         if (!Kcb)
00665         {
00666             /* Release registry lock and return failure */
00667             CmpUnlockRegistry();
00668             return STATUS_INSUFFICIENT_RESOURCES;
00669         }
00670     }
00671 
00672     /* Make sure it's also locked, and set the pointer */
00673     //ASSERT(CmpIsKcbLockedExclusive(Kcb));
00674     *CachedKcb = Kcb;
00675 
00676     /* Release the registry lock */
00677     CmpUnlockRegistry();
00678 
00679     /* Allocate the key object */
00680     Status = ObCreateObject(AccessMode,
00681                             CmpKeyObjectType,
00682                             NULL,
00683                             AccessMode,
00684                             NULL,
00685                             sizeof(CM_KEY_BODY),
00686                             0,
00687                             0,
00688                             Object);
00689     if (NT_SUCCESS(Status))
00690     {
00691         /* Get the key body and fill it out */
00692         KeyBody = (PCM_KEY_BODY)(*Object);       
00693         KeyBody->KeyControlBlock = Kcb;
00694         KeyBody->Type = '20yk';
00695         KeyBody->ProcessID = PsGetCurrentProcessId();
00696         KeyBody->NotifyBlock = NULL;
00697         
00698         /* Link to the KCB */
00699         EnlistKeyBodyWithKCB(KeyBody, 0);
00700 
00701         if (!ObCheckObjectAccess(*Object,
00702                                  AccessState,
00703                                  FALSE,
00704                                  AccessMode,
00705                                  &Status))
00706         {
00707             /* Access check failed */
00708             ObDereferenceObject(*Object);
00709         }
00710     }
00711     else
00712     {
00713         /* Failed, dereference the KCB */
00714         CmpDereferenceKeyControlBlockWithLock(Kcb, FALSE);
00715     }
00716 
00717     /* Return status */
00718     return Status;
00719 }
00720 
00721 /* Remove calls to CmCreateRootNode once this is used! */
00722 NTSTATUS
00723 NTAPI
00724 CmpCreateLinkNode(IN PHHIVE Hive,
00725                   IN HCELL_INDEX Cell,
00726                   IN PACCESS_STATE AccessState,
00727                   IN UNICODE_STRING Name,
00728                   IN KPROCESSOR_MODE AccessMode,
00729                   IN ULONG CreateOptions,
00730                   IN PCM_PARSE_CONTEXT Context,
00731                   IN PCM_KEY_CONTROL_BLOCK ParentKcb,
00732                   OUT PVOID *Object)
00733 {
00734     NTSTATUS Status;
00735     HCELL_INDEX KeyCell, LinkCell, ChildCell;
00736     PCM_KEY_BODY KeyBody;
00737     LARGE_INTEGER TimeStamp;
00738     PCM_KEY_NODE KeyNode;
00739     PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb;
00740 
00741     /* Link nodes only allowed on the master */
00742     if (Hive != &CmiVolatileHive->Hive)
00743     {
00744         /* Fail */
00745         DPRINT1("Invalid link node attempt\n");
00746         return STATUS_ACCESS_DENIED;
00747     }
00748     
00749     /* Check if the parent is being deleted */
00750     if (ParentKcb->Delete)
00751     {
00752         /* It is, quit */
00753         ASSERT(FALSE);
00754         Status = STATUS_OBJECT_NAME_NOT_FOUND;
00755         goto Exit;
00756     }
00757     
00758     /* Allocate a link node */
00759     LinkCell = HvAllocateCell(Hive,
00760                               FIELD_OFFSET(CM_KEY_NODE, Name) +
00761                               CmpNameSize(Hive, &Name),
00762                               Stable,
00763                               HCELL_NIL);
00764     if (LinkCell == HCELL_NIL)
00765     {
00766         /* Fail */
00767         Status = STATUS_INSUFFICIENT_RESOURCES;
00768         goto Exit;
00769     }
00770     
00771     /* Get the key cell */
00772     KeyCell = Context->ChildHive.KeyCell;
00773     if (KeyCell != HCELL_NIL)
00774     {
00775         /* Hive exists! */
00776         ChildCell = KeyCell;
00777         
00778         /* Get the node data */
00779         KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell);
00780         if (!KeyNode)
00781         {
00782             /* Fail */
00783             ASSERT(FALSE);
00784             Status = STATUS_INSUFFICIENT_RESOURCES;
00785             goto Exit;
00786         }
00787         
00788         /* Fill out the data */
00789         KeyNode->Parent = LinkCell;
00790         KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
00791         HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
00792         
00793         /* Now open the key cell */
00794         KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, KeyCell);
00795         if (!KeyNode)
00796         {
00797             /* Fail */
00798             ASSERT(FALSE);
00799             Status = STATUS_INSUFFICIENT_RESOURCES;
00800             goto Exit;
00801         }
00802         
00803         /* Open the parent */
00804         Status = CmpDoOpen(Context->ChildHive.KeyHive,
00805                            KeyCell,
00806                            KeyNode,
00807                            AccessState,
00808                            AccessMode,
00809                            CreateOptions,
00810                            NULL,
00811                            0,
00812                            &Kcb,
00813                            &Name,
00814                            Object);
00815         HvReleaseCell(Context->ChildHive.KeyHive, KeyCell);
00816     }
00817     else
00818     {
00819         /* Do the actual create operation */
00820         Status = CmpDoCreateChild(Context->ChildHive.KeyHive,
00821                                   Cell,
00822                                   NULL,
00823                                   AccessState,
00824                                   &Name,
00825                                   AccessMode,
00826                                   Context,
00827                                   ParentKcb,
00828                                   KEY_HIVE_ENTRY | KEY_NO_DELETE,
00829                                   &ChildCell,
00830                                   Object);
00831         if (NT_SUCCESS(Status))
00832         {
00833             /* Setup root pointer */
00834             Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell;
00835         }
00836     }
00837     
00838     /* Check if open or create suceeded */
00839     if (NT_SUCCESS(Status))
00840     {
00841         /* Mark the cell dirty */
00842         HvMarkCellDirty(Context->ChildHive.KeyHive, ChildCell, FALSE);
00843         
00844         /* Get the key node */
00845         KeyNode = HvGetCell(Context->ChildHive.KeyHive, ChildCell);
00846         if (!KeyNode)
00847         {
00848             /* Fail */
00849             ASSERT(FALSE);
00850             Status = STATUS_INSUFFICIENT_RESOURCES;
00851             goto Exit;
00852         }
00853         
00854         /* Release it */
00855         HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
00856         
00857         /* Set the parent and flags */
00858         KeyNode->Parent = LinkCell;
00859         KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
00860         
00861         /* Get the link node */
00862         KeyNode = HvGetCell(Hive, LinkCell);
00863         if (!KeyNode)
00864         {
00865             /* Fail */
00866             ASSERT(FALSE);
00867             Status = STATUS_INSUFFICIENT_RESOURCES;
00868             goto Exit;
00869         }
00870         
00871         /* Set it up */
00872         KeyNode->Signature = CM_LINK_NODE_SIGNATURE;
00873         KeyNode->Flags = KEY_HIVE_EXIT | KEY_NO_DELETE;
00874         KeyNode->Parent = Cell;
00875         KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, &Name);
00876         if (KeyNode->NameLength < Name.Length) KeyNode->Flags |= KEY_COMP_NAME;
00877         KeQuerySystemTime(&TimeStamp);
00878         KeyNode->LastWriteTime = TimeStamp;
00879         
00880         /* Clear out the rest */
00881         KeyNode->SubKeyCounts[Stable] = 0;
00882         KeyNode->SubKeyCounts[Volatile] = 0;
00883         KeyNode->SubKeyLists[Stable] = HCELL_NIL;
00884         KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
00885         KeyNode->ValueList.Count = 0;
00886         KeyNode->ValueList.List = HCELL_NIL;
00887         KeyNode->ClassLength = 0;
00888         
00889         /* Reference the root node */
00890         KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive;
00891         KeyNode->ChildHiveReference.KeyCell = ChildCell;
00892         HvReleaseCell(Hive, LinkCell);
00893         
00894         /* Get the parent node */
00895         KeyNode = HvGetCell(Hive, Cell);
00896         if (!KeyNode)
00897         {
00898             /* Fail */
00899             ASSERT(FALSE);
00900             Status = STATUS_INSUFFICIENT_RESOURCES;
00901             goto Exit;  
00902         }
00903         
00904         /* Now add the subkey */
00905         if (!CmpAddSubKey(Hive, Cell, LinkCell))
00906         {
00907             /* Failure! We don't handle this yet! */
00908             ASSERT(FALSE);
00909         }
00910         
00911         /* Get the key body */
00912         KeyBody = (PCM_KEY_BODY)*Object;
00913 
00914         /* Sanity checks */
00915         ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
00916         ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
00917         ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
00918         
00919         /* Update the timestamp */
00920         KeQuerySystemTime(&TimeStamp);
00921         KeyNode->LastWriteTime = TimeStamp;
00922         KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
00923         
00924         /* Check if we need to update name maximum */
00925         if (KeyNode->MaxNameLen < Name.Length)
00926         {
00927             /* Do it */
00928             KeyNode->MaxNameLen = Name.Length;
00929             KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name.Length;
00930         }
00931         
00932         /* Check if we need toupdate class length maximum */
00933         if (KeyNode->MaxClassLen < Context->Class.Length)
00934         {
00935             /* Update it */
00936             KeyNode->MaxClassLen = Context->Class.Length;
00937         }
00938         
00939         /* Release the cell */
00940         HvReleaseCell(Hive, Cell);
00941     }
00942     else
00943     {
00944         /* Release the link cell */
00945         HvReleaseCell(Hive, LinkCell);
00946     }
00947     
00948 Exit:
00949     /* Release the flusher locks and return status */
00950     return Status;
00951 }
00952 
00953 VOID
00954 NTAPI
00955 CmpHandleExitNode(IN OUT PHHIVE *Hive,
00956                   IN OUT HCELL_INDEX *Cell,
00957                   IN OUT PCM_KEY_NODE *KeyNode,
00958                   IN OUT PHHIVE *ReleaseHive,
00959                   IN OUT HCELL_INDEX *ReleaseCell)
00960 {
00961     /* Check if we have anything to release */
00962     if (*ReleaseCell != HCELL_NIL)
00963     {
00964         /* Release it */
00965         ASSERT(*ReleaseHive != NULL);
00966         HvReleaseCell((*ReleaseHive), *ReleaseCell);
00967     }
00968     
00969     /* Get the link references */
00970     *Hive = (*KeyNode)->ChildHiveReference.KeyHive;
00971     *Cell = (*KeyNode)->ChildHiveReference.KeyCell;
00972     
00973     /* Get the new node */
00974     *KeyNode = (PCM_KEY_NODE)HvGetCell((*Hive), *Cell);
00975     if (*KeyNode)
00976     {
00977         /* Set the new release values */
00978         *ReleaseCell = *Cell;
00979         *ReleaseHive = *Hive;
00980     }
00981     else
00982     {
00983         /* Nothing to release */
00984         *ReleaseCell = HCELL_NIL;
00985         *ReleaseHive = NULL;
00986     }
00987 }
00988 
00989 NTSTATUS
00990 NTAPI
00991 CmpBuildHashStackAndLookupCache(IN PCM_KEY_BODY ParseObject,
00992                                 IN OUT PCM_KEY_CONTROL_BLOCK *Kcb,
00993                                 IN PUNICODE_STRING Current,
00994                                 OUT PHHIVE *Hive,
00995                                 OUT HCELL_INDEX *Cell,
00996                                 OUT PULONG TotalRemainingSubkeys,
00997                                 OUT PULONG MatchRemainSubkeyLevel,
00998                                 OUT PULONG TotalSubkeys,
00999                                 OUT PULONG OuterStackArray,
01000                                 OUT PULONG *LockedKcbs)
01001 {
01002     /* We don't lock anything for now */
01003     *LockedKcbs = NULL;
01004 
01005     /* Calculate hash values */
01006     *TotalRemainingSubkeys = 0xBAADF00D;
01007     
01008     /* Lock the registry */
01009     CmpLockRegistry();
01010     
01011     /* Return hive and cell data */
01012     *Hive = (*Kcb)->KeyHive;
01013     *Cell = (*Kcb)->KeyCell;
01014 
01015     /* Make sure it's not a dead KCB */
01016     ASSERT((*Kcb)->RefCount > 0);
01017 
01018     /* Reference it */
01019     (VOID)CmpReferenceKeyControlBlock(*Kcb);
01020 
01021     /* Return success for now */
01022     return STATUS_SUCCESS;
01023 }
01024 
01025 NTSTATUS
01026 NTAPI
01027 CmpParseKey(IN PVOID ParseObject,
01028             IN PVOID ObjectType,
01029             IN OUT PACCESS_STATE AccessState,
01030             IN KPROCESSOR_MODE AccessMode,
01031             IN ULONG Attributes,
01032             IN OUT PUNICODE_STRING CompleteName,
01033             IN OUT PUNICODE_STRING RemainingName,
01034             IN OUT PVOID Context OPTIONAL,
01035             IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
01036             OUT PVOID *Object)
01037 {
01038     NTSTATUS Status;
01039     PCM_KEY_CONTROL_BLOCK Kcb, ParentKcb;
01040     PHHIVE Hive = NULL;
01041     PCM_KEY_NODE Node = NULL;
01042     HCELL_INDEX Cell = HCELL_NIL, NextCell;
01043     PHHIVE HiveToRelease = NULL;
01044     HCELL_INDEX CellToRelease = HCELL_NIL;
01045     UNICODE_STRING Current, NextName;
01046     PCM_PARSE_CONTEXT ParseContext = Context;
01047     ULONG TotalRemainingSubkeys = 0, MatchRemainSubkeyLevel = 0, TotalSubkeys = 0;
01048     PULONG LockedKcbs = NULL;
01049     BOOLEAN Result, Last;
01050     PAGED_CODE();
01051 
01052     /* Loop path separators at the end */
01053     while ((RemainingName->Length) &&
01054            (RemainingName->Buffer[(RemainingName->Length / sizeof(WCHAR)) - 1] ==
01055             OBJ_NAME_PATH_SEPARATOR))
01056     {
01057         /* Remove path separator */
01058         RemainingName->Length -= sizeof(WCHAR);
01059     }
01060 
01061     /* Fail if this isn't a key object */
01062     if (ObjectType != CmpKeyObjectType) return STATUS_OBJECT_TYPE_MISMATCH;
01063     
01064     /* Copy the remaining name */
01065     Current = *RemainingName;
01066     
01067     /* Check if this is a create */
01068     if (!(ParseContext) || !(ParseContext->CreateOperation))
01069     {
01070         /* It isn't, so no context */
01071         ParseContext = NULL;
01072     }
01073     
01074     /* Grab the KCB */
01075     Kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock;
01076 
01077     /* Lookup in the cache */
01078     Status = CmpBuildHashStackAndLookupCache(ParseObject,
01079                                              &Kcb,
01080                                              &Current,
01081                                              &Hive,
01082                                              &Cell,
01083                                              &TotalRemainingSubkeys,
01084                                              &MatchRemainSubkeyLevel,
01085                                              &TotalSubkeys,
01086                                              NULL,
01087                                              &LockedKcbs);
01088     
01089     /* This is now the parent */
01090     ParentKcb = Kcb;
01091     
01092     /* Check if everything was found cached */
01093     if (!TotalRemainingSubkeys) ASSERTMSG("Caching not implemented", FALSE);
01094 
01095     /* Don't do anything if we're being deleted */
01096     if (Kcb->Delete)
01097     {
01098         Status = STATUS_OBJECT_NAME_NOT_FOUND;
01099         goto Quickie;
01100     }
01101 
01102     /* Check if this is a symlink */
01103     if (Kcb->Flags & KEY_SYM_LINK)
01104     {
01105         /* Get the next name */
01106         Result = CmpGetNextName(&Current, &NextName, &Last);
01107         Current.Buffer = NextName.Buffer;
01108 
01109         /* Validate the current name string length */
01110         if (Current.Length + NextName.Length > MAXUSHORT)
01111         {
01112             /* too long */
01113             Status = STATUS_NAME_TOO_LONG;
01114             goto Quickie;
01115         }
01116         Current.Length += NextName.Length;
01117 
01118         /* Validate the current name string maximum length */
01119         if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
01120         {
01121             /* too long */
01122             Status = STATUS_NAME_TOO_LONG;
01123             goto Quickie;
01124         }
01125         Current.MaximumLength += NextName.MaximumLength;
01126         
01127         /* Parse the symlink */
01128         if (CmpGetSymbolicLink(Hive,
01129                                CompleteName,
01130                                Kcb,
01131                                &Current))
01132         {
01133             /* Symlink parse succeeded */
01134             Status = STATUS_REPARSE;
01135         }
01136         else
01137         {
01138             /* Couldn't find symlink */
01139             Status = STATUS_OBJECT_NAME_NOT_FOUND;
01140         }
01141 
01142         /* We're done */
01143         goto Quickie;
01144     }
01145     
01146     /* Get the key node */
01147     Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
01148     if (!Node)
01149     {
01150         Status = STATUS_INSUFFICIENT_RESOURCES;
01151         goto Quickie;
01152     }
01153 
01154     /* Start parsing */
01155     Status = STATUS_NOT_IMPLEMENTED;
01156     while (TRUE)
01157     {
01158         /* Get the next component */
01159         Result = CmpGetNextName(&Current, &NextName, &Last);
01160         if ((Result) && (NextName.Length))
01161         {
01162             /* See if this is a sym link */
01163             if (!(Kcb->Flags & KEY_SYM_LINK))
01164             {
01165                 /* Find the subkey */
01166                 NextCell = CmpFindSubKeyByName(Hive, Node, &NextName);
01167                 if (NextCell != HCELL_NIL)
01168                 {
01169                     /* Get the new node */
01170                     Cell = NextCell;
01171                     Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
01172                     if (!Node) ASSERT(FALSE);
01173                     
01174                     /* Check if this was the last key */
01175                     if (Last)
01176                     {
01177                         /* Is this an exit node */
01178                         if (Node->Flags & KEY_HIVE_EXIT)
01179                         {
01180                             /* Handle it */
01181                             CmpHandleExitNode(&Hive,
01182                                               &Cell,
01183                                               &Node,
01184                                               &HiveToRelease,
01185                                               &CellToRelease);
01186                             if (!Node) ASSERT(FALSE);
01187                         }
01188                         
01189                         /* Do the open */
01190                         Status = CmpDoOpen(Hive,
01191                                            Cell,
01192                                            Node,
01193                                            AccessState,
01194                                            AccessMode,
01195                                            Attributes,
01196                                            ParseContext,
01197                                            0,
01198                                            &Kcb,
01199                                            &NextName,
01200                                            Object);
01201                         if (Status == STATUS_REPARSE)
01202                         {
01203                             /* Parse the symlink */
01204                             if (!CmpGetSymbolicLink(Hive,
01205                                                     CompleteName,
01206                                                     Kcb,
01207                                                     NULL))
01208                             {
01209                                 /* Symlink parse failed */
01210                                 Status = STATUS_OBJECT_NAME_NOT_FOUND;
01211                             }
01212                         }
01213                         
01214                         /* We are done */
01215                         break;
01216                     }
01217                     
01218                     /* Is this an exit node */
01219                     if (Node->Flags & KEY_HIVE_EXIT)
01220                     {
01221                         /* Handle it */
01222                         CmpHandleExitNode(&Hive,
01223                                           &Cell,
01224                                           &Node,
01225                                           &HiveToRelease,
01226                                           &CellToRelease);
01227                         if (!Node) ASSERT(FALSE);
01228                     }
01229 
01230                     /* Create a KCB for this key */
01231                     Kcb = CmpCreateKeyControlBlock(Hive,
01232                                                    Cell,
01233                                                    Node,
01234                                                    ParentKcb,
01235                                                    0,
01236                                                    &NextName);
01237                     if (!Kcb) ASSERT(FALSE);
01238                     
01239                     /* Dereference the parent and set the new one */
01240                     CmpDereferenceKeyControlBlock(ParentKcb);
01241                     ParentKcb = Kcb;
01242                 }
01243                 else
01244                 {
01245                     /* Check if this was the last key for a create */
01246                     if ((Last) && (ParseContext))
01247                     {
01248                         /* Check if we're doing a link node */
01249                         if (ParseContext->CreateLink)
01250                         {
01251                             /* The only thing we should see */
01252                             Status = CmpCreateLinkNode(Hive,
01253                                                        Cell,
01254                                                        AccessState,
01255                                                        NextName,
01256                                                        AccessMode,
01257                                                        Attributes,
01258                                                        ParseContext,
01259                                                        ParentKcb,
01260                                                        Object);
01261                         }
01262                         else
01263                         {
01264                             /* Do the create */
01265                             Status = CmpDoCreate(Hive,
01266                                                  Cell,
01267                                                  AccessState,
01268                                                  &NextName,
01269                                                  AccessMode,
01270                                                  ParseContext,
01271                                                  ParentKcb,
01272                                                  Object);
01273                         }
01274                         
01275                         /* Check for reparse (in this case, someone beat us) */
01276                         if (Status == STATUS_REPARSE) break;
01277 
01278                         /* Update disposition */
01279                         ParseContext->Disposition = REG_CREATED_NEW_KEY;
01280                         break;
01281                     }
01282                     else
01283                     {
01284                         /* Key not found */
01285                         Status = STATUS_OBJECT_NAME_NOT_FOUND;
01286                         break;
01287                     }
01288                 }
01289             }
01290             else
01291             {
01292                 /* Save the next name */
01293                 Current.Buffer = NextName.Buffer;
01294                 
01295                 /* Validate the current name string length */
01296                 if (Current.Length + NextName.Length > MAXUSHORT)
01297                 {
01298                     /* too long */
01299                     Status = STATUS_NAME_TOO_LONG;
01300                     break;
01301                 }
01302                 Current.Length += NextName.Length;
01303                 
01304                 /* Validate the current name string maximum length */
01305                 if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
01306                 {
01307                     /* too long */
01308                     Status = STATUS_NAME_TOO_LONG;
01309                     break;
01310                 }
01311                 Current.MaximumLength += NextName.MaximumLength;
01312                 
01313                 /* Parse the symlink */
01314                 if (CmpGetSymbolicLink(Hive,
01315                                        CompleteName,
01316                                        Kcb,
01317                                        &Current))
01318                 {
01319                     /* Symlink parse succeeded */
01320                     Status = STATUS_REPARSE;
01321                 }
01322                 else
01323                 {
01324                     /* Couldn't find symlink */
01325                     Status = STATUS_OBJECT_NAME_NOT_FOUND;
01326                 }
01327 
01328                 /* We're done */
01329                 break;
01330             }
01331         }
01332         else if ((Result) && (Last))
01333         {
01334             /* Opening the root. Is this an exit node? */
01335             if (Node->Flags & KEY_HIVE_EXIT)
01336             {
01337                 /* Handle it */
01338                 CmpHandleExitNode(&Hive,
01339                                   &Cell,
01340                                   &Node,
01341                                   &HiveToRelease,
01342                                   &CellToRelease);
01343                 if (!Node) ASSERT(FALSE);
01344             }
01345 
01346             /* Do the open */
01347             Status = CmpDoOpen(Hive,
01348                                Cell,
01349                                Node,
01350                                AccessState,
01351                                AccessMode,
01352                                Attributes,
01353                                ParseContext,
01354                                CMP_OPEN_KCB_NO_CREATE /* | CMP_CREATE_KCB_KCB_LOCKED */,
01355                                &Kcb,
01356                                &NextName,
01357                                Object);
01358             if (Status == STATUS_REPARSE)
01359             {
01360                 /* Nothing to do */
01361             }
01362             
01363             /* We're done */
01364             break;
01365         }
01366         else
01367         {
01368             /* Bogus */
01369             Status = STATUS_INVALID_PARAMETER;
01370             break;
01371         }
01372     }
01373 
01374     /* Dereference the parent if it exists */
01375 Quickie:
01376     if (ParentKcb) CmpDereferenceKeyControlBlock(ParentKcb);
01377     
01378     /* Unlock the registry */
01379     CmpUnlockRegistry();
01380     return Status;
01381 }

Generated on Sat May 26 2012 04:35:58 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.