1 /*----------------------------------------------------------------------------
  2 Name:      XmlBlasterUnmanagedCE.c
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   See XmlBlasterUnmanagedCE.h
  6            Access C dll from C# on Windows CE with P/Invoke
  7 Todo:      Callback function (update from Dll to C#)
  8 Author:    "Marcel Ruff" <xmlBlaster@marcelruff.info>
  9 See:       http://www.xmlblaster.org/xmlBlaster/doc/requirements/protocol.socket.html
 10 -----------------------------------------------------------------------------*/
 11 #include <string.h> /* memset (ISO C forbids an empty source file) */

 12 #if defined(_WINDOWS) || defined(WINCE)

 13 #include <stdio.h>  /* printf */

 14 #include <XmlBlasterUnmanagedCE.h>

 15 #ifndef WINCE

 16 #  include <stdarg.h>

 17 #  include <locale.h> /* setlocal() */

 18 #endif

 19 
 20 #ifdef __cplusplus

 21 #       define XBFORCE_EXTERNC extern "C"

 22 #else

 23 #       define XBFORCE_EXTERNC

 24 #endif

 25 
 26 static const bool freeIt = true;
 27 
 28 /*
 29  We should avoid C++ code as the name mangling makes difficulties,
 30  so we force C code here.
 31  See: http://www.opennetcf.org/Forums/topic.asp?TOPIC_ID=255
 32 */
 33 
 34 static void myLogger(XmlBlasterLogging logUserP,
 35                      XMLBLASTER_LOG_LEVEL currLevel,
 36                      XMLBLASTER_LOG_LEVEL level,
 37                      const char *location, const char *fmt, ...);
 38  
 39 static void myLogger(XmlBlasterLogging logUserP,
 40                      XMLBLASTER_LOG_LEVEL currLevel,
 41                      XMLBLASTER_LOG_LEVEL level,
 42                      const char *location, const char *fmt, ...)
 43 {
 44    /* Guess we need no more than 200 bytes. */
 45    int n, size = 200;
 46    char *p = 0;
 47    va_list ap;
 48    int32_t lvl = (int32_t)level;
 49    XmlBlasterUnmanagedCELoggerFp managedLoggerFp = (XmlBlasterUnmanagedCELoggerFp)logUserP;
 50 
 51 
 52    if (managedLoggerFp == 0)
 53       return;
 54 
 55    if (level > currLevel) { /* XMLBLASTER_LOG_ERROR, XMLBLASTER_LOG_WARN, XMLBLASTER_LOG_INFO, XMLBLASTER_LOG_TRACE */
 56       return;
 57    }
 58    if ((p = (char *)malloc (size)) == NULL)
 59       return;
 60 
 61    for (;;) {
 62       /* Try to print in the allocated space. */
 63       va_start(ap, fmt);
 64       n = VSNPRINTF(p, size, fmt, ap); /* UNIX: vsnprintf(), WINDOWS: _vsnprintf() */
 65       va_end(ap);
 66       /* If that worked, print the string to console. */
 67       if (n > -1 && n < size) {
 68          /*printf("{%s-%s-%s} [%s] %s\n",
 69                    __DATE__, __TIME__, getLogLevelStr(level), location, p);*/
 70          /* Call now the C# logger XmlBlasterUnmanagedCELoggerFp */
 71 
 72          (*managedLoggerFp)(lvl, location, p);
 73 
 74          /* The C# code does not free 'p' during its UNICODE marshalling
 75             with byteArrayFromIntPtr(false) -> no xmlBlasterUnmanagedCEFree() */
 76          free(p);
 77 
 78          return;
 79       }
 80       /* Else try again with more space. */
 81       if (n > -1)    /* glibc 2.1 */
 82          size = n+1; /* precisely what is needed */
 83       else           /* glibc 2.0 */
 84          size *= 2;  /* twice the old size */
 85       if ((p = (char *)realloc (p, size)) == NULL) {
 86          return;
 87       }
 88    }
 89 }
 90 
 91 /* extern "C" __declspec (dllexport) */
 92 XBFORCE_EXTERNC Dll_Export void xmlBlasterUnmanagedCERegisterLogger(struct XmlBlasterAccessUnparsed *xa,
 93                            XmlBlasterUnmanagedCELoggerFp logger) {
 94    /*MessageBox(NULL, L"Entering xmlBlasterUnmanagedCERegisterLogger", _T("Unmanaged"), MB_OK);*/
 95    /*printf("dll: Register logger\n");*/
 96    if (logger != 0) {
 97       /* Register our own logging function */
 98       xa->log = (XmlBlasterLogging)myLogger;
 99       /* Pass a pointer which we can use in myLogger() again */
100       xa->logUserP = (void*)logger;
101    }
102    else { /* unregister */
103       xa->log = 0;
104       xa->logUserP = 0;
105    }
106    /*xa->log(xa->logUserP, xa->logLevel, XMLBLASTER_LOG_ERROR, __FILE__, "Testing logging output only");*/
107 }
108 
109 
110 static void callbackProgressListener(void *userP, const size_t currBytesRead, const size_t nbytes);
111 /**
112  * Access the read socket progress.
113  * You need to register this function pointer if you want to see the progress of huge messages
114  * on slow connections.
115  */
116 static void callbackProgressListener(void *userP, const size_t currBytesRead, const size_t nbytes) {
117    XmlBlasterUnmanagedCECallbackProgressListenerFp *fp = (XmlBlasterUnmanagedCECallbackProgressListenerFp *)userP;
118    if (fp != 0) {
119       int32_t curr = (int32_t)currBytesRead;
120       int32_t n = (int32_t)nbytes;
121       printf("C-DLL: entering callbackProgressListener(fp=%p) %d/%d\n", fp, curr, n);
122       (*fp)(curr, n);
123       printf("C-DLL: done callbackProgressListener(fp=%p) %d/%d\n", fp, curr, n);
124    }
125 }
126 /**
127  * Called by managed C# code to register for progress notifications
128  */
129 XBFORCE_EXTERNC Dll_Export void xmlBlasterUnmanagedCERegisterProgressListener(
130    struct XmlBlasterAccessUnparsed *xa,
131    XmlBlasterUnmanagedCECallbackProgressListenerFp csharpProgressListenerFp) {
132 
133    if (xa && xa->callbackP != 0) {
134       xa->callbackP->readFromSocket.numReadUserP = (void*)csharpProgressListenerFp;
135       if (callbackProgressListener != 0) {
136          printf("C-DLL: doing xmlBlasterUnmanagedCERegisterProgressListener(csharpProgressListenerFp=%p)\n", csharpProgressListenerFp);
137          xa->callbackP->readFromSocket.numReadFuncP = callbackProgressListener;
138       }
139       else {
140          xa->callbackP->readFromSocket.numReadFuncP = 0; /* Dangerous: not thread safe, TODO: Add a mutex */
141       }
142    }
143 }
144 
145 /**
146  * malloc size bytes
147  * @param size > 0
148  * @return p the allocated pointer
149  */
150 XBFORCE_EXTERNC extern char *xmlBlasterUnmanagedCEMalloc(int32_t size) {
151    /*printf("dll: xmlBlasterUnmanagedCEMalloc(size=%d)\n", size);*/
152    if (size > 0)
153       return (char *)malloc(size*sizeof(char));
154    return (char *)0;
155 }
156 
157 /**
158  * Frees the malloced pointer
159  * @param p Can be null
160  */
161 XBFORCE_EXTERNC extern void xmlBlasterUnmanagedCEFree(char *p)  {
162    /*if (p!=0)
163       printf("dll: xmlBlasterUnmanagedCEFree size=%d:\n%s\n", strlen(p), p);*/ /* dangeraous for none strings like IntPtr */
164    xmlBlasterFree(p);
165 }
166 
167 /**
168  * Frees the content of the malloced pointer
169  * It is a hack as i don't know how to free the IntPtr which arrived as ** and was allocated on (*ppStruct)
170  * for example in unSubscribe(): So we call this function similar as the unSubscribe() ...
171  * @param pp Can be null
172  */
173 XBFORCE_EXTERNC extern void xmlBlasterUnmanagedCEFreePP(char **pp)  {
174    if (pp==0)
175       return;
176    else {
177       char *p = *pp;
178       /*printf("dll: xmlBlasterUnmanagedCEFreePP('%s')\n", ((p!=(char *)0)?p:""));*/
179       xmlBlasterFree(p);
180    }
181 }
182 
183 /**
184  * Allocates the members of XmlBlasterUnmanagedCEException
185  * You need to free it after usage
186  */
187 XBFORCE_EXTERNC static void convert(XmlBlasterException *in, XmlBlasterUnmanagedCEException *out) {
188    if (*in->errorCode != 0) {
189       out->errorCode = strcpyAlloc(in->errorCode);
190       out->message = strcpyAlloc(in->message);
191       out->remote = in->remote;
192    }
193    else {
194       out->errorCode = 0;
195    }
196 }
197 
198 XBFORCE_EXTERNC extern void xmlBlasterUnmanagedCEExceptionFree(XmlBlasterUnmanagedCEException *ex) {
199    if (ex == 0) return;
200    xmlBlasterFree(ex->errorCode);
201    ex->errorCode = 0;
202    xmlBlasterFree(ex->message);
203    ex->message = 0;
204    ex->remote = 0;
205 }
206 
207 
208 /**
209  * We intercept the callbacks here and convert it to a more simple form to
210  * be easy transferable to C# (Csharp).
211  */
212 XBFORCE_EXTERNC static XMLBLASTER_C_bool interceptUpdate(MsgUnitArr *msgUnitArr, void *userData, XmlBlasterException *exception) {
213    size_t i;
214    XmlBlasterUnmanagedCEException unmanagedException;
215    XMLBLASTER_C_bool retVal = true;
216    int32_t isOneway = 0;
217    /*MessageBox(NULL, L"Entering interceptUpdate0", _T("Unmanaged"), MB_OK);*/
218 
219    XmlBlasterAccessUnparsed *xa = (XmlBlasterAccessUnparsed *)userData;
220    XmlBlasterUnmanagedCEUpdateFp unmanagedUpdate = (XmlBlasterUnmanagedCEUpdateFp)(xa->userFp);
221 
222    if (xa->logLevel>=XMLBLASTER_LOG_TRACE)
223       xa->log(xa->logUserP, xa->logLevel, XMLBLASTER_LOG_TRACE, __FILE__, "Got update message");
224 
225    if (userData != 0) ;  /* Supress compiler warning */
226    if (unmanagedUpdate == 0) return false;
227 
228    /*memset(&unmanagedException, 0, sizeof(struct XmlBlasterUnmanagedCEException));*/
229    unmanagedException.remote = false;
230    unmanagedException.errorCode = (char)0;
231    unmanagedException.message = (char)0;
232 
233    isOneway = msgUnitArr->isOneway;
234    for (i=0; i<msgUnitArr->len; i++) {
235       const char *cbSessionId = strcpyAlloc(msgUnitArr->secretSessionId);
236       /*
237       char *xml = messageUnitToXml(&msgUnitArr->msgUnitArr[i]);
238       printf("[client] CALLBACK update(): Asynchronous message update arrived:%s\n",
239              xml);
240       xmlBlasterFree(xml);
241 
242       printf("XmlBlasterUnmanaged.c: before update() %d\n", (int)msgUnitArr->len);
243       */
244 
245       if (xa->logLevel>=XMLBLASTER_LOG_TRACE) xa->log(xa->logUserP, xa->logLevel, XMLBLASTER_LOG_TRACE, __FILE__, "Got update, calling C# ...");
246 
247       /* Call C# ..., it may allocate errorCode */
248       unmanagedUpdate(cbSessionId, &msgUnitArr->msgUnitArr[i], isOneway, &unmanagedException);
249 
250       if (xa->logLevel>=XMLBLASTER_LOG_TRACE) xa->log(xa->logUserP, xa->logLevel, XMLBLASTER_LOG_TRACE, __FILE__, "Got update, calling C# DONE");
251 
252       if (unmanagedException.errorCode != 0) {
253          /* catch first exception set and return */
254          strncpy0(exception->errorCode, unmanagedException.errorCode, EXCEPTIONSTRUCT_ERRORCODE_LEN);
255          if (unmanagedException.message != 0)
256             strncpy0(exception->message, unmanagedException.message, EXCEPTIONSTRUCT_MESSAGE_LEN);
257          exception->remote = unmanagedException.remote;
258          xmlBlasterUnmanagedCEExceptionFree(&unmanagedException);
259          msgUnitArr->msgUnitArr[i].responseQos = 0;
260          xa->log(xa->logUserP, xa->logLevel, XMLBLASTER_LOG_WARN, __FILE__, "Rethrowing exception from C# '%s' '%s'", exception->errorCode, exception->message);
261          retVal = false;
262       }
263       else {
264          msgUnitArr->msgUnitArr[i].responseQos = strcpyAlloc("<qos><state id='OK'/></qos>");
265          /* Return QoS: Everything is OK */
266       }
267    }
268 
269    return retVal;
270 }
271 
272 /*
273  * We take a clone of argv, and not free your argv (crashes for some reason if we free it here)
274  * @paran argc
275  * @param argv [0] contains the exe name, [1] the first argument, etc.
276  *   "Hello.exe" "-dispatch/connection/plugin/socket/hostname" "192.168.1.2"
277  * @return the XmlBlasterAccessUnparsed handle
278  */
279 XBFORCE_EXTERNC Dll_Export XmlBlasterAccessUnparsed *getXmlBlasterAccessUnparsedUnmanagedCE(int argc, char** argv){
280    int i=0;
281    XmlBlasterAccessUnparsed *xa;
282    const char ** ptr = (const char **)malloc(argc*sizeof(char *));
283    for (i=0; i<argc; ++i) {
284       ptr[i] = strcpyAlloc(argv[i]);
285       /*printf("dll: getAccess '%s'\n", argv[i]);*/
286       /*if (freeIt) { xmlBlasterFree(argv[i]); argv[i] = 0; }*/
287    }
288    /*if (freeIt) { xmlBlasterFree((char *)argv); }*/
289    xa = getXmlBlasterAccessUnparsed(argc, ptr);
290    /*xa->userObject = ...; // Transports something to the interceptUpdate() method*/
291    return xa;
292 }
293 
294 XBFORCE_EXTERNC Dll_Export void freeXmlBlasterAccessUnparsedUnmanagedCE(XmlBlasterAccessUnparsed *xmlBlasterAccess) {
295    if (xmlBlasterAccess != 0) {
296       int i;
297       for (i=0; i<xmlBlasterAccess->argc; ++i)
298          free((void*)xmlBlasterAccess->argv[i]);
299       free((void*)xmlBlasterAccess->argv);
300       freeXmlBlasterAccessUnparsed(xmlBlasterAccess);
301    }
302 }
303 
304 XBFORCE_EXTERNC Dll_Export bool xmlBlasterUnmanagedCEInitialize(struct XmlBlasterAccessUnparsed *xa,
305             XmlBlasterUnmanagedCEUpdateFp update, XmlBlasterUnmanagedCEException *exception) {
306    XmlBlasterException e;
307    bool ret = false;
308    xa->userFp = (XmlBlasterAccessGenericFp)update;
309    ret = xa->initialize(xa, interceptUpdate, &e);
310    convert(&e, exception);
311    return ret;
312 }
313 
314 /**
315  * Your qos is freed
316  */
317 XBFORCE_EXTERNC Dll_Export char *xmlBlasterUnmanagedCEConnect(struct XmlBlasterAccessUnparsed *xa,
318                            char *qos, XmlBlasterUnmanagedCEUpdateFp update, XmlBlasterUnmanagedCEException *exception) {
319    XmlBlasterException e;
320    char *ret = 0;
321    /*MessageBox(NULL, L"Entering xmlBlasterUnmanagedCEConnect", _T("Unmanaged"), MB_OK);*/
322    if (update != 0)
323       xa->userFp = (XmlBlasterAccessGenericFp)update;
324    ret = xa->connect(xa, qos, interceptUpdate, &e);
325    convert(&e, exception);
326    if (freeIt) { xmlBlasterFree(qos); qos=0; }
327    return ret;
328 }
329 
330 /**
331  * Your qos is freed
332  */
333 XBFORCE_EXTERNC Dll_Export extern bool xmlBlasterUnmanagedCEDisconnect(struct XmlBlasterAccessUnparsed *xa,
334                            char * qos, XmlBlasterUnmanagedCEException *exception) {
335    XmlBlasterException e;
336    bool ret = xa->disconnect(xa, qos, &e);
337    convert(&e, exception);
338    if (freeIt) { xmlBlasterFree(qos); qos=0; }
339    return ret;
340 }
341 
342 XBFORCE_EXTERNC Dll_Export extern char *xmlBlasterUnmanagedCEPublish(struct XmlBlasterAccessUnparsed *xa,
343                 MsgUnitUnmanagedCEpublish *msgUnitUnmanaged, XmlBlasterUnmanagedCEException *exception) {
344    XmlBlasterException e;
345    char *ret = xa->publish(xa, msgUnitUnmanaged, &e);
346    convert(&e, exception);
347    if (freeIt) freeMsgUnitData(msgUnitUnmanaged);
348    return ret;
349 }
350 
351 XBFORCE_EXTERNC Dll_Export extern QosArr *xmlBlasterUnmanagedCEPublishArr(struct XmlBlasterAccessUnparsed *xa, MsgUnitArr *msgUnitArr, XmlBlasterUnmanagedCEException *exception) {
352    XmlBlasterException e;
353    QosArr *ret = xa->publishArr(xa, msgUnitArr, &e);
354    convert(&e, exception);
355    return ret;
356 }
357 
358 XBFORCE_EXTERNC Dll_Export extern void xmlBlasterUnmanagedCEPublishOneway(struct XmlBlasterAccessUnparsed *xa, void *msgUnitArr, int length, XmlBlasterUnmanagedCEException *exception) {
359    XmlBlasterException e;
360    MsgUnitArr arr;
361    /*printf("C: xmlBlasterUnmanagedCEPublishOneway %d\n", length);*/
362    arr.isOneway = true;
363    arr.len = length;
364    arr.msgUnitArr = (MsgUnit*)msgUnitArr;
365    *arr.secretSessionId = 0;
366    xa->publishOneway(xa, &arr, &e);
367    convert(&e, exception);
368    if (freeIt) {
369       size_t i;
370       for (i=0; i<arr.len; i++) {
371          freeMsgUnitData(&arr.msgUnitArr[i]);
372       }
373       /*free(msgUnitArr.msgUnitArr); is memory from C# IntPtr*/
374    }
375 }
376 
377 /**
378  * Your key and qos is freed
379  */
380 XBFORCE_EXTERNC Dll_Export extern char *xmlBlasterUnmanagedCESubscribe(struct XmlBlasterAccessUnparsed *xa, char *key, char *qos, XmlBlasterUnmanagedCEException *exception) {
381    XmlBlasterException e;
382    char *ret = xa->subscribe(xa, key, qos, &e);
383    convert(&e, exception);
384    if (freeIt) { xmlBlasterFree(key); key=0; }
385    if (freeIt) { xmlBlasterFree(qos); qos=0; }
386    return ret;
387 }
388 
389 XBFORCE_EXTERNC Dll_Export void xmlBlasterUnmanagedCEUnSubscribe(struct XmlBlasterAccessUnparsed *xa,
390    char * key, char * qos, XmlBlasterUnmanagedCEException *exception, uint32_t* pSize, XmlBlasterUnmanagedCEStringArr** ppStruct) {
391    XmlBlasterException e;
392    QosArr *ret = 0;
393    initializeXmlBlasterException(&e);
394    ret = xa->unSubscribe(xa, key, qos, &e);
395    convert(&e, exception);
396    if (freeIt) { xmlBlasterFree(key); key=0; }
397    if (freeIt) { xmlBlasterFree(qos); qos=0; }
398    if (*e.errorCode != 0) {
399       /*printf("C: Caught exception in unSubscribe errorCode=%s, message=%s\n", e.errorCode, e.message);*/
400       if (ret) freeQosArr(ret);
401       return;
402    }
403    if (ret) {
404       size_t i;
405       XmlBlasterUnmanagedCEStringArr* pCurStruct = 0;
406       const uint32_t cArraySize = ret->len;
407       *pSize = cArraySize;
408       *ppStruct = (XmlBlasterUnmanagedCEStringArr*)malloc( cArraySize * sizeof( XmlBlasterUnmanagedCEStringArr ));
409       pCurStruct = *ppStruct;
410       for (i=0; i<ret->len; i++, pCurStruct++) {
411          /*printf("C: Unsubscribe success, returned status is '%s'\n", ret->qosArr[i]);*/
412          pCurStruct->str = strcpyAlloc(ret->qosArr[i]);
413       }
414       freeQosArr(ret);
415    }
416 }
417 
418 XBFORCE_EXTERNC Dll_Export void xmlBlasterUnmanagedCEErase(struct XmlBlasterAccessUnparsed *xa, char * key,
419      char * qos, XmlBlasterUnmanagedCEException *exception, uint32_t* pSize, XmlBlasterUnmanagedCEStringArr** ppStruct) {
420    XmlBlasterException e;
421    QosArr *ret = 0;
422    initializeXmlBlasterException(&e);
423    ret = xa->erase(xa, key, qos, &e);
424    convert(&e, exception);
425    if (freeIt) { xmlBlasterFree(key); key=0; }
426    if (freeIt) { xmlBlasterFree(qos); qos=0; }
427    if (*e.errorCode != 0) {
428       if (ret) freeQosArr(ret);
429       return;
430    }
431    if (ret) {
432       size_t i;
433       XmlBlasterUnmanagedCEStringArr* pCurStruct = 0;
434       const uint32_t cArraySize = ret->len;
435       *pSize = cArraySize;
436       if (cArraySize == 0) {
437          *ppStruct = 0;
438       }
439       else {
440          *ppStruct = (XmlBlasterUnmanagedCEStringArr*)malloc( cArraySize * sizeof( XmlBlasterUnmanagedCEStringArr ));
441          pCurStruct = *ppStruct;
442          for (i=0; i<ret->len; i++, pCurStruct++) {
443             /*printf("dll: erase success, returned status is '%s'\n", ret->qosArr[i]);*/
444             pCurStruct->str = strcpyAlloc(ret->qosArr[i]);
445          }
446       }
447       freeQosArr(ret);
448    }
449 }
450 
451 XBFORCE_EXTERNC Dll_Export void xmlBlasterUnmanagedCEGet(struct XmlBlasterAccessUnparsed *xa,
452         char * key, char *qos, XmlBlasterUnmanagedCEException *exception,
453         uint32_t* pSize, MsgUnitUnmanagedCEget** ppStruct) {
454    XmlBlasterException e;
455    uint32_t i;
456    MsgUnitArr *msgUnitArr = xa->get(xa, key, qos, &e);
457    convert(&e, exception);
458    if (freeIt) { xmlBlasterFree(key); key=0; }
459    if (freeIt) { xmlBlasterFree(qos); qos=0; }
460    if (*e.errorCode != 0) {
461       return;
462    }
463    /*printf("dll: xmlBlasterUnmanagedCEGet building response\n");*/
464    if (msgUnitArr != (MsgUnitArr *)0) {
465       const uint32_t cArraySize = msgUnitArr->len;
466       MsgUnitUnmanagedCEget* msgUnitUnmanagedP = 0;
467       if (cArraySize == 0) {
468          *ppStruct = 0;
469          freeMsgUnitArr(msgUnitArr);
470          return;
471       }
472 
473       *pSize = cArraySize;
474       *ppStruct = (MsgUnitUnmanagedCEget*)malloc( cArraySize * sizeof( MsgUnitUnmanagedCEget ));
475       msgUnitUnmanagedP = *ppStruct;
476       /*printf("dll: xmlBlasterUnmanagedCEGet %ud\n", cArraySize);*/
477       /* TODO: It should be possible to pass msgUnitArr->msgUnitArr* directly
478          as it has the same memory layout as the IntPtr
479       */
480       /* NOTE:
481          The sizeof(MsgUnitUnmanagedCEget) returns 20 bytes
482          The same bytes are reported on the C# side (otherwise this approach fails)
483       */
484       for(i=0; i < cArraySize; i++, msgUnitUnmanagedP++) {
485          MsgUnit *msgUnit = &msgUnitArr->msgUnitArr[i];
486          char *cnt = (char *)malloc(msgUnit->contentLen*sizeof(char));
487          /*printf("dll: xmlBlasterUnmanagedCEGet processing #%u\n", i);*/
488          msgUnitUnmanagedP->contentLen = (int32_t)msgUnit->contentLen;
489          if (cnt != 0) {
490             size_t j;
491             for (j=0; j<msgUnit->contentLen; j++) cnt[j] = (char)msgUnit->content[j];
492          }
493          msgUnitUnmanagedP->content = cnt;
494          msgUnitUnmanagedP->key = strcpyAlloc(msgUnit->key);
495          msgUnitUnmanagedP->qos = strcpyAlloc(msgUnit->qos);
496          msgUnitUnmanagedP->responseQos = strcpyAlloc("<qos/>");
497          /*printf("dll: xmlBlasterUnmanagedCEGet processing #%u key=%s qos=%s\n", i, msgUnitUnmanagedP->key, msgUnitUnmanagedP->qos);*/
498       }
499       freeMsgUnitArr(msgUnitArr);
500    }
501    /*printf("DONE in get\n");*/
502 }
503 
504 XBFORCE_EXTERNC Dll_Export char *xmlBlasterUnmanagedCEPing(struct XmlBlasterAccessUnparsed *xa, char *qos, XmlBlasterUnmanagedCEException *exception) {
505    XmlBlasterException e;
506    char *ret = xa->ping(xa, qos, &e);
507    convert(&e, exception);
508    if (freeIt) { xmlBlasterFree(qos); qos=0; }
509    return ret;
510 }
511 
512 XBFORCE_EXTERNC Dll_Export bool xmlBlasterUnmanagedCEIsConnected(struct XmlBlasterAccessUnparsed *xa) {
513    return xa->isConnected(xa);
514 }
515 
516 XBFORCE_EXTERNC Dll_Export const char *xmlBlasterUnmanagedCEUsage() {
517    char *usage = (char *)malloc(XMLBLASTER_MAX_USAGE_LEN*sizeof(char));
518    return xmlBlasterAccessUnparsedUsage(usage);
519 }
520 
521 XBFORCE_EXTERNC Dll_Export const char *xmlBlasterUnmanagedCEVersion() {
522    char *version = strcpyAlloc(getXmlBlasterVersion());
523    return version;
524 }
525 
526 #ifdef WINCE_EMEI

