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-server.h"
16 #include "shared_globals.h"
17 #include "ntservice.h"
21 #if __amd64 || defined(_M_AMD64) // 64-bit
27 #include "KMSServer_s2_x64_mingw_gcc.c"
31 #include "KMSServer_s2_mingw_gcc.c"
36 #if !defined(NO_LIMIT)
37 #define MAXCALLS MaxTasks
38 #else // defined(NO_LIMIT)
39 #define MAXCALLS RPC_C_LISTEN_MAX_CALLS_DEFAULT
46 * This is the main run loop for the KMS server
47 * We actually just setup things (must be after Cygwin fork) and then sleep
51 # if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
53 // The RPC setup survives a Cygwin exec without problems but no daemonizing
54 // SIGHUP is currently disabled for Cygwin. So this code should never compile
59 logger("vlmcsd %s started successfully\n", Version
);
63 # endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
67 // Endpoint is actually a TCP port for "ncacn_ip_tcp"
68 status
= RpcServerUseProtseqEpA
70 (RPC_CSTR
)"ncacn_ip_tcp",
71 RPC_C_PROTSEQ_MAX_REQS_DEFAULT
,
72 (RPC_CSTR
)defaultport
,
78 printerrorf("Fatal: Cannot bind to port %s: %s\n", defaultport
, win_strerror(status
));
83 logger("Listening on port %s\n", defaultport
);
86 // Registers the KMSServer interface.
87 status
= RpcServerRegisterIf2
89 KMSServer_v1_0_s_ifspec
,
92 RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH
| RPC_IF_AUTOLISTEN
,
94 MAX_RESPONSE_SIZE
, // currently set to sizeof(RESPONSE_V6)
100 printerrorf("Fatal: Cannot register RPC interface: %s\n", win_strerror(status
));
105 logger("vlmcsd %s started successfully\n", Version
);
108 if (IsNTService
) ReportServiceStatus(SERVICE_RUNNING
, NO_ERROR
, 200);
111 // We could run RpcServerListen here but we need something
112 // that can be signaled from Cygwin. So we just sleep 24h (POSIX sleep, no Windows Sleep),
113 // wake up for some nanoseconds and sleep again.
115 while(TRUE
) sleep(86400); // Sleep one day
121 * Get's the IP address from an RPC_BINDING_HANDLE. Caller must call RpcStringFreeA to
122 * release memory allocated in *ipAddress
125 RPC_STATUS
getClientIp(const RPC_BINDING_HANDLE clientBinding
, RPC_CSTR
*ipAddress
)
128 RPC_CSTR stringBinding
;
129 RPC_BINDING_HANDLE serverBinding
;
131 // Fix for wine (disabled by default, because vlmcsd runs natively on all platforms where wine runs)
132 // Feel free to #define SUPPORT_WINE if you really want to run the Windows version with MS RPC (Wine RPC in this case)
134 HMODULE h
= GetModuleHandleA("kernel32.dll");
138 // Since wine simply terminates the thread when RpcBindingServerFromClient is called, we exit with an error
139 if (GetProcAddress(h
, "wine_get_unix_file_name")) return RPC_S_CANNOT_SUPPORT
;
141 #endif // SUPPORT_WINE
143 if ((result
= RpcBindingServerFromClient(clientBinding
, &serverBinding
)) != RPC_S_OK
) return result
;
145 if ((result
= RpcBindingToStringBindingA(serverBinding
, &stringBinding
)) != RPC_S_OK
)
147 RpcBindingFree(&serverBinding
);
151 result
= RpcStringBindingParseA(stringBinding
, NULL
, NULL
, ipAddress
, NULL
, NULL
);
152 RpcStringFreeA(&stringBinding
);
153 RpcBindingFree(&serverBinding
);
162 * This is the callback function for the RPC request as defined in KMSServer.idl
163 * Output from the MIDL compiler has been modified manually to support gcc (and compatible compilers)
164 * as well as Cygwin and MingW-w64 toolchains.
166 int ProcessActivationRequest(handle_t IDL_handle
, int requestSize
, unsigned char *request
, int *responseSize
, unsigned char **response
)
168 RPC_CSTR clientIpAddress
;
170 int status
= RPC_S_OK
;
172 result
= getClientIp(IDL_handle
, &clientIpAddress
);
176 logger("RPC connection accepted: %s\n", !result
? (const char*)clientIpAddress
: "Unknown IP");
180 // Discard any packet smaller than a v4 request
181 if (requestSize
< (int)sizeof(REQUEST_V4
))
183 if (!result
) RpcStringFreeA(&clientIpAddress
);
184 return RPC_S_CANNOT_SUPPORT
;
187 *response
= (uint8_t *)midl_user_allocate(MAX_RESPONSE_SIZE
);
189 switch(LE16(((REQUEST
*)(request
))->MajorVer
))
192 *responseSize
= CreateResponseV4((REQUEST_V4
*)request
, *response
, (char*)clientIpAddress
);
196 *responseSize
= CreateResponseV6((REQUEST_V6
*) request
, *response
, (char*)clientIpAddress
);
199 status
= RPC_S_INVALID_ARG
;
203 if (!result
) RpcStringFreeA(&clientIpAddress
);
208 // Memory allocation function for RPC.
209 void *__RPC_USER
midl_user_allocate(SIZE_T len
)
211 return vlmcsd_malloc(len
);
215 // Memory deallocation function for RPC.
216 void __RPC_USER
midl_user_free(void __RPC_FAR
*ptr
)