#ifndef CONFIG #define CONFIG "config.h" #endif // CONFIG #include CONFIG #ifdef USE_MSRPC #if !defined(_WIN32) && !defined(__CYGWIN__) #error MSRPC is only available with native Windows or Cygwin #endif #include "msrpc-client.h" #include #include "output.h" #include "helpers.h" #if __amd64 || defined(_M_AMD64) // 64-bit #ifndef _M_AMD64 #define _M_AMD64 #endif // _M_AMD64 #include "KMSServer_c_x64_mingw_gcc.c" #else // 32-bit #include "KMSServer_c_mingw_gcc.c" #endif // 32-bit static RPC_CSTR stringBinding; jmp_buf jmp; RPC_STATUS PreviousRpcCallFailed = RPC_S_OK; /* * Creates an RPC string binding that is used to connect to the server. * Input is host:port, e.g. "[::1]:1688" or "127.0.0.1:1688" * Output is for example "ncacn_ip_tcp:127.0.0.1[endpoint=1688]" */ #if !__amd64 #pragma GCC optimize("O0") ////TODO: Find out why gcc needs -O0 for RPC handling #endif static RPC_STATUS createStringBinding(char *const addr, RPC_CSTR* stringBinding) { char *szHost, *szPort; parseAddress(addr, &szHost, &szPort); return RpcStringBindingComposeA ( NULL, /* UUID */ (RPC_CSTR)"ncacn_ip_tcp", /* use TCP */ (RPC_CSTR)szHost, /* host name or IP address */ (RPC_CSTR)szPort, /* endpoint (TCP port here) */ NULL, /* options */ stringBinding /* resulting string binding */ ); } /* * This does not actually connect to a TCP port because MS RPC doesn't connect * before the actual RPC call is made. So this a stub */ RpcCtx connectToAddress(char *const addr, const int AddressFamily_unused, int_fast8_t showHostName_unused) { RPC_STATUS status; printf("Connecting to %s ... ", addr); if ((status = createStringBinding(addr, &stringBinding)) != RPC_S_OK) { errorout("%s\n", win_strerror(status)); return !0; } if (PreviousRpcCallFailed) { errorout("%s\n", win_strerror(PreviousRpcCallFailed)); return !0; } printf("successful\n"); return 0; } /* * Does not do RPC binding on the wire. Just initializes the interface */ RpcStatus rpcBindClient(const RpcCtx handle, const int_fast8_t verbose) { RPC_STATUS status; if ((status = RpcBindingFromStringBindingA(stringBinding, &KMSServer_v1_0_c_ifspec)) != RPC_S_OK) { errorout("\n%s\n", win_strerror(status)); } return status; } /* * You never know if you have a TCP connection or not * This returns true if the previous RPC call failed */ int_fast8_t isDisconnected(const RpcCtx handle) { return PreviousRpcCallFailed; } /* * This is the exception handler because the RPC call may * throw an SEH exception and gcc does not support * __try / __except as MSVC does. */ static LONG WINAPI rpcException (LPEXCEPTION_POINTERS exception_pointers) { DWORD exception = exception_pointers->ExceptionRecord->ExceptionCode; if (!exception) exception = (DWORD)~0; longjmp(jmp, exception_pointers->ExceptionRecord->ExceptionCode); return EXCEPTION_EXECUTE_HANDLER; } /* * This actually calls the RPC server */ #define try SetUnhandledExceptionFilter(rpcException); RPC_STATUS exception = setjmp(jmp); if (!exception) #define catch else RpcStatus rpcSendRequest(const RpcCtx handle, BYTE* KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t* responseSize) { *KmsResponse = NULL; // Let midl_user_allocate do the job try { exception = RequestActivation(KMSServer_v1_0_c_ifspec, (int)requestSize, KmsRequest, (int*)responseSize, KmsResponse); } catch { errorout("\n%s", win_strerror(exception)); } PreviousRpcCallFailed = exception; SetUnhandledExceptionFilter(NULL); return exception; } #undef catch #undef try /* * Only frees local handles. Cannot close the TCP connection */ RpcStatus closeRpc(const RpcCtx handle) { RPC_STATUS status; if ((status = RpcBindingFree(&KMSServer_v1_0_c_ifspec)) != RPC_S_OK) return status; status = RpcStringFreeA(&stringBinding); //Ctx = INVALID_RPCCTX; return status; } #if !MULTI_CALL_BINARY // Memory allocation function for RPC. void *__RPC_USER midl_user_allocate(SIZE_T len) { return vlmcsd_malloc(len); } // Memory deallocation function for RPC. void __RPC_USER midl_user_free(void __RPC_FAR *ptr) { if (ptr) free(ptr); ptr = NULL; } #endif // !MULTI_CALL_BINARY #endif // USE_MSRPC