527 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/apisp/html/sp_extapi_linegetgeneralinfo.asp */
528 /* Tutorial: http://www.developer.com/ws/pc/print.php/10947_3503761_1 */
529 #include <commctrl.h>

530 #include "tapi.h"

531 #include "extapi.h"

532 
533 #define TAPI_API_HIGH_VERSION   0x00020000

534 #define EXT_API_LOW_VERSION     0x00010000

535 #define EXT_API_HIGH_VERSION    0x00010000

536    /*
537    OS Versions: Windows CE 3.0 and later
538    Header: extapi.h
539    Library: cellcore.lib
540    */
541 
542 #define DEVICE_ID_LENGTH            20

543 #define APPLICATION_DATA            "@^!MyAppName!^@"

544 #define APPLICATION_DATA_LENGTH     15

545 
546 static void GetTAPIErrorMsg(TCHAR *szMsg,int nSize, DWORD dwError)
547 {
548         LPTSTR lpBuffer = 0;
549         DWORD dwRet = 0;
550 
551         dwRet = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
552                 NULL,TAPIERROR_FORMATMESSAGE(dwError),MAKELANGID(LANG_NEUTRAL, LANG_NEUTRAL),
553                 (LPTSTR) &lpBuffer,0,NULL);
554         memset(szMsg,0,nSize);
555         if (lpBuffer && dwRet)
556         {
557                 _tcscpy(szMsg,lpBuffer);
558                 LocalFree(lpBuffer);
559         }
560         else
561         {
562                 _stprintf(szMsg,L"Unknown Error: 0x%X",dwError);
563         }
564 }
565 #endif /* WINCE_EMEI */

