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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
));
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
= 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 DEVINST dnDevInst OPTIONAL
,
321 IN DEVINST dnParentDevInst OPTIONAL
,
331 DataSize
= BufferSize
* sizeof(WCHAR
);
333 if (dnParentDevInst
!= 0)
335 /* query the parent node name */
336 if (CM_Get_DevNode_Registry_Property(dnParentDevInst
,
342 RegDataType
== REG_SZ
&&
343 LoadAndFormatString(hDllInstance
,
351 szBuffer
[BufferSize
- 1] = L
'\0';
352 LocalFree((HLOCAL
)szFormatted
);
356 else if (dnDevInst
!= 0)
358 cRet
= CM_Get_DevNode_Registry_Property(dnDevInst
,
359 CM_DRP_LOCATION_INFORMATION
,
364 if (cRet
== CR_SUCCESS
&& RegDataType
== REG_SZ
)
366 /* FIXME - check string for NULL termination! */
370 if (Ret
&& szBuffer
[0] >= L
'0' && szBuffer
[0] <= L
'9')
372 /* convert the string to an integer value and create a
374 ULONG ulLocation
= (ULONG
)wcstoul(szBuffer
,
377 if (LoadAndFormatString(hDllInstance
,
386 szBuffer
[BufferSize
- 1] = L
'\0';
387 LocalFree((HLOCAL
)szFormatted
);
395 LoadString(hDllInstance
,
408 GetDeviceStatusString(IN DEVINST DevInst
,
409 IN HMACHINE hMachine
,
414 ULONG Status
, ProblemNumber
;
415 UINT MessageId
= IDS_UNKNOWN
;
419 cr
= CM_Get_DevNode_Status_Ex(&Status
,
424 if (cr
== CR_SUCCESS
)
426 if (Status
& DN_HAS_PROBLEM
)
430 uRet
= DeviceProblemText(hMachine
,
434 (BufferSize
!= 0 ? BufferSize
: BufferSize
- 1));
436 Ret
= (uRet
!= 0 && uRet
< BufferSize
);
440 if (!(Status
& (DN_DRIVER_LOADED
| DN_STARTED
)))
442 MessageId
= IDS_NODRIVERLOADED
;
446 MessageId
= IDS_DEV_NO_PROBLEM
;
455 if (LoadString(hDllInstance
,
469 GetDriverProviderString(IN HDEVINFO DeviceInfoSet
,
470 IN PSP_DEVINFO_DATA DeviceInfoData
,
475 DWORD dwSize
, dwType
;
480 /* get driver provider, date and version */
481 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
487 if (hKey
!= INVALID_HANDLE_VALUE
)
489 /* query the driver provider */
491 if (RegQueryValueEx(hKey
,
492 REGSTR_VAL_PROVIDER_NAME
,
496 &dwSize
) == ERROR_SUCCESS
&&
498 szBuffer
[0] != L
'\0')
510 if (szBuffer
[0] == L
'\0')
512 /* unable to query the information */
513 if (LoadString(hDllInstance
,
527 GetDriverVersionString(IN HDEVINFO DeviceInfoSet
,
528 IN PSP_DEVINFO_DATA DeviceInfoData
,
533 DWORD dwSize
, dwType
;
538 /* get driver provider, date and version */
539 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
545 if (hKey
!= INVALID_HANDLE_VALUE
)
547 /* query the driver provider */
549 if (RegQueryValueEx(hKey
,
554 &dwSize
) == ERROR_SUCCESS
&&
556 szBuffer
[0] != L
'\0')
568 if (szBuffer
[0] == L
'\0')
570 /* unable to query the information */
571 if (LoadString(hDllInstance
,
584 GetDriverDateString(IN HDEVINFO DeviceInfoSet
,
585 IN PSP_DEVINFO_DATA DeviceInfoData
,
591 SYSTEMTIME SystemTime
, LocalTime
;
592 DWORD dwSize
, dwType
;
597 /* get driver provider, date and version */
598 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
604 if (hKey
!= INVALID_HANDLE_VALUE
)
606 /* query the driver provider */
607 dwSize
= sizeof(FILETIME
);
608 if (RegQueryValueEx(hKey
,
613 &dwSize
) == ERROR_SUCCESS
&&
614 dwType
== REG_BINARY
&&
615 dwSize
== sizeof(FILETIME
) &&
616 FileTimeToSystemTime(&DriverDate
,
618 SystemTimeToTzSpecificLocalTime(NULL
,
621 GetDateFormat(LOCALE_USER_DEFAULT
,
636 /* unable to query the information */
637 if (LoadString(hDllInstance
,
652 IsDeviceHidden(IN DEVINST DevInst
,
653 IN HMACHINE hMachine
,
657 ULONG Status
, ProblemNumber
;
660 cr
= CM_Get_DevNode_Status_Ex(&Status
,
665 if (cr
== CR_SUCCESS
)
667 *IsHidden
= ((Status
& DN_NO_SHOW_IN_DM
) != 0);
676 CanDisableDevice(IN DEVINST DevInst
,
677 IN HMACHINE hMachine
,
678 OUT BOOL
*CanDisable
)
681 ULONG Status
, ProblemNumber
;
684 cr
= CM_Get_DevNode_Status_Ex(&Status
,
689 if (cr
== CR_SUCCESS
)
691 *CanDisable
= ((Status
& DN_DISABLEABLE
) != 0);
700 IsDeviceStarted(IN DEVINST DevInst
,
701 IN HMACHINE hMachine
,
705 ULONG Status
, ProblemNumber
;
708 cr
= CM_Get_DevNode_Status_Ex(&Status
,
713 if (cr
== CR_SUCCESS
)
715 *IsStarted
= ((Status
& DN_STARTED
) != 0);
724 IsDriverInstalled(IN DEVINST DevInst
,
725 IN HMACHINE hMachine
,
729 ULONG Status
, ProblemNumber
;
732 cr
= CM_Get_DevNode_Status_Ex(&Status
,
737 if (cr
== CR_SUCCESS
)
739 *Installed
= ((Status
& DN_HAS_PROBLEM
) != 0 ||
740 (Status
& (DN_DRIVER_LOADED
| DN_STARTED
)) != 0);
749 EnableDevice(IN HDEVINFO DeviceInfoSet
,
750 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
,
752 IN DWORD HardwareProfile OPTIONAL
,
753 OUT BOOL
*bNeedReboot OPTIONAL
)
755 SP_PROPCHANGE_PARAMS pcp
;
756 SP_DEVINSTALL_PARAMS dp
;
760 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
761 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
762 pcp
.HwProfile
= HardwareProfile
;
766 /* try to enable the device on the global profile */
767 pcp
.StateChange
= DICS_ENABLE
;
768 pcp
.Scope
= DICS_FLAG_GLOBAL
;
771 LastErr
= GetLastError();
772 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
774 &pcp
.ClassInstallHeader
,
775 sizeof(SP_PROPCHANGE_PARAMS
)))
777 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
781 SetLastError(LastErr
);
784 /* try config-specific */
785 pcp
.StateChange
= (bEnable
? DICS_ENABLE
: DICS_DISABLE
);
786 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
788 if (SetupDiSetClassInstallParams(DeviceInfoSet
,
790 &pcp
.ClassInstallHeader
,
791 sizeof(SP_PROPCHANGE_PARAMS
)) &&
792 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
796 dp
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
797 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
801 if (bNeedReboot
!= NULL
)
803 *bNeedReboot
= ((dp
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
814 GetDeviceTypeString(IN PSP_DEVINFO_DATA DeviceInfoData
,
820 if (!SetupDiGetClassDescription(&DeviceInfoData
->ClassGuid
,
826 if (LoadString(hDllInstance
,
836 /* FIXME - check string for NULL termination! */
845 GetDeviceDescriptionString(IN HDEVINFO DeviceInfoSet
,
846 IN PSP_DEVINFO_DATA DeviceInfoData
,
853 if ((SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
858 BufferSize
* sizeof(WCHAR
),
860 SetupDiGetDeviceRegistryProperty(DeviceInfoSet
,
865 BufferSize
* sizeof(WCHAR
),
867 RegDataType
== REG_SZ
)
869 /* FIXME - check string for NULL termination! */
875 if (LoadString(hDllInstance
,
889 FindCurrentDriver(IN HDEVINFO DeviceInfoSet
,
890 IN PSP_DEVINFO_DATA DeviceInfoData
,
891 OUT PSP_DRVINFO_DATA DriverInfoData
)
893 HKEY hKey
= INVALID_HANDLE_VALUE
;
894 SP_DEVINSTALL_PARAMS InstallParams
= {0};
895 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData
= {0};
896 WCHAR InfPath
[MAX_PATH
];
897 WCHAR InfSection
[LINE_LEN
];
898 DWORD dwType
, dwLength
;
903 /* Steps to find the right driver:
904 * 1) Get the device install parameters
905 * 2) Open the driver registry key
906 * 3) Read the .inf file name
907 * 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name
908 * 5) Build class driver list
909 * 6) Read inf section and inf section extension from registry
910 * 7) Enumerate drivers
911 * 8) Find the one who is in the same section as current driver?
914 /* 1) Get the install params */
915 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
916 if (!SetupDiGetDeviceInstallParams(DeviceInfoSet
,
920 DPRINT1("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
924 #ifdef DI_FLAGSEX_INSTALLEDDRIVER
925 InstallParams
.FlagsEx
|= (DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
926 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
930 if (SetupDiBuildDriverInfoList(DeviceInfoSet
,
932 SPDIT_CLASSDRIVER
) &&
933 SetupDiEnumDriverInfo(DeviceInfoSet
,
944 InstallParams
.FlagsEx
&= ~(DI_FLAGSEX_INSTALLEDDRIVER
| DI_FLAGSEX_ALLOWEXCLUDEDDRVS
);
947 /* 2) Open the driver registry key */
948 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
954 if (hKey
== INVALID_HANDLE_VALUE
)
956 DPRINT1("SetupDiOpenDevRegKey() failed with error 0x%lx\n", GetLastError());
960 /* 3) Read the .inf file name */
961 dwLength
= (sizeof(InfPath
) / sizeof(InfPath
[0])) - 1;
962 rc
= RegQueryValueEx(hKey
,
968 if (rc
!= ERROR_SUCCESS
)
971 DPRINT1("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
974 else if (dwType
!= REG_SZ
)
976 SetLastError(ERROR_GEN_FAILURE
);
977 DPRINT1("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
980 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
982 /* 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name */
983 InstallParams
.Flags
|= DI_ENUMSINGLEINF
;
984 InstallParams
.FlagsEx
|= DI_FLAGSEX_ALLOWEXCLUDEDDRVS
;
985 wcscpy(InstallParams
.DriverPath
, InfPath
);
986 if (!SetupDiSetDeviceInstallParams(DeviceInfoSet
,
990 DPRINT1("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
994 /* 5) Build class driver list */
995 if (!SetupDiBuildDriverInfoList(DeviceInfoSet
,
999 DPRINT1("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
1003 /* 6) Read inf section and from registry */
1004 dwLength
= (sizeof(InfSection
) / sizeof(InfSection
[0])) - 1;
1005 rc
= RegQueryValueEx(hKey
,
1006 REGSTR_VAL_INFSECTION
,
1011 if (rc
!= ERROR_SUCCESS
)
1014 DPRINT1("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
1017 else if (dwType
!= REG_SZ
)
1019 SetLastError(ERROR_GEN_FAILURE
);
1020 DPRINT1("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ
, dwType
);
1023 InfPath
[(dwLength
/ sizeof(WCHAR
)) - 1] = L
'\0';
1025 /* 7) Enumerate drivers */
1026 DriverInfoData
->cbSize
= sizeof(SP_DRVINFO_DATA
);
1027 DriverInfoDetailData
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
1028 while (SetupDiEnumDriverInfo(DeviceInfoSet
,
1034 /* 8) Find the one who is in the same section as current driver */
1035 if (!SetupDiGetDriverInfoDetail(DeviceInfoSet
,
1038 &DriverInfoDetailData
,
1039 DriverInfoDetailData
.cbSize
,
1041 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1043 DPRINT1("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", GetLastError());
1046 if (!wcsicmp(DriverInfoDetailData
.SectionName
,
1049 /* We have found the right driver */
1056 if (GetLastError() != ERROR_NO_MORE_ITEMS
)
1058 DPRINT1("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
1062 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1065 if (hKey
!= INVALID_HANDLE_VALUE
)
1072 LoadAndInitComctl32(VOID
)
1074 typedef VOID (WINAPI
*PINITCOMMONCONTROLS
)(VOID
);
1075 PINITCOMMONCONTROLS pInitCommonControls
;
1076 HINSTANCE hComCtl32
;
1078 hComCtl32
= LoadLibrary(L
"comctl32.dll");
1079 if (hComCtl32
!= NULL
)
1081 /* initialize the common controls */
1082 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hComCtl32
,
1083 "InitCommonControls");
1084 if (pInitCommonControls
== NULL
)
1086 FreeLibrary(hComCtl32
);
1090 pInitCommonControls();
1099 DllMain(IN HINSTANCE hinstDLL
,
1101 IN LPVOID lpvReserved
)
1105 case DLL_PROCESS_ATTACH
:
1106 DisableThreadLibraryCalls(hinstDLL
);
1107 hDllInstance
= hinstDLL
;