Windows2003-3790/termsrv/newclient/rdpdr/w32drdev.cpp
2020-09-30 16:53:55 +02:00

601 lines
13 KiB
C++

/*++
Copyright (c) 1998-2000 Microsoft Corporation
Module Name:
w32drdev
Abstract:
This module defines the parent for the Win32 client-side RDP
device redirection "device" class hierarchy, W32DrDevice.
Author:
Tad Brockway 3/23/99
Revision History:
--*/
#include <precom.h>
#define TRC_FILE "W32DrDevice"
#include "w32drdev.h"
#include "proc.h"
#include "drdbg.h"
#include "w32utl.h"
#include "utl.h"
#include "w32proc.h"
#ifdef OS_WINCE
#include "filemgr.h"
#endif
///////////////////////////////////////////////////////////////
//
// W32DrDevice Members
//
//
W32DrDevice::W32DrDevice(
IN ProcObj *processObject,
IN ULONG deviceID,
IN const TCHAR *devicePath
) : DrDevice(processObject, deviceID)
/*++
Routine Description:
Constructor for the W32DrDevice class.
Arguments:
processObject - Associated Process Object
deviceID - Unique device identifier.
devicePath - Path to device that can be used by
CreateFile to open device.
Return Value:
NA
--*/
{
DC_BEGIN_FN("W32DrDevice::W32DrDevice");
//
// Record device path.
//
ASSERT(STRLEN(devicePath) < MAX_PATH);
STRNCPY(_devicePath, devicePath, MAX_PATH);
_devicePath[MAX_PATH-1] = '\0';
//
// Initialize the handle to the string resource module.
//
_hRdpDrModuleHandle = NULL;
DC_END_FN();
}
W32DrDevice::~W32DrDevice()
/*++
Routine Description:
Destructor for the W32DrDevice class.
Arguments:
NA
Return Value:
NA
--*/
{
DC_BEGIN_FN("W32DrDevice::~W32DrDevice");
//
// Close the string resource module.
//
if (_hRdpDrModuleHandle != NULL) {
FreeLibrary( _hRdpDrModuleHandle );
}
DC_END_FN();
}
TCHAR*
W32DrDevice::ConstructFileName(
PWCHAR Path,
ULONG PathBytes
)
/*++
Routine Description:
Setup the file name
--*/
{
TCHAR *pFileName;
HRESULT hr;
UINT cchFileName;
//
// Get the File Name
//
if (PathBytes) {
ULONG PathLen, DeviceLen;
//
// Open a File
//
//
// Path is assumed string null terminated
//
PathLen = PathBytes / sizeof(WCHAR) - 1;
Path[PathLen] = L'\0';
#ifndef OS_WINCE
DeviceLen = _tcslen(_devicePath);
#else
DeviceLen = 0;
#endif
//
// Append device path and file path together
// Assuming we need the \\?\ format, string
// is null terminated
//
#ifndef OS_WINCE
cchFileName = (DeviceLen + PathLen + 5);
pFileName = new TCHAR[cchFileName];
#else
cchFileName = PathLen + 1
pFileName = new TCHAR[cchFileName];
#endif
if (pFileName) {
#ifndef OS_WINCE
if (DeviceLen + PathLen < MAX_PATH) {
//
// Buffer is allocated large enough for the string
//
StringCchCopy(pFileName, cchFileName, _devicePath);
}
else {
//
// Buffer is allocated large enough for the string
//
StringCchPrintf(pFileName, cchFileName,
TEXT("\\\\?\\%s"),
_devicePath);
DeviceLen += 4;
}
#endif
}
else {
goto Cleanup;
}
#ifndef UNICODE
RDPConvertToAnsi(Path, pFileName + DeviceLen, PathLen + 1);
#else
memcpy(pFileName + DeviceLen, Path, PathLen * sizeof(WCHAR));
pFileName[DeviceLen + PathLen] = _T('\0');
#endif
}
else {
//
// Open the device itself
//
pFileName = _devicePath;
}
Cleanup:
return pFileName;
}
DWORD
W32DrDevice::ConstructCreateDisposition(
DWORD Disposition
)
/*++
Routine Description:
Construct client create disposition
--*/
{
DWORD CreateDisposition;
//
// Setup CreateDisposition
//
switch (Disposition) {
case FILE_CREATE :
CreateDisposition = CREATE_NEW;
break;
case FILE_OVERWRITE_IF :
CreateDisposition = CREATE_ALWAYS;
break;
case FILE_OPEN :
CreateDisposition = OPEN_EXISTING;
break;
case FILE_OPEN_IF :
CreateDisposition = OPEN_ALWAYS;
break;
default :
CreateDisposition = 0;
}
return CreateDisposition;
}
DWORD
W32DrDevice::ConstructDesiredAccess(
DWORD AccessMask
)
/*++
Routine Description:
Construct client desired access from server's access mask
--*/
{
DWORD DesiredAccess;
//
// Setup DesiredAccess
//
DesiredAccess = 0;
//
// If the user requested WRITE_DATA, return write.
//
if (AccessMask & FILE_WRITE_DATA) {
DesiredAccess |= GENERIC_WRITE;
}
//
// If the user requested READ_DATA, return read.
//
if (AccessMask & FILE_READ_DATA) {
DesiredAccess |= GENERIC_READ;
}
//
// If the user requested FILE_EXECUTE, return execute.
//
if (AccessMask & FILE_EXECUTE) {
DesiredAccess |= GENERIC_READ;
}
return DesiredAccess;
}
DWORD
W32DrDevice::ConstructFileFlags(
DWORD CreateOptions
)
/*++
Routine Description:
Construct file flags
--*/
{
DWORD CreateFlags;
CreateFlags = 0;
CreateFlags |= (CreateOptions & FILE_WRITE_THROUGH ? FILE_FLAG_WRITE_THROUGH : 0);
CreateFlags |= (CreateOptions & FILE_RANDOM_ACCESS ? FILE_FLAG_RANDOM_ACCESS : 0 );
//CreateFlags |= (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT ? 0 : FILE_FLAG_OVERLAPPED);
#ifndef OS_WINCE
CreateFlags |= (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING ? FILE_FLAG_NO_BUFFERING : 0);
CreateFlags |= (CreateOptions & FILE_SEQUENTIAL_ONLY ? FILE_FLAG_SEQUENTIAL_SCAN : 0);
CreateFlags |= (CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT ? FILE_FLAG_BACKUP_SEMANTICS : 0);
CreateFlags |= (CreateOptions & FILE_DELETE_ON_CLOSE ? FILE_FLAG_DELETE_ON_CLOSE : 0);
CreateFlags |= (CreateOptions & FILE_OPEN_REPARSE_POINT ? FILE_FLAG_OPEN_REPARSE_POINT : 0);
CreateFlags |= (CreateOptions & FILE_OPEN_NO_RECALL ? FILE_FLAG_OPEN_NO_RECALL : 0);
#endif
return CreateFlags;
}
BOOL
W32DrDevice::IsDirectoryFile(
DWORD DesiredAccess, DWORD CreateOptions, DWORD FileAttributes,
PDWORD FileFlags
)
/*++
Routine Description:
Check if the pFileName corresponds to a directory
--*/
{
BOOL IsDirectory = FALSE;
//
// Set up the directory check
//
if (!(CreateOptions & FILE_DIRECTORY_FILE)) {
//
// File doesn't have the directory flag on
// or nondirecotry flag on, so it's not sure
// if the file is a directory request or not
//
if (!(CreateOptions & FILE_NON_DIRECTORY_FILE)) {
if (FileAttributes != -1) {
//
// From file attributes, we know this is an directory file
// and we are requesting query access only. So, we add the
// BACKUP_SEMANTICS for the file and set the directory flag
// to be true. We always set the backup_semantics flag
//
#ifndef OS_WINCE
*FileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
#endif
if ((FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && DesiredAccess == 0) {
IsDirectory = TRUE;
}
}
}
else {
//
// Non directory file flag is on, so we are doing file create/open request
//
}
}
else {
//
// File has the directory flag on, but we still want to do create file
// on the directory
//
// Set the BACKUP_SEMANTICS, add it to the file flags
// and remember this is a directory
//
if (FileAttributes != -1) {
#ifndef OS_WINCE
*FileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
#endif
IsDirectory = TRUE;
}
}
return IsDirectory;
}
VOID
W32DrDevice::MsgIrpFlushBuffers(
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
IN UINT32 packetLen
)
/*++
Routine Description:
Handle a "Cleanup" IO request from the server.
Arguments:
pIoRequestPacket - Server IO request packet.
Return Value:
NA
--*/
{
PRDPDR_DEVICE_IOREQUEST pIoRequest;
BOOL result;
DWORD returnValue;
DrFile* pFile;
HANDLE FileHandle;
DC_BEGIN_FN("W32DrDevice::MsgIrpFlushBuffers");
//
// Get IO request pointer.
//
pIoRequest = &pIoRequestPacket->IoRequest;
//
// Get File Object
//
pFile = _FileMgr->GetObject(pIoRequest->FileId);
if (pFile)
FileHandle = pFile->GetFileHandle();
else
FileHandle = INVALID_HANDLE_VALUE;
//
// Flush the device handle.
//
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
#ifndef OS_WINCE
result = FlushFileBuffers(FileHandle);
#else
result = CEFlushFileBuffers(FileHandle);
#endif
if (!result) {
TRC_ERR((TB, _T("Flush returned %ld."), GetLastError()));
}
//
// Send the result to the server.
//
returnValue = result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
DefaultIORequestMsgHandle(pIoRequestPacket, returnValue);
DC_END_FN();
}
VOID
W32DrDevice::MsgIrpClose(
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
IN UINT32 packetLen
)
/*++
Routine Description:
Handle a "Close" IO request from the server.
Arguments:
pIoRequestPacket - Server IO request packet.
Return Value:
NA
--*/
{
PRDPDR_DEVICE_IOREQUEST pIoRequest;
DWORD returnValue = STATUS_SUCCESS;
DrFile* pFile;
DC_BEGIN_FN("W32DrDevice::MsgIrpClose");
//
// Get IO request pointer.
//
pIoRequest = &pIoRequestPacket->IoRequest;
if (_FileMgr == NULL) {
returnValue = STATUS_UNSUCCESSFUL;
goto Cleanup;
}
//
// Remove the File Object
//
pFile = _FileMgr->RemoveObject(pIoRequest->FileId);
if ( pFile != NULL) {
if (!pFile->Close()) {
TRC_ERR((TB, _T("Close returned %ld."), GetLastError()));
returnValue = STATUS_UNSUCCESSFUL;
}
pFile->Release();
}
else {
returnValue = STATUS_UNSUCCESSFUL;
}
Cleanup:
//
// Send the result to the server.
//
DefaultIORequestMsgHandle(pIoRequestPacket, returnValue);
DC_END_FN();
}
ULONG
W32DrDevice::ReadResources(
ULONG ulMessageID,
LPTSTR *ppStringBuffer,
PVOID pArguments,
BOOL bFromSystemModule
)
/*++
Routine Description:
Read a string from the resources file.
Arguments:
lMessageID - Message ID.
ppStringBuffer - Buffer pointer where the alloted buffer pointer
is returned.
pArguments - Pointer array.
bFromSystemModule - When set TRUE return the message from the system
module otherwise from the rdpdr.dll message module.
Return Value:
Returns ERROR_SUCCESS on success. Otherwise, a Windows error code is
returned.
--*/
{
ULONG ulError;
HINSTANCE hModuleHandle;
ULONG ulModuleFlag;
ULONG ulLen;
DC_BEGIN_FN("W32DrDevice::ReadResources");
if( !bFromSystemModule ) {
if (_hRdpDrModuleHandle == NULL ) {
_hRdpDrModuleHandle = LoadLibrary(RDPDR_MODULE_NAME);
if( _hRdpDrModuleHandle == NULL ) {
ulError = GetLastError();
TRC_ERR((TB, _T("LoadLibrary failed for %s: %ld."),
RDPDR_MODULE_NAME, ulError));
goto Cleanup;
}
}
hModuleHandle = _hRdpDrModuleHandle;
ulModuleFlag = FORMAT_MESSAGE_FROM_HMODULE;
}
else {
hModuleHandle = NULL;
ulModuleFlag = FORMAT_MESSAGE_FROM_SYSTEM;
}
ulLen =
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
ulModuleFlag |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
hModuleHandle,
ulMessageID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)ppStringBuffer,
0,
(va_list *)pArguments );
if( ulLen == 0 ) {
ulError = GetLastError();
TRC_ERR((TB, _T("FormatMessage() %ld."), ulError));
goto Cleanup;
}
ASSERT(*ppStringBuffer != NULL);
ulError = ERROR_SUCCESS;
Cleanup:
DC_END_FN();
return ulError;
}