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.

408 lines
9.8 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. SrvHShak.c
  14. Abstract:
  15. The server component of Remote. Handshake with
  16. client at start of session.
  17. Author:
  18. Dave Hart 30 May 1997
  19. Environment:
  20. Console App. User mode.
  21. Revision History:
  22. --*/
  23. #include <precomp.h>
  24. #include "Remote.h"
  25. #include "Server.h"
  26. VOID
  27. FASTCALL
  28. HandshakeWithRemoteClient(
  29. PREMOTE_CLIENT pClient
  30. )
  31. {
  32. pClient->ServerFlags |= SFLG_HANDSHAKING;
  33. AddClientToHandshakingList(pClient);
  34. //
  35. // Read hostname from client
  36. //
  37. ZeroMemory(
  38. &pClient->ReadOverlapped,
  39. sizeof(pClient->ReadOverlapped)
  40. );
  41. if ( ! ReadFileEx(
  42. pClient->PipeReadH,
  43. pClient->Name,
  44. HOSTNAMELEN - 1,
  45. &pClient->ReadOverlapped,
  46. ReadClientNameCompleted
  47. )) {
  48. CloseClient(pClient);
  49. }
  50. }
  51. VOID
  52. WINAPI
  53. ReadClientNameCompleted(
  54. DWORD dwError,
  55. DWORD cbRead,
  56. LPOVERLAPPED lpO
  57. )
  58. {
  59. PREMOTE_CLIENT pClient;
  60. SESSION_STARTREPLY ssr;
  61. pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
  62. if (pClient->ServerFlags & SFLG_CLOSING) {
  63. return;
  64. }
  65. if (dwError) {
  66. CloseClient(pClient);
  67. return;
  68. }
  69. if ((HOSTNAMELEN - 1) != cbRead) {
  70. printf("ReadClientNameCompleted read %d s/b %d.\n", cbRead, (HOSTNAMELEN - 1));
  71. CloseClient(pClient);
  72. return;
  73. }
  74. //
  75. // The client name read is 15 bytes always. The last four
  76. // should match MAGICNUMBER, which conveniently has the
  77. // low byte zeroed to terminate the client name after 11
  78. // characters.
  79. //
  80. if (MAGICNUMBER != *(DWORD UNALIGNED *)&pClient->Name[11]) {
  81. pClient->Name[11] = 0;
  82. CloseClient(pClient);
  83. return;
  84. }
  85. //
  86. // Now we can tell if this is a single-pipe or two-pipe
  87. // client, because single-pipe clients replace the
  88. // first byte of the computername with the illegal
  89. // character '?'.
  90. //
  91. if ('?' == pClient->Name[0]) {
  92. pClient->PipeWriteH = pClient->PipeReadH;
  93. TRACE(CONNECT, ("Client %d pipe %p is single-pipe.\n", pClient->dwID, pClient->PipeWriteH));
  94. //
  95. // In order for things to work reliably for 2-pipe clients
  96. // when there are multiple remote servers on the same pipename,
  97. // we need to tear down the listening OUT pipe and recreate it so
  98. // that the oldest listening IN pipe will be from the same process
  99. // as the oldest listening OUT pipe.
  100. //
  101. if (1 == cConnectIns) {
  102. TRACE(CONNECT, ("Recycling OUT pipe %p as well for round-robin behavior.\n",
  103. hPipeOut));
  104. CancelIo(hPipeOut);
  105. DisconnectNamedPipe(hPipeOut);
  106. CloseHandle(hPipeOut);
  107. hPipeOut = INVALID_HANDLE_VALUE;
  108. bOutPipeConnected = FALSE;
  109. CreatePipeAndIssueConnect(OUT_PIPE);
  110. }
  111. } else {
  112. if ( ! bOutPipeConnected ) {
  113. printf("Remote: %p two-pipe client connected to IN pipe but not OUT?\n", pClient);
  114. CloseClient(pClient);
  115. return;
  116. }
  117. bOutPipeConnected = FALSE;
  118. if (INVALID_HANDLE_VALUE != hConnectOutTimer) {
  119. CancelWaitableTimer(hConnectOutTimer);
  120. }
  121. pClient->PipeWriteH = hPipeOut;
  122. hPipeOut = INVALID_HANDLE_VALUE;
  123. TRACE(CONNECT, ("Client %d is dual-pipe IN %p OUT %p.\n", pClient->dwID, pClient->PipeReadH, pClient->PipeWriteH));
  124. CreatePipeAndIssueConnect(OUT_PIPE);
  125. }
  126. TRACE(SHAKE, ("Read client name %s\n", pClient->Name));
  127. //
  128. // Send our little pile of goodies to the client
  129. //
  130. ssr.MagicNumber = MAGICNUMBER;
  131. ssr.Size = sizeof(ssr);
  132. ssr.FileSize = dwWriteFilePointer;
  133. //
  134. // Copy ssr structure to a buffer that will be around
  135. // for the entire I/O.
  136. //
  137. CopyMemory(pClient->WriteBuffer, &ssr, sizeof(ssr));
  138. if ( ! WriteFileEx(
  139. pClient->PipeWriteH,
  140. pClient->WriteBuffer,
  141. sizeof(ssr),
  142. &pClient->WriteOverlapped,
  143. WriteServerReplyCompleted
  144. )) {
  145. CloseClient(pClient);
  146. }
  147. }
  148. VOID
  149. WINAPI
  150. WriteServerReplyCompleted(
  151. DWORD dwError,
  152. DWORD cbWritten,
  153. LPOVERLAPPED lpO
  154. )
  155. {
  156. PREMOTE_CLIENT pClient;
  157. pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, WriteOverlapped);
  158. if (pClient->ServerFlags & SFLG_CLOSING) {
  159. return;
  160. }
  161. if (HandleSessionError(pClient, dwError)) {
  162. return;
  163. }
  164. TRACE(SHAKE, ("Wrote server reply\n"));
  165. //
  166. // Read the size of the SESSION_STARTUPINFO the client is
  167. // sending us, to deal gracefully with different versions
  168. // on client and server.
  169. //
  170. if ( ! ReadFileEx(
  171. pClient->PipeReadH,
  172. pClient->ReadBuffer,
  173. sizeof(DWORD),
  174. &pClient->ReadOverlapped,
  175. ReadClientStartupInfoSizeCompleted
  176. )) {
  177. CloseClient(pClient);
  178. }
  179. }
  180. VOID
  181. WINAPI
  182. ReadClientStartupInfoSizeCompleted(
  183. DWORD dwError,
  184. DWORD cbRead,
  185. LPOVERLAPPED lpO
  186. )
  187. {
  188. PREMOTE_CLIENT pClient;
  189. DWORD dwSize;
  190. pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
  191. if (HandleSessionError(pClient, dwError)) {
  192. return;
  193. }
  194. if (cbRead != sizeof(DWORD)) {
  195. CloseClient(pClient);
  196. return;
  197. }
  198. //
  199. // Sanity check the size
  200. //
  201. dwSize = *(DWORD *)pClient->ReadBuffer;
  202. if (dwSize > 1024) {
  203. CloseClient(pClient);
  204. return;
  205. }
  206. //
  207. // Squirrel away the size in the write buffer,
  208. // since during handshaking we never have both a
  209. // read and write pending this is OK.
  210. //
  211. *(DWORD *)pClient->WriteBuffer = dwSize;
  212. TRACE(SHAKE, ("Read client reply size %d\n", dwSize));
  213. //
  214. // Read the rest of the SESSION_STARTUPINFO into the read buffer
  215. // after the size.
  216. //
  217. RtlZeroMemory(
  218. &pClient->ReadOverlapped,
  219. sizeof(pClient->ReadOverlapped)
  220. );
  221. if ( ! ReadFileEx(
  222. pClient->PipeReadH,
  223. pClient->ReadBuffer + sizeof(DWORD),
  224. dwSize - sizeof(DWORD),
  225. &pClient->ReadOverlapped,
  226. ReadClientStartupInfoCompleted
  227. )) {
  228. CloseClient(pClient);
  229. }
  230. }
  231. VOID
  232. WINAPI
  233. ReadClientStartupInfoCompleted(
  234. DWORD dwError,
  235. DWORD cbRead,
  236. LPOVERLAPPED lpO
  237. )
  238. {
  239. PREMOTE_CLIENT pClient;
  240. DWORD dwSize;
  241. SESSION_STARTUPINFO ssi;
  242. char Buf[256];
  243. pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
  244. if (HandleSessionError(pClient, dwError)) {
  245. return;
  246. }
  247. dwSize = *(DWORD *)pClient->WriteBuffer;
  248. if (cbRead != (dwSize - sizeof(ssi.Size))) {
  249. CloseClient(pClient);
  250. return;
  251. }
  252. CopyMemory(&ssi, pClient->ReadBuffer, min(dwSize, sizeof(ssi)));
  253. CopyMemory(pClient->Name, ssi.ClientName, sizeof(pClient->Name));
  254. pClient->Flag = ssi.Flag;
  255. if (ssi.Version != VERSION) {
  256. printf("Remote Warning: Server Version=%d Client Version=%d for %s\n", VERSION, ssi.Version, pClient->Name);
  257. }
  258. TRACE(SHAKE, ("Read client info, new name %s, %d lines\n", pClient->Name, ssi.LinesToSend));
  259. //
  260. // Set temp file position according to the client's
  261. // requested lines to send. The heuristic of 45 chars
  262. // per average line is used by the client. However since old clients
  263. // hardcode this knowledge and sit and spin trying to read that many
  264. // bytes before completing initialization, and because we might not send
  265. // that many due to stripping BEGINMARK and ENDMARK characters, we
  266. // use 50 chars per line to calculate the temp file position in hopes
  267. // the extra bytes will overcome the missing MARK characters.
  268. //
  269. pClient->dwFilePos = dwWriteFilePointer > (ssi.LinesToSend * 50)
  270. ? dwWriteFilePointer - (ssi.LinesToSend * 50)
  271. : 0;
  272. //
  273. // This client's ready to roll.
  274. //
  275. pClient->ServerFlags &= ~SFLG_HANDSHAKING;
  276. MoveClientToNormalList(pClient);
  277. //
  278. // Start read operation against this client's input.
  279. //
  280. StartReadClientInput(pClient);
  281. //
  282. // Announce the connection.
  283. //
  284. sprintf(Buf,
  285. "\n**Remote: Connected to %s %s%s [%s]\n",
  286. pClient->Name,
  287. pClient->UserName,
  288. (pClient->PipeReadH != pClient->PipeWriteH)
  289. ? " (two pipes)"
  290. : "",
  291. GetFormattedTime(TRUE));
  292. if (WriteFileSynch(hWriteTempFile,Buf,strlen(Buf),&dwSize,dwWriteFilePointer,&olMainThread)) {
  293. dwWriteFilePointer += dwSize;
  294. StartServerToClientFlow();
  295. }
  296. //
  297. // Start write cycle for client output from the temp
  298. // file.
  299. // not needed because of StartServerToClientFlow() just above
  300. // StartReadTempFile(pClient);
  301. }