Leaked source code of windows server 2003
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.

433 lines
10 KiB

  1. /******************************************************************************\
  2. * This is a part of the Microsoft Source Code Samples.
  3. * Copyright 1995 - 1997 Microsoft Corporation.
  4. * All rights reserved.
  5. * This source code is only intended as a supplement to
  6. * Microsoft Development Tools and/or WinHelp documentation.
  7. * See these sources for detailed information regarding the
  8. * Microsoft samples programs.
  9. \******************************************************************************/
  10. /*++
  11. Copyright (c) 1997 Microsoft Corporation
  12. Module Name:
  13. SrvQuery.c
  14. Abstract:
  15. The server component of Remote. Respond to client
  16. "remote /q" requests to list available remote servers
  17. on this machine.
  18. Author:
  19. Dave Hart 30 May 1997
  20. derived from code by Mihai Costea in server.c.
  21. Environment:
  22. Console App. User mode.
  23. Revision History:
  24. --*/
  25. #include <precomp.h>
  26. #include "Remote.h"
  27. #include "Server.h"
  28. VOID
  29. FASTCALL
  30. InitializeQueryServer(
  31. VOID
  32. )
  33. {
  34. //
  35. // hQPipe is the handle to the listening query pipe,
  36. // if we're serving it.
  37. //
  38. hQPipe = INVALID_HANDLE_VALUE;
  39. QueryOverlapped.hEvent =
  40. CreateEvent(
  41. NULL, // security
  42. TRUE, // manual-reset
  43. FALSE, // initially nonsignaled
  44. NULL // unnamed
  45. );
  46. rghWait[WAITIDX_QUERYSRV_WAIT] =
  47. CreateMutex(
  48. &saLocalNamedObjects,
  49. FALSE, // not owner in case we open not create
  50. "MS RemoteSrv Q Mutex"
  51. );
  52. if (NULL == rghWait[WAITIDX_QUERYSRV_WAIT]) {
  53. rghWait[WAITIDX_QUERYSRV_WAIT] = INVALID_HANDLE_VALUE;
  54. }
  55. if (INVALID_HANDLE_VALUE == rghWait[WAITIDX_QUERYSRV_WAIT]) {
  56. ErrorExit("Remote: Unable to create/open query server mutex.\n");
  57. }
  58. }
  59. VOID
  60. FASTCALL
  61. QueryWaitCompleted(
  62. VOID
  63. )
  64. {
  65. HANDLE hWait;
  66. DWORD dwThreadId;
  67. BOOL b;
  68. DWORD dwRead;
  69. //
  70. // The remote server (not us) which was servicing the query
  71. // pipe has left the arena. Or someone has connected.
  72. //
  73. hWait = rghWait[WAITIDX_QUERYSRV_WAIT];
  74. if (hWait == QueryOverlapped.hEvent) {
  75. //
  76. // We're the query server and someone has connected.
  77. // Start a thread to service them.
  78. //
  79. b = GetOverlappedResult(hQPipe, &QueryOverlapped, &dwRead, TRUE);
  80. if ( !b && ERROR_PIPE_CONNECTED != GetLastError()) {
  81. TRACE(QUERY,("Connect Query Pipe returned %d\n", GetLastError()));
  82. if (INVALID_HANDLE_VALUE != hQPipe) {
  83. CloseHandle(hQPipe);
  84. hQPipe = INVALID_HANDLE_VALUE;
  85. }
  86. } else {
  87. TRACE(QUERY, ("Client connected to query pipe.\n"));
  88. ResetEvent(hWait);
  89. CloseHandle( (HANDLE)
  90. _beginthreadex(
  91. NULL, // security
  92. 0, // default stack size
  93. QueryHandlerThread,
  94. (LPVOID) hQPipe, // parameter
  95. 0, // not suspended
  96. &dwThreadId
  97. ));
  98. hQPipe = INVALID_HANDLE_VALUE;
  99. }
  100. } else {
  101. TRACE(QUERY, ("Remote server entered query mutex, will handle queries.\n"));
  102. rghWait[WAITIDX_QUERYSRV_WAIT] = QueryOverlapped.hEvent;
  103. }
  104. //
  105. // Either a client has connected and we've handed that pipe
  106. // off to a query thread to deal with, or we're just starting
  107. // to serve the query pipe, or we had an error from
  108. // ConnectNamedPipe. In any case we want to create another
  109. // query pipe instance and start listening on it.
  110. //
  111. ASSERT(INVALID_HANDLE_VALUE == hQPipe);
  112. StartServingQueryPipe();
  113. }
  114. VOID
  115. FASTCALL
  116. StartServingQueryPipe(
  117. VOID
  118. )
  119. {
  120. BOOL b;
  121. DWORD dwThreadId;
  122. char fullname[BUFFSIZE];
  123. sprintf(fullname, QUERY_DEBUGGERS_PIPE, ".");
  124. do { // hand off each pipe as connected until IO_PENDING
  125. hQPipe =
  126. CreateNamedPipe(
  127. fullname,
  128. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  129. PIPE_TYPE_BYTE | PIPE_WAIT,
  130. PIPE_UNLIMITED_INSTANCES,
  131. 0,
  132. 0,
  133. 0,
  134. &saPublic
  135. );
  136. if (INVALID_HANDLE_VALUE == hQPipe) {
  137. ErrorExit("Unable to create query server pipe.");
  138. }
  139. b = ConnectNamedPipe(hQPipe, &QueryOverlapped);
  140. if ( ! b && ERROR_PIPE_CONNECTED == GetLastError()) {
  141. b = TRUE;
  142. }
  143. if (b) {
  144. //
  145. // That was fast.
  146. //
  147. TRACE(QUERY, ("Client connected quickly to query pipe.\n"));
  148. CloseHandle( (HANDLE)
  149. _beginthreadex(
  150. NULL, // security
  151. 0, // default stack size
  152. QueryHandlerThread,
  153. (LPVOID) hQPipe, // parameter
  154. 0, // not suspended
  155. &dwThreadId
  156. ));
  157. hQPipe = INVALID_HANDLE_VALUE;
  158. } else if (ERROR_IO_PENDING == GetLastError()) {
  159. //
  160. // The main thread will call QueryWaitCompleted when
  161. // someone connects.
  162. //
  163. TRACE(QUERY, ("Awaiting query pipe connect\n"));
  164. } else {
  165. sprintf(fullname, "Remote: error %d connecting query pipe.\n", GetLastError());
  166. OutputDebugString(fullname);
  167. ErrorExit(fullname);
  168. }
  169. } while (b);
  170. }
  171. DWORD
  172. WINAPI
  173. QueryHandlerThread(
  174. LPVOID lpvArg
  175. )
  176. {
  177. HANDLE hQueryPipe = (HANDLE) lpvArg;
  178. DWORD cb;
  179. BOOL b;
  180. OVERLAPPED ol;
  181. QUERY_MESSAGE QData;
  182. char pIn[1];
  183. ZeroMemory(&ol, sizeof(ol));
  184. ol.hEvent =
  185. CreateEvent(
  186. NULL, // security
  187. TRUE, // manual-reset
  188. FALSE, // initially nonsignaled
  189. NULL // unnamed
  190. );
  191. // get command
  192. b = ReadFileSynch(
  193. hQueryPipe,
  194. pIn,
  195. 1,
  196. &cb,
  197. 0,
  198. &ol
  199. );
  200. if ( ! b || 1 != cb ) {
  201. TRACE(QUERY, ("Query server unable to read byte from query pipe.\n"));
  202. goto failure;
  203. }
  204. TRACE(QUERY, ("Query server read command '%c'\n", pIn[0]));
  205. //
  206. // !!!!!!
  207. // REMOVE 'h' support, it's only here for transitional compatibility
  208. // with 1570+ remote /q original server implementation.
  209. //
  210. if(pIn[0] == 'h') {
  211. DWORD dwMinusOne = (DWORD) -1;
  212. b = WriteFileSynch(
  213. hQueryPipe,
  214. &dwMinusOne,
  215. sizeof(dwMinusOne),
  216. &cb,
  217. 0,
  218. &ol
  219. );
  220. if ( !b || sizeof(dwMinusOne) != cb )
  221. {
  222. goto failure;
  223. }
  224. }
  225. if(pIn[0] == 'q') {
  226. QData.size = 0;
  227. QData.allocated = 0;
  228. QData.out = NULL;
  229. EnumWindows(EnumWindowProc, (LPARAM)&QData);
  230. b = WriteFileSynch(
  231. hQueryPipe,
  232. &QData.size,
  233. sizeof(QData.size),
  234. &cb,
  235. 0,
  236. &ol
  237. );
  238. if ( ! b || sizeof(int) != cb) {
  239. TRACE(QUERY, ("Remote: Can't write query length\n"));
  240. goto failure;
  241. }
  242. if (QData.size) { // anything to say?
  243. b = WriteFileSynch(
  244. hQueryPipe,
  245. QData.out,
  246. QData.size * sizeof(char),
  247. &cb,
  248. 0,
  249. &ol
  250. );
  251. free(QData.out);
  252. if ( ! b || QData.size * sizeof(char) != cb) {
  253. TRACE(QUERY, ("Remote: Can't write query"));
  254. goto failure;
  255. }
  256. TRACE(QUERY, ("Sent query response\n"));
  257. }
  258. }
  259. FlushFileBuffers(hQueryPipe);
  260. failure:
  261. DisconnectNamedPipe(hQueryPipe);
  262. CloseHandle(hQueryPipe);
  263. CloseHandle(ol.hEvent);
  264. return 0;
  265. }
  266. BOOL
  267. CALLBACK
  268. EnumWindowProc(
  269. HWND hWnd,
  270. LPARAM lParam
  271. )
  272. {
  273. #define MAX_TITLELEN 200
  274. QUERY_MESSAGE *pQm;
  275. int titleLen;
  276. char title[MAX_TITLELEN];
  277. char* tmp;
  278. pQm = (QUERY_MESSAGE*)lParam;
  279. if(titleLen = GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0])))
  280. {
  281. //
  282. // search for all windows that are visible
  283. //
  284. if (strstr(title, "] visible") &&
  285. strstr(title, "[Remote "))
  286. {
  287. if(pQm->size) // if message not empty
  288. pQm->out[(pQm->size)++] = '\n'; // overwrite ending null with \n
  289. else
  290. {
  291. pQm->out = (char*)malloc(MAX_TITLELEN); // first allocation
  292. if(!pQm->out)
  293. {
  294. printf("\nOut of memory\n");
  295. return FALSE;
  296. }
  297. pQm->allocated = MAX_TITLELEN;
  298. }
  299. // fill the result
  300. if((pQm->size + titleLen) >= pQm->allocated)
  301. {
  302. tmp = (char*)realloc(pQm->out, pQm->allocated + MAX_TITLELEN);
  303. if(!tmp)
  304. {
  305. printf("\nOut of memory\n");
  306. free(pQm->out);
  307. pQm->size = 0;
  308. return FALSE;
  309. }
  310. pQm->out = tmp;
  311. pQm->allocated += MAX_TITLELEN;
  312. }
  313. strcpy(pQm->out + pQm->size, title);
  314. pQm->size += titleLen;
  315. }
  316. }
  317. return TRUE;
  318. #undef MAX_TITLELEN
  319. }