1 /* 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 7 */ 8 9 #include "precomp.h" 10 11 #include <wchar.h> 12 13 #define NTOS_MODE_USER 14 #include <ndk/cmtypes.h> 15 16 typedef enum _PORT_TYPE 17 { 18 UnknownPort, 19 ParallelPort, 20 SerialPort 21 } PORT_TYPE; 22 23 LPWSTR pszCom = L"COM"; 24 LPWSTR pszLpt = L"LPT"; 25 26 27 BOOL 28 GetBootResourceList(HDEVINFO DeviceInfoSet, 29 PSP_DEVINFO_DATA DeviceInfoData, 30 PCM_RESOURCE_LIST *ppResourceList) 31 { 32 WCHAR DeviceInstanceIdBuffer[128]; 33 HKEY hEnumKey = NULL; 34 HKEY hDeviceKey = NULL; 35 HKEY hConfigKey = NULL; 36 LPBYTE lpBuffer = NULL; 37 DWORD dwDataSize; 38 LONG lError; 39 BOOL ret = FALSE; 40 41 FIXME("GetBootResourceList()\n"); 42 43 *ppResourceList = NULL; 44 45 if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet, 46 DeviceInfoData, 47 DeviceInstanceIdBuffer, 48 ARRAYSIZE(DeviceInstanceIdBuffer), 49 &dwDataSize)) 50 { 51 ERR("SetupDiGetDeviceInstanceIdW() failed\n"); 52 return FALSE; 53 } 54 55 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 56 L"SYSTEM\\CurrentControlSet\\Enum", 57 0, 58 KEY_QUERY_VALUE, 59 &hEnumKey); 60 if (lError != ERROR_SUCCESS) 61 { 62 ERR("RegOpenKeyExW() failed (Error %lu)\n", lError); 63 goto done; 64 } 65 66 lError = RegOpenKeyExW(hEnumKey, 67 DeviceInstanceIdBuffer, 68 0, 69 KEY_QUERY_VALUE, 70 &hDeviceKey); 71 if (lError != ERROR_SUCCESS) 72 { 73 ERR("RegOpenKeyExW() failed (Error %lu)\n", lError); 74 goto done; 75 } 76 77 lError = RegOpenKeyExW(hDeviceKey, 78 L"LogConf", 79 0, 80 KEY_QUERY_VALUE, 81 &hConfigKey); 82 if (lError != ERROR_SUCCESS) 83 { 84 ERR("RegOpenKeyExW() failed (Error %lu)\n", lError); 85 goto done; 86 } 87 88 /* Get the configuration data size */ 89 lError = RegQueryValueExW(hConfigKey, 90 L"BootConfig", 91 NULL, 92 NULL, 93 NULL, 94 &dwDataSize); 95 if (lError != ERROR_SUCCESS) 96 { 97 ERR("RegQueryValueExW() failed (Error %lu)\n", lError); 98 goto done; 99 } 100 101 /* Allocate the buffer */ 102 lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwDataSize); 103 if (lpBuffer == NULL) 104 { 105 ERR("Failed to allocate the resource list buffer\n"); 106 goto done; 107 } 108 109 /* Retrieve the configuration data */ 110 lError = RegQueryValueExW(hConfigKey, 111 L"BootConfig", 112 NULL, 113 NULL, 114 (LPBYTE)lpBuffer, 115 &dwDataSize); 116 if (lError == ERROR_SUCCESS) 117 { 118 ERR("RegQueryValueExW() failed (Error %lu)\n", lError); 119 ret = TRUE; 120 } 121 122 done: 123 if (ret == FALSE && lpBuffer != NULL) 124 HeapFree(GetProcessHeap(), 0, lpBuffer); 125 126 if (hConfigKey) 127 RegCloseKey(hConfigKey); 128 129 if (hDeviceKey) 130 RegCloseKey(hDeviceKey); 131 132 if (hEnumKey) 133 RegCloseKey(hEnumKey); 134 135 if (ret != FALSE) 136 *ppResourceList = (PCM_RESOURCE_LIST)lpBuffer; 137 138 return ret; 139 } 140 141 142 DWORD 143 GetSerialPortNumber(IN HDEVINFO DeviceInfoSet, 144 IN PSP_DEVINFO_DATA DeviceInfoData) 145 { 146 PCM_RESOURCE_LIST lpResourceList = NULL; 147 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes; 148 ULONG i; 149 DWORD dwBaseAddress = 0; 150 DWORD dwPortNumber = 0; 151 152 TRACE("GetSerialPortNumber(%p, %p)\n", 153 DeviceInfoSet, DeviceInfoData); 154 155 if (GetBootResourceList(DeviceInfoSet, 156 DeviceInfoData, 157 &lpResourceList)) 158 { 159 TRACE("Full resource descriptors: %ul\n", lpResourceList->Count); 160 if (lpResourceList->Count > 0) 161 { 162 TRACE("Partial resource descriptors: %ul\n", lpResourceList->List[0].PartialResourceList.Count); 163 164 for (i = 0; i < lpResourceList->List[0].PartialResourceList.Count; i++) 165 { 166 lpResDes = &lpResourceList->List[0].PartialResourceList.PartialDescriptors[i]; 167 TRACE("Type: %u\n", lpResDes->Type); 168 169 switch (lpResDes->Type) 170 { 171 case CmResourceTypePort: 172 TRACE("Port: Start: %I64x Length: %lu\n", 173 lpResDes->u.Port.Start.QuadPart, 174 lpResDes->u.Port.Length); 175 if ((lpResDes->u.Port.Start.HighPart == 0) && (dwBaseAddress == 0)) 176 dwBaseAddress = (DWORD)lpResDes->u.Port.Start.LowPart; 177 break; 178 179 case CmResourceTypeInterrupt: 180 TRACE("Interrupt: Level: %lu Vector: %lu\n", 181 lpResDes->u.Interrupt.Level, 182 lpResDes->u.Interrupt.Vector); 183 break; 184 } 185 } 186 } 187 188 HeapFree(GetProcessHeap(), 0, lpResourceList); 189 } 190 191 switch (dwBaseAddress) 192 { 193 case 0x3f8: 194 dwPortNumber = 1; 195 break; 196 197 case 0x2f8: 198 dwPortNumber = 2; 199 break; 200 201 case 0x3e8: 202 dwPortNumber = 3; 203 break; 204 205 case 0x2e8: 206 dwPortNumber = 4; 207 break; 208 } 209 210 return dwPortNumber; 211 } 212 213 214 DWORD 215 GetParallelPortNumber(IN HDEVINFO DeviceInfoSet, 216 IN PSP_DEVINFO_DATA DeviceInfoData) 217 { 218 PCM_RESOURCE_LIST lpResourceList = NULL; 219 PCM_PARTIAL_RESOURCE_DESCRIPTOR lpResDes; 220 ULONG i; 221 DWORD dwBaseAddress = 0; 222 DWORD dwPortNumber = 0; 223 224 TRACE("GetParallelPortNumber(%p, %p)\n", 225 DeviceInfoSet, DeviceInfoData); 226 227 if (GetBootResourceList(DeviceInfoSet, 228 DeviceInfoData, 229 &lpResourceList)) 230 { 231 TRACE("Full resource descriptors: %ul\n", lpResourceList->Count); 232 if (lpResourceList->Count > 0) 233 { 234 TRACE("Partial resource descriptors: %ul\n", lpResourceList->List[0].PartialResourceList.Count); 235 236 for (i = 0; i < lpResourceList->List[0].PartialResourceList.Count; i++) 237 { 238 lpResDes = &lpResourceList->List[0].PartialResourceList.PartialDescriptors[i]; 239 TRACE("Type: %u\n", lpResDes->Type); 240 241 switch (lpResDes->Type) 242 { 243 case CmResourceTypePort: 244 TRACE("Port: Start: %I64x Length: %lu\n", 245 lpResDes->u.Port.Start.QuadPart, 246 lpResDes->u.Port.Length); 247 if ((lpResDes->u.Port.Start.HighPart == 0) && (dwBaseAddress == 0)) 248 dwBaseAddress = (DWORD)lpResDes->u.Port.Start.LowPart; 249 break; 250 251 case CmResourceTypeInterrupt: 252 TRACE("Interrupt: Level: %lu Vector: %lu\n", 253 lpResDes->u.Interrupt.Level, 254 lpResDes->u.Interrupt.Vector); 255 break; 256 } 257 258 } 259 260 } 261 262 HeapFree(GetProcessHeap(), 0, lpResourceList); 263 } 264 265 switch (dwBaseAddress) 266 { 267 case 0x378: 268 dwPortNumber = 1; 269 break; 270 271 case 0x278: 272 dwPortNumber = 2; 273 break; 274 } 275 276 return dwPortNumber; 277 } 278 279 280 static DWORD 281 InstallSerialPort(IN HDEVINFO DeviceInfoSet, 282 IN PSP_DEVINFO_DATA DeviceInfoData) 283 { 284 WCHAR szDeviceDescription[256]; 285 WCHAR szFriendlyName[256]; 286 WCHAR szPortName[8]; 287 DWORD dwPortNumber = 0; 288 DWORD dwSize; 289 HCOMDB hComDB = HCOMDB_INVALID_HANDLE_VALUE; 290 HKEY hKey; 291 LONG lError; 292 293 TRACE("InstallSerialPort(%p, %p)\n", 294 DeviceInfoSet, DeviceInfoData); 295 296 /* Open the com port database */ 297 ComDBOpen(&hComDB); 298 299 /* Try to read the 'PortName' value and determine the port number */ 300 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, 301 DeviceInfoData, 302 DICS_FLAG_GLOBAL, 303 0, 304 DIREG_DEV, 305 NULL, 306 NULL); 307 if (hKey != INVALID_HANDLE_VALUE) 308 { 309 dwSize = sizeof(szPortName); 310 lError = RegQueryValueEx(hKey, 311 L"PortName", 312 NULL, 313 NULL, 314 (PBYTE)szPortName, 315 &dwSize); 316 if (lError == ERROR_SUCCESS) 317 { 318 if (_wcsnicmp(szPortName, pszCom, wcslen(pszCom)) == 0) 319 { 320 dwPortNumber = _wtoi(szPortName + wcslen(pszCom)); 321 TRACE("COM port number found: %lu\n", dwPortNumber); 322 } 323 } 324 325 RegCloseKey(hKey); 326 } 327 328 /* Determine the port number from its resources ... */ 329 if (dwPortNumber == 0) 330 dwPortNumber = GetSerialPortNumber(DeviceInfoSet, 331 DeviceInfoData); 332 333 if (dwPortNumber != 0) 334 { 335 /* ... and claim the port number in the database */ 336 ComDBClaimPort(hComDB, 337 dwPortNumber, 338 FALSE, 339 NULL); 340 } 341 else 342 { 343 /* ... or claim the next free port number */ 344 ComDBClaimNextFreePort(hComDB, 345 &dwPortNumber); 346 } 347 348 /* Build the name of the port device */ 349 swprintf(szPortName, L"%s%u", pszCom, dwPortNumber); 350 351 /* Close the com port database */ 352 if (hComDB != HCOMDB_INVALID_HANDLE_VALUE) 353 ComDBClose(hComDB); 354 355 /* Set the 'PortName' value */ 356 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, 357 DeviceInfoData, 358 DICS_FLAG_GLOBAL, 359 0, 360 DIREG_DEV, 361 NULL, 362 NULL); 363 if (hKey != INVALID_HANDLE_VALUE) 364 { 365 RegSetValueExW(hKey, 366 L"PortName", 367 0, 368 REG_SZ, 369 (LPBYTE)szPortName, 370 (wcslen(szPortName) + 1) * sizeof(WCHAR)); 371 372 RegCloseKey(hKey); 373 } 374 375 /* Install the device */ 376 if (!SetupDiInstallDevice(DeviceInfoSet, 377 DeviceInfoData)) 378 { 379 return GetLastError(); 380 } 381 382 /* Get the device description... */ 383 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, 384 DeviceInfoData, 385 SPDRP_DEVICEDESC, 386 NULL, 387 (LPBYTE)szDeviceDescription, 388 256 * sizeof(WCHAR), 389 NULL)) 390 { 391 /* ... and use it to build a new friendly name */ 392 swprintf(szFriendlyName, 393 L"%s (%s)", 394 szDeviceDescription, 395 szPortName); 396 } 397 else 398 { 399 /* ... or build a generic friendly name */ 400 swprintf(szFriendlyName, 401 L"Serial Port (%s)", 402 szPortName); 403 } 404 405 /* Set the friendly name for the device */ 406 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet, 407 DeviceInfoData, 408 SPDRP_FRIENDLYNAME, 409 (LPBYTE)szFriendlyName, 410 (wcslen(szFriendlyName) + 1) * sizeof(WCHAR)); 411 412 return ERROR_SUCCESS; 413 } 414 415 416 static DWORD 417 InstallParallelPort(IN HDEVINFO DeviceInfoSet, 418 IN PSP_DEVINFO_DATA DeviceInfoData) 419 { 420 WCHAR szDeviceDescription[256]; 421 WCHAR szFriendlyName[256]; 422 WCHAR szPortName[8]; 423 DWORD dwPortNumber = 0; 424 DWORD dwSize; 425 DWORD dwValue; 426 LONG lError; 427 HKEY hKey; 428 429 TRACE("InstallParallelPort(%p, %p)\n", 430 DeviceInfoSet, DeviceInfoData); 431 432 /* Try to read the 'PortName' value and determine the port number */ 433 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, 434 DeviceInfoData, 435 DICS_FLAG_GLOBAL, 436 0, 437 DIREG_DEV, 438 NULL, 439 NULL); 440 if (hKey != INVALID_HANDLE_VALUE) 441 { 442 dwSize = sizeof(szPortName); 443 lError = RegQueryValueEx(hKey, 444 L"PortName", 445 NULL, 446 NULL, 447 (PBYTE)szPortName, 448 &dwSize); 449 if (lError == ERROR_SUCCESS) 450 { 451 if (_wcsnicmp(szPortName, pszLpt, wcslen(pszLpt)) == 0) 452 { 453 dwPortNumber = _wtoi(szPortName + wcslen(pszLpt)); 454 TRACE("LPT port number found: %lu\n", dwPortNumber); 455 } 456 } 457 458 RegCloseKey(hKey); 459 } 460 461 /* ... try to determine the port number from its resources */ 462 if (dwPortNumber == 0) 463 { 464 dwPortNumber = GetParallelPortNumber(DeviceInfoSet, 465 DeviceInfoData); 466 TRACE("GetParallelPortNumber() returned port number: %lu\n", dwPortNumber); 467 } 468 469 if (dwPortNumber == 0) 470 { 471 /* FIXME */ 472 FIXME("Got no valid port numer!\n"); 473 } 474 475 if (dwPortNumber != 0) 476 { 477 swprintf(szPortName, L"%s%u", pszLpt, dwPortNumber); 478 } 479 else 480 { 481 wcscpy(szPortName, L"LPTx"); 482 } 483 484 if (dwPortNumber != 0) 485 { 486 /* Set the 'PortName' value */ 487 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, 488 DeviceInfoData, 489 DICS_FLAG_GLOBAL, 490 0, 491 DIREG_DEV, 492 NULL, 493 NULL); 494 if (hKey != INVALID_HANDLE_VALUE) 495 { 496 RegSetValueExW(hKey, 497 L"PortName", 498 0, 499 REG_SZ, 500 (LPBYTE)szPortName, 501 (wcslen(szPortName) + 1) * sizeof(WCHAR)); 502 503 /* 504 * FIXME / HACK: 505 * This is to get the w2k3 parport.sys to work until we have our own. 506 * This setting makes the driver accept resources with an IRQ instead 507 * of only resources without an IRQ. 508 * 509 * We should probably also fix IO manager to actually give devices a 510 * chance to register without an IRQ. CORE-9645 511 */ 512 dwValue = 0; 513 RegSetValueExW(hKey, 514 L"FilterResourceMethod", 515 0, 516 REG_DWORD, 517 (LPBYTE)&dwValue, 518 sizeof(dwValue)); 519 520 RegCloseKey(hKey); 521 } 522 } 523 524 /* Install the device */ 525 if (!SetupDiInstallDevice(DeviceInfoSet, 526 DeviceInfoData)) 527 { 528 return GetLastError(); 529 } 530 531 /* Get the device description... */ 532 if (SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, 533 DeviceInfoData, 534 SPDRP_DEVICEDESC, 535 NULL, 536 (LPBYTE)szDeviceDescription, 537 256 * sizeof(WCHAR), 538 NULL)) 539 { 540 /* ... and use it to build a new friendly name */ 541 swprintf(szFriendlyName, 542 L"%s (%s)", 543 szDeviceDescription, 544 szPortName); 545 } 546 else 547 { 548 /* ... or build a generic friendly name */ 549 swprintf(szFriendlyName, 550 L"Parallel Port (%s)", 551 szPortName); 552 } 553 554 TRACE("Friendly name: %S\n", szFriendlyName); 555 556 /* Set the friendly name for the device */ 557 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet, 558 DeviceInfoData, 559 SPDRP_FRIENDLYNAME, 560 (LPBYTE)szFriendlyName, 561 (wcslen(szFriendlyName) + 1) * sizeof(WCHAR)); 562 563 return ERROR_SUCCESS; 564 } 565 566 567 VOID 568 InstallDeviceData(IN HDEVINFO DeviceInfoSet, 569 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 570 { 571 HKEY hKey = NULL; 572 HINF hInf = INVALID_HANDLE_VALUE; 573 SP_DRVINFO_DATA DriverInfoData; 574 PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData; 575 WCHAR InfSectionWithExt[256]; 576 BYTE buffer[2048]; 577 DWORD dwRequired; 578 579 TRACE("InstallDeviceData()\n"); 580 581 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, 582 DeviceInfoData, 583 DICS_FLAG_GLOBAL, 584 0, 585 DIREG_DRV, 586 NULL, 587 NULL); 588 if (hKey == NULL) 589 goto done; 590 591 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA); 592 if (!SetupDiGetSelectedDriverW(DeviceInfoSet, 593 DeviceInfoData, 594 &DriverInfoData)) 595 { 596 goto done; 597 } 598 599 DriverInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)buffer; 600 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); 601 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, 602 DeviceInfoData, 603 &DriverInfoData, 604 DriverInfoDetailData, 605 2048, 606 &dwRequired)) 607 { 608 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 609 goto done; 610 } 611 612 TRACE("Inf file name: %S\n", DriverInfoDetailData->InfFileName); 613 614 hInf = SetupOpenInfFileW(DriverInfoDetailData->InfFileName, 615 NULL, 616 INF_STYLE_WIN4, 617 NULL); 618 if (hInf == INVALID_HANDLE_VALUE) 619 goto done; 620 621 TRACE("Section name: %S\n", DriverInfoDetailData->SectionName); 622 623 if (!SetupDiGetActualSectionToInstallW(hInf, 624 DriverInfoDetailData->SectionName, 625 InfSectionWithExt, 626 256, 627 NULL, 628 NULL)) 629 goto done; 630 631 TRACE("InfSectionWithExt: %S\n", InfSectionWithExt); 632 633 SetupInstallFromInfSectionW(NULL, 634 hInf, 635 InfSectionWithExt, 636 SPINST_REGISTRY, 637 hKey, 638 NULL, 639 0, 640 NULL, 641 NULL, 642 NULL, 643 NULL); 644 645 TRACE("Done\n"); 646 647 done: 648 if (hKey != NULL) 649 RegCloseKey(hKey); 650 651 if (hInf != INVALID_HANDLE_VALUE) 652 SetupCloseInfFile(hInf); 653 } 654 655 656 657 PORT_TYPE 658 GetPortType(IN HDEVINFO DeviceInfoSet, 659 IN PSP_DEVINFO_DATA DeviceInfoData) 660 { 661 HKEY hKey = NULL; 662 DWORD dwSize; 663 DWORD dwType = 0; 664 BYTE bData = 0; 665 PORT_TYPE PortType = UnknownPort; 666 LONG lError; 667 668 TRACE("GetPortType()\n"); 669 670 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, 671 DeviceInfoData, 672 DICS_FLAG_GLOBAL, 673 0, 674 DIREG_DRV, 675 NULL, 676 NULL); 677 if (hKey == NULL) 678 { 679 goto done; 680 } 681 682 dwSize = sizeof(BYTE); 683 lError = RegQueryValueExW(hKey, 684 L"PortSubClass", 685 NULL, 686 &dwType, 687 &bData, 688 &dwSize); 689 690 TRACE("lError: %ld\n", lError); 691 TRACE("dwSize: %lu\n", dwSize); 692 TRACE("dwType: %lu\n", dwType); 693 694 if (lError == ERROR_SUCCESS && 695 dwSize == sizeof(BYTE) && 696 dwType == REG_BINARY) 697 { 698 if (bData == 0) 699 PortType = ParallelPort; 700 else 701 PortType = SerialPort; 702 } 703 704 done: 705 if (hKey != NULL) 706 RegCloseKey(hKey); 707 708 TRACE("GetPortType() returns %u \n", PortType); 709 710 return PortType; 711 } 712 713 714 static DWORD 715 InstallPort(IN HDEVINFO DeviceInfoSet, 716 IN PSP_DEVINFO_DATA DeviceInfoData) 717 { 718 PORT_TYPE PortType; 719 720 InstallDeviceData(DeviceInfoSet, DeviceInfoData); 721 722 PortType = GetPortType(DeviceInfoSet, DeviceInfoData); 723 switch (PortType) 724 { 725 case ParallelPort: 726 return InstallParallelPort(DeviceInfoSet, DeviceInfoData); 727 728 case SerialPort: 729 return InstallSerialPort(DeviceInfoSet, DeviceInfoData); 730 731 default: 732 return ERROR_DI_DO_DEFAULT; 733 } 734 } 735 736 737 static DWORD 738 RemovePort(IN HDEVINFO DeviceInfoSet, 739 IN PSP_DEVINFO_DATA DeviceInfoData) 740 { 741 PORT_TYPE PortType; 742 HCOMDB hComDB = HCOMDB_INVALID_HANDLE_VALUE; 743 HKEY hKey; 744 LONG lError; 745 DWORD dwPortNumber; 746 DWORD dwPortNameSize; 747 WCHAR szPortName[8]; 748 749 /* If we are removing a serial port ... */ 750 PortType = GetPortType(DeviceInfoSet, DeviceInfoData); 751 if (PortType == SerialPort) 752 { 753 /* Open the port database */ 754 if (ComDBOpen(&hComDB) == ERROR_SUCCESS) 755 { 756 /* Open the device key */ 757 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, 758 DeviceInfoData, 759 DICS_FLAG_GLOBAL, 760 0, 761 DIREG_DEV, 762 KEY_READ); 763 if (hKey != INVALID_HANDLE_VALUE) 764 { 765 /* Query the port name */ 766 dwPortNameSize = sizeof(szPortName); 767 lError = RegQueryValueEx(hKey, 768 L"PortName", 769 NULL, 770 NULL, 771 (PBYTE)szPortName, 772 &dwPortNameSize); 773 774 /* Close the device key */ 775 RegCloseKey(hKey); 776 777 /* If we got a valid port name ...*/ 778 if (lError == ERROR_SUCCESS) 779 { 780 /* Get the port number */ 781 dwPortNumber = _wtoi(szPortName + wcslen(pszCom)); 782 783 /* Release the port */ 784 ComDBReleasePort(hComDB, dwPortNumber); 785 } 786 } 787 788 /* Close the port database */ 789 ComDBClose(hComDB); 790 } 791 } 792 793 /* Remove the device */ 794 if (!SetupDiRemoveDevice(DeviceInfoSet, DeviceInfoData)) 795 return GetLastError(); 796 797 return ERROR_SUCCESS; 798 } 799 800 801 DWORD 802 WINAPI 803 PortsClassInstaller(IN DI_FUNCTION InstallFunction, 804 IN HDEVINFO DeviceInfoSet, 805 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 806 { 807 TRACE("PortsClassInstaller(%lu, %p, %p)\n", 808 InstallFunction, DeviceInfoSet, DeviceInfoData); 809 810 switch (InstallFunction) 811 { 812 case DIF_INSTALLDEVICE: 813 return InstallPort(DeviceInfoSet, DeviceInfoData); 814 815 case DIF_REMOVE: 816 return RemovePort(DeviceInfoSet, DeviceInfoData); 817 818 default: 819 TRACE("Install function %u ignored\n", InstallFunction); 820 return ERROR_DI_DO_DEFAULT; 821 } 822 } 823 824 /* EOF */ 825