Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
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;
    }
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
    }

}
Exemplo n.º 6
0
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;
    }
}