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 typedef enum _PORT_TYPE
18 LPWSTR pszCom
= L
"COM";
19 LPWSTR pszLpt
= L
"LPT";
23 GetBootResourceList(HDEVINFO DeviceInfoSet
,
24 PSP_DEVINFO_DATA DeviceInfoData
,
25 PCM_RESOURCE_LIST
*ppResourceList
)
27 HKEY hDeviceKey
= NULL
;
28 HKEY hConfigKey
= NULL
;
29 LPBYTE lpBuffer
= NULL
;
34 *ppResourceList
= NULL
;
36 hDeviceKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
46 lError
= RegOpenKeyExW(hDeviceKey
,
51 if (lError
!= ERROR_SUCCESS
)
54 /* Get the configuration data size */
55 lError
= RegQueryValueExW(hConfigKey
,
61 if (lError
!= ERROR_SUCCESS
)
64 /* Allocate the buffer */
65 lpBuffer
= HeapAlloc(GetProcessHeap(), 0, dwDataSize
);
69 /* Retrieve the configuration data */
70 lError
= RegQueryValueExW(hConfigKey
,
76 if (lError
== ERROR_SUCCESS
)
80 if (ret
== FALSE
&& lpBuffer
!= NULL
)
81 HeapFree(GetProcessHeap(), 0, lpBuffer
);
84 RegCloseKey(hConfigKey
);
87 RegCloseKey(hDeviceKey
);
90 *ppResourceList
= (PCM_RESOURCE_LIST
)lpBuffer
;
97 GetSerialPortNumber(IN HDEVINFO DeviceInfoSet
,
98 IN PSP_DEVINFO_DATA DeviceInfoData
)
100 PCM_RESOURCE_LIST lpResourceList
= NULL
;
101 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes
;
103 DWORD dwBaseAddress
= 0;
104 DWORD dwPortNumber
= 0;
106 TRACE("GetSerialPortNumber(%p, %p)\n",
107 DeviceInfoSet
, DeviceInfoData
);
109 if (GetBootResourceList(DeviceInfoSet
,
113 TRACE("Full resource descriptors: %ul\n", lpResourceList
->Count
);
114 if (lpResourceList
->Count
> 0)
116 TRACE("Partial resource descriptors: %ul\n", lpResourceList
->List
[0].PartialResourceList
.Count
);
118 for (i
= 0; i
< lpResourceList
->List
[0].PartialResourceList
.Count
; i
++)
120 lpResDes
= &lpResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
121 TRACE("Type: %u\n", lpResDes
->Type
);
123 switch (lpResDes
->Type
)
125 case CmResourceTypePort
:
126 TRACE("Port: Start: %I64x Length: %lu\n",
127 lpResDes
->u
.Port
.Start
.QuadPart
,
128 lpResDes
->u
.Port
.Length
);
129 if ((lpResDes
->u
.Port
.Start
.HighPart
== 0) && (dwBaseAddress
== 0))
130 dwBaseAddress
= (DWORD
)lpResDes
->u
.Port
.Start
.LowPart
;
133 case CmResourceTypeInterrupt
:
134 TRACE("Interrupt: Level: %lu Vector: %lu\n",
135 lpResDes
->u
.Interrupt
.Level
,
136 lpResDes
->u
.Interrupt
.Vector
);
142 HeapFree(GetProcessHeap(), 0, lpResourceList
);
145 switch (dwBaseAddress
)
169 GetParallelPortNumber(IN HDEVINFO DeviceInfoSet
,
170 IN PSP_DEVINFO_DATA DeviceInfoData
)
172 PCM_RESOURCE_LIST lpResourceList
= NULL
;
173 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes
;
175 DWORD dwBaseAddress
= 0;
176 DWORD dwPortNumber
= 0;
178 TRACE("GetParallelPortNumber(%p, %p)\n",
179 DeviceInfoSet
, DeviceInfoData
);
181 if (GetBootResourceList(DeviceInfoSet
,
185 TRACE("Full resource descriptors: %ul\n", lpResourceList
->Count
);
186 if (lpResourceList
->Count
> 0)
188 TRACE("Partial resource descriptors: %ul\n", lpResourceList
->List
[0].PartialResourceList
.Count
);
190 for (i
= 0; i
< lpResourceList
->List
[0].PartialResourceList
.Count
; i
++)
192 lpResDes
= &lpResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
193 TRACE("Type: %u\n", lpResDes
->Type
);
195 switch (lpResDes
->Type
)
197 case CmResourceTypePort
:
198 TRACE("Port: Start: %I64x Length: %lu\n",
199 lpResDes
->u
.Port
.Start
.QuadPart
,
200 lpResDes
->u
.Port
.Length
);
201 if ((lpResDes
->u
.Port
.Start
.HighPart
== 0) && (dwBaseAddress
== 0))
202 dwBaseAddress
= (DWORD
)lpResDes
->u
.Port
.Start
.LowPart
;
205 case CmResourceTypeInterrupt
:
206 TRACE("Interrupt: Level: %lu Vector: %lu\n",
207 lpResDes
->u
.Interrupt
.Level
,
208 lpResDes
->u
.Interrupt
.Vector
);
216 HeapFree(GetProcessHeap(), 0, lpResourceList
);
219 switch (dwBaseAddress
)
235 InstallSerialPort(IN HDEVINFO DeviceInfoSet
,
236 IN PSP_DEVINFO_DATA DeviceInfoData
)
238 WCHAR szDeviceDescription
[256];
239 WCHAR szFriendlyName
[256];
241 DWORD dwPortNumber
= 0;
243 HCOMDB hComDB
= HCOMDB_INVALID_HANDLE_VALUE
;
247 TRACE("InstallSerialPort(%p, %p)\n",
248 DeviceInfoSet
, DeviceInfoData
);
250 /* Open the com port database */
253 /* Try to read the 'PortName' value and determine the port number */
254 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
261 if (hKey
!= INVALID_HANDLE_VALUE
)
263 dwSize
= sizeof(szPortName
);
264 lError
= RegQueryValueEx(hKey
,
270 if (lError
== ERROR_SUCCESS
)
272 if (_wcsnicmp(szPortName
, pszCom
, wcslen(pszCom
)) == 0)
274 dwPortNumber
= _wtoi(szPortName
+ wcslen(pszCom
));
275 TRACE("COM port number found: %lu\n", dwPortNumber
);
282 /* Determine the port number from its resources ... */
283 if (dwPortNumber
== 0)
284 dwPortNumber
= GetSerialPortNumber(DeviceInfoSet
,
287 if (dwPortNumber
!= 0)
289 /* ... and claim the port number in the database */
290 ComDBClaimPort(hComDB
,
297 /* ... or claim the next free port number */
298 ComDBClaimNextFreePort(hComDB
,
302 /* Build the name of the port device */
303 swprintf(szPortName
, L
"%s%u", pszCom
, dwPortNumber
);
305 /* Close the com port database */
306 if (hComDB
!= HCOMDB_INVALID_HANDLE_VALUE
)
309 /* Set the 'PortName' value */
310 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
317 if (hKey
!= INVALID_HANDLE_VALUE
)
324 (wcslen(szPortName
) + 1) * sizeof(WCHAR
));
329 /* Install the device */
330 if (!SetupDiInstallDevice(DeviceInfoSet
,
333 return GetLastError();
336 /* Get the device description... */
337 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
341 (LPBYTE
)szDeviceDescription
,
345 /* ... and use it to build a new friendly name */
346 swprintf(szFriendlyName
,
353 /* ... or build a generic friendly name */
354 swprintf(szFriendlyName
,
359 /* Set the friendly name for the device */
360 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet
,
363 (LPBYTE
)szFriendlyName
,
364 (wcslen(szFriendlyName
) + 1) * sizeof(WCHAR
));
366 return ERROR_SUCCESS
;
371 InstallParallelPort(IN HDEVINFO DeviceInfoSet
,
372 IN PSP_DEVINFO_DATA DeviceInfoData
)
374 WCHAR szDeviceDescription
[256];
375 WCHAR szFriendlyName
[256];
377 DWORD dwPortNumber
= 0;
382 TRACE("InstallParallelPort(%p, %p)\n",
383 DeviceInfoSet
, DeviceInfoData
);
385 /* Try to read the 'PortName' value and determine the port number */
386 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
393 if (hKey
!= INVALID_HANDLE_VALUE
)
395 dwSize
= sizeof(szPortName
);
396 lError
= RegQueryValueEx(hKey
,
402 if (lError
== ERROR_SUCCESS
)
404 if (_wcsnicmp(szPortName
, pszLpt
, wcslen(pszLpt
)) == 0)
406 dwPortNumber
= _wtoi(szPortName
+ wcslen(pszLpt
));
407 TRACE("LPT port number found: %lu\n", dwPortNumber
);
414 /* ... try to determine the port number from its resources */
415 if (dwPortNumber
== 0)
417 dwPortNumber
= GetParallelPortNumber(DeviceInfoSet
,
419 TRACE("GetParallelPortNumber() returned port number: %lu\n", dwPortNumber
);
422 if (dwPortNumber
== 0)
425 FIXME("Got no valid port numer!\n");
428 if (dwPortNumber
!= 0)
430 swprintf(szPortName
, L
"%s%u", pszLpt
, dwPortNumber
);
434 wcscpy(szPortName
, L
"LPTx");
437 if (dwPortNumber
!= 0)
439 /* Set the 'PortName' value */
440 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
447 if (hKey
!= INVALID_HANDLE_VALUE
)
454 (wcslen(szPortName
) + 1) * sizeof(WCHAR
));
460 /* Install the device */
461 if (!SetupDiInstallDevice(DeviceInfoSet
,
464 return GetLastError();
467 /* Get the device description... */
468 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
472 (LPBYTE
)szDeviceDescription
,
476 /* ... and use it to build a new friendly name */
477 swprintf(szFriendlyName
,
484 /* ... or build a generic friendly name */
485 swprintf(szFriendlyName
,
486 L
"Parallel Port (%s)",
490 TRACE("Friendly name: %S\n", szFriendlyName
);
492 /* Set the friendly name for the device */
493 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet
,
496 (LPBYTE
)szFriendlyName
,
497 (wcslen(szFriendlyName
) + 1) * sizeof(WCHAR
));
499 return ERROR_SUCCESS
;
504 InstallDeviceData(IN HDEVINFO DeviceInfoSet
,
505 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
508 HINF hInf
= INVALID_HANDLE_VALUE
;
509 SP_DRVINFO_DATA DriverInfoData
;
510 PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData
;
511 WCHAR InfSectionWithExt
[256];
515 TRACE("InstallDeviceData()\n");
517 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
527 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA
);
528 if (!SetupDiGetSelectedDriverW(DeviceInfoSet
,
535 DriverInfoDetailData
= (PSP_DRVINFO_DETAIL_DATA
)buffer
;
536 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
537 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
540 DriverInfoDetailData
,
544 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
548 TRACE("Inf file name: %S\n", DriverInfoDetailData
->InfFileName
);
550 hInf
= SetupOpenInfFileW(DriverInfoDetailData
->InfFileName
,
554 if (hInf
== INVALID_HANDLE_VALUE
)
557 TRACE("Section name: %S\n", DriverInfoDetailData
->SectionName
);
559 SetupDiGetActualSectionToInstallW(hInf
,
560 DriverInfoDetailData
->SectionName
,
566 TRACE("InfSectionWithExt: %S\n", InfSectionWithExt
);
568 SetupInstallFromInfSectionW(NULL
,
586 if (hInf
!= INVALID_HANDLE_VALUE
)
587 SetupCloseInfFile(hInf
);
593 GetPortType(IN HDEVINFO DeviceInfoSet
,
594 IN PSP_DEVINFO_DATA DeviceInfoData
)
600 PORT_TYPE PortType
= UnknownPort
;
603 TRACE("GetPortType()\n");
605 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
617 dwSize
= sizeof(BYTE
);
618 lError
= RegQueryValueExW(hKey
,
625 TRACE("lError: %ld\n", lError
);
626 TRACE("dwSize: %lu\n", dwSize
);
627 TRACE("dwType: %lu\n", dwType
);
629 if (lError
== ERROR_SUCCESS
&&
630 dwSize
== sizeof(BYTE
) &&
631 dwType
== REG_BINARY
)
634 PortType
= ParallelPort
;
636 PortType
= SerialPort
;
643 TRACE("GetPortType() returns %u \n", PortType
);
650 InstallPort(IN HDEVINFO DeviceInfoSet
,
651 IN PSP_DEVINFO_DATA DeviceInfoData
)
655 InstallDeviceData(DeviceInfoSet
, DeviceInfoData
);
657 PortType
= GetPortType(DeviceInfoSet
, DeviceInfoData
);
661 return InstallParallelPort(DeviceInfoSet
, DeviceInfoData
);
664 return InstallSerialPort(DeviceInfoSet
, DeviceInfoData
);
667 return ERROR_DI_DO_DEFAULT
;
673 RemovePort(IN HDEVINFO DeviceInfoSet
,
674 IN PSP_DEVINFO_DATA DeviceInfoData
)
677 HCOMDB hComDB
= HCOMDB_INVALID_HANDLE_VALUE
;
681 DWORD dwPortNameSize
;
684 /* If we are removing a serial port ... */
685 PortType
= GetPortType(DeviceInfoSet
, DeviceInfoData
);
686 if (PortType
== SerialPort
)
688 /* Open the port database */
689 if (ComDBOpen(&hComDB
) == ERROR_SUCCESS
)
691 /* Open the device key */
692 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
,
698 if (hKey
!= INVALID_HANDLE_VALUE
)
700 /* Query the port name */
701 dwPortNameSize
= sizeof(szPortName
);
702 lError
= RegQueryValueEx(hKey
,
709 /* Close the device key */
712 /* If we got a valid port name ...*/
713 if (lError
== ERROR_SUCCESS
)
715 /* Get the port number */
716 dwPortNumber
= _wtoi(szPortName
+ wcslen(pszCom
));
718 /* Release the port */
719 ComDBReleasePort(hComDB
, dwPortNumber
);
723 /* Close the port database */
728 /* Remove the device */
729 if (!SetupDiRemoveDevice(DeviceInfoSet
, DeviceInfoData
))
730 return GetLastError();
732 return ERROR_SUCCESS
;
738 PortsClassInstaller(IN DI_FUNCTION InstallFunction
,
739 IN HDEVINFO DeviceInfoSet
,
740 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
742 TRACE("PortsClassInstaller(%lu, %p, %p)\n",
743 InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
745 switch (InstallFunction
)
747 case DIF_INSTALLDEVICE
:
748 return InstallPort(DeviceInfoSet
, DeviceInfoData
);
751 return RemovePort(DeviceInfoSet
, DeviceInfoData
);
754 TRACE("Install function %u ignored\n", InstallFunction
);
755 return ERROR_DI_DO_DEFAULT
;