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.

504 lines
13 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. server.c
  5. Abstract:
  6. This module contains the server code for dealing with clients.
  7. Author:
  8. Michael Tsang (MikeTs) 02-May-2000
  9. Environment:
  10. User mode
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. /*++
  15. @doc INTERNAL
  16. @func VOID | ServerThread | Server thread procedure.
  17. @parm IN PVOID | pv | (Not Used).
  18. @rvalue None.
  19. --*/
  20. VOID __cdecl
  21. ServerThread(
  22. IN PVOID pv
  23. )
  24. {
  25. TRTRACEPROC("ServerThread", 1)
  26. RPC_STATUS status;
  27. RPC_BINDING_VECTOR *BindingVector = NULL;
  28. TRENTER(("(pv=%p)\n", pv));
  29. if ((status = RpcServerUseProtseq("ncalrpc",
  30. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  31. // "\\pipe\\tracer",
  32. NULL)) != RPC_S_OK)
  33. {
  34. TRERRPRINT(("RpcServerUseProtseq failed (status=%d)\n", status));
  35. }
  36. else if ((status = RpcServerRegisterIf(WTServer_v1_0_s_ifspec, NULL, NULL))
  37. != RPC_S_OK)
  38. {
  39. TRERRPRINT(("RpcServerRegisterIf failed (status=%d)\n", status));
  40. }
  41. else if ((status = RpcServerInqBindings(&BindingVector)) != RPC_S_OK)
  42. {
  43. TRERRPRINT(("RpcServerInqBindings failed (status=%d)\n", status));
  44. }
  45. else if ((status = RpcEpRegister(WTServer_v1_0_s_ifspec,
  46. BindingVector,
  47. NULL,
  48. NULL)) != RPC_S_OK)
  49. {
  50. RpcBindingVectorFree(&BindingVector);
  51. TRERRPRINT(("RpcEpRegister failed (status=%d)\n", status));
  52. }
  53. else if ((status = RpcServerRegisterAuthInfo(NULL,
  54. RPC_C_AUTHN_WINNT,
  55. NULL,
  56. NULL)) != RPC_S_OK)
  57. {
  58. RpcEpUnregister(WTServer_v1_0_s_ifspec, BindingVector, NULL);
  59. RpcBindingVectorFree(&BindingVector);
  60. TRERRPRINT(("RpcServerRegisterAuthInfo failed (status=%d)\n", status));
  61. }
  62. else
  63. {
  64. status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
  65. TRASSERT(status == RPC_S_OK);
  66. RpcEpUnregister(WTServer_v1_0_s_ifspec, BindingVector, NULL);
  67. RpcBindingVectorFree(&BindingVector);
  68. }
  69. _endthread();
  70. TREXIT(("!\n"));
  71. return;
  72. } //ServerThread
  73. /*++
  74. @doc EXTERNAL
  75. @func HCLIENT | WTRegisterClient | Register a new client.
  76. @parm IN handle_t | hBinding | RPC binding handle.
  77. @parm IN unsigned char * | pszClientName |
  78. Points to the client name string.
  79. @rvalue SUCCESS | Returns new client handle.
  80. @rvalue FAILURE | Returns NULL.
  81. --*/
  82. HCLIENT
  83. WTRegisterClient(
  84. IN handle_t hBinding,
  85. IN unsigned char *pszClientName
  86. )
  87. {
  88. TRTRACEPROC("WTRegisterClient", 1)
  89. PCLIENT_ENTRY ClientEntry;
  90. TRENTER(("(hBinding=%p,ClientName=%s)\n", hBinding, pszClientName));
  91. ClientEntry = (PCLIENT_ENTRY)malloc(sizeof(CLIENT_ENTRY));
  92. if (ClientEntry != NULL)
  93. {
  94. memset(ClientEntry, 0, sizeof(*ClientEntry));
  95. lstrcpynA(ClientEntry->szClientName,
  96. pszClientName,
  97. sizeof(ClientEntry->szClientName));
  98. InsertTailList(&glistClients, &ClientEntry->list);
  99. WTGetClientInfo(&ClientEntry->ClientInfo);
  100. if ((ClientEntry->ClientInfo.Settings.iVerboseLevel +
  101. ClientEntry->ClientInfo.Settings.iTraceLevel +
  102. ClientEntry->ClientInfo.Settings.dwfSettings == 0) &&
  103. (gDefGlobalSettings.iVerboseLevel +
  104. gDefGlobalSettings.iTraceLevel +
  105. gDefGlobalSettings.dwfSettings != 0))
  106. {
  107. ClientEntry->ClientInfo.Settings = gDefGlobalSettings;
  108. WTSetClientInfo(&ClientEntry->ClientInfo);
  109. }
  110. if (ghwndPropSheet != NULL)
  111. {
  112. PROPSHEETPAGEA psp;
  113. HPROPSHEETPAGE hpsp;
  114. psp.dwSize = sizeof(psp);
  115. psp.dwFlags = PSP_USETITLE;
  116. psp.hInstance = ghInstance;
  117. psp.pszTitle = ClientEntry->szClientName;
  118. psp.lParam = (LPARAM)ClientEntry;
  119. psp.pszTemplate = (LPSTR)MAKEINTRESOURCE(IDD_CLIENTSETTINGS);
  120. psp.pfnDlgProc = ClientSettingsDlgProc;
  121. hpsp = CreatePropertySheetPageA(&psp);
  122. ClientEntry->hPage = hpsp;
  123. PropSheet_AddPage(ghwndPropSheet, hpsp);
  124. }
  125. }
  126. else
  127. {
  128. TRERRPRINT(("failed to allocate client entry for %s\n", pszClientName));
  129. }
  130. TREXIT(("=%p\n", ClientEntry));
  131. return (HCLIENT)ClientEntry;
  132. } //WTRegisterClient
  133. /*++
  134. @doc EXTERNAL
  135. @func VOID | WTDeregisterClient | Deregister a client.
  136. @parm IN handle_t | hBinding | RPC binding handle.
  137. @parm IN HCLIENT | hClient | Client handle.
  138. @rvalue None.
  139. --*/
  140. VOID
  141. WTDeregisterClient(
  142. IN handle_t hBinding,
  143. IN HCLIENT hClient
  144. )
  145. {
  146. TRTRACEPROC("WTDeregisterClient", 1)
  147. PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient;
  148. TRENTER(("(hBinding=%p,hClient=%p)\n", hBinding, hClient));
  149. RemoveEntryList(&ClientEntry->list);
  150. if (ghwndPropSheet != NULL)
  151. {
  152. PropSheet_RemovePage(ghwndPropSheet, 0, ClientEntry->hPage);
  153. }
  154. SendServerRequest(ClientEntry, SRVREQ_TERMINATE, NULL);
  155. free(ClientEntry);
  156. TREXIT(("!\n"));
  157. return;
  158. } //WTDeregisterClient
  159. /*++
  160. @doc EXTERNAL
  161. @func VOID | WTTraceProc | Print the TraceProc text.
  162. @parm IN handle_t | hBinding | RPC binding handle.
  163. @parm IN HCLIENT | hClient | Client handle.
  164. @parm IN DWORD | dwThreadId | Thread ID.
  165. @parm IN int | iIndentLevel | Specifies the level of indentation.
  166. @parm IN unsigned char * | pszText | Points to the TraceProc text.
  167. @rvalue None.
  168. --*/
  169. VOID
  170. WTTraceProc(
  171. IN handle_t hBinding,
  172. IN HCLIENT hClient,
  173. IN DWORD dwThreadId,
  174. IN int iIndentLevel,
  175. IN unsigned char *pszText
  176. )
  177. {
  178. TRTRACEPROC("WTTraceProc", 1)
  179. PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient;
  180. static char szText[1024];
  181. int i;
  182. LONG lSel;
  183. TRENTER(("(hBinding=%p,hClient=%p,ThreadId=%x,IndentLevel=%d,Text=%s)\n",
  184. hBinding, hClient, dwThreadId, iIndentLevel, pszText));
  185. wsprintfA(szText, "[%08x]%s: ", dwThreadId, ClientEntry->szClientName);
  186. for (i = 0; i < iIndentLevel; ++i)
  187. {
  188. lstrcpyA(&szText[lstrlenA(szText)], "| ");
  189. }
  190. CopyStr(&szText[lstrlenA(szText)], pszText);
  191. lSel = (LONG)SendMessage(ghwndEdit, WM_GETTEXTLENGTH, 0, 0);
  192. SendMessage(ghwndEdit, EM_SETSEL, lSel, lSel);
  193. SendMessage(ghwndEdit, EM_REPLACESEL, 0, (LPARAM)szText);
  194. TREXIT(("!\n"));
  195. return;
  196. } //WTTraceProc
  197. /*++
  198. @doc EXTERNAL
  199. @func VOID | WTTraceMsg | Print the TraceMsg text.
  200. @parm IN handle_t | hBinding | RPC binding handle.
  201. @parm IN HCLIENT | hClient | Client handle.
  202. @parm IN unsigned char * | pszMsg | Points to the TraceMsg text.
  203. @rvalue None.
  204. --*/
  205. VOID
  206. WTTraceMsg(
  207. IN handle_t hBinding,
  208. IN HCLIENT hClient,
  209. IN unsigned char *pszMsg
  210. )
  211. {
  212. TRTRACEPROC("WTTraceMsg", 1)
  213. PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient;
  214. static char szText[1024];
  215. LONG lSel;
  216. TRENTER(("(hBinding=%p,hClient=%p,Msg=%s)\n", hBinding, hClient, pszMsg));
  217. CopyStr(szText, pszMsg);
  218. lSel = (LONG)SendMessage(ghwndEdit, WM_GETTEXTLENGTH, 0, 0);
  219. SendMessage(ghwndEdit, EM_SETSEL, lSel, lSel);
  220. SendMessage(ghwndEdit, EM_REPLACESEL, 0, (LPARAM)szText);
  221. TREXIT(("!\n"));
  222. return;
  223. } //WTTraceMsg
  224. /*++
  225. @doc EXTERNAL
  226. @func VOID | WTDispatchServerRequests | Dispatch server requests to the
  227. client.
  228. @parm IN handle_t | hBinding | RPC binding handle.
  229. @parm IN HCLIENT | hClient | Client handle.
  230. @rvalue None.
  231. --*/
  232. VOID
  233. WTDispatchServerRequests(
  234. IN handle_t hBinding,
  235. IN HCLIENT hClient
  236. )
  237. {
  238. TRTRACEPROC("WTDispatchServerRequests", 1)
  239. PCLIENT_ENTRY ClientEntry = (PCLIENT_ENTRY)hClient;
  240. TRENTER(("(hBinding=%p,hClient=%p)\n", hBinding, hClient));
  241. TRASSERT(ClientEntry->hSrvReqEvent == 0);
  242. ClientEntry->hSrvReqEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  243. if (ClientEntry->hSrvReqEvent == NULL)
  244. {
  245. TRERRPRINT(("failed to create server request event (err=%d)\n",
  246. GetLastError()));
  247. }
  248. else
  249. {
  250. BOOL fDone = FALSE;
  251. LONG Req;
  252. DWORD rcWait;
  253. while (!fDone)
  254. {
  255. Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest,
  256. SRVREQ_BUSY);
  257. switch (Req)
  258. {
  259. case SRVREQ_NONE:
  260. Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest,
  261. Req);
  262. TRASSERT(Req == SRVREQ_BUSY);
  263. rcWait = WaitForSingleObject(ClientEntry->hSrvReqEvent,
  264. INFINITE);
  265. if (rcWait != WAIT_OBJECT_0)
  266. {
  267. TRERRPRINT(("failed waiting for server request event (err=%d)\n",
  268. GetLastError));
  269. }
  270. break;
  271. case SRVREQ_BUSY:
  272. //
  273. // Try again.
  274. //
  275. break;
  276. case SRVREQ_GETCLIENTINFO:
  277. WTGetClientInfo((PCLIENTINFO)ClientEntry->SrvReq.Context);
  278. Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest,
  279. SRVREQ_NONE);
  280. TRASSERT(Req == SRVREQ_BUSY);
  281. break;
  282. case SRVREQ_SETCLIENTINFO:
  283. WTSetClientInfo((PCLIENTINFO)ClientEntry->SrvReq.Context);
  284. Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest,
  285. SRVREQ_NONE);
  286. TRASSERT(Req == SRVREQ_BUSY);
  287. break;
  288. case SRVREQ_TERMINATE:
  289. fDone = TRUE;
  290. Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest,
  291. SRVREQ_NONE);
  292. TRASSERT(Req == SRVREQ_BUSY);
  293. break;
  294. default:
  295. TRERRPRINT(("unexpected server request %x.\n", Req));
  296. Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest,
  297. SRVREQ_NONE);
  298. TRASSERT(Req == SRVREQ_BUSY);
  299. }
  300. }
  301. CloseHandle(ClientEntry->hSrvReqEvent);
  302. ClientEntry->hSrvReqEvent = 0;
  303. }
  304. TREXIT(("!\n"));
  305. return;
  306. } //WTDispatchServerRequests
  307. /*++
  308. @doc INTERNAL
  309. @func VOID | SendServerRequest | Send a server request to the client.
  310. @parm IN PCLIENT_ENTRY | ClientEntry | Points to the client entry.
  311. @parm IN LONG | lRequest | Request.
  312. @parm IN PVOID | Context | Request context.
  313. @rvalue None.
  314. --*/
  315. VOID
  316. SendServerRequest(
  317. IN PCLIENT_ENTRY ClientEntry,
  318. IN LONG lRequest,
  319. IN PVOID Context
  320. )
  321. {
  322. TRTRACEPROC("SendServerRequest", 1)
  323. LONG Req;
  324. TRENTER(("(ClientEntry=%p,Request=%x,Context=%p)\n",
  325. ClientEntry, lRequest, Context));
  326. while (InterlockedCompareExchange(&ClientEntry->SrvReq.lRequest,
  327. SRVREQ_BUSY,
  328. SRVREQ_NONE) != SRVREQ_NONE)
  329. ;
  330. ClientEntry->SrvReq.Context = Context;
  331. Req = InterlockedExchange(&ClientEntry->SrvReq.lRequest, lRequest);
  332. TRASSERT(Req == SRVREQ_BUSY);
  333. SetEvent(ClientEntry->hSrvReqEvent);
  334. TREXIT(("!\n"));
  335. return;
  336. } //SendServerRequest
  337. /*++
  338. @doc INTERNAL
  339. @func LPSTR | CopyStr | Copy string from source to destination and
  340. replaces all the '\n' to '\r\n'.
  341. @parm OUT LPSTR | pszDest | Points to the destination string.
  342. @parm IN LPCSTR | pszSrc | Points to the source string.
  343. @rvalue Returns pointer to the destination string.
  344. --*/
  345. LPSTR
  346. CopyStr(
  347. OUT LPSTR pszDest,
  348. IN LPCSTR pszSrc
  349. )
  350. {
  351. TRTRACEPROC("CopyStr", 3)
  352. LPSTR psz;
  353. TRENTER(("(Dest=%p,Src=%s)\n", pszDest, pszSrc));
  354. for (psz = pszDest; *pszSrc != '\0'; psz++, pszSrc++)
  355. {
  356. if (*pszSrc != '\n')
  357. {
  358. *psz = *pszSrc;
  359. }
  360. else
  361. {
  362. *psz = '\r';
  363. psz++;
  364. *psz = '\n';
  365. }
  366. }
  367. *psz = '\0';
  368. TREXIT(("=%p (Dest=%s)\n", pszDest, pszDest));
  369. return pszDest;
  370. } //CopyStr
  371. /*++
  372. @doc EXTERNAL
  373. @func void __RPC_FAR * | MIDL_user_allocate | MIDL allocate.
  374. @parm IN size_t | len | size of allocation.
  375. @rvalue SUCCESS | Returns the pointer to the memory allocated.
  376. @rvalue FAILURE | Returns NULL.
  377. --*/
  378. void __RPC_FAR * __RPC_USER
  379. MIDL_user_allocate(
  380. IN size_t len
  381. )
  382. {
  383. TRTRACEPROC("MIDL_user_allocate", 5)
  384. void __RPC_FAR *ptr;
  385. TRENTER(("(len=%d)\n", len));
  386. ptr = malloc(len);
  387. TREXIT(("=%p\n", ptr));
  388. return ptr;
  389. } //MIDL_user_allocate
  390. /*++
  391. @doc EXTERNAL
  392. @func void | MIDL_user_free | MIDL free.
  393. @parm IN void __PRC_FAR * | ptr | Points to the memory to be freed.
  394. @rvalue None.
  395. --*/
  396. void __RPC_USER
  397. MIDL_user_free(
  398. IN void __RPC_FAR *ptr
  399. )
  400. {
  401. TRTRACEPROC("MIDL_user_free", 5)
  402. TRENTER(("(ptr=%p)\n", ptr));
  403. free(ptr);
  404. TREXIT(("!\n"));
  405. return;
  406. } //MIDL_user_free