|
|
/*++
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
|