1c2c66affSColin Finck /* 2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory 3c2c66affSColin Finck * PROJECT: ReactOS kernel 4c2c66affSColin Finck * PURPOSE: GDI Driver Device Functions 5c2c66affSColin Finck * FILE: win32ss/gdi/eng/device.c 6c2c66affSColin Finck * PROGRAMER: Jason Filby 7c2c66affSColin Finck * Timo Kreuzer 8c2c66affSColin Finck */ 9c2c66affSColin Finck 10c2c66affSColin Finck #include <win32k.h> 110ad65796SHermès Bélusca-Maïto #include <ntddvdeo.h> 120ad65796SHermès Bélusca-Maïto 130ad65796SHermès Bélusca-Maïto DBG_DEFAULT_CHANNEL(EngDev); 14c2c66affSColin Finck 15c2c66affSColin Finck PGRAPHICS_DEVICE gpPrimaryGraphicsDevice; 16c2c66affSColin Finck PGRAPHICS_DEVICE gpVgaGraphicsDevice; 17c2c66affSColin Finck 18c2c66affSColin Finck static PGRAPHICS_DEVICE gpGraphicsDeviceFirst = NULL; 19c2c66affSColin Finck static PGRAPHICS_DEVICE gpGraphicsDeviceLast = NULL; 20c2c66affSColin Finck static HSEMAPHORE ghsemGraphicsDeviceList; 21c2c66affSColin Finck static ULONG giDevNum = 1; 22c2c66affSColin Finck 235c7ce447SVictor Perevertkin CODE_SEG("INIT") 24c2c66affSColin Finck NTSTATUS 25c2c66affSColin Finck NTAPI 26c2c66affSColin Finck InitDeviceImpl(VOID) 27c2c66affSColin Finck { 28c2c66affSColin Finck ghsemGraphicsDeviceList = EngCreateSemaphore(); 29c2c66affSColin Finck if (!ghsemGraphicsDeviceList) 30c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 31c2c66affSColin Finck 32c2c66affSColin Finck return STATUS_SUCCESS; 33c2c66affSColin Finck } 34c2c66affSColin Finck 356739fb1bSHervé Poussineau NTSTATUS 366739fb1bSHervé Poussineau EngpUpdateGraphicsDeviceList(VOID) 376739fb1bSHervé Poussineau { 386739fb1bSHervé Poussineau ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0; 39c05a45e1SOleg Dubinskiy WCHAR awcDeviceName[20], awcWinDeviceName[20]; 4077e891b8STimo Kreuzer UNICODE_STRING ustrDeviceName; 416739fb1bSHervé Poussineau WCHAR awcBuffer[256]; 426739fb1bSHervé Poussineau NTSTATUS Status; 436739fb1bSHervé Poussineau PGRAPHICS_DEVICE pGraphicsDevice; 446739fb1bSHervé Poussineau ULONG cbValue; 456739fb1bSHervé Poussineau HKEY hkey; 466739fb1bSHervé Poussineau 476739fb1bSHervé Poussineau /* Open the key for the adapters */ 486739fb1bSHervé Poussineau Status = RegOpenKey(L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO", &hkey); 496739fb1bSHervé Poussineau if (!NT_SUCCESS(Status)) 506739fb1bSHervé Poussineau { 516739fb1bSHervé Poussineau ERR("Could not open HARDWARE\\DEVICEMAP\\VIDEO registry key:0x%lx\n", Status); 526739fb1bSHervé Poussineau return Status; 536739fb1bSHervé Poussineau } 546739fb1bSHervé Poussineau 556739fb1bSHervé Poussineau /* Read the name of the VGA adapter */ 566739fb1bSHervé Poussineau cbValue = sizeof(awcDeviceName); 576739fb1bSHervé Poussineau Status = RegQueryValue(hkey, L"VgaCompatible", REG_SZ, awcDeviceName, &cbValue); 586739fb1bSHervé Poussineau if (NT_SUCCESS(Status)) 596739fb1bSHervé Poussineau { 606739fb1bSHervé Poussineau iVGACompatible = _wtoi(&awcDeviceName[sizeof("\\Device\\Video")-1]); 616739fb1bSHervé Poussineau ERR("VGA adapter = %lu\n", iVGACompatible); 626739fb1bSHervé Poussineau } 636739fb1bSHervé Poussineau 646739fb1bSHervé Poussineau /* Get the maximum mumber of adapters */ 656739fb1bSHervé Poussineau if (!RegReadDWORD(hkey, L"MaxObjectNumber", &ulMaxObjectNumber)) 666739fb1bSHervé Poussineau { 676739fb1bSHervé Poussineau ERR("Could not read MaxObjectNumber, defaulting to 0.\n"); 686739fb1bSHervé Poussineau } 696739fb1bSHervé Poussineau 706739fb1bSHervé Poussineau TRACE("Found %lu devices\n", ulMaxObjectNumber + 1); 716739fb1bSHervé Poussineau 726739fb1bSHervé Poussineau /* Loop through all adapters */ 736739fb1bSHervé Poussineau for (iDevNum = 0; iDevNum <= ulMaxObjectNumber; iDevNum++) 746739fb1bSHervé Poussineau { 756739fb1bSHervé Poussineau /* Create the adapter's key name */ 766739fb1bSHervé Poussineau swprintf(awcDeviceName, L"\\Device\\Video%lu", iDevNum); 77c05a45e1SOleg Dubinskiy 78c05a45e1SOleg Dubinskiy /* Create the display device name */ 79c05a45e1SOleg Dubinskiy swprintf(awcWinDeviceName, L"\\\\.\\DISPLAY%lu", iDevNum + 1); 80c05a45e1SOleg Dubinskiy RtlInitUnicodeString(&ustrDeviceName, awcWinDeviceName); 8177e891b8STimo Kreuzer 8277e891b8STimo Kreuzer /* Check if the device exists already */ 83*ded971c4SHervé Poussineau pGraphicsDevice = EngpFindGraphicsDevice(&ustrDeviceName, iDevNum); 8477e891b8STimo Kreuzer if (pGraphicsDevice != NULL) 8577e891b8STimo Kreuzer { 8677e891b8STimo Kreuzer continue; 8777e891b8STimo Kreuzer } 886739fb1bSHervé Poussineau 896739fb1bSHervé Poussineau /* Read the reg key name */ 906739fb1bSHervé Poussineau cbValue = sizeof(awcBuffer); 916739fb1bSHervé Poussineau Status = RegQueryValue(hkey, awcDeviceName, REG_SZ, awcBuffer, &cbValue); 926739fb1bSHervé Poussineau if (!NT_SUCCESS(Status)) 936739fb1bSHervé Poussineau { 946739fb1bSHervé Poussineau ERR("failed to query the registry path:0x%lx\n", Status); 956739fb1bSHervé Poussineau continue; 966739fb1bSHervé Poussineau } 976739fb1bSHervé Poussineau 986739fb1bSHervé Poussineau /* Initialize the driver for this device */ 996739fb1bSHervé Poussineau pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer); 1006739fb1bSHervé Poussineau if (!pGraphicsDevice) continue; 1016739fb1bSHervé Poussineau 1026739fb1bSHervé Poussineau /* Check if this is a VGA compatible adapter */ 1036739fb1bSHervé Poussineau if (pGraphicsDevice->StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE) 1046739fb1bSHervé Poussineau { 1056739fb1bSHervé Poussineau /* Save this as the VGA adapter */ 1066739fb1bSHervé Poussineau if (!gpVgaGraphicsDevice) 10739d8a822STimo Kreuzer { 1086739fb1bSHervé Poussineau gpVgaGraphicsDevice = pGraphicsDevice; 1096739fb1bSHervé Poussineau TRACE("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice); 1106739fb1bSHervé Poussineau } 11139d8a822STimo Kreuzer } 11239d8a822STimo Kreuzer 1136739fb1bSHervé Poussineau /* Set the first one as primary device */ 1146739fb1bSHervé Poussineau if (!gpPrimaryGraphicsDevice) 11539d8a822STimo Kreuzer { 1166739fb1bSHervé Poussineau gpPrimaryGraphicsDevice = pGraphicsDevice; 1176739fb1bSHervé Poussineau TRACE("gpPrimaryGraphicsDevice = %p\n", gpPrimaryGraphicsDevice); 1186739fb1bSHervé Poussineau } 1196739fb1bSHervé Poussineau } 1206739fb1bSHervé Poussineau 1216739fb1bSHervé Poussineau /* Close the device map registry key */ 1226739fb1bSHervé Poussineau ZwClose(hkey); 1236739fb1bSHervé Poussineau 1246739fb1bSHervé Poussineau return STATUS_SUCCESS; 1256739fb1bSHervé Poussineau } 1266739fb1bSHervé Poussineau 127c2c66affSColin Finck BOOLEAN 128c2c66affSColin Finck EngpPopulateDeviceModeList( 129c2c66affSColin Finck _Inout_ PGRAPHICS_DEVICE pGraphicsDevice, 130c2c66affSColin Finck _In_ PDEVMODEW pdmDefault) 131c2c66affSColin Finck { 132c2c66affSColin Finck PDEVMODEINFO pdminfo; 1333cb1dd8aSHervé Poussineau PDEVMODEW pdm, pdmSelected; 13421ddeb76SHervé Poussineau ULONG i; 135c2c66affSColin Finck 136c2c66affSColin Finck ASSERT(pGraphicsDevice->pdevmodeInfo == NULL); 137c2c66affSColin Finck ASSERT(pGraphicsDevice->pDevModeList == NULL); 138c2c66affSColin Finck 1393cb1dd8aSHervé Poussineau if (!LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, pdmDefault, &pdmSelected, TRUE)) 140c2c66affSColin Finck { 1413cb1dd8aSHervé Poussineau ERR("LDEVOBJ_bProbeAndCaptureDevmode() failed\n"); 142c2c66affSColin Finck return FALSE; 143c2c66affSColin Finck } 144c2c66affSColin Finck 145c2c66affSColin Finck /* Loop through all DEVMODEINFOs */ 146c2c66affSColin Finck for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0; 147c2c66affSColin Finck pdminfo; 148c2c66affSColin Finck pdminfo = pdminfo->pdmiNext) 149c2c66affSColin Finck { 150c2c66affSColin Finck /* Loop through the DEVMODEs */ 15121ddeb76SHervé Poussineau for (i = 0; i < pGraphicsDevice->cDevModes; i++) 152c2c66affSColin Finck { 15321ddeb76SHervé Poussineau pdm = pGraphicsDevice->pDevModeList[i].pdm; 15421ddeb76SHervé Poussineau 1553cb1dd8aSHervé Poussineau /* Compare with the selected entry */ 1563cb1dd8aSHervé Poussineau if (pdm->dmSize == pdmSelected->dmSize && 1573cb1dd8aSHervé Poussineau RtlCompareMemory(pdm, pdmSelected, pdm->dmSize) == pdm->dmSize) 158c2c66affSColin Finck { 159c2c66affSColin Finck pGraphicsDevice->iDefaultMode = i; 160c2c66affSColin Finck pGraphicsDevice->iCurrentMode = i; 161c2c66affSColin Finck TRACE("Found default entry: %lu '%ls'\n", i, pdm->dmDeviceName); 1623cb1dd8aSHervé Poussineau break; 163c2c66affSColin Finck } 164c2c66affSColin Finck } 165c2c66affSColin Finck } 166c2c66affSColin Finck return TRUE; 167c2c66affSColin Finck } 168c2c66affSColin Finck 1690ad65796SHermès Bélusca-Maïto extern VOID 1700ad65796SHermès Bélusca-Maïto UserRefreshDisplay(IN PPDEVOBJ ppdev); 1710ad65796SHermès Bélusca-Maïto 1720ad65796SHermès Bélusca-Maïto // PVIDEO_WIN32K_CALLOUT 1730ad65796SHermès Bélusca-Maïto VOID 1740ad65796SHermès Bélusca-Maïto NTAPI 1750ad65796SHermès Bélusca-Maïto VideoPortCallout( 1760ad65796SHermès Bélusca-Maïto _In_ PVOID Params) 1770ad65796SHermès Bélusca-Maïto { 1780ad65796SHermès Bélusca-Maïto /* 1790ad65796SHermès Bélusca-Maïto * IMPORTANT NOTICE!! On Windows XP/2003 this function triggers the creation of 1800ad65796SHermès Bélusca-Maïto * a specific VideoPortCalloutThread() system thread using the same mechanism 1810ad65796SHermès Bélusca-Maïto * as the RIT/desktop/Ghost system threads. 1820ad65796SHermès Bélusca-Maïto */ 1830ad65796SHermès Bélusca-Maïto 1840ad65796SHermès Bélusca-Maïto PVIDEO_WIN32K_CALLBACKS_PARAMS CallbackParams = (PVIDEO_WIN32K_CALLBACKS_PARAMS)Params; 1850ad65796SHermès Bélusca-Maïto 1860ad65796SHermès Bélusca-Maïto TRACE("VideoPortCallout(0x%p, 0x%x)\n", 1870ad65796SHermès Bélusca-Maïto CallbackParams, CallbackParams ? CallbackParams->CalloutType : -1); 1880ad65796SHermès Bélusca-Maïto 1890ad65796SHermès Bélusca-Maïto if (!CallbackParams) 1900ad65796SHermès Bélusca-Maïto return; 1910ad65796SHermès Bélusca-Maïto 1920ad65796SHermès Bélusca-Maïto switch (CallbackParams->CalloutType) 1930ad65796SHermès Bélusca-Maïto { 1940ad65796SHermès Bélusca-Maïto case VideoFindAdapterCallout: 1950ad65796SHermès Bélusca-Maïto { 1960ad65796SHermès Bélusca-Maïto TRACE("VideoPortCallout: VideoFindAdapterCallout called - Param = %s\n", 1970ad65796SHermès Bélusca-Maïto CallbackParams->Param ? "TRUE" : "FALSE"); 1980ad65796SHermès Bélusca-Maïto if (CallbackParams->Param == TRUE) 1990ad65796SHermès Bélusca-Maïto { 2000ad65796SHermès Bélusca-Maïto /* Re-enable the display */ 2010ad65796SHermès Bélusca-Maïto UserRefreshDisplay(gppdevPrimary); 2020ad65796SHermès Bélusca-Maïto } 2030ad65796SHermès Bélusca-Maïto else 2040ad65796SHermès Bélusca-Maïto { 2050ad65796SHermès Bélusca-Maïto /* Disable the display */ 2060ad65796SHermès Bélusca-Maïto NOTHING; // Nothing to do for the moment... 2070ad65796SHermès Bélusca-Maïto } 2080ad65796SHermès Bélusca-Maïto 2090ad65796SHermès Bélusca-Maïto CallbackParams->Status = STATUS_SUCCESS; 2100ad65796SHermès Bélusca-Maïto break; 2110ad65796SHermès Bélusca-Maïto } 2120ad65796SHermès Bélusca-Maïto 2130ad65796SHermès Bélusca-Maïto case VideoPowerNotifyCallout: 2140ad65796SHermès Bélusca-Maïto case VideoDisplaySwitchCallout: 2150ad65796SHermès Bélusca-Maïto case VideoEnumChildPdoNotifyCallout: 2160ad65796SHermès Bélusca-Maïto case VideoWakeupCallout: 2170ad65796SHermès Bélusca-Maïto case VideoChangeDisplaySettingsCallout: 2180ad65796SHermès Bélusca-Maïto case VideoPnpNotifyCallout: 2190ad65796SHermès Bélusca-Maïto case VideoDxgkDisplaySwitchCallout: 2200ad65796SHermès Bélusca-Maïto case VideoDxgkMonitorEventCallout: 2210ad65796SHermès Bélusca-Maïto case VideoDxgkFindAdapterTdrCallout: 2220ad65796SHermès Bélusca-Maïto ERR("VideoPortCallout: CalloutType 0x%x is UNIMPLEMENTED!\n", CallbackParams->CalloutType); 2230ad65796SHermès Bélusca-Maïto CallbackParams->Status = STATUS_NOT_IMPLEMENTED; 2240ad65796SHermès Bélusca-Maïto break; 2250ad65796SHermès Bélusca-Maïto 2260ad65796SHermès Bélusca-Maïto default: 2270ad65796SHermès Bélusca-Maïto ERR("VideoPortCallout: Unknown CalloutType 0x%x\n", CallbackParams->CalloutType); 2280ad65796SHermès Bélusca-Maïto CallbackParams->Status = STATUS_UNSUCCESSFUL; 2290ad65796SHermès Bélusca-Maïto break; 2300ad65796SHermès Bélusca-Maïto } 2310ad65796SHermès Bélusca-Maïto } 2320ad65796SHermès Bélusca-Maïto 233c2c66affSColin Finck PGRAPHICS_DEVICE 234c2c66affSColin Finck NTAPI 235c2c66affSColin Finck EngpRegisterGraphicsDevice( 236c2c66affSColin Finck _In_ PUNICODE_STRING pustrDeviceName, 237c2c66affSColin Finck _In_ PUNICODE_STRING pustrDiplayDrivers, 238c2c66affSColin Finck _In_ PUNICODE_STRING pustrDescription, 239c2c66affSColin Finck _In_ PDEVMODEW pdmDefault) 240c2c66affSColin Finck { 241c2c66affSColin Finck PGRAPHICS_DEVICE pGraphicsDevice; 242c2c66affSColin Finck PDEVICE_OBJECT pDeviceObject; 243c2c66affSColin Finck PFILE_OBJECT pFileObject; 244c2c66affSColin Finck NTSTATUS Status; 2450ad65796SHermès Bélusca-Maïto VIDEO_WIN32K_CALLBACKS Win32kCallbacks; 2460ad65796SHermès Bélusca-Maïto ULONG ulReturn; 247c2c66affSColin Finck PWSTR pwsz; 248c2c66affSColin Finck ULONG cj; 249c2c66affSColin Finck 250c2c66affSColin Finck TRACE("EngpRegisterGraphicsDevice(%wZ)\n", pustrDeviceName); 251c2c66affSColin Finck 252c2c66affSColin Finck /* Allocate a GRAPHICS_DEVICE structure */ 253c2c66affSColin Finck pGraphicsDevice = ExAllocatePoolWithTag(PagedPool, 254c2c66affSColin Finck sizeof(GRAPHICS_DEVICE), 255c2c66affSColin Finck GDITAG_GDEVICE); 256c2c66affSColin Finck if (!pGraphicsDevice) 257c2c66affSColin Finck { 258c2c66affSColin Finck ERR("ExAllocatePoolWithTag failed\n"); 259c2c66affSColin Finck return NULL; 260c2c66affSColin Finck } 261c2c66affSColin Finck 2620ad90f83SHermès Bélusca-Maïto /* Try to open and enable the device */ 263c2c66affSColin Finck Status = IoGetDeviceObjectPointer(pustrDeviceName, 264c2c66affSColin Finck FILE_READ_DATA | FILE_WRITE_DATA, 265c2c66affSColin Finck &pFileObject, 266c2c66affSColin Finck &pDeviceObject); 267c2c66affSColin Finck if (!NT_SUCCESS(Status)) 268c2c66affSColin Finck { 2690ad90f83SHermès Bélusca-Maïto ERR("Could not open device %wZ, 0x%lx\n", pustrDeviceName, Status); 270c2c66affSColin Finck ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); 271c2c66affSColin Finck return NULL; 272c2c66affSColin Finck } 273c2c66affSColin Finck 274c2c66affSColin Finck /* Copy the device and file object pointers */ 275c2c66affSColin Finck pGraphicsDevice->DeviceObject = pDeviceObject; 276c2c66affSColin Finck pGraphicsDevice->FileObject = pFileObject; 277c2c66affSColin Finck 2780ad65796SHermès Bélusca-Maïto /* Initialize and register the device with videoprt for Win32k callbacks */ 2790ad65796SHermès Bélusca-Maïto Win32kCallbacks.PhysDisp = pGraphicsDevice; 2800ad65796SHermès Bélusca-Maïto Win32kCallbacks.Callout = VideoPortCallout; 2810ad65796SHermès Bélusca-Maïto // Reset the data being returned prior to the call. 2820ad65796SHermès Bélusca-Maïto Win32kCallbacks.bACPI = FALSE; 2830ad65796SHermès Bélusca-Maïto Win32kCallbacks.pPhysDeviceObject = NULL; 2840ad65796SHermès Bélusca-Maïto Win32kCallbacks.DualviewFlags = 0; 2850ad65796SHermès Bélusca-Maïto Status = (NTSTATUS)EngDeviceIoControl((HANDLE)pDeviceObject, 2860ad65796SHermès Bélusca-Maïto IOCTL_VIDEO_INIT_WIN32K_CALLBACKS, 2870ad65796SHermès Bélusca-Maïto &Win32kCallbacks, 2880ad65796SHermès Bélusca-Maïto sizeof(Win32kCallbacks), 2890ad65796SHermès Bélusca-Maïto &Win32kCallbacks, 2900ad65796SHermès Bélusca-Maïto sizeof(Win32kCallbacks), 2910ad65796SHermès Bélusca-Maïto &ulReturn); 2920ad65796SHermès Bélusca-Maïto if (Status != ERROR_SUCCESS) 2930ad65796SHermès Bélusca-Maïto { 2940ad65796SHermès Bélusca-Maïto ERR("EngDeviceIoControl(0x%p, IOCTL_VIDEO_INIT_WIN32K_CALLBACKS) failed, Status 0x%lx\n", 2950ad65796SHermès Bélusca-Maïto pDeviceObject, Status); 2960ad65796SHermès Bélusca-Maïto } 2970ad65796SHermès Bélusca-Maïto // TODO: Set flags according to the results. 2980ad65796SHermès Bélusca-Maïto // if (Win32kCallbacks.bACPI) 2990ad65796SHermès Bélusca-Maïto // if (Win32kCallbacks.DualviewFlags & ???) 3000ad65796SHermès Bélusca-Maïto // Win32kCallbacks.pPhysDeviceObject; 3010ad65796SHermès Bélusca-Maïto 302acf689a9SHermès Bélusca-Maïto /* Copy the device name */ 303c2c66affSColin Finck RtlStringCbCopyNW(pGraphicsDevice->szNtDeviceName, 304c2c66affSColin Finck sizeof(pGraphicsDevice->szNtDeviceName), 305c2c66affSColin Finck pustrDeviceName->Buffer, 306c2c66affSColin Finck pustrDeviceName->Length); 307c2c66affSColin Finck 308acf689a9SHermès Bélusca-Maïto /* Create a Win32 device name (FIXME: virtual devices!) */ 309acf689a9SHermès Bélusca-Maïto RtlStringCbPrintfW(pGraphicsDevice->szWinDeviceName, 310acf689a9SHermès Bélusca-Maïto sizeof(pGraphicsDevice->szWinDeviceName), 311acf689a9SHermès Bélusca-Maïto L"\\\\.\\DISPLAY%d", 312acf689a9SHermès Bélusca-Maïto (int)giDevNum); 313c2c66affSColin Finck 314c2c66affSColin Finck /* Allocate a buffer for the strings */ 315c2c66affSColin Finck cj = pustrDiplayDrivers->Length + pustrDescription->Length + sizeof(WCHAR); 316c2c66affSColin Finck pwsz = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_DRVSUP); 317c2c66affSColin Finck if (!pwsz) 318c2c66affSColin Finck { 319c2c66affSColin Finck ERR("Could not allocate string buffer\n"); 320c2c66affSColin Finck ASSERT(FALSE); // FIXME 321c2c66affSColin Finck ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); 322c2c66affSColin Finck return NULL; 323c2c66affSColin Finck } 324c2c66affSColin Finck 3250ad90f83SHermès Bélusca-Maïto /* Copy the display driver names */ 326c2c66affSColin Finck pGraphicsDevice->pDiplayDrivers = pwsz; 327c2c66affSColin Finck RtlCopyMemory(pGraphicsDevice->pDiplayDrivers, 328c2c66affSColin Finck pustrDiplayDrivers->Buffer, 329c2c66affSColin Finck pustrDiplayDrivers->Length); 330c2c66affSColin Finck 3310ad90f83SHermès Bélusca-Maïto /* Copy the description */ 332c2c66affSColin Finck pGraphicsDevice->pwszDescription = pwsz + pustrDiplayDrivers->Length / sizeof(WCHAR); 333c2c66affSColin Finck RtlCopyMemory(pGraphicsDevice->pwszDescription, 334c2c66affSColin Finck pustrDescription->Buffer, 335c2c66affSColin Finck pustrDescription->Length); 336c2c66affSColin Finck pGraphicsDevice->pwszDescription[pustrDescription->Length/sizeof(WCHAR)] = 0; 337c2c66affSColin Finck 338c2c66affSColin Finck /* Initialize the pdevmodeInfo list and default index */ 339c2c66affSColin Finck pGraphicsDevice->pdevmodeInfo = NULL; 340c2c66affSColin Finck pGraphicsDevice->iDefaultMode = 0; 341c2c66affSColin Finck pGraphicsDevice->iCurrentMode = 0; 342c2c66affSColin Finck 343c2c66affSColin Finck // FIXME: initialize state flags 344c2c66affSColin Finck pGraphicsDevice->StateFlags = 0; 345c2c66affSColin Finck 346c2c66affSColin Finck /* Create the mode list */ 347c2c66affSColin Finck pGraphicsDevice->pDevModeList = NULL; 348c2c66affSColin Finck if (!EngpPopulateDeviceModeList(pGraphicsDevice, pdmDefault)) 349c2c66affSColin Finck { 350c2c66affSColin Finck ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); 351c2c66affSColin Finck return NULL; 352c2c66affSColin Finck } 353c2c66affSColin Finck 354c2c66affSColin Finck /* Lock loader */ 355c2c66affSColin Finck EngAcquireSemaphore(ghsemGraphicsDeviceList); 356c2c66affSColin Finck 357c2c66affSColin Finck /* Insert the device into the global list */ 358c2c66affSColin Finck pGraphicsDevice->pNextGraphicsDevice = NULL; 359c2c66affSColin Finck if (gpGraphicsDeviceLast) 360c2c66affSColin Finck gpGraphicsDeviceLast->pNextGraphicsDevice = pGraphicsDevice; 361c2c66affSColin Finck gpGraphicsDeviceLast = pGraphicsDevice; 362c2c66affSColin Finck if (!gpGraphicsDeviceFirst) 363c2c66affSColin Finck gpGraphicsDeviceFirst = pGraphicsDevice; 364c2c66affSColin Finck 3650ad90f83SHermès Bélusca-Maïto /* Increment the device number */ 366c2c66affSColin Finck giDevNum++; 367c2c66affSColin Finck 368c2c66affSColin Finck /* Unlock loader */ 369c2c66affSColin Finck EngReleaseSemaphore(ghsemGraphicsDeviceList); 370c2c66affSColin Finck TRACE("Prepared %lu modes for %ls\n", pGraphicsDevice->cDevModes, pGraphicsDevice->pwszDescription); 371c2c66affSColin Finck 3720f6b9664SHervé Poussineau /* HACK: already in graphic mode; display wallpaper on this new display */ 3730f6b9664SHervé Poussineau if (ScreenDeviceContext) 3740f6b9664SHervé Poussineau { 3750f6b9664SHervé Poussineau UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY"); 3760f6b9664SHervé Poussineau UNICODE_STRING DisplayName; 3770f6b9664SHervé Poussineau HDC hdc; 3780f6b9664SHervé Poussineau RtlInitUnicodeString(&DisplayName, pGraphicsDevice->szWinDeviceName); 3790f6b9664SHervé Poussineau hdc = IntGdiCreateDC(&DriverName, &DisplayName, NULL, NULL, FALSE); 3800f6b9664SHervé Poussineau IntPaintDesktop(hdc); 3810f6b9664SHervé Poussineau } 3820f6b9664SHervé Poussineau 383c2c66affSColin Finck return pGraphicsDevice; 384c2c66affSColin Finck } 385c2c66affSColin Finck 386c2c66affSColin Finck PGRAPHICS_DEVICE 387c2c66affSColin Finck NTAPI 388c2c66affSColin Finck EngpFindGraphicsDevice( 389c2c66affSColin Finck _In_opt_ PUNICODE_STRING pustrDevice, 390*ded971c4SHervé Poussineau _In_ ULONG iDevNum) 391c2c66affSColin Finck { 392c2c66affSColin Finck UNICODE_STRING ustrCurrent; 393c2c66affSColin Finck PGRAPHICS_DEVICE pGraphicsDevice; 394c2c66affSColin Finck ULONG i; 395*ded971c4SHervé Poussineau TRACE("EngpFindGraphicsDevice('%wZ', %lu)\n", 396*ded971c4SHervé Poussineau pustrDevice, iDevNum); 397c2c66affSColin Finck 398c2c66affSColin Finck /* Lock list */ 399c2c66affSColin Finck EngAcquireSemaphore(ghsemGraphicsDeviceList); 400c2c66affSColin Finck 401c2c66affSColin Finck if (pustrDevice && pustrDevice->Buffer) 402c2c66affSColin Finck { 403c2c66affSColin Finck /* Loop through the list of devices */ 404c2c66affSColin Finck for (pGraphicsDevice = gpGraphicsDeviceFirst; 405c2c66affSColin Finck pGraphicsDevice; 406c2c66affSColin Finck pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice) 407c2c66affSColin Finck { 408c2c66affSColin Finck /* Compare the device name */ 409c2c66affSColin Finck RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName); 410c2c66affSColin Finck if (RtlEqualUnicodeString(&ustrCurrent, pustrDevice, FALSE)) 411c2c66affSColin Finck { 412c2c66affSColin Finck break; 413c2c66affSColin Finck } 414c2c66affSColin Finck } 415c2c66affSColin Finck } 416c2c66affSColin Finck else 417c2c66affSColin Finck { 418c2c66affSColin Finck /* Loop through the list of devices */ 419c2c66affSColin Finck for (pGraphicsDevice = gpGraphicsDeviceFirst, i = 0; 420c2c66affSColin Finck pGraphicsDevice && i < iDevNum; 421c2c66affSColin Finck pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice, i++); 422c2c66affSColin Finck } 423c2c66affSColin Finck 424c2c66affSColin Finck /* Unlock list */ 425c2c66affSColin Finck EngReleaseSemaphore(ghsemGraphicsDeviceList); 426c2c66affSColin Finck 427c2c66affSColin Finck return pGraphicsDevice; 428c2c66affSColin Finck } 429c2c66affSColin Finck 430c2c66affSColin Finck static 431c2c66affSColin Finck NTSTATUS 432c2c66affSColin Finck EngpFileIoRequest( 433c2c66affSColin Finck _In_ PFILE_OBJECT pFileObject, 434c2c66affSColin Finck _In_ ULONG ulMajorFunction, 435c2c66affSColin Finck _In_reads_(nBufferSize) PVOID lpBuffer, 436c2c66affSColin Finck _In_ SIZE_T nBufferSize, 437c2c66affSColin Finck _In_ ULONGLONG ullStartOffset, 438c2c66affSColin Finck _Out_ PULONG_PTR lpInformation) 439c2c66affSColin Finck { 440c2c66affSColin Finck PDEVICE_OBJECT pDeviceObject; 441c2c66affSColin Finck KEVENT Event; 442c2c66affSColin Finck PIRP pIrp; 443c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 444c2c66affSColin Finck NTSTATUS Status; 445c2c66affSColin Finck LARGE_INTEGER liStartOffset; 446c2c66affSColin Finck 447c2c66affSColin Finck /* Get corresponding device object */ 448c2c66affSColin Finck pDeviceObject = IoGetRelatedDeviceObject(pFileObject); 449c2c66affSColin Finck if (!pDeviceObject) 450c2c66affSColin Finck { 451c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 452c2c66affSColin Finck } 453c2c66affSColin Finck 454c2c66affSColin Finck /* Initialize an event */ 455c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 456c2c66affSColin Finck 457c2c66affSColin Finck /* Build IRP */ 458c2c66affSColin Finck liStartOffset.QuadPart = ullStartOffset; 459c2c66affSColin Finck pIrp = IoBuildSynchronousFsdRequest(ulMajorFunction, 460c2c66affSColin Finck pDeviceObject, 461c2c66affSColin Finck lpBuffer, 462c2c66affSColin Finck (ULONG)nBufferSize, 463c2c66affSColin Finck &liStartOffset, 464c2c66affSColin Finck &Event, 465c2c66affSColin Finck &Iosb); 466c2c66affSColin Finck if (!pIrp) 467c2c66affSColin Finck { 468c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 469c2c66affSColin Finck } 470c2c66affSColin Finck 471c2c66affSColin Finck /* Call the driver */ 472c2c66affSColin Finck Status = IoCallDriver(pDeviceObject, pIrp); 473c2c66affSColin Finck 474c2c66affSColin Finck /* Wait if neccessary */ 475c2c66affSColin Finck if (STATUS_PENDING == Status) 476c2c66affSColin Finck { 477c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0); 478c2c66affSColin Finck Status = Iosb.Status; 479c2c66affSColin Finck } 480c2c66affSColin Finck 481c2c66affSColin Finck /* Return information to the caller about the operation. */ 482c2c66affSColin Finck *lpInformation = Iosb.Information; 483c2c66affSColin Finck 484c2c66affSColin Finck /* Return NTSTATUS */ 485c2c66affSColin Finck return Status; 486c2c66affSColin Finck } 487c2c66affSColin Finck 488c2c66affSColin Finck VOID 489c2c66affSColin Finck APIENTRY 490c2c66affSColin Finck EngFileWrite( 491c2c66affSColin Finck _In_ PFILE_OBJECT pFileObject, 492c2c66affSColin Finck _In_reads_(nLength) PVOID lpBuffer, 493c2c66affSColin Finck _In_ SIZE_T nLength, 494c2c66affSColin Finck _Out_ PSIZE_T lpBytesWritten) 495c2c66affSColin Finck { 496c2c66affSColin Finck NTSTATUS status; 497c2c66affSColin Finck 498c2c66affSColin Finck status = EngpFileIoRequest(pFileObject, 499c2c66affSColin Finck IRP_MJ_WRITE, 500c2c66affSColin Finck lpBuffer, 501c2c66affSColin Finck nLength, 502c2c66affSColin Finck 0, 503c2c66affSColin Finck lpBytesWritten); 504c2c66affSColin Finck if (!NT_SUCCESS(status)) 505c2c66affSColin Finck { 506c2c66affSColin Finck *lpBytesWritten = 0; 507c2c66affSColin Finck } 508c2c66affSColin Finck } 509c2c66affSColin Finck 510c2c66affSColin Finck _Success_(return>=0) 511c2c66affSColin Finck NTSTATUS 512c2c66affSColin Finck APIENTRY 513c2c66affSColin Finck EngFileIoControl( 514c2c66affSColin Finck _In_ PFILE_OBJECT pFileObject, 515c2c66affSColin Finck _In_ DWORD dwIoControlCode, 516c2c66affSColin Finck _In_reads_(nInBufferSize) PVOID lpInBuffer, 517c2c66affSColin Finck _In_ SIZE_T nInBufferSize, 518c2c66affSColin Finck _Out_writes_(nOutBufferSize) PVOID lpOutBuffer, 519c2c66affSColin Finck _In_ SIZE_T nOutBufferSize, 520c2c66affSColin Finck _Out_ PULONG_PTR lpInformation) 521c2c66affSColin Finck { 522c2c66affSColin Finck PDEVICE_OBJECT pDeviceObject; 523c2c66affSColin Finck KEVENT Event; 524c2c66affSColin Finck PIRP pIrp; 525c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 526c2c66affSColin Finck NTSTATUS Status; 527c2c66affSColin Finck 528c2c66affSColin Finck /* Get corresponding device object */ 529c2c66affSColin Finck pDeviceObject = IoGetRelatedDeviceObject(pFileObject); 530c2c66affSColin Finck if (!pDeviceObject) 531c2c66affSColin Finck { 532c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 533c2c66affSColin Finck } 534c2c66affSColin Finck 535c2c66affSColin Finck /* Initialize an event */ 536c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 537c2c66affSColin Finck 538c2c66affSColin Finck /* Build IO control IRP */ 539c2c66affSColin Finck pIrp = IoBuildDeviceIoControlRequest(dwIoControlCode, 540c2c66affSColin Finck pDeviceObject, 541c2c66affSColin Finck lpInBuffer, 542c2c66affSColin Finck (ULONG)nInBufferSize, 543c2c66affSColin Finck lpOutBuffer, 544c2c66affSColin Finck (ULONG)nOutBufferSize, 545c2c66affSColin Finck FALSE, 546c2c66affSColin Finck &Event, 547c2c66affSColin Finck &Iosb); 548c2c66affSColin Finck if (!pIrp) 549c2c66affSColin Finck { 550c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 551c2c66affSColin Finck } 552c2c66affSColin Finck 553c2c66affSColin Finck /* Call the driver */ 554c2c66affSColin Finck Status = IoCallDriver(pDeviceObject, pIrp); 555c2c66affSColin Finck 556c2c66affSColin Finck /* Wait if neccessary */ 557c2c66affSColin Finck if (Status == STATUS_PENDING) 558c2c66affSColin Finck { 559c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0); 560c2c66affSColin Finck Status = Iosb.Status; 561c2c66affSColin Finck } 562c2c66affSColin Finck 563c2c66affSColin Finck /* Return information to the caller about the operation. */ 564c2c66affSColin Finck *lpInformation = Iosb.Information; 565c2c66affSColin Finck 566c2c66affSColin Finck /* This function returns NTSTATUS */ 567c2c66affSColin Finck return Status; 568c2c66affSColin Finck } 569c2c66affSColin Finck 570c2c66affSColin Finck /* 571c2c66affSColin Finck * @implemented 572c2c66affSColin Finck */ 573c2c66affSColin Finck _Success_(return==0) 574c2c66affSColin Finck DWORD 575c2c66affSColin Finck APIENTRY 576c2c66affSColin Finck EngDeviceIoControl( 577c2c66affSColin Finck _In_ HANDLE hDevice, 578c2c66affSColin Finck _In_ DWORD dwIoControlCode, 579c2c66affSColin Finck _In_reads_bytes_opt_(cjInBufferSize) LPVOID lpInBuffer, 580c2c66affSColin Finck _In_ DWORD cjInBufferSize, 581c2c66affSColin Finck _Out_writes_bytes_opt_(cjOutBufferSize) LPVOID lpOutBuffer, 582c2c66affSColin Finck _In_ DWORD cjOutBufferSize, 583c2c66affSColin Finck _Out_ LPDWORD lpBytesReturned) 584c2c66affSColin Finck { 585c2c66affSColin Finck PIRP Irp; 586c2c66affSColin Finck NTSTATUS Status; 587c2c66affSColin Finck KEVENT Event; 588c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 589c2c66affSColin Finck PDEVICE_OBJECT DeviceObject; 590c2c66affSColin Finck 591c2c66affSColin Finck TRACE("EngDeviceIoControl() called\n"); 592c2c66affSColin Finck 59301b580d8SPierre Schweitzer if (!hDevice) 59401b580d8SPierre Schweitzer { 59501b580d8SPierre Schweitzer return ERROR_INVALID_HANDLE; 59601b580d8SPierre Schweitzer } 59701b580d8SPierre Schweitzer 598c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 599c2c66affSColin Finck 600c2c66affSColin Finck DeviceObject = (PDEVICE_OBJECT) hDevice; 601c2c66affSColin Finck 602c2c66affSColin Finck Irp = IoBuildDeviceIoControlRequest(dwIoControlCode, 603c2c66affSColin Finck DeviceObject, 604c2c66affSColin Finck lpInBuffer, 605c2c66affSColin Finck cjInBufferSize, 606c2c66affSColin Finck lpOutBuffer, 607c2c66affSColin Finck cjOutBufferSize, 608c2c66affSColin Finck FALSE, 609c2c66affSColin Finck &Event, 610c2c66affSColin Finck &Iosb); 611c2c66affSColin Finck if (!Irp) return ERROR_NOT_ENOUGH_MEMORY; 612c2c66affSColin Finck 613c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 614c2c66affSColin Finck 615c2c66affSColin Finck if (Status == STATUS_PENDING) 616c2c66affSColin Finck { 617c2c66affSColin Finck (VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0); 618c2c66affSColin Finck Status = Iosb.Status; 619c2c66affSColin Finck } 620c2c66affSColin Finck 621c2c66affSColin Finck TRACE("EngDeviceIoControl(): Returning %X/%X\n", Iosb.Status, 622c2c66affSColin Finck Iosb.Information); 623c2c66affSColin Finck 624c2c66affSColin Finck /* Return information to the caller about the operation. */ 625c2c66affSColin Finck *lpBytesReturned = (DWORD)Iosb.Information; 626c2c66affSColin Finck 627c2c66affSColin Finck /* Convert NT status values to win32 error codes. */ 628c2c66affSColin Finck switch (Status) 629c2c66affSColin Finck { 630c2c66affSColin Finck case STATUS_INSUFFICIENT_RESOURCES: 631c2c66affSColin Finck return ERROR_NOT_ENOUGH_MEMORY; 632c2c66affSColin Finck 633c2c66affSColin Finck case STATUS_BUFFER_OVERFLOW: 634c2c66affSColin Finck return ERROR_MORE_DATA; 635c2c66affSColin Finck 636c2c66affSColin Finck case STATUS_NOT_IMPLEMENTED: 637c2c66affSColin Finck return ERROR_INVALID_FUNCTION; 638c2c66affSColin Finck 639c2c66affSColin Finck case STATUS_INVALID_PARAMETER: 640c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 641c2c66affSColin Finck 642c2c66affSColin Finck case STATUS_BUFFER_TOO_SMALL: 643c2c66affSColin Finck return ERROR_INSUFFICIENT_BUFFER; 644c2c66affSColin Finck 645c2c66affSColin Finck case STATUS_DEVICE_DOES_NOT_EXIST: 646c2c66affSColin Finck return ERROR_DEV_NOT_EXIST; 647c2c66affSColin Finck 648c2c66affSColin Finck case STATUS_PENDING: 649c2c66affSColin Finck return ERROR_IO_PENDING; 650c2c66affSColin Finck } 651c2c66affSColin Finck 652c2c66affSColin Finck return Status; 653c2c66affSColin Finck } 654c2c66affSColin Finck 655c2c66affSColin Finck /* EOF */ 656