You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1669 lines
45 KiB
1669 lines
45 KiB
/*++
|
|
|
|
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>
|
|
#include <ccstock.h>
|
|
|
|
// this will change when the .h is moved to a public location
|
|
#include "comp.h"
|
|
|
|
const TCHAR szWhackDevice[] = TEXT("\\Device");
|
|
|
|
#define IsRegStringType(x) (((x) == REG_SZ) || ((x) == REG_EXPAND_SZ) || ((x) == REG_MULTI_SZ))
|
|
|
|
//
|
|
// 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;
|
|
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(osVer));
|
|
osVer.dwOSVersionInfoSize = sizeof(osVer);
|
|
|
|
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 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);
|
|
}
|
|
|
|
|
|
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(InterfaceData);
|
|
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(*pInterfaceDetailData);
|
|
DevInfoData.cbSize = sizeof(DevInfoData);
|
|
|
|
if ((*gpfn_SetupDiGetDeviceInterfaceDetail)(hDevInfo,
|
|
&InterfaceData,
|
|
pInterfaceDetailData,
|
|
InterfaceSize,
|
|
&InterfaceSize,
|
|
&DevInfoData))
|
|
{
|
|
//
|
|
// Is the InterfaceName the same as the DevicePath?
|
|
//
|
|
|
|
pwDevicePath = pInterfaceDetailData->DevicePath;
|
|
|
|
//
|
|
// 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);
|
|
|
|
if (bMatch)
|
|
{
|
|
//
|
|
// We found the device
|
|
//
|
|
|
|
*phDevInfo = hDevInfo;
|
|
CopyMemory(pDevInfoData, &DevInfoData, sizeof(*pDevInfoData));
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean-up
|
|
//
|
|
|
|
LocalFree(pInterfaceDetailData);
|
|
pInterfaceDetailData = NULL;
|
|
|
|
//
|
|
// Next interface ...
|
|
//
|
|
|
|
InterfaceData.cbSize = sizeof(InterfaceData);
|
|
++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);
|
|
|
|
pInstanceID = pwInstanceID;
|
|
|
|
bLocate = ((*gpfn_CM_Locate_DevNode)(&DevInst, pInstanceID, 0) == CR_SUCCESS);
|
|
|
|
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(DevInfoData);
|
|
while (SetupDiEnumDeviceInfo(hDevInfo, DeviceIndex, &DevInfoData))
|
|
{
|
|
if (DevInfoData.DevInst == DevInst)
|
|
{
|
|
//
|
|
// We found it
|
|
//
|
|
|
|
*phDevInfo = hDevInfo;
|
|
CopyMemory(pDevInfoData, &DevInfoData, sizeof(*pDevInfoData));
|
|
bSuccess = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Next display adapter
|
|
//
|
|
|
|
++DeviceIndex;
|
|
DevInfoData.cbSize = sizeof(DevInfoData);
|
|
}
|
|
|
|
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;
|
|
|
|
hinstSetupApi = LoadLibrary(TEXT("SETUPAPI.DLL"));
|
|
|
|
if (hinstSetupApi == NULL)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
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");
|
|
|
|
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))
|
|
{
|
|
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
|
|
//
|
|
|
|
StringCchPrintf(Buffer, ARRAYSIZE(Buffer), TEXT("%s%d"), SZ_VU_PHYSICAL, 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
|
|
//
|
|
|
|
StringCchPrintf(Buffer, ARRAYSIZE(Buffer), TEXT("%s%d"), SZ_VU_LOGICAL, 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;
|
|
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;
|
|
}
|
|
|
|
CopyMemory(pmszTemp, pmszVideoServices, TotalLen * sizeof(TCHAR));
|
|
|
|
LocalFree(pmszVideoServices);
|
|
|
|
pmszVideoServices = pmszTemp;
|
|
pmszTemp = NULL;
|
|
}
|
|
|
|
StringCchCopy(pmszVideoServices + TotalLen, AllocatedLen - 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 (RegOpenKeyEx(hKey,
|
|
lpSubKey,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hkDeleteKey) == ERROR_SUCCESS)
|
|
{
|
|
bReturn = TRUE;
|
|
while (RegEnumKey(hkDeleteKey, 0, szChild, ARRAYSIZE(szChild)) == 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;
|
|
DWORD cchAppExt;
|
|
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)
|
|
{
|
|
pAppExtTemp = pAppExt;
|
|
while (pAppExtTemp)
|
|
{
|
|
Len += lstrlen(pAppExtTemp->szDefaultValue) + 1;
|
|
pAppExtTemp = pAppExtTemp->pNext;
|
|
}
|
|
|
|
cchAppExt = (Len + 1);
|
|
pmszAppExt = (PTCHAR)LocalAlloc(LPTR, cchAppExt * sizeof(TCHAR));
|
|
if (pmszAppExt != NULL) {
|
|
|
|
pAppExtTemp = pAppExt;
|
|
Len = 0;
|
|
while (pAppExtTemp) {
|
|
|
|
StringCchCopy(pmszAppExt + Len, cchAppExt - 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);
|
|
}
|
|
|
|
RegCloseKey(hkDisplay);
|
|
}
|
|
}
|
|
|