2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dlls\win32\msports\classinst.c
5 * PURPOSE: Ports class installer
6 * PROGRAMMERS: Copyright 2011 Eric Kohl
9 #define WIN32_NO_STATUS
15 #include <wine/debug.h>
17 WINE_DEFAULT_DEBUG_CHANNEL(msports
);
20 typedef enum _PORT_TYPE
29 GetBootResourceList(HDEVINFO DeviceInfoSet
,
30 PSP_DEVINFO_DATA DeviceInfoData
,
31 PCM_RESOURCE_LIST
*ppResourceList
)
33 HKEY hDeviceKey
= NULL
;
34 HKEY hConfigKey
= NULL
;
35 LPBYTE lpBuffer
= NULL
;
40 *ppResourceList
= NULL
;
42 hDeviceKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
52 lError
= RegOpenKeyExW(hDeviceKey
,
57 if (lError
!= ERROR_SUCCESS
)
60 /* Get the configuration data size */
61 lError
= RegQueryValueExW(hConfigKey
,
67 if (lError
!= ERROR_SUCCESS
)
70 /* Allocate the buffer */
71 lpBuffer
= HeapAlloc(GetProcessHeap(), 0, dwDataSize
);
75 /* Retrieve the configuration data */
76 lError
= RegQueryValueExW(hConfigKey
,
82 if (lError
== ERROR_SUCCESS
)
86 if (ret
== FALSE
&& lpBuffer
!= NULL
)
87 HeapFree(GetProcessHeap(), 0, lpBuffer
);
90 RegCloseKey(hConfigKey
);
93 RegCloseKey(hDeviceKey
);
96 *ppResourceList
= (PCM_RESOURCE_LIST
)lpBuffer
;
103 GetSerialPortNumber(IN HDEVINFO DeviceInfoSet
,
104 IN PSP_DEVINFO_DATA DeviceInfoData
)
106 PCM_RESOURCE_LIST lpResourceList
= NULL
;
107 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes
;
109 DWORD dwBaseAddress
= 0;
110 DWORD dwPortNumber
= 0;
112 TRACE("GetSerialPortNumber(%p, %p)\n",
113 DeviceInfoSet
, DeviceInfoData
);
115 if (GetBootResourceList(DeviceInfoSet
,
119 TRACE("Full resource descriptors: %ul\n", lpResourceList
->Count
);
120 if (lpResourceList
->Count
> 0)
122 TRACE("Partial resource descriptors: %ul\n", lpResourceList
->List
[0].PartialResourceList
.Count
);
124 for (i
= 0; i
< lpResourceList
->List
[0].PartialResourceList
.Count
; i
++)
126 lpResDes
= &lpResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
127 TRACE("Type: %u\n", lpResDes
->Type
);
129 switch (lpResDes
->Type
)
131 case CmResourceTypePort
:
132 TRACE("Port: Start: %I64x Length: %lu\n",
133 lpResDes
->u
.Port
.Start
.QuadPart
,
134 lpResDes
->u
.Port
.Length
);
135 if (lpResDes
->u
.Port
.Start
.HighPart
== 0)
136 dwBaseAddress
= (DWORD
)lpResDes
->u
.Port
.Start
.LowPart
;
139 case CmResourceTypeInterrupt
:
140 TRACE("Interrupt: Level: %lu Vector: %lu\n",
141 lpResDes
->u
.Interrupt
.Level
,
142 lpResDes
->u
.Interrupt
.Vector
);
148 HeapFree(GetProcessHeap(), 0, lpResourceList
);
151 switch (dwBaseAddress
)
175 GetParallelPortNumber(IN HDEVINFO DeviceInfoSet
,
176 IN PSP_DEVINFO_DATA DeviceInfoData
)
178 PCM_RESOURCE_LIST lpResourceList
= NULL
;
179 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes
;
181 DWORD dwBaseAddress
= 0;
182 DWORD dwPortNumber
= 0;
184 TRACE("GetParallelPortNumber(%p, %p)\n",
185 DeviceInfoSet
, DeviceInfoData
);
187 if (GetBootResourceList(DeviceInfoSet
,
191 TRACE("Full resource descriptors: %ul\n", lpResourceList
->Count
);
192 if (lpResourceList
->Count
> 0)
194 TRACE("Partial resource descriptors: %ul\n", lpResourceList
->List
[0].PartialResourceList
.Count
);
196 for (i
= 0; i
< lpResourceList
->List
[0].PartialResourceList
.Count
; i
++)
198 lpResDes
= &lpResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
199 TRACE("Type: %u\n", lpResDes
->Type
);
201 switch (lpResDes
->Type
)
203 case CmResourceTypePort
:
204 TRACE("Port: Start: %I64x Length: %lu\n",
205 lpResDes
->u
.Port
.Start
.QuadPart
,
206 lpResDes
->u
.Port
.Length
);
207 if (lpResDes
->u
.Port
.Start
.HighPart
== 0)
208 dwBaseAddress
= (DWORD
)lpResDes
->u
.Port
.Start
.LowPart
;
211 case CmResourceTypeInterrupt
:
212 TRACE("Interrupt: Level: %lu Vector: %lu\n",
213 lpResDes
->u
.Interrupt
.Level
,
214 lpResDes
->u
.Interrupt
.Vector
);
222 HeapFree(GetProcessHeap(), 0, lpResourceList
);
225 switch (dwBaseAddress
)
241 InstallSerialPort(IN HDEVINFO DeviceInfoSet
,
242 IN PSP_DEVINFO_DATA DeviceInfoData
)
244 WCHAR szDeviceDescription
[256];
245 WCHAR szFriendlyName
[256];
248 HCOMDB hComDB
= HCOMDB_INVALID_HANDLE_VALUE
;
251 TRACE("InstallSerialPort(%p, %p)\n",
252 DeviceInfoSet
, DeviceInfoData
);
254 /* Open the com port database */
257 /* Determine the port number from its resources ... */
258 dwPortNumber
= GetSerialPortNumber(DeviceInfoSet
,
260 if (dwPortNumber
!= 0)
262 /* ... and claim the port number in the database */
263 ComDBClaimPort(hComDB
,
270 /* ... or claim the next free port number */
271 ComDBClaimNextFreePort(hComDB
,
275 /* Build the name of the port device */
276 swprintf(szPortName
, L
"COM%u", dwPortNumber
);
278 /* Close the com port database */
279 if (hComDB
!= HCOMDB_INVALID_HANDLE_VALUE
)
282 /* Set the 'PortName' value */
283 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
290 if (hKey
!= INVALID_HANDLE_VALUE
)
297 (wcslen(szPortName
) + 1) * sizeof(WCHAR
));
302 /* Install the device */
303 if (!SetupDiInstallDevice(DeviceInfoSet
,
306 return GetLastError();
309 /* Get the device description... */
310 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
314 (LPBYTE
)szDeviceDescription
,
318 /* ... and use it to build a new friendly name */
319 swprintf(szFriendlyName
,
326 /* ... or build a generic friendly name */
327 swprintf(szFriendlyName
,
332 /* Set the friendly name for the device */
333 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet
,
336 (LPBYTE
)szFriendlyName
,
337 (wcslen(szFriendlyName
) + 1) * sizeof(WCHAR
));
339 return ERROR_SUCCESS
;
344 InstallParallelPort(IN HDEVINFO DeviceInfoSet
,
345 IN PSP_DEVINFO_DATA DeviceInfoData
)
347 WCHAR szDeviceDescription
[256];
348 WCHAR szFriendlyName
[256];
352 TRACE("InstallParallelPort(%p, %p)\n",
353 DeviceInfoSet
, DeviceInfoData
);
355 dwPortNumber
= GetParallelPortNumber(DeviceInfoSet
,
357 if (dwPortNumber
!= 0)
359 swprintf(szPortName
, L
"LPT%u", dwPortNumber
);
363 wcscpy(szPortName
, L
"LPTx");
367 /* Install the device */
368 if (!SetupDiInstallDevice(DeviceInfoSet
,
371 return GetLastError();
374 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
378 (LPBYTE
)szDeviceDescription
,
382 swprintf(szFriendlyName
,
389 swprintf(szFriendlyName
,
394 /* Set the friendly name for the device */
395 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet
,
398 (LPBYTE
)szFriendlyName
,
399 (wcslen(szFriendlyName
) + 1) * sizeof(WCHAR
));
401 return ERROR_SUCCESS
;
406 InstallDeviceData(IN HDEVINFO DeviceInfoSet
,
407 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
410 HINF hInf
= INVALID_HANDLE_VALUE
;
411 SP_DRVINFO_DATA DriverInfoData
;
412 PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData
;
413 WCHAR InfSectionWithExt
[256];
417 TRACE("InstallDeviceData()\n");
419 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
429 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA
);
430 if (!SetupDiGetSelectedDriverW(DeviceInfoSet
,
437 DriverInfoDetailData
= (PSP_DRVINFO_DETAIL_DATA
)buffer
;
438 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
439 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
442 DriverInfoDetailData
,
446 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
450 TRACE("Inf file name: %S\n", DriverInfoDetailData
->InfFileName
);
452 hInf
= SetupOpenInfFileW(DriverInfoDetailData
->InfFileName
,
456 if (hInf
== INVALID_HANDLE_VALUE
)
459 TRACE("Section name: %S\n", DriverInfoDetailData
->SectionName
);
461 SetupDiGetActualSectionToInstallW(hInf
,
462 DriverInfoDetailData
->SectionName
,
468 TRACE("InfSectionWithExt: %S\n", InfSectionWithExt
);
470 SetupInstallFromInfSectionW(NULL
,
488 if (hInf
!= INVALID_HANDLE_VALUE
)
489 SetupCloseInfFile(hInf
);
495 GetPortType(IN HDEVINFO DeviceInfoSet
,
496 IN PSP_DEVINFO_DATA DeviceInfoData
)
502 PORT_TYPE PortType
= UnknownPort
;
505 TRACE("GetPortType()\n");
507 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
519 dwSize
= sizeof(BYTE
);
520 lError
= RegQueryValueExW(hKey
,
527 TRACE("lError: %ld\n", lError
);
528 TRACE("dwSize: %lu\n", dwSize
);
529 TRACE("dwType: %lu\n", dwType
);
531 if (lError
== ERROR_SUCCESS
&&
532 dwSize
== sizeof(BYTE
) &&
533 dwType
== REG_BINARY
)
536 PortType
= ParallelPort
;
538 PortType
= SerialPort
;
545 TRACE("GetPortType() returns %u \n", PortType
);
552 InstallPort(IN HDEVINFO DeviceInfoSet
,
553 IN PSP_DEVINFO_DATA DeviceInfoData
)
557 InstallDeviceData(DeviceInfoSet
, DeviceInfoData
);
559 PortType
= GetPortType(DeviceInfoSet
, DeviceInfoData
);
563 return InstallParallelPort(DeviceInfoSet
, DeviceInfoData
);
566 return InstallSerialPort(DeviceInfoSet
, DeviceInfoData
);
569 return ERROR_DI_DO_DEFAULT
;
576 PortsClassInstaller(IN DI_FUNCTION InstallFunction
,
577 IN HDEVINFO DeviceInfoSet
,
578 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
580 TRACE("PortsClassInstaller(%lu, %p, %p)\n",
581 InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
583 switch (InstallFunction
)
585 case DIF_INSTALLDEVICE
:
586 return InstallPort(DeviceInfoSet
, DeviceInfoData
);
589 TRACE("Install function %u ignored\n", InstallFunction
);
590 return ERROR_DI_DO_DEFAULT
;