David Connell

Software Developer - Red Gate Software

Copying File Security Attributes

Published Tuesday, December 20, 2005 11:49 AM

Last week I was investigating writing out files and what happens if I over-write an existing file.

 

I remembered back from my MFC days that CDocument makes up a little internal C++ class called CMirrorFile. This is a very clever class that when overwriting an existing file, it copies the original file to a temporary file, writes out the new file and then deletes the temporary file. (However if the serialization of the data fails then the user has an existing copy of their original file. For more information check out doccore.cpp in the MFC source code.)

 

When developing a .NET version of this code I found that the original MFC code did not work as expected.

 

The MFC code made two calls to GetFileSecurity. The first to find out how much space is needed to be allocated in order to get the security information. The second call then gets the security information.

 

Unfortunately the call to GetFileSecurity returned back 0 (Last Error Code was set to 0x7a - The data area passed to a system call is too small). However the resultant length was set correctly.

 

Below is .NET version of how to copy file securities. So far I have only tested this code on XP.

 

using System;

using System.Runtime.InteropServices;

 

 

namespace Test

{

  using DWORD = System.UInt32;

  using PSECURITY_DESCRIPTOR = System.IntPtr;

  public class Security

  {

    enum SECURITY_INFORMATION  : int

    {

      DACL_SECURITY_INFORMATION = 4,

    }

 

    [DllImport("advapi32.dll", SetLastError=true)]

      [return: MarshalAs(UnmanagedType.Bool)]

     static extern bool GetFileSecurity(

       string lpszUsername,

       SECURITY_INFORMATION info,

       PSECURITY_DESCRIPTOR descriptor,

       DWORD val2,

       out uint length);

 

    [DllImport("advapi32.dll", SetLastError=true)]

      [return: MarshalAs(UnmanagedType.Bool)]

    static extern bool SetFileSecurity(string lpszUsername,

      SECURITY_INFORMATION info, PSECURITY_DESCRIPTOR descriptor);

 

    static public void CopyFileSecurity(string fileName,
string targetFileName)

    {

      uint dwLength = 0;               

      bool result = GetFileSecurity(fileName,
      SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
      IntPtr.Zero, 0, out dwLength);

      int lastError = Marshal.GetLastWin32Error() ;

 

      //Console.WriteLine(string.Format("Last Error = {0}", lastError));

 

      if ( ( result || lastError == 0x7a) && dwLength > 0)

      {

        PSECURITY_DESCRIPTOR pSecurityDescriptor =
        System.Runtime.InteropServices.Marshal.
AllocHGlobal((int) dwLength);

        if (GetFileSecurity(fileName,
          SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
          pSecurityDescriptor, dwLength, out dwLength))

        {

          SetFileSecurity(targetFileName,
            SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
            pSecurityDescriptor);

        }

        System.Runtime.InteropServices.Marshal.FreeHGlobal
   (pSecurityDescriptor);

      }

    }

  }

}

For some more information check out Microsoft Article Q163253 and Paul DiLascia’s article.

Comments

No Comments
You need to sign in to comment on this blog

















<December 2005>
SuMoTuWeThFrSa
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567
Reporting on Mobile Device Activity Using Exchange 2007 ActiveSync Logs
 In this new column giving practical advice on all things Sys Admin related, Ben Lye takes on the often... Read more...

The Bejeweled Puzzle in SQL
 Alex Kozak provides another SQL puzzle to hone your SQL Skills with.  Read more...

Using Powershell to Generate Table-Creation Scripts
 For all of us who learn best by trying out examples, Bob Sheldon produces a PowerShell script file for... Read more...

Configuring Exchange Server 2007 to Support Information Rights Management
 In Exchange Server 2007, Information Rights management is easy to set up once you have set up the... Read more...

SQL Response: The dim sum interview
 Richard Morris met David and Nigel of the SQL Response team, in a dim sum Restaurant in Cambridge. They... Read more...