How to determine the version number of a registered OCX in Delphi XE2 - windows

I have an ActiveX component in XE2 that connects to a database to handle transaction processing, and it includes a check of its version against that of the database to determine if they are compatible.
Unlike C#, where the AssemblyVersion attribute can be obtained at runtime using the Application.ProductVersion property, Delphi XE2 has no such built-in property for getting the version information included in the project options, with the preferred method being to use GetFileVersionInfo, passing in the full path to the program, or in this case the OCX.
Originally the OCX was always installed to the Windows System path but we have changed our installation process so that the OCX is installed to the same folder as the executable that uses it, which is a location determined by the user.
What I need is a consistent method that I can use from within the OCX code to obtain the installation folder from the registry across the multitude of Windows environments. I assume it would have something to do with the GUID's defined in the _TLB.pas file.

You don't need to query the Registry at all. The OCX can retreive its own filename by passing Delphi's global HInstance variable as the module handle to the Win32 API GetModuleFileName() function, then it can pass that filename to GetFileVersionInfo().
Although, a better way for the OCX to access its own version, without resorting to GetFileVersionInfo(), is to use Find/Load/LockResource() to access its own version resource directly, then no filename is needed at all. You can copy the version resource data into a temp buffer and pass that to VerQueryValue() to retrieve the resource's VS_FIXEDFILEINFO structure (retrieving anything else from the resource gets a bit trickier because GetFileVersionInfo() prepares certain lookup data that VerQueryValue() then uses).

You certainly don't need to use the registry here. Not least because there could potentially be multiple versions of the DLL on the machine, because you are installing to the executable directory of any program that uses the DLL.
You could certainly read the version resource as Remy describes. But another alternative would be to include a constant in your program that encodes the database version compatibility.
const
DatabaseVersion = 1;
Check this constant against the value read from the database and fail if not compatible.
To me this makes a little more sense as it separates the version of the DLL from the version of the database. The two are not necessarily linked. You could, and probably do, update the DLL without changing the database structure.

Related

Visual c++ programatically get file version number within the file itself

I know I can call GetFileVersionInfo() windows API to retrieve file version information.
Is there an easier way to determine the version information, from within the program itself?
For example, suppose I am writing codes for Foo.dll, and inside Foo.dll, I want to support a version function, say GetFooVersion(), which reports the version number of Foo.dll.
If I have to use GetFileVersionInfo(), then I need to search which Foo.dll in the path that is been linked (dynamically), and apply GetFileVersionInfo(). It's tedious and error-prone.
The target visual studio version is VS2012.
There is no GetFileVersionInfoByHandle nor GetFileVersionInfoFromModule unfortunately.
You can use FindResource etc. on your own module but you then have to parse the version info yourself because GetFileVersionInfo does not always retrieve the raw resource data (it can translate to/from Unicode etc.).
Another option is to put version #defines in a .h file that your function and your resource.rc can use so you only have to update a single file when the version changes.

Simulating LoadLibraryEx's LOAD_LIBRARY_SEARCH_SYSTEM32 functionality

Often one wants to LoadLibrary a system DLL like Kernel32.dll, handily LoadLibraryEx has a dwFlags parameter that allows you to specify LOAD_LIBRARY_SEARCH_SYSTEM32.
For security reasons, this can be very important as malicious attackers can subvert the default search paths that LoadLibrary looks through.
However Windows XP, which I must still support, cannot use LOAD_LIBRARY_SEARCH_SYSTEM32 as it didn't exist eons ago. This leads me to the following conclusion: I need to come up with a fully qualified path and pass that to LoadLibrary.
However, a robust implementation of this is tricky due to WoW64 and file-system redirection.
I have to worry about this possibility because the code in question lives in a library and can be called in strange environments.
My current thoughts are something like the following pseudo-code:
string Path;
BOOL Wow64Process;
if (IsWow64Process(CurrentProcess(), &Wow64Process) && Wow64Process &&
WoW64FSRedirectionIsDisabled)
Path = GetSystemWow64Directory();
else
Path = GetSystemDirectory();
Path += "\Kernel32.dll";
LoadLibrary(Path);
I have considered, and rejected using Wow64DisableWow64FsRedirection and Wow64RevertWow64FsRedirection but this is problematic as it will leave FS redirection disabled in the library's DLLMain.
Given the above, what's the best way to go about what I am trying to do?
Thanks!
In terms of loading a DLL without dependencies, you are over thinking this. If the user has disabled file system redirection in a WOW64 process then LoadLibraryEx will attempt to load the DLLs from the 64 bit system32 folder. So you can simply do exactly the same and remove all that WOW64 code.
However, the documentation says (emphasis mine):
If this value is used, %windows%\system32 is searched for the DLL and its dependencies.
So, your approach cannot replicate LOAD_LIBRARY_SEARCH_SYSTEM32 because you can only supply the full path for the DLL you load, but not for its dependencies.
The only way to hope to replicate this is to force system32 to be at the head of the DLL search path. Specifying a full path won't help you.
Finally, are you sure that LOAD_LIBRARY_SEARCH_SYSTEM32 is not available on XP64?
As an alternative to the other answers use SetDlldirectory.
The advantage ist that the current Directory isn't checked for a DLL-load.
Still open is the search via PATH... but this is in the last Position, so your DLL located in the SYSTEM32 directoryies should be loaded first using SettDllDirectory.
Also it is supported since XP SP1

