Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmparse.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
1.7.6.1
|