Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

URGENT:  Linking resolution problem

Posted on 2004-04-27
20
Medium Priority
?
1,289 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
  • 5
  • +2
20 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 10935908
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
ID: 10936254
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 41

Expert Comment

by:Kyle Abrahams
ID: 10936414
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 1200 total points
ID: 10936896
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_
ID: 10940291
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
ID: 10940763
>> 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_
ID: 10941142
itsmeandnobodyelse:

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

Expert Comment

by:itsmeandnobodyelse
ID: 10941571
>> 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_
ID: 10941644
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
ID: 10946922
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
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10947040
>> 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
ID: 10950406
I see that now.  Thanks.  Out of curiosity, why are these headers structured like this?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10951370
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_
ID: 10951975
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
ID: 11052772
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
ID: 11053320
btw, no other files are using these vars.
0
 
LVL 8

Assisted Solution

by:_corey_
_corey_ earned 800 total points
ID: 11053363
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
ID: 11054172
no, that was in my cpp file, moving now...
0
 
LVL 8

Expert Comment

by:_corey_
ID: 11054198
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
ID: 11054357
ARG -- found it.  Initguid.h was called in a different header.  I removed it and now my headers work fine.
0

Featured Post

Tech or Treat!

Submit an article about your scariest tech experience—and the solution—and you’ll be automatically entered to win one of 4 fantastic tech gadgets.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

636 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