* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Video initialization and display settings
- * FILE: subsystems/win32/win32k/ntuser/display.c
+ * FILE: win32ss/user/ntuser/display.c
* PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
DBG_DEFAULT_CHANNEL(UserDisplay);
BOOL gbBaseVideo = 0;
+static PPROCESSINFO gpFullscreen = NULL;
static const PWCHAR KEY_VIDEO = L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
DEVMODEW dmDefault;
DWORD dwVga;
- ERR("InitDisplayDriver(%S, %S);\n",
- pwszDeviceName, pwszRegKey);
+ TRACE("InitDisplayDriver(%S, %S);\n",
+ pwszDeviceName, pwszRegKey);
/* Open the driver's registry key */
Status = RegOpenKey(pwszRegKey, &hkey);
NTSTATUS
NTAPI
-InitVideo()
+InitVideo(VOID)
{
ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0;
WCHAR awcDeviceName[20];
Status = RegOpenKey(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control", &hkey);
if (NT_SUCCESS(Status))
{
- cbValue = 256;
+ cbValue = sizeof(awcBuffer);
Status = RegQueryValue(hkey, L"SystemStartOptions", REG_SZ, awcBuffer, &cbValue);
if (NT_SUCCESS(Status))
{
Status = RegOpenKey(KEY_VIDEO, &hkey);
if (!NT_SUCCESS(Status))
{
- ERR("Could not open device registry key!\n");
+ ERR("Could not open HARDWARE\\DEVICEMAP\\VIDEO registry key:0x%lx\n", Status);
return Status;
}
/* Read the name of the VGA adapter */
- cbValue = 20;
+ cbValue = sizeof(awcDeviceName);
Status = RegQueryValue(hkey, L"VgaCompatible", REG_SZ, awcDeviceName, &cbValue);
if (NT_SUCCESS(Status))
{
- iVGACompatible = _wtoi(&awcDeviceName[13]);
- ERR("VGA adapter = %ld\n", iVGACompatible);
+ iVGACompatible = _wtoi(&awcDeviceName[sizeof("\\Device\\Video")-1]);
+ ERR("VGA adapter = %lu\n", iVGACompatible);
}
/* Get the maximum mumber of adapters */
ERR("Could not read MaxObjectNumber, defaulting to 0.\n");
}
- TRACE("Found %ld devices\n", ulMaxObjectNumber + 1);
+ TRACE("Found %lu devices\n", ulMaxObjectNumber + 1);
/* Loop through all adapters */
for (iDevNum = 0; iDevNum <= ulMaxObjectNumber; iDevNum++)
DISPLAY_DEVICEW dispdev;
NTSTATUS Status;
- TRACE("Enter NtUserEnumDisplayDevices(%wZ, %ld)\n",
- pustrDevice, iDevNum);
+ TRACE("Enter NtUserEnumDisplayDevices(%wZ, %lu)\n",
+ pustrDevice, iDevNum);
dispdev.cb = sizeof(dispdev);
{
/* No device found */
ERR("No PDEV found!\n");
- return STATUS_UNSUCCESSFUL;
+ return STATUS_INVALID_PARAMETER_1;
}
*ppdm = ppdev->pdmwDev;
PGRAPHICS_DEVICE pGraphicsDevice;
PDEVMODEENTRY pdmentry;
ULONG i, iFoundMode;
+ PPDEVOBJ ppdev;
- TRACE("Enter UserEnumDisplaySettings('%wZ', %ld)\n",
- pustrDevice, iModeNum);
+ TRACE("Enter UserEnumDisplaySettings('%wZ', %lu)\n",
+ pustrDevice, iModeNum);
/* Ask GDI for the GRAPHICS_DEVICE */
pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, 0, 0);
+ ppdev = EngpGetPDEV(pustrDevice);
- if (!pGraphicsDevice)
+ if (!pGraphicsDevice || !ppdev)
{
/* No device found */
ERR("No device found!\n");
- return STATUS_UNSUCCESSFUL;
+ return STATUS_INVALID_PARAMETER_1;
}
- if (iModeNum >= pGraphicsDevice->cDevModes)
- return STATUS_NO_MORE_ENTRIES;
+ /* let's politely ask the driver for an updated mode list,
+ just in case there's something new in there (vbox) */
+
+ PDEVOBJ_vRefreshModeList(ppdev);
+ PDEVOBJ_vRelease(ppdev);
iFoundMode = 0;
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
}
/* Nothing was found */
- return STATUS_INVALID_PARAMETER;
+ return STATUS_INVALID_PARAMETER_2;
}
NTSTATUS
ULONG cbSize, cbExtra;
DEVMODEW dmReg, *pdm;
- TRACE("Enter NtUserEnumDisplaySettings(%wZ, %ld, %p, 0x%lx)\n",
- pustrDevice, iModeNum, lpDevMode, dwFlags);
+ TRACE("Enter NtUserEnumDisplaySettings(%wZ, %lu, %p, 0x%lx)\n",
+ pustrDevice, iModeNum, lpDevMode, dwFlags);
+
+ _SEH2_TRY
+ {
+ ProbeForRead(lpDevMode, sizeof(DEVMODEW), sizeof(UCHAR));
+
+ cbSize = lpDevMode->dmSize;
+ cbExtra = lpDevMode->dmDriverExtra;
+
+ ProbeForWrite(lpDevMode, cbSize + cbExtra, sizeof(UCHAR));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ if (lpDevMode->dmSize != sizeof(DEVMODEW))
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
if (pustrDevice)
{
_SEH2_TRY
{
/* Probe the UNICODE_STRING and the buffer */
- ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
- ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+ ProbeForReadUnicodeString(pustrDevice);
+
+ if (!pustrDevice->Length || !pustrDevice->Buffer)
+ ExRaiseStatus(STATUS_NO_MEMORY);
+
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, sizeof(UCHAR));
/* Copy the string */
RtlCopyUnicodeString(&ustrDevice, pustrDevice);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ _SEH2_YIELD(return STATUS_INVALID_PARAMETER_1);
}
- _SEH2_END
+ _SEH2_END;
pustrDevice = &ustrDevice;
- }
+ }
/* Acquire global USER lock */
UserEnterShared();
/* Get the registry settings */
Status = UserEnumRegistryDisplaySettings(pustrDevice, &dmReg);
pdm = &dmReg;
+ pdm->dmSize = sizeof(DEVMODEW);
}
else if (iModeNum == ENUM_CURRENT_SETTINGS)
{
/* Copy some information back */
_SEH2_TRY
{
- ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
- cbSize = lpDevMode->dmSize;
- cbExtra = lpDevMode->dmDriverExtra;
-
- ProbeForWrite(lpDevMode, cbSize + cbExtra, 1);
/* Output what we got */
RtlCopyMemory(lpDevMode, pdm, min(cbSize, pdm->dmSize));
return Status;
}
+VOID
+UserUpdateFullscreen(
+ DWORD flags)
+{
+ if (flags & CDS_FULLSCREEN)
+ gpFullscreen = gptiCurrent->ppi;
+ else
+ gpFullscreen = NULL;
+}
LONG
APIENTRY
UserChangeDisplaySettings(
PUNICODE_STRING pustrDevice,
LPDEVMODEW pdm,
- HWND hwnd,
DWORD flags,
LPVOID lParam)
{
HKEY hkey;
NTSTATUS Status;
PPDEVOBJ ppdev;
+ WORD OrigBC;
//PDESKTOP pdesk;
/* If no DEVMODE is given, use registry settings */
}
}
else if (pdm->dmSize < FIELD_OFFSET(DEVMODEW, dmFields))
- return DISP_CHANGE_BADMODE; /* This is what winXP SP3 returns */
+ {
+ return DISP_CHANGE_BADMODE; /* This is what WinXP SP3 returns */
+ }
else
+ {
dm = *pdm;
+ }
+
+ /* Save original bit count */
+ OrigBC = gpsi->BitCount;
/* Check params */
if ((dm.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT))
}
/* Fixup values */
- if(dm.dmBitsPerPel == 0 || !(dm.dmFields & DM_BITSPERPEL))
+ if (dm.dmBitsPerPel == 0 || !(dm.dmFields & DM_BITSPERPEL))
{
dm.dmBitsPerPel = ppdev->pdmwDev->dmBitsPerPel;
dm.dmFields |= DM_BITSPERPEL;
}
- if((dm.dmFields & DM_DISPLAYFREQUENCY) && (dm.dmDisplayFrequency == 0))
+ if ((dm.dmFields & DM_DISPLAYFREQUENCY) && (dm.dmDisplayFrequency == 0))
dm.dmDisplayFrequency = ppdev->pdmwDev->dmDisplayFrequency;
/* Look for the requested DEVMODE */
}
}
- /* Check if DEVMODE matches the current mode */
- if (pdm == ppdev->pdmwDev && !(flags & CDS_RESET))
- {
- ERR("DEVMODE matches, nothing to do\n");
- goto leave;
- }
-
/* Shall we apply the settings? */
if (!(flags & CDS_NORESET))
{
ULONG ulResult;
PVOID pvOldCursor;
+ TEXTMETRICW tmw;
/* Remove mouse pointer */
pvOldCursor = UserSetCursor(NULL, TRUE);
ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
/* Restore mouse pointer, no hooks called */
- UserSetCursor(pvOldCursor, TRUE);
+ pvOldCursor = UserSetCursor(pvOldCursor, TRUE);
+ ASSERT(pvOldCursor == NULL);
/* Check for failure */
if (!ulResult)
goto leave;
}
+ UserUpdateFullscreen(flags);
+
/* Update the system metrics */
InitMetrics();
- //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
-
/* Set new size of the monitor */
UserUpdateMonitorSize((HDEV)ppdev);
+ /* Update the SERVERINFO */
+ gpsi->dmLogPixels = ppdev->gdiinfo.ulLogPixelsY;
+ gpsi->Planes = ppdev->gdiinfo.cPlanes;
+ gpsi->BitsPixel = ppdev->gdiinfo.cBitsPixel;
+ gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel;
+ if (ppdev->gdiinfo.flRaster & RC_PALETTE)
+ {
+ gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
+ }
+ else
+ gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
+ // Font is realized and this dc was previously set to internal DC_ATTR.
+ gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar);
+ gpsi->tmSysFont = tmw;
+
/* Remove all cursor clipping */
UserClipCursor(NULL);
//IntHideDesktop(pdesk);
/* Send WM_DISPLAYCHANGE to all toplevel windows */
- co_IntSendMessageTimeout(HWND_BROADCAST,
- WM_DISPLAYCHANGE,
- (WPARAM)ppdev->gdiinfo.cBitsPixel,
- (LPARAM)(ppdev->gdiinfo.ulHorzRes + (ppdev->gdiinfo.ulVertRes << 16)),
- SMTO_NORMAL,
- 100,
- &ulResult);
+ UserSendNotifyMessage(HWND_BROADCAST,
+ WM_DISPLAYCHANGE,
+ gpsi->BitCount,
+ MAKELONG(gpsi->aiSysMet[SM_CXSCREEN], gpsi->aiSysMet[SM_CYSCREEN]));
+
+ ERR("BitCount New %d Orig %d ChkNew %d\n",gpsi->BitCount,OrigBC,ppdev->gdiinfo.cBitsPixel);
+
+ /* Not full screen and different bit count, send messages */
+ if (!(flags & CDS_FULLSCREEN) &&
+ gpsi->BitCount != OrigBC)
+ {
+ ERR("Detect settings changed.\n");
+ UserSendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0);
+ UserSendNotifyMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
+ }
//co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
return lResult;
}
+VOID
+UserDisplayNotifyShutdown(
+ PPROCESSINFO ppiCurrent)
+{
+ if (ppiCurrent == gpFullscreen)
+ {
+ UserChangeDisplaySettings(NULL, NULL, 0, NULL);
+ if (gpFullscreen)
+ ERR("Failed to restore display mode!\n");
+ }
+}
+
LONG
APIENTRY
NtUserChangeDisplaySettings(
PUNICODE_STRING pustrDevice,
LPDEVMODEW lpDevMode,
- HWND hwnd,
DWORD dwflags,
LPVOID lParam)
{
LONG lRet;
/* Check arguments */
- if ((dwflags != CDS_VIDEOPARAMETERS && lParam != NULL) ||
- (hwnd != NULL))
+ if ((dwflags != CDS_VIDEOPARAMETERS) && (lParam != NULL))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return DISP_CHANGE_BADPARAM;
UserEnterExclusive();
/* Call internal function */
- lRet = UserChangeDisplaySettings(pustrDevice, lpDevMode, hwnd, dwflags, NULL);
+ lRet = UserChangeDisplaySettings(pustrDevice, lpDevMode, dwflags, NULL);
/* Release lock */
UserLeave();