Beispiel #1
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- 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;    
}
Beispiel #2
0
NTSTATUS
DrDriverServiceExist(
	PWSTR  DriverServiceName
){
	NTSTATUS	status;

	status = RtlCheckRegistryKey(RTL_REGISTRY_SERVICES,
									DriverServiceName);

	return status;
}
Beispiel #3
0
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;	
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}