msrpc-client.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #ifndef CONFIG
  2. #define CONFIG "config.h"
  3. #endif // CONFIG
  4. #include CONFIG
  5. #ifdef USE_MSRPC
  6. #if !defined(_WIN32) && !defined(__CYGWIN__)
  7. #error MSRPC is only available with native Windows or Cygwin
  8. #endif
  9. #include "msrpc-client.h"
  10. #include <stdio.h>
  11. #include "output.h"
  12. #include "helpers.h"
  13. #if __amd64 || defined(_M_AMD64) // 64-bit
  14. #ifndef _M_AMD64
  15. #define _M_AMD64
  16. #endif // _M_AMD64
  17. #include "KMSServer_c_x64_mingw_gcc.c"
  18. #else // 32-bit
  19. #include "KMSServer_c_mingw_gcc.c"
  20. #endif // 32-bit
  21. static RPC_CSTR stringBinding;
  22. jmp_buf jmp;
  23. RPC_STATUS PreviousRpcCallFailed = RPC_S_OK;
  24. /*
  25. * Creates an RPC string binding that is used to connect to the server.
  26. * Input is host:port, e.g. "[::1]:1688" or "127.0.0.1:1688"
  27. * Output is for example "ncacn_ip_tcp:127.0.0.1[endpoint=1688]"
  28. */
  29. #if !__amd64
  30. #pragma GCC optimize("O0") ////TODO: Find out why gcc needs -O0 for RPC handling
  31. #endif
  32. static RPC_STATUS createStringBinding(char *const addr, RPC_CSTR* stringBinding)
  33. {
  34. char *szHost, *szPort;
  35. parseAddress(addr, &szHost, &szPort);
  36. return RpcStringBindingComposeA
  37. (
  38. NULL, /* UUID */
  39. (RPC_CSTR)"ncacn_ip_tcp", /* use TCP */
  40. (RPC_CSTR)szHost, /* host name or IP address */
  41. (RPC_CSTR)szPort, /* endpoint (TCP port here) */
  42. NULL, /* options */
  43. stringBinding /* resulting string binding */
  44. );
  45. }
  46. /*
  47. * This does not actually connect to a TCP port because MS RPC doesn't connect
  48. * before the actual RPC call is made. So this a stub
  49. */
  50. RpcCtx connectToAddress(char *const addr, const int AddressFamily_unused, int_fast8_t showHostName_unused)
  51. {
  52. RPC_STATUS status;
  53. printf("Connecting to %s ... ", addr);
  54. if ((status = createStringBinding(addr, &stringBinding)) != RPC_S_OK)
  55. {
  56. errorout("%s\n", win_strerror(status));
  57. return !0;
  58. }
  59. if (PreviousRpcCallFailed)
  60. {
  61. errorout("%s\n", win_strerror(PreviousRpcCallFailed));
  62. return !0;
  63. }
  64. printf("successful\n");
  65. return 0;
  66. }
  67. /*
  68. * Does not do RPC binding on the wire. Just initializes the interface
  69. */
  70. RpcStatus rpcBindClient(const RpcCtx handle, const int_fast8_t verbose)
  71. {
  72. RPC_STATUS status;
  73. if ((status = RpcBindingFromStringBindingA(stringBinding, &KMSServer_v1_0_c_ifspec)) != RPC_S_OK)
  74. {
  75. errorout("\n%s\n", win_strerror(status));
  76. }
  77. return status;
  78. }
  79. /*
  80. * You never know if you have a TCP connection or not
  81. * This returns true if the previous RPC call failed
  82. */
  83. int_fast8_t isDisconnected(const RpcCtx handle)
  84. {
  85. return PreviousRpcCallFailed;
  86. }
  87. /*
  88. * This is the exception handler because the RPC call may
  89. * throw an SEH exception and gcc does not support
  90. * __try / __except as MSVC does.
  91. */
  92. static LONG WINAPI rpcException (LPEXCEPTION_POINTERS exception_pointers)
  93. {
  94. DWORD exception = exception_pointers->ExceptionRecord->ExceptionCode;
  95. if (!exception) exception = (DWORD)~0;
  96. longjmp(jmp, exception_pointers->ExceptionRecord->ExceptionCode);
  97. return EXCEPTION_EXECUTE_HANDLER;
  98. }
  99. /*
  100. * This actually calls the RPC server
  101. */
  102. #define try SetUnhandledExceptionFilter(rpcException); RPC_STATUS exception = setjmp(jmp); if (!exception)
  103. #define catch else
  104. RpcStatus rpcSendRequest(const RpcCtx handle, BYTE* KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t* responseSize)
  105. {
  106. *KmsResponse = NULL; // Let midl_user_allocate do the job
  107. try
  108. {
  109. exception = RequestActivation(KMSServer_v1_0_c_ifspec, (int)requestSize, KmsRequest, (int*)responseSize, KmsResponse);
  110. }
  111. catch
  112. {
  113. errorout("\n%s", win_strerror(exception));
  114. }
  115. PreviousRpcCallFailed = exception;
  116. SetUnhandledExceptionFilter(NULL);
  117. return exception;
  118. }
  119. #undef catch
  120. #undef try
  121. /*
  122. * Only frees local handles. Cannot close the TCP connection
  123. */
  124. RpcStatus closeRpc(const RpcCtx handle)
  125. {
  126. RPC_STATUS status;
  127. if ((status = RpcBindingFree(&KMSServer_v1_0_c_ifspec)) != RPC_S_OK) return status;
  128. status = RpcStringFreeA(&stringBinding);
  129. //Ctx = INVALID_RPCCTX;
  130. return status;
  131. }
  132. #if !MULTI_CALL_BINARY
  133. // Memory allocation function for RPC.
  134. void *__RPC_USER midl_user_allocate(SIZE_T len)
  135. {
  136. return vlmcsd_malloc(len);
  137. }
  138. // Memory deallocation function for RPC.
  139. void __RPC_USER midl_user_free(void __RPC_FAR *ptr)
  140. {
  141. if (ptr) free(ptr);
  142. ptr = NULL;
  143. }
  144. #endif // !MULTI_CALL_BINARY
  145. #endif // USE_MSRPC