[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

VC++/RPC: Problem using IDL file, Linker errors

Posted on 2012-08-18
7
Medium Priority
?
1,529 Views
Last Modified: 2012-08-23
Hi folks,

Since I've got no suffisient answers on my question about RPC programming yet, I'm trying to find out somthing on my own.

Unfortunately I'm kind of stuck with the IDL spec of the interface I try to use. I've set up a minimalistic test project to show the problem, but couldn' attach it (too much unallowed extensions :( )
Steps to reproduce:

Using Visual Studio 200, I created a simple VC++ console project (no ATL, no MFC) with just an empty tmain() function and the include for Rpc.h

// Test.cpp 
#include "stdafx.h"
#include <rpc.h>
#include "initshutdown_h.h"

int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}

Open in new window


In the project properties - configuration -> linker -> Input -> Additional references I added Rpcrt4.lib.

Into that project I included the file initshutdown.idl from the MS-RSP spec:

typedef struct _REG_UNICODE_STRING {
    unsigned short Length;
    unsigned short MaximumLength;
    [size_is(MaximumLength / 2), length_is((Length) / 2) ] 
        unsigned short* Buffer;
} REG_UNICODE_STRING,
 *PREG_UNICODE_STRING;

[
uuid(894de0c0-0d55-11d3-a322-00c04fa321a1),
    pointer_default( unique ),
version(1.0)
]
interface InitShutdown
//
// Interface body
//
{

//
// Server name, binding handles.
//
typedef [handle] wchar_t* PREGISTRY_SERVER_NAME;

//
// Shutdown APIs.
//

unsigned long
BaseInitiateShutdown(
    [ in, unique ] PREGISTRY_SERVER_NAME ServerName,
    [ in, unique ] PREG_UNICODE_STRING lpMessage,
    [ in ] unsigned long dwTimeout,
    [ in ] unsigned char bForceAppsClosed,
    [ in ] unsigned char bRebootAfterShutdown
    );

unsigned long
BaseAbortShutdown(
    [ in, unique ] PREGISTRY_SERVER_NAME ServerName
    );

unsigned long
BaseInitiateShutdownEx(
    [ in, unique ] PREGISTRY_SERVER_NAME ServerName,
    [ in, unique ] PREG_UNICODE_STRING lpMessage,
    [ in ] unsigned long dwTimeout,
    [ in ] unsigned char bForceAppsClosed,
    [ in ] unsigned char bRebootAfterShutdown,
    [ in ] unsigned long dwReason
    );                      
}

Open in new window


When I started to build the project, the MIDL compiler was called and the three files

initshutdown_h.h
initshutdown_c.c
initshutdown_s.c

were generated. I've included these files in my project and inserted

#include "initshutdown_h.h

Open in new window


into the source file with the tmain() function.

When I rebuilt the project, the compiler went thru flawless, but the linker threw errors - here's the content of the Build log (sorry for the german phrases).

Die temporäre Datei "g:\Test\Test\Debug\RSP00000163206508.rsp" wird erstellt. Inhalt:
[
/char signed /env win32  /tlb "Debug/Test.tlb" /h "initshutdown_h.h"

.\initshutdown.idl
]Erstellen der Befehlszeile "midl.exe @g:\Test\Test\Debug\RSP00000163206508.rsp /nologo"Die temporäre Datei "g:\Test\Test\Debug\RSP00000263206508.rsp" wird erstellt. Inhalt:
[
/Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /c /ZI /TP .\Test.cpp
]Erstellen der Befehlszeile "cl.exe @g:\Test\Test\Debug\RSP00000263206508.rsp /nologo /errorReport:prompt"Die temporäre Datei "g:\Test\Test\Debug\RSP00000363206508.rsp" wird erstellt. Inhalt:
[
/Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /c /ZI /TC .\initshutdown_s.c

.\initshutdown_c.c
]Erstellen der Befehlszeile "cl.exe @g:\Test\Test\Debug\RSP00000363206508.rsp /nologo /errorReport:prompt"Die temporäre Datei "g:\Test\Test\Debug\RSP00000463206508.rsp" wird erstellt. Inhalt:
[
/OUT:"G:\Test\Debug\Test.exe" /INCREMENTAL /MANIFEST /MANIFESTFILE:"Debug\Test.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"G:\Test\Debug\Test.pdb" /SUBSYSTEM:CONSOLE /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Rpcrt4.lib  Rpcns4.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

".\Debug\initshutdown_c.obj"

".\Debug\initshutdown_s.obj"

".\Debug\stdafx.obj"

".\Debug\Test.obj"

".\Debug\Test.exe.embed.manifest.res"
]Erstellen der Befehlszeile "link.exe @g:\Test\Test\Debug\RSP00000463206508.rsp /NOLOGO /ERRORREPORT:PROMPT"

Ausgabefenster
 	 	

