/*********************************************************************************************************************************** Remote command ***********************************************************************************************************************************/ void cmdRemote(int handleRead, int handleWrite) { FUNCTION_LOG_VOID(logLevelDebug); MEM_CONTEXT_TEMP_BEGIN() { String *name = strNewFmt(PROTOCOL_SERVICE_REMOTE "-%u", cfgOptionUInt(cfgOptProcess)); IoRead *read = ioHandleReadNew(name, handleRead, (TimeMSec)(cfgOptionDbl(cfgOptProtocolTimeout) * 1000)); ioReadOpen(read); IoWrite *write = ioHandleWriteNew(name, handleWrite); ioWriteOpen(write); ProtocolServer *server = protocolServerNew(name, PROTOCOL_SERVICE_REMOTE_STR, read, write); protocolServerHandlerAdd(server, storageRemoteProtocol); protocolServerHandlerAdd(server, configProtocol); // Acquire a lock if this command needs one. We'll use the noop that is always sent from the client right after the // handshake to return an error. volatile bool success = false; TRY_BEGIN() { // Read the command. No need to parse it since we know this is the first noop. ioReadLine(read); // Only try the lock if this is process 0, i.e. the remote started from the main process if (cfgOptionUInt(cfgOptProcess) == 0) { ConfigCommand commandId = cfgCommandId(strPtr(cfgOptionStr(cfgOptCommand))); // Acquire a lock if this command requires a lock if (cfgLockRemoteRequired(commandId)) lockAcquire(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgLockRemoteType(commandId), 0, true); } protocolServerResponse(server, NULL); success = true; } CATCH_ANY() { protocolServerError(server, errorCode(), STR(errorMessage()), STR(errorStackTrace())); } TRY_END(); // If not successful we'll just exit if (success) protocolServerProcess(server); } MEM_CONTEXT_TEMP_END(); FUNCTION_LOG_RETURN_VOID(); }
/*********************************************************************************************************************************** Compare log to a regexp After the comparison the log is cleared so the next result can be compared. ***********************************************************************************************************************************/ void harnessLogResultRegExp(const char *expression) { FUNCTION_HARNESS_BEGIN(); FUNCTION_HARNESS_PARAM(STRINGZ, expression); FUNCTION_HARNESS_ASSERT(expression != NULL); FUNCTION_HARNESS_END(); regex_t regExp; TRY_BEGIN() { harnessLogLoad(logFile); // Compile the regexp and process errors int result = 0; if ((result = regcomp(®Exp, expression, REG_NOSUB | REG_EXTENDED)) != 0) { char buffer[4096]; regerror(result, NULL, buffer, sizeof(buffer)); THROW(FormatError, buffer); } // Do the match if (regexec(®Exp, harnessLogBuffer, 0, NULL, 0) != 0) THROW_FMT(AssertError, "\n\nexpected log regexp:\n\n%s\n\nbut actual log was:\n\n%s\n\n", expression, harnessLogBuffer); close(logHandleFile); logHandleFile = harnessLogOpen(logFile, O_WRONLY | O_CREAT | O_TRUNC, 0640); } FINALLY() { regfree(®Exp); } TRY_END(); FUNCTION_HARNESS_RESULT_VOID(); }
/*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ void testRun(void) { FUNCTION_HARNESS_VOID(); // ***************************************************************************************************************************** if (testBegin("stackTraceFmt()")) { char buffer[8]; TEST_RESULT_INT(stackTraceFmt(buffer, 8, 0, "%s", "1234567"), 7, "fill buffer"); TEST_RESULT_STR(buffer, "1234567", " check buffer"); TEST_RESULT_INT(stackTraceFmt(buffer, 8, 7, "%s", "1234567"), 7, "try to fill buffer - at end"); TEST_RESULT_STR(buffer, "1234567", " check buffer is unmodified"); TEST_RESULT_INT(stackTraceFmt(buffer, 8, 8, "%s", "1234567"), 7, "try to fill buffer - past end"); TEST_RESULT_STR(buffer, "1234567", " check buffer is unmodified"); } // ***************************************************************************************************************************** if (testBegin("stackTraceInit() and stackTraceError()")) { #ifdef WITH_BACKTRACE stackTraceInit(BOGUS_STR); // This time does nothing stackTraceInit(BOGUS_STR); // This will call the error routine since we passed a bogus exe assert(stackTracePush("file1.c", "function1", logLevelDebug) == logLevelDebug); stackTracePop("file1.c", "function1"); backTraceState = NULL; #endif } // ***************************************************************************************************************************** if (testBegin("stackTraceTestStart(), stackTraceTestStop(), and stackTraceTest()")) { #ifndef NDEBUG assert(stackTraceTest()); stackTraceTestStop(); assert(!stackTraceTest()); stackTraceTestStart(); assert(stackTraceTest()); #endif } // ***************************************************************************************************************************** if (testBegin("stackTracePush(), stackTracePop(), and stackTraceClean()")) { char buffer[4096]; #ifdef WITH_BACKTRACE stackTraceInit(testExe()); #endif TEST_ERROR(stackTracePop("file1", "function1", false), AssertError, "assertion 'stackSize > 0' failed"); assert(stackTracePush("file1", "function1", logLevelDebug) == logLevelDebug); assert(stackSize == 1); TEST_ERROR( stackTracePop("file2", "function2", false), AssertError, "popping file2:function2 but expected file1:function1"); assert(stackTracePush("file1", "function1", logLevelDebug) == logLevelDebug); TEST_ERROR( stackTracePop("file1", "function2", false), AssertError, "popping file1:function2 but expected file1:function1"); TRY_BEGIN() { assert(stackTracePush("file1.c", "function1", logLevelDebug) == logLevelDebug); stackTraceParamLog(); assert(strcmp(stackTraceParam(), "void") == 0); stackTraceToZ(buffer, sizeof(buffer), "file1.c", "function2", 99); #ifdef WITH_BACKTRACE TEST_RESULT_STR( buffer, "file1:function2:99:(test build required for parameters)\n" " ... function(s) ommitted ...\n" "file1:function1:0:(void)", " check stack trace"); #else TEST_RESULT_STR( buffer, "file1:function2:99:(test build required for parameters)\n" " ... function(s) ommitted ...\n" "file1:function1:(void)", " check stack trace"); #endif assert(stackTracePush("file1.c", "function2", logLevelTrace) == logLevelTrace); stackTrace[stackSize - 2].fileLine = 7777; assert(strcmp(stackTraceParam(), "trace log level required for parameters") == 0); stackTrace[stackSize - 1].functionLogLevel = logLevelDebug; TRY_BEGIN() { // Function with one param assert(stackTracePush("file2.c", "function2", logLevelDebug) == logLevelDebug); stackTrace[stackSize - 2].fileLine = 7777; stackTraceParamAdd((size_t)snprintf(stackTraceParamBuffer("param1"), STACK_TRACE_PARAM_MAX, "value1")); stackTraceParamLog(); assert(strcmp(stackTraceParam(), "param1: value1") == 0); // Function with multiple params assert(stackTracePush("file3.c", "function3", logLevelTrace) == logLevelTrace); stackTrace[stackSize - 2].fileLine = 7777; stackTraceParamLog(); stackTraceParamAdd((size_t)snprintf(stackTraceParamBuffer("param1"), STACK_TRACE_PARAM_MAX, "value1")); stackTraceParamAdd((size_t)snprintf(stackTraceParamBuffer("param2"), STACK_TRACE_PARAM_MAX, "value2")); assert(strcmp(stackTraceParam(), "param1: value1, param2: value2") == 0); // Calculate exactly where the buffer will overflow (4 is for the separators) size_t bufferOverflow = sizeof(functionParamBuffer) - (STACK_TRACE_PARAM_MAX * 2) - strlen("param1") - 4 - (size_t)(stackTrace[stackSize - 1].param - functionParamBuffer); // Munge the previous previous param in the stack so that the next one will just barely fit stackTrace[stackSize - 1].paramSize = bufferOverflow - 1; assert(stackTracePush("file4.c", "function4", logLevelDebug) == logLevelTrace); stackTrace[stackSize - 2].fileLine = 7777; stackTraceParamLog(); assert(stackSize == 5); // This param will fit exactly stackTraceParamAdd((size_t)snprintf(stackTraceParamBuffer("param1"), STACK_TRACE_PARAM_MAX, "value1")); assert(strcmp(stackTraceParam(), "param1: value1") == 0); // But when we increment the param pointer by one there will be overflow stackTrace[stackSize - 1].param += 1; stackTrace[stackSize - 1].paramSize = 0; stackTraceParamAdd((size_t)snprintf(stackTraceParamBuffer("param1"), STACK_TRACE_PARAM_MAX, "value1")); assert(strcmp(stackTraceParam(), "buffer full - parameters not available") == 0); stackTraceToZ(buffer, sizeof(buffer), "file4.c", "function4", 99); #ifdef WITH_BACKTRACE TEST_RESULT_STR( buffer, "file4:function4:99:(buffer full - parameters not available)\n" "file3:function3:7777:(param1: value1, param2: value2)\n" "file2:function2:7777:(param1: value1)\n" "file1:function2:7777:(debug log level required for parameters)\n" "file1:function1:7777:(void)", "stack trace"); #else TEST_RESULT_STR( buffer, "file4:function4:99:(buffer full - parameters not available)\n" "file3:function3:(param1: value1, param2: value2)\n" "file2:function2:(param1: value1)\n" "file1:function2:(debug log level required for parameters)\n" "file1:function1:(void)", "stack trace"); #endif stackTracePop("file4.c", "function4", false); assert(stackSize == 4); // Check that stackTracePop() works with test tracing stackTracePush("file_test.c", "function_test", logLevelDebug); stackTracePop("file_test.c", "function_test", true); // Check that stackTracePop() does nothing when test tracing is disabled stackTraceTestStop(); stackTracePop("bogus.c", "bogus", true); stackTraceTestStart(); THROW(ConfigError, "test"); } CATCH(ConfigError) { // Ignore the error since we are just testing stack cleaup } TRY_END(); assert(stackSize == 2); THROW(ConfigError, "test"); } CATCH(ConfigError) { // Ignore the error since we are just testing stack cleaup } TRY_END(); assert(stackSize == 0); }
/*********************************************************************************************************************************** Do cleanup and return result code ***********************************************************************************************************************************/ int exitSafe(int result, bool error, SignalType signalType) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(INT, result); FUNCTION_LOG_PARAM(BOOL, error); FUNCTION_LOG_PARAM(ENUM, signalType); FUNCTION_LOG_END(); // Report error if one was thrown if (error) { // Don't log the error if it has already been logged by Perl #ifdef HAVE_LIBPERL if (strcmp(errorMessage(), PERL_EMBED_ERROR) != 0) { #endif LogLevel logLevel = errorCode() == errorTypeCode(&AssertError) ? logLevelAssert : logLevelError; // Assert errors always output a stack trace if (logLevel == logLevelAssert) LOG(logLevel, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); else { // Log just the error to non-debug levels LOG_INTERNAL(logLevel, LOG_LEVEL_MIN, logLevelDetail, 0, errorCode(), errorMessage()); // Log the stack trace debug levels if (logAny(logLevelDebug)) { LOG_INTERNAL( logLevel, logLevelDebug, LOG_LEVEL_MAX, 0, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); } } #ifdef HAVE_LIBPERL } #endif result = errorCode(); } // Free protocol objects but ignore errors TRY_BEGIN() { protocolFree(); } TRY_END(); // Free Perl but ignore errors #ifdef HAVE_LIBPERL TRY_BEGIN() { perlFree(result); } TRY_END(); #endif // Log command end if a command is set if (cfgCommand() != cfgCmdNone) { String *errorMessage = NULL; // On error generate an error message if (result != 0) { // On process terminate if (result == errorTypeCode(&TermError)) { errorMessage = strNew("terminated on signal "); // Terminate from a child if (signalType == signalTypeNone) strCat(errorMessage, "from child process"); // Else terminated directly else strCatFmt(errorMessage, "[SIG%s]", exitSignalName(signalType)); } // Standard error exit message else if (error) errorMessage = strNewFmt("aborted with exception [%03d]", result); } cmdEnd(result, errorMessage); } // Release any locks but ignore errors TRY_BEGIN() { lockRelease(false); } TRY_END(); // Return result - caller should immediate pass this result to exit() FUNCTION_LOG_RETURN(INT, result); }
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; } }