Windows NT 4.0 source code leak
 
 
 
 
 
 

1540 lines
38 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
attr.c
Abstract:
Make and Verify routines for Attribute class (Query/Set) SMBs.
Author:
David Treadwell (davidtr) 20-Nov-1989
Chuck Lenzmeier (chuckl)
Revision History:
--*/
#define INCLUDE_SMB_QUERY_SET
#include "usrv.h"
#pragma pack(1)
typedef struct _FILESTATUS {
SMB_DATE CreationDate;
SMB_TIME CreationTime;
SMB_DATE LastAccessDate;
SMB_TIME LastAccessTime;
SMB_DATE LastWriteDate;
SMB_TIME LastWriteTime;
_ULONG( DataSize );
_ULONG( AllocationSize );
_USHORT( Attributes );
_ULONG( EaSize ); // this field intentionally misaligned!
} FILESTATUS, *PFILESTATUS;
#pragma pack()
NTSTATUS
MakeQueryInformationSmb(
IN OUT PDESCRIPTOR Redir,
IN OUT PVOID Buffer,
IN OUT PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG SmbSize
)
{
PSMB_HEADER Header;
PREQ_QUERY_INFORMATION Params;
NTSTATUS status;
AndXCommand; // prevent compiler warnings
Header = (PSMB_HEADER)Buffer;
if ( ForcedParams == NULL ) {
Params = (PREQ_QUERY_INFORMATION)(Header + 1);
status = MakeSmbHeader(
Redir,
Header,
SMB_COM_QUERY_INFORMATION,
IdSelections,
IdValues
);
if ( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PREQ_QUERY_INFORMATION)(ForcedParams);
}
Params->WordCount = 0;
SmbPutUshort(
&Params->ByteCount,
FileDefs[IdSelections->Fid].Name.Length
);
RtlMoveMemory(
Params->Buffer,
FileDefs[IdSelections->Fid].Name.Buffer,
(ULONG)SmbGetUshort( &Params->ByteCount )
);
*SmbSize = GET_ANDX_OFFSET(
Header,
Params,
REQ_QUERY_INFORMATION,
SmbGetUshort( &Params->ByteCount )
);
return STATUS_SUCCESS;
} // MakeQueryInformationSmb
NTSTATUS
VerifyQueryInformation(
IN OUT PDESCRIPTOR Redir,
IN PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN OUT PID_VALUES IdValues,
OUT PULONG SmbSize,
IN PVOID Buffer
)
{
PSMB_HEADER Header;
PRESP_QUERY_INFORMATION Params;
NTSTATUS status;
AndXCommand, SmbSize; // prevent compiler warnings
Header = (PSMB_HEADER)(Buffer);
if ( ForcedParams == NULL ) {
Params = (PRESP_QUERY_INFORMATION)(Header + 1);
status = VerifySmbHeader(
Redir,
IdSelections,
IdValues,
Header,
SMB_COM_QUERY_INFORMATION
);
if( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PRESP_QUERY_INFORMATION)ForcedParams;
}
return STATUS_SUCCESS;
} // VerifyQueryInformation
NTSTATUS
MakeSetInformationSmb(
IN OUT PDESCRIPTOR Redir,
IN OUT PVOID Buffer,
IN OUT PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG SmbSize
)
{
PSMB_HEADER Header;
PREQ_SET_INFORMATION Params;
NTSTATUS status;
AndXCommand; // prevent compiler warnings
Header = (PSMB_HEADER)Buffer;
if ( ForcedParams == NULL ) {
Params = (PREQ_SET_INFORMATION)(Header + 1);
status = MakeSmbHeader(
Redir,
Header,
SMB_COM_SET_INFORMATION,
IdSelections,
IdValues
);
if ( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PREQ_SET_INFORMATION)(ForcedParams);
}
Params->WordCount = 8;
SmbPutUlong( &Params->LastWriteTimeInSeconds, 0xbadf00d );
RtlZeroMemory( &Params->Reserved[0], sizeof(Params->Reserved) );
if ( IdSelections->Fid != 0xF) {
SmbPutUshort( &Params->FileAttributes, SMB_FILE_ATTRIBUTE_SYSTEM );
SmbPutUshort(
&Params->ByteCount,
FileDefs[IdSelections->Fid].Name.Length
);
RtlMoveMemory(
Params->Buffer,
FileDefs[IdSelections->Fid].Name.Buffer,
(ULONG)SmbGetUshort( &Params->ByteCount )
);
} else {
USHORT attr = 0;
PSZ name;
PCHAR c;
if ( Redir->argc < 3 ||
(*Redir->argv[1] != '-' && *Redir->argv[1] != '/') ) {
printf( "Usage: chmode -X filename\n" );
return STATUS_INVALID_PARAMETER;
}
for ( c = Redir->argv[1]+1; *c != '\0'; c++ ) {
switch ( *c ) {
case 'r':
attr |= SMB_FILE_ATTRIBUTE_READONLY;
continue;
case 'h':
attr |= SMB_FILE_ATTRIBUTE_HIDDEN;
continue;
case 's':
attr |= SMB_FILE_ATTRIBUTE_SYSTEM;
continue;
case 'a':
attr |= SMB_FILE_ATTRIBUTE_ARCHIVE;
continue;
case 'o':
attr = 0;
continue;
default:
printf( "Invalid mode letter: %s\n", Redir->argv[1] );
return STATUS_INVALID_PARAMETER;
}
}
SmbPutUshort( &Params->FileAttributes, attr );
name = Redir->argv[2];
if ( *(name+1) == ':' ) {
name += 2;
}
SmbPutUshort( &Params->ByteCount, (USHORT)(strlen( name ) + 2) );
Params->Buffer[0] = '\004';
RtlMoveMemory( Params->Buffer + 1, name, strlen( name ) + 1 );
}
*SmbSize = GET_ANDX_OFFSET(
Header,
Params,
REQ_SET_INFORMATION,
SmbGetUshort( &Params->ByteCount )
);
return STATUS_SUCCESS;
} // MakeSetInformationSmb
NTSTATUS
VerifySetInformation(
IN OUT PDESCRIPTOR Redir,
IN PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN OUT PID_VALUES IdValues,
OUT PULONG SmbSize,
IN PVOID Buffer
)
{
PSMB_HEADER Header;
PRESP_SET_INFORMATION Params;
NTSTATUS status;
AndXCommand, SmbSize; // prevent compiler warnings
Header = (PSMB_HEADER)(Buffer);
if ( ForcedParams == NULL ) {
Params = (PRESP_SET_INFORMATION)(Header + 1);
status = VerifySmbHeader(
Redir,
IdSelections,
IdValues,
Header,
SMB_COM_SET_INFORMATION
);
if( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PRESP_SET_INFORMATION)ForcedParams;
}
return STATUS_SUCCESS;
} // VerifySetInformation
NTSTATUS
MakeQueryInformation2Smb(
IN OUT PDESCRIPTOR Redir,
IN OUT PVOID Buffer,
IN OUT PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG SmbSize
)
{
PSMB_HEADER Header;
PREQ_QUERY_INFORMATION2 Params;
NTSTATUS status;
AndXCommand; // prevent compiler warnings
Header = (PSMB_HEADER)Buffer;
if ( ForcedParams == NULL ) {
Params = (PREQ_QUERY_INFORMATION2)(Header + 1);
status = MakeSmbHeader(
Redir,
Header,
SMB_COM_QUERY_INFORMATION2,
IdSelections,
IdValues
);
if ( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PREQ_QUERY_INFORMATION2)(ForcedParams);
}
Params->WordCount = 2;
SmbPutUshort( &Params->Fid, IdValues->Fid[IdSelections->Fid] );
SmbPutUshort( &Params->ByteCount, FileDefs[IdSelections->Fid].Name.Length );
RtlMoveMemory(
Params->Buffer,
FileDefs[IdSelections->Fid].Name.Buffer,
(ULONG)SmbGetUshort( &Params->ByteCount )
);
*SmbSize = GET_ANDX_OFFSET(
Header,
Params,
REQ_QUERY_INFORMATION2,
SmbGetUshort( &Params->ByteCount )
);
return STATUS_SUCCESS;
} // MakeQueryInformation2Smb
NTSTATUS
VerifyQueryInformation2(
IN OUT PDESCRIPTOR Redir,
IN PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN OUT PID_VALUES IdValues,
OUT PULONG SmbSize,
IN PVOID Buffer
)
{
PSMB_HEADER Header;
PRESP_QUERY_INFORMATION2 Params;
NTSTATUS status;
AndXCommand, SmbSize; // prevent compiler warnings
Header = (PSMB_HEADER)(Buffer);
if ( ForcedParams == NULL ) {
Params = (PRESP_QUERY_INFORMATION2)(Header + 1);
status = VerifySmbHeader(
Redir,
IdSelections,
IdValues,
Header,
SMB_COM_QUERY_INFORMATION2
);
if( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PRESP_QUERY_INFORMATION2)ForcedParams;
}
return STATUS_SUCCESS;
} // VerifyQueryInformation2
NTSTATUS
MakeSetInformation2Smb(
IN OUT PDESCRIPTOR Redir,
IN OUT PVOID Buffer,
IN OUT PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG SmbSize
)
{
PSMB_HEADER Header;
PREQ_SET_INFORMATION2 Params;
NTSTATUS status;
AndXCommand; // prevent compiler warnings
Header = (PSMB_HEADER)Buffer;
if ( ForcedParams == NULL ) {
Params = (PREQ_SET_INFORMATION2)(Header + 1);
status = MakeSmbHeader(
Redir,
Header,
SMB_COM_SET_INFORMATION2,
IdSelections,
IdValues
);
if ( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PREQ_SET_INFORMATION2)(ForcedParams);
}
Params->WordCount = 1;
SmbPutUshort( &Params->Fid, IdValues->Fid[IdSelections->Fid] );
SmbPutUshort( &Params->CreationDate.Ushort, 0xeef );
SmbPutUshort( &Params->CreationTime.Ushort, 0x7765 );
SmbPutUshort( &Params->LastAccessDate.Ushort, 0xeee );
SmbPutUshort( &Params->LastAccessTime.Ushort, 0x7764 );
SmbPutUshort( &Params->LastWriteDate.Ushort, 0xeed );
SmbPutUshort( &Params->LastWriteTime.Ushort, 0x7763 );
SmbPutUshort( &Params->ByteCount, FileDefs[IdSelections->Fid].Name.Length );
RtlMoveMemory(
Params->Buffer,
FileDefs[IdSelections->Fid].Name.Buffer,
(ULONG)SmbGetUshort( &Params->ByteCount )
);
*SmbSize = GET_ANDX_OFFSET(
Header,
Params,
REQ_SET_INFORMATION2,
SmbGetUshort( &Params->ByteCount )
);
return STATUS_SUCCESS;
} // MakeSetInformation2Smb
NTSTATUS
VerifySetInformation2(
IN OUT PDESCRIPTOR Redir,
IN PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN OUT PID_VALUES IdValues,
OUT PULONG SmbSize,
IN PVOID Buffer
)
{
PSMB_HEADER Header;
PRESP_SET_INFORMATION2 Params;
NTSTATUS status;
AndXCommand, SmbSize; // prevent compiler warnings
Header = (PSMB_HEADER)(Buffer);
if ( ForcedParams == NULL ) {
Params = (PRESP_SET_INFORMATION2)(Header + 1);
status = VerifySmbHeader(
Redir,
IdSelections,
IdValues,
Header,
SMB_COM_SET_INFORMATION2
);
if( !NT_SUCCESS(status) ) {
return status;
}
} else {
Params = (PRESP_SET_INFORMATION2)ForcedParams;
}
return STATUS_SUCCESS;
} // VerifySetInformation2
NTSTATUS
QueryPathOrFileInformation(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN BOOLEAN PathInformation,
IN UCHAR CodedInformationLevel,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PVOID *Information,
OUT PCLONG InformationLength
)
{
NTSTATUS status;
USHORT setup;
CLONG inSetupCount;
CLONG outSetupCount;
PVOID parameters;
CLONG inParameterCount;
CLONG outParameterCount;
PVOID data;
CLONG inDataCount;
CLONG outDataCount;
BOOLEAN isQea;
PSZ fileName = NULL;
USHORT informationLevel;
PFILE_BASIC_INFORMATION fileBasicInfo;
PFILE_STANDARD_INFORMATION fileStandardInfo;
PFILE_EA_INFORMATION fileEaInfo;
PFILE_NAME_INFORMATION fileNameInfo;
PFILE_ALLOCATION_INFORMATION fileAllocationInfo;
PFILE_END_OF_FILE_INFORMATION fileEndOfFileInfo;
UNICODE_STRING unicodeName;
//
// The information level is code as follows
// 0 - 7F => 0 - 7F
// 80 - FF => 100 - 17F
//
informationLevel = CodedInformationLevel;
if (CodedInformationLevel > 0x80) {
informationLevel += 0x80;
}
if ( strcmp( Redir->argv[0], "QEA" ) == 0 ) {
if ( Redir->argc < 2 ) {
printf( "Usage: qea filename [EA-name]...\n" );
return STATUS_INVALID_PARAMETER;
}
isQea = TRUE;
fileName = Redir->argv[1];
if ( *(fileName+1) == ':' ) {
fileName += 2;
}
if ( Redir->argc == 2 ) {
informationLevel = SMB_INFO_QUERY_ALL_EAS;
} else {
informationLevel = SMB_INFO_QUERY_EAS_FROM_LIST;
}
} else {
isQea = FALSE;
}
switch ( informationLevel ) {
case SMB_INFO_STANDARD:
inDataCount = 0;
outDataCount = sizeof(FILESTATUS) - sizeof(ULONG);
data = malloc( outDataCount );
break;
case SMB_INFO_QUERY_EA_SIZE:
inDataCount = 0;
outDataCount = sizeof(FILESTATUS);
data = malloc( outDataCount );
break;
case SMB_INFO_QUERY_ALL_EAS:
inDataCount = 0;
outDataCount = 8192;
data = malloc( outDataCount );
break;
case SMB_INFO_QUERY_EAS_FROM_LIST:
outDataCount = 8192;
data = malloc( outDataCount );
BuildGeaList(
data,
&inDataCount,
&Redir->argv[1],
(SHORT)(Redir->argc-1)
);
break;
case SMB_QUERY_FILE_BASIC_INFO:
inDataCount = 0;
outDataCount = sizeof( FILE_BASIC_INFORMATION );
data = malloc( outDataCount );
break;
case SMB_QUERY_FILE_STANDARD_INFO:
inDataCount = 0;
outDataCount = sizeof( FILE_STANDARD_INFORMATION );
data = malloc( outDataCount );
break;
case SMB_QUERY_FILE_EA_INFO:
inDataCount = 0;
outDataCount = sizeof( FILE_EA_INFORMATION );
data = malloc( outDataCount );
break;
case SMB_QUERY_FILE_NAME_INFO:
inDataCount = 0;
outDataCount = 5000;
data = malloc( outDataCount );
break;
case SMB_QUERY_FILE_ALLOCATION_INFO:
inDataCount = 0;
outDataCount = sizeof( FILE_ALLOCATION_INFORMATION );
data = malloc( outDataCount );
break;
case SMB_QUERY_FILE_END_OF_FILEINFO:
inDataCount = 0;
outDataCount = sizeof( FILE_END_OF_FILE_INFORMATION );
data = malloc( outDataCount );
break;
case SMB_QUERY_FILE_ALL_INFO:
inDataCount = 0;
outDataCount = 5000;
data = malloc( outDataCount );
break;
default:
printf( "STATUS_NOT_IMPLEMENTED, #1\n" );
return STATUS_NOT_IMPLEMENTED;
}
inSetupCount = 1;
outSetupCount = 0;
setup = (USHORT)(PathInformation ?
TRANS2_QUERY_PATH_INFORMATION : TRANS2_QUERY_FILE_INFORMATION);
if ( PathInformation ) {
if ( !isQea ) {
inParameterCount = sizeof(REQ_QUERY_PATH_INFORMATION) - 1 +
FileDefs[IdSelections->Fid].Name.Length - 1;
} else {
inParameterCount = sizeof(REQ_QUERY_PATH_INFORMATION) +
strlen( fileName );
}
} else {
inParameterCount = sizeof(REQ_QUERY_FILE_INFORMATION);
}
outParameterCount = 2;
parameters = malloc( inParameterCount );
if ( PathInformation ) {
PREQ_QUERY_PATH_INFORMATION request = parameters;
SmbPutUshort( &request->InformationLevel, informationLevel );
SmbPutUlong( &request->Reserved, 0 );
if ( !isQea ) {
RtlMoveMemory(
request->Buffer,
Redir->argv[1],
strlen( Redir->argv[1] ) + 1
);
} else {
RtlMoveMemory(
request->Buffer,
fileName,
strlen( fileName ) + 1
);
}
} else {
PREQ_QUERY_FILE_INFORMATION request = parameters;
SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] );
SmbPutUshort( &request->InformationLevel, informationLevel );
}
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION2,
&setup,
inSetupCount,
&outSetupCount,
"",
0,
parameters,
inParameterCount,
&outParameterCount,
data,
inDataCount,
&outDataCount
);
if ( !NT_SUCCESS(status) ) {
goto exit;
}
if ( outSetupCount != 0 ) {
printf( "QueryPathOrFileInformation: bad return setup count: %ld\n",
outSetupCount );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
if ( outParameterCount != 2 ) {
printf( "QueryPathOrFileInformation: bad return parameter count: %ld\n",
outParameterCount );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
#if 0 // OS/2 server doesn't set this
if ( ((PRESP_QUERY_PATH_INFORMATION)parameters)->EaErrorOffset != 0 ) {
printf( "QueryPathOrFileInformation: EA error. Offset: %ld\n",
((PRESP_QUERY_PATH_INFORMATION)parameters)->EaErrorOffset );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
#endif
switch ( informationLevel ) {
case SMB_INFO_STANDARD:
if ( outDataCount != sizeof(FILESTATUS)-sizeof(ULONG) ) {
printf( "QueryPathOrFileInformation: bad return data count: %ld\n",
outDataCount );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
goto put_info;
case SMB_INFO_QUERY_EA_SIZE:
if ( outDataCount != sizeof(FILESTATUS) ) {
printf( "QueryPathOrFileInformation: bad return data count: %ld",
outDataCount );
goto exit;
}
put_info:
IF_DEBUG(3) {
PFILESTATUS info = data;
printf( "Information about %s %s\n",
PathInformation ? "path" : "file",
FileDefs[IdSelections->Fid].Name.Buffer + 1 );
PutDateAndTime( " Creation", info->CreationDate,
info->CreationTime );
PutDateAndTime( " Last access", info->LastAccessDate,
info->LastAccessTime );
PutDateAndTime( " Last write", info->LastWriteDate,
info->LastWriteTime );
printf( " Data size: %ld, Allocation: %ld\n",
SmbGetAlignedUlong( &info->DataSize ),
SmbGetAlignedUlong( &info->AllocationSize ) );
printf( " Attributes: 0x%lx\n",
SmbGetAlignedUshort( &info->Attributes ) );
if ( informationLevel == SMB_INFO_QUERY_EA_SIZE ) {
printf( " EA size: %ld\n", SmbGetUlong( &info->EaSize ) );
}
}
break;
case SMB_INFO_QUERY_EAS_FROM_LIST:
case SMB_INFO_QUERY_ALL_EAS:
printf( "Query EA results:\n" );
PrintFeaList( (PFEALIST)data );
break;
case SMB_QUERY_FILE_BASIC_INFO:
fileBasicInfo = (PFILE_BASIC_INFORMATION)data;
printf( "File Basic Info: \n" );
PutNtDateAndTime(
"\tCreationTime: ",
fileBasicInfo->CreationTime
);
PutNtDateAndTime(
"\tBasicTime: ",
fileBasicInfo->LastAccessTime
);
PutNtDateAndTime(
"\tLastWriteTime: ",
fileBasicInfo->LastWriteTime
);
PutNtDateAndTime(
"\tChangeTime: ",
fileBasicInfo->ChangeTime
);
printf(
"\tFile attributes: 0x%08lx\n",
fileBasicInfo->FileAttributes
);
break;
case SMB_QUERY_FILE_STANDARD_INFO:
fileStandardInfo = (PFILE_STANDARD_INFORMATION)data;
printf("File standard info\n");
printf(
"\tAllocation Size 0x%lx%08lx\n",
fileStandardInfo->AllocationSize.HighPart,
fileStandardInfo->AllocationSize.LowPart
);
printf(
"\tAllocation Size 0x%lx%08lx\n",
fileStandardInfo->EndOfFile.HighPart,
fileStandardInfo->EndOfFile.LowPart
);
printf(
"\tNumber of links: %d\n",
fileStandardInfo->NumberOfLinks
);
printf(
"\tDeletePending: %s\n",
fileStandardInfo->DeletePending ? "TRUE" : "FALSE"
);
printf(
"\tDirectory: %s\n",
fileStandardInfo->Directory ? "TRUE" : "FALSE"
);
break;
case SMB_QUERY_FILE_EA_INFO:
fileEaInfo = (PFILE_EA_INFORMATION)data;
printf("File EA info\n");
printf(
"\tEA size %d\n",
fileEaInfo->EaSize
);
break;
case SMB_QUERY_FILE_NAME_INFO:
fileNameInfo = (PFILE_NAME_INFORMATION)data;
printf("File name information\n");
unicodeName.Buffer = fileNameInfo->FileName;
unicodeName.Length = (USHORT)fileNameInfo->FileNameLength;
printf("\tFile name %wZ\n", &unicodeName );
break;
case SMB_QUERY_FILE_ALLOCATION_INFO:
fileAllocationInfo = (PFILE_ALLOCATION_INFORMATION)data;
printf(
"\tAllocation Size 0x%lx%08lx\n",
fileAllocationInfo->AllocationSize.HighPart,
fileAllocationInfo->AllocationSize.LowPart
);
break;
case SMB_QUERY_FILE_END_OF_FILEINFO:
fileEndOfFileInfo = (PFILE_END_OF_FILE_INFORMATION)data;
printf("End of file information\n" );
printf(
"\tEnd of file 0x%lx%08lx\n",
fileEndOfFileInfo->EndOfFile.HighPart,
fileEndOfFileInfo->EndOfFile.LowPart
);
break;
case SMB_QUERY_FILE_ALL_INFO:
printf( "File All Info: \n" );
fileBasicInfo = (PFILE_BASIC_INFORMATION)data;
PutNtDateAndTime(
"\tCreationTime: ",
fileBasicInfo->CreationTime
);
PutNtDateAndTime(
"\tBasicTime: ",
fileBasicInfo->LastAccessTime
);
PutNtDateAndTime(
"\tLastWriteTime: ",
fileBasicInfo->LastWriteTime
);
PutNtDateAndTime(
"\tChangeTime: ",
fileBasicInfo->ChangeTime
);
printf(
"\tFile attributes: 0x%08lx\n",
fileBasicInfo->FileAttributes
);
fileStandardInfo = (PFILE_STANDARD_INFORMATION)(fileBasicInfo+1);
printf(
"\tAllocation Size 0x%lx%08lx\n",
fileStandardInfo->AllocationSize.HighPart,
fileStandardInfo->AllocationSize.LowPart
);
printf(
"\tAllocation Size 0x%lx%08lx\n",
fileStandardInfo->EndOfFile.HighPart,
fileStandardInfo->EndOfFile.LowPart
);
printf(
"\tNumber of links: %d\n",
fileStandardInfo->NumberOfLinks
);
printf(
"\tDeletePending: %s\n",
fileStandardInfo->DeletePending ? "TRUE" : "FALSE"
);
printf(
"\tDirectory: %s\n",
fileStandardInfo->Directory ? "TRUE" : "FALSE"
);
fileEaInfo = (PFILE_EA_INFORMATION)(fileStandardInfo+1);
printf(
"\tEA size %d\n",
fileEaInfo->EaSize
);
fileNameInfo = (PFILE_NAME_INFORMATION)(fileEaInfo+1);
unicodeName.Buffer = fileNameInfo->FileName;
unicodeName.Length = (USHORT)fileNameInfo->FileNameLength;
printf("\tFile name %wZ\n", &unicodeName );
break;
default:
printf( "STATUS_NOT_IMPLEMENTED, #2\n" );
status = STATUS_NOT_IMPLEMENTED;
goto exit;
}
free( parameters );
*Information = data;
*InformationLength = outDataCount;
return STATUS_PENDING;
exit:
free( parameters );
free( data );
*Information = NULL;
*InformationLength = 0;
return status;
} // QueryPathOrFileInformation
NTSTATUS
QueryFileInformationController(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PVOID Unused,
IN UCHAR SubCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG Unused2
)
{
NTSTATUS status;
PVOID information;
CLONG informationLength;
Unused, Unused2;
status = QueryPathOrFileInformation(
Redir,
DebugString,
FALSE,
SubCommand,
IdSelections,
IdValues,
&information,
&informationLength
);
if ( NT_SUCCESS(status) ) {
free( information );
}
return status;
} // QueryFileInformationController
NTSTATUS
QueryPathInformationController(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PVOID Unused,
IN UCHAR SubCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG Unused2
)
{
NTSTATUS status;
PVOID information;
CLONG informationLength;
Unused, Unused2;
status = QueryPathOrFileInformation(
Redir,
DebugString,
TRUE,
SubCommand,
IdSelections,
IdValues,
&information,
&informationLength
);
if ( NT_SUCCESS(status) ) {
free( information );
}
return status;
} // QueryPathInformationController
NTSTATUS
SetPathOrFileInformation(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN BOOLEAN PathInformation,
IN UCHAR CodedInformationLevel,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN PVOID Information,
IN CLONG InformationLength
)
{
NTSTATUS status;
USHORT realInformationLevel;
USHORT setup;
CLONG inSetupCount;
CLONG outSetupCount;
PVOID parameters;
CLONG inParameterCount;
CLONG outParameterCount;
CLONG outDataCount;
BOOLEAN isSea;
PSZ fileName = NULL;
realInformationLevel = CodedInformationLevel;
if ( CodedInformationLevel > 0x80 ) {
realInformationLevel += 0x80;
}
if ( strcmp( Redir->argv[0], "SEA" ) == 0 ) {
if ( Redir->argc < 2 ) {
printf( "Usage: sea filename [EA-name EA-value]...\n" );
return STATUS_INVALID_PARAMETER;
}
isSea = TRUE;
fileName = Redir->argv[1];
if ( *(fileName+1) == ':' ) {
fileName += 2;
}
realInformationLevel = SMB_INFO_QUERY_EA_SIZE;
} else {
isSea = FALSE;
}
inSetupCount = 1;
outSetupCount = 0;
setup = (USHORT)(PathInformation ?
TRANS2_SET_PATH_INFORMATION : TRANS2_SET_FILE_INFORMATION);
outDataCount = 0;
if ( PathInformation ) {
if ( !isSea ) {
inParameterCount = sizeof(REQ_SET_PATH_INFORMATION) - 1 +
FileDefs[IdSelections->Fid].Name.Length - 1;
} else {
inParameterCount = sizeof(REQ_QUERY_PATH_INFORMATION) +
strlen( fileName );
}
} else {
inParameterCount = sizeof(REQ_SET_FILE_INFORMATION);
}
outParameterCount = 2;
parameters = malloc( inParameterCount );
if ( PathInformation ) {
PREQ_SET_PATH_INFORMATION request = parameters;
SmbPutUshort( &request->InformationLevel, realInformationLevel );
SmbPutUlong( &request->Reserved, 0 );
if ( !isSea ) {
RtlMoveMemory(
request->Buffer,
Redir->argv[1],
strlen( Redir->argv[1] ) + 1
);
} else {
RtlMoveMemory(
request->Buffer,
fileName,
strlen( fileName ) + 1
);
}
} else {
PREQ_SET_FILE_INFORMATION request = parameters;
SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] );
SmbPutUshort( &request->InformationLevel, realInformationLevel );
SmbPutUshort( &request->Flags, 0 );
}
switch ( realInformationLevel ) {
case SMB_INFO_STANDARD:
case SMB_INFO_QUERY_EA_SIZE:
case SMB_SET_FILE_BASIC_INFO:
case SMB_SET_FILE_DISPOSITION_INFO:
break;
default:
printf( "STATUS_NOT_IMPLEMENTED, #3\n" );
return STATUS_NOT_IMPLEMENTED;
}
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION2,
&setup,
inSetupCount,
&outSetupCount,
"",
0,
parameters,
inParameterCount,
&outParameterCount,
Information,
InformationLength,
&outDataCount
);
if ( !NT_SUCCESS(status) ) {
goto exit;
}
if ( outSetupCount != 0 ) {
printf( "SetPathOrFileInformation: bad return setup count: %ld\n",
outSetupCount );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
if ( outParameterCount != 2 ) {
printf( "SetPathOrFileInformation: bad return parameter count: %ld\n",
outParameterCount );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
#if 0 // OS/2 server doesn't set this
if ( ((PRESP_SET_PATH_INFORMATION)parameters)->EaErrorOffset != 0 ) {
printf( "SetPathOrFileInformation: EA error. Offset: %ld\n",
((PRESP_SET_PATH_INFORMATION)parameters)->EaErrorOffset );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
#endif
if ( outDataCount != 0 ) {
printf( "SetPathOrFileInformation: bad return data count: %ld\n",
outDataCount );
status = STATUS_UNSUCCESSFUL;
goto exit;
}
status = STATUS_PENDING;
exit:
free( parameters );
return status;
} // SetPathOrFileInformation
NTSTATUS
SetPathOrFileInformationCtrl(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN UCHAR PathInformation,
IN UCHAR CodedInformationLevel,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues
)
{
NTSTATUS status;
PVOID information;
CLONG informationLength;
PFILESTATUS fileStatus;
BOOLEAN isSea;
USHORT realInformationLevel;
PFILE_BASIC_INFORMATION fileBasicInfo;
PFILE_DISPOSITION_INFORMATION fileDispositionInfo;
TIME_FIELDS timeFields;
realInformationLevel = CodedInformationLevel;
if ( CodedInformationLevel > 0x80 ) {
realInformationLevel += 0x80;
}
switch ( realInformationLevel ) {
case SMB_INFO_STANDARD:
case SMB_INFO_QUERY_EA_SIZE:
case SMB_SET_FILE_BASIC_INFO:
case SMB_SET_FILE_DISPOSITION_INFO:
break;
default:
printf( "STATUS_NOT_IMPLEMENTED, #4\n" );
return STATUS_NOT_IMPLEMENTED;
}
if ( strcmp( Redir->argv[0], "SEA" ) != 0 &&
realInformationLevel < SMB_SET_FILE_BASIC_INFO ) {
status = QueryPathOrFileInformation(
Redir,
DebugString,
PathInformation,
(UCHAR)(realInformationLevel == SMB_INFO_QUERY_EA_SIZE ?
SMB_INFO_QUERY_EAS_FROM_LIST :
SMB_INFO_STANDARD),
IdSelections,
IdValues,
&information,
&informationLength
);
if ( !NT_SUCCESS(status) ) {
return status;
}
isSea = FALSE;
} else {
isSea = TRUE;
}
switch ( realInformationLevel ) {
case SMB_INFO_STANDARD:
fileStatus = information;
SmbZeroDate( &fileStatus->CreationDate );
SmbZeroTime( &fileStatus->CreationTime );
SmbZeroDate( &fileStatus->LastAccessDate );
SmbZeroTime( &fileStatus->LastAccessTime );
fileStatus->LastWriteDate.Struct.Year =
(USHORT)((fileStatus->LastWriteDate.Struct.Year + 1) % 16);
#ifndef MIPS
fileStatus->LastWriteDate.Struct.Month =
(USHORT)(fileStatus->LastWriteDate.Struct.Month % 12 + 1);
fileStatus->LastWriteDate.Struct.Day =
(USHORT)(fileStatus->LastWriteDate.Struct.Day % 27 + 1);
fileStatus->LastWriteTime.Struct.Hours =
(USHORT)((fileStatus->LastWriteTime.Struct.Hours + 1) % 24);
fileStatus->LastWriteTime.Struct.Minutes =
(USHORT)((fileStatus->LastWriteTime.Struct.Minutes + 1) % 60);
#endif
fileStatus->LastWriteTime.Struct.TwoSeconds =
(USHORT)((fileStatus->LastWriteTime.Struct.TwoSeconds + 1) % 30);
SmbPutAlignedUlong( &fileStatus->DataSize, 0 );
SmbPutAlignedUlong( &fileStatus->AllocationSize, 0 );
SmbPutAlignedUshort( &fileStatus->Attributes, 0 );
break;
case SMB_INFO_QUERY_EA_SIZE: {
if ( !isSea ) {
free( information );
}
AllocateAndBuildFeaList(
&information,
&informationLength,
&Redir->argv[1],
(USHORT)(Redir->argc - 1)
);
break;
}
case SMB_SET_FILE_BASIC_INFO:
informationLength = sizeof( FILE_BASIC_INFORMATION );
information = malloc(informationLength);
fileBasicInfo = information;
timeFields.Year = 1980;
timeFields.Month = 7;
timeFields.Day = 10;
timeFields.Hour = 14;
timeFields.Minute = 10;
timeFields.Second = 43;
timeFields.Milliseconds = 4;
timeFields.Weekday = 6;
RtlTimeFieldsToTime( &timeFields, &fileBasicInfo->CreationTime );
fileBasicInfo->LastAccessTime = fileBasicInfo->CreationTime;
fileBasicInfo->LastWriteTime = fileBasicInfo->CreationTime;
fileBasicInfo->ChangeTime = fileBasicInfo->CreationTime;
fileBasicInfo->FileAttributes = FILE_ATTRIBUTE_READONLY;
break;
case SMB_SET_FILE_DISPOSITION_INFO:
informationLength = sizeof( FILE_DISPOSITION_INFORMATION );
information = malloc(informationLength);
fileDispositionInfo = information;
fileDispositionInfo->DeleteFile = TRUE;
break;
default:
printf( "STATUS_NOT_IMPLEMENTED, #5\n" );
return STATUS_NOT_IMPLEMENTED;
}
status = SetPathOrFileInformation(
Redir,
DebugString,
PathInformation,
CodedInformationLevel,
IdSelections,
IdValues,
information,
informationLength
);
free( information );
if ( !NT_SUCCESS(status) ) {
return status;
}
if ( !isSea && realInformationLevel < SMB_SET_FILE_BASIC_INFO) {
printf( "Set information for %s %s succeeded\n",
PathInformation ? "path" : "file",
FileDefs[IdSelections->Fid].Name.Buffer + 1 );
status = QueryPathOrFileInformation(
Redir,
DebugString,
PathInformation,
(UCHAR)(realInformationLevel == SMB_INFO_QUERY_EA_SIZE ?
SMB_INFO_QUERY_ALL_EAS : SMB_INFO_STANDARD),
IdSelections,
IdValues,
&information,
&informationLength
);
if ( NT_SUCCESS(status) ) {
free( information );
}
}
return status;
} // SetPathOrFileInformationCtrl
NTSTATUS
SetFileInformationController(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PVOID Unused,
IN UCHAR SubCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG Unused2
)
{
Unused, Unused2;
return SetPathOrFileInformationCtrl(
Redir,
DebugString,
FALSE,
SubCommand,
IdSelections,
IdValues
);
} // SetFileInformationController
NTSTATUS
SetPathInformationController(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PVOID Unused,
IN UCHAR SubCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG Unused2
)
{
Unused, Unused2;
return SetPathOrFileInformationCtrl(
Redir,
DebugString,
TRUE,
SubCommand,
IdSelections,
IdValues
);
} // SetPathInformationController