aquila98
asked on
RPC server in NT... How to pass callback from client????
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
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
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)
[ 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)
BTW - if you still want to pursue the 'RPC_IF_CALLBACK_FN' path, see http://www.ntdev.org/archive/ntdev0001/msg0272.html
ASKER
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();
...
???
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();
...
???
In the above example:
int ShutDownCallBack ( void)
{
// ...
return ( 0);
}
MIDL will generate the code that calls the callback implementation.
int ShutDownCallBack ( void)
{
// ...
return ( 0);
}
MIDL will generate the code that calls the callback implementation.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
thanks it works ;-)
ASKER
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.
???
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.
???
Sorry, I didn't ever get a notif for your last comment (see also https://www.experts-exchange.com/jsp/qManageQuestion.jsp?qid=2030914999 - I'll check about the bindings...
ASKER
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!
???
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!
???
Iiih, yikes, sorry - just saw this one by chance by going through old Qs - do you still have that problem?
ASKER
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
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
>>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...
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...
ASKER
ASKER
ASKER
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(BufferL ength), in ] byte Key[],
[in] unsigned long BufferLength);
error_status_t ShutDown([size_is(PwdLengt h), 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_ReLo adCallback (...
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(co nst char* key);
extern void Callback_UrlLoadedCallback (const char* url, const char* dir);
extern void Callback_ErrUrlLoadedCallb ack(const char* url, const char* dir, const char* err);
unsigned long ReLoadCallback(char * key)
{
Callback_ReLoadCallback(ke y);
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_ErrUrlLoadedCallb ack(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(co nst char* key)
{
Beep(300,300);
// this the a call to my singleton class
if (RPCClient::Instance()->Ge tClientWin dowPtr())
::SendMessage(RPCClient::I nstance()- >GetClient WindowPtr( ), RPCClient::Instance()->Get MessageRel oadID(), (WPARAM) NULL, (LPARAM) key);
}
void Callback_UrlLoadedCallback (const char* url, const char* dir)
{
Beep(300,300);
if (RPCClient::Instance()->Ge tClientWin dowPtr())
::SendMessage(RPCClient::I nstance()- >GetClient WindowPtr( ), RPCClient::Instance()->Get MessageLoa dingUrlID( ), (WPARAM) url, (LPARAM) dir);
}
void Callback_ErrUrlLoadedCallb ack(const char* url, const char* dir, const char* err)
{
CString tmp= url;
tmp += " :: ";
tmp += dir;
Beep(300,300);
if (RPCClient::Instance()->Ge tClientWin dowPtr())
::SendMessage(RPCClient::I nstance()- >GetClient WindowPtr( ), RPCClient::Instance()->Get MessageErr orLoadingU rlID(), (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
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?qid=20317066
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(BufferL
[in] unsigned long BufferLength);
error_status_t ShutDown([size_is(PwdLengt
[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
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_ReLo
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(co
extern void Callback_UrlLoadedCallback
extern void Callback_ErrUrlLoadedCallb
unsigned long ReLoadCallback(char * key)
{
Callback_ReLoadCallback(ke
return (0);
}
unsigned long UrlLoadedCallback(char * url, char* dir)
{
Callback_UrlLoadedCallback
return (0);
}
unsigned long ErrUrlLoadedCallback(char * url, char* dir, char * err)
{
Callback_ErrUrlLoadedCallb
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(co
{
Beep(300,300);
// this the a call to my singleton class
if (RPCClient::Instance()->Ge
::SendMessage(RPCClient::I
}
void Callback_UrlLoadedCallback
{
Beep(300,300);
if (RPCClient::Instance()->Ge
::SendMessage(RPCClient::I
}
void Callback_ErrUrlLoadedCallb
{
CString tmp= url;
tmp += " :: ";
tmp += dir;
Beep(300,300);
if (RPCClient::Instance()->Ge
::SendMessage(RPCClient::I
}
}
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
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?qid=20317066
>>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?
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,
ASKER
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!
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!
ASKER
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
!
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
!
>>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...
Not that I would know of - at least not a general problem, maybe a configuration problem. The server I mentioned runs on both...
You can post just a link back to here so that you get twice the bang for your points.
I hope this helps !