fileinfo.c revision 78a072e1b56619e3230735ae073668311232ec94
/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
Abstract:
This module implements the mini redirector call down routines pertaining to retrieval/
--*/
#include "precomp.h"
#pragma hdrstop
/** Macro for copying a SHFLSTRING file name into a FILE_DIRECTORY_INFORMATION structure. */
do { \
} while (0)
/*++
Routine Description:
This routine does a directory query. Only the NT-->NT path is implemented.
Arguments:
RxContext - the RDBSS context
Return Value:
NTSTATUS - The return status for the operation
--*/
{
int vboxRC;
ULONG *pNextOffset = 0;
PSHFLSTRING ParsedPath = 0;
{
Log(("VBOXSF: QueryDirectory: pVBoxFobx is invalid!\n"));
return STATUS_INVALID_PARAMETER;
}
Log(("VBOXSF: QueryDirectory: vboxFobx = 0x%08x VBox file handle = 0x%08x\n", pVBoxFobx, pVBoxFobx->hFile));
if (NULL == DirectoryName)
return STATUS_INVALID_PARAMETER;
if (DirectoryName->Length == 0)
{
Log(("VBOXSF: QueryDirectory: DirectoryName = \\ (null string)\n"));
}
else Log(("VBOXSF: QueryDirectory: DirectoryName = %.*ls\n", DirectoryName->Length / sizeof(WCHAR), DirectoryName->Buffer));
return STATUS_INVALID_PARAMETER;
{
Log(("VBOXSF: QueryDirectory: Template = \\ (null string)\n"));
}
else Log(("VBOXSF: QueryDirectory: Template = %.*ls\n", Template->Length / sizeof(WCHAR), Template->Buffer));
if (pHGCMBuffer == NULL)
{
AssertFailed();
return STATUS_NO_MEMORY;
}
/* Assume start from the beginning. */
index = 0;
{
}
{
Log(("VBOXSF: QueryDirectory: Query single entry\n"));
}
{
/* Calculate length required for parsed path. */
ParsedPathSize = sizeof(*ParsedPath) + (DirectoryName->Length + Template->Length + 3 * sizeof(WCHAR));
if (!ParsedPath)
{
goto end;
}
len = 0;
if (DirectoryName->Length)
{
/* Copy directory name into ParsedPath. */
/* Add terminating backslash. */
len++;
}
Log(("VBOXSF: QueryDirectory: ParsedPath = %.*ls\n", ParsedPath->u16Length / sizeof(WCHAR), ParsedPath->String.ucs2));
}
cFiles = 0;
/* vboxCallDirInfo requires a pointer to uint32_t. */
Log(("VBOXSF: QueryDirectory: CallDirInfo: File = 0x%08x, Flags = 0x%08x, Index = %d\n", pVBoxFobx->hFile, fSFFlags, index));
vboxRC = vboxCallDirInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, ParsedPath, fSFFlags, index, &u32BufSize, (PSHFLDIRINFO)pHGCMBuffer, &cFiles);
switch (vboxRC)
{
case VINF_SUCCESS:
/* Nothing to do here. */
break;
case VERR_NO_TRANSLATION:
Log(("VBOXSF: QueryDirectory: Host could not translate entry!\n"));
break;
case VERR_NO_MORE_FILES:
if (cFiles <= 0) /* VERR_NO_MORE_FILES appears at the first lookup when just returning the current dir ".".
* So we also have to check for the cFiles counter. */
{
/* Not an error, but we have to handle the return value. */
Log(("VBOXSF: QueryDirectory: Host reported no more files!\n"));
{
/* First call. MSDN on FindFirstFile: "If the function fails because no matching files
* can be found, the GetLastError function returns ERROR_FILE_NOT_FOUND."
* So map this rc to file not found.
*/
}
else
{
/* Search continued. */
}
}
break;
case VERR_FILE_NOT_FOUND:
Log(("VBOXSF: QueryDirectory: no such file!\n"));
break;
default:
break;
}
if (Status != STATUS_SUCCESS)
goto end;
/* Verify that the returned buffer length is not greater than the original one. */
{
goto end;
}
/* How many bytes remain in the buffer. */
{
if (cbEntry > cbHGCMBuffer)
{
Log(("VBOXSF: QueryDirectory: Entry size (%d) exceeds the buffer size (%d)!!!\n", cbEntry, cbHGCMBuffer));
goto end;
}
switch (FileInformationClass)
{
case FileDirectoryInformation:
{
CopySize = sizeof(FILE_DIRECTORY_INFORMATION);
/* Struct already contains one char for null terminator. */
if (*pLengthRemaining >= CopySize)
{
pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
/* Align to 8 byte boundary */
}
else
{
}
break;
}
{
CopySize = sizeof(FILE_FULL_DIR_INFORMATION);
/* Struct already contains one char for null terminator. */
if (*pLengthRemaining >= CopySize)
{
pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
/* Align to 8 byte boundary */
}
else
{
}
break;
}
{
CopySize = sizeof(FILE_BOTH_DIR_INFORMATION);
/* struct already contains one char for null terminator */
if (*pLengthRemaining >= CopySize)
{
pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation cbAlloc = %x cbObject = %x\n", pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation CopySize = %d, name size=%d name len=%d\n", CopySize, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation File name %.*ls (DirInfo)\n", pDirInfo->FileNameLength / sizeof(WCHAR), pDirInfo->FileName));
Log(("VBOXSF: QueryDirectory: FileBothDirectoryInformation File name %.*ls (DirEntry)\n", pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
/* Align to 8 byte boundary. */
}
else
{
}
break;
}
{
CopySize = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
/* struct already contains one char for null terminator */
if (*pLengthRemaining >= CopySize)
{
pDirInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pDirEntry->Info.BirthTime); /* ridiculous name */
Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation cbAlloc = %x cbObject = %x\n", pDirEntry->Info.cbAllocated, pDirEntry->Info.cbObject));
Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation CopySize = %d, name size=%d name len=%d\n", CopySize, pDirEntry->name.u16Size, pDirEntry->name.u16Length));
Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirInfo)\n", pDirInfo->FileNameLength / sizeof(WCHAR), pDirInfo->FileName));
Log(("VBOXSF: QueryDirectory: FileIdBothDirectoryInformation File name %.*ls (DirEntry)\n", pDirEntry->name.u16Size / sizeof(WCHAR), pDirEntry->name.String.ucs2));
/* Align to 8 byte boundary. */
}
else
{
}
break;
}
case FileNamesInformation:
{
CopySize = sizeof(FILE_NAMES_INFORMATION);
/* Struct already contains one char for null terminator. */
if (*pLengthRemaining >= CopySize)
{
Log(("VBOXSF: QueryDirectory: FileNamesInformation File name %.*ls\n", pDirInfo->FileNameLength / sizeof(WCHAR), pDirInfo->FileName));
/* Align to 8 byte boundary. */
}
else
{
}
break;
}
default:
goto end;
}
cbHGCMBuffer -= cbEntry;
if (*pLengthRemaining >= CopySize)
{
*pLengthRemaining -= CopySize;
}
else break;
break;
/* More left? */
if (cbHGCMBuffer <= 0)
break;
index++; /* File Index. */
cFiles--;
}
if (pNextOffset)
*pNextOffset = 0; /* Last pDirInfo->NextEntryOffset should be set to zero! */
end: if (pHGCMBuffer)
if (ParsedPath)
return (Status);
}
/*++
Routine Description:
This routine queries the volume information
Arguments:
pRxContext - the RDBSS context
FsInformationClass - the kind of Fs information desired.
pBuffer - the buffer for copying the information
pBufferLength - the buffer length ( set to buffer length on input and set
to the remaining length on output)
Return Value:
NTSTATUS - The return status for the operation
--*/
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: vboxFobx = %p, Handle = 0x%08x\n", pVBoxFobx, pVBoxFobx->hFile));
switch (FsInformationClass)
{
case FileFsVolumeInformation:
{
int vboxRC;
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: Insufficient buffer size (%d)\n", RxContext->Info.LengthRemaining));
break;
}
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: pVBoxFobx is invalid!\n"));
return STATUS_INVALID_PARAMETER;
}
pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
pRootName++; /* remove leading backslash */
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: Root name = %.*ls\n", RootNameLength / sizeof(WCHAR), pRootName));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsVolumeInformation: Prefix %ls has %d elements\n", VBOX_VOLNAME_PREFIX, RT_ELEMENTS(VBOX_VOLNAME_PREFIX)));
/* Query serial number. */
cbHGCMBuffer = sizeof(SHFLVOLINFO);
if (pHGCMBuffer == 0)
{
AssertFailed();
break;
}
vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
if (vboxRC != VINF_SUCCESS)
{
break;
}
{
/* Copy prefix */
/* Copy share name (- 1 for zero terminator) */
RtlCopyMemory( &pVolInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, RootNameLength );
}
else
{
/* Copy prefix */
RtlCopyMemory( &pVolInfo->VolumeLabel[0], (PVOID)VBOX_VOLNAME_PREFIX, RT_MIN(BytesToCopy, VBOX_VOLNAME_PREFIX_SIZE) );
{
/* Copy share name (- 1 for zero terminator) */
RtlCopyMemory( &pVolInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, BytesToCopy - VBOX_VOLNAME_PREFIX_SIZE );
}
}
break;
}
case FileFsLabelInformation:
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: Insufficient buffer size (%d)\n", RxContext->Info.LengthRemaining));
break;
}
pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
pRootName++; /* remove leading backslash */
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: Root name = %.*ls\n", RootNameLength / sizeof(WCHAR), pRootName));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsLabelInformation: Prefix %ls has %d elements\n", VBOX_VOLNAME_PREFIX, RT_ELEMENTS(VBOX_VOLNAME_PREFIX)));
{
/* Copy prefix */
/* Copy share name (- 1 for zero terminator) */
RtlCopyMemory( &pLabelInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, RootNameLength );
}
else
{
/* Copy prefix */
RtlCopyMemory( &pLabelInfo->VolumeLabel[0], (PVOID)VBOX_VOLNAME_PREFIX, RT_MIN(BytesToCopy, VBOX_VOLNAME_PREFIX_SIZE) );
{
/* Copy share name (- 1 for zero terminator) */
RtlCopyMemory( &pLabelInfo->VolumeLabel[RT_ELEMENTS(VBOX_VOLNAME_PREFIX) - 1], (PVOID)pRootName, BytesToCopy - VBOX_VOLNAME_PREFIX_SIZE );
}
}
break;
}
case FileFsSizeInformation:
{
int vboxRC;
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
BytesToCopy = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
}
else
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: OriginalBuffer = %p, LenRemaining = %d\n", OriginalBuffer, RxContext->Info.LengthRemaining));
BytesToCopy = sizeof(FILE_FS_SIZE_INFORMATION);
}
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation/FileFsSizeInformation: Insufficient buffer size (%d)!\n", RxContext->Info.LengthRemaining));
break;
}
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: pVBoxFobx is invalid!\n"));
return STATUS_INVALID_PARAMETER;
}
cbHGCMBuffer = sizeof(SHFLVOLINFO);
if (pHGCMBuffer == 0)
{
AssertFailed();
break;
}
vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
if (vboxRC != VINF_SUCCESS)
{
break;
}
{
pFullSizeInfo->SectorsPerAllocationUnit = pVolInfo->ulBytesPerAllocationUnit / pVolInfo->ulBytesPerSector;
pFullSizeInfo->ActualAvailableAllocationUnits.QuadPart = pVolInfo->ullAvailableAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
pFullSizeInfo->CallerAvailableAllocationUnits.QuadPart = pFullSizeInfo->ActualAvailableAllocationUnits.QuadPart;
pFullSizeInfo->TotalAllocationUnits.QuadPart = pVolInfo->ullTotalAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: SectorsPerAllocationUnit %08x\n", (ULONG)pFullSizeInfo->SectorsPerAllocationUnit));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: BytesPerSector %08x\n", (ULONG)pFullSizeInfo->BytesPerSector));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: ActualAvailableAllocationUnits %RX64\n", pFullSizeInfo->ActualAvailableAllocationUnits.QuadPart));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsFullSizeInformation: TotalAllocationUnits %RX64\n", pFullSizeInfo->TotalAllocationUnits.QuadPart));
}
else
{
pSizeInfo->SectorsPerAllocationUnit = pVolInfo->ulBytesPerAllocationUnit / pVolInfo->ulBytesPerSector;
pSizeInfo->AvailableAllocationUnits.QuadPart = pVolInfo->ullAvailableAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
pSizeInfo->TotalAllocationUnits.QuadPart = pVolInfo->ullTotalAllocationBytes / pVolInfo->ulBytesPerAllocationUnit;
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: SectorsPerAllocationUnit %08x\n", (ULONG)pSizeInfo->SectorsPerAllocationUnit));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: BytesPerSector %08x\n", (ULONG)pSizeInfo->BytesPerSector));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: AvailableAllocationUnits %RX64\n", pSizeInfo->AvailableAllocationUnits.QuadPart));
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsSizeInformation: TotalAllocationUnits %RX64\n", pSizeInfo->TotalAllocationUnits.QuadPart));
}
if (pHGCMBuffer)
break;
}
case FileFsDeviceInformation:
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsDeviceInformation: Type = 0x%x\n", NetRoot->DeviceType));
BytesToCopy = sizeof(FILE_FS_DEVICE_INFORMATION);
{
{
break;
}
}
else
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsDeviceInformation: Buffer too small (%d vs %d)!\n", RxContext->Info.LengthRemaining, BytesToCopy));
}
break;
}
{
BytesToCopy = sizeof(MRX_VBOX_FILESYS_NAME_U) + FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[0]);
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsAttributeInformation: BytesToCopy = %d\n", BytesToCopy));
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsAttributeInformation: Buffer too small (%d)!\n", RxContext->Info.LengthRemaining));
break;
}
/** @todo set unicode, case sensitive etc? */
RtlCopyMemory( pAttribInfo->FileSystemName, MRX_VBOX_FILESYS_NAME_U, pAttribInfo->FileSystemNameLength);
break;
}
case FileFsControlInformation:
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsControlInformation (skipping ...)\n"));
break;
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsObjectIdInformation (skipping ...)\n"));
break;
case FileFsMaximumInformation:
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: FileFsMaximumInformation (skipping ...)\n"));
break;
default:
Log(("VBOXSF: VBoxMRxQueryVolumeInformationWithFullBuffer: Invalid parameter!\n"));
break;
}
return (Status);
}
/*++
Routine Description:
This routine queries the volume information. Since the NT server does not
handle bufferoverflow gracefully on query-fs-info, we allocate a buffer here
that is big enough to hold anything passed back; then we call the "real"
queryvolinfo routine.
Arguments:
pRxContext - the RDBSS context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
uint32_t cbSideBuffer = 0;
typedef struct
{
union
{
} Info;
} SideBuffer;
PAGED_CODE();
Log(
("VBOXSF: VBoxMRxQueryVolumeInformation: rxContextBufferAddr = 0x%x, rxContextBufferLengthRem = %d, (SideBufferSize = %d)\n", RxContext->Info.Buffer, RxContext->Info.LengthRemaining, sizeof(SideBuffer)));
{
/* I replace the buffer and length in the context with my stuff. */
Log(("VBOXSF: VBoxMRxQueryVolumeInformation: Using Sidebuffer ...\n"));
}
Log(("VBOXSF: VBoxMRxQueryVolumeInformation: RxContext->Info.LengthRemaining = %d\n", RxContext->Info.LengthRemaining));
if (Status != STATUS_SUCCESS)
{
Log(("VBOXSF: VBoxMRxQueryVolumeInformation: VBoxMRxQueryVolumeInformationWithFullBuffer failed with 0x%x\n", Status));
goto FINALLY;
}
if (UsingSideBuffer == TRUE)
{
}
else
{
}
Log(("VBOXSF: VBoxMRxQueryVolumeInformation: ReturnedLength = %d, OriginalLength = %d\n", ReturnedLength, OriginalLength));
if (ReturnedLength > OriginalLength)
{
}
if (UsingSideBuffer == TRUE)
{
}
Log(("VBOXSF: VBoxMRxQueryVolumeInformation: OriginalLength = %d, LengthRemaining = %d, Status = 0x%x\n", OriginalLength, RxContext->Info.LengthRemaining, Status));
Log(("VBOXSF: VBoxMRxQueryVolumeInformation: Final rxContextBufferAddr = 0x%x, rxContextBufferLengthRem = %d\n", RxContext->Info.Buffer, RxContext->Info.LengthRemaining));
if (NULL != pSideBuffer)
return Status;
}
/*++
Routine Description:
This routine sets the volume information
Arguments:
pRxContext - the RDBSS context
FsInformationClass - the kind of Fs information desired.
pBuffer - the buffer for copying the information
BufferLength - the buffer length
Return Value:
NTSTATUS - The return status for the operation
--*/
{
Log(("VBOXSF: VBoxMRxSetVolumeInformation called.\n"));
return (Status);
}
/*++
Routine Description:
This routine does a query file info. Only the NT-->NT path is implemented.
The NT-->NT path works by just remoting the call basically without further ado.
Arguments:
RxContext - the RDBSS context
Return Value:
NTSTATUS - The return status for the operation
--*/
{
uint8_t *pHGCMBuffer = 0;
int vboxRC = 0;
if (NULL == pLengthRemaining)
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: Invalid length pointer detected!\n"));
return STATUS_INVALID_PARAMETER;
}
Log(("VBOXSF: VBoxMRxQueryFileInformation: InfoBuffer = 0x%08x, Size = %d bytes, LenRemain = %d bytes\n", pInfoBuffer, cbMaxSize, *pLengthRemaining));
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: pVBoxFobx is invalid!\n"));
return STATUS_INVALID_PARAMETER;
}
if (NULL == pInfoBuffer)
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: Invalid information buffer detected!\n"));
return STATUS_INVALID_PARAMETER;
}
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: Directory -> Copy info retrieved during the create call\n"));
switch (FunctionalityRequested)
{
case FileBasicInformation:
{
CopySize = sizeof(FILE_BASIC_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: File attributes: 0x%x\n", pFileInfo->FileAttributes));
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileStandardInformation:
{
CopySize = sizeof(FILE_STANDARD_INFORMATION);
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer = 0x%08x\n", pFileInfo));
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileNamesInformation:
{
CopySize = sizeof(FILE_NAMES_INFORMATION);
/* Struct already contains one char for null terminator. */
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNamesInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileInternalInformation:
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer = 0x%08x\n", pInfoBuffer));
/*
* Note: We use the address of the FCB to determine the
* index number of the file. If we have to maintain persistance between
* file opens for this request, then we might have to do something
* like checksuming the reserved fields on a FUNIQUE SMB response.
*
*
* NT64: the address of capFcb used to be stuffed into
* IndexNumber.LowPart, with HighPart being zeroed.
*
* Whoever is asking for this pointer value should be
* prepared to deal with the returned 64-bit value.
*/
CopySize = sizeof(FILE_INTERNAL_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer overflow (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileEaInformation:
{
CopySize = sizeof(FILE_EA_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEaInformation: Buffer overflow (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer = 0x%08x\n", pInfoBuffer));
CopySize = sizeof(FILE_NETWORK_OPEN_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
default:
Log(("VBOXSF: VBoxMRxQueryFileInformation: Invalid filesystem information class %d!\n", FunctionalityRequested));
goto end;
}
}
else /* Entry is a file. */
{
if (pHGCMBuffer == 0)
return STATUS_NO_MEMORY;
vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_GET | SHFL_INFO_FILE, &cbHGCMBuffer, (PSHFLDIRINFO)pHGCMBuffer);
if (vboxRC != VINF_SUCCESS)
{
goto end;
}
switch (FunctionalityRequested)
{
case FileBasicInformation:
{
CopySize = sizeof(FILE_BASIC_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
pFileInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: File attributes = 0x%x\n", pFileInfo->FileAttributes));
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileBasicInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileStandardInformation:
{
CopySize = sizeof(FILE_STANDARD_INFORMATION);
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer = 0x%08x\n", pInfoBuffer));
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileStandardInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileNamesInformation:
{
CopySize = sizeof(FILE_NAMES_INFORMATION);
/* Struct already contains one char for null terminator */
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNamesInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileInternalInformation:
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer = 0x%08x\n", pInfoBuffer));
/* Note: We use the address of the FCB to determine the
index number of the file. If we have to maintain persistance between
file opens for this request, then we might have to do something
like checksuming the reserved fields on a FUNIQUE SMB response.
NT64: the address of capFcb used to be stuffed into
IndexNumber.LowPart, with HighPart being zeroed.
Whoever is asking for this pointer value should be
prepared to deal with the returned 64-bit value. */
CopySize = sizeof(FILE_INTERNAL_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileInternalInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileEaInformation:
{
CopySize = sizeof(FILE_EA_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEaInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAttributeTagInformation: Buffer = 0x%08x\n", pInfoBuffer));
CopySize = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
pAttrTag->ReparseTag = 0;
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAttributeTagInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
case FileEndOfFileInformation:
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEndOfFileInformation: Buffer = %08x\n", pInfoBuffer));
CopySize = sizeof(FILE_END_OF_FILE_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileEndOfFileInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAllocationInformation: Buffer = 0x%08x\n", pInfoBuffer));
CopySize = sizeof(FILE_ALLOCATION_INFORMATION);
if (*pLengthRemaining >= CopySize)
{
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileAllocationInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
{
CopySize = sizeof(FILE_NETWORK_OPEN_INFORMATION);
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer = 0x%08x\n", pInfoBuffer));
if (*pLengthRemaining >= CopySize)
{
pFileInfo->CreationTime.QuadPart = RTTimeSpecGetNtTime(&pFileEntry->BirthTime); /* Ridiculous name. */
}
else
{
Log(("VBOXSF: VBoxMRxQueryFileInformation: FileNetworkOpenInformation: Buffer too small (%d vs %d)!\n", *pLengthRemaining, CopySize));
}
break;
}
default:
Log(("VBOXSF: VBoxMRxQueryFileInformation: Unknown functionality requested (0x%x)!\n", FunctionalityRequested));
goto end;
}
}
if (Status == STATUS_SUCCESS)
{
if (*pLengthRemaining < CopySize)
{
/* This situation must be already taken into account by the above code. */
AssertMsgFailed(("VBOXSF: VBoxMRxQueryFileInformation: Length remaing is below 0! (%d - %d)!\n", *pLengthRemaining, CopySize));
}
else
{
pInfoBuffer += CopySize;
*pLengthRemaining -= CopySize;
}
}
if (pHGCMBuffer)
if (Status == STATUS_SUCCESS)
return Status;
}
/*++
Routine Description:
This routine does a set file info. Only the NT-->NT path is implemented.
The NT-->NT path works by just remoting the call basically without further ado.
Arguments:
RxContext - the RDBSS context
Return Value:
NTSTATUS - The return status for the operation
--*/
{
uint8_t *pHGCMBuffer = 0;
int vboxRC;
Log(("VBOXSF: VBoxMRxSetFileInformation called.\n"));
switch (FunctionalityRequested)
{
case FileBasicInformation:
{
Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: CreationTime %RX64\n", pFileInfo->CreationTime.QuadPart));
Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: LastAccessTime %RX64\n", pFileInfo->LastAccessTime.QuadPart));
Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: LastWriteTime %RX64\n", pFileInfo->LastWriteTime.QuadPart));
Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: ChangeTime %RX64\n", pFileInfo->ChangeTime.QuadPart));
Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: FileAttributes %RX32\n", pFileInfo->FileAttributes));
/* When setting file attributes, a value of -1 indicates to the server that it MUST NOT change this attribute
* for all subsequent operations on the same file handle.
*/
{
}
{
}
{
}
{
}
cbBuffer = sizeof(RTFSOBJINFO);
if (pHGCMBuffer == 0)
{
AssertFailed();
return STATUS_NO_MEMORY;
}
Log(("VBOXSF: VBoxMRxSetFileInformation: FileBasicInformation: keeps %d %d %d %d\n",
pVBoxFobx->fKeepCreationTime, pVBoxFobx->fKeepLastAccessTime, pVBoxFobx->fKeepLastWriteTime, pVBoxFobx->fKeepChangeTime));
/* The properties, that need to be changed, are set to something other than zero */
if (pFileInfo->FileAttributes)
vboxRC = vboxCallFSInfo(&pDeviceExtension->hgcmClient, &pNetRootExtension->map, pVBoxFobx->hFile, SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)pSHFLFileInfo);
if (vboxRC != VINF_SUCCESS)
{
goto end;
}
else
{
/* Update our internal copy */
}
break;
}
{
Log(("VBOXSF: VBoxMRxSetFileInformation: FileDispositionInformation: Delete = %d\n", pDispInfo->DeleteFile));
else Status = STATUS_SUCCESS;
break;
}
case FilePositionInformation:
{
Log(("VBOXSF: VBoxMRxSetFileInformation: FilePositionInformation: CurrentByteOffset = %RX64\n", pPosInfo->CurrentByteOffset.QuadPart));
/* Unsupported */
break;
}
{
Log(("VBOXSF: VBoxMRxSetFileInformation: FileAllocationInformation: AllocSize = %RX64\n", pAllocInfo->AllocationSize.QuadPart));
/* Pretend success */
break;
}
case FileEndOfFileInformation:
{
Log(("VBOXSF: VBoxMRxSetFileInformation: FileEndOfFileInformation: FileSize = %RX64\n", capFcb->Header.AllocationSize.QuadPart));
{
Log(("VBOXSF: VBoxMRxSetFileInformation: FileEndOfFileInformation: AllocSize = %d AllocSizeHigh = %d\n", NewAllocationSize.LowPart, NewAllocationSize.HighPart));
//
// Change the file allocation
//
}
else
{
}
/** @todo is this really necessary? */
break;
}
case FileLinkInformation:
{
Log(
("VBOXSF: VBoxMRxSetFileInformation: FileLinkInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = %.*ls\n", pRenameInfo->ReplaceIfExists, pRenameInfo->RootDirectory, pRenameInfo->FileNameLength
break;
}
case FileRenameInformation:
{
Log(
("VBOXSF: VBoxMRxSetFileInformation: FileRenameInformation: ReplaceIfExists = %d, RootDirectory = 0x%x = %.*ls\n", pRenameInfo->ReplaceIfExists, pRenameInfo->RootDirectory, pRenameInfo->FileNameLength
break;
}
default:
Log(("VBOXSF: VBoxMRxSetFileInformation: Unknown functionality requested (0x%x)!\n", FunctionalityRequested));
break;
}
end:
if (pHGCMBuffer)
return Status;
}
/*++
Routine Description:
This routine sets the file information on cleanup. the old rdr just swallows this operation (i.e.
it doesn't generate it). we are doing the same..........
Arguments:
pRxContext - the RDBSS context
Return Value:
NTSTATUS - The return status for the operation
--*/
{
Log(("VBOXSF: VBoxMRxSetFileInformationAtCleanup\n"));
return (Status);
}