566 
567 /**
568  * You need to add cellcore.lib for compilation (WINCE).
569  * TODO: Not yet tested: What is inside the lineGeneralInfo.dwSerialNumberOffset??
570  * TODO: Needs security model?
571  * @return malloced string with IMEI, you need to free it
572  */
573 const char *getXmlBlasterEmei() {
574 #ifdef WINCE_EMEI

575    /*TCHAR imei[80]; // 40 should be OK */
576    LPBYTE pLineGeneralInfoBytes = NULL;
577    LINEGENERALINFO lineGeneralInfo;
578    HLINEAPP hLineApp = 0;
579    HLINE hLine = 0;
580    DWORD dwNumDevs;
581    DWORD dwAPIVersion = TAPI_API_HIGH_VERSION;
582    DWORD dwExtVersion = 0;
583    DWORD dwDeviceID;
584    DWORD dwMediaMode = LINEMEDIAMODE_DATAMODEM; /* | LINEMEDIAMODE_INTERACTIVEVOICE; */
585    LONG tapiresult; /* functions return 0 (SUCCESS) */
586    LINEINITIALIZEEXPARAMS lineInitializeExParams;
587 
588    lineGeneralInfo.dwTotalSize = sizeof(lineGeneralInfo);
589 
590    lineInitializeExParams.dwTotalSize = sizeof(lineInitializeExParams);
591    lineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; /*The application desires to use the Event Handle event notification mechanism*/
592    tapiresult = lineInitializeEx(&hLineApp, 0, 0, L"MyApp", &dwNumDevs, &dwAPIVersion, &lineInitializeExParams);
593    if (tapiresult) {
594       MessageBox(NULL, L"lineInitializeEx failed", _T("Unmanaged"), MB_OK);
595       return 0;
596    }
597 
598    /*MessageBox(NULL, L"lineInitializeEx OK", _T("Unmanaged"), MB_OK);*/
599    for (dwDeviceID = 0; dwDeviceID < dwNumDevs; dwDeviceID++) {
600       tapiresult = lineOpen(hLineApp, dwDeviceID, &hLine, dwAPIVersion, 0, 0,
601                           LINECALLPRIVILEGE_OWNER, dwMediaMode, 0); /*returns 0 (SUCCESS)*/
602       if (tapiresult) {
603          MessageBox(NULL, L"lineOpen failed", _T("Unmanaged"), MB_OK);
604          continue;
605       }
606 
607       tapiresult = lineNegotiateExtVersion(hLineApp, dwDeviceID, dwAPIVersion,
608                   EXT_API_LOW_VERSION, EXT_API_HIGH_VERSION, &dwExtVersion); /*returns 0 (SUCCESS)*/
609       if (tapiresult) {
610          MessageBox(NULL, L"lineNegotiateExtVersion failed", _T("Unmanaged"), MB_OK);
611          continue;
612       }
613 
614       tapiresult = lineGetGeneralInfo(hLine, &lineGeneralInfo); /*FAILs and gives error: -2147483595 (Invalid pointer)*/
615       if (tapiresult != 0 && tapiresult != LINEERR_STRUCTURETOOSMALL) {
616                    TCHAR szMsg[255];
617                    GetTAPIErrorMsg(szMsg,sizeof(szMsg), tapiresult);
618          MessageBox(NULL, szMsg, _T("Unmanaged"), MB_OK);
619                    continue;
620       }
621 
622       /*MessageBox(NULL, L"success!!!", _T("Unmanaged"), MB_OK);*/
623 
624       pLineGeneralInfoBytes = new BYTE[lineGeneralInfo.dwNeededSize];
625       LPLINEGENERALINFO plviGeneralInfo;
626       plviGeneralInfo = (LPLINEGENERALINFO)pLineGeneralInfoBytes;
627 
628       if(pLineGeneralInfoBytes != NULL) {
629          plviGeneralInfo->dwTotalSize = lineGeneralInfo.dwNeededSize;
630          if ((tapiresult = lineGetGeneralInfo(hLine, plviGeneralInfo)) != 0) {
631                       TCHAR szMsg[255];
632                       GetTAPIErrorMsg(szMsg,sizeof(szMsg), tapiresult);
633             MessageBox(NULL, szMsg, _T("Unmanaged"), MB_OK);
634          }
635          else {
636             LPTSTR tsManufacturer, tsModel, tsRevision, tsSerialNumber, tsSubscriberNumber;
637                            TCHAR szUnavailable[] = L"Unavailable";
638                            if(plviGeneralInfo->dwManufacturerSize) {
639                               tsManufacturer = (WCHAR*)(((BYTE*)plviGeneralInfo)+plviGeneralInfo->dwManufacturerOffset);
640                            }
641                            else {
642                               tsManufacturer = szUnavailable;
643                            }
644 
645                            if(plviGeneralInfo->dwModelSize)     {
646                               tsModel = (WCHAR*)(((BYTE*)plviGeneralInfo)+plviGeneralInfo->dwModelOffset);
647                            }
648                            else {
649                               tsModel = szUnavailable;
650                            }
651 
652                            if(plviGeneralInfo->dwRevisionSize)  {
653                               tsRevision = (WCHAR*)(((BYTE*)plviGeneralInfo)+plviGeneralInfo->dwRevisionOffset);
654                            }
655                            else {
656                               tsRevision = szUnavailable;
657                            }
658 
659                            if(plviGeneralInfo->dwSerialNumberSize) {
660                               tsSerialNumber = (WCHAR*)(((BYTE*)plviGeneralInfo)+plviGeneralInfo->dwSerialNumberOffset);
661                            }
662                            else {
663                               tsSerialNumber = szUnavailable;
664                            }
665 
666                            if(plviGeneralInfo->dwSubscriberNumberSize)
667                            {
668                               tsSubscriberNumber = (WCHAR*)(((BYTE*)plviGeneralInfo)+plviGeneralInfo->dwSubscriberNumberOffset);
669                            }
670                            else
671                            {
672                               tsSubscriberNumber = szUnavailable;
673                            }
674 
675             /* AFXSTR.H*/
676             /*typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;*/
677             /*
678             CString sInfo;
679                            sInfo.Format(L"Manufacturer: %s\nModel: %s\nRevision: %s\nSerial No: %s\nSubscriber No: %s\n",
680                                    tsManufacturer,
681                                    tsModel,
682                                    tsRevision,
683                                    tsSerialNumber,
684                                    tsSubscriberNumber);
685             */
686             char *imeiId = (char *)malloc(128);
687             strcpy(imeiId, ( ( (char*)plviGeneralInfo) + lineGeneralInfo.dwSerialNumberOffset));
688 
689             /*MessageBox(NULL, (LPCWSTR)( ( (char*)plviGeneralInfo) + lineGeneralInfo.dwSerialNumberOffset),  _T("Unmanaged"), MB_OK);*/
690 
691             delete plviGeneralInfo;
692             return imeiId;
693          }
694          delete plviGeneralInfo;
695       }
696   } /* for */
697   return 0;
698 #else

699    return strcpyAlloc("NotImplemented");
700 #endif

701 }
702 
703 #endif /*defined(_WINDOWS) || defined(WINCE)*/



syntax highlighted by Code2HTML, v. 0.9.1