Click here to Skip to main content
Click here to Skip to main content

Introduction to RPC - Part 1

By , 22 Dec 2012
 

Hello RPC World!

Contents

Introduction

I have worked with client-server applications for a couple of years now, all of these applications use RPC as the layer of communication between the client and the server. I found it strange that no real article existed on this matter here on CodeProject, so I decided to write one of my own to spread my knowledge on this matter.

The matter is, on the other hand, a bit big so I will split it into several articles of different levels of difficulty. This first one is at beginner level.

IDL, RPC and you

In order to use RPC, you need to have some knowledge about IDL, but don't you worry, this article will help you.

Interface Definition Language (IDL)

IDL stands for Interface Definition Language and it's a language for defining interfaces (no kidding). Writing an IDL file is somewhat like writing a C header file with some additional keywords and constructs. IDL is an attributed programming language and thus it can describe parameters, functions and interfaces in more detail than C.

Remote Procedure Call (RPC)

Remote Procedure Call (RPC) defines a powerful technology for creating distributed client/server programs. The RPC runtime libraries manage most of the details relating to network protocols and communication. This enables you to focus on the details of the application rather than the details of the network.

With RPC a client can connect to a server running on another platform. For example: In theory the server could be written for Linux and the client could be written for Win32.  The reality is somewhat more complicated.

Are you scared yet?

If you're not scared, I think it's good time for an example.

The standalone application

This standalone application will not use RPC and it is a simple HelloWorld application that we later will transform into a RPC client/server application.

Hello Lonely World!

// File Standalone.cpp
#include <iostream>

// Future server function.
void Output(const char* szOutput)
{
   std::cout << szOutput << std::endl;
}

int main()
{
   // Future client call.
   Output("Hello Lonely World!");
}

I don't think anyone can think of anything to say about the above application. It outputs the string "Hello Lonely World!" to the standard output.

The IDL file

It is time to define our interface in IDL.

Hello IDL World! 

// File Example1.idl
[
   // A unique identifier that distinguishes this
   // interface from other interfaces.
   uuid(00000001-EAF3-4A7A-A0F2-BCE4C30DA77E),

   // This is version 1.0 of this interface.
   version(1.0),

   // This interface will use an implicit binding
   // handle named hExample1Binding.
   implicit_handle(handle_t hExample1Binding)
]
interface Example1 // The interface is named Example1
{
   // A function that takes a zero-terminated string.
   void Output(
      [in, string] const char* szOutput);
}

Here you see the attribute programming used by IDL. The above example defines an interface with an universally unique identifier (uuid) and version (version) that is named Example1. The Example1 interface defines one function named Output that takes a const char* argument named szOutput as input (in) that is zero-terminated (string).

The implicit_handle attribute for the interface will be discussed later, leave it there for now.

What's next?

In order to use the IDL in our application we need to run it through a compiler (midl.exe) that will translate the IDL to a client proxy and a server stub in C. The proxy/stub will later be compiled using your favorite compiler (cl.exe in my case).

How files are generated with midl.exe

How may I serve you?

It's time to take the generated files and put them to use in our server application.

Hello Server World!

// File Example1Server.cpp
#include <iostream>
#include "Example1.h"

// Server function.
void Output(const char* szOutput)
{
   std::cout << szOutput << std::endl;
}

// Naive security callback.
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void* /*pBindingHandle*/)
{
    return RPC_S_OK; // Always allow anyone.
}

