Monday, November 29, 2004

Toronto conference...

Just ended day 1 of the Falafel Developers Conference here in Toronto, Ontario, Canada.  I outlined just a few of the new features in Delphi 2005, Danny covered the .NET fundementals and new language features in Delphi/.NET and Delphi/Win32 and Lino covered .NET remoting and component development for .NET WinForms.  So far, I've enjoyed talking with some of the folks here in Toronto.  I also enjoyed the dinner at Ruth's Chris Steakhouse in downtown Toronto :-).  Thanks, Lino!

Tomorrow will be a part 2 of the What's New in Delphi 2005.  Danny will cover some .NET security fundementals, and Lino will be covering ASP.NET.

Sunday, November 28, 2004

Bean spillage..

Danny has finally relinquished some information regarding the upcoming Delphi 8 patch that will resolve the issue surrounding .NET 1.1 SP1.  Also, as Danny noted, he, Lino Tadros and I are here in Toronto, Ontario Canada and will be doing a “launch” style event at the Falafel Developers Conference.  We also did a small user group launch at a local Bay area .NET usergroup.

Monday, November 22, 2004

Toronto, Nov 29th & 30th

Just a quick note.. I presume that there is still time to sign up for the Falafel Developers Conference in Toronto on November 29th and 30th, 2004.  Danny Thorpe and I will both be speaking.  Also, our good friend, Lino Tadros, will be speaking as well.  If you've never heard Danny or Lino speak, now is your chance.  Both are excellent and will be certain to have a lot of great information.  I'll be presenting an overview of Delphi 2005.

Tuesday, November 16, 2004

MSAA and Delphi

Steve Trefethen has started looking closely at MS Active Accessibility. This is going to be some good stuff...

Monday, November 15, 2004

Demand-loaded component packages in Delphi 2005

