2626
2727extern BOOLEAN VpBaseVideo ;
2828
29+ static UNICODE_STRING VideoClassName = RTL_CONSTANT_STRING (L"VIDEO" );
30+
2931/* PRIVATE FUNCTIONS **********************************************************/
3032
3133static BOOLEAN
@@ -209,21 +211,41 @@ IntVideoPortReleaseResources(
209211 // An empty CM_RESOURCE_LIST
210212 UCHAR EmptyResourceList [FIELD_OFFSET (CM_RESOURCE_LIST , List )] = {0 };
211213
212- Status = IoReportResourceForDetection (
213- DeviceExtension -> DriverObject ,
214- NULL , 0 , /* Driver List */
215- DeviceExtension -> PhysicalDeviceObject ,
216- (PCM_RESOURCE_LIST )EmptyResourceList ,
217- sizeof (EmptyResourceList ),
218- & ConflictDetected );
214+ if (DeviceExtension -> IsLegacyDevice || DeviceExtension -> IsLegacyDetect || DeviceExtension -> IsVgaDetect )
215+ {
216+ Status = IoReportResourceForDetection (
217+ DeviceExtension -> DriverObject ,
218+ NULL , 0 , /* Driver List */
219+ DeviceExtension -> PhysicalDeviceObject ,
220+ (PCM_RESOURCE_LIST )EmptyResourceList ,
221+ sizeof (EmptyResourceList ),
222+ & ConflictDetected );
219223
220- if (!NT_SUCCESS (Status ))
224+ if (!NT_SUCCESS (Status ))
225+ {
226+ ERR_ (VIDEOPRT ,
227+ "VideoPortReleaseResources (Detect) failed with 0x%08lx ; ConflictDetected: %s\n" ,
228+ Status , ConflictDetected ? "TRUE" : "FALSE" );
229+ }
230+ }
231+ else
221232 {
222- ERR_ (VIDEOPRT ,
223- "VideoPortReleaseResources IoReportResource failed with 0x%08lx ; ConflictDetected: %s\n" ,
224- Status , ConflictDetected ? "TRUE" : "FALSE" );
233+ Status = IoReportResourceUsage (& VideoClassName ,
234+ DeviceExtension -> DriverObject ,
235+ NULL ,
236+ 0 ,
237+ DeviceExtension -> PhysicalDeviceObject ,
238+ (PCM_RESOURCE_LIST )EmptyResourceList ,
239+ sizeof (EmptyResourceList ),
240+ FALSE,
241+ & ConflictDetected );
242+ if (!NT_SUCCESS (Status ))
243+ {
244+ ERR_ (VIDEOPRT ,
245+ "VideoPortReleaseResources (Usage) failed with 0x%08lx ; ConflictDetected: %s\n" ,
246+ Status , ConflictDetected ? "TRUE" : "FALSE" );
247+ }
225248 }
226- /* Ignore the returned status however... */
227249}
228250
229251NTSTATUS NTAPI
@@ -276,6 +298,38 @@ IntVideoPortMapPhysicalMemory(
276298 return Status ;
277299}
278300
301+ static BOOLEAN
302+ IntAccessRangeIsInAllocatedResources (
303+ _In_ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension ,
304+ _In_ PVIDEO_ACCESS_RANGE Range )
305+ {
306+ CM_RESOURCE_LIST * Res = DeviceExtension -> AllocatedResources ;
307+ CM_FULL_RESOURCE_DESCRIPTOR * Full ;
308+ CM_PARTIAL_RESOURCE_DESCRIPTOR * Desc ;
309+
310+ if (!Res || Res -> Count == 0 )
311+ return FALSE;
312+ Full = & Res -> List [0 ];
313+ for (Desc = Full -> PartialResourceList .PartialDescriptors ;
314+ Desc < Full -> PartialResourceList .PartialDescriptors + Full -> PartialResourceList .Count ;
315+ ++ Desc )
316+ {
317+ if (Range -> RangeInIoSpace && Desc -> Type == CmResourceTypePort )
318+ {
319+ if (Desc -> u .Port .Start .QuadPart == Range -> RangeStart .QuadPart &&
320+ Desc -> u .Port .Length == Range -> RangeLength )
321+ return TRUE;
322+ }
323+ else if (!Range -> RangeInIoSpace && Desc -> Type == CmResourceTypeMemory )
324+ {
325+ if (Desc -> u .Memory .Start .QuadPart == Range -> RangeStart .QuadPart &&
326+ Desc -> u .Memory .Length == Range -> RangeLength )
327+ return TRUE;
328+ }
329+ }
330+ return FALSE;
331+ }
332+
279333
280334PVOID NTAPI
281335IntVideoPortMapMemory (
@@ -952,12 +1006,82 @@ VideoPortVerifyAccessRanges(
9521006 {
9531007 /* Release the resources and do nothing more for now... */
9541008 IntVideoPortReleaseResources (DeviceExtension );
1009+ /* If releasing VGA device resources, clear tracked ranges */
1010+ if (DeviceExtension -> IsVgaDriver )
1011+ {
1012+ KeWaitForMutexObject (& VgaSyncLock , Executive , KernelMode , FALSE, NULL );
1013+ if (VgaRanges )
1014+ {
1015+ ExFreePoolWithTag (VgaRanges , TAG_VIDEO_PORT );
1016+ VgaRanges = NULL ;
1017+ }
1018+ NumOfVgaRanges = 0 ;
1019+ VgaDeviceExtension = NULL ;
1020+ KeReleaseMutex (& VgaSyncLock , FALSE);
1021+ }
1022+ return NO_ERROR ;
1023+ }
1024+
1025+ /*
1026+ * For non-legacy PCI devices, validate that the relevant I/O or memory
1027+ * decoding bits are enabled in the PCI command register before claiming
1028+ */
1029+ if (!DeviceExtension -> IsLegacyDevice && DeviceExtension -> AdapterInterfaceType == PCIBus )
1030+ {
1031+ USHORT PciCommand ;
1032+ ULONG BytesRead ;
1033+
1034+ BytesRead = HalGetBusDataByOffset (PCIConfiguration ,
1035+ DeviceExtension -> SystemIoBusNumber ,
1036+ DeviceExtension -> SystemIoSlotNumber ,
1037+ & PciCommand ,
1038+ FIELD_OFFSET (PCI_COMMON_CONFIG , Command ),
1039+ sizeof (PciCommand ));
1040+ if (BytesRead == sizeof (PciCommand ))
1041+ {
1042+ for (i = 0 ; i < NumAccessRanges ; i ++ )
1043+ {
1044+ if (AccessRanges [i ].RangeInIoSpace )
1045+ {
1046+ if ((PciCommand & PCI_ENABLE_IO_SPACE ) == 0 )
1047+ {
1048+ WARN_ (VIDEOPRT , "PCI I/O space disabled; refusing access range claim\n" );
1049+ return ERROR_INVALID_PARAMETER ;
1050+ }
1051+ }
1052+ else
1053+ {
1054+ if ((PciCommand & PCI_ENABLE_MEMORY_SPACE ) == 0 )
1055+ {
1056+ WARN_ (VIDEOPRT , "PCI memory space disabled; refusing access range claim\n" );
1057+ return ERROR_INVALID_PARAMETER ;
1058+ }
1059+ }
1060+ }
1061+ }
1062+ }
1063+
1064+ /* Determine which ranges need to be claimed (exclude PnP-assigned ones) */
1065+ ULONG Needed = 0 ;
1066+ for (i = 0 ; i < NumAccessRanges ; ++ i )
1067+ {
1068+ if (DeviceExtension -> PhysicalDeviceObject && !DeviceExtension -> IsLegacyDevice )
1069+ {
1070+ if (IntAccessRangeIsInAllocatedResources (DeviceExtension , & AccessRanges [i ]))
1071+ continue ;
1072+ }
1073+ ++ Needed ;
1074+ }
1075+
1076+ if (Needed == 0 )
1077+ {
1078+ /* Nothing to report/claim */
9551079 return NO_ERROR ;
9561080 }
9571081
958- /* Create the resource list */
1082+ /* Create the resource list for the non-PnP-assigned ranges */
9591083 ResourceListSize = sizeof (CM_RESOURCE_LIST )
960- + (NumAccessRanges - 1 ) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR );
1084+ + (Needed - 1 ) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR );
9611085 ResourceList = ExAllocatePoolWithTag (PagedPool , ResourceListSize , TAG_VIDEO_PORT );
9621086 if (!ResourceList )
9631087 {
@@ -971,47 +1095,86 @@ VideoPortVerifyAccessRanges(
9711095 ResourceList -> List [0 ].BusNumber = DeviceExtension -> SystemIoBusNumber ;
9721096 ResourceList -> List [0 ].PartialResourceList .Version = 1 ;
9731097 ResourceList -> List [0 ].PartialResourceList .Revision = 1 ;
974- ResourceList -> List [0 ].PartialResourceList .Count = NumAccessRanges ;
975- for (i = 0 ; i < NumAccessRanges ; i ++ , AccessRanges ++ )
1098+ ResourceList -> List [0 ].PartialResourceList .Count = Needed ;
1099+
1100+ ULONG j = 0 ;
1101+ for (i = 0 ; i < NumAccessRanges ; ++ i )
9761102 {
977- PartialDescriptor = & ResourceList -> List [0 ].PartialResourceList .PartialDescriptors [i ];
978- if (AccessRanges -> RangeInIoSpace )
1103+ if (DeviceExtension -> PhysicalDeviceObject && !DeviceExtension -> IsLegacyDevice )
1104+ {
1105+ if (IntAccessRangeIsInAllocatedResources (DeviceExtension , & AccessRanges [i ]))
1106+ continue ;
1107+ }
1108+
1109+ PartialDescriptor = & ResourceList -> List [0 ].PartialResourceList .PartialDescriptors [j ++ ];
1110+ if (AccessRanges [i ].RangeInIoSpace )
9791111 {
9801112 PartialDescriptor -> Type = CmResourceTypePort ;
981- PartialDescriptor -> u .Port .Start = AccessRanges -> RangeStart ;
982- PartialDescriptor -> u .Port .Length = AccessRanges -> RangeLength ;
1113+ PartialDescriptor -> u .Port .Start = AccessRanges [ i ]. RangeStart ;
1114+ PartialDescriptor -> u .Port .Length = AccessRanges [ i ]. RangeLength ;
9831115 }
9841116 else
9851117 {
9861118 PartialDescriptor -> Type = CmResourceTypeMemory ;
987- PartialDescriptor -> u .Memory .Start = AccessRanges -> RangeStart ;
988- PartialDescriptor -> u .Memory .Length = AccessRanges -> RangeLength ;
1119+ PartialDescriptor -> u .Memory .Start = AccessRanges [ i ]. RangeStart ;
1120+ PartialDescriptor -> u .Memory .Length = AccessRanges [ i ]. RangeLength ;
9891121 }
990- if (AccessRanges -> RangeShareable )
991- PartialDescriptor -> ShareDisposition = CmResourceShareShared ;
992- else
993- PartialDescriptor -> ShareDisposition = CmResourceShareDeviceExclusive ;
1122+ PartialDescriptor -> ShareDisposition = AccessRanges [i ].RangeShareable ?
1123+ CmResourceShareShared : CmResourceShareDeviceExclusive ;
9941124 PartialDescriptor -> Flags = 0 ;
995- if (AccessRanges -> RangePassive & VIDEO_RANGE_PASSIVE_DECODE )
1125+ if (AccessRanges [ i ]. RangePassive & VIDEO_RANGE_PASSIVE_DECODE )
9961126 PartialDescriptor -> Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE ;
997- if (AccessRanges -> RangePassive & VIDEO_RANGE_10_BIT_DECODE )
1127+ if (AccessRanges [ i ]. RangePassive & VIDEO_RANGE_10_BIT_DECODE )
9981128 PartialDescriptor -> Flags |= CM_RESOURCE_PORT_10_BIT_DECODE ;
9991129 }
10001130
1001- /* Try to acquire all resource ranges */
1002- Status = IoReportResourceForDetection (
1003- DeviceExtension -> DriverObject ,
1004- NULL , 0 , /* Driver List */
1005- DeviceExtension -> PhysicalDeviceObject ,
1006- ResourceList , ResourceListSize ,
1007- & ConflictDetected );
1008-
1131+ if (DeviceExtension -> IsLegacyDevice || DeviceExtension -> IsLegacyDetect || DeviceExtension -> IsVgaDetect )
1132+ {
1133+ Status = IoReportResourceForDetection (
1134+ DeviceExtension -> DriverObject ,
1135+ NULL , 0 , /* Driver List */
1136+ DeviceExtension -> PhysicalDeviceObject ,
1137+ ResourceList , ResourceListSize ,
1138+ & ConflictDetected );
1139+
1140+ /* IntIsVgaSaveDriver() will later ignore STATUS_CONFLICTING_ADDRESSES, but we still claim it */
1141+ if (!NT_SUCCESS (Status ) && IntIsVgaSaveDriver (DeviceExtension ))
1142+ {
1143+ NTSTATUS fbStatus ;
1144+ BOOLEAN fbConflict = FALSE;
1145+ fbStatus = IoReportResourceUsage (& VideoClassName ,
1146+ DeviceExtension -> DriverObject ,
1147+ NULL ,
1148+ 0 ,
1149+ DeviceExtension -> PhysicalDeviceObject ,
1150+ ResourceList ,
1151+ ResourceListSize ,
1152+ FALSE,
1153+ & fbConflict );
1154+ INFO_ (VIDEOPRT , "VGA detect->usage fallback: Status=0x%lx Conflict=%d fbStatus=0x%lx fbConflict=%d\n" ,
1155+ Status , ConflictDetected , fbStatus , fbConflict );
1156+ Status = fbStatus ;
1157+ ConflictDetected = fbConflict ;
1158+ }
1159+ }
1160+ else
1161+ {
1162+ Status = IoReportResourceUsage (& VideoClassName ,
1163+ DeviceExtension -> DriverObject ,
1164+ NULL ,
1165+ 0 ,
1166+ DeviceExtension -> PhysicalDeviceObject ,
1167+ ResourceList ,
1168+ ResourceListSize ,
1169+ FALSE,
1170+ & ConflictDetected );
1171+ }
10091172 ExFreePoolWithTag (ResourceList , TAG_VIDEO_PORT );
10101173
10111174 /* If VgaSave driver is conflicting and we don't explicitely want
10121175 * to use it, ignore the problem (because win32k will try to use
10131176 * this driver only if all other ones are failing). */
1014- if (Status == STATUS_CONFLICTING_ADDRESSES &&
1177+ if (( Status == STATUS_CONFLICTING_ADDRESSES || ConflictDetected ) &&
10151178 IntIsVgaSaveDriver (DeviceExtension ) &&
10161179 !VpBaseVideo )
10171180 {
@@ -1021,7 +1184,34 @@ VideoPortVerifyAccessRanges(
10211184 if (!NT_SUCCESS (Status ) || ConflictDetected )
10221185 return ERROR_INVALID_PARAMETER ;
10231186 else
1187+ {
1188+ /* Track VGA access ranges on success for fallback handling */
1189+ if (DeviceExtension -> IsVgaDriver )
1190+ {
1191+ KeWaitForMutexObject (& VgaSyncLock , Executive , KernelMode , FALSE, NULL );
1192+ if (VgaRanges )
1193+ {
1194+ ExFreePoolWithTag (VgaRanges , TAG_VIDEO_PORT );
1195+ VgaRanges = NULL ;
1196+ NumOfVgaRanges = 0 ;
1197+ }
1198+ if (NumAccessRanges )
1199+ {
1200+ SIZE_T sz = NumAccessRanges * sizeof (VIDEO_ACCESS_RANGE );
1201+ VgaRanges = ExAllocatePoolWithTag (PagedPool , sz , TAG_VIDEO_PORT );
1202+ if (VgaRanges )
1203+ {
1204+ RtlCopyMemory (VgaRanges , AccessRanges , sz );
1205+ NumOfVgaRanges = NumAccessRanges ;
1206+ VgaDeviceExtension = DeviceExtension ;
1207+ }
1208+ }
1209+ KeReleaseMutex (& VgaSyncLock , FALSE);
1210+ }
1211+ /* Leave VGA detect phase after first successful claim */
1212+ DeviceExtension -> IsVgaDetect = FALSE;
10241213 return NO_ERROR ;
1214+ }
10251215}
10261216
10271217/*
0 commit comments