2 #define CONFIG "config.h"
8 #if !defined(_WIN32) && !defined(__CYGWIN__)
9 #error MSRPC is only available with native Windows or Cygwin
12 #include "msrpc-client.h"
17 #if __amd64 || defined(_M_AMD64) // 64-bit
23 #include "KMSServer_c_x64_mingw_gcc.c"
27 #include "KMSServer_c_mingw_gcc.c"
31 static RPC_CSTR stringBinding
;
33 RPC_STATUS PreviousRpcCallFailed
= RPC_S_OK
;
37 * Creates an RPC string binding that is used to connect to the server.
38 * Input is host:port, e.g. "[::1]:1688" or "127.0.0.1:1688"
39 * Output is for example "ncacn_ip_tcp:127.0.0.1[endpoint=1688]"
42 #pragma GCC optimize("O0") ////TODO: Find out why gcc needs -O0 for RPC handling
45 static RPC_STATUS
createStringBinding(char *const addr
, RPC_CSTR
* stringBinding
)
47 char *szHost
, *szPort
;
49 parseAddress(addr
, &szHost
, &szPort
);
51 return RpcStringBindingComposeA
54 (RPC_CSTR
)"ncacn_ip_tcp", /* use TCP */
55 (RPC_CSTR
)szHost
, /* host name or IP address */
56 (RPC_CSTR
)szPort
, /* endpoint (TCP port here) */
58 stringBinding
/* resulting string binding */
64 * This does not actually connect to a TCP port because MS RPC doesn't connect
65 * before the actual RPC call is made. So this a stub
67 RpcCtx
connectToAddress(char *const addr
, const int AddressFamily_unused
, int_fast8_t showHostName_unused
)
71 printf("Connecting to %s ... ", addr
);
73 if ((status
= createStringBinding(addr
, &stringBinding
)) != RPC_S_OK
)
75 errorout("%s\n", win_strerror(status
));
79 if (PreviousRpcCallFailed
)
81 errorout("%s\n", win_strerror(PreviousRpcCallFailed
));
85 printf("successful\n");
91 * Does not do RPC binding on the wire. Just initializes the interface
93 RpcStatus
rpcBindClient(const RpcCtx handle
, const int_fast8_t verbose
)
97 if ((status
= RpcBindingFromStringBindingA(stringBinding
, &KMSServer_v1_0_c_ifspec
)) != RPC_S_OK
)
99 errorout("\n%s\n", win_strerror(status
));
107 * You never know if you have a TCP connection or not
108 * This returns true if the previous RPC call failed
110 int_fast8_t isDisconnected(const RpcCtx handle
)
112 return PreviousRpcCallFailed
;
117 * This is the exception handler because the RPC call may
118 * throw an SEH exception and gcc does not support
119 * __try / __except as MSVC does.
121 static LONG WINAPI
rpcException (LPEXCEPTION_POINTERS exception_pointers
)
123 DWORD exception
= exception_pointers
->ExceptionRecord
->ExceptionCode
;
124 if (!exception
) exception
= (DWORD
)~0;
125 longjmp(jmp
, exception_pointers
->ExceptionRecord
->ExceptionCode
);
126 return EXCEPTION_EXECUTE_HANDLER
;
130 * This actually calls the RPC server
132 #define try SetUnhandledExceptionFilter(rpcException); RPC_STATUS exception = setjmp(jmp); if (!exception)
134 RpcStatus
rpcSendRequest(const RpcCtx handle
, BYTE
* KmsRequest
, const size_t requestSize
, BYTE
**KmsResponse
, size_t* responseSize
)
136 *KmsResponse
= NULL
; // Let midl_user_allocate do the job
140 exception
= RequestActivation(KMSServer_v1_0_c_ifspec
, (int)requestSize
, KmsRequest
, (int*)responseSize
, KmsResponse
);
144 errorout("\n%s", win_strerror(exception
));
147 PreviousRpcCallFailed
= exception
;
148 SetUnhandledExceptionFilter(NULL
);
158 * Only frees local handles. Cannot close the TCP connection
160 RpcStatus
closeRpc(const RpcCtx handle
)
164 if ((status
= RpcBindingFree(&KMSServer_v1_0_c_ifspec
)) != RPC_S_OK
) return status
;
165 status
= RpcStringFreeA(&stringBinding
);
166 //Ctx = INVALID_RPCCTX;
171 #if !MULTI_CALL_BINARY
172 // Memory allocation function for RPC.
173 void *__RPC_USER
midl_user_allocate(SIZE_T len
)
175 return vlmcsd_malloc(len
);
179 // Memory deallocation function for RPC.
180 void __RPC_USER
midl_user_free(void __RPC_FAR
*ptr
)
186 #endif // !MULTI_CALL_BINARY