1709 lines
49 KiB
C
1709 lines
49 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
volinfo.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the NtQueryVolumeInformationFile NT API
|
|||
|
functionality.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Colin Watson (Colinw) 24-Aug-1990
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
24-Aug-1990 Colinw
|
|||
|
|
|||
|
Created
|
|||
|
|
|||
|
--*/
|
|||
|
#define INCLUDE_SMB_MISC
|
|||
|
#define INCLUDE_SMB_TRANSACTION
|
|||
|
|
|||
|
#ifdef _CAIRO_
|
|||
|
#define INCLUDE_SMB_QUERY_SET
|
|||
|
#endif // _CAIRO_
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
|
|||
|
typedef struct _CORELABELCONTEXT {
|
|||
|
TRANCEIVE_HEADER Header; // Standard NetTranceive context header
|
|||
|
SMB_DIRECTORY_INFORMATION Result;
|
|||
|
} CORELABELCONTEXT, *PCORELABELCONTEXT;
|
|||
|
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryVolumeInfo(
|
|||
|
IN PIRP Irp OPTIONAL,
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_VOLUME_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QuerySizeInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_SIZE_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryDeviceInfo(
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_DEVICE_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryAAttributeInfo(
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_ATTRIBUTE_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryAttributeInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_ATTRIBUTE_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
NTSTATUS
|
|||
|
ReadCoreLabel(
|
|||
|
IN PIRP Irp OPTIONAL,
|
|||
|
IN PICB Icb,
|
|||
|
OUT PSMB_DIRECTORY_INFORMATION UsersBuffer
|
|||
|
);
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
STANDARD_CALLBACK_HEADER (
|
|||
|
CoreLabelCallBack
|
|||
|
);
|
|||
|
|
|||
|
#ifdef _CAIRO_
|
|||
|
|
|||
|
#ifdef _CAIRO_QUOTAS_
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryQuotaInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_QUOTA_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
);
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryControlInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_CONTROL_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
);
|
|||
|
#endif // _CAIRO_QUOTAS_
|
|||
|
#endif // _CAIRO_
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, RdrFsdQueryVolumeInformationFile)
|
|||
|
#pragma alloc_text(PAGE, RdrFspQueryVolumeInformationFile)
|
|||
|
#pragma alloc_text(PAGE, RdrFscQueryVolumeInformationFile)
|
|||
|
#pragma alloc_text(PAGE, QueryVolumeInfo)
|
|||
|
#pragma alloc_text(PAGE, QueryDeviceInfo)
|
|||
|
#pragma alloc_text(PAGE, QueryAttributeInfo)
|
|||
|
#pragma alloc_text(PAGE, QuerySizeInfo)
|
|||
|
#ifdef _CAIRO_
|
|||
|
#ifdef _CAIRO_QUOTAS_
|
|||
|
#pragma alloc_text(PAGE, QueryQuotaInfo)
|
|||
|
#pragma alloc_text(PAGE, QueryControlInfo)
|
|||
|
#endif // _CAIRO_QUOTAS_
|
|||
|
#endif // _CAIRO_
|
|||
|
#pragma alloc_text(PAGE, RdrQueryDiskQuota)
|
|||
|
#pragma alloc_text(PAGE, RdrQueryDiskControl)
|
|||
|
#pragma alloc_text(PAGE, ReadCoreLabel)
|
|||
|
#pragma alloc_text(PAGE3FILE, CoreLabelCallBack)
|
|||
|
#endif
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RdrFsdQueryVolumeInformationFile (
|
|||
|
IN PFS_DEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FSD version of the NtQueryInformationFile API.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
|
|||
|
request
|
|||
|
IN PIRP Irp - Supplies the IRP that describes the request
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|||
|
PFCB Fcb = FCB_OF(IrpSp);
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
dprintf(DPRT_VOLINFO|DPRT_DISPATCH, ("RdrFsdQueryVolumeInformationFile: Device: %08lx Irp:%08lx\n", DeviceObject, Irp));
|
|||
|
|
|||
|
Status = RdrFscQueryVolumeInformationFile(CanFsdWait(Irp), DeviceObject, Irp);
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RdrFspQueryVolumeInformationFile (
|
|||
|
IN PFS_DEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FSP version of the NtQueryVolumeInformationFile
|
|||
|
API.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
|
|||
|
request
|
|||
|
IN PIRP Irp - Supplies the IRP that describes the request
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
dprintf(DPRT_VOLINFO, ("RdrFspQueryVolumeInformationFile: Device: %08lx Irp:%08lx\n", DeviceObject, Irp));
|
|||
|
|
|||
|
return RdrFscQueryVolumeInformationFile(TRUE, DeviceObject, Irp);
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RdrFscQueryVolumeInformationFile (
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN PFS_DEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the common version of the
|
|||
|
NtQueryVolumeInformationFile API.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN BOOLEAN Wait - True if routine can block waiting for the request
|
|||
|
to complete.
|
|||
|
|
|||
|
IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
|
|||
|
request
|
|||
|
IN PIRP Irp - Supplies the IRP that describes the request
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
This code assumes that this is a buffered I/O operation. If it is ever
|
|||
|
implemented as a non buffered operation, then we have to put code to map
|
|||
|
in the users buffer here.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|||
|
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
|
|||
|
PVOID UsersBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
ULONG BufferSize = IrpSp->Parameters.QueryVolume.Length;
|
|||
|
PICB Icb = ICB_OF(IrpSp);
|
|||
|
BOOLEAN QueueToFsp = FALSE;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ASSERT (Icb->Signature == STRUCTURE_SIGNATURE_ICB);
|
|||
|
ASSERT (Irp->Flags & IRP_BUFFERED_IO);
|
|||
|
|
|||
|
dprintf(DPRT_VOLINFO, ("NtQueryVolumeInformationFile File Class %ld Buffer %lx, Length %lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass, UsersBuffer, BufferSize));
|
|||
|
|
|||
|
if (!RdrAcquireFcbLock(Icb->Fcb, SharedLock, Wait)) {
|
|||
|
RdrFsdPostToFsp(DeviceObject, Irp);
|
|||
|
return STATUS_PENDING;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Now make sure that the file that we are dealing with is of an
|
|||
|
// appropriate type for us to perform this operation.
|
|||
|
//
|
|||
|
// We can perform these operation on any file that has an instantiation
|
|||
|
// on the remote server, so ignore any that have either purely local
|
|||
|
// semantics, or on tree connections.
|
|||
|
//
|
|||
|
|
|||
|
Status = RdrIsOperationValid(ICB_OF(IrpSp), IRP_MJ_QUERY_VOLUME_INFORMATION, IrpSp->FileObject);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
try_return(Status);
|
|||
|
}
|
|||
|
|
|||
|
switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
|
|||
|
|
|||
|
case FileFsVolumeInformation:
|
|||
|
|
|||
|
QueueToFsp = QueryVolumeInfo(Irp, Icb,
|
|||
|
UsersBuffer,
|
|||
|
&BufferSize,
|
|||
|
&Status,
|
|||
|
Wait);
|
|||
|
break;
|
|||
|
|
|||
|
case FileFsSizeInformation:
|
|||
|
|
|||
|
QueueToFsp = QuerySizeInfo(Irp, Icb,
|
|||
|
UsersBuffer,
|
|||
|
&BufferSize,
|
|||
|
&Status,
|
|||
|
Wait);
|
|||
|
break;
|
|||
|
case FileFsDeviceInformation:
|
|||
|
|
|||
|
QueueToFsp = QueryDeviceInfo(Icb,
|
|||
|
UsersBuffer,
|
|||
|
&BufferSize,
|
|||
|
&Status,
|
|||
|
Wait);
|
|||
|
break;
|
|||
|
|
|||
|
case FileFsAttributeInformation:
|
|||
|
|
|||
|
QueueToFsp = QueryAttributeInfo(Irp, Icb,
|
|||
|
UsersBuffer,
|
|||
|
&BufferSize,
|
|||
|
&Status,
|
|||
|
Wait);
|
|||
|
break;
|
|||
|
|
|||
|
#ifdef _CAIRO_
|
|||
|
#ifdef _CAIRO_QUOTAS_
|
|||
|
case FileFsQuotaQueryInformation:
|
|||
|
QueueToFsp = QueryQuotaInfo(Irp, Icb,
|
|||
|
UsersBuffer,
|
|||
|
&BufferSize,
|
|||
|
&Status,
|
|||
|
Wait);
|
|||
|
break;
|
|||
|
|
|||
|
case FileFsControlQueryInformation:
|
|||
|
QueueToFsp = QueryControlInfo(Irp, Icb,
|
|||
|
UsersBuffer,
|
|||
|
&BufferSize,
|
|||
|
&Status,
|
|||
|
Wait);
|
|||
|
#endif // _CAIRO_QUOTAS_
|
|||
|
#endif // _CAIRO_
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
Status = STATUS_NOT_IMPLEMENTED;
|
|||
|
|
|||
|
};
|
|||
|
try_exit:NOTHING;
|
|||
|
} finally {
|
|||
|
RdrReleaseFcbLock(Icb->Fcb);
|
|||
|
}
|
|||
|
|
|||
|
if (QueueToFsp) {
|
|||
|
RdrFsdPostToFsp(DeviceObject, Irp);
|
|||
|
return STATUS_PENDING;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_ERROR(Status)) {
|
|||
|
Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length -
|
|||
|
BufferSize;
|
|||
|
}
|
|||
|
|
|||
|
dprintf(DPRT_VOLINFO, ("Returning status: %X\n", Status));
|
|||
|
|
|||
|
//
|
|||
|
// Complete the I/O request with the specified status.
|
|||
|
//
|
|||
|
|
|||
|
RdrCompleteRequest(Irp, Status);
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryVolumeInfo (
|
|||
|
IN PIRP Irp OPTIONAL,
|
|||
|
IN PICB Icb,
|
|||
|
OUT PFILE_FS_VOLUME_INFORMATION UsersBuffer,
|
|||
|
IN OUT PULONG BufferSize,
|
|||
|
OUT PNTSTATUS FinalStatus,
|
|||
|
IN BOOLEAN Wait
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FileFsVolumeInformation value of the
|
|||
|
NtQueryVolumeInformationFile api.
|
|||
|
|
|||
|
It returns the following information:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PICB Icb - Supplies the Icb associated with this request.
|
|||
|
|
|||
|
OUT PFILE_FS_VOLUME_INFORMATION UsersBuffer - Supplies the user's buffer
|
|||
|
that is filled in with the
|
|||
|
requested data.
|
|||
|
IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
|
|||
|
with the amount used.
|
|||
|
OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
|
|||
|
|
|||
|
IN BOOLEAN Wait - True if FSP can wait for this request.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (Icb->Fcb->Connection->Server->Capabilities & DF_LANMAN20) {
|
|||
|
|
|||
|
//
|
|||
|
// Use TRANSACT2_QFSINFO to get the Label and serial number
|
|||
|
// The other information is not available.
|
|||
|
|
|||
|
USHORT Setup[] = {TRANS2_QUERY_FS_INFORMATION};
|
|||
|
|
|||
|
REQ_QUERY_FS_INFORMATION Parameters;
|
|||
|
|
|||
|
UCHAR Buffer[MAX(sizeof(QFSINFO), sizeof(FILE_FS_VOLUME_INFORMATION) + MAXIMUM_FILENAME_LENGTH)];
|
|||
|
|
|||
|
PQFSINFO FsInfo = (PQFSINFO)Buffer;
|
|||
|
|
|||
|
CLONG OutParameterCount = sizeof(REQ_QUERY_FS_INFORMATION);
|
|||
|
|
|||
|
CLONG OutDataCount = sizeof(Buffer);
|
|||
|
|
|||
|
CLONG OutSetupCount = 0;
|
|||
|
|
|||
|
if (!Wait) {
|
|||
|
return TRUE; // FSP must process this request- we always hit the
|
|||
|
// network and must therefore block.
|
|||
|
}
|
|||
|
|
|||
|
if (Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) {
|
|||
|
|
|||
|
SmbPutAlignedUshort(&Parameters.InformationLevel, SMB_QUERY_FS_VOLUME_INFO);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Build and initialize the Parameters
|
|||
|
//
|
|||
|
|
|||
|
SmbPutAlignedUshort(&Parameters.InformationLevel, SMB_INFO_VOLUME);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*FinalStatus = RdrTransact(Irp, // Irp,
|
|||
|
Icb->Fcb->Connection,
|
|||
|
Icb->Se,
|
|||
|
Setup,
|
|||
|
(CLONG) sizeof(Setup), // InSetupCount,
|
|||
|
&OutSetupCount,
|
|||
|
NULL, // Name,
|
|||
|
&Parameters,
|
|||
|
sizeof(Parameters), // InParameterCount,
|
|||
|
&OutParameterCount,
|
|||
|
NULL, // InData,
|
|||
|
0, // InDataCount,
|
|||
|
Buffer, // OutData,
|
|||
|
&OutDataCount,
|
|||
|
NULL, // Fid
|
|||
|
0, // Timeout
|
|||
|
(USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
if (Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) {
|
|||
|
PFILE_FS_VOLUME_INFORMATION VolInfo = (PFILE_FS_VOLUME_INFORMATION)Buffer;
|
|||
|
|
|||
|
if (Icb->Fcb->Connection->Server->Capabilities & DF_UNICODE) {
|
|||
|
|
|||
|
if (*BufferSize < sizeof(FILE_FS_VOLUME_INFORMATION)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_TOO_SMALL;
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Put as much as is possible into the users buffer, either
|
|||
|
// the full information returned or the users buffer.
|
|||
|
//
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer, VolInfo, MIN(*BufferSize, OutDataCount));
|
|||
|
|
|||
|
//
|
|||
|
// If the entire buffer wouldn't fit, then return an
|
|||
|
// error.
|
|||
|
//
|
|||
|
|
|||
|
if (OutDataCount > *BufferSize) {
|
|||
|
|
|||
|
//
|
|||
|
// There's no more user buffer remaining.
|
|||
|
//
|
|||
|
|
|||
|
*BufferSize = 0;
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Account for this buffer in the request.
|
|||
|
//
|
|||
|
|
|||
|
*BufferSize -= OutDataCount;
|
|||
|
|
|||
|
} else {
|
|||
|
UNICODE_STRING UnicodeString;
|
|||
|
OEM_STRING OemString;
|
|||
|
|
|||
|
if (*BufferSize < OutDataCount) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy over the fixed portion of the buffer.
|
|||
|
//
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer, VolInfo, FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel));
|
|||
|
|
|||
|
OemString.Buffer = (PUCHAR)VolInfo->VolumeLabel;
|
|||
|
OemString.Length = (USHORT)VolInfo->VolumeLabelLength;
|
|||
|
OemString.MaximumLength = (USHORT)VolInfo->VolumeLabelLength;
|
|||
|
|
|||
|
UnicodeString.Buffer = UsersBuffer->VolumeLabel;
|
|||
|
UnicodeString.MaximumLength = (USHORT)(*BufferSize - FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel));
|
|||
|
|
|||
|
*FinalStatus = RtlOemStringToUnicodeString(&UnicodeString, &OemString, FALSE);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
|
|||
|
//
|
|||
|
// Account for this buffer in the request.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->VolumeLabelLength = UnicodeString.Length;
|
|||
|
|
|||
|
*BufferSize -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION,
|
|||
|
VolumeLabel)+UsersBuffer->VolumeLabelLength;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
} else {
|
|||
|
if (*BufferSize < sizeof(FILE_FS_VOLUME_INFORMATION)+FsInfo->cch*sizeof(WCHAR)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
} else {
|
|||
|
|
|||
|
UsersBuffer->VolumeCreationTime.LowPart = 0;
|
|||
|
UsersBuffer->VolumeCreationTime.HighPart = 0;
|
|||
|
UsersBuffer->VolumeSerialNumber = FsInfo->ulVSN;
|
|||
|
UsersBuffer->SupportsObjects = FALSE;
|
|||
|
|
|||
|
if (Icb->Fcb->Connection->Server->Capabilities & DF_UNICODE) {
|
|||
|
PWSTR label = ALIGN_SMB_WSTR(FsInfo->szVolLabel);
|
|||
|
wcsncpy(UsersBuffer->VolumeLabel, label, FsInfo->cch/2);
|
|||
|
|
|||
|
*BufferSize -= (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel)+FsInfo->cch);
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
} else {
|
|||
|
UNICODE_STRING VolumeLabelU;
|
|||
|
OEM_STRING VolumeLabelA;
|
|||
|
ULONG BytesToCopy;
|
|||
|
|
|||
|
|
|||
|
VolumeLabelA.Length = FsInfo->cch;
|
|||
|
VolumeLabelA.MaximumLength = FsInfo->cch;
|
|||
|
VolumeLabelA.Buffer = FsInfo->szVolLabel;
|
|||
|
|
|||
|
*FinalStatus = RtlOemStringToUnicodeString(&VolumeLabelU, &VolumeLabelA, TRUE);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
BytesToCopy = MIN((ULONG)VolumeLabelU.Length, (*BufferSize-sizeof(FILE_FS_VOLUME_INFORMATION)));
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer->VolumeLabel, VolumeLabelU.Buffer, BytesToCopy);
|
|||
|
|
|||
|
RtlFreeUnicodeString(&VolumeLabelU);
|
|||
|
|
|||
|
UsersBuffer->VolumeLabelLength = VolumeLabelU.Length;
|
|||
|
|
|||
|
*BufferSize -= (sizeof(FILE_FS_VOLUME_INFORMATION)-1+BytesToCopy);
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// This is a < LANMAN 2.0 Server
|
|||
|
//
|
|||
|
|
|||
|
UNICODE_STRING VolumeLabelU;
|
|||
|
OEM_STRING VolumeLabelA;
|
|||
|
SMB_DIRECTORY_INFORMATION Buffer;
|
|||
|
ULONG NameLength;
|
|||
|
ULONG BytesToCopy = 0;
|
|||
|
|
|||
|
if (!Wait) {
|
|||
|
return TRUE; // FSP must process this request- we always hit the
|
|||
|
// network and must therefore block.
|
|||
|
}
|
|||
|
|
|||
|
*FinalStatus = ReadCoreLabel(Irp, Icb, &Buffer);
|
|||
|
|
|||
|
UsersBuffer->SupportsObjects = FALSE;
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
|
|||
|
UsersBuffer->VolumeCreationTime.LowPart = 0;
|
|||
|
UsersBuffer->VolumeCreationTime.HighPart = 0;
|
|||
|
UsersBuffer->VolumeSerialNumber =
|
|||
|
(((SmbGetUshort(&Buffer.LastWriteTime.Ushort)) << 16) |
|
|||
|
(SmbGetUshort(&Buffer.LastWriteDate.Ushort)));
|
|||
|
|
|||
|
NAME_LENGTH(NameLength, Buffer.FileName, MAXIMUM_COMPONENT_CORE);
|
|||
|
|
|||
|
VolumeLabelA.Length = (USHORT )NameLength;
|
|||
|
VolumeLabelA.MaximumLength = (USHORT )NameLength;
|
|||
|
VolumeLabelA.Buffer = Buffer.FileName;
|
|||
|
|
|||
|
*FinalStatus = RtlOemStringToUnicodeString(&VolumeLabelU, &VolumeLabelA, TRUE);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
|
|||
|
BytesToCopy = MIN((ULONG)VolumeLabelU.Length, (*BufferSize-sizeof(FILE_FS_VOLUME_INFORMATION)));
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer->VolumeLabel,
|
|||
|
VolumeLabelU.Buffer,
|
|||
|
BytesToCopy);
|
|||
|
|
|||
|
if (( BytesToCopy >= (9 * sizeof(WCHAR)) ) &&
|
|||
|
( VolumeLabelU.Buffer[8] == L'.' )) {
|
|||
|
|
|||
|
//
|
|||
|
// Some downlevel servers insert a dot in the 11 byte
|
|||
|
// volume label. Remove it.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
if ( BytesToCopy > (9 * sizeof(WCHAR)) ) {
|
|||
|
|
|||
|
//
|
|||
|
// Copy characters after dot. Use VolumeLabelU
|
|||
|
// to get the characters to avoid using RtlMoveMemory
|
|||
|
// instead of RtlCopyMemory.
|
|||
|
//
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
&UsersBuffer->VolumeLabel[8],
|
|||
|
&VolumeLabelU.Buffer[9],
|
|||
|
BytesToCopy - (9 * sizeof(WCHAR)));
|
|||
|
|
|||
|
} // else last character was the dot
|
|||
|
|
|||
|
VolumeLabelU.Length -= sizeof(L'.');
|
|||
|
|
|||
|
BytesToCopy -= sizeof(WCHAR);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RtlFreeUnicodeString(&VolumeLabelU);
|
|||
|
|
|||
|
UsersBuffer->VolumeLabelLength = VolumeLabelU.Length;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
//
|
|||
|
// If we got no such file, this means that there's no volume label
|
|||
|
// the remote volume. Return success with no data.
|
|||
|
//
|
|||
|
if (*FinalStatus == STATUS_NO_SUCH_FILE) {
|
|||
|
|
|||
|
UsersBuffer->VolumeCreationTime.LowPart = 0;
|
|||
|
UsersBuffer->VolumeCreationTime.HighPart = 0;
|
|||
|
UsersBuffer->VolumeSerialNumber = 0;
|
|||
|
UsersBuffer->VolumeLabelLength = 0;
|
|||
|
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
|
|||
|
VolumeLabelU.Length = 0;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
*BufferSize -= (sizeof(FILE_FS_VOLUME_INFORMATION)-1+BytesToCopy);
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryDeviceInfo(
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_DEVICE_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FileFsSizeInformation value of the
|
|||
|
NtQueryVolumeInformationFile api. It returns the following information:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PICB Icb - Supplies the Icb associated with this request.
|
|||
|
|
|||
|
OUT PFILE_FS_DEVICE_INFORMATION UsersBuffer - Supplies the user's buffer
|
|||
|
that is filled in with the
|
|||
|
requested data.
|
|||
|
IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
|
|||
|
with the amount used.
|
|||
|
OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
|
|||
|
|
|||
|
IN BOOLEAN Wait - True if FSP can wait for this request.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
|
|||
|
if (*BufferSize < sizeof(FILE_FS_DEVICE_INFORMATION)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
} else {
|
|||
|
|
|||
|
UsersBuffer->Characteristics = FILE_REMOTE_DEVICE;
|
|||
|
switch (Icb->Type) {
|
|||
|
case DiskFile:
|
|||
|
case Directory:
|
|||
|
case FileOrDirectory:
|
|||
|
case NetRoot:
|
|||
|
case ServerRoot:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_DISK;
|
|||
|
break;
|
|||
|
|
|||
|
case TreeConnect:
|
|||
|
|
|||
|
//
|
|||
|
// On a tree connection, we determine the type of device from
|
|||
|
// the connection type.
|
|||
|
//
|
|||
|
|
|||
|
switch (Icb->Fcb->Connection->Type) {
|
|||
|
case CONNECT_DISK:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_DISK;
|
|||
|
break;
|
|||
|
case CONNECT_PRINT:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_PRINTER;
|
|||
|
break;
|
|||
|
case CONNECT_COMM:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_SERIAL_PORT;
|
|||
|
break;
|
|||
|
case CONNECT_IPC:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_NAMED_PIPE;
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case Redirector:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
|||
|
break;
|
|||
|
case PrinterFile:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_PRINTER;
|
|||
|
break;
|
|||
|
case NamedPipe:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_NAMED_PIPE;
|
|||
|
break;
|
|||
|
case Com:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_SERIAL_PORT;
|
|||
|
break;
|
|||
|
case Mailslot:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_MAILSLOT;
|
|||
|
break;
|
|||
|
default:
|
|||
|
UsersBuffer->DeviceType = FILE_DEVICE_UNKNOWN;
|
|||
|
InternalError(("Unknown file type %lx passed to QueryDeviceInfo\n", Icb->Type));
|
|||
|
break;
|
|||
|
}
|
|||
|
*BufferSize -= (sizeof(FILE_FS_DEVICE_INFORMATION));
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if (Icb||Wait);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryAttributeInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_ATTRIBUTE_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FileFsAttributeInformation value of the
|
|||
|
NtQueryVolumeInformationFile api. It returns the following information:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PICB Icb - Supplies the Icb associated with this request.
|
|||
|
|
|||
|
OUT PFILE_FS_ATTRIBUTE_INFORMATION UsersBuffer - Supplies the user's buffer
|
|||
|
that is filled in with the
|
|||
|
requested data.
|
|||
|
IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
|
|||
|
with the amount used.
|
|||
|
OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
|
|||
|
|
|||
|
IN BOOLEAN Wait - True if FSP can wait for this request.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (*BufferSize < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_TOO_SMALL;
|
|||
|
} else {
|
|||
|
if (Icb->Fcb->Connection->Server->Capabilities & DF_NT_FIND) {
|
|||
|
|
|||
|
if (Icb->Fcb->Connection->MaximumComponentLength == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Use TRANSACT2_QFSINFO to get the Label and serial number
|
|||
|
// The serial number is not used.
|
|||
|
|
|||
|
USHORT Setup[] = {TRANS2_QUERY_FS_INFORMATION};
|
|||
|
|
|||
|
REQ_QUERY_FS_INFORMATION Parameters;
|
|||
|
|
|||
|
UCHAR Buffer[MAX(sizeof(QFSINFO), sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAXIMUM_FILENAME_LENGTH)];
|
|||
|
|
|||
|
PQFSINFO FsInfo = (PQFSINFO)Buffer;
|
|||
|
|
|||
|
CLONG OutParameterCount = sizeof(REQ_QUERY_FS_INFORMATION);
|
|||
|
|
|||
|
CLONG OutDataCount = sizeof(Buffer);
|
|||
|
|
|||
|
CLONG OutSetupCount = 0;
|
|||
|
|
|||
|
if (!Wait) {
|
|||
|
return TRUE; // FSP must process this request- we always hit the
|
|||
|
// network and must therefore block.
|
|||
|
}
|
|||
|
|
|||
|
SmbPutAlignedUshort(&Parameters.InformationLevel, SMB_QUERY_FS_ATTRIBUTE_INFO);
|
|||
|
|
|||
|
//
|
|||
|
// Build and initialize the Parameters
|
|||
|
//
|
|||
|
|
|||
|
*FinalStatus = RdrTransact(Irp, // Irp,
|
|||
|
Icb->Fcb->Connection,
|
|||
|
Icb->Se,
|
|||
|
Setup,
|
|||
|
(CLONG) sizeof(Setup), // InSetupCount,
|
|||
|
&OutSetupCount,
|
|||
|
NULL, // Name,
|
|||
|
&Parameters,
|
|||
|
sizeof(Parameters), // InParameterCount,
|
|||
|
&OutParameterCount,
|
|||
|
NULL, // InData,
|
|||
|
0, // InDataCount,
|
|||
|
Buffer, // OutData,
|
|||
|
&OutDataCount,
|
|||
|
NULL, // Fid
|
|||
|
0, // Timeout
|
|||
|
(USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
PFILE_FS_ATTRIBUTE_INFORMATION AttribInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
|
|||
|
|
|||
|
if (*BufferSize < OutDataCount) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
} else {
|
|||
|
RtlCopyMemory(UsersBuffer, AttribInfo, OutDataCount);
|
|||
|
|
|||
|
if (Icb->Fcb->Connection->MaximumComponentLength == 0) {
|
|||
|
Icb->Fcb->Connection->MaximumComponentLength = AttribInfo->MaximumComponentNameLength;
|
|||
|
Icb->Fcb->Connection->FileSystemAttributes = AttribInfo->FileSystemAttributes;
|
|||
|
} else {
|
|||
|
ASSERT(Icb->Fcb->Connection->MaximumComponentLength == AttribInfo->MaximumComponentNameLength);
|
|||
|
ASSERT(Icb->Fcb->Connection->FileSystemAttributes == AttribInfo->FileSystemAttributes);
|
|||
|
}
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
Icb->Fcb->Connection->FileSystemType,
|
|||
|
AttribInfo->FileSystemName,
|
|||
|
MIN(AttribInfo->FileSystemNameLength, LM20_DEVLEN*sizeof(WCHAR))
|
|||
|
);
|
|||
|
Icb->Fcb->Connection->FileSystemTypeLength =
|
|||
|
(USHORT)MIN(AttribInfo->FileSystemNameLength, LM20_DEVLEN*sizeof(WCHAR));
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
if (*BufferSize <= (ULONG)(FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName)+Icb->Fcb->Connection->FileSystemTypeLength)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
} else {
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = Icb->Fcb->Connection->MaximumComponentLength;
|
|||
|
UsersBuffer->FileSystemAttributes = Icb->Fcb->Connection->FileSystemAttributes;
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer->FileSystemName, Icb->Fcb->Connection->FileSystemType, Icb->Fcb->Connection->FileSystemTypeLength);
|
|||
|
UsersBuffer->FileSystemNameLength = Icb->Fcb->Connection->FileSystemTypeLength;
|
|||
|
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else if (Icb->Fcb->Connection->Server->Capabilities & DF_LANMAN21) {
|
|||
|
|
|||
|
if (*BufferSize < (ULONG)(FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName)+Icb->Fcb->Connection->FileSystemTypeLength)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
} else {
|
|||
|
if (Icb->Fcb->Connection->FileSystemTypeLength == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// We don't know what type of file system this is, so
|
|||
|
// assume the redirector defaults.
|
|||
|
//
|
|||
|
// wcsncmp will return 0 if the length is 0.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = 255;
|
|||
|
UsersBuffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES;
|
|||
|
|
|||
|
} else if (wcsncmp(Icb->Fcb->Connection->FileSystemType, L"FAT", Icb->Fcb->Connection->FileSystemTypeLength) == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// We know that this is a FAT file system.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = 12;
|
|||
|
UsersBuffer->FileSystemAttributes = 0;
|
|||
|
|
|||
|
} else if (wcsncmp(Icb->Fcb->Connection->FileSystemType, L"HPFS", Icb->Fcb->Connection->FileSystemTypeLength) == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// We know that this is HPFS, so we can assume it's HPFS size.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = 254;
|
|||
|
UsersBuffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES;
|
|||
|
|
|||
|
} else if (wcsncmp(Icb->Fcb->Connection->FileSystemType, L"HPFS386", Icb->Fcb->Connection->FileSystemTypeLength) == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// We know that this is HPFS, so we can assume it's HPFS size.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = 254;
|
|||
|
UsersBuffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// If we could determine the type of file system on the remote
|
|||
|
// media, we could make a better guess at this, but until we
|
|||
|
// have this capability (LM 2.1), we have to guess.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = 255;
|
|||
|
UsersBuffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES;
|
|||
|
}
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer->FileSystemName, Icb->Fcb->Connection->FileSystemType, Icb->Fcb->Connection->FileSystemTypeLength);
|
|||
|
UsersBuffer->FileSystemNameLength = Icb->Fcb->Connection->FileSystemTypeLength;
|
|||
|
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
} else if (Icb->Fcb->Connection->Server->Capabilities & DF_LANMAN20) {
|
|||
|
if (*BufferSize < FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName)+sizeof(DD_NFS_FILESYS_NAME_U)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// If we could determine the type of file system on the remote
|
|||
|
// media, we could make a better guess at this, but until we
|
|||
|
// have this capability (LM 2.1), we have to guess.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = 255;
|
|||
|
UsersBuffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES;
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer->FileSystemName, DD_NFS_FILESYS_NAME_U, sizeof(DD_NFS_FILESYS_NAME_U) - sizeof(WCHAR));
|
|||
|
UsersBuffer->FileSystemNameLength = sizeof(DD_NFS_FILESYS_NAME_U) - sizeof(WCHAR);
|
|||
|
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (*BufferSize < FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName)+sizeof(L"FAT")) {
|
|||
|
*FinalStatus = STATUS_BUFFER_OVERFLOW;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// We know that all non lanman 2.0 servers must have FAT
|
|||
|
// filesystems, so we should use FAT naming conventions.
|
|||
|
//
|
|||
|
|
|||
|
UsersBuffer->MaximumComponentNameLength = 12;
|
|||
|
UsersBuffer->FileSystemAttributes = 0;
|
|||
|
|
|||
|
RtlCopyMemory(UsersBuffer->FileSystemName, L"FAT", sizeof(L"FAT") - sizeof(WCHAR));
|
|||
|
UsersBuffer->FileSystemNameLength = sizeof(L"FAT") - sizeof(WCHAR);
|
|||
|
|
|||
|
*FinalStatus = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
*BufferSize -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + UsersBuffer->FileSystemNameLength);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if (Icb||Wait);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QuerySizeInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_SIZE_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FileFsSizeInformation value of the
|
|||
|
NtQueryVolumeInformationFile api. It returns the following information:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
IN PIRP Irp - Supplies an Irp to use for this request.
|
|||
|
|
|||
|
IN PICB Icb - Supplies the Icb associated with this request.
|
|||
|
|
|||
|
OUT PFILE_FS_SIZE_INFORMATION UsersBuffer - Supplies the user's buffer
|
|||
|
that is filled in with the
|
|||
|
requested data.
|
|||
|
IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
|
|||
|
with the amount used.
|
|||
|
OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
|
|||
|
|
|||
|
IN BOOLEAN Wait - True if FSP can wait for this request.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONNECTLISTENTRY *connection = Icb->Fcb->Connection;
|
|||
|
LARGE_INTEGER currentTime;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
KeQuerySystemTime( ¤tTime );
|
|||
|
|
|||
|
if (*BufferSize < sizeof(FILE_FS_SIZE_INFORMATION)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_TOO_SMALL;
|
|||
|
|
|||
|
} else if( currentTime.QuadPart <= connection->FsSizeInformationExpiration.QuadPart ) {
|
|||
|
//
|
|||
|
// We have the information in our cache... use it!
|
|||
|
//
|
|||
|
RtlCopyMemory( UsersBuffer,
|
|||
|
&connection->FsSizeInformation,
|
|||
|
sizeof( FILE_FS_SIZE_INFORMATION ) );
|
|||
|
|
|||
|
*BufferSize -= sizeof(FILE_FS_SIZE_INFORMATION);
|
|||
|
|
|||
|
} else {
|
|||
|
//
|
|||
|
// We can not use our cached information -- need to hit the server
|
|||
|
//
|
|||
|
|
|||
|
if (!Wait) {
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
*FinalStatus = RdrQueryDiskAttributes(Irp, Icb,
|
|||
|
&UsersBuffer->TotalAllocationUnits,
|
|||
|
&UsersBuffer->AvailableAllocationUnits,
|
|||
|
&UsersBuffer->SectorsPerAllocationUnit,
|
|||
|
&UsersBuffer->BytesPerSector);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
|
|||
|
connection->FileSystemGranularity =
|
|||
|
UsersBuffer->SectorsPerAllocationUnit *
|
|||
|
UsersBuffer->BytesPerSector;
|
|||
|
|
|||
|
connection->FileSystemSize.QuadPart =
|
|||
|
UsersBuffer->TotalAllocationUnits.QuadPart *
|
|||
|
UsersBuffer->SectorsPerAllocationUnit * UsersBuffer->BytesPerSector;
|
|||
|
|
|||
|
*BufferSize -= sizeof(FILE_FS_SIZE_INFORMATION);
|
|||
|
|
|||
|
connection->FsSizeInformation.TotalAllocationUnits =
|
|||
|
UsersBuffer->TotalAllocationUnits;
|
|||
|
connection->FsSizeInformation.AvailableAllocationUnits =
|
|||
|
UsersBuffer->AvailableAllocationUnits;
|
|||
|
connection->FsSizeInformation.SectorsPerAllocationUnit =
|
|||
|
UsersBuffer->SectorsPerAllocationUnit;
|
|||
|
connection->FsSizeInformation.BytesPerSector =
|
|||
|
UsersBuffer->BytesPerSector;
|
|||
|
|
|||
|
KeQuerySystemTime( ¤tTime );
|
|||
|
//
|
|||
|
// Expires in 2 seconds
|
|||
|
//
|
|||
|
connection->FsSizeInformationExpiration.QuadPart = currentTime.QuadPart + 2*10*1000*1000;
|
|||
|
}
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
NTSTATUS
|
|||
|
ReadCoreLabel(
|
|||
|
IN PIRP Irp,
|
|||
|
IN PICB Icb,
|
|||
|
OUT PSMB_DIRECTORY_INFORMATION UsersBuffer
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine uses the search SMB to read a disk volume label and serial
|
|||
|
number. It is used for all servers negotiating Core or Lanman 1.0.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PICB Icb - Supplies the ICB with the associated SearchControlBlock
|
|||
|
|
|||
|
OUT PSMB_DIRECTORY_INFORMATION UsersBuffer - Supplies the user's buffer
|
|||
|
that is filled in with the requested data.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
PSMB_BUFFER SmbBuffer;
|
|||
|
PSMB_HEADER Smb;
|
|||
|
PUCHAR TrailingBytes;
|
|||
|
NTSTATUS Status;
|
|||
|
PREQ_SEARCH Search;
|
|||
|
PCORELABELCONTEXT Context = NULL;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Context = ALLOCATE_POOL(NonPagedPool, sizeof(CORELABELCONTEXT), POOL_CORELABELCONTEXT);
|
|||
|
|
|||
|
if (Context == NULL) {
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
if ((SmbBuffer = RdrAllocateSMBBuffer()) == NULL) {
|
|||
|
FREE_POOL(Context);
|
|||
|
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
Smb = (PSMB_HEADER )SmbBuffer->Buffer;
|
|||
|
Search = (PREQ_SEARCH)(Smb+1);
|
|||
|
|
|||
|
Smb->Command = SMB_COM_SEARCH;
|
|||
|
Search->WordCount = 2;
|
|||
|
SmbPutUshort(&Search->MaxCount, 1);
|
|||
|
|
|||
|
SmbPutUshort(&Search->SearchAttributes, SMB_FILE_ATTRIBUTE_VOLUME);
|
|||
|
|
|||
|
// Calculate the addresses of the various buffers.
|
|||
|
|
|||
|
TrailingBytes = ((PUCHAR)Search)+sizeof(REQ_SEARCH)-1;
|
|||
|
|
|||
|
//TrailingBytes now points to where the 0x04 of FileName is to go.
|
|||
|
|
|||
|
*TrailingBytes++ = SMB_FORMAT_ASCII;
|
|||
|
|
|||
|
Status = RdrCopyUnicodeStringToAscii( &TrailingBytes, &RdrAll8dot3Files, TRUE, MAXIMUM_FILENAME_LENGTH);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
RdrFreeSMBBuffer(SmbBuffer);
|
|||
|
|
|||
|
FREE_POOL(Context);
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
*TrailingBytes++ = '\0';
|
|||
|
|
|||
|
*TrailingBytes++ = SMB_FORMAT_VARIABLE;
|
|||
|
*TrailingBytes++ = 0; //smb_keylen must be zero
|
|||
|
*TrailingBytes = 0; //smb_keylen must be zero
|
|||
|
|
|||
|
SmbPutUshort(&Search->ByteCount,(
|
|||
|
(USHORT)(TrailingBytes-(PUCHAR)Search-sizeof(REQ_SEARCH)+2)
|
|||
|
// the plus 2 is for the last smb_keylen and REQ_SEARCH.Buffer[1]
|
|||
|
));
|
|||
|
|
|||
|
SmbBuffer->Mdl->ByteCount = (ULONG)(TrailingBytes - (PUCHAR)(Smb)+1);
|
|||
|
|
|||
|
Context->Header.Type = CONTEXT_CORE_LABEL;
|
|||
|
Context->Header.TransferSize =
|
|||
|
SmbBuffer->Mdl->ByteCount +
|
|||
|
sizeof(RESP_SEARCH) +
|
|||
|
sizeof(SMB_DIRECTORY_INFORMATION);
|
|||
|
|
|||
|
Status = RdrNetTranceiveWithCallback(NT_NORMAL, Irp,
|
|||
|
Icb->Fcb->Connection,
|
|||
|
SmbBuffer->Mdl,
|
|||
|
Context,
|
|||
|
CoreLabelCallBack,
|
|||
|
Icb->Se,
|
|||
|
NULL);
|
|||
|
|
|||
|
RdrFreeSMBBuffer(SmbBuffer);
|
|||
|
|
|||
|
if ( Status == STATUS_NO_MORE_FILES ) {
|
|||
|
FREE_POOL(Context);
|
|||
|
|
|||
|
return STATUS_NO_SUCH_FILE;
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
RtlCopyMemory( UsersBuffer,
|
|||
|
&Context->Result,
|
|||
|
sizeof(SMB_DIRECTORY_INFORMATION));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
FREE_POOL(Context);
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
STANDARD_CALLBACK_HEADER (
|
|||
|
CoreLabelCallBack
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the callback routine for the processing of a Search SMB.
|
|||
|
|
|||
|
It copies the resulting information from the SMB into the context block.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
IN PSMB_HEADER Smb - SMB response from server.
|
|||
|
IN PMPX_ENTRY MpxTable - MPX table entry for request.
|
|||
|
IN PCORELABELCONTEXT Context - Context from caller.
|
|||
|
IN BOOLEAN ErrorIndicator - TRUE if error indication
|
|||
|
IN NTSTATUS NetworkErrorCode OPTIONAL - Network error if error indication.
|
|||
|
IN OUT PIRP *Irp - IRP from TDI
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of the request
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PRESP_SEARCH SearchResponse;
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PCORELABELCONTEXT Context = Ctx;
|
|||
|
|
|||
|
DISCARDABLE_CODE(RdrFileDiscardableSection);
|
|||
|
|
|||
|
ASSERT(Context->Header.Type == CONTEXT_CORE_LABEL);
|
|||
|
|
|||
|
dprintf(DPRT_DIRECTORY, ("CoreLabelComplete\n"));
|
|||
|
|
|||
|
Context->Header.ErrorType = NoError; // Assume no error at first.
|
|||
|
|
|||
|
//
|
|||
|
// If we are called because the VC dropped, indicate it in the response
|
|||
|
//
|
|||
|
|
|||
|
if (ErrorIndicator) {
|
|||
|
Context->Header.ErrorType = NetError;
|
|||
|
Context->Header.ErrorCode = RdrMapNetworkError(NetworkErrorCode);
|
|||
|
goto ReturnStatus;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status = RdrMapSmbError(Smb, Server))) {
|
|||
|
Context->Header.ErrorType = SMBError;
|
|||
|
Context->Header.ErrorCode = Status;
|
|||
|
goto ReturnStatus;
|
|||
|
}
|
|||
|
|
|||
|
SearchResponse = (PRESP_SEARCH )(Smb+1);
|
|||
|
ASSERT(SearchResponse->WordCount == 1);
|
|||
|
|
|||
|
if (SmbGetUshort(&SearchResponse->Count) != 1) {
|
|||
|
// If theres nothing there then on core servers count-returned == 0
|
|||
|
Context->Header.ErrorType = SMBError;
|
|||
|
Context->Header.ErrorCode = STATUS_NO_MORE_FILES;
|
|||
|
goto ReturnStatus;
|
|||
|
} else {
|
|||
|
RtlCopyMemory(&Context->Result,
|
|||
|
&SearchResponse->Buffer[0]+3,
|
|||
|
sizeof(SMB_DIRECTORY_INFORMATION));
|
|||
|
}
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
Context->Header.ErrorType = SMBError;
|
|||
|
Context->Header.ErrorCode = Status;
|
|||
|
}
|
|||
|
|
|||
|
// Set the event that allows CoreLabel to continue
|
|||
|
ReturnStatus:
|
|||
|
KeSetEvent(&Context->Header.KernelEvent, IO_NETWORK_INCREMENT, FALSE);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
if (SmbLength || MpxEntry || Irp || Server);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#ifdef _CAIRO_
|
|||
|
#ifdef _CAIRO_QUOTAS_
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryQuotaInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_QUOTA_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FileFsQuotaQueryInformation value of the
|
|||
|
NtQueryVolumeInformationFile api. It returns the following information:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PIRP Irp - Supplies an Irp to use for this request.
|
|||
|
|
|||
|
IN PICB Icb - Supplies the Icb associated with this request.
|
|||
|
|
|||
|
OUT PFILE_QUOTA_INFORMATION UsersBuffer - Supplies the user's buffer
|
|||
|
that is filled in with the
|
|||
|
requested data.
|
|||
|
IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
|
|||
|
with the amount used.
|
|||
|
OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
|
|||
|
|
|||
|
IN BOOLEAN Wait - True if FSP can wait for this request.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (*BufferSize < sizeof(FILE_QUOTA_INFORMATION)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_TOO_SMALL;
|
|||
|
} else {
|
|||
|
|
|||
|
if (!Wait) {
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
*FinalStatus = RdrQueryDiskQuota(Irp, Icb, UsersBuffer, BufferSize);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
//*BufferSize -= sizeof(FILE_QUOTA_INFORMATION);
|
|||
|
}
|
|||
|
}
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DBGSTATIC
|
|||
|
BOOLEAN
|
|||
|
QueryControlInfo(
|
|||
|
PIRP Irp,
|
|||
|
PICB Icb,
|
|||
|
PFILE_FS_CONTROL_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize,
|
|||
|
PNTSTATUS FinalStatus,
|
|||
|
BOOLEAN Wait
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FileFsControlQueryInformation value of the
|
|||
|
NtQueryVolumeInformationFile api. It returns the following information:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PIRP Irp - Supplies an Irp to use for this request.
|
|||
|
|
|||
|
IN PICB Icb - Supplies the Icb associated with this request.
|
|||
|
|
|||
|
OUT PFILE_FS_CONTROL_INFORMATION UsersBuffer - Supplies the user's buffer
|
|||
|
that is filled in with the
|
|||
|
requested data.
|
|||
|
IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
|
|||
|
with the amount used.
|
|||
|
OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
|
|||
|
|
|||
|
IN BOOLEAN Wait - True if FSP can wait for this request.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (*BufferSize < sizeof(FILE_FS_CONTROL_INFORMATION)) {
|
|||
|
*FinalStatus = STATUS_BUFFER_TOO_SMALL;
|
|||
|
} else {
|
|||
|
|
|||
|
if (!Wait) {
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
*FinalStatus = RdrQueryDiskControl(Irp, Icb, UsersBuffer);
|
|||
|
|
|||
|
if (NT_SUCCESS(*FinalStatus)) {
|
|||
|
*BufferSize -= sizeof(FILE_FS_CONTROL_INFORMATION);
|
|||
|
}
|
|||
|
}
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RdrQueryDiskQuota(
|
|||
|
IN PIRP Irp OPTIONAL,
|
|||
|
IN PICB Icb,
|
|||
|
PFILE_QUOTA_INFORMATION UsersBuffer,
|
|||
|
PULONG BufferSize)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine returns information about the file system backing a share
|
|||
|
on the specified remote server.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PIRP Irp - Supplies an optional I/O Request packet to use for the
|
|||
|
SMBdskattr request.
|
|||
|
IN PICB Icb - Supplies an ICB associated with the file to check.
|
|||
|
|
|||
|
OUT PFILE_QUOTA_INFORMATION UsersBuffer - Returns the quota info
|
|||
|
|
|||
|
IN OUT PULONG BufferSize - Adjusted by the size returned
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
USHORT Setup[1];
|
|||
|
REQ_QUERY_FS_INFORMATION_FID ParameterBuf;
|
|||
|
CLONG OutParameterCount;
|
|||
|
CLONG OutSetupCount = 0;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if ((Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) == 0) {
|
|||
|
return(STATUS_INVALID_DEVICE_REQUEST);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Use TRANSACT2_QFSINFO to get the volume size information
|
|||
|
//
|
|||
|
|
|||
|
BuildTrans2QueryRequest(
|
|||
|
Icb,
|
|||
|
SMB_QUERY_QUOTA_INFO,
|
|||
|
0,
|
|||
|
Setup,
|
|||
|
(UCHAR *) &ParameterBuf,
|
|||
|
&OutParameterCount);
|
|||
|
|
|||
|
Status = RdrTransact(
|
|||
|
Irp, // Irp,PICB
|
|||
|
Icb->Fcb->Connection,
|
|||
|
Icb->Se,
|
|||
|
Setup,
|
|||
|
(CLONG) sizeof(Setup), // InSetupCount,
|
|||
|
&OutSetupCount,
|
|||
|
NULL, // Name,
|
|||
|
&ParameterBuf,
|
|||
|
OutParameterCount, // InParameterCount,
|
|||
|
&OutParameterCount,
|
|||
|
NULL, // InData,
|
|||
|
0, // InDataCount,
|
|||
|
UsersBuffer, // OutData,
|
|||
|
BufferSize,
|
|||
|
NULL, // Fid
|
|||
|
0, // Timeout
|
|||
|
FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? (USHORT) SMB_TRANSACTION_DFSFILE : 0,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RdrQueryDiskControl(
|
|||
|
IN PIRP Irp OPTIONAL,
|
|||
|
IN PICB Icb,
|
|||
|
PFILE_FS_CONTROL_INFORMATION UsersBuffer)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine returns information about the file system backing a share
|
|||
|
on the specified remote server.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PIRP Irp - Supplies an optional I/O Request packet to use for the
|
|||
|
SMBdskattr request.
|
|||
|
IN PICB Icb - Supplies an ICB associated with the file to check.
|
|||
|
|
|||
|
OUT PFILE_FS_CONTROL_INFORMATION UsersBuffer - Returns the quota info
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Status of operation performed.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
USHORT Setup[1];
|
|||
|
REQ_QUERY_FS_INFORMATION_FID ParameterBuf;
|
|||
|
CLONG OutParameterCount;
|
|||
|
CLONG OutDataCount = sizeof(*UsersBuffer);
|
|||
|
CLONG OutSetupCount = 0;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if ((Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) == 0) {
|
|||
|
return(STATUS_INVALID_DEVICE_REQUEST);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Use TRANSACT2_QFSINFO to get the volume size information
|
|||
|
//
|
|||
|
|
|||
|
BuildTrans2QueryRequest(
|
|||
|
Icb,
|
|||
|
SMB_QUERY_FS_CONTROL_INFO,
|
|||
|
0,
|
|||
|
Setup,
|
|||
|
(UCHAR *) &ParameterBuf,
|
|||
|
&OutParameterCount);
|
|||
|
|
|||
|
Status = RdrTransact(
|
|||
|
Irp, // Irp,PICB
|
|||
|
Icb->Fcb->Connection,
|
|||
|
Icb->Se,
|
|||
|
Setup,
|
|||
|
(CLONG) sizeof(Setup), // InSetupCount,
|
|||
|
&OutSetupCount,
|
|||
|
NULL, // Name,
|
|||
|
&ParameterBuf,
|
|||
|
OutParameterCount, // InParameterCount,
|
|||
|
&OutParameterCount,
|
|||
|
NULL, // InData,
|
|||
|
0, // InDataCount,
|
|||
|
UsersBuffer, // OutData,
|
|||
|
&OutDataCount,
|
|||
|
NULL, // Fid
|
|||
|
0, // Timeout
|
|||
|
FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? (USHORT) SMB_TRANSACTION_DFSFILE : 0,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
#endif // _CAIRO_QUOTAS_
|
|||
|
#endif // _CAIRO_
|