Delphi 2005 introduced a new mechanism for handling design-time component packages that allows them to now be demand-loaded.  This allows the IDE to be more intelligent about when and what packages to load and only when actually needed, thus decreasing overall startup time (since D2005 is now three products in one, every little bit helps).  In general the qualifications for demand-loading a package, or a group of packages (which I'll explain in a moment), is very deterministic.  When loading a package the IDE is always analysing the package as it is registering its contents in order to best determine whether or not it is a candidate for demand-loading.  There are, however, a few gotchas that you may encounter that can lead to confusion.  There are a few rare cases where the IDE is unable to properly determine the eligibility of a set of packages.  I'll try and outline and describe the logic which the IDE uses to qualify or disqualify a package's demand-load-ability.

Let's start with a few assumptions.  In Delphi Win32, when you boil it all down, a class reference is nothing more than a pointer to that class' virtual method table.  That VMT is located in the “text” or “code” segment of a given module (.exe, .dll or package).  This is important to understand because it provides crucial information about the location of implementation of a given class.  By using VirtualQueryEx, you can easily determine the actual module in which a class is defined.  Simply pass the class reference to that function and one of the values returned in the MEMORY_BASIC_INFORMATION structure.  The AllocationBase field happens to correspond to that module's HMODULE.  You can pass this value to GetModuleFileName in order to get the fully qualified path to the module that was loaded.

Next, I need to define what a “package group” is.  This is simply a given package and all its dependencies, both direct and indirect.  Say package A requires packages B and C.  The package group for package A contains A, B, and C, with A being the “root” package (ie. the package that caused all the others to be loaded).  Now what's the group for package B?  It's just B.  That is because B doesn't require A, nor does it require C.  Had B required C, then B's group would hav contained B and C.  (of course B or C cannot require A since that would be circular and that is not a possible situation to have).  Of course A, B and C can also exist in another root package's group as well.  For instance, say package D also requires packages B and C.  So now there are two groups, one containg A, B and C and another containing D, B and C with the group roots being A and D.

Now that you understand these two basics, lets start in on how the IDE analyses the design-time packages for demand-load eligibility.  When the IDE loads a design-time package, it will typically “require” various run-time packages that contain *only* those bits needed for run-time use of the components. (you have separated your run-time bits from the design-time bits haven't you?... If not.. that is a discussion for another day ;-)..  The design-time only package is where the actual component and property/component/selection editors are registered.  This is done by calling RegisterComponents, RegisterPropertyEditor, RegisterComponentEditor, etc from within various global procedures called “Register”.  It is important that this always be done within the “Register” procedure in order for the demand-loading to properly function.  See this blog entry.  What the IDE is basically looking for in order to determine the eligibility for demand-loading is that all component/property editor/ etc... registrations are restricted to that package's group only.  If a propertly editor were to be registered that could apply to any component outside the currently loading group, then that group is disqualified from being demand-loaded.  This is an important point.

Internally the IDE creates some datastructures that are filled in while all this “registering” is going on.  So as each component and property/component/selection editor is registered they are cross-checked against the package group.  Remember the VirtualQueryEx trick above?  This is used to determine what packages contain a given component or property/component/selection editor.  If the package is in the group then all is well.  If a reference were allowed to “leak” outside the group, then it could be possible that a component/property/selection editor would not be properly loaded and used when needed.  For instance, say you register a new propertly editor for any property of type TStrings on any TPersistent.  This is a perfectly legal registration, however it would cause your package to be disqualified from being demand-loaded.  Disqualification isn't nessesarily a bad thing.  It may be that you actually wanted to override the Borland supplied TStrings property editor with one of your own design.  It simply means that your package will now always be loaded either at startup or when a project that has it enabled is loaded.

Now what if you want your package to be demand-loaded but it isn't?  How can you tell why it was disqualified?  When implementing this feature, I asked the same questions.  So in addition to the package analysis logic, I also added extensive logging and reporting.  This functionality is also available to you as well.  There are two ways you can turn this on.  One is to enable it on a per-package basis.  You can do this by calling EnableDemandLoadReport(Detailed: Boolean) inDesignIntf from one of the Register procedures in your design-time package.  Pass False to simply get a report of why your package was disqualified and True to get a fully detailed report of what your package registered (which may be useful for many other uses as well).  Once your package is loaded and fully registered, the IDE will create a text file that is the same base name as the design-time package being loaded with the extension .rpt in the same folder containing your package.  You can also enable reporting globally by going to HKCUSoftwareBorlandBDS3.0Package Cache and adding one or both of the following values:  Report=1 or DetailedReport=1.  They correspond to EnableDemandLoadReport(False) and EnableDemandLoadReport(True), respectively.  The cool thing is that you can enable reporting in this manner and see detailed reports for *all* design-time packages that the IDE loads, including all the Borland supplied packages.

There are some cases where the IDE can get confused about what to demand-load.  For instance, if you have a design-time package that requires a run-time/design-time package.  The run-time/design-time package registers some components and the design-time package registers some property or component editors for the components in the run-time/design-time package.  In this case you can do one of two things.  The preferred method is to simply make the run-time/design-time package into a run-time only package and move the component registration into the design-time only package.  The other technique is to call ForceDemandLoadState(dlDisable) from the design-time only package.  Which brings up another new global function, ForceDemandLoadState().  This allows you to circumvent and override the descisions made by the IDE's automatic analysis code.  There may be cases where the IDE, for whatever reason disqualified your package from being demand-loaded, but you feel that it really should be demand-loaded.  You can call ForceDemandLoadState(dlEnable) from a Register procedure in your design-time package.  For more information on this you can see the various comments in DesignIntf.pas.

So your packages are now being demand-loaded, how and when does it actually get loaded?  When an instance of a registered component is created, the IDE will notice that the component is from a demand-loaded package and then load the package “on-demand.”  This can happen by either manually dropping the component onto a design-surface or loading a form/datamodule/frame that contains that component.  What about property/component editors?  All the property/component/selection editors are “component centric” meaning that they always require a live component instance in order to be selected.  Since they are also registered when the demand-loaded package is finally loaded, they too become available.

There is more that the demand-loading logic does, both in what it tracks and how it manages the state and palette filtering logic, but that will be left for another blog entry.

Thursday, November 4, 2004

Case Closed...

After speaking with “Bob” from Microsoft Developer Support, it seems that my supposition regarding the implementation of IOleCommandTarget on our ActiveX client site was spot on.  According to them, they were able to debug things from their side and look at the code path surrounding that call to IOleCommandTarget.Exec() and determined that it was in fact directly related to an S_OK return code from that method.  It was also confirmed that the command ID of 66 was in fact a new command ID introduced with the latest patch (KB834707).  What strikes me as odd about this whole thing is that the return code in this case seems backward.  I would have presumed that a return code of S_OK would mean “Sure, go ahead and download the file and don't ask the user.”  Obviously this was not the case as S_OK actually meant, “Ask the user if they want to open the file.”  Unfortunately, I was not able to get a resolution to this problem prior to releasing Delphi 2005 to manufacturing.  So look for a fix to this problem in a upcoming patch... soon.

I know that “Bob” reads this blog since in our last conversation he mentioned that he went to this site (since it was listed in my email sig).  So, “Bob”, if you're reading this, thanks for all your help.  I have to commend you and your support group for their reasonably quick and very proactive response.

Tuesday, November 2, 2004


The IE web browser security dialog mystery may be solved.  I was able to convince “Bob” to take a Delphi build example for them to observe from their end of things.  After fighting with email filters and virus scanners (you know they *really* don't like it when you send a zip file containing an .exe ;-)... I finally got an example of the problem to “Bob.”  You can read about the problem here along with the very interesting conversation with MS Developer support.  Anyway, in my quest to build an example of the problem in C#, I came across the determination that an imported ActiveX control wrapped in a WinForm control is a sealed box.  I cannot add implementations of specific interfaces to the AX container in order to instrument the browser control to the level needed to faithfully reproduce the problem.  This is an area where Delphi/Win32 strips .NET and WinForms to its skivvies!  There is a night and day difference between the ease by which an imported ActiveX control can be enhanced in C# compared to native Delphi... but I digress. 

It seems that our specialized IE web browser wrapper implements IOleCommandTarget.  This was done to keep the control from popping up scripting error dialogs all the time.  Since this same control is also used for the integrated ASP.NET designer, this was a critcal item to control.  It also needed to trap the “New Window.”  Apparently there was a change in behaviour from XP/SP2 and XP/SP2+KB834707.  It seems that right before the security file download dialog is displayed, IE calls IOleCommandTarget.Exec with CmdGroup=CGID_Explorer and an nCmdId=66.  I cannot find *anyplace* where this command ID is documented.  Well, it seems that if we return S_OK from that call, the dialog is displayed.  However if we return either OLECMDERR_E_UNKNOWNGROUP or OLECMDERR_E_NOTSUPPORTED, then that dialog is not displayed.  Now of course, it can be argued that we should have returned the proper error codes for commands we don't support, however it is a change in behaviour exhibited by the control.  Who'da thought that IOleCommandTarget would be involved?

I just (while typing this) got an email from “Bob” so this may about to get wrapped up.

Voting day...

Just a quick note here for all of you that live here in the States... If you're 18 or older and registered to vote make sure you actually make an effort to get out and vote.  That's today, November 2, 2004, folks.  I don't care what your political leanings are, who you like or dislike, the important thing is that you vote.  I have never missed a presidential election since I've been able to vote, and rarely ever miss the lesser local and state elections.  The interesting thing is that this election is shaping up to be one of the most watched from the international community that I can remember.  There is no question that this is a pivitol point in our nation's history.  Voting your conscience is very personal thing, so I don't want folks to start posting comments for or against a certain candidate or issue.  This isn't a political forum, and I won't discuss my personal convictions regarding politics.  The issue here is voting.  Not for whom or against what issue.  If you don't vote you have no business complaining about the outcome.  'Nuf said.

(stepping down off my soapbox)

Just, FYI... I will delete any politically charged comments, whether or not I agree with that particular comment.

Monday, November 1, 2004

Past lives come a haunting...

My previous post reminded me of what I used to do before I worked for Borland.  I've been at Borland for nearly 13 years.  Prior to working for Borland, I designed access control and magnetic stripe reading/encoding equipment.  It was a very small company, Elcom Industries, based in St. Louis, Missouri.  Only about 15-20 employees.  I started as a technician repairing the equipment as it came in for repair and mantenance.  After a while started I learning the firmware code and also the microcontrollers we began using at the time (6801/6803/68701).  Previous systems were, I am not lying about this, based on a 6100 CPU.. For those of you who don't know what that was... it was a PDP8 on a chip!  A 12bit CPU.  What a nightmare!  Here's some more info.  Of course, the 6801/6803 microcontrollers are now considered antiques as well... C'mon... I'm not even 40 yet!

Thank goodness that cheaper, more mainstream microcontrollers were becoming popular. When I took the existing magnetic card encoder hardware and designed an RS232 controlled encoder using a single microcontroller (a 68701) and a couple of support chips, the boss took notice and quickly moved me into engineering.  I went on to do a ground-up redesign of the access control units.  Since this was such a small shop, the engineers did *all* the work for a particular product.  From schematic design and printed circuit board layout to case and enclosure design to the actual firmware.  I had fun and learned a lot.  What is frightening is that this company is still selling the products I designed over 15 years ago.  Here's a couple of links... I hope their site doesn't go down from a small “Slashdot” effect ;-)..

Scroll down a little. The A4ER is the first thing I designed.  It had a single MC68701

This is the staple of this companies' products.  I had designed the mag-stripe and barcode version.  Looks like they finally added proximity readers... those were the subject of many debates about whether or not we should get into that market or not... looks like they did.  I wonder how much of the firware is still my code.  From the specs it certainly looks like the hardware hasn't changed too much.

Be careful what you title your blog entries..

Apparently metaphors and similes don't translate too well to the web.  When I titled an entry “Shotgun Fix for...” I got the following comment from Jay Cotter:


Now, I don't know if this person is actually being serious or not, but nonetheless it is still hilarious.  So, for all you folks looking to fix your shotguns, this ain't the place.  Sorry for the confusion since I was using the term “Shotgun” to refer to a very inexact method of fixing a software issue.  I used this term a lot when I was designing and programming security access control hardware.  When a repair would come in and we couldn't quite narrow the problem down to a specific component, we'd just start replacing all the usual suspects until the problem went away.  This was a “shotgun fix.”  Inaccurate and indiscriminate...  Just like a shotgun with bird-shot at, say, 25-50 yards..