You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
4.9 KiB
205 lines
4.9 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cf.c
|
|
|
|
|
|
Abstract:
|
|
|
|
This module implements a utlity that copies files using the
|
|
Single Instance Store file system filter functionality.
|
|
|
|
Author:
|
|
|
|
Scott Cutshall [scottc] 8-July-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "cf.h"
|
|
|
|
|
|
//
|
|
// We can have: cf SrcPath DstPath {-o NtFileNameOfFileOnWhichToMakeTheCall}
|
|
//
|
|
|
|
|
|
#define BUFF_SIZE 2048
|
|
|
|
void __cdecl
|
|
main(
|
|
int argc,
|
|
char **argv
|
|
)
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
HANDLE volHandle;
|
|
UNICODE_STRING srcFileName, dstFileName;
|
|
UNICODE_STRING srcDosFileName, dstDosFileName;
|
|
UNICODE_STRING callOnFileName;
|
|
PSI_COPYFILE copyFile;
|
|
ULONG NameBuffer[BUFF_SIZE];
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
int i;
|
|
|
|
copyFile = (PSI_COPYFILE) NameBuffer;
|
|
|
|
if (argc != 3 && argc != 5)
|
|
Usage();
|
|
|
|
if (argc == 5) {
|
|
if (strcmp(argv[3],"-o")) {
|
|
Usage();
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Convert the ansii names to unicode and place in the copyFile buffer.
|
|
//
|
|
|
|
RtlCreateUnicodeStringFromAsciiz( &srcDosFileName, argv[1] );
|
|
RtlCreateUnicodeStringFromAsciiz( &dstDosFileName, argv[2] );
|
|
|
|
RtlDosPathNameToNtPathName_U(
|
|
srcDosFileName.Buffer,
|
|
&srcFileName,
|
|
NULL,
|
|
NULL );
|
|
|
|
RtlDosPathNameToNtPathName_U(
|
|
dstDosFileName.Buffer,
|
|
&dstFileName,
|
|
NULL,
|
|
NULL );
|
|
|
|
copyFile->SourceFileNameLength = srcFileName.Length + sizeof(WCHAR);
|
|
copyFile->DestinationFileNameLength = dstFileName.Length + sizeof(WCHAR);
|
|
copyFile->Flags = COPYFILE_SIS_REPLACE;
|
|
|
|
RtlCopyMemory(
|
|
©File->FileNameBuffer[0],
|
|
srcFileName.Buffer,
|
|
copyFile->SourceFileNameLength);
|
|
|
|
RtlCopyMemory(
|
|
©File->FileNameBuffer[copyFile->SourceFileNameLength / sizeof(WCHAR)],
|
|
dstFileName.Buffer,
|
|
copyFile->DestinationFileNameLength);
|
|
|
|
#define copyFileSize (FIELD_OFFSET(SI_COPYFILE, FileNameBuffer) + \
|
|
copyFile->SourceFileNameLength + \
|
|
copyFile->DestinationFileNameLength)
|
|
|
|
if (argc == 3) {
|
|
//
|
|
// Get a handle to the source file's containing directory to pass into
|
|
// FSCTL_SIS_COPYFILE,
|
|
//
|
|
|
|
for (i = srcFileName.Length / sizeof(WCHAR) - 1;
|
|
i >= 0 && srcFileName.Buffer[i] != '\\';
|
|
--i)
|
|
continue;
|
|
|
|
srcFileName.Length = (USHORT)(i * sizeof(WCHAR));
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
&srcFileName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
} else {
|
|
//
|
|
// Get a handle to the NT file specified in argv[4] to send down the call on.
|
|
//
|
|
unsigned i;
|
|
callOnFileName.MaximumLength = callOnFileName.Length = sizeof(WCHAR) * strlen(argv[4]);
|
|
callOnFileName.Buffer = (PWCHAR)malloc(callOnFileName.MaximumLength);
|
|
for (i = 0; i < strlen(argv[4]); i++) {
|
|
callOnFileName.Buffer[i] = argv[4][i];
|
|
}
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
&callOnFileName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
|
|
Status = NtCreateFile(
|
|
&volHandle,
|
|
GENERIC_READ,
|
|
&objectAttributes,
|
|
&ioStatusBlock,
|
|
NULL,
|
|
0,
|
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
if (5 == argc) {
|
|
fprintf(stderr, "Unable to open file, %.*ls (%x)\n",
|
|
callOnFileName.Length / sizeof(WCHAR), callOnFileName.Buffer, Status);
|
|
} else {
|
|
fprintf(stderr, "Unable to open directory, %.*ls (%x)\n",
|
|
srcFileName.Length / sizeof(WCHAR), srcFileName.Buffer, Status);
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
|
|
//
|
|
// Invoke the SIS CopyFile FsCtrl.
|
|
//
|
|
|
|
Status = NtFsControlFile(
|
|
volHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
FSCTL_SIS_COPYFILE,
|
|
copyFile, // Input buffer
|
|
copyFileSize, // Input buffer length
|
|
NULL, // Output buffer
|
|
0 ); // Output buffer length
|
|
|
|
if (NT_SUCCESS( Status )) {
|
|
|
|
fprintf( stderr, "NtFsControlFile CopyFile succeeded\n" );
|
|
|
|
} else {
|
|
|
|
fprintf( stderr, "NtFsControlFile CopyFile failed %x\n", Status );
|
|
|
|
}
|
|
|
|
exit (0);
|
|
|
|
} // main
|
|
|
|
|
|
void
|
|
Usage( void )
|
|
{
|
|
fprintf( stderr, "\n" );
|
|
fprintf( stderr, "Usage: cf Path1 Path2 {-o NtFileNameOfFileOnWhichToMakeTheCall}\n" );
|
|
fprintf( stderr, " cf copies Path1 to Path2 using SIS links.\n" );
|
|
fprintf( stderr, " if -o is specified, opens that file to send down the call on,\n");
|
|
fprintf( stderr, " rather than using the directory containing the source file.\n");
|
|
exit(1);
|
|
|
|
} // Usage
|