Solved

RPC server in NT... How to pass callback from client????

Posted on 2002-06-18
20
870 Views
Last Modified: 2013-12-23
Hello,

I'd like to know how to code a function in my IDL so that
a client can pass a callback function pointer to the server?
Is there an example of this kind of stuff available???

All I have so far is RPC_IF_CALLBACK_FN but I have yet to
find any example of how to use it? I don't know if this
is the kind of stuff I should use?

I need something like:
error_status_t ShutDown(
              [size_is(PwdLength), in ] byte Password[],
              [in] unsigned long PwdLength,
---------->>>    [in] RPC_IF_CALLBACK_FN aClientFunctionPtr
             );

Any hints will be appreciated ;-)

thanks
0
Comment
Question by:aquila98
  • 10
  • 9
20 Comments
 
LVL 63

Expert Comment

by:SysExpert
ID: 7090349
I would post this is the programming section of EE, rather than here.

You can post just a link back to here so that you get twice the bang for your points.

I hope this helps !
0
 
LVL 86

Expert Comment

by:jkr
ID: 7090683
I did something similar a while ago, but I defined the function in the interface itself (which is IMHO better, as you are free to provide whatever function signature you want):

[ uuid (<removed>),
  version(1.0),
  pointer_default(unique)
]
interface TheServer
{

error_status_t ShutDown(
             [size_is(PwdLength), in ] byte Password[],
             [in] unsigned long PwdLength
            );

[ callback]
unsigned int    ShutDownCallBack  ( );
};

Anyway, you will have to declare the callback in the interface also, as MIDL needs to generate stubs for that function - or you are willing to use 'RpcServerRegisterIfEx()' (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/pr-func2_9prs.asp)
0
 
LVL 86

Expert Comment

by:jkr
ID: 7090707
BTW - if you still want to pursue the 'RPC_IF_CALLBACK_FN' path, see http://www.ntdev.org/archive/ntdev0001/msg0272.html
0
Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

 
LVL 2

Author Comment

by:aquila98
ID: 7090839
And just how is the client suposed to implement ShutDownCallBack???

The server will do something like this:
error_status_t ShutDown(
            [size_is(PwdLength), in ] byte Password[],
            [in] unsigned long PwdLength
           )
{ ...
    ShutDownCallBack();
}

while the client is expected to do this:
 myserver->ShutDown();
...

???
0
 
LVL 86

Expert Comment

by:jkr
ID: 7091066
In the above example:

int     ShutDownCallBack (     void)
{
     // ...

     return     (     0);
}

MIDL will generate the code that calls the callback implementation.
0
 
LVL 86

Accepted Solution

by:
jkr earned 200 total points
ID: 7091069
BTW, here is the (generated) stub code:

void __RPC_STUB
TheServer_ShutDownCallback(
    PRPC_MESSAGE _pRpcMessage )
{
    int _RetVal;
    MIDL_STUB_MESSAGE _StubMsg;
    RPC_STATUS _Status;

    ((void)(_Status));
    NdrServerInitializeNew(
                          _pRpcMessage,
                          &_StubMsg,
                          &IRLicSrv_StubDesc);

    RpcTryFinally
        {
        RpcTryExcept
            {
            if(_StubMsg.Buffer > _StubMsg.BufferEnd)
                {
                RpcRaiseException(RPC_X_BAD_STUB_DATA);
                }
            }
        RpcExcept( RPC_BAD_STUB_DATA_EXCEPTION_FILTER )
            {
            RpcRaiseException(RPC_X_BAD_STUB_DATA);
            }
        RpcEndExcept

        _RetVal = ShutDownCallback();

        _StubMsg.BufferLength = 4U;
        _pRpcMessage->BufferLength = _StubMsg.BufferLength;

        _Status = I_RpcGetBuffer( _pRpcMessage );
        if ( _Status )
            RpcRaiseException( _Status );

        _StubMsg.Buffer = (unsigned char __RPC_FAR *) _pRpcMessage->Buffer;

        *(( int __RPC_FAR * )_StubMsg.Buffer)++ = _RetVal;

        }
    RpcFinally
        {
        }
    RpcEndFinally
    _pRpcMessage->BufferLength =
        (unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);

}
0
 
LVL 2

Author Comment

