DWORD LW_USERMONITORLIB_API DecodeUserChange( IN PVOID pBuffer, IN size_t sBufferLen, OUT PUSER_CHANGE* ppValue ) { DWORD dwError = 0; idl_es_handle_t encodingHandle = NULL; error_status_t status = 0; error_status_t status2; PUSER_CHANGE pValue = NULL; idl_es_decode_buffer( (idl_byte *)pBuffer, sBufferLen, &encodingHandle, &status); BAIL_ON_ERR_STATUS(status); DCETHREAD_TRY USER_CHANGE_Decode(encodingHandle, &pValue); DCETHREAD_CATCH_ALL(status); DCETHREAD_ENDTRY BAIL_ON_ERR_STATUS(status); idl_es_handle_free(&encodingHandle, &status); encodingHandle = NULL; BAIL_ON_ERR_STATUS(status); *ppValue = pValue; cleanup: return dwError; error: if (pValue != NULL) { FreeUserChange(pValue); } if (encodingHandle != NULL) { // Do not return status2 idl_es_handle_free(&encodingHandle, &status2); } goto cleanup; }
DWORD LW_USERMONITORLIB_API EncodeUserChange( IN PUSER_CHANGE pValue, OUT PDWORD pdwEncodedSize, OUT PVOID* ppEncodedBuffer ) { DWORD dwError = 0; idl_es_handle_t encodingHandle = NULL; error_status_t status = 0; error_status_t status2; idl_es_encode_dyn_buffer( (idl_byte**) (void*) ppEncodedBuffer, (idl_ulong_int*) pdwEncodedSize, &encodingHandle, &status); BAIL_ON_ERR_STATUS(status); DCETHREAD_TRY USER_CHANGE_Encode(encodingHandle, pValue); DCETHREAD_CATCH_ALL(status); DCETHREAD_ENDTRY BAIL_ON_ERR_STATUS(status); idl_es_handle_free(&encodingHandle, &status); encodingHandle = NULL; BAIL_ON_ERR_STATUS(status); cleanup: return dwError; error: if (encodingHandle != NULL) { // Do not return status2 idl_es_handle_free(&encodingHandle, &status2); } goto cleanup; }
DWORD WinRegRegisterForRPC( PSTR pszServiceName, rpc_binding_vector_p_t* ppServerBinding ) { volatile DWORD dwError = 0; volatile DWORD dwRpcStatus = 0; rpc_binding_vector_p_t pServerBinding = NULL; BOOLEAN bRegistered = FALSE; BOOLEAN bBound = FALSE; BOOLEAN bEPRegistered = FALSE; static ENDPOINT endpoints[] = { {"ncacn_ip_tcp", NULL}, {"ncacn_np" , "\\\\pipe\\\\winreg"}, {NULL , NULL} }; DCETHREAD_TRY { rpc_server_register_if(winreg_v1_0_s_ifspec, NULL, NULL, (unsigned32*)&dwRpcStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if (dwRpcStatus == RPC_S_OK) { dwError = dcethread_exc_getstatus(THIS_CATCH); if (!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } } DCETHREAD_ENDTRY; BAIL_ON_DCE_ERROR(dwError, dwRpcStatus); BAIL_ON_SRVSVC_ERROR(dwError); bRegistered = TRUE; SRVSVC_LOG_INFO("RPC Service registered successfully."); DCETHREAD_TRY { dwError = bind_server(&pServerBinding, winreg_v1_0_s_ifspec, endpoints); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if (!dwError) { dwError = dcethread_exc_getstatus(THIS_CATCH); } if (!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } DCETHREAD_ENDTRY; BAIL_ON_SRVSVC_ERROR(dwError); bBound = TRUE; DCETHREAD_TRY { rpc_ep_register(winreg_v1_0_s_ifspec, pServerBinding, NULL, (idl_char*)pszServiceName, (unsigned32*)&dwRpcStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if (dwRpcStatus == RPC_S_OK) { dwError = dcethread_exc_getstatus(THIS_CATCH); if (!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } } DCETHREAD_ENDTRY; BAIL_ON_DCE_ERROR(dwError, dwRpcStatus); BAIL_ON_SRVSVC_ERROR(dwError); bEPRegistered = TRUE; SRVSVC_LOG_INFO("RPC Endpoint registered successfully."); *ppServerBinding = pServerBinding; cleanup: return dwError; error: SRVSVC_LOG_ERROR("Failed to register RPC endpoint. Error Code: [%u]\n", dwError); if (bEPRegistered) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_ep_unregister(winreg_v1_0_s_ifspec, pServerBinding, NULL, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } if (bBound) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_binding_vector_free(&pServerBinding, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } if (bRegistered) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_server_unregister_if(winreg_v1_0_s_ifspec, NULL, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } *ppServerBinding = NULL; goto cleanup; }
DWORD SrvSvcRegisterForRPC( PSTR pszServiceName, rpc_binding_vector_p_t* ppServerBinding ) { volatile DWORD dwError = 0; volatile DWORD dwRpcStatus = 0; rpc_binding_vector_p_t pServerBinding = NULL; BOOLEAN bRegistered = FALSE; BOOLEAN bBound = FALSE; BOOLEAN bEPRegistered = FALSE; static ENDPOINT endpoints[] = { {"ncacn_np", "\\\\pipe\\\\srvsvc"}, {"ncalrpc", NULL}, // endpoint is fetched from config parameter {NULL, NULL}, // placeholder for ncacn_ip_tcp (if enabled) {NULL, NULL} }; DWORD i = 0; PSTR lpcSocketPath = NULL; BOOLEAN registerTcpIp = FALSE; dwError = SrvSvcConfigGetLpcSocketPath(&lpcSocketPath); BAIL_ON_SRVSVC_ERROR(dwError); // Fill in the socket path for local procedure calls (ncalrpc) while (endpoints[i].protocol) { if (lpcSocketPath && LwRtlCStringIsEqual(endpoints[i].protocol, "ncalrpc", TRUE)) { endpoints[i].endpoint = lpcSocketPath; } i++; } dwError = SrvSvcConfigGetRegisterTcpIp(®isterTcpIp); BAIL_ON_SRVSVC_ERROR(dwError); // Append ncacn_ip_tcp endpoint if it's enabled in the configuration if (registerTcpIp) { endpoints[i++].protocol = "ncacn_ip_tcp"; } DCETHREAD_TRY { rpc_server_register_if (srvsvc_v3_0_s_ifspec, NULL, NULL, (unsigned32*)&dwRpcStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if ( dwRpcStatus == RPC_S_OK ) { dwError = dcethread_exc_getstatus (THIS_CATCH); if(!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } } DCETHREAD_ENDTRY; BAIL_ON_DCE_ERROR(dwError, dwRpcStatus); BAIL_ON_SRVSVC_ERROR(dwError); bRegistered = TRUE; SRVSVC_LOG_INFO("RPC Service registered successfully."); DCETHREAD_TRY { dwError = bind_server(&pServerBinding, srvsvc_v3_0_s_ifspec, endpoints); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if(!dwError) { dwError = dcethread_exc_getstatus (THIS_CATCH); } if(!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } DCETHREAD_ENDTRY; BAIL_ON_SRVSVC_ERROR(dwError); bBound = TRUE; DCETHREAD_TRY { rpc_ep_register(srvsvc_v3_0_s_ifspec, pServerBinding, NULL, (idl_char*)pszServiceName, (unsigned32*)&dwRpcStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) { if ( dwRpcStatus == RPC_S_OK ) { dwError = dcethread_exc_getstatus (THIS_CATCH); if(!dwError) { dwError = SRVSVC_ERROR_RPC_EXCEPTION_UPON_REGISTER; } } } DCETHREAD_ENDTRY; BAIL_ON_DCE_ERROR(dwError, dwRpcStatus); BAIL_ON_SRVSVC_ERROR(dwError); bEPRegistered = TRUE; SRVSVC_LOG_INFO("RPC Endpoint registered successfully."); *ppServerBinding = pServerBinding; cleanup: // DCE/RPC runtime makes a copy of ncalrpc socket path internally // so it is safe to free it here LW_SAFE_FREE_MEMORY(lpcSocketPath); return dwError; error: SRVSVC_LOG_ERROR("Failed to register RPC endpoint. Error Code: [%u]\n", dwError); if (bEPRegistered) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_ep_unregister(srvsvc_v3_0_s_ifspec, pServerBinding, NULL, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } if (bBound) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_binding_vector_free(&pServerBinding, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } if (bRegistered) { DCETHREAD_TRY { DWORD tmpStatus = 0; rpc_server_unregister_if (srvsvc_v3_0_s_ifspec, NULL, (unsigned32*)&tmpStatus); } DCETHREAD_CATCH_ALL(THIS_CATCH) DCETHREAD_ENDTRY; } *ppServerBinding = NULL; goto cleanup; }
void rpc_ss_rundown_client ( /* [in] */ rpc_client_handle_t failed_client ) { error_status_t result; callee_client_entry_t *this_client; callee_context_entry_t *this_context; rpc_client_handle_t close_client = NULL; /* NULL or client to stop monitoring */ /* FIXME: is the volatility set correctly here? */ rpc_ss_rundown_list_elt * volatile rundown_list; rpc_ss_rundown_list_elt * volatile rundown_elt; rundown_list = NULL; #ifdef PERFMON RPC_SS_RUNDOWN_CLIENT_N; #endif RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); for( this_client = &client_table[HASH_CLIENT_ID(failed_client)]; (this_client != NULL) && (close_client == NULL); this_client = this_client->next_h_client ) { if (this_client->client == failed_client) { while (this_client->ref_count != 0) { this_client->rundown_pending = idl_true; RPC_SS_THREADS_CONDITION_WAIT(&this_client->cond_var, &rpc_ss_context_table_mutex); /* Mutex has been released */ RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); } if (this_client->count == 0) { /* The manager closed the contexts while a rundown was pending */ rpc_ss_ctx_remove_client_entry(this_client); RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); #ifdef PERFMON RPC_SS_RUNDOWN_CLIENT_X; #endif return; } /* Need to clear the rundown pending flag so that the client entry can be deleted */ this_client->rundown_pending = idl_false; while (close_client == NULL) { /* Loop until all contexts for this client have been removed from the context table. Note that each iteration brings a different context to first_context position */ this_context = this_client->first_context; rundown_elt = (rpc_ss_rundown_list_elt *) malloc(sizeof(rpc_ss_rundown_list_elt)); if (rundown_elt == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); /* * rpc_m_ctxrundown_nomem * "Out of memory while trying to run down contexts of client %x" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%x"), rpc_svc_libidl, svc_c_sev_error, rpc_m_ctxrundown_nomem, this_client )); return; } rundown_elt->rundown = this_context->rundown; rundown_elt->user_context = this_context->user_context; rundown_elt->next = rundown_list; rundown_list = rundown_elt; rpc_ss_lkddest_callee_context (&this_context->uuid,&close_client,&result); } } } RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); while (rundown_list != NULL) { if (rundown_list->rundown != NULL) { DCETHREAD_TRY (*(rundown_list->rundown))(rundown_list->user_context); DCETHREAD_CATCH_ALL(caught) /* * rpc_m_ctxrundown_exc * "Exception in routine at %x, running down context %x of client %x" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%x%x%x"), rpc_svc_libidl, svc_c_sev_error, rpc_m_ctxrundown_exc, rundown_list->rundown, rundown_list->user_context, this_client )); DCETHREAD_ENDTRY } rundown_elt = rundown_list; rundown_list = rundown_list->next; free(rundown_elt); }
NET_API_STATUS NetShareGetInfo( const char * ServerName, const char * NetName, uint32_t Level, PSHARE_INFO * ShareInfo) { WCHAR * serverName = SMBConvertFromUTF8ToUTF16(ServerName, 1024, 0); WCHAR * netName = SMBConvertFromUTF8ToUTF16(NetName, 1024, 0); if (!serverName || !netName || !ShareInfo) { if (serverName) free(serverName); if (netName) free(netName); return ERROR_INVALID_PARAMETER; } rpc_binding binding = make_rpc_binding(ServerName, "srvsvc"); if (binding.get() == NULL) { SMBLogInfo("make_rpc_binding failed", ASL_LEVEL_DEBUG); if (serverName) { free(serverName); } if (netName) { free(netName); } return ERROR_INVALID_PARAMETER; } rpc_ss_allocator_t allocator; NET_API_STATUS api_status = NERR_Success; error_status_t rpc_status = rpc_s_ok; memset(&allocator, 0, sizeof(allocator)); std::pair<rpc_mempool *, SHARE_INFO *> result( allocate_rpc_mempool<SHARE_INFO>()); allocator.p_allocate = share_memalloc; allocator.p_free = share_memfree; allocator.p_context = (idl_void_p_t)result.first; rpc_ss_swap_client_alloc_free_ex(&allocator, &allocator); DCETHREAD_TRY api_status = NetrShareGetInfo( binding.get(), const_cast<WCHAR *>(serverName), const_cast<WCHAR *>(netName), Level, result.second, &rpc_status); DCETHREAD_CATCH_ALL(exc) /* * Unmarshalling a response with an unknown level will throw a * rpc_x_invalid_tag exception since the unknown level is not defined as * a union discriminator. */ rpc_status = rpc_exception_status(exc); DCETHREAD_ENDTRY free(serverName); free(netName); rpc_ss_swap_client_alloc_free_ex(&allocator, &allocator); if (rpc_status != rpc_s_ok) { SMBLogInfo("RPC to srvsrvc gave error %#08x", ASL_LEVEL_ERR, rpc_status); NetApiBufferFree(result.second); return RPC_S_PROTOCOL_ERROR; } if (api_status == NERR_Success) { *ShareInfo = result.second; } else { NetApiBufferFree(result.second); *ShareInfo = NULL; } return api_status; }
NET_API_STATUS NetShareEnum( const char * ServerName, uint32_t Level, PSHARE_ENUM_STRUCT * InfoStruct) { WCHAR * serverName = SMBConvertFromUTF8ToUTF16(ServerName, 1024, 0); if (!serverName || !InfoStruct) { if (serverName) free(serverName); return ERROR_INVALID_PARAMETER; } rpc_binding binding = make_rpc_binding(ServerName, "srvsvc"); if (binding.get() == NULL) { SMBLogInfo("make_rpc_binding failed", ASL_LEVEL_DEBUG); if (serverName) { free(serverName); } return ERROR_INVALID_PARAMETER; } rpc_ss_allocator_t allocator; NET_API_STATUS api_status = NERR_Success; error_status_t rpc_status = rpc_s_ok; memset(&allocator, 0, sizeof(allocator)); std::pair<rpc_mempool *, SHARE_ENUM_STRUCT *> result( allocate_rpc_mempool<SHARE_ENUM_STRUCT>()); DWORD entries = 0; DWORD resume = 0; allocator.p_allocate = share_memalloc; allocator.p_free = share_memfree; allocator.p_context = (idl_void_p_t)result.first; rpc_ss_swap_client_alloc_free_ex(&allocator, &allocator); result.second->Level = Level; /* * Windows requires a valid pointer for the ShareInfo union. It doesn't matter * which container type we choose here, since they all have the same binary * layout. */ result.second->ShareInfo.Level0 = (SHARE_INFO_0_CONTAINER *)result.first->alloc( sizeof(SHARE_INFO_0_CONTAINER)); result.second->ShareInfo.Level0->EntriesRead = 0; result.second->ShareInfo.Level0->Buffer = NULL; DCETHREAD_TRY api_status = NetrShareEnum( binding.get(), const_cast<WCHAR *>(serverName), result.second, 0xffffffff, &entries, &resume, &rpc_status); DCETHREAD_CATCH_ALL(exc) rpc_status = rpc_exception_status(exc); DCETHREAD_ENDTRY rpc_ss_swap_client_alloc_free_ex(&allocator, &allocator); free(serverName); if (rpc_status != rpc_s_ok) { SMBLogInfo("RPC to srvsrvc gave error %#08x", ASL_LEVEL_ERR, rpc_status); NetApiBufferFree(result.second); return RPC_S_PROTOCOL_ERROR; } if (api_status == NERR_Success) { *InfoStruct = result.second; } else { NetApiBufferFree(result.second); *InfoStruct = NULL; } return api_status; }