windows-nt/Source/XPSP1/NT/net/dhcp/client/nt/apinmp.c

204 lines
7.5 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//================================================================================
// Copyright (C) 1997 Microsoft Corporation
// Author: RamesV
// description: implements the API stuff for a named pipe.
//================================================================================
#include "precomp.h"
#include <apistub.h>
#include <apiimpl.h>
typedef
BOOL (*PFILE_OP_FN) (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
#define DEFAULT_SERVER_TIMEOUT (2*60*1000) // two minutes.
DWORD INLINE // win32 status
BlockFileOp( // synchronous read/write file
IN HANDLE Handle, // handle to read/write on
IN OUT LPBYTE Buffer, // buffer to read/write into
IN DWORD BufSize, // o/p buffer size
OUT LPDWORD nBytes, // the # of bytes read/written
IN LPOVERLAPPED Overlap,
IN PFILE_OP_FN FileOp // file operation, ReadFile or WriteFile
) {
BOOL Success;
DWORD Error;
BOOL fCancelled = FALSE;
Success = FileOp(Handle, Buffer, BufSize, nBytes, Overlap);
if( Success ) return ERROR_SUCCESS;
Error = GetLastError();
if( ERROR_MORE_DATA == Error ) {
(*nBytes) = BufSize;
return ERROR_SUCCESS;
}
if( ERROR_IO_PENDING != Error ) return Error;
/*
if( (PFILE_OP_FN)WriteFile == FileOp ) {
Success = FlushFileBuffers(Handle);
if( !Success ) return GetLastError();
}
*/
Error = WaitForSingleObject(Overlap->hEvent, DEFAULT_SERVER_TIMEOUT );
if( WAIT_TIMEOUT == Error ) {
//
// Waited too long?
//
DhcpPrint((DEBUG_ERRORS, "Waited too long on pipe. Cancelling IO\n"));
fCancelled = CancelIo(Handle);
if( 0 == Error ) DhcpAssert( 0 == GetLastError());
//
// Hopefully, even if we cancel, get Overlapped result would return..
//
}
Success = GetOverlappedResult(Handle, Overlap, nBytes, TRUE);
if( Success ) return ERROR_SUCCESS;
Error = GetLastError();
if( ERROR_MORE_DATA == Error ) {
(*nBytes) = BufSize;
return ERROR_SUCCESS;
}
if( fCancelled ) DhcpAssert( ERROR_OPERATION_ABORTED == Error);
return Error;
}
DWORD INLINE // win32 status
BlockReadFile( // synchronous read/write file
IN HANDLE Handle, // handle to read on
IN OUT LPBYTE OutBuffer, // buffer to read into
IN DWORD OutBufSize, // o/p buffer size
OUT LPDWORD nBytesRead, // the # of bytes read
IN LPOVERLAPPED Overlap
) {
return BlockFileOp(Handle,OutBuffer, OutBufSize, nBytesRead, Overlap, ReadFile);
}
DWORD INLINE // win32 status
BlockWriteFile( // synchronous read/write file
IN HANDLE Handle, // handle to write on
IN OUT LPBYTE InBuffer, // buffer to writeinto
IN DWORD InBufSize, // i/p buffer size
OUT LPDWORD nBytesWritten, // the # of bytes written
IN LPOVERLAPPED Overlap
) {
return BlockFileOp(Handle, InBuffer, InBufSize, nBytesWritten, Overlap, WriteFile);
}
DWORD
ProcessApiRequest( // win32 status
IN HANDLE PipeHandle, // input pipe to read from
IN LPOVERLAPPED Overlap // overlap buffer to use for this
) {
DWORD Tmp[2];
DWORD OutBufSize;
DWORD InBufSize;
DWORD Error;
DWORD BytesRead;
DWORD BytesWritten;
LPBYTE InBuf;
LPBYTE OutBuf;
LPBYTE RealOutBuf;
BOOL Success;
ResetEvent(Overlap->hEvent);
Error = BlockReadFile(PipeHandle, (LPBYTE)Tmp, sizeof(Tmp), &BytesRead, Overlap);
if( ERROR_SUCCESS != Error ) return Error;
if( sizeof(Tmp) != BytesRead ) return ERROR_INVALID_PARAMETER;
InBufSize = ntohl(Tmp[1]);
OutBufSize = ntohl(Tmp[0]);
if( 0 == InBufSize ) return ERROR_INVALID_PARAMETER;
InBuf = DhcpAllocateMemory(InBufSize);
if( NULL == InBuf ) return ERROR_NOT_ENOUGH_MEMORY;
RealOutBuf = DhcpAllocateMemory(2*sizeof(DWORD) + OutBufSize);
if( NULL == RealOutBuf ) {
DhcpFreeMemory(InBuf);
return ERROR_NOT_ENOUGH_MEMORY;
}
OutBuf = RealOutBuf+sizeof(DWORD);
Error = BlockReadFile(PipeHandle, InBuf, InBufSize, &BytesRead, Overlap);
if( ERROR_SUCCESS != Error ) goto Cleanup;
if( InBufSize != BytesRead ) {
Error = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
Error = DhcpApiProcessBuffer(InBuf,InBufSize, OutBuf, &OutBufSize);
((DWORD UNALIGNED*)RealOutBuf)[0] = htonl(Error);
((DWORD UNALIGNED*)RealOutBuf)[1] = htonl(OutBufSize);
if( ERROR_SUCCESS == Error ) OutBufSize += sizeof(DWORD)*2;
else OutBufSize = sizeof(DWORD)*2;
Error = BlockWriteFile(PipeHandle, RealOutBuf, OutBufSize, &BytesWritten, Overlap);
if( ERROR_SUCCESS != Error ) goto Cleanup;
DhcpAssert(OutBufSize == BytesWritten);
Cleanup:
DhcpAssert(InBuf);
DhcpFreeMemory(InBuf);
if( NULL != RealOutBuf) DhcpFreeMemory(RealOutBuf);
return Error;
}
DWORD // error status
ExecuteApiRequest( // execute an api request
IN LPBYTE InBuffer, // buffer to process
OUT LPBYTE OutBuffer, // place to copy the output data
IN OUT LPDWORD OutBufSize // ip: how big can the outbuf be, o/p: how big it really is
) {
LPBYTE xOutBuf;
LPBYTE Tmp;
DWORD xOutBufSize;
DWORD BytesRead;
BOOL Status;
xOutBufSize = (*OutBufSize) + 2 * sizeof(DWORD); // the first two dwords are STATUS and reqd SIZE respectively
xOutBuf = DhcpAllocateMemory(xOutBufSize);
if( NULL == xOutBuf ) return ERROR_NOT_ENOUGH_MEMORY;
Status = CallNamedPipe(
DHCP_PIPE_NAME,
InBuffer,
ntohl(((DWORD UNALIGNED *)InBuffer)[1]) + 2*sizeof(DWORD),
xOutBuf,
xOutBufSize,
&BytesRead,
NMPWAIT_WAIT_FOREVER
);
if( FALSE == Status ) {
Status = GetLastError();
DhcpAssert(ERROR_MORE_DATA != Status);
DhcpFreeMemory(xOutBuf);
return Status;
}
DhcpAssert( BytesRead >= 2*sizeof(DWORD)); // expect to read STATUS and SIZE at the minimum..
Status = *(DWORD UNALIGNED *)xOutBuf; Tmp = xOutBuf + sizeof(DWORD);
xOutBufSize = *(DWORD UNALIGNED *)Tmp; Tmp += sizeof(DWORD);
Status = ntohl(Status);
xOutBufSize = ntohl(xOutBufSize);
if( ERROR_SUCCESS == Status && 0 != xOutBufSize ) {
memcpy(OutBuffer, Tmp, xOutBufSize);
}
(*OutBufSize) = xOutBufSize;
DhcpFreeMemory(xOutBuf);
return Status;
}
//================================================================================
// end of file
//================================================================================