PRMARJORAM

Im having a strange problem with regsvr32 when registering a DLL.

Get the following error message:

Linking...

Creating library C:\DEV8\cbwbCalculator\Debug\cbwbCalculator.lib and object C:\DEV8\cbwbCalculator\Debug\cbwbCalculator.exp

Embedding manifest...

Registering output...

Project : error PRJ0050: Failed to register output. Please ensure you have the appropriate permissions to modify the registry.

It seems if i start commenting out some global data references that use extern then problem seems to go away - but i have lots of externs.

extern BOOL bIsOLE;

I dont understand why global extern references would cause a problem with regsvr32...

Can you just not use global data references with a COM DLL

Can anybody shed some light on this perplexing problem.

Thanks.



Re: Visual C++ General RegSvr32 and global data and extern problem

Sahir Shah

 PRMARJORAM wrote:
Im having a strange problem with regsvr32 when registering a DLL.

Get the following error message:

Linking...

Creating library C:\DEV8\cbwbCalculator\Debug\cbwbCalculator.lib and object C:\DEV8\cbwbCalculator\Debug\cbwbCalculator.exp

Embedding manifest...

Registering output...

Project : error PRJ0050: Failed to register output. Please ensure you have the appropriate permissions to modify the registry.

  It seems if i start commenting out some global data references that use extern then problem seems to go away -  but i have lots of externs.

  extern BOOL bIsOLE;

  I dont understand why global extern references would cause a problem with regsvr32...

 Can you just not use global data references with a COM DLL

 

 Having global data members with extern storage specifier in itself will not cause the error message you describe.  I tried it in VC6 and VC 2005 and did not see this error message.  It must an unrelated problem that is causing this error message. 

 Regards

    Sahir





Re: Visual C++ General RegSvr32 and global data and extern problem

PRMARJORAM

Thanks Sahir...

Iv since got a bit further on this problem.

The client is a MFC COM DLL that depends on an old C DLL explicit linking via lib file.

If i call a few functions from the MFC COM DLL into the C DLL is all ok. So this proves it can find the DLL ok.

If i add a few calls via function pointers again from the MFC COM DLL to the C DLL, then this is when the error message occurs. So why would it not like C function pointers

If i link the C DLL statically i rebuild the project as a static lib, then all is fine. Although this is not an option, but just throws some light on the problem

So why would regsvr32 fail to register a COM DLL than implicitly links to a C DLL which declares some pointer to functions and these are used from the client





Re: Visual C++ General RegSvr32 and global data and extern problem

Sahir Shah

 PRMARJORAM wrote:

The client is a MFC COM DLL that depends on an old C DLL explicit linking via lib file.

If i call a few functions from the MFC COM DLL into the C DLL is all ok. So this proves it can find the DLL ok.

If i add a few calls via function pointers again from the MFC COM DLL to the C DLL, then this is when the error message occurs. So why would it not like C function pointers

If i link the C DLL statically i rebuild the project as a static lib, then all is fine. Although this is not an option, but just throws some light on the problem

So why would regsvr32 fail to register a COM DLL than implicitly links to a C DLL which declares some pointer to functions and these are used from the client



What I understand from the above is that your COM dll wraps some calls to a C DLL. The client calls the COM dll and the COM dll in turn calls the C dll. When you use implicit linking ( to the C dll) your COM dll registers OK and when you use explicit linking (dynamic linking) you are unable to register the COM dll. When regsvr32 is called the target dll and it's dependencies are loaded. AFAIK dynamic linking does not count as a dependency in this context. So this is perplexing indeed.

You can try the following :

1) Since the error message says :
error PRJ0050: Failed to register output. Please ensure you have the appropriate permissions to modify the registry.

Check if you have the neceszsary permissions.

2) Try building the dll and calling regsvr32 manually instead of using the IDE. Check if you get the same response.

3)
Try checking your COM dll's dependencies using Depends.exe; this may throw some light on the issue.

Regards

Sahir Shah




Re: Visual C++ General RegSvr32 and global data and extern problem

PRMARJORAM

Thanks Sahir for your continued interest in this problem, it still exists...

Yes a client makes calls to the COM DLL and the COM DLL links to an old legacy C DLL.

The COM DLL implicitly links to the C DLL via its Lib file, although still uses the C DLL also.

What i mean here it does not use LoadLibrary it uses the Lib file generated in conjunction with the DLL.

I have tried all you have said:

I do have the permissions - as stated if certian code is commented out then it is fine. This proves it finds the DLL ok and I have permissions. This also covers the Depends option which i have checked. Just the COM DLL depends on the C DLL, all dependencies after that are system ones.

If i run regsvr32 from the CLI i get the following error message:

LoadLibrary("MyCom.dll") failed - The specified procedure could not be found

Again what procedure could not be found

I isolated the code i thought was suspect and created a dummy C DLL and dummy client COM DLL to depend on this, but all ok.

Any ideas greatly appreciated





Re: Visual C++ General RegSvr32 and global data and extern problem

Sahir Shah

This has fired my interest particularly because I had a similar problem with IBM's pcsapi.dll many years ago. So, I cannot sleep until I find out what's happening 

Can you post the code of the dummy C dll and the dummy COM dll ,  and tell me in what way it differs from the actual thing   If it's very long don't post it here, mail it to me


Regards
  Sahir





Re: Visual C++ General RegSvr32 and global data and extern problem

PRMARJORAM

Hi Sahir;

Here is a sample the COM DLL client code

