<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JEDI Windows API &#187; file</title>
	<atom:link href="http://blog.delphi-jedi.net/tag/file/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.delphi-jedi.net</link>
	<description>Joint Endeavor of Delphi Innovators of Windows Programming</description>
	<lastBuildDate>Wed, 19 Oct 2011 18:52:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Is File In Use</title>
		<link>http://blog.delphi-jedi.net/2010/11/14/is-file-in-use/</link>
		<comments>http://blog.delphi-jedi.net/2010/11/14/is-file-in-use/#comments</comments>
		<pubDate>Sun, 14 Nov 2010 19:57:43 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Conversion]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[JWA]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=861</guid>
		<description><![CDATA[In a thread on DelphiPraxis there was a question that comes up several times a year. However, this time I could remember that there is actually an COM API that can solve the problem. The question was about how to find out which process has a lock on a file. The main problem was, in [...]]]></description>
			<content:encoded><![CDATA[<p>In a thread on DelphiPraxis there was a question that comes up several times a year. However, this time I could remember that there is actually an COM API that can solve the problem. The question was about how to find out which process has a lock on a file. The main problem was, in deed, that I could not remember the API&#8217;s name so Assarbad put some effort in retrieving it. Thanks.<span id="more-861"></span></p>
<p>The name of the API is <a href="http://msdn.microsoft.com/en-us/library/bb775874%28VS.85%29.aspx" target="_blank">IFileIsInUse</a>, an interface. It resides in Shobjidl.h, Shobjidl.idl and newly in JwaShlObj.pas. This is the translation:</p>
<pre class="brush:delphi">{$IFDEF WINVISTA_UP}
const
  IID_IFileIsInUse: TGUID = (
    D1:$64a1cbf0; D2:$3a1a; D3:$4461; D4:($91,$58,$37,$69,$69,$69,$39,$50));

type
  {$ALIGN 4}
  tagFILE_USAGE_TYPE = (
    FUT_PLAYING = 0,
    FUT_EDITING = 1,
    FUT_GENERIC = 2
  );
  FILE_USAGE_TYPE = tagFILE_USAGE_TYPE;
  TFileUsageType = FILE_USAGE_TYPE;

const
  OF_CAP_CANSWITCHTO     = $0001;
  OF_CAP_CANCLOSE        = $0002;

type
  IFileIsInUse = interface(IUnknown)
    ['{64a1cbf0-3a1a-4461-9158-376969693950}']
    function GetAppName(out ppszName: LPWSTR) : HRESULT; stdcall;
    function GetUsage(out pfut : FILE_USAGE_TYPE) : HRESULT; stdcall;
    function GetCapabilities(out pdwCapFlags : DWORD) : HRESULT; stdcall;
    function GetSwitchToHWND(out phwnd : HWND) : HRESULT; stdcall;
    function CloseFile() : HRESULT; stdcall;
  end;

{$ENDIF WINVISTA_UP}
</pre>
<p>The interface can be used as a client and also can be implemented by a server. A client usually checks if a file has a lock and retrieves a pointer to this interface to access the methods. A server usually holds a lock on a given file and implements the interface to provide the methods to the client. This article will discuss only the client side.<br />
 You see that this API only works if both sides do their jobs. A process that locks a file must also implement this interface and register it, so a client can receive a status information. There is no direct link between a file lock and the process name. If a process holds a lock on a file but does not implement the interface you are on your own again. <br />
 Eventually, this is only a shell helper for the nice Windows Explorer deletion dialog.</p>
<p><a href="http://blog.delphi-jedi.net/wp-content/uploads/2010/11/FileInUse-2.png"><img class="alignnone size-full wp-image-869" title="FileInUse Windows Explorer Dialog" src="http://blog.delphi-jedi.net/wp-content/uploads/2010/11/FileInUse-2.png" alt="" width="496" height="293" /></a></p>
<pre class="brush:delphi">  IFileIsInUse = interface(IUnknown)
    function GetAppName(out ppszName: LPWSTR) : HRESULT; stdcall;
    function GetUsage(out pfut : FILE_USAGE_TYPE) : HRESULT; stdcall;
    function GetCapabilities(out pdwCapFlags : DWORD) : HRESULT; stdcall;
    function GetSwitchToHWND(out phwnd : HWND) : HRESULT; stdcall;
    function CloseFile() : HRESULT; stdcall;
  end;
</pre>
<p>The methods of the interface are really easy to understand.</p>
<ul>
<li><em>GetAppName </em>retrieves the name of the process that holds the file. It can be any chosen name by the application designer. To get the name use always a PWideChar and don&#8217;t forget to free it with CoTaskMemFree (it uses the interface IMalloc). Don&#8217;t forget to check for the result. If you like exception you can also rewrite the code using <strong>safecall</strong> (convert the function to a procedure then).</li>
<li><em>GetUsage </em>returns the reason why the file is locked. It can be one of the enumeration constant of  TFileUsage. Either it can be playing a video or music or editing a file. If these are not sufficient the value FUT_GENERIC must be used. Maybe there will be more values in future.</li>
<li> <em>GetCapabilities </em>returns a set of flags in a DWORD. They define whether the file can be closed (OF_CAP_CANCLOSE) by calling <em>CloseFile</em> or the we can put the application into foreground (OF_CAP_CANSWITCHTO). Be aware that you should inform the user that you are about to switch the window. Otherwise she could get nervous about her missing application window. Switching the window can be done by <a href="http://msdn.microsoft.com/en-us/library/ms633539%28VS.85%29.aspx" target="_blank"><em>SetForegroundWindow</em></a>. But your application must have a focus (and some other rules, see MSDN SetForegroundWindow) to switch the window; otherwise nothing happens.</li>
<li><em>GetSwitchToHWND</em> returns a window handle of the other process. Only use this handle to switch to the window. You don&#8217;t really know what window is returned here. Don&#8217;t try to close it or anything else because this is just bad behaviour. At all costs, check the return value. Otherwise you don&#8217;t know whether the returned window handle is valid or just an random number. In worst case it is an existing window from your process. Well, COM rules tell us to nullify the out parameters but usually it is better to check.<br />
 Of course, the call is only valid if GetCapabilities returns the bit OF_CAP_CANSWITCHTO.</li>
<li><em>CloseFile</em> implements the server side of closing the file. The call is only valid if <em>GetCapabilities </em>returns the bit OF_CAP_CANCLOSE. Well, this is really nice. However, don&#8217;t trust it! Always recheck the lock on the file instead of continuing blindly.</li>
</ul>
<p>To retrieve an interface on the file you have to lock it first. Either you download and compile the MSDN example <a href="http://msdn.microsoft.com/en-us/library/ee330722(v=VS.85).aspx" target="_blank">IsFileInUse</a> or you open up an application that implements the interface (e.g. a PDF Reader, MS Office).</p>
<p>The next step is to know where the locked files are placed. The location is the running object table, short ROT (ActiveX.GetRunningObjectTable() retrieves it). It is a global* (on machine) table that holds running COM objects. You can implement your own interfaces and put it in this table. Because interfaces can be arbitrary in its structure and reason to be,  they are attached to monikers (<a href="http://msdn.microsoft.com/en-us/library/ms679705%28VS.85%29.aspx" target="_blank">IMoniker</a>) which describe them uniquely. There are several types of monikers like class, item and file moniker (more information provides IMoniker in MSDN). We are interested in the latter only. <br />
 So the whole work is an enumeration over all monikers in the ROT.  Usually there are not that much in there (I got 5 here). Each moniker is checked for its type (IsSystemMoniker) and if it is a file moniker (MKSYS_FILEMONIKER) the path is compared to the input parameter FileName. Honestly, I cannot tell why there is a comparison of the prefix at first followed by a comparison of the moniker itself, sorry. <br />
 The object itself is retrieved from the moniker by GetObject. It may fail with E_ACCESS_DENIED so a check is done using <em>Succeeded</em>. In the end, we can try to retrieve the IFileIsInUse interface. There may be such a file registered but without the implementation of the interface, thus an additional check.</p>
<p>I didn&#8217;t create this whole source by myself. In fact, there is a <a href="http://msdn.microsoft.com/en-us/library/ee330722(v=VS.85).aspx" target="_blank">FileIsInUse example </a>in MSDN that is the base of this article. The original source is located in the docx file in the download. The example FileIsInUse will create a server.</p>
<p><br class="spacer_" /></p>
<pre class="brush:delphi">function GetFileInUseInfo(const FileName : WideString) : IFileIsInUse;
var
  ROT : IRunningObjectTable;
  mFile, enumIndex, Prefix : IMoniker;
  enumMoniker : IEnumMoniker;
  MonikerType : LongInt;
  unkInt  : IInterface;
begin
  result := nil;

  OleCheck(GetRunningObjectTable(0, ROT));
  OleCheck(CreateFileMoniker(PWideChar(FileName), mFile));

  OleCheck(ROT.EnumRunning(enumMoniker));

  while (enumMoniker.Next(1, enumIndex, nil) = S_OK) do
  begin
    OleCheck(enumIndex.IsSystemMoniker(MonikerType));
    if MonikerType = MKSYS_FILEMONIKER then
    begin
      if Succeeded(mFile.CommonPrefixWith(enumIndex, Prefix)) and
         (mFile.IsEqual(Prefix) = S_OK) then
      begin
       if Succeeded(ROT.GetObject(enumIndex, unkInt)) then
        begin
          if Succeeded(unkInt.QueryInterface(IID_IFileIsInUse, result)) then
          begin
            result := unkInt as IFileIsInUse;
            exit;
          end;
        end;
      end;
    end;
  end;
end;
</pre>
<p><br class="spacer_" /></p>
<h3>Conclusion<br class="spacer_" /></h3>
<p>This whole API has some caveats</p>
<ul>
<li>This API relies on a server that registers an interface in the ROT honestly. If an application doesn&#8217;t do the effort, you will be unable to aquire the name of it.</li>
<li>If you lock a file on a shared folder and you want to access the very same file on the local file system, you cannot determine the process if you access the shared folder from localhost. The reason is Windows itself. Windows is the provider of the file to the outer world (even if it is a loopback) so Windows Explorer shows &#8220;System&#8221; as origin. In the ROT you will see the the UNC path instead of the local file system path. Thus the comparison and our function will fail.</li>
<li>*Security: A ROT is not really global. In fact, there are several ROTs in the system. ROTs are divided by a user and then the mandatory integrity control (MIC) or integrity levels (IL) high, medium and propably low (didn&#8217;t check). If you run as a user, your processes get an medium level and as an Administrator you&#8217;ll get an high integrity level. A server that runs with an medium integrity level will only be allowed to register itself into the medium ROT. So it must be started at least once as Administrator to be allowed to create some Registry keys for COM (LOCAL_MACHINE\Classes\AppID\<em>guid</em>). In this way it will be available in all ROTs if it wants. Unfortunately, this is not the end. On a multi user system, every object in a moniker has a security descriptor that tells COM who is allowed to access it. If Alice wants to access an object in the ROT that was created by Bob, Bob has to explicitily grant Alice access to it. By default the security, which allow access to SYSTEM, Administrators and the creator, is copied from the global COM security settings and can be changed either in the registry for an AppID, at process startup or for each registered object by the server. JWSCL provides all of them in JwsclComSecurity.pas (only Subversion trunk and &gt;= 0.9.4). In this way a server can change the settings to, say, allow all authenticated users access to the object. </li>
</ul>
<h3>Downloads</h3>
<p>You can download the example file from the Subversion directly.</p>
<table border="0">
<tbody>
<tr>
<td><a href="tsvn:https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwapi/trunk/Examples/FileIsInUse/Client/FileIsInUseClientExample.dpr"><img class="size-full wp-image-387 alignnone" title="tortoisecheckout" src="http://blog.delphi-jedi.net/wp-content/uploads/2007/12/tortoisecheckout.png" alt="Checkout with TortoiseSVN" width="48" height="48" /></a></td>
<td><a href="https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwapi/trunk/Examples/FileIsInUse/Client/FileIsInUseClientExample.dpr" target="_blank">https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwapi/trunk/Examples/FileIsInUse/Client/FileIsInUseClientExample.dpr</a></td>
</tr>
</tbody>
</table>
<p><br class="spacer_" /></p>
<h3>Sequel</h3>
<p>The next article discusses the the implementation if the interface IFileIsInUse.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/11/14/is-file-in-use/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Setting Folder Security</title>
		<link>http://blog.delphi-jedi.net/2010/03/24/setting-folder-security/</link>
		<comments>http://blog.delphi-jedi.net/2010/03/24/setting-folder-security/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 18:03:38 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[DACL]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[permission]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=721</guid>
		<description><![CDATA[This article describes some ways how to set the security on a folder using JWSCL. Usually, we want to add some rights for a particular user to a folder so she gets access. I can say that is a heck of work to do with WinAPI. But still with JWSCL we need to consider some [...]]]></description>
			<content:encoded><![CDATA[<p>This article describes some ways how to set the security on a folder using JWSCL. Usually, we want to add some rights for a particular user to a folder so she gets access. I can say that is a heck of work to do with WinAPI. But still with JWSCL we need to consider some things. <span id="more-721"></span></p>
<p>The following code creates a folder named &#8220;JWSCLTest&#8221; and applies a DACL that allows full control to everyone. The folder will inherit its security settings to child folders and files (check the afXXX flags).</p>
<pre class="brush:delphi">const JWSCLTestFolder = 'JWSCLTestFolder';

var
  SD : TJwSecurityDescriptor;
  pSA : PSecurityAttributes;
begin
  JwInitWellKnownSIDs;

  SD := TJwSecurityDescriptor.Create;
  try
    SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,
      [afContainerInheritAce, afObjectInheritAce], FILE_ALL_ACCESS, JwWorldSID));

    pSA := SD.Create_SA();
    try
      Win32Check(CreateDirectory(JWSCLTestFolder, pSA));
    finally
      SD.Free_SA(pSA); //remember to free pointer
    end;
  finally
    SD.Free;
  end;
end.
</pre>
<p>CreateDirectory receives a security attributes structure that is applied to the folder directly. However, in this way the parent security descriptor is not inherited to our folder. This is called a protected DACL because the inheritance flow is stopped. So we get a folder with only one Access Control Entry (ACE) : Everyone (aka World SID).  To remedy that we can copy the ACEs from the parent folder to our own folder:</p>
<pre class="brush:delphi">procedure MergeParentDACL(const Location : String; TargetSD : TJwSecurityDescriptor);
var DirSD : TJwSecureFileObject;
begin
  DirSD := TJwSecureFileObject.Create(Location);
  try
    TargetSD.DACL.AddACEs(DirSD.DACL);
  finally
    DirSD.Free;
  end;
end;

var
  DirSD : TJwSecureFileObject;

  SD, SD2 : TJwSecurityDescriptor;
  pSA : PSecurityAttributes;
begin
  JwInitWellKnownSIDs;

  SD := TJwSecurityDescriptor.Create;

  try
    SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,
      [afContainerInheritAce, afObjectInheritAce], FILE_ALL_ACCESS, JwWorldSID));

    MergeParentDACL('.', SD);

    pSA := SD.Create_SA();
    try
      Win32Check(CreateDirectory(JWSCLTestFolder, pSA));
    finally
      SD.Free_SA(pSA);
    end;
  finally
    SD.Free;
  end;
end.
</pre>
<p>The function <em>MergeParentDACL</em> receives the location of the parent folder and retrieves its security settings. Then its DACL is copied to the target security descriptor. JWSCL with <em>TargetSD.DACL.AddACEs</em> makes sure that the order of the ACEs are still correct (first deny then allow entries) by moving them accordingly.</p>
<p>In addition, there is a second, much easier way to achieve the same result.</p>
<pre class="brush:delphi">var
  SD : TJwSecurityDescriptor;
  DirSD : TJwSecureFileObject;
begin
  JwInitWellKnownSIDs;

  Win32Check(CreateDirectory(JWSCLTestFolder, nil));

  DirSD := TJwSecureFileObject.Create(JWSCLTestFolder);
  try
    SD := DirSD.GetSecurityDescriptor([siDaclSecurityInformation]);
    try
      SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,
        [afContainerInheritAce, afObjectInheritAce], FILE_ALL_ACCESS, JwWorldSID));

      DirSD.SetSecurityDescriptor(SD, [siDaclSecurityInformation]);
    finally
      SD.Free;
    end;
  finally
    DirSD.Free;
  end;
