LocalRegistrationManager.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 
39 
41 #include "LocalAPIManager.hpp"
42 #include "SysLibrary.hpp"
43 #include "ClientMessage.hpp"
44 #include "Utilities.hpp"
45 #include "RegistrationTable.hpp"
46 
47 
48 
50 {
51  // no state in this
52 }
53 
54 /**
55  * Register a DLL-based callback type.
56  *
57  * @param type The type of callback being registered
58  * @param name The name of the callback (unique within the type)
59  * @param module The name of the library containing the callback.
60  * @param proc The name of the callback entry point within the library.
61  * @param userData Pointer to userdata saved with the registered callback.
62  * @param drop The drop authority.
63  *
64  * @return The return code for the registration.
65  */
67  const char *module, const char *proc, const char *userData, bool drop)
68 {
69  // first parameter for these calls is ALWAYS the type, second is always the name
71 
72  // we have a secondary data area to send
73  ServiceRegistrationData regData(module, proc, drop, userData);
74  message.setMessageData(&regData, sizeof(ServiceRegistrationData));
75 
76  message.send();
77  return mapReturnResult(message);
78 }
79 
80 /**
81  * Register an in-process callback handler.
82  *
83  * @param type The type of handler.
84  * @param name The name of the handler.
85  * @param entryPoint The callback entry point.
86  * @param userData The optional userdata pointer.
87  *
88  * @return The message return code.
89  */
91  const char *userData)
92 {
93  // first parameter for these calls is ALWAYS the type
95 
96  // and fill in the secondary data area
97  ServiceRegistrationData regData(entryPoint, userData);
98  message.setMessageData((char *)&regData, sizeof(ServiceRegistrationData));
99 
100  // we handle the exe callback registration locally. So, this is a simulated SEND operation
102 
103  // perform the registration locally
104  table.registerCallback(message);
105  return mapReturnResult(message);
106 }
107 
108 /**
109  * Locate the target table for a registration based on the type.
110  *
111  * @param type The target registration type
112  *
113  * @return A reference to the registration table.
114  */
116 {
117  // if this is the first request for local registration information, we need to
118  // lock the rxapi library into memory by requesting an additional load. This
119  // is necessary because some apps dynamically load rexxapi, call a function, then
120  // unload the library. This wipes out the local registration tables. By doing a
121  // second load, then we are protected until the process goes away.
122  if (!locked)
123  {
124  SysLibrary lib;
125  // not necessarily an error if this fails, but we will be subject to
126  // the loading/unloading behavior. It is possible this might not be
127  // an issue for most applications, so an error doesn't really seem necessary.
128  if (lib.load("rexxapi"))
129  {
130  locked = true;
131  }
132  }
133 
134  if (type == FunctionAPI)
135  {
136  return functions;
137  }
138  else if (type == SubcomAPI)
139  {
140  return commandHandlers;
141  }
142  else {
143  return exits ;
144  }
145 }
146 
147 
148 /**
149  * Drop a registered callback.
150  *
151  * @param type The type of callback to process.
152  * @param name The name of the callback.
153  * @param module An optional library qualifier
154  *
155  * @return The operation return code.
156  */
158 {
159  // this is a different operation depending on whether we have a module specified
160  if (module != NULL)
161  {
162  // first parameter for these calls is ALWAYS the type. Library registrations are
163  // handled by the server, so this is always a send.
165  // we have extra data to send
166  ServiceRegistrationData regData(module);
167  message.setMessageData((char *)&regData, sizeof(ServiceRegistrationData));
168 
169  message.send();
170  return mapReturnResult(message);
171  }
172  else
173  {
174  // first parameter for these calls is ALWAYS the type
176 
178 
179  // try to drop this locally
180  table.dropCallback(message);
181  RexxReturnCode rc = mapReturnResult(message);
182  // if handled ok at this level, we're done
183  if (rc == RXSUBCOM_OK)
184  {
185  return RXSUBCOM_OK;
186  }
187 
188  // need to send this to the server.
189  message.send();
190  return mapReturnResult(message);
191  }
192 }
193 
194 
195 /**
196  * Perform an existance query for a callback
197  *
198  * @param type The type of callback to check.
199  * @param name The callback name.
200  *
201  * @return The query return code.
202  */
204 {
205  // first parameter for these calls is ALWAYS the type
207 
209 
210  // try to drop this locally
211  table.queryCallback(message);
212  RexxReturnCode rc = mapReturnResult(message);
213  // if handled ok at this level, we're done
214  if (rc == RXSUBCOM_OK)
215  {
216  return RXSUBCOM_OK;
217  }
218 
219  // need to send this to the server.
220 
221  message.send();
222  // the returned extra message data is released automatically.
223  return mapReturnResult(message);
224 }
225 
226 /**
227  * Perform a callback query, retrieving the userdata
228  * provided when the callback was registered.
229  *
230  * @param type The registration type.
231  * @param name The name of the callback,
232  * @param module The optional target library.
233  * @param userData The pointer for the returned userdata.
234  *
235  * @return The service return code.
236  */
238  char *userData)
239 {
240  if (module != NULL)
241  {
242  // first parameter for these calls is ALWAYS the type
244  ServiceRegistrationData regData(module);
245 
246  message.setMessageData((char *)&regData, sizeof(ServiceRegistrationData));
247 
248  message.send();
249  // if this was there, copy the user information back
250  if (message.result == CALLBACK_EXISTS)
251  {
253 
254  retData->retrieveUserData(userData);
255  }
256  // the returned extra message data is released automatically.
257  return mapReturnResult(message);
258  }
259  else
260  {
261  // first parameter for these calls is ALWAYS the type
264 
265  // try to drop this locally
266  table.queryCallback(message);
267  // if this wasn't found locally, ask the server
268  if (message.result != CALLBACK_EXISTS)
269  {
270  // need to send this to the server.
271  message.send();
272  }
273 
274  // if this was there, copy the user information back
275  if (message.result == CALLBACK_EXISTS)
276  {
278 
279  retData->retrieveUserData(userData);
280  }
281  // the returned extra message data is released automatically.
282  return mapReturnResult(message);
283  }
284 }
285 
286 /**
287  * Resolve a registered callback entry point.
288  *
289  * @param type The registration type
290  * @param name The name of the callback.
291  * @param module An optional library qualifier.
292  * @param entryPoint Pointer for returning the entry point address.
293  */
295  REXXPFN &entryPoint)
296 {
297  entryPoint = NULL; // assume failure
298 
299  // first parameter for these calls is ALWAYS the type
301 
303 
304  // try to locate this locally
305  table.queryCallback(message);
306  // if this wasn't found locally, ask the server
307  if (message.result != CALLBACK_EXISTS)
308  {
309  // need to send this to the server.
310  message.send();
311  }
312 
313  // if this was there, now try to load the module, if necessary.
314  if (message.result == CALLBACK_EXISTS)
315  {
317  if (strlen(retData->moduleName) != 0)
318  {
319  entryPoint = NULL;
320  SysLibrary lib;
321  if (lib.load(retData->moduleName))
322  {
323  entryPoint = (REXXPFN)lib.getProcedure(retData->procedureName);
324  if (entryPoint == NULL)
325  {
326  // uppercase the name in place (this is local storage, so it's safe)
327  // and try again to resolve this
329  entryPoint = (REXXPFN)lib.getProcedure(retData->procedureName);
330  if (entryPoint == NULL)
331  {
332  return RXSUBCOM_NOTREG;
333  }
334  }
335  }
336  }
337  else
338  {
339  entryPoint = (REXXPFN)retData->entryPoint;
340  }
341  }
342  // the returned extra message data is released automatically.
343  return mapReturnResult(message);
344 }
345 
346 
347 /**
348  * Convert an exception returned from the service into a
349  * return code.
350  *
351  * @param e The service exception.
352  *
353  * @return The mapped return code.
354  */
356 {
357  switch (e->getErrorCode())
358  {
359  case CALLBACK_NOT_FOUND:
360  return RXSUBCOM_NOTREG;
361 
362  case DROP_NOT_AUTHORIZED:
363  return RXSUBCOM_NOCANDROP;
364 
365  default:
366  return RXAPI_MEMFAIL;
367  }
368 }
369 
370 
371 /**
372  * Process an result returned from the server and
373  * map it into an API return code.
374  *
375  * @param m The return message.
376  *
377  * @return The mapped return code.
378  */
380 {
381  switch (m.result)
382  {
383  case CALLBACK_NOT_FOUND:
384  return RXSUBCOM_NOTREG;
385 
386  case DROP_NOT_AUTHORIZED:
387  return RXSUBCOM_NOCANDROP;
388 
389  default:
390  return RXSUBCOM_OK;
391  }
392 }
RegistrationType
@ SubcomAPI
@ FunctionAPI
@ CALLBACK_EXISTS
@ CALLBACK_NOT_FOUND
@ DROP_NOT_AUTHORIZED
@ REGISTER_LOAD_LIBRARY
@ REGISTER_QUERY_LIBRARY
@ REGISTER_DROP_LIBRARY
@ REGISTER_ENTRYPOINT
@ REGISTER_DROP
@ REGISTER_LIBRARY
@ REGISTER_QUERY
@ RegistrationManager
RexxReturnCode resolveCallback(RegistrationType type, const char *name, const char *module, REXXPFN &entryPoint)
virtual RexxReturnCode processServiceException(ServiceException *e)
RegistrationTable & locateTable(RegistrationType type)
RexxReturnCode queryCallback(RegistrationType type, const char *name)
RexxReturnCode registerCallback(RegistrationType type, const char *name, const char *module, const char *proc, const char *userData, bool drop)
RexxReturnCode mapReturnResult(ServiceMessage &m)
RexxReturnCode dropCallback(RegistrationType type, const char *name, const char *module)
void queryCallback(ServiceMessage &message)
void registerCallback(ServiceMessage &message)
void dropCallback(ServiceMessage &message)
ErrorCode getErrorCode()
void setMessageData(void *data, size_t length)
void * getMessageData()
ServiceReturn result
char procedureName[MAX_NAME_LENGTH]
void retrieveUserData(char *userPointer)
char moduleName[MAX_NAME_LENGTH]
void * getProcedure(const char *name)
bool load(const char *name)
static void strupper(char *str)
Definition: Utilities.cpp:132
int type
Definition: cmdparse.cpp:383
int RexxReturnCode
Definition: rexx.h:73
#define RXSUBCOM_NOTREG
Definition: rexxapidefs.h:90
#define RXSUBCOM_OK
Definition: rexxapidefs.h:85
#define RXSUBCOM_NOCANDROP
Definition: rexxapidefs.h:91
#define RXAPI_MEMFAIL
Definition: rexxapidefs.h:61
void * REXXPFN