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
11 WINE_DEFAULT_DEBUG_CHANNEL(msports
);
14 typedef enum _PORT_TYPE
21 LPWSTR pszCom
= L
"COM";
22 LPWSTR pszLpt
= L
"LPT";
26 GetBootResourceList(HDEVINFO DeviceInfoSet
,
27 PSP_DEVINFO_DATA DeviceInfoData
,
28 PCM_RESOURCE_LIST
*ppResourceList
)
30 HKEY hDeviceKey
= NULL
;
31 HKEY hConfigKey
= NULL
;
32 LPBYTE lpBuffer
= NULL
;
37 *ppResourceList
= NULL
;
39 hDeviceKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
49 lError
= RegOpenKeyExW(hDeviceKey
,
54 if (lError
!= ERROR_SUCCESS
)
57 /* Get the configuration data size */
58 lError
= RegQueryValueExW(hConfigKey
,
64 if (lError
!= ERROR_SUCCESS
)
67 /* Allocate the buffer */
68 lpBuffer
= HeapAlloc(GetProcessHeap(), 0, dwDataSize
);
72 /* Retrieve the configuration data */
73 lError
= RegQueryValueExW(hConfigKey
,
79 if (lError
== ERROR_SUCCESS
)
83 if (ret
== FALSE
&& lpBuffer
!= NULL
)
84 HeapFree(GetProcessHeap(), 0, lpBuffer
);
87 RegCloseKey(hConfigKey
);
90 RegCloseKey(hDeviceKey
);
93 *ppResourceList
= (PCM_RESOURCE_LIST
)lpBuffer
;
100 GetSerialPortNumber(IN HDEVINFO DeviceInfoSet
,
101 IN PSP_DEVINFO_DATA DeviceInfoData
)
103 PCM_RESOURCE_LIST lpResourceList
= NULL
;
104 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes
;
106 DWORD dwBaseAddress
= 0;
107 DWORD dwPortNumber
= 0;
109 TRACE("GetSerialPortNumber(%p, %p)\n",
110 DeviceInfoSet
, DeviceInfoData
);
112 if (GetBootResourceList(DeviceInfoSet
,
116 TRACE("Full resource descriptors: %ul\n", lpResourceList
->Count
);
117 if (lpResourceList
->Count
> 0)
119 TRACE("Partial resource descriptors: %ul\n", lpResourceList
->List
[0].PartialResourceList
.Count
);
121 for (i
= 0; i
< lpResourceList
->List
[0].PartialResourceList
.Count
; i
++)
123 lpResDes
= &lpResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
124 TRACE("Type: %u\n", lpResDes
->Type
);
126 switch (lpResDes
->Type
)
128 case CmResourceTypePort
:
129 TRACE("Port: Start: %I64x Length: %lu\n",
130 lpResDes
->u
.Port
.Start
.QuadPart
,
131 lpResDes
->u
.Port
.Length
);
132 if (lpResDes
->u
.Port
.Start
.HighPart
== 0)
133 dwBaseAddress
= (DWORD
)lpResDes
->u
.Port
.Start
.LowPart
;
136 case CmResourceTypeInterrupt
:
137 TRACE("Interrupt: Level: %lu Vector: %lu\n",
138 lpResDes
->u
.Interrupt
.Level
,
139 lpResDes
->u
.Interrupt
.Vector
);
145 HeapFree(GetProcessHeap(), 0, lpResourceList
);
148 switch (dwBaseAddress
)
172 GetParallelPortNumber(IN HDEVINFO DeviceInfoSet
,
173 IN PSP_DEVINFO_DATA DeviceInfoData
)
175 PCM_RESOURCE_LIST lpResourceList
= NULL
;
176 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes
;
178 DWORD dwBaseAddress
= 0;
179 DWORD dwPortNumber
= 0;
181 TRACE("GetParallelPortNumber(%p, %p)\n",
182 DeviceInfoSet
, DeviceInfoData
);
184 if (GetBootResourceList(DeviceInfoSet
,
188 TRACE("Full resource descriptors: %ul\n", lpResourceList
->Count
);
189 if (lpResourceList
->Count
> 0)
191 TRACE("Partial resource descriptors: %ul\n", lpResourceList
->List
[0].PartialResourceList
.Count
);
193 for (i
= 0; i
< lpResourceList
->List
[0].PartialResourceList
.Count
; i
++)
195 lpResDes
= &lpResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
196 TRACE("Type: %u\n", lpResDes
->Type
);
198 switch (lpResDes
->Type
)
200 case CmResourceTypePort
:
201 TRACE("Port: Start: %I64x Length: %lu\n",
202 lpResDes
->u
.Port
.Start
.QuadPart
,
203 lpResDes
->u
.Port
.Length
);
204 if (lpResDes
->u
.Port
.Start
.HighPart
== 0)
205 dwBaseAddress
= (DWORD
)lpResDes
->u
.Port
.Start
.LowPart
;
208 case CmResourceTypeInterrupt
:
209 TRACE("Interrupt: Level: %lu Vector: %lu\n",
210 lpResDes
->u
.Interrupt
.Level
,
211 lpResDes
->u
.Interrupt
.Vector
);
219 HeapFree(GetProcessHeap(), 0, lpResourceList
);
222 switch (dwBaseAddress
)
238 InstallSerialPort(IN HDEVINFO DeviceInfoSet
,
239 IN PSP_DEVINFO_DATA DeviceInfoData
)
241 WCHAR szDeviceDescription
[256];
242 WCHAR szFriendlyName
[256];
244 DWORD dwPortNumber
= 0;
246 HCOMDB hComDB
= HCOMDB_INVALID_HANDLE_VALUE
;
250 TRACE("InstallSerialPort(%p, %p)\n",
251 DeviceInfoSet
, DeviceInfoData
);
253 /* Open the com port database */
256 /* Try to read the 'PortName' value and determine the port number */
257 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
264 if (hKey
!= INVALID_HANDLE_VALUE
)
266 dwSize
= sizeof(szPortName
);
267 lError
= RegQueryValueEx(hKey
,
273 if (lError
== ERROR_SUCCESS
)
275 if (_wcsnicmp(szPortName
, pszCom
, wcslen(pszCom
)) == 0)
277 dwPortNumber
= _wtoi(szPortName
+ wcslen(pszCom
));
278 TRACE("COM port number found: %lu\n", dwPortNumber
);
285 /* Determine the port number from its resources ... */
286 if (dwPortNumber
== 0)
287 dwPortNumber
= GetSerialPortNumber(DeviceInfoSet
,
290 if (dwPortNumber
!= 0)
292 /* ... and claim the port number in the database */
293 ComDBClaimPort(hComDB
,
300 /* ... or claim the next free port number */
301 ComDBClaimNextFreePort(hComDB
,
305 /* Build the name of the port device */
306 swprintf(szPortName
, L
"%s%u", pszCom
, dwPortNumber
);
308 /* Close the com port database */
309 if (hComDB
!= HCOMDB_INVALID_HANDLE_VALUE
)
312 /* Set the 'PortName' value */
313 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
320 if (hKey
!= INVALID_HANDLE_VALUE
)
327 (wcslen(szPortName
) + 1) * sizeof(WCHAR
));
332 /* Install the device */
333 if (!SetupDiInstallDevice(DeviceInfoSet
,
336 return GetLastError();
339 /* Get the device description... */
340 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
344 (LPBYTE
)szDeviceDescription
,
348 /* ... and use it to build a new friendly name */
349 swprintf(szFriendlyName
,
356 /* ... or build a generic friendly name */
357 swprintf(szFriendlyName
,
362 /* Set the friendly name for the device */
363 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet
,
366 (LPBYTE
)szFriendlyName
,
367 (wcslen(szFriendlyName
) + 1) * sizeof(WCHAR
));
369 return ERROR_SUCCESS
;
374 InstallParallelPort(IN HDEVINFO DeviceInfoSet
,
375 IN PSP_DEVINFO_DATA DeviceInfoData
)
377 WCHAR szDeviceDescription
[256];
378 WCHAR szFriendlyName
[256];
380 DWORD dwPortNumber
= 0;
385 TRACE("InstallParallelPort(%p, %p)\n",
386 DeviceInfoSet
, DeviceInfoData
);
388 /* Try to read the 'PortName' value and determine the port number */
389 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
396 if (hKey
!= INVALID_HANDLE_VALUE
)
398 dwSize
= sizeof(szPortName
);
399 lError
= RegQueryValueEx(hKey
,
405 if (lError
== ERROR_SUCCESS
)
407 if (_wcsnicmp(szPortName
, pszLpt
, wcslen(pszLpt
)) == 0)
409 dwPortNumber
= _wtoi(szPortName
+ wcslen(pszLpt
));
410 TRACE("LPT port number found: %lu\n", dwPortNumber
);
417 /* ... try to determine the port number from its resources */
418 if (dwPortNumber
== 0)
419 dwPortNumber
= GetParallelPortNumber(DeviceInfoSet
,
422 if (dwPortNumber
== 0)
427 if (dwPortNumber
!= 0)
429 swprintf(szPortName
, L
"%s%u", pszLpt
, dwPortNumber
);
433 wcscpy(szPortName
, L
"LPTx");
436 if (dwPortNumber
!= 0)
438 /* Set the 'PortName' value */
439 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
446 if (hKey
!= INVALID_HANDLE_VALUE
)
453 (wcslen(szPortName
) + 1) * sizeof(WCHAR
));
459 /* Install the device */
460 if (!SetupDiInstallDevice(DeviceInfoSet
,
463 return GetLastError();
466 /* Get the device description... */
467 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
471 (LPBYTE
)szDeviceDescription
,
475 /* ... and use it to build a new friendly name */
476 swprintf(szFriendlyName
,
483 /* ... or build a generic friendly name */
484 swprintf(szFriendlyName
,
485 L
"Parallel Port (%s)",
489 /* Set the friendly name for the device */
490 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet
,
493 (LPBYTE
)szFriendlyName
,
494 (wcslen(szFriendlyName
) + 1) * sizeof(WCHAR
));
496 return ERROR_SUCCESS
;
501 InstallDeviceData(IN HDEVINFO DeviceInfoSet
,
502 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
505 HINF hInf
= INVALID_HANDLE_VALUE
;
506 SP_DRVINFO_DATA DriverInfoData
;
507 PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData
;
508 WCHAR InfSectionWithExt
[256];
512 TRACE("InstallDeviceData()\n");
514 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
524 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA
);
525 if (!SetupDiGetSelectedDriverW(DeviceInfoSet
,
532 DriverInfoDetailData
= (PSP_DRVINFO_DETAIL_DATA
)buffer
;
533 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
534 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
537 DriverInfoDetailData
,
541 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
545 TRACE("Inf file name: %S\n", DriverInfoDetailData
->InfFileName
);
547 hInf
= SetupOpenInfFileW(DriverInfoDetailData
->InfFileName
,
551 if (hInf
== INVALID_HANDLE_VALUE
)
554 TRACE("Section name: %S\n", DriverInfoDetailData
->SectionName
);
556 SetupDiGetActualSectionToInstallW(hInf
,
557 DriverInfoDetailData
->SectionName
,
563 TRACE("InfSectionWithExt: %S\n", InfSectionWithExt
);
565 SetupInstallFromInfSectionW(NULL
,
583 if (hInf
!= INVALID_HANDLE_VALUE
)
584 SetupCloseInfFile(hInf
);
590 GetPortType(IN HDEVINFO DeviceInfoSet
,
591 IN PSP_DEVINFO_DATA DeviceInfoData
)
597 PORT_TYPE PortType
= UnknownPort
;
600 TRACE("GetPortType()\n");
602 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
614 dwSize
= sizeof(BYTE
);
615 lError
= RegQueryValueExW(hKey
,
622 TRACE("lError: %ld\n", lError
);
623 TRACE("dwSize: %lu\n", dwSize
);
624 TRACE("dwType: %lu\n", dwType
);
626 if (lError
== ERROR_SUCCESS
&&
627 dwSize
== sizeof(BYTE
) &&
628 dwType
== REG_BINARY
)
631 PortType
= ParallelPort
;
633 PortType
= SerialPort
;
640 TRACE("GetPortType() returns %u \n", PortType
);
647 InstallPort(IN HDEVINFO DeviceInfoSet
,
648 IN PSP_DEVINFO_DATA DeviceInfoData
)
652 InstallDeviceData(DeviceInfoSet
, DeviceInfoData
);
654 PortType
= GetPortType(DeviceInfoSet
, DeviceInfoData
);
658 return InstallParallelPort(DeviceInfoSet
, DeviceInfoData
);
661 return InstallSerialPort(DeviceInfoSet
, DeviceInfoData
);
664 return ERROR_DI_DO_DEFAULT
;
670 RemovePort(IN HDEVINFO DeviceInfoSet
,
671 IN PSP_DEVINFO_DATA DeviceInfoData
)
674 HCOMDB hComDB
= HCOMDB_INVALID_HANDLE_VALUE
;
678 DWORD dwPortNameSize
;
681 /* If we are removing a serial port ... */
682 PortType
= GetPortType(DeviceInfoSet
, DeviceInfoData
);
683 if (PortType
== SerialPort
)
685 /* Open the port database */
686 if (ComDBOpen(&hComDB
) == ERROR_SUCCESS
)
688 /* Open the device key */
689 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
695 if (hKey
!= INVALID_HANDLE_VALUE
)
697 /* Query the port name */
698 dwPortNameSize
= sizeof(szPortName
);
699 lError
= RegQueryValueEx(hKey
,
706 /* Close the device key */
709 /* If we got a valid port name ...*/
710 if (lError
== ERROR_SUCCESS
)
712 /* Get the port number */
713 dwPortNumber
= _wtoi(szPortName
+ wcslen(pszCom
));
715 /* Release the port */
716 ComDBReleasePort(hComDB
, dwPortNumber
);
720 /* Close the port database */
725 /* Remove the device */
726 if (!SetupDiRemoveDevice(DeviceInfoSet
, DeviceInfoData
))
727 return GetLastError();
729 return ERROR_SUCCESS
;
735 PortsClassInstaller(IN DI_FUNCTION InstallFunction
,
736 IN HDEVINFO DeviceInfoSet
,
737 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
739 TRACE("PortsClassInstaller(%lu, %p, %p)\n",
740 InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
742 switch (InstallFunction
)
744 case DIF_INSTALLDEVICE
:
745 return InstallPort(DeviceInfoSet
, DeviceInfoData
);
748 return RemovePort(DeviceInfoSet
, DeviceInfoData
);
751 TRACE("Install function %u ignored\n", InstallFunction
);
752 return ERROR_DI_DO_DEFAULT
;