</pre>
<p>In this way we didn&#8217;t set the security descriptor directly when the folder was created. Nevertheless we get a combination of inheritace ACEs plus the explicit one (JwWorldSID).</p>
<h3>Note</h3>
<p>It is always a good idea to check whether SD.DACL (in above codes) is nil and if so ignore it or create a new and empty one to be used instead. It is always possible that a file or folder comes with a nil DACL which means either no access at all (flag DACLpresent) or everyone has full access (flag DACLpresent not available).</p>
<h3>I used the following JEDI units:</h3>
<pre class="brush:delphi">uses
  JwaWindows,

  JwsclDescriptor,
  JwsclTypes,
  JwsclConstants,
  JwsclKnownSid,
  JwsclAcl,
  JwsclMapping,
  JwsclSecureObjects,
  JwsclSid,
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/24/setting-folder-security/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Retrieving File Owner</title>
		<link>http://blog.delphi-jedi.net/2010/03/11/retrieving-file-owner/</link>
		<comments>http://blog.delphi-jedi.net/2010/03/11/retrieving-file-owner/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 13:52:11 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[JWA]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=676</guid>
		<description><![CDATA[This article is about how to retrieve the owner of a file. If you are experienced with some of the WinAPI security function this can be pretty easy. There are some problems that needs to be addressed though. The first one is the size of the security items like the SID name of the owner. [...]]]></description>
			<content:encoded><![CDATA[<p>This article is about how to retrieve the owner of a file. If you are experienced with some of the WinAPI security function this can be pretty easy. There are some problems that needs to be addressed though. The first one is the size of the security items like the SID name of the owner. Secondly, there is the possibility that a SID cannot be resolved to a human readable name at all. And thirdly, we need to check all the result values.</p>
<p><span id="more-676"></span></p>
<h2>WinAPI</h2>
<pre class="brush:delphi">
uses
  SysUtils,
  //JwaWindows, //Use either JwaWindows or these JEDI headers:
  JwaWinBase,
  JwaWinType,
  JwaWinNT,
  JwaAclApi,
  JwaAccCtrl,
  JwaWinError,
  JwaSddl;

type
  TOwnerResult = (orNone, orName, orSID);

function GetFileOwner(const FileName: string;
  out Domain, Username: String): TOwnerResult;
var
  pSD: PSecurityDescriptor;
  dwOwnerNameSize, dwDomainNameSize: DWORD;
  pOwnerSID: PSID;
  pszOwnerName, pszDomainName: PChar;
  OwnerType: SID_NAME_USE;
  dwError : DWORD;
begin
  result := orNone;

  pSD := nil;
  dwError := GetNamedSecurityInfo(
     PChar(FileName),//__in       LPTSTR pObjectName,
     SE_FILE_OBJECT,//__in       SE_OBJECT_TYPE ObjectType,
     OWNER_SECURITY_INFORMATION,//__in       SECURITY_INFORMATION SecurityInfo,
     @pOwnerSID,//__out_opt  PSID *ppsidOwner,
     nil,//__out_opt  PSID *ppsidGroup,
     nil,//__out_opt  PACL *ppDacl,
     nil,//__out_opt  PACL *ppSacl,
     pSD//__out_opt  PSECURITY_DESCRIPTOR *ppSecurityDescriptor
   );
  if (dwError <> NOERROR) then
  begin
    SetLastError(dwError);
    RaiseLastOSError;
  end;

  //First get necessary memory size for Owner and Domain
  dwOwnerNameSize  := 0;
  dwDomainNameSize := 0;
  if not LookupAccountSID(nil, pOwnerSID, nil,
    dwOwnerNameSize, nil, dwDomainNameSize, OwnerType) then
  begin
    //Check for SIDs that are unknown on this local system
    if (GetLastError() = ERROR_NONE_MAPPED) then
    begin
      Win32Check(ConvertSidToStringSid(pOwnerSID, pszOwnerName));
      Domain := '';
      Username := pszOwnerName;
      LocalFree(HLOCAL(pszOwnerName));
      result := orSID;
      exit;
    end
    else
    //Any other error exits the function
    if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then
      RaiseLastOsError;
  end;

  //Allocate memory for owner and domain
  //Take into account the size of a char type (like WideCHAR)
  GetMem(pszOwnerName, dwOwnerNameSize*sizeof(CHAR));
  try
    GetMem(pszDomainName, dwDomainNameSize*sizeof(CHAR));
    try
      //Retrieve name and domain
      Win32Check(LookupAccountSID(nil, pOwnerSID, pszOwnerName,
        dwOwnerNameSize, pszDomainName, dwDomainNameSize, OwnerType));

      result := orName;

      Domain   := pszDomainName;
      Username := pszOwnerName;
    finally
      FreeMem(pszDomainName);
    end;
  finally
    FreeMem(pszOwnerName);
  end;
end;
</pre>
<p>The function behaves the following:</p>
<ul>
<li>If an WinAPI error occurs the exception EOSError is thrown. You can retrieve the error value from its property Errorcode.</li>
<li>If the user name could be retrieved the result value is <em>orName</em> and both parameter <em>Domain </em>and <em>UserName</em> contain a value. Otherwise the result is orSID and only UserName contains the User Security Identifier (e.g. S-1-5-21-564352346-2735467565-567745764-1001).</li>
</ul>
<h2>JWSCL</h2>
<p>Of course, JWSCL wraps these function calls already. Thus the source size decreases rapidly. See another <a href="http://blog.delphi-jedi.net/2007/10/21/why-jwscl">example here</a>.<br />
In JWSCL it is quite different to implement the function. However the behaviour is equal:</p>
<pre class="brush:delphi">function JwsclGetFileOwner(const FileName: string;
  out Domain, Username: String): TOwnerResult;
var
  F : TJwSecureFileObject;
  Owner : TJwSecurityId;
begin
  F := TJwSecureFileObject.Create(FileName);
  try
    Owner := F.Owner; //Owner is cached/freed by TJwSecureFileObject
    try
      Domain := Owner.GetAccountDomainName();
      Username := Owner.GetAccountName();
      Result := orName;
    except
      on E : EJwsclWinCallFailedException do
      begin
        if E.LastError = ERROR_NONE_MAPPED then
        begin
          Domain := '';
          Username := Owner.StringSID;
          Result := orSID;
        end
        else
          raise;
      end;
    end;
  finally
    F.Free;
  end;
end;
</pre>
<p>In a next version of JWSCL (currently trunk) the exception handling will be a little bit different:</p>
<pre class="brush:delphi">function JwsclGetFileOwner2(const FileName: string;
  out Domain, Username: String): TOwnerResult;
var
  F : TJwSecureFileObject;
  Owner : TJwSecurityId;
begin
  F := TJwSecureFileObject.Create(FileName);
  try
    Owner := F.Owner; //Owner is cached/freed by TJwSecureFileObject
    try
      Domain := Owner.GetAccountDomainName();
      Username := Owner.GetAccountName();
      Result := orName;
    except
      on E : EJwsclSidNotMappedException do //not mapped error is handled differently
      begin
        Domain := '';
        Username := Owner.StringSID;
        Result := orSID;
      end;
    end;
  finally
    F.Free;
  end;
end;
</pre>
<p>If you use JWSCL (Version >= 0.9.2a) and enable the compiler switch <strong>JWSCL_SIDCACHE</strong> in file Include\Jwscl.inc, JWSCL will add a SID cache (for all TJwSecurityID instances globally). In this way LookupAccountSid will be called only once for every unknown SID and thus SIDs that were already translated are retrieved from cache instead.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/11/retrieving-file-owner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting file security with JWSCL</title>
		<link>http://blog.delphi-jedi.net/2008/04/28/setting-file-security-with-jwscl/</link>
		<comments>http://blog.delphi-jedi.net/2008/04/28/setting-file-security-with-jwscl/#comments</comments>
		<pubDate>Mon, 28 Apr 2008 16:12:39 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[DACL]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[folder]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[Token]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=170</guid>
		<description><![CDATA[Sometimes it is necessary to change the security settings of a file or folder for getting or denying write access. With JWSCL this task is made very easy. However there are some pitfalls to avoid. The following code will also be available in the example section of the source code. The application gets a file [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it is necessary to change the security settings of a file or folder for getting or denying write access. With JWSCL this task is made very easy. However there are some pitfalls to avoid.</p>
<p>The following code will also be available in the example section of the source code. The application gets a file or folder name as parameter and tries to add the user with full access control. It even tries to get ownership if it can&#8217;t change the access control list.</p>
<p>First of all we need some JWSCL classes:</p>
<ul>
<li>TJwSecurityDescriptor<br />
A security descriptor contains all information about security of an object. It contains the owner and the access control list (also some other thing, we don&#8217;t need here)</li>
<li>TJwSecureFileObject<br />
This class provides methods to read and write security information on a file or folder. Despite its name it does also support folders. It even supports inheritance.<br />
You can access a file or folder through its name, a handle or the VCL class TFileStream.</li>
<li>TJwDAccessControlList<br />
This class contains methods to maintain a discreationary access control list (DACL). A DACL contains a list of users and their possible access on the object.</li>
<li>TJwSecurityId<br />
Every user is identified by a unique number which is maintained by this class.</li>
<li>TJwSecurityToken<br />
Every logged on user gets a security pass which contains information what she can do or not. We mainly use it to retrieve the user&#8217;s SID (TJwSecurityID)</li>
</ul>
<p>These classes are stored in the JWSCL units. We use the following ones:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span><br />
&nbsp;JwaWindows,<br />
&nbsp;JwsclSid,<br />
&nbsp;JwsclToken,<br />
&nbsp;JwsclACl,<br />
&nbsp;JwsclDescriptor,<br />
&nbsp;JwsclSecureObjects,<br />
&nbsp;JwsclKnownSid;</div>
<p>The units above are necessary and contain all the classes described earlier Of course we have to declare the classes:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span><br />
&nbsp; UserToken : TJwSecurityToken;<br />
&nbsp; SD : TJwSecurityDescriptor;<br />
&nbsp; FileObject : TJwSecureFileObject;<br />
&nbsp; Owner : TJwSecurityId;<br />
&nbsp; DACL : TJwDAccessControlList;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="kw1">if</span> <span class="kw1">not</span> <span class="kw3">FileExists</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; <span class="kw3">exit</span>;</div>
<p>This example also shows how we can add well known Security Identifiers (SID) to a secured object. We have to initialize them. The variable JwWorldSID will then contain the correct SID for group Everyone. If we didn&#8217;t call it, we would get nil instead.<br />
JwInitWellKnownSIDs;</p>
<p>The next steps are creating the classes. We get the user name through her token and save the SID into Owner.<br />
Later we will use the Owner instance to add it into the security information of the object.</p>
<div class="dean_ch" style="white-space: wrap;">UserToken := TJwSecurityToken.<span class="me1">CreateTokenEffective</span><span class="br0">&#40;</span>MAXIMUM_ALLOWED<span class="br0">&#41;</span>;<br />
Owner := UserToken.<span class="me1">GetTokenOwner</span>;<br />
<span class="kw1">try</span><br />
&nbsp; FileObject := TJwSecureFileObject.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
<p>The actual class which does all the work on the file/folder is TJwSecureFileObject. We just apply the first parameter.</p>
<p>Notice: A user can only change security information of an object if she has the right to do it. There are two options to allow it.</p>
<ol>
<li>The user is listed in the DACL. Additionally the right WRITE_DAC is granted for her.</li>
<li>The user is the owner. In this case she don&#8217;t need to be listed and allowed in the DACL. It is automatically granted</li>
</ol>
<p>We can check both version in one call.</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp;<span class="kw1">try</span><br />
&nbsp; <span class="kw1">if</span> <span class="kw1">not</span> FileObject.<span class="me1">AccessCheck</span><span class="br0">&#40;</span>WRITE_DAC<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">begin</span></div>
<p>This call is very easy. If we can&#8217;t change the DACL, we can try to become the owner. The only way to become an owner is to enable a privilege called SE_TAKE_OWNERSHIP_NAME. It is usually only granted to Administrators.</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp; &nbsp; JwEnablePrivilege<span class="br0">&#40;</span>SE_TAKE_OWNERSHIP_NAME, pst_Enable<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; FileObject.<span class="me1">Owner</span> := Owner;<br />
&nbsp; <span class="kw1">end</span>;</div>
<p>JwEnablePrivilege will fail, if it can&#8217;t activate the privilege. Otherwise we can set the file/folder&#8217;s owner to the token user.</p>
<p>The main work is done here. We get the default DACL from the existing object and adapt it.</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp; &nbsp;DACL := FileObject.<span class="me1">DACL</span>;</div>
<p>Adaption is done by adding the user to the DACL with full control. We additionally allow the Everyone group to demonstrate the well known Sids initialized by JwInitWellKnownSIDs. The last parameters (false) define that we don&#8217;t want the list to free the given SIDs (Owner and JwWorldSid) automatically.</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp; &nbsp;DACL.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_ALL, Owner, <span class="kw2">false</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; DACL.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_READ, JwWorldSID, <span class="kw2">false</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
<p>And finally we reset the DACL.</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp; &nbsp;FileObject.<span class="me1">SetDACL</span><span class="br0">&#40;</span>DACL<span class="br0">&#41;</span>;</div>
<p>The DACL of the file or folder will receive the newly created control entries in addition to its existing ones. If it contains inherited entries (entries from a parent folder) they will be conserved. However if you don&#8217;t retrieve the DACL and just use an empty one, all previously existing entries which are not inherited will be removed. Of course the inherited entries will still remain intact.</p>
<p>And of course we free all allocated resources</p>
<div class="dean_ch" style="white-space: wrap;"> &nbsp;<span class="kw1">finally</span><br />
&nbsp; &nbsp; FileObject.<span class="me1">Free</span>;<br />
&nbsp; <span class="kw1">end</span>;</p>
<p><span class="kw1">finally</span><br />
&nbsp; Owner.<span class="me1">Free</span>;<br />
&nbsp; UserToken.<span class="me1">Free</span>;<br />
<span class="kw1">end</span>;<br />
<span class="kw1">end</span>.</div>
<p>Since I cut the source code into pieces, I&#8217;ll show it here in full glory</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">program</span> SetFileSecurity;</p>
<p><span class="coMULTI">{$APPTYPE CONSOLE}</span></p>
<p><span class="kw1">uses</span><br />
&nbsp; SysUtils,<br />
&nbsp; JwaWindows,<br />
&nbsp; JwsclSid,<br />
&nbsp; JwsclToken,<br />
&nbsp; JwsclAcl,<br />
&nbsp; JwsclDescriptor,<br />
&nbsp; JwsclSecureObjects,<br />
&nbsp; JwsclKnownSid;</p>
<p><span class="kw1">var</span><br />
&nbsp; UserToken : TJwSecurityToken;<br />
&nbsp; SD : TJwSecurityDescriptor;<br />
&nbsp; FileObject : TJwSecureFileObject;<br />
&nbsp; Owner : TJwSecurityId;<br />
&nbsp; DACL : TJwDAccessControlList;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="kw1">if</span> <span class="kw1">not</span> <span class="kw3">FileExists</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; <span class="kw3">exit</span>;</p>
<p>&nbsp; JwInitWellKnownSIDs;</p>
<p>&nbsp; UserToken := TJwSecurityToken.<span class="me1">CreateTokenEffective</span><span class="br0">&#40;</span>MAXIMUM_ALLOWED<span class="br0">&#41;</span>;<br />
&nbsp; Owner := UserToken.<span class="me1">GetTokenOwner</span>;<br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; FileObject := TJwSecureFileObject.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; <span class="co1">//Make me owner if we cant access DACL</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> FileObject.<span class="me1">AccessCheck</span><span class="br0">&#40;</span>WRITE_DAC<span class="br0">&#41;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//try to become owner</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; JwEnablePrivilege<span class="br0">&#40;</span>SE_TAKE_OWNERSHIP_NAME, pst_Enable<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; FileObject.<span class="me1">Owner</span> := Owner;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;</p>
<p>&nbsp; &nbsp; &nbsp; DACL := FileObject.<span class="me1">DACL</span>;<br />
&nbsp; &nbsp; &nbsp; DACL.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_ALL, Owner, <span class="kw2">false</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; DACL.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_READ, JwWorldSID, <span class="kw2">false</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; FileObject.<span class="me1">SetDACL</span><span class="br0">&#40;</span>DACL<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; &nbsp; FileObject.<span class="me1">Free</span>;<br />
&nbsp; &nbsp; <span class="kw1">end</span>;</p>
<p>&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; Owner.<span class="me1">Free</span>;<br />
&nbsp; &nbsp; UserToken.<span class="me1">Free</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
<span class="kw1">end</span>.</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/04/28/setting-file-security-with-jwscl/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to use a Security Attribute structure Part #2</title>
		<link>http://blog.delphi-jedi.net/2008/03/22/how-to-use-a-security-attribute-structure-part-2/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/22/how-to-use-a-security-attribute-structure-part-2/#comments</comments>
		<pubDate>Sat, 22 Mar 2008 16:40:55 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[DACL]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[inheritance]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[permission]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/22/how-to-use-a-security-attribute-structure-part-2/</guid>
		<description><![CDATA[This discussion continues How to use a SecurityAttribute structure. Last time we used the SecurityAttribute parameter in CreateFile to change the security descriptor of the newly created file. However this approach did not add inherited access control elements from the parent folder. We are about to change that. Filesystem and Registry-key inheritance is implemented since [...]]]></description>
			<content:encoded><![CDATA[<p>This discussion continues <a href="http://blog.delphi-jedi.net/2008/03/04/how-to-use-a-security-attribute-structure" title="Go to blog.">How to use a SecurityAttribute structure</a>.</p>
<p>Last time we used the SecurityAttribute parameter in CreateFile to change the security descriptor of the newly created file. However this approach did not add inherited access control elements from the parent folder. We are about to change that.</p>
<p>Filesystem and Registry-key inheritance is implemented since Windows 2000 and also can be added to Windows NT 4 by installing an update. It is a really convenient way to set security over many files in a complex folder tree.</p>
<p>So what did we last time?</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span> SD : TJwSecurityDescriptor;<br />
&nbsp; &nbsp; &nbsp;AliceSid : TJwSecurityId;<br />
&nbsp; &nbsp; &nbsp;SecAttrPtr : PSecurityAttributes;<br />
&nbsp; &nbsp; &nbsp;Handle : <span class="kw4">THandle</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="kw3">DeleteFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span><span class="br0">&#41;</span>; </p>
<p>&nbsp; SD := TJwSecurityDescriptor.<span class="me1">CreateDefaultByToken</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; AliceSid := TJwSecurityId.<span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">&#8221;</span>,<span class="st0">&#8216;Alice&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; SD.<span class="me1">DACL</span>.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_READ, AliceSid, <span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>; </p>
<p>&nbsp; SecAttrPtr := SD.<span class="me1">Create_SA</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; </p>
<p>&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; Handle := jwaWindows.<span class="me1">CreateFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span>, FILE_ALL_ACCESS, <span class="nu0">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">Pointer</span><span class="br0">&#40;</span>SecAttrPtr<span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CREATE_NEW, FILE_ATTRIBUTE_NORMAL,<span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> handle = ERROR_INVALID_HANDLE <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw3">RaiseLastOSError</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; SD.<span class="me1">Free</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
&#8230;</div>
<p>This code assigns a simple security descriptor. In my tests there was no way to let CreateFile add the inherited elements to the DACL. Luckily there are several ways to do so.</p>
<ol>
<li>Get the inherited access elements from the parent and add them to our DACL by hand</li>
<li>Let the system handle inheritance</li>
<li>Do the second way much faster</li>
</ol>
<p><u>1. Get the inherited access elements from the parent and add them to our DACL by hand</u></p>
<p>The first choice needs a lot of work to do. First we need all the inheritable access control elements from the parent folders. This would become very nasty if we had to recursively go up to all parent folders to get the elements. However we are lucky because all inherited ACEs are always available through the direct parent container (if they are not blocked).<br />
Because I will need more time to describe this approach. I&#8217;m going to skip this part for now and discuss it in a separate blog entry.</p>
<p><u>2. Let the system handle inheritance</u></p>
<p><strong>JWSCL </strong>supports inheritance of file, folder and registry keys with the classes <em><a href="http://jwscldoc.delphi-jedi.net/JwsclSecureObjects.TJwSecureFileObject.html">TJwSecureFileObject</a> </em>and <a href="http://jwscldoc.delphi-jedi.net/JwsclSecureObjects.TJwSecureRegistryKey.html"><em>TJwSecureRegistryKey</em></a>. We are going to use only <em>TJwSecureFileObject </em>for our task. However changing permissons and inheritance of a registry key is straight forward and is much the same job as it is with files and folders.</p>
<p><em>TJwSecureFileObject </em>offers three ways to adapt security of a file or folder. You can use a file/folder handle (retrieved by <em>CreateFile</em>), a file or folder name or you use the VCL class <em>TFileStream</em>. However the last variant has some disadvantages like not being able to work with folders.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span> SD : TJwSecurityDescriptor;<br />
&nbsp; &nbsp; AliceSid : TJwSecurityId;<br />
&nbsp; &nbsp; SecAttrPtr : PSecurityAttributes;<br />
&nbsp; &nbsp; Handle : <span class="kw4">THandle</span>;<br />
&nbsp; &nbsp; <span class="kw3">Sec</span> : TJwSecureFileObject;<br />
&nbsp; &nbsp; DACL : TJwDAccessControlList;<br />
<span class="kw1">begin</span> </p>
<p>&nbsp; &#8230;<br />
&nbsp; <span class="me1">SecAttrPtr</span> := SD.<span class="me1">Create_SA</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; </p>
<p>&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; Handle := jwaWindows.<span class="me1">CreateFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span>, FILE_ALL_ACCESS, <span class="nu0">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">Pointer</span><span class="br0">&#40;</span>SecAttrPtr<span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CREATE_NEW, FILE_ATTRIBUTE_NORMAL,<span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> handle = ERROR_INVALID_HANDLE <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw3">RaiseLastOSError</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; SD.<span class="me1">Free</span>;<br />
&nbsp; <span class="kw1">end</span>; </p>
<p>&nbsp; CloseHandle<span class="br0">&#40;</span>Handle<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw3">Sec</span> := TJwSecureFileObject.<span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; DACL := <span class="kw3">Sec</span>.<span class="me1">GetDACL</span>;<br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; <span class="kw3">Sec</span>.<span class="me1">SetDACL</span><span class="br0">&#40;</span>DACL,apUnprotected<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; DACL.<span class="me1">Free</span>;<br />
&nbsp; &nbsp; <span class="kw3">Sec</span>.<span class="me1">Free</span>;<br />
&nbsp; <span class="kw1">end</span>;<br />
&#8230;</div>
<p><em>TJwSecureFileObject </em>retrieves the DACL of the file after newly created file was opened. The method <em>SetDACL </em>sets the DACL back but also removes the protection flag from security descriptor control. Thus all the inherited access elements flow to the file&#8217;s access control list.</p>
<p><u>3. Do the second way which is much less to write<br />
</u></p>
<p><em>TJwSecureFileObject </em>offers class methods to act with file or folders much faster. We can either restore the inheritance flow by using the file/folder name&#8230;</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">begin</span><br />
&nbsp; <span class="kw3">DeleteFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; &#8230;<br />
&nbsp; <span class="me1">TJwSecureFileObject</span>.<span class="me1">RestoreInheritanceFlow</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; &#8230;</div>
<p>or reestablish the inheritance flow by using a file handle.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">begin</span><br />
&nbsp; <span class="kw3">DeleteFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; Handle := jwaWindows.<span class="me1">CreateFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span>, FILE_ALL_ACCESS, <span class="nu0">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">Pointer</span><span class="br0">&#40;</span>SecAttrPtr<span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CREATE_NEW, FILE_ATTRIBUTE_NORMAL,<span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp;<span class="kw1">if</span> handle = ERROR_INVALID_HANDLE <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">RaiseLastOSError</span>;<br />
&nbsp; &nbsp; TJwSecureFileObject.<span class="me1">RestoreInheritanceFlow</span><span class="br0">&#40;</span>Handle<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">finally</span> &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; SD.<span class="me1">Free</span>; &nbsp; <br />
&nbsp; <span class="kw1">end</span>;</div>
<p>You can use one way or the other.</p>
<p><strong>Tell me how you liked this blog entry by adding a comment.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/22/how-to-use-a-security-attribute-structure-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moving a file does not recalculate inherited permissions</title>
		<link>http://blog.delphi-jedi.net/2008/03/11/moving-a-file-does-not-recalculate-inherited-permissions/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/11/moving-a-file-does-not-recalculate-inherited-permissions/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 14:15:34 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[move]]></category>
		<category><![CDATA[permission]]></category>
		<category><![CDATA[Raymond]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/11/moving-a-file-does-not-recalculate-inherited-permissions/</guid>
		<description><![CDATA[Are you interested in security attributes of a file? If yes, you should read Raymond Chen&#8217;s article about how permissions are handled when moving a file. Cite: Inherited permissions on an object are established when it is created. Once the object has been created, you can change the permissions of the parent and it won&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>Are you interested in security attributes of a file? If yes, you should read Raymond Chen&#8217;s article about how permissions are handled when moving a file.</p>
<blockquote><p>Cite:<br />
Inherited permissions on an object are established when it is created. Once the object has been created, you can change the permissions of the parent and it won&#8217;t have any effect unless you explicitly ask for the inheritable properties to be re-propagated to the child objects.</p></blockquote>
<p>Read more about it at <a href="http://blogs.msdn.com/oldnewthing/archive/2006/08/24/717181.aspx" title="Go to Raymond's Blog">Raymond&#8217;s blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/11/moving-a-file-does-not-recalculate-inherited-permissions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to use a SecurityAttribute structure</title>
		<link>http://blog.delphi-jedi.net/2008/03/04/how-to-use-a-security-attribute-structure/</link>
		<comments>http://blog.delphi-jedi.net/2008/03/04/how-to-use-a-security-attribute-structure/#comments</comments>
		<pubDate>Tue, 04 Mar 2008 15:43:25 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[ACE]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[CreateFile]]></category>
		<category><![CDATA[descriptor]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[security attribute]]></category>
		<category><![CDATA[Sid]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2008/03/04/how-to-use-a-security-attribute-structure/</guid>
		<description><![CDATA[Many developers know that mysterious parameter some WinAPI function offer to use. What I am talking about is a parameter called lpSecurityAttributes. The documentation states that it allows to change the security descriptor of the desired element. The most known function is CreateFile which I want to use here. It allows to create a file [...]]]></description>
			<content:encoded><![CDATA[<p>Many developers know that mysterious parameter some WinAPI function offer to use. What I am talking about is a parameter called <em>lpSecurityAttributes</em>. The documentation states that it allows to change the security descriptor of the desired element. The most known function is <em>CreateFile</em> which I want to use here. It allows to create a file and more. But we stay to create a file. Usually we set the parameter <em>lpSecurityAttributes</em> simply to <strong>NULL</strong>/<strong>nil</strong> because this sets the default security configuration we want to use in most of the times (this also includes file/folder inheritance).</p>
<p>However sometimes we want to use our own security configuration to allow other participants to access a resource we created. JWSCL makes this task much more simple than using the security runtime function written in plain C. We do not have to create the security descriptor from scratch. The JWSCL methods allow us to get the default security descriptor and adapt it to our needs.<span id="more-30"></span></p>
<p>Let&#8217;s start with the required classes and methods we need to add another user who wants access.</p>
<ul>
<li><a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwSecurityDescriptor.html"><em>TJwSecurityDescriptor</em></a> in unit <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/JwsclDescriptor_pas.html"><em>JwsclDescriptor</em></a></li>
<li><a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwDAccessControlList.html"><em>TJwDAccessControlList</em></a> in unit <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/JwsclAcl_pas.html"><em>JwsclAcl</em></a></li>
<li><a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwDiscretionaryAccessControlEntryAllow.html"><em>TJwDiscretionaryAccessControlEntryAllow</em></a> in unit <em>JwsclAcl</em></li>
<li><a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwSecurityId.html"><em>TJwSecurityID</em></a> in unit <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/JwsclSid_pas.html"><em>JwsclSid</em></a></li>
</ul>
<p>That&#8217;s all.</p>
<p>Since the system already creates us an adequate security access list we want to continue using it. For this reason <em>TJwSecurityDescriptor</em> implements a constructor called <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwSecurityDescriptor.html#CreateDefaultByToken">CreateDefaultByToken</a> that creates such a security access list automatically.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span> JwaWindows,&#8230;,JwsclDescriptor, JwsclAcl, JwsclTypes, JwsclStrings;<br />
<span class="kw1">var</span> SD : TJwSecurityDescriptor;<br />
<span class="kw1">begin</span><br />
&nbsp; SD := TJwSecurityDescriptor.<span class="me1">CreateDefaultByToken</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw3">Writeln</span><span class="br0">&#40;</span>SD.<span class="me1">Text</span><span class="br0">&#41;</span>;</div>
<p>The output may look like this, depending on your Windows system.</p>
<blockquote><p>Owner: chris@ Christian (S-1-5-21-2735234258-346234578-4357623456-1000) []<br />
 Group: chris@ None (S-1-5-21-2735234258-346234578-4357623456-513) [sidaGroupMandatory]<br />
 DACL:<br />
 ACE Count: 3<br />
 \#0<br />
 ClassName: TJwDiscretionaryAccessControlEntryAllow<br />
 AceType: Allow<br />
 Flags:<br />
 Accessmask: No map class given. 268435456, 0&#215;10000000<br />
 SID: chris@ Christian (S-1-5-21-2735234258-346234578-4357623456-1000) []<br />
 #1<br />
 ClassName: TJwDiscretionaryAccessControlEntryAllow<br />
 AceType: Allow<br />
 Flags:<br />
 Accessmask: No map class given. 268435456, 0&#215;10000000<br />
 SID: NT-AUTORIT-T@ SYSTEM (S-1-5-18) []<br />
 #2<br />
 ClassName: TJwDiscretionaryAccessControlEntryAllow<br />
 AceType: Allow<br />
 Flags:<br />
 Accessmask: No map class given. 2684354560, 0xA0000000<br />
 SID: (S-1-5-5-0-151391) []</p>
<p>SACL:<br />
 ACE Count: 0<br />
 \</p>
</blockquote>
<p>(<em>No map class given</em> is shown because the security descriptor class does not know the type of secured object. A map class (derived from <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwSecurityGenericMapping.html">TJwSecurityGenericMapping</a>)  can convert the AccessMask to an human readable string)</p>
<p>The system sets the owner to the current token owner of the process or thread. It also adds my user account and the SYSTEM principal with full access (0&#215;10000000 = GENERIC_ALL). The unknown principal with the Sid S-1-5-5-0-151391 describes the loggon session Sid. At a later point we will remove it.<br />
 For the discussion we want to add another principal called Alice so she can get read access to the file/folder. Because we need the Alice&#8217;s Sid we have to add another variable called <em>AliceSid</em>.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span> SD : TJwSecurityDescriptor;<br />
&nbsp; &nbsp; AliceSid : TJwSecurityId;<br />
<span class="kw1">begin</span><br />
&nbsp; &nbsp;SD := TJwSecurityDescriptor.<span class="me1">CreateDefaultByToken</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp;AliceSid := TJwSecurityId.<span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">&#8221;</span>,<span class="st0">&#8216;Alice&#8217;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp;SD.<span class="me1">DACL</span>.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_READ, AliceSid, <span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw3">Writeln</span><span class="br0">&#40;</span>SD.<span class="me1">Text</span><span class="br0">&#41;</span>;</div>
<p>In the code above a new class instance of <em>TJwDiscretionaryAccessControlEntryAllow</em> is added to the DACL. Because we create just a simple file we do not need special flags thus an empty flag set [] is applied. The access mask parameter will receive GENERIC_READ as the maximum possible access to this file granted to Alice. The last parameter (OwnSid) is set to <strong>true</strong> and defines that the access control list (here property <em>DACL</em>) destroys the instance <em>AliceSid</em> at the end.</p>
<p>The resulting security descriptor has now a new access control entry. The output is the same like above but with this additional element.</p>
<blockquote><p>ClassName: TJwDiscretionaryAccessControlEntryAllow<br />
 AceType: Allow<br />
 Flags:<br />
 Accessmask: No map class given. 2147483648, 0&#215;80000000<br />
 SID: chris@ Alice (S-1-5-21-2735234258-346234578-4357623456-1008) []</p>
</blockquote>
<p>Now we can arrive at the part where <a title="Go to MSDN." href="http://msdn2.microsoft.com/en-us/library/aa363858(VS.85).aspx"><em>CreateFile</em></a> comes in. How can we create a pointer to a <a title="Go to MSDN." href="http://msdn2.microsoft.com/en-us/library/aa379560(VS.85).aspx">TSecurityAttribute</a> type? It is really simple! We just have to declare some more helper variables that <em>CreateFile</em> needs and use <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwSecurityDescriptor.html#Create_SA"><em>Create_SA</em></a>.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span> SD : TJwSecurityDescriptor;<br />
&nbsp; &nbsp; &nbsp;AliceSid : TJwSecurityId;<br />
&nbsp; &nbsp; &nbsp;SecAttrPtr : PSecurityAttributes;<br />
&nbsp; &nbsp; &nbsp;Handle : <span class="kw4">THandle</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; <span class="kw3">DeleteFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; SD := TJwSecurityDescriptor.<span class="me1">CreateDefaultByToken</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; AliceSid := TJwSecurityId.<span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">&#8221;</span>,<span class="st0">&#8216;Alice&#8217;</span><span class="br0">&#41;</span>;<br />
&nbsp; SD.<span class="me1">DACL</span>.<span class="me1">Add</span><span class="br0">&#40;</span>TJwDiscretionaryAccessControlEntryAllow.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">nil</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span>, GENERIC_READ, AliceSid, <span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; SecAttrPtr := SD.<span class="me1">Create_SA</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; Handle := jwaWindows.<span class="me1">CreateFile</span><span class="br0">&#40;</span><span class="st0">&#8216;testfile&#8217;</span>, FILE_ALL_ACCESS, <span class="nu0">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">Pointer</span><span class="br0">&#40;</span>SecAttrPtr<span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CREATE_NEW, FILE_ATTRIBUTE_NORMAL,<span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> handle = ERROR_INVALID_HANDLE <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw3">RaiseLastOSError</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; SD.<span class="me1">Free</span>;<br />
&nbsp; <span class="kw1">end</span>;</div>
<p><a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwSecurityDescriptor.html#Create_SA"><em>Create_SA</em></a> from <em>TJwSecurityDescriptor</em> creates the necessary memory structure (<em>SecurityAttributes</em>) and returns a pointer of type <em>PSecurityAttributes</em>. The pointer is used in CreateFile to apply our own security descriptor. Our access control list of the newly created file will contain all the elements you see above as output. In tests, both the creation flags CREATE_NEW and CREATE_ALWAYS never change the security attributes after the file has already been created. Although MSDN explains it correctly for CREATE_ALWAYS it does not say anything about CREATE_NEW in this context. Because of this we simply delete the file everytime.</p>
<p>The security editor of Windows Explorer shows us the new descriptor.</p>
<p><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-3.jpg" alt="Bild" width="350" height="476" /></p>
<p>As you can see we did not remove the LogonSession Sid from the security descriptor. The logon SID resides in the principal&#8217;s token. It is used to add allow or deny access to a secured object but only for the time the user is logged on. This is because every time the user logs on, a new session Sid is generated. Additionally all calls to the LogonUser API get their own session Sid so a logon Sid is a fine grained access control that allows us not only to restrict access between users but also control access between several different instances of a user (consider the user itself as a class and all user tokens as instances of this class) .<br />
 However removing this LogonSID will be our next task because we do not need it here.</p>
<p>JWSCL supports us with a function that returns a <em>TJwSecurityId</em> of the logon session. The function is called <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/JwsclKnownSid_pas.html#JwGetLogonSID"><em>JwGetLogonSID</em></a> and resides in unit <a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/JwsclKnownSid_pas.html"><em>JwsclKnownSid</em></a> that we have to include additionally. Unfortunately there is a bug in <a title="Go to downloads." href="http://blog.delphi-jedi.net/2008/03/03/jwscl-release-revision-316/">revision 316</a> that makes it impossible to use it. For this reason I added an adapted version of the whole unit <em>JwsclKnownSid</em> . You can get it <a href="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/jwsclknownsid.zip">here</a>.</p>
<p>Let&#8217;s see how we can get rid of the logon sid.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">var</span> SD : TJwSecurityDescriptor;<br />
&nbsp; &nbsp; LogonSid,<br />
&nbsp; &nbsp; AliceSid : TJwSecurityId;<br />
&nbsp; &nbsp; SecAttrPtr : PSecurityAttributes;<br />
&nbsp; &nbsp; Handle : <span class="kw4">THandle</span>;<br />
&nbsp; &nbsp; PosInt : <span class="kw4">Integer</span>;<br />
<span class="kw1">begin</span><br />
&nbsp; SD := TJwSecurityDescriptor.<span class="me1">CreateDefaultByToken</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; LogonSid := JwGetLogonSID;</p>
<p>&nbsp; PosInt := SD.<span class="me1">DACL</span>.<span class="me1">FindSID</span><span class="br0">&#40;</span>LogonSid<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">if</span> PosInt &gt;= <span class="nu0">0</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp;SD.<span class="me1">DACL</span>.<span class="me1">Remove</span><span class="br0">&#40;</span>PosInt<span class="br0">&#41;</span>;<br />
&nbsp; LogonSid.<span class="me1">Free</span>;<br />
&#8230;</div>
<p><em>JwGetLogonSid </em>returns a new instance that can be used to search for the logon Sid in the DACL. The method <em><a title="Go to JWSCL Online Documentation." href="http://jwscldoc.delphi-jedi.net/TJwSecurityAccessControlList.html#FindSID">FindSID</a> </em>in <em>TJwDAccessControlList</em> goes through the whole access control list and returns the zero based index of the entry we search for. If it were not to be found we would get a negative result value, but this is not the case here (although we check for it because it is good programming style). At the end do not forget to remove the instance.</p>
<p><img src="http://blog.delphi-jedi.net/wp-content/uploads/2008/03/bild-4.jpg" alt="Bild" width="350" height="473" /></p>
<p>The new security descriptor does not contain the annoying logon Sid anymore. Eventually we can use this discussed approach not only for <em>CreateFile</em> but also for <em>CreatePipe</em>, <em>CreateProcess</em>, RegCreateKeyEx, <em>RegSaveKeyEx</em>, <em>CreateFileMapping</em> and many more. I used <em>CreateFile</em> so you can easily look up the descriptor in the security editor of Windows Explorer.</p>
<p>The next article will discuss how we can use inheritance and why there are no inherited access control elements in our created security descriptor although the parent folder hand them down.</p>
<p><strong>Tell me how you liked this blog entry by adding a comment.</strong></p>
<h2><strong>Update</strong></h2>
<p>Fixed all the links to the <a href="http://jwscldoc.delphi-jedi.net/" target="_blank">JWSCL Documentation</a>. I didn&#8217;t recognize that Doc-O-Matic changed the output tree format of the HTML Help.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2008/03/04/how-to-use-a-security-attribute-structure/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

