xref: /reactos/base/applications/dxdiag/display.c (revision 40462c92)
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 DisplayPageSetDeviceDetails(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_NOT_APPLICABLE, szText, sizeof(szText)/sizeof(WCHAR));
240             }
241         }
242         IDirect3D9_Release(ppObj);
243     }
244     else
245     {
246         LoadStringW(hInst, IDS_NOT_APPLICABLE, 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     DisplayPageSetDeviceDetails(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 }
400