by:aquila98
ID: 7092330
thanks it works ;-)
0
 
LVL 2

Author Comment

by:aquila98
ID: 7097100
I should say It compiled :)

Now I have it running and the client does NOT receive any
thing when the server executes a callback function. There
is NO error on the server side, just that the client's side
callback function never gets executed...

Should I do anything special during client binding to
say that I can get a rpc from the server? My protocol is
tcp_ip by the way.

???
0
 
LVL 86

Expert Comment

by:jkr
ID: 7115479
Sorry, I didn't ever get a notif for your last comment (see also http://www.experts-exchange.com/jsp/qManageQuestion.jsp?qid=2030914999 - I'll check about the bindings...
0
 
LVL 2

Author Comment

by:aquila98
ID: 7124684
Thanks,

I posted an another question in case you wish to get 100 points more ;-)

Strange, I get no compilation error, no runtime errors
and yet the client's function never gets executed, but the
server does call them!

???
0
 
LVL 86

Expert Comment

by:jkr
ID: 7145001
Iiih, yikes, sorry - just saw this one by chance by going through old Qs - do you still have that problem?
0
 
LVL 2

Author Comment

by:aquila98
ID: 7145788
yes, for some reason there are no errors during compile or run time but whenever the server calls a callback function the client's code never gets executed!

Should I put the callback function in the acf like the other "regular" rpc call? How can I trace within the stub to see where the error occurs? Any other way to do this? I am not familar with RPC_IF_CALLBACK_FN's way. Do you have a working example by chance???

thanks
0
 
LVL 86

Expert Comment

by:jkr
ID: 7147863
>>Do you have a working example by chance???

I have a "production" license server that I wrote which uses the same way to detect whether the clients are "alive" by implementing a "ping" RPC callback, but I cannot post code - but, you could. There might be just a detail missing...
0
 
LVL 2

Author Comment

by:aquila98
ID: 7148818
0
 
LVL 2

Author Comment

by:aquila98
ID: 7148819
0
 
LVL 2

Author Comment

by:aquila98
ID: 7148825
Here is the server's idl:
interface SOPFEUMETEORpcService
{
    const unsigned long BUFFER_SIZE = 100;
    typedef struct {
        unsigned long BufferLength;
        [unique, size_is(BufferLength)] byte *Buffer;
        } BUFFER;
error_status_t Ping();
error_status_t ReloadURL([size_is(BufferLength), in ] byte Key[],
                       [in] unsigned long BufferLength);
error_status_t ShutDown([size_is(PwdLength), in ] byte Password[],
                      [in] unsigned long PwdLength);
error_status_t GetRootDirectory([out] BUFFER *pBuffer);
[callback] error_status_t ReLoadCallback([in, string] char* key);
[callback] error_status_t UrlLoadedCallback([in, string] char* url, [in, string] char* dir);
[callback] error_status_t ErrUrlLoadedCallback([in, string] char* url, [in, string] char* dir, [in, string] char* err);
}

Its acf:
[implicit_handle (handle_t global_SOPFEUMETEO_handle)]
interface SOPFEUMETEORpcService
{
    [comm_status, fault_status] Ping();
    [comm_status, fault_status] ReloadURL();
    [comm_status, fault_status] ShutDown();
    [comm_status, fault_status] GetRootDirectory();
      [comm_status, fault_status] ReLoadCallback();
      [comm_status, fault_status] UrlLoadedCallback();
      [comm_status, fault_status] ErrUrlLoadedCallback();
      [comm_status, fault_status] GetServerInCharge();
}
I tried to put the callback within the acf... Is this ok?

Now the server code where it is usig the callback:
error_status_t ReloadURL(byte Key[], unsigned long pwdLength)
{
      static char buf[1000];

      if (!SUCCEEDED(g_LoadFunction(NULL)))
            return RPC_S_ENTRY_NOT_FOUND;

      memset(buf, 0, 999);
      strncpy(buf, Key, pwdLength);
      ReLoadCallback(buf);
    return(0);
}

