//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- CheckAndCreateRegistryPath -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus CheckAndCreateRegistryPath( WDFDRIVER Driver, DtString* pItemPath) { DtStringChar* pRegistryPath; DtString RegistryPath; DtString FullKeyName; UInt PathLength; DtStatus Status; Int i; DT_STRING_DECL(ParamItemName, "\\Parameters"); // Build the full path pRegistryPath = WdfDriverGetRegistryPath(Driver); PathLength = wcslen(pRegistryPath); DT_STRING_INIT_CONST(RegistryPath, pRegistryPath, PathLength); // Allocate a new DtString buffer for the complete path inclusive a '\0' character and // extra '\' if (!DT_SUCCESS(DtStringAlloc(&FullKeyName, PathLength+ DtStringGetStringLength(&ParamItemName)+ DtStringGetStringLength(pItemPath)+2))) return STATUS_NO_MEMORY; DtStringAppendDtString(&FullKeyName, &RegistryPath); DtStringAppendDtString(&FullKeyName, &ParamItemName); if (RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer) != STATUS_SUCCESS) RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer); Status = DT_STATUS_OK; i = 1; // Get all subitems from pItemPath and check if the registry entry exist. // If not, create the registry entry. // This function is needed, because Wuindows only allows us to create one registry entry // at a time and not a complete path. while (Status == DT_STATUS_OK) { DtStringAppendChars(&FullKeyName, "\\"); Status = DtStringAppendSubstring(&FullKeyName, pItemPath, i, '\\'); if (DT_SUCCESS(Status)) { if (RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer) != STATUS_SUCCESS) RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer); } i++; } DtStringFree(&FullKeyName); return DT_STATUS_OK; }
NTSTATUS DrDriverServiceExist( PWSTR DriverServiceName ){ NTSTATUS status; status = RtlCheckRegistryKey(RTL_REGISTRY_SERVICES, DriverServiceName); return status; }
NTSTATUS LurCreate ( IN PLURELATION_DESC LurDesc2, IN BOOLEAN EnableSecondaryOnly, IN BOOLEAN EnableW2kReadOnlyPacth, IN PDEVICE_OBJECT AdapterFunctionDeviceObject, IN PVOID AdapterHardwareExtension, IN LURN_EVENT_CALLBACK LurnEventCallback, OUT PLURELATION *Lur ) { NTSTATUS status; PLURELATION tmpLur; ULONG tmpLurLength; PLURELATION_NODE tmpLurn[LUR_MAX_LURNS_PER_LUR]; PLURELATION_NODE_DESC currentLurnDesc; LONG idx_lurn; LONG idx_child; ULONG child; BOOLEAN writeCheckRequired = FALSE; ULONG lowestHwVersion; NDAS_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); if (LurDesc2->LurnDescCount <= 0 || LurDesc2->LurnDescCount > LUR_MAX_LURNS_PER_LUR) { NDAS_ASSERT(FALSE); return STATUS_INVALID_PARAMETER; } #if __ENABLE_CONTENTENCRYPT_AES_TEST__ InitialEcrKey( LurDesc ); #endif // create LURELATION tmpLurLength = sizeof(LURELATION) + sizeof(PLURELATION_NODE) * (LurDesc2->LurnDescCount - 1) + LurDesc2->Length; tmpLur = (PLURELATION)ExAllocatePoolWithTag( NonPagedPool, tmpLurLength, LUR_POOL_TAG ); if (!tmpLur) { NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES ); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory( tmpLur, tmpLurLength ); tmpLur->LurDesc = (PLURELATION_DESC) ((PUCHAR)tmpLur + (sizeof(LURELATION) + sizeof(PLURELATION_NODE) * (LurDesc2->LurnDescCount - 1))); RtlCopyMemory( tmpLur->LurDesc, LurDesc2, LurDesc2->Length ); tmpLur->Type = LSSTRUC_TYPE_LUR; tmpLur->Length = sizeof(LURELATION); tmpLur->DeviceMode = tmpLur->LurDesc->DeviceMode; tmpLur->EndingBlockAddr = tmpLur->LurDesc->EndingBlockAddr; tmpLur->LowestHwVer = -1; tmpLur->LurFlags = 0; tmpLur->SupportedNdasFeatures = 0; tmpLur->EnabledNdasFeatures = 0; tmpLur->StartOffset = tmpLur->LurDesc->StartOffset; tmpLur->LockImpossible = tmpLur->LurDesc->LockImpossible; tmpLur->EmergencyMode = tmpLur->LurDesc->EmergencyMode; tmpLur->UnitBlocks = tmpLur->LurDesc->EndingBlockAddr + 1; tmpLur->MaxChildrenSectorCount = tmpLur->UnitBlocks; tmpLur->NodeCount = tmpLur->LurDesc->LurnDescCount; RtlCopyMemory( tmpLur->LurId, tmpLur->LurDesc->LurId, LURID_LENGTH ); tmpLur->AdapterFunctionDeviceObject = AdapterFunctionDeviceObject; tmpLur->AdapterHardwareExtension = AdapterHardwareExtension; tmpLur->LurnEventCallback = LurnEventCallback; LsuInitializeBlockAcl( &tmpLur->SystemBacl ); LsuInitializeBlockAcl( &tmpLur->UserBacl ); InitializeListHead( &tmpLur->ListEntry ); NDAS_ASSERT( tmpLur->StartOffset == 0 || tmpLur->StartOffset == NDAS_RAID_DEFAULT_START_OFFSET ); #if __ENABLE_BACL_TEST__ { PLSU_BLOCK_ACE blockAce; blockAce = LsuCreateBlockAce(LSUBACE_ACCESS_READ, 0x3f, 0x3f); if (blockAce) { LsuInsertAce( &tmpLur->SystemBacl, blockAce ); } } #endif // Content encryption tmpLur->CntEcrMethod = tmpLur->LurDesc->CntEcrMethod; tmpLur->CntEcrKeyLength = tmpLur->LurDesc->CntEcrKeyLength; if (tmpLur->LurDesc->CntEcrKeyLength) { RtlCopyMemory( tmpLur->CntEcrKey, tmpLur->LurDesc->CntEcrKey, tmpLur->CntEcrKeyLength ); #if DBG { ULONG keyIdx; DebugTrace( NDASSCSI_DBG_LUR_INFO, ("Encryption key method:%02x, key length:%d * 4bytes, ", tmpLur->LurDesc->CntEcrMethod, (int)tmpLur->LurDesc->CntEcrKeyLength) ); for (keyIdx = 0; keyIdx<tmpLur->CntEcrKeyLength; keyIdx++) { DebugTrace( NDASSCSI_DBG_LUR_INFO, ("%02x ", (int)tmpLur->CntEcrKey[keyIdx]) ); if ((keyIdx%4) == 0) { DebugTrace( NDASSCSI_DBG_LUR_INFO, (" ") ); } } DebugTrace( NDASSCSI_DBG_LUR_INFO, ("\n") ); } #endif } status = NdasRaidStart( &NdasrGlobalData ); if (status != STATUS_SUCCESS) { goto error_out; } // Allocate LURNs to LURN descriptor Table and sanity check. RtlZeroMemory( tmpLurn, sizeof(PLURELATION_NODE) * LUR_MAX_LURNS_PER_LUR ); lowestHwVersion = -1; currentLurnDesc = tmpLur->LurDesc->LurnDesc; for (idx_lurn = 0; idx_lurn < (LONG)tmpLur->LurDesc->LurnDescCount; idx_lurn++) { DebugTrace( NDASSCSI_DBG_LUR_INFO, ("Idx:%d LurnDesc:%p NextOffset:%d %d\n", idx_lurn, currentLurnDesc, currentLurnDesc->NextOffset, currentLurnDesc->LurnChildrenCnt) ); DebugTrace( NDASSCSI_DBG_LUR_INFO, ("LurnDesc->MaxDataSendLength = %d, LurnDesc->MaxDataRecvLength = %d\n", currentLurnDesc->MaxDataSendLength, currentLurnDesc->MaxDataRecvLength) ); DebugTrace( NDASSCSI_DBG_LUR_INFO, ("LurnDesc->LurnIde.HWVersion = %d, LurnDesc->LurnIde.HWRevision = %d\n", currentLurnDesc->LurnIde.HWVersion, currentLurnDesc->LurnIde.HWRevision) ); // Save the lowest hardware version from leaf nodes. if (currentLurnDesc->LurnChildrenCnt == 0) { if (lowestHwVersion > currentLurnDesc->LurnIde.HWVersion) { lowestHwVersion = currentLurnDesc->LurnIde.HWVersion; DebugTrace( NDASSCSI_DBG_LUR_INFO, ("lowestHwVersion = %d\n", lowestHwVersion) ); } } if (currentLurnDesc->NextOffset == 0 && (LONG)idx_lurn + 1 < (LONG)tmpLur->LurDesc->LurnDescCount) { NDAS_ASSERT(FALSE); status = STATUS_INVALID_PARAMETER; } if (currentLurnDesc->LurnType < 0 || currentLurnDesc->LurnType > LURN_LAST_DEVICE_TYPE) { NDAS_ASSERT(FALSE); status = STATUS_INVALID_PARAMETER; break; } status = LurnAllocate( &tmpLurn[idx_lurn], currentLurnDesc->LurnChildrenCnt ); if (status != STATUS_SUCCESS) { NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES ); break; } // Also initialize LURN index in the LUR. tmpLurn[idx_lurn]->LurnStatus = LURN_STATUS_INIT; tmpLur->Nodes[idx_lurn] = tmpLurn[idx_lurn]; tmpLurn[idx_lurn]->LurnDesc = currentLurnDesc; currentLurnDesc = (PLURELATION_NODE_DESC)((PBYTE)tmpLur->LurDesc + currentLurnDesc->NextOffset); } if (status != STATUS_SUCCESS) { goto error_out; } if (lowestHwVersion > LANSCSIIDE_CURRENT_VERSION) { NDAS_ASSERT(FALSE); status = STATUS_INVALID_PARAMETER; goto error_out; } if (lowestHwVersion < LANSCSIIDE_VERSION_1_1) { if (tmpLur->LurDesc->LurnDescCount > 1) { if (tmpLur->LockImpossible == FALSE) { tmpLur->LockImpossible = TRUE; } } } if (tmpLur->LockImpossible) { NDAS_ASSERT( tmpLur->StartOffset == 0 ); if (tmpLur->LurDesc->LurnDescCount > 1) { lowestHwVersion = LANSCSIIDE_VERSION_1_0; } } // Detect supported NDAS features based on the lowest hardware version // We can only support minimum of all child hardware for RAID. LurDetectSupportedNdasFeatures( &tmpLur->SupportedNdasFeatures, lowestHwVersion ); // Enable features to default values or values set by a user. // User requests overrides the default features. status = LurEnableNdasFeauresByDeviceMode( &tmpLur->EnabledNdasFeatures, tmpLur->SupportedNdasFeatures, EnableW2kReadOnlyPacth, tmpLur->DeviceMode ); if (status != STATUS_SUCCESS) { NDAS_ASSERT(FALSE); goto error_out; } status = LurEnableNdasFeaturesByUserRequest( &tmpLur->EnabledNdasFeatures, tmpLur->SupportedNdasFeatures, tmpLur->LurDesc->LurOptions ); if (status != STATUS_SUCCESS) { NDAS_ASSERT(FALSE); goto error_out; } DebugTrace( NDASSCSI_DBG_LUR_INFO, ("LurOptions=%08lx Supported features=%08lx Enabled features=%08lx tmpLur->DeviceMode = %x\n", tmpLur->LurDesc->LurOptions, tmpLur->SupportedNdasFeatures, tmpLur->EnabledNdasFeatures, tmpLur->DeviceMode) ); // Build tree. Set up LURN. // Initialize nodes from leaves to a root. // Node 0 is root. status = STATUS_SUCCESS; for (idx_lurn = tmpLur->LurDesc->LurnDescCount - 1; idx_lurn >= 0; idx_lurn--) { // Set LURN IDs of itself, parent,and children. // LURN ID must be the index number in LUR->Nodes[] array. tmpLurn[idx_lurn]->LurnId = tmpLurn[idx_lurn]->LurnDesc->LurnId; tmpLurn[idx_lurn]->LurnParent = tmpLurn[tmpLurn[idx_lurn]->LurnDesc->LurnParent]; // Children tmpLurn[idx_lurn]->LurnChildrenCnt = tmpLurn[idx_lurn]->LurnDesc->LurnChildrenCnt; status = STATUS_SUCCESS; for (idx_child = 0; idx_child < (LONG)tmpLurn[idx_lurn]->LurnDesc->LurnChildrenCnt; idx_child++) { child = tmpLurn[idx_lurn]->LurnDesc->LurnChildren[idx_child]; if (child > tmpLur->LurDesc->LurnDescCount) { NDAS_ASSERT(FALSE); DebugTrace( NDASSCSI_DBG_LUR_INFO, ("invalid child number.\n") ); status = STATUS_INVALID_PARAMETER; break; } tmpLurn[idx_lurn]->LurnChildren[idx_child] = tmpLurn[child]; tmpLurn[child]->LurnChildIdx = idx_child; } if (status != STATUS_SUCCESS) { break; } // LUR Node's access right tmpLurn[idx_lurn]->LurnDesc->AccessRight = 0; if (tmpLur->DeviceMode == DEVMODE_SHARED_READONLY) { tmpLurn[idx_lurn]->LurnDesc->AccessRight = GENERIC_READ; } else if (tmpLur->DeviceMode == DEVMODE_SHARED_READWRITE) { if (FlagOn(tmpLur->LurDesc->LurOptions, LUROPTION_DONOT_ADJUST_PRIM_SEC_ROLE)) { if (EnableSecondaryOnly) { tmpLurn[idx_lurn]->LurnDesc->AccessRight = GENERIC_READ; tmpLur->EnabledNdasFeatures |= NDASFEATURE_SECONDARY; } else { tmpLurn[idx_lurn]->LurnDesc->AccessRight = GENERIC_WRITE | GENERIC_READ; } } else { tmpLur->EnabledNdasFeatures |= NDASFEATURE_SECONDARY; tmpLurn[idx_lurn]->LurnDesc->AccessRight = GENERIC_READ; } } else { //NDAS_ASSERT( tmpLur->DeviceMode == DEVMODE_EXCLUSIVE_READWRITE ); tmpLurn[idx_lurn]->LurnDesc->AccessRight = GENERIC_WRITE | GENERIC_READ; } // LUR node options if ((tmpLur->EnabledNdasFeatures & NDASFEATURE_BUFFER_CONTROL) == 0) { tmpLurn[idx_lurn]->LurnDesc->LurnOptions |= LURNOPTION_NO_BUFF_CONTROL; } if (tmpLurn[idx_lurn]->LurnDesc->LurnOptions & LURNOPTION_RESTRICT_UDMA) { tmpLurn[idx_lurn]->UDMARestrictValid = TRUE; tmpLurn[idx_lurn]->UDMARestrict = tmpLurn[idx_lurn]->LurnDesc->UDMARestrict; } else { tmpLurn[idx_lurn]->UDMARestrictValid = FALSE; } if (LURN_DIRECT_ACCESS == tmpLurn[idx_lurn]->LurnDesc->LurnType && LANSCSIIDE_VERSION_2_0 == tmpLurn[idx_lurn]->LurnDesc->LurnIde.HWVersion) { writeCheckRequired = TRUE; } DebugTrace( NDASSCSI_DBG_LUR_INFO, ("tmpLurn[idx_lurn]->LurnDesc->LurnOptions = %x\n", tmpLurn[idx_lurn]->LurnDesc->LurnOptions) ); if (!FlagOn(tmpLurn[idx_lurn]->LurnDesc->LurnOptions, LURNOPTION_SET_RECONNECTION)) { if (!LURN_IS_ROOT_NODE(tmpLurn[idx_lurn])) { if (tmpLurn[idx_lurn]->LurnParent->LurnDesc->LurnType == LURN_NDAS_RAID1 || tmpLurn[idx_lurn]->LurnParent->LurnDesc->LurnType == LURN_NDAS_RAID5) { tmpLurn[idx_lurn]->LurnDesc->ReconnTrial = RECONNECTION_MAX_TRY / 4; tmpLurn[idx_lurn]->LurnDesc->ReconnInterval = MAX_RECONNECTION_INTERVAL / NANO100_PER_MSEC; if (FlagOn(tmpLur->LurDesc->LurOptions, LUROPTION_REDUCE_TIMEOUT)) { tmpLurn[idx_lurn]->LurnDesc->ReconnTrial /= 2; } DebugTrace( NDASSCSI_DBG_LUR_INFO, ("LURNOPTION_SET_RECONNECTION\n") ); SetFlag( tmpLurn[idx_lurn]->LurnDesc->LurnOptions, LURNOPTION_SET_RECONNECTION ); } } } // Initialize the LURN status = LurnCreate( tmpLur, tmpLurn[idx_lurn] ); if (status != STATUS_SUCCESS) { if (tmpLurn[idx_lurn]->LurnDesc->LurnChildrenCnt != 0) { NDAS_ASSERT( NDAS_ASSERT_NODE_UNRECHABLE ); DebugTrace( NDASSCSI_DBG_LUR_INFO, ("LurnCreate() failed. LURN#:%d NTSTATUS:%08lx\n", idx_lurn, status) ); break; } } } error_out: if (status != STATUS_SUCCESS) { for (idx_lurn = 0; (ULONG)idx_lurn < tmpLur->LurDesc->LurnDescCount; idx_lurn++) { if (tmpLurn[idx_lurn]) { DebugTrace( NDASSCSI_DBG_LUR_INFO, ("Freeing LURN:%p(%d)\n", tmpLurn[idx_lurn], idx_lurn) ); if (LURN_IS_RUNNING(tmpLurn[idx_lurn]->LurnStatus)) { LurnSendStopCcb( tmpLurn[idx_lurn] ); LurnClose( tmpLurn[idx_lurn] ); } LurnFree( tmpLurn[idx_lurn] ); tmpLurn[idx_lurn] = NULL; } } if (tmpLur) { LsuFreeAllBlockAce( &tmpLur->UserBacl.BlockAclHead ); LsuFreeAllBlockAce( &tmpLur->SystemBacl.BlockAclHead ); ExFreePoolWithTag( tmpLur, LUR_POOL_TAG ); } NdasRaidClose( &NdasrGlobalData ); NDAS_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); return status; } NDAS_ASSERT( status == STATUS_SUCCESS ); // Block access control list if (tmpLur->LurDesc->BACLOffset) { PNDAS_BLOCK_ACL srcBACL; srcBACL = (PNDAS_BLOCK_ACL)((PUCHAR)tmpLur->LurDesc + tmpLur->LurDesc->BACLOffset); NDAS_ASSERT( srcBACL->Length == tmpLur->LurDesc->BACLLength ); NDAS_ASSERT( tmpLur->BlockBytes ); status = LsuConvertNdasBaclToLsuBacl( &tmpLur->SystemBacl, srcBACL, tmpLur->BlockBytes ); if (status != STATUS_SUCCESS) { NDAS_ASSERT(FALSE); } } if (tmpLur->DeviceMode == DEVMODE_SHARED_READWRITE) { if (EnableSecondaryOnly) { } else if (FlagOn(tmpLur->LurDesc->LurOptions, LUROPTION_DONOT_ADJUST_PRIM_SEC_ROLE)) { DebugTrace( NDASSCSI_DBG_LUR_INFO, ("DONOT_ADJUST_ACCESSMODE is set. Can not go to Secondary mode.\n") ); } else { UCHAR ccbStatus; status = LurUpdateSynchrously( tmpLurn[0], LURN_UPDATECLASS_WRITEACCESS_USERID, &ccbStatus ); DebugTrace( NDASSCSI_DBG_LUR_INFO, ("LurUpdateSynchrously status = %x, ccbStatus = %x", status, ccbStatus) ); } } // Indicate Win2K read-only patch if (EnableW2kReadOnlyPacth) { if (RtlCheckRegistryKey(RTL_REGISTRY_SERVICES, NDAS_ROFS_NAME) != STATUS_SUCCESS) { tmpLur->LurFlags |= LURFLAG_W2K_READONLY_PATCH; } } if (writeCheckRequired) { if (tmpLur->LurDesc->LurOptions & LUROPTION_ON_NDAS_2_0_WRITE_CHECK) { tmpLur->LurFlags |= LURFLAG_WRITE_CHECK_REQUIRED; } else if (tmpLur->LurDesc->LurOptions & LUROPTION_OFF_NDAS_2_0_WRITE_CHECK) { tmpLur->LurFlags &= ~LURFLAG_WRITE_CHECK_REQUIRED; } else { // Default on. tmpLur->LurFlags |= LURFLAG_WRITE_CHECK_REQUIRED; } } // set Lur RtlCopyMemory( LurDesc2, tmpLur->LurDesc, LurDesc2->Length ); *Lur = tmpLur; return STATUS_SUCCESS; }
NTSTATUS NTAPI IntCreateRegistryPath( IN PCUNICODE_STRING DriverRegistryPath, OUT PUNICODE_STRING DeviceRegistryPath) { static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\"; static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\"; static WCHAR ControlSet[] = L"CONTROLSET"; static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\"; static WCHAR Insert2[] = L"\\Device0"; BOOLEAN Valid; UNICODE_STRING AfterControlSet; AfterControlSet = *DriverRegistryPath; /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */ Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) && 0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem, wcslen(RegistryMachineSystem))); if (Valid) { AfterControlSet.Buffer += wcslen(RegistryMachineSystem); AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL); /* Check if path contains CURRENTCONTROLSET */ if (AfterControlSet.Length > sizeof(CurrentControlSet) && 0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet))) { AfterControlSet.Buffer += wcslen(CurrentControlSet); AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL); } /* Check if path contains CONTROLSETnum */ else if (AfterControlSet.Length > sizeof(ControlSet) && 0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet))) { AfterControlSet.Buffer += wcslen(ControlSet); AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL); while (AfterControlSet.Length > 0 && *AfterControlSet.Buffer >= L'0' && *AfterControlSet.Buffer <= L'9') { AfterControlSet.Buffer++; AfterControlSet.Length -= sizeof(WCHAR); } Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer); AfterControlSet.Buffer++; AfterControlSet.Length -= sizeof(WCHAR); AfterControlSet.MaximumLength = AfterControlSet.Length; } else { Valid = FALSE; } } if (Valid) { DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2); DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool, DeviceRegistryPath->MaximumLength, TAG_VIDEO_PORT); if (DeviceRegistryPath->Buffer != NULL) { /* Build device path */ wcsncpy(DeviceRegistryPath->Buffer, DriverRegistryPath->Buffer, AfterControlSet.Buffer - DriverRegistryPath->Buffer); DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR); RtlAppendUnicodeToString(DeviceRegistryPath, Insert1); RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet); RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); /* Check if registry key exists */ Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer)); if (!Valid) ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT); } else { Valid = FALSE; } } else { WARN_(VIDEOPRT, "Unparsable registry path %wZ", DriverRegistryPath); } /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */ if (!Valid) { DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2); DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(NonPagedPool, DeviceRegistryPath->MaximumLength, TAG_VIDEO_PORT); if (!DeviceRegistryPath->Buffer) return STATUS_NO_MEMORY; RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath); RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); } DbgPrint("Formatted registry key '%wZ' -> '%wZ'\n", DriverRegistryPath, DeviceRegistryPath); return STATUS_SUCCESS; }
NTSTATUS NTAPI IntCreateNewRegistryPath( PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension) { static UNICODE_STRING VideoIdValueName = RTL_CONSTANT_STRING(L"VideoId"); static UNICODE_STRING ControlVideoPathName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"); HANDLE DevInstRegKey, SettingsKey, NewKey; UCHAR VideoIdBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + GUID_STRING_LENGTH]; UNICODE_STRING VideoIdString; UUID VideoId; PKEY_VALUE_PARTIAL_INFORMATION ValueInformation ; NTSTATUS Status; ULONG ResultLength; USHORT KeyMaxLength; OBJECT_ATTRIBUTES ObjectAttributes; /* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */ Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_ALL_ACCESS, &DevInstRegKey); if (Status != STATUS_SUCCESS) { ERR_(VIDEOPRT, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status); return Status; } /* Query the VideoId value */ ValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)VideoIdBuffer; Status = ZwQueryValueKey(DevInstRegKey, &VideoIdValueName, KeyValuePartialInformation, ValueInformation, sizeof(VideoIdBuffer), &ResultLength); if (!NT_SUCCESS(Status)) { /* Create a new video Id */ Status = ExUuidCreate(&VideoId); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "ExUuidCreate failed: status 0x%lx\n", Status); ObCloseHandle(DevInstRegKey, KernelMode); return Status; } /* Convert the GUID into a string */ Status = RtlStringFromGUID(&VideoId, &VideoIdString); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "RtlStringFromGUID failed: status 0x%lx\n", Status); ObCloseHandle(DevInstRegKey, KernelMode); return Status; } /* Copy the GUID String to our buffer */ ValueInformation->DataLength = min(VideoIdString.Length, GUID_STRING_LENGTH); RtlCopyMemory(ValueInformation->Data, VideoIdString.Buffer, ValueInformation->DataLength); /* Free the GUID string */ RtlFreeUnicodeString(&VideoIdString); /* Write the VideoId registry value */ Status = ZwSetValueKey(DevInstRegKey, &VideoIdValueName, 0, REG_SZ, ValueInformation->Data, ValueInformation->DataLength); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status); ObCloseHandle(DevInstRegKey, KernelMode); return Status; } } /* Initialize the VideoId string from the registry data */ VideoIdString.Buffer = (PWCHAR)ValueInformation->Data; VideoIdString.Length = (USHORT)ValueInformation->DataLength; VideoIdString.MaximumLength = VideoIdString.Length; /* Close the hardware key */ ObCloseHandle(DevInstRegKey, KernelMode); /* Calculate the size needed for the new registry path name */ KeyMaxLength = ControlVideoPathName.Length + VideoIdString.Length + sizeof(L"\\0000"); /* Allocate the path name buffer */ DeviceExtension->NewRegistryPath.Length = 0; DeviceExtension->NewRegistryPath.MaximumLength = KeyMaxLength; DeviceExtension->NewRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, KeyMaxLength, TAG_VIDEO_PORT); if (DeviceExtension->NewRegistryPath.Buffer == NULL) { ERR_(VIDEOPRT, "Failed to allocate key name buffer.\n"); return STATUS_INSUFFICIENT_RESOURCES; } /* Copy the root key name and append the VideoId string */ RtlCopyUnicodeString(&DeviceExtension->NewRegistryPath, &ControlVideoPathName); RtlAppendUnicodeStringToString(&DeviceExtension->NewRegistryPath, &VideoIdString); /* Check if we have the key already */ Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); if (Status != STATUS_SUCCESS) { /* Try to create the new key */ Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); } /* Append a the instance path */ /// \todo HACK RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"\\"); RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"0000"); /* Check this key again */ Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); if (Status != STATUS_SUCCESS) { /* Try to create the new key */ Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "Failed create key '%wZ'\n", &DeviceExtension->NewRegistryPath); return Status; } /* Open the new key */ InitializeObjectAttributes(&ObjectAttributes, &DeviceExtension->NewRegistryPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&NewKey, KEY_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); return Status; } /* Open the device profile key */ InitializeObjectAttributes(&ObjectAttributes, &DeviceExtension->RegistryPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&SettingsKey, KEY_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); ObCloseHandle(NewKey, KernelMode); return Status; } /* Copy the registry data from the legacy key */ Status = IntCopyRegistryKey(SettingsKey, NewKey); } return Status; }