|
|
/****************************** Module Header ******************************\
* Module Name: pipe.c * * Copyright (c) 1991, Microsoft Corporation * * This module implements: * 1. a version of CreatePipe that allows control over the file * flags. e.g. FILE_FLAG_OVERLAPPED * 2. Timed-out pipe read and write * * History: * 06-29-92 Davidc Created. * 05-17-94 DaveTh Added ReadPipe, WritePipe. \***************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <windef.h>
#include <nturtl.h>
#include <winbase.h>
#include "rcmdsrv.h"
ULONG PipeSerialNumber = 0;
#define PIPE_FORMAT_STRING "\\\\.\\pipe\\rshsrv\\%08x.%08x"
/////////////////////////////////////////////////////////////////////////////
//
// RcCreatePipe
//
// Creates a uni-directional pipe with the specified security attributes,
// size and timeout. The handles are opened with the specified file-flags
// so FILE_FLAG_OVERLAPPED etc. can be specified.
//
// Returns handles to both end of pipe in passed parameters.
//
// Returns TRUE on success, FALSE on failure. (GetLastError() for details)
//
/////////////////////////////////////////////////////////////////////////////
BOOL RcCreatePipe( LPHANDLE ReadHandle, LPHANDLE WriteHandle, LPSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size, DWORD Timeout, DWORD ReadHandleFlags, DWORD WriteHandleFlags ) { CHAR PipeName[MAX_PATH];
//
// Make up a random pipe name
//
sprintf(PipeName, PIPE_FORMAT_STRING, GetCurrentProcessId(), PipeSerialNumber++);
//
// Create the pipe
//
*ReadHandle = CreateNamedPipeA( PipeName, PIPE_ACCESS_INBOUND | ReadHandleFlags, PIPE_TYPE_BYTE | PIPE_WAIT, 1, // Number of pipes
Size, // Out buffer size
Size, // In buffer size
Timeout, // Timeout in ms
SecurityAttributes );
if (*ReadHandle == NULL) { RcDbgPrint("RcCreatePipe: failed to created pipe <%s>, error = %d\n", PipeName, GetLastError()); return(FALSE); }
//
// Open the client end of the pipe
//
*WriteHandle = CreateFileA( PipeName, GENERIC_WRITE, 0, // No sharing
SecurityAttributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | WriteHandleFlags, NULL // Template file
);
if (*WriteHandle == INVALID_HANDLE_VALUE ) { RcDbgPrint("Failed to open client end of pipe <%s>, error = %d\n", PipeName, GetLastError()); RcCloseHandle(*ReadHandle, "async pipe (server(read) side)"); return(FALSE); }
//
// Everything succeeded
//
return(TRUE); }
/***************************************************************************\
* FUNCTION: ReadPipe * * PURPOSE: Implements a timed-out (ms) read on a pipe. * * RETURNS: ERROR_SUCCESS on success * WAIT_TIMEOUT if timed out before completing read * or respective error code on other failures * * HISTORY: * * 05-17-94 DaveTh Created from DavidC read pipe. * \***************************************************************************/
DWORD ReadPipe( HANDLE PipeHandle, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, DWORD Timeout ) { DWORD Result; OVERLAPPED Overlapped; HANDLE EventHandle; DWORD Error;
//
// Create an event for the overlapped operation
//
EventHandle = CreateEvent( NULL, // no security
TRUE, // Manual reset
FALSE, // Initial state
NULL // Name
); if (EventHandle == NULL) { RcDbgPrint("Internal error = %d\n", GetLastError()); return(GetLastError()); }
Overlapped.hEvent = EventHandle;
Result = ReadFile( PipeHandle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, &Overlapped ); if (Result) {
//
// Success without waiting - it's too easy !
//
CloseHandle(EventHandle);
} else {
//
// Read failed, if it's overlapped io, go wait for it
//
Error = GetLastError();
if (Error != ERROR_IO_PENDING) { RcDbgPrint("ReadPipe: ReadFile failed, error = %d\n", Error); CloseHandle(EventHandle); return(Error); }
//
// Wait for the I/O to complete
//
Result = WaitForSingleObject(EventHandle, Timeout); if (Result != WAIT_OBJECT_0) { if (Result == WAIT_TIMEOUT) { return(Result); } else { RcDbgPrint("ReadPipe: event wait failed, result = %d, last error = %d\n", Result, GetLastError()); } CloseHandle(EventHandle); }
//
// Go get the I/O result
//
Result = GetOverlappedResult( PipeHandle, &Overlapped, lpNumberOfBytesRead, FALSE ); //
// We're finished with the event handle
//
CloseHandle(EventHandle);
//
// Check result of GetOverlappedResult
//
if (!Result) { RcDbgPrint("ReadPipe: GetOverlappedResult failed, error = %d\n", GetLastError()); return(GetLastError()); } }
return(ERROR_SUCCESS); }
/***************************************************************************\
* FUNCTION: WritePipe * * PURPOSE: Implements a timed-out (ms) write on a pipe. * * RETURNS: ERROR_SUCCESS on success * WAIT_TIMEOUT if timed out before completing write * or respective error code on other failures * * HISTORY: * * 05-22-94 DaveTh Created. * \***************************************************************************/
DWORD WritePipe( HANDLE PipeHandle, LPVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, DWORD Timeout ) { DWORD Result; OVERLAPPED Overlapped; HANDLE EventHandle; DWORD Error;
//
// Create an event for the overlapped operation
//
EventHandle = CreateEvent( NULL, // no security
TRUE, // Manual reset
FALSE, // Initial state
NULL // Name
); if (EventHandle == NULL) { RcDbgPrint("Internal error = %d\n", GetLastError()); return(GetLastError()); }
Overlapped.hEvent = EventHandle;
Result = WriteFile( PipeHandle, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, &Overlapped ); if (Result) {
//
// Success without waiting - it's too easy !
//
CloseHandle(EventHandle);
} else {
//
// Write failed, if it's overlapped io, go wait for it
//
Error = GetLastError();
if (Error != ERROR_IO_PENDING) { RcDbgPrint("WritePipe: WriteFile failed, error = %d\n", Error); CloseHandle(EventHandle); return(Error); }
//
// Wait for the I/O to complete
//
Result = WaitForSingleObject(EventHandle, Timeout); if (Result != WAIT_OBJECT_0) { if (Result == WAIT_TIMEOUT) { return(Result); } else { RcDbgPrint("Write: event wait failed, result = %d, last error = %d\n", Result, GetLastError()); } CloseHandle(EventHandle); }
//
// Go get the I/O result
//
Result = GetOverlappedResult( PipeHandle, &Overlapped, lpNumberOfBytesWritten, FALSE ); //
// We're finished with the event handle
//
CloseHandle(EventHandle);
//
// Check result of GetOverlappedResult
//
if (!Result) { RcDbgPrint("WritePipe: GetOverlappedResult failed, error = %d\n", GetLastError()); return(GetLastError()); } }
return(ERROR_SUCCESS); }
|