within the stub ReloadCallBack is defined as:
SOPFEUMETEORpcService_ReLoadCallback(...

On the client side, the callback functions are defined thus
to ensure that there is no undefined symbol (because of
c++ mangeling I guess, that's the only way I figured to get
it to link)
extern void Callback_ReLoadCallback(const char* key);
extern void Callback_UrlLoadedCallback(const char* url, const char* dir);
extern void Callback_ErrUrlLoadedCallback(const char* url, const char* dir, const char* err);
unsigned long ReLoadCallback(char * key)
{
      Callback_ReLoadCallback(key);
      return (0);
}

unsigned long UrlLoadedCallback(char * url, char* dir)
{
      Callback_UrlLoadedCallback(url, dir);
      return (0);
}

unsigned long ErrUrlLoadedCallback(char * url, char* dir, char * err)
{
      Callback_ErrUrlLoadedCallback(url, dir, err);
      return (0);
}

These functions are in their own .c file NOT using pre-
compiled header.

Now within a singleton controller class (RPCClient) I
have these functions that are called by the callback
(declared external above)
extern "C" {

void Callback_ReLoadCallback(const char* key)
{
  Beep(300,300);
  // this the a call to my singleton class
  if (RPCClient::Instance()->GetClientWindowPtr())
            ::SendMessage(RPCClient::Instance()->GetClientWindowPtr(), RPCClient::Instance()->GetMessageReloadID(), (WPARAM) NULL, (LPARAM) key);
}

void Callback_UrlLoadedCallback(const char* url, const char* dir)
{
      Beep(300,300);
      if (RPCClient::Instance()->GetClientWindowPtr())
            ::SendMessage(RPCClient::Instance()->GetClientWindowPtr(), RPCClient::Instance()->GetMessageLoadingUrlID(), (WPARAM) url, (LPARAM) dir);
}

void Callback_ErrUrlLoadedCallback(const char* url, const char* dir, const char* err)
{
      CString tmp= url;
      tmp += " :: ";
      tmp += dir;
      Beep(300,300);
      if (RPCClient::Instance()->GetClientWindowPtr())
            ::SendMessage(RPCClient::Instance()->GetClientWindowPtr(), RPCClient::Instance()->GetMessageErrorLoadingUrlID(), (WPARAM) (LPCTSTR)tmp, (LPARAM) err);
}

}

And no beeps are heard, no messages sent and a breakpoint
anywhere within the callback functions on the client's side never gets executed :(

Anything wrong with that layout??? hints?

thanks

ps there are 100 points waiting for you in
http://www.experts-exchange.com/jsp/qManageQuestion.jsp?qid=20317066
0
 
LVL 86

Expert Comment

by:jkr
ID: 7150079
>>I tried to put the callback within the acf... Is this ok?

Acually, your .acf file doesn't need to contain anything but

implicit_handle (handle_t global_SOPFEUMETEO_handle)]
interface SOPFEUMETEORpcService
{
}

You are linking the client with SOPFEUMETEORpcService_c.c, are you?
0
 
LVL 2

Author Comment

by:aquila98
ID: 7150097
Yes,

I have included in my project the rpcsvc_c.c file
(first few lines:
//@@MIDL_FILE_HEADING(  )

#include <string.h>
#if defined( _ALPHA_ )
#include <stdarg.h>
#endif

#include "rpcsvc.h"
)

I liked the acf because I used to work with DCE RPC and via
the acf we could get more error info ;-) does not seems to
be of use in NT though!

have a nice week end!
0
 
LVL 2

Author Comment

by:aquila98
ID: 7165118
Hmmm...

I moved the server from a NT machine tou our production
server which is running W2k AS and behold! It is now
working!

I did make a great amount of chance to the client and a
good cleanup and rebuild in release might have also
contributed to the success of the callback? Or is there a
problem with NT???

Thanks for all your help

!
0
 
LVL 86

Expert Comment

by:jkr
ID: 7172686
>>Or is there a problem with NT???

Not that I would know of - at least not a general problem, maybe a configuration problem. The server I mentioned runs on both...
0

Featured Post

VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

Question has a verified solution.

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

Greetings, Experts! First let me state that this website is top notch. I thoroughly enjoy the community that is shared here; those seeking help and those willing to sacrifice their time to help. It is fantastic. I am writing this article at th…
Trying to figure out group policy inheritance and which settings apply where can be a chore.  Here's a very simple summary I've written which might help.  Keep in mind, this is just a high-level conceptual overview where I try to avoid getting bogge…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.

831 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