INIT_FUNCTION NTSTATUS NTAPI PiInitCacheGroupInformation(VOID) { HANDLE KeyHandle; NTSTATUS Status; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; PUNICODE_STRING GroupTable; ULONG Count; UNICODE_STRING GroupString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" L"\\Control\\ServiceGroupOrder"); /* Open the registry key */ Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ); if (NT_SUCCESS(Status)) { /* Get the list */ Status = IopGetRegistryValue(KeyHandle, L"List", &KeyValueInformation); ZwClose(KeyHandle); /* Make sure we got it */ if (NT_SUCCESS(Status)) { /* Make sure it's valid */ if ((KeyValueInformation->Type == REG_MULTI_SZ) && (KeyValueInformation->DataLength)) { /* Convert it to unicode strings */ Status = PnpRegMultiSzToUnicodeStrings(KeyValueInformation, &GroupTable, &Count); /* Cache it for later */ PiInitGroupOrderTable = GroupTable; PiInitGroupOrderTableCount = (USHORT)Count; } else { /* Fail */ Status = STATUS_UNSUCCESSFUL; } /* Free the information */ ExFreePool(KeyValueInformation); } } /* Return status */ return Status; }
USHORT NTAPI PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle) { NTSTATUS Status; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; USHORT i; PVOID Buffer; UNICODE_STRING Group; PAGED_CODE(); /* Make sure we have a cache */ if (!PiInitGroupOrderTable) return -1; /* If we don't have a handle, the rest is easy -- return the count */ if (!ServiceHandle) return PiInitGroupOrderTableCount + 1; /* Otherwise, get the group value */ Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); if (!NT_SUCCESS(Status)) return PiInitGroupOrderTableCount; /* Make sure we have a valid string */ ASSERT(KeyValueInformation->Type == REG_SZ); ASSERT(KeyValueInformation->DataLength); /* Convert to unicode string */ Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); Group.MaximumLength = (USHORT)KeyValueInformation->DataLength; Group.Buffer = Buffer; /* Loop the groups */ for (i = 0; i < PiInitGroupOrderTableCount; i++) { /* Try to find a match */ if (RtlEqualUnicodeString(&Group, &PiInitGroupOrderTable[i], TRUE)) break; } /* We're done */ ExFreePool(KeyValueInformation); return i; }
BOOLEAN PiAddPlugPlayBusEnumeratorToList( IN HANDLE ServiceKeyHandle, IN PUNICODE_STRING ServiceName, IN OUT PVOID Context ) /*++ Routine Description: This routine is a callback function for IopApplyFunctionToSubKeys. It is called for each service key under HKLM\System\CurrentControlSet\Services. Its purpose is to take each service entry representing a bus enumerator, and create a corresponding bus enumerator entry in the Plug&Play bus enumerator list. NOTE: The PnP Bus Enumerator list resource must be held for exclusive (write) access before invoking this routine. The PnP device-specific registry resource must be held for shared (read) access. Arguments: ServiceKeyHandle - Supplies a handle to a service entry key. ServiceName - Supplies the name of this service. Context - Not used. Returns: TRUE to continue the enumeration. FALSE to abort it. --*/ { UNICODE_STRING ValueName; NTSTATUS Status; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; ULONG RequiredLength; BOOLEAN IsBusExtender = FALSE; PUNICODE_STRING DeviceIDList; ULONG DeviceIDCount; PPLUGPLAY_BUS_ENUMERATOR BusEnumerator; // // First, see if this service is for a bus extender. (Since we have // scratch space, use it, so we don't do memory allocations when checking // each service.) // RtlInitUnicodeString(&ValueName, REGSTR_VALUE_PLUGPLAY_SERVICE_TYPE); Status = NtQueryValueKey(ServiceKeyHandle, &ValueName, KeyValueFullInformation, PiScratchBuffer, PNP_LARGE_SCRATCH_BUFFER_SIZE, &RequiredLength ); if(NT_SUCCESS(Status)) { if((((PKEY_VALUE_FULL_INFORMATION)PiScratchBuffer)->Type == REG_DWORD) && (((PKEY_VALUE_FULL_INFORMATION)PiScratchBuffer)->DataLength >= sizeof(ULONG))) { IsBusExtender = (PlugPlayServiceBusExtender == (PLUGPLAY_SERVICE_TYPE) (*(PULONG)KEY_VALUE_DATA((PKEY_VALUE_FULL_INFORMATION)PiScratchBuffer))); } } if(!IsBusExtender) { return TRUE; } // // We have a bus extender, so allocate a node for it. // BusEnumerator = (PPLUGPLAY_BUS_ENUMERATOR)ExAllocatePool(PagedPool, sizeof(PLUGPLAY_BUS_ENUMERATOR)); if(!BusEnumerator) { return TRUE; } if(!IopConcatenateUnicodeStrings(&(BusEnumerator->ServiceName), ServiceName, NULL )) { ExFreePool(BusEnumerator); return TRUE; } // // Now, retrieve the list of compatible device IDs from the service's // DeviceIDs REG_MULTI_SZ value entry. // Status = IopGetRegistryValue(ServiceKeyHandle, REGSTR_VALUE_DEVICE_IDS, &KeyValueInformation ); if(!NT_SUCCESS(Status)) { // // Since we couldn't retrieve any compatible IDs, assume there are none, // and initialize the BusEnumerator structure with a device ID count of zero. // DeviceIDList = NULL; DeviceIDCount = 0; } else { Status = IopRegMultiSzToUnicodeStrings(KeyValueInformation, &DeviceIDList, &DeviceIDCount ); ExFreePool(KeyValueInformation); if(!NT_SUCCESS(Status)) { ExFreePool(BusEnumerator->ServiceName.Buffer); ExFreePool(BusEnumerator); return TRUE; } } // // Finish filling in the bus enumerator node and insert it into the tail of the list. // InitializeListHead(&(BusEnumerator->BusInstanceListEntry)); BusEnumerator->PlugPlayIDs = DeviceIDList; BusEnumerator->PlugPlayIDCount = DeviceIDCount; RtlInitUnicodeString(&(BusEnumerator->DriverName), NULL); //BusEnumerator->DriverObject = NULL; InsertTailList(&PpBusListHead, &(BusEnumerator->BusEnumeratorListEntry)); return TRUE; }
NTSTATUS PiInitializeSystemEnumSubKeys( IN HANDLE CurrentKeyHandle, IN PUNICODE_STRING ValueName ) /*++ Routine Description: This routine checks to see if the key whose handle was passed in contains a value whose name was specified by the ValueName argument. If so, it resets this value to a REG_DWORD 0. It then enumerates all subkeys under the current key, and recursively calls itself for each one. Arguments: CurrentKeyHandle - Supplies a handle to the key which will be enumerated. ValueName - Supplies a pointer to the value entry name to be initialized. Return Value: None. --*/ { NTSTATUS Status; PKEY_BASIC_INFORMATION KeyInformation; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; USHORT i; ULONG TempValue, ResultLength; UNICODE_STRING UnicodeName; HANDLE WorkHandle; // // Set "FoundAtEnum=" entry of current key to FALSE, if exists. // Status = IopGetRegistryValue(CurrentKeyHandle, ValueName->Buffer, &KeyValueInformation ); if(NT_SUCCESS(Status)) { ExFreePool(KeyValueInformation); TempValue = 0; Status = NtSetValueKey(CurrentKeyHandle, ValueName, TITLE_INDEX_VALUE, REG_DWORD, &TempValue, sizeof(TempValue) ); if(!NT_SUCCESS(Status)) { return Status; } } // // Enumerate current node's children and apply ourselves to each one // KeyInformation = (PKEY_BASIC_INFORMATION)PiScratchBuffer; for(i = 0; TRUE; i++) { Status = NtEnumerateKey(CurrentKeyHandle, i, KeyBasicInformation, KeyInformation, PNP_LARGE_SCRATCH_BUFFER_SIZE, &ResultLength ); if(Status == STATUS_NO_MORE_ENTRIES) { break; } else if(!NT_SUCCESS(Status)) { continue; } UnicodeName.Length = (USHORT)KeyInformation->NameLength; UnicodeName.MaximumLength = (USHORT)KeyInformation->NameLength; UnicodeName.Buffer = KeyInformation->Name; Status = IopOpenRegistryKey(&WorkHandle, CurrentKeyHandle, &UnicodeName, KEY_ALL_ACCESS, FALSE ); if(!NT_SUCCESS(Status)) { continue; } Status = PiInitializeSystemEnumSubKeys(WorkHandle, ValueName); NtClose(WorkHandle); if(!NT_SUCCESS(Status)) { return Status; } } return STATUS_SUCCESS; }
NTSTATUS IopInitializeRegistryNode( IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, IN HANDLE EnumRootHandle, IN PUNICODE_STRING WorkName, IN PUNICODE_STRING KeyName, IN ULONG Instance, IN INTERFACE_TYPE InterfaceType, IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber ) /*++ Routine Description: This routine creates a node for the current firmware component and puts component data to the data part of the node. Arguments: CurrentEntry - Supplies a pointer to a configuration component. EnumRootHandle - Supplies the handle of Enum key under which we will build our new key. WorkName - Supplies a point to a unicode string which is the name of its parent node. KeyName - Suppiles a pointer to a UNICODE string which will be the name of the new key. Instance - Supplies an instance number of KeyName. InterfaceType - Specify the Interface type of the bus that the CurrentEntry component resides. (See BusNumber also) BusDataType - Specifies the configuration type of the bus. BusNumber - Specify the Bus Number of the bus that the CurrentEntry component resides on. If Bus number is -1, it means InterfaceType and BusNumber are meaningless for this component. Returns: None. --*/ { NTSTATUS status; HANDLE handle, keyHandle; UNICODE_STRING unicodeName, unicodeValueName; PCONFIGURATION_COMPONENT component; PKEY_VALUE_FULL_INFORMATION keyValueInformation, serviceInfo = NULL; PWSTR service = (PWSTR)NULL, p; ULONG disposition, foundAlready, dataLength = 0; ULONG serviceLength = 0, tmpValue, emptyResource = 0; BOOLEAN newKey = FALSE; PCM_RESOURCE_LIST dataArea, configuration1; CHAR unicodeBuffer[20]; PUCHAR resourceBuffer = IopPnpScratchBuffer2; BOOLEAN freeDataArea = FALSE, isDuplicated; component = &CurrentEntry->ComponentEntry; // // Open/Create a key under Enum/Root bransh. If fails, // exit (nothing we can do.) // status = IopOpenRegistryKeyPersist ( &keyHandle, EnumRootHandle, KeyName, KEY_ALL_ACCESS, TRUE, &disposition ); if (!NT_SUCCESS(status)) { return status; } #if 0 // not sure if we need it // // If the key is newly created, set its NewDevice value to TRUE so that // user mode Pnp mgr can initiate a device installation. The NewDevice // value will be reset by user mode Pnp mgr. SO , we don't touch it here. // if (disposition == REG_CREATED_NEW_KEY) { newKey = TRUE; PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_NEWDEVICE); tmpValue = 1; NtSetValueKey( keyHandle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof (tmpValue) ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_STATIC); NtSetValueKey( keyHandle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); } #endif if (component->Type > OtherController) { // // The current component is a peripheral. // // // Create a new instance key under KeyName // PiUlongToInstanceKeyUnicodeString(&unicodeName, unicodeBuffer, 20, Instance); status = IopOpenRegistryKeyPersist ( &handle, keyHandle, &unicodeName, KEY_ALL_ACCESS, TRUE, &disposition ); NtClose(keyHandle); if (!NT_SUCCESS(status)) { goto init_Exit; } // // // Create all the default value entry for the newly created key. // Service = (do NOT create) // BaseDevicePath = WorkName // FoundAtEnum = 1 // InterfaceType = InterfaceType (only for bus device) // SystemBusNumber = BusNumber (only for bus device) // BusDataType = BusDataType (only for bus device) // PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_BASEDEVICEPATH); p = WorkName->Buffer; p += WorkName->Length / sizeof(WCHAR); *p = UNICODE_NULL; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_SZ, WorkName->Buffer, WorkName->Length + sizeof (UNICODE_NULL) ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_FOUNDATENUM); tmpValue = 1; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_SYSTEMBUSNUMBER); tmpValue = BusNumber; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_INTERFACETYPE); tmpValue = InterfaceType; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_BUSDATATYPE); tmpValue = BusDataType; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); NtClose(handle); // // Append keyanme and instance key name to workname // (In fact, we don't need to do this because there // is nothing under peripheral component.) // // // Append KeyName to workname // p = WorkName->Buffer; p += WorkName->Length / sizeof(WCHAR); *p = OBJ_NAME_PATH_SEPARATOR; WorkName->Length += sizeof (WCHAR); RtlAppendStringToString((PSTRING)WorkName, (PSTRING)KeyName); } else { // // Current component is a controller // // // Append KeyName to workname // p = WorkName->Buffer; p += WorkName->Length / sizeof(WCHAR); *p = OBJ_NAME_PATH_SEPARATOR; WorkName->Length += sizeof (WCHAR); RtlAppendStringToString((PSTRING)WorkName, (PSTRING)KeyName); // // We need to convert the h/w tree configuration data format from // CM_PARTIAL_RESOURCE_DESCRIPTIOR to CM_RESOURCE_LIST. // if (CurrentEntry->ConfigurationData) { // // This component has configuration data, we copy the data // to our work area, add some more data items and copy the new // configuration data to the registry. // dataLength = component->ConfigurationDataLength + FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) + FIELD_OFFSET(CM_RESOURCE_LIST, List); dataArea = (PCM_RESOURCE_LIST)resourceBuffer; // // Make sure our reserved area is big enough to hold the data. // if (dataLength > PNP_LARGE_SCRATCH_BUFFER_SIZE) { // // If reserved area is not big enough, we resize our reserved // area. If, unfortunately, the reallocation fails, we simply // loss the configuration data of this particular component. // dataArea = (PCM_RESOURCE_LIST)ExAllocatePool( PagedPool, dataLength ); if (dataArea) { freeDataArea = TRUE; } } if (dataArea) { RtlMoveMemory((PUCHAR)&dataArea->List->PartialResourceList.Version, CurrentEntry->ConfigurationData, component->ConfigurationDataLength ); dataArea->Count = 1; dataArea->List[0].InterfaceType = InterfaceType; dataArea->List[0].BusNumber = BusNumber; } } if (CurrentEntry->ConfigurationData == NULL || !dataArea) { // // This component has NO configuration data (or we can't resize // our reserved area to hold the data), we simple add whatever // is required to set up a CM_FULL_RESOURCE_LIST. // dataArea = (PCM_RESOURCE_LIST)&emptyResource; dataLength = FIELD_OFFSET(CM_RESOURCE_LIST, List); } if (!newKey) { // // If the key exists already, we need to check if current entry // already being converted (most likely the answer is yes.). If it already // converted, we simply set "FoundAtEnum=" to TRUE. Otherwise, we will // create it. // tmpValue = 0; PiUlongToInstanceKeyUnicodeString(&unicodeName, unicodeBuffer, 20, tmpValue); status = IopOpenRegistryKey (&handle, keyHandle, &unicodeName, KEY_ALL_ACCESS, FALSE ); while (NT_SUCCESS(status)) { // // if the current key has been Found/Enum'ed already, we need // to skip it. // foundAlready = 0; status = IopGetRegistryValue (handle, REGSTR_VALUE_FOUNDATENUM, &keyValueInformation); if (NT_SUCCESS(status)) { if (keyValueInformation->DataLength != 0) { foundAlready = *(PULONG)KEY_VALUE_DATA(keyValueInformation); } ExFreePool(keyValueInformation); } if (!foundAlready) { keyValueInformation = NULL; status = IopGetRegistryValue (handle, REGSTR_VALUE_DETECTSIGNATURE, &keyValueInformation); if (NT_SUCCESS(status) && keyValueInformation->DataLength != 0) { configuration1 = (PCM_RESOURCE_LIST)KEY_VALUE_DATA(keyValueInformation); } else if (status == STATUS_OBJECT_NAME_NOT_FOUND || keyValueInformation->DataLength == 0) { // // If no "DetectSignature =" value entry, we set up an empty // CM_RESOURCE_LIST. // configuration1 = (PCM_RESOURCE_LIST)&emptyResource; } // // To detect ARC duplicated components, we should be able // to simply compare the RAW resource list. If they are the // same *most likely* they are duplicates. This includes // the case that both resource list are empty. (if they // are empty, we should be able to simply pick up the // key and use it.) // isDuplicated = IopIsDuplicatedResourceLists( configuration1, dataArea); if (!isDuplicated) { // // BUGBUG We should also check for bus info. // isDuplicated = IopIsDuplicatedDevices( configuration1, dataArea, NULL, NULL ); } if (keyValueInformation) { ExFreePool(keyValueInformation); } if (isDuplicated) { PiWstrToUnicodeString( &unicodeValueName, REGSTR_VALUE_FOUNDATENUM); tmpValue = 1; status = NtSetValueKey(handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); NtClose(handle); NtClose(keyHandle); goto init_Exit0; } } NtClose(handle); tmpValue++; PiUlongToInstanceKeyUnicodeString(&unicodeName, unicodeBuffer, 20, tmpValue); status = IopOpenRegistryKey (&handle, keyHandle, &unicodeName, KEY_ALL_ACCESS, FALSE ); } Instance = tmpValue; } // // We need to create the new instance key if we can come here... // PiUlongToInstanceKeyUnicodeString(&unicodeName, unicodeBuffer, 20, Instance); status = IopOpenRegistryKeyPersist ( &handle, keyHandle, &unicodeName, KEY_ALL_ACCESS, TRUE, NULL ); NtClose(keyHandle); PNP_ASSERT(NT_SUCCESS(status), "IopInitRegistryNode: Fail to create new key."); if (!NT_SUCCESS(status)) { goto init_Exit; } // // Newly created key -- // // Create all the default value entry for the newly created key. // Service = #if 0 // NewInstance = 1 #endif // FoundAtEnum = 1 // Configuration = // InterfaceType = InterfaceType // SystemBusNumber = BusNumber // BusDataType = BusDataType // #if 0 PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_NEWINSTANCE); tmpValue = 1; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); #endif PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_FOUNDATENUM); tmpValue = 1; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); #if 0 // // SystemBusNumber, InterfaceType and BusDataType are for Bus // devices only. For ntdetect/arc detected devices, we don't set // up bus devices. // PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_SYSTEMBUSNUMBER); tmpValue = BusNumber; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_INTERFACETYPE); tmpValue = InterfaceType; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_BUSDATATYPE); tmpValue = BusDataType; NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue, sizeof(tmpValue) ); #endif PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_CONFIGURATION); NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_RESOURCE_LIST, dataArea, dataLength ); PiWstrToUnicodeString(&unicodeValueName, REGSTR_VALUE_DETECTSIGNATURE); NtSetValueKey( handle, &unicodeValueName, TITLE_INDEX_VALUE, REG_RESOURCE_LIST, dataArea, dataLength ); NtClose(handle); } status = STATUS_SUCCESS; init_Exit0: p = WorkName->Buffer; p += WorkName->Length / sizeof(WCHAR); *p = OBJ_NAME_PATH_SEPARATOR; WorkName->Length += sizeof (WCHAR); RtlAppendStringToString((PSTRING)WorkName, (PSTRING)&unicodeName); init_Exit: if (freeDataArea) { ExFreePool(dataArea); } if (serviceInfo) { ExFreePool(serviceInfo); } return(status); }
BOOLEAN IopInitializeDeviceInstanceKey( IN HANDLE KeyHandle, IN PUNICODE_STRING KeyName, IN OUT PVOID WorkName ) /*++ Routine Description: This routine is a callback function for IopApplyFunctionToSubKeys. It is called for each subkey under HKLM\System\Enum\BusKey\DeviceKey. Arguments: KeyHandle - Supplies a handle to this key. KeyName - Supplies the name of this key. WorkName - points to the unicodestring which describes the path up to this key. Returns: TRUE to continue the enumeration. FALSE to abort it. --*/ { UNICODE_STRING unicodeName, serviceName; PKEY_VALUE_FULL_INFORMATION keyValueInformation; NTSTATUS status; BOOLEAN duplicate = FALSE; ULONG foundAtEnum, deviceFlags, instance, tmpValue1, tmpValue2; USHORT length; PUNICODE_STRING pUnicode; // // Get the "Problem" value entry to determine what we need to do with // the device instance key. // deviceFlags = 0; status = IopGetRegistryValue ( KeyHandle, REGSTR_VALUE_PROBLEM, &keyValueInformation ); if (NT_SUCCESS(status)) { if ((keyValueInformation->Type == REG_DWORD) && (keyValueInformation->DataLength >= sizeof(ULONG))) { deviceFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation); } ExFreePool(keyValueInformation); } if (deviceFlags == CM_PROB_MOVED) { // // If the device instance was moved, we simply delete the key. // The key will be deleted once the caller close the open handle. // NtDeleteKey(KeyHandle); return TRUE; } // // The device instance key exists. We need to propagate the ConfigFlag // to problem and StatusFlags // deviceFlags = 0; status = IopGetRegistryValue(KeyHandle, REGSTR_VALUE_CONFIG_FLAGS, &keyValueInformation); if (NT_SUCCESS(status)) { if ((keyValueInformation->Type == REG_DWORD) && (keyValueInformation->DataLength >= sizeof(ULONG))) { deviceFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation); } ExFreePool(keyValueInformation); } if (deviceFlags & CONFIGFLAG_REINSTALL) { tmpValue1 = CM_PROB_REINSTALL; // Problem tmpValue2 = DN_HAS_PROBLEM; // StatusFlags } else { tmpValue1 = tmpValue2 = 0; } PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_PROBLEM); NtSetValueKey(KeyHandle, &unicodeName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue1, sizeof(tmpValue1) ); PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_STATUSFLAGS); NtSetValueKey(KeyHandle, &unicodeName, TITLE_INDEX_VALUE, REG_DWORD, &tmpValue2, sizeof(tmpValue2) ); // // Get the "DuplicateOf" value entry to determine if the device instance // should be registered. If the device instance is duplicate, We don't // add it to its service key's enum branch. // status = IopGetRegistryValue ( KeyHandle, REGSTR_VALUE_DUPLICATEOF, &keyValueInformation ); if (NT_SUCCESS(status)) { if ((keyValueInformation->Type == REG_SZ) && (keyValueInformation->DataLength > 0)) { duplicate = TRUE; } ExFreePool(keyValueInformation); } if (!duplicate) { // // Combine WorkName and KeyName to form device instance path // and register this device instance by // constructing new value entry for ServiceKeyName\Enum key. // i.e., <Number> = <PathToSystemEnumBranch> // pUnicode = (PUNICODE_STRING)WorkName; length = pUnicode->Length; // Save WorkName if (pUnicode->Buffer[pUnicode->Length / sizeof(WCHAR) - 1] != OBJ_NAME_PATH_SEPARATOR) { pUnicode->Buffer[pUnicode->Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR; pUnicode->Length += 2; } RtlAppendStringToString((PSTRING)pUnicode, (PSTRING)KeyName); PpDeviceRegistration(pUnicode, TRUE); pUnicode->Length = length; // Restore WorkName } // // Get the "Service=" value entry from KeyHandle // keyValueInformation = NULL; serviceName.Length = 0; status = IopGetRegistryValue ( KeyHandle, REGSTR_VALUE_SERVICE, &keyValueInformation ); if (NT_SUCCESS(status)) { // // Append the new instance to its corresponding // Service\Name\Enum. // if ((keyValueInformation->Type == REG_SZ) && (keyValueInformation->DataLength != 0)) { // // Set up ServiceKeyName unicode string // IopRegistryDataToUnicodeString( &serviceName, (PWSTR)KEY_VALUE_DATA(keyValueInformation), keyValueInformation->DataLength ); } // // Do not Free keyValueInformation // } // // The Pnp mgr set FoundAtEnum to 0 for everything under system\ccs\enum. // For the stuff under Root we need to set them to 1 except if their // CsConfigFlags was set to CSCONFIGFLAG_DO_NOT_CREATE. // foundAtEnum = 1; status = RtlUnicodeStringToInteger(KeyName, 10, &instance); if (NT_SUCCESS(status)) { if (serviceName.Length != 0) { status = IopGetDeviceInstanceCsConfigFlags( &serviceName, instance, &deviceFlags ); if (NT_SUCCESS(status) && (deviceFlags & CSCONFIGFLAG_DO_NOT_CREATE)) { foundAtEnum = 0; } } } if (keyValueInformation) { ExFreePool(keyValueInformation); } PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_FOUNDATENUM); NtSetValueKey(KeyHandle, &unicodeName, TITLE_INDEX_VALUE, REG_DWORD, &foundAtEnum, sizeof(foundAtEnum) ); // // Clean up "NtLogicalDevicePaths=" and "NtPhysicalDevicePaths=" of this key // PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_NT_PHYSICAL_DEVICE_PATHS); NtDeleteValueKey(KeyHandle, &unicodeName); PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_NT_LOGICAL_DEVICE_PATHS); NtDeleteValueKey(KeyHandle, &unicodeName); return TRUE; }
NTSTATUS NTAPI PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode, IN BOOLEAN LoadDriver, IN PDRIVER_OBJECT DriverObject) { NTSTATUS Status; HANDLE EnumRootKey, SubKey, ControlKey, ClassKey, PropertiesKey; UNICODE_STRING ClassGuid, Properties; UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); UNICODE_STRING ControlClass = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class"); PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; PWCHAR Buffer; /* Open enumeration root key */ Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, &EnumRoot, KEY_READ); if (!NT_SUCCESS(Status)) { DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); return Status; } /* Open instance subkey */ Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, &DeviceNode->InstancePath, KEY_READ); ZwClose(EnumRootKey); if (!NT_SUCCESS(Status)) { DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); return Status; } /* Get class GUID */ Status = IopGetRegistryValue(SubKey, REGSTR_VAL_CLASSGUID, &KeyValueInformation); if (NT_SUCCESS(Status)) { /* Convert to unicode string */ Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &ClassGuid.Length); ClassGuid.MaximumLength = (USHORT)KeyValueInformation->DataLength; ClassGuid.Buffer = Buffer; /* Open the key */ Status = IopOpenRegistryKeyEx(&ControlKey, NULL, &ControlClass, KEY_READ); if (!NT_SUCCESS(Status)) { /* No class key */ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); ClassKey = NULL; } else { /* Open the class key */ Status = IopOpenRegistryKeyEx(&ClassKey, ControlKey, &ClassGuid, KEY_READ); ZwClose(ControlKey); if (!NT_SUCCESS(Status)) { /* No class key */ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); ClassKey = NULL; } } /* Check if we made it till here */ if (ClassKey) { /* Get the device properties */ RtlInitUnicodeString(&Properties, REGSTR_KEY_DEVICE_PROPERTIES); Status = IopOpenRegistryKeyEx(&PropertiesKey, ClassKey, &Properties, KEY_READ); ZwClose(ClassKey); if (!NT_SUCCESS(Status)) { /* No properties */ DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); PropertiesKey = NULL; } else { ZwClose(PropertiesKey); } } /* Free the registry data */ ExFreePool(KeyValueInformation); } /* Do ReactOS-style setup */ Status = IopAttachFilterDrivers(DeviceNode, TRUE); if (!NT_SUCCESS(Status)) { IopRemoveDevice(DeviceNode); return Status; } Status = IopInitializeDevice(DeviceNode, DriverObject); if (NT_SUCCESS(Status)) { Status = IopAttachFilterDrivers(DeviceNode, FALSE); if (!NT_SUCCESS(Status)) { IopRemoveDevice(DeviceNode); return Status; } Status = IopStartDevice(DeviceNode); } /* Return status */ return Status; }
USHORT NTAPI PipGetDriverTagPriority(IN HANDLE ServiceHandle) { NTSTATUS Status; HANDLE KeyHandle = NULL; PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag; PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList; PVOID Buffer; UNICODE_STRING Group; PULONG GroupOrder; ULONG Count, Tag = 0; USHORT i = -1; UNICODE_STRING GroupString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" L"\\Control\\ServiceGroupOrder"); /* Open the key */ Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ); if (!NT_SUCCESS(Status)) goto Quickie; /* Read the group */ Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); if (!NT_SUCCESS(Status)) goto Quickie; /* Make sure we have a group */ if ((KeyValueInformation->Type == REG_SZ) && (KeyValueInformation->DataLength)) { /* Convert to unicode string */ Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); Group.MaximumLength = (USHORT)KeyValueInformation->DataLength; Group.Buffer = Buffer; } /* Now read the tag */ Status = IopGetRegistryValue(ServiceHandle, L"Tag", &KeyValueInformationTag); if (!NT_SUCCESS(Status)) goto Quickie; /* Make sure we have a tag */ if ((KeyValueInformationTag->Type == REG_DWORD) && (KeyValueInformationTag->DataLength)) { /* Read it */ Tag = *(PULONG)((ULONG_PTR)KeyValueInformationTag + KeyValueInformationTag->DataOffset); } /* We can get rid of this now */ ExFreePool(KeyValueInformationTag); /* Now let's read the group's tag order */ Status = IopGetRegistryValue(KeyHandle, Group.Buffer, &KeyValueInformationGroupOrderList); /* We can get rid of this now */ Quickie: if (KeyValueInformation) ExFreePool(KeyValueInformation); if (KeyHandle) NtClose(KeyHandle); if (!NT_SUCCESS(Status)) return -1; /* We're on the success path -- validate the tag order*/ if ((KeyValueInformationGroupOrderList->Type == REG_BINARY) && (KeyValueInformationGroupOrderList->DataLength)) { /* Get the order array */ GroupOrder = (PULONG)((ULONG_PTR)KeyValueInformationGroupOrderList + KeyValueInformationGroupOrderList->DataOffset); /* Get the count */ Count = *GroupOrder; ASSERT(((Count + 1) * sizeof(ULONG)) <= KeyValueInformationGroupOrderList->DataLength); /* Now loop each tag */ GroupOrder++; for (i = 1; i <= Count; i++) { /* If we found it, we're out */ if (Tag == *GroupOrder) break; /* Try the next one */ GroupOrder++; } } /* Last buffer to free */ ExFreePool(KeyValueInformationGroupOrderList); return i; }