root/trunk/activex/activex.d

Revision 39, 12.9 kB (checked in by l8night, 3 years ago)

setup the keywords on all files, and got the activex lib building

  • Property svn:mergeinfo set to
  • Property svn:keywords set to Date Revision Author HeadURL Id
Line 
1 module activex;
2 /***************************************************************
3  * $HeadURL$
4  * $Revision$
5  * $Date$
6  * $Author$
7  */
8
9 private:
10 import std.array; /* for ArrayBoundsError */
11 import std.stdarg;
12 import std.string;
13 import std.utf;
14 import std.stdio; /* for writefln */
15
16 import win32.api;
17 import win32.com.oaidl; /* for VARIANTARG */
18
19 pragma(lib, "win32.lib");
20 pragma(lib, "uuid.lib");
21
22 pragma(lib, "ole32.lib");
23 /* for _CLSIDFromProgID@8, _CoCreateInstance@20, _CoInitialize@4, _CoUninitialize@0 */
24
25 pragma(lib, "oleaut32.lib");
26 /* for _SysFreeString@4, _SysAllocString@4 */
27
28 public:
29 class AXO
30 {
31     private static LCID defaultLCID;
32
33     static this()
34     {
35         defaultLCID = GetUserDefaultLCID();
36         CoInitialize(null);
37     }
38
39     static ~this()
40     {
41         CoUninitialize();
42     }
43
44     struct MemberDef
45     {
46         char [] name;
47         DISPID dispid;
48         INVOKEKIND invkind;
49         FUNCDESC * pFuncDesc;
50     }
51
52     private ITypeInfo [FUNCDESC *] allFuncDescs;
53     private ITypeInfo typeInfo;
54     private IDispatch pIDispatch;
55     private MemberDef [] allMembers;
56     private char[] [ DISPID ] methods;
57     private char[] [ DISPID ] getters;
58         private SHORT [ DISPID ] returns;
59     private char[] [ DISPID ] setters;
60     private char[] [ DISPID ] settersbyref;
61
62     this(char [] appName)
63     {
64         const(wchar)* prog = toUTF16z(appName);
65         CLSID clsid;
66         HRESULT hr = CLSIDFromProgID(cast(wchar*)prog, &clsid);
67         hr = CoCreateInstance(&clsid, null, CLSCTX_SERVER, &IID_IDispatch, cast(void**)&pIDispatch);
68         loadMembers();
69     }
70
71     ~this()
72     {
73         foreach ( const(FUNCDESC) * pFuncDesc, ITypeInfo ti; allFuncDescs)
74             ti.ReleaseFuncDesc(cast(FUNCDESC *)pFuncDesc);
75     }
76
77     void loadMembers()
78     {
79         HRESULT hr = pIDispatch.GetTypeInfo(0,defaultLCID, &typeInfo);
80         loadMembers(typeInfo);
81     }
82
83     void loadMembers(ITypeInfo pTypeInfo)
84     {
85         TYPEATTR * pTypeAttr;
86         HRESULT hr = pTypeInfo.GetTypeAttr(&pTypeAttr);
87
88         for(uint i;i<pTypeAttr.cImplTypes;++i)
89         {
90             HREFTYPE pRefType;
91             hr = pTypeInfo.GetRefTypeOfImplType(i,&pRefType);
92             ITypeInfo  ppTInfo;
93             hr = pTypeInfo.GetRefTypeInfo(pRefType,&ppTInfo);
94             loadMembers(ppTInfo);
95         }
96
97         for(uint i;i<pTypeAttr.cFuncs;++i)
98         {
99             MemberDef mem;
100             hr = pTypeInfo.GetFuncDesc(i,& mem.pFuncDesc);
101             FUNCDESC * pFuncDesc=mem.pFuncDesc;
102
103             allFuncDescs[pFuncDesc] = pTypeInfo;
104
105             wchar * methodName;
106             hr = pTypeInfo.GetDocumentation(pFuncDesc.memid, &methodName, null, null, null);
107
108             wchar [] tmp;
109             uint l=wcslen(methodName);
110             tmp.length=l;
111             for (uint j;j<l;++j)
112                 tmp[j]=methodName[j];
113             immutable(char []) theName_i=toUTF8(tmp);
114             char [] theName = theName_i.dup;
115
116             mem.name=theName;
117             mem.invkind=pFuncDesc.invkind;
118
119             DISPID dispid/* = pFuncDesc.memid*/;
120             //*
121             hr = pIDispatch.GetIDsOfNames(cast(REFIID) &IID_NULL, &methodName, 1, defaultLCID, &dispid);
122             mem.dispid=dispid;
123             /**/
124             allMembers ~= mem;
125             SysFreeString (methodName);
126
127             switch (mem.invkind)
128             {
129                 case INVOKE_FUNC:
130                     methods[dispid] = theName;
131                     break;
132                 case INVOKE_PROPERTYGET:
133                     getters[dispid] = theName;
134                     returns[dispid] = pFuncDesc.lprgelemdescParam[0].tdesc.vt;
135                     break;
136                 case INVOKE_PROPERTYPUT:
137                     setters[dispid] = theName;
138                     break;
139                 case INVOKE_PROPERTYPUTREF:
140                     settersbyref[dispid] = theName;
141                     break;
142                 default:
143             }
144         }
145
146         pTypeInfo.ReleaseTypeAttr(pTypeAttr);
147     }
148
149     public void showMembers()
150     {
151
152         writefln("\nmethods");     
153         foreach(char[] key; methods)
154             writefln("\t%s", key);
155
156         writefln("\ngetters");
157         foreach(DISPID value, char[] key; getters)
158             writefln("\t%s", key);
159
160         writefln("\nsetters");
161         foreach(DISPID value, char[] key; setters)
162             writefln("\t%s", key);
163
164         writefln("\nsettersbyref");
165         foreach(DISPID value, char[] key; settersbyref)
166             writefln("\t%s", key);
167
168 /+     
169     private SHORT [ DISPID ] returns;
170 +/
171        
172     }
173    
174     VARIANTARG [] makeArray(TypeInfo [] args, void* ptr)
175     {
176         VARIANTARG [] array;
177         array.length = args.length;
178
179         for (uint i;i<args.length;++i)
180         {
181             if (args[i] == typeid(VARIANTARG))
182                 array [i] = va_arg!(VARIANTARG)(ptr);
183             else
184                 throw new Exception( "Expected arguments of type VARIANTARG" );
185         }
186
187         return array;
188     }
189
190     private DISPID findMember(char [] member, INVOKEKIND ik)
191     {
192         INVOKEKIND tmp=0xffff;
193         foreach(inout MemberDef mem; allMembers)
194             if (mem.name==member)
195                 if (mem.invkind==ik)
196                     return mem.dispid;
197                 else
198                     tmp=mem.invkind;
199
200         if (tmp==0xffff)
201             throw new Exception(format("no such member '%s'",member));
202         else
203             throw new Exception(format("member '%s' found with INVOKEKIND %s",member,tmp));
204     }
205
206     VARIANT get(char [] member)
207     {
208         INVOKEKIND ik=INVOKE_PROPERTYGET;
209         DISPID dispid = findMember(member,ik);
210
211         if (!(dispid in getters))
212             throw new Exception("can only get properties");
213
214         DISPPARAMS param;
215         VARIANT result;
216         HRESULT hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, defaultLCID,
217                                        ik, &param, &result, null, null);
218         return result;
219     }
220
221     void set(char [] member,VARIANTARG arg)
222     {
223         INVOKEKIND ik=INVOKE_PROPERTYPUT;
224         DISPID dispid = findMember(member,ik);
225
226         if (!(dispid in setters))
227             throw new Exception("can only set properties");
228
229         VARIANTARG [] myArgs = (&arg)[0..1];
230
231         DISPPARAMS param;
232         param.cArgs=myArgs.length;
233         param.rgvarg=myArgs.ptr;
234
235         DISPID dispidNamed = DISPID_PROPERTYPUT;
236         param.cNamedArgs = 1;
237         param.rgdispidNamedArgs = &dispidNamed;
238
239         HRESULT hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, defaultLCID,
240                                        ik, &param, null, null, null);
241     }
242
243     void setByRef(char [] member,VARIANTARG arg)
244     {
245         INVOKEKIND ik=INVOKE_PROPERTYPUTREF;
246         DISPID dispid = findMember(member,ik);
247
248         if (!(dispid in settersbyref))
249             throw new Exception("can only set properties");
250
251         VARIANTARG [] myArgs = (&arg)[0..1];
252
253         DISPPARAMS param;
254         param.cArgs=myArgs.length;
255         param.rgvarg=myArgs.ptr;
256
257         DISPID dispidNamed = DISPID_PROPERTYPUT;
258         param.cNamedArgs = 1;
259         param.rgdispidNamedArgs = &dispidNamed;
260
261         VARIANT * result;
262         HRESULT hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, defaultLCID,
263                                        ik, &param, result, null, null);
264     }
265
266     VARIANT call(char [] member,...)
267     {
268
269         /* Can I change the char[] into a variant? */
270
271
272         INVOKEKIND ik = INVOKE_FUNC;
273         DISPID dispid = findMember(member,ik);
274
275         if (!(dispid in methods))
276             throw new Exception("can only call methods");
277
278         VARIANTARG [] myArgs = makeArray(_arguments,_argptr);
279
280         DISPPARAMS param;
281         param.cArgs=myArgs.length;
282         param.rgvarg=myArgs.ptr;
283
284         debug writef("Calling %s...", member);
285        
286         VARIANT result;
287         HRESULT hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, defaultLCID,
288                                        ik, &param, &result, null, null);
289         return result;
290     }
291 }
292
293
294
295
296 VARIANTARG toVariant(...)
297 {
298     VARIANTARG variant;
299
300     if (_arguments.length < 1)
301         return VARIANT.init;
302
303     if(_arguments.length == 1)
304     {
305
306         /* Strings */
307
308         if (_arguments[0] == typeid(wchar[]))
309         {
310             debug writef("wchar[]\t");
311             variant.n1.n2.vt = VT_BSTR;
312             variant.n1.n2.n3.bstrVal = cast(wchar*) (va_arg!(char[])(_argptr) ~ "\0");
313         }
314
315         else if (_arguments[0] == typeid(char[]))
316         {
317             debug writef("char[]\t");
318             variant.n1.n2.vt = VT_BSTR;
319             immutable(wchar)[] buf = std.utf.toUTF16(va_arg!(char[])(_argptr) ~ "\0");
320             variant.n1.n2.n3.bstrVal = SysAllocString( cast(wchar*)(buf.ptr) );
321         }
322
323
324         /* Unsigned Integers */
325
326         else if (_arguments[0] == typeid(bool))
327         {
328             debug writef("bool\t");
329             variant.n1.n2.vt = VT_BOOL;           
330             if(va_arg!(bool)(_argptr) == true)
331                 variant.n1.n2.n3.boolVal = 1;
332             else
333                 variant.n1.n2.n3.boolVal = 0;               
334         }
335         else if (_arguments[0] == typeid(ubyte))
336         {
337             debug writef("ubyte\t");
338             variant.n1.n2.vt = VT_UI1; /* I'm not sure about this. */
339             variant.n1.n2.n3.bVal = va_arg!(ubyte)(_argptr);
340         }
341         else if (_arguments[0] == typeid(ushort))
342         {
343             debug writef("ushort\t");
344             variant.n1.n2.vt = VT_UI2; /* I'm not sure about this. */
345             variant.n1.n2.n3.uiVal = va_arg!(ushort)(_argptr);
346         }
347         else if (_arguments[0] == typeid(uint))
348         {
349             debug writef("uint\t");
350             variant.n1.n2.vt = VT_UI4; /* I'm not sure about this. */
351             variant.n1.n2.n3.ulVal = va_arg!(uint)(_argptr);
352         }
353         else if (_arguments[0] == typeid(ulong)) /* 8 bits */
354         {
355             debug writef("ulong\t");
356             variant.n1.n2.vt = VT_UI4; /* 4 bits -- long won't fit! */
357             variant.n1.n2.n3.lVal = va_arg!(ulong)(_argptr);
358         }
359
360
361         /* Signed Integers */
362
363         else if (_arguments[0] == typeid(byte))
364         {
365             debug writef("byte\t");
366             variant.n1.n2.vt = VT_I1; /* I'm not sure about this. */
367             variant.n1.n2.n3. cVal = va_arg!(byte)(_argptr);
368         }
369         else if (_arguments[0] == typeid(short))
370         {
371             debug writef("short\t");
372             variant.n1.n2.vt = VT_I2;
373             variant.n1.n2.n3.iVal = va_arg!(short)(_argptr);
374         }
375         else if (_arguments[0] == typeid(int))
376         {
377             debug writef("int\t");
378             variant.n1.n2.vt = VT_I4;
379             variant.n1.n2.n3.lVal = va_arg!(int)(_argptr);
380         }
381         else if (_arguments[0] == typeid(long)) /* 8 bits */
382         {
383             debug writef("long\t");
384             variant.n1.n2.vt = VT_I4; /* 4 bits -- long might not fit! */
385             variant.n1.n2.n3.lVal = cast(int) va_arg!(long)(_argptr);
386         }
387
388
389         /* Floating Point */
390
391         else if (_arguments[0] == typeid(float))
392         {
393             debug writef("float\t");
394             variant.n1.n2.vt = VT_R4;
395             variant.n1.n2.n3.fltVal = va_arg!(float)(_argptr);
396         }
397         else if (_arguments[0] == typeid(double))
398         {
399             debug writef("double\t");
400             variant.n1.n2.vt = VT_R8;
401             variant.n1.n2.n3.dblVal = va_arg!(double)(_argptr);
402         }
403
404
405         /* objects */
406
407         else if (_arguments[0] == typeid(Object))
408             /* need to be an AXO to work right now */
409         {
410             debug writef("object\t");
411             variant.n1.n2.vt = VT_BYREF; //VT_STORED_OBJECT; /* I doubt this is right. */
412             variant.n1.n2.n3.byref = cast(void*)( va_arg!(Object)(_argptr) );
413                 /* need to get some kind of pointer from the AXO object */
414         }
415        
416
417         else
418             throw new Exception("toVariant doesn't know what to do with it.");
419
420     }
421     else
422         throw new Exception("[unimplemented feature] toVariant can't use more than one arguemnt yet");
423
424     return variant;
425 }
426
427
428
429 extern(C)
430 int wcslen(wchar*);
431
432 extern(Windows)
433 {
434     alias uint tagINVOKEKIND;
435     alias tagINVOKEKIND INVOKEKIND;
436     enum :INVOKEKIND
437     {
438         INVOKE_FUNC    = 1,
439         INVOKE_PROPERTYGET    = 2,
440         INVOKE_PROPERTYPUT    = 4,
441         INVOKE_PROPERTYPUTREF    = 8
442     }
443
444     const WORD DISPATCH_METHOD = 0x1;
445     const WORD DISPATCH_PROPERTYGET = 0x2;
446     const WORD DISPATCH_PROPERTYPUT = 0x4;
447     const WORD DISPATCH_PROPERTYPUTREF = 0x8;
448     alias GUID_NULL IID_NULL;
449
450     HRESULT CLSIDFromProgID (LPCOLESTR lpszProgID, CLSID * lpclsid);
451     LCID GetUserDefaultLCID();
452     BSTR SysAllocString(OLECHAR *);
453     void SysFreeString(wchar*);
454     DWORD FormatMessageA(DWORD dwFlags,LPCVOID lpSource,DWORD dwMessageId,DWORD dwLanguageId,LPSTR lpBuffer,DWORD nSize,va_list *Arguments);
455 }
Note: See TracBrowser for help on using the browser.