I have a 32bit COM object that I want to use with 64bit PHP.
I am trying to follow the tutorial here:
http://www.gfi.com/blog/32bit-object-64bit-environment/
But I am stuck on "Locate your COM object GUID", as I have no idea where I can find out this information.
Does anyone know how I can find the GUID of the COM object?
You will at least have to know the ProgID of the COM component. Something similar to "Word.Application", the string you pass to the COM() constructor. Run Regedit.exe and look through the HKEY_CLASSES_ROOT for that string. Open the node, the CLSID key's default value gives you the GUID you are looking for.
Related
Forgive me if the title is not so accurate.
I have met some problem when I am doing something related to COM server and registry redirection and not quite sure is my understanding is correct or not. Hoping anyone could share some light on it. Thanks in advance.
Basically a COM server has been registered in the registry before anyone can use its service. On a 64bit Windows OS, there could be 2 possible views in the registry table, one is for default and the other for the WOW64 view. For example, first registry key is: COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID{GUID}\LocalServer32 and the other is: COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}\LocalServer32.
And depends on the process bitness (64bit vs. 32bit) that either one can be read by default, and also we can use KEY_WOW64_64KEY or KEY_WOW64_32KEY (as: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx) to access the other alternative registry key.
What I need is that, I want to get the LocalServer32 executable file by reading the registry key and this can work. The problem is that, for the executable file path I read back, do I need to do the file path translation (in order to get the correct value) depending on which view I get the value from? For example, if the file path is got from COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}\LocalServer32 and the file path is: C:\Windows\System32\abc.exe, do I need to translate the path to: C:\Windows\SysWow64\abc.exe? Or do I need to translate C:\Program Files\abc.exe to C:\Program Files(x86).exe?
Another question is that, if, for some registry key for COM, the values set in the two Views are different (for example, one has C:\Program Files\abc.exe and the other has C:\Program Files(x86)\abc.exe), then when the COM server is started, how could svchost.exe know which one to start, C:\Program Files\abc.exe or C:\Program Files(x86)\abc.exe? Does anyone know the logic for svchost.exe to determine this? Use the first one if it exists otherwise use the second one?
Thanks a lot.
A 64-bit version of Windows already has all the features in place to make it unnecessary for you to take care of it yourself. You just need to keep the rules in mind when you troubleshoot problems.
First is the registry redirector, it ensures that a 32-bit client program cannot accidentally read keys that contain configuration information that's only appropriate for 64-bit programs. You already know it, most of the HKLM\Software registry accesses are redirected to HKLM\Software\Wow6432Node. This redirection is already in place when the COM server is registered, a 32-bit installer is automatically redirected to write the keys to Wow6432Node instead. The installer is completely unaware that Wow6432Node even exists. Everything falls together automatically, the installer is redirected and the COM server client is redirected as well. All that you care about is knowing where to look to verify that the install was done properly, you do have to look at HKLM\Software\Wow6432Node\Classes\CLSID with Regedit.exe to find the keys back.
File redirection works much the same way, any access to c:\windows\system32 is redirected to c:\windows\syswow64, from c:\program files to c:\program files (x86). And very similarly, a 32-bit installer doesn't have to know beans about this, it can simply use the legacy 32-bit path names. Same for any 32-bit client program, it will be redirected the same way. All that you care about is knowing where to look for a file to verify the installer.
This can only go wrong if bitness is mixed, a 64-bit program reading registry keys or files installed by a 32-bit program. Or the other way around. Like it does with your troubleshooting tools, like Explorer, Regedit and SysInternals' Process Monitor. In general something that should be strongly avoided in COM, most servers are in-process servers and running 32-bit code in a 64-bit process is not possible. The biggest reason that the registry and file redirectors exist in the first place.
Windows Shell Scripting (vbs) has the following method:
object.GetObject(strPathname [,strProgID], [strPrefix])
Now suppose I have the following code:
set myval = getObject("myObjectRef:myObjectArgs")
This works on one machine - and not on another.
What I want to do is find the definitive list where all the myObjectRef/progIds are maintained.
My question is:How are the GetObject progids maintained?
Assumptions:
I'm looking for an answer more sophisticated that "do a search in the registry"
I'm looking to find a particular place where I can go looking for my progid to see if it exists or not.
I'm looking for an answer more sophisticated that "do a search in the registry"
Well, that's a bit difficult because that is really all it takes. You don't exactly have to "search", just look at where you expect it to find. Which is right underneath the HKEY_CLASSES_ROOT hive in regedit.exe, the keys are sorted alphabetically so just type the "m" key on your keyboard and you are already close the progid you are looking for. If you don't see the "myObjectRef.myObjectArgs" key then you can count on a kaboom at runtime when COM cannot find it either.
There is no "definite list" and no entity that maintains progids to ensure that they are unique. The list is specific to each machine, whatever was installed on that machine determines what you find back with Regedit.exe. They are simply a human-friendly version of the GUID, the value that really matters to locate a COM component. A Globally Unique ID that unambiguously identifies the server. The CLSID subkey of the progid key provides that GUID. It is a big number, not very human-friendly.
The progid key is written to the registry when the component installs itself. So a missing key simply means that it isn't installed.
A not uncommon problem on machines that boot a 64-bit version of Windows is that the COM server is only available as a 32-bit component but the client is a 64-bit process. This is resolved in the registry as well, the CLSID key is only present in HKLM\Software\Wow6432Node\Classes. The Wow6432Node section is what a 32-bit client sees. So a 64-bit client looks in HKLM\Software\Classes and won't find the key. Looks just like a "not-installed" problem, even though it is actually present. Just not the 64-bit version of it. SysInternals' Process Monitor is a great tool to diagnose problems like this. You see the failing client program searching through the registry.
I need to acquire registry path by it's handle in runtime. For this, I'm using NtQueryObject function. My problem is that NtQueryObject gives me the path in strange format (see image below).
I guess, this is the kind of format you need to use when you are writing drivers, but I want to have this path converted to standard reg path, such as
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run".
Currently I'm replacing
\REGISTRY\MACHINE\etc
with
HKEY_LOCAL_MACHINE\etc
but this Wow6432Node key is a problem. I guess it's name will vary across different machines, even 32 bit windows didn't have that key there. So my question is, is there any standard way to do reg path conversion (maybe some win api does it)?
The Wow6432Node really is part of the registry path to that particular key, although it is hidden from 32-bit processes. If you look in the Software key with Regedit you will find Wow6432Node.
On 64-bit systems both HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run and HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run exist. Depending on what you are trying to do, you may need to work with both of them or only one.
This describes the registry keys affected by WOW64:
http://msdn.microsoft.com/en-us/library/aa384253%28v=VS.85%29.aspx
You can explicitly access the 32-bit or 64-bit view of the registry as described here:
http://msdn.microsoft.com/en-us/library/aa384129%28v=VS.85%29.aspx
getting a COM error trying to run 32 bit OOP COM exe's on a 64 bit OS.
Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)).
If I have a compiled 32bit EXE that reads registry for GUID's how do I resolve this?
David D
That's probably a registration problem. The type library is used when you use the standard marshaller for the out-of-process server. Which uses the info in the type library to figure out how to properly serialize the arguments of a function call. On a 64-bit machine, the type library needs to be registered in the HKLM/Software/Wow6432Node/Classes/Typelib key. It is referenced by the TypeLib key in the registry key for the interface, a subkey of HKLM/Software/Wow6432Node/Classes/Interface.
Use SysInternals' ProcMon utility to observe where it is looking, contact the server's vendor or author for installer support.
Found the answer... The .NET solutions I had were set to "Any CPU". Once I changed it to x86... this solved the issue.
Does anyone have any idea why CoCreateInstance would be failing on ITaskBarList3 on Windows 7 64-bit? The error code is 0x80040154, which is Class Not Registered.
The calling code (VB6) is:
Public Const IID_ITaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
Public Const CLSID_TaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
'....
Dim IID As GUID_API
Dim CLSID As GUID_API
Dim iTaskBarVB3 As ShellLib.ITaskbarList3
rc = CLSIDFromString(StrPtr(CLSID_TaskbarList3), CLSID)
rc = IIDFromString(StrPtr(IID_ITaskbarList3), IID)
rc = CoCreateInstance(CLSID, 0, CLSCTX_SERVER, IID, iTaskBarVB3)
The returns from CLSIDFromString and IIDFromString are both 0 (Success). I can find the string in the registry. Since my taskbar is obviously working just fine, I know the interface is able to be called by other processes just fine.
ITaskBarList3 is declared in a typelib compiled using mktyplib.exe. I've double checked the GUID values, and they match those in the SDK.
Any help would be greatly appreciated.
The most likely reason is that the calling code is 32-bit and the COM server is 64-bit and therefore can't be loaded as an in-proc server.
A possible solution could be to create a COM+ application for the COM server to force its creation as an out-proc server. However this will not help if the COM server is meant to supply an ActiveX control.
I'm also surprised to see the class id being equal to the interface id - it's common practice to have them different. Since you are not the developer of the component implementing that interface but only the consumer it's likely that you just misplaced the class id with the interface id and this is the reason why your client program is not working. You should find the class id of the class implementing the ITaskBarList3 interface and use it as the class id.
CLSID_TaskbarList3 doesn't exist! It's simply,
CLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}"
which indeed has a different GUID than the IID_TaskbarList3 IID.
In COM you have typically one class implementing one or more interface. There doesn't generally exist a new class for every interface.
The ClassID wasn't the problem, as this worked correctly about a week ago. I was previously compiling on Windows Vista, 32-bit.
I've now updated my system to Windows 7, 64-bit. The problem isn't a matter of 32/64-bit compatibility. The TaskBar is accessible through Wow64, and I am able to call the interface just fine from a 32-bit ATL DLL.
I did some more searching, and I found a number of references on the web regarding problems with actxprxy.dll on 64-bit windows. This is the DLL where the interfaces appear to reside, according to OLE Viewer.
Anyways, some people have had luck with various combinations of .reg scripts and unregistering/re-registering the files. Unfortunately, I'm not one of those people.
I've decided to save myself the headache, and just wrote a small DLL using ATL, and I have the VB code calling that. Works fine in that setup...
Thanks again for your help.