2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Driver Device Functions
5 * FILE: subsys/win32k/eng/device.c
6 * PROGRAMER: Jason Filby
15 static PGRAPHICS_DEVICE gpGraphicsDeviceFirst
= NULL
;
16 static PGRAPHICS_DEVICE gpGraphicsDeviceLast
= NULL
;
17 static HSEMAPHORE ghsemGraphicsDeviceList
;
18 static ULONG giDevNum
= 1;
24 ghsemGraphicsDeviceList
= EngCreateSemaphore();
25 if (!ghsemGraphicsDeviceList
)
34 EngpRegisterGraphicsDevice(
35 PUNICODE_STRING pustrDeviceName
,
36 PUNICODE_STRING pustrDiplayDrivers
,
37 PUNICODE_STRING pustrDescription
,
40 PGRAPHICS_DEVICE pGraphicsDevice
;
41 PDEVICE_OBJECT pDeviceObject
;
42 PFILE_OBJECT pFileObject
;
45 ULONG i
, cj
, cModes
= 0;
48 PDEVMODEW pdm
, pdmEnd
;
51 DPRINT1("EngpRegisterGraphicsDevice(%S)\n", pustrDeviceName
->Buffer
);
53 /* Allocate a GRAPHICS_DEVICE structure */
54 pGraphicsDevice
= ExAllocatePoolWithTag(PagedPool
,
55 sizeof(GRAPHICS_DEVICE
),
59 DPRINT1("ExAllocatePoolWithTag failed\n");
63 /* Try to open the driver */
64 Status
= IoGetDeviceObjectPointer(pustrDeviceName
,
65 FILE_READ_DATA
| FILE_WRITE_DATA
,
68 if (!NT_SUCCESS(Status
))
70 DPRINT1("Could not open driver, 0x%lx\n", Status
);
71 ExFreePoolWithTag(pGraphicsDevice
, GDITAG_GDEVICE
);
75 /* Enable the device */
76 EngFileWrite(pFileObject
, &bEnable
, sizeof(BOOL
), &cj
);
78 /* Copy the device and file object pointers */
79 pGraphicsDevice
->DeviceObject
= pDeviceObject
;
80 pGraphicsDevice
->FileObject
= pFileObject
;
82 /* Copy device name */
83 wcsncpy(pGraphicsDevice
->szNtDeviceName
,
84 pustrDeviceName
->Buffer
,
85 sizeof(pGraphicsDevice
->szNtDeviceName
) / sizeof(WCHAR
));
87 /* Create a win device name (FIXME: virtual devices!) */
88 swprintf(pGraphicsDevice
->szWinDeviceName
, L
"\\\\.\\VIDEO%d", (CHAR
)giDevNum
);
90 /* Allocate a buffer for the strings */
91 cj
= pustrDiplayDrivers
->Length
+ pustrDescription
->Length
+ sizeof(WCHAR
);
92 pwsz
= ExAllocatePoolWithTag(PagedPool
, cj
, GDITAG_DRVSUP
);
95 DPRINT1("Could not allocate string buffer\n");
96 ASSERT(FALSE
); // FIXME
99 /* Copy display driver names */
100 pGraphicsDevice
->pDiplayDrivers
= pwsz
;
101 RtlCopyMemory(pGraphicsDevice
->pDiplayDrivers
,
102 pustrDiplayDrivers
->Buffer
,
103 pustrDiplayDrivers
->Length
);
105 /* Copy description */
106 pGraphicsDevice
->pwszDescription
= pwsz
+ pustrDiplayDrivers
->Length
/ sizeof(WCHAR
);
107 RtlCopyMemory(pGraphicsDevice
->pwszDescription
,
108 pustrDescription
->Buffer
,
109 pustrDescription
->Length
+ sizeof(WCHAR
));
111 /* Initialize the pdevmodeInfo list and default index */
112 pGraphicsDevice
->pdevmodeInfo
= NULL
;
113 pGraphicsDevice
->iDefaultMode
= 0;
114 pGraphicsDevice
->iCurrentMode
= 0;
116 // FIXME: initialize state flags
117 pGraphicsDevice
->StateFlags
= 0;
119 /* Loop through the driver names
120 * This is a REG_MULTI_SZ string */
121 for (; *pwsz
; pwsz
+= wcslen(pwsz
) + 1)
123 DPRINT1("trying driver: %ls\n", pwsz
);
124 /* Try to load the display driver */
125 pldev
= EngLoadDriver(pwsz
, LDEV_DEVICE_DISPLAY
);
128 DPRINT1("Could not load driver: '%ls'\n", pwsz
);
132 /* Get the mode list from the driver */
133 pdminfo
= LDEVOBJ_pdmiGetModes(pldev
, pDeviceObject
);
136 DPRINT1("Could not get mode list for '%ls'\n", pwsz
);
140 /* Attach the mode info to the device */
141 pdminfo
->pdmiNext
= pGraphicsDevice
->pdevmodeInfo
;
142 pGraphicsDevice
->pdevmodeInfo
= pdminfo
;
145 pdmEnd
= (DEVMODEW
*)((PCHAR
)pdminfo
->adevmode
+ pdminfo
->cbdevmode
);
146 for (pdm
= pdminfo
->adevmode
;
148 pdm
= (DEVMODEW
*)((PCHAR
)pdm
+ pdm
->dmSize
+ pdm
->dmDriverExtra
))
153 // FIXME: release the driver again until it's used?
156 if (!pGraphicsDevice
->pdevmodeInfo
|| cModes
== 0)
158 DPRINT1("No devmodes\n");
159 ExFreePool(pGraphicsDevice
);
163 /* Allocate an index buffer */
164 pGraphicsDevice
->cDevModes
= cModes
;
165 pGraphicsDevice
->pDevModeList
= ExAllocatePoolWithTag(PagedPool
,
166 cModes
* sizeof(DEVMODEENTRY
),
168 if (!pGraphicsDevice
->pDevModeList
)
170 DPRINT1("No devmode list\n");
171 ExFreePool(pGraphicsDevice
);
175 /* Loop through all DEVMODEINFOs */
176 for (pdminfo
= pGraphicsDevice
->pdevmodeInfo
, i
= 0;
178 pdminfo
= pdminfo
->pdmiNext
)
180 /* Calculate End of the DEVMODEs */
181 pdmEnd
= (DEVMODEW
*)((PCHAR
)pdminfo
->adevmode
+ pdminfo
->cbdevmode
);
183 /* Loop through the DEVMODEs */
184 for (pdm
= pdminfo
->adevmode
;
186 pdm
= (PDEVMODEW
)((PCHAR
)pdm
+ pdm
->dmSize
+ pdm
->dmDriverExtra
))
188 /* Compare with the default entry */
189 if (pdm
->dmBitsPerPel
== pdmDefault
->dmBitsPerPel
&&
190 pdm
->dmPelsWidth
== pdmDefault
->dmPelsWidth
&&
191 pdm
->dmPelsHeight
== pdmDefault
->dmPelsHeight
&&
192 pdm
->dmDisplayFrequency
== pdmDefault
->dmDisplayFrequency
)
194 pGraphicsDevice
->iDefaultMode
= i
;
195 pGraphicsDevice
->iCurrentMode
= i
;
196 DPRINT1("Found default entry: %ld '%ls'\n", i
, pdm
->dmDeviceName
);
199 /* Initialize the entry */
200 pGraphicsDevice
->pDevModeList
[i
].dwFlags
= 0;
201 pGraphicsDevice
->pDevModeList
[i
].pdm
= pdm
;
207 EngAcquireSemaphore(ghsemGraphicsDeviceList
);
209 /* Insert the device into the global list */
210 pGraphicsDevice
->pNextGraphicsDevice
= gpGraphicsDeviceLast
;
211 gpGraphicsDeviceLast
= pGraphicsDevice
;
212 if (!gpGraphicsDeviceFirst
)
213 gpGraphicsDeviceFirst
= pGraphicsDevice
;
215 /* Increment device number */
219 EngReleaseSemaphore(ghsemGraphicsDeviceList
);
220 DPRINT1("Prepared %ld modes for %ls\n", cModes
, pGraphicsDevice
->pwszDescription
);
222 return pGraphicsDevice
;
228 EngpFindGraphicsDevice(
229 PUNICODE_STRING pustrDevice
,
233 UNICODE_STRING ustrCurrent
;
234 PGRAPHICS_DEVICE pGraphicsDevice
;
238 EngAcquireSemaphore(ghsemGraphicsDeviceList
);
242 /* Loop through the list of devices */
243 for (pGraphicsDevice
= gpGraphicsDeviceFirst
, i
= 0;
245 pGraphicsDevice
= pGraphicsDevice
->pNextGraphicsDevice
, i
++)
247 /* Compare the device name */
248 RtlInitUnicodeString(&ustrCurrent
, pGraphicsDevice
->szWinDeviceName
);
249 if (RtlEqualUnicodeString(&ustrCurrent
, pustrDevice
, FALSE
))
257 /* Loop through the list of devices */
258 for (pGraphicsDevice
= gpGraphicsDeviceFirst
, i
= 0;
259 pGraphicsDevice
&& i
< iDevNum
;
260 pGraphicsDevice
= pGraphicsDevice
->pNextGraphicsDevice
, i
++);
264 EngReleaseSemaphore(ghsemGraphicsDeviceList
);
266 return pGraphicsDevice
;
273 PFILE_OBJECT pFileObject
,
274 ULONG ulMajorFunction
,
277 ULONGLONG ullStartOffset
,
278 OUT LPDWORD lpInformation
)
280 PDEVICE_OBJECT pDeviceObject
;
283 IO_STATUS_BLOCK Iosb
;
285 LARGE_INTEGER liStartOffset
;
287 /* Get corresponding device object */
288 pDeviceObject
= IoGetRelatedDeviceObject(pFileObject
);
291 return STATUS_INVALID_PARAMETER
;
294 /* Initialize an event */
295 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
298 liStartOffset
.QuadPart
= ullStartOffset
;
299 pIrp
= IoBuildSynchronousFsdRequest(ulMajorFunction
,
308 return STATUS_INSUFFICIENT_RESOURCES
;
311 /* Call the driver */
312 Status
= IoCallDriver(pDeviceObject
, pIrp
);
314 /* Wait if neccessary */
315 if (STATUS_PENDING
== Status
)
317 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, TRUE
, 0);
318 Status
= Iosb
.Status
;
321 /* Return information to the caller about the operation. */
322 *lpInformation
= Iosb
.Information
;
324 /* Return NTSTATUS */
331 IN PFILE_OBJECT pFileObject
,
334 IN PSIZE_T lpBytesWritten
)
336 EngpFileIoRequest(pFileObject
,
347 IN PFILE_OBJECT pFileObject
,
348 IN DWORD dwIoControlCode
,
350 IN SIZE_T nInBufferSize
,
351 OUT PVOID lpOutBuffer
,
352 IN SIZE_T nOutBufferSize
,
353 OUT LPDWORD lpInformation
)
355 PDEVICE_OBJECT pDeviceObject
;
358 IO_STATUS_BLOCK Iosb
;
361 /* Get corresponding device object */
362 pDeviceObject
= IoGetRelatedDeviceObject(pFileObject
);
365 return STATUS_INVALID_PARAMETER
;
368 /* Initialize an event */
369 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
371 /* Build IO control IRP */
372 pIrp
= IoBuildDeviceIoControlRequest(dwIoControlCode
,
383 return STATUS_INSUFFICIENT_RESOURCES
;
386 /* Call the driver */
387 Status
= IoCallDriver(pDeviceObject
, pIrp
);
389 /* Wait if neccessary */
390 if (Status
== STATUS_PENDING
)
392 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, TRUE
, 0);
393 Status
= Iosb
.Status
;
396 /* Return information to the caller about the operation. */
397 *lpInformation
= Iosb
.Information
;
399 /* This function returns NTSTATUS */
409 DWORD dwIoControlCode
,
413 DWORD nOutBufferSize
,
414 DWORD
*lpBytesReturned
)
419 IO_STATUS_BLOCK Iosb
;
420 PDEVICE_OBJECT DeviceObject
;
422 DPRINT("EngDeviceIoControl() called\n");
424 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
426 DeviceObject
= (PDEVICE_OBJECT
) hDevice
;
428 Irp
= IoBuildDeviceIoControlRequest(dwIoControlCode
,
433 nOutBufferSize
, FALSE
, &Event
, &Iosb
);
434 if (!Irp
) return ERROR_NOT_ENOUGH_MEMORY
;
436 Status
= IoCallDriver(DeviceObject
, Irp
);
438 if (Status
== STATUS_PENDING
)
440 (VOID
)KeWaitForSingleObject(&Event
, Executive
, KernelMode
, TRUE
, 0);
441 Status
= Iosb
.Status
;
444 DPRINT("EngDeviceIoControl(): Returning %X/%X\n", Iosb
.Status
,
447 /* Return information to the caller about the operation. */
448 *lpBytesReturned
= Iosb
.Information
;
450 /* Convert NT status values to win32 error codes. */
453 case STATUS_INSUFFICIENT_RESOURCES
:
454 return ERROR_NOT_ENOUGH_MEMORY
;
456 case STATUS_BUFFER_OVERFLOW
:
457 return ERROR_MORE_DATA
;
459 case STATUS_NOT_IMPLEMENTED
:
460 return ERROR_INVALID_FUNCTION
;
462 case STATUS_INVALID_PARAMETER
:
463 return ERROR_INVALID_PARAMETER
;
465 case STATUS_BUFFER_TOO_SMALL
:
466 return ERROR_INSUFFICIENT_BUFFER
;
468 case STATUS_DEVICE_DOES_NOT_EXIST
:
469 return ERROR_DEV_NOT_EXIST
;
472 return ERROR_IO_PENDING
;