How to copy a disk file or directory with ALL attributes?

338 views
Skip to first unread message

David Arnstein

unread,
Apr 17, 1996, 3:00:00 AM4/17/96
to
Under WinNT using NTFS, I would like to copy a disk file (or
directory) to another. I would like to preserve ALL file attributes,
includeing security and ownership. My model is the SCOPY.EXE utility
contained in the WinNT 3.5 Resource Kit.

I suspect that the SDK function CreateFile takes care of writing out
all attributes. Does it skip any? Also, what function queries all
attributes from an existing file?

Thanks for help in getting started!
--
David Arnstein
arns...@netcom.com

Jerry Coffin

unread,
Apr 18, 1996, 3:00:00 AM4/18/96
to
In article <arnsteinD...@netcom.com>, arns...@netcom.com says...

> Under WinNT using NTFS, I would like to copy a disk file (or
> directory) to another. I would like to preserve ALL file attributes,
> includeing security and ownership. My model is the SCOPY.EXE utility
> contained in the WinNT 3.5 Resource Kit.

Here's some code. Right now, it's only set up to handle one file; I'll leave
it to you to expand it to handle things like wildcards.

#include <windows.h>
#include <stdarg.h>
#include <stdio.h>

// try to retain sanity by making their IDIOTIC return value from CreateFile
// at least look a little like it's sensible.
#define HNULL INVALID_HANDLE_VALUE

//
// Retrieve, format, and print out a message from the
// last errror. The `name' that's passed should be in the form of a
// present tense noun (phrase) such as "opening file".
//
void system_error(char *name) {
char *ptr = NULL;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
0,
GetLastError(),
0,
(char *)&ptr,
1024,
NULL);

fprintf(stderr, "\nError: %s - %s\n", name, ptr);
LocalFree(ptr);
exit(1);
}

//
// Enable or disable a privilege in the calling process.
//
BOOL SetCurrentPrivilege(
LPCTSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
BOOL bSuccess=FALSE; // assume this function will fail

//
// obtain the Luid of the privilege from the target computer
//
if(!LookupPrivilegeValue(NULL, Privilege, &luid)) return FALSE;

//
// open our access token, which we read and modify later
//
if(!OpenProcessToken(
GetCurrentProcess(),
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
&hToken
)) return FALSE;

//
// first pass. get current privilege setting
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;

AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);

if(GetLastError() == ERROR_SUCCESS) {
//
// second pass. set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;

if(bEnablePrivilege)
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
else
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);

AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL
);

if (GetLastError() == ERROR_SUCCESS) bSuccess=TRUE;
}

CloseHandle(hToken);

return bSuccess;
}

//
// Copy a file, retaining its date, time, attributes and security.
//
void BackupCopy(char const *infile_name, char const *outfile_name) {
char buffer[256];
SECURITY_INFORMATION info = OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |DACL_SECURITY_INFORMATION |
SACL_SECURITY_INFORMATION;
DWORD ignore;

//
// First try to set out privileges so we'll be able to read/write
// the file's security attributes.
//
SetCurrentPrivilege(SE_SECURITY_NAME, TRUE);

// Copy the file.
CopyFile(infile_name, outfile_name, TRUE);

//
// Copy the security attributes.
//
if ( !GetFileSecurity(infile_name, info, buffer, sizeof(buffer), &ignore))
system_error("getting security descriptor");

if ( !SetFileSecurity(outfile_name, info, buffer))
system_error("setting security descriptor");

//
// Disable the security privileges again.
//
SetCurrentPrivilege(SE_SECURITY_NAME, FALSE);
}

int main(int argc, char **argv) {

if ( argc < 3 ) {
fprintf(stderr,"Usage: fcopy infile outfile");
return 1;
}

BackupCopy(argv[1], argv[2]);
return 0;
}

I suspect that may have been a bit more code than you were expecting it to
take - now you know why NT is so secure: it's so damn complicated to even do
something legitimate, they figure it'll be _years_ before a lowly hacker can
figure out a way through the mess. <G> Anyhow, have fun and let me know how
things go.
Later,
Jerry.

Robert Mashlan

unread,
Apr 24, 1996, 3:00:00 AM4/24/96
to
arns...@netcom.com (David Arnstein) wrote:

>Under WinNT using NTFS, I would like to copy a disk file (or
>directory) to another. I would like to preserve ALL file attributes,
>includeing security and ownership. My model is the SCOPY.EXE utility
>contained in the WinNT 3.5 Resource Kit.
>

>I suspect that the SDK function CreateFile takes care of writing out
>all attributes. Does it skip any? Also, what function queries all
>attributes from an existing file?

Have you tried using CopyFile, which copies everything but security
attributes, then use SetFileSecurity?

rm


---
Robert Mashlan R2M Software rmas...@r2m.com http://r2m.com/~rmashlan
Internet Resources for Windows Developers http://www.r2m.com/windev/

Reply all
Reply to author
Forward
0 new messages