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