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
20 * PROJECT: ReactOS devmgr.dll
21 * FILE: lib/devmgr/misc.c
22 * PURPOSE: ReactOS Device Manager
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
29 #include <devmgr/devmgr.h>
30 #include "properties.h"
35 LengthOfStrResource(IN HINSTANCE hInst
,
47 /* There are always blocks of 16 strings */
48 lpName
= (LPWSTR
)MAKEINTRESOURCE((uID
>> 4) + 1);
50 /* Find the string table block */
51 if ((hrSrc
= FindResourceW(hInst
, lpName
, (LPWSTR
)RT_STRING
)) &&
52 (hRes
= LoadResource(hInst
, hrSrc
)) &&
53 (lpStr
= (LPWSTR
)LockResource(hRes
)))
57 /* Find the string we're looking for */
58 uID
&= 0xF; /* position in the block, same as % 16 */
59 for (x
= 0; x
< uID
; x
++)
61 lpStr
+= (*lpStr
) + 1;
64 /* Found the string */
72 AllocAndLoadString(OUT LPWSTR
*lpTarget
,
78 ln
= LengthOfStrResource(hInst
,
82 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
84 if ((*lpTarget
) != NULL
)
87 if (!(Ret
= LoadStringW(hInst
, uID
, *lpTarget
, ln
)))
89 LocalFree((HLOCAL
)(*lpTarget
));
99 AllocAndLoadStringsCat(OUT LPWSTR
*lpTarget
,
111 ln
+= LengthOfStrResource(hInst
,
117 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
118 (ln
+ 1) * sizeof(WCHAR
));
119 if ((*lpTarget
) != NULL
)
121 LPWSTR s
= *lpTarget
;
128 if (!(Ret
= LoadStringW(hInst
, uID
[i
], s
, ln
)))
130 LocalFree((HLOCAL
)(*lpTarget
));
137 return s
- *lpTarget
;
145 LoadAndFormatString(IN HINSTANCE hInstance
,
147 OUT LPWSTR
*lpTarget
,
154 if (AllocAndLoadString(&lpFormat
,
158 va_start(lArgs
, lpTarget
);
159 /* let's use FormatMessage to format it because it has the ability to allocate
160 memory automatically */
161 Ret
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
170 LocalFree((HLOCAL
)lpFormat
);
178 LoadAndFormatStringsCat(IN HINSTANCE hInstance
,
181 OUT LPWSTR
*lpTarget
,
188 if (AllocAndLoadStringsCat(&lpFormat
,
193 va_start(lArgs
, lpTarget
);
194 /* let's use FormatMessage to format it because it has the ability to allocate
195 memory automatically */
196 Ret
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
205 LocalFree((HLOCAL
)lpFormat
);
213 ListViewGetSelectedItemData(IN HWND hwnd
)
217 Index
= ListView_GetNextItem(hwnd
,
224 li
.mask
= LVIF_PARAM
;
228 if (ListView_GetItem(hwnd
,
240 ConvertMultiByteToUnicode(IN LPCSTR lpMultiByteStr
,
246 nLength
= MultiByteToWideChar(uCodePage
,
255 lpUnicodeStr
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
257 nLength
* sizeof(WCHAR
));
258 if (lpUnicodeStr
== NULL
)
260 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
264 if (!MultiByteToWideChar(uCodePage
,
271 HeapFree(GetProcessHeap(),
282 GetDeviceManufacturerString(IN HDEVINFO DeviceInfoSet
,
283 IN PSP_DEVINFO_DATA DeviceInfoData
,
290 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
295 BufferSize
* sizeof(WCHAR
),
297 RegDataType
!= REG_SZ
)
300 if (LoadString(hDllInstance
,
310 /* FIXME - check string for NULL termination! */
319 GetDeviceLocationString(IN HDEVINFO DeviceInfoSet
,
320 IN PSP_DEVINFO_DATA DeviceInfoData
,
321 IN DEVINST dnParentDevInst OPTIONAL
,
330 DWORD dwSize
, dwType
;
333 DataSize
= BufferSize
* sizeof(WCHAR
);
336 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
342 if (hKey
!= INVALID_HANDLE_VALUE
)
344 /* query the LocationInformationOverride value */
346 if (RegQueryValueEx(hKey
,
347 L
"LocationInformationOverride",
351 &dwSize
) == ERROR_SUCCESS
&&
353 szBuffer
[0] != L
'\0')
368 if (dnParentDevInst
!= 0)
370 /* query the parent node name */
371 if (CM_Get_DevNode_Registry_Property(dnParentDevInst
,
377 RegDataType
== REG_SZ
&&
378 LoadAndFormatString(hDllInstance
,
386 szBuffer
[BufferSize
- 1] = L
'\0';
387 LocalFree((HLOCAL
)szFormatted
);
391 else if (DeviceInfoData
->DevInst
!= 0)
393 cRet
= CM_Get_DevNode_Registry_Property(DeviceInfoData
->DevInst
,
394 CM_DRP_LOCATION_INFORMATION
,
399 if (cRet
== CR_SUCCESS
&& RegDataType
== REG_SZ
)
401 /* FIXME - check string for NULL termination! */
405 if (Ret
&& szBuffer
[0] >= L
'0' && szBuffer
[0] <= L
'9')
407 /* convert the string to an integer value and create a
409 ULONG ulLocation
= (ULONG
)wcstoul(szBuffer
,
412 if (LoadAndFormatString(hDllInstance
,
421 szBuffer
[BufferSize
- 1] = L
'\0';
422 LocalFree((HLOCAL
)szFormatted
);
431 LoadString(hDllInstance
,
444 GetDeviceStatusString(IN DEVINST DevInst
,
445 IN HMACHINE hMachine
,
450 ULONG Status
, ProblemNumber
;
451 UINT MessageId
= IDS_UNKNOWN
;
455 cr
= CM_Get_DevNode_Status_Ex(&Status
,
460 if (cr
== CR_SUCCESS
)
462 if (Status
& DN_HAS_PROBLEM
)
466 uRet
= DeviceProblemTextW(hMachine
,
470 (BufferSize
!= 0 ? BufferSize
: BufferSize
- 1));
472 Ret
= (uRet
!= 0 && uRet
< BufferSize
);
476 if (!(Status
& (DN_DRIVER_LOADED
| DN_STARTED
)))
478 MessageId
= IDS_NODRIVERLOADED
;
482 MessageId
= IDS_DEV_NO_PROBLEM
;
491 if (LoadString(hDllInstance
,
505 GetDriverProviderString(IN HDEVINFO DeviceInfoSet
,
506 IN PSP_DEVINFO_DATA DeviceInfoData
,
511 DWORD dwSize
, dwType
;
516 /* get driver provider, date and version */
517 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
523 if (hKey
!= INVALID_HANDLE_VALUE
)
525 /* query the driver provider */
527 if (RegQueryValueEx(hKey
,
528 REGSTR_VAL_PROVIDER_NAME
,
532 &dwSize
) == ERROR_SUCCESS
&&
534 szBuffer
[0] != L
'\0')
546 if (szBuffer
[0] == L
'\0')
548 /* unable to query the information */
549 if (LoadString(hDllInstance
,
563 GetDriverVersionString(IN HDEVINFO DeviceInfoSet
,
564 IN PSP_DEVINFO_DATA DeviceInfoData
,
569 DWORD dwSize
, dwType
;
574 /* get driver provider, date and version */
575 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
581 if (hKey
!= INVALID_HANDLE_VALUE
)
583 /* query the driver provider */
585 if (RegQueryValueEx(hKey
,
590 &dwSize
) == ERROR_SUCCESS
&&
592 szBuffer
[0] != L
'\0')
604 if (szBuffer
[0] == L
'\0')
606 /* unable to query the information */
607 if (LoadString(hDllInstance
,
620 GetDriverDateString(IN HDEVINFO DeviceInfoSet
,
621 IN PSP_DEVINFO_DATA DeviceInfoData
,
627 SYSTEMTIME SystemTime
, LocalTime
;
628 DWORD dwSize
, dwType
;
633 /* get driver provider, date and version */
634 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
640 if (hKey
!= INVALID_HANDLE_VALUE
)
642 /* query the driver provider */
643 dwSize
= sizeof(FILETIME
);
644 if (RegQueryValueEx(hKey
,
649 &dwSize
) == ERROR_SUCCESS
&&
650 dwType
== REG_BINARY
&&
651 dwSize
== sizeof(FILETIME
) &&
652 FileTimeToSystemTime(&DriverDate
,
654 SystemTimeToTzSpecificLocalTime(NULL
,
657 GetDateFormat(LOCALE_USER_DEFAULT
,
672 /* unable to query the information */
673 if (LoadString(hDllInstance
,
688 IsDeviceHidden(IN DEVINST DevInst
,
689 IN HMACHINE hMachine
,
693 ULONG Status
, ProblemNumber
;
696 cr
= CM_Get_DevNode_Status_Ex(&Status
,
701 if (cr
== CR_SUCCESS
)
703 *IsHidden
= ((Status
& DN_NO_SHOW_IN_DM
) != 0);
712 CanDisableDevice(IN DEVINST DevInst
,
713 IN HMACHINE hMachine
,
714 OUT BOOL
*CanDisable
)
717 ULONG Status
, ProblemNumber
;
720 cr
= CM_Get_DevNode_Status_Ex(&Status
,
725 if (cr
== CR_SUCCESS
)
727 *CanDisable
= ((Status
& DN_DISABLEABLE
) != 0);
736 IsDeviceStarted(IN DEVINST DevInst
,
737 IN HMACHINE hMachine
,
741 ULONG Status
, ProblemNumber
;
744 cr
= CM_Get_DevNode_Status_Ex(&Status
,
749 if (cr
== CR_SUCCESS
)
751 *IsStarted
= ((Status
& DN_STARTED
) != 0);
760 IsDriverInstalled(IN DEVINST DevInst
,
761 IN HMACHINE hMachine
,
765 ULONG Status
, ProblemNumber
;
768 cr
= CM_Get_DevNode_Status_Ex(&Status
,
773 if (cr
== CR_SUCCESS
)
775 *Installed
= ((Status
& DN_HAS_PROBLEM
) != 0 ||
776 (Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
785 EnableDevice(IN HDEVINFO DeviceInfoSet
,
786 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
,
788 IN DWORD HardwareProfile OPTIONAL
,
789 OUT BOOL
*bNeedReboot OPTIONAL
)
791 SP_PROPCHANGE_PARAMS pcp
;
792 SP_DEVINSTALL_PARAMS dp
;
796 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
797 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
798 pcp
.HwProfile
= HardwareProfile
;
802 /* try to enable the device on the global profile */
803 pcp
.StateChange
= DICS_ENABLE
;
804 pcp
.Scope
= DICS_FLAG_GLOBAL
;
807 LastErr
= GetLastError();
808 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
810 &pcp
.ClassInstallHeader
,
811 sizeof(SP_PROPCHANGE_PARAMS
)))
813 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
817 SetLastError(LastErr
);
820 /* try config-specific */
821 pcp
.StateChange
= (bEnable
? DICS_ENABLE
: DICS_DISABLE
);
822 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
824 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
826 &pcp
.ClassInstallHeader
,
827 sizeof(SP_PROPCHANGE_PARAMS
)) &&
828 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
832 dp
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
833 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
837 if (bNeedReboot
!= NULL
)
839 *bNeedReboot
= ((dp
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
850 GetDeviceTypeString(IN PSP_DEVINFO_DATA DeviceInfoData
,
856 if (!SetupDiGetClassDescription(&DeviceInfoData
->ClassGuid
,
862 if (LoadString(hDllInstance
,
872 /* FIXME - check string for NULL termination! */
881 GetDeviceDescriptionString(IN HDEVINFO DeviceInfoSet
,
882 IN PSP_DEVINFO_DATA DeviceInfoData
,
889 if ((SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
894 BufferSize
* sizeof(WCHAR
),
896 SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
901 BufferSize
* sizeof(WCHAR
),
903 RegDataType
== REG_SZ
)
905 /* FIXME - check string for NULL termination! */
911 if (LoadString(hDllInstance
,
925 FindCurrentDriver(IN HDEVINFO DeviceInfoSet
,
926 IN PSP_DEVINFO_DATA DeviceInfoData
,
927 OUT PSP_DRVINFO_DATA DriverInfoData
)
929 HKEY hKey
= (HKEY
)INVALID_HANDLE_VALUE
;
930 SP_DEVINSTALL_PARAMS InstallParams
= {0};
931 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData
= {0};
932 WCHAR InfPath
[MAX_PATH
];
933 WCHAR InfSection
[LINE_LEN
];
934 DWORD dwType
, dwLength
;
939 /* Steps to find the right driver:
940 * 1) Get the device install parameters
941 * 2) Open the driver registry key
942 * 3) Read the .inf file name
943 * 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name
944 * 5) Build class driver list
945 * 6) Read inf section and inf section extension from registry
946 * 7) Enumerate drivers
947 * 8) Find the one who is in the same section as current driver?
950 /* 1) Get the install params */
951 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
952 if (!SetupDiGetDeviceInstallParams(DeviceInfoSet
,
956 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
960 #ifdef DI_FLAGSEX_INSTALLEDDRIVER
961 InstallParams
.FlagsEx
|= (DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
962 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
966 if (SetupDiBuildDriverInfoList(DeviceInfoSet
,
968 SPDIT_CLASSDRIVER
) &&
969 SetupDiEnumDriverInfo(DeviceInfoSet
,
980 InstallParams
.FlagsEx
&= ~(DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
983 /* 2) Open the driver registry key */
984 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
990 if (hKey
== INVALID_HANDLE_VALUE
)
992 ERR("SetupDiOpenDevRegKey() failed with error 0x%lx\n", GetLastError());
996 /* 3) Read the .inf file name */
997 dwLength
= (sizeof(InfPath
) / sizeof(InfPath
[0])) - 1;
998 rc
= RegQueryValueEx(hKey
,
1004 if (rc
!= ERROR_SUCCESS
)
1006 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1010 else if (dwType
!= REG_SZ
)
1012 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1013 SetLastError(ERROR_GEN_FAILURE
);
1016 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1018 /* 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name */
1019 InstallParams
.Flags
|= DI_ENUMSINGLEINF
;
1020 InstallParams
.FlagsEx
|= DI_FLAGSEX_ALLOWEXCLUDEDDRVS
;
1021 wcscpy(InstallParams
.DriverPath
, InfPath
);
1022 if (!SetupDiSetDeviceInstallParams(DeviceInfoSet
,
1026 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
1030 /* 5) Build class driver list */
1031 if (!SetupDiBuildDriverInfoList(DeviceInfoSet
,
1035 ERR("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
1039 /* 6) Read inf section and from registry */
1040 dwLength
= (sizeof(InfSection
) / sizeof(InfSection
[0])) - 1;
1041 rc
= RegQueryValueEx(hKey
,
1042 REGSTR_VAL_INFSECTION
,
1047 if (rc
!= ERROR_SUCCESS
)
1049 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1053 else if (dwType
!= REG_SZ
)
1055 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1056 SetLastError(ERROR_GEN_FAILURE
);
1059 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1061 /* 7) Enumerate drivers */
1062 DriverInfoData
->cbSize
= sizeof(SP_DRVINFO_DATA
);
1063 DriverInfoDetailData
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
1064 while (SetupDiEnumDriverInfo(DeviceInfoSet
,
1070 /* 8) Find the one who is in the same section as current driver */
1071 if (!SetupDiGetDriverInfoDetail(DeviceInfoSet
,
1074 &DriverInfoDetailData
,
1075 DriverInfoDetailData
.cbSize
,
1077 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1079 ERR("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", GetLastError());
1082 if (!_wcsicmp(DriverInfoDetailData
.SectionName
,
1085 /* We have found the right driver */
1092 if (GetLastError() != ERROR_NO_MORE_ITEMS
)
1094 ERR("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
1098 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1101 if (hKey
!= INVALID_HANDLE_VALUE
)
1108 LoadAndInitComctl32(VOID
)
1110 typedef VOID (WINAPI
*PINITCOMMONCONTROLS
)(VOID
);
1111 PINITCOMMONCONTROLS pInitCommonControls
;
1112 HINSTANCE hComCtl32
;
1114 hComCtl32
= LoadLibrary(L
"comctl32.dll");
1115 if (hComCtl32
!= NULL
)
1117 /* initialize the common controls */
1118 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hComCtl32
,
1119 "InitCommonControls");
1120 if (pInitCommonControls
== NULL
)
1122 FreeLibrary(hComCtl32
);
1126 pInitCommonControls();
1134 GetDeviceAndComputerName(LPWSTR lpString
,
1136 WCHAR szMachineName
[])
1140 szDeviceID
[0] = L
'\0';
1141 szMachineName
[0] = L
'\0';
1143 while (*lpString
!= L
'\0')
1145 if (*lpString
== L
'/')
1148 if (!_wcsnicmp(lpString
, L
"DeviceID", 8))
1151 if (*lpString
!= L
'\0')
1154 while ((*lpString
!= L
' ') &&
1155 (*lpString
!= L
'\0') &&
1156 (i
<= MAX_DEVICE_ID_LEN
))
1158 szDeviceID
[i
++] = *lpString
++;
1160 szDeviceID
[i
] = L
'\0';
1164 else if (!_wcsnicmp(lpString
, L
"MachineName", 11))
1167 if (*lpString
!= L
'\0')
1170 while ((*lpString
!= L
' ') &&
1171 (*lpString
!= L
'\0') &&
1172 (i
<= MAX_COMPUTERNAME_LENGTH
))
1174 szMachineName
[i
++] = *lpString
++;
1176 szMachineName
[i
] = L
'\0';
1179 /* knock the pointer back one and let the next
1180 * pointer deal with incrementing, otherwise we
1181 * go past the end of the string */