<?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; JEDI Windows Security Code Lib</title>
	<atom:link href="http://blog.delphi-jedi.net/category/jedi-windows-security-code-library/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>Sat, 21 Aug 2010 05:44:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<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>
<p><pre><pre class="brush:delphi">const JWSCLTestFolder = &#039;JWSCLTestFolder&#039;;

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

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

&nbsp;&nbsp;&nbsp;&nbsp;pSA := SD.Create_SA();
&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Win32Check(CreateDirectory(JWSCLTestFolder, pSA));
&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SD.Free_SA(pSA); //remember to free pointer
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;SD.Free;
&nbsp;&nbsp;end;
end.
</pre></pre></p>
<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>
<p><pre><pre class="brush:delphi">procedure MergeParentDACL(const Location : String; TargetSD : TJwSecurityDescriptor);
var DirSD : TJwSecureFileObject;
begin
&nbsp;&nbsp;DirSD := TJwSecureFileObject.Create(Location);
&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;TargetSD.DACL.AddACEs(DirSD.DACL);
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;DirSD.Free;
&nbsp;&nbsp;end;
end;

var
&nbsp;&nbsp;DirSD : TJwSecureFileObject;

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

&nbsp;&nbsp;SD := TJwSecurityDescriptor.Create;

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

&nbsp;&nbsp;&nbsp;&nbsp;MergeParentDACL(&#039;.&#039;, SD);

&nbsp;&nbsp;&nbsp;&nbsp;pSA := SD.Create_SA();
&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Win32Check(CreateDirectory(JWSCLTestFolder, pSA));
&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SD.Free_SA(pSA);
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;SD.Free;
&nbsp;&nbsp;end;
end.
</pre></pre></p>
<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>
<p><pre><pre class="brush:delphi">var
&nbsp;&nbsp;SD : TJwSecurityDescriptor;
&nbsp;&nbsp;DirSD : TJwSecureFileObject;
begin
&nbsp;&nbsp;JwInitWellKnownSIDs;

&nbsp;&nbsp;Win32Check(CreateDirectory(JWSCLTestFolder, nil));

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

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DirSD.SetSecurityDescriptor(SD, [siDaclSecurityInformation]);
&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SD.Free;
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;DirSD.Free;
&nbsp;&nbsp;end;
</pre></pre></p>
<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>
<p><pre><pre class="brush:delphi">uses
&nbsp;&nbsp;JwaWindows,

&nbsp;&nbsp;JwsclDescriptor,
&nbsp;&nbsp;JwsclTypes,
&nbsp;&nbsp;JwsclConstants,
&nbsp;&nbsp;JwsclKnownSid,
&nbsp;&nbsp;JwsclAcl,
&nbsp;&nbsp;JwsclMapping,
&nbsp;&nbsp;JwsclSecureObjects,
&nbsp;&nbsp;JwsclSid,
</pre></pre></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/24/setting-folder-security/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What is GetEffectiveRightsFromAcl for? #2</title>
		<link>http://blog.delphi-jedi.net/2010/03/13/what-is-geteffectiverightsfromacl-for-2/</link>
		<comments>http://blog.delphi-jedi.net/2010/03/13/what-is-geteffectiverightsfromacl-for-2/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 21:04:43 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[JWSCL]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=701</guid>
		<description><![CDATA[A long time ago I wrote an article about this strange WinAPI function called GetEffectiveRightsFromAcl. There was a problem that I showed how to solve (see my article and the comment in the MSDN doc). However, this function has never been a good way for retrieving the possible access mask. It seems that MS has [...]]]></description>
			<content:encoded><![CDATA[<p>A long time ago I wrote an <a href="http://blog.delphi-jedi.net/2008/09/10/what-is-geteffectiverightsfromacl-for/" target="_blank">article</a> about this strange WinAPI function called <a href="http://msdn.microsoft.com/en-us/library/aa446637%28VS.85%29.aspx" target="_blank">GetEffectiveRightsFromAcl</a>. There was a problem that I showed how to solve (see my article and the comment in the MSDN doc). However, this function has never been a good way for retrieving the possible access mask. It seems that MS has changed the MSDN article of this function and instead wrote an example that uses the MS Authz API. I translated the example but using JWSCL. You can see yourself how different it looks&#8230;</p>
<p><span id="more-701"></span></p>
<p>I have added some comments to the source code itself so you can read a description directly in the code.</p>
<p><pre><pre class="brush:delphi">program GetEffectiveRightsFromAclTest;

uses
&nbsp;&nbsp;JwaWindows,
&nbsp;&nbsp;JwsclKnownSid,
&nbsp;&nbsp;JwsclConstants,
&nbsp;&nbsp;JwsclTypes,
&nbsp;&nbsp;JwsclExceptions,
&nbsp;&nbsp;JwsclSecureObjects,
&nbsp;&nbsp;JwsclSid,
&nbsp;&nbsp;JwsclDescriptor,
&nbsp;&nbsp;JwsclAuthCtx,
&nbsp;&nbsp;JwsclMapping,
&nbsp;&nbsp;JwsclUtils,
&nbsp;&nbsp;JwsclACL,

&nbsp;&nbsp;Dialogs,
&nbsp;&nbsp;SysUtils;

//computes granted access mask for a security descriptor and a SID
//An error is thrown by an exception - typical JWSCL
function GetEffectiveAccess(const SD : TJwSecurityDescriptor;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const Sid : TJwSecurityId) : DWORD;
var
&nbsp;&nbsp;AuthRM : TJwAuthResourceManager;
&nbsp;&nbsp;AuthCtx : TJwAuthContext;
&nbsp;&nbsp;AuthReply : TJwAuthZAccessReply;
&nbsp;&nbsp;Request : TJwAuthZAccessRequest;
begin
&nbsp;&nbsp;//The following code uses the MS AuthZ API
&nbsp;&nbsp;//JWSCL wraps the function calls
&nbsp;&nbsp;AuthRM := TJwAuthResourceManager.Create(&#039;&#039;, [], nil, nil);
&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;//Tell AuthZ to use a SID for access checking
&nbsp;&nbsp;&nbsp;&nbsp;//We also could use a token and prevent the problem of
&nbsp;&nbsp;&nbsp;&nbsp;// restricted Administrators in Vista/7
&nbsp;&nbsp;&nbsp;&nbsp;AuthCtx := TJwAuthContext.CreateBySid(AuthRM, [], Sid, 0, nil);
&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//As documented AccessCheck returns a GrantedAccessMask
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;when using MAXIMUM_ALLOWED
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Request := TJwAuthZAccessRequest.Create(MAXIMUM_ALLOWED,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JwNullSID, nil, nil, shOwned);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//does the access check using a generic mapping to file/folder
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AuthCtx.AccessCheck(0, Request, 0, SD, nil,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TJwSecurityFileFolderMapping, AuthReply, nil);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//return the granted access mask
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result := AuthReply.GrantedAccessMask[0];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Request.Free;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AuthCtx.Free;
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;AuthRM.Free;
&nbsp;&nbsp;end;
end;

//computes granted access mask for a file and username
//An error is thrown by an exception - typical JWSCL
function GetEffectiveAccessFromFile(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const FileName,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DomainName, UserName : string) : DWORD;
var
&nbsp;&nbsp;F : TJwSecureFileObject;
&nbsp;&nbsp;SD : TJwSecurityDescriptor;
&nbsp;&nbsp;Flags : TJwSecurityInformationFlagSet;
&nbsp;&nbsp;Sid : TJwSecurityId;
begin
&nbsp;&nbsp;//Translate username and domainname into a SID
&nbsp;&nbsp;//Throws an EJwsclWinCallFailedException if
&nbsp;&nbsp;//&nbsp;&nbsp;the username could not be translated
&nbsp;&nbsp;Sid := TJwSecurityId.Create(DomainName, UserName);
&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;F := TJwSecureFileObject.Create(FileName);
&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//adding siLabelSecurityInformation makes no sense
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;since it cannot be checked against a simple SID
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flags := [siOwnerSecurityInformation,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;siGroupSecurityInformation,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;siDaclSecurityInformation];

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//get the security descriptor (result is not cached)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SD := F.GetSecurityDescriptor(Flags);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result := GetEffectiveAccess(SD, Sid);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SD.Free;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;F.Free;
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;Sid.Free;
&nbsp;&nbsp;end;
end;

const
&nbsp;&nbsp;Target = &#039;C:\Windows&#039;;
&nbsp;&nbsp;UserName = &#039;Christian&#039;;

var AccessMask : TJwAccessMask;
begin
&nbsp;&nbsp;JwInitWellKnownSIDs;

&nbsp;&nbsp;AccessMask := GetEffectiveAccessFromFile(Target, &#039;&#039;, UserName);
&nbsp;&nbsp;ShowMessage(Format(&#039;File/Folder: %s&#039;#13#10&#039;User: %s&#039;#13#10&#039;%s&#039;,
&nbsp;&nbsp;&nbsp;&nbsp;[Target,
&nbsp;&nbsp;&nbsp;&nbsp; UserName,
&nbsp;&nbsp;&nbsp;&nbsp; JwFormatAccessRights(AccessMask, FileFolderMapping)]));
end.
</pre></pre></p>
<p>Be aware that the code does the same as GetEffectiveRightsFromAcl.</p>
<h3>Restricted Administrator account in Vista/7</h3>
<p>Also it does not take into account a restricted Vista account. The reason is that the privileges of an Administrator account are stripped away only when a user logs on. So the account management does not behave differently to Windows XP. Since we use an account name the function only finds the Administrators group in the membership list of the user. Thus we may see a fullly granted access mask as a result when using the function on e.g. the Windows folder.</p>
<h3>Integrity Level in Vista/7</h3>
<p>Of course, we cannot use the mandatory label (notice <em>siLabelSecurityInformation</em>) of a file or folder because the integrity level of the user is only known when she is logged on. Thus if a folder has a high integrity level, the function will still return full access control even if the user cannot write access (no-write-up) the folder when logged on.</p>
<h3>Download</h3>
<p>Download <a href="http://blog.delphi-jedi.net/wp-content/uploads/2010/03/GetEffectiveRightsFromAclWithAuthZ.zip">GetEffectiveRightsFromAclWithAuthZ</a>.pas</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/13/what-is-geteffectiverightsfromacl-for-2/feed/</wfw:commentRss>
		<slash:comments>0</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>
<p><pre><pre class="brush:delphi">
uses
&nbsp;&nbsp;SysUtils,
&nbsp;&nbsp;//JwaWindows, //Use either JwaWindows or these JEDI headers:
&nbsp;&nbsp;JwaWinBase,
&nbsp;&nbsp;JwaWinType,
&nbsp;&nbsp;JwaWinNT,
&nbsp;&nbsp;JwaAclApi,
&nbsp;&nbsp;JwaAccCtrl,
&nbsp;&nbsp;JwaWinError,
&nbsp;&nbsp;JwaSddl;

type
&nbsp;&nbsp;TOwnerResult = (orNone, orName, orSID);

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

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

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

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

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result := orName;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Domain&nbsp;&nbsp; := pszDomainName;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Username := pszOwnerName;
&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeMem(pszDomainName);
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;FreeMem(pszOwnerName);
&nbsp;&nbsp;end;
end;
</pre></pre></p>
<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>
<p><pre><pre class="brush:delphi">function JwsclGetFileOwner(const FileName: string;
&nbsp;&nbsp;out Domain, Username: String): TOwnerResult;
var
&nbsp;&nbsp;F : TJwSecureFileObject;
&nbsp;&nbsp;Owner : TJwSecurityId;
begin
&nbsp;&nbsp;F := TJwSecureFileObject.Create(FileName);
&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;Owner := F.Owner; //Owner is cached/freed by TJwSecureFileObject
&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Domain := Owner.GetAccountDomainName();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Username := Owner.GetAccountName();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Result := orName;
&nbsp;&nbsp;&nbsp;&nbsp;except
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on E : EJwsclWinCallFailedException do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if E.LastError = ERROR_NONE_MAPPED then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Domain := &#039;&#039;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Username := Owner.StringSID;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Result := orSID;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;F.Free;
&nbsp;&nbsp;end;
end;
</pre></pre></p>
<p>In a next version of JWSCL (currently trunk) the exception handling will be a little bit different:</p>
<p><pre><pre class="brush:delphi">function JwsclGetFileOwner2(const FileName: string;
&nbsp;&nbsp;out Domain, Username: String): TOwnerResult;
var
&nbsp;&nbsp;F : TJwSecureFileObject;
&nbsp;&nbsp;Owner : TJwSecurityId;
begin
&nbsp;&nbsp;F := TJwSecureFileObject.Create(FileName);
&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;Owner := F.Owner; //Owner is cached/freed by TJwSecureFileObject
&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Domain := Owner.GetAccountDomainName();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Username := Owner.GetAccountName();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Result := orName;
&nbsp;&nbsp;&nbsp;&nbsp;except
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on E : EJwsclSidNotMappedException do //not mapped error is handled differently
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Domain := &#039;&#039;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Username := Owner.StringSID;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Result := orSID;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;F.Free;
&nbsp;&nbsp;end;
end;
</pre></pre></p>
<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>
<!-- PHP 5.x -->]]></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>JWSCL and FreeAndNil</title>
		<link>http://blog.delphi-jedi.net/2010/02/25/jwscl-and-freeandnil/</link>
		<comments>http://blog.delphi-jedi.net/2010/02/25/jwscl-and-freeandnil/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 11:54:59 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[JWSCL]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=660</guid>
		<description><![CDATA[There is a lot of talking about the usage of FreeAndNil in destructors. I&#8217;ve never thought about it before so I used it quite often even in destructors. Although I don&#8217;t use it as a universal remedy function, it still seems to be a bad design: a thought shared by many leading Delphi experts.  Thus [...]]]></description>
			<content:encoded><![CDATA[<p>There is a lot of talking about the usage of FreeAndNil in destructors. I&#8217;ve never thought about it before so I used it quite often even in destructors. Although I don&#8217;t use it as a universal remedy function, it still seems to be a bad design: a thought shared by many leading Delphi experts.  Thus I refactored the destructors in JWSCL to accompany them.</p>
<p><span id="more-660"></span>I introduced a function similar to FreeAndNil</p>
<p><pre class="brush:delphi">procedure JwFree(var Obj);</pre></p>
<p>It just frees an object&#8230;in the release build of an application. However, in a debug build it additionally sets the value of obj to $C which isn&#8217;t a valid memory address. So &#8220;Assigned&#8221; won&#8217;t work here.<br />
 Any access to this &#8220;freed&#8221; member will generate an AccessViolation at address $0000000C. So you will know that a member of JWSCL was used beyond its life time.</p>
<p><pre><pre class="brush:delphi">procedure JwFree(var Obj);
var
 Temp: TObject;
begin
&nbsp;&nbsp;Temp := TObject(Obj);
{$IFDEF DEBUG}
&nbsp;&nbsp;Pointer(Obj) := Pointer($C);
{$ENDIF DEBUG}
&nbsp;&nbsp;Temp.Free;
end;</pre></pre></p>
<p>I wonder if it should be extended to support different flavors like</p>
<ol>
<li>$C in debug build and don&#8217;t touch the value in release (as currently shown)</li>
<li>Set the value $C also in release mode.</li>
<li>Nil the value in release mode. (quiet death mode)</li>
</ol>
<p>They could be set by a compiler switch. Still have to think about this though&#8230;<br />
 What do you think?</p>
<h2>Changes</h2>
<p>I have commited these changes into the developer branch. They will be published in a next release so the current release won&#8217;t break a bad design.</p>
<p> <img src='http://blog.delphi-jedi.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/02/25/jwscl-and-freeandnil/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>ACTRL_ACCESS Diagram</title>
		<link>http://blog.delphi-jedi.net/2010/02/11/actrl_access-diagram/</link>
		<comments>http://blog.delphi-jedi.net/2010/02/11/actrl_access-diagram/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 12:08:22 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=631</guid>
		<description><![CDATA[I had some trouble with this rather complicated COM structure called ACTRL_ACCESS. So I post a diagram to show its design. Otherwise it would be a pity to leave it on my private hard drive. The ACTRL_ACCESS structure is used by the interface method IAccessControl::GetAllAccessRights (and others) which is rather hard to implement yourself because [...]]]></description>
			<content:encoded><![CDATA[<p>I had some trouble with this rather complicated COM structure called ACTRL_ACCESS. So I post a diagram to show its design. Otherwise it would be a pity to leave it on my private hard drive.</p>
<p><span id="more-631"></span></p>
<p>The <a href="http://msdn.microsoft.com/en-us/library/ms693447%28VS.85%29.aspx">ACTRL_ACCESS</a> structure is used by the interface method <a href="http://msdn.microsoft.com/en-us/library/ms688536%28VS.85%29.aspx">IAccessControl::GetAllAccessRights</a> (and others) which is rather hard to implement yourself because the structure must be created in a single block of memory that can be freed by CoTaskMemFree.</p>
<p>So here is how it looks like</p>
<div id="attachment_632" class="wp-caption alignnone" style="width: 427px"><a href="http://blog.delphi-jedi.net/wp-content/uploads/2010/02/IAccessControl_GetAllAccessRights-structures.png" rel="lightbox[631]" title="IAccessControl_GetAllAccessRights structures"><img class="size-full wp-image-632 " title="IAccessControl_GetAllAccessRights structures" src="http://blog.delphi-jedi.net/wp-content/uploads/2010/02/IAccessControl_GetAllAccessRights-structures.png" alt="ACTRL_ACCESS design diagram" width="417" height="399" /></a><p class="wp-caption-text">ACTRL_ACCESS design diagram</p></div>
<p>Luckily, JWSCL will provide an implementation of IAccessControl so don&#8217;t worry.</p>
<p><br class="spacer_" /></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/02/11/actrl_access-diagram/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bugfix in JwsclTerminalServer</title>
		<link>http://blog.delphi-jedi.net/2010/01/13/bugfix-in-jwsclterminalserver/</link>
		<comments>http://blog.delphi-jedi.net/2010/01/13/bugfix-in-jwsclterminalserver/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 12:43:20 +0000</pubDate>
		<dc:creator>Remko</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/2010/01/13/bugfix-in-jwsclterminalserver/</guid>
		<description><![CDATA[I just commited (revision 843) a little bugfix that existed since revision 833. In TJwWTSSession.Create LocalFree was called (after StrConnect) without LocalAlloc. Since utildll.dll handles the memory allocation is it not needed at all. [Update] The fix is currently only available in the developer version repository (aka trunk) of Subversion.]]></description>
			<content:encoded><![CDATA[<p>I just commited (revision 843) a little bugfix that existed since revision 833. In TJwWTSSession.Create LocalFree was called (after StrConnect) without LocalAlloc. Since utildll.dll handles the memory allocation is it not needed at all.</p>
<p>[Update]<br />
The fix is currently only available in the developer version repository (aka trunk) of Subversion.</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/01/13/bugfix-in-jwsclterminalserver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Improvements to Jwscl&#8217;s Terminal Server unit</title>
		<link>http://blog.delphi-jedi.net/2010/01/08/improvements-to-jwscls-terminal-server-unit/</link>
		<comments>http://blog.delphi-jedi.net/2010/01/08/improvements-to-jwscls-terminal-server-unit/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 15:38:05 +0000</pubDate>
		<dc:creator>Remko</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=595</guid>
		<description><![CDATA[I have just commited an updated version of my Terminal Server unit (revision 842) into SVN. I have done some tests on Windows 7 (a fix for Windows 7 was done in Jwa revision 830 btw) and all seems to work well. Internally the Connect method of TJwTerminalServer verifies the connection to Terminal Server by [...]]]></description>
			<content:encoded><![CDATA[<p>I have just commited an updated version of my <a href="http://jwscldoc.delphi-jedi.net/index.html?frmname=topic&amp;frmfile=JwsclTerminalServer_pas.html">Terminal Server unit</a> (revision 842) into SVN. I have done some tests on Windows 7 (a fix for Windows 7 was done in Jwa revision 830 btw) and all seems to work well.</p>
<p>Internally the <a href="http://jwscldoc.delphi-jedi.net/TJwTerminalServer_Connect.html">Connect</a> method of TJwTerminalServer verifies the connection to Terminal Server by reading some property. This is done because of a change in the API&#8217;s by Microsoft: opening a handle with WTSOpenServer to a nonexisting server actually returns a valid handle. I reported this as a bug to Microsoft some time ago and the &#8220;fixed it&#8221; by changing the <a href="http://msdn.microsoft.com/en-us/library/aa383837%28VS.85%29.aspx">documentation</a>.</p>
<p>For those interested in the code: it is a class function called IsValidServerHandle which can be used to verify a handle returned by WTSOpenServer:</p>
<p><pre><pre class="brush:delphi">class function TJwTerminalServer.IsValidServerHandle(const hServer: THandle): Boolean;
var
&nbsp;&nbsp;dwSize: DWORD;
&nbsp;&nbsp;WinStaInfo: WINSTATIONINFORMATIONW;
begin
&nbsp;&nbsp;{ All Windows &lt; Vista return 0 on Invalid handle }
&nbsp;&nbsp;Result := hServer &lt;&gt; 0;

&nbsp;&nbsp;{ No need to continue if it&#039;s already invalid... }
&nbsp;&nbsp;if not Result then
&nbsp;&nbsp;&nbsp;&nbsp;Exit;

&nbsp;&nbsp;{ For Windows &gt;= Vista we need to make a query to be sure
&nbsp;&nbsp;&nbsp;&nbsp;A non valid connection will fail on WTSQuerySessionInformation and will
&nbsp;&nbsp;&nbsp;&nbsp;return LastError RPC_S_SERVER_UNAVAILABLE }
&nbsp;&nbsp;if (TJwWindowsVersion.IsWindowsVista(True)) or
&nbsp;&nbsp;&nbsp;&nbsp;(TJwWindowsVersion.IsWindows2008(True)) then
&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;Result := WinStationQueryInformationW(hServer, 65536, WinStationInformation,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@WinStaInfo, sizeof(WinStaInfo), dwSize) or (GetLastError() &lt;&gt; RPC_S_SERVER_UNAVAILABLE);
&nbsp;&nbsp;end;
end;</pre></pre></p>
<p>A more visible change is the introduction of the Session function of TJwTerminalServer, with this function you can get all details for a specific session. It is meant for those cases where you need only one specific session and is of course far more efficient than enumerating all sessions, retrieving all sessions details and then finding the particular session in the SessionList.</p>
<p>The signature of the function is:</p>
<p><pre><pre class="brush:delphi">function TJwTerminalServer.Session(const SessionId: TJwSessionId = WTS_CURRENT_SESSION): TJwWTSSession;
</pre></pre></p>
<p>Note that the parameter is default so you can call both:</p>
<p><pre class="brush:delphi">Session := TS.Session;&nbsp;&nbsp;// Retrieve the current Session</pre></p>
<p>and</p>
<p><pre class="brush:delphi">Session := TS.Session(1); // Retrieve the session with SessionId 1</pre></p>
<p>It is important to understand the difference between Session and Sessions: where Session returns an instance of <a href="http://jwscldoc.delphi-jedi.net/TJwWTSSession.html">TJwWTSSession</a>, SessionS returns a <a href="http://jwscldoc.delphi-jedi.net/TJwWTSSessionList.html">SessionList</a>. This is especially important because Session works with a SessionId parameters and Sessions (being a TObjectList descendant) is accessed with by Index which is just the position in the ObjectList.</p>
<p>If a Session is not found an EJwsclWinCallFailedException will be raised so you&#8217;d better wrap the call into a try..except handler!</p>
<p>The last remark is that you, the caller, are responsible for freeing the object so a more complete sample would be like this:</p>
<p><pre><pre class="brush:delphi">var
&nbsp;&nbsp;TS: TJwTerminalServer;
&nbsp;&nbsp;Session: TJwWTSSession;
begin
&nbsp;&nbsp;TS := TJwTerminalServer.Create;
&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session := TS.Session;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Work with the session object
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowMessageFmt(&#039;Username=%s&#039;, [Session.Username]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session.PostMessage(&#039;Hello from the Jedi guys!&#039;, &#039;Message&#039;, MB_OK);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeAndNil(Session);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;&nbsp;&nbsp;except
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Handle Exception here!
&nbsp;&nbsp;&nbsp;&nbsp;end;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;FreeAndNil(TS);
&nbsp;&nbsp;end;
end;
</pre></pre></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/01/08/improvements-to-jwscls-terminal-server-unit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Update of JWSCL 0.9.2a for Supporting Windows 7</title>
		<link>http://blog.delphi-jedi.net/2009/11/16/update-of-jwscl-0-9-2a-for-supporting-windows-7/</link>
		<comments>http://blog.delphi-jedi.net/2009/11/16/update-of-jwscl-0-9-2a-for-supporting-windows-7/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 13:06:50 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows Security Code Lib]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=580</guid>
		<description><![CDATA[I have updated JWSCL Version 0.9.2a to support Windows 7. Version 0.9.3 supports Windows 7 from the beginning but since many people use 0.9.2a, I have decided to merge Windows 7 support. You can still use 0.9.2a because bugs and problems will still be fixed (until told otherwise). However, there won&#8217;t be added any new [...]]]></description>
			<content:encoded><![CDATA[<p>I have updated JWSCL Version <strong>0.9.2a</strong> to support Windows 7. Version <strong>0.9.3</strong> supports Windows 7 from the beginning but since many people use 0.9.2a, I have decided to merge Windows 7 support.</p>
<p><span id="more-580"></span></p>
<p>You can still use 0.9.2a because bugs and problems will still be fixed (until told otherwise). However, there won&#8217;t be added any new features. To get new features you need to upgrade to a newer version.</p>
<h3>Details</h3>
<p>The problem is located in class TJwWindowsVersion (unit JwsclVersion.pas) where all <em>IsWindowsXXX </em>routines  return <strong>false </strong>if you check for a specific Windows Version or newer (Parameter set to true) and run it on Windows 7.</p>
<h3>How to Update</h3>
<p>There is no separate download, but you can update your local source if you have &#8220;.svn&#8221; folders in your JWSCL folders. Just use a Subversion client like TortoiseSVN and open the Explorer&#8217;s context menu to selected &#8220;SVN Update&#8221; on the root folder of JWSCL (e.g. JWSCL\0.9.2a\).</p>
<h3>Update &lt;-&gt; Upgrade</h3>
<p>Be aware that update means that you get the latest changes for this version (e.g. 0.9.2a). So you won&#8217;t upgrade to any newer version like 0.9.3.</p>
<h3>Update Notifications</h3>
<p>You can subscribe to a mailinglist to get notified about changes in JWSCL and JWA. Just subscribe to <a href="http://sourceforge.net/mailarchive/forum.php?forum_name=jedi-apilib-wscl-svn"> jedi-apilib-wscl-svn </a> (also use this <a title="Go to subscription page" href="http://lists.sourceforge.net/mailman/listinfo/jedi-apilib-wscl-svn" target="_blank">link</a> to subscribe). Furthermore there is an archive to see all commits of JWSCL and JWA.</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2009/11/16/update-of-jwscl-0-9-2a-for-supporting-windows-7/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Case of The Failed Loading of The User Profile</title>
		<link>http://blog.delphi-jedi.net/2009/07/20/the-case-of-the-failed-loading-of-the-user-profile/</link>
		<comments>http://blog.delphi-jedi.net/2009/07/20/the-case-of-the-failed-loading-of-the-user-profile/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 20:52:45 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[JEDI Windows Security Code Lib]]></category>
		<category><![CDATA[Administrator]]></category>
		<category><![CDATA[JWSCL]]></category>
		<category><![CDATA[profile]]></category>
		<category><![CDATA[Registry]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=370</guid>
		<description><![CDATA[Some time ago, I was in the situation to set up a new computer with a Windows XP 64 CD. Well it doesn&#8217;t matter that it was 64bit.  However, I always create a separate partitions for Windows XP. And because user profiles tend to get big, I moved a new user to a second partition. [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago, I was in the situation to set up a new computer with a Windows XP 64 CD. Well it doesn&#8217;t matter that it was 64bit.  However, I always create a separate partitions for Windows XP. And because user profiles tend to get big, I moved a new user to a second partition. (See the Internet how it is done) But as if it wasn&#8217;t enough I thought that I also could move the Administrator profile that easy. Way wrong!</p>
<p><span id="more-370"></span>First of all, copying a loaded user profile isn&#8217;t possible without the BACKUP privilege. You can&#8217;t open already opened files a second time (share deny). The solution is: Either you can use a backup application that runs with the special privilege or you can just use another administrative user (which I did).</p>
<p>There are some keys which have absolute path variables that must be changed, too. But that is a minor problem. The big problem was that Windows could not load the profile of the Administrator. Windows tried to start up the users desktop but then failed with the dialog:  &#8220;Windows failed to load user profile.&#8221;</p>
<p>It got more confusing because every other user in the system didn&#8217;t suffer from this problem. And to top it,  sometimes I could successfully login to the Administrator account.</p>
<h3>Solution</h3>
<p>In such cases the event manager is a good way to find the error source. In my case, it told me that &#8220;NTUSER.DAT&#8221; (this is where Windows stores the current user keys called a <a href="http://msdn.microsoft.com/en-us/library/ms724877%28VS.85%29.aspx">registry hive</a>) was already opened by another process. I really can&#8217;t say why this was the case because it shouldn&#8217;t be the case shortly after a fresh boot up. (Of course, the file was correct, it had no write protection, and security was set accordingly)</p>
<p>In such a case you usually have some ways to fix the problem:</p>
<p>1. Reinstall Windows<br />
Good choice. But too much work &#8212; and who will promise me that it won&#8217;t happen again?</p>
<p>2. Leave Administrator where it was<br />
Also good choice. And I tried it. However my Windows could not handle two profile places somehow and the very same error occured with the old profile location.</p>
<p>3. Live with the situation<br />
Some people do it. I thought about it, too, I have to admit. That&#8217;s because there is a user called root in the system now.</p>
<p>4. Find the bug and ignore how much time it will cost.<br />
Ouch. I don&#8217;t have time, so not a good option.</p>
<p>5.Create a workaround.<br />
YES! That&#8217;s what I did.</p>
<p>So I came up with a practical and fast solution. As I&#8217;ve already written, the user&#8217;s registry hive could not be loaded.<br />
Why? I don&#8217;t know much about it but the registry file was blocked.<br />
Well, I&#8217;ve found out that if the Administrator registry hive was already loaded (HKEY_USERS\S-1-5-21-xxx-500 is visible) the Windows could successfully logon the Administrator. I simulated this situation by manually loading the user&#8217;s profile using the <a href="http://msdn.microsoft.com/en-us/library/bb762281%28VS.85%29.aspx" target="_blank">LoadUserProfile</a> function from Windows API. Well, it always worked!</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">uses</span><br />
&nbsp; JwaWindows,<br />
&nbsp; JwsclToken,<br />
&nbsp; jwscltypes;</p>
<p><span class="kw1">var</span><br />
&nbsp; &nbsp;T : TJwSecurityToken;<br />
&nbsp; &nbsp;ProfileInfo : TJwProfileInfo;<br />
<span class="kw1">begin</span><br />
&nbsp; T := TJwSecurityToken.<span class="me1">CreateTokenByProcess</span><span class="br0">&#40;</span><span class="nu0">0</span>, TOKEN_ALL_ACCESS<span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; T.<span class="me1">LoadUserProfile</span><span class="br0">&#40;</span>ProfileInfo, <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; <span class="kw1">finally</span><br />
&nbsp; &nbsp; T.<span class="me1">Free</span>;<br />
&nbsp; <span class="kw1">end</span>;</div>
<p>The next step was to do it automatically before an Administrator could logon. Of course, I could have created a service which loads the user profile at startup but I wanted to be fast so there is another option called Task Scheduler.<br />
Every Windows startup I let run the code above as a simple task with Administrator credentials (needs password).</p>
<p>I don&#8217;t know whether the Task Scheduler loads the profile (I would guess so). However the problem is that the profile could be unloaded after the process has ended. So the hive would be removed and logon would no more be possible.</p>
<p>Thus the code above just loads the profile but does not unload it. Since profiles are not watched by Windows (at least in XP) the registry hive  stays loaded and a logon attempt will work (T.Free won&#8217;t unload it!).</p>
<h3>JEDI Windows Security Code Library used features</h3>
<ul>
<li><a href="http://jwscldoc.delphi-jedi.net/TJwSecurityToken.html">TJwSecurityToken</a> (class)<a href="http://jwscldoc.delphi-jedi.net/TJwSecurityToken.html"><br />
</a></li>
<li>TJwSecurityToken.<a href="http://jwscldoc.delphi-jedi.net/TJwSecurityToken_LoadUserProfile@TJwProfileInfo@TJwProfileMembers.html" target="_blank">LoadUserProfile</a> (method)</li>
</ul>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2009/07/20/the-case-of-the-failed-loading-of-the-user-profile/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>When 4 bytes can be too much</title>
		<link>http://blog.delphi-jedi.net/2009/03/16/when-4-bytes-can-be-too-much/</link>
		<comments>http://blog.delphi-jedi.net/2009/03/16/when-4-bytes-can-be-too-much/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 13:00:26 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JEDI Windows Security Code Lib]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=310</guid>
		<description><![CDATA[Recently, I&#8217;ve found a bug in JWSCL. It happened that the function GetInheritanceSourceW didn&#8217;t work for me anymore. A long time ago I used this function for the last time and now again. However the strange thing was that the function returned no error but it didn&#8217;t fill a result array with expected inheritance data. [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I&#8217;ve found a bug in JWSCL. It happened that the function <em>GetInheritanceSourceW </em>didn&#8217;t work for me anymore. A long time ago I used this function for the last time and now again. However the strange thing was that the function returned no error but it didn&#8217;t fill a result array with expected inheritance data. The result was always zero for all members of the structure. What happened?</p>
<p><span id="more-310"></span></p>
<p>After long back and forth trying to find the error by reviewing codes, I decided to go back to an older version of JWSCL. I had to get back about 300 revisions (commits) to find a working JWSCL code. However I still couldn&#8217;t find out what the difference was until&#8230;</p>
<p>Well, after the 301th revision (anywhere near that) I decided to rewrite the codes which maintain the access control list and elements for WinAPI functions (structures like ACL, ACE_HEADER) . I conducted intensive tests but it seemed that this particular function GetInheritanceSourceW wasn&#8217;t tested at all! Shame on me.</p>
<p>&#8230; until I could compare old, but working ACL structures with new ones. Each ACL consists of access control elements (ACE) which usually look like this:</p>
<div class="dean_ch" style="white-space: wrap;">_ACCESS_XXX_ACE = <span class="kw1">record</span><br />
&nbsp;Header: ACE_HEADER;<br />
&nbsp;Mask: ACCESS_MASK;<br />
&nbsp;SidStart: <span class="kw4">DWORD</span>;<br />
<span class="kw1">end</span>;</div>
<p>(XXX stands for ALLOW or DENY.)</p>
<p>This record is much more complicated than it looks. If you need to find out its real size you cannot just use the sizeof operator. Some background information will explain why. An ACE consists of a header which is also a structure (but not the problem here), its access mask (no problem again) and a SidStart. What about the Start in Sid? Well, a Security Identifier (SID &#8211; the user&#8217;s ID) is assigned to every ACE. But how does it work? A SID is a variable length structure. And so usually, we store a SID into a structure and retrieve a pointer to it. But a DWORD is apparently not a pointer and it would not be a good idea to just typecast it to DWORD. The main idea is that SidStart is a placeholder where the SID structure starts. If you&#8217;re ever going to create an ACE structure you need to create a block of memory that can hold the first two members of the ACE structure and the SID you want to store. So actually the ACE structure looks like this:</p>
<div class="dean_ch" style="white-space: wrap;">_ACCESS_XXX_ACE = <span class="kw1">record</span><br />
&nbsp;Header: ACE_HEADER;<br />
&nbsp;Mask: ACCESS_MASK;<br />
&nbsp;Sid: <span class="kw1">array</span><span class="br0">&#91;</span><span class="nu0">0</span>..<span class="me1">variable_sid_size</span><span class="nu0">-1</span><span class="br0">&#93;</span> <span class="kw1">of</span> <span class="kw4">byte</span>;<br />
<span class="kw1">end</span>;</div>
<p>As you already figured out, this structure is invalid in Delphi. However it should just show you how the structure is intended to be used.</p>
<p>The bug, this article is about, came from the fact that in addition to the size of the structure, the size of the SID was added. So in total 4+4+4+x = 12+x bytes were returned where x is size of the SID.<br />
The real size is in fact: 4+4+x = 8+x bytes.</p>
<p>The reason why this can be a problem comes from the fact that these ACE structures are stored in a row in memory. If you jump 12+x bytes from the first ACE structure you&#8217;ll get to the second one. 12+x bytes more you have the 3rd one and so on. The size of an ACE structure is applied to the AddAce function so it knows how far to jump to get to a specific ACE. However if a function doesn&#8217;t care about the size and uses the &#8220;correct&#8221; 8+x bytes to jump &#8211; well, it gets messy.<br />
IMO this happened here.</p>
<p>Many functions obviously don&#8217;t care about this because they use the official API (GetAce etc) . I didn&#8217;t find this problem because I&#8217;ve used a lot of JWSCL functions which internally convert the ACL classes to C-structures with no problem most of the WinAPI functions. However GetInheritanceSourceW is a big function which is messing around with the ACL directly to obtain the correct inheritance path. I didn&#8217;t try to understand it completely because I&#8217;ve already created a method which simulates the behavior of the original. I call it TJwSecureFileObject.GetFileInheritanceSource (currently only files are supported).</p>
<p>Strange things can happen if you dive deep into Win32 programming. As an advice you should always check every byte several times over and over to avoid or find such errors.</p>
<p>Happy programming!</p>
<h2>Update</h2>
<p>This error was fixed in revision 761 of 0.9.2.a branch and, of course, the developer version (trunk).</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2009/03/16/when-4-bytes-can-be-too-much/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
