<?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</title>
	<atom:link href="http://blog.delphi-jedi.net/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, 13 Mar 2010 21:10:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<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>
]]></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>Site Recommendation: History of Windows</title>
		<link>http://blog.delphi-jedi.net/2010/03/13/site-recommondation-history-of-windows/</link>
		<comments>http://blog.delphi-jedi.net/2010/03/13/site-recommondation-history-of-windows/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 23:13:27 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[Recommendation]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=697</guid>
		<description><![CDATA[If you are interested in the history of Windows, as I am, you should read the article The Secret Origin of Windows by Tandy Trower the product manager of Windows 1.0. This article gives a deep insight into the journey Tandy and his developers had to endure to bring a product on the market that [...]]]></description>
			<content:encoded><![CDATA[<p>If you are interested in the history of Windows, as I am, you should read the article<a href="http://technologizer.com/2010/03/08/the-secret-origin-of-windows/" target="_blank"> <strong>The Secret Origin of Windows</strong></a> by Tandy Trower the product manager of Windows 1.0. This article gives a deep insight into the journey Tandy and his developers had to endure to bring a product on the market that should change the world (although it took a while).</p>
<p><span id="more-697"></span>Tandy also mentions the competitor Borland with its famous Turbo Pascal (that I also used) and how it got Bill Gates to tremble.</p>
<p><cite>At $50 for the Borland product vs. the Microsoft $400 compiler, it was a bit like comparing a VW to a Porsche. But while Turbo Pascal was lighter weight for serious development, it was almost as quick for programming and debugging as Microsoft’s BASIC interpreters</cite></p>
<p>I wonder if the comment about the speed is true?</p>
<p>And did you know that Microsoft had been using the language Pascal for their projects until they developed C ?</p>
<p>Read more about <a onclick="pageTracker._trackPageview ('/outgoing/http_technologizer_com_2010_03_08_the_secret_origin_of_windows_');" rel="nofollow" href="http://technologizer.com/2010/03/08/the-secret-origin-of-windows/" target="_blank">The Secret Origin of Windows</a></p>
<p><br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/13/site-recommondation-history-of-windows/feed/</wfw:commentRss>
		<slash:comments>2</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>
]]></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>Site Recommendation: Terminal Session and Desktops</title>
		<link>http://blog.delphi-jedi.net/2010/03/05/site-recommendation-terminal-session-and-desktops/</link>
		<comments>http://blog.delphi-jedi.net/2010/03/05/site-recommendation-terminal-session-and-desktops/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 18:24:46 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>
		<category><![CDATA[Recommendation]]></category>
		<category><![CDATA[Russinovich]]></category>
		<category><![CDATA[Session]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=674</guid>
		<description><![CDATA[Many Windows Programmers still have trouble when it comes to sessions, window stations and desktops. They frequently get mixed up and we can see a lot of question on the Internet about e.g. how to spawn processes in all logged-on user desktops (rather than sessions).  Hence, I have listed some articles that you can read [...]]]></description>
			<content:encoded><![CDATA[<p>Many Windows Programmers still have trouble when it comes to sessions, window stations and desktops. They frequently get mixed up and we can see a lot of question on the Internet about e.g. how to spawn processes in all logged-on user desktops (rather than sessions).  Hence, I have listed some articles that you can read to get a better understanding of such things like a Terminal Sessions.</p>
<p><span id="more-674"></span></p>
<p>To understand the concept of Window Sessions, Stations and Desktop it is not necessary to read all articles to the end. I think the beginning is just fine.</p>
<ul>
<li><strong>Pushing the Limits of Windows: USER and GDI Objects</strong><br />
 Mark Russinovich writes about USER and GDI objects but he also gives a basic introduction how sessions, windowstations and desktops are related.  </p>
<ul>
<li><a href="http://blogs.technet.com/markrussinovich/archive/2010/02/24/3315174.aspx" target="_blank">Part 1 </a></li>
<li>Part 2  (still writing)</li>
</ul>
</li>
<li><strong>Desktop Heap Overview</strong><br />
 The guys from<strong> Advanced Windows Debugging and Troubleshooting</strong> explain how it is possible that a desktop can run out of heap. It is a quite technical article but it gives a nice insight into some of the Windows internals.</p>
<ul>
<li><a href="http://blogs.msdn.com/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx" target="_blank">Part1</a></li>
<li><a href="http://blogs.msdn.com/ntdebugging/archive/2007/07/05/desktop-heap-part-2.aspx" target="_blank">Part2</a></li>
</ul>
</li>
</ul>
<p>I often prefer such blog articles to MSDN articles because blog articles are much more fun to read.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/03/05/site-recommendation-terminal-session-and-desktops/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JWSCL and FreeAndNil Second Attempt</title>
		<link>http://blog.delphi-jedi.net/2010/02/25/jwscl-and-freeandnil-second-attempt/</link>
		<comments>http://blog.delphi-jedi.net/2010/02/25/jwscl-and-freeandnil-second-attempt/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 19:48:08 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JEDI Windows API Headers]]></category>
		<category><![CDATA[JWA]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=665</guid>
		<description><![CDATA[In my last article &#8220;Jwscl and FreeAndNil&#8221; there were some great comments on the source design. Oliver told me to use a guarded memory page so the memory is always invalid. With his information I wrote a source code that creates a pointer which always triggers an access violation.
Unfortunately, Access Violations are rather common and [...]]]></description>
			<content:encoded><![CDATA[<p>In my last article &#8220;<a href="http://blog.delphi-jedi.net/2010/02/25/jwscl-and-freeandnil/" target="_blank">Jwscl and FreeAndNil</a>&#8221; there were some great comments on the source design. Oliver told me to use a guarded memory page so the memory is always invalid. With his information I wrote a source code that creates a pointer which always triggers an access violation.</p>
<p><span id="more-665"></span>Unfortunately, Access Violations are rather common and thus nobody can tell why it happens at a first glance. So I added an exception handler that maps this special access violation to a separate exception class (I called it EJwsclAccessedGuardPointerException).</p>
<p><pre><pre class="brush:delphi">uses
&nbsp;&nbsp;ExceptionLog,
&nbsp;&nbsp;//JwaWindows, //or
&nbsp;&nbsp;JwaWinBase, JwaWinNT, JwaNtStatus,
&nbsp;&nbsp;SysUtils;

type
&nbsp;&nbsp;EJwsclAccessedGuardPointerException = class(Exception)
&nbsp;&nbsp;public
&nbsp;&nbsp;&nbsp;&nbsp;ExceptionRecord: PExceptionRecord;
&nbsp;&nbsp;end;

resourcestring
&nbsp;&nbsp;SGuardPageException = &#039;It was tried to access a guarded pointer. This &#039;+
&nbsp;&nbsp; &#039;pointer was freed previously and is now accessed without initialization. &#039;+
&nbsp;&nbsp; &#039;JWSCL may guard its class members in this way. You should check for &#039;+
&nbsp;&nbsp; &#039; accesses to e.g. class members which instance was freed.&#039;#13#10+
&nbsp;&nbsp; &#039;Exception was raised at this address: $%p&#039;;

var
&nbsp;&nbsp;GuardPtr : Pointer;
&nbsp;&nbsp;OldExcpObj : function (P: PExceptionRecord): Exception;
&nbsp;&nbsp;OldExitProc : procedure;

procedure MyExitProcessProc;
begin
&nbsp;&nbsp;VirtualFree(GuardPtr, 0, MEM_RELEASE);

&nbsp;&nbsp;if @OldExitProc &amp;lt;&amp;gt; nil then
&nbsp;&nbsp;&nbsp;&nbsp;OldExitProc;
end;

function MyGetExceptionObject(P: PExceptionRecord): Exception;
var ErrorCode : Integer;
begin
&nbsp;&nbsp;if (P.ExceptionCode = STATUS_ACCESS_VIOLATION) and
&nbsp;&nbsp;&nbsp;&nbsp;(P.ExceptObject = GuardPtr) then
&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;result := EJwsclAccessedGuardPointerException.CreateFmt(SGuardPageException,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[P.ExceptionAddress]);
&nbsp;&nbsp;&nbsp;&nbsp;EJwsclAccessedGuardPointerException(Result).ExceptionRecord := P;
&nbsp;&nbsp;end
&nbsp;&nbsp;else
&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;result := OldExcpObj(P);
&nbsp;&nbsp;end;
end;

var
&nbsp;&nbsp;T : TObject;
&nbsp;&nbsp;SysInfo : TSystemInfo;
begin
&nbsp;&nbsp;OldExcpObj := ExceptObjProc;
&nbsp;&nbsp;ExceptObjProc := @MyGetExceptionObject;

&nbsp;&nbsp;OldExitProc := ExitProcessProc;
&nbsp;&nbsp;ExitProcessProc := MyExitProcessProc;

&nbsp;&nbsp;//On 32Bit OS call
&nbsp;&nbsp;//GetSystemInfo(@SysInfo);
&nbsp;&nbsp;//On WOW64Bit OS call (use IsWow64Process)
&nbsp;&nbsp;GetNativeSystemInfo(@SysInfo);

&nbsp;&nbsp;GuardPtr := VirtualAlloc(
&nbsp;&nbsp;&nbsp;&nbsp;Pointer($BADC0DE),//&nbsp;&nbsp;__in_opt&nbsp;&nbsp;LPVOID lpAddress,
&nbsp;&nbsp;&nbsp;&nbsp;SysInfo.dwPageSize,//&nbsp;&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SIZE_T dwSize,
&nbsp;&nbsp;&nbsp;&nbsp;MEM_RESERVE,//&nbsp;&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD flAllocationType,
&nbsp;&nbsp;&nbsp;&nbsp;PAGE_NOACCESS//&nbsp;&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD flProtect
&nbsp;&nbsp;);
&nbsp;&nbsp;if GuardPtr = nil then
&nbsp;&nbsp;&nbsp;&nbsp;RaiseLastOSError;

&nbsp;&nbsp;T := TObject(Pointer(GuardPtr));
&nbsp;&nbsp;T.Free;
end.
</pre></pre></p>
<p>Since the object has this guard pointer value (which may be dynamic) a call to Free (or Destroy) will fail with the exception EJwsclAccessedGuardPointerException. Be aware that there is no actual memory allocated. It is all about virtual memory.</p>
<p>The MyExitProcessProc is called right before the process exits. There is another exit handler called ExitProc that is called before the units are finalized. So I&#8217;m stuck with ExitProcessProc which is fine though.</p>
<p>I must say that I like this approach since it seems to be safer than just using a nearly arbitrary magic value. The value is still there so you can see it as an invalid memory address in a debugger. However, Assigned or similar workarounds will not work because the memory location can vary.<br />
 And of course the exception message clearly states what happened here.  There could added more information like stack trace but that I leave to you (or the JCL).</p>
<p>Be aware that there still might be errors. This code is hot.  <img src='http://blog.delphi-jedi.net/wp-includes/images/smilies/icon_cool.gif' alt='8-)' class='wp-smiley' /> </p>
<p>What is your opinion?<br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/02/25/jwscl-and-freeandnil-second-attempt/feed/</wfw:commentRss>
		<slash:comments>8</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>
]]></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>JWSCL Features Overview</title>
		<link>http://blog.delphi-jedi.net/2010/02/22/jwscl-features-overview/</link>
		<comments>http://blog.delphi-jedi.net/2010/02/22/jwscl-features-overview/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 12:43:46 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[JWSCL Downloads]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=652</guid>
		<description><![CDATA[I had some free time that I used to put together all the features JWSCL provides currently. There are some more features that are implemented by other tool classes or functions that I left out in favor of a good overview. A complete overview of all classes, methods and more gives you the documentation at [...]]]></description>
			<content:encoded><![CDATA[<p>I had some free time that I used to put together all the features JWSCL provides currently. There are some more features that are implemented by other tool classes or functions that I left out in favor of a good overview. A complete overview of all classes, methods and more gives you the documentation at <a href="http://jwscldoc.delphi-jedi.net." target="_blank">http://jwscldoc.delphi-jedi.net</a>.</p>
<p>So here are the feautures (You can look up the class names on the documentation page):</p>
<p><span id="more-652"></span></p>
<ul>
<li> Windows Token management (TJwSecurityToken)
<ul>
<li>Impersonation</li>
<li>Supports LogonUser, LsaLogonUser </li>
<li>Lots more</li>
</ul>
</li>
<li>Full support of Security ID (SID) (TJwSecurityID, TJwSecurityIDList)
<ul>
<li>Also well known security IDs like Everyone (JwsclKnownSid.pas) are stored as simple to use variables.</li>
</ul>
</li>
<li>Full support of Access Control Lists (also CALLBACK_ACE and OBJECT_ACE)
<ul>
<li>DACL, SACL</li>
</ul>
</li>
<li>Full support of Security Descriptor (SECURITY_DESCRIPTOR) (TJwSecurityDescriptor)
<ul>
<li>DACL, SACL, Owner, Group</li>
<li>Implements a simple to use Security Descriptor (TJwSimpleDescriptor)</li>
</ul>
</li>
<li>Security Rights Mapping; Maps Generic Rights to specific ones (JwsclMapping.pas)
<ul>
<li>Conversion of Security Rights (DWORD) to Human Readable names (JwFormatAccessRights)</li>
</ul>
</li>
<li>Privileges (TJwPrivilege, TJwPrivilegeSet, JwsclPrivileges.pas)</li>
<li>Windowstation and Desktops (TJwSecurityWindowStation, TJwSecurityDesktop)</li>
<li>Local Security Authority Logon Sessions (TJwLsaLogonSession)</li>
<li>Security of Windows objects; files, registry, handles (TJwSecureFileObject, TJwSecureFileObject, TJwSecureGeneralObject)
<ul>
<li>Support of Access Checking (AccessCheck)</li>
<li>Supports Inheritance (by default only files and registry)</li>
</ul>
</li>
<li>Support of MS AuthZ API; Client Side Access Checks for custom Resources (JwsclAuthCtx.pas) </li>
<li>Credentials GUI API (TJwCredentialsPrompt)</li>
<li>MS Encryption and Protection API (TJwEncryptionApi,  TJwEncryptMemory, TJwRandomDataGenerator)</li>
<li>Windows Version Detection on remote or local client (TJwFileVersion, TJwServerInfo, TJwWindowsVersion) Security Descriptor GUI (TJwSecurityDescriptorDialog)</li>
<li>Terminal Sessions (TJwTerminalServer)
<ul>
<li>Server Management</li>
<li>Sessions Management</li>
<li>Processes Management</li>
</ul>
</li>
<li>Vista Elevation (JwShellExecute, JwElevateProcess, JwsclElevation.pas)
<ul>
<li>Supports <a title="German page only" href="http://kay-bruns.de/wp/software/surun/" target="_blank">SuRun</a> (<a title="Auto Translation" href="http://translate.google.com/translate?u=http%3A%2F%2Fkay-bruns.de%2Fwp%2Fsoftware%2Fsurun%2F&amp;langpair=de%7Cen&amp;hl=de&amp;safe=active&amp;ie=UTF-8&amp;oe=UTF-8&amp;prev=%2Flanguage_tools" target="_blank">English version</a>) (JwElevateProcess, JwCheckSuRunStatus)</li>
</ul>
</li>
<li>Vista Integrity Level (Built in)</li>
<li>Firewall Administration (TJwsclFirewall)</li>
<li>Builtin basic Sma rtpointer Support (TJwAutoLock)</li>
<li>Job Object support (TJwJobObject) even with several sessions (TJwJobObjectSessionList)</li>
<li>Process Handling that encapsulates support for different Windows Versions and bugs in API (functions JwCreateProcessAsAdminUser, JwCreateProcessInSession, JwGetProcessSessionID, JwGetTokenFromProcess, JwProcessIdToSessionId) </li>
<li>Support Memory Mapped Objects (TJwFileStreamEx, TJwIPCStream, TJwVirtualStream)</li>
<li>Extended Thread Support lile naming threads and WaitWithTimeOut (TJwThread)</li>
<li>Hashing Support (TJwHash) 
<ul>
<li>For JWSCL classes (JwObjectHash)</li>
<li>For files (JwCreateFileHash, JwCompareFileHash, JwDataHash, JwIntegerHash) in combination with fast Memory Mapping.</li>
</ul>
</li>
<li>DCOM support for Client and Server (currently only developer branch); CoInitializeSecurity (TJwComProcessSecurity), Authentication, Impersonation, Proxy Security Blanket (TJwComClientSecurity, TJwComServerSecurity), Access Control (TJwServerAccessControl), DCOM Configuration (TJwComRegistrySecurity) of Global Configs and Class Security.</li>
<li>Easy to use WinAPI (Msg)WaitForMultipleObjects functions (JwMsgWaitForMultipleObjects, JwMsgWaitForMultipleObjects)</li>
<li>Multi Language Support of Resource Files (LoadLocalizedString)</li>
<li>Ansi- &amp; Unicode due to own Delphi compatible String type TJwString (JwsclAnsiUniCode.pas)</li>
<li>Mapping of Windows Constants to Delphi enumeration (TJwEnumMap)</li>
<li>All errors are reported by exceptions using a derived class from EJwsclSecurityException. (JwsclExceptions.pas)</li>
<li> Supports Bugreports with Eurekalog (JwsclEurekaLogUtils.pas)</li>
<li>JWSCL is based on OOP </li>
</ul>
<p>To come</p>
<ul>
<li> Active Directory Support</li>
<li>User Account Management</li>
</ul>
<p>Current version is <a href="http://blog.delphi-jedi.net/2009/09/23/releases-for-delphi-2010/">0.9.3 Download.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/02/22/jwscl-features-overview/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reminder to You</title>
		<link>http://blog.delphi-jedi.net/2010/02/15/reminder-to-you/</link>
		<comments>http://blog.delphi-jedi.net/2010/02/15/reminder-to-you/#comments</comments>
		<pubDate>Mon, 15 Feb 2010 18:28:13 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=640</guid>
		<description><![CDATA[I had some trouble writing these lines because usually I do not want to publish criticism. But Oliver told me that it would be a good idea and I don&#8217;t want to disagree   .
Valid for all open source projects, also the JEDI API&#38;WSCL projects heavily depend on their users. This is not a [...]]]></description>
			<content:encoded><![CDATA[<p>I had some trouble writing these lines because usually I do not want to publish criticism. But <a href="http://blog.assarbad.net/" target="_blank">Oliver</a> told me that it would be a good idea and I don&#8217;t want to disagree <img src='http://blog.delphi-jedi.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .</p>
<p><span id="more-640"></span><span style="font-size: large;">Valid for all open source projects</span>, also the JEDI API&amp;WSCL projects heavily depend on their users. This is not a company where people work all day to make a  great project. I and other members of JEDI use our spare time after real work to bring forward projects such as JEDI.</p>
<p><span style="font-size: large;">Unfortunately, time has changed </span>and less and less people want to provide their skills and manpower in projects like JEDI&#8230;and I am not talking about JEDI API exclusively. That is a pity because we will not provide you with source code forever. Instead the process will come to a halt and we will see more and more questions in newsgroup asking why the project doesn&#8217;t work anymore in Delphi 2020 (or similar).</p>
<p><span style="font-size: large;">I don&#8217;t get it.</span> There are many new API functions in Vista and Windows 7. And I see a lot of people writing conversions from C to Delphi so they can use the new functionality. But instead of donating these sources to JEDI API they post it to their local forum or use it in their project as an internal unit. Usually, I come along and ask these people if they want to donate their source to JEDI API. And the chat goes like this:</p>
<p><em>Christian: &#8220;Hey, I am from JEDI API. Maybe you heard from us. It would be great if your conversion could be integrated into JEDI. Do you agree?&#8221;</em></p>
<p><em>X: &#8220;Yeah, I&#8217;m using your projects a lot. And of course, I would like to see my source integrated into JEDI.&#8221;</em></p>
<p><em>C: &#8220;Well, I need your source code to be converted to some standards we use. I will send you more information about this easy process. If you have further question just ask.&#8221;</em></p>
<p><em>X: &#8220;Eh? Sorry, but I don&#8217;t have time to put more effort into this. Can&#8217;t you just do it yourself?&#8221;</em></p>
<p>Let me answer: <em>Well, If we could do it ourselves we would already have done it. </em>But that means that we would need to give up our jobs and private life to convert over 20.000 functions, interfaces and types only for this project.</p>
<p>Did you know that there is a <a href="http://jedi-apilib.svn.sourceforge.net/viewvc/jedi-apilib/jwapi/trunk/Win32API/_JwaTemplate.pas?revision=857&amp;view=markup" target="_blank">template</a> that shows you how to create a JEDI API file?</p>
<p>Also it often happens that I don&#8217;t hear anything from them. Therefore these conversions never get integrated because I need an explicit agreement.</p>
<p><span style="font-size: large;">On the other hand</span> there are many people who like just to use the source code in their own project because it makes it easier to write good programs. <br />
 May I ask what <span style="text-decoration: underline;">you</span> did to keep alive the project that you gained from?  I have to say from experience that the donations in source and money (in relation to current software prices) are that rare that zero (0) would describe it best. Luckily, this is not entirely true but it is very close to the truth.</p>
<p><span style="font-size: large;">Fortunately, there are a lot of companies</span> which are <strong>generous</strong> and allow us to use their products for free. You can find the list  in the sponsors section of this blog. With a monetary donation of nearly zero we could never use their products. I cannot stop saying: &#8220;<strong>Thank you!</strong>&#8220;</p>
<p><span style="font-size: large;">Also </span>let me use this article to thank all the people who helped or are still helping in these projects. I want to thank them again and again and again! And let me thank the donators again (I wrote them a mail).</p>
<p>&#8211;</p>
<p>Christian</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/02/15/reminder-to-you/feed/</wfw:commentRss>
		<slash:comments>24</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 the [...]]]></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"><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>
]]></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>Programming Habits</title>
		<link>http://blog.delphi-jedi.net/2010/01/14/programming-habits/</link>
		<comments>http://blog.delphi-jedi.net/2010/01/14/programming-habits/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 16:45:29 +0000</pubDate>
		<dc:creator>Christian Wimmer</dc:creator>
				<category><![CDATA[Common]]></category>

		<guid isPermaLink="false">http://blog.delphi-jedi.net/?p=612</guid>
		<description><![CDATA[I&#8217;m writing this article because I want to share programming habits with you. What habit did prove to be a good one for you? Share yours then, please. 
I always add &#8220;RaiseLastOsError&#8221; to every Windows API call.
if not ImpersonateLoggedOnUser(token) then
&#160;&#160;RaiseLastOsError;

In this way you don&#8217;t miss any failed call and wonder what is happening (I can [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m writing this article because I want to share programming habits with you. What habit did prove to be a good one for you? Share yours then, please. <span id="more-612"></span></p>
<h3>I always add &#8220;RaiseLastOsError&#8221; to every Windows API call.</h3>
<p><pre><pre class="brush:delphi">if not ImpersonateLoggedOnUser(token) then
&nbsp;&nbsp;RaiseLastOsError;
</pre></pre></p>
<p>In this way you don&#8217;t miss any failed call and wonder what is happening (I can recall a lot of forum threads that ask about this). <br />
 RaiseLastOsError generates an EOSError exception that contains the error number and text in its message. It also stores the GetLastError value in its property ErrorCode.</p>
<p>One more good thing is that a caller of the function, where this code is implemented, cannot ignore an error value. The API function ImpersonateLoggedOnUser is very problematic because if it fails all subsequent calls are made on the security token of the process instead of the thread. So a client could access more things than usual. So if we had a function that implements the example</p>
<p><pre><pre class="brush:delphi">function MyImpersonateUserToken(UserName : String; out UserData : PUserData) : Boolean;
begin
&nbsp;&nbsp;//get user token here
&nbsp;&nbsp;//get user information from token here and store it into UserData

&nbsp;&nbsp;result := ImpersonateLoggedOnUser(token);
</pre></pre></p>
<p>As you can see a caller can just do the following</p>
<p><pre><pre class="brush:delphi">MyImpersonateUserToken(UserName, UserData);
If UserData.Groups.IsMemberOf(&#039;Administrators&#039;) then
</pre></pre></p>
<p>Be aware that the example is only fictional. However I have seen many production codes that call WinAPI without error checking. The WinAPI usually (and the code above definitely) does not touch any of the output parameters if they fail. So you probably get an Access Violation (best case) or it works randomly (worst case). See that UserData is not initialized here.   But what about this one:</p>
<p><pre><pre class="brush:delphi">procedure MyImpersonateUserToken(UserName : String; out UserData : PUserData);
begin
&nbsp;&nbsp;//get user token here
&nbsp;&nbsp;if not GetUserToken then
&nbsp;&nbsp;&nbsp;&nbsp;raiseLastOsError;
&nbsp;&nbsp;//get user information from token here and store it into UserData
&nbsp;&nbsp;if not GetTokenInformation then
&nbsp;&nbsp;&nbsp;&nbsp;raiseLastOsError; 

&nbsp;&nbsp;if not ImpersonateLoggedOnUser(token) then
&nbsp;&nbsp;&nbsp;&nbsp;raiseLastOsError;
</pre></pre></p>
<p>You see that the function is really a procedure now that throws exceptions in case of failure. In this way the code following the function call MyImpersonateUserToken isn&#8217;t executed at all. Instead, we need to wrap an exception trap around the function call to let the code continue.</p>
<p><pre><pre class="brush:delphi">try
&nbsp;&nbsp;MyImpersonateUserToken(UserName, UserData);
except
end;

if UserData.Groups.IsMemberOf(&#039;Administrators&#039;) then
</pre></pre></p>
<p>Okay, everbody should see that this is a really ******* code and should not be left in this way.</p>
<p>If you make an habit from this you won&#8217;t miss the old way. Instead it takes less time to implement and I don&#8217;t mention the time searching for memory leaks.</p>
<p>Furthermore, I think it looks much better and besides of that it is really easy to read and understand.<br />
 However, the most important reason (for me) is that any user who calls this function incorrectly (e.g. user not found) gets a nasty exception thrown into the face.</p>
<p>These are the reasons why JWSCL throws exceptions in 99,99% of its methods instead of returning error values.<br class="spacer_" /></p>
<h4>I always use try/finally for memory allocations</h4>
<p>Programmers have a hard to find memory leaks. There are libraries (like JWSCL) that support smart pointers but Delphi comes also with &#8220;smart pointers&#8221; (besides interfaces). Although it needs some more work. If you have translated code from C to Delphi you have seen it maybe. I&#8217;m talking about &#8220;goto&#8221; statements in C code.</p>
<p><pre><pre class="brush:c">{
&nbsp;&nbsp;...
&nbsp;&nbsp;if (!GetTokenInformation(...))
&nbsp;&nbsp;&nbsp;&nbsp;goto exit_1;

goto exit_0;
:exit_1
&nbsp;&nbsp;CloseHandle(hToken);

:exit_0
return (result);
}
</pre></pre></p>
<p>In Delphi we don&#8217;t use goto because we were told that it is  bad habit. So we directly put the exit after each failed function called.</p>
<p><pre><pre class="brush:delphi">begin
&nbsp;&nbsp;...
&nbsp;&nbsp;if not GetToken(hToken) then
&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;result := true;
&nbsp;&nbsp;&nbsp;&nbsp;exit;
&nbsp;&nbsp;end;
&nbsp;&nbsp;if (not GetTokenInformation(...)) then
&nbsp;&nbsp;begin
&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hToken);
&nbsp;&nbsp;&nbsp;&nbsp;result := FALSE;
&nbsp;&nbsp;&nbsp;&nbsp;exit;
&nbsp;&nbsp;end;

&nbsp;&nbsp;CloseHandle(hToken);
&nbsp;&nbsp;result := TRUE;
end;
</pre></pre></p>
<p>In more complex code you can easily miss a failure code path or miss to close a handle or free an object. So why don&#8217;t do it this way?</p>
<p><pre><pre class="brush:delphi">&nbsp;&nbsp;...
&nbsp;&nbsp;if not GetToken(hToken) then
&nbsp;&nbsp;&nbsp;&nbsp;raiseLastError;

&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;if (not GetTokenInformation(...)) then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raiseLastError;

&nbsp;&nbsp;&nbsp;&nbsp;if GetMeOutOfHere() then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit;
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hToken);
&nbsp;&nbsp;end;
end;
</pre></pre></p>
<p>The try/finally statement ensures that the code within finally is executed. It does not matter that an exception is raised (we know that already). Even if we call &#8220;exit&#8221; the finally part is also executed.</p>
<p>However, you need to make sure that the variables within finally are valid.</p>
<p>1. CloseHandle throws an exception if the handle is not valid. This only happens if it detects an attached debugger.</p>
<p>2. Free, FreeAndNil, FreeMem, Dispose will throw an exception depending on the content of the given pointer. In worst case nothing happens and you get garbage results anywhere else in your application.</p>
<p>So the correct way is to trap every allocated variable (pointer, class) in a separate try/finally statement.</p>
<p><pre><pre class="brush:delphi">New(Ptr);
try
&nbsp;&nbsp;MyClass := TMyClass.Create;
&nbsp;&nbsp;try
&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;finally
&nbsp;&nbsp;&nbsp;&nbsp;FreeAndNil(MyClass);
&nbsp;&nbsp;end;
finally
&nbsp;&nbsp;Dispose(Ptr);
&nbsp;&nbsp;Ptr := nil;
end;
</pre></pre></p>
<p>Make it an habit to implement the finally part immediately. Delphi helps you by adding the finally part automatically.</p>
<p><pre><pre class="brush:delphi">New(Ptr);
try
&nbsp;&nbsp;(1)
finally
&nbsp;&nbsp;Dispose(Ptr);
&nbsp;&nbsp;Ptr := nil;
end;
</pre></pre></p>
<p>Now continue at position (1).</p>
<p>One more tip:  If you have a lot of source lines between try/finally you can also put a comment behind finally to show the initial call.</p>
<p><pre><pre class="brush:delphi">New(Ptr);
try
&nbsp;&nbsp;... many lines ...
finally //New(Ptr);
&nbsp;&nbsp;Dispose(Ptr);
&nbsp;&nbsp;Ptr := nil;
end;
</pre></pre></p>
<p>In this way you don&#8217;t mix up the variable names allocated and freed. And we also don&#8217;t mix up the allocation types (e.g. GetMem &lt;&gt; Dispose)</p>
<p><br class="spacer_" /></p>
<h3>Your programming habits</h3>
<p>If you want to share your habits you can do this by leaving a comment. Or better you can write your own article and link it here so a conection is made.</p>
<p>Looking forward to hearing from you!</p>
<p><br class="spacer_" /></p>
<p>Christian</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.delphi-jedi.net/2010/01/14/programming-habits/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
