summaryrefslogtreecommitdiff
path: root/reschange/DisplayUtils.cpp
blob: cccc5afebd01940b56e7e461d01f1d7da4db5f98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "stdafx.h"
#include <stdio.h>
#include "windows.h"
#include "DisplayUtils.h"

#define MAX_DEVICE_NUMBER 10
#define WIN2K_MAJOR_BUILD 5
#define WIN2K_MINOR_BUILD 0
#define QUMRANET_DEVICE_SIGNATURE L"Red Hat"

//#define DEBUG

BOOL isWin2K()
{
	OSVERSIONINFO ver;
	ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	if (GetVersionEx(&ver)) {
		if (WIN2K_MAJOR_BUILD == ver.dwMajorVersion &&
		    WIN2K_MINOR_BUILD == ver.dwMinorVersion) {
			return TRUE;
		}
	}
	return FALSE;
}

BOOL isAttached(LPCTSTR DeviceName)
{
	DEVMODE DevMode;
	ZeroMemory(&DevMode, sizeof(DEVMODE));
	DevMode.dmSize = sizeof(DEVMODE);
	DevMode.dmDriverExtra = 0;
	EnumDisplaySettings(DeviceName, ENUM_CURRENT_SETTINGS, &DevMode);
	return !!DevMode.dmBitsPerPel;
}

void InitModeStructure(DEVMODE *DevMode, MonitorConfig *MonConfig, BOOL bSetPos)
{
	ZeroMemory(DevMode, sizeof(DEVMODE));
	DevMode->dmSize = sizeof(DEVMODE);
	if (MonConfig) {
		DevMode->dmBitsPerPel = MonConfig->dwDepth;
		DevMode->dmPelsWidth = MonConfig->dwWidth;
		DevMode->dmPelsHeight = MonConfig->dwHeight;
		DevMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
		if (bSetPos) {
			DevMode->dmPosition.x = MonConfig->dwPosX;
			DevMode->dmPosition.y = MonConfig->dwPosY;
			DevMode->dmFields |= DM_POSITION;
		}
	} else {
		//detach monitor
		DevMode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
	}
}

BOOL GetQxlDeviceID(CHAR *DeviceKey, DWORD *DeviceID)
{
	DWORD dwType = REG_BINARY;
	DWORD dwSize = sizeof(*DeviceID);
	BOOL bKeyFound = FALSE;
	HKEY hKey;
	
	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strstr(DeviceKey, "System"),
	                 0L, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
		bKeyFound = (RegQueryValueEx(hKey, "QxlDeviceID", NULL, &dwType,
		                             (LPBYTE)DeviceID, &dwSize) == ERROR_SUCCESS);
		RegCloseKey(hKey);
	}
	return bKeyFound;
}

int ChangeResolution(TCHAR *strDevicePNPID, BOOL bAll, BOOL bAttach, BOOL bPosition,
                     int nMons, MonitorConfig *monConfig)
{
	DISPLAY_DEVICE displayDevice;
	DEVMODE DevMode;
	HDESK hdeskInput;
	HDESK hdeskCurrent;
	BOOL attached;
	int monsCount = 0;
	int totalWidth = 0;
	int ret;
	
	hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
	if (hdeskCurrent == NULL)
		return 0;

	hdeskInput = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
	if (hdeskInput == NULL)
		return 0;

	if (!SetThreadDesktop(hdeskInput)) {
		CloseDesktop(hdeskInput);
		return 0;
	}

	for (DWORD dwI = 0; dwI < MAX_DEVICE_NUMBER; dwI++)	{
		displayDevice.cb = sizeof(DISPLAY_DEVICE);
		if (EnumDisplayDevices(NULL, dwI, &displayDevice, 0)) {
            printf("id=%s\n", displayDevice.DeviceID);
			if (displayDevice.DeviceID && displayDevice.DeviceID[0] &&
			    (bAll || _tcsstr(displayDevice.DeviceID, strDevicePNPID))) {
				if (isWin2K()) {
					ChangeDisplaySettings(NULL, 0);
				}
				DWORD dwDeviceID = 0;
				if (!bAll && !GetQxlDeviceID(displayDevice.DeviceKey, &dwDeviceID)) {
#ifdef DEBUG
					dwDeviceID = monsCount;
#else
					continue;
#endif
				}
				if ((int)dwDeviceID < nMons) {
					attached = isAttached(displayDevice.DeviceName);
					InitModeStructure(&DevMode, &monConfig[dwDeviceID], (attached && !bPosition) ? FALSE : bAttach);
					if (bAll) {
						DevMode.dmPosition.x = monsCount * DevMode.dmPelsWidth;
					} else if (bAttach && !attached && !bPosition) {
						DevMode.dmPosition.x = totalWidth;
					}
					totalWidth += monConfig[dwDeviceID].dwWidth;
				} else {
					InitModeStructure(&DevMode, NULL, FALSE);
				}
				ret = ChangeDisplaySettingsEx(displayDevice.DeviceName, &DevMode,
				                              NULL, CDS_RESET | CDS_GLOBAL |
				                              CDS_UPDATEREGISTRY, NULL);
				if (ret == DISP_CHANGE_SUCCESSFUL) {
					monsCount++;
				}
			}
		}
	}
	if (monsCount) {
		ChangeDisplaySettings(NULL, 0);
	}
	SetThreadDesktop(hdeskCurrent);
	CloseDesktop(hdeskInput);
	return monsCount;
}