Solved

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

Posted on 2002-06-18
20
861 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
 
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

The Need In an Active Directory enviroment, the PDC emulator provide time synchronization for the domain. This is important since Active Directory uses Kerberos for authentication.  By default, if the time difference between systems is off by more …
We recently endured a series of broadcast storms that caused our ISP to shut us down for brief periods of time. After going through a multitude of tests, we determined that the issue was related to Intel NIC drivers on some new HP desktop computers …
This video discusses moving either the default database or any database to a new volume.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

708 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

10 Experts available now in Live!

Get 1:1 Help Now