- better loading of *.tlb files
[wine.git] / dlls / oleaut32 / typelib.c
blob8cdd9a2ecba7a91b91012cc9df671553663fdec9
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * there is much left to do here before it can be useful for real world
7 * programs
8 * know problems:
9 * -. Only one format of typelibs is supported
10 * -. All testing so far is done using special written windows programs
11 * -. Data structures are straightforward, but slow for look-ups.
12 * -. (related) nothing is hashed
13 * -. a typelib is always read in its entirety into memory and never released.
14 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
15 * of them I don't know yet how to implement them.
16 * -. Most error return values are just guessed not checked with windows
17 * behaviour.
18 * -. all locale stuff ignored
19 * -. move stuff to wine/dlls
20 * -. didn't bother with a c++ interface
21 * -. lousy fatal error handling
22 * -. some methods just return pointers to internal data structures, this is
23 * partly laziness, partly I want to check how windows does it.
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <assert.h>
31 #include "winerror.h"
32 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
33 #include "winnls.h" /* for PRIMARYLANGID */
34 #include "wine/winbase16.h" /* for RegQueryValue16(HKEY,LPSTR,LPSTR,LPDWORD) */
35 #include "heap.h"
36 #include "wine/obj_base.h"
37 #include "debugtools.h"
38 #include "winversion.h"
39 #include "typelib.h"
41 DEFAULT_DEBUG_CHANNEL(ole);
42 DECLARE_DEBUG_CHANNEL(typelib);
44 /****************************************************************************
45 * QueryPathOfRegTypeLib16 [TYPELIB.14]
47 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
48 * RETURNS
49 * path of typelib
51 HRESULT WINAPI
52 QueryPathOfRegTypeLib16(
53 REFGUID guid, /* [in] referenced guid */
54 WORD wMaj, /* [in] major version */
55 WORD wMin, /* [in] minor version */
56 LCID lcid, /* [in] locale id */
57 LPBSTR16 path /* [out] path of typelib */
58 ) {
59 char xguid[80];
60 char typelibkey[100],pathname[260];
61 DWORD plen;
63 TRACE("\n");
65 if (HIWORD(guid)) {
66 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
67 guid->Data1, guid->Data2, guid->Data3,
68 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
69 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
70 wMaj,wMin,lcid);
71 } else {
72 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
73 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
74 return E_FAIL;
76 plen = sizeof(pathname);
77 if (RegQueryValue16(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
78 /* try again without lang specific id */
79 if (SUBLANGID(lcid))
80 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
81 FIXME("key %s not found\n",typelibkey);
82 return E_FAIL;
84 *path = SysAllocString16(pathname);
85 return S_OK;
88 /****************************************************************************
89 * QueryPathOfRegTypeLib [OLEAUT32.164]
90 * RETURNS
91 * path of typelib
93 HRESULT WINAPI
94 QueryPathOfRegTypeLib(
95 REFGUID guid, /* [in] referenced guid */
96 WORD wMaj, /* [in] major version */
97 WORD wMin, /* [in] minor version */
98 LCID lcid, /* [in] locale id */
99 LPBSTR path /* [out] path of typelib */
101 char xguid[80];
102 char typelibkey[100],pathname[260];
103 DWORD plen;
105 TRACE("\n");
107 if (HIWORD(guid)) {
108 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
109 guid->Data1, guid->Data2, guid->Data3,
110 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
111 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
112 wMaj,wMin,lcid);
113 } else {
114 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
115 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n",xguid,wMaj,wMin,(DWORD)lcid,path);
116 return E_FAIL;
118 plen = sizeof(pathname);
119 if (RegQueryValue16(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
120 /* try again without lang specific id */
121 if (SUBLANGID(lcid))
122 return QueryPathOfRegTypeLib(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
123 FIXME("key %s not found\n",typelibkey);
124 return E_FAIL;
126 *path = HEAP_strdupAtoW(GetProcessHeap(),0,pathname);
127 return S_OK;
130 /******************************************************************************
131 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
132 * NOTES
133 * Docs: OLECHAR FAR* szFile
134 * Docs: iTypeLib FAR* FAR* pptLib
136 * RETURNS
137 * Success: S_OK
138 * Failure: Status
140 HRESULT WINAPI LoadTypeLib16(
141 LPOLESTR szFile, /* [in] Name of file to load from */
142 void * *pptLib) /* [out] Pointer to pointer to loaded type library */
144 FIXME("('%s',%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
146 if (pptLib!=0)
147 *pptLib=0;
149 return E_FAIL;
152 /******************************************************************************
153 * LoadTypeLib [OLEAUT32.161]
154 * Loads and registers a type library
155 * NOTES
156 * Docs: OLECHAR FAR* szFile
157 * Docs: iTypeLib FAR* FAR* pptLib
159 * RETURNS
160 * Success: S_OK
161 * Failure: Status
163 int TLB_ReadTypeLib(PCHAR file, ITypeLib2 **ppTypelib);
165 HRESULT WINAPI LoadTypeLib(
166 OLECHAR *szFile, /* [in] Name of file to load from */
167 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
169 TRACE("\n");
170 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
173 /******************************************************************************
174 * LoadTypeLibEx [OLEAUT32.183]
175 * Loads and optionally registers a type library
177 * RETURNS
178 * Success: S_OK
179 * Failure: Status
181 HRESULT WINAPI LoadTypeLibEx(
182 LPOLESTR szFile, /* [in] Name of file to load from */
183 REGKIND regkind, /* specify kind of registration */
184 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
186 LPSTR p;
187 HRESULT res;
188 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
190 p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile);
192 if(regkind != REGKIND_NONE)
193 FIXME ("registration of typelibs not supported yet!\n");
195 res= TLB_ReadTypeLib(p, (ITypeLib2**)pptLib);
196 HeapFree(GetProcessHeap(),0,p);
197 TRACE(" returns %08lx\n",res);
199 return res;
202 /******************************************************************************
203 * LoadRegTypeLib [OLEAUT32.162]
205 HRESULT WINAPI LoadRegTypeLib(
206 REFGUID rguid, /* [in] referenced guid */
207 WORD wVerMajor, /* [in] major version */
208 WORD wVerMinor, /* [in] minor version */
209 LCID lcid, /* [in] locale id */
210 ITypeLib **ppTLib) /* [out] path of typelib */
212 BSTR bstr=NULL;
213 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
215 if(SUCCEEDED(res))
217 res= LoadTypeLib(bstr, ppTLib);
218 SysFreeString(bstr);
221 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
223 return res;
227 /******************************************************************************
228 * RegisterTypeLib [OLEAUT32.163]
229 * Adds information about a type library to the System Registry
230 * NOTES
231 * Docs: ITypeLib FAR * ptlib
232 * Docs: OLECHAR FAR* szFullPath
233 * Docs: OLECHAR FAR* szHelpDir
235 * RETURNS
236 * Success: S_OK
237 * Failure: Status
239 HRESULT WINAPI RegisterTypeLib(
240 ITypeLib * ptlib, /*[in] Pointer to the library*/
241 OLECHAR * szFullPath, /*[in] full Path of the library*/
242 OLECHAR * szHelpDir) /*[in] dir to the helpfile for the library,
243 may be NULL*/
244 { FIXME("(%p,%s,%s): stub\n",ptlib, debugstr_w(szFullPath),debugstr_w(szHelpDir));
245 return S_OK; /* FIXME: pretend everything is OK */
249 /******************************************************************************
250 * UnRegisterTypeLib [OLEAUT32.186]
251 * Removes information about a type library from the System Registry
252 * NOTES
254 * RETURNS
255 * Success: S_OK
256 * Failure: Status
258 HRESULT WINAPI UnRegisterTypeLib(
259 REFGUID libid, /* [in] Guid of the library */
260 WORD wVerMajor, /* [in] major version */
261 WORD wVerMinor, /* [in] minor version */
262 LCID lcid, /* [in] locale id */
263 SYSKIND syskind)
265 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
266 return S_OK; /* FIXME: pretend everything is OK */
269 /****************************************************************************
270 * OaBuildVersion (TYPELIB.15)
272 * known TYPELIB.DLL versions:
274 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
275 * OLE 2.02 1993-94 02 3002
276 * OLE 2.03 23 730
277 * OLE 2.03 03 3025
278 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
279 * OLE 2.1 NT 1993-95 ?? ???
280 * OLE 2.3.1 W95 23 700
282 DWORD WINAPI OaBuildVersion16(void)
284 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
285 switch(VERSION_GetVersion())
287 case WIN31:
288 return MAKELONG(3027, 3); /* WfW 3.11 */
289 case WIN95:
290 return MAKELONG(700, 23); /* Win95A */
291 case WIN98:
292 return MAKELONG(3024, 10); /* W98 SE */
293 default:
294 FIXME_(ole)("Version value not known yet. Please investigate it !");
295 return 0;
299 /********************************************************************
300 * LHashValOfNameSysA [OLEAUT32]
302 HRESULT WINAPI LHashValOfNameSysA(SYSKIND sys, LCID lcid, LPSTR name)
304 FIXME("%s\n", name);
305 return 0;
308 /* for better debugging info leave the static out for the time being */
309 #define static
311 /*======================= ITypeLib implementation =======================*/
313 typedef struct tagTLBCustData
315 GUID guid;
316 VARIANT data;
317 struct tagTLBCustData* next;
318 } TLBCustData;
320 /* data structure for import typelibs */
321 typedef struct tagTLBImpLib
323 int offset; /* offset in the file */
324 GUID guid; /* libid */
325 PCHAR name; /* name; */
326 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib */
327 struct tagTLBImpLib * next;
328 } TLBImpLib;
330 /* internal ITypeLib data */
331 typedef struct tagITypeLibImpl
333 ICOM_VFIELD(ITypeLib2);
334 UINT ref;
335 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
336 /* type libs seem to store the doc strings in ascii
337 * so why should we do it in unicode?
339 PCHAR Name;
340 PCHAR DocString;
341 PCHAR HelpFile;
342 PCHAR HelpStringDll;
343 unsigned long dwHelpContext;
344 int TypeInfoCount; /* nr of typeinfo's in librarry */
345 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
346 int ctCustData; /* number of items in cust data list */
347 TLBCustData * pCustData; /* linked list to cust data; */
348 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
349 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the libary */
350 } ITypeLibImpl;
352 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
354 /* ITypeLib methods */
355 static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib);
357 /*======================= ITypeInfo implementation =======================*/
359 /* internal Parameter data */
360 typedef struct tagTLBParDesc
362 PCHAR Name;
363 int ctCustData;
364 TLBCustData * pCustData; /* linked list to cust data; */
365 } TLBParDesc;
367 /* internal Function data */
368 typedef struct tagTLBFuncDesc
370 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
371 PCHAR Name; /* the name of this function */
372 TLBParDesc *pParamDesc; /* array with name and custom data */
373 int helpcontext;
374 int HelpStringContext;
375 PCHAR HelpString;
376 PCHAR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
377 int ctCustData;
378 TLBCustData * pCustData; /* linked list to cust data; */
379 struct tagTLBFuncDesc * next;
380 } TLBFuncDesc;
382 /* internal Variable data */
383 typedef struct tagTLBVarDesc
385 VARDESC vardesc; /* lots of info on the variable and its attributes. */
386 PCHAR Name; /* the name of this variable */
387 int HelpContext;
388 int HelpStringContext; /* fixme: where? */
389 PCHAR HelpString;
390 int ctCustData;
391 TLBCustData * pCustData;/* linked list to cust data; */
392 struct tagTLBVarDesc * next;
393 } TLBVarDesc;
395 /* data for refernced types in a coclass, or an inherited interface */
396 typedef struct tagTLBRefType
398 GUID guid; /* guid of the referenced type */
399 /* (important if its a imported type) */
400 HREFTYPE reference;
401 int flags;
402 int ctCustData;
403 TLBCustData * pCustData;/* linked list to custom data; */
404 TLBImpLib *pImpTLInfo;
405 struct tagTLBRefType * next;
406 } TLBRefType;
408 /* internal TypeInfo data */
409 typedef struct tagITypeInfoImpl
411 ICOM_VFIELD(ITypeInfo2);
412 UINT ref;
413 TYPEATTR TypeAttr ; /* _lots_ of type information. */
414 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
415 int index; /* index in this typelib; */
416 /* type libs seem to store the doc strings in ascii
417 * so why should we do it in unicode?
419 PCHAR Name;
420 PCHAR DocString;
421 unsigned long dwHelpContext;
422 unsigned long dwHelpStringContext;
424 /* functions */
425 TLBFuncDesc * funclist; /* linked list with function descriptions */
427 /* variables */
428 TLBVarDesc * varlist; /* linked list with variable descriptions */
430 /* Implemented Interfaces */
431 TLBRefType * impltypelist;
432 int ctCustData;
433 TLBCustData * pCustData; /* linked list to cust data; */
434 struct tagITypeInfoImpl * next;
435 } ITypeInfoImpl;
437 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
439 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
441 typedef struct tagTLBContext
443 unsigned int oStart; /* start of TLB in file */
444 unsigned int pos; /* current pos */
445 unsigned int length; /* total length */
446 void *mapping; /* memory mapping */
447 TLBSegDir * pTblDir;
448 ITypeLibImpl* pLibInfo;
449 } TLBContext;
452 debug
454 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
456 while (pfd)
458 TRACE("%s(%u)\n", pfd->Name, pfd->funcdesc.cParams);
459 pfd = pfd->next;
462 static void dump_TLBVarDesc(TLBVarDesc * pvd)
464 while (pvd)
466 TRACE("%s\n", pvd->Name);
467 pvd = pvd->next;
470 static void dump_TLBRefType(TLBRefType * prt)
472 while (prt)
474 TRACE("%s\n", debugstr_guid(&(prt->guid)));
475 TRACE(" href:0x%08lx\n", prt->reference);
476 prt = prt->next;
480 static void dump_Variant(VARIANT * pvar)
482 TRACE("%p %x\n", pvar, pvar?pvar->vt:0 );
483 if(!pvar) return;
485 if (pvar->vt & VT_BYREF)
486 return dump_Variant(pvar->u.pvarVal);
489 static void dump_DispParms(DISPPARAMS * pdp)
491 dump_Variant( pdp->rgvarg);
492 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
495 static char * typekind_desc[] =
497 "TKIND_ENUM",
498 "TKIND_RECORD",
499 "TKIND_MODULE",
500 "TKIND_INTERFACE",
501 "TKIND_DISPATCH",
502 "TKIND_COCLASS",
503 "TKIND_ALIAS",
504 "TKIND_UNION",
505 "TKIND_MAX"
508 static void dump_TypeInfo(ITypeInfoImpl * pty)
510 TRACE("%p ref=%u\n", pty, pty->ref);
511 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
512 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
513 TRACE("fct:%u var:%u impl:%u\n",
514 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
515 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
516 TRACE("%s %s\n", pty->Name, pty->DocString);
517 dump_TLBFuncDesc(pty->funclist);
518 dump_TLBVarDesc(pty->varlist);
519 dump_TLBRefType(pty->impltypelist);
522 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
524 /* VT_LPWSTR is largest type that */
525 /* may appear in type description*/
526 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
527 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
528 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
529 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
530 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
531 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
532 {{0},30},{{0},31}
535 static void TLB_abort()
537 DebugBreak();
539 static void * TLB_Alloc(unsigned size)
541 void * ret;
542 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
543 /* FIXME */
544 ERR("cannot allocate memory\n");
546 return ret;
549 /* candidate for a more global appearance... */
550 static BSTR TLB_DupAtoBstr(PCHAR Astr)
552 int len;
553 BSTR bstr;
554 DWORD *pdw ;
555 if(!Astr)
556 return NULL;
557 len=strlen(Astr);
558 pdw =TLB_Alloc((len+3)*sizeof(OLECHAR));
559 pdw[0]=(len)*sizeof(OLECHAR);
560 bstr=(BSTR)&( pdw[1]);
561 lstrcpyAtoW( bstr, Astr);
562 TRACE("copying %s to (%p)\n", Astr, bstr);
563 return bstr;
566 static void TLB_Free(void * ptr)
568 HeapFree(GetProcessHeap(), 0, ptr);
570 /* read function */
571 DWORD TLB_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
573 TRACE("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
574 pcx->pos, count, pcx->oStart, pcx->length, where);
576 if (where != DO_NOT_SEEK)
578 where += pcx->oStart;
579 if (where > pcx->length)
581 /* FIXME */
582 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
583 TLB_abort();
585 pcx->pos = where;
587 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
588 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
589 pcx->pos += count;
590 return count;
593 static void TLB_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
595 TRACE("%s\n", debugstr_guid(pGuid));
597 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
598 memset(pGuid,0, sizeof(GUID));
599 return;
601 TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
604 PCHAR TLB_ReadName( TLBContext *pcx, int offset)
606 char * name;
607 TLBNameIntro niName;
609 TLB_Read(&niName, sizeof(niName), pcx,
610 pcx->pTblDir->pNametab.offset+offset);
611 niName.namelen &= 0xFF; /* FIXME: correct ? */
612 name=TLB_Alloc((niName.namelen & 0xff) +1);
613 TLB_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
614 name[niName.namelen & 0xff]='\0';
615 TRACE("%s\n", debugstr_a(name));
616 return name;
618 PCHAR TLB_ReadString( TLBContext *pcx, int offset)
620 char * string;
621 INT16 length;
623 if(offset<0) return NULL;
624 TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
625 if(length <= 0) return 0;
626 string=TLB_Alloc(length +1);
627 TLB_Read(string, length, pcx, DO_NOT_SEEK);
628 string[length]='\0';
629 TRACE("%s\n", debugstr_a(string));
630 return string;
633 * read a value and fill a VARIANT structure
635 static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
637 int size;
639 TRACE("\n");
641 if(offset <0) { /* data is packed in here */
642 pVar->vt = (offset & 0x7c000000 )>> 26;
643 V_UNION(pVar, iVal) = offset & 0xffff;
644 return;
646 TLB_Read(&(pVar->vt), sizeof(VARTYPE), pcx,
647 pcx->pTblDir->pCustData.offset + offset );
648 TRACE("Vartype = %x\n", pVar->vt);
649 switch(pVar->vt){
650 case VT_EMPTY: /* FIXME: is this right? */
651 case VT_NULL: /* FIXME: is this right? */
652 case VT_I2 : /* this should not happen */
653 case VT_I4 :
654 case VT_R4 :
655 case VT_ERROR :
656 case VT_BOOL :
657 case VT_I1 :
658 case VT_UI1 :
659 case VT_UI2 :
660 case VT_UI4 :
661 case VT_INT :
662 case VT_UINT :
663 case VT_VOID : /* FIXME: is this right? */
664 case VT_HRESULT :
665 size=4; break;
666 case VT_R8 :
667 case VT_CY :
668 case VT_DATE :
669 case VT_I8 :
670 case VT_UI8 :
671 case VT_DECIMAL : /* FIXME: is this right? */
672 case VT_FILETIME :
673 size=8;break;
674 /* pointer types with known behaviour */
675 case VT_BSTR :{
676 char * ptr;
677 TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
678 if(size <= 0) {
679 FIXME("BSTR length = %d?\n", size);
680 } else {
681 ptr=TLB_Alloc(size);/* allocate temp buffer */
682 TLB_Read(ptr, size, pcx, DO_NOT_SEEK); /* read string (ANSI) */
683 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
684 /* FIXME: do we need a AtoW conversion here? */
685 V_UNION(pVar, bstrVal[size])=L'\0';
686 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
687 TLB_Free(ptr);
690 size=-4; break;
691 /* FIXME: this will not work AT ALL when the variant contains a pointer */
692 case VT_DISPATCH :
693 case VT_VARIANT :
694 case VT_UNKNOWN :
695 case VT_PTR :
696 case VT_SAFEARRAY :
697 case VT_CARRAY :
698 case VT_USERDEFINED :
699 case VT_LPSTR :
700 case VT_LPWSTR :
701 case VT_BLOB :
702 case VT_STREAM :
703 case VT_STORAGE :
704 case VT_STREAMED_OBJECT :
705 case VT_STORED_OBJECT :
706 case VT_BLOB_OBJECT :
707 case VT_CF :
708 case VT_CLSID :
709 default:
710 size=0;
711 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
712 pVar->vt);
715 if(size>0) /* (big|small) endian correct? */
716 TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
717 return;
720 * create a linked list with custom data
722 static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
724 TLBCDGuid entry;
725 TLBCustData* pNew;
726 int count=0;
728 TRACE("\n");
730 while(offset >=0){
731 count++;
732 pNew=TLB_Alloc(sizeof(TLBCustData));
733 TLB_Read(&entry, sizeof(entry), pcx,
734 pcx->pTblDir->pCDGuids.offset+offset);
735 TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
736 TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx);
737 /* add new custom data at head of the list */
738 pNew->next=*ppCustData;
739 *ppCustData=pNew;
740 offset = entry.next;
742 return count;
745 static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd )
747 TRACE("\n");
749 if(type <0)
750 pTd->vt=type & VT_TYPEMASK;
751 else
752 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
754 static void TLB_DoFuncs(TLBContext *pcx, int cFuncs, int cVars,
755 int offset, TLBFuncDesc ** pptfd)
758 * member information is stored in a data structure at offset
759 * indicated by the memoffset field of the typeinfo structure
760 * There are several distinctive parts.
761 * the first part starts with a field that holds the total length
762 * of this (first) part excluding this field. Then follow the records,
763 * for each member there is one record.
765 * First entry is always the length of the record (excluding this
766 * length word).
767 * Rest of the record depends on the type of the member. If there is
768 * a field indicating the member type (function variable intereface etc)
769 * I have not found it yet. At this time we depend on the information
770 * in the type info and the usual order how things are stored.
772 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
773 * for each member;
775 * Third is a equal sized array with file offsets to the name entry
776 * of each member.
778 * Forth and last (?) part is an array with offsets to the records in the
779 * first part of this file segment.
782 int infolen, nameoffset, reclength, nrattributes;
783 char recbuf[512];
784 TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf;
785 int i, j;
786 int recoffset=offset+sizeof(INT);
788 TRACE("\n");
790 TLB_Read(&infolen,sizeof(INT), pcx, offset);
791 for(i=0;i<cFuncs;i++){
792 *pptfd=TLB_Alloc(sizeof(TLBFuncDesc));
793 /* name, eventually add to a hash table */
794 TLB_Read(&nameoffset, sizeof(INT), pcx,
795 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
796 (*pptfd)->Name=TLB_ReadName(pcx, nameoffset);
797 /* read the function information record */
798 TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
799 reclength &=0x1ff;
800 TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
801 /* do the attributes */
802 nrattributes=(reclength-pFuncRec->nrargs*3*sizeof(int)-0x18)
803 /sizeof(int);
804 if(nrattributes>0){
805 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
806 if(nrattributes>1){
807 (*pptfd)->HelpString = TLB_ReadString(pcx,
808 pFuncRec->OptAttr[1]) ;
809 if(nrattributes>2){
810 if(pFuncRec->FKCCIC & 0x2000)
811 (*pptfd)->Entry = (char *) pFuncRec->OptAttr[2] ;
812 else
813 (*pptfd)->Entry = TLB_ReadString(pcx,
814 pFuncRec->OptAttr[2]);
815 if(nrattributes>5 )
816 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
817 if(nrattributes>6 && pFuncRec->FKCCIC & 0x80){
818 TLB_CustData(pcx, pFuncRec->OptAttr[6],
819 &(*pptfd)->pCustData);
824 /* fill the FuncDesc Structure */
825 TLB_Read(&(*pptfd)->funcdesc.memid, sizeof(INT), pcx,
826 offset + infolen + ( i + 1) * sizeof(INT));
827 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
828 (*pptfd)->funcdesc.invkind = ((pFuncRec->FKCCIC) >>3) & 0xF;
829 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >>8 & 0xF;
830 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
831 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
832 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
833 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
834 TLB_GetTdesc(pcx, pFuncRec->DataType,
835 &(*pptfd)->funcdesc.elemdescFunc.tdesc) ;
837 /* do the parameters/arguments */
838 if(pFuncRec->nrargs){
839 TLBParameterInfo paraminfo;
840 (*pptfd)->funcdesc.lprgelemdescParam=
841 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
842 (*pptfd)->pParamDesc=TLB_Alloc(pFuncRec->nrargs *
843 sizeof(TLBParDesc));
845 TLB_Read(&paraminfo,sizeof(paraminfo), pcx, recoffset+reclength -
846 pFuncRec->nrargs * sizeof(TLBParameterInfo));
847 for(j=0;j<pFuncRec->nrargs;j++){
848 TLB_GetTdesc(pcx, paraminfo.DataType,
849 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ;
850 V_UNION(&((*pptfd)->funcdesc.lprgelemdescParam[j]),
851 paramdesc.wParamFlags) = paraminfo.Flags;
852 (*pptfd)->pParamDesc[j].Name=(void *)paraminfo.oName;
853 TLB_Read(&paraminfo,sizeof(TLBParameterInfo), pcx,
854 DO_NOT_SEEK);
856 /* second time around */
857 for(j=0;j<pFuncRec->nrargs;j++){
858 /* name */
859 (*pptfd)->pParamDesc[j].Name=
860 TLB_ReadName(pcx, (int)(*pptfd)->pParamDesc[j].Name);
861 /* default value */
862 if((PARAMFLAG_FHASDEFAULT & V_UNION(&((*pptfd)->funcdesc.
863 lprgelemdescParam[j]),paramdesc.wParamFlags)) &&
864 ((pFuncRec->FKCCIC) & 0x1000)){
865 INT *pInt=(INT *)((char *)pFuncRec + reclength -
866 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
867 PARAMDESC * pParamDesc= &V_UNION(&((*pptfd)->funcdesc.
868 lprgelemdescParam[j]),paramdesc);
869 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
870 pParamDesc->pparamdescex->cBytes= sizeof(PARAMDESCEX);
871 TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
872 pInt[j], pcx);
874 /* custom info */
875 if(nrattributes>7+j && pFuncRec->FKCCIC & 0x80)
876 TLB_CustData(pcx, pFuncRec->OptAttr[7+j],
877 &(*pptfd)->pParamDesc[j].pCustData);
880 /* scode is not used: archaic win16 stuff FIXME: right? */
881 (*pptfd)->funcdesc.cScodes = 0 ;
882 (*pptfd)->funcdesc.lprgscode = NULL ;
883 pptfd=&((*pptfd)->next);
884 recoffset += reclength;
887 static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars,
888 int offset, TLBVarDesc ** pptvd)
890 int infolen, nameoffset, reclength;
891 char recbuf[256];
892 TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf;
893 int i;
894 int recoffset;
896 TRACE("\n");
898 TLB_Read(&infolen,sizeof(INT), pcx, offset);
899 TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
900 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
901 recoffset += offset+sizeof(INT);
902 for(i=0;i<cVars;i++){
903 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
904 /* name, eventually add to a hash table */
905 TLB_Read(&nameoffset, sizeof(INT), pcx,
906 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
907 (*pptvd)->Name=TLB_ReadName(pcx, nameoffset);
908 /* read the variable information record */
909 TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
910 reclength &=0xff;
911 TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
912 /* Optional data */
913 if(reclength >(6*sizeof(INT)) )
914 (*pptvd)->HelpContext=pVarRec->HelpContext;
915 if(reclength >(7*sizeof(INT)) )
916 (*pptvd)->HelpString = TLB_ReadString(pcx, pVarRec->oHelpString) ;
917 if(reclength >(8*sizeof(INT)) )
918 if(reclength >(9*sizeof(INT)) )
919 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
920 /* fill the VarDesc Structure */
921 TLB_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
922 offset + infolen + ( i + 1) * sizeof(INT));
923 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
924 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
925 TLB_GetTdesc(pcx, pVarRec->DataType,
926 &(*pptvd)->vardesc.elemdescVar.tdesc) ;
927 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
928 if(pVarRec->VarKind == VAR_CONST ){
929 V_UNION(&((*pptvd)->vardesc),lpvarValue)=TLB_Alloc(sizeof(VARIANT));
930 TLB_ReadValue(V_UNION(&((*pptvd)->vardesc),lpvarValue),
931 pVarRec->OffsValue, pcx);
932 }else
933 V_UNION(&((*pptvd)->vardesc),oInst)=pVarRec->OffsValue;
934 pptvd=&((*pptvd)->next);
935 recoffset += reclength;
938 /* fill in data for a hreftype (offset). When the refernced type is contained
939 * in the typelib, its just an (file) offset in the type info base dir.
940 * If comes from import, its an offset+1 in the ImpInfo table
941 * */
942 static void TLB_DoRefType(TLBContext *pcx,
943 int offset, TLBRefType ** pprtd)
945 int j;
947 TRACE("\n");
949 if(!HREFTYPE_INTHISFILE( offset)) {
950 /* external typelib */
951 TLBImpInfo impinfo;
952 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
953 TLB_Read(&impinfo, sizeof(impinfo), pcx,
954 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
955 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
956 if(pImpLib->offset==impinfo.oImpFile) break;
957 pImpLib=pImpLib->next;
959 if(pImpLib){
960 (*pprtd)->reference=offset;
961 (*pprtd)->pImpTLInfo = pImpLib;
962 TLB_ReadGuid(&(*pprtd)->guid, impinfo.oGuid, pcx);
963 }else{
964 ERR("Cannot find a reference\n");
965 (*pprtd)->reference=-1;
966 (*pprtd)->pImpTLInfo=(void *)-1;
968 }else{
969 /* in this typelib */
970 (*pprtd)->reference=offset;
971 (*pprtd)->pImpTLInfo=(void *)-2;
975 /* process Implemented Interfaces of a com class */
976 static void TLB_DoImplTypes(TLBContext *pcx, int count,
977 int offset, TLBRefType ** pprtd)
979 int i;
980 TLBRefRecord refrec;
982 TRACE("\n");
984 for(i=0;i<count;i++){
985 if(offset<0) break; /* paranoia */
986 *pprtd=TLB_Alloc(sizeof(TLBRefType));
987 TLB_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
988 TLB_DoRefType(pcx, refrec.reftype, pprtd);
989 (*pprtd)->flags=refrec.flags;
990 (*pprtd)->ctCustData=
991 TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData);
992 offset=refrec.onext;
993 pprtd=&((*pprtd)->next);
997 * process a typeinfo record
999 ITypeInfoImpl * TLB_DoTypeInfo(
1000 TLBContext *pcx,
1001 int count,
1002 ITypeLibImpl * pLibInfo)
1004 TLBTypeInfoBase tiBase;
1005 ITypeInfoImpl *ptiRet;
1007 TRACE("count=%u\n", count);
1009 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1010 TLB_Read(&tiBase, sizeof(tiBase) ,pcx ,
1011 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1012 /* this where we are coming from */
1013 ptiRet->pTypeLib = pLibInfo;
1014 ptiRet->index=count;
1015 /* fill in the typeattr fields */
1016 TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1017 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1018 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1019 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1020 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1021 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1022 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1023 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1024 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1025 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1026 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1027 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1028 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1029 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1030 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1031 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1032 TLB_GetTdesc(pcx, tiBase.datatype1,
1033 &ptiRet->TypeAttr.tdescAlias) ;
1035 /* FIXME: */
1036 /* IDLDESC idldescType; *//* never saw this one != zero */
1038 /* name, eventually add to a hash table */
1039 ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset);
1040 TRACE("reading %s\n", ptiRet->Name);
1041 /* help info */
1042 ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs);
1043 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1044 ptiRet->dwHelpContext=tiBase.helpcontext;
1045 /* note: InfoType's Help file and HelpStringDll come from the containing
1046 * library. Further HelpString and Docstring appear to be the same thing :(
1048 /* functions */
1049 if(ptiRet->TypeAttr.cFuncs >0 )
1050 TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars,
1051 tiBase.memoffset, & ptiRet->funclist);
1052 /* variables */
1053 if(ptiRet->TypeAttr.cVars >0 )
1054 TLB_DoVars(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars,
1055 tiBase.memoffset, & ptiRet->varlist);
1056 if(ptiRet->TypeAttr.cImplTypes >0 ){
1057 if(ptiRet->TypeAttr.typekind == TKIND_COCLASS)
1058 TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes ,
1059 tiBase.datatype1, & ptiRet->impltypelist);
1060 else if(ptiRet->TypeAttr.typekind != TKIND_DISPATCH){
1061 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1062 TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1065 ptiRet->ctCustData=
1066 TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1068 TRACE("%s guid: %s kind:%s\n",
1069 ptiRet->Name,
1070 debugstr_guid(&ptiRet->TypeAttr.guid),
1071 typekind_desc[ptiRet->TypeAttr.typekind]);
1073 return ptiRet;
1076 /****************************************************************************
1077 * TLB_ReadTypeLib
1079 * find the type of the typelib file and map the typelib resource into
1080 * the memory
1082 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1083 int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib)
1085 int ret = E_FAIL;
1086 DWORD dwSignature = 0;
1087 HFILE hFile;
1089 TRACE("%s\n", pszFileName);
1091 *ppTypeLib = NULL;
1093 /* check the signature of the file */
1094 hFile = CreateFileA( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, -1 );
1095 if (INVALID_HANDLE_VALUE != hFile)
1097 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1098 if (hMapping)
1100 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1101 if(pBase)
1103 /* first try to load as *.tlb */
1104 dwSignature = *((DWORD*) pBase);
1105 if ( dwSignature == MSFT_SIGNATURE)
1107 *ppTypeLib = ITypeLib2_Constructor(pBase);
1109 UnmapViewOfFile(pBase);
1111 CloseHandle(hMapping);
1113 CloseHandle(hFile);
1116 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1118 /* find the typelibrary resource*/
1119 HINSTANCE hinstDLL = LoadLibraryExA(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1120 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1121 if (hinstDLL)
1123 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(1), "TYPELIB");
1124 if (hrsrc)
1126 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1127 if (hGlobal)
1129 LPVOID pBase = LockResource(hGlobal);
1130 if (pBase)
1132 *ppTypeLib = ITypeLib2_Constructor(pBase);
1134 FreeResource( hGlobal );
1137 FreeLibrary(hinstDLL);
1141 if(*ppTypeLib)
1142 ret = S_OK;
1143 else
1144 ERR("Loading of typelib %s failed with error 0x%08lx\n", pszFileName, GetLastError());
1146 return ret;
1149 /*================== ITypeLib(2) Methods ===================================*/
1151 /****************************************************************************
1152 * ITypeLib2_Constructor
1154 * loading a typelib from a in-memory image
1156 static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib)
1158 TLBContext cx;
1159 long lPSegDir;
1160 TLB2Header tlbHeader;
1161 TLBSegDir tlbSegDir;
1162 ITypeLibImpl * pTypeLibImpl;
1164 TRACE("%p\n", pLib);
1166 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1167 if (!pTypeLibImpl) return NULL;
1169 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1170 pTypeLibImpl->ref = 1;
1172 /* get pointer to beginning of typelib data */
1173 cx.pos = 0;
1174 cx.oStart=0;
1175 cx.mapping = pLib;
1176 cx.pLibInfo = pTypeLibImpl;
1178 /* read header */
1179 TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1180 TRACE("read header (0x%08x 0x%08x)\n",tlbHeader.magic1,tlbHeader.magic2 );
1182 /* there is a small number of information here until the next important
1183 * part:
1184 * the segment directory . Try to calculate the amount of data */
1185 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + (tlbHeader.varflags & HELPDLLFLAG? 4 :0);
1187 /* now read the segment directory */
1188 TRACE("read segment directory\n");
1189 TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
1190 cx.pTblDir = &tlbSegDir;
1192 /* just check two entries */
1193 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
1195 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
1196 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
1197 return NULL;
1200 /* now fill our internal data */
1201 /* TLIBATTR fields */
1202 TLB_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
1203 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
1204 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
1205 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
1206 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
1207 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
1209 /* name, eventually add to a hash table */
1210 pTypeLibImpl->Name = TLB_ReadName(&cx, tlbHeader.NameOffset);
1212 /* help info */
1213 pTypeLibImpl->DocString = TLB_ReadString(&cx, tlbHeader.helpstring);
1214 pTypeLibImpl->HelpFile = TLB_ReadString(&cx, tlbHeader.helpfile);
1216 if( tlbHeader.varflags & HELPDLLFLAG)
1218 int offset;
1219 TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
1220 pTypeLibImpl->HelpStringDll = TLB_ReadString(&cx, offset);
1223 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
1225 /* custom data */
1226 if(tlbHeader.CustomDataOffset >= 0)
1228 pTypeLibImpl->ctCustData = TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
1231 /* fill in typedescriptions */
1232 if(tlbSegDir.pTypdescTab.length > 0)
1234 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
1235 INT16 td[4];
1236 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
1237 TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
1238 for(i=0; i<cTD; )
1240 /* FIXME: add several sanity checks here */
1241 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
1242 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
1244 /* FIXME: check safearray */
1245 if(td[3] < 0)
1246 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & stndTypeDesc[td[2]];
1247 else
1248 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & pTypeLibImpl->pTypeDesc[td[3]/8];
1250 else if(td[0] == VT_CARRAY)
1252 /* array descr table here */
1253 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = (void *)((int) td[2]); /* temp store offset in*/
1255 else if(td[0] == VT_USERDEFINED)
1257 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),hreftype) = MAKELONG(td[2],td[3]);
1259 if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
1262 /* second time around to fill the array subscript info */
1263 for(i=0;i<cTD;i++)
1265 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
1266 if(tlbSegDir.pArrayDescriptions.offset>0)
1268 TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc));
1269 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
1271 if(td[1]<0)
1272 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem.vt = td[0] & VT_TYPEMASK;
1273 else
1274 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem = stndTypeDesc[td[0]/8];
1276 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->cDims = td[2];
1278 for(j = 0; j<td[2]; j++)
1280 TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements,
1281 sizeof(INT), &cx, DO_NOT_SEEK);
1282 TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].lLbound,
1283 sizeof(INT), &cx, DO_NOT_SEEK);
1286 else
1288 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = NULL;
1289 ERR("didn't find array description data\n");
1294 /* imported type libs */
1295 if(tlbSegDir.pImpFiles.offset>0)
1297 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
1298 int oGuid, offset = tlbSegDir.pImpFiles.offset;
1299 UINT16 size;
1301 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
1303 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
1304 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
1305 TLB_Read(&oGuid, sizeof(INT), &cx, offset);
1306 TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
1308 /* we are skipping some unknown info here */
1309 TLB_Read(& size,sizeof(UINT16), &cx, offset+3*(sizeof(INT)));
1310 size >>= 2;
1311 (*ppImpLib)->name = TLB_Alloc(size+1);
1312 TLB_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
1313 offset = (offset + 3 * (sizeof(INT)) + sizeof(UINT16) + size + 3) & 0xfffffffc;
1315 ppImpLib = &(*ppImpLib)->next;
1319 /* type info's */
1320 if(tlbHeader.nrtypeinfos >= 0 )
1322 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
1323 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
1324 int i;
1325 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
1327 *ppTI = TLB_DoTypeInfo(&cx, i, pTypeLibImpl);
1328 ppTI = &((*ppTI)->next);
1329 (pTypeLibImpl->TypeInfoCount)++;
1333 TRACE("(%p)\n", pTypeLibImpl);
1334 return (ITypeLib2*) pTypeLibImpl;
1337 /* ITypeLib::QueryInterface
1339 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
1340 ITypeLib2 * iface,
1341 REFIID riid,
1342 VOID **ppvObject)
1344 ICOM_THIS( ITypeLibImpl, iface);
1346 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
1348 *ppvObject=NULL;
1349 if(IsEqualIID(riid, &IID_IUnknown) ||
1350 IsEqualIID(riid,&IID_ITypeLib)||
1351 IsEqualIID(riid,&IID_ITypeLib2))
1353 *ppvObject = This;
1356 if(*ppvObject)
1358 ITypeLib2_AddRef(iface);
1359 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1360 return S_OK;
1362 TRACE("-- Interface: E_NOINTERFACE\n");
1363 return E_NOINTERFACE;
1366 /* ITypeLib::AddRef
1368 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
1370 ICOM_THIS( ITypeLibImpl, iface);
1372 TRACE("(%p)->ref is %u\n",This, This->ref);
1374 return ++(This->ref);
1377 /* ITypeLib::Release
1379 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
1381 ICOM_THIS( ITypeLibImpl, iface);
1383 TRACE("(%p)->(%u)\n",This, This->ref);
1385 if (!--(This->ref))
1387 /* fixme destroy child objects */
1389 TRACE(" destroying ITypeLib(%p)\n",This);
1391 HeapFree(GetProcessHeap(),0,This);
1392 return 0;
1394 return This->ref;
1397 /* ITypeLib::GetTypeInfoCount
1399 * Returns the number of type descriptions in the type library
1401 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
1403 ICOM_THIS( ITypeLibImpl, iface);
1404 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
1405 return This->TypeInfoCount;
1408 /* ITypeLib::GetTypeInfo
1410 * retrieves the specified type description in the library.
1412 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
1413 ITypeLib2 *iface,
1414 UINT index,
1415 ITypeInfo **ppTInfo)
1417 int i;
1418 ICOM_THIS( ITypeLibImpl, iface);
1419 ITypeInfoImpl *pTLBTInfo = This->pTypeInfo;
1421 TRACE("(%p)->(index=%d) \n",This, index);
1423 if (!ppTInfo) return E_INVALIDARG;
1425 /* search element n in list */
1426 for(i=0; i < index; i++)
1428 pTLBTInfo = pTLBTInfo->next;
1429 if (!pTLBTInfo)
1431 TRACE("-- element not found\n");
1432 return TYPE_E_ELEMENTNOTFOUND;
1436 *ppTInfo = (ITypeInfo *) pTLBTInfo;
1437 ITypeInfo_AddRef(*ppTInfo);
1438 TRACE("-- found (%p)\n",*ppTInfo);
1439 return S_OK;
1442 /* ITypeLibs::GetTypeInfoType
1444 * Retrieves the type of a type description.
1446 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
1447 ITypeLib2 *iface,
1448 UINT index,
1449 TYPEKIND *pTKind)
1451 ICOM_THIS( ITypeLibImpl, iface);
1452 int i;
1453 ITypeInfoImpl *pTInfo = This->pTypeInfo;
1455 TRACE("(%p) index %d \n",This, index);
1457 if(!pTKind) return E_INVALIDARG;
1459 /* search element n in list */
1460 for(i=0; i < index; i++)
1462 if(!pTInfo)
1464 TRACE("-- element not found\n");
1465 return TYPE_E_ELEMENTNOTFOUND;
1467 pTInfo = pTInfo->next;
1470 *pTKind = pTInfo->TypeAttr.typekind;
1471 TRACE("-- found Type (%d)\n", *pTKind);
1472 return S_OK;
1475 /* ITypeLib::GetTypeInfoOfGuid
1477 * Retrieves the type description that corresponds to the specified GUID.
1480 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
1481 ITypeLib2 *iface,
1482 REFGUID guid,
1483 ITypeInfo **ppTInfo)
1485 ICOM_THIS( ITypeLibImpl, iface);
1486 ITypeInfoImpl *ppTLBTInfo = This->pTypeInfo; /* head of list */
1488 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
1490 /* serach linked list for guid */
1491 while( !IsEqualIID(guid,&ppTLBTInfo->TypeAttr.guid) )
1493 ppTLBTInfo = ppTLBTInfo->next;
1494 if (!ppTLBTInfo)
1496 /* end of list reached */
1497 TRACE("-- element not found\n");
1498 return TYPE_E_ELEMENTNOTFOUND;
1502 TRACE("-- found (%p, %s)\n", ppTLBTInfo, ppTLBTInfo->Name);
1504 *ppTInfo = (ITypeInfo*)ppTLBTInfo;
1505 ITypeInfo_AddRef(*ppTInfo);
1506 return S_OK;
1509 /* ITypeLib::GetLibAttr
1511 * Retrieves the structure that contains the library's attributes.
1514 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
1515 ITypeLib2 *iface,
1516 LPTLIBATTR *ppTLibAttr)
1518 ICOM_THIS( ITypeLibImpl, iface);
1519 TRACE("(%p)\n",This);
1520 /* FIXME: must do a copy here */
1521 *ppTLibAttr=&This->LibAttr;
1522 return S_OK;
1525 /* ITypeLib::GetTypeComp
1527 * Enables a client compiler to bind to a library's types, variables,
1528 * constants, and global functions.
1531 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
1532 ITypeLib2 *iface,
1533 ITypeComp **ppTComp)
1535 ICOM_THIS( ITypeLibImpl, iface);
1536 FIXME("(%p): stub!\n",This);
1537 return E_NOTIMPL;
1540 /* ITypeLib::GetDocumentation
1542 * Retrieves the library's documentation string, the complete Help file name
1543 * and path, and the context identifier for the library Help topic in the Help
1544 * file.
1547 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
1548 ITypeLib2 *iface,
1549 INT index,
1550 BSTR *pBstrName,
1551 BSTR *pBstrDocString,
1552 DWORD *pdwHelpContext,
1553 BSTR *pBstrHelpFile)
1555 ICOM_THIS( ITypeLibImpl, iface);
1556 HRESULT result;
1557 ITypeInfo *pTInfo;
1558 TRACE("(%p) index %d Name(%p) DocString(%p)"
1559 " HelpContext(%p) HelpFile(%p)\n",
1560 This, index, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
1561 if(index<0){ /* documentation for the typelib */
1562 if(pBstrName)
1563 *pBstrName=TLB_DupAtoBstr(This->Name);
1564 if(pBstrDocString)
1565 *pBstrDocString=TLB_DupAtoBstr(This->DocString);
1566 if(pdwHelpContext)
1567 *pdwHelpContext=This->dwHelpContext;
1568 if(pBstrHelpFile)
1569 *pBstrHelpFile=TLB_DupAtoBstr(This->HelpFile);
1570 }else {/* for a typeinfo */
1571 result=ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
1572 if(SUCCEEDED(result)){
1573 result=ITypeInfo_GetDocumentation(pTInfo, MEMBERID_NIL, pBstrName,
1574 pBstrDocString, pdwHelpContext, pBstrHelpFile);
1575 ITypeInfo_Release(pTInfo);
1577 if(!SUCCEEDED(result))
1578 return result;
1580 return S_OK;
1583 /* ITypeLib::IsName
1585 * Indicates whether a passed-in string contains the name of a type or member
1586 * described in the library.
1589 static HRESULT WINAPI ITypeLib2_fnIsName(
1590 ITypeLib2 *iface,
1591 LPOLESTR szNameBuf,
1592 ULONG lHashVal,
1593 BOOL *pfName)
1595 ICOM_THIS( ITypeLibImpl, iface);
1596 ITypeInfoImpl *pTInfo;
1597 TLBFuncDesc *pFInfo;
1598 TLBVarDesc *pVInfo;
1599 int i;
1600 PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
1602 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
1603 pfName);
1605 *pfName=TRUE;
1606 if(!strcmp(astr,This->Name)) goto ITypeLib2_fnIsName_exit;
1607 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
1608 if(!strcmp(astr,pTInfo->Name)) goto ITypeLib2_fnIsName_exit;
1609 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
1610 if(!strcmp(astr,pFInfo->Name)) goto ITypeLib2_fnIsName_exit;
1611 for(i=0;i<pFInfo->funcdesc.cParams;i++)
1612 if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
1613 goto ITypeLib2_fnIsName_exit;
1615 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
1616 if(!strcmp(astr,pVInfo->Name)) goto ITypeLib2_fnIsName_exit;
1619 *pfName=FALSE;
1621 ITypeLib2_fnIsName_exit:
1622 TRACE("(%p)slow! search for %s: %s found!\n", This,
1623 debugstr_a(astr), *pfName?"NOT":"");
1625 HeapFree( GetProcessHeap(), 0, astr );
1626 return S_OK;
1629 /* ITypeLib::FindName
1631 * Finds occurrences of a type description in a type library. This may be used
1632 * to quickly verify that a name exists in a type library.
1635 static HRESULT WINAPI ITypeLib2_fnFindName(
1636 ITypeLib2 *iface,
1637 LPOLESTR szNameBuf,
1638 ULONG lHashVal,
1639 ITypeInfo **ppTInfo,
1640 MEMBERID *rgMemId,
1641 UINT16 *pcFound)
1643 ICOM_THIS( ITypeLibImpl, iface);
1644 ITypeInfoImpl *pTInfo;
1645 TLBFuncDesc *pFInfo;
1646 TLBVarDesc *pVInfo;
1647 int i,j = 0;
1648 PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
1649 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
1650 if(!strcmp(astr,pTInfo->Name)) goto ITypeLib2_fnFindName_exit;
1651 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
1652 if(!strcmp(astr,pFInfo->Name)) goto ITypeLib2_fnFindName_exit;
1653 for(i=0;i<pFInfo->funcdesc.cParams;i++)
1654 if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
1655 goto ITypeLib2_fnFindName_exit;
1657 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) ;
1658 if(!strcmp(astr,pVInfo->Name)) goto ITypeLib2_fnFindName_exit;
1659 continue;
1660 ITypeLib2_fnFindName_exit:
1661 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
1662 ppTInfo[j]=(LPTYPEINFO)pTInfo;
1663 j++;
1665 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
1666 This, *pcFound, debugstr_a(astr), j);
1668 *pcFound=j;
1670 HeapFree( GetProcessHeap(), 0, astr );
1671 return S_OK;
1674 /* ITypeLib::ReleaseTLibAttr
1676 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
1679 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
1680 ITypeLib2 *iface,
1681 TLIBATTR *pTLibAttr)
1683 ICOM_THIS( ITypeLibImpl, iface);
1684 TRACE("freeing (%p)\n",This);
1685 /* nothing to do */
1688 /* ITypeLib2::GetCustData
1690 * gets the custom data
1692 static HRESULT WINAPI ITypeLib2_fnGetCustData(
1693 ITypeLib2 * iface,
1694 REFGUID guid,
1695 VARIANT *pVarVal)
1697 ICOM_THIS( ITypeLibImpl, iface);
1698 TLBCustData *pCData;
1700 for(pCData=This->pCustData; pCData; pCData = pCData->next)
1702 if( IsEqualIID(guid, &pCData->guid)) break;
1705 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
1707 if(pCData)
1709 VariantInit( pVarVal);
1710 VariantCopy( pVarVal, &pCData->data);
1711 return S_OK;
1713 return E_INVALIDARG; /* FIXME: correct? */
1716 /* ITypeLib2::GetLibStatistics
1718 * Returns statistics about a type library that are required for efficient
1719 * sizing of hash tables.
1722 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
1723 ITypeLib2 * iface,
1724 ULONG *pcUniqueNames,
1725 ULONG *pcchUniqueNames)
1727 ICOM_THIS( ITypeLibImpl, iface);
1729 FIXME("(%p): stub!\n", This);
1731 if(pcUniqueNames) *pcUniqueNames=1;
1732 if(pcchUniqueNames) *pcchUniqueNames=1;
1733 return S_OK;
1736 /* ITypeLib2::GetDocumentation2
1738 * Retrieves the library's documentation string, the complete Help file name
1739 * and path, the localization context to use, and the context ID for the
1740 * library Help topic in the Help file.
1743 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
1744 ITypeLib2 * iface,
1745 INT index,
1746 LCID lcid,
1747 BSTR *pbstrHelpString,
1748 DWORD *pdwHelpStringContext,
1749 BSTR *pbstrHelpStringDll)
1751 ICOM_THIS( ITypeLibImpl, iface);
1752 HRESULT result;
1753 ITypeInfo *pTInfo;
1755 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
1757 /* the help string should be obtained from the helpstringdll,
1758 * using the _DLLGetDocumentation function, based on the supplied
1759 * lcid. Nice to do sometime...
1761 if(index<0)
1763 /* documentation for the typelib */
1764 if(pbstrHelpString)
1765 *pbstrHelpString=TLB_DupAtoBstr(This->DocString);
1766 if(pdwHelpStringContext)
1767 *pdwHelpStringContext=This->dwHelpContext;
1768 if(pbstrHelpStringDll)
1769 *pbstrHelpStringDll=TLB_DupAtoBstr(This->HelpStringDll);
1771 else
1773 /* for a typeinfo */
1774 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
1775 if(SUCCEEDED(result))
1777 ITypeInfo2 * pTInfo2;
1778 result = ITypeInfo_QueryInterface(pTInfo, &IID_ITypeInfo2, (LPVOID*) &pTInfo2);
1779 if(SUCCEEDED(result))
1781 result = ITypeInfo2_GetDocumentation2(pTInfo2, MEMBERID_NIL, lcid,
1782 pbstrHelpString, pdwHelpStringContext, pbstrHelpStringDll);
1783 ITypeInfo2_Release(pTInfo);
1785 ITypeInfo_Release(pTInfo);
1787 if(!SUCCEEDED(result))
1788 return result;
1790 return S_OK;
1793 /* ITypeLib2::GetAllCustData
1795 * Gets all custom data items for the library.
1798 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
1799 ITypeLib2 * iface,
1800 CUSTDATA *pCustData)
1802 ICOM_THIS( ITypeLibImpl, iface);
1803 TLBCustData *pCData;
1804 int i;
1805 TRACE("(%p) returning %d items\n", This, This->ctCustData);
1806 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
1807 if(pCustData->prgCustData ){
1808 pCustData->cCustData=This->ctCustData;
1809 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
1810 pCustData->prgCustData[i].guid=pCData->guid;
1811 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
1813 }else{
1814 ERR(" OUT OF MEMORY! \n");
1815 return E_OUTOFMEMORY;
1817 return S_OK;
1820 static ICOM_VTABLE(ITypeLib2) tlbvt = {
1821 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1822 ITypeLib2_fnQueryInterface,
1823 ITypeLib2_fnAddRef,
1824 ITypeLib2_fnRelease,
1825 ITypeLib2_fnGetTypeInfoCount,
1826 ITypeLib2_fnGetTypeInfo,
1827 ITypeLib2_fnGetTypeInfoType,
1828 ITypeLib2_fnGetTypeInfoOfGuid,
1829 ITypeLib2_fnGetLibAttr,
1830 ITypeLib2_fnGetTypeComp,
1831 ITypeLib2_fnGetDocumentation,
1832 ITypeLib2_fnIsName,
1833 ITypeLib2_fnFindName,
1834 ITypeLib2_fnReleaseTLibAttr,
1836 ITypeLib2_fnGetCustData,
1837 ITypeLib2_fnGetLibStatistics,
1838 ITypeLib2_fnGetDocumentation2,
1839 ITypeLib2_fnGetAllCustData
1842 /*================== ITypeInfo(2) Methods ===================================*/
1843 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
1845 ITypeInfoImpl * pTypeInfoImpl;
1847 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
1848 if (pTypeInfoImpl)
1850 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
1851 pTypeInfoImpl->ref=1;
1853 TRACE("(%p)\n", pTypeInfoImpl);
1854 return (ITypeInfo2*) pTypeInfoImpl;
1857 /* ITypeInfo::QueryInterface
1859 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
1860 ITypeInfo2 *iface,
1861 REFIID riid,
1862 VOID **ppvObject)
1864 ICOM_THIS( ITypeLibImpl, iface);
1866 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
1868 *ppvObject=NULL;
1869 if(IsEqualIID(riid, &IID_IUnknown) ||
1870 IsEqualIID(riid,&IID_ITypeInfo)||
1871 IsEqualIID(riid,&IID_ITypeInfo2))
1872 *ppvObject = This;
1874 if(*ppvObject){
1875 ITypeInfo_AddRef(iface);
1876 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1877 return S_OK;
1879 TRACE("-- Interface: E_NOINTERFACE\n");
1880 return E_NOINTERFACE;
1883 /* ITypeInfo::AddRef
1885 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
1887 ICOM_THIS( ITypeInfoImpl, iface);
1888 TRACE("(%p)->ref is %u\n",This, This->ref);
1889 ITypeLib2_AddRef((ITypeLib*)This->pTypeLib);
1890 return ++(This->ref);
1893 /* ITypeInfo::Release
1895 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
1897 ICOM_THIS( ITypeInfoImpl, iface);
1898 FIXME("(%p)->ref is %u: stub\n",This, This->ref);
1899 TRACE("(%p)->(%u)\n",This, This->ref);
1901 ITypeLib2_Release((ITypeLib*)This->pTypeLib);
1903 if (!--(This->ref))
1905 /* fixme destroy child objects */
1907 TRACE(" destroying ITypeInfo(%p)\n",This);
1909 HeapFree(GetProcessHeap(),0,This);
1910 return 0;
1912 return This->ref;
1915 /* ITypeInfo::GetTypeAttr
1917 * Retrieves a TYPEATTR structure that contains the attributes of the type
1918 * description.
1921 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
1922 LPTYPEATTR *ppTypeAttr)
1924 ICOM_THIS( ITypeInfoImpl, iface);
1925 TRACE("(%p)\n",This);
1926 /* FIXME: must do a copy here */
1927 *ppTypeAttr=&This->TypeAttr;
1928 return S_OK;
1931 /* ITypeInfo::GetTypeComp
1933 * Retrieves the ITypeComp interface for the type description, which enables a
1934 * client compiler to bind to the type description's members.
1937 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
1938 ITypeComp * *ppTComp)
1940 ICOM_THIS( ITypeInfoImpl, iface);
1941 FIXME("(%p) stub!\n", This);
1942 return S_OK;
1945 /* ITypeInfo::GetFuncDesc
1947 * Retrieves the FUNCDESC structure that contains information about a
1948 * specified function.
1951 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
1952 LPFUNCDESC *ppFuncDesc)
1954 ICOM_THIS( ITypeInfoImpl, iface);
1955 int i;
1956 TLBFuncDesc * pFDesc;
1957 TRACE("(%p) index %d\n", This, index);
1958 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
1960 if(pFDesc){
1961 /* FIXME: must do a copy here */
1962 *ppFuncDesc=&pFDesc->funcdesc;
1963 return S_OK;
1965 return E_INVALIDARG;
1968 /* ITypeInfo::GetVarDesc
1970 * Retrieves a VARDESC structure that describes the specified variable.
1973 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
1974 LPVARDESC *ppVarDesc)
1976 ICOM_THIS( ITypeInfoImpl, iface);
1977 int i;
1978 TLBVarDesc * pVDesc;
1979 TRACE("(%p) index %d\n", This, index);
1980 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
1982 if(pVDesc){
1983 /* FIXME: must do a copy here */
1984 *ppVarDesc=&pVDesc->vardesc;
1985 return S_OK;
1987 return E_INVALIDARG;
1990 /* ITypeInfo_GetNames
1992 * Retrieves the variable with the specified member ID (or the name of the
1993 * property or method and its parameters) that correspond to the specified
1994 * function ID.
1996 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
1997 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
1999 ICOM_THIS( ITypeInfoImpl, iface);
2000 TLBFuncDesc * pFDesc;
2001 TLBVarDesc * pVDesc;
2002 int i;
2003 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
2004 for(pFDesc=This->funclist; pFDesc->funcdesc.memid != memid && pFDesc; pFDesc=pFDesc->next);
2005 if(pFDesc)
2007 /* function found, now return function and parameter names */
2008 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
2010 if(!i)
2011 *rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
2012 else
2013 rgBstrNames[i]=TLB_DupAtoBstr(pFDesc->pParamDesc[i-1].Name);
2015 *pcNames=i;
2017 else
2019 for(pVDesc=This->varlist; pVDesc->vardesc.memid != memid && pVDesc; pVDesc=pVDesc->next);
2020 if(pVDesc)
2022 *rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
2023 *pcNames=1;
2025 else
2027 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
2029 /* recursive search */
2030 ITypeInfo *pTInfo;
2031 HRESULT result;
2032 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->reference, &pTInfo);
2033 if(SUCCEEDED(result))
2035 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
2036 ITypeInfo_Release(pTInfo);
2037 return result;
2039 WARN("Could not search inherited interface!\n");
2041 else
2043 WARN("no names found\n");
2045 *pcNames=0;
2046 return TYPE_E_ELEMENTNOTFOUND;
2049 return S_OK;
2053 /* ITypeInfo::GetRefTypeOfImplType
2055 * If a type description describes a COM class, it retrieves the type
2056 * description of the implemented interface types. For an interface,
2057 * GetRefTypeOfImplType returns the type information for inherited interfaces,
2058 * if any exist.
2061 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
2062 ITypeInfo2 *iface,
2063 UINT index,
2064 HREFTYPE *pRefType)
2066 ICOM_THIS( ITypeInfoImpl, iface);
2067 int(i);
2068 TLBRefType *pIref = This->impltypelist;
2070 TRACE("(%p) index %d\n", This, index);
2071 dump_TypeInfo(This);
2073 if(index==(UINT)-1)
2075 /* get the retated interface for this dispinterface */
2076 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
2077 FIXME("TKIND_INTERFACE expected\n");
2078 return TYPE_E_ELEMENTNOTFOUND;
2081 /* get element n from linked list */
2082 for(i=0; i<index; i++)
2084 if (!pIref) return TYPE_E_ELEMENTNOTFOUND;
2085 pIref = pIref->next;
2088 *pRefType = pIref->reference;
2089 TRACE("-- 0x%08lx %s\n",pIref->reference, debugstr_guid(&pIref->guid) );
2090 return S_OK;
2093 /* ITypeInfo::GetImplTypeFlags
2095 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
2096 * or base interface in a type description.
2098 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
2099 UINT index, INT *pImplTypeFlags)
2101 ICOM_THIS( ITypeInfoImpl, iface);
2102 int(i);
2103 TLBRefType *pIref;
2104 TRACE("(%p) index %d\n", This, index);
2105 for(i=0, pIref=This->impltypelist; i<index && pIref; i++, pIref=pIref->next)
2107 if(i==index && pIref){
2108 *pImplTypeFlags=pIref->flags;
2109 return S_OK;
2111 *pImplTypeFlags=0;
2112 return TYPE_E_ELEMENTNOTFOUND;
2115 /* GetIDsOfNames
2116 * Maps between member names and member IDs, and parameter names and
2117 * parameter IDs.
2119 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
2120 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
2122 ICOM_THIS( ITypeInfoImpl, iface);
2123 TLBFuncDesc * pFDesc;
2124 TLBVarDesc * pVDesc;
2125 HRESULT ret=S_OK;
2126 PCHAR aszName= HEAP_strdupWtoA( GetProcessHeap(), 0, *rgszNames);
2127 TRACE("(%p) Name %s cNames %d\n", This, debugstr_a(aszName),
2128 cNames);
2129 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
2130 int i, j;
2131 if( !strcmp(aszName, pFDesc->Name)) {
2132 if(cNames) *pMemId=pFDesc->funcdesc.memid;
2133 for(i=1; i < cNames; i++){
2134 PCHAR aszPar= HEAP_strdupWtoA( GetProcessHeap(), 0,
2135 rgszNames[i]);
2136 for(j=0; j<pFDesc->funcdesc.cParams; j++)
2137 if(strcmp(aszPar,pFDesc->pParamDesc[j].Name))
2138 break;
2139 if( j<pFDesc->funcdesc.cParams)
2140 pMemId[i]=j;
2141 else
2142 ret=DISP_E_UNKNOWNNAME;
2143 HeapFree( GetProcessHeap(), 0, aszPar);
2145 HeapFree (GetProcessHeap(), 0, aszName);
2146 return ret;
2149 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
2150 if( !strcmp(aszName, pVDesc->Name)) {
2151 if(cNames) *pMemId=pVDesc->vardesc.memid;
2152 HeapFree (GetProcessHeap(), 0, aszName);
2153 return ret;
2156 /* not found, see if this is and interface with an inheritance */
2157 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
2158 This->TypeAttr.cImplTypes ){
2159 /* recursive search */
2160 ITypeInfo *pTInfo;
2161 ret=ITypeInfo_GetRefTypeInfo(iface,
2162 This->impltypelist->reference, &pTInfo);
2163 if(SUCCEEDED(ret)){
2164 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
2165 ITypeInfo_Release(pTInfo);
2166 return ret;
2168 WARN("Could not search inherited interface!\n");
2169 } else
2170 WARN("no names found\n");
2171 return DISP_E_UNKNOWNNAME;
2174 /* ITypeInfo::Invoke
2176 * Invokes a method, or accesses a property of an object, that implements the
2177 * interface described by the type description.
2179 static HRESULT WINAPI ITypeInfo_fnInvoke(
2180 ITypeInfo2 *iface,
2181 VOID *pIUnk,
2182 MEMBERID memid,
2183 UINT16 dwFlags,
2184 DISPPARAMS *pDispParams,
2185 VARIANT *pVarResult,
2186 EXCEPINFO *pExcepInfo,
2187 UINT *pArgErr)
2189 ICOM_THIS( ITypeInfoImpl, iface);
2190 FIXME("(%p)(%p,id=0x%08lx,0x%08x,%p,%p,%p,%p) stub!\n",
2191 This, pIUnk, memid, dwFlags, pDispParams, pVarResult, pExcepInfo, pArgErr );
2192 dump_DispParms(pDispParams);
2193 return S_OK;
2196 /* ITypeInfo::GetDocumentation
2198 * Retrieves the documentation string, the complete Help file name and path,
2199 * and the context ID for the Help topic for a specified type description.
2201 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
2202 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
2203 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
2205 ICOM_THIS( ITypeInfoImpl, iface);
2206 TLBFuncDesc * pFDesc;
2207 TLBVarDesc * pVDesc;
2208 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
2209 " HelpContext(%p) HelpFile(%p)\n",
2210 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
2211 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
2212 if(pBstrName)
2213 *pBstrName=TLB_DupAtoBstr(This->Name);
2214 if(pBstrDocString)
2215 *pBstrDocString=TLB_DupAtoBstr(This->DocString);
2216 if(pdwHelpContext)
2217 *pdwHelpContext=This->dwHelpContext;
2218 if(pBstrHelpFile)
2219 *pBstrHelpFile=TLB_DupAtoBstr(This->DocString);/* FIXME */
2220 return S_OK;
2221 }else {/* for a member */
2222 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
2223 if(pFDesc->funcdesc.memid==memid){
2224 return S_OK;
2226 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
2227 if(pVDesc->vardesc.memid==memid){
2228 return S_OK;
2231 return TYPE_E_ELEMENTNOTFOUND;
2234 /* ITypeInfo::GetDllEntry
2236 * Retrieves a description or specification of an entry point for a function
2237 * in a DLL.
2239 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
2240 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
2241 WORD *pwOrdinal)
2243 ICOM_THIS( ITypeInfoImpl, iface);
2244 FIXME("(%p) stub!\n", This);
2245 return E_FAIL;
2248 /* ITypeInfo::GetRefTypeInfo
2250 * If a type description references other type descriptions, it retrieves
2251 * the referenced type descriptions.
2253 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
2254 ITypeInfo2 *iface,
2255 HREFTYPE hRefType,
2256 ITypeInfo **ppTInfo)
2258 ICOM_THIS( ITypeInfoImpl, iface);
2259 HRESULT result;
2261 if(HREFTYPE_INTHISFILE(hRefType))
2263 ITypeLib *pTLib;
2264 int Index;
2265 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
2266 if(SUCCEEDED( result ))
2268 result=ITypeLib2_GetTypeInfo(pTLib, HREFTYPE_INDEX(hRefType), ppTInfo);
2269 ITypeLib2_Release(pTLib );
2272 else
2274 /* imported type lib */
2275 TLBRefType * pRefType;
2276 ITypeLibImpl *pTypeLib;
2277 for( pRefType=This->impltypelist; pRefType &&
2278 pRefType->reference != hRefType; pRefType=pRefType->next);
2279 if(!pRefType)
2280 return TYPE_E_ELEMENTNOTFOUND; /* FIXME : correct? */
2282 pTypeLib = pRefType->pImpTLInfo->pImpTypeLib;
2283 if(pTypeLib) /* typelib already loaded */
2285 result=ITypeLib2_GetTypeInfoOfGuid(
2286 (LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
2288 else
2290 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
2291 0,0,0, /* FIXME */
2292 (LPTYPELIB *)&pTypeLib);
2293 if(!SUCCEEDED(result))
2295 BSTR libnam=TLB_DupAtoBstr(pRefType->pImpTLInfo->name);
2296 result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib);
2297 SysFreeString(libnam);
2299 if(SUCCEEDED(result))
2301 result=ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
2302 pRefType->pImpTLInfo->pImpTypeLib = pTypeLib;
2306 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
2307 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
2308 return result;
2311 /* ITypeInfo::AddressOfMember
2313 * Retrieves the addresses of static functions or variables, such as those
2314 * defined in a DLL.
2316 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
2317 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
2319 ICOM_THIS( ITypeInfoImpl, iface);
2320 FIXME("(%p) stub!\n", This);
2321 return S_OK;
2324 /* ITypeInfo::CreateInstance
2326 * Creates a new instance of a type that describes a component object class
2327 * (coclass).
2329 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
2330 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
2332 ICOM_THIS( ITypeInfoImpl, iface);
2333 FIXME("(%p) stub!\n", This);
2334 return S_OK;
2337 /* ITypeInfo::GetMops
2339 * Retrieves marshaling information.
2341 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
2342 BSTR *pBstrMops)
2344 ICOM_THIS( ITypeInfoImpl, iface);
2345 FIXME("(%p) stub!\n", This);
2346 return S_OK;
2349 /* ITypeInfo::GetContainingTypeLib
2351 * Retrieves the containing type library and the index of the type description
2352 * within that type library.
2354 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
2355 ITypeLib * *ppTLib, UINT *pIndex)
2357 ICOM_THIS( ITypeInfoImpl, iface);
2358 *ppTLib=(LPTYPELIB )(This->pTypeLib);
2359 *pIndex=This->index;
2360 ITypeLib2_AddRef(*ppTLib);
2361 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
2362 return S_OK;
2365 /* ITypeInfo::ReleaseTypeAttr
2367 * Releases a TYPEATTR previously returned by GetTypeAttr.
2370 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
2371 TYPEATTR* pTypeAttr)
2373 ICOM_THIS( ITypeInfoImpl, iface);
2374 TRACE("(%p)->(%p)\n", This, pTypeAttr);
2375 return S_OK;
2378 /* ITypeInfo::ReleaseFuncDesc
2380 * Releases a FUNCDESC previously returned by GetFuncDesc. *
2382 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
2383 ITypeInfo2 *iface,
2384 FUNCDESC *pFuncDesc)
2386 ICOM_THIS( ITypeInfoImpl, iface);
2387 TRACE("(%p)->(%p)\n", This, pFuncDesc);
2388 return S_OK;
2391 /* ITypeInfo::ReleaseVarDesc
2393 * Releases a VARDESC previously returned by GetVarDesc.
2395 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
2396 VARDESC *pVarDesc)
2398 ICOM_THIS( ITypeInfoImpl, iface);
2399 TRACE("(%p)->(%p)\n", This, pVarDesc);
2400 return S_OK;
2403 /* ITypeInfo2::GetTypeKind
2405 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
2408 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
2409 TYPEKIND *pTypeKind)
2411 ICOM_THIS( ITypeInfoImpl, iface);
2412 *pTypeKind=This->TypeAttr.typekind;
2413 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
2414 return S_OK;
2417 /* ITypeInfo2::GetTypeFlags
2419 * Returns the type flags without any allocations. This returns a DWORD type
2420 * flag, which expands the type flags without growing the TYPEATTR (type
2421 * attribute).
2424 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
2425 UINT *pTypeFlags)
2427 ICOM_THIS( ITypeInfoImpl, iface);
2428 *pTypeFlags=This->TypeAttr.wTypeFlags;
2429 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
2430 return S_OK;
2433 /* ITypeInfo2::GetFuncIndexOfMemId
2434 * Binds to a specific member based on a known DISPID, where the member name
2435 * is not known (for example, when binding to a default member).
2438 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
2439 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
2441 ICOM_THIS( ITypeInfoImpl, iface);
2442 TLBFuncDesc *pFuncInfo;
2443 int i;
2444 HRESULT result;
2445 /* FIXME: should check for invKind??? */
2446 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
2447 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
2448 if(pFuncInfo){
2449 *pFuncIndex=i;
2450 result= S_OK;
2451 }else{
2452 *pFuncIndex=0;
2453 result=E_INVALIDARG;
2455 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
2456 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
2457 return result;
2460 /* TypeInfo2::GetVarIndexOfMemId
2462 * Binds to a specific member based on a known DISPID, where the member name
2463 * is not known (for example, when binding to a default member).
2466 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
2467 MEMBERID memid, UINT *pVarIndex)
2469 ICOM_THIS( ITypeInfoImpl, iface);
2470 TLBVarDesc *pVarInfo;
2471 int i;
2472 HRESULT result;
2473 for(i=0, pVarInfo=This->varlist; pVarInfo &&
2474 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
2476 if(pVarInfo){
2477 *pVarIndex=i;
2478 result= S_OK;
2479 }else{
2480 *pVarIndex=0;
2481 result=E_INVALIDARG;
2483 TRACE("(%p) memid 0x%08lx -> %s\n", This,
2484 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
2485 return result;
2488 /* ITypeInfo2::GetCustData
2490 * Gets the custom data
2492 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
2493 ITypeInfo2 * iface,
2494 REFGUID guid,
2495 VARIANT *pVarVal)
2497 ICOM_THIS( ITypeInfoImpl, iface);
2498 TLBCustData *pCData;
2500 for(pCData=This->pCustData; pCData; pCData = pCData->next)
2501 if( IsEqualIID(guid, &pCData->guid)) break;
2503 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2505 if(pCData)
2507 VariantInit( pVarVal);
2508 VariantCopy( pVarVal, &pCData->data);
2509 return S_OK;
2511 return E_INVALIDARG; /* FIXME: correct? */
2514 /* ITypeInfo2::GetFuncCustData
2516 * Gets the custom data
2518 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
2519 ITypeInfo2 * iface,
2520 UINT index,
2521 REFGUID guid,
2522 VARIANT *pVarVal)
2524 ICOM_THIS( ITypeInfoImpl, iface);
2525 TLBCustData *pCData=NULL;
2526 TLBFuncDesc * pFDesc;
2527 int i;
2528 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
2529 pFDesc=pFDesc->next);
2531 if(pFDesc)
2532 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
2533 if( IsEqualIID(guid, &pCData->guid)) break;
2535 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2537 if(pCData){
2538 VariantInit( pVarVal);
2539 VariantCopy( pVarVal, &pCData->data);
2540 return S_OK;
2542 return E_INVALIDARG; /* FIXME: correct? */
2545 /* ITypeInfo2::GetParamCustData
2547 * Gets the custom data
2549 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
2550 ITypeInfo2 * iface,
2551 UINT indexFunc,
2552 UINT indexParam,
2553 REFGUID guid,
2554 VARIANT *pVarVal)
2556 ICOM_THIS( ITypeInfoImpl, iface);
2557 TLBCustData *pCData=NULL;
2558 TLBFuncDesc * pFDesc;
2559 int i;
2561 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
2563 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
2564 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
2565 pCData = pCData->next)
2566 if( IsEqualIID(guid, &pCData->guid)) break;
2568 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2570 if(pCData)
2572 VariantInit( pVarVal);
2573 VariantCopy( pVarVal, &pCData->data);
2574 return S_OK;
2576 return E_INVALIDARG; /* FIXME: correct? */
2579 /* ITypeInfo2::GetVarcCustData
2581 * Gets the custom data
2583 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
2584 ITypeInfo2 * iface,
2585 UINT index,
2586 REFGUID guid,
2587 VARIANT *pVarVal)
2589 ICOM_THIS( ITypeInfoImpl, iface);
2590 TLBCustData *pCData=NULL;
2591 TLBVarDesc * pVDesc;
2592 int i;
2594 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
2596 if(pVDesc)
2598 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
2600 if( IsEqualIID(guid, &pCData->guid)) break;
2604 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2606 if(pCData)
2608 VariantInit( pVarVal);
2609 VariantCopy( pVarVal, &pCData->data);
2610 return S_OK;
2612 return E_INVALIDARG; /* FIXME: correct? */
2615 /* ITypeInfo2::GetImplcCustData
2617 * Gets the custom data
2619 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
2620 ITypeInfo2 * iface,
2621 UINT index,
2622 REFGUID guid,
2623 VARIANT *pVarVal)
2625 ICOM_THIS( ITypeInfoImpl, iface);
2626 TLBCustData *pCData=NULL;
2627 TLBRefType * pRDesc;
2628 int i;
2630 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
2632 if(pRDesc)
2634 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
2636 if( IsEqualIID(guid, &pCData->guid)) break;
2640 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2642 if(pCData)
2644 VariantInit( pVarVal);
2645 VariantCopy( pVarVal, &pCData->data);
2646 return S_OK;
2648 return E_INVALIDARG; /* FIXME: correct? */
2651 /* ITypeInfo2::GetDocumentation2
2653 * Retrieves the documentation string, the complete Help file name and path,
2654 * the localization context to use, and the context ID for the library Help
2655 * topic in the Help file.
2658 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
2659 ITypeInfo2 * iface,
2660 MEMBERID memid,
2661 LCID lcid,
2662 BSTR *pbstrHelpString,
2663 DWORD *pdwHelpStringContext,
2664 BSTR *pbstrHelpStringDll)
2666 ICOM_THIS( ITypeInfoImpl, iface);
2667 TLBFuncDesc * pFDesc;
2668 TLBVarDesc * pVDesc;
2669 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
2670 "HelpStringContext(%p) HelpStringDll(%p)\n",
2671 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
2672 pbstrHelpStringDll );
2673 /* the help string should be obtained from the helpstringdll,
2674 * using the _DLLGetDocumentation function, based on the supplied
2675 * lcid. Nice to do sometime...
2677 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
2678 if(pbstrHelpString)
2679 *pbstrHelpString=TLB_DupAtoBstr(This->Name);
2680 if(pdwHelpStringContext)
2681 *pdwHelpStringContext=This->dwHelpStringContext;
2682 if(pbstrHelpStringDll)
2683 *pbstrHelpStringDll=
2684 TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
2685 return S_OK;
2686 }else {/* for a member */
2687 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
2688 if(pFDesc->funcdesc.memid==memid){
2689 if(pbstrHelpString)
2690 *pbstrHelpString=TLB_DupAtoBstr(pFDesc->HelpString);
2691 if(pdwHelpStringContext)
2692 *pdwHelpStringContext=pFDesc->HelpStringContext;
2693 if(pbstrHelpStringDll)
2694 *pbstrHelpStringDll=
2695 TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
2696 return S_OK;
2698 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
2699 if(pVDesc->vardesc.memid==memid){
2700 if(pbstrHelpString)
2701 *pbstrHelpString=TLB_DupAtoBstr(pVDesc->HelpString);
2702 if(pdwHelpStringContext)
2703 *pdwHelpStringContext=pVDesc->HelpStringContext;
2704 if(pbstrHelpStringDll)
2705 *pbstrHelpStringDll=
2706 TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
2707 return S_OK;
2710 return TYPE_E_ELEMENTNOTFOUND;
2713 /* ITypeInfo2::GetAllCustData
2715 * Gets all custom data items for the Type info.
2718 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
2719 ITypeInfo2 * iface,
2720 CUSTDATA *pCustData)
2722 ICOM_THIS( ITypeInfoImpl, iface);
2723 TLBCustData *pCData;
2724 int i;
2726 TRACE("(%p) returning %d items\n", This, This->ctCustData);
2728 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
2729 if(pCustData->prgCustData ){
2730 pCustData->cCustData=This->ctCustData;
2731 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
2732 pCustData->prgCustData[i].guid=pCData->guid;
2733 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
2735 }else{
2736 ERR(" OUT OF MEMORY! \n");
2737 return E_OUTOFMEMORY;
2739 return S_OK;
2742 /* ITypeInfo2::GetAllFuncCustData
2744 * Gets all custom data items for the specified Function
2747 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
2748 ITypeInfo2 * iface,
2749 UINT index,
2750 CUSTDATA *pCustData)
2752 ICOM_THIS( ITypeInfoImpl, iface);
2753 TLBCustData *pCData;
2754 TLBFuncDesc * pFDesc;
2755 int i;
2756 TRACE("(%p) index %d\n", This, index);
2757 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
2758 pFDesc=pFDesc->next)
2760 if(pFDesc){
2761 pCustData->prgCustData =
2762 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
2763 if(pCustData->prgCustData ){
2764 pCustData->cCustData=pFDesc->ctCustData;
2765 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
2766 pCData = pCData->next){
2767 pCustData->prgCustData[i].guid=pCData->guid;
2768 VariantCopy(& pCustData->prgCustData[i].varValue,
2769 & pCData->data);
2771 }else{
2772 ERR(" OUT OF MEMORY! \n");
2773 return E_OUTOFMEMORY;
2775 return S_OK;
2777 return TYPE_E_ELEMENTNOTFOUND;
2780 /* ITypeInfo2::GetAllParamCustData
2782 * Gets all custom data items for the Functions
2785 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
2786 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
2788 ICOM_THIS( ITypeInfoImpl, iface);
2789 TLBCustData *pCData=NULL;
2790 TLBFuncDesc * pFDesc;
2791 int i;
2792 TRACE("(%p) index %d\n", This, indexFunc);
2793 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
2794 pFDesc=pFDesc->next)
2796 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
2797 pCustData->prgCustData =
2798 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
2799 sizeof(CUSTDATAITEM));
2800 if(pCustData->prgCustData ){
2801 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
2802 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
2803 pCData; i++, pCData = pCData->next){
2804 pCustData->prgCustData[i].guid=pCData->guid;
2805 VariantCopy(& pCustData->prgCustData[i].varValue,
2806 & pCData->data);
2808 }else{
2809 ERR(" OUT OF MEMORY! \n");
2810 return E_OUTOFMEMORY;
2812 return S_OK;
2814 return TYPE_E_ELEMENTNOTFOUND;
2817 /* ITypeInfo2::GetAllVarCustData
2819 * Gets all custom data items for the specified Variable
2822 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
2823 UINT index, CUSTDATA *pCustData)
2825 ICOM_THIS( ITypeInfoImpl, iface);
2826 TLBCustData *pCData;
2827 TLBVarDesc * pVDesc;
2828 int i;
2829 TRACE("(%p) index %d\n", This, index);
2830 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
2831 pVDesc=pVDesc->next)
2833 if(pVDesc){
2834 pCustData->prgCustData =
2835 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
2836 if(pCustData->prgCustData ){
2837 pCustData->cCustData=pVDesc->ctCustData;
2838 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
2839 pCData = pCData->next){
2840 pCustData->prgCustData[i].guid=pCData->guid;
2841 VariantCopy(& pCustData->prgCustData[i].varValue,
2842 & pCData->data);
2844 }else{
2845 ERR(" OUT OF MEMORY! \n");
2846 return E_OUTOFMEMORY;
2848 return S_OK;
2850 return TYPE_E_ELEMENTNOTFOUND;
2853 /* ITypeInfo2::GetAllImplCustData
2855 * Gets all custom data items for the specified implementation type
2858 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
2859 ITypeInfo2 * iface,
2860 UINT index,
2861 CUSTDATA *pCustData)
2863 ICOM_THIS( ITypeInfoImpl, iface);
2864 TLBCustData *pCData;
2865 TLBRefType * pRDesc;
2866 int i;
2867 TRACE("(%p) index %d\n", This, index);
2868 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
2869 pRDesc=pRDesc->next)
2871 if(pRDesc){
2872 pCustData->prgCustData =
2873 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
2874 if(pCustData->prgCustData ){
2875 pCustData->cCustData=pRDesc->ctCustData;
2876 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
2877 pCData = pCData->next){
2878 pCustData->prgCustData[i].guid=pCData->guid;
2879 VariantCopy(& pCustData->prgCustData[i].varValue,
2880 & pCData->data);
2882 }else{
2883 ERR(" OUT OF MEMORY! \n");
2884 return E_OUTOFMEMORY;
2886 return S_OK;
2888 return TYPE_E_ELEMENTNOTFOUND;
2891 static ICOM_VTABLE(ITypeInfo2) tinfvt =
2893 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2895 ITypeInfo_fnQueryInterface,
2896 ITypeInfo_fnAddRef,
2897 ITypeInfo_fnRelease,
2899 ITypeInfo_fnGetTypeAttr,
2900 ITypeInfo_fnGetTypeComp,
2901 ITypeInfo_fnGetFuncDesc,
2902 ITypeInfo_fnGetVarDesc,
2903 ITypeInfo_fnGetNames,
2904 ITypeInfo_fnGetRefTypeOfImplType,
2905 ITypeInfo_fnGetImplTypeFlags,
2906 ITypeInfo_fnGetIDsOfNames,
2907 ITypeInfo_fnInvoke,
2908 ITypeInfo_fnGetDocumentation,
2909 ITypeInfo_fnGetDllEntry,
2910 ITypeInfo_fnGetRefTypeInfo,
2911 ITypeInfo_fnAddressOfMember,
2912 ITypeInfo_fnCreateInstance,
2913 ITypeInfo_fnGetMops,
2914 ITypeInfo_fnGetContainingTypeLib,
2915 ITypeInfo_fnReleaseTypeAttr,
2916 ITypeInfo_fnReleaseFuncDesc,
2917 ITypeInfo_fnReleaseVarDesc,
2919 ITypeInfo2_fnGetTypeKind,
2920 ITypeInfo2_fnGetTypeFlags,
2921 ITypeInfo2_fnGetFuncIndexOfMemId,
2922 ITypeInfo2_fnGetVarIndexOfMemId,
2923 ITypeInfo2_fnGetCustData,
2924 ITypeInfo2_fnGetFuncCustData,
2925 ITypeInfo2_fnGetParamCustData,
2926 ITypeInfo2_fnGetVarCustData,
2927 ITypeInfo2_fnGetImplTypeCustData,
2928 ITypeInfo2_fnGetDocumentation2,
2929 ITypeInfo2_fnGetAllCustData,
2930 ITypeInfo2_fnGetAllFuncCustData,
2931 ITypeInfo2_fnGetAllParamCustData,
2932 ITypeInfo2_fnGetAllVarCustData,
2933 ITypeInfo2_fnGetAllImplTypeCustData,