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"
36 LengthOfStrResource(IN HINSTANCE hInst
,
48 /* There are always blocks of 16 strings */
49 lpName
= (LPWSTR
)MAKEINTRESOURCE((uID
>> 4) + 1);
51 /* Find the string table block */
52 if ((hrSrc
= FindResourceW(hInst
, lpName
, (LPWSTR
)RT_STRING
)) &&
53 (hRes
= LoadResource(hInst
, hrSrc
)) &&
54 (lpStr
= (LPWSTR
)LockResource(hRes
)))
58 /* Find the string we're looking for */
59 uID
&= 0xF; /* position in the block, same as % 16 */
60 for (x
= 0; x
< uID
; x
++)
62 lpStr
+= (*lpStr
) + 1;
65 /* Found the string */
73 AllocAndLoadString(OUT LPWSTR
*lpTarget
,
79 ln
= LengthOfStrResource(hInst
,
83 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
85 if ((*lpTarget
) != NULL
)
88 if (!(Ret
= LoadStringW(hInst
, uID
, *lpTarget
, ln
)))
90 LocalFree((HLOCAL
)(*lpTarget
));
100 AllocAndLoadStringsCat(OUT LPWSTR
*lpTarget
,
112 ln
+= LengthOfStrResource(hInst
,
118 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
119 (ln
+ 1) * sizeof(WCHAR
));
120 if ((*lpTarget
) != NULL
)
122 LPWSTR s
= *lpTarget
;
129 if (!(Ret
= LoadStringW(hInst
, uID
[i
], s
, ln
)))
131 LocalFree((HLOCAL
)(*lpTarget
));
138 return s
- *lpTarget
;
146 LoadAndFormatString(IN HINSTANCE hInstance
,
148 OUT LPWSTR
*lpTarget
,
155 if (AllocAndLoadString(&lpFormat
,
159 va_start(lArgs
, lpTarget
);
160 /* let's use FormatMessage to format it because it has the ability to allocate
161 memory automatically */
162 Ret
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
171 LocalFree((HLOCAL
)lpFormat
);
179 LoadAndFormatStringsCat(IN HINSTANCE hInstance
,
182 OUT LPWSTR
*lpTarget
,
189 if (AllocAndLoadStringsCat(&lpFormat
,
194 va_start(lArgs
, lpTarget
);
195 /* let's use FormatMessage to format it because it has the ability to allocate
196 memory automatically */
197 Ret
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
206 LocalFree((HLOCAL
)lpFormat
);
214 ListViewGetSelectedItemData(IN HWND hwnd
)
218 Index
= ListView_GetNextItem(hwnd
,
225 li
.mask
= LVIF_PARAM
;
229 if (ListView_GetItem(hwnd
,
241 ConvertMultiByteToUnicode(IN LPCSTR lpMultiByteStr
,
247 nLength
= MultiByteToWideChar(uCodePage
,
256 lpUnicodeStr
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
258 nLength
* sizeof(WCHAR
));
259 if (lpUnicodeStr
== NULL
)
261 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
265 if (!MultiByteToWideChar(uCodePage
,
272 HeapFree(GetProcessHeap(),
283 GetDeviceManufacturerString(IN HDEVINFO DeviceInfoSet
,
284 IN PSP_DEVINFO_DATA DeviceInfoData
,
291 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
296 BufferSize
* sizeof(WCHAR
),
298 RegDataType
!= REG_SZ
)
301 if (LoadString(hDllInstance
,
311 /* FIXME - check string for NULL termination! */
320 GetDeviceLocationString(IN HDEVINFO DeviceInfoSet
,
321 IN PSP_DEVINFO_DATA DeviceInfoData
,
322 IN DEVINST dnParentDevInst OPTIONAL
,
331 DWORD dwSize
, dwType
;
334 DataSize
= BufferSize
* sizeof(WCHAR
);
337 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
343 if (hKey
!= INVALID_HANDLE_VALUE
)
345 /* query the LocationInformationOverride value */
347 if (RegQueryValueEx(hKey
,
348 L
"LocationInformationOverride",
352 &dwSize
) == ERROR_SUCCESS
&&
354 szBuffer
[0] != L
'\0')
369 if (dnParentDevInst
!= 0)
371 /* query the parent node name */
372 if (CM_Get_DevNode_Registry_Property(dnParentDevInst
,
378 RegDataType
== REG_SZ
&&
379 LoadAndFormatString(hDllInstance
,
387 szBuffer
[BufferSize
- 1] = L
'\0';
388 LocalFree((HLOCAL
)szFormatted
);
392 else if (DeviceInfoData
->DevInst
!= 0)
394 cRet
= CM_Get_DevNode_Registry_Property(DeviceInfoData
->DevInst
,
395 CM_DRP_LOCATION_INFORMATION
,
400 if (cRet
== CR_SUCCESS
&& RegDataType
== REG_SZ
)
402 /* FIXME - check string for NULL termination! */
406 if (Ret
&& szBuffer
[0] >= L
'0' && szBuffer
[0] <= L
'9')
408 /* convert the string to an integer value and create a
410 ULONG ulLocation
= (ULONG
)wcstoul(szBuffer
,
413 if (LoadAndFormatString(hDllInstance
,
422 szBuffer
[BufferSize
- 1] = L
'\0';
423 LocalFree((HLOCAL
)szFormatted
);
432 LoadString(hDllInstance
,
445 GetDeviceStatusString(IN DEVINST DevInst
,
446 IN HMACHINE hMachine
,
451 ULONG Status
, ProblemNumber
;
452 UINT MessageId
= IDS_UNKNOWN
;
456 cr
= CM_Get_DevNode_Status_Ex(&Status
,
461 if (cr
== CR_SUCCESS
)
463 if (Status
& DN_HAS_PROBLEM
)
467 uRet
= DeviceProblemTextW(hMachine
,
471 (BufferSize
!= 0 ? BufferSize
: BufferSize
- 1));
473 Ret
= (uRet
!= 0 && uRet
< BufferSize
);
477 if (!(Status
& (DN_DRIVER_LOADED
| DN_STARTED
)))
479 MessageId
= IDS_NODRIVERLOADED
;
483 MessageId
= IDS_DEV_NO_PROBLEM
;
492 if (LoadString(hDllInstance
,
506 GetDriverProviderString(IN HDEVINFO DeviceInfoSet
,
507 IN PSP_DEVINFO_DATA DeviceInfoData
,
512 DWORD dwSize
, dwType
;
517 /* get driver provider, date and version */
518 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
524 if (hKey
!= INVALID_HANDLE_VALUE
)
526 /* query the driver provider */
528 if (RegQueryValueEx(hKey
,
529 REGSTR_VAL_PROVIDER_NAME
,
533 &dwSize
) == ERROR_SUCCESS
&&
535 szBuffer
[0] != L
'\0')
547 if (szBuffer
[0] == L
'\0')
549 /* unable to query the information */
550 if (LoadString(hDllInstance
,
564 GetDriverVersionString(IN HDEVINFO DeviceInfoSet
,
565 IN PSP_DEVINFO_DATA DeviceInfoData
,
570 DWORD dwSize
, dwType
;
575 /* get driver provider, date and version */
576 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
582 if (hKey
!= INVALID_HANDLE_VALUE
)
584 /* query the driver provider */
586 if (RegQueryValueEx(hKey
,
591 &dwSize
) == ERROR_SUCCESS
&&
593 szBuffer
[0] != L
'\0')
605 if (szBuffer
[0] == L
'\0')
607 /* unable to query the information */
608 if (LoadString(hDllInstance
,
621 GetDriverDateString(IN HDEVINFO DeviceInfoSet
,
622 IN PSP_DEVINFO_DATA DeviceInfoData
,
628 SYSTEMTIME SystemTime
, LocalTime
;
629 DWORD dwSize
, dwType
;
634 /* get driver provider, date and version */
635 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
641 if (hKey
!= INVALID_HANDLE_VALUE
)
643 /* query the driver provider */
644 dwSize
= sizeof(FILETIME
);
645 if (RegQueryValueEx(hKey
,
650 &dwSize
) == ERROR_SUCCESS
&&
651 dwType
== REG_BINARY
&&
652 dwSize
== sizeof(FILETIME
) &&
653 FileTimeToSystemTime(&DriverDate
,
655 SystemTimeToTzSpecificLocalTime(NULL
,
658 GetDateFormat(LOCALE_USER_DEFAULT
,
673 /* unable to query the information */
674 if (LoadString(hDllInstance
,
689 IsDeviceHidden(IN DEVINST DevInst
,
690 IN HMACHINE hMachine
,
694 ULONG Status
, ProblemNumber
;
697 cr
= CM_Get_DevNode_Status_Ex(&Status
,
702 if (cr
== CR_SUCCESS
)
704 *IsHidden
= ((Status
& DN_NO_SHOW_IN_DM
) != 0);
713 CanDisableDevice(IN DEVINST DevInst
,
714 IN HMACHINE hMachine
,
715 OUT BOOL
*CanDisable
)
718 ULONG Status
, ProblemNumber
;
721 cr
= CM_Get_DevNode_Status_Ex(&Status
,
726 if (cr
== CR_SUCCESS
)
728 *CanDisable
= ((Status
& DN_DISABLEABLE
) != 0);
737 IsDeviceStarted(IN DEVINST DevInst
,
738 IN HMACHINE hMachine
,
742 ULONG Status
, ProblemNumber
;
745 cr
= CM_Get_DevNode_Status_Ex(&Status
,
750 if (cr
== CR_SUCCESS
)
752 *IsStarted
= ((Status
& DN_STARTED
) != 0);
761 IsDriverInstalled(IN DEVINST DevInst
,
762 IN HMACHINE hMachine
,
766 ULONG Status
, ProblemNumber
;
769 cr
= CM_Get_DevNode_Status_Ex(&Status
,
774 if (cr
== CR_SUCCESS
)
776 *Installed
= ((Status
& DN_HAS_PROBLEM
) != 0 ||
777 (Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
786 EnableDevice(IN HDEVINFO DeviceInfoSet
,
787 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
,
789 IN DWORD HardwareProfile OPTIONAL
,
790 OUT BOOL
*bNeedReboot OPTIONAL
)
792 SP_PROPCHANGE_PARAMS pcp
;
793 SP_DEVINSTALL_PARAMS dp
;
797 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
798 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
799 pcp
.HwProfile
= HardwareProfile
;
803 /* try to enable the device on the global profile */
804 pcp
.StateChange
= DICS_ENABLE
;
805 pcp
.Scope
= DICS_FLAG_GLOBAL
;
808 LastErr
= GetLastError();
809 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
811 &pcp
.ClassInstallHeader
,
812 sizeof(SP_PROPCHANGE_PARAMS
)))
814 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
818 SetLastError(LastErr
);
821 /* try config-specific */
822 pcp
.StateChange
= (bEnable
? DICS_ENABLE
: DICS_DISABLE
);
823 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
825 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
827 &pcp
.ClassInstallHeader
,
828 sizeof(SP_PROPCHANGE_PARAMS
)) &&
829 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
833 dp
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
834 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
838 if (bNeedReboot
!= NULL
)
840 *bNeedReboot
= ((dp
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
851 GetDeviceTypeString(IN PSP_DEVINFO_DATA DeviceInfoData
,
857 if (!SetupDiGetClassDescription(&DeviceInfoData
->ClassGuid
,
863 if (LoadString(hDllInstance
,
873 /* FIXME - check string for NULL termination! */
882 GetDeviceDescriptionString(IN HDEVINFO DeviceInfoSet
,
883 IN PSP_DEVINFO_DATA DeviceInfoData
,
890 if ((SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
895 BufferSize
* sizeof(WCHAR
),
897 SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
902 BufferSize
* sizeof(WCHAR
),
904 RegDataType
== REG_SZ
)
906 /* FIXME - check string for NULL termination! */
912 if (LoadString(hDllInstance
,
926 FindCurrentDriver(IN HDEVINFO DeviceInfoSet
,
927 IN PSP_DEVINFO_DATA DeviceInfoData
,
928 OUT PSP_DRVINFO_DATA DriverInfoData
)
930 HKEY hKey
= (HKEY
)INVALID_HANDLE_VALUE
;
931 SP_DEVINSTALL_PARAMS InstallParams
= {0};
932 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData
= {0};
933 WCHAR InfPath
[MAX_PATH
];
934 WCHAR InfSection
[LINE_LEN
];
935 DWORD dwType
, dwLength
;
940 /* Steps to find the right driver:
941 * 1) Get the device install parameters
942 * 2) Open the driver registry key
943 * 3) Read the .inf file name
944 * 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name
945 * 5) Build class driver list
946 * 6) Read inf section and inf section extension from registry
947 * 7) Enumerate drivers
948 * 8) Find the one who is in the same section as current driver?
951 /* 1) Get the install params */
952 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
953 if (!SetupDiGetDeviceInstallParams(DeviceInfoSet
,
957 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
961 #ifdef DI_FLAGSEX_INSTALLEDDRIVER
962 InstallParams
.FlagsEx
|= (DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
963 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
967 if (SetupDiBuildDriverInfoList(DeviceInfoSet
,
969 SPDIT_CLASSDRIVER
) &&
970 SetupDiEnumDriverInfo(DeviceInfoSet
,
981 InstallParams
.FlagsEx
&= ~(DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
984 /* 2) Open the driver registry key */
985 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
991 if (hKey
== INVALID_HANDLE_VALUE
)
993 ERR("SetupDiOpenDevRegKey() failed with error 0x%lx\n", GetLastError());
997 /* 3) Read the .inf file name */
998 dwLength
= (sizeof(InfPath
) / sizeof(InfPath
[0])) - 1;
999 rc
= RegQueryValueEx(hKey
,
1005 if (rc
!= ERROR_SUCCESS
)
1007 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1011 else if (dwType
!= REG_SZ
)
1013 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1014 SetLastError(ERROR_GEN_FAILURE
);
1017 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1019 /* 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name */
1020 InstallParams
.Flags
|= DI_ENUMSINGLEINF
;
1021 InstallParams
.FlagsEx
|= DI_FLAGSEX_ALLOWEXCLUDEDDRVS
;
1022 wcscpy(InstallParams
.DriverPath
, InfPath
);
1023 if (!SetupDiSetDeviceInstallParams(DeviceInfoSet
,
1027 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
1031 /* 5) Build class driver list */
1032 if (!SetupDiBuildDriverInfoList(DeviceInfoSet
,
1036 ERR("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
1040 /* 6) Read inf section and from registry */
1041 dwLength
= (sizeof(InfSection
) / sizeof(InfSection
[0])) - 1;
1042 rc
= RegQueryValueEx(hKey
,
1043 REGSTR_VAL_INFSECTION
,
1048 if (rc
!= ERROR_SUCCESS
)
1050 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1054 else if (dwType
!= REG_SZ
)
1056 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1057 SetLastError(ERROR_GEN_FAILURE
);
1060 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1062 /* 7) Enumerate drivers */
1063 DriverInfoData
->cbSize
= sizeof(SP_DRVINFO_DATA
);
1064 DriverInfoDetailData
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
1065 while (SetupDiEnumDriverInfo(DeviceInfoSet
,
1071 /* 8) Find the one who is in the same section as current driver */
1072 if (!SetupDiGetDriverInfoDetail(DeviceInfoSet
,
1075 &DriverInfoDetailData
,
1076 DriverInfoDetailData
.cbSize
,
1078 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1080 ERR("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", GetLastError());
1083 if (!_wcsicmp(DriverInfoDetailData
.SectionName
,
1086 /* We have found the right driver */
1093 if (GetLastError() != ERROR_NO_MORE_ITEMS
)
1095 ERR("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
1099 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1102 if (hKey
!= INVALID_HANDLE_VALUE
)
1109 LoadAndInitComctl32(VOID
)
1111 typedef VOID (WINAPI
*PINITCOMMONCONTROLS
)(VOID
);
1112 PINITCOMMONCONTROLS pInitCommonControls
;
1113 HINSTANCE hComCtl32
;
1115 hComCtl32
= LoadLibrary(L
"comctl32.dll");
1116 if (hComCtl32
!= NULL
)
1118 /* initialize the common controls */
1119 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hComCtl32
,
1120 "InitCommonControls");
1121 if (pInitCommonControls
== NULL
)
1123 FreeLibrary(hComCtl32
);
1127 pInitCommonControls();
1135 GetDeviceAndComputerName(LPWSTR lpString
,
1137 WCHAR szMachineName
[])
1141 szDeviceID
[0] = L
'\0';
1142 szMachineName
[0] = L
'\0';
1144 while (*lpString
!= L
'\0')
1146 if (*lpString
== L
'/')
1149 if (!_wcsnicmp(lpString
, L
"DeviceID", 8))
1152 if (*lpString
!= L
'\0')
1155 while ((*lpString
!= L
' ') &&
1156 (*lpString
!= L
'\0') &&
1157 (i
<= MAX_DEVICE_ID_LEN
))
1159 szDeviceID
[i
++] = *lpString
++;
1161 szDeviceID
[i
] = L
'\0';
1165 else if (!_wcsnicmp(lpString
, L
"MachineName", 11))
1168 if (*lpString
!= L
'\0')
1171 while ((*lpString
!= L
' ') &&
1172 (*lpString
!= L
'\0') &&
1173 (i
<= MAX_COMPUTERNAME_LENGTH
))
1175 szMachineName
[i
++] = *lpString
++;
1177 szMachineName
[i
] = L
'\0';
1180 /* knock the pointer back one and let the next
1181 * pointer deal with incrementing, otherwise we
1182 * go past the end of the string */