int _cdecl main (int argc, CHAR **argv) { DWORD rc; BOOL Server; if (argc<2) { printf (USAGE(argv[0])); return 0; } if (_stricmp (argv[1], "s")==0) Server = TRUE; else if (_stricmp (argv[1], "c")==0) Server = FALSE; else { printf ("Must specify s(erver) or c(lient).\n"); printf (USAGE(argv[0])); return -1; } if ((rc=WahOpenNotificationHandleHelper (&hHelper))!=NO_ERROR) { printf ("WahOpenNotificationHandleHelper failed, err: %ld.\n", rc); return -1; } if (Server) { HANDLE hSync, hApc, hAEvent, hAPort, hANoPort; OVERLAPPED oApc, oEvent, oPort, oNoPort; LPOVERLAPPED lpo; HANDLE hPort; HANDLE hEvent; DWORD count, key; hPort = CreateIoCompletionPort ( INVALID_HANDLE_VALUE, NULL, 0, 0 ); if (hPort==INVALID_HANDLE_VALUE) { printf ("CreateIoCompletionPort (create) failed, err: %ld.\n", GetLastError ()); return -1; } hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); if (hEvent==NULL) { printf ("CreateEvent failed, err: %ld.\n", GetLastError ()); return -1; } rc = WahCreateNotificationHandle (hHelper, &hSync); if (rc!=0) { printf ("WahCreateNotificationHandle failed, err: %ld.\n", rc); return -1; } rc = WahCreateNotificationHandle (hHelper, &hApc); if (rc!=0) { printf ("WahCreateNotificationHandle failed, err: %ld.\n", rc); return -1; } oApc.hEvent = NULL; rc = WahCreateNotificationHandle (hHelper, &hAEvent); if (rc!=0) { printf ("WahCreateNotificationHandle failed, err: %ld.\n", rc); return -1; } oEvent.hEvent = hEvent; rc = WahCreateNotificationHandle (hHelper, &hAPort); if (rc!=0) { printf ("WahCreateNotificationHandle failed, err: %ld.\n", rc); return -1; } if (CreateIoCompletionPort (hAPort, hPort, (DWORD)hAPort, 0) == INVALID_HANDLE_VALUE) { printf ("CreateIoCompletionPort (associate) failed, err: %ld.\n", GetLastError ()); return -1; } oPort.hEvent = NULL; rc = WahCreateNotificationHandle (hHelper, &hANoPort); if (rc!=0) { printf ("WahCreateNotificationHandle failed, err: %ld.\n", rc); return -1; } if (CreateIoCompletionPort (hANoPort, hPort, (DWORD)hANoPort, 0) == INVALID_HANDLE_VALUE) { printf ("CreateIoCompletionPort (associate) failed, err: %ld.\n", GetLastError ()); return -1; } oNoPort.hEvent = (HANDLE)1; while (1) { printf ("Posting apc wait.\n"); rc = WahWaitForNotification (hHelper, hApc, &oApc, WsCompletion); if ((rc!=0) && (rc!=WSA_IO_PENDING)) { printf ("WahWaitForNotification(apc) failed, err: %ld.\n", rc); return -1; } printf ("Posting event wait.\n"); rc = WahWaitForNotification (hHelper, hAEvent, &oEvent, NULL); if ((rc!=0) && (rc!=WSA_IO_PENDING)) { printf ("WahWaitForNotification(event) failed, err: %ld.\n", rc); return -1; } printf ("Posting port wait.\n"); rc = WahWaitForNotification (hHelper, hAPort, &oPort, NULL); if ((rc!=0) && (rc!=WSA_IO_PENDING)) { printf ("WahWaitForNotification(port) failed, err: %ld.\n", rc); return -1; } printf ("Posting noport wait.\n"); rc = WahWaitForNotification (hHelper, hANoPort, &oNoPort, NULL); if ((rc!=0) && (rc!=WSA_IO_PENDING)) { printf ("WahWaitForNotification(port) failed, err: %ld.\n", rc); return -1; } printf ("Posting sync wait.\n"); memset (&ovlp, 0, sizeof (ovlp)); rc = WahWaitForNotification (hHelper, hSync, NULL, NULL); if (rc!=0) { printf ("WahWaitForNotification failed, err: %ld.\n", rc); return -1; } printf ("Waiting for apc\n"); rc = SleepEx (INFINITE, TRUE); if (rc!=WAIT_IO_COMPLETION) { printf ("Unexpected result on wait for apc: %ld.\n", rc); return rc; } printf ("Waiting for port\n"); if (GetQueuedCompletionStatus (hPort, &count, &key, &lpo, INFINITE)) { rc = 0; } else if (lpo) { rc = GetLastError (); if (rc==0) printf ("No error code for failed GetQueuedCompletionStatus.\n"); } else { printf ("GetQueuedCompletionStatus failed, err: %ld.\n", GetLastError ()); return -1; } if (key!=(DWORD)hAPort) printf ("Wrong completion key: %lx (expected : %lx)", key, hAPort); WsCompletion (rc, count, lpo, 0); printf ("Waiting for noport\n"); oNoPort.hEvent = NULL; if (GetOverlappedResult (hANoPort, &oNoPort, &count, TRUE)) { rc = 0; } else { rc = GetLastError (); if (rc==0) printf ("No error code for failed GetOverlappedResult.\n"); } WsCompletion (rc, count, &oNoPort, 0); printf ("Waiting for event\n"); if (GetOverlappedResult (hAEvent, &oEvent, &count, TRUE)) { rc = 0; } else { rc = GetLastError (); if (rc==0) printf ("No error code for failed GetOverlappedResult.\n"); } WsCompletion (rc, count, &oEvent, 0); } CloseHandle (hSync); CloseHandle (hANoPort); CloseHandle (hAPort); CloseHandle (hAEvent); CloseHandle (hApc); CloseHandle (hPort); CloseHandle (hEvent); } else if (argc<3) { rc = WahNotifyAllProcesses (hHelper); if (rc==0) { printf ("Notified all ok.\n"); } else { printf ("WahNotifyAllProcesses failed, err: %ld.\n", rc); } } else if (argc>=5) { HANDLE hPipe; DWORD id = GetCurrentProcessId (), count; WCHAR name[MAX_PATH]; // // Create client and of the pipe that matched the // pattern // wsprintfW (name, L"\\\\%hs\\pipe\\Winsock2\\CatalogChangeListener-%hs-%hs", argv[2], argv[3], argv[4]); hPipe = CreateFileW (name, GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if (hPipe!=INVALID_HANDLE_VALUE) { printf ("Opened pipe %ls.\n", name); CloseHandle (hPipe); } else { printf ("Could not open pipe %ls, err: %ld\n", name, GetLastError ()); } } else printf (USAGE(argv[0])); WahCloseNotificationHandleHelper (hHelper); return 0; }
VOID WSAAPI WsProcDelete(IN PWSPROCESS Process) { /* Check if we didn't even initialize yet */ if (!Process->LockReady) return; /* No more current process */ CurrentWsProcess = NULL; /* If we have a socket table */ if (WsSockHandleTable) { /* Enumerate the sockets with a delete callback */ WahEnumerateHandleContexts(WsSockHandleTable, WsSockDeleteSockets, Process); } /* Close APC Helper */ if (Process->ApcHelper) WahCloseApcHelper(Process->ApcHelper); /* Close handle helper */ if (Process->HandleHelper) WahCloseHandleHelper(Process->HandleHelper); /* Check for notification helper */ if (Process->NotificationHelper) { /* Close notification helper */ WahCloseNotificationHandleHelper(Process->NotificationHelper); } /* Check if we have a protocol catalog*/ if (Process->ProtocolCatalog) { /* Enumerate it to clean it up */ WsTcEnumerateCatalogItems(Process->ProtocolCatalog, CleanupProtocolProviders, NULL); /* Delete it */ WsTcDelete(Process->ProtocolCatalog); Process->ProtocolCatalog = NULL; } /* Check if we have a namespace catalog*/ if (Process->NamespaceCatalog) { /* Enumerate it to clean it up */ WsNcEnumerateCatalogItems(Process->NamespaceCatalog, CleanupNamespaceProviders, NULL); /* Delete it */ WsNcDelete(Process->NamespaceCatalog); Process->NamespaceCatalog = NULL; } /* Delete the thread lock */ DeleteCriticalSection(&Process->ThreadLock); /* Delete us */ HeapFree(WsSockHeap, 0, Process); }
INT WSAAPI WSCInstallNameSpace ( IN LPWSTR lpszIdentifier, IN LPWSTR lpszPathName, IN DWORD dwNameSpace, IN DWORD dwVersion, IN LPGUID lpProviderId ) /*++ Routine Description: WSCInstallNameSpace() is used to install a name space provider. For providers that are able to support multiple names spaces, this function must be called once for every name space supported, and a unique provider ID must be supplied each time. Arguments: lpszIdentifier - Display string for the provider. lpszPathname - Points to a path to the providers DLL image which follows the usual rules for path resolution. This path may contain embedded environment strings (such as %SystemRoot%). Such environment strings are expanded whenever the WinSock 2 DLL needs to subsequently load theprovider DLL on behalf of an application. After any embedded environment strings are expanded, the WinSock 2 DLL passes the resulting string into the LoadLibrary() function to load the provider into memory. dwNameSpace - Specifies the name space supported by this provider. dwVersion - Specifies the version number of the provider. bStoresAllServiceClassInfo - Specifies that this provider supports the storage of service class schema information for all service classes across all namespaces. The Winsock DLL will then use this provider to get all of its classinfo information rather than asking each individual provider. lpProviderId - A unique identifier for this provider. This GUID should be generated by UUIDGEN.EXE. Return Value: The function should return NO_ERROR (0) if the routine succeeds. It should return SOCKET_ERROR (-1) if the routine fails and it must set the appropriate error code using SetLastError(). --*/ { INT ReturnCode; PNSCATALOG Catalog =NULL; PNSCATALOGENTRY Item =NULL; HKEY registry_root; BOOL lock_owned = FALSE; registry_root = OpenWinSockRegistryRoot(); if (NULL == registry_root) { DEBUGF( DBG_ERR, ("Opening registry root\n")); SetLastError(WSASYSCALLFAILURE); return(SOCKET_ERROR); } // // Check the current protocol catalog key. If it doesn't match // the expected value, blow away the old key and update the // stored value. // ValidateCurrentCatalogName( registry_root, WINSOCK_CURRENT_NAMESPACE_CATALOG_NAME, NSCATALOG::GetCurrentCatalogName() ); TRY_START(guard_memalloc){ GUID_MATCH_CONTEXT context; Catalog = new NSCATALOG; if (NULL == Catalog){ ReturnCode = WSA_NOT_ENOUGH_MEMORY; TRY_THROW(guard_memalloc); } //item Item = new NSCATALOGENTRY; if (NULL == Item){ ReturnCode = WSA_NOT_ENOUGH_MEMORY; TRY_THROW(guard_memalloc); } //if __try { context.ProviderId = *lpProviderId; ReturnCode = Item->InitializeFromValues( lpszPathName, lpszIdentifier, lpProviderId, dwNameSpace, dwVersion ); } __except (WS2_EXCEPTION_FILTER()) { ReturnCode = WSAEFAULT; TRY_THROW(guard_memalloc); } if (ERROR_SUCCESS != ReturnCode){ TRY_THROW(guard_memalloc); } //if ReturnCode = Catalog->InitializeFromRegistry( registry_root, // ParentKey NULL // ChangeEvent ); if (ERROR_SUCCESS != ReturnCode){ TRY_THROW(guard_memalloc); } //if context.CatalogItem = NULL; Catalog->EnumerateCatalogItems( GuidMatcher, &context ); if (context.CatalogItem != NULL){ ReturnCode = WSAEINVAL; TRY_THROW(guard_memalloc); } //if Catalog->AppendCatalogItem( Item ); Item = NULL; // item deletion is now covered by catalog ReturnCode = Catalog->WriteToRegistry(); if (ReturnCode!=ERROR_SUCCESS) { TRY_THROW (guard_memalloc); } delete Catalog; } TRY_CATCH(guard_memalloc){ assert (ReturnCode!=ERROR_SUCCESS); if (Item){ Item->Dereference (); } //if if (Catalog){ delete Catalog; } //if } TRY_END(guard_memalloc); CloseWinSockRegistryRoot(registry_root); if (ReturnCode == ERROR_SUCCESS) { HANDLE hHelper; // // Alert all interested apps of change via the notification method // if (WahOpenNotificationHandleHelper( &hHelper )==ERROR_SUCCESS) { WahNotifyAllProcesses( hHelper ); WahCloseNotificationHandleHelper( hHelper ); } else { // This is non-fatal and catalog was updated anyway } return ERROR_SUCCESS; } else { SetLastError(ReturnCode); return SOCKET_ERROR; } }
int WSPAPI WSCWriteNameSpaceOrder ( IN LPGUID lpProviderId, IN DWORD dwNumberOfEntries ) /*++ Routine Description: Reorder existing WinSock2 name space providers. The order of the service providers determines their priority in being selected for use. The sporder.exe tool will show you the installed provider and their ordering, Alternately, WSAEnumNameSpaces(), in conjunction with this function, will allow you to write your own tool. Arguments: lpwdCatalogEntryId [in] An array of CatalogEntryId elements as found in the WSAPROTOCOL_INFO structure. The order of the CatalogEntryId elements is the new priority ordering for the service providers. dwNumberOfEntries [in] The number of elements in the lpwdCatalogEntryId array. Return Value: ERROR_SUCCESS - the service providers have been reordered. WSAEINVAL - input parameters were bad, no action was taken. WSAEFAULT - CatalogEnryId array is not fully contained within process address space. WSATRY_AGAIN - the routine is being called by another thread or process. any registry error code Comments: Here are scenarios in which the WSCWriteProviderOrder function may fail: The dwNumberOfEntries is not equal to the number of registered service providers. The lpwdCatalogEntryId contains an invalid catalog ID. The lpwdCatalogEntryId does not contain all valid catalog IDs exactly 1 time. The routine is not able to access the registry for some reason (e.g. inadequate user persmissions) Another process (or thread) is currently calling the routine. --*/ { INT errno_result; HKEY registry_root; PNSCATALOGENTRY item; PNSCATALOGENTRY *items = NULL; DWORD i; // object protected by "try" block PNSCATALOG catalog = NULL; items = new PNSCATALOGENTRY[dwNumberOfEntries]; if (items==NULL) { DEBUGF( DBG_ERR, ("Allocating items array\n")); return WSA_NOT_ENOUGH_MEMORY; } memset (items, 0, sizeof (PNSCATALOGENTRY)*dwNumberOfEntries); errno_result = ERROR_SUCCESS; TRY_START(guard_memalloc) { PROVIDER_SNAP_CONTEXT context; registry_root = OpenWinSockRegistryRoot(); if (registry_root == NULL) { DEBUGF( DBG_ERR, ("Opening registry root\n")); errno_result = WSANO_RECOVERY; TRY_THROW(guard_memalloc); } catalog = new NSCATALOG(); if (catalog == NULL) { errno_result = WSA_NOT_ENOUGH_MEMORY; TRY_THROW(guard_memalloc); } errno_result = catalog->InitializeFromRegistry( registry_root, // ParentKey NULL // ChangeEvent ); if (errno_result != ERROR_SUCCESS) { TRY_THROW(guard_memalloc); } context.Items = items; context.ProviderIds = lpProviderId; context.Count = dwNumberOfEntries; context.ErrorCode = ERROR_SUCCESS; catalog->EnumerateCatalogItems( ProviderSnap, // Iteration & context // PassBack ); if (context.ErrorCode!=ERROR_SUCCESS) { errno_result = context.ErrorCode; TRY_THROW(guard_memalloc); } for (i=0; i<dwNumberOfEntries; i++) { if (context.Items[i]!=NULL) { // // Remove catalog item and add it in the end. // catalog->RemoveCatalogItem (context.Items[i]); catalog->AppendCatalogItem (context.Items[i]); } else { DEBUGF (DBG_ERR, ("Checking item array against catalog, item: %ld.\n", i)); errno_result = WSAEINVAL; TRY_THROW(guard_memalloc); } } // for i errno_result = catalog->WriteToRegistry(); if (errno_result!=ERROR_SUCCESS) { TRY_THROW(guard_memalloc); } delete catalog; CloseWinSockRegistryRoot(registry_root); } TRY_CATCH(guard_memalloc) { assert (errno_result != ERROR_SUCCESS); if (catalog != NULL) { delete catalog; // This destroys the items as well } if (registry_root!=NULL) { CloseWinSockRegistryRoot(registry_root); } } TRY_END(guard_memalloc); delete items; if (errno_result == ERROR_SUCCESS) { HANDLE hHelper; // // Alert all interested apps of change via the notification method // if (WahOpenNotificationHandleHelper( &hHelper) == ERROR_SUCCESS) { WahNotifyAllProcesses( hHelper ); WahCloseNotificationHandleHelper( hHelper ); } else { // // This in non-fatal and catalog was updated anyway. // } } return errno_result; }
INT WSAAPI WSCEnableNSProvider ( IN LPGUID lpProviderId, IN BOOL fEnable ) /*++ Routine Description: WSCEnableNSProvider() is used to change the state of a given name space provider. This function is intended to be used by the control panel applet to change the state of the providers. An ISV should not just blindly de-activate another ISV's provider in order to activate their own. This choice should be left up to the user.description-of-function Arguments: lpProviderId - The unique identifier for this provider. fEnable - If TRUE, the provider is set to the active state. If FALSE, the provider is disabled and will not be available for query operations or service registration. Return Value: The function should return NO_ERROR (0) if the routine succeeds. It should return SOCKET_ERROR (-1) if the routine fails and it must set the appropriate error code using SetLastError(). --*/ { INT ReturnCode; PNSCATALOG Catalog =NULL; HKEY registry_root; registry_root = OpenWinSockRegistryRoot(); if (NULL == registry_root) { DEBUGF( DBG_ERR, ("Opening registry root\n")); SetLastError(WSASYSCALLFAILURE); return(SOCKET_ERROR); } TRY_START(guard_memalloc){ GUID_MATCH_CONTEXT context; Catalog = new NSCATALOG; if (NULL == Catalog){ ReturnCode = WSA_NOT_ENOUGH_MEMORY; TRY_THROW(guard_memalloc); } //item ReturnCode = Catalog->InitializeFromRegistry( registry_root, // ParentKey NULL // ChangeEvent ); if (ERROR_SUCCESS != ReturnCode){ TRY_THROW(guard_memalloc); } //if __try { context.ProviderId = *lpProviderId; } __except (WS2_EXCEPTION_FILTER()) { ReturnCode = WSAEFAULT; TRY_THROW(guard_memalloc); } context.CatalogItem = NULL; Catalog->EnumerateCatalogItems( GuidMatcher, &context); if (context.CatalogItem!=NULL) { context.CatalogItem->Enable (fEnable ? TRUE : FALSE); } else { ReturnCode = WSAEINVAL; TRY_THROW(guard_memalloc); } ReturnCode = Catalog->WriteToRegistry(); if (ReturnCode != ERROR_SUCCESS) { TRY_THROW(guard_memalloc); } delete Catalog; } TRY_CATCH(guard_memalloc){ assert (ReturnCode!=ERROR_SUCCESS); if (Catalog){ delete Catalog; } //if } TRY_END(guard_memalloc); CloseWinSockRegistryRoot(registry_root); if (ERROR_SUCCESS == ReturnCode){ HANDLE hHelper; // // Alert all interested apps of change via the notification method // if (WahOpenNotificationHandleHelper( &hHelper) == ERROR_SUCCESS) { WahNotifyAllProcesses( hHelper ); WahCloseNotificationHandleHelper( hHelper ); } else { // // This in non-fatal and catalog was updated anyway. // } return ERROR_SUCCESS; } else { SetLastError(ReturnCode); return SOCKET_ERROR; } }
INT WSAAPI WSCUnInstallNameSpace ( IN LPGUID lpProviderId ) /*++ Routine Description: WSCUnInstallNameSpace() is used to uninstall the indicated name space provider. Arguments: lpProviderId - The unique identifier for a provider. Return Value: The function should return NO_ERROR (0) if the routine succeeds. It should return SOCKET_ERROR (-1) if the routine fails and it must set the appropriate error code using SetLastError(). --*/ { INT ReturnCode; PNSCATALOG Catalog =NULL; HKEY registry_root; //Open and Initialize a name space jprovider catalog registry_root = OpenWinSockRegistryRoot(); if (NULL == registry_root) { DEBUGF( DBG_ERR, ("Opening registry root\n")); SetLastError(WSASYSCALLFAILURE); return(SOCKET_ERROR); } TRY_START(guard_memalloc){ GUID_MATCH_CONTEXT context; Catalog = new NSCATALOG; if (NULL == Catalog){ ReturnCode = WSA_NOT_ENOUGH_MEMORY; TRY_THROW(guard_memalloc); } //item ReturnCode = Catalog->InitializeFromRegistry( registry_root, // ParentKey NULL // ChangeEvent ); if (ERROR_SUCCESS != ReturnCode){ TRY_THROW(guard_memalloc); } //if __try { context.ProviderId = *lpProviderId; } __except (WS2_EXCEPTION_FILTER()) { ReturnCode = WSAEFAULT; TRY_THROW(guard_memalloc); } context.CatalogItem = NULL; Catalog->EnumerateCatalogItems( GuidMatcher, &context); if (context.CatalogItem!=NULL) { Catalog->RemoveCatalogItem (context.CatalogItem); context.CatalogItem->Dereference (); } else { ReturnCode = WSAEINVAL; TRY_THROW(guard_memalloc); } ReturnCode = Catalog->WriteToRegistry(); if (ERROR_SUCCESS != ReturnCode){ TRY_THROW(guard_memalloc); } //if delete Catalog; } TRY_CATCH(guard_memalloc){ assert (ReturnCode!=ERROR_SUCCESS); if (Catalog){ delete Catalog; } //if } TRY_END(guard_memalloc); CloseWinSockRegistryRoot(registry_root); if (ERROR_SUCCESS == ReturnCode){ HANDLE hHelper; // // Alert all interested apps of change via the notification method // if (WahOpenNotificationHandleHelper( &hHelper) == ERROR_SUCCESS) { WahNotifyAllProcesses( hHelper ); WahCloseNotificationHandleHelper( hHelper ); } else { // // This in non-fatal and catalog was updated anyway. // } return ERROR_SUCCESS; } else { SetLastError(ReturnCode); return SOCKET_ERROR; } }