Solved

URGENT:  Linking resolution problem

Posted on 2004-04-27
20
1,227 Views
Last Modified: 2007-12-19
I'm having a problem with Unresolved Symbols.  

I'm trying to integrate the source code found here:

http://support.microsoft.com/?kbid=171907

into  a MAPI project.  I'm having errors when it tries to reference the variables:

OutlookCOM error LNK2001: unresolved external symbol _CLSID_MailMessage
OutlookCOM error LNK2001: unresolved external symbol _IID_IMessage

Where CLSID_MailMessage is defined in that source code as

DEFINE_GUID(CLSID_MailMessage,
0x00020D0B,
0x0000, 0x0000, 0xC0, 0x00, 0x0, 0x00, 0x0, 0x00, 0x00, 0x46);

in mapiguid.h there is the code

#if !defined(INITGUID) || defined(USES_IID_IMessage)
DEFINE_OLEGUID(IID_IMessage,          0x00020307, 0, 0);

Both of the macros DEFINE_GUID and DEFINE_OLEGUID are called at the tope of my .cpp source file These vars are then referenced inside a class method in the same .cpp file.

Any thoughts as to why I am having this error:
0
Comment
Question by:jjacksn
  • 7
  • 6
  • 5
  • +2
20 Comments
 
LVL 48

Expert Comment

by:AlexFM
Comment Utility
Try to add line

#define USES_IID_IMessage

to one of the project .cpp files, before #include "mapiguid.h"
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
it is currently above the #include directive.  here is the top of the source file:

#include "OutlookCOMHdr.h"
#include "ContactCreator.h"

#define INITGUID
#include <objbase.h>

#define USES_IID_IMessage

#include <mapix.h>
#include <mapitags.h>
#include <mapidefs.h>
#include <mapiutil.h>
#include <mapiguid.h>
#include <imessage.h>

// {00020D0B-0000-0000-C000-000000000046}
DEFINE_GUID(CLSID_MailMessage,
0x00020D0B,
0x0000, 0x0000, 0xC0, 0x00, 0x0, 0x00, 0x0, 0x00, 0x00, 0x46);
0
 
LVL 39

Expert Comment

by:Kyle Abrahams
Comment Utility
Try removing the underscores before the 2 variables.

IE:

OutlookCOM error LNK2001: unresolved external symbol _CLSID_MailMessage   -> Replace just with CLSID_MailMessage
OutlookCOM error LNK2001: unresolved external symbol _IID_IMessage            -> Replace just with IID_Imessage

try that or define them as external variables.

0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 300 total points
Comment Utility
In objbase.h i found this

#ifndef INITGUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    EXTERN_C const GUID FAR name
#else

#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
        EXTERN_C const GUID name \
                = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
#endif // INITGUID

That means that if INITGUID is defined with DEFINE_GUID you only declare an extern variable. That's why the linker didn't found any code where the variable gets _defined_ as it is in the #else branch of the code snippet above.

What to do?

I think that you may not define these INITGUID macro before including any standard header files or if you do, you may not use DEFINE_GUID macro but that

        EXTERN_C const GUID CLSID_MailMessage = {  0x00020D0B,
               0x0000, { 0x0000, 0xC0, 0x00, 0x0, 0x00, 0x0, 0x00, 0x00, 0x46} };

A similar problem you have with DEFINE_OLEGUID as it is defined as

#define DEFINE_OLEGUID(name, l, w1, w2) \
    DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)

So, if DEFINE_GUID is wrong DEFINE_OLEGUID is wrong as well.

Regards, Alex


0
 
LVL 8

Expert Comment

by:_corey_
Comment Utility
I believe the solution is to include initguid.h  at the very beginning.

--
ged325
--
That _ (underscore) is added by the compiler, it isn't the source of the problem.

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>> I believe the solution is to include initguid.h  at the very beginning.

That is wrong as in initguid.h there is an

#ifndef DEFINE_GUID
#error initguid: must include objbase.h first.
#endif

Try to skip

#define INITGUID

in the CPP file you posted above

Regards, Alex

0
 
LVL 8

Expert Comment

by:_corey_
Comment Utility
itsmeandnobodyelse:

I don't see that all in the file.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>> I don't see that all in the file.

Maybe a subject of change... I am working with VC6.

initguid.h :

/*****************************************************************************\
*                                                                             *
* initguid.h -  Definitions for controlling GUID initialization               *
*                                                                             *
*               OLE Version 2.0                                               *
*                                                                             *
*               Copyright 1992 - 1998 Microsoft Corp. All rights reserved. *
*                                                                             *
\*****************************************************************************/

Pretty old, maybe they changed it in a younger version.

However, the problem is NOT that the source didn't include header files  BUT that the macro INITGUID has been explicitly defined before including any Windows headers. That turns the GUID variables to be defined as 'extern' ==> the linker misses the storage for these GUID variables.

