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