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