📄 fileinfo.c
字号:
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
--*/
{
NTSTATUS Status;
RxCaptureFcb; RxCaptureFobx;
PVOID OriginalBuffer;
ULONG OriginalLength = RxContext->Info.LengthRemaining;
ULONG ReturnedLength;
BOOLEAN UsingSideBuffer = FALSE;
struct {
union {
FILE_FS_LABEL_INFORMATION labelinfo;
FILE_FS_VOLUME_INFORMATION volumeinfo;
FILE_FS_SIZE_INFORMATION sizeinfo;
FILE_FS_DEVICE_INFORMATION deviceinfo;
FILE_FS_ATTRIBUTE_INFORMATION attributeinfo;
} Info;
WCHAR VolumeName[MAXIMUM_FILENAME_LENGTH];
} SideBuffer;
PAGED_CODE();
if( RxContext->Info.LengthRemaining < sizeof( SideBuffer ) ) {
//
// i replace the buffer and length in the context with my stuff.
// This, of course, means that we can't go async....for that we'd
// have to allocate instead of using a stack-allocated buffer.
UsingSideBuffer = TRUE;
OriginalBuffer = RxContext->Info.Buffer;
RxContext->Info.Buffer = &SideBuffer;
RxContext->Info.LengthRemaining = sizeof(SideBuffer);
}
Status = MRxSmbQueryVolumeInformationWithFullBuffer(RxContext);
if (Status != STATUS_SUCCESS) {
goto FINALLY;
}
if( UsingSideBuffer == TRUE ) {
ReturnedLength = sizeof(SideBuffer) - RxContext->Info.LengthRemaining;
} else {
ReturnedLength = OriginalLength - RxContext->Info.LengthRemaining;
}
if (ReturnedLength > OriginalLength) {
Status = STATUS_BUFFER_OVERFLOW;
ReturnedLength = OriginalLength;
}
if( UsingSideBuffer == TRUE ) {
RtlCopyMemory(OriginalBuffer,&SideBuffer,ReturnedLength);
}
RxContext->Info.LengthRemaining = OriginalLength - ReturnedLength;
FINALLY:
return Status;
}
NTSTATUS
MRxSmbQueryVolumeInformationWithFullBuffer(
IN OUT PRX_CONTEXT RxContext
)
/*++
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:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
RxCaptureFcb;
PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
RxCaptureFobx;
FS_INFORMATION_CLASS FsInformationClass = RxContext->Info.FsInformationClass;
PVOID pBuffer = RxContext->Info.Buffer;
PLONG pLengthRemaining = &RxContext->Info.LengthRemaining;
PSMBCEDB_SERVER_ENTRY pServerEntry;
BOOLEAN DoAsDownLevel;
PVOID pInputParamBuffer;
ULONG InputParamBufferLength;
USHORT InformationLevel;
USHORT Setup;
REQ_QUERY_FS_INFORMATION QueryFsInformationRequest;
REQ_QUERY_FS_INFORMATION_FID DfsQueryFsInformationRequest;
PAGED_CODE();
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
if ( FsInformationClass == FileFsDeviceInformation ) {
PFILE_FS_DEVICE_INFORMATION UsersBuffer = (PFILE_FS_DEVICE_INFORMATION)pBuffer;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
UsersBuffer->Characteristics = FILE_REMOTE_DEVICE;
if (NetRoot->Type==NET_ROOT_PIPE) {
NetRoot->DeviceType = RxDeviceType(NAMED_PIPE);
return STATUS_INVALID_PARAMETER;
}
else
{
UsersBuffer->DeviceType = NetRoot->DeviceType;
*pLengthRemaining -= (sizeof(FILE_FS_DEVICE_INFORMATION));
RxDbgTrace( 0, Dbg, ("MRxSmbQueryVolumeInformation: devinfo .. returning\n"));
return STATUS_SUCCESS;
}
}
if (capFobx == NULL) {
return STATUS_INVALID_PARAMETER;
}
TURN_BACK_ASYNCHRONOUS_OPERATIONS();
for (;;) {
if (capFobx != NULL) {
PMRX_V_NET_ROOT pVNetRoot;
// Avoid device opens for which the FOBX is the VNET_ROOT instance
pVNetRoot = (PMRX_V_NET_ROOT)capFobx;
if (NodeType(pVNetRoot) != RDBSS_NTC_V_NETROOT) {
PUNICODE_STRING AlreadyPrefixedName =
GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
ULONG FcbAlreadyPrefixedNameLength = AlreadyPrefixedName->Length;
ULONG NetRootInnerNamePrefixLength = capFcb->pNetRoot->InnerNamePrefix.Length;
PWCHAR pName = AlreadyPrefixedName->Buffer;
// If an FSCTL is being attempted against the root of a share.
// The AlreadyPrefixedName associated with the FCB is the same as
// the AlreadyPrefixedName length associated with the NET_ROOT instance
// or atmost one character greater than it ( appending a \) try and
// reestablish the connection before attempting the FSCTL.
// This solves thorny issues regarding deletion/creation of shares
// on the server sides, DFS referrals etc.
if ((FcbAlreadyPrefixedNameLength == NetRootInnerNamePrefixLength) ||
((FcbAlreadyPrefixedNameLength == NetRootInnerNamePrefixLength + sizeof(WCHAR)) &&
(*((PCHAR)pName + FcbAlreadyPrefixedNameLength - sizeof(WCHAR)) ==
L'\\'))) {
Status = SmbCeReconnect(capFobx->pSrvOpen->pVNetRoot);
}
}
}
DoAsDownLevel = MRxSmbForceCoreInfo;
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
DoAsDownLevel = TRUE;
}
if (FlagOn(pServerEntry->Server.DialectFlags,DF_W95)
&& (FsInformationClass==FileFsAttributeInformation)){ //use uplevel for w95 attribute info
DoAsDownLevel = FALSE;
}
if (DoAsDownLevel) {
return MRxSmbCoreInformation(RxContext,
(ULONG)FsInformationClass,
pBuffer,
pLengthRemaining,
SMBPSE_OE_FROM_QUERYVOLUMEINFO
);
}
Status = STATUS_MORE_PROCESSING_REQUIRED;
switch (FsInformationClass) {
case FileFsVolumeInformation :
InformationLevel = SMB_QUERY_FS_VOLUME_INFO;
break;
case FileFsLabelInformation :
InformationLevel = SMB_QUERY_FS_LABEL_INFO;
break;
case FileFsSizeInformation :
InformationLevel = SMB_QUERY_FS_SIZE_INFO;
break;
case FileFsAttributeInformation :
InformationLevel = SMB_QUERY_FS_ATTRIBUTE_INFO;
break;
default:
if( FlagOn( pServerEntry->Server.DialectFlags, DF_NT_INFO_PASSTHROUGH ) ) {
InformationLevel = FsInformationClass + SMB_INFO_PASSTHROUGH;
} else {
RxDbgTrace( 0, Dbg, ("MRxSmbQueryVolumeInformation: Invalid FS information class\n"));
Status = STATUS_INVALID_PARAMETER;
}
break;
}
if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
PSMB_TRANSACTION_OPTIONS pTransactionOptions = &RxDefaultTransactionOptions;
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_DFS_TRANS2)) {
Setup = TRANS2_QUERY_FS_INFORMATION;
QueryFsInformationRequest.InformationLevel = InformationLevel;
pInputParamBuffer = &QueryFsInformationRequest;
InputParamBufferLength = sizeof(QueryFsInformationRequest);
} else {
Setup = TRANS2_QUERY_FS_INFORMATION_FID;
DfsQueryFsInformationRequest.InformationLevel = InformationLevel;
DfsQueryFsInformationRequest.Fid = smbSrvOpen->Fid;
pInputParamBuffer = &DfsQueryFsInformationRequest;
InputParamBufferLength = sizeof(DfsQueryFsInformationRequest);
}
Status = SmbCeTransact(
RxContext,
pTransactionOptions,
&Setup,
sizeof(Setup),
NULL,
0,
pInputParamBuffer,
InputParamBufferLength,
NULL,
0,
NULL,
0,
pBuffer,
*pLengthRemaining,
&ResumptionContext);
if (NT_SUCCESS(Status)) {
*pLengthRemaining -= ResumptionContext.DataBytesReceived;
}
}
if (!NT_SUCCESS(Status)) {
RxDbgTrace( 0, Dbg, ("MRxSmbQueryVolumeInformation: Failed .. returning %lx\n",Status));
}
if (Status != STATUS_NETWORK_NAME_DELETED) {
break;
}
}
return Status;
}
NTSTATUS
MRxSmbSetVolumeInformation(
IN OUT PRX_CONTEXT RxContext
)
/*++
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:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
RxCaptureFcb;
RxCaptureFobx;
FILE_INFORMATION_CLASS FileInformationClass;
PVOID pBuffer;
ULONG BufferLength;
PSMBCEDB_SERVER_ENTRY pServerEntry;
BOOLEAN ServerSupportsPassThroughForSetInfo = FALSE;
PAGED_CODE();
TURN_BACK_ASYNCHRONOUS_OPERATIONS();
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
FileInformationClass = RxContext->Info
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -