"Library not registered" error, can I determine which one exactly? - c++

In C++ add-in for Outlook, I'm now getting "Library not registered" error. This add-in worked for ages on this machine but somehow things got broken now (although it still works fine on other machines).
Is there any way to find out which particular library is missing (not registered) without reinstalling everything? Is there a WinAPI call with some extended error information, such as the library name/path in question?
CComGITPtr< Outlook::_Application > m_GITPointer;
...
hr = m_GITPointer.CopyTo( &application ); // hr is 0x8002801d

Related

OCX AfxOleRegisterTypeLib fails with error 0x80040200

I upgraded an OCX library from VS2010/Win7 to VS2019/Win10. The project builds, however when I try and use RegSvr32.exe from an elevated command prompt, I receive error 0x0040200. I did a bit of debugging and the offending call is the call to AfxOleRegisterTypeLib.
Yes, I saw this SO article, which states that "absence of a tlb file near the dll". Other searches state to run from an administrative command prompt.
I do NOT have a TLB near the OCX control. If I try and create one using tlbexp.exe, I get the following error:
TlbExp : error TX0000 : Could not load file or assembly 'file:///C:\pathto.ocx' or one of its dependencies. The module was expected to contain an assembly manifest.
TlbExp command line (used Run as Administrator for all cmd.exe):
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\x64\tlbexp.exe" /VERBOSE "<path to OCX file>" /out:"<path to .tlb output file>"
I downloaded Resource Tuner and that shows the manifest nicely. The manifest does not have any TLB information.
I am thinking that maybe the OCX manifest needs something more that helps TlbExp get at the information that it wants, just a thought.
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="DriveOps.ocx"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
</assembly>
I did use Depends64 (aka Dependency Walker 64-bit) and there are no missing components DLLs. It finds all of them nicely, as does RegSvr32.exe.
Placing the OCX file in C:\Windows\System32 does not help.
To anyone looking at the DLLs, these same DLLs work fine on the Win7 box. Here is some more information on the non-Windows DLLs
PlxApi720_x64.dll: PLX v7.2 API (The Broadcom PLX chip is a PCIe switch (think USB/network switch, just w/PCIe lanes)
LSIDirectAccess.dll: The LSI API is a self-contained DLL that allows the software to talk to the LSI HBA RAID adapter
Ipp*.dll: The Ipp prefix are the DLLs used by the Intel Code Composer Studio redistribution (x64) files, here version 2011, an older one that needs to be updated to the latest and greatest, not to mention now free API. These are all in the System32 folder.
Here is the code:
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
return ResultFromScode(SELFREG_E_TYPELIB); // <- failure line, through debugging
if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
return ResultFromScode(SELFREG_E_CLASS);
return NOERROR;
}
The Intel Code Composer Studio 2011 files are in the C:\Windows\System32 directory, just like on the Win7 box.
For what it is worth, TlbExp fails on the Win7 box too, just it registers, which is probably why the UI can add the control. As I recall, I once replaced the OCX on the Win7 project and VS2010 automatically created the TLB and prefixed Ax in front, but that was a couple of years ago, so my memory may not be the most accurate. Attempting to add the OCX to the UI (.Net WinForms) fails miserably and just says could not be added.
The OCX does use the latest platform tool set (Visual Studio 2019 (v142)).
A comment for developer newbies, regasm.exe is for .Net Assemblies. RegSvr32.exe is for ActiveX Controls (OCX/DLL), which is what I have. RegSvr32 is for dynamically loaded modules, hence the DllRegister entry point.
Thoughts?
Notes From Further Testing
(Saturday 9/21/2019) When I upgraded, I created an empty C++ DLL project and then added all the files, changing the target extension to OCX going through the old project settings and when reasonable aligning them to the new project file wanting to keep things the same. I wanted to do a test and see what happens with a brand new OCX project. I saw that there was such a thing as "MFC ActiveX Control" for a project type in VS2019. I created that and saw that I got different base files, but more importantly RegSvr32.exe works. That means that either the mistake was the initial project file, so I need to import to a clean project or import piece by piece, if that is possible, and see where things break.
(Saturday 9/21/2019) The new test project did not come with a manifest file and TlbExp.exe failed with the same error message like my real project. I went to add new item and saw "Package Manifest". That manifest file, though still produces the same TlbExp.exe error, looks quite different from the application manifest file from above. I created yet another new MFC ActiveX Control project and added in the manifest from above just changing names and saw that the project refused to build throwing 1) Error c1010001 Values of attribute "level" not equal in different manifest snippets. and 2) LNK1327 failure during running mt.exe. That tells me that the original Win7 project and my Win10 project files probably have some error in it, otherwise VS should have thrown these errors to me. That does not answer why even on the test project TlbExp.exe fails. Maybe some attributes in the manifest are required. I just left the defaults.
Package Manifest
(It is the first time that I ever saw one of these. I always saw the app.manifest kind.)
<?xml version="1.0" encoding="utf-8"?>
<!-- TODO: Make sure to set the Package attributes -->
<Package xmlns="urn:Microsoft.WindowsPhone/PackageSchema.v8.00"
Owner=""
OwnerType="OEM"
Platform=""
Component=""
SubComponent="Package"
ReleaseType="Test" >
<Components>
<Driver InfSource="$(_RELEASEDIR)$(TARGETNAME).inf">
<Reference Source="$(_RELEASEDIR)$(TARGETNAME)$(TARGETEXT)" />
<Files>
<!-- For kernel mode drivers, $(DRIVER_DEST) evaluates to "drivers" by default -->
<!-- For user mode drivers, $(DRIVER_DEST) evaluates to "drivers\umdf" by default -->
<File Source="$(_RELEASEDIR)$(TARGETNAME)$(TARGETEXT)" DestinationDir="$(runtime.system32)\$(DRIVER_DEST)" />
</Files>
</Driver>
</Components>
</Package>
This article has an interesting approach, namely create a C++ DLL and then call LoadLibrary(dll) and after that GetProcAddress(module, "DllRegisterServer") to see which one fails. Well, in my case the both functions succeed. That means that the author missed one other failure branch and these two API calls are not the only thing that RegSvr32.exe does.
Though I am still not at the end of the road, as I have aximp.exe / tlbimp.exe issues on the OCX, I found the problem that prevented me from registering the ActiveX control, which was the question here.
The answer is the GUID in the main CPP file:
(I am giving my research, as I could not find anyone explaining how RegSvr32.exe works and what it does. I wanted to share in hopes that it helps others.)
const GUID CDECL _tlid = { 0xFE5C7D88,0xD53C,0x4977,{0xBA,0x56,0x4B,0xF3,0x02,0x0A,0x5D,0x8A} };
which gets used in the main registration function STDAPI DllRegisterServer(void) must match the GUID present in the IDL:
[uuid(FE5C7D88-D53C-4977-BA56-4BF3020A5D8A), version(1.0),
helpfile("DriveOps.hlp"),
helpstring("DriveOps ActiveX Control module"),
control]
library DriveOpsLib
{
...
}
I had 2 different values, hence the failure.
Here is the methodology and research that I used to find the problem, but first I will state the registration function, as that is key again.
STDAPI DllRegisterServer(void)
{
AFX_MANAGE_STATE(_afxModuleAddrThis);
HINSTANCE hiTypeLib = AfxGetInstanceHandle();
if (!AfxOleRegisterTypeLib(hiTypeLib, _tlid))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
return ResultFromScode(SELFREG_E_CLASS);
return NOERROR;
}
The failure was at this line, as I believe was mentioned in the question.
if (!AfxOleRegisterTypeLib(hiTypeLib, _tlid))
I had already found the source code for RegSvr32.exe on the internet. It was part of Microsoft GitHub sources located in VCSamples-master.
Direct Link to RegSvr32.exe: here
Direct Link to download zip: here
The code was a sort of dead end, as it told me what should have been obvious, namely that utility called the DllRegisterServer entry point of a DLL to do all the work. I should have known that, but, well, I had to see it to make sense.
Using procmon.exe, did not shed any light and the various calls to the registry was like reading a foreign language, not helpful.
Here I drew a blank until it occurred to me to get the source code for AfxOleRegisterTypeLib, as that what was failing. I wanted to see what the heck that thing did and what was at line 113 of source file ctlreg.cpp.
I was still thinking on the comment of procmon and a registry issue, but I figured that the code will tell me which one. It took me a bit of research, but I found the code. I love Microsoft sharing code. Their error messages are not helpful, but being able to actually see what they were trying to do so totally helps.
Here is the code:
BOOL AFXAPI AfxOleRegisterTypeLib(HINSTANCE hInstance, REFGUID tlid,
LPCTSTR pszFileName, LPCTSTR pszHelpDir)
{
USES_CONVERSION;
BOOL bSuccess = FALSE;
CString strPathName;
TCHAR *szPathName = strPathName.GetBuffer(_MAX_PATH);
::GetModuleFileName(hInstance, szPathName, _MAX_PATH);
strPathName.ReleaseBuffer();
LPTYPELIB ptlib = NULL;
// If a filename was specified, replace final component of path with it.
if (pszFileName != NULL)
{
int iBackslash = strPathName.ReverseFind('\\');
if (iBackslash != -1)
strPathName = strPathName.Left(iBackslash+1);
strPathName += pszFileName;
}
if (SUCCEEDED(LoadTypeLib(T2COLE(strPathName), &ptlib)))
{
ASSERT_POINTER(ptlib, ITypeLib);
LPTLIBATTR pAttr;
GUID tlidActual = GUID_NULL;
if (SUCCEEDED(ptlib->GetLibAttr(&pAttr)))
{
ASSERT_POINTER(pAttr, TLIBATTR);
tlidActual = pAttr->guid;
ptlib->ReleaseTLibAttr(pAttr);
}
// Check that the guid of the loaded type library matches
// the tlid parameter.
ASSERT(IsEqualGUID(tlid, tlidActual));
if (IsEqualGUID(tlid, tlidActual))
{
// Register the type library.
if (SUCCEEDED(RegisterTypeLib(ptlib, T2OLE((LPTSTR)(LPCTSTR)strPathName), T2OLE((LPTSTR)pszHelpDir))))
bSuccess = TRUE;
}
RELEASE(ptlib);
}
else
{
TRACE1("Warning: Could not load type library from %s\n", (LPCTSTR)strPathName);
}
return bSuccess;
}
I kept receiving an ASSERT, so although line 113 did was on a non-code line, the actual failure was obvious. I knew that I did not fail out on the ASSERT_POINTER, as that error message is different, which meant that I failed at:
ASSERT(IsEqualGUID(tlid, tlidActual));
I looked at the code in detail as well as the entry arguments. I decided to copy and paste this function contents into the real registration code in my OCX to gain further visibility while debugging. I wanted to see the values.
Sure enough, I saw 2 different GUID values, one from the top, my _tlid, and the one returned from the instance handle. I took out my handy-dandy TextPad text editor, though Visual Studio has a Find in Files, but TextPad is so much easier to use. That led to one other instance in the entire solution, namely in DriveOps.idl. That file up until that moment meant nothing to me, but suddenly I saw that the GUID here was the one that RegSvr32.exe pulled from the instance handle.
I unified the IDs, rebuilt, and now RegSvr32.exe no longer complains. Yeah, since I got the code, it had no choice but to register. That it does not modify the registry is a different story and problem from what I can tell, but that is another question. RegSvr32.exe now registers without complaint.
(Yes, I still have tlbimp.exe, aximp.exe, and adding my OCX project to my WinForms project problems, but I got this thing licked and learned something in the process. I guess the difference in line numbers may be some changes Microsoft made in the header, either way, functionality appears the same.)
Great. Issue in all such cases is the IDL has a different GUID as compared to what the DLL / OCX has in code for registration. How it changed, I did not investigate but was able to fix this issue by reading new GUID from project generated *.idl file.

stat not returning properly on centos 7?

So I am running a C++ app, built with CMake (not by me). It works fine on other people testing with it, but not found anyone to test on centos7 yet.
The issue seems to arrise at this snippet of code:
struct stat fileStat;
if ( stat( pszFilePath, &fileStat) == -1 )
{
DEBUG_ERR(( "Can't open input dir [%s]\n", pszFilePath ));
return( false );
}
Which is the first part of the ReadFileInfo call here:
time_t dateChange;
DWORD dwSize;
if ( ! CFileList::ReadFileInfo( GetFilePath(), dateChange, dwSize ))
{
DEBUG_ERR(( "Can't get stats info for file '%s'\n", static_cast<LPCTSTR>(GetFilePath()) ));
return false;
}
Now, pszFilePath is many value, a few examples are:
'scripts/sphere_template_vend.scp'
'scripts/sphere_serv_triggers.scp'
The application is owned by root, the whole folder it all sits in is owned by root. The scripts folder is there and has read/write permissions as do all files (all also owned by root)
Running the application triggers both errors in the above code, there is nothing before them that influences anything.
Im not a C++ developer and do not have the tools to compile with debugs for checking the current path and so on, but I see no reason why it throws these errors. The files exist, the files are accessible, no one else seems to have this problem.
I do have cPanel on the server, but it shouldn't be causing any issues as I am using root user and also keeping out of the /home/ directory
Anyone know of any issue this could be because of? I tried with a '/sphere/' prepending the paths but it still has the same issue, it seems the application does not have access to the files (the application oddly reports line errors within the files it says it cannot read, but they do not match, so assuming its not correct).
Issue reported on the Github for the project here: https://github.com/Sphereserver/Source/issues/64
But no one seems to know whats going on