So, in exactly one CPP file using DEFINE_GUID and DEFINE_OLEGUID macros the #define INITGUID preprocessor statement MUST NOT be defined in order to get a storage for these variables.

Regards, Alex
0
 
LVL 8

Expert Comment

by:_corey_
Comment Utility
You're right about the forced definition of INITGUID being bad.  I see that part of his code in the other posts.

My initguid.h defines that and then includes the proper guiddef header which creates all the macros/etc.

I'm using VS6 to answer this Q as well, which is interesting. Oh yes, I'm using the PlatformSDK on this machine.  It is a lot more cleaned up by using guiddef.h after INITGUID definition and doesn't have that warning.

0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
Thanks people!  I'm out of town until Sunday, but I'm pretty sure you all pointed out the correct error and I will give you all points when I can verify it is what you think it is.  

I'm still kind of confused though:  why would FAR matter when its in the same source/object file?
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>> I'm still kind of confused though:  why would FAR matter

FAR is an obsolete macro that defaults to nothing. So, it doesn't matter.

What matters is the different definition of macro DEFINE_GUID that is either

    EXTERN_C const GUID FAR name

where name is the argument of the macro  OR

    EXTERN_C const GUID name \
                = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }

The second one is a definition, i. e. a storage is allocated, while the first one only is an 'extern' declaration, where no storage is allocated.

Regards, Alex
   
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
I see that now.  Thanks.  Out of curiosity, why are these headers structured like this?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
It's rather a C++ problem but a header file problem:

If you will use a global variable - as a GUID - in more than one module (cpp file), there is a problem. If you define the variable in all modules as

    int variable = 0;

the Linker will complain because of duplicate names. And the prog wouldn't work also as you need the _SAME_ variable in all modules.

The way out is the C++ keyword extern. If you declare in module b.cpp

    extern int variable;

the Compiler knows, that for this variable no storage must be allocated, because it has already been defined in another module - say a.cpp - like

    int variable = 0;

So in one module it must be defined and in all others it must be declared as extern.

But, a new problem arises, if you would like to make both alternatives by including the same header file - say h.h - both in a.cpp and b.cpp.

Mostly the solution is made using macros similar to that we had seen above:

// h.h

#ifdef DEFINE_MY_VARIABLE
    int variable = 0;
#else
    extern int variable;
#endif


That will be used like this in a.cpp

#define DEFINE_MY_VARIABLE
#include <h.h>

and in b.cpp and all other modules that need access to 'variable'

#include <h.h>

not defining DEFINE_MY_VARIABLE before.

A similar technique had been used above: defining INITGUID before including system headers leads to a defining macro that makes an extern declaration and ommitting the #define INITGUID turns the macro DEFINE_GUID to make a definition.

Hope, that was clear enough

Regards, Alex
0
 
LVL 8

Expert Comment

by:_corey_
Comment Utility
Yea, and the PlatformSDK cleans this up a bit by providing a header change -- initguid.h -- that does this special declaration for you.  You don't have to switch though, just the reason I gave the confusing/contradicting info before.
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
Just got around to trying to fix this,

#include "OutlookCOMHdr.h"
#include "ContactCreator.h"

//#define INITGUID
#include <objbase.h>

#define USES_IID_IMessage

#include <mapix.h>
#include <mapitags.h>
#include <mapidefs.h>
#include <mapiutil.h>
#include <mapiguid.h>
#include <imessage.h>

// {00020D0B-0000-0000-C000-000000000046}
DEFINE_GUID(CLSID_MailMessage,
0x00020D0B,
0x0000, 0x0000, 0xC0, 0x00, 0x0, 0x00, 0x0, 0x00, 0x00, 0x46);

This is still giving me the linking error  
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
btw, no other files are using these vars.
0
 
LVL 8

Assisted Solution

by:_corey_
_corey_ earned 200 total points
Comment Utility
This is in your header file, right?

I'm not sure anymore because I use the platformSDK includes, but you should include

#include <initguid.h>

ONCE in your .cpp file after

#include <objbase.h>

and get rid of that include in the header you pasted above.

So in the CPP:

#include <objbase.h>
#include <initguid.h>

#include "YourHeader.h"

--
Don't kill me if that's wrong ;)

0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
no, that was in my cpp file, moving now...
0
 
LVL 8

Expert Comment

by:_corey_
Comment Utility
Well, ok if it is your .cpp file then do the order I did with the objbase and initguid headers.

Then have your GUID defs/etc code after that.

As long as that include only called once within a .cpp file somewhere in the project.
0
 
LVL 5

Author Comment

by:jjacksn
Comment Utility
ARG -- found it.  Initguid.h was called in a different header.  I removed it and now my headers work fine.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now