[MSAFD][WS2_32] Better WSASocket parameters check
[reactos.git] / reactos / dll / win32 / ws2_32 / src / dcatalog.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32_new/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((LPCRITICAL_SECTION)&Catalog->Lock);
19 #define WsTcUnlock() LeaveCriticalSection((LPCRITICAL_SECTION)&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((LPCRITICAL_SECTION)&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
63 CatalogKeyName = HeapAlloc(WsSockHeap, 0, RegSize);
64
65 /* Read the catalog name */
66 ErrorCode = RegQueryValueEx(ParentKey,
67 "Current_Protocol_Catalog",
68 0,
69 &RegType,
70 (LPBYTE)CatalogKeyName,
71 &RegSize);
72
73 /* Open the Catalog Key */
74 ErrorCode = RegOpenKeyEx(ParentKey,
75 CatalogKeyName,
76 0,
77 MAXIMUM_ALLOWED,
78 &CatalogKey);
79
80 /* If we didn't find the key, create it */
81 if (ErrorCode == ERROR_SUCCESS)
82 {
83 /* Fake that we opened an existing key */
84 CreateDisposition = REG_OPENED_EXISTING_KEY;
85 }
86 else if (ErrorCode == ERROR_FILE_NOT_FOUND)
87 {
88 /* Create the Catalog Name */
89 ErrorCode = RegCreateKeyEx(ParentKey,
90 CatalogKeyName,
91 0,
92 NULL,
93 REG_OPTION_NON_VOLATILE,
94 KEY_ALL_ACCESS,
95 NULL,
96 &CatalogKey,
97 &CreateDisposition);
98 }
99
100 HeapFree(WsSockHeap, 0, CatalogKeyName);
101 RegType = REG_DWORD;
102 RegSize = sizeof(DWORD);
103
104 /* Fail if that didn't work */
105 if (ErrorCode != ERROR_SUCCESS) return FALSE;
106
107 /* Check if we had to create the key */
108 if (CreateDisposition == REG_CREATED_NEW_KEY)
109 {
110 /* Write the count of entries (0 now) */
111 ErrorCode = RegSetValueEx(CatalogKey,
112 "Num_Catalog_Entries",
113 0,
114 REG_DWORD,
115 (LPBYTE)&NewData,
116 sizeof(NewData));
117 if (ErrorCode != ERROR_SUCCESS)
118 {
119 /* Close the key and fail */
120 RegCloseKey(CatalogKey);
121 return FALSE;
122 }
123
124 /* Write the first catalog entry ID */
125 NewData = 1001;
126 ErrorCode = RegSetValueEx(CatalogKey,
127 "Next_Catalog_Entry_ID",
128 0,
129 REG_DWORD,
130 (LPBYTE)&NewData,
131 sizeof(NewData));
132 if (ErrorCode != ERROR_SUCCESS)
133 {
134 /* Close the key and fail */
135 RegCloseKey(CatalogKey);
136 return FALSE;
137 }
138
139 /* Write the first catalog entry Uniqe ID */
140 NewData = 1;
141 ErrorCode = RegSetValueEx(CatalogKey,
142 "Serial_Access_Num",
143 0,
144 REG_DWORD,
145 (LPBYTE)&NewData,
146 sizeof(NewData));
147 if (ErrorCode != ERROR_SUCCESS)
148 {
149 /* Close the key and fail */
150 RegCloseKey(CatalogKey);
151 return FALSE;
152 }
153
154 /* Create a key for this entry */
155 ErrorCode = RegCreateKeyEx(CatalogKey,
156 "Catalog_Entries",
157 0,
158 NULL,
159 REG_OPTION_NON_VOLATILE,
160 KEY_ALL_ACCESS,
161 NULL,
162 &NewKey,
163 &CreateDisposition);
164 if (ErrorCode != ERROR_SUCCESS)
165 {
166 /* Close the key and fail */
167 RegCloseKey(CatalogKey);
168 return FALSE;
169 }
170
171 /* Close the key since we don't need it */
172 RegCloseKey(NewKey);
173 }
174 else
175 {
176 RegSize = sizeof(DWORD);
177 /* Read the serial number */
178 ErrorCode = RegQueryValueEx(CatalogKey,
179 "Serial_Access_Num",
180 0,
181 &RegType,
182 (LPBYTE)&UniqueId,
183 &RegSize);
184
185 /* Check if it's missing for some reason */
186 if (ErrorCode != ERROR_SUCCESS)
187 {
188 /* Write the first catalog entry Unique ID */
189 NewData = 1;
190 ErrorCode = RegSetValueEx(CatalogKey,
191 "Serial_Access_Num",
192 0,
193 REG_DWORD,
194 (LPBYTE)&NewData,
195 sizeof(NewData));
196 }
197 }
198
199 /* Set the Catalog Key */
200 Catalog->CatalogKey = CatalogKey;
201 return TRUE;
202 }
203
204 DWORD
205 WSAAPI
206 WsTcInitializeFromRegistry(IN PTCATALOG Catalog,
207 IN HKEY ParentKey,
208 IN HANDLE CatalogEvent)
209 {
210 INT ErrorCode = WSASYSCALLFAILURE;
211
212 /* Open the catalog */
213 if (WsTcOpen(Catalog, ParentKey))
214 {
215 /* Refresh it */
216 ErrorCode = WsTcRefreshFromRegistry(Catalog, CatalogEvent);
217 }
218
219 /* Return the status */
220 return ErrorCode;
221 }
222
223 DWORD
224 WSAAPI
225 WsTcRefreshFromRegistry(IN PTCATALOG Catalog,
226 IN HANDLE CatalogEvent)
227 {
228 INT ErrorCode;
229 BOOLEAN LocalEvent = FALSE;
230 LIST_ENTRY LocalList;
231 DWORD UniqueId;
232 HKEY EntriesKey;
233 DWORD CatalogEntries;
234 PTCATALOG_ENTRY CatalogEntry;
235 DWORD NextCatalogEntry;
236 BOOL NewChangesMade;
237 PLIST_ENTRY Entry;
238 DWORD RegType = REG_DWORD;
239 DWORD RegSize = sizeof(DWORD);
240 DWORD i;
241
242 /* Check if we got an event */
243 if (!CatalogEvent)
244 {
245 /* Create an event ourselves */
246 CatalogEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
247 if (!CatalogEvent) return WSASYSCALLFAILURE;
248 LocalEvent = TRUE;
249 }
250
251 /* Lock the catalog */
252 WsTcLock();
253
254 /* Initialize our local list for the loop */
255 InitializeListHead(&LocalList);
256
257 /* Start looping */
258 do
259 {
260 /* Setup notifications for the catalog entry */
261 ErrorCode = WsSetupCatalogProtection(Catalog->CatalogKey,
262 CatalogEvent,
263 &UniqueId);
264 if (ErrorCode != ERROR_SUCCESS) break;
265
266 /* Check if we've changed till now */
267 if (UniqueId == Catalog->UniqueId)
268 {
269 /* We haven't, so return */
270 ErrorCode = ERROR_SUCCESS;
271 break;
272 }
273
274 /* Now Open the Entries */
275 ErrorCode = RegOpenKeyEx(Catalog->CatalogKey,
276 "Catalog_Entries",
277 0,
278 MAXIMUM_ALLOWED,
279 &EntriesKey);
280 if (ErrorCode != ERROR_SUCCESS)
281 {
282 /* Critical failure */
283 ErrorCode = WSASYSCALLFAILURE;
284 break;
285 }
286
287 /* Get the next entry */
288 ErrorCode = RegQueryValueEx(Catalog->CatalogKey,
289 "Next_Catalog_Entry_ID",
290 0,
291 &RegType,
292 (LPBYTE)&NextCatalogEntry,
293 &RegSize);
294 if (ErrorCode != ERROR_SUCCESS)
295 {
296 /* Critical failure */
297 ErrorCode = WSASYSCALLFAILURE;
298 break;
299 }
300
301 /* Find out how many there are */
302 ErrorCode = RegQueryValueEx(Catalog->CatalogKey,
303 "Num_Catalog_Entries",
304 0,
305 &RegType,
306 (LPBYTE)&CatalogEntries,
307 &RegSize);
308 if (ErrorCode != ERROR_SUCCESS)
309 {
310 /* Critical failure */
311 ErrorCode = WSASYSCALLFAILURE;
312 break;
313 }
314
315 /* Initialize them all */
316 for (i = 1; i <= CatalogEntries; i++)
317 {
318 /* Allocate a Catalog Entry Structure */
319 CatalogEntry = WsTcEntryAllocate();
320 if (!CatalogEntry)
321 {
322 /* Not enough memory, fail */
323 ErrorCode = WSA_NOT_ENOUGH_MEMORY;
324 break;
325 }
326
327 /* Initialize it from the Registry Key */
328 ErrorCode = WsTcEntryInitializeFromRegistry(CatalogEntry,
329 EntriesKey,
330 i);
331 if (ErrorCode != ERROR_SUCCESS)
332 {
333 /* We failed to get it, dereference the entry and leave */
334 WsTcEntryDereference(CatalogEntry);
335 break;
336 }
337
338 /* Insert it to our List */
339 InsertTailList(&LocalList, &CatalogEntry->CatalogLink);
340 }
341
342 /* Close the catalog key */
343 RegCloseKey(EntriesKey);
344
345 /* Check if we changed during our read and if we have success */
346 NewChangesMade = WsCheckCatalogState(CatalogEvent);
347 if (!NewChangesMade && ErrorCode == ERROR_SUCCESS)
348 {
349 /* All is good, update the protocol list */
350 WsTcUpdateProtocolList(Catalog, &LocalList);
351
352 /* Update and return */
353 Catalog->UniqueId = UniqueId;
354 Catalog->NextId = NextCatalogEntry;
355 break;
356 }
357
358 /* We failed and/or catalog data changed, free what we did till now */
359 while (!IsListEmpty(&LocalList))
360 {
361 /* Get the LP Catalog Item */
362 Entry = RemoveHeadList(&LocalList);
363 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
364
365 /* Dereference it */
366 WsTcEntryDereference(CatalogEntry);
367 }
368 } while (NewChangesMade);
369
370 /* Release the lock */
371 WsTcUnlock();
372
373 /* Close the event, if any was created by us */
374 if (LocalEvent) CloseHandle(CatalogEvent);
375
376 /* All Done */
377 return ErrorCode;
378 }
379
380 DWORD
381 WSAAPI
382 WsTcGetEntryFromAf(IN PTCATALOG Catalog,
383 IN INT AddressFamily,
384 IN PTCATALOG_ENTRY *CatalogEntry)
385 {
386 INT ErrorCode = WSAEINVAL;
387 PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
388 PTCATALOG_ENTRY Entry;
389
390 /* Assume failure */
391 *CatalogEntry = NULL;
392
393 /* Lock the catalog */
394 WsTcLock();
395
396 /* Match the Id with all the entries in the List */
397 while (NextEntry != &Catalog->ProtocolList)
398 {
399 /* Get the Current Entry */
400 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
401 NextEntry = NextEntry->Flink;
402
403 /* Check if this is the Catalog Entry ID we want */
404 if (Entry->ProtocolInfo.iAddressFamily == AddressFamily)
405 {
406 /* Check if it doesn't already have a provider */
407 if (!Entry->Provider)
408 {
409 /* Match, load the Provider */
410 ErrorCode = WsTcLoadProvider(Catalog, Entry);
411
412 /* Make sure this didn't fail */
413 if (ErrorCode != ERROR_SUCCESS) break;
414 }
415
416 /* Reference the entry and return it */
417 InterlockedIncrement(&Entry->RefCount);
418 *CatalogEntry = Entry;
419 ErrorCode = ERROR_SUCCESS;
420 break;
421 }
422 }
423
424 /* Release the catalog */
425 WsTcUnlock();
426
427 /* Return */
428 return ErrorCode;
429 }
430
431 DWORD
432 WSAAPI
433 WsTcGetEntryFromCatalogEntryId(IN PTCATALOG Catalog,
434 IN DWORD CatalogEntryId,
435 IN PTCATALOG_ENTRY *CatalogEntry)
436 {
437 INT ErrorCode = WSAEINVAL;
438 PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
439 PTCATALOG_ENTRY Entry;
440
441 /* Lock the catalog */
442 WsTcLock();
443
444 /* Match the Id with all the entries in the List */
445 while (NextEntry != &Catalog->ProtocolList)
446 {
447 /* Get the Current Entry */
448 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
449 NextEntry = NextEntry->Flink;
450
451 /* Check if this is the Catalog Entry ID we want */
452 if (Entry->ProtocolInfo.dwCatalogEntryId == CatalogEntryId)
453 {
454 /* Check if it doesn't already have a provider */
455 if (!Entry->Provider)
456 {
457 /* Match, load the Provider */
458 WsTcLoadProvider(Catalog, Entry);
459 }
460
461 /* Reference the entry and return it */
462 InterlockedIncrement(&Entry->RefCount);
463 *CatalogEntry = Entry;
464 ErrorCode = ERROR_SUCCESS;
465 break;
466 }
467 }
468
469 /* Release the catalog */
470 WsTcUnlock();
471
472 /* Return */
473 return ErrorCode;
474 }
475
476 DWORD
477 WSAAPI
478 WsTcGetEntryFromTriplet(IN PTCATALOG Catalog,
479 IN INT af,
480 IN INT type,
481 IN INT protocol,
482 IN DWORD StartId,
483 IN PTCATALOG_ENTRY *CatalogEntry)
484 {
485 INT ErrorCode = WSAEINVAL;
486 PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
487 PTCATALOG_ENTRY Entry;
488 DPRINT("WsTcGetEntryFromTriplet: %lx, %lx, %lx, %lx\n", af, type, protocol, StartId);
489
490 /* Assume failure */
491 *CatalogEntry = NULL;
492
493 /* Params can't be all wildcards */
494 if (af == AF_UNSPEC && type == 0 && protocol == 0)
495 return WSAEINVAL;
496
497 /* FIXME: AF_NETDES should be AF_MAX */
498 if (af < AF_UNSPEC || af > AF_NETDES)
499 return WSAEINVAL;
500
501 if (type < 0 && type > SOCK_SEQPACKET)
502 return WSAEINVAL;
503
504 if (protocol < 0 && protocol > IPPROTO_MAX)
505 return WSAEINVAL;
506
507 /* Lock the catalog */
508 WsTcLock();
509
510 /* Check if we are starting past 0 */
511 if (StartId)
512 {
513 /* Loop the list */
514 while (NextEntry != &Catalog->ProtocolList)
515 {
516 /* Get the Current Entry */
517 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
518 NextEntry = NextEntry->Flink;
519
520 /* Check if this is the ID where we are starting */
521 if (Entry->ProtocolInfo.dwCatalogEntryId == StartId) break;
522 }
523 }
524
525 /* Match the Id with all the entries in the List */
526 while (NextEntry != &Catalog->ProtocolList)
527 {
528 /* Get the Current Entry */
529 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
530 NextEntry = NextEntry->Flink;
531
532 /* Check if Address Family Matches or if it's wildcard */
533 if ((Entry->ProtocolInfo.iAddressFamily == af) || (af == AF_UNSPEC))
534 {
535 /* Check if Socket Type Matches or if it's wildcard */
536 if ((Entry->ProtocolInfo.iSocketType == type) || (type == 0))
537 {
538 /* Check if Protocol is In Range or if it's wildcard */
539 if (((Entry->ProtocolInfo.iProtocol <= protocol) &&
540 ((Entry->ProtocolInfo.iProtocol +
541 Entry->ProtocolInfo.iProtocolMaxOffset) >= protocol)) ||
542 (protocol == 0))
543 {
544 /* Check that if type and protocol are 0 provider entry has PFL_MATCHES_PROTOCOL_ZERO flag set */
545 if (type == 0 && protocol == 0 && (Entry->ProtocolInfo.dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO) == 0)
546 {
547 ErrorCode = WSAEPROTONOSUPPORT;
548 continue;
549 }
550
551 /* Check if it doesn't already have a provider */
552 if (!Entry->Provider)
553 {
554 /* Match, load the Provider */
555 ErrorCode = WsTcLoadProvider(Catalog, Entry);
556
557 /* Make sure this didn't fail */
558 if (ErrorCode != ERROR_SUCCESS) break;
559 }
560
561 /* Reference the entry and return it */
562 InterlockedIncrement(&Entry->RefCount);
563 *CatalogEntry = Entry;
564 ErrorCode = ERROR_SUCCESS;
565 break;
566 }
567 else
568 {
569 ErrorCode = WSAEPROTONOSUPPORT;
570 }
571 }
572 else
573 {
574 if (ErrorCode != WSAEPROTONOSUPPORT)
575 ErrorCode = WSAESOCKTNOSUPPORT;
576 }
577 }
578 else
579 {
580 if (ErrorCode != WSAEPROTONOSUPPORT && ErrorCode != WSAESOCKTNOSUPPORT)
581 ErrorCode = WSAEAFNOSUPPORT;
582 }
583 }
584
585 /* Release the catalog */
586 WsTcUnlock();
587
588 /* Return */
589 return ErrorCode;
590 }
591
592 PTPROVIDER
593 WSAAPI
594 WsTcFindProvider(IN PTCATALOG Catalog,
595 IN LPGUID ProviderId)
596 {
597 PTPROVIDER Provider;
598 PLIST_ENTRY Entry;
599 PTCATALOG_ENTRY CatalogEntry;
600
601 /* Loop the provider list */
602 Entry = Catalog->ProtocolList.Flink;
603 while (Entry != &Catalog->ProtocolList)
604 {
605 /* Get the entry */
606 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
607
608 /* Move to the next one, get the provider */
609 Entry = Entry->Flink;
610 Provider = CatalogEntry->Provider;
611
612 /* Check for a match */
613 if ((Provider) &&
614 !(memcmp(&CatalogEntry->ProtocolInfo.ProviderId,
615 ProviderId,
616 sizeof(GUID))))
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 on 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 on 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 on 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 DWORD 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 (LPINT)&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 suceeded, 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 */
902 WsTcRemoveCatalogItem(Catalog, CatalogEntry);
903
904 /* Dereference it */
905 WsTcEntryDereference(CatalogEntry);
906
907 /* Move to the next entry */
908 Entry = Catalog->ProtocolList.Flink;
909 }
910
911 /* Check if the catalog key is opened */
912 if (Catalog->CatalogKey)
913 {
914 /* Close it */
915 RegCloseKey(Catalog->CatalogKey);
916 Catalog->CatalogKey = NULL;
917 }
918
919 /* Release and delete the lock */
920 WsTcUnlock();
921 DeleteCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
922
923 /* Delete the object */
924 HeapFree(WsSockHeap, 0, Catalog);
925 }