Error when instantiating ADODB ConnectionPtr on Windows Server 2008

I have an application that I have compiled on Windows 7 64-bit. It works fine on that PC, but I am now trying to get it to work on Windows Server 2008 R2 Standard.
Whenever I try and instantiate ADODB::Connection, I receive the following error:
HRESULT : No such interface supported; hr=0x80004002
Code that generates the error is below:
CoInitialize(NULL);
_ConnectionPtr link;
link.CreateInstance(__uuidof(Connection) );
if (link == NULL) {
_com_error err(hr);
Error(err);
}
Now I found this thread: http://social.msdn.microsoft.com/Forums/vstudio/en-US/12c95ba7-60ed-4303-b4da-e811150b8d13/cannot-able-to-instance-adodbconnection-in-2008-r2-server-core-no-such-interface-supported?forum=vcgeneral, which seems to suggest the problem with a particular windows update, and provides a fix for it. However, the update that supposedly causes the problems is not on this machine, and if I try to install the fix I simply get an error saying that the update "does not apply to this computer".
Any ideas anyone? Thanks in advance.

EDSDK cpp error: 10 EDS_ERR_MISSING_SUBCOMPONENT

I am trying to get started with EDSDK to control my Canon 500D. I'm new to cpp, and windows XP apps and I'm using visual studio. After a great deal of blind trial and error I have finally managed to get the app to compile the basic sample code from the documentation. To do this I have the EDSDK.h, EDSDKTypes.h and EDSDKErrors.h headers in the right places and the EDSDK.dll and EDSDK.lib in the same folder as the code. It seems to be picking these up. I have got the 500D to be recognised by the PC so I believe the USB drivers are there.
The code is just trying to pick up the camera:
EdsError err=EDS_ERR_OK;
EdsCameraListRef cameraList=NULL;
err = EdsGetCameraList(&cameraList);
if(err == EDS_ERR_OK)
{...}
However, when I run this console app the error is picked up as 10 - which suggests, according to the document, that there is a missing subcomponent. This happens both if the camera is connected or not, so I'm thinking this is something missing from the compile. But I am getting nowhere with the documentation.
I have installed the edsdk 2.4 Windows version from a download not the official route, so this may be an issue.
Can anyone help? Specifically how can I find out what the missing subcomponent might be so I might include it. Is this a subcmponent of the build like a header file or something like a driver?
I know, old question but still it might help someone with the same problem.
From the documentation:
All DLLs are required in order to execute an EDSDK client application.
All of the modules in the DLL folder must be copied into the same folder where the EDSDK client application is in.
This means you'll have to have all DLLs beside your *.exe. Namely these DLLs:
DPPDLL.dll
DPPLibCom.dll
DPPRSC.dll
EDSDK.dll
EdsImage.dll
Mlib.dll
Ucs32P.dll