If you check the test() function below - that is the line that fails.

When it works the global afx object is created and the initInstance member function is called. The DLL register API is then called.

When it does not work - it seems to fail even creating the app object - it does not get this far. This i tested via inserting message boxes.

If you need anymore code - please let me know.

Ill post a sample of the C DLL next. This is assuming the problem is not linked to some compiler/linker switch.

BEGIN_MESSAGE_MAP(CcDLLClientApp, CWinApp)

END_MESSAGE_MAP()

CcDLLClientApp::CcDLLClientApp()

{

}

CcDLLClientApp theApp;

const GUID CDECL BASED_CODE _tlid =

{ 0xD6497620, 0x61C8, 0x4FF5, { 0x99, 0xAE, 0xCF, 0x86, 0xFD, 0x9C, 0xB7, 0x73 } };

const WORD _wVerMajor = 1;

const WORD _wVerMinor = 0;

// CcDLLClientApp initialization

BOOL CcDLLClientApp::InitInstance()

{

CWinApp::InitInstance();

COleObjectFactory::RegisterAll();

Test();

return TRUE;

}

void CcDLLClientApp::Test()

{

// This ensures it links correctly to the C DLL

Array* m_vResultPtr;

m_vResultPtr = c_PCodeArray();

FromStringFn bFn = NULL;

// THIS LINE CAUSES THE FAIL - when commented out all works fine.

bFn = (FromStringFn)b_DelimitedPCode;

}

/}

// DllGetClassObject - Returns class factory

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

return AfxDllGetClassObject(rclsid, riid, ppv);

}

// DllCanUnloadNow - Allows COM to unload DLL

STDAPI DllCanUnloadNow(void)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

return AfxDllCanUnloadNow();

}

// DllRegisterServer - Adds entries to the system registry

STDAPI DllRegisterServer(void)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))

return SELFREG_E_TYPELIB;

if (!COleObjectFactory::UpdateRegistryAll())

return SELFREG_E_CLASS;

return S_OK;

}

// DllUnregisterServer - Removes entries from the system registry

STDAPI DllUnregisterServer(void)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))

return SELFREG_E_TYPELIB;

if (!COleObjectFactory::UpdateRegistryAll(FALSE))

return SELFREG_E_CLASS;

return S_OK;

}





Re: Visual C++ General RegSvr32 and global data and extern problem

PRMARJORAM

Here is a sample of the C DLL - sorry for all the typdefs, but the original code contained these

The problem is the problem does not manifest itself with this simple substitution.

Where it goes onto differ, im not familar with yet, i just assume its link to dependencies in terms of headers etc.

#pragma once

typedef unsigned char Logical;

typedef void Void;

typedef char Char;

#define String Char /* standard C string class */

#define Const const

#ifdef __cplusplus /* C++ specific */

#define Public extern "C" /* global C function in C++ code */

#define Friend /* implementation documentation */

#else /* C specific */

#define Public extern /* globally available item */

#endif

typedef String* PCode;

typedef Logical ( *FromStringFn )( Void*, Const String* ); /* b_ */

Public Logical b_DelimitedPCode

(

PCode* instance,

Const String* string

);

Public Logical c_PCodeArray

(

Void

);

#include"Function.h"

/*

* Logical b_DelimitedPCode()

*

* Convert from string.

*/

Public Logical b_DelimitedPCode

(

PCode* instance,

Const String* string

)

{

return '1';

}

Public Logical c_PCodeArray

(

Void

)

{

return '1';

}





Re: Visual C++ General RegSvr32 and global data and extern problem

Sahir Shah

PRMARJORAM wrote:

typedef char ( *FromStringFn )( void*, const char* );
extern "C" char b_DelimitedPCode (char** instance, const char* string);
extern "C" char c_PCodeArray(void);

PRMARJORAM wrote:

BOOL CcDLLClientApp::InitInstance(){
CWinApp::InitInstance();
COleObjectFactory::RegisterAll();
Test();
return TRUE;
}

void CcDLLClientApp::Test(){
FromStringFn bFn = NULL;
bFn = (FromStringFn)b_DelimitedPCode;
}

You seem to have declared the function pointer in the called dll and attempt to initialize and use the function pointer in the calling dll. That is highly unusual , any particular reason for doing it this way

Regards

Sahir





Re: Visual C++ General RegSvr32 and global data and extern problem

PRMARJORAM

Sahir, I would never write code like this.

It was written over 15 years ago by somone long gone.

Im just trying to replicate the conditions for the problem to manifest itself. But it does not.

This is just how the original code is written.

I suspect in the original code because of including the header that includes these definitions subsequent headers then get included.

Believe me there are loads of them. At some point it seems im going to have to trawl through them all.... Oh its a lovely job :-)

But generically i just cannot get a handle on why regsvr32 would fail to load the calling DLL based on some presence in the called DLL.

I mean to register it - it does not even call into the C DLL





Re: Visual C++ General RegSvr32 and global data and extern problem

PRMARJORAM

Solved it.

It fails from within the project when building and from the command prompt when in the same directory as the DLL.

But when i used a full absolute path for the COM DLL as the parameter for regsvr32 then its registered fine.

So its a relative path problem! Not sure why - but at least i can move on.





Re: Visual C++ General RegSvr32 and global data and extern problem

tsgomez

I'm having the same exact problem. I've tried to manually register the dll but, even using the absolute path, it fails.

Has anyone looked further into this to see what is happening Where else can I look to find information to resolve my problem

Any assistance would be appreciated.