|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
migrate.cpp
Environment:
WIN32 User Mode
--*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <initguid.h>
#include "migrate.h"
#include <regstr.h>
// this will change when the .h is moved to a public location
#include "comp.h"
const TCHAR szWhackDevice[] = TEXT("\\Device");
//
// Data
//
PFN_CM_LOCATE_DEVNODE gpfn_CM_Locate_DevNode = NULL; PFN_SETUP_DI_ENUM_DEVICES_INTERFACES gpfn_SetupDiEnumDeviceInterfaces = NULL; PFN_SETUP_DI_GET_DEVICE_INTERFACE_DETAIL gpfn_SetupDiGetDeviceInterfaceDetail = NULL; PFN_SETUP_DI_CREATE_DEVICE_INTERFACE_REG_KEY gpfn_SetupDiCreateDeviceInterfaceRegKey = NULL; PFN_SETUP_DI_OPEN_DEVICE_INTERFACE_REG_KEY gpfn_SetupDiOpenDeviceInterfaceRegKey = NULL; PFN_SETUP_DI_CREATE_DEVICE_INTERFACE gpfn_SetupDiCreateDeviceInterface = NULL;
//
// DllMain
//
extern "C" {
BOOL APIENTRY DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) {
case DLL_PROCESS_ATTACH: break;
case DLL_PROCESS_DETACH: break;
case DLL_THREAD_DETACH: break;
case DLL_THREAD_ATTACH: break;
default: break; }
return TRUE; }
}
BOOL VideoUpgradeCheck( PCOMPAIBILITYCALLBACK CompatibilityCallback, LPVOID Context ) { DWORD dwDisposition; HKEY hKey = 0; OSVERSIONINFO osVer; DWORD cb; BOOL bSuccess = FALSE;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, SZ_UPDATE_SETTINGS, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS) {
//
// Oh well, guess we can't write it, no big deal
//
hKey = 0; goto Cleanup; }
ZeroMemory(&osVer, sizeof(OSVERSIONINFO)); osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osVer)) {
//
// We can't get the version info, no big deal
//
goto Cleanup; }
//
// Get the current device caps and store them away for the
// display applet to apply later.
// Do it only if this is not a remote session.
//
if (!GetSystemMetrics(SM_REMOTESESSION)) { SaveDisplaySettings(hKey, &osVer); }
//
// Store the OS version we are upgrading from
//
SaveOsInfo(hKey, &osVer);
//
// Save info about the legacy driver
//
SaveLegacyDriver(hKey);
//
// Save the video services
//
if ((osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osVer.dwMajorVersion <= 4)) { SaveNT4Services(hKey); }
//
// Save the applet extensions
//
if ((osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osVer.dwMajorVersion <= 5)) {
SaveAppletExtensions(hKey); }
bSuccess = TRUE;
Cleanup:
if (hKey != 0) { RegCloseKey(hKey); }
return bSuccess; }
VOID SaveOsInfo( HKEY hKey, POSVERSIONINFO posVer ) { DWORD cb;
//
// Can't just dump the struct into the registry b/c of the size
// difference between CHAR and WCHAR (ie, szCSDVersion)
//
cb = sizeof(DWORD); RegSetValueEx(hKey, SZ_UPGRADE_FROM_PLATFORM, 0, REG_DWORD, (PBYTE)&(posVer->dwPlatformId), cb);
cb = sizeof(DWORD); RegSetValueEx(hKey, SZ_UPGRADE_FROM_MAJOR_VERSION, 0, REG_DWORD, (PBYTE)&(posVer->dwMajorVersion), cb);
cb = sizeof(DWORD); RegSetValueEx(hKey, SZ_UPGRADE_FROM_MINOR_VERSION, 0, REG_DWORD, (PBYTE)&(posVer->dwMinorVersion), cb);
cb = sizeof(DWORD); RegSetValueEx(hKey, SZ_UPGRADE_FROM_BUILD_NUMBER, 0, REG_DWORD, (PBYTE)&(posVer->dwBuildNumber), cb);
cb = lstrlen(posVer->szCSDVersion); RegSetValueEx(hKey, SZ_UPGRADE_FROM_VERSION_DESC, 0, REG_SZ, (PBYTE)&(posVer->szCSDVersion), cb); }
VOID SaveLegacyDriver( HKEY hKey ) { LPTSTR pszEnd; HKEY hKeyMap, hKeyDriver; int i = 0, num = 0; TCHAR szValueName[128], szData[128]; PTCHAR szPath; DWORD cbValue, cbData, dwType;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_VIDEOMAP, 0, KEY_READ, &hKeyMap) != ERROR_SUCCESS) { return; }
for (cbValue = (sizeof(szValueName) - 1) / sizeof(TCHAR), cbData = sizeof(szData) / sizeof(TCHAR);
RegEnumValue(hKeyMap, i++, szValueName, &cbValue, NULL, &dwType, (PBYTE) szData, &cbData) != ERROR_NO_MORE_ITEMS;
cbValue = (sizeof(szValueName) - 1) / sizeof(TCHAR), cbData = sizeof(szData) / sizeof(TCHAR) ) {
if ((REG_SZ != dwType) || (_tcsicmp(szData, TEXT("VgaSave")) == 0)) {
continue; }
//
// Make sure the value's name is \Device\XxxY
//
if ((cbValue < (DWORD) lstrlen(szWhackDevice)) || _tcsnicmp(szValueName, szWhackDevice, lstrlen(szWhackDevice))) {
continue; }
szPath = SubStrEnd(SZ_REGISTRYMACHINE, szData);
for (pszEnd = szPath + lstrlen(szPath); pszEnd != szPath && *pszEnd != TEXT('\\'); pszEnd--) { ; // nothing
}
//
// Remove the \DeviceX at the end of the path
//
*pszEnd = TEXT('\0');
//
// First check if their is a binary name in there that we should use.
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKeyDriver) == ERROR_SUCCESS) {
//
// Parse the device map and open the registry.
//
cbValue = sizeof(szValueName); if (RegQueryValueEx(hKeyDriver, TEXT("ImagePath"), NULL, NULL, (LPBYTE) szValueName, &cbValue) == ERROR_SUCCESS) {
//
// This is a binary, extract the name, which will be of the form
// ...\driver.sys
//
LPTSTR pszDriver, pszDriverEnd;
pszDriver = szValueName; pszDriverEnd = pszDriver + lstrlen(pszDriver);
while(pszDriverEnd != pszDriver && *pszDriverEnd != TEXT('.')) { pszDriverEnd--; }
*pszDriverEnd = UNICODE_NULL;
while(pszDriverEnd != pszDriver && *pszDriverEnd != TEXT('\\')) { pszDriverEnd--; }
pszDriverEnd++;
//
// If pszDriver and pszDriverEnd are different, we now
// have the driver name.
//
if (pszDriverEnd > pszDriver) { if (_tcsicmp(pszDriverEnd, TEXT("vga")) != 0) { RegCloseKey(hKeyDriver); continue; }
wsprintf(szValueName, TEXT("Driver%d"), num); cbValue = lstrlen(pszDriverEnd); RegSetValueEx(hKey, szValueName, 0, REG_SZ, (PBYTE) pszDriverEnd, cbValue); } }
RegCloseKey(hKeyDriver); }
//
// Get the actual service name
//
for( ; pszEnd > szPath && *pszEnd != TEXT('\\'); pszEnd--) { ; } pszEnd++;
//
// Save the service name
//
wsprintf(szValueName, TEXT("Service%d"), num++); cbValue = lstrlen(pszEnd); RegSetValueEx(hKey, szValueName, 0, REG_SZ, (PBYTE) pszEnd, cbValue); }
cbValue = sizeof(DWORD); RegSetValueEx(hKey, TEXT("NumDrivers"), 0, REG_DWORD, (PBYTE) &num, cbValue);
RegCloseKey(hKeyMap); }
BOOL SaveDisplaySettings( HKEY hKey, POSVERSIONINFO posVer ) { PVU_PHYSICAL_DEVICE pPhysicalDevice = NULL; BOOL bSuccess = FALSE;
if ((posVer->dwPlatformId == VER_PLATFORM_WIN32_NT) && (posVer->dwMajorVersion >= 5)) {
//
// Try the new way to get the display settings
//
CollectDisplaySettings(&pPhysicalDevice); }
if (pPhysicalDevice == NULL) {
//
// Try the old way to get the display settings
//
LegacyCollectDisplaySettings(&pPhysicalDevice); }
if (pPhysicalDevice != NULL) {
//
// Save the display settings to registry
//
bSuccess = WriteDisplaySettingsToRegistry(hKey, pPhysicalDevice);
//
// Cleanup
//
FreeAllNodes(pPhysicalDevice); }
return bSuccess; }
BOOL GetDevInfoData( IN LPTSTR pDeviceKey, OUT HDEVINFO* phDevInfo, OUT PSP_DEVINFO_DATA pDevInfoData )
/*
Note: If this function retuns success, the caller is responsible to destroy the device info list returned in phDevInfo
*/
{ LPWSTR pwInterfaceName = NULL; LPWSTR pwInstanceID = NULL; BOOL bSuccess = FALSE;
ASSERT (pDeviceKey != NULL);
if (AllocAndReadInterfaceName(pDeviceKey, &pwInterfaceName)) {
bSuccess = GetDevInfoDataFromInterfaceName(pwInterfaceName, phDevInfo, pDevInfoData); LocalFree(pwInterfaceName);
}
if ((!bSuccess) && AllocAndReadInstanceID(pDeviceKey, &pwInstanceID)) {
bSuccess = GetDevInfoDataFromInstanceID(pwInstanceID, phDevInfo, pDevInfoData); LocalFree(pwInstanceID);
}
return bSuccess; }
BOOL GetDevInfoDataFromInterfaceName( IN LPWSTR pwInterfaceName, OUT HDEVINFO* phDevInfo, OUT PSP_DEVINFO_DATA pDevInfoData )
/*
Note: If this function retuns success, the caller is responsible to destroy the device info list returned in phDevInfo
*/
{ LPWSTR pwDevicePath = NULL; HDEVINFO hDevInfo = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA DevInfoData; SP_DEVICE_INTERFACE_DATA InterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL; DWORD InterfaceIndex = 0; DWORD InterfaceSize = 0; BOOL bMatch = FALSE;
ASSERT (pwInterfaceName != NULL); ASSERT (phDevInfo != NULL); ASSERT (pDevInfoData != NULL);
ASSERT(gpfn_SetupDiEnumDeviceInterfaces != NULL); ASSERT(gpfn_SetupDiGetDeviceInterfaceDetail != NULL);
//
// Enumerate all display adapter interfaces
//
hDevInfo = SetupDiGetClassDevs(&GUID_DISPLAY_ADAPTER_INTERFACE, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE) { goto Cleanup; }
InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); while ((*gpfn_SetupDiEnumDeviceInterfaces)(hDevInfo, NULL, &GUID_DISPLAY_ADAPTER_INTERFACE, InterfaceIndex, &InterfaceData)) {
//
// Get the required size for the interface
//
InterfaceSize = 0; (*gpfn_SetupDiGetDeviceInterfaceDetail)(hDevInfo, &InterfaceData, NULL, 0, &InterfaceSize, NULL);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto Cleanup; }
//
// Alloc memory for the interface
//
pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc(LPTR, InterfaceSize); if (pInterfaceDetailData == NULL) goto Cleanup;
//
// Get the interface
//
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if ((*gpfn_SetupDiGetDeviceInterfaceDetail)(hDevInfo, &InterfaceData, pInterfaceDetailData, InterfaceSize, &InterfaceSize, &DevInfoData)) {
//
// Is the InterfaceName the same as the DevicePath?
//
#ifdef UNICODE
pwDevicePath = pInterfaceDetailData->DevicePath; #else
{ SIZE_T cch = strlen(pInterfaceDetailData->DevicePath) + 1; pwDevicePath = LocalAlloc(LPTR, cch * sizeof(WCHAR)); if (pwDevicePath == NULL) { goto Cleanup; } MultiByteToWideChar(CP_ACP, 0, pInterfaceDetailData->DevicePath, -1, pwDevicePath, cch); } #endif
//
// The first 4 characters of the interface name are different
// between user mode and kernel mode (e.g. "\\?\" vs "\\.\")
// Therefore, ignore them.
//
bMatch = (_wcsnicmp(pwInterfaceName + 4, pwDevicePath + 4, wcslen(pwInterfaceName + 4)) == 0);
#ifndef UNICODE
LocalFree(pwDevicePath); pwDevicePath = NULL; #endif
if (bMatch) {
//
// We found the device
//
*phDevInfo = hDevInfo; CopyMemory(pDevInfoData, &DevInfoData, sizeof(SP_DEVINFO_DATA));
break; } }
//
// Clean-up
//
LocalFree(pInterfaceDetailData); pInterfaceDetailData = NULL;
//
// Next interface ...
//
InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); ++InterfaceIndex; }
Cleanup:
if (pInterfaceDetailData != NULL) { LocalFree(pInterfaceDetailData); }
//
// Upon success, the caller is responsible to destroy the list
//
if (!bMatch && (hDevInfo != INVALID_HANDLE_VALUE)) { SetupDiDestroyDeviceInfoList(hDevInfo); }
return bMatch; }
BOOL GetDevInfoDataFromInstanceID( IN LPWSTR pwInstanceID, OUT HDEVINFO* phDevInfo, OUT PSP_DEVINFO_DATA pDevInfoData )
/*
Note: If this function retuns success, the caller is responsible to destroy the device info list returned in phDevInfo
*/
{ LPTSTR pInstanceID = NULL; HDEVINFO hDevInfo = INVALID_HANDLE_VALUE; DWORD DeviceIndex = 0; SP_DEVINFO_DATA DevInfoData; DEVINST DevInst; BOOL bSuccess = FALSE, bLocate = FALSE;
ASSERT (pwInstanceID != NULL); ASSERT (phDevInfo != NULL); ASSERT (pDevInfoData != NULL);
ASSERT (gpfn_CM_Locate_DevNode != NULL);
#ifdef UNICODE
pInstanceID = pwInstanceID; #else
{ SIZE_T cch = wcslen(pwInstanceID) + 1; pInstanceID = LocalAlloc(LPTR, cch * sizeof(CHAR)); if (pInstanceID == NULL) { return FALSE; } WideCharToMultiByte(CP_ACP, 0, pwDeviceID, -1, pInstanceID, cch * sizeof(CHAR), NULL, NULL); } #endif
bLocate = ((*gpfn_CM_Locate_DevNode)(&DevInst, pInstanceID, 0) == CR_SUCCESS);
#ifndef UNICODE
LocalFree(pInstanceID); pInstanceID = NULL; #endif
if (!bLocate) { goto Cleanup; }
//
// Enumerate all display adapters
//
hDevInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE) { goto Cleanup; }
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); while (SetupDiEnumDeviceInfo(hDevInfo, DeviceIndex, &DevInfoData)) {
if (DevInfoData.DevInst == DevInst) {
//
// We found it
//
*phDevInfo = hDevInfo; CopyMemory(pDevInfoData, &DevInfoData, sizeof(SP_DEVINFO_DATA)); bSuccess = TRUE;
break; }
//
// Next display adapter
//
++DeviceIndex; DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); }
Cleanup:
//
// Upon success, the caller is responsible to destroy the list
//
if (!bSuccess && (hDevInfo != INVALID_HANDLE_VALUE)) { SetupDiDestroyDeviceInfoList(hDevInfo); }
return bSuccess; }
VOID CollectDisplaySettings( PVU_PHYSICAL_DEVICE* ppPhysicalDevice ) { DISPLAY_DEVICE DisplayDevice; DEVMODE DevMode; PVU_LOGICAL_DEVICE pLogicalDevice = NULL; DWORD dwEnum = 0; BOOL bGoOn = FALSE; HDEVINFO hDevInfo = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA DevInfoData; DWORD BusNumber = 0, Address = 0; LPTSTR pDeviceX = NULL, pX = NULL; HINSTANCE hinstSetupApi = NULL; BOOL bInserted = FALSE; HKEY hDeviceKey = NULL; BOOL bDummy;
hinstSetupApi = LoadLibrary(TEXT("SETUPAPI.DLL"));
if (hinstSetupApi == NULL) { goto Cleanup; }
#ifdef UNICODE
gpfn_CM_Locate_DevNode = (PFN_CM_LOCATE_DEVNODE) GetProcAddress(hinstSetupApi, "CM_Locate_DevNodeW");
gpfn_SetupDiGetDeviceInterfaceDetail = (PFN_SETUP_DI_GET_DEVICE_INTERFACE_DETAIL) GetProcAddress(hinstSetupApi, "SetupDiGetDeviceInterfaceDetailW");
gpfn_SetupDiCreateDeviceInterfaceRegKey = (PFN_SETUP_DI_CREATE_DEVICE_INTERFACE_REG_KEY) GetProcAddress(hinstSetupApi, "SetupDiCreateDeviceInterfaceRegKeyW");
gpfn_SetupDiCreateDeviceInterface = (PFN_SETUP_DI_CREATE_DEVICE_INTERFACE) GetProcAddress(hinstSetupApi, "SetupDiCreateDeviceInterfaceW");
#else // UNICODE
gpfn_CM_Locate_DevNode = (PFN_CM_LOCATE_DEVNODE) GetProcAddress(hinstSetupApi, "CM_Locate_DevNodeA");
gpfn_SetupDiGetDeviceInterfaceDetail = (PFN_SETUP_DI_GET_DEVICE_INTERFACE_DETAIL) GetProcAddress(hinstSetupApi, "SetupDiGetDeviceInterfaceDetailA");
gpfn_SetupDiCreateDeviceInterfaceRegKey = (PFN_SETUP_DI_CREATE_DEVICE_INTERFACE_REG_KEY) GetProcAddress(hinstSetupApi, "SetupDiCreateDeviceInterfaceRegKeyA");
gpfn_SetupDiCreateDeviceInterface = (PFN_SETUP_DI_CREATE_DEVICE_INTERFACE) GetProcAddress(hinstSetupApi, "SetupDiCreateDeviceInterfaceA");
#endif // UNICODE
gpfn_SetupDiEnumDeviceInterfaces = (PFN_SETUP_DI_ENUM_DEVICES_INTERFACES) GetProcAddress(hinstSetupApi, "SetupDiEnumDeviceInterfaces");
gpfn_SetupDiOpenDeviceInterfaceRegKey = (PFN_SETUP_DI_OPEN_DEVICE_INTERFACE_REG_KEY) GetProcAddress(hinstSetupApi, "SetupDiOpenDeviceInterfaceRegKey");
if ((gpfn_CM_Locate_DevNode == NULL) || (gpfn_SetupDiEnumDeviceInterfaces == NULL) || (gpfn_SetupDiGetDeviceInterfaceDetail == NULL) || (gpfn_SetupDiCreateDeviceInterfaceRegKey == NULL) || (gpfn_SetupDiOpenDeviceInterfaceRegKey == NULL) || (gpfn_SetupDiCreateDeviceInterface == NULL)) {
goto Cleanup; }
//
// Enumerate all video devices
//
DisplayDevice.cb = sizeof(DISPLAY_DEVICE); while (EnumDisplayDevices(NULL, dwEnum, &DisplayDevice, 0)) {
bInserted = FALSE; pLogicalDevice = NULL;
//
// Get the device info data corresponding to the current
// video device
//
if (!GetDevInfoData(DisplayDevice.DeviceKey, &hDevInfo, &DevInfoData)) {
goto NextDevice; } ASSERT (hDevInfo != INVALID_HANDLE_VALUE);
//
// Retrieve the bus number and address
//
bGoOn = SetupDiGetDeviceRegistryProperty(hDevInfo, &DevInfoData, SPDRP_BUSNUMBER, NULL, (PBYTE)&BusNumber, sizeof(BusNumber), NULL) && SetupDiGetDeviceRegistryProperty(hDevInfo, &DevInfoData, SPDRP_ADDRESS, NULL, (PBYTE)&Address, sizeof(Address), NULL);
SetupDiDestroyDeviceInfoList(hDevInfo);
if (!bGoOn) {
goto NextDevice; }
//
// Allocate memory for the logical device
//
pLogicalDevice = (PVU_LOGICAL_DEVICE) LocalAlloc(LPTR, sizeof(VU_LOGICAL_DEVICE));
if (pLogicalDevice == NULL) { goto NextDevice; }
//
// DeviceX
//
pDeviceX = DisplayDevice.DeviceKey + _tcslen(DisplayDevice.DeviceKey);
while ((pDeviceX != DisplayDevice.DeviceKey) && (*pDeviceX != TEXT('\\'))) { pDeviceX--; }
if (pDeviceX == DisplayDevice.DeviceKey) { goto NextDevice; }
pX = SubStrEnd(SZ_DEVICE, pDeviceX); if (pX == pDeviceX) {
//
// The new key is used: CCS\Control\Video\[GUID]\000X
//
pX++; pLogicalDevice->DeviceX = _ttoi(pX); } else {
//
// The old key is used: CCS\Services\[SrvName]\DeviceX
//
pLogicalDevice->DeviceX = _ttoi(pX); }
//
// AttachedToDesktop
//
pLogicalDevice->AttachedToDesktop = ((DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0); pLogicalDevice->ValidFields |= VU_ATTACHED_TO_DESKTOP;
if (pLogicalDevice->AttachedToDesktop) {
//
// Get the current mode
//
DevMode.dmSize = sizeof(DEVMODE); if (EnumDisplaySettings(DisplayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &DevMode)) {
//
// RelativeX, RelativeY, BitsPerPel, XResolution,
// YResolution, VRefresh & Flags
//
pLogicalDevice->ValidFields |= VU_RELATIVE_X; pLogicalDevice->RelativeX = DevMode.dmPosition.x;
pLogicalDevice->ValidFields |= VU_RELATIVE_Y; pLogicalDevice->RelativeY = DevMode.dmPosition.y;
pLogicalDevice->ValidFields |= VU_BITS_PER_PEL; pLogicalDevice->BitsPerPel = DevMode.dmBitsPerPel;
pLogicalDevice->ValidFields |= VU_X_RESOLUTION; pLogicalDevice->XResolution = DevMode.dmPelsWidth;
pLogicalDevice->ValidFields |= VU_Y_RESOLUTION; pLogicalDevice->YResolution = DevMode.dmPelsHeight;
pLogicalDevice->ValidFields |= VU_VREFRESH; pLogicalDevice->VRefresh = DevMode.dmDisplayFrequency;
pLogicalDevice->ValidFields |= VU_FLAGS; pLogicalDevice->Flags = DevMode.dmDisplayFlags;
//
// Ignore the following settings for now:
// DefaultSettings.XPanning - DevMode.dmPanningWidth
// DefaultSettings.YPanning - DevMode.dmPanningHeight
// DefaultSettings.DriverExtra - DevMode.dmDriverExtra
//
} }
if (GetDeviceRegKey(DisplayDevice.DeviceKey, &hDeviceKey, &bDummy)) { DWORD dwTemp, cb; //
// Hardware acceleration
//
cb = sizeof(dwTemp); if (RegQueryValueEx(hDeviceKey, SZ_HW_ACCELERATION, NULL, NULL, (LPBYTE)&dwTemp, &cb) == ERROR_SUCCESS) {
pLogicalDevice->ValidFields |= VU_HW_ACCELERATION; pLogicalDevice->HwAcceleration = dwTemp; } //
// Pruning mode
//
cb = sizeof(dwTemp); if (RegQueryValueEx(hDeviceKey, SZ_PRUNNING_MODE, NULL, NULL, (LPBYTE)&dwTemp, &cb) == ERROR_SUCCESS) {
pLogicalDevice->ValidFields |= VU_PRUNING_MODE; pLogicalDevice->PruningMode = dwTemp; }
RegCloseKey(hDeviceKey); }
bInserted = InsertNode(ppPhysicalDevice, pLogicalDevice, 0, BusNumber, Address);
NextDevice:
if (!bInserted && (pLogicalDevice != NULL)) {
LocalFree(pLogicalDevice); pLogicalDevice = NULL; }
DisplayDevice.cb = sizeof(DISPLAY_DEVICE); ++dwEnum; }
Cleanup:
if (hinstSetupApi != NULL) {
gpfn_CM_Locate_DevNode = NULL; gpfn_SetupDiEnumDeviceInterfaces = NULL; gpfn_SetupDiGetDeviceInterfaceDetail = NULL; gpfn_SetupDiCreateDeviceInterfaceRegKey = NULL; gpfn_SetupDiOpenDeviceInterfaceRegKey = NULL; gpfn_SetupDiCreateDeviceInterface = NULL;
FreeLibrary(hinstSetupApi); } }
BOOL InsertNode( PVU_PHYSICAL_DEVICE* ppPhysicalDevice, PVU_LOGICAL_DEVICE pLogicalDevice, DWORD Legacy, DWORD BusNumber, DWORD Address ) { PVU_PHYSICAL_DEVICE pPhysicalDevice = *ppPhysicalDevice; BOOL bSuccess = FALSE; PVU_LOGICAL_DEVICE pPrevLogicalDevice = NULL; PVU_LOGICAL_DEVICE pNextLogicalDevice = NULL;
ASSERT (pLogicalDevice != NULL); ASSERT((Legacy == 0) || (*ppPhysicalDevice == NULL));
if (Legacy == 0) {
//
// If not Legacy, try to find if there is a device
// with the same bus location
//
while (pPhysicalDevice != NULL) {
if ((pPhysicalDevice->BusNumber == BusNumber) && (pPhysicalDevice->Address == Address)) {
break; }
pPhysicalDevice = pPhysicalDevice->pNextPhysicalDevice; } }
if (pPhysicalDevice != NULL) {
//
// There is already a logical device with the same address
//
ASSERT (pPhysicalDevice->pFirstLogicalDevice != NULL);
pPhysicalDevice->CountOfLogicalDevices++;
pPrevLogicalDevice = pNextLogicalDevice = pPhysicalDevice->pFirstLogicalDevice;
while (pNextLogicalDevice && (pNextLogicalDevice->DeviceX <= pLogicalDevice->DeviceX)) {
pPrevLogicalDevice = pNextLogicalDevice; pNextLogicalDevice = pNextLogicalDevice->pNextLogicalDevice; }
if (pPrevLogicalDevice == pNextLogicalDevice) {
ASSERT (pPrevLogicalDevice == pPhysicalDevice->pFirstLogicalDevice);
pLogicalDevice->pNextLogicalDevice = pPhysicalDevice->pFirstLogicalDevice; pPhysicalDevice->pFirstLogicalDevice = pLogicalDevice;
} else {
pPrevLogicalDevice->pNextLogicalDevice = pLogicalDevice; pLogicalDevice->pNextLogicalDevice = pNextLogicalDevice; }
bSuccess = TRUE;
} else {
//
// This is a new physical device
//
pPhysicalDevice = (PVU_PHYSICAL_DEVICE) LocalAlloc(LPTR, sizeof(VU_PHYSICAL_DEVICE));
if (pPhysicalDevice != NULL) {
pPhysicalDevice->pNextPhysicalDevice = *ppPhysicalDevice; *ppPhysicalDevice = pPhysicalDevice;
pPhysicalDevice->pFirstLogicalDevice = pLogicalDevice; pPhysicalDevice->CountOfLogicalDevices = 1; pPhysicalDevice->Legacy = Legacy; pPhysicalDevice->BusNumber = BusNumber; pPhysicalDevice->Address = Address;
bSuccess = TRUE; } }
return bSuccess; }
VOID FreeAllNodes( PVU_PHYSICAL_DEVICE pPhysicalDevice ) { PVU_PHYSICAL_DEVICE pTempPhysicalDevice = NULL; PVU_LOGICAL_DEVICE pLogicalDevice = NULL, pTempLogicalDevice = NULL;
while (pPhysicalDevice != NULL) {
pTempPhysicalDevice = pPhysicalDevice->pNextPhysicalDevice; pLogicalDevice = pPhysicalDevice->pFirstLogicalDevice;
while (pLogicalDevice != NULL) {
pTempLogicalDevice = pLogicalDevice->pNextLogicalDevice; LocalFree(pLogicalDevice); pLogicalDevice = pTempLogicalDevice; }
LocalFree(pPhysicalDevice); pPhysicalDevice = pTempPhysicalDevice; } }
BOOL WriteDisplaySettingsToRegistry( HKEY hKey, PVU_PHYSICAL_DEVICE pPhysicalDevice ) { PVU_LOGICAL_DEVICE pLogicalDevice = NULL; DWORD CountOfPhysicalDevices = 0; DWORD CountOfLogicalDevices = 0; HKEY hPysicalDeviceKey = 0; HKEY hLogicalDeviceKey = 0; BOOL bSuccess = FALSE; TCHAR Buffer[20];
while (pPhysicalDevice != NULL) {
//
// Create physical device subkey
//
_tcscpy(Buffer, SZ_VU_PHYSICAL); _stprintf(Buffer + _tcslen(Buffer), TEXT("%d"), CountOfPhysicalDevices); DeleteKeyAndSubkeys(hKey, Buffer);
if (RegCreateKeyEx(hKey, Buffer, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hPysicalDeviceKey, NULL) != ERROR_SUCCESS) {
hPysicalDeviceKey = 0; goto NextPhysicalDevice; }
if (pPhysicalDevice->Legacy == 0) {
//
// BusNumber
//
if (RegSetValueEx(hPysicalDeviceKey, SZ_VU_BUS_NUMBER, 0, REG_DWORD, (PBYTE)&pPhysicalDevice->BusNumber, sizeof(pPhysicalDevice->BusNumber)) != ERROR_SUCCESS) {
goto NextPhysicalDevice; }
//
// Address
//
if (RegSetValueEx(hPysicalDeviceKey, SZ_VU_ADDRESS, 0, REG_DWORD, (PBYTE)&pPhysicalDevice->Address, sizeof(pPhysicalDevice->Address)) != ERROR_SUCCESS) {
goto NextPhysicalDevice; }
}
pLogicalDevice = pPhysicalDevice->pFirstLogicalDevice; CountOfLogicalDevices = 0;
while (pLogicalDevice != NULL) {
//
// Create logical device subkey
//
_tcscpy(Buffer, SZ_VU_LOGICAL); _stprintf(Buffer + _tcslen(Buffer), TEXT("%d"), CountOfLogicalDevices); if (RegCreateKeyEx(hPysicalDeviceKey, Buffer, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hLogicalDeviceKey, NULL) != ERROR_SUCCESS) {
hLogicalDeviceKey = 0;
//
// Cannot go on with this physical device.
// The order of logical devices DOES matter in the dual-view case.
//
break; }
//
// AttachedToDesktop
//
if (pLogicalDevice->ValidFields & VU_ATTACHED_TO_DESKTOP) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_ATTACHED_TO_DESKTOP, 0, REG_DWORD, (PBYTE)&pLogicalDevice->AttachedToDesktop, sizeof(pLogicalDevice->AttachedToDesktop)); }
//
// RelativeX
//
if (pLogicalDevice->ValidFields & VU_RELATIVE_X) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_RELATIVE_X, 0, REG_DWORD, (PBYTE)&pLogicalDevice->RelativeX, sizeof(pLogicalDevice->RelativeX)); }
//
// RelativeY
//
if (pLogicalDevice->ValidFields & VU_RELATIVE_Y) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_RELATIVE_Y, 0, REG_DWORD, (PBYTE)&pLogicalDevice->RelativeY, sizeof(pLogicalDevice->RelativeY)); }
//
// BitsPerPel
//
if (pLogicalDevice->ValidFields & VU_BITS_PER_PEL) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_BITS_PER_PEL, 0, REG_DWORD, (PBYTE)&pLogicalDevice->BitsPerPel, sizeof(pLogicalDevice->BitsPerPel)); }
//
// XResolution
//
if (pLogicalDevice->ValidFields & VU_X_RESOLUTION) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_X_RESOLUTION, 0, REG_DWORD, (PBYTE)&pLogicalDevice->XResolution, sizeof(pLogicalDevice->XResolution)); }
//
// YResolution
//
if (pLogicalDevice->ValidFields & VU_Y_RESOLUTION) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_Y_RESOLUTION, 0, REG_DWORD, (PBYTE)&pLogicalDevice->YResolution, sizeof(pLogicalDevice->YResolution)); }
//
// VRefresh
//
if (pLogicalDevice->ValidFields & VU_VREFRESH) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_VREFRESH, 0, REG_DWORD, (PBYTE)&pLogicalDevice->VRefresh, sizeof(pLogicalDevice->VRefresh)); }
//
// Flags
//
if (pLogicalDevice->ValidFields & VU_FLAGS) {
RegSetValueEx(hLogicalDeviceKey, SZ_VU_FLAGS, 0, REG_DWORD, (PBYTE)&pLogicalDevice->Flags, sizeof(pLogicalDevice->Flags)); }
//
// Hardware acceleration
//
if (pLogicalDevice->ValidFields & VU_HW_ACCELERATION) {
RegSetValueEx(hLogicalDeviceKey, SZ_HW_ACCELERATION, 0, REG_DWORD, (PBYTE)&pLogicalDevice->HwAcceleration, sizeof(pLogicalDevice->HwAcceleration)); }
//
// Pruning mode
//
if (pLogicalDevice->ValidFields & VU_PRUNING_MODE) {
RegSetValueEx(hLogicalDeviceKey, SZ_PRUNNING_MODE, 0, REG_DWORD, (PBYTE)&pLogicalDevice->PruningMode, sizeof(pLogicalDevice->PruningMode)); }
++CountOfLogicalDevices;
RegCloseKey(hLogicalDeviceKey); hLogicalDeviceKey = 0;
pLogicalDevice = pLogicalDevice->pNextLogicalDevice; }
if ((CountOfLogicalDevices > 0) && (RegSetValueEx(hPysicalDeviceKey, SZ_VU_COUNT, 0, REG_DWORD, (PBYTE)&CountOfLogicalDevices, sizeof(CountOfLogicalDevices)) == ERROR_SUCCESS)) {
++CountOfPhysicalDevices; }
NextPhysicalDevice:
if (hPysicalDeviceKey != 0) {
RegCloseKey(hPysicalDeviceKey); hPysicalDeviceKey = 0; }
pPhysicalDevice = pPhysicalDevice->pNextPhysicalDevice; }
if (CountOfPhysicalDevices > 0) {
bSuccess = (RegSetValueEx(hKey, SZ_VU_COUNT, 0, REG_DWORD, (PBYTE)&CountOfPhysicalDevices, sizeof(CountOfPhysicalDevices)) != ERROR_SUCCESS) ; }
return bSuccess; }
VOID LegacyCollectDisplaySettings( PVU_PHYSICAL_DEVICE* ppPhysicalDevice ) { PVU_LOGICAL_DEVICE pLogicalDevice = NULL; DWORD cb; INT Width, Height, Index; BOOL useVga = FALSE; HDC hDisplay; POINT Res[] = { { 640, 480}, { 800, 600}, { 1024, 768}, { 1152, 900}, { 1280, 1024}, { 1600, 1200}, { 0, 0} // end of table
};
ASSERT (*ppPhysicalDevice == NULL);
//
// Allocate memory for the logical device
//
pLogicalDevice = (PVU_LOGICAL_DEVICE) LocalAlloc(LPTR, sizeof(VU_LOGICAL_DEVICE)); if (pLogicalDevice == NULL) { return; }
Width = GetSystemMetrics(SM_CXSCREEN); Height = GetSystemMetrics(SM_CYSCREEN);
if (Width == 0 || Height == 0) {
//
// Something went wrong, default to lowest common res
//
useVga = TRUE; }
//
// NT 4.0 multimon via driver vendor, not the OS ... adjust the width and height
// back to normal values. Once setup is complete, the second card will come
// on line and it will be taken care of. In both cases, the video area must
// be rectangular, not like MM on 5.0 where we can have "holes"
//
else if (Width >= 2 * Height) {
//
// Wide
//
for (Index = 0; Res[Index].x != 0; Index++) {
if (Res[Index].y == Height) {
Width = Res[Index].x; break; } }
useVga = (Res[Index].x == 0);
} else if (Height > Width) {
//
// Tall
//
for (Index = 0; Res[Index].x != 0; Index++) {
if (Res[Index].x == Width) {
Height = Res[Index].y; break; } }
useVga = (Res[Index].x == 0); }
if (useVga) {
//
// No match, default to VGA
//
Width = 640; Height = 480; }
pLogicalDevice->ValidFields |= VU_ATTACHED_TO_DESKTOP; pLogicalDevice->AttachedToDesktop = 1;
pLogicalDevice->ValidFields |= VU_X_RESOLUTION; pLogicalDevice->XResolution = Width;
pLogicalDevice->ValidFields |= VU_Y_RESOLUTION; pLogicalDevice->YResolution = Height;
hDisplay = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); if (hDisplay) { pLogicalDevice->ValidFields |= VU_BITS_PER_PEL; pLogicalDevice->BitsPerPel = GetDeviceCaps(hDisplay, BITSPIXEL);
pLogicalDevice->ValidFields |= VU_VREFRESH; pLogicalDevice->VRefresh = GetDeviceCaps(hDisplay, VREFRESH); DeleteDC(hDisplay); }
if (!InsertNode(ppPhysicalDevice, pLogicalDevice, 1, 0, 0)) {
//
// Clean-up
//
LocalFree(pLogicalDevice); } }
VOID SaveNT4Services( HKEY hKey ) { SC_HANDLE hSCManager = NULL; ENUM_SERVICE_STATUS* pmszAllServices = NULL; QUERY_SERVICE_CONFIG* pServiceConfig = NULL; SC_HANDLE hService = NULL; DWORD cbBytesNeeded = 0; DWORD ServicesReturned = 0; DWORD ResumeHandle = 0; DWORD ServiceLen = 0, TotalLen = 0, AllocatedLen = 128; PTCHAR pmszVideoServices = NULL, pmszTemp = NULL;
//
// Allocate initial memory
//
pmszVideoServices = (PTCHAR)LocalAlloc(LPTR, AllocatedLen * sizeof(TCHAR)); if (pmszVideoServices == NULL) { goto Fallout; } //
// Open the service control manager
//
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCManager == NULL) { goto Fallout; }
//
// Get the required size
//
if ((!EnumServicesStatus(hSCManager, SERVICE_DRIVER, SERVICE_STATE_ALL, NULL, 0, &cbBytesNeeded, &ServicesReturned, &ResumeHandle)) && (GetLastError() != ERROR_MORE_DATA)) {
goto Fallout; }
//
// Allocate the memory
//
pmszAllServices = (ENUM_SERVICE_STATUS*)LocalAlloc(LPTR, cbBytesNeeded);
if (pmszAllServices == NULL) { goto Fallout; }
//
// Get the services
//
ServicesReturned = ResumeHandle = 0; if (!EnumServicesStatus(hSCManager, SERVICE_DRIVER, SERVICE_STATE_ALL, pmszAllServices, cbBytesNeeded, &cbBytesNeeded, &ServicesReturned, &ResumeHandle)) { goto Fallout; }
while (ServicesReturned--) { //
// Open the service
//
hService = OpenService(hSCManager, pmszAllServices[ServicesReturned].lpServiceName, SERVICE_ALL_ACCESS);
if (hService != NULL) { //
// Get the required size to store the config info
//
cbBytesNeeded = 0; if (QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded) || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { //
// Allocate the memory
//
pServiceConfig = (QUERY_SERVICE_CONFIG*) LocalAlloc(LPTR, cbBytesNeeded);
if (pServiceConfig != NULL) { //
// Get the config info
//
if (QueryServiceConfig(hService, pServiceConfig, cbBytesNeeded, &cbBytesNeeded) && (pServiceConfig->dwStartType != SERVICE_DISABLED) && (_tcsicmp(pServiceConfig->lpLoadOrderGroup, TEXT("Video")) == 0)) {
ServiceLen = _tcslen(pmszAllServices[ServicesReturned].lpServiceName); if (TotalLen + ServiceLen + 2 > AllocatedLen) {
AllocatedLen = TotalLen + ServiceLen + 128;
pmszTemp = (PTCHAR)LocalAlloc(LPTR, AllocatedLen * sizeof(TCHAR));
if (pmszTemp == NULL) { goto Fallout; }
memcpy(pmszTemp, pmszVideoServices, TotalLen * sizeof(TCHAR));
LocalFree(pmszVideoServices);
pmszVideoServices = pmszTemp; pmszTemp = NULL; }
_tcscpy(pmszVideoServices + TotalLen, pmszAllServices[ServicesReturned].lpServiceName); TotalLen += ServiceLen + 1; }
LocalFree(pServiceConfig); pServiceConfig = NULL; } }
CloseServiceHandle(hService); hService = NULL; } }
//
// Save the services to the registry
//
pmszVideoServices[TotalLen++] = TEXT('\0'); RegSetValueEx(hKey, SZ_SERVICES_TO_DISABLE, 0, REG_MULTI_SZ, (BYTE*)pmszVideoServices, TotalLen * sizeof(TCHAR));
Fallout: if (hService != NULL) { CloseServiceHandle(hService); }
if (pServiceConfig != NULL) { LocalFree(pServiceConfig); }
if (pmszAllServices != NULL) { LocalFree(pmszAllServices); }
if (hSCManager != NULL) { CloseServiceHandle(hSCManager); }
if (pmszVideoServices != NULL) { LocalFree(pmszVideoServices); }
} // SaveNT4Services
BOOL DeleteKeyAndSubkeys( HKEY hKey, LPCTSTR lpSubKey ) { HKEY hkDeleteKey; TCHAR szChild[MAX_PATH + 1]; BOOL bReturn = FALSE;
if (RegOpenKey(hKey, lpSubKey, &hkDeleteKey) == ERROR_SUCCESS) {
bReturn = TRUE; while (RegEnumKey(hkDeleteKey, 0, szChild, MAX_PATH) == ERROR_SUCCESS) { if (!DeleteKeyAndSubkeys(hkDeleteKey, szChild)) { bReturn = FALSE; break; } }
RegCloseKey(hkDeleteKey);
if (bReturn) bReturn = (RegDeleteKey(hKey, lpSubKey) == ERROR_SUCCESS); }
return bReturn; }
VOID SaveAppletExtensions( HKEY hKey ) { PAPPEXT pAppExt = NULL; PAPPEXT pAppExtTemp; DWORD Len = 0; PTCHAR pmszAppExt = NULL; HKEY hkDisplay;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER_DISPLAY_SHEX_PROPSHEET, 0, KEY_READ, &hkDisplay) == ERROR_SUCCESS) {
DeskAESnapshot(hkDisplay, &pAppExt); }
if (pAppExt == NULL) return;
pAppExtTemp = pAppExt; while (pAppExtTemp) { Len += lstrlen(pAppExtTemp->szDefaultValue) + 1; pAppExtTemp = pAppExtTemp->pNext; }
pmszAppExt = (PTCHAR)LocalAlloc(LPTR, (Len + 1) * sizeof(TCHAR)); if (pmszAppExt != NULL) { pAppExtTemp = pAppExt; Len = 0; while (pAppExtTemp) {
lstrcpy(pmszAppExt + Len, pAppExtTemp->szDefaultValue); Len += lstrlen(pAppExtTemp->szDefaultValue) + 1; pAppExtTemp = pAppExtTemp->pNext; }
RegSetValueEx(hKey, SZ_APPEXT_TO_DELETE, 0, REG_MULTI_SZ, (BYTE*)pmszAppExt, (Len + 1) * sizeof(TCHAR)); LocalFree(pmszAppExt); }
DeskAECleanup(pAppExt); }
|