HRESULT "Class Not Registered" Implementing simple COM server DLL

I'm following this sites tutorial:
http://progtutorials.tripod.com/COM.htm
Preliminary evidence: Visual Studio 2010, Windows 7 64 bit.
and I'm coding the examples in section 3. (Implementing a server DLL). I've typed out the code exactly as shown and I'm getting a "Class not registered" exception when executing this code on line 12 of the code outlined in section 4.1 (where the tutorial shows you how to access the DLL and I have followed 3.1 to the letter):
hresult hr = CoGetClassObject(CLSID_Car, CLSCTX_SERVER, NULL, IID_IClassFactory, (void **) &pClassFactory);
I tried running:
regsvr32 xyz.dll
with xyz.dll being the path to my dll in order to register the DLL. This resulted in an error trying to find DLLRegisterServer:
I have already run
REGEDIT
HKEY_CLASSES_ROOT\CarDLL.Car\CLSID = {d969084c-b758-43ea-a218-a48763167abd}
HKEY_CLASSES_ROOT\CLSID\{d969084c-b758-43ea-a218-a48763167abd} = CarDLL.Car
HKEY_CLASSES_ROOT\CLSID\{d969084c-b758-43ea-a218-a48763167abd}\InProcServer32 = C:\Users\wiocl2\Documents\Visual Studio 2010\Projects\CarDLL\debug\CarDLL.dll
that I assumed put all the GUIDS I needed in the registry (The GUIDS were generated by me).
I'm assuming that a function is needed to be added to the class that allows it to be registered but I don't know how to do this and how to go about figuring it out. I'm kind of lost, as I haven't been working with COM for very long. If someone could give me a shove in the right direction that would be helpful.
Edit: Oh yes, I moved
#include // contains definition of DEFINE_GUID
to the iid.h file from iid.cpp, otherwise I was getting unresolved external errors on the build.
The most likely explanation: you are building your COM object as a 32-bit DLL, but the registration has been performed as a 64-bit DLL.
The treatment: open an admin privileged command window and navigate to the location of your DLL (C:\Users\wiocl2\Documents\Visual Studio 2010\Projects\CarDLL\debug). Once there, type:
c:\windows\sysWOW64\regedit <filename of .reg file whose contents are displayed above>
This will run the 32-bit version of REGEDIT, ensuring that the registry entries are created in the correct part of the hive. To verify this, you should see an entry for {d969084c-b758-43ea-a218-a48763167abd} in HKLM\Software\Wow6432Node\Classes\CLSID, not HKLM\Software\Classes\CLSID.
DllRegisterServer is a method you can implement in your COM server DLL, and is required if you want to use regsvr32 to perform the same operation you are currently using the .REG approach for. The same caveat applies: for a 32-bit DLL, you'll need to invoke c:\windows\sysWOW64\regsvr32.exe.
And Yes! COM is still mostly alive and well :) At least there is still standard support for it in VS 2012.
Hope that helps.