2 * ReactOS Device Manager Applet
3 * Copyright (C) 2004 - 2005 ReactOS Team
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.
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.
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
19 /* $Id: devmgr.c 12852 2005-01-06 13:58:04Z mf $
21 * PROJECT: ReactOS devmgr.dll
22 * FILE: lib/devmgr/misc.c
23 * PURPOSE: ReactOS Device Manager
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
33 HINSTANCE hDllInstance
= NULL
;
37 LengthOfStrResource(IN HINSTANCE hInst
,
49 /* There are always blocks of 16 strings */
50 lpName
= (LPWSTR
)MAKEINTRESOURCE((uID
>> 4) + 1);
52 /* Find the string table block */
53 if ((hrSrc
= FindResourceW(hInst
, lpName
, (LPWSTR
)RT_STRING
)) &&
54 (hRes
= LoadResource(hInst
, hrSrc
)) &&
55 (lpStr
= LockResource(hRes
)))
59 /* Find the string we're looking for */
60 uID
&= 0xF; /* position in the block, same as % 16 */
61 for (x
= 0; x
< uID
; x
++)
63 lpStr
+= (*lpStr
) + 1;
66 /* Found the string */
74 AllocAndLoadString(OUT LPWSTR
*lpTarget
,
80 ln
= LengthOfStrResource(hInst
,
84 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
86 if ((*lpTarget
) != NULL
)
89 if (!(Ret
= LoadStringW(hInst
, uID
, *lpTarget
, ln
)))
91 LocalFree((HLOCAL
)(*lpTarget
));
101 AllocAndLoadStringsCat(OUT LPWSTR
*lpTarget
,
113 ln
+= LengthOfStrResource(hInst
,
119 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
120 (ln
+ 1) * sizeof(WCHAR
));
121 if ((*lpTarget
) != NULL
)
123 LPWSTR s
= *lpTarget
;
130 if (!(Ret
= LoadStringW(hInst
, uID
[i
], s
, ln
)))
132 LocalFree((HLOCAL
)(*lpTarget
));
139 return s
- *lpTarget
;
147 LoadAndFormatString(IN HINSTANCE hInstance
,
149 OUT LPWSTR
*lpTarget
,
156 if (AllocAndLoadString(&lpFormat
,
160 va_start(lArgs
, lpTarget
);
161 /* let's use FormatMessage to format it because it has the ability to allocate
162 memory automatically */
163 Ret
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
172 LocalFree((HLOCAL
)lpFormat
);
180 LoadAndFormatStringsCat(IN HINSTANCE hInstance
,
183 OUT LPWSTR
*lpTarget
,
190 if (AllocAndLoadStringsCat(&lpFormat
,
195 va_start(lArgs
, lpTarget
);
196 /* let's use FormatMessage to format it because it has the ability to allocate
197 memory automatically */
198 Ret
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
207 LocalFree((HLOCAL
)lpFormat
);
215 ListViewGetSelectedItemData(IN HWND hwnd
)
219 Index
= ListView_GetNextItem(hwnd
,
226 li
.mask
= LVIF_PARAM
;
230 if (ListView_GetItem(hwnd
,
242 ConvertMultiByteToUnicode(IN LPCSTR lpMultiByteStr
,
248 nLength
= MultiByteToWideChar(uCodePage
,
257 lpUnicodeStr
= HeapAlloc(GetProcessHeap(),
259 nLength
* sizeof(WCHAR
));
260 if (lpUnicodeStr
== NULL
)
262 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
266 if (!MultiByteToWideChar(uCodePage
,
273 HeapFree(GetProcessHeap(),
284 GetDeviceManufacturerString(IN HDEVINFO DeviceInfoSet
,
285 IN PSP_DEVINFO_DATA DeviceInfoData
,
292 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
297 BufferSize
* sizeof(WCHAR
),
299 RegDataType
!= REG_SZ
)
302 if (LoadString(hDllInstance
,
312 /* FIXME - check string for NULL termination! */
321 GetDeviceLocationString(IN HDEVINFO DeviceInfoSet
,
322 IN PSP_DEVINFO_DATA DeviceInfoData
,
323 IN DEVINST dnParentDevInst OPTIONAL
,
332 DWORD dwSize
, dwType
;
335 DataSize
= BufferSize
* sizeof(WCHAR
);
338 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
344 if (hKey
!= INVALID_HANDLE_VALUE
)
346 /* query the LocationInformationOverride value */
348 if (RegQueryValueEx(hKey
,
349 L
"LocationInformationOverride",
353 &dwSize
) == ERROR_SUCCESS
&&
355 szBuffer
[0] != L
'\0')
370 if (dnParentDevInst
!= 0)
372 /* query the parent node name */
373 if (CM_Get_DevNode_Registry_Property(dnParentDevInst
,
379 RegDataType
== REG_SZ
&&
380 LoadAndFormatString(hDllInstance
,
388 szBuffer
[BufferSize
- 1] = L
'\0';
389 LocalFree((HLOCAL
)szFormatted
);
393 else if (DeviceInfoData
->DevInst
!= 0)
395 cRet
= CM_Get_DevNode_Registry_Property(DeviceInfoData
->DevInst
,
396 CM_DRP_LOCATION_INFORMATION
,
401 if (cRet
== CR_SUCCESS
&& RegDataType
== REG_SZ
)
403 /* FIXME - check string for NULL termination! */
407 if (Ret
&& szBuffer
[0] >= L
'0' && szBuffer
[0] <= L
'9')
409 /* convert the string to an integer value and create a
411 ULONG ulLocation
= (ULONG
)wcstoul(szBuffer
,
414 if (LoadAndFormatString(hDllInstance
,
423 szBuffer
[BufferSize
- 1] = L
'\0';
424 LocalFree((HLOCAL
)szFormatted
);
433 LoadString(hDllInstance
,
446 GetDeviceStatusString(IN DEVINST DevInst
,
447 IN HMACHINE hMachine
,
452 ULONG Status
, ProblemNumber
;
453 UINT MessageId
= IDS_UNKNOWN
;
457 cr
= CM_Get_DevNode_Status_Ex(&Status
,
462 if (cr
== CR_SUCCESS
)
464 if (Status
& DN_HAS_PROBLEM
)
468 uRet
= DeviceProblemText(hMachine
,
472 (BufferSize
!= 0 ? BufferSize
: BufferSize
- 1));
474 Ret
= (uRet
!= 0 && uRet
< BufferSize
);
478 if (!(Status
& (DN_DRIVER_LOADED
| DN_STARTED
)))
480 MessageId
= IDS_NODRIVERLOADED
;
484 MessageId
= IDS_DEV_NO_PROBLEM
;
493 if (LoadString(hDllInstance
,
507 GetDriverProviderString(IN HDEVINFO DeviceInfoSet
,
508 IN PSP_DEVINFO_DATA DeviceInfoData
,
513 DWORD dwSize
, dwType
;
518 /* get driver provider, date and version */
519 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
525 if (hKey
!= INVALID_HANDLE_VALUE
)
527 /* query the driver provider */
529 if (RegQueryValueEx(hKey
,
530 REGSTR_VAL_PROVIDER_NAME
,
534 &dwSize
) == ERROR_SUCCESS
&&
536 szBuffer
[0] != L
'\0')
548 if (szBuffer
[0] == L
'\0')
550 /* unable to query the information */
551 if (LoadString(hDllInstance
,
565 GetDriverVersionString(IN HDEVINFO DeviceInfoSet
,
566 IN PSP_DEVINFO_DATA DeviceInfoData
,
571 DWORD dwSize
, dwType
;
576 /* get driver provider, date and version */
577 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
583 if (hKey
!= INVALID_HANDLE_VALUE
)
585 /* query the driver provider */
587 if (RegQueryValueEx(hKey
,
592 &dwSize
) == ERROR_SUCCESS
&&
594 szBuffer
[0] != L
'\0')
606 if (szBuffer
[0] == L
'\0')
608 /* unable to query the information */
609 if (LoadString(hDllInstance
,
622 GetDriverDateString(IN HDEVINFO DeviceInfoSet
,
623 IN PSP_DEVINFO_DATA DeviceInfoData
,
629 SYSTEMTIME SystemTime
, LocalTime
;
630 DWORD dwSize
, dwType
;
635 /* get driver provider, date and version */
636 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
642 if (hKey
!= INVALID_HANDLE_VALUE
)
644 /* query the driver provider */
645 dwSize
= sizeof(FILETIME
);
646 if (RegQueryValueEx(hKey
,
651 &dwSize
) == ERROR_SUCCESS
&&
652 dwType
== REG_BINARY
&&
653 dwSize
== sizeof(FILETIME
) &&
654 FileTimeToSystemTime(&DriverDate
,
656 SystemTimeToTzSpecificLocalTime(NULL
,
659 GetDateFormat(LOCALE_USER_DEFAULT
,
674 /* unable to query the information */
675 if (LoadString(hDllInstance
,
690 IsDeviceHidden(IN DEVINST DevInst
,
691 IN HMACHINE hMachine
,
695 ULONG Status
, ProblemNumber
;
698 cr
= CM_Get_DevNode_Status_Ex(&Status
,
703 if (cr
== CR_SUCCESS
)
705 *IsHidden
= ((Status
& DN_NO_SHOW_IN_DM
) != 0);
714 CanDisableDevice(IN DEVINST DevInst
,
715 IN HMACHINE hMachine
,
716 OUT BOOL
*CanDisable
)
719 ULONG Status
, ProblemNumber
;
722 cr
= CM_Get_DevNode_Status_Ex(&Status
,
727 if (cr
== CR_SUCCESS
)
729 *CanDisable
= ((Status
& DN_DISABLEABLE
) != 0);
738 IsDeviceStarted(IN DEVINST DevInst
,
739 IN HMACHINE hMachine
,
743 ULONG Status
, ProblemNumber
;
746 cr
= CM_Get_DevNode_Status_Ex(&Status
,
751 if (cr
== CR_SUCCESS
)
753 *IsStarted
= ((Status
& DN_STARTED
) != 0);
762 IsDriverInstalled(IN DEVINST DevInst
,
763 IN HMACHINE hMachine
,
767 ULONG Status
, ProblemNumber
;
770 cr
= CM_Get_DevNode_Status_Ex(&Status
,
775 if (cr
== CR_SUCCESS
)
777 *Installed
= ((Status
& DN_HAS_PROBLEM
) != 0 ||
778 (Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
787 EnableDevice(IN HDEVINFO DeviceInfoSet
,
788 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
,
790 IN DWORD HardwareProfile OPTIONAL
,
791 OUT BOOL
*bNeedReboot OPTIONAL
)
793 SP_PROPCHANGE_PARAMS pcp
;
794 SP_DEVINSTALL_PARAMS dp
;
798 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
799 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
800 pcp
.HwProfile
= HardwareProfile
;
804 /* try to enable the device on the global profile */
805 pcp
.StateChange
= DICS_ENABLE
;
806 pcp
.Scope
= DICS_FLAG_GLOBAL
;
809 LastErr
= GetLastError();
810 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
812 &pcp
.ClassInstallHeader
,
813 sizeof(SP_PROPCHANGE_PARAMS
)))
815 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
819 SetLastError(LastErr
);
822 /* try config-specific */
823 pcp
.StateChange
= (bEnable
? DICS_ENABLE
: DICS_DISABLE
);
824 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
826 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
828 &pcp
.ClassInstallHeader
,
829 sizeof(SP_PROPCHANGE_PARAMS
)) &&
830 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
834 dp
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
835 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
839 if (bNeedReboot
!= NULL
)
841 *bNeedReboot
= ((dp
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
852 GetDeviceTypeString(IN PSP_DEVINFO_DATA DeviceInfoData
,
858 if (!SetupDiGetClassDescription(&DeviceInfoData
->ClassGuid
,
864 if (LoadString(hDllInstance
,
874 /* FIXME - check string for NULL termination! */
883 GetDeviceDescriptionString(IN HDEVINFO DeviceInfoSet
,
884 IN PSP_DEVINFO_DATA DeviceInfoData
,
891 if ((SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
896 BufferSize
* sizeof(WCHAR
),
898 SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
903 BufferSize
* sizeof(WCHAR
),
905 RegDataType
== REG_SZ
)
907 /* FIXME - check string for NULL termination! */
913 if (LoadString(hDllInstance
,
927 FindCurrentDriver(IN HDEVINFO DeviceInfoSet
,
928 IN PSP_DEVINFO_DATA DeviceInfoData
,
929 OUT PSP_DRVINFO_DATA DriverInfoData
)
931 HKEY hKey
= INVALID_HANDLE_VALUE
;
932 SP_DEVINSTALL_PARAMS InstallParams
= {0};
933 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData
= {0};
934 WCHAR InfPath
[MAX_PATH
];
935 WCHAR InfSection
[LINE_LEN
];
936 DWORD dwType
, dwLength
;
941 /* Steps to find the right driver:
942 * 1) Get the device install parameters
943 * 2) Open the driver registry key
944 * 3) Read the .inf file name
945 * 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name
946 * 5) Build class driver list
947 * 6) Read inf section and inf section extension from registry
948 * 7) Enumerate drivers
949 * 8) Find the one who is in the same section as current driver?
952 /* 1) Get the install params */
953 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
954 if (!SetupDiGetDeviceInstallParams(DeviceInfoSet
,
958 DPRINT1("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
962 #ifdef DI_FLAGSEX_INSTALLEDDRIVER
963 InstallParams
.FlagsEx
|= (DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
964 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
968 if (SetupDiBuildDriverInfoList(DeviceInfoSet
,
970 SPDIT_CLASSDRIVER
) &&
971 SetupDiEnumDriverInfo(DeviceInfoSet
,
982 InstallParams
.FlagsEx
&= ~(DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
985 /* 2) Open the driver registry key */
986 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
992 if (hKey
== INVALID_HANDLE_VALUE
)
994 DPRINT1("SetupDiOpenDevRegKey() failed with error 0x%lx\n", GetLastError());
998 /* 3) Read the .inf file name */
999 dwLength
= (sizeof(InfPath
) / sizeof(InfPath
[0])) - 1;
1000 rc
= RegQueryValueEx(hKey
,
1006 if (rc
!= ERROR_SUCCESS
)
1009 DPRINT1("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1012 else if (dwType
!= REG_SZ
)
1014 SetLastError(ERROR_GEN_FAILURE
);
1015 DPRINT1("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1018 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1020 /* 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name */
1021 InstallParams
.Flags
|= DI_ENUMSINGLEINF
;
1022 InstallParams
.FlagsEx
|= DI_FLAGSEX_ALLOWEXCLUDEDDRVS
;
1023 wcscpy(InstallParams
.DriverPath
, InfPath
);
1024 if (!SetupDiSetDeviceInstallParams(DeviceInfoSet
,
1028 DPRINT1("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
1032 /* 5) Build class driver list */
1033 if (!SetupDiBuildDriverInfoList(DeviceInfoSet
,
1037 DPRINT1("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
1041 /* 6) Read inf section and from registry */
1042 dwLength
= (sizeof(InfSection
) / sizeof(InfSection
[0])) - 1;
1043 rc
= RegQueryValueEx(hKey
,
1044 REGSTR_VAL_INFSECTION
,
1049 if (rc
!= ERROR_SUCCESS
)
1052 DPRINT1("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1055 else if (dwType
!= REG_SZ
)
1057 SetLastError(ERROR_GEN_FAILURE
);
1058 DPRINT1("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1061 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1063 /* 7) Enumerate drivers */
1064 DriverInfoData
->cbSize
= sizeof(SP_DRVINFO_DATA
);
1065 DriverInfoDetailData
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
1066 while (SetupDiEnumDriverInfo(DeviceInfoSet
,
1072 /* 8) Find the one who is in the same section as current driver */
1073 if (!SetupDiGetDriverInfoDetail(DeviceInfoSet
,
1076 &DriverInfoDetailData
,
1077 DriverInfoDetailData
.cbSize
,
1079 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1081 DPRINT1("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", GetLastError());
1084 if (!wcsicmp(DriverInfoDetailData
.SectionName
,
1087 /* We have found the right driver */
1094 if (GetLastError() != ERROR_NO_MORE_ITEMS
)
1096 DPRINT1("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
1100 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1103 if (hKey
!= INVALID_HANDLE_VALUE
)
1110 LoadAndInitComctl32(VOID
)
1112 typedef VOID (WINAPI
*PINITCOMMONCONTROLS
)(VOID
);
1113 PINITCOMMONCONTROLS pInitCommonControls
;
1114 HINSTANCE hComCtl32
;
1116 hComCtl32
= LoadLibrary(L
"comctl32.dll");
1117 if (hComCtl32
!= NULL
)
1119 /* initialize the common controls */
1120 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hComCtl32
,
1121 "InitCommonControls");
1122 if (pInitCommonControls
== NULL
)
1124 FreeLibrary(hComCtl32
);
1128 pInitCommonControls();
1137 DllMain(IN HINSTANCE hinstDLL
,
1139 IN LPVOID lpvReserved
)
1143 case DLL_PROCESS_ATTACH
:
1144 DisableThreadLibraryCalls(hinstDLL
);
1145 hDllInstance
= hinstDLL
;