int main()
{
   RPC_STATUS status;

   // Uses the protocol combined with the endpoint for receiving
   // remote procedure calls.
   status = RpcServerUseProtseqEp(
      reinterpret_cast<unsigned char*>("ncacn_ip_tcp"), // Use TCP/IP protocol.
      RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // Backlog queue length for TCP/IP.
      reinterpret_cast<unsigned char*>("4747"), // TCP/IP port to use.
      NULL); // No security.

   if (status)
      exit(status);

   // Registers the Example1 interface.
   status = RpcServerRegisterIf2(
      Example1_v1_0_s_ifspec, // Interface to register.
      NULL, // Use the MIDL generated entry-point vector.
      NULL, // Use the MIDL generated entry-point vector.
      RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH, // Forces use of security callback.
      RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Use default number of concurrent calls.
      (unsigned)-1, // Infinite max size of incoming data blocks.
      SecurityCallback); // Naive security callback.

   if (status)
      exit(status);

   // Start to listen for remote procedure
   // calls for all registered interfaces.
   // This call will not return until
   // RpcMgmtStopServerListening is called.
   status = RpcServerListen(
     1, // Recommended minimum number of threads.
     RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Recommended maximum number of threads.
     FALSE); // Start listening now.

   if (status)
      exit(status);
}

// Memory allocation function for RPC.
// The runtime uses these two functions for allocating/deallocating
// enough memory to pass the string to the server.
void* __RPC_USER midl_user_allocate(size_t size)
{
    return malloc(size);
}

// Memory deallocation function for RPC.
void __RPC_USER midl_user_free(void* p)
{
    free(p);
}

This is a bit different from the standalone application, but not much. It has some initialization code for registering the interface but the Output function remains the same.

Let me be your client

Time has come to write our client application that will connect to the server.

Hello Client World!

// File Example1Client.cpp
#include <iostream>
#include "Example1.h"

int main()
{
   RPC_STATUS status;
   unsigned char* szStringBinding = NULL;

   // Creates a string binding handle.
   // This function is nothing more than a printf.
   // Connection is not done here.
   status = RpcStringBindingCompose(
      NULL, // UUID to bind to.
      reinterpret_cast<unsigned char*>("ncacn_ip_tcp"), // Use TCP/IP protocol.
      reinterpret_cast<unsigned char*>("localhost"), // TCP/IP network address to use.
      reinterpret_cast<unsigned char*>("4747"), // TCP/IP port to use.
      NULL, // Protocol dependent network options to use.
      &szStringBinding); // String binding output.

   if (status)
      exit(status);

   // Validates the format of the string binding handle and converts
   // it to a binding handle.
   // Connection is not done here either.
   status = RpcBindingFromStringBinding(
      szStringBinding, // The string binding to validate.
      &hExample1Binding); // Put the result in the implicit binding
                          // handle defined in the IDL file.

   if (status)
      exit(status);

   RpcTryExcept
   {
      // Calls the RPC function. The hExample1Binding binding handle
      // is used implicitly.
      // Connection is done here.
      Output("Hello RPC World!");
   }
   RpcExcept(1)
   {
      std::cerr << "Runtime reported exception " << RpcExceptionCode()
                << std::endl;
   }
   RpcEndExcept

   // Free the memory allocated by a string.
   status = RpcStringFree(
      &szStringBinding); // String to be freed.

   if (status)
      exit(status);

   // Releases binding handle resources and disconnects from the server.
   status = RpcBindingFree(
      &hExample1Binding); // Frees the implicit binding handle defined in the IDL file.

   if (status)
      exit(status);
}

// Memory allocation function for RPC.
// The runtime uses these two functions for allocating/deallocating
// enough memory to pass the string to the server.
void* __RPC_USER midl_user_allocate(size_t size)
{
    return malloc(size);
}

// Memory deallocation function for RPC.
void __RPC_USER midl_user_free(void* p)
{
    free(p);
}

Other than connecting to the server and some cleanup, the actual call is the same, except that I've changed the string to be outputted.

Putting it all together

First we need to compile the IDL file to get the client proxy, the server stub and the common header file. The proxy and the stub is compiled, as are the client and server implementation. We link the two applications and run them. If everything works, we can be really glad as we have done our first RPC client/server application.

Putting it all together

Appendix

This section describes some techniques useful when writing RPC applications.

Debugging and RPC

If you get into trouble when debugging and the problem seem to be in a MIDL generated file, the real problem will most likely be in the client or in the server. I have sometime run into problems with pointers, but in a follow up article I will describe these things more thoroughly.

Implicit and explicit handles