Typbibliothek wird erstellt...
Processing .\initshutdown.idl
initshutdown.idl
Kompilieren...
Test.cpp
Kompilieren...
initshutdown_c.c
initshutdown_s.c
Code wird generiert...
Verknüpfen...
initshutdown_c.obj : error LNK2001: Nicht aufgelöstes externes Symbol "_MIDL_user_free@4".
initshutdown_s.obj : error LNK2001: Nicht aufgelöstes externes Symbol "_MIDL_user_free@4".
initshutdown_c.obj : error LNK2001: Nicht aufgelöstes externes Symbol "_MIDL_user_allocate@4".
initshutdown_s.obj : error LNK2001: Nicht aufgelöstes externes Symbol "_MIDL_user_allocate@4".
initshutdown_c.obj : error LNK2001: Nicht aufgelöstes externes Symbol "_PREGISTRY_SERVER_NAME_unbind@8".
initshutdown_c.obj : error LNK2001: Nicht aufgelöstes externes Symbol "_PREGISTRY_SERVER_NAME_bind@4".
G:\Test\Debug\Test.exe : fatal error LNK1120: 4 nicht aufgelöste externe Verweise.

Open in new window


I presume that some library reference is missing, or some crucial project setting is wrong, but I can't figure out what I've missed.

Any hint ?
0
Comment
Question by:frankhelk
  • 4
  • 3
7 Comments
 
LVL 86

Assisted Solution

by:jkr
jkr earned 2000 total points
ID: 38308414
The 1st two missing symbols always need to be defined by the application itself, e.g.

/******************************************************/
/*         MIDL allocate and free                     */
/******************************************************/
 
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
{
    return(malloc(len));
}
 
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
    free(ptr);
}

Open in new window


Regarding the other ones, are you using an .acf file as well?
0
 
LVL 14

Author Comment

by:frankhelk
ID: 38309635
Regarding the other ones, are you using an .acf file as well?

No. I've checked my project files, and there's nothing with .acf.
0
 
LVL 14

Author Comment

by:frankhelk
ID: 38313324
@jkr: The tip removed the _MIDL_... errors as told. Good tip.

 The other 2 errors remain, and no clue how to resolve that ...
0
Industry Leaders: 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 86

Expert Comment

by:jkr
ID: 38313529
The remaining problem seems to be caused by the [handle] attribute of 'PREGISTRY_SERVER_NAME' (sure you need that? It's a plain string after all). See http://msdn.microsoft.com/en-us/library/windows/desktop/aa366846%28v=vs.85%29.aspx ("handle attribute"). The gist is that you basically have to provide these two functions yourself as well.
0
 
LVL 14

Author Comment

by:frankhelk
ID: 38315855
The remaining problem seems to be caused by the [handle] attribute of 'PREGISTRY_SERVER_NAME' (sure you need that? It's a plain string after all).

I'm not completely sure. But the IDL file is taken from the IDL spec of the InitShutdown interface in the MS-RSP specification on MSDN without any changes.  I want to call that interface as built into Windows, therefore I presume that spec as sacrosanct.

If I have to implement those routines by myself, I don't know what to do within 'em.

Unfortunately I havn't seen any implemetation of such calls anywhere - that would help enormusly, wouldn't it ?
0
 
LVL 86

Accepted Solution

by:
jkr earned 2000 total points
ID: 38318426
Well, MS has examples regarding that, see e.g. http://msdn.microsoft.com/en-us/library/windows/desktop/aa374382%28v=vs.85%29.aspx ("Primitive and Custom Binding Handles")

In your case, I guess that would be like

/* The client stub calls this _bind routine at the */
/* beginning of each remote procedure call                */
 
RPC_BINDING_HANDLE __RPC_USER PREGISTRY_SERVER_NAME_bind(
    PREGISTRY_SERVER_NAME prsn)
{
    RPC_BINDING_HANDLE hBinding;
    RPC_STATUS status;
 
status = RpcBindingFromStringBinding(
          pszStringBinding,
          &hBinding);
 
    status = RpcStringFree(&prsn); 
 
    return(hBinding);
}
 
/* The client stub calls this _unbind routine */
/* after each remote procedure call.                            */
void __RPC_USER PREGISTRY_SERVER_NAME_unbind(
    DATA_HANDLE_TYPE dh1, 
    RPC_BINDING_HANDLE h1)
{
    RPC_STATUS status;
    status = RpcBindingFree(&h1); 
    ...
}

Open in new window

0
 
LVL 14

Author Closing Comment

by:frankhelk
ID: 38324641
Application still not doin' what I want it to - get errors reminding me of wrong types and insane pointers.

But I got rid of the linkage errors at lest, which ponted me in the right direction a little bit of the way.

Looks like there's more work to do.
0

Featured Post

Independent Software Vendors: 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!

Question has a verified solution.

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

Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
If you are a mobile app developer and especially develop hybrid mobile apps then these 4 mistakes you must avoid for hybrid app development to be the more genuine app developer.
Six Sigma Control Plans
Starting up a Project

873 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