Sync up with trunk r61578.
[reactos.git] / base / applications / dxdiag / display.c
1 /*
2 * PROJECT: ReactX Diagnosis Application
3 * LICENSE: LGPL - See COPYING in the top level directory
4 * FILE: base/applications/dxdiag/display.c
5 * PURPOSE: ReactX diagnosis display page
6 * COPYRIGHT: Copyright 2008 Johannes Anderwald
7 *
8 */
9
10 #include "precomp.h"
11
12 #include <d3d9.h>
13
14 BOOL
15 GetFileModifyTime(LPCWSTR pFullPath, WCHAR * szTime, int szTimeSize)
16 {
17 HANDLE hFile;
18 FILETIME AccessTime;
19 SYSTEMTIME SysTime, LocalTime;
20 UINT Length;
21 TIME_ZONE_INFORMATION TimeInfo;
22
23 hFile = CreateFileW(pFullPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
24 if (!hFile)
25 return FALSE;
26
27 if (!GetFileTime(hFile, NULL, NULL, &AccessTime))
28 {
29 CloseHandle(hFile);
30 return FALSE;
31 }
32 CloseHandle(hFile);
33
34 if(!GetTimeZoneInformation(&TimeInfo))
35 return FALSE;
36
37 if (!FileTimeToSystemTime(&AccessTime, &SysTime))
38 return FALSE;
39
40 if (!SystemTimeToTzSpecificLocalTime(&TimeInfo, &SysTime, &LocalTime))
41 return FALSE;
42
43 Length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &LocalTime, NULL, szTime, szTimeSize);
44 szTime[Length-1] = L' ';
45 return GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT, &LocalTime, NULL, &szTime[Length], szTimeSize-Length);
46 }
47
48
49
50 static UINT WINAPI
51 DriverFilesCallback(IN PVOID Context,
52 IN UINT Notification,
53 IN UINT_PTR Param1,
54 IN UINT_PTR Param2)
55 {
56 LPCWSTR pFile;
57 LPWSTR pBuffer;
58 LPCWSTR pFullPath = (LPCWSTR)Param1;
59 WCHAR szVer[60];
60 LRESULT Length, fLength;
61 HWND * hDlgCtrls = (HWND *)Context;
62
63 if (wcsstr(pFullPath, L"\\DRIVERS\\"))
64 {
65 /* exclude files from drivers dir to have failsafe file version/date information */
66 return NO_ERROR;
67 }
68
69 pFile = wcsrchr(pFullPath, L'\\');
70 if (!pFile)
71 return NO_ERROR;
72
73 pFile++;
74 fLength = wcslen(pFile) + 1;
75
76 Length = SendMessageW(hDlgCtrls[0], WM_GETTEXTLENGTH, 0, 0) + 1;
77 pBuffer = HeapAlloc(GetProcessHeap(), 0, (Length + fLength) * sizeof(WCHAR));
78 if (!pBuffer)
79 return ERROR_OUTOFMEMORY;
80
81 Length = SendMessageW(hDlgCtrls[0], WM_GETTEXT, Length, (LPARAM)pBuffer);
82 if (Length)
83 {
84 pBuffer[Length++] = L',';
85 }
86 else
87 {
88 /* set file version */
89 if (GetFileVersion(pFullPath, szVer, sizeof(szVer)/sizeof(WCHAR)))
90 SendMessageW(hDlgCtrls[1], WM_SETTEXT, 0, (LPARAM)szVer);
91 /* set file time */
92 if (GetFileModifyTime(pFullPath, szVer, sizeof(szVer)/sizeof(WCHAR)))
93 SendMessageW(hDlgCtrls[2], WM_SETTEXT, 0, (LPARAM)szVer);
94 }
95
96 wcscpy(&pBuffer[Length], pFile);
97 SendMessageW(hDlgCtrls[0], WM_SETTEXT, 0, (LPARAM)pBuffer);
98 HeapFree(GetProcessHeap(), 0, pBuffer);
99 return NO_ERROR;
100 }
101
102 VOID
103 EnumerateDrivers(PVOID Context, HDEVINFO hList, PSP_DEVINFO_DATA pInfoData)
104 {
105 HSPFILEQ hQueue;
106 SP_DEVINSTALL_PARAMS DeviceInstallParams = {0};
107 SP_DRVINFO_DATA DriverInfoData;
108 DWORD Result;
109
110 DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
111 if (!SetupDiGetDeviceInstallParamsW(hList, pInfoData, &DeviceInstallParams))
112 return;
113
114 DeviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
115 if (!SetupDiSetDeviceInstallParams(hList, pInfoData, &DeviceInstallParams))
116 return;
117
118 if (!SetupDiBuildDriverInfoList(hList, pInfoData, SPDIT_CLASSDRIVER))
119 return;
120
121 DriverInfoData.cbSize = sizeof(DriverInfoData);
122 if (!SetupDiEnumDriverInfoW(hList, pInfoData, SPDIT_CLASSDRIVER, 0, &DriverInfoData))
123 return;
124
125 DriverInfoData.cbSize = sizeof(DriverInfoData);
126 if (!SetupDiSetSelectedDriverW(hList, pInfoData, &DriverInfoData))
127 return;
128
129 hQueue = SetupOpenFileQueue();
130 if (hQueue == (HSPFILEQ)INVALID_HANDLE_VALUE)
131 return;
132
133 DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
134 if (!SetupDiGetDeviceInstallParamsW(hList, pInfoData, &DeviceInstallParams))
135 {
136 SetupCloseFileQueue(hQueue);
137 return;
138 }
139
140 DeviceInstallParams.FileQueue = hQueue;
141 DeviceInstallParams.Flags |= DI_NOVCP;
142
143 if (!SetupDiSetDeviceInstallParamsW(hList, pInfoData, &DeviceInstallParams))
144 {
145 SetupCloseFileQueue(hQueue);
146 return;
147 }
148
149 if(!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, hList, pInfoData))
150 {
151 SetupCloseFileQueue(hQueue);
152 return;
153 }
154
155
156 /* enumerate the driver files */
157 SetupScanFileQueueW(hQueue, SPQ_SCAN_USE_CALLBACK, NULL, DriverFilesCallback, Context, &Result);
158 SetupCloseFileQueue(hQueue);
159 }
160
161 static
162 void
163 SetDeviceDetails(HWND * hDlgCtrls, LPCGUID classGUID, LPGUID * deviceGUID)
164 {
165 HDEVINFO hInfo;
166 DWORD dwIndex = 0;
167 SP_DEVINFO_DATA InfoData;
168 WCHAR szText[100];
169
170 /* create the setup list */
171 hInfo = SetupDiGetClassDevsW(classGUID, NULL, NULL, DIGCF_PRESENT|DIGCF_PROFILE);
172 if (hInfo == INVALID_HANDLE_VALUE)
173 return;
174
175 do
176 {
177 ZeroMemory(&InfoData, sizeof(InfoData));
178 InfoData.cbSize = sizeof(InfoData);
179
180 if (SetupDiEnumDeviceInfo(hInfo, dwIndex, &InfoData))
181 {
182 /* set device name */
183 if (SetupDiGetDeviceRegistryPropertyW(hInfo, &InfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szText, sizeof(szText), NULL))
184 SendMessageW(hDlgCtrls[0], WM_SETTEXT, 0, (LPARAM)szText);
185
186 /* set the manufacturer name */
187 if (SetupDiGetDeviceRegistryPropertyW(hInfo, &InfoData, SPDRP_MFG, NULL, (PBYTE)szText, sizeof(szText), NULL))
188 SendMessageW(hDlgCtrls[1], WM_SETTEXT, 0, (LPARAM)szText);
189
190 /* FIXME
191 * we currently enumerate only the first adapter
192 */
193 EnumerateDrivers(&hDlgCtrls[2], hInfo, &InfoData);
194 break;
195 }
196
197 if (GetLastError() == ERROR_NO_MORE_ITEMS)
198 break;
199
200 dwIndex++;
201 }while(TRUE);
202
203 /* destroy the setup list */
204 SetupDiDestroyDeviceInfoList(hInfo);
205 }
206
207
208 static
209 BOOL
210 InitializeDialog(HWND hwndDlg, PDISPLAY_DEVICEW pDispDevice)
211 {
212 WCHAR szText[100];
213 WCHAR szFormat[30];
214 HKEY hKey;
215 HWND hDlgCtrls[5];
216 DWORD dwMemory;
217 DEVMODEW DevMode;
218 IDirect3D9 * ppObj = NULL;
219 D3DADAPTER_IDENTIFIER9 Identifier;
220 HRESULT hResult;
221
222 szText[0] = L'\0';
223
224 /* fix wine */
225 //ppObj = Direct3DCreate9(D3D_SDK_VERSION);
226 if (ppObj)
227 {
228 hResult = IDirect3D9_GetAdapterIdentifier(ppObj, D3DADAPTER_DEFAULT , 2/*D3DENUM_WHQL_LEVEL*/, &Identifier);
229 if (hResult == D3D_OK)
230 {
231
232 if (Identifier.WHQLLevel)
233 {
234 /* adapter is WHQL certified */
235 LoadStringW(hInst, IDS_OPTION_YES, szText, sizeof(szText)/sizeof(WCHAR));
236 }
237 else
238 {
239 LoadStringW(hInst, IDS_OPTION_NO, szText, sizeof(szText)/sizeof(WCHAR));
240 }
241 }
242 IDirect3D9_Release(ppObj);
243 }
244 else
245 {
246 LoadStringW(hInst, IDS_DEVICE_STATUS_UNKNOWN, szText, sizeof(szText)/sizeof(WCHAR));
247 }
248 szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
249 SendDlgItemMessageW(hwndDlg, IDC_STATIC_ADAPTER_LOGO, WM_SETTEXT, 0, (LPARAM)szText);
250
251 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, &pDispDevice->DeviceKey[18], 0, KEY_READ, &hKey) != ERROR_SUCCESS)
252 return FALSE;
253
254 if (GetRegValue(hKey, NULL, L"HardwareInformation.ChipType", REG_BINARY, szText, sizeof(szText)))
255 {
256 /* set chip type */
257 SendDlgItemMessageW(hwndDlg, IDC_STATIC_ADAPTER_CHIP, WM_SETTEXT, 0, (LPARAM)szText);
258 }
259
260 if (GetRegValue(hKey, NULL, L"HardwareInformation.DacType", REG_BINARY, szText, sizeof(szText)))
261 {
262 /* set DAC type */
263 SendDlgItemMessageW(hwndDlg, IDC_STATIC_ADAPTER_DAC, WM_SETTEXT, 0, (LPARAM)szText);
264 }
265
266 if (GetRegValue(hKey, NULL, L"HardwareInformation.MemorySize", REG_BINARY, (LPWSTR)&dwMemory, sizeof(dwMemory)))
267 {
268 /* set chip memory size */
269 if (dwMemory > (1048576))
270 {
271 /* buggy ATI driver requires that */
272 dwMemory /= 1048576;
273 }
274 szFormat[0] = L'\0';
275 if (LoadStringW(hInst, IDS_FORMAT_ADAPTER_MEM, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
276 szFormat[(sizeof(szFormat)/sizeof(WCHAR))-1] = L'\0';
277 wsprintfW(szText, szFormat, dwMemory);
278 SendDlgItemMessageW(hwndDlg, IDC_STATIC_ADAPTER_MEM, WM_SETTEXT, 0, (LPARAM)szText);
279 }
280
281 /* retrieve current display mode */
282 DevMode.dmSize = sizeof(DEVMODEW);
283 if (EnumDisplaySettingsW(pDispDevice->DeviceName, ENUM_CURRENT_SETTINGS, &DevMode))
284 {
285 szFormat[0] = L'\0';
286 if (LoadStringW(hInst, IDS_FORMAT_ADAPTER_MODE, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
287 szFormat[(sizeof(szFormat)/sizeof(WCHAR))-1] = L'\0';
288 wsprintfW(szText, szFormat, DevMode.dmPelsWidth, DevMode.dmPelsHeight, DevMode.dmBitsPerPel, DevMode.dmDisplayFrequency);
289 SendDlgItemMessageW(hwndDlg, IDC_STATIC_ADAPTER_MODE, WM_SETTEXT, 0, (LPARAM)szText);
290 }
291
292 /* query attached monitor */
293 wcscpy(szText, pDispDevice->DeviceName);
294 ZeroMemory(pDispDevice, sizeof(DISPLAY_DEVICEW));
295 pDispDevice->cb = sizeof(DISPLAY_DEVICEW);
296 if (EnumDisplayDevicesW(szText, 0, pDispDevice, 0))
297 {
298 /* set monitor name */
299 SendDlgItemMessageW(hwndDlg, IDC_STATIC_ADAPTER_MONITOR, WM_SETTEXT, 0, (LPARAM)pDispDevice->DeviceString);
300 }
301
302 hDlgCtrls[0] = GetDlgItem(hwndDlg, IDC_STATIC_ADAPTER_ID);
303 hDlgCtrls[1] = GetDlgItem(hwndDlg, IDC_STATIC_ADAPTER_VENDOR);
304 hDlgCtrls[2] = GetDlgItem(hwndDlg, IDC_STATIC_ADAPTER_DRIVER);
305 hDlgCtrls[3] = GetDlgItem(hwndDlg, IDC_STATIC_ADAPTER_VERSION);
306 hDlgCtrls[4] = GetDlgItem(hwndDlg, IDC_STATIC_ADAPTER_DATE);
307
308 SetDeviceDetails(hDlgCtrls, &GUID_DEVCLASS_DISPLAY, NULL);
309 return TRUE;
310 }
311
312 void InitializeDisplayAdapters(PDXDIAG_CONTEXT pContext)
313 {
314 DISPLAY_DEVICEW DispDevice;
315 HWND * hDlgs;
316 HWND hwndDlg;
317 WCHAR szDisplay[20];
318 WCHAR szText[30];
319 DWORD dwOffset = 0;
320
321 while(TRUE)
322 {
323 ZeroMemory(&DispDevice, sizeof(DISPLAY_DEVICEW));
324 DispDevice.cb = sizeof(DISPLAY_DEVICEW);
325 if (!EnumDisplayDevicesW(NULL, pContext->NumDisplayAdapter + dwOffset, &DispDevice, 0))
326 return;
327
328 /* skip devices not attached to the desktop and mirror drivers */
329 if (!(DispDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) || (DispDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
330 {
331 dwOffset++;
332 continue;
333 }
334 if (pContext->NumDisplayAdapter)
335 hDlgs = HeapReAlloc(GetProcessHeap(), 0, pContext->hDisplayWnd, (pContext->NumDisplayAdapter + 1) * sizeof(HWND));
336 else
337 hDlgs = HeapAlloc(GetProcessHeap(), 0, (pContext->NumDisplayAdapter + 1) * sizeof(HWND));
338
339 if (!hDlgs)
340 break;
341
342 pContext->hDisplayWnd = hDlgs;
343 hwndDlg = CreateDialogParamW(hInst, MAKEINTRESOURCEW(IDD_DISPLAY_DIALOG), pContext->hMainDialog, DisplayPageWndProc, (LPARAM)pContext); EnableDialogTheme(hwndDlg);
344 if (!hwndDlg)
345 break;
346
347 /* initialize the dialog */
348 InitializeDialog(hwndDlg, &DispDevice);
349
350 szDisplay[0] = L'\0';
351 LoadStringW(hInst, IDS_DISPLAY_DIALOG, szDisplay, sizeof(szDisplay)/sizeof(WCHAR));
352 szDisplay[(sizeof(szDisplay)/sizeof(WCHAR))-1] = L'\0';
353
354 wsprintfW (szText, L"%s %u", szDisplay, pContext->NumDisplayAdapter + 1);
355 InsertTabCtrlItem(GetDlgItem(pContext->hMainDialog, IDC_TAB_CONTROL), pContext->NumDisplayAdapter + 1, szText);
356
357 hDlgs[pContext->NumDisplayAdapter] = hwndDlg;
358 pContext->NumDisplayAdapter++;
359 }
360
361
362 }
363
364
365 INT_PTR CALLBACK
366 DisplayPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
367 {
368 RECT rect;
369 PDXDIAG_CONTEXT pContext = (PDXDIAG_CONTEXT)GetWindowLongPtr(hDlg, DWLP_USER);
370 switch (message)
371 {
372 case WM_INITDIALOG:
373 {
374 pContext = (PDXDIAG_CONTEXT) lParam;
375 SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pContext);
376 SetWindowPos(hDlg, NULL, 10, 32, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
377 return TRUE;
378 }
379 case WM_COMMAND:
380 {
381 switch(LOWORD(wParam))
382 {
383 case IDC_BUTTON_TESTDD:
384 case IDC_BUTTON_TEST3D:
385 GetWindowRect(pContext->hMainDialog, &rect);
386 /* FIXME log result errors */
387 if (IDC_BUTTON_TESTDD == LOWORD(wParam))
388 DDTests();
389 else if (IDC_BUTTON_TEST3D == LOWORD(wParam))
390 D3DTests();
391 SetWindowPos(pContext->hMainDialog, NULL, rect.left, rect.top, rect.right, rect.bottom, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
392 break;
393 }
394 break;
395 }
396 }
397
398 return FALSE;
399 }