Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 861 lines (754 sloc) 25.652 kb
a1a87f7 @antirez first commit
authored
1 /* Copyright (C) 2005 Pat Thoyts <patthoyts@users.sourceforge.net>
2 *
3 * Windows COM extension.
4 *
5 * Example:
6 * load jim-win32com
7 * set obj [ole32 createobject "SysInfo.SysInfo"]
8 * puts "OS Version: [ole32.invoke $obj OSVersion]"
9 * unset obj
10 *
11 * NOTES:
12 * We could use something ro register a shutdown function so that we can
13 * call CoUninitialize() on exit.
14 *
15 */
16
17
18 #define STRICT
19 #define WIN32_LEAN_AND_MEAN
20 #include <stdio.h>
21 #include <windows.h>
22 #include <ole2.h>
23 #include <tchar.h>
24 #include <assert.h>
25 #include <ctype.h>
26
27 #define JIM_EXTENSION
28 #include "jim.h"
29
30 #ifndef JIM_INTEGER_SPACE
31 #define JIM_INTEGER_SPACE 24
32 #endif
33
34 #if _MSC_VER >= 1000
35 #pragma comment(lib, "shell32")
36 #pragma comment(lib, "user32")
37 #pragma comment(lib, "advapi32")
38 #pragma comment(lib, "ole32")
39 #pragma comment(lib, "oleaut32")
40 #pragma comment(lib, "uuid")
41 #endif /* _MSC_VER >= 1000 */
42
43 static int Ole32_Create(Jim_Interp *interp, int objc, Jim_Obj *const objv[]);
44 static int Ole32_Foreach(Jim_Interp *interp, int objc, Jim_Obj *const objv[]);
45 static int Ole32_Finalizer(Jim_Interp *interp, int objc, Jim_Obj *const objv[]);
46 static int Ole32_GetObject(Jim_Interp *interp, int objc, Jim_Obj *const objv[]);
47 static int Ole32_GetActiveObject(Jim_Interp *interp, int objc, Jim_Obj *const objv[]);
48 static int Ole32_Invoke(Jim_Interp *interp, int objc, Jim_Obj *const objv[]);
49
50 /* ----------------------------------------------------------------------
51 * Debugging bits
52 */
53
54 #ifndef _DEBUG
55 #define JIM_ASSERT(x) ((void)0)
56 #define JIM_TRACE 1 ? ((void)0) : LocalTrace
57 #else /* _DEBUG */
58 #define JIM_ASSERT(x) if (!(x)) _assert(#x, __FILE__, __LINE__)
59 #define JIM_TRACE LocalTrace
60 #endif /* _DEBUG */
61
62 void
63 LocalTrace(LPCTSTR format, ...)
64 {
65 int n;
66 const int max = sizeof(TCHAR) * 512;
67 TCHAR buffer[512];
68 va_list args;
69 va_start (args, format);
70
71 n = _vsntprintf(buffer, max, format, args);
72 JIM_ASSERT(n < max);
73 OutputDebugString(buffer);
74 va_end(args);
75 }
76
77 /* ---------------------------------------------------------------------- */
78
79 static Jim_Obj *
80 Win32ErrorObj(Jim_Interp *interp, const char * szPrefix, DWORD dwError)
81 {
82 Jim_Obj *msgObj = NULL;
83 char * lpBuffer = NULL;
84 DWORD dwLen = 0;
85
86 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
87 | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, LANG_NEUTRAL,
88 (char *)&lpBuffer, 0, NULL);
89 if (dwLen < 1) {
90 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
91 | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
92 "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
93 (char *)&lpBuffer, 0, (va_list *)&dwError);
94 }
95
96 msgObj = Jim_NewStringObj(interp, szPrefix, -1);
97 if (dwLen > 0) {
98 char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */
99 for ( ; p && *p && isspace(*p); p--)
100 ;
101 *++p = 0;
102 Jim_AppendString(interp, msgObj, ": ", 2);
103 Jim_AppendString(interp, msgObj, lpBuffer, -1);
104 }
105 LocalFree((HLOCAL)lpBuffer);
106 return msgObj;
107 }
108
109 /* ----------------------------------------------------------------------
110 * Unicode strings
111 */
112
113 static void UnicodeFreeInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
114 static void UnicodeDupInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
115 static int UnicodeSetFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
116
117 Jim_ObjType unicodeObjType = {
118 "unicode",
119 UnicodeFreeInternalRep,
120 UnicodeDupInternalRep,
121 NULL, /*UpdateUnicodeStringProc*/
122 JIM_TYPE_REFERENCES,
123 };
124
125 static LPOLESTR
126 A2OLE(LPCSTR sz)
127 {
128 DWORD nChars = 0;
129 LPOLESTR wsz = NULL;
130 if (sz != NULL) {
131 nChars = MultiByteToWideChar(CP_ACP, 0, sz, -1, NULL, 0);
132 wsz = (LPOLESTR)Jim_Alloc((nChars + 1) * sizeof(OLECHAR));
133 if (wsz != NULL) {
134 nChars = MultiByteToWideChar(CP_ACP, 0, sz, nChars, wsz, nChars + 1);
135 wsz[nChars] = 0;
136 }
137 }
138 return wsz;
139 }
140
141 static LPSTR
142 OLE2A(LPCOLESTR wsz)
143 {
144 DWORD nChars = 0;
145 LPSTR sz = NULL;
146 if (wsz != NULL) {
147 nChars = WideCharToMultiByte(CP_ACP, 0, wsz, -1, NULL, 0, NULL, NULL);
148 sz = (LPSTR)Jim_Alloc((nChars + 1) * sizeof(CHAR));
149 if (sz != NULL) {
150 nChars = WideCharToMultiByte(CP_ACP, 0, wsz, nChars, sz, nChars+1, NULL, NULL);
151 sz[nChars] = 0;
152 }
153 }
154 return sz;
155 }
156
157 void
158 UnicodeFreeInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
159 {
160 JIM_NOTUSED(interp);
161
162 JIM_TRACE("UnicodeFreeInternalRep 0x%08x\n", (DWORD)objPtr);
163 Jim_Free(objPtr->internalRep.binaryValue.data);
164 objPtr->internalRep.binaryValue.data = NULL;
165 objPtr->internalRep.binaryValue.len = 0;
166 objPtr->typePtr = NULL;
167 }
168
169 /*
170 * string rep is copied and internal rep is duplicated.
171 */
172 void
173 UnicodeDupInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
174 {
175 int len = srcPtr->internalRep.binaryValue.len;
176 JIM_TRACE("UnicodeDupInternalRep 0x%08x duped into 0x%08x\n",
177 (DWORD)srcPtr, (DWORD)dupPtr);
178 interp = interp;
179 dupPtr->internalRep.binaryValue.len = len;
180 if (srcPtr->internalRep.binaryValue.data != NULL) {
181 dupPtr->internalRep.binaryValue.data =
182 Jim_Alloc(sizeof(WCHAR) * (len + 1));
183 wcsncpy((LPWSTR)dupPtr->internalRep.binaryValue.data,
184 (LPWSTR)srcPtr->internalRep.binaryValue.data, len);
185 }
186 }
187
188 int
189 UnicodeSetFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
190 {
191 int nChars;
192 LPWSTR wsz;
193
194 JIM_TRACE("UnicodeSetFromAny 0x%08x\n", (DWORD)objPtr);
195 Jim_GetString(objPtr, NULL);
196 Jim_FreeIntRep(interp, objPtr);
197
198 nChars = MultiByteToWideChar(CP_ACP, 0, objPtr->bytes, objPtr->length, NULL, 0);
199 wsz = Jim_Alloc((nChars + 1) * sizeof(WCHAR));
200 nChars = MultiByteToWideChar(CP_ACP, 0, objPtr->bytes, objPtr->length, wsz, nChars + 1);
201 wsz[nChars] = 0;
202
203 objPtr->internalRep.binaryValue.len = nChars;
204 objPtr->internalRep.binaryValue.data = (unsigned char *)wsz;
205 objPtr->typePtr = &unicodeObjType;
206 return JIM_OK;
207 }
208
209 Jim_Obj *
210 Jim_NewUnicodeObj(Jim_Interp *interp, LPCWSTR wsz, int len)
211 {
212 Jim_Obj *objPtr;
213 JIM_ASSERT(wsz != NULL);
214 if (wsz != NULL && len < 0)
215 len = wcslen(wsz);
216 if (wsz == NULL || len == 0) {
217 objPtr = Jim_NewStringObj(interp, "", 0);
218 objPtr->internalRep.binaryValue.data = NULL;
219 objPtr->internalRep.binaryValue.len = 0;
220 } else {
221 objPtr = Jim_NewObj(interp);
222 objPtr->internalRep.binaryValue.data = Jim_Alloc(sizeof(WCHAR) * (len + 1));
223 wcsncpy((LPWSTR)objPtr->internalRep.binaryValue.data, wsz, len);
224 ((LPWSTR)objPtr->internalRep.binaryValue.data)[len] = 0;
225 objPtr->internalRep.binaryValue.len = len;
226 objPtr->bytes = OLE2A(wsz);
227 objPtr->length = len;
228 }
229 objPtr->typePtr = &unicodeObjType;
230 return objPtr;
231 }
232
233 LPWSTR
234 Jim_GetUnicode(Jim_Obj *objPtr, int *lenPtr)
235 {
236 if (objPtr->typePtr != &unicodeObjType) {
237 if (UnicodeSetFromAny(NULL, objPtr) != JIM_OK) {
238 JIM_ASSERT("Jim_GetUnicode cannot convert item to unicode rep");
239 Jim_Panic(NULL, "Jim_GetUnicode cannot convert item to unicode rep",
240 objPtr->typePtr->name);
241 }
242 }
243 if (lenPtr != NULL)
244 *lenPtr = objPtr->internalRep.binaryValue.len;
245 return (LPWSTR)objPtr->internalRep.binaryValue.data;
246 }
247
248 /* ----------------------------------------------------------------------
249 * Package interp associated data
250 */
251
252 typedef struct Ole32PackageData {
253 Jim_HashTable table;
254 jim_wide uid;
255 } Ole32PackageData;
256
257 static void Ole32PackageDataDelete(Jim_Interp *interp, void *data)
258 {
259 Ole32PackageData *pkgPtr = (Ole32PackageData *)data;
260 Jim_FreeHashTable(&pkgPtr->table);
261 Jim_Free(data);
262 }
263
264 /* ----------------------------------------------------------------------
265 * Ole32 object hash table
266 */
267
268 typedef struct Ole32ObjectData {
269 DWORD refcount;
270 LPDISPATCH pdispatch;
271 LPTYPEINFO ptypeinfo;
272 } Ole32ObjectData;
273
274 static unsigned int Ole32HashTableHash(const void *key)
275 {
276 /*return Jim_DjbHashFunction(key, strlen(key));*/
277 unsigned int h = 5381;
278 size_t len = strlen(key);
279 while(len--)
280 h = (h + (h << 5)) ^ *((const char *)key)++;
281 return h;
282 }
283
284 static const void *Ole32HashTableCopyKey(void *privdata, const void *key)
285 {
286 int len = strlen(key);
287 char *copy = Jim_Alloc(len + 1);
288 JIM_NOTUSED(privdata);
289 memcpy(copy, key, len);
290 copy[len] = '\0';
291 return copy;
292 }
293
294 static int Ole32HashTableCompare(void *privdata, const void *key1, const void *key2)
295 {
296 JIM_NOTUSED(privdata);
297 return strcmp(key1, key2) == 0;
298 }
299
300 static void Ole32HashTableDestroyKey(void *privdata, const void *key)
301 {
302 JIM_NOTUSED(privdata);
303 Jim_Free((void*)key); /* ATTENTION: const cast */
304 }
305
306 static void Ole32HashTableDestroyValue(void *interp, void *val)
307 {
308 Ole32ObjectData *entryPtr = (Ole32ObjectData *)val;
309 JIM_NOTUSED(interp);
310 entryPtr->pdispatch->lpVtbl->Release(entryPtr->pdispatch);
311 if (entryPtr->ptypeinfo != NULL)
312 entryPtr->ptypeinfo->lpVtbl->Release(entryPtr->ptypeinfo);
313 Jim_Free((void*)entryPtr);
314 }
315
316 static Jim_HashTableType Ole32HashTableType = {
317 Ole32HashTableHash, /* hash function */
318 Ole32HashTableCopyKey, /* key dup */
319 NULL, /* val dup */
320 Ole32HashTableCompare, /* key compare */
321 Ole32HashTableDestroyKey, /* key destructor */
322 Ole32HashTableDestroyValue /* val destructor */
323 };
324
325 /* ---------------------------------------------------------------------- */
326
327 static void Ole32FreeInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
328 static void Ole32DupInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
329 static int Ole32SetFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
330 Jim_Obj *Jim_NewOle32Obj(Jim_Interp *interp, LPDISPATCH pdispatch);
331
332 #define Ole32_DispatchPtr(o) (((Ole32ObjectData *)((o)->internalRep.ptr))->pdispatch)
333 #define Ole32_TypeInfoPtr(o) (((Ole32ObjectData *)((o)->internalRep.ptr))->ptypeinfo)
334
335 Jim_ObjType ole32ObjType = {
336 "ole32",
337 Ole32FreeInternalRep,
338 Ole32DupInternalRep,
339 NULL,
340 JIM_TYPE_REFERENCES,
341 };
342
343 void
344 Ole32FreeInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
345 {
346 Ole32ObjectData *entryPtr;
347 entryPtr = objPtr->internalRep.ptr;
348 --entryPtr->refcount;
349 if (entryPtr->refcount == 0) {
350 //Ole32PackageData *pkgPtr = Jim_GetAssocData(interp, "ole32:package");
351 //Jim_DeleteHashEntry(&pkgPtr->table, objPtr->bytes);
352 JIM_TRACE("free ole32 object 0x%08x\n", entryPtr->pdispatch);
353 }
354 objPtr->internalRep.ptr = NULL;
355 }
356
357 void
358 Ole32DupInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
359 {
360 Ole32ObjectData *entryPtr;
361 JIM_NOTUSED(interp);
362
363 entryPtr = srcPtr->internalRep.ptr;
364 ++entryPtr->refcount;
365 dupPtr->internalRep.ptr = entryPtr;
366 JIM_TRACE("dup ole32 object 0x%08x from 0x%08x to 0x%08x\n", entryPtr->pdispatch, srcPtr, dupPtr);
367 }
368
369 int
370 Ole32SetFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
371 {
372 Ole32PackageData *pkgPtr;
373 Ole32ObjectData *entryPtr;
374
375 JIM_TRACE("Ole32SetFromAny from 0x%08x\n", objPtr);
376 if (objPtr->typePtr != &ole32ObjType) {
377 pkgPtr = Jim_GetAssocData(interp, "ole32:package");
378
379 Jim_GetString(objPtr, NULL);
380 entryPtr = (Ole32ObjectData *)Jim_FindHashEntry(&pkgPtr->table, objPtr->bytes);
381 if (entryPtr == NULL) {
382 Jim_SetResultString(interp, "not a ole32 object", -1);
383 return JIM_ERR;
384 }
385
386 Jim_FreeIntRep(interp, objPtr);
387 objPtr->internalRep.ptr = entryPtr;
388 ++entryPtr->refcount;
389 objPtr->typePtr = &ole32ObjType;
390 }
391 return JIM_OK;
392 }
393
394 static int
395 Ole32_Finalizer(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
396 {
397 //objv[1] == referencesobj.
398 JIM_TRACE("Ole32_Finalizer for %s\n", Jim_GetString(objv[1], NULL));
399 Jim_DeleteCommand(interp, Jim_GetString(objv[1], NULL));
400 return JIM_OK;
401 }
402
403 /*
404 * Jim_NewOle32Obj --
405 *
406 * This is the only way to create Ole32 objects in Jim. These
407 * hold a reference to the IDispatch interface of the COM
408 * object. We also attempt to acquire the typelibrary information
409 * if this is available. Objects with typeinfo know how many
410 * arguments are required for a method/property call and can
411 * manage without programmer hints.
412 *
413 * The string rep never changes and when this object is destroyed
414 * we release our COM references.
415 */
416 Jim_Obj *
417 Jim_NewOle32Obj(Jim_Interp *interp, LPDISPATCH pdispatch)
418 {
419 unsigned int n = 0;
420 jim_wide id;
421 char *name;
422 Jim_Obj *objPtr, *refPtr;
423 Ole32PackageData *pkgPtr;
424 Ole32ObjectData *entryPtr;
425
426 pkgPtr = Jim_GetAssocData(interp, "ole32:package");
427 id = pkgPtr->uid++;
428 name = Jim_Alloc(23);
429 sprintf(name, "ole32:%" JIM_WIDE_MODIFIER, id);
430 entryPtr = (Ole32ObjectData *)Jim_Alloc(sizeof(Ole32ObjectData));
431 entryPtr->pdispatch = pdispatch;
432 entryPtr->ptypeinfo = NULL;
433 entryPtr->refcount = 1;
434 pdispatch->lpVtbl->AddRef(pdispatch);
435
436 pdispatch->lpVtbl->GetTypeInfoCount(pdispatch, &n);
437 if (n != 0)
438 pdispatch->lpVtbl->GetTypeInfo(pdispatch, 0, LOCALE_SYSTEM_DEFAULT,
439 &entryPtr->ptypeinfo);
440
441 //Jim_AddHashEntry(&pkgPtr->table, name, entryPtr);
442 objPtr = Jim_NewStringObj(interp, name, -1);
443 objPtr->internalRep.ptr = entryPtr;
444 objPtr->typePtr = &ole32ObjType;
445
446 refPtr = Jim_NewReference(interp, objPtr, Jim_NewStringObj(interp, "ole32", -1),
447 Jim_NewStringObj(interp, "ole32.finalizer", -1));
448 if (Jim_CreateCommand(interp, Jim_GetString(refPtr, NULL), Ole32_Invoke,
449 objPtr->internalRep.ptr, NULL /*Ole32CmdDeleteProc*/) != JIM_OK) {
450 JIM_ASSERT(FALSE && "Its all going wrong");
451 }
452
453 JIM_TRACE("created ole32 object 0x%08x in Jim obj 0x%08x\n", pdispatch, objPtr);
454 return refPtr;
455 }
456
457 /* ---------------------------------------------------------------------- */
458
459 static DISPPARAMS*
460 Ole32_GetDispParams(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
461 {
462 DISPPARAMS * dp;
463 int cn;
464
465 dp = (DISPPARAMS*)Jim_Alloc(sizeof(DISPPARAMS));
466 if (dp != NULL) {
467 dp->cArgs = objc;
468 dp->cNamedArgs = 0;
469 dp->rgdispidNamedArgs = NULL;
470 dp->rgvarg = NULL;
471 if (objc > 0)
472 dp->rgvarg = (VARIANT*)Jim_Alloc(sizeof(VARIANT) * dp->cArgs);
473
474 /* Note: this array is filled backwards */
475 for (cn = 0; cn < objc; cn++) {
476 LPOLESTR olestr;
477 Jim_Obj *objPtr = objv[objc - cn - 1];
478 const char *type = NULL;
479
480 if (objPtr->typePtr != NULL)
481 type = objPtr->typePtr->name;
482
483 VariantInit(&dp->rgvarg[cn]);
484 if (type != NULL) {
485 if (strcmp(type, "int") == 0) {
486 Jim_GetLong(interp, objPtr, &(dp->rgvarg[cn].lVal));
487 dp->rgvarg[cn].vt = VT_I4;
488 } else if (strcmp(type, "double") == 0) {
489 Jim_GetDouble(interp, objPtr, &(dp->rgvarg[cn].dblVal));
490 dp->rgvarg[cn].vt = VT_R8;
491 }
492 }
493 if (dp->rgvarg[cn].vt == VT_EMPTY) {
494 olestr = A2OLE(Jim_GetString(objv[objc - cn - 1], NULL));
495 dp->rgvarg[cn].bstrVal = SysAllocString(olestr);
496 dp->rgvarg[cn].vt = VT_BSTR;
497 Jim_Free(olestr);
498 }
499 }
500 }
501 return dp;
502 }
503
504 static void
505 Ole32_FreeDispParams(DISPPARAMS *dp)
506 {
507 VARIANT *pv = dp->rgvarg;
508 size_t n;
509 for (n = 0; n < dp->cArgs; n++, pv++) {
510 VariantClear(pv);
511 }
512 Jim_Free(dp->rgvarg);
513 Jim_Free(dp);
514 }
515
516 static HRESULT
517 VariantToJim(Jim_Interp *interp, VARIANT v, Jim_Obj **resultPtr)
518 {
519 HRESULT hr = S_OK;
520
521 /*
522 * FIX ME: Needs to handle VT_ARRAY and VT_BYREF flags
523 */
524
525 switch (v.vt) {
526 case VT_BOOL:
527 *resultPtr = Jim_NewStringObj(interp, (v.boolVal == VARIANT_TRUE) ? "True" : "False", -1);
528 break;
529 case VT_I2:
530 *resultPtr = Jim_NewIntObj(interp, v.iVal);
531 break;
532 case VT_I4:
533 *resultPtr = Jim_NewIntObj(interp, v.lVal);
534 break;
535 case VT_R4:
536 *resultPtr = Jim_NewDoubleObj(interp, v.fltVal);
537 break;
538 case VT_R8:
539 *resultPtr = Jim_NewDoubleObj(interp, v.dblVal);
540 break;
541 case VT_UNKNOWN:
542 hr = VariantChangeType(&v, &v, 0, VT_DISPATCH);
543 if (SUCCEEDED(hr))
544 *resultPtr = Jim_NewOle32Obj(interp, v.pdispVal);
545 break;
546 case VT_DISPATCH:
547 *resultPtr = Jim_NewOle32Obj(interp, v.pdispVal);
548 break;
549 case VT_CY: case VT_DATE: case VT_DECIMAL:
550 default: {
551 hr = VariantChangeType(&v, &v, VARIANT_ALPHABOOL, VT_BSTR);
552 if (SUCCEEDED(hr))
553 *resultPtr = Jim_NewUnicodeObj(interp, v.bstrVal, -1);
554 }
555 }
556 return hr;
557 }
558
559 static int
560 Jim_GetIndexFromObj(Jim_Interp *interp, Jim_Obj *objPtr, const char **tablePtr,
561 const char *msg, int flags, int *indexPtr)
562 {
563 const char **entryPtr = NULL;
564 const char *p1, *p2;
565 const char *key = Jim_GetString(objPtr, NULL);
566 int i;
567 JIM_NOTUSED(msg);
568 JIM_NOTUSED(flags);
569
570 *indexPtr = -1;
571 for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
572 for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) {
573 if (*p1 == '\0') {
574 *indexPtr = i;
575 return JIM_OK;
576 }
577 }
578 }
579 Jim_SetResultString(interp, "needs a better message", -1);
580 return JIM_ERR;
581 }
582
583 /* $object method|prop ?args...? */
584 static int
585 Ole32_Invoke(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
586 {
587 HRESULT hr = S_OK;
588 LPWSTR name;
589 DISPID dispid;
590 LPDISPATCH pdisp;
591 Jim_Obj *resultObj = NULL;
592 Ole32ObjectData *ole32Ptr = (Ole32ObjectData*)Jim_CmdPrivData(interp);
593 int optind, argc = 1;
594 WORD mode = DISPATCH_PROPERTYGET | DISPATCH_METHOD;
595 static const char *options[] = {"-get", "-put", "-putref", "-call", NULL };
596 enum { OPT_GET, OPT_PUT, OPT_PUTREF, OPT_CALL };
597
598 if (objc < 2) {
599 Jim_WrongNumArgs(interp, 1, objv, "?options? method|property ?args ...?");
600 return JIM_ERR;
601 }
602
603 if (Jim_GetEnum(interp, objv[1], options, &optind, NULL, 0) == JIM_OK) {
604 argc++;
605 switch (optind) {
606 case OPT_GET: mode = DISPATCH_PROPERTYGET; break;
607 case OPT_PUT: mode = DISPATCH_PROPERTYPUT; break;
608 case OPT_PUTREF: mode = DISPATCH_PROPERTYPUTREF; break;
609 case OPT_CALL: mode = DISPATCH_METHOD; break;
610 }
611 }
612
613 /*
614 if (objv[argc]->typePtr != &ole32ObjType) {
615 if (Ole32SetFromAny(interp, objv[argc]) != JIM_OK) {
616 Jim_SetResultString(interp, "first argument must be a ole32 created object", -1);
617 return JIM_ERR;
618 }
619 }
620 */
621
622 pdisp = ole32Ptr->pdispatch; // Ole32_DispatchPtr(objv[argc]);
623 name = Jim_GetUnicode(objv[argc], NULL);
624 hr = pdisp->lpVtbl->GetIDsOfNames(pdisp, &IID_NULL, &name, 1,
625 LOCALE_SYSTEM_DEFAULT, &dispid);
626
627 {
628 VARIANT v;
629 EXCEPINFO ei;
630 DISPPARAMS *dp = NULL;
631 UINT uierr;
632
633 VariantInit(&v);
634 dp = Ole32_GetDispParams(interp, objc-(argc+1), objv+argc+1);
635
636 if (mode & DISPATCH_PROPERTYPUT || mode & DISPATCH_PROPERTYPUTREF) {
637 static DISPID putid = DISPID_PROPERTYPUT;
638 dp->rgdispidNamedArgs = &putid;
639 dp->cNamedArgs = 1;
640 }
641
642 hr = pdisp->lpVtbl->Invoke(pdisp, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, mode, dp, &v, &ei, &uierr);
643 Ole32_FreeDispParams(dp);
644
645 if (SUCCEEDED(hr)) {
646 hr = VariantToJim(interp, v, &resultObj);
647 }
648 VariantClear(&v);
649 }
650
651 if (FAILED(hr))
652 resultObj = Win32ErrorObj(interp, "dispatch", (DWORD)hr);
653 Jim_SetResult(interp, resultObj);
654 return SUCCEEDED(hr) ? JIM_OK : JIM_ERR;
655 }
656
657 /* ---------------------------------------------------------------------- */
658
659 static void
660 Ole32CmdDeleteProc(void *privData)
661 {
662 Ole32ObjectData *ole32Ptr = (Ole32ObjectData *)privData;
663 ole32Ptr->pdispatch->lpVtbl->Release(ole32Ptr->pdispatch);
664 Jim_Free(privData);
665 }
666
667 /* ---------------------------------------------------------------------- */
668
669 static int
670 Ole32_Create(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
671 {
672 HRESULT hr = S_OK;
673 IDispatch *pdisp = NULL;
674 CLSID clsid;
675
676 if (objc != 2) {
677 Jim_WrongNumArgs(interp, 1, objv, "progid");
678 return JIM_ERR;
679 }
680
681 hr = CLSIDFromProgID(Jim_GetUnicode(objv[1], NULL), &clsid);
682 if (SUCCEEDED(hr))
683 hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER,
684 &IID_IDispatch, (LPVOID*)&pdisp);
685 if (SUCCEEDED(hr)) {
686 Jim_SetResult(interp, Jim_NewOle32Obj(interp, pdisp));
687 pdisp->lpVtbl->Release(pdisp);
688 } else {
689 Jim_SetResult(interp, Win32ErrorObj(interp, "CreateObject", hr));
690 }
691 return SUCCEEDED(hr) ? JIM_OK : JIM_ERR;
692 }
693
694 static int
695 Ole32_GetActiveObject(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
696 {
697 HRESULT hr = S_OK;
698 LPUNKNOWN punk = NULL;
699 CLSID clsid;
700
701 if (objc != 2) {
702 Jim_WrongNumArgs(interp, 1, objv, "progid");
703 return JIM_ERR;
704 }
705
706 hr = CLSIDFromProgID(Jim_GetUnicode(objv[1], NULL), &clsid);
707 if (SUCCEEDED(hr))
708 hr = GetActiveObject(&clsid, NULL, &punk);
709 if (SUCCEEDED(hr)) {
710 LPDISPATCH pdisp;
711 hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, (LPVOID*)&pdisp);
712 if (SUCCEEDED(hr)) {
713 Jim_SetResult(interp, Jim_NewOle32Obj(interp, pdisp));
714 pdisp->lpVtbl->Release(pdisp);
715 }
716 punk->lpVtbl->Release(punk);
717 }
718 if (FAILED(hr))
719 Jim_SetResult(interp, Win32ErrorObj(interp, "GetActiveObject", hr));
720 return SUCCEEDED(hr) ? JIM_OK : JIM_ERR;
721 }
722
723 static int
724 Ole32_GetObject(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
725 {
726 HRESULT hr = S_OK;
727 LPDISPATCH pdisp = NULL;
728 LPCOLESTR name;
729
730 if (objc != 2) {
731 Jim_WrongNumArgs(interp, 1, objv, "progid");
732 return JIM_ERR;
733 }
734
735 name = Jim_GetUnicode(objv[1], NULL);
736 hr = CoGetObject(name, NULL, &IID_IDispatch, (LPVOID*)&pdisp);
737 if (SUCCEEDED(hr)) {
738 Jim_SetResult(interp, Jim_NewOle32Obj(interp, pdisp));
739 pdisp->lpVtbl->Release(pdisp);
740 }
741 if (FAILED(hr))
742 Jim_SetResult(interp, Win32ErrorObj(interp, "GetObject", hr));
743 return SUCCEEDED(hr) ? JIM_OK : JIM_ERR;
744 }
745
746 /* ole32.foreach varname $object body */
747 static int
748 Ole32_Foreach(Jim_Interp *interp, int objc, Jim_Obj *const objv[])
749 {
750 HRESULT hr = S_OK;
751 IDispatch *pdisp;
752 VARIANT vEnum;
753 DISPPARAMS dpNull = {NULL, NULL, 0, 0};
754 int result = JIM_OK;
755
756 if (objc != 4) {
757 Jim_WrongNumArgs(interp, 1, objv, "varname ole32object script");
758 return JIM_ERR;
759 }
760
761 if (objv[2]->typePtr != &ole32ObjType) {
762 Jim_SetResultString(interp, "second argument must be a ole32 created object", -1);
763 return JIM_ERR;
764 }
765
766 VariantInit(&vEnum);
767 pdisp = Ole32_DispatchPtr(objv[2]);
768 hr = pdisp->lpVtbl->Invoke(pdisp, DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
769 DISPATCH_PROPERTYGET, &dpNull, &vEnum, NULL, NULL);
770 if (SUCCEEDED(hr)) {
771 IEnumVARIANT *pEnum;
772 hr = vEnum.punkVal->lpVtbl->QueryInterface(vEnum.punkVal, &IID_IEnumVARIANT, (LPVOID*)&pEnum);
773 if (SUCCEEDED(hr)) {
774 HRESULT hrLoop = S_OK;
775 ULONG n, cbElt;
776 VARIANT rgVar[16];
777 for (n = 0; n < 16; n++) VariantInit(&rgVar[n]);
778 do {
779 hrLoop = pEnum->lpVtbl->Next(pEnum, 16, rgVar, &cbElt);
780 for (n = 0; SUCCEEDED(hr) && n < cbElt; n++) {
781 Jim_Obj *valPtr = NULL;
782 hr = VariantToJim(interp, rgVar[n], &valPtr);
783 if (SUCCEEDED(hr)) {
784 Jim_SetVariable(interp, objv[1], valPtr);
785 switch (result = Jim_EvalObj(interp, objv[3])) {
786 case JIM_OK: case JIM_CONTINUE: break;
787 case JIM_BREAK:
788 default:
789 goto break_for;
790 }
791 }
792 }
793 break_for:
794 for (n = 0; n < cbElt; n++) VariantClear(&rgVar[n]);
795 } while ((result == JIM_OK || result == JIM_CONTINUE) && hrLoop == S_OK && SUCCEEDED(hr));
796 pEnum->lpVtbl->Release(pEnum);
797 }
798 VariantClear(&vEnum);
799 }
800 if (FAILED(hr))
801 Jim_SetResult(interp, Win32ErrorObj(interp, "ole32.foreach", (DWORD)hr));
802 if (result == JIM_BREAK) result = JIM_OK;
803 return SUCCEEDED(hr) ? result : JIM_ERR;
804 }
805
806 /* ---------------------------------------------------------------------- */
807 static Jim_ObjType origCommandObjType;
808 static Jim_ObjType ole32CommandObjType;
809
810 void Ole32CommandFreeIntRep(Jim_Interp *interp, Jim_Obj *objPtr)
811 {
812 if (origCommandObjType.freeIntRepProc != NULL)
813 origCommandObjType.freeIntRepProc(interp, objPtr);
814 }
815
816
817 DLLEXPORT int
818 Jim_OnLoad(Jim_Interp *interp)
819 {
820 HRESULT hr;
821 Ole32PackageData *pkgPtr;
822 //Jim_ObjType *commandObjType;
823
824 Jim_InitExtension(interp);
825 if (Jim_PackageProvide(interp, "win32com", "1.0", JIM_ERRMSG) != JIM_OK)
826 return JIM_ERR;
827
828 hr = CoInitialize(0);
829 if (FAILED(hr)) {
830 Jim_SetResult(interp,
831 Win32ErrorObj(interp, "CoInitialize", (DWORD)hr));
832 return JIM_ERR;
833 }
834
835 pkgPtr = (Ole32PackageData *)Jim_Alloc(sizeof(Ole32PackageData));
836 pkgPtr->uid = 0;
837 Jim_InitHashTable(&pkgPtr->table, &Ole32HashTableType, interp);
838 Jim_SetAssocData(interp, "ole32:package", Ole32PackageDataDelete, pkgPtr);
839
840 /*
841 commandObjType = Jim_GetObjType(interp, "command");
842 memcpy(&origCommandObjType, commandObjType, sizeof(Jim_ObjType));
843 memcpy(&ole32CommandObjType, commandObjType, sizeof(Jim_ObjType));
844 ole32CommandObjType.freeIntRepProc = Ole32CommandFreeIntRep;
845 memcpy(commandObjType, &ole32CommandObjType, sizeof(Jim_ObjType));
846 */
847
848 Jim_CreateCommand(interp, "ole32.create", Ole32_Create, NULL, NULL);
849 Jim_CreateCommand(interp, "ole32.invoke", Ole32_Invoke, NULL, NULL);
850 Jim_CreateCommand(interp, "ole32.foreach", Ole32_Foreach, NULL, NULL);
851 Jim_CreateCommand(interp, "ole32.finalizer", Ole32_Finalizer, NULL, NULL);
852 return JIM_OK;
853 }
854
855 /* ----------------------------------------------------------------------
856 * Local variables:
857 * mode: c
858 * indent-tabs-mode: nil
859 * End:
860 */
Something went wrong with that request. Please try again.