VOID WSAAPI WsSockDelete(IN PWSSOCKET Socket) { /* Check if we have a catalog entry */ if (Socket->CatalogEntry) { /* Dereference it */ WsTcEntryDereference(Socket->CatalogEntry); Socket->CatalogEntry = NULL; } }
VOID WSAAPI WsTcDelete(IN PTCATALOG Catalog) { PLIST_ENTRY Entry; PTCATALOG_ENTRY CatalogEntry; /* Check if we're initialized */ if (!Catalog->ProtocolList.Flink) return; /* Acquire lock */ WsTcLock(); /* Loop every entry */ Entry = Catalog->ProtocolList.Flink; while (Entry != &Catalog->ProtocolList) { /* Get this entry */ CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); /* Remove it */ WsTcRemoveCatalogItem(Catalog, CatalogEntry); /* Dereference it */ WsTcEntryDereference(CatalogEntry); /* Move to the next entry */ Entry = Catalog->ProtocolList.Flink; } /* Check if the catalog key is opened */ if (Catalog->CatalogKey) { /* Close it */ RegCloseKey(Catalog->CatalogKey); Catalog->CatalogKey = NULL; } /* Release and delete the lock */ WsTcUnlock(); DeleteCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock); /* Delete the object */ HeapFree(WsSockHeap, 0, Catalog); }
/* * @implemented */ INT WSAAPI WSAStringToAddressW(IN LPWSTR AddressString, IN INT AddressFamily, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, OUT LPSOCKADDR lpAddress, IN OUT LPINT lpAddressLength) { PWSPROCESS Process; PWSTHREAD Thread; INT ErrorCode, Status; DWORD CatalogEntryId; PTCATALOG Catalog; PTCATALOG_ENTRY CatalogEntry; DPRINT("WSAStringToAddressW: %S\n", AddressString); /* Enter prolog */ if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) { /* Leave now */ SetLastError(ErrorCode); return SOCKET_ERROR; } /* Get the catalog */ Catalog = WsProcGetTCatalog(Process); /* Check if we got custom protocol info */ if (lpProtocolInfo) { /* Get the entry ID */ CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; /* Get the entry associated with it */ ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, CatalogEntryId, &CatalogEntry); } else { /* Get it from the address family */ ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry); } /* Check for success */ if (ErrorCode == ERROR_SUCCESS) { /* Call the provider */ Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(AddressString, AddressFamily, &CatalogEntry-> ProtocolInfo, lpAddress, lpAddressLength, &ErrorCode); /* Dereference the entry */ WsTcEntryDereference(CatalogEntry); /* Check for success and return */ if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; } /* Set the error and return */ SetLastError(ErrorCode); return SOCKET_ERROR; }
/* * @implemented */ INT WSAAPI WSAStringToAddressA(IN LPSTR AddressString, IN INT AddressFamily, IN LPWSAPROTOCOL_INFOA lpProtocolInfo, OUT LPSOCKADDR lpAddress, IN OUT LPINT lpAddressLength) { PWSPROCESS Process; PWSTHREAD Thread; INT ErrorCode, Status; DWORD CatalogEntryId; PTCATALOG Catalog; PTCATALOG_ENTRY CatalogEntry; LPWSTR UnicodeString; DWORD Length = (DWORD)strlen(AddressString) + 1; DPRINT("WSAStringToAddressA: %s\n", AddressString); /* Enter prolog */ if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) { /* Leave now */ SetLastError(ErrorCode); return SOCKET_ERROR; } /* Allocate the unicode string */ UnicodeString = HeapAlloc(WsSockHeap, 0, Length * 2); if (!UnicodeString) { /* No memory; fail */ SetLastError(WSAENOBUFS); return SOCKET_ERROR; } /* Convert the string */ MultiByteToWideChar(CP_ACP, 0, AddressString, -1, UnicodeString, Length); /* Get the catalog */ Catalog = WsProcGetTCatalog(Process); /* Check if we got custom protocol info */ if (lpProtocolInfo) { /* Get the entry ID */ CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; /* Get the entry associated with it */ ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, CatalogEntryId, &CatalogEntry); } else { /* Get it from the address family */ ErrorCode = WsTcGetEntryFromAf(Catalog, AddressFamily, &CatalogEntry); } /* Check for success */ if (ErrorCode == ERROR_SUCCESS) { /* Call the provider */ Status = CatalogEntry->Provider->Service.lpWSPStringToAddress(UnicodeString, AddressFamily, &CatalogEntry-> ProtocolInfo, lpAddress, lpAddressLength, &ErrorCode); /* Dereference the entry */ WsTcEntryDereference(CatalogEntry); /* Free the unicode string */ HeapFree(WsSockHeap, 0, UnicodeString); /* Check for success and return */ if (Status == ERROR_SUCCESS) return ERROR_SUCCESS; } else { /* Free the unicode string */ HeapFree(WsSockHeap, 0, UnicodeString); } /* Set the error and return */ SetLastError(ErrorCode); return SOCKET_ERROR; }
DWORD WSAAPI WsTcFindIfsProviderForSocket(IN PTCATALOG Catalog, IN SOCKET Handle) { PTPROVIDER Provider; IN SOCKET NewHandle; INT Error; DWORD OptionLength; PLIST_ENTRY Entry; WSAPROTOCOL_INFOW ProtocolInfo; DWORD UniqueId; INT ErrorCode; PTCATALOG_ENTRY CatalogEntry; /* Get the catalog lock */ WsTcLock(); /* Loop as long as the catalog changes */ CatalogChanged: /* Loop every provider */ Entry = Catalog->ProtocolList.Flink; while (Entry != &Catalog->ProtocolList) { /* Get the catalog entry */ CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); /* Move to the next entry */ Entry = Entry->Flink; /* Skip it if it doesn't support IFS */ if (!(CatalogEntry->ProtocolInfo.dwServiceFlags1 & XP1_IFS_HANDLES)) continue; /* Check if we need to load it */ if (!(Provider = CatalogEntry->Provider)) { /* Load it */ ErrorCode = WsTcLoadProvider(Catalog, CatalogEntry); /* Skip it if we failed to load it */ if (ErrorCode != ERROR_SUCCESS) continue; /* Get the provider again */ Provider = CatalogEntry->Provider; } /* Reference the entry and get our unique id */ InterlockedIncrement(&CatalogEntry->RefCount); UniqueId = Catalog->UniqueId; /* Release the lock now */ WsTcUnlock(); /* Get the catalog entry ID */ OptionLength = sizeof(ProtocolInfo); ErrorCode = Provider->Service.lpWSPGetSockOpt(Handle, SOL_SOCKET, SO_PROTOCOL_INFOW, (PCHAR)&ProtocolInfo, (LPINT)&OptionLength, &Error); /* Dereference the entry and check the result */ WsTcEntryDereference(CatalogEntry); if (ErrorCode != ERROR_SUCCESS) { /* Lock and make sure this provider is still valid */ WsTcLock(); if (UniqueId == Catalog->UniqueId) continue; /* It changed! We need to start over */ goto CatalogChanged; } /* Now get the IFS handle */ NewHandle = WPUModifyIFSHandle(ProtocolInfo.dwCatalogEntryId, Handle, &Error); /* Check if the socket is invalid */ if (NewHandle == INVALID_SOCKET) return WSAENOTSOCK; /* We suceeded, get out of here */ return ERROR_SUCCESS; } /* Unrecognized socket if we get here: note, we still have the lock */ WsTcUnlock(); return WSAENOTSOCK; }
VOID WSAAPI WsTcUpdateProtocolList(IN PTCATALOG Catalog, IN PLIST_ENTRY List) { LIST_ENTRY TempList; PTCATALOG_ENTRY CatalogEntry, OldCatalogEntry; PLIST_ENTRY Entry; /* First move from our list to the old one */ InsertHeadList(&Catalog->ProtocolList, &TempList); RemoveEntryList(&Catalog->ProtocolList); InitializeListHead(&Catalog->ProtocolList); /* Loop every item on the list */ while (!IsListEmpty(List)) { /* Get the catalog entry */ Entry = RemoveHeadList(List); CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); /* Check if this item is already on our list */ Entry = TempList.Flink; while (Entry != &TempList) { /* Get the catalog entry */ OldCatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); Entry = Entry->Flink; /* Check if they match */ if (CatalogEntry->ProtocolInfo.dwCatalogEntryId == OldCatalogEntry->ProtocolInfo.dwCatalogEntryId) { /* We have a match, use the old item instead */ WsTcEntryDereference(CatalogEntry); CatalogEntry = OldCatalogEntry; RemoveEntryList(&CatalogEntry->CatalogLink); /* Decrease the number of protocols we have */ Catalog->ItemCount--; break; } } /* Add this item */ InsertTailList(&Catalog->ProtocolList, &CatalogEntry->CatalogLink); Catalog->ItemCount++; } /* If there's anything left on the temporary list */ while (!IsListEmpty(&TempList)) { /* Get the entry */ Entry = RemoveHeadList(&TempList); CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); /* Remove it */ Catalog->ItemCount--; WsTcEntryDereference(CatalogEntry); } }
DWORD WSAAPI WsTcRefreshFromRegistry(IN PTCATALOG Catalog, IN HANDLE CatalogEvent) { INT ErrorCode; BOOLEAN LocalEvent = FALSE; LIST_ENTRY LocalList; DWORD UniqueId; HKEY EntriesKey; DWORD CatalogEntries; PTCATALOG_ENTRY CatalogEntry; DWORD NextCatalogEntry; BOOL NewChangesMade; PLIST_ENTRY Entry; DWORD RegType = REG_DWORD; DWORD RegSize = sizeof(DWORD); DWORD i; /* Check if we got an event */ if (!CatalogEvent) { /* Create an event ourselves */ CatalogEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!CatalogEvent) return WSASYSCALLFAILURE; LocalEvent = TRUE; } /* Lock the catalog */ WsTcLock(); /* Initialize our local list for the loop */ InitializeListHead(&LocalList); /* Start looping */ do { /* Setup notifications for the catalog entry */ ErrorCode = WsSetupCatalogProtection(Catalog->CatalogKey, CatalogEvent, &UniqueId); if (ErrorCode != ERROR_SUCCESS) break; /* Check if we've changed till now */ if (UniqueId == Catalog->UniqueId) { /* We haven't, so return */ ErrorCode = ERROR_SUCCESS; break; } /* Now Open the Entries */ ErrorCode = RegOpenKeyEx(Catalog->CatalogKey, "Catalog_Entries", 0, MAXIMUM_ALLOWED, &EntriesKey); if (ErrorCode != ERROR_SUCCESS) { /* Critical failure */ ErrorCode = WSASYSCALLFAILURE; break; } /* Get the next entry */ ErrorCode = RegQueryValueEx(Catalog->CatalogKey, "Next_Catalog_Entry_ID", 0, &RegType, (LPBYTE)&NextCatalogEntry, &RegSize); if (ErrorCode != ERROR_SUCCESS) { /* Critical failure */ ErrorCode = WSASYSCALLFAILURE; break; } /* Find out how many there are */ ErrorCode = RegQueryValueEx(Catalog->CatalogKey, "Num_Catalog_Entries", 0, &RegType, (LPBYTE)&CatalogEntries, &RegSize); if (ErrorCode != ERROR_SUCCESS) { /* Critical failure */ ErrorCode = WSASYSCALLFAILURE; break; } /* Initialize them all */ for (i = 1; i <= CatalogEntries; i++) { /* Allocate a Catalog Entry Structure */ CatalogEntry = WsTcEntryAllocate(); if (!CatalogEntry) { /* Not enough memory, fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; break; } /* Initialize it from the Registry Key */ ErrorCode = WsTcEntryInitializeFromRegistry(CatalogEntry, EntriesKey, i); if (ErrorCode != ERROR_SUCCESS) { /* We failed to get it, dereference the entry and leave */ WsTcEntryDereference(CatalogEntry); break; } /* Insert it to our List */ InsertTailList(&LocalList, &CatalogEntry->CatalogLink); } /* Close the catalog key */ RegCloseKey(EntriesKey); /* Check if we changed during our read and if we have success */ NewChangesMade = WsCheckCatalogState(CatalogEvent); if (!NewChangesMade && ErrorCode == ERROR_SUCCESS) { /* All is good, update the protocol list */ WsTcUpdateProtocolList(Catalog, &LocalList); /* Update and return */ Catalog->UniqueId = UniqueId; Catalog->NextId = NextCatalogEntry; break; } /* We failed and/or catalog data changed, free what we did till now */ while (!IsListEmpty(&LocalList)) { /* Get the LP Catalog Item */ Entry = RemoveHeadList(&LocalList); CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink); /* Dereference it */ WsTcEntryDereference(CatalogEntry); } } while (NewChangesMade); /* Release the lock */ WsTcUnlock(); /* Close the event, if any was created by us */ if (LocalEvent) CloseHandle(CatalogEvent); /* All Done */ return ErrorCode; }
/* * @implemented */ SOCKET WSAAPI WSASocketW(IN INT af, IN INT type, IN INT protocol, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, IN GROUP g, IN DWORD dwFlags) { PWSPROCESS Process; PWSTHREAD Thread; INT ErrorCode; PTCATALOG Catalog; DWORD CatalogId; PTCATALOG_ENTRY CatalogEntry; LPWSAPROTOCOL_INFOW ProtocolInfo; DWORD OpenType; SOCKET Status = INVALID_SOCKET; DPRINT("WSASocketW: %lx, %lx, %lx, %p\n", af, type, protocol, lpProtocolInfo); /* Enter prolog */ if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) { /* Fail now */ SetLastError(ErrorCode); return INVALID_SOCKET; } /* Get the catalog */ Catalog = WsProcGetTCatalog(Process); /* Find a Provider for the Catalog ID */ if (lpProtocolInfo) { /* Get the catalog ID */ CatalogId = lpProtocolInfo->dwCatalogEntryId; /* Get the Catalog Entry */ ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, CatalogId, &CatalogEntry); } else { /* No ID */ CatalogId = 0; DoLookup: /* Get the Catalog Data from the Socket Info */ ErrorCode = WsTcGetEntryFromTriplet(Catalog, af, type, protocol, CatalogId, &CatalogEntry); } /* Check for Success */ if (ErrorCode == ERROR_SUCCESS) { /* Use the default Protocol Info if none given */ ProtocolInfo = lpProtocolInfo ? lpProtocolInfo : &CatalogEntry->ProtocolInfo; /* Save the open type and set new one */ OpenType = Thread->OpenType; Thread->OpenType = (dwFlags & WSA_FLAG_OVERLAPPED) ? 0 : SO_SYNCHRONOUS_NONALERT; /* Call the Provider to create the Socket */ Status = CatalogEntry->Provider->Service.lpWSPSocket(af, type, protocol, ProtocolInfo, g, dwFlags, &ErrorCode); /* Restore open type */ Thread->OpenType = OpenType; /* Get the catalog ID now, and dereference */ CatalogId = ProtocolInfo->dwCatalogEntryId; WsTcEntryDereference(CatalogEntry); /* Did we fail with WSAEINPROGRESS and had no specific provider? */ if ((Status == INVALID_SOCKET) && (ErrorCode == WSAEINPROGRESS) && !(lpProtocolInfo)) { /* In that case, restart the lookup from this ID */ goto DoLookup; } /* Check if we got a valid socket */ if (Status != INVALID_SOCKET) { /* Add an API reference and return */ WsSockAddApiReference(Status); return Status; } } /* Return with an Error */ SetLastError(ErrorCode); return INVALID_SOCKET; }
/* * @implemented */ SOCKET WSPAPI WPUModifyIFSHandle(IN DWORD dwCatalogEntryId, IN SOCKET ProposedHandle, OUT LPINT lpErrno) { SOCKET Handle = INVALID_SOCKET; DWORD ErrorCode = ERROR_SUCCESS; PWSPROCESS Process; PTCATALOG Catalog; PTCATALOG_ENTRY Entry; PWSSOCKET Socket; DPRINT("WPUModifyIFSHandle: %lx, %lx\n", dwCatalogEntryId, ProposedHandle); /* Get the current process */ if ((Process = WsGetProcess())) { /* Get the Transport Catalog */ if ((Catalog = WsProcGetTCatalog(Process))) { /* Get the entry for this ID */ ErrorCode = WsTcGetEntryFromCatalogEntryId(Catalog, dwCatalogEntryId, &Entry); /* Check for success */ if (ErrorCode == ERROR_SUCCESS) { /* Create a socket object */ if ((Socket = WsSockAllocate())) { /* Initialize it */ WsSockInitialize(Socket, Entry); /* Associate it */ ErrorCode = WsSockAssociateHandle(Socket, ProposedHandle, TRUE); /* Check for success */ if (ErrorCode == ERROR_SUCCESS) { /* Return */ Handle = ProposedHandle; *lpErrno = ERROR_SUCCESS; } else { /* Fail */ WsSockDereference(Socket); *lpErrno = ErrorCode; } /* Dereference the extra count */ WsSockDereference(Socket); } else { /* No memory to allocate a socket */ *lpErrno = WSAENOBUFS; } /* Dereference the catalog entry */ WsTcEntryDereference(Entry); } else { /* Entry not found */ *lpErrno = ErrorCode; } } else { /* Catalog not found */ *lpErrno = WSANOTINITIALISED; } } else { /* Process not ready */ *lpErrno = WSANOTINITIALISED; } /* Return */ return Handle; }