home *** CD-ROM | disk | FTP | other *** search
-
- /******************************************************************************\
- * This is a part of the Microsoft Source Code Samples.
- * Copyright 1995 - 1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- \******************************************************************************/
-
- /*++
-
- Copyright (c) 1997 Microsoft Corporation
-
- Module Name:
-
- SrvHShak.c
-
- Abstract:
-
- The server component of Remote. Handshake with
- client at start of session.
-
-
- Author:
-
- Dave Hart 30 May 1997
-
- Environment:
-
- Console App. User mode.
-
- Revision History:
-
- --*/
-
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <io.h>
- #include <string.h>
- #include "Remote.h"
- #include "Server.h"
-
-
-
-
- VOID
- FASTCALL
- HandshakeWithRemoteClient(
- PREMOTE_CLIENT pClient
- )
- {
- pClient->ServerFlags |= SFLG_HANDSHAKING;
-
- AddClientToHandshakingList(pClient);
-
- //
- // Read hostname from client
- //
-
- ZeroMemory(
- &pClient->ReadOverlapped,
- sizeof(pClient->ReadOverlapped)
- );
-
- if ( ! ReadFileEx(
- pClient->PipeReadH,
- pClient->Name,
- HOSTNAMELEN - 1,
- &pClient->ReadOverlapped,
- ReadClientNameCompleted
- )) {
-
- CloseClient(pClient);
- }
- }
-
- VOID
- WINAPI
- ReadClientNameCompleted(
- DWORD dwError,
- DWORD cbRead,
- LPOVERLAPPED lpO
- )
- {
- PREMOTE_CLIENT pClient;
- SESSION_STARTREPLY ssr;
-
- pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
-
- if (pClient->ServerFlags & SFLG_CLOSING) {
-
- return;
- }
-
- if (dwError) {
- CloseClient(pClient);
- return;
- }
-
- if ((HOSTNAMELEN - 1) != cbRead) {
- printf("ReadClientNameCompleted read %d s/b %d.\n", cbRead, (HOSTNAMELEN - 1));
- CloseClient(pClient);
- return;
- }
-
- //
- // The client name read is 15 bytes always. The last four
- // should match MAGICNUMBER, which conveniently has the
- // low byte zeroed to terminate the client name after 11
- // characters.
- //
-
- if (MAGICNUMBER != *(DWORD *)&pClient->Name[11]) {
-
- pClient->Name[11] = 0;
- CloseClient(pClient);
- return;
- }
-
- //
- // Now we can tell if this is a single-pipe or two-pipe
- // client, because single-pipe clients replace the
- // first byte of the computername with the illegal
- // character '?'.
- //
-
- if ('?' == pClient->Name[0]) {
-
- pClient->PipeWriteH = pClient->PipeReadH;
-
- TRACE(CONNECT, ("Client %d pipe %x is single-pipe.\n", pClient->dwID, pClient->PipeWriteH));
-
- //
- // In order for things to work reliably for 2-pipe clients
- // when there are multiple remote servers on the same pipename,
- // we need to tear down the listening OUT pipe and recreate it so
- // that the oldest listening IN pipe will be from the same process
- // as the oldest listening OUT pipe.
- //
-
- if (1 == cConnectIns) {
-
- TRACE(CONNECT, ("Recycling OUT pipe %x as well for round-robin behavior.\n",
- hPipeOut));
-
- CANCELIO(hPipeOut);
- DisconnectNamedPipe(hPipeOut);
- CloseHandle(hPipeOut);
- hPipeOut = INVALID_HANDLE_VALUE;
- bOutPipeConnected = FALSE;
-
- CreatePipeAndIssueConnect(OUT_PIPE);
- }
-
- } else {
-
- if ( ! bOutPipeConnected ) {
-
- printf("Remote: %x two-pipe client connected to IN pipe but not OUT?\n", pClient);
- CloseClient(pClient);
- return;
- }
-
- bOutPipeConnected = FALSE;
-
- if (INVALID_HANDLE_VALUE != hConnectOutTimer) {
- pfnCancelWaitableTimer(hConnectOutTimer);
- }
-
- pClient->PipeWriteH = hPipeOut;
- hPipeOut = INVALID_HANDLE_VALUE;
-
- TRACE(CONNECT, ("Client %d is dual-pipe IN %x OUT %x.\n", pClient->dwID, pClient->PipeReadH, pClient->PipeWriteH));
-
- CreatePipeAndIssueConnect(OUT_PIPE);
- }
-
- TRACE(SHAKE, ("Read client name %s\n", pClient->Name));
-
- //
- // Send our little pile of goodies to the client
- //
-
- ssr.MagicNumber = MAGICNUMBER;
- ssr.Size = sizeof(ssr);
- ssr.FileSize = dwWriteFilePointer;
-
- //
- // Copy ssr structure to a buffer that will be around
- // for the entire I/O.
- //
-
- CopyMemory(pClient->WriteBuffer, &ssr, sizeof(ssr));
-
- if ( ! WriteFileEx(
- pClient->PipeWriteH,
- pClient->WriteBuffer,
- sizeof(ssr),
- &pClient->WriteOverlapped,
- WriteServerReplyCompleted
- )) {
-
- CloseClient(pClient);
- }
- }
-
-
- VOID
- WINAPI
- WriteServerReplyCompleted(
- DWORD dwError,
- DWORD cbWritten,
- LPOVERLAPPED lpO
- )
- {
- PREMOTE_CLIENT pClient;
-
- pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, WriteOverlapped);
-
- if (pClient->ServerFlags & SFLG_CLOSING) {
-
- return;
- }
-
- if (HandleSessionError(pClient, dwError)) {
- return;
- }
-
- TRACE(SHAKE, ("Wrote server reply\n"));
-
- //
- // Read the size of the SESSION_STARTUPINFO the client is
- // sending us, to deal gracefully with different versions
- // on client and server.
- //
-
- if ( ! ReadFileEx(
- pClient->PipeReadH,
- pClient->ReadBuffer,
- sizeof(DWORD),
- &pClient->ReadOverlapped,
- ReadClientStartupInfoSizeCompleted
- )) {
-
- CloseClient(pClient);
- }
- }
-
-
- VOID
- WINAPI
- ReadClientStartupInfoSizeCompleted(
- DWORD dwError,
- DWORD cbRead,
- LPOVERLAPPED lpO
- )
- {
- PREMOTE_CLIENT pClient;
- DWORD dwSize;
-
- pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
-
- if (HandleSessionError(pClient, dwError)) {
-
- return;
- }
-
- if (cbRead != sizeof(DWORD)) {
-
- CloseClient(pClient);
- return;
- }
-
- //
- // Sanity check the size
- //
-
- dwSize = *(DWORD *)pClient->ReadBuffer;
-
- if (dwSize > 1024) {
- CloseClient(pClient);
- return;
- }
-
- //
- // Squirrel away the size in the write buffer,
- // since during handshaking we never have both a
- // read and write pending this is OK.
- //
-
- *(DWORD *)pClient->WriteBuffer = dwSize;
-
- TRACE(SHAKE, ("Read client reply size %d\n", dwSize));
-
- //
- // Read the rest of the SESSION_STARTUPINFO into the read buffer
- // after the size.
- //
-
- RtlZeroMemory(
- &pClient->ReadOverlapped,
- sizeof(pClient->ReadOverlapped)
- );
-
- if ( ! ReadFileEx(
- pClient->PipeReadH,
- pClient->ReadBuffer + sizeof(DWORD),
- dwSize - sizeof(DWORD),
- &pClient->ReadOverlapped,
- ReadClientStartupInfoCompleted
- )) {
-
- CloseClient(pClient);
- }
- }
-
-
- VOID
- WINAPI
- ReadClientStartupInfoCompleted(
- DWORD dwError,
- DWORD cbRead,
- LPOVERLAPPED lpO
- )
- {
- PREMOTE_CLIENT pClient;
- DWORD dwSize;
- SESSION_STARTUPINFO ssi;
- char Buf[256];
-
- pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
-
- if (HandleSessionError(pClient, dwError)) {
-
- return;
- }
-
- dwSize = *(DWORD *)pClient->WriteBuffer;
-
- if (cbRead != (dwSize - sizeof(ssi.Size))) {
-
- CloseClient(pClient);
- return;
- }
-
- CopyMemory(&ssi, pClient->ReadBuffer, min(dwSize, sizeof(ssi)));
-
- CopyMemory(pClient->Name, ssi.ClientName, sizeof(pClient->Name));
- pClient->Flag = ssi.Flag;
-
- if (ssi.Version != VERSION) {
-
- printf("Remote Warning: Server Version=%d Client Version=%d for %s\n", VERSION, ssi.Version, pClient->Name);
- }
-
- TRACE(SHAKE, ("Read client info, new name %s, %d lines\n", pClient->Name, ssi.LinesToSend));
-
-
- //
- // Set temp file position according to the client's
- // requested lines to send. The heuristic of 45 chars
- // per average line is used by the client. However since old clients
- // hardcode this knowledge and sit and spin trying to read that many
- // bytes before completing initialization, and because we might not send
- // that many due to stripping BEGINMARK and ENDMARK characters, we
- // use 50 chars per line to calculate the temp file position in hopes
- // the extra bytes will overcome the missing MARK characters.
- //
-
- pClient->dwFilePos = dwWriteFilePointer > (ssi.LinesToSend * 50)
- ? dwWriteFilePointer - (ssi.LinesToSend * 50)
- : 0;
-
- //
- // This client's ready to roll.
- //
-
- pClient->ServerFlags &= ~SFLG_HANDSHAKING;
-
- MoveClientToNormalList(pClient);
-
- //
- // Start read operation against this client's input.
- //
-
- StartReadClientInput(pClient);
-
- //
- // Announce the connection.
- //
-
- sprintf(Buf,
- "\n**Remote: Connected to %s %s%s [%s]\n",
- pClient->Name,
- pClient->UserName,
- (pClient->PipeReadH != pClient->PipeWriteH)
- ? " (two pipes)"
- : "",
- GetFormattedTime(TRUE));
-
- if (WriteFileSynch(hWriteTempFile,Buf,strlen(Buf),&dwSize,dwWriteFilePointer,&olMainThread)) {
- dwWriteFilePointer += dwSize;
- StartServerToClientFlow();
- }
-
- //
- // Start write cycle for client output from the temp
- // file.
- // not needed because of StartServerToClientFlow() just above
- // StartReadTempFile(pClient);
-
- }
-