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