1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock 2 API 4 * FILE: dll/win32/ws2_32/src/dcatalog.c 5 * PURPOSE: Transport Catalog Object 6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ws2_32.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* DATA **********************************************************************/ 17 18 #define WsTcLock() EnterCriticalSection(&Catalog->Lock) 19 #define WsTcUnlock() LeaveCriticalSection(&Catalog->Lock) 20 21 /* FUNCTIONS *****************************************************************/ 22 23 PTCATALOG 24 WSAAPI 25 WsTcAllocate(VOID) 26 { 27 PTCATALOG Catalog; 28 29 /* Allocate the object */ 30 Catalog = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Catalog)); 31 32 /* Return it */ 33 return Catalog; 34 } 35 36 BOOL 37 WSAAPI 38 WsTcOpen(IN PTCATALOG Catalog, 39 IN HKEY ParentKey) 40 { 41 INT ErrorCode; 42 DWORD CreateDisposition; 43 HKEY CatalogKey, NewKey; 44 //DWORD CatalogEntries = 0; 45 DWORD RegType = REG_DWORD; 46 DWORD RegSize = sizeof(DWORD); 47 DWORD UniqueId = 0; 48 DWORD NewData = 0; 49 CHAR* CatalogKeyName; 50 51 /* Initialize the catalog lock and namespace list */ 52 InitializeCriticalSection(&Catalog->Lock); 53 InitializeListHead(&Catalog->ProtocolList); 54 55 /* Read the catalog name */ 56 ErrorCode = RegQueryValueEx(ParentKey, 57 "Current_Protocol_Catalog", 58 0, 59 &RegType, 60 NULL, 61 &RegSize); 62 if (ErrorCode == ERROR_FILE_NOT_FOUND) 63 { 64 static const CHAR DefaultCatalogName[] = "Protocol_Catalog9"; 65 RegSize = sizeof(DefaultCatalogName); 66 CatalogKeyName = HeapAlloc(WsSockHeap, 0, RegSize); 67 memcpy(CatalogKeyName, DefaultCatalogName, RegSize); 68 } 69 else 70 { 71 if (ErrorCode != ERROR_SUCCESS) 72 { 73 DPRINT1("Failed to get protocol catalog name: %d.\n", ErrorCode); 74 return FALSE; 75 } 76 77 if (RegType != REG_SZ) 78 { 79 DPRINT1("Protocol catalog name is not a string (Type %d).\n", RegType); 80 return FALSE; 81 } 82 83 CatalogKeyName = HeapAlloc(WsSockHeap, 0, RegSize); 84 85 /* Read the catalog name */ 86 ErrorCode = RegQueryValueEx(ParentKey, 87 "Current_Protocol_Catalog", 88 0, 89 &RegType, 90 (LPBYTE)CatalogKeyName, 91 &RegSize); 92 93 /* Open the Catalog Key */ 94 ErrorCode = RegOpenKeyEx(ParentKey, 95 CatalogKeyName, 96 0, 97 MAXIMUM_ALLOWED, 98 &CatalogKey); 99 } 100 101 /* If we didn't find the key, create it */ 102 if (ErrorCode == ERROR_SUCCESS) 103 { 104 /* Fake that we opened an existing key */ 105 CreateDisposition = REG_OPENED_EXISTING_KEY; 106 } 107 else if (ErrorCode == ERROR_FILE_NOT_FOUND) 108 { 109 /* Create the Catalog Name */ 110 ErrorCode = RegCreateKeyEx(ParentKey, 111 CatalogKeyName, 112 0, 113 NULL, 114 REG_OPTION_NON_VOLATILE, 115 KEY_ALL_ACCESS, 116 NULL, 117 &CatalogKey, 118 &CreateDisposition); 119 } 120 121 HeapFree(WsSockHeap, 0, CatalogKeyName); 122 RegType = REG_DWORD; 123 RegSize = sizeof(DWORD); 124 125 /* Fail if that didn't work */ 126 if (ErrorCode != ERROR_SUCCESS) return FALSE; 127 128 /* Check if we had to create the key */ 129 if (CreateDisposition == REG_CREATED_NEW_KEY) 130 { 131 /* Write the count of entries (0 now) */ 132 ErrorCode = RegSetValueEx(CatalogKey, 133 "Num_Catalog_Entries", 134 0, 135 REG_DWORD, 136 (LPBYTE)&NewData, 137 sizeof(NewData)); 138 if (ErrorCode != ERROR_SUCCESS) 139 { 140 /* Close the key and fail */ 141 RegCloseKey(CatalogKey); 142 return FALSE; 143 } 144 145 /* Write the first catalog entry ID */ 146 NewData = 1001; 147 ErrorCode = RegSetValueEx(CatalogKey, 148 "Next_Catalog_Entry_ID", 149 0, 150 REG_DWORD, 151 (LPBYTE)&NewData, 152 sizeof(NewData)); 153 if (ErrorCode != ERROR_SUCCESS) 154 { 155 /* Close the key and fail */ 156 RegCloseKey(CatalogKey); 157 return FALSE; 158 } 159 160 /* Write the first catalog entry Uniqe ID */ 161 NewData = 1; 162 ErrorCode = RegSetValueEx(CatalogKey, 163 "Serial_Access_Num", 164 0, 165 REG_DWORD, 166 (LPBYTE)&NewData, 167 sizeof(NewData)); 168 if (ErrorCode != ERROR_SUCCESS) 169 { 170 /* Close the key and fail */ 171 RegCloseKey(CatalogKey); 172 return FALSE; 173 } 174 175 /* Create a key for this entry */ 176 ErrorCode = RegCreateKeyEx(CatalogKey, 177 "Catalog_Entries", 178 0, 179 NULL, 180 REG_OPTION_NON_VOLATILE, 181 KEY_ALL_ACCESS, 182 NULL, 183 &NewKey, 184 &CreateDisposition); 185 if (ErrorCode != ERROR_SUCCESS) 186 { 187 /* Close the key and fail */ 188 RegCloseKey(CatalogKey); 189 return FALSE; 190 } 191 192 /* Close the key since we don't need it */ 193 RegCloseKey(NewKey); 194 } 195 else 196 { 197 RegSize = sizeof(DWORD); 198 /* Read the serial number */ 199 ErrorCode = RegQueryValueEx(CatalogKey, 200 "Serial_Access_Num", 201 0, 202 &RegType, 203 (LPBYTE)&UniqueId, 204 &RegSize); 205 206 /* Check if it's missing for some reason */ 207 if (ErrorCode != ERROR_SUCCESS) 208 { 209 /* Write the first catalog entry Unique ID */ 210 NewData = 1; 211 ErrorCode = RegSetValueEx(CatalogKey, 212 "Serial_Access_Num", 213 0, 214 REG_DWORD, 215 (LPBYTE)&NewData, 216 sizeof(NewData)); 217 } 218 } 219 220 /* Set the Catalog Key */ 221 Catalog->CatalogKey = CatalogKey; 222 return TRUE; 223 } 224 225 DWORD 226 WSAAPI 227 WsTcInitializeFromRegistry(IN PTCATALOG Catalog, 228 IN HKEY ParentKey, 229 IN HANDLE CatalogEvent) 230 { 231 INT ErrorCode = WSASYSCALLFAILURE; 232 233 /* Open the catalog */ 234 if (WsTcOpen(Catalog, ParentKey)) 235 { 236 /* Refresh it */ 237 ErrorCode = WsTcRefreshFromRegistry(Catalog, CatalogEvent); 238 } 239 240 /* Return the status */ 241 return ErrorCode; 242 } 243 244 DWORD 245 WSAAPI 246 WsTcRefreshFromRegistry(IN PTCATALOG Catalog, 247 IN HANDLE CatalogEvent) 248 { 249 INT ErrorCode; 250 BOOLEAN LocalEvent = FALSE; 251 LIST_ENTRY LocalList; 252 DWORD UniqueId; 253 HKEY EntriesKey; 254 DWORD CatalogEntries; 255 PTCATALOG_ENTRY CatalogEntry; 256 DWORD NextCatalogEntry; 257 BOOL NewChangesMade; 258 PLIST_ENTRY Entry; 259 DWORD RegType = REG_DWORD; 260 DWORD RegSize = sizeof(DWORD); 261 DWORD i; 262 263 /* Check if we got an event */ 264 if (!CatalogEvent) 265 { 266 /* Create an event ourselves */ 267 CatalogEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 268 if (!CatalogEvent) return WSASYSCALLFAILURE; 269 LocalEvent = TRUE; 270 } 271 272 /* Lock the catalog */ 273 WsTcLock(); 274 275 /* Initialize our local list for the loop */ 276 InitializeListHead(&LocalList); 277 278 /* Start looping */ 279 do 280 { 281 /* Setup notifications for the catalog entry */ 282 ErrorCode = WsSetupCatalogProtection(Catalog->CatalogKey, 283 CatalogEvent, 284 &UniqueId); 285 if (ErrorCode != ERROR_SUCCESS) break; 286 287 /* Check if we've changed till now */ 288 if (UniqueId == Catalog->UniqueId) 289 { 290 /* We haven't, so return */ 291 ErrorCode = ERROR_SUCCESS; 292 break; 293 } 294 295 /* Now Open the Entries */ 296 ErrorCode = RegOpenKeyEx(Catalog->CatalogKey, 297 "Catalog_Entries", 298 0, 299 MAXIMUM_ALLOWED, 300 &EntriesKey); 301 if (ErrorCode != ERROR_SUCCESS) 302 { 303 /* Critical failure */ 304 ErrorCode = WSASYSCALLFAILURE; 305 break; 306 } 307 308 /* Get the next entry */ 309 ErrorCode = RegQueryValueEx(Catalog->CatalogKey, 310 "Next_Catalog_Entry_ID", 311 0, 312 &RegType, 313 (LPBYTE)&NextCatalogEntry, 314 &RegSize); 315 if (ErrorCode != ERROR_SUCCESS) 316 { 317 /* Critical failure */ 318 ErrorCode = WSASYSCALLFAILURE; 319 break; 320 } 321 322 /* Find out how many there are */ 323 ErrorCode = RegQueryValueEx(Catalog->CatalogKey, 324 "Num_Catalog_Entries", 325 0, 326 &RegType, 327 (LPBYTE)&CatalogEntries, 328 &RegSize); 329 if (ErrorCode != ERROR_SUCCESS) 330 { 331 /* Critical failure */ 332 ErrorCode = WSASYSCALLFAILURE; 333 break; 334 } 335 336 /* Initialize them all */ 337 for (i = 1; i <= CatalogEntries; i++) 338 { 339 /* Allocate a Catalog Entry Structure */ 340 CatalogEntry = WsTcEntryAllocate(); 341 if (!CatalogEntry) 342 { 343 /* Not enough memory, fail */ 344 ErrorCode = WSA_NOT_ENOUGH_MEMORY; 345 break; 346 } 347 348 /* Initialize it from the Registry Key */ 349 ErrorCode = WsTcEntryInitializeFromRegistry(CatalogEntry, 350 EntriesKey, 351 i); 352 if (ErrorCode != ERROR_SUCCESS) 353 { 354 /* We failed to get it, dereference the entry and leave */ 355 WsTcEntryDereference(CatalogEntry); 356 break; 357 } 358 359 /* Insert it to our List */ 360 InsertTailList(&LocalList, &CatalogEntry->CatalogLink); 361 } 362 363 /* Close the catalog key */ 364 RegCloseKey(EntriesKey); 365 366 /* Check if we changed during our read and if we have success */ 367 NewChangesMade = WsCheckCatalogState(CatalogEvent); 368 if (!NewChangesMade && ErrorCode == ERROR_SUCCESS) 369 { 370 /* All is good, update the protocol list */ 371 WsTcUpdateProtocolList(Catalog, &LocalList); 372 373 /* Update and return */ 374 Catalog->UniqueId = UniqueId; 375 Catalog->NextId = NextCatalogEntry; 376 break; 377 } 378 379 /* We failed and/or catalog data changed, free what we did till now */ 380 while (!IsListEmpty(&LocalList)) 381 { 382 /* Get the LP Catalog Item */ 383 Entry = RemoveHeadList(&LocalList); 384 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 385 386 /* Dereference it */ 387 WsTcEntryDereference(CatalogEntry); 388 } 389 } while (NewChangesMade); 390 391 /* Release the lock */ 392 WsTcUnlock(); 393 394 /* Close the event, if any was created by us */ 395 if (LocalEvent) CloseHandle(CatalogEvent); 396 397 /* All Done */ 398 return ErrorCode; 399 } 400 401 DWORD 402 WSAAPI 403 WsTcGetEntryFromAf(IN PTCATALOG Catalog, 404 IN INT AddressFamily, 405 IN PTCATALOG_ENTRY *CatalogEntry) 406 { 407 INT ErrorCode = WSAEINVAL; 408 PLIST_ENTRY NextEntry; 409 PTCATALOG_ENTRY Entry; 410 411 /* Assume failure */ 412 *CatalogEntry = NULL; 413 414 /* Lock the catalog */ 415 WsTcLock(); 416 417 /* Match the Id with all the entries in the List */ 418 NextEntry = Catalog->ProtocolList.Flink; 419 while (NextEntry != &Catalog->ProtocolList) 420 { 421 /* Get the Current Entry */ 422 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink); 423 NextEntry = NextEntry->Flink; 424 425 /* Check if this is the Catalog Entry ID we want */ 426 if (Entry->ProtocolInfo.iAddressFamily == AddressFamily) 427 { 428 /* Check if it doesn't already have a provider */ 429 if (!Entry->Provider) 430 { 431 /* Match, load the Provider */ 432 ErrorCode = WsTcLoadProvider(Catalog, Entry); 433 434 /* Make sure this didn't fail */ 435 if (ErrorCode != ERROR_SUCCESS) break; 436 } 437 438 /* Reference the entry and return it */ 439 InterlockedIncrement(&Entry->RefCount); 440 *CatalogEntry = Entry; 441 ErrorCode = ERROR_SUCCESS; 442 break; 443 } 444 } 445 446 /* Release the catalog */ 447 WsTcUnlock(); 448 449 /* Return */ 450 return ErrorCode; 451 } 452 453 DWORD 454 WSAAPI 455 WsTcGetEntryFromCatalogEntryId(IN PTCATALOG Catalog, 456 IN DWORD CatalogEntryId, 457 IN PTCATALOG_ENTRY *CatalogEntry) 458 { 459 INT ErrorCode = WSAEINVAL; 460 PLIST_ENTRY NextEntry; 461 PTCATALOG_ENTRY Entry; 462 463 /* Lock the catalog */ 464 WsTcLock(); 465 466 /* Match the Id with all the entries in the List */ 467 NextEntry = Catalog->ProtocolList.Flink; 468 while (NextEntry != &Catalog->ProtocolList) 469 { 470 /* Get the Current Entry */ 471 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink); 472 NextEntry = NextEntry->Flink; 473 474 /* Check if this is the Catalog Entry ID we want */ 475 if (Entry->ProtocolInfo.dwCatalogEntryId == CatalogEntryId) 476 { 477 /* Check if it doesn't already have a provider */ 478 if (!Entry->Provider) 479 { 480 /* Match, load the Provider */ 481 WsTcLoadProvider(Catalog, Entry); 482 } 483 484 /* Reference the entry and return it */ 485 InterlockedIncrement(&Entry->RefCount); 486 *CatalogEntry = Entry; 487 ErrorCode = ERROR_SUCCESS; 488 break; 489 } 490 } 491 492 /* Release the catalog */ 493 WsTcUnlock(); 494 495 /* Return */ 496 return ErrorCode; 497 } 498 499 DWORD 500 WSAAPI 501 WsTcGetEntryFromTriplet(IN PTCATALOG Catalog, 502 IN INT af, 503 IN INT type, 504 IN INT protocol, 505 IN DWORD StartId, 506 IN PTCATALOG_ENTRY *CatalogEntry) 507 { 508 INT ErrorCode = WSAEINVAL; 509 PLIST_ENTRY NextEntry; 510 PTCATALOG_ENTRY Entry; 511 DPRINT("WsTcGetEntryFromTriplet: %lx, %lx, %lx, %lx\n", af, type, protocol, StartId); 512 513 /* Assume failure */ 514 *CatalogEntry = NULL; 515 516 /* Lock the catalog */ 517 WsTcLock(); 518 519 NextEntry = Catalog->ProtocolList.Flink; 520 521 /* Check if we are starting past 0 */ 522 if (StartId) 523 { 524 /* Loop the list */ 525 while (NextEntry != &Catalog->ProtocolList) 526 { 527 /* Get the Current Entry */ 528 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink); 529 NextEntry = NextEntry->Flink; 530 531 /* Check if this is the ID where we are starting */ 532 if (Entry->ProtocolInfo.dwCatalogEntryId == StartId) break; 533 } 534 } 535 536 /* Match the Id with all the entries in the List */ 537 while (NextEntry != &Catalog->ProtocolList) 538 { 539 /* Get the Current Entry */ 540 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink); 541 NextEntry = NextEntry->Flink; 542 543 /* Check if Address Family Matches or if it's wildcard */ 544 if ((Entry->ProtocolInfo.iAddressFamily == af) || (af == AF_UNSPEC)) 545 { 546 /* Check if Socket Type Matches or if it's wildcard */ 547 if ((Entry->ProtocolInfo.iSocketType == type) || (type == 0)) 548 { 549 /* Check if Protocol is In Range or if it's wildcard */ 550 if (((Entry->ProtocolInfo.iProtocol <= protocol) && 551 ((Entry->ProtocolInfo.iProtocol + 552 Entry->ProtocolInfo.iProtocolMaxOffset) >= protocol)) || 553 (protocol == 0)) 554 { 555 /* Check if it doesn't already have a provider */ 556 if (!Entry->Provider) 557 { 558 /* Match, load the Provider */ 559 ErrorCode = WsTcLoadProvider(Catalog, Entry); 560 561 /* Make sure this didn't fail */ 562 if (ErrorCode != ERROR_SUCCESS) break; 563 } 564 565 /* Reference the entry and return it */ 566 InterlockedIncrement(&Entry->RefCount); 567 *CatalogEntry = Entry; 568 ErrorCode = ERROR_SUCCESS; 569 break; 570 } 571 else 572 { 573 ErrorCode = WSAEPROTONOSUPPORT; 574 } 575 } 576 else 577 { 578 ErrorCode = WSAESOCKTNOSUPPORT; 579 } 580 } 581 else 582 { 583 ErrorCode = WSAEAFNOSUPPORT; 584 } 585 } 586 587 /* Release the catalog */ 588 WsTcUnlock(); 589 590 /* Return */ 591 return ErrorCode; 592 } 593 594 PTPROVIDER 595 WSAAPI 596 WsTcFindProvider(IN PTCATALOG Catalog, 597 IN LPGUID ProviderId) 598 { 599 PTPROVIDER Provider; 600 PLIST_ENTRY Entry; 601 PTCATALOG_ENTRY CatalogEntry; 602 603 /* Loop the provider list */ 604 Entry = Catalog->ProtocolList.Flink; 605 while (Entry != &Catalog->ProtocolList) 606 { 607 /* Get the entry */ 608 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 609 610 /* Move to the next one, get the provider */ 611 Entry = Entry->Flink; 612 Provider = CatalogEntry->Provider; 613 614 /* Check for a match */ 615 if (Provider && 616 IsEqualGUID(&CatalogEntry->ProtocolInfo.ProviderId, ProviderId)) 617 { 618 /* Found a match */ 619 return Provider; 620 } 621 } 622 623 /* No match here */ 624 return NULL; 625 } 626 627 DWORD 628 WSAAPI 629 WsTcLoadProvider(IN PTCATALOG Catalog, 630 IN PTCATALOG_ENTRY CatalogEntry) 631 { 632 INT ErrorCode = ERROR_SUCCESS; 633 PTPROVIDER Provider; 634 DPRINT("WsTcLoadProvider: %p, %p\n", Catalog, CatalogEntry); 635 636 /* Lock the catalog */ 637 WsTcLock(); 638 639 /* Check if we have a provider already */ 640 if (!CatalogEntry->Provider) 641 { 642 /* Try to find another instance */ 643 Provider = WsTcFindProvider(Catalog, 644 &CatalogEntry->ProtocolInfo.ProviderId); 645 646 /* Check if we found one now */ 647 if (Provider) 648 { 649 /* Set this one as the provider */ 650 WsTcEntrySetProvider(CatalogEntry, Provider); 651 ErrorCode = ERROR_SUCCESS; 652 } 653 else 654 { 655 /* Nothing found, Allocate a provider */ 656 if ((Provider = WsTpAllocate())) 657 { 658 /* Initialize it */ 659 ErrorCode = WsTpInitialize(Provider, 660 CatalogEntry->DllPath, 661 &CatalogEntry->ProtocolInfo); 662 663 /* Ensure success */ 664 if (ErrorCode == ERROR_SUCCESS) 665 { 666 /* Set the provider */ 667 WsTcEntrySetProvider(CatalogEntry, Provider); 668 } 669 670 /* Dereference it */ 671 WsTpDereference(Provider); 672 } 673 else 674 { 675 /* No memory */ 676 ErrorCode = WSA_NOT_ENOUGH_MEMORY; 677 } 678 } 679 } 680 681 /* Release the lock */ 682 WsTcUnlock(); 683 return ErrorCode; 684 } 685 686 VOID 687 WSAAPI 688 WsTcUpdateProtocolList(IN PTCATALOG Catalog, 689 IN PLIST_ENTRY List) 690 { 691 LIST_ENTRY TempList; 692 PTCATALOG_ENTRY CatalogEntry, OldCatalogEntry; 693 PLIST_ENTRY Entry; 694 695 /* First move from our list to the old one */ 696 InsertHeadList(&Catalog->ProtocolList, &TempList); 697 RemoveEntryList(&Catalog->ProtocolList); 698 InitializeListHead(&Catalog->ProtocolList); 699 700 /* Loop every item in the list */ 701 while (!IsListEmpty(List)) 702 { 703 /* Get the catalog entry */ 704 Entry = RemoveHeadList(List); 705 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 706 707 /* Check if this item is already in our list */ 708 Entry = TempList.Flink; 709 while (Entry != &TempList) 710 { 711 /* Get the catalog entry */ 712 OldCatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 713 Entry = Entry->Flink; 714 715 /* Check if they match */ 716 if (CatalogEntry->ProtocolInfo.dwCatalogEntryId == 717 OldCatalogEntry->ProtocolInfo.dwCatalogEntryId) 718 { 719 /* We have a match, use the old item instead */ 720 WsTcEntryDereference(CatalogEntry); 721 CatalogEntry = OldCatalogEntry; 722 RemoveEntryList(&CatalogEntry->CatalogLink); 723 724 /* Decrease the number of protocols we have */ 725 Catalog->ItemCount--; 726 break; 727 } 728 } 729 730 /* Add this item */ 731 InsertTailList(&Catalog->ProtocolList, &CatalogEntry->CatalogLink); 732 Catalog->ItemCount++; 733 } 734 735 /* If there's anything left in the temporary list */ 736 while (!IsListEmpty(&TempList)) 737 { 738 /* Get the entry */ 739 Entry = RemoveHeadList(&TempList); 740 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 741 742 /* Remove it */ 743 Catalog->ItemCount--; 744 WsTcEntryDereference(CatalogEntry); 745 } 746 } 747 748 VOID 749 WSAAPI 750 WsTcEnumerateCatalogItems(IN PTCATALOG Catalog, 751 IN PTCATALOG_ENUMERATE_PROC Callback, 752 IN PVOID Context) 753 { 754 PLIST_ENTRY Entry; 755 PTCATALOG_ENTRY CatalogEntry; 756 BOOL GoOn = TRUE; 757 758 /* Lock the catalog */ 759 WsTcLock(); 760 761 /* Loop the entries */ 762 Entry = Catalog->ProtocolList.Flink; 763 while (GoOn && (Entry != &Catalog->ProtocolList)) 764 { 765 /* Get the entry */ 766 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 767 768 /* Move to the next one and call the callback */ 769 Entry = Entry->Flink; 770 GoOn = Callback(Context, CatalogEntry); 771 } 772 773 /* Release lock */ 774 WsTcUnlock(); 775 } 776 777 DWORD 778 WSAAPI 779 WsTcFindIfsProviderForSocket(IN PTCATALOG Catalog, 780 IN SOCKET Handle) 781 { 782 PTPROVIDER Provider; 783 IN SOCKET NewHandle; 784 INT Error; 785 INT OptionLength; 786 PLIST_ENTRY Entry; 787 WSAPROTOCOL_INFOW ProtocolInfo; 788 DWORD UniqueId; 789 INT ErrorCode; 790 PTCATALOG_ENTRY CatalogEntry; 791 792 /* Get the catalog lock */ 793 WsTcLock(); 794 795 /* Loop as long as the catalog changes */ 796 CatalogChanged: 797 798 /* Loop every provider */ 799 Entry = Catalog->ProtocolList.Flink; 800 while (Entry != &Catalog->ProtocolList) 801 { 802 /* Get the catalog entry */ 803 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 804 805 /* Move to the next entry */ 806 Entry = Entry->Flink; 807 808 /* Skip it if it doesn't support IFS */ 809 if (!(CatalogEntry->ProtocolInfo.dwServiceFlags1 & XP1_IFS_HANDLES)) continue; 810 811 /* Check if we need to load it */ 812 if (!(Provider = CatalogEntry->Provider)) 813 { 814 /* Load it */ 815 ErrorCode = WsTcLoadProvider(Catalog, CatalogEntry); 816 817 /* Skip it if we failed to load it */ 818 if (ErrorCode != ERROR_SUCCESS) continue; 819 820 /* Get the provider again */ 821 Provider = CatalogEntry->Provider; 822 } 823 824 /* Reference the entry and get our unique id */ 825 InterlockedIncrement(&CatalogEntry->RefCount); 826 UniqueId = Catalog->UniqueId; 827 828 /* Release the lock now */ 829 WsTcUnlock(); 830 831 /* Get the catalog entry ID */ 832 OptionLength = sizeof(ProtocolInfo); 833 ErrorCode = Provider->Service.lpWSPGetSockOpt(Handle, 834 SOL_SOCKET, 835 SO_PROTOCOL_INFOW, 836 (PCHAR)&ProtocolInfo, 837 &OptionLength, 838 &Error); 839 840 /* Dereference the entry and check the result */ 841 WsTcEntryDereference(CatalogEntry); 842 if (ErrorCode != ERROR_SUCCESS) 843 { 844 /* Lock and make sure this provider is still valid */ 845 WsTcLock(); 846 if (UniqueId == Catalog->UniqueId) continue; 847 848 /* It changed! We need to start over */ 849 goto CatalogChanged; 850 } 851 852 /* Now get the IFS handle */ 853 NewHandle = WPUModifyIFSHandle(ProtocolInfo.dwCatalogEntryId, 854 Handle, 855 &Error); 856 857 /* Check if the socket is invalid */ 858 if (NewHandle == INVALID_SOCKET) return WSAENOTSOCK; 859 860 /* We succeeded, get out of here */ 861 return ERROR_SUCCESS; 862 } 863 864 /* Unrecognized socket if we get here: note, we still have the lock */ 865 WsTcUnlock(); 866 return WSAENOTSOCK; 867 } 868 869 VOID 870 WSAAPI 871 WsTcRemoveCatalogItem(IN PTCATALOG Catalog, 872 IN PTCATALOG_ENTRY Entry) 873 { 874 /* Remove the entry from the list */ 875 RemoveEntryList(&Entry->CatalogLink); 876 877 /* Decrease our count */ 878 Catalog->ItemCount--; 879 } 880 881 VOID 882 WSAAPI 883 WsTcDelete(IN PTCATALOG Catalog) 884 { 885 PLIST_ENTRY Entry; 886 PTCATALOG_ENTRY CatalogEntry; 887 888 /* Check if we're initialized */ 889 if (!Catalog->ProtocolList.Flink) return; 890 891 /* Acquire lock */ 892 WsTcLock(); 893 894 /* Loop every entry */ 895 Entry = Catalog->ProtocolList.Flink; 896 while (Entry != &Catalog->ProtocolList) 897 { 898 /* Get this entry */ 899 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); 900 901 /* Remove it and dereference it */ 902 WsTcRemoveCatalogItem(Catalog, CatalogEntry); 903 WsTcEntryDereference(CatalogEntry); 904 905 /* Move to the next entry */ 906 Entry = Catalog->ProtocolList.Flink; 907 } 908 909 /* Check if the catalog key is opened */ 910 if (Catalog->CatalogKey) 911 { 912 /* Close it */ 913 RegCloseKey(Catalog->CatalogKey); 914 Catalog->CatalogKey = NULL; 915 } 916 917 /* Release and delete the lock */ 918 WsTcUnlock(); 919 DeleteCriticalSection(&Catalog->Lock); 920 921 /* Delete the object */ 922 HeapFree(WsSockHeap, 0, Catalog); 923 } 924