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

cmboot.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            ntoskrnl/config/cmboot.c
00005  * PURPOSE:         Configuration Manager - Boot Initialization
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  *                  Alex Ionescu (alex.ionescu@reactos.org)
00008  */
00009 
00010 /* INCLUDES *******************************************************************/
00011 
00012 #include "ntoskrnl.h"
00013 #define NDEBUG
00014 #include "debug.h"
00015 
00016 /* GLOBALS ********************************************************************/
00017 
00018 extern ULONG InitSafeBootMode;
00019 
00020 /* FUNCTIONS ******************************************************************/
00021 
00022 HCELL_INDEX
00023 NTAPI
00024 INIT_FUNCTION
00025 CmpFindControlSet(IN PHHIVE SystemHive,
00026                   IN HCELL_INDEX RootCell,
00027                   IN PUNICODE_STRING SelectKeyName,
00028                   OUT PBOOLEAN AutoSelect)
00029 {
00030     UNICODE_STRING KeyName;
00031     PCM_KEY_NODE Node;
00032     HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
00033     HCELL_INDEX CurrentValueCell;
00034     PCM_KEY_VALUE KeyValue;
00035     ULONG Length;
00036     PULONG ControlSetId;
00037     ANSI_STRING ControlSetAnsiName;
00038     CHAR Buffer[128];
00039     WCHAR WideBuffer[128];
00040     NTSTATUS Status;
00041     PULONG CurrentData;
00042 
00043     /* Sanity check */
00044     ASSERT(SystemHive->ReleaseCellRoutine == NULL);
00045 
00046     /* Get the Select subkey */
00047     RtlInitUnicodeString(&KeyName, L"select");
00048     Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
00049     if (!Node) return HCELL_NIL;
00050     SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
00051     if (SelectCell == HCELL_NIL) return SelectCell;
00052 
00053     /* Get AutoSelect value */
00054     RtlInitUnicodeString(&KeyName, L"AutoSelect");
00055     Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
00056     if (!Node) return HCELL_NIL;
00057     AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName);
00058     if (AutoSelectCell == HCELL_NIL)
00059     {
00060         /* Assume TRUE if the value is missing. */
00061         *AutoSelect = TRUE;
00062     }
00063     else
00064     {
00065         /* Read the value */
00066         KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
00067         if (KeyValue == NULL) return HCELL_NIL;
00068 
00069         /* Convert it to a boolean */
00070         *AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length);
00071     }
00072 
00073     /* Now find the control set being looked up */
00074     Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
00075     if (!Node) return HCELL_NIL;
00076     SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
00077     if (SelectValueCell == HCELL_NIL) return SelectValueCell;
00078 
00079     /* Read the value (corresponding to the CCS ID) */
00080     KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
00081     if (!KeyValue) return HCELL_NIL;
00082     if (KeyValue->Type != REG_DWORD) return HCELL_NIL;
00083     ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length);
00084 
00085     /* Now build an Ansi String for the CCS's Name */
00086     sprintf(Buffer, "ControlSet%03lu", *ControlSetId);
00087     ControlSetAnsiName.Length = (USHORT)strlen(Buffer);
00088     ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer);
00089     ControlSetAnsiName.Buffer = Buffer;
00090 
00091     /* And convert it to Unicode... */
00092     KeyName.MaximumLength = 256;
00093     KeyName.Buffer = WideBuffer;
00094     Status = RtlAnsiStringToUnicodeString(&KeyName,
00095                                           &ControlSetAnsiName,
00096                                           FALSE);
00097     if (!NT_SUCCESS(Status)) return HCELL_NIL;
00098 
00099     /* Now open it */
00100     Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
00101     if (!Node) return HCELL_NIL;
00102     ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
00103     if (ControlSetCell == HCELL_NIL) return ControlSetCell;
00104 
00105     /* Get the value of the "Current" CCS */
00106     RtlInitUnicodeString(&KeyName, L"Current");
00107     Node =  (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
00108     if (!Node) return HCELL_NIL;
00109     CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
00110 
00111     /* Make sure it exists */
00112     if (CurrentValueCell != HCELL_NIL)
00113     {
00114         /* Get the current value and make sure its a ULONG */
00115         KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
00116         if (!KeyValue) return HCELL_NIL;
00117         if (KeyValue->Type == REG_DWORD)
00118         {
00119             /* Get the data and update it */
00120             CurrentData = (PULONG)CmpValueToData(SystemHive,
00121                                                  KeyValue,
00122                                                  &Length);
00123             if (!CurrentData) return HCELL_NIL;
00124             *CurrentData = *ControlSetId;
00125         }
00126     }
00127 
00128     /* Return the CCS Cell */
00129     return ControlSetCell;
00130 }
00131 
00132 ULONG
00133 NTAPI
00134 INIT_FUNCTION
00135 CmpFindTagIndex(IN PHHIVE Hive,
00136                 IN HCELL_INDEX TagCell,
00137                 IN HCELL_INDEX GroupOrderCell,
00138                 IN PUNICODE_STRING GroupName)
00139 {
00140     PCM_KEY_VALUE TagValue, Value;
00141     HCELL_INDEX OrderCell;
00142     PULONG TagOrder, DriverTag;
00143     ULONG CurrentTag, Length;
00144     PCM_KEY_NODE Node;
00145     BOOLEAN BufferAllocated;
00146     ASSERT(Hive->ReleaseCellRoutine == NULL);
00147     
00148     /* Get the tag */
00149     Value = HvGetCell(Hive, TagCell);
00150     ASSERT(Value);
00151     DriverTag = (PULONG)CmpValueToData(Hive, Value, &Length);
00152     ASSERT(DriverTag);
00153 
00154     /* Get the order array */
00155     Node = HvGetCell(Hive, GroupOrderCell);
00156     ASSERT(Node);
00157     OrderCell = CmpFindValueByName(Hive, Node, GroupName);
00158     if (OrderCell == HCELL_NIL) return -2;
00159     
00160     /* And read it */
00161     TagValue = HvGetCell(Hive, OrderCell);
00162     CmpGetValueData(Hive, TagValue, &Length, (PVOID*)&TagOrder, &BufferAllocated, &OrderCell);
00163     ASSERT(TagOrder);
00164     
00165     /* Parse each tag */
00166     for (CurrentTag = 1; CurrentTag <= TagOrder[0]; CurrentTag++)
00167     {
00168         /* Find a match */
00169         if (TagOrder[CurrentTag] == *DriverTag)
00170         {
00171             /* Found it -- return the tag */
00172             if (BufferAllocated) ExFreePool(TagOrder);
00173             return CurrentTag;
00174         }
00175     }
00176     
00177     /* No matches, so assume next to last ordering */
00178     if (BufferAllocated) ExFreePool(TagOrder);
00179     return -2;
00180 }
00181 
00182 BOOLEAN
00183 NTAPI
00184 INIT_FUNCTION
00185 CmpAddDriverToList(IN PHHIVE Hive,
00186                    IN HCELL_INDEX DriverCell,
00187                    IN HCELL_INDEX GroupOrderCell,
00188                    IN PUNICODE_STRING RegistryPath,
00189                    IN PLIST_ENTRY BootDriverListHead)
00190 {
00191     PBOOT_DRIVER_NODE DriverNode;
00192     PBOOT_DRIVER_LIST_ENTRY DriverEntry;
00193     PCM_KEY_NODE Node;
00194     ULONG Length;
00195     USHORT NameLength;
00196     HCELL_INDEX ValueCell, TagCell;    PCM_KEY_VALUE Value;
00197     PUNICODE_STRING FileName, RegistryString;
00198     UNICODE_STRING UnicodeString;
00199     PULONG ErrorControl;
00200     PWCHAR Buffer;
00201     ASSERT(Hive->ReleaseCellRoutine == NULL);
00202     
00203     /* Allocate a driver node and initialize it */
00204     DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM);
00205     if (!DriverNode) return FALSE;
00206     DriverEntry = &DriverNode->ListEntry;
00207     DriverEntry->RegistryPath.Buffer = NULL;
00208     DriverEntry->FilePath.Buffer = NULL;
00209     
00210     /* Get the driver cell */
00211     Node = HvGetCell(Hive, DriverCell);
00212     ASSERT(Node);
00213     
00214     /* Get the name from the cell */
00215     DriverNode->Name.Length = Node->Flags & KEY_COMP_NAME ?
00216                               CmpCompressedNameSize(Node->Name, Node->NameLength) :
00217                               Node->NameLength;
00218     DriverNode->Name.MaximumLength = DriverNode->Name.Length;
00219     NameLength = DriverNode->Name.Length;
00220     
00221     /* Now allocate the buffer for it and copy the name */
00222     DriverNode->Name.Buffer = CmpAllocate(NameLength, FALSE, TAG_CM);
00223     if (!DriverNode->Name.Buffer) return FALSE;
00224     if (Node->Flags & KEY_COMP_NAME)
00225     {
00226         /* Compressed name */
00227         CmpCopyCompressedName(DriverNode->Name.Buffer,
00228                               DriverNode->Name.Length,
00229                               Node->Name,
00230                               Node->NameLength);
00231     }
00232     else
00233     {
00234         /* Normal name */
00235         RtlCopyMemory(DriverNode->Name.Buffer, Node->Name, Node->NameLength);
00236     }
00237     
00238     /* Now find the image path */
00239     RtlInitUnicodeString(&UnicodeString, L"ImagePath");
00240     ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
00241     if (ValueCell == HCELL_NIL)
00242     {
00243         /* Couldn't find it, so assume the drivers path */
00244         Length = sizeof(L"System32\\Drivers\\") + NameLength + sizeof(L".sys");
00245         
00246         /* Allocate the path name */
00247         FileName = &DriverEntry->FilePath;
00248         FileName->Length = 0;
00249         FileName->MaximumLength = (USHORT)Length;
00250         FileName->Buffer = CmpAllocate(Length, FALSE,TAG_CM);
00251         if (!FileName->Buffer) return FALSE;
00252 
00253         /* Write the path name */
00254         RtlAppendUnicodeToString(FileName, L"System32\\Drivers\\");
00255         RtlAppendUnicodeStringToString(FileName, &DriverNode->Name);
00256         RtlAppendUnicodeToString(FileName, L".sys");
00257     }
00258     else
00259     {
00260         /* Path name exists, so grab it */
00261         Value = HvGetCell(Hive, ValueCell);
00262         ASSERT(Value);
00263 
00264         /* Allocate and setup the path name */
00265         FileName = &DriverEntry->FilePath;
00266         Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length);
00267         FileName->MaximumLength = FileName->Length = (USHORT)Length;
00268         FileName->Buffer = CmpAllocate(Length, FALSE, TAG_CM);
00269         
00270         /* Transfer the data */
00271         if (!(FileName->Buffer) || !(Buffer)) return FALSE;
00272         RtlCopyMemory(FileName->Buffer, Buffer, Length);
00273     }
00274     
00275     /* Now build the registry path */
00276     RegistryString = &DriverEntry->RegistryPath;
00277     RegistryString->Length = 0;
00278     RegistryString->MaximumLength = RegistryPath->Length + NameLength;
00279     RegistryString->Buffer = CmpAllocate(RegistryString->MaximumLength, FALSE, TAG_CM);
00280     if (!RegistryString->Buffer) return FALSE;
00281     
00282     /* Add the driver name to it */
00283     RtlAppendUnicodeStringToString(RegistryString, RegistryPath);
00284     RtlAppendUnicodeStringToString(RegistryString, &DriverNode->Name);
00285     
00286     /* The entry is done, add it */
00287     InsertHeadList(BootDriverListHead, &DriverEntry->Link);
00288     
00289     /* Now find error control settings */
00290     RtlInitUnicodeString(&UnicodeString, L"ErrorControl");
00291     ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
00292     if (ValueCell == HCELL_NIL)
00293     {
00294         /* Couldn't find it, so assume default */
00295         DriverNode->ErrorControl = NormalError;
00296     }
00297     else
00298     {
00299         /* Otherwise, read whatever the data says */
00300         Value = HvGetCell(Hive, ValueCell);
00301         ASSERT(Value);
00302         ErrorControl = (PULONG)CmpValueToData(Hive, Value, &Length);
00303         ASSERT(ErrorControl);
00304         DriverNode->ErrorControl = *ErrorControl;
00305     }
00306     
00307     /* Next, get the group cell */
00308     RtlInitUnicodeString(&UnicodeString, L"group");
00309     ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
00310     if (ValueCell == HCELL_NIL)
00311     {
00312         /* Couldn't find, so set an empty string */
00313         RtlInitEmptyUnicodeString(&DriverNode->Group, NULL, 0);
00314     }
00315     else
00316     {
00317         /* Found it, read the group value */
00318         Value = HvGetCell(Hive, ValueCell);
00319         ASSERT(Value);
00320         
00321         /* Copy it into the node */
00322         DriverNode->Group.Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length);
00323         if (!DriverNode->Group.Buffer) return FALSE;
00324         DriverNode->Group.Length = (USHORT)Length - sizeof(UNICODE_NULL);
00325         DriverNode->Group.MaximumLength = DriverNode->Group.Length;
00326     }
00327     
00328     /* Finally, find the tag */
00329     RtlInitUnicodeString(&UnicodeString, L"Tag");
00330     TagCell = CmpFindValueByName(Hive, Node, &UnicodeString);
00331     if (TagCell == HCELL_NIL)
00332     {
00333         /* No tag, so load last */
00334         DriverNode->Tag = -1;
00335     }
00336     else
00337     {
00338         /* Otherwise, decode it based on tag order */
00339         DriverNode->Tag = CmpFindTagIndex(Hive,
00340                                           TagCell,
00341                                           GroupOrderCell,
00342                                           &DriverNode->Group);
00343     }
00344     
00345     /* All done! */
00346     return TRUE;
00347 }
00348 
00349 BOOLEAN
00350 NTAPI
00351 INIT_FUNCTION
00352 CmpIsLoadType(IN PHHIVE Hive,
00353               IN HCELL_INDEX Cell,
00354               IN SERVICE_LOAD_TYPE LoadType)
00355 {
00356     PCM_KEY_NODE Node;
00357     HCELL_INDEX ValueCell;
00358     UNICODE_STRING ValueString = RTL_CONSTANT_STRING(L"Start");
00359     PCM_KEY_VALUE Value;
00360     ULONG Length;
00361     PLONG Data;
00362     ASSERT(Hive->ReleaseCellRoutine == NULL);
00363 
00364     /* Open the start cell */
00365     Node = HvGetCell(Hive, Cell);
00366     ASSERT(Node);
00367     ValueCell = CmpFindValueByName(Hive, Node, &ValueString);
00368     if (ValueCell == HCELL_NIL) return FALSE;
00369     
00370     /* Read the start value */
00371     Value = HvGetCell(Hive, ValueCell);
00372     ASSERT(Value);
00373     Data = (PLONG)CmpValueToData(Hive, Value, &Length);
00374     ASSERT(Data);
00375     
00376     /* Return if the type matches */
00377     return (*Data == LoadType);
00378 }
00379 
00380 BOOLEAN
00381 NTAPI
00382 INIT_FUNCTION
00383 CmpFindDrivers(IN PHHIVE Hive,
00384                IN HCELL_INDEX ControlSet,
00385                IN SERVICE_LOAD_TYPE LoadType,
00386                IN PWCHAR BootFileSystem OPTIONAL,
00387                IN PLIST_ENTRY DriverListHead)
00388 {
00389     HCELL_INDEX ServicesCell, ControlCell, GroupOrderCell, DriverCell;
00390     HCELL_INDEX SafeBootCell = HCELL_NIL;
00391     UNICODE_STRING Name;
00392     ULONG i;
00393     WCHAR Buffer[128];
00394     UNICODE_STRING UnicodeString, KeyPath;
00395     PBOOT_DRIVER_NODE FsNode;
00396     PCM_KEY_NODE ControlNode, ServicesNode, Node;
00397     ASSERT(Hive->ReleaseCellRoutine == NULL);
00398     
00399     /* Open the control set key */
00400     ControlNode = HvGetCell(Hive, ControlSet);
00401     ASSERT(ControlNode);
00402     
00403     /* Get services cell */
00404     RtlInitUnicodeString(&Name, L"Services");
00405     ServicesCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
00406     if (ServicesCell == HCELL_NIL) return FALSE;
00407 
00408     /* Open services key */
00409     ServicesNode = HvGetCell(Hive, ServicesCell);
00410     ASSERT(ServicesNode);
00411     
00412     /* Get control cell */
00413     RtlInitUnicodeString(&Name, L"Control");
00414     ControlCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
00415     if (ControlCell == HCELL_NIL) return FALSE;
00416     
00417     /* Get the group order cell and read it */
00418     RtlInitUnicodeString(&Name, L"GroupOrderList");
00419     Node = HvGetCell(Hive, ControlCell);
00420     ASSERT(Node);
00421     GroupOrderCell = CmpFindSubKeyByName(Hive, Node, &Name);
00422     if (GroupOrderCell == HCELL_NIL) return FALSE;
00423 
00424     /* Get Safe Boot cell */
00425     if(InitSafeBootMode)
00426     {
00427         /* Open the Safe Boot key */
00428         RtlInitUnicodeString(&Name, L"SafeBoot");
00429         Node = HvGetCell(Hive, ControlCell);
00430         ASSERT(Node);
00431         SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name);
00432         if (SafeBootCell == HCELL_NIL) return FALSE;
00433 
00434         /* Open the correct start key (depending on the mode) */
00435         Node = HvGetCell(Hive, SafeBootCell);
00436         ASSERT(Node);
00437         switch(InitSafeBootMode)
00438         {
00439             /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
00440             case 1:
00441             case 3: RtlInitUnicodeString(&Name, L"Minimal"); break;
00442             case 2: RtlInitUnicodeString(&Name, L"Network"); break;
00443             default: return FALSE;
00444         }
00445         SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name);
00446         if(SafeBootCell == HCELL_NIL) return FALSE;
00447     }
00448 
00449     /* Build the root registry path */
00450     RtlInitEmptyUnicodeString(&KeyPath, Buffer, sizeof(Buffer));
00451     RtlAppendUnicodeToString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
00452     
00453     /* Find the first subkey (ie: the first driver or service) */
00454     i = 0;
00455     DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, i);
00456     while (DriverCell != HCELL_NIL)
00457     {
00458         /* Make sure it's a driver of this start type AND is "safe" to load */
00459         if (CmpIsLoadType(Hive, DriverCell, LoadType) &&
00460             CmpIsSafe(Hive, SafeBootCell, DriverCell))
00461         {
00462             /* Add it to the list */
00463             CmpAddDriverToList(Hive,
00464                                DriverCell,
00465                                GroupOrderCell,
00466                                &KeyPath,
00467                                DriverListHead);
00468             
00469         }
00470         
00471         /* Try the next subkey */
00472         DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, ++i);
00473     }
00474     
00475     /* Check if we have a boot file system */
00476     if (BootFileSystem)
00477     {
00478         /* Find it */
00479         RtlInitUnicodeString(&UnicodeString, BootFileSystem);
00480         DriverCell = CmpFindSubKeyByName(Hive, ServicesNode, &UnicodeString);
00481         if (DriverCell != HCELL_NIL)
00482         {
00483             /* Always add it to the list */
00484             CmpAddDriverToList(Hive,
00485                                DriverCell,
00486                                GroupOrderCell,
00487                                &KeyPath,
00488                                DriverListHead);
00489             
00490             /* Mark it as critical so it always loads */
00491             FsNode = CONTAINING_RECORD(DriverListHead->Flink,
00492                                        BOOT_DRIVER_NODE,
00493                                        ListEntry.Link);
00494             FsNode->ErrorControl = SERVICE_ERROR_CRITICAL;
00495         }
00496     }
00497     
00498     /* We're done! */
00499     return TRUE;
00500 }
00501 
00502 BOOLEAN
00503 NTAPI
00504 INIT_FUNCTION
00505 CmpDoSort(IN PLIST_ENTRY DriverListHead,
00506           IN PUNICODE_STRING OrderList)
00507 {
00508     PWCHAR Current, End = NULL;
00509     PLIST_ENTRY NextEntry;
00510     UNICODE_STRING GroupName;
00511     PBOOT_DRIVER_NODE CurrentNode;
00512     
00513     /* We're going from end to start, so get to the last group and keep going */
00514     Current = &OrderList->Buffer[OrderList->Length / sizeof(WCHAR)];
00515     while (Current > OrderList->Buffer)
00516     {
00517         /* Scan the current string */
00518         do
00519         {
00520             if (*Current == UNICODE_NULL) End = Current;
00521         } while ((*(--Current - 1) != UNICODE_NULL) && (Current != OrderList->Buffer));
00522 
00523         /* This is our cleaned up string for this specific group */
00524         ASSERT(End != NULL);
00525         GroupName.Length = (USHORT)(End - Current) * sizeof(WCHAR);
00526         GroupName.MaximumLength = GroupName.Length;
00527         GroupName.Buffer = Current;
00528 
00529         /* Now loop the driver list */
00530         NextEntry = DriverListHead->Flink;
00531         while (NextEntry != DriverListHead)
00532         {
00533             /* Get this node */
00534             CurrentNode = CONTAINING_RECORD(NextEntry,
00535                                             BOOT_DRIVER_NODE,
00536                                             ListEntry.Link);
00537                                             
00538             /* Get the next entry now since we'll do a relink */
00539             NextEntry = CurrentNode->ListEntry.Link.Flink;
00540             
00541             /* Is there a group name and does it match the current group? */
00542             if ((CurrentNode->Group.Buffer) &&
00543                 (RtlEqualUnicodeString(&GroupName, &CurrentNode->Group, TRUE)))
00544             {
00545                 /* Remove from this location and re-link in the new one */
00546                 RemoveEntryList(&CurrentNode->ListEntry.Link);
00547                 InsertHeadList(DriverListHead, &CurrentNode->ListEntry.Link);
00548             }
00549         }
00550         
00551         /* Move on */
00552         Current--;
00553     }
00554     
00555     /* All done */
00556     return TRUE;
00557 }
00558 
00559 BOOLEAN
00560 NTAPI
00561 INIT_FUNCTION
00562 CmpSortDriverList(IN PHHIVE Hive,
00563                   IN HCELL_INDEX ControlSet,
00564                   IN PLIST_ENTRY DriverListHead)
00565 {
00566     HCELL_INDEX Controls, GroupOrder, ListCell;
00567     UNICODE_STRING Name, DependList;
00568     PCM_KEY_VALUE ListNode;
00569     ULONG Length;
00570     PCM_KEY_NODE Node;
00571     ASSERT(Hive->ReleaseCellRoutine == NULL);
00572 
00573     /* Open the control key */
00574     Node = HvGetCell(Hive, ControlSet);
00575     ASSERT(Node);
00576     RtlInitUnicodeString(&Name, L"Control");
00577     Controls = CmpFindSubKeyByName(Hive, Node, &Name);
00578     if (Controls == HCELL_NIL) return FALSE;
00579 
00580     /* Open the service group order */
00581     Node = HvGetCell(Hive, Controls);
00582     ASSERT(Node);
00583     RtlInitUnicodeString(&Name, L"ServiceGroupOrder");
00584     GroupOrder = CmpFindSubKeyByName(Hive, Node, &Name);
00585     if (GroupOrder == HCELL_NIL) return FALSE;
00586 
00587     /* Open the list key */
00588     Node = HvGetCell(Hive, GroupOrder);
00589     ASSERT(Node);
00590     RtlInitUnicodeString(&Name, L"list");
00591     ListCell = CmpFindValueByName(Hive, Node, &Name);
00592     if (ListCell == HCELL_NIL) return FALSE;
00593     
00594     /* Now read the actual list */
00595     ListNode = HvGetCell(Hive, ListCell);
00596     ASSERT(ListNode);
00597     if (ListNode->Type != REG_MULTI_SZ) return FALSE;
00598     
00599     /* Copy it into a buffer */
00600     DependList.Buffer = (PWCHAR)CmpValueToData(Hive, ListNode, &Length);
00601     if (!DependList.Buffer) return FALSE;
00602     DependList.Length = DependList.MaximumLength = (USHORT)Length - sizeof(UNICODE_NULL);
00603     
00604     /* And start the recurive sort algorithm */
00605     return CmpDoSort(DriverListHead, &DependList);
00606 }
00607 
00608 BOOLEAN
00609 NTAPI
00610 INIT_FUNCTION
00611 CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode,
00612               IN PBOOT_DRIVER_NODE EndNode)
00613 {
00614     PBOOT_DRIVER_NODE CurrentNode, PreviousNode;
00615     PLIST_ENTRY ListEntry;
00616     
00617     /* Base case, nothing to do */
00618     if (StartNode == EndNode) return TRUE;
00619     
00620     /* Loop the nodes */
00621     CurrentNode = StartNode;
00622     do
00623     {
00624         /* Save this as the previous node */
00625         PreviousNode = CurrentNode;
00626         
00627         /* And move to the next one */
00628         ListEntry = CurrentNode->ListEntry.Link.Flink;
00629         CurrentNode = CONTAINING_RECORD(ListEntry,
00630                                         BOOT_DRIVER_NODE,
00631                                         ListEntry.Link);
00632         
00633         /* Check if the previous driver had a bigger tag */
00634         if (PreviousNode->Tag > CurrentNode->Tag)
00635         {
00636             /* Check if we need to update the tail */
00637             if (CurrentNode == EndNode)
00638             {
00639                 /* Update the tail */
00640                 ListEntry = CurrentNode->ListEntry.Link.Blink;
00641                 EndNode = CONTAINING_RECORD(ListEntry,
00642                                             BOOT_DRIVER_NODE,
00643                                             ListEntry.Link);
00644             }
00645             
00646             /* Remove this driver since we need to move it */
00647             RemoveEntryList(&CurrentNode->ListEntry.Link);
00648             
00649             /* Keep looping until we find a driver with a lower tag than ours */
00650             while ((PreviousNode->Tag > CurrentNode->Tag) && (PreviousNode != StartNode))
00651             {
00652                 /* We'll be re-inserted at this spot */
00653                 ListEntry = PreviousNode->ListEntry.Link.Blink;
00654                 PreviousNode = CONTAINING_RECORD(ListEntry,
00655                                                  BOOT_DRIVER_NODE,
00656                                                  ListEntry.Link);
00657             }
00658             
00659             /* Do the insert in the new location */
00660             InsertTailList(&PreviousNode->ListEntry.Link, &CurrentNode->ListEntry.Link);
00661             
00662             /* Update the head, if needed */
00663             if (PreviousNode == StartNode) StartNode = CurrentNode;
00664         }
00665     } while (CurrentNode != EndNode);
00666     
00667     /* All done */
00668     return TRUE;
00669 }
00670 
00671 BOOLEAN
00672 NTAPI
00673 INIT_FUNCTION
00674 CmpResolveDriverDependencies(IN PLIST_ENTRY DriverListHead)
00675 {
00676     PLIST_ENTRY NextEntry;
00677     PBOOT_DRIVER_NODE StartNode, EndNode, CurrentNode;
00678     
00679     /* Loop the list */
00680     NextEntry = DriverListHead->Flink;
00681     while (NextEntry != DriverListHead)
00682     {
00683         /* Find the first entry */
00684         StartNode = CONTAINING_RECORD(NextEntry,
00685                                       BOOT_DRIVER_NODE,
00686                                       ListEntry.Link);
00687         do
00688         {
00689             /* Find the last entry */
00690             EndNode = CONTAINING_RECORD(NextEntry,
00691                                         BOOT_DRIVER_NODE,
00692                                         ListEntry.Link);
00693             
00694             /* Get the next entry */
00695             NextEntry = NextEntry->Flink;
00696             CurrentNode = CONTAINING_RECORD(NextEntry,
00697                                             BOOT_DRIVER_NODE,
00698                                             ListEntry.Link);
00699             
00700             /* If the next entry is back to the top, break out */
00701             if (NextEntry == DriverListHead) break;
00702             
00703             /* Otherwise, check if this entry is equal */
00704             if (!RtlEqualUnicodeString(&StartNode->Group,
00705                                        &CurrentNode->Group,
00706                                        TRUE))
00707             {
00708                 /* It is, so we've detected a cycle, break out */
00709                 break;
00710             }
00711         } while (NextEntry != DriverListHead);
00712         
00713         /* Now we have the correct start and end pointers, so do the sort */
00714         CmpOrderGroup(StartNode, EndNode);
00715     }
00716     
00717     /* We're done */
00718     return TRUE;
00719 }
00720 
00721 BOOLEAN
00722 NTAPI
00723 INIT_FUNCTION
00724 CmpIsSafe(IN PHHIVE Hive,
00725           IN HCELL_INDEX SafeBootCell,
00726           IN HCELL_INDEX DriverCell)
00727 {
00728     PCM_KEY_NODE SafeBootNode;
00729     PCM_KEY_NODE DriverNode;
00730     PCM_KEY_VALUE KeyValue;
00731     HCELL_INDEX CellIndex;
00732     ULONG Length = 0;
00733     UNICODE_STRING Name;
00734     PWCHAR OriginalName;
00735     ASSERT(Hive->ReleaseCellRoutine == NULL);
00736 
00737     /* Driver key node (mandatory) */
00738     ASSERT(DriverCell != HCELL_NIL);
00739     DriverNode = HvGetCell(Hive, DriverCell);
00740     ASSERT(DriverNode);
00741 
00742     /* Safe boot key node (optional but return TRUE if not present) */
00743     if(SafeBootCell == HCELL_NIL) return TRUE;
00744     SafeBootNode = HvGetCell(Hive, SafeBootCell);
00745     if(!SafeBootNode) return FALSE;
00746 
00747     /* Search by the name from the group */
00748     RtlInitUnicodeString(&Name, L"Group");
00749     CellIndex = CmpFindValueByName(Hive, DriverNode, &Name);
00750     if(CellIndex != HCELL_NIL)
00751     {
00752         KeyValue = HvGetCell(Hive, CellIndex);
00753         ASSERT(KeyValue);
00754         if (KeyValue->Type == REG_SZ || KeyValue->Type == REG_EXPAND_SZ)
00755         {
00756             /* Compose the search 'key' */
00757             Name.Buffer = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length);
00758             if (!Name.Buffer) return FALSE;
00759             Name.Length = (USHORT)Length - sizeof(UNICODE_NULL);
00760             Name.MaximumLength = Name.Length;
00761             /* Search for corresponding key in the Safe Boot key */
00762             CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
00763             if(CellIndex != HCELL_NIL) return TRUE;
00764         }
00765     }
00766 
00767     /* Group has not been found - find driver name */
00768     Name.Length = DriverNode->Flags & KEY_COMP_NAME ?
00769                               CmpCompressedNameSize(DriverNode->Name,
00770                                                     DriverNode->NameLength) :
00771                               DriverNode->NameLength;
00772     Name.MaximumLength = Name.Length;
00773     /* Now allocate the buffer for it and copy the name */
00774     Name.Buffer = CmpAllocate(Name.Length, FALSE, TAG_CM);
00775     if (!Name.Buffer) return FALSE;
00776     if (DriverNode->Flags & KEY_COMP_NAME)
00777     {
00778         /* Compressed name */
00779         CmpCopyCompressedName(Name.Buffer,
00780                               Name.Length,
00781                               DriverNode->Name,
00782                               DriverNode->NameLength);
00783     }
00784     else
00785     {
00786         /* Normal name */
00787         RtlCopyMemory(Name.Buffer, DriverNode->Name, DriverNode->NameLength);
00788     }
00789     CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
00790     RtlFreeUnicodeString(&Name);
00791     if(CellIndex != HCELL_NIL) return TRUE;
00792 
00793     /* Not group or driver name - search by image name */
00794     RtlInitUnicodeString(&Name, L"ImagePath");
00795     CellIndex = CmpFindValueByName(Hive, DriverNode, &Name);
00796     if(CellIndex != HCELL_NIL)
00797     {
00798         KeyValue = HvGetCell(Hive, CellIndex);
00799         ASSERT(KeyValue);
00800         if (KeyValue->Type == REG_SZ || KeyValue->Type == REG_EXPAND_SZ)
00801         {
00802             /* Compose the search 'key' */
00803             OriginalName = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length);
00804             if (!OriginalName) return FALSE;
00805             /* Get the base image file name */
00806             Name.Buffer = wcsrchr(OriginalName, L'\\');
00807             if (!Name.Buffer) return FALSE;
00808             ++Name.Buffer;
00809             /* Length of the base name must be >=1 */
00810             Name.Length = (USHORT)Length - (USHORT)((PUCHAR)Name.Buffer - (PUCHAR)OriginalName)
00811                                  - sizeof(UNICODE_NULL);
00812             if(Name.Length < 1) return FALSE;
00813             Name.MaximumLength = Name.Length;
00814             /* Search for corresponding key in the Safe Boot key */
00815             CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
00816             if(CellIndex != HCELL_NIL) return TRUE;
00817         }
00818     }
00819     /* Nothing found - nothing else to search */
00820     return FALSE;
00821 }
00822 
00823 /* EOF */

Generated on Sun May 27 2012 04:37:05 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.