When using RPC, the binding handles can be implicit (as in the example in this article) or explicit. I always use explicit handles as I sometime are connected to multiple servers, and that does not work with the implicit handle. To use explicit handles, you'll have to change the IDL file, the server and the client:

// File Example1Explicit.idl
[
   // A unique identifier that distinguishes this
   // interface from other interfaces.
   uuid(00000002-EAF3-4A7A-A0F2-BCE4C30DA77E),

   // This is version 1.0 of this interface.
   version(1.0),

   // This interface will use explicit binding handle.
   explicit_handle
]
interface Example1Explicit // The interface is named Example1Explicit
{
   // A function that takes a binding handle and a zero-terminated string.
   void Output(
      [in] handle_t hBinding,
      [in, string] const char* szOutput);
}
// File Example1ExplicitServer.cpp
#include <iostream>
#include "Example1Explicit.h"

// Server function.
void Output(handle_t hBinding, const char* szOutput)
{
   std::cout << szOutput << std::endl;
}

// main - same as before.
// File Example1ExplicitClient.cpp
#include "Example1Explicit.h"

int main()
{
   // Call to RpcStringBindingCompose - same as before.

   handle_t hExample1ExplicitBinding = NULL;

   // Validates the format of the string binding handle and converts
   // it to a binding handle.
   // Connection is not done here either.
   status = RpcBindingFromStringBinding(
      szStringBinding, // The string binding to validate.
      &hExample1ExplicitBinding); // Put the result in the explicit binding handle.

   if (status)
      exit(status);

   RpcTryExcept
   {
      // Calls the RPC function. The hExample1ExplicitBinding binding handle
      // is used explicitly.
      // Connection is done here.
      Output(hExample1ExplicitBinding, "Hello RPC World!");
   }
   RpcExcept(1)
   {
      std::cerr << "Runtime reported exception " << RpcExceptionCode()
                << std::endl;
   }
   RpcEndExcept

   // Call to RpcStringFree - same as before.

   // Releases binding handle resources and disconnects from the server.
   status = RpcBindingFree(
      &hExample1ExplicitBinding); // Frees the binding handle.

   if (status)
      exit(status);
}

There are also something called auto_handle, but I've never ever used that. It somehow takes care about connecting to the server automatically. 

Application Configuration File (ACF)

In this example I used implicit_handle and explicit_handle directly in the IDL file, but that is a Microsoft extension. One usually need to use a separate Application Configuration File that contain these. The sample code in the zip file does use a separate ACF file, but I felt like, writing that in the article would only confuse you even more.

Don't fiddle with the generated files

You should not fiddle with the generated files to make them compile, they are (should be) correct. Check the switches to midl.exe if you feel that they are incorrect. When compiling them you may on the other hand get a lot of warnings, but when lowering the warning level to 2, they are silent.

Shutting down the server

The example server will run until it is shut down by closing it somehow. That ain't the best way of doing it, another better way is to call the RpcMgmtStopServerListening function. But how would you call it? You could add another function in the interface (perhaps named Shutdown?) that will call RpcMgmtStopServerListening or you could create another thread in the server before calling RpcServerListen that will call RpcMgmtStopServerListening after a minute or so. More on this in another article.

Conclusion

This is only the entry door to the world of RPC and client/server applications. If you step through and read my other (future) articles on this matter, you'll be fully prepared for the world at hand.

This was my first ever article on CodeProject, I hope you enjoyed reading it as much as I enjoyed writing it.

References

Revision history 

  • 2012-12-22:
    • Finally updated to work with Visual Studio 2010 and fixed security callback.
  • 2003-08-25:
    • Updated demo and source.  
    • Changed from Named Pipe to TCP/IP (suggestion by Hector Santos).  
  • 2003-08-23:
    • Original article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Anders Dalvander
