Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

401 lines
11 KiB

  1. #define DBG 1
  2. #include <nt.h>
  3. #include <ntrtl.h>
  4. #include <nturtl.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <memory.h>
  8. #include <malloc.h>
  9. #include <stdlib.h>
  10. #ifndef WIN32_LEAN_AND_MEAN
  11. #define WIN32_LEAN_AND_MEAN
  12. #endif
  13. #include <windows.h>
  14. #include <rpc.h>
  15. #include <midles.h>
  16. #include "smgr.h"
  17. #define RPC_CHAR WCHAR
  18. #define CHECK_STATUS(status, string) if (status) { \
  19. printf("%s failed - %d (%08x)\n", (string), (status), (status)); \
  20. exit(1); \
  21. } else printf("%s okay\n", (string));
  22. PVOID SystemHeap = NULL;
  23. extern "C" {
  24. void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t bytes)
  25. {
  26. return RtlAllocateHeap(SystemHeap, 0, bytes);
  27. }
  28. void __RPC_USER MIDL_user_free(void __RPC_FAR * p)
  29. {
  30. RtlFreeHeap(SystemHeap, 0, p);
  31. }
  32. }
  33. inline UString *AllocateUString(unsigned short *pString)
  34. {
  35. int nStringSize = wcslen(pString); // we don't do + 1, because the UString data structure
  36. // has one slot
  37. UString *pNewString;
  38. pNewString = (UString *)RtlAllocateHeap(SystemHeap, 0, sizeof(UString) + nStringSize * 2);
  39. if (pNewString)
  40. {
  41. pNewString->nlength = nStringSize + 1;
  42. wcscpy(&(pNewString->pString[0]), pString);
  43. }
  44. return pNewString;
  45. }
  46. inline UString *DuplicateUString(UString *pString)
  47. {
  48. if (pString)
  49. {
  50. // -1 because we have on slot in the structure
  51. int nMemSize = sizeof(UString) + (pString->nlength - 1) * 2;
  52. UString *pNewString;
  53. pNewString = (UString *)RtlAllocateHeap(SystemHeap, 0, nMemSize);
  54. memcpy(pNewString, pString, nMemSize);
  55. return pNewString;
  56. }
  57. else
  58. return NULL;
  59. }
  60. typedef enum tagSyncManagerState
  61. {
  62. smsRunning,
  63. smsDone,
  64. smsWaiting
  65. } SyncManagerState;
  66. FILE *fp;
  67. FILE *fpLogFile;
  68. long AvailableClients = 0;
  69. long NeededClients = 0;
  70. long RunningClients = 0;
  71. BOOL fServerAvailable = FALSE;
  72. SyncManagerCommands CurrentClientCommand = smcExec;
  73. SyncManagerCommands CurrentServerCommand = smcExec;
  74. UString *CurrentClientParam = NULL;
  75. UString *CurrentServerParam = NULL;
  76. SyncManagerState state = smsDone;
  77. CRITICAL_SECTION ActionLock;
  78. HANDLE GoEvent;
  79. int __cdecl main(int argc, char *argv[])
  80. {
  81. RPC_STATUS status;
  82. RPC_CHAR *string_binding;
  83. RPC_BINDING_VECTOR *pBindingVector;
  84. RPC_CHAR *Endpoint;
  85. SystemHeap = GetProcessHeap();
  86. if (argc != 2)
  87. {
  88. printf("Usage:\n\tsyncmgr script_file\n");
  89. return 2;
  90. }
  91. fp = fopen(argv[1], "rt");
  92. if (fp == NULL)
  93. {
  94. printf("Couldn't open file: %s\n", argv[1]);
  95. return 2;
  96. }
  97. fpLogFile = fopen("c:\\syncmgr.log", "wt");
  98. if (fpLogFile == NULL)
  99. {
  100. printf("Couldn't open log file: %s\n", "c:\\syncmgr.log");
  101. return 2;
  102. }
  103. InitializeCriticalSection(&ActionLock);
  104. GoEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  105. status = RpcServerUseProtseqW(L"ncacn_ip_tcp", 300, 0);
  106. CHECK_STATUS(status, "RpcServerUseProtseqW");
  107. status = RpcServerInqBindings(&pBindingVector);
  108. CHECK_STATUS(status, "RpcServerInqBindings");
  109. status = RpcEpRegister(_SyncManager_v1_0_s_ifspec,
  110. pBindingVector,
  111. 0,
  112. 0);
  113. CHECK_STATUS(status, "RpcEpRegister");
  114. status = RpcBindingToStringBindingW(pBindingVector->BindingH[0],
  115. &string_binding);
  116. CHECK_STATUS(status, "RpcBindingToStringBinding");
  117. status = RpcStringBindingParseW(string_binding,
  118. 0, 0, 0, &Endpoint, 0);
  119. CHECK_STATUS(status, "RpcStringBindingParse");
  120. printf("Listening to %S:[%S]\n\n", "ncacn_ip_tcp", Endpoint);
  121. status = RpcServerRegisterIf(_SyncManager_v1_0_s_ifspec,0,0);
  122. CHECK_STATUS(status, "RpcServerRegisterIf");
  123. printf("Server listening\n\n");
  124. status = RpcServerListen(3, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
  125. CHECK_STATUS(status, "RpcServerListen");
  126. return 0;
  127. }
  128. inline BOOL IsWhiteSpace(int c)
  129. {
  130. return ((c == '\n')
  131. || (c == '\t')
  132. || (c == ' '));
  133. }
  134. void _GetCommand(handle_t IDL_handle, int ClientOrServer, SyncManagerCommands __RPC_FAR *cmd,
  135. UString __RPC_FAR *__RPC_FAR *param)
  136. {
  137. RPC_CHAR NewCommand[400];
  138. RPC_CHAR *pPosition;
  139. RPC_CHAR *Clients;
  140. RPC_CHAR *ClientCmd;
  141. RPC_CHAR *SvrCmd;
  142. RPC_CHAR *Ignored;
  143. handle_t hClientHandle;
  144. RPC_STATUS RpcStatus;
  145. RPC_CHAR *StringBinding;
  146. DWORD WaitResult;
  147. RpcStatus = RpcBindingServerFromClient(IDL_handle, &hClientHandle);
  148. if (RpcStatus != RPC_S_OK)
  149. {
  150. printf("RpcBindingServerFromClient failed: %d\n", RpcStatus);
  151. *cmd = smcExit;
  152. *param = NULL;
  153. return;
  154. }
  155. RpcStatus = RpcBindingToStringBindingW(hClientHandle, &StringBinding);
  156. if (RpcStatus != RPC_S_OK)
  157. {
  158. printf("RpcBindingToStringBindingW failed: %d\n", RpcStatus);
  159. RpcBindingFree(&hClientHandle);
  160. *cmd = smcExit;
  161. *param = NULL;
  162. return;
  163. }
  164. RpcBindingFree(&hClientHandle);
  165. // if we came in the middle of a test, wait for it to finish
  166. while (TRUE)
  167. {
  168. EnterCriticalSection(&ActionLock);
  169. if (state != smsRunning)
  170. break;
  171. else
  172. {
  173. LeaveCriticalSection(&ActionLock);
  174. printf("%S came in the middle of a test - waiting for it to finish\n", StringBinding);
  175. Sleep(60000);
  176. }
  177. }
  178. // are we the first one after a run?
  179. if (state == smsDone)
  180. {
  181. printf("Client %S is reading next command\n", StringBinding);
  182. ResetEvent(GoEvent);
  183. RunningClients = 0;
  184. // free old arguments if any
  185. if (CurrentClientParam)
  186. {
  187. MIDL_user_free(CurrentClientParam);
  188. CurrentClientParam = NULL;
  189. }
  190. if (CurrentServerParam)
  191. {
  192. MIDL_user_free(CurrentServerParam);
  193. CurrentServerParam = NULL;
  194. }
  195. while (TRUE)
  196. {
  197. // get the new command line
  198. pPosition = fgetws(NewCommand, sizeof(NewCommand), fp);
  199. if (pPosition == NULL)
  200. {
  201. CurrentClientCommand = smcExit;
  202. CurrentServerCommand = smcExit;
  203. CurrentClientParam = NULL;
  204. CurrentServerParam = NULL;
  205. fprintf(fpLogFile, "End of file encountered\n");
  206. break;
  207. }
  208. else
  209. {
  210. // parse the command
  211. // first, trim spaces from the end
  212. pPosition = wcschr(NewCommand, '\0') - 1;
  213. while (IsWhiteSpace(*pPosition) && (pPosition > NewCommand))
  214. {
  215. *pPosition = 0;
  216. pPosition --;
  217. }
  218. // was anything left?
  219. if (pPosition == NewCommand)
  220. continue;
  221. // is this a comment line?
  222. if (NewCommand[0] == ';')
  223. continue;
  224. // real line - should have the format #,srv_cmd,clnt_cmd
  225. pPosition = wcschr(NewCommand, ',');
  226. *pPosition = '\0';
  227. Clients = NewCommand;
  228. pPosition ++;
  229. SvrCmd = pPosition;
  230. pPosition = wcschr(pPosition, ',');
  231. *pPosition = '\0';
  232. ClientCmd = pPosition + 1;
  233. NeededClients = wcstol(Clients, &Ignored, 10);
  234. CurrentServerParam = AllocateUString(SvrCmd);
  235. CurrentClientParam = AllocateUString(ClientCmd);
  236. break;
  237. }
  238. }
  239. state = smsWaiting;
  240. }
  241. if (CurrentClientCommand == smcExit)
  242. {
  243. printf("Client %S is getting exit command\n", StringBinding);
  244. if (ClientOrServer)
  245. {
  246. *cmd = CurrentClientCommand;
  247. *param = DuplicateUString(CurrentClientParam);
  248. LeaveCriticalSection(&ActionLock);
  249. goto CleanupAndExit;
  250. }
  251. else
  252. {
  253. *cmd = CurrentServerCommand;
  254. *param = DuplicateUString(CurrentServerParam);
  255. LeaveCriticalSection(&ActionLock);
  256. goto CleanupAndExit;
  257. }
  258. }
  259. if (ClientOrServer)
  260. {
  261. AvailableClients ++;
  262. printf("Client %S has increased the number of available clients to %d (%d needed)\n",
  263. StringBinding, AvailableClients, NeededClients);
  264. }
  265. else
  266. {
  267. fServerAvailable = TRUE;
  268. printf("Server %S has become available\n", StringBinding);
  269. }
  270. // we have everybody for this test - kick it off
  271. if ((AvailableClients >= NeededClients) && fServerAvailable)
  272. {
  273. printf("Client %S is kicking off tests\n", StringBinding);
  274. *cmd = smcExec;
  275. if (ClientOrServer)
  276. {
  277. AvailableClients --;
  278. RunningClients = 1;
  279. *param = DuplicateUString(CurrentClientParam);
  280. }
  281. else
  282. {
  283. fServerAvailable = FALSE;
  284. *param = DuplicateUString(CurrentServerParam);
  285. }
  286. state = smsRunning;
  287. LeaveCriticalSection(&ActionLock);
  288. SetEvent(GoEvent);
  289. // if we were client, create artificial delay for server to start
  290. if (ClientOrServer)
  291. Sleep(40000);
  292. printf("Client %S kicked off test and returns\n", StringBinding);
  293. goto CleanupAndExit;
  294. }
  295. else
  296. {
  297. // we don't have enough clients or the server is not there yet
  298. LeaveCriticalSection(&ActionLock);
  299. printf("Client %S starts waiting .... Tid is 0x%x\n", StringBinding, GetCurrentThreadId());
  300. }
  301. do
  302. {
  303. WaitResult = WaitForSingleObject(GoEvent, 600000);
  304. if (WaitResult == WAIT_TIMEOUT)
  305. {
  306. printf("Client %S is still waiting for GoEvent ...\n", StringBinding);
  307. }
  308. }
  309. while (WaitResult != WAIT_OBJECT_0);
  310. EnterCriticalSection(&ActionLock);
  311. if (ClientOrServer)
  312. AvailableClients --;
  313. else
  314. fServerAvailable = FALSE;
  315. if ((AvailableClients == 0) && (fServerAvailable == FALSE))
  316. state = smsDone;
  317. // if we are client and were left out don't do anything
  318. if (ClientOrServer && ((RunningClients + 1) > NeededClients))
  319. {
  320. printf("Client %S was left out and returns. Available: %d\n", StringBinding, AvailableClients);
  321. *param = NULL;
  322. *cmd = smcNOP;
  323. }
  324. else
  325. {
  326. printf("Client %S picked a command and returns\n", StringBinding);
  327. if (ClientOrServer)
  328. RunningClients ++;
  329. *cmd = smcExec;
  330. if (ClientOrServer)
  331. *param = DuplicateUString(CurrentClientParam);
  332. else
  333. *param = DuplicateUString(CurrentServerParam);
  334. }
  335. LeaveCriticalSection(&ActionLock);
  336. // if we were a client, create a 15 second artificial delay, giving the
  337. // server a chance to start - this saves us some more sync-ing
  338. if ((*cmd == smcExec) && ClientOrServer)
  339. Sleep(15000);
  340. CleanupAndExit:
  341. RpcStringFreeW(&StringBinding);
  342. }