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:
-
- SrvStoC.c
-
- Abstract:
-
- This file implements the server-to-client flow
- of data for remote server. The data is the output
- of the child program intermingled with client input.
-
- 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
- StartServerToClientFlow(
- VOID
- )
- {
- PREMOTE_CLIENT pClient;
-
- //
- // Start read operations against the temp file for
- // all active clients that aren't currently doing
- // read temp/write client operations and that are
- // fully connected.
- //
-
- for (pClient = (PREMOTE_CLIENT) ClientListHead.Flink;
- pClient != (PREMOTE_CLIENT) &ClientListHead;
- pClient = (PREMOTE_CLIENT) pClient->Links.Flink ) {
-
-
- if (! pClient->cbWrite) {
-
- StartReadTempFile( pClient );
- }
- }
- }
-
-
- VOID
- FASTCALL
- StartReadTempFile(
- PREMOTE_CLIENT pClient
- )
- {
- //
- // pClient->cbWrite is used dually. WriteSessionOutputCompleted
- // uses it when 0 bytes are written to know how much to ask
- // to write when it resubmits the request. We use it to
- // indicate whether a read temp/write session chain of I/Os
- // is currently active for this client.
- //
-
- if (pClient->cbWrite) {
-
- ErrorExit("StartReadTempFile entered with nonzero cbWrite.");
- }
-
- if (dwWriteFilePointer > pClient->dwFilePos) {
-
- pClient->cbWrite = min(BUFFSIZE,
- dwWriteFilePointer - pClient->dwFilePos);
-
- pClient->WriteOverlapped.OffsetHigh = 0;
- pClient->WriteOverlapped.Offset = pClient->dwFilePos;
-
- if ( ! ReadFileEx(
- pClient->rSaveFile,
- pClient->ReadTempBuffer,
- pClient->cbWrite,
- &pClient->WriteOverlapped,
- ReadTempFileCompleted
- )) {
-
- if (ERROR_HANDLE_EOF == GetLastError()) {
-
- pClient->cbWrite = 0;
-
- } else {
-
- TRACE(SESSION, ("ReadFileEx for temp file failed error %d, closing client.\n", GetLastError()));
-
- CloseClient(pClient);
- }
- }
-
- }
- }
-
- VOID
- WINAPI
- ReadTempFileCompleted(
- DWORD dwError,
- DWORD cbRead,
- LPOVERLAPPED lpO
- )
- {
- PREMOTE_CLIENT pClient;
-
- pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, WriteOverlapped);
-
- if (HandleSessionError(pClient, dwError)) {
-
- return;
- }
-
-
- if (cbRead != pClient->cbWrite) {
-
- TRACE(SESSION, ("Read %d from temp file asked for %d\n", cbRead, pClient->cbWrite));
- }
-
- if (cbRead) {
-
- pClient->cbReadTempBuffer = cbRead;
- pClient->dwFilePos += cbRead;
-
- StartWriteSessionOutput(pClient);
-
- } else {
-
- //
- // Note that the server to client flow is halting for now
- // for this client.
- //
-
- pClient->cbWrite = 0;
- }
- }
-
-
- VOID
- FASTCALL
- StartWriteSessionOutput(
- PREMOTE_CLIENT pClient
- )
- {
- DWORD cbRead;
- char *pch;
-
- cbRead = pClient->cbReadTempBuffer;
-
- //
- // We need to split commands from other text read
- // from the temp file and hold off on writing them
- // to the client until we make sure we're not the
- // client that submitted it. This isn't perfect
- // since we match on client name which can be
- // duplicated but it solves the problem of
- // duplicated input most of the time.
- //
-
- for (pch = pClient->ReadTempBuffer;
- pch < pClient->ReadTempBuffer + cbRead;
- pch++) {
-
- if ( ! (pClient->ServerFlags & SFLG_READINGCOMMAND) ) {
-
- if (BEGINMARK == *pch) {
-
- pClient->ServerFlags |= SFLG_READINGCOMMAND;
-
- if (pch != pClient->ReadTempBuffer &&
- pClient->cbWriteBuffer) {
-
- //
- // Start a write of everything we've come across
- // before the start of this command, with
- // WriteSessionOutputCompletedWriteNext specified
- // so we can continue processing the remainder
- // of pReadTempBuffer.
- //
-
- pClient->cbReadTempBuffer -= ( pch - pClient->ReadTempBuffer) + 1;
- cbRead = pClient->cbReadTempBuffer;
-
- #if DBG
- if (pClient->cbReadTempBuffer == (DWORD)-1) {
- ErrorExit("cbReadTempBuffer underflow.");
- }
- #endif
-
- MoveMemory(pClient->ReadTempBuffer, pch + 1, cbRead);
-
- pClient->cbWrite = pClient->cbWriteBuffer;
-
- pClient->WriteOverlapped.OffsetHigh = 0;
- pClient->WriteOverlapped.Offset = 0;
-
- if ( ! WriteFileEx(
- pClient->PipeWriteH,
- pClient->WriteBuffer,
- pClient->cbWrite,
- &pClient->WriteOverlapped,
- WriteSessionOutputCompletedWriteNext
- )) {
-
- CloseClient(pClient);
- }
-
- TRACE(SESSION, ("%x Wrote %d bytes pre-command output\n", pClient, pClient->cbWrite));
-
- pClient->cbWriteBuffer = 0;
-
- return;
- }
-
- } else {
-
- if (pClient->cbWriteBuffer == BUFFSIZE) {
-
- ErrorExit("cbWriteBuffer overflow");
- }
-
- pClient->WriteBuffer[ pClient->cbWriteBuffer++ ] = *pch;
- }
-
- } else {
-
- if (ENDMARK == *pch ||
- pClient->cbCommandBuffer == BUFFSIZE) {
-
- pClient->ServerFlags &= ~SFLG_READINGCOMMAND;
-
- //
- // Preceding ENDMARK is the pClient in hex ascii of the
- // client that generated the command, not null terminated.
- //
-
- if (ENDMARK == *pch) {
-
- pClient->cbCommandBuffer -=
- min(pClient->cbCommandBuffer, sizeof(pClient->HexAsciiId));
-
- }
-
- //
- // We hide each client's input from their output pipe
- // because their local remote.exe has already displayed it.
- //
-
- if ( pClient->cbCommandBuffer &&
- ! (ENDMARK == *pch &&
- ! memcmp(
- pch - sizeof(pClient->HexAsciiId),
- pClient->HexAsciiId,
- sizeof(pClient->HexAsciiId)))) {
-
- //
- // Start a write of the accumulated command with
- // WriteSessionOutputCompletedWriteNext specified
- // so we can continue processing the remainder
- // of pReadTempBuffer.
- //
-
- pClient->cbReadTempBuffer -= (pch - pClient->ReadTempBuffer) + 1;
- MoveMemory(pClient->ReadTempBuffer, pch + 1, pClient->cbReadTempBuffer);
-
- pClient->cbWrite = pClient->cbCommandBuffer;
- pClient->cbCommandBuffer = 0;
-
- pClient->WriteOverlapped.OffsetHigh = 0;
- pClient->WriteOverlapped.Offset = 0;
-
- if ( ! WriteFileEx(
- pClient->PipeWriteH,
- pClient->CommandBuffer,
- pClient->cbWrite,
- &pClient->WriteOverlapped,
- WriteSessionOutputCompletedWriteNext
- )) {
-
- CloseClient(pClient);
- return;
-
- } else {
-
- TRACE(SESSION, ("%x Wrote %d bytes command\n", pClient, pClient->cbWrite));
-
- return;
-
- }
-
- } else {
-
- //
- // We're eating this command for this session.
- //
-
- pClient->cbCommandBuffer = 0;
- }
-
- } else {
-
- pClient->CommandBuffer[ pClient->cbCommandBuffer++ ] = *pch;
-
- }
- }
- }
-
- //
- // We're done with the ReadTempBuffer.
- //
-
- pClient->cbReadTempBuffer = 0;
-
- if (pClient->cbWriteBuffer) {
-
- pClient->cbWrite = pClient->cbWriteBuffer;
-
- pClient->WriteOverlapped.OffsetHigh = 0;
- pClient->WriteOverlapped.Offset = 0;
-
- if ( ! WriteFileEx(
- pClient->PipeWriteH,
- pClient->WriteBuffer,
- pClient->cbWrite,
- &pClient->WriteOverlapped,
- WriteSessionOutputCompletedReadNext
- )) {
-
- CloseClient(pClient);
- return;
-
- } else {
-
- TRACE(SESSION, ("%x Wrote %d bytes normal\n", pClient, pClient->cbWrite));
-
- pClient->cbWriteBuffer = 0;
- }
-
- } else {
-
- //
- // Write buffer is empty.
- //
-
- pClient->cbWrite = 0;
-
- StartReadTempFile(pClient);
-
- }
- }
-
-
- BOOL
- FASTCALL
- WriteSessionOutputCompletedCommon(
- PREMOTE_CLIENT pClient,
- DWORD dwError,
- DWORD cbWritten,
- LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
- )
- {
- if (HandleSessionError(pClient, dwError)) {
-
- return TRUE;
- }
-
- if (!pClient->cbWrite) {
-
- ErrorExit("Zero cbWrite in WriteSessionOutputCompletedCommon");
- }
-
- if (!cbWritten && pClient->cbWrite) {
-
- printf("WriteSessionOutput zero bytes written of %d.\n", pClient->cbWrite);
- ErrorExit("WriteSessionOutputCompletedCommon failure");
-
- return TRUE;
- }
-
- #if DBG
- if (cbWritten != pClient->cbWrite) {
- printf("%x cbWritten %d cbWrite %d\n", pClient, cbWritten, pClient->cbWrite);
- }
- #endif
-
- return FALSE;
- }
-
-
- VOID
- WINAPI
- WriteSessionOutputCompletedWriteNext(
- DWORD dwError,
- DWORD cbWritten,
- LPOVERLAPPED lpO
- )
- {
- PREMOTE_CLIENT pClient;
-
- pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, WriteOverlapped);
-
- if (WriteSessionOutputCompletedCommon(
- pClient,
- dwError,
- cbWritten,
- WriteSessionOutputCompletedWriteNext
- )) {
-
- return;
- }
-
- StartWriteSessionOutput(pClient);
- }
-
-
- VOID
- WINAPI
- WriteSessionOutputCompletedReadNext(
- DWORD dwError,
- DWORD cbWritten,
- LPOVERLAPPED lpO
- )
- {
- PREMOTE_CLIENT pClient;
-
- pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, WriteOverlapped);
-
- if (WriteSessionOutputCompletedCommon(
- pClient,
- dwError,
- cbWritten,
- WriteSessionOutputCompletedReadNext
- )) {
-
- return;
- }
-
- //
- // Start another temp file read.
- //
-
- pClient->cbWrite = 0;
-
- StartReadTempFile(pClient);
- }
-