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