1 /* 2 * ReactOS Device Manager Applet 3 * Copyright (C) 2004 - 2005 ReactOS Team 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /* 20 * PROJECT: ReactOS devmgr.dll 21 * FILE: lib/devmgr/misc.c 22 * PURPOSE: ReactOS Device Manager 23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com> 24 * UPDATE HISTORY: 25 * 2005/11/24 Created 26 */ 27 28 #include "precomp.h" 29 #include "properties.h" 30 #include "resource.h" 31 32 33 INT 34 LengthOfStrResource(IN HINSTANCE hInst, 35 IN UINT uID) 36 { 37 HRSRC hrSrc; 38 HGLOBAL hRes; 39 LPWSTR lpName, lpStr; 40 41 if (hInst == NULL) 42 { 43 return -1; 44 } 45 46 /* There are always blocks of 16 strings */ 47 lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1); 48 49 /* Find the string table block */ 50 if ((hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING)) && 51 (hRes = LoadResource(hInst, hrSrc)) && 52 (lpStr = (LPWSTR)LockResource(hRes))) 53 { 54 UINT x; 55 56 /* Find the string we're looking for */ 57 uID &= 0xF; /* position in the block, same as % 16 */ 58 for (x = 0; x < uID; x++) 59 { 60 lpStr += (*lpStr) + 1; 61 } 62 63 /* Found the string */ 64 return (int)(*lpStr); 65 } 66 return -1; 67 } 68 69 70 static INT 71 AllocAndLoadString(OUT LPWSTR *lpTarget, 72 IN HINSTANCE hInst, 73 IN UINT uID) 74 { 75 INT ln; 76 77 ln = LengthOfStrResource(hInst, 78 uID); 79 if (ln++ > 0) 80 { 81 (*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED, 82 ln * sizeof(WCHAR)); 83 if ((*lpTarget) != NULL) 84 { 85 INT Ret; 86 if (!(Ret = LoadStringW(hInst, uID, *lpTarget, ln))) 87 { 88 LocalFree((HLOCAL)(*lpTarget)); 89 } 90 return Ret; 91 } 92 } 93 return 0; 94 } 95 96 97 static INT 98 AllocAndLoadStringsCat(OUT LPWSTR *lpTarget, 99 IN HINSTANCE hInst, 100 IN UINT *uID, 101 IN UINT nIDs) 102 { 103 INT ln = 0; 104 UINT i; 105 106 for (i = 0; 107 i != nIDs; 108 i++) 109 { 110 ln += LengthOfStrResource(hInst, 111 uID[i]); 112 } 113 114 if (ln != 0) 115 { 116 (*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED, 117 (ln + 1) * sizeof(WCHAR)); 118 if ((*lpTarget) != NULL) 119 { 120 LPWSTR s = *lpTarget; 121 INT Ret = 0; 122 123 for (i = 0; 124 i != nIDs; 125 i++) 126 { 127 if (!(Ret = LoadStringW(hInst, uID[i], s, ln))) 128 { 129 LocalFree((HLOCAL)(*lpTarget)); 130 return 0; 131 } 132 133 s += Ret; 134 } 135 136 return s - *lpTarget; 137 } 138 } 139 return 0; 140 } 141 142 143 DWORD 144 LoadAndFormatString(IN HINSTANCE hInstance, 145 IN UINT uID, 146 OUT LPWSTR *lpTarget, 147 ...) 148 { 149 DWORD Ret = 0; 150 LPWSTR lpFormat; 151 va_list lArgs; 152 153 if (AllocAndLoadString(&lpFormat, 154 hInstance, 155 uID) != 0) 156 { 157 va_start(lArgs, lpTarget); 158 /* let's use FormatMessage to format it because it has the ability to allocate 159 memory automatically */ 160 Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, 161 lpFormat, 162 0, 163 0, 164 (LPWSTR)lpTarget, 165 0, 166 &lArgs); 167 va_end(lArgs); 168 169 LocalFree((HLOCAL)lpFormat); 170 } 171 172 return Ret; 173 } 174 175 176 DWORD 177 LoadAndFormatStringsCat(IN HINSTANCE hInstance, 178 IN UINT *uID, 179 IN UINT nIDs, 180 OUT LPWSTR *lpTarget, 181 ...) 182 { 183 DWORD Ret = 0; 184 LPWSTR lpFormat; 185 va_list lArgs; 186 187 if (AllocAndLoadStringsCat(&lpFormat, 188 hInstance, 189 uID, 190 nIDs) != 0) 191 { 192 va_start(lArgs, lpTarget); 193 /* let's use FormatMessage to format it because it has the ability to allocate 194 memory automatically */ 195 Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, 196 lpFormat, 197 0, 198 0, 199 (LPWSTR)lpTarget, 200 0, 201 &lArgs); 202 va_end(lArgs); 203 204 LocalFree((HLOCAL)lpFormat); 205 } 206 207 return Ret; 208 } 209 210 211 LPARAM 212 ListViewGetSelectedItemData(IN HWND hwnd) 213 { 214 int Index; 215 216 Index = ListView_GetNextItem(hwnd, 217 -1, 218 LVNI_SELECTED); 219 if (Index != -1) 220 { 221 LVITEM li; 222 223 li.mask = LVIF_PARAM; 224 li.iItem = Index; 225 li.iSubItem = 0; 226 227 if (ListView_GetItem(hwnd, 228 &li)) 229 { 230 return li.lParam; 231 } 232 } 233 234 return 0; 235 } 236 237 238 LPWSTR 239 ConvertMultiByteToUnicode(IN LPCSTR lpMultiByteStr, 240 IN UINT uCodePage) 241 { 242 LPWSTR lpUnicodeStr; 243 INT nLength; 244 245 nLength = MultiByteToWideChar(uCodePage, 246 0, 247 lpMultiByteStr, 248 -1, 249 NULL, 250 0); 251 if (nLength == 0) 252 return NULL; 253 254 lpUnicodeStr = (LPWSTR)HeapAlloc(GetProcessHeap(), 255 0, 256 nLength * sizeof(WCHAR)); 257 if (lpUnicodeStr == NULL) 258 { 259 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 260 return NULL; 261 } 262 263 if (!MultiByteToWideChar(uCodePage, 264 0, 265 lpMultiByteStr, 266 nLength, 267 lpUnicodeStr, 268 nLength)) 269 { 270 HeapFree(GetProcessHeap(), 271 0, 272 lpUnicodeStr); 273 return NULL; 274 } 275 276 return lpUnicodeStr; 277 } 278 279 280 BOOL 281 GetDeviceManufacturerString(IN HDEVINFO DeviceInfoSet, 282 IN PSP_DEVINFO_DATA DeviceInfoData, 283 OUT LPWSTR szBuffer, 284 IN DWORD BufferSize) 285 { 286 DWORD RegDataType; 287 BOOL Ret = FALSE; 288 289 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet, 290 DeviceInfoData, 291 SPDRP_MFG, 292 &RegDataType, 293 (PBYTE)szBuffer, 294 BufferSize * sizeof(WCHAR), 295 NULL) || 296 RegDataType != REG_SZ) 297 { 298 szBuffer[0] = L'\0'; 299 if (LoadString(hDllInstance, 300 IDS_UNKNOWN, 301 szBuffer, 302 BufferSize)) 303 { 304 Ret = TRUE; 305 } 306 } 307 else 308 { 309 /* FIXME - check string for NULL termination! */ 310 Ret = TRUE; 311 } 312 313 return Ret; 314 } 315 316 317 BOOL 318 GetDeviceLocationString(IN HDEVINFO DeviceInfoSet, 319 IN PSP_DEVINFO_DATA DeviceInfoData, 320 IN DEVINST dnParentDevInst OPTIONAL, 321 OUT LPWSTR szBuffer, 322 IN DWORD BufferSize) 323 { 324 DWORD RegDataType; 325 ULONG DataSize; 326 CONFIGRET cRet; 327 LPWSTR szFormatted; 328 HKEY hKey; 329 DWORD dwSize, dwType; 330 BOOL Ret = FALSE; 331 332 DataSize = BufferSize * sizeof(WCHAR); 333 szBuffer[0] = L'\0'; 334 335 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, 336 DeviceInfoData, 337 DICS_FLAG_GLOBAL, 338 0, 339 DIREG_DRV, 340 KEY_QUERY_VALUE); 341 if (hKey != INVALID_HANDLE_VALUE) 342 { 343 /* query the LocationInformationOverride value */ 344 dwSize = BufferSize; 345 if (RegQueryValueEx(hKey, 346 L"LocationInformationOverride", 347 NULL, 348 &dwType, 349 (LPBYTE)szBuffer, 350 &dwSize) == ERROR_SUCCESS && 351 dwType == REG_SZ && 352 szBuffer[0] != L'\0') 353 { 354 Ret = TRUE; 355 } 356 else 357 { 358 szBuffer[0] = L'\0'; 359 } 360 361 RegCloseKey(hKey); 362 } 363 364 365 if (!Ret) 366 { 367 if (dnParentDevInst != 0) 368 { 369 /* query the parent node name */ 370 if (CM_Get_DevNode_Registry_Property(dnParentDevInst, 371 CM_DRP_DEVICEDESC, 372 &RegDataType, 373 szBuffer, 374 &DataSize, 375 0) == CR_SUCCESS && 376 RegDataType == REG_SZ && 377 LoadAndFormatString(hDllInstance, 378 IDS_DEVONPARENT, 379 &szFormatted, 380 szBuffer) != 0) 381 { 382 wcsncpy(szBuffer, 383 szFormatted, 384 BufferSize - 1); 385 szBuffer[BufferSize - 1] = L'\0'; 386 LocalFree((HLOCAL)szFormatted); 387 Ret = TRUE; 388 } 389 } 390 else if (DeviceInfoData->DevInst != 0) 391 { 392 cRet = CM_Get_DevNode_Registry_Property(DeviceInfoData->DevInst, 393 CM_DRP_LOCATION_INFORMATION, 394 &RegDataType, 395 szBuffer, 396 &DataSize, 397 0); 398 if (cRet == CR_SUCCESS && RegDataType == REG_SZ) 399 { 400 /* FIXME - check string for NULL termination! */ 401 Ret = TRUE; 402 } 403 404 if (Ret && szBuffer[0] >= L'0' && szBuffer[0] <= L'9') 405 { 406 /* convert the string to an integer value and create a 407 formatted string */ 408 ULONG ulLocation = (ULONG)wcstoul(szBuffer, 409 NULL, 410 10); 411 if (LoadAndFormatString(hDllInstance, 412 IDS_LOCATIONSTR, 413 &szFormatted, 414 ulLocation, 415 szBuffer) != 0) 416 { 417 wcsncpy(szBuffer, 418 szFormatted, 419 BufferSize - 1); 420 szBuffer[BufferSize - 1] = L'\0'; 421 LocalFree((HLOCAL)szFormatted); 422 } 423 else 424 Ret = FALSE; 425 } 426 } 427 } 428 429 if (!Ret && 430 LoadString(hDllInstance, 431 IDS_UNKNOWN, 432 szBuffer, 433 BufferSize)) 434 { 435 Ret = TRUE; 436 } 437 438 return Ret; 439 } 440 441 442 BOOL 443 GetDeviceStatusString(IN DEVINST DevInst, 444 IN HMACHINE hMachine, 445 OUT LPWSTR szBuffer, 446 IN DWORD BufferSize) 447 { 448 CONFIGRET cr; 449 ULONG Status, ProblemNumber; 450 UINT MessageId = IDS_UNKNOWN; 451 BOOL Ret = FALSE; 452 453 szBuffer[0] = L'\0'; 454 cr = CM_Get_DevNode_Status_Ex(&Status, 455 &ProblemNumber, 456 DevInst, 457 0, 458 hMachine); 459 if (cr == CR_SUCCESS) 460 { 461 if (Status & DN_HAS_PROBLEM) 462 { 463 UINT uRet; 464 465 uRet = DeviceProblemTextW(hMachine, 466 DevInst, 467 ProblemNumber, 468 szBuffer, 469 (BufferSize != 0 ? BufferSize : BufferSize - 1)); 470 471 Ret = (uRet != 0 && uRet < BufferSize); 472 } 473 else 474 { 475 if (!(Status & (DN_DRIVER_LOADED | DN_STARTED))) 476 { 477 MessageId = IDS_NODRIVERLOADED; 478 } 479 else 480 { 481 MessageId = IDS_DEV_NO_PROBLEM; 482 } 483 484 goto GeneralMessage; 485 } 486 } 487 else 488 { 489 GeneralMessage: 490 if (LoadString(hDllInstance, 491 MessageId, 492 szBuffer, 493 (int)BufferSize)) 494 { 495 Ret = TRUE; 496 } 497 } 498 499 return Ret; 500 } 501 502 503 BOOL 504 GetDriverProviderString(IN HDEVINFO DeviceInfoSet, 505 IN PSP_DEVINFO_DATA DeviceInfoData, 506 OUT LPWSTR szBuffer, 507 IN DWORD BufferSize) 508 { 509 HKEY hKey; 510 DWORD dwSize, dwType; 511 BOOL Ret = FALSE; 512 513 szBuffer[0] = L'\0'; 514 515 /* get driver provider, date and version */ 516 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, 517 DeviceInfoData, 518 DICS_FLAG_GLOBAL, 519 0, 520 DIREG_DRV, 521 KEY_QUERY_VALUE); 522 if (hKey != INVALID_HANDLE_VALUE) 523 { 524 /* query the driver provider */ 525 dwSize = BufferSize; 526 if (RegQueryValueEx(hKey, 527 REGSTR_VAL_PROVIDER_NAME, 528 NULL, 529 &dwType, 530 (LPBYTE)szBuffer, 531 &dwSize) == ERROR_SUCCESS && 532 dwType == REG_SZ && 533 szBuffer[0] != L'\0') 534 { 535 Ret = TRUE; 536 } 537 else 538 { 539 szBuffer[0] = L'\0'; 540 } 541 542 RegCloseKey(hKey); 543 } 544 545 if (szBuffer[0] == L'\0') 546 { 547 /* unable to query the information */ 548 if (LoadString(hDllInstance, 549 IDS_UNKNOWN, 550 szBuffer, 551 BufferSize)) 552 { 553 Ret = TRUE; 554 } 555 } 556 557 return Ret; 558 } 559 560 561 BOOL 562 GetDriverVersionString(IN HDEVINFO DeviceInfoSet, 563 IN PSP_DEVINFO_DATA DeviceInfoData, 564 OUT LPWSTR szBuffer, 565 IN DWORD BufferSize) 566 { 567 HKEY hKey; 568 DWORD dwSize, dwType; 569 BOOL Ret = FALSE; 570 571 szBuffer[0] = L'\0'; 572 573 /* get driver provider, date and version */ 574 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, 575 DeviceInfoData, 576 DICS_FLAG_GLOBAL, 577 0, 578 DIREG_DRV, 579 KEY_QUERY_VALUE); 580 if (hKey != INVALID_HANDLE_VALUE) 581 { 582 /* query the driver provider */ 583 dwSize = BufferSize; 584 if (RegQueryValueEx(hKey, 585 L"DriverVersion", 586 NULL, 587 &dwType, 588 (LPBYTE)szBuffer, 589 &dwSize) == ERROR_SUCCESS && 590 dwType == REG_SZ && 591 szBuffer[0] != L'\0') 592 { 593 Ret = TRUE; 594 } 595 else 596 { 597 szBuffer[0] = L'\0'; 598 } 599 600 RegCloseKey(hKey); 601 } 602 603 if (szBuffer[0] == L'\0') 604 { 605 /* unable to query the information */ 606 if (LoadString(hDllInstance, 607 IDS_NOTAVAILABLE, 608 szBuffer, 609 BufferSize)) 610 { 611 Ret = TRUE; 612 } 613 } 614 615 return Ret; 616 } 617 618 BOOL 619 GetDriverDateString(IN HDEVINFO DeviceInfoSet, 620 IN PSP_DEVINFO_DATA DeviceInfoData, 621 OUT LPWSTR szBuffer, 622 IN DWORD BufferSize) 623 { 624 HKEY hKey; 625 FILETIME DriverDate; 626 SYSTEMTIME SystemTime, LocalTime; 627 DWORD dwSize, dwType; 628 BOOL Ret = FALSE; 629 630 szBuffer[0] = L'\0'; 631 632 /* get driver provider, date and version */ 633 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, 634 DeviceInfoData, 635 DICS_FLAG_GLOBAL, 636 0, 637 DIREG_DRV, 638 KEY_QUERY_VALUE); 639 if (hKey != INVALID_HANDLE_VALUE) 640 { 641 /* query the driver provider */ 642 dwSize = sizeof(FILETIME); 643 if (RegQueryValueEx(hKey, 644 L"DriverDateData", 645 NULL, 646 &dwType, 647 (LPBYTE)&DriverDate, 648 &dwSize) == ERROR_SUCCESS && 649 dwType == REG_BINARY && 650 dwSize == sizeof(FILETIME) && 651 FileTimeToSystemTime(&DriverDate, 652 &SystemTime) && 653 SystemTimeToTzSpecificLocalTime(NULL, 654 &SystemTime, 655 &LocalTime) && 656 GetDateFormat(LOCALE_USER_DEFAULT, 657 DATE_SHORTDATE, 658 &LocalTime, 659 NULL, 660 szBuffer, 661 BufferSize) != 0) 662 { 663 Ret = TRUE; 664 } 665 666 RegCloseKey(hKey); 667 } 668 669 if (!Ret) 670 { 671 /* unable to query the information */ 672 if (LoadString(hDllInstance, 673 IDS_NOTAVAILABLE, 674 szBuffer, 675 BufferSize)) 676 { 677 Ret = TRUE; 678 } 679 } 680 681 return Ret; 682 } 683 684 685 686 BOOL 687 IsDeviceHidden(IN DEVINST DevInst, 688 IN HMACHINE hMachine, 689 OUT BOOL *IsHidden) 690 { 691 CONFIGRET cr; 692 ULONG Status, ProblemNumber; 693 BOOL Ret = FALSE; 694 695 cr = CM_Get_DevNode_Status_Ex(&Status, 696 &ProblemNumber, 697 DevInst, 698 0, 699 hMachine); 700 if (cr == CR_SUCCESS) 701 { 702 *IsHidden = ((Status & DN_NO_SHOW_IN_DM) != 0); 703 Ret = TRUE; 704 } 705 706 return Ret; 707 } 708 709 710 BOOL 711 CanDisableDevice(IN DEVINST DevInst, 712 IN HMACHINE hMachine, 713 OUT BOOL *CanDisable) 714 { 715 CONFIGRET cr; 716 ULONG Status, ProblemNumber; 717 BOOL Ret = FALSE; 718 719 cr = CM_Get_DevNode_Status_Ex(&Status, 720 &ProblemNumber, 721 DevInst, 722 0, 723 hMachine); 724 if (cr == CR_SUCCESS) 725 { 726 *CanDisable = ((Status & DN_DISABLEABLE) != 0); 727 Ret = TRUE; 728 } 729 730 return Ret; 731 } 732 733 734 BOOL 735 IsDeviceStarted(IN DEVINST DevInst, 736 IN HMACHINE hMachine, 737 OUT BOOL *IsStarted) 738 { 739 CONFIGRET cr; 740 ULONG Status, ProblemNumber; 741 BOOL Ret = FALSE; 742 743 cr = CM_Get_DevNode_Status_Ex(&Status, 744 &ProblemNumber, 745 DevInst, 746 0, 747 hMachine); 748 if (cr == CR_SUCCESS) 749 { 750 *IsStarted = ((Status & DN_STARTED) != 0); 751 Ret = TRUE; 752 } 753 754 return Ret; 755 } 756 757 758 BOOL 759 IsDriverInstalled(IN DEVINST DevInst, 760 IN HMACHINE hMachine, 761 OUT BOOL *Installed) 762 { 763 CONFIGRET cr; 764 ULONG Status, ProblemNumber; 765 BOOL Ret = FALSE; 766 767 cr = CM_Get_DevNode_Status_Ex(&Status, 768 &ProblemNumber, 769 DevInst, 770 0, 771 hMachine); 772 if (cr == CR_SUCCESS) 773 { 774 *Installed = ((Status & DN_HAS_PROBLEM) != 0 || 775 (Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0); 776 Ret = TRUE; 777 } 778 779 return Ret; 780 } 781 782 783 BOOL 784 EnableDevice(IN HDEVINFO DeviceInfoSet, 785 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL, 786 IN BOOL bEnable, 787 IN DWORD HardwareProfile OPTIONAL, 788 OUT BOOL *bNeedReboot OPTIONAL) 789 { 790 SP_PROPCHANGE_PARAMS pcp; 791 SP_DEVINSTALL_PARAMS dp; 792 DWORD LastErr; 793 BOOL Ret = FALSE; 794 795 pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); 796 pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; 797 pcp.HwProfile = HardwareProfile; 798 799 if (bEnable) 800 { 801 /* try to enable the device on the global profile */ 802 pcp.StateChange = DICS_ENABLE; 803 pcp.Scope = DICS_FLAG_GLOBAL; 804 805 /* ignore errors */ 806 LastErr = GetLastError(); 807 if (SetupDiSetClassInstallParams(DeviceInfoSet, 808 DevInfoData, 809 &pcp.ClassInstallHeader, 810 sizeof(SP_PROPCHANGE_PARAMS))) 811 { 812 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, 813 DeviceInfoSet, 814 DevInfoData); 815 } 816 SetLastError(LastErr); 817 } 818 819 /* try config-specific */ 820 pcp.StateChange = (bEnable ? DICS_ENABLE : DICS_DISABLE); 821 pcp.Scope = DICS_FLAG_CONFIGSPECIFIC; 822 823 if (SetupDiSetClassInstallParams(DeviceInfoSet, 824 DevInfoData, 825 &pcp.ClassInstallHeader, 826 sizeof(SP_PROPCHANGE_PARAMS)) && 827 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, 828 DeviceInfoSet, 829 DevInfoData)) 830 { 831 dp.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 832 if (SetupDiGetDeviceInstallParams(DeviceInfoSet, 833 DevInfoData, 834 &dp)) 835 { 836 if (bNeedReboot != NULL) 837 { 838 *bNeedReboot = ((dp.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) != 0); 839 } 840 841 Ret = TRUE; 842 } 843 } 844 return Ret; 845 } 846 847 848 BOOL 849 GetDeviceTypeString(IN PSP_DEVINFO_DATA DeviceInfoData, 850 OUT LPWSTR szBuffer, 851 IN DWORD BufferSize) 852 { 853 BOOL Ret = FALSE; 854 855 if (!SetupDiGetClassDescription(&DeviceInfoData->ClassGuid, 856 szBuffer, 857 BufferSize, 858 NULL)) 859 { 860 szBuffer[0] = L'\0'; 861 if (LoadString(hDllInstance, 862 IDS_UNKNOWN, 863 szBuffer, 864 BufferSize)) 865 { 866 Ret = TRUE; 867 } 868 } 869 else 870 { 871 /* FIXME - check string for NULL termination! */ 872 Ret = TRUE; 873 } 874 875 return Ret; 876 } 877 878 879 BOOL 880 GetDeviceDescriptionString(IN HDEVINFO DeviceInfoSet, 881 IN PSP_DEVINFO_DATA DeviceInfoData, 882 OUT LPWSTR szBuffer, 883 IN DWORD BufferSize) 884 { 885 DWORD RegDataType; 886 BOOL Ret = FALSE; 887 888 if ((SetupDiGetDeviceRegistryProperty(DeviceInfoSet, 889 DeviceInfoData, 890 SPDRP_FRIENDLYNAME, 891 &RegDataType, 892 (PBYTE)szBuffer, 893 BufferSize * sizeof(WCHAR), 894 NULL) || 895 SetupDiGetDeviceRegistryProperty(DeviceInfoSet, 896 DeviceInfoData, 897 SPDRP_DEVICEDESC, 898 &RegDataType, 899 (PBYTE)szBuffer, 900 BufferSize * sizeof(WCHAR), 901 NULL)) && 902 RegDataType == REG_SZ) 903 { 904 /* FIXME - check string for NULL termination! */ 905 Ret = TRUE; 906 } 907 else 908 { 909 szBuffer[0] = L'\0'; 910 if (LoadString(hDllInstance, 911 IDS_UNKNOWNDEVICE, 912 szBuffer, 913 BufferSize)) 914 { 915 Ret = TRUE; 916 } 917 } 918 919 return Ret; 920 } 921 922 923 BOOL 924 FindCurrentDriver(IN HDEVINFO DeviceInfoSet, 925 IN PSP_DEVINFO_DATA DeviceInfoData, 926 OUT PSP_DRVINFO_DATA DriverInfoData) 927 { 928 HKEY hKey = (HKEY)INVALID_HANDLE_VALUE; 929 SP_DEVINSTALL_PARAMS InstallParams = {0}; 930 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData = {0}; 931 WCHAR InfPath[MAX_PATH]; 932 WCHAR InfSection[LINE_LEN]; 933 DWORD dwType, dwLength; 934 DWORD i = 0; 935 LONG rc; 936 BOOL Ret = FALSE; 937 938 /* Steps to find the right driver: 939 * 1) Get the device install parameters 940 * 2) Open the driver registry key 941 * 3) Read the .inf file name 942 * 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name 943 * 5) Build class driver list 944 * 6) Read inf section and inf section extension from registry 945 * 7) Enumerate drivers 946 * 8) Find the one who is in the same section as current driver? 947 */ 948 949 /* 1) Get the install params */ 950 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 951 if (!SetupDiGetDeviceInstallParams(DeviceInfoSet, 952 DeviceInfoData, 953 &InstallParams)) 954 { 955 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError()); 956 goto Cleanup; 957 } 958 959 #ifdef DI_FLAGSEX_INSTALLEDDRIVER 960 InstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); 961 if (SetupDiSetDeviceInstallParams(DeviceInfoSet, 962 DeviceInfoData, 963 &InstallParams)) 964 { 965 if (SetupDiBuildDriverInfoList(DeviceInfoSet, 966 DeviceInfoData, 967 SPDIT_CLASSDRIVER) && 968 SetupDiEnumDriverInfo(DeviceInfoSet, 969 DeviceInfoData, 970 SPDIT_CLASSDRIVER, 971 0, 972 DriverInfoData)) 973 { 974 Ret = TRUE; 975 } 976 977 goto Cleanup; 978 } 979 InstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); 980 #endif 981 982 /* 2) Open the driver registry key */ 983 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, 984 DeviceInfoData, 985 DICS_FLAG_GLOBAL, 986 0, 987 DIREG_DRV, 988 KEY_QUERY_VALUE); 989 if (hKey == INVALID_HANDLE_VALUE) 990 { 991 ERR("SetupDiOpenDevRegKey() failed with error 0x%lx\n", GetLastError()); 992 goto Cleanup; 993 } 994 995 /* 3) Read the .inf file name */ 996 dwLength = (sizeof(InfPath) / sizeof(InfPath[0])) - 1; 997 rc = RegQueryValueEx(hKey, 998 REGSTR_VAL_INFPATH, 999 0, 1000 &dwType, 1001 (LPBYTE)InfPath, 1002 &dwLength); 1003 if (rc != ERROR_SUCCESS) 1004 { 1005 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError()); 1006 SetLastError(rc); 1007 goto Cleanup; 1008 } 1009 else if (dwType != REG_SZ) 1010 { 1011 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ, dwType); 1012 SetLastError(ERROR_GEN_FAILURE); 1013 goto Cleanup; 1014 } 1015 InfPath[(dwLength / sizeof(WCHAR)) - 1] = L'\0'; 1016 1017 /* 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name */ 1018 InstallParams.Flags |= DI_ENUMSINGLEINF; 1019 InstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; 1020 wcscpy(InstallParams.DriverPath, InfPath); 1021 if (!SetupDiSetDeviceInstallParams(DeviceInfoSet, 1022 DeviceInfoData, 1023 &InstallParams)) 1024 { 1025 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError()); 1026 goto Cleanup; 1027 } 1028 1029 /* 5) Build class driver list */ 1030 if (!SetupDiBuildDriverInfoList(DeviceInfoSet, 1031 DeviceInfoData, 1032 SPDIT_CLASSDRIVER)) 1033 { 1034 ERR("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError()); 1035 goto Cleanup; 1036 } 1037 1038 /* 6) Read inf section and from registry */ 1039 dwLength = (sizeof(InfSection) / sizeof(InfSection[0])) - 1; 1040 rc = RegQueryValueEx(hKey, 1041 REGSTR_VAL_INFSECTION, 1042 0, 1043 &dwType, 1044 (LPBYTE)InfSection, 1045 &dwLength); 1046 if (rc != ERROR_SUCCESS) 1047 { 1048 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError()); 1049 SetLastError(rc); 1050 goto Cleanup; 1051 } 1052 else if (dwType != REG_SZ) 1053 { 1054 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ, dwType); 1055 SetLastError(ERROR_GEN_FAILURE); 1056 goto Cleanup; 1057 } 1058 InfPath[(dwLength / sizeof(WCHAR)) - 1] = L'\0'; 1059 1060 /* 7) Enumerate drivers */ 1061 DriverInfoData->cbSize = sizeof(SP_DRVINFO_DATA); 1062 DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); 1063 while (SetupDiEnumDriverInfo(DeviceInfoSet, 1064 DeviceInfoData, 1065 SPDIT_CLASSDRIVER, 1066 i, 1067 DriverInfoData)) 1068 { 1069 /* 8) Find the one who is in the same section as current driver */ 1070 if (!SetupDiGetDriverInfoDetail(DeviceInfoSet, 1071 DeviceInfoData, 1072 DriverInfoData, 1073 &DriverInfoDetailData, 1074 DriverInfoDetailData.cbSize, 1075 NULL) && 1076 GetLastError() != ERROR_INSUFFICIENT_BUFFER) 1077 { 1078 ERR("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", GetLastError()); 1079 goto Cleanup; 1080 } 1081 if (_wcsicmp(DriverInfoDetailData.SectionName, InfSection) == 0) 1082 { 1083 /* We have found the right driver */ 1084 Ret = TRUE; 1085 goto Cleanup; 1086 } 1087 1088 i++; 1089 } 1090 if (GetLastError() != ERROR_NO_MORE_ITEMS) 1091 { 1092 ERR("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError()); 1093 goto Cleanup; 1094 } 1095 1096 SetLastError(ERROR_NO_DRIVER_SELECTED); 1097 1098 Cleanup: 1099 if (hKey != INVALID_HANDLE_VALUE) 1100 RegCloseKey(hKey); 1101 return Ret; 1102 } 1103 1104 1105 HINSTANCE 1106 LoadAndInitComctl32(VOID) 1107 { 1108 typedef VOID (WINAPI *PINITCOMMONCONTROLS)(VOID); 1109 PINITCOMMONCONTROLS pInitCommonControls; 1110 HINSTANCE hComCtl32; 1111 1112 hComCtl32 = LoadLibrary(L"comctl32.dll"); 1113 if (hComCtl32 != NULL) 1114 { 1115 /* initialize the common controls */ 1116 pInitCommonControls = (PINITCOMMONCONTROLS)GetProcAddress(hComCtl32, 1117 "InitCommonControls"); 1118 if (pInitCommonControls == NULL) 1119 { 1120 FreeLibrary(hComCtl32); 1121 return NULL; 1122 } 1123 1124 pInitCommonControls(); 1125 } 1126 1127 return hComCtl32; 1128 } 1129 1130 1131 BOOL 1132 GetDeviceAndComputerName(LPWSTR lpString, 1133 WCHAR szDeviceID[], 1134 WCHAR szMachineName[]) 1135 { 1136 BOOL ret = FALSE; 1137 1138 szDeviceID[0] = L'\0'; 1139 szMachineName[0] = L'\0'; 1140 1141 while (*lpString != L'\0') 1142 { 1143 if (*lpString == L'/') 1144 { 1145 lpString++; 1146 if (!_wcsnicmp(lpString, L"DeviceID", 8)) 1147 { 1148 lpString += 9; 1149 if (*lpString != L'\0') 1150 { 1151 int i = 0; 1152 while ((*lpString != L' ') && 1153 (*lpString != L'\0') && 1154 (i <= MAX_DEVICE_ID_LEN)) 1155 { 1156 szDeviceID[i++] = *lpString++; 1157 } 1158 szDeviceID[i] = L'\0'; 1159 ret = TRUE; 1160 } 1161 } 1162 else if (!_wcsnicmp(lpString, L"MachineName", 11)) 1163 { 1164 lpString += 12; 1165 if (*lpString != L'\0') 1166 { 1167 int i = 0; 1168 while ((*lpString != L' ') && 1169 (*lpString != L'\0') && 1170 (i <= MAX_COMPUTERNAME_LENGTH)) 1171 { 1172 szMachineName[i++] = *lpString++; 1173 } 1174 szMachineName[i] = L'\0'; 1175 } 1176 } 1177 /* knock the pointer back one and let the next 1178 * pointer deal with incrementing, otherwise we 1179 * go past the end of the string */ 1180 lpString--; 1181 } 1182 lpString++; 1183 } 1184 1185 return ret; 1186 } 1187