Software Developer (Senior) Umetrics
Sweden Sweden
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionUsing ncalrpc protocal in windows 7/Vistamemberamilamad14 Oct '11 - 23:23 
Hi,
I`m new to rpc programming. My question is how can we use ncalrpc protocol for communicating in windows 7/Vista. I have read somewhere that in windows Vista ncalrpc protocol has been removed. Plz help. Any reference to a web site will be ok.
 
Thanx
GeneralMy vote of 4memberVEMS12 Sep '11 - 3:21 
Thanks ... looking forward to reading the additional articles.
SuggestionGetting error when linking in command promptmemberselvamellumalai4 Aug '11 - 2:28 
Its getting error that _output is unresolved external symbol.Please suggest me something to correct this.
GeneralRe: Getting error when linking in command promptmemberselvamellumalai4 Aug '11 - 2:37 
Hi Guys i resolved this.But getting Runtime exception in client
SuggestionRe: Getting error when linking in command promptmembergeorgethomas_v9 May '12 - 19:40 
Check this http://blogs.msdn.com/b/distributedservices/archive/2008/11/12/troubleshooting-msdtc-issues-with-the-dtcping-tool.aspx[^]
I was getting run time exception in client and was solved using the registry modification mentioned in section "ERROR MESSAGE 5 - ERROR MESSAGE 5 - Access is Denied" in this link
Questionwhen I called RpcMgmtWaitServerListen , it was blockedmemberhost2828 Jun '11 - 3:04 
Hi Anders:
I am searching a resolution to close RPC server.
Now, I created 2 thread.
in thread A, RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE),and it works well.
in thread B, when condition matches, RpcMgmtStopServerListening(NULL) called.
When RpcMgmtWaitServerListen was called, I found it suspend often.
someone said it is RpcMgmtWaitServerListen bug.
Could you give me some advice?
thank you.
AnswerRe: when I called RpcMgmtWaitServerListen , it was blockedmemberAnders Dalvander28 Jun '11 - 6:29 
The RpcMgmtWaitServerListen function should block, according to the documentation[^]:
The RpcMgmtWaitServerListen function returns after the server application calls RpcMgmtStopServerListening and all active remote procedure calls complete, or after a fatal error occurs in the RPC run-time library.

GeneralRe: when I called RpcMgmtWaitServerListen , it was blockedmemberhost2828 Jun '11 - 15:17 
thank for your reply.
But I confirmed no one client call any RPC.
QuestionMore about APIsmemberDebojyoti Majumder15 May '11 - 20:43 
Well you have demonstrated a very basic RPC program.
The article would have been better if you explained the API's in more detail.
GeneralWrong server [modified]memberMember 777565220 Apr '11 - 3:20 
I got Runtime reported exception 5 when i run server and client. What should i do for that

modified on Wednesday, April 20, 2011 9:43 AM

GeneralRe: Wrong servermemberAnders Dalvander20 Apr '11 - 4:20 
See this[^].
GeneralWrong servermemberMember 777565220 Apr '11 - 3:20 
The server can't wait for client request. Immediately closed the server when i am run the Example1Server
GeneralproblemmemberJameskerry31 Mar '11 - 1:43 
Hello,
 
strange problem today, ip conflict on a workgroup where all machines have fixed ip's, internet and LAN both suddenly go very very slow when the lab (15 machines) were booted, tracked it down to one of the machines in the lab having the same ip as one in the office, but no warnings or messages of any kind came up like happens with XP.... is this normal for 7 ? and can the warning actually be turned off/on? or is it a glitch or corrupt file.
 
sys is win 7 enterprise clean install SP1 all updates loaded, Netgear ADSL2+ modem and routers with a lot of virtual shared drives (over 20) on the 2nd machine that had the same IP addy.
 

 
Product Warnings:
"Fragile. Do not drop." -- Posted on a Boeing 757.
 
dissertation help thesis help assignment help
GeneralVisual Studio 2010 - errormemberdemioz15 May '10 - 10:59 
Converted this solution to VS2010 and when I build the Example1 project I get this error:
 
LINK : error LNK2001: unresolved external symbol _mainCRTStartup
GeneralRe: Visual Studio 2010 - errormemberpant.ashish26 May '10 - 7:25 
I too get the same error. anybody please do help
GeneralRe: Visual Studio 2010 - errormemberAnders Dalvander27 May '10 - 7:09 
Select Example1 project in Solution Explorer.
Open the menu Project > Properties.
Go to Configuration Properties > General.
Set Configuration Type to Utility.
Click OK.
 
Repeat for Example1Explicit.
 
Rebuild solution.
 
You also need to change the RpcServerRegisterIf call to RpcServerRegisterIfEx in the server:
   status = RpcServerRegisterIfEx(
      Example1Explicit_v1_0_s_ifspec, // Interface to register.
      NULL, // Use the MIDL generated entry-point vector.
      NULL, // Use the MIDL generated entry-point vector.
      RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH,
      RPC_C_LISTEN_MAX_CALLS_DEFAULT,
      NULL);

GeneralRe: Visual Studio 2010 - errormemberdemioz28 May '10 - 5:29 
thanks, now it works.
GeneralRe: Visual Studio 2010 - errormemberJameskerry17 Jun '10 - 22:14 
Hi,
Thanks Anders Dalvander to solve our problems..

Generalerror C2664membermohjak23 Apr '10 - 2:03 
error C2664: 'RpcServerUseProtseqEpW' : cannot convert parameter 1 from 'unsigned char *' to 'RPC_WSTR'
 
how t fix this problem?
GeneralRe: error C2664memberAnders Dalvander23 Apr '10 - 2:12 
Use wide strings instead of narrow strings:
 
RpcServerUseProtseqEp(L"ncacn_ip_tcp", RPC_C_PROTSEQ_MAX_REQS_DEFAULT, L"4747", NULL);
 
or:
 
RpcServerUseProtseqEp(_T("ncacn_ip_tcp"), RPC_C_PROTSEQ_MAX_REQS_DEFAULT, _T("4747"), NULL);

GeneralRe: error C2664membermohjak23 Apr '10 - 2:56 
for your sollution it returns this for L:
Error	1	error C2664: 'RpcServerUseProtseqEpW' : cannot convert parameter 1 from 'const wchar_t [13]' to 'RPC_WSTR'
 
and for _T:
Error	1	error C3861: '_T': identifier not found
 
I wrote
 
RpcServerUseProtseqEp((RPC_WSTR)"ncacn_ip_tcp",RPC_C_PROTSEQ_MAX_REQS_DEFAULT,(RPC_WSTR)"4747",NULL); 
 
for compile time is good
but does it affect run time?
another question:
how to run client and server because i face a problem runnung them
thanks a lot, and have a nice day.
GeneralRe: error C2664memberAnders Dalvander23 Apr '10 - 3:20 
Sorry about that, use the L-version and a reinterpret_cast:
 
RpcServerUseProtseqEp(reinterpret_cast<RPC_WSTR>(L"ncacn_ip_tcp"), RPC_C_PROTSEQ_MAX_REQS_DEFAULT, reinterpret_cast<RPC_WSTR>(L"4747"), NULL);
 
I don't know what other problem you are referring to. You need to explain better.
GeneralRe: error C2664 [modified]membermohjak23 Apr '10 - 3:52 
thanks a lot well done
 
to be more specific in my further questions
my server is work an wait for requests
but client didn't work when I click it, it instantly disappeared
this what I see on:
 
when I start client with out server I got:
Runtime reported exception 5
 
when I started client after server:
Runtime reported exception 1722
 
what was my fault
 
thanks more and more Smile | :) ...

modified on Friday, April 23, 2010 10:05 AM

QuestionRPC interface upgrade, help pls!memberNatik2 Nov '09 - 23:12 
The RPC interface working fine on windows up to XP.
I run my RPC interface on Windows Vista/Windows 7
it fails with error 1702 - binding handle is invalid.
How to resolve this problem, help pls!!!
AnswerRe: RPC interface upgrade, help pls!memberhenry hanqing17 Jul '11 - 19:34 
I got the some problem...anyone can help ?
GeneralOverlapped I/O operation is in progress.memberSaransankar29 Apr '09 - 23:59 
i am getting this error while debugging the server part. can you please help me to get rid of this?
(error code: 997) Cry | :((
 
saravanan

Generalbuild in visual studio 2005 team editionmembernetcreator8 Apr '09 - 3:17 
by efford
the example all build ok.
but when i run on the local machine with command line, there always errors on client,and no reponse on server:
Runtime reported exception 5
my os is winxp sp3,win32
btw:
i use the macro define _WIN32_WINNT=0X500 to resolve the win2000 problem
 
thank you.
GeneralCompiling in Visual Studio 2003 [modified]memberCodtor19 Mar '09 - 8:39 
There are several errors that might appear, here's how to solve them:
 
Error:
ACF attributes in the IDL file need the /app_config switch : [implicit_handle]
Solution:
Right-click Example1.idl, Properties > Configuration Properties > MIDL > Command Line, and add: /app_config
 
Error:
unresolved external symbol _Example1_v1_0_s_ifspec and others
Solution:
Go to project Properties > Configuration Properties > Linker > Input, and add: rpcrt4.lib
Add #include "Example1_h.h" to your Example1Server.cpp file
Add Example1_s.c and Example1_h.h to your project
 
Error:
You need a Windows 2000 or later to run this stub because it uses these features
Solution:
Go to project Properties > Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions, and modify to: WIN32;_WIN32_WINNT=0x0500;_DEBUG;_CONSOLE
 
Error:
unresolved external symbol _Output
Solution:
modify void Output(const char* szOutput) to void Output(const unsigned char* szOutput) in your Example1Server.cpp file
 
Everything should compile fine
 
Nothing is impossible. No, really.
modified on Thursday, March 19, 2009 2:50 PM

GeneralRe: Compiling in Visual Studio 2003memberAnders Dalvander19 Mar '09 - 22:00 
Great work!
GeneralCompile the client code on Linuxmemberalterego_12315 Mar '09 - 23:44 
What all changes are required to make the client work on Linux (if possible)? Can we create a server on Windows and Client on Linux?
GeneralRe: Compile the client code on LinuxmemberAnders Dalvander16 Mar '09 - 0:03 
First you need a DCE RPC library for Linux. Perhaps one of these:
http://freedce.sourceforge.net/[^]
http://www.opengroup.org/dce/[^]
http://www.netwaysglobal.com/DCE/[^]
 
Secondly you need to replace function calls with the DCE RPC counterparts (lower_case instead of Win32 PascalCase).
GeneralRe: Compile the client code on Linuxmemberalterego_12316 Mar '09 - 1:55 
Can you help me write the above client on linux which connects to Windows Server?
GeneralRe: Compile the client code on LinuxmemberAnders Dalvander16 Mar '09 - 1:58 
Short answer: No.
Long answer: No, not unless I get paid.
GeneralRe: Compile the client code on Linuxmemberalterego_12316 Mar '09 - 19:05 
How much will it cost??
GeneralRe: Compile the client code on LinuxmemberAnders Dalvander16 Mar '09 - 23:10 
No really, I don't want to do it.
Generalabout idlmemberrgeorge55555555514 Jan '09 - 21:20 
Can i declare multiple interface in one IDL file?
GeneralAccess denied Error 5membersuiram4013 Dec '08 - 10:32 
WIN XP SP 2
 
I just compiler fine adding midl.exe /app_config extra parameter.
As soon I run it I get Exception ACCESS DENIED (WIN ERROR 5)
I've tried several RCP initialization and did not help.
I also downloaded from msn site DCOM sample (ATLDraw)
and I is much worst It crashes in system calls.
I dowloaded several remote over DCOM and RPC and
I got pretty much same errors error ACCESS DENIED, CLASS NOT REGISTERS, RPC SERVER UNAVALIABLE.
 
I think microsoft is going retard... and will die pretty soon.
AnswerRe: Access denied Error 5memberAlezis7 Apr '09 - 11:27 
I have had the same problem. here it is solved:
 
http://www.emergin.com/knowledgebase/WebHelp/RPC_Error_-5.htm
GeneralRe: Access denied Error 5memberfgobber3 Sep '09 - 3:33 
I have the same error with an RPC server running on Windows XP Sp2, the application is using security authentication and the same application it's running well on Windows 2003 Sp2.
 
This is the code:
 
Server Program
 
status = RpcServerUseProtseqEp("ncacn_ip_tcp",20,"9491",NULL);
status = RpcServerRegisterIf(hello_ServerIfHandle,NULL,NULL);
status = RpcServerRegisterAuthInfo(NULL,RPC_C_AUTHN_GSS_NEGOTIATE,NULL,NULL);
status = RpcServerListen(1,20,FALSE);
 
Client Program
 
This procedure create a SEC_WINNT_AUTH_IDENTITY with credential embedded:
 
SEC_WINNT_AUTH_IDENTITY *RpcAuthenticationWithUser (LPCTSTR szUsername,LPCTSTR szDomain,LPCTSTR szPassword)
{
DWORD csSize = sizeof (SEC_WINNT_AUTH_IDENTITY) ;
SEC_WINNT_AUTH_IDENTITY *lpsecCred ;
LPTSTR szCred ;
 
csSize += strlen(szUsername)+1+strlen(szPassword)+1+ strlen(szDomain)+1 ;
lpsecCred = HeapAlloc (GetProcessHeap(),HEAP_ZERO_MEMORY,csSize);
szCred = ((unsigned char *)lpsecCred)+sizeof(SEC_WINNT_AUTH_IDENTITY)) ;
lpsecCred->User = szCred ;
strcpy(szCred,szUsername) ;
lpsecCred->UserLength = strlen(szUsername) ;
szCred += lpsecCred->UserLength + 1 ;
lpsecCred->Password = szCred ;
strcpy(szCred,szPassword) ;
lpsecCred->PasswordLength = strlen(szPassword) ;
szCred += lpsecCred->PasswordLength + 1 ;
lpsecCred->Domain = szCred ;
strcpy(szCred,szDomain) ;
lpsecCred->DomainLength = strlen(szDomain) ;
lpsecCred->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI ;
return lpsecCred ;
}
 
unsigned char * pszStringBinding = NULL;
SEC_WINNT_AUTH_IDENTITY *lpsecCredentials ;
 
status = RpcStringBindingCompose (NULL,"ncacn_ip_tcp","RPCServerName","9491",NULL&pszStringBinding);
 
status = RpcBindingFromStringBinding (pszStringBinding,&hello_IfHandle);
 
lpsecCredentials = RpcAuthenticationWithUser ("Administrator","RPCServerName","password") ;
 
status = RpcBindingSetAuthInfo (hello_IfHandle,NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,RPC_C_AUTHN_GSS_NEGOTIATE,(RPC_AUTH_IDENTITY_HANDLE)lpsecCredentials,RPC_C_AUTHN_GSS_NEGOTIATE);
 
RpcTryExcept {
HelloProc(pszString); // make call with user message
printf("Calling the remote procedure 'Shutdown'\n");
Shutdown(); // shut down the server side
}
RpcExcept(1) {
ulCode = RpcExceptionCode();
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
}
RpcEndExcept
 
This application is working fine with the RPC server application running on a Windows 2003 R2 Sp2 system, but when the RPC server application is running on a Windows XP Sp2 it’s get an exception “Access Denied”.
The same application, when change the code in this way:
 
status = RpcBindingSetAuthInfo (hello_IfHandle,NULL, RPC_C_AUTHN_LEVEL_CONNECT,RPC_C_AUTHN_GSS_NEGOTIATE,(RPC_AUTH_IDENTITY_HANDLE)lpsecCredentials,RPC_C_AUTHN_GSS_NEGOTIATE);

run on Windows 2003 and also on Windows XP Sp2.
The data capture of the network monitor, shows the with the option RPC_C_AUTHN_LEVEL_PKT_PRIVACY the data are crypted and the the option RPC_C_AUTHN_LEVEL_CONNECT the data are in clear.
 

Any help would be appreciated
AnswerRe: Access denied Error 5memberPeter Husemann17 Sep '09 - 23:55 
Use RpcServerRegisterIfEx instead of RpcServerRegisterIf.
 
// Check interface Access
// ----------------------
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*Interface*/, void* /*BindingHandle*/)
{
    return RPC_S_OK;	// always allow 
}
 
// main program
// ------------
int main()
{
    // ....

																                             // make interfave available
    status = RpcServerRegisterIfEx(....,             // - interface name
		NULL,			             // - no UUID
                NULL,			             // - use MIDL entry point
		RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH, // - security
		RPC_C_LISTEN_MAX_CALLS_DEFAULT,	     // - max calls auto-listen
		SecurityCallback);		     // - function pointer

    // ....
}

GeneralRe: Access denied Error 5memberjoyjjjz6 Jan '10 - 15:18 
it works. thank you very much!
QuestionNeed Help for Exchange RPCmembermanish.patel6 Dec '08 - 0:03 
Hello,
 
I am developing RPC Server as like Exchange server.
I am able to do communication between my custom server and client.
 
But when i use outlook 2007 to connect with my custom rpc server, it is not allowing to connect with my server.
 
I have used idl from Microsoft Open specification of protocol.
My os is Windows XP SP2 64 bit.
 
Do you have any idea regarding adding my server interface to end point mapper database.
 
Because outlook connect to endpoint mapper first to see Exchange is running or not.
 

Regards,
 
Manish Patel.
B.E. - Information Technology.


AnswerRe: Need Help for Exchange RPCmemberAnders Dalvander7 Dec '08 - 20:14 
The endpoint and interface should be registered with RpcServerUseProtseqEp, RpcEpRegister and RpcServerRegisterIf2 (or similar).
 
Perhaps you haven't set the security authentication and authorization correctly.
GeneralRPC with VisualC++ 6.0membersunilkumar.d9 Aug '08 - 18:32 
Hi Anders,
I have to work on RPC in my new project.
Can I use your code and compile in VC6?
how to copile idl file in vc6.0.
Please help me as I am very new to this concept.
 
Regards,
Sunil Kumar

GeneralC++ Builder 2007memberCaetano.n.a30 Jul '08 - 7:38 
Hello. This example (IDL file) is compatible with c++ builder 2007. I don't use Visual Studio. Thanks
QuestionCan not Communicate if Example1Server.exe and Example1Client.exe locate on different machinesmemberlianyanzexjtu23 Jun '08 - 23:08 
Hi, My System is Win XP and SP2. when I put the ExampleServer.exe and Example1Client.exe on the same machine, they can communicate successfully. But if they locate on different machines ,they can not communicate. and the Example1Client.exe prompt the errror "Runtime reported exception 1722";
AnswerRe: Can not Communicate if Example1Server.exe and Example1Client.exe locate on different machinesmemberAnders Dalvander24 Jun '08 - 1:56 
Do you have a firewall?
AnswerRe: Can not Communicate if Example1Server.exe and Example1Client.exe locate on different machinesmemberlianyanzexjtu24 Jun '08 - 15:26 
I closed all of firewalls, but it can not work yet.
AnswerRe: Can not Communicate if Example1Server.exe and Example1Client.exe locate on different machinesmemberkun pat29 Jul '08 - 12:03 
I have the same problem with win xp sp3. Although the programs work fine on the same computer.
GeneralRe: Can not Communicate if Example1Server.exe and Example1Client.exe locate on different machinesmemberkun pat1 Aug '08 - 11:51 
Silly problem. I didn't change the ip address of the client code to the machine with the server.
 
change
reinterpret_cast<unsigned char*>("localhost"),
in the RpcStringBindingCompose function to
reinterpret_cast<unsigned char*>("00.11.22.33"),
where 00.11.22.33 is the ip address of the other machine.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 22 Dec 2012
Article Copyright 2003 by Anders Dalvander
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid