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

x
?
Solved

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

Posted on 2002-06-18
20
Medium Priority
?
921 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
[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
  • 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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 800 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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Are you one of those front-line IT Service Desk staff fielding calls, replying to emails, all-the-while working to resolve end-user technological nightmares? I am! That's why I have put together this brief overview of tools and techniques I use in o…
An article on effective troubleshooting
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…

618 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