msrpc-client.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. printerrorf("%s\n", win_strerror(status));
  57. return !0;
  58. }
  59. if (PreviousRpcCallFailed)
  60. {
  61. printerrorf("%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, PRpcDiag_t rpcDiag)
  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. rpcDiag->HasRpcDiag = FALSE;
  78. return status;
  79. }
  80. /*
  81. * You never know if you have a TCP connection or not
  82. * This returns true if the previous RPC call failed
  83. */
  84. int_fast8_t isDisconnected(const RpcCtx handle)
  85. {
  86. return PreviousRpcCallFailed;
  87. }
  88. /*
  89. * This is the exception handler because the RPC call may
  90. * throw an SEH exception and gcc does not support
  91. * __try / __except as MSVC does.
  92. */
  93. static LONG WINAPI rpcException (LPEXCEPTION_POINTERS exception_pointers)
  94. {
  95. DWORD exception = exception_pointers->ExceptionRecord->ExceptionCode;
  96. if (!exception) exception = (DWORD)~0;
  97. longjmp(jmp, exception_pointers->ExceptionRecord->ExceptionCode);
  98. return EXCEPTION_EXECUTE_HANDLER;
  99. }
  100. /*
  101. * This actually calls the RPC server
  102. */
  103. #define try SetUnhandledExceptionFilter(rpcException); RPC_STATUS exception = setjmp(jmp); if (!exception)
  104. #define catch else
  105. RpcStatus rpcSendRequest(const RpcCtx handle, BYTE* KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t* responseSize)
  106. {
  107. *KmsResponse = NULL; // Let midl_user_allocate do the job
  108. try
  109. {
  110. exception = RequestActivation(KMSServer_v1_0_c_ifspec, (int)requestSize, KmsRequest, (int*)responseSize, KmsResponse);
  111. }
  112. catch
  113. {
  114. errorout("\n%s", win_strerror(exception));
  115. }
  116. PreviousRpcCallFailed = exception;
  117. SetUnhandledExceptionFilter(NULL);
  118. return exception;
  119. }
  120. #undef catch
  121. #undef try
  122. /*
  123. * Only frees local handles. Cannot close the TCP connection
  124. */
  125. RpcStatus closeRpc(const RpcCtx handle)
  126. {
  127. RPC_STATUS status;
  128. if ((status = RpcBindingFree(&KMSServer_v1_0_c_ifspec)) != RPC_S_OK) return status;
  129. status = RpcStringFreeA(&stringBinding);
  130. //Ctx = INVALID_RPCCTX;
  131. return status;
  132. }
  133. #if !MULTI_CALL_BINARY
  134. // Memory allocation function for RPC.
  135. void *__RPC_USER midl_user_allocate(size_t len)
  136. {
  137. return vlmcsd_malloc(len);
  138. }
  139. // Memory deallocation function for RPC.
  140. void __RPC_USER midl_user_free(void __RPC_FAR *ptr)
  141. {
  142. if (ptr) free(ptr);
  143. ptr = NULL;
  144. }
  145. #endif // !MULTI_CALL_BINARY
  146. #endif // USE_MSRPC