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
WsTcAllocate(VOID)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
WsTcOpen(IN PTCATALOG Catalog,IN HKEY ParentKey)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
WsTcInitializeFromRegistry(IN PTCATALOG Catalog,IN HKEY ParentKey,IN HANDLE CatalogEvent)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
WsTcRefreshFromRegistry(IN PTCATALOG Catalog,IN HANDLE CatalogEvent)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
WsTcGetEntryFromAf(IN PTCATALOG Catalog,IN INT AddressFamily,IN PTCATALOG_ENTRY * CatalogEntry)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
WsTcGetEntryFromCatalogEntryId(IN PTCATALOG Catalog,IN DWORD CatalogEntryId,IN PTCATALOG_ENTRY * CatalogEntry)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
WsTcGetEntryFromTriplet(IN PTCATALOG Catalog,IN INT af,IN INT type,IN INT protocol,IN DWORD StartId,IN PTCATALOG_ENTRY * CatalogEntry)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
WsTcFindProvider(IN PTCATALOG Catalog,IN LPGUID ProviderId)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
WsTcLoadProvider(IN PTCATALOG Catalog,IN PTCATALOG_ENTRY CatalogEntry)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
WsTcUpdateProtocolList(IN PTCATALOG Catalog,IN PLIST_ENTRY List)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
WsTcEnumerateCatalogItems(IN PTCATALOG Catalog,IN PTCATALOG_ENUMERATE_PROC Callback,IN PVOID Context)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
WsTcFindIfsProviderForSocket(IN PTCATALOG Catalog,IN SOCKET Handle)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
WsTcRemoveCatalogItem(IN PTCATALOG Catalog,IN PTCATALOG_ENTRY Entry)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
WsTcDelete(IN PTCATALOG Catalog)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