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>
31 HINSTANCE hDllInstance
= NULL
;
34 LengthOfStrResource(IN HINSTANCE hInst
,
46 /* There are always blocks of 16 strings */
47 lpName
= (LPWSTR
)MAKEINTRESOURCE((uID
>> 4) + 1);
49 /* Find the string table block */
50 if ((hrSrc
= FindResourceW(hInst
, lpName
, (LPWSTR
)RT_STRING
)) &&
51 (hRes
= LoadResource(hInst
, hrSrc
)) &&
52 (lpStr
= LockResource(hRes
)))
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
++)
60 lpStr
+= (*lpStr
) + 1;
63 /* Found the string */
71 AllocAndLoadString(OUT LPWSTR
*lpTarget
,
77 ln
= LengthOfStrResource(hInst
,
81 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
83 if ((*lpTarget
) != NULL
)
86 if (!(Ret
= LoadStringW(hInst
, uID
, *lpTarget
, ln
)))
88 LocalFree((HLOCAL
)(*lpTarget
));
98 AllocAndLoadStringsCat(OUT LPWSTR
*lpTarget
,
110 ln
+= LengthOfStrResource(hInst
,
116 (*lpTarget
) = (LPWSTR
)LocalAlloc(LMEM_FIXED
,
117 (ln
+ 1) * sizeof(WCHAR
));
118 if ((*lpTarget
) != NULL
)
120 LPWSTR s
= *lpTarget
;
127 if (!(Ret
= LoadStringW(hInst
, uID
[i
], s
, ln
)))
129 LocalFree((HLOCAL
)(*lpTarget
));
136 return s
- *lpTarget
;
144 LoadAndFormatString(IN HINSTANCE hInstance
,
146 OUT LPWSTR
*lpTarget
,
153 if (AllocAndLoadString(&lpFormat
,
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
,
169 LocalFree((HLOCAL
)lpFormat
);
177 LoadAndFormatStringsCat(IN HINSTANCE hInstance
,
180 OUT LPWSTR
*lpTarget
,
187 if (AllocAndLoadStringsCat(&lpFormat
,
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
,
204 LocalFree((HLOCAL
)lpFormat
);
212 ListViewGetSelectedItemData(IN HWND hwnd
)
216 Index
= ListView_GetNextItem(hwnd
,
223 li
.mask
= LVIF_PARAM
;
227 if (ListView_GetItem(hwnd
,
239 ConvertMultiByteToUnicode(IN LPCSTR lpMultiByteStr
,
245 nLength
= MultiByteToWideChar(uCodePage
,
254 lpUnicodeStr
= HeapAlloc(GetProcessHeap(),
256 nLength
* sizeof(WCHAR
));
257 if (lpUnicodeStr
== NULL
)
259 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
263 if (!MultiByteToWideChar(uCodePage
,
270 HeapFree(GetProcessHeap(),
281 GetDeviceManufacturerString(IN HDEVINFO DeviceInfoSet
,
282 IN PSP_DEVINFO_DATA DeviceInfoData
,
289 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
294 BufferSize
* sizeof(WCHAR
),
296 RegDataType
!= REG_SZ
)
299 if (LoadString(hDllInstance
,
309 /* FIXME - check string for NULL termination! */
318 GetDeviceLocationString(IN HDEVINFO DeviceInfoSet
,
319 IN PSP_DEVINFO_DATA DeviceInfoData
,
320 IN DEVINST dnParentDevInst OPTIONAL
,
329 DWORD dwSize
, dwType
;
332 DataSize
= BufferSize
* sizeof(WCHAR
);
335 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
341 if (hKey
!= INVALID_HANDLE_VALUE
)
343 /* query the LocationInformationOverride value */
345 if (RegQueryValueEx(hKey
,
346 L
"LocationInformationOverride",
350 &dwSize
) == ERROR_SUCCESS
&&
352 szBuffer
[0] != L
'\0')
367 if (dnParentDevInst
!= 0)
369 /* query the parent node name */
370 if (CM_Get_DevNode_Registry_Property(dnParentDevInst
,
376 RegDataType
== REG_SZ
&&
377 LoadAndFormatString(hDllInstance
,
385 szBuffer
[BufferSize
- 1] = L
'\0';
386 LocalFree((HLOCAL
)szFormatted
);
390 else if (DeviceInfoData
->DevInst
!= 0)
392 cRet
= CM_Get_DevNode_Registry_Property(DeviceInfoData
->DevInst
,
393 CM_DRP_LOCATION_INFORMATION
,
398 if (cRet
== CR_SUCCESS
&& RegDataType
== REG_SZ
)
400 /* FIXME - check string for NULL termination! */
404 if (Ret
&& szBuffer
[0] >= L
'0' && szBuffer
[0] <= L
'9')
406 /* convert the string to an integer value and create a
408 ULONG ulLocation
= (ULONG
)wcstoul(szBuffer
,
411 if (LoadAndFormatString(hDllInstance
,
420 szBuffer
[BufferSize
- 1] = L
'\0';
421 LocalFree((HLOCAL
)szFormatted
);
430 LoadString(hDllInstance
,
443 GetDeviceStatusString(IN DEVINST DevInst
,
444 IN HMACHINE hMachine
,
449 ULONG Status
, ProblemNumber
;
450 UINT MessageId
= IDS_UNKNOWN
;
454 cr
= CM_Get_DevNode_Status_Ex(&Status
,
459 if (cr
== CR_SUCCESS
)
461 if (Status
& DN_HAS_PROBLEM
)
465 uRet
= DeviceProblemText(hMachine
,
469 (BufferSize
!= 0 ? BufferSize
: BufferSize
- 1));
471 Ret
= (uRet
!= 0 && uRet
< BufferSize
);
475 if (!(Status
& (DN_DRIVER_LOADED
| DN_STARTED
)))
477 MessageId
= IDS_NODRIVERLOADED
;
481 MessageId
= IDS_DEV_NO_PROBLEM
;
490 if (LoadString(hDllInstance
,
504 GetDriverProviderString(IN HDEVINFO DeviceInfoSet
,
505 IN PSP_DEVINFO_DATA DeviceInfoData
,
510 DWORD dwSize
, dwType
;
515 /* get driver provider, date and version */
516 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
522 if (hKey
!= INVALID_HANDLE_VALUE
)
524 /* query the driver provider */
526 if (RegQueryValueEx(hKey
,
527 REGSTR_VAL_PROVIDER_NAME
,
531 &dwSize
) == ERROR_SUCCESS
&&
533 szBuffer
[0] != L
'\0')
545 if (szBuffer
[0] == L
'\0')
547 /* unable to query the information */
548 if (LoadString(hDllInstance
,
562 GetDriverVersionString(IN HDEVINFO DeviceInfoSet
,
563 IN PSP_DEVINFO_DATA DeviceInfoData
,
568 DWORD dwSize
, dwType
;
573 /* get driver provider, date and version */
574 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
580 if (hKey
!= INVALID_HANDLE_VALUE
)
582 /* query the driver provider */
584 if (RegQueryValueEx(hKey
,
589 &dwSize
) == ERROR_SUCCESS
&&
591 szBuffer
[0] != L
'\0')
603 if (szBuffer
[0] == L
'\0')
605 /* unable to query the information */
606 if (LoadString(hDllInstance
,
619 GetDriverDateString(IN HDEVINFO DeviceInfoSet
,
620 IN PSP_DEVINFO_DATA DeviceInfoData
,
626 SYSTEMTIME SystemTime
, LocalTime
;
627 DWORD dwSize
, dwType
;
632 /* get driver provider, date and version */
633 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
639 if (hKey
!= INVALID_HANDLE_VALUE
)
641 /* query the driver provider */
642 dwSize
= sizeof(FILETIME
);
643 if (RegQueryValueEx(hKey
,
648 &dwSize
) == ERROR_SUCCESS
&&
649 dwType
== REG_BINARY
&&
650 dwSize
== sizeof(FILETIME
) &&
651 FileTimeToSystemTime(&DriverDate
,
653 SystemTimeToTzSpecificLocalTime(NULL
,
656 GetDateFormat(LOCALE_USER_DEFAULT
,
671 /* unable to query the information */
672 if (LoadString(hDllInstance
,
687 IsDeviceHidden(IN DEVINST DevInst
,
688 IN HMACHINE hMachine
,
692 ULONG Status
, ProblemNumber
;
695 cr
= CM_Get_DevNode_Status_Ex(&Status
,
700 if (cr
== CR_SUCCESS
)
702 *IsHidden
= ((Status
& DN_NO_SHOW_IN_DM
) != 0);
711 CanDisableDevice(IN DEVINST DevInst
,
712 IN HMACHINE hMachine
,
713 OUT BOOL
*CanDisable
)
716 ULONG Status
, ProblemNumber
;
719 cr
= CM_Get_DevNode_Status_Ex(&Status
,
724 if (cr
== CR_SUCCESS
)
726 *CanDisable
= ((Status
& DN_DISABLEABLE
) != 0);
735 IsDeviceStarted(IN DEVINST DevInst
,
736 IN HMACHINE hMachine
,
740 ULONG Status
, ProblemNumber
;
743 cr
= CM_Get_DevNode_Status_Ex(&Status
,
748 if (cr
== CR_SUCCESS
)
750 *IsStarted
= ((Status
& DN_STARTED
) != 0);
759 IsDriverInstalled(IN DEVINST DevInst
,
760 IN HMACHINE hMachine
,
764 ULONG Status
, ProblemNumber
;
767 cr
= CM_Get_DevNode_Status_Ex(&Status
,
772 if (cr
== CR_SUCCESS
)
774 *Installed
= ((Status
& DN_HAS_PROBLEM
) != 0 ||
775 (Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
784 EnableDevice(IN HDEVINFO DeviceInfoSet
,
785 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
,
787 IN DWORD HardwareProfile OPTIONAL
,
788 OUT BOOL
*bNeedReboot OPTIONAL
)
790 SP_PROPCHANGE_PARAMS pcp
;
791 SP_DEVINSTALL_PARAMS dp
;
795 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
796 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
797 pcp
.HwProfile
= HardwareProfile
;
801 /* try to enable the device on the global profile */
802 pcp
.StateChange
= DICS_ENABLE
;
803 pcp
.Scope
= DICS_FLAG_GLOBAL
;
806 LastErr
= GetLastError();
807 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
809 &pcp
.ClassInstallHeader
,
810 sizeof(SP_PROPCHANGE_PARAMS
)))
812 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
816 SetLastError(LastErr
);
819 /* try config-specific */
820 pcp
.StateChange
= (bEnable
? DICS_ENABLE
: DICS_DISABLE
);
821 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
823 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
825 &pcp
.ClassInstallHeader
,
826 sizeof(SP_PROPCHANGE_PARAMS
)) &&
827 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
831 dp
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
832 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
836 if (bNeedReboot
!= NULL
)
838 *bNeedReboot
= ((dp
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
849 GetDeviceTypeString(IN PSP_DEVINFO_DATA DeviceInfoData
,
855 if (!SetupDiGetClassDescription(&DeviceInfoData
->ClassGuid
,
861 if (LoadString(hDllInstance
,
871 /* FIXME - check string for NULL termination! */
880 GetDeviceDescriptionString(IN HDEVINFO DeviceInfoSet
,
881 IN PSP_DEVINFO_DATA DeviceInfoData
,
888 if ((SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
893 BufferSize
* sizeof(WCHAR
),
895 SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
900 BufferSize
* sizeof(WCHAR
),
902 RegDataType
== REG_SZ
)
904 /* FIXME - check string for NULL termination! */
910 if (LoadString(hDllInstance
,
924 FindCurrentDriver(IN HDEVINFO DeviceInfoSet
,
925 IN PSP_DEVINFO_DATA DeviceInfoData
,
926 OUT PSP_DRVINFO_DATA DriverInfoData
)
928 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
;
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?
949 /* 1) Get the install params */
950 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
951 if (!SetupDiGetDeviceInstallParams(DeviceInfoSet
,
955 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
959 #ifdef DI_FLAGSEX_INSTALLEDDRIVER
960 InstallParams
.FlagsEx
|= (DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
961 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
965 if (SetupDiBuildDriverInfoList(DeviceInfoSet
,
967 SPDIT_CLASSDRIVER
) &&
968 SetupDiEnumDriverInfo(DeviceInfoSet
,
979 InstallParams
.FlagsEx
&= ~(DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
982 /* 2) Open the driver registry key */
983 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
989 if (hKey
== INVALID_HANDLE_VALUE
)
991 ERR("SetupDiOpenDevRegKey() failed with error 0x%lx\n", GetLastError());
995 /* 3) Read the .inf file name */
996 dwLength
= (sizeof(InfPath
) / sizeof(InfPath
[0])) - 1;
997 rc
= RegQueryValueEx(hKey
,
1003 if (rc
!= ERROR_SUCCESS
)
1005 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1009 else if (dwType
!= REG_SZ
)
1011 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1012 SetLastError(ERROR_GEN_FAILURE
);
1015 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
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
,
1025 ERR("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
1029 /* 5) Build class driver list */
1030 if (!SetupDiBuildDriverInfoList(DeviceInfoSet
,
1034 ERR("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
1038 /* 6) Read inf section and from registry */
1039 dwLength
= (sizeof(InfSection
) / sizeof(InfSection
[0])) - 1;
1040 rc
= RegQueryValueEx(hKey
,
1041 REGSTR_VAL_INFSECTION
,
1046 if (rc
!= ERROR_SUCCESS
)
1048 ERR("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1052 else if (dwType
!= REG_SZ
)
1054 ERR("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1055 SetLastError(ERROR_GEN_FAILURE
);
1058 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1060 /* 7) Enumerate drivers */
1061 DriverInfoData
->cbSize
= sizeof(SP_DRVINFO_DATA
);
1062 DriverInfoDetailData
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
1063 while (SetupDiEnumDriverInfo(DeviceInfoSet
,
1069 /* 8) Find the one who is in the same section as current driver */
1070 if (!SetupDiGetDriverInfoDetail(DeviceInfoSet
,
1073 &DriverInfoDetailData
,
1074 DriverInfoDetailData
.cbSize
,
1076 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1078 ERR("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", GetLastError());
1081 if (!wcsicmp(DriverInfoDetailData
.SectionName
,
1084 /* We have found the right driver */
1091 if (GetLastError() != ERROR_NO_MORE_ITEMS
)
1093 ERR("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
1097 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1100 if (hKey
!= INVALID_HANDLE_VALUE
)
1107 LoadAndInitComctl32(VOID
)
1109 typedef VOID (WINAPI
*PINITCOMMONCONTROLS
)(VOID
);
1110 PINITCOMMONCONTROLS pInitCommonControls
;
1111 HINSTANCE hComCtl32
;
1113 hComCtl32
= LoadLibrary(L
"comctl32.dll");
1114 if (hComCtl32
!= NULL
)
1116 /* initialize the common controls */
1117 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hComCtl32
,
1118 "InitCommonControls");
1119 if (pInitCommonControls
== NULL
)
1121 FreeLibrary(hComCtl32
);
1125 pInitCommonControls();
1134 DllMain(IN HINSTANCE hinstDLL
,
1136 IN LPVOID lpvReserved
)
1140 case DLL_PROCESS_ATTACH
:
1141 DisableThreadLibraryCalls(hinstDLL
);
1142 hDllInstance
= hinstDLL
;