File Versioning Rules When Neither Components Has a Key File

According to URLs I referenced, I understand that the Windows Installer uses key files to compare the version, date, and language of components and determine whether to update the component on target machine.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa368599%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa371221%28v=vs.85%29.aspx
I also understand that default versining rules consist of 4 different cases as listed below.
Both Files Have a Version
Neither File Has a Version
Neither File Has a Version with File Hash Check
One File Has a Version
What I don't understand is that how does the installer determine whether the component needs to be updated if neither components has a key file?
And what's going to happen if neither components has a key file, but a file on the target computer indicates that its Modified date is later than the Create date? In this case, even when both products have a version, are they going to be considered as having Non-versioned files because no key file is set to components? How does the installer determine whether to install?
Any answers would be really appreciated,
Every component from the installer must have a key member, this is imposed by Windows Installer to build a valid MSI package. Also, Microsoft strongly recommends that you create independent components for each DLL, EXE, OCX and hlp/help file. This will allow the file versioning rules to be correctly applied.

Determining why binary compatibility is broken

When I try to rebuild one of my VB6 DLLs, I get a warning:
"The binary compatibility DLL or EXE contains a parameter type or
return type whose definition can not be found"
I have to release a few changes in selected DLLs (simple changes internal to methods - nothing that breaks the compatibility according to this)
The generally accepted method which I have followed is to maintain the old DLLs in a separate shared directory and while making the new DLLs, compile them with binary compatibility set to the old set of DLLs. This is done to not change the GUIDs while I register my new DLLs. These GUIDs are used as references in other DLLs which I have not disturbed during the release.
I'm pretty sure I didn't add anything to break the binary compatibility rule (No change in signature, public methods, variables etc.) Why is this error occurring?
Am I being a noob by not checking something basic? Scratching my head since morning. Any help is much appreciated.
EDIT: If at all there are changes to my signature, Is there a way that I can know without comparing code?
Take your old DLLs and add a compat_ prefix to them.
Basically rename your MyAppDataAccess.dll file to compat_MyAppDataAccess.dll.
Now go to the properties of your ActiveX DLL and set your project to have binary compatibility with the new compat_MyAppDataAccess.dll, like below.
Now just build your DLL and deploy it.
It should work. If, in fact you binary compatibility would be broken as a result of your changes, then you'll get a warning stating that.

Recreating a COM DLL, do I need to worry about the GUID?

A change needs to be made in a DLL. The DLL was originally coded in VB6 (not by me), and the source code lost.
It is very simple in its functionality, so I recreated it from scratch, but I only have access to VB Express 2008.
I created it first as a normal DLL then realized it had to be a COM DLL. Fortunately, an excellent article at http://www.codeproject.com/KB/COM/nettocom.aspx tells me how.
But, I don't know anything about GUIDs...
Should I use the same GUID as the original DLL or not? Does it make any difference?
Edit: Does it really matter since it's a COM DLL? It is called into by an Active X control & I can see no reference in the web page to the GUI ... (but I'm just a n00b, so what do I know? ;-)
If you want this library to be a direct replacement of the original and it is fully binary compatible (all interfaces are unchanged) - then yes, you should use the same GUIDs for the class ids and interface ids. If you don't do that users of the original library will not be able to use yours without recompiling their programs.
Beware that binary compatibility is a must for reusing the GUIDs. If you break any interface - change its id and the id of the class implementing it and recompile the client.
The GUIDs acts as a kind of identifier for your COM object and DLL. If you use the same GUID you need to register your new DLL so that the location is updated (i.e. if you don't place it exactly in the same spot and have recreated all interfaces the old DLL previously had registered).
The cleaner approach is to generate a new GUID and modify the caller to use the new GUID/DLL instead.

Resources