Repaired shared PE data sections.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blobaf4852c12105bbe721f17317d54ec531e1b1ca08
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * --------------------------------------------------------------------------------------
8 * Known problems (2000, Francois Jacques)
10 * - Tested using OLEVIEW (Platform SDK tool) only.
12 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
13 * creating by doing a straight copy of the dispinterface instance and just changing
14 * its typekind. Pointed structures aren't copied - only the address of the pointers.
15 * So when you release the dispinterface, you delete the vtable-interface structures
16 * as well... fortunately, clean up of structures is not implemented.
18 * - locale stuff is partially implemented but hasn't been tested.
20 * - imported typelib should be stored together in a linked list instead of having
21 * independant TLBImpLib strucutures in each ITypeInfo. This way, imported libraries
22 * are just imported once (major optimization)
24 * - typelib file is still read it's in entirety, but it is released now.
25 * - some garbage is read from function names on some very rare occasion
27 * --------------------------------------------------------------------------------------
28 * Known problems left from previous implementation (1999, Rein Klazes) :
30 * -. Only one format of typelibs is supported
31 * -. Data structures are straightforward, but slow for look-ups.
32 * -. (related) nothing is hashed
33 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
34 * of them I don't know yet how to implement them.
35 * -. Most error return values are just guessed not checked with windows
36 * behaviour.
37 * -. didn't bother with a c++ interface
38 * -. lousy fatal error handling
39 * -. some methods just return pointers to internal data structures, this is
40 * partly laziness, partly I want to check how windows does it.
44 #include <stdlib.h>
45 #include <string.h>
46 #include <stdio.h>
47 #include <ctype.h>
48 #include "winerror.h"
49 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
50 #include "winnls.h" /* for PRIMARYLANGID */
51 #include "ole.h"
52 #include "heap.h"
53 #include "wine/obj_base.h"
54 #include "debugtools.h"
55 #include "typelib.h"
57 DEFAULT_DEBUG_CHANNEL(ole);
58 DECLARE_DEBUG_CHANNEL(typelib);
60 /****************************************************************************
61 * QueryPathOfRegTypeLib16 [TYPELIB.14]
63 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
64 * RETURNS
65 * path of typelib
67 HRESULT WINAPI
68 QueryPathOfRegTypeLib16(
69 REFGUID guid, /* [in] referenced guid */
70 WORD wMaj, /* [in] major version */
71 WORD wMin, /* [in] minor version */
72 LCID lcid, /* [in] locale id */
73 LPBSTR16 path /* [out] path of typelib */
74 ) {
75 char xguid[80];
76 char typelibkey[100],pathname[260];
77 DWORD plen;
79 TRACE("\n");
81 if (HIWORD(guid)) {
82 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
83 guid->Data1, guid->Data2, guid->Data3,
84 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
85 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
86 wMaj,wMin,lcid);
87 } else {
88 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
89 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
90 return E_FAIL;
92 plen = sizeof(pathname);
93 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
94 /* try again without lang specific id */
95 if (SUBLANGID(lcid))
96 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
97 FIXME("key %s not found\n",typelibkey);
98 return E_FAIL;
100 *path = SysAllocString16(pathname);
101 return S_OK;
104 /****************************************************************************
105 * QueryPathOfRegTypeLib [OLEAUT32.164]
106 * RETURNS
107 * path of typelib
109 HRESULT WINAPI
110 QueryPathOfRegTypeLib(
111 REFGUID guid, /* [in] referenced guid */
112 WORD wMaj, /* [in] major version */
113 WORD wMin, /* [in] minor version */
114 LCID lcid, /* [in] locale id */
115 LPBSTR path ) /* [out] path of typelib */
117 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
118 string termination character on output strings */
120 HRESULT hr = E_FAIL;
122 DWORD dwPathLen = _MAX_PATH;
123 LCID myLCID = lcid;
125 char szXGUID[80];
126 char szTypeLibKey[100];
127 char szPath[dwPathLen];
129 if ( !HIWORD(guid) )
131 sprintf(szXGUID,
132 "<guid 0x%08lx>",
133 (DWORD) guid);
135 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
136 return E_FAIL;
139 while (hr != S_OK)
141 sprintf(szTypeLibKey,
142 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
143 guid->Data1, guid->Data2, guid->Data3,
144 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
145 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
146 wMaj,
147 wMin,
148 myLCID);
150 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
152 if (!lcid)
153 break;
154 else if (myLCID == lcid)
156 /* try with sub-langid */
157 myLCID = SUBLANGID(lcid);
159 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
161 /* try with system langid */
162 myLCID = 0;
164 else
166 break;
169 else
171 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
172 BSTR bstrPath = SysAllocStringLen(NULL,len);
174 MultiByteToWideChar(CP_ACP,
175 MB_PRECOMPOSED,
176 szPath,
177 dwPathLen,
178 bstrPath,
179 len);
180 *path = bstrPath;
181 hr = S_OK;
185 if (hr != S_OK)
186 TRACE_(typelib)("%s not found\n", szTypeLibKey);
188 return hr;
191 /******************************************************************************
192 * CreateTypeLib [OLEAUT32] creates a typelib
194 * RETURNS
195 * Success: S_OK
196 * Failure: Status
198 HRESULT WINAPI CreateTypeLib(
199 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
201 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
202 return E_FAIL;
204 /******************************************************************************
205 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
206 * NOTES
207 * Docs: OLECHAR FAR* szFile
208 * Docs: iTypeLib FAR* FAR* pptLib
210 * RETURNS
211 * Success: S_OK
212 * Failure: Status
214 HRESULT WINAPI LoadTypeLib16(
215 LPOLESTR szFile, /* [in] Name of file to load from */
216 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
218 FIXME("('%s',%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
220 if (pptLib!=0)
221 *pptLib=0;
223 return E_FAIL;
226 /******************************************************************************
227 * LoadTypeLib [OLEAUT32.161]
228 * Loads and registers a type library
229 * NOTES
230 * Docs: OLECHAR FAR* szFile
231 * Docs: iTypeLib FAR* FAR* pptLib
233 * RETURNS
234 * Success: S_OK
235 * Failure: Status
237 int TLB_ReadTypeLib(PCHAR file, ITypeLib2 **ppTypelib);
239 HRESULT WINAPI LoadTypeLib(
240 const OLECHAR *szFile,/* [in] Name of file to load from */
241 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
243 TRACE("\n");
244 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
247 /******************************************************************************
248 * LoadTypeLibEx [OLEAUT32.183]
249 * Loads and optionally registers a type library
251 * RETURNS
252 * Success: S_OK
253 * Failure: Status
255 HRESULT WINAPI LoadTypeLibEx(
256 LPCOLESTR szFile, /* [in] Name of file to load from */
257 REGKIND regkind, /* [in] Specify kind of registration */
258 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
260 LPSTR p;
261 HRESULT res;
262 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
264 p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile);
266 if(regkind != REGKIND_NONE)
267 FIXME ("registration of typelibs not supported yet!\n");
269 res= TLB_ReadTypeLib(p, (ITypeLib2**)pptLib);
270 HeapFree(GetProcessHeap(),0,p);
271 TRACE(" returns %08lx\n",res);
273 return res;
276 /******************************************************************************
277 * LoadRegTypeLib [OLEAUT32.162]
279 HRESULT WINAPI LoadRegTypeLib(
280 REFGUID rguid, /* [in] referenced guid */
281 WORD wVerMajor, /* [in] major version */
282 WORD wVerMinor, /* [in] minor version */
283 LCID lcid, /* [in] locale id */
284 ITypeLib **ppTLib) /* [out] path of typelib */
286 BSTR bstr=NULL;
287 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
289 if(SUCCEEDED(res))
291 res= LoadTypeLib(bstr, ppTLib);
292 SysFreeString(bstr);
295 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
297 return res;
301 /******************************************************************************
302 * RegisterTypeLib [OLEAUT32.163]
303 * Adds information about a type library to the System Registry
304 * NOTES
305 * Docs: ITypeLib FAR * ptlib
306 * Docs: OLECHAR FAR* szFullPath
307 * Docs: OLECHAR FAR* szHelpDir
309 * RETURNS
310 * Success: S_OK
311 * Failure: Status
313 HRESULT WINAPI RegisterTypeLib(
314 ITypeLib * ptlib, /* [in] Pointer to the library*/
315 OLECHAR * szFullPath, /* [in] full Path of the library*/
316 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
317 may be NULL*/
318 { FIXME("(%p,%s,%s): stub\n",ptlib, debugstr_w(szFullPath),debugstr_w(szHelpDir));
319 return S_OK; /* FIXME: pretend everything is OK */
323 /******************************************************************************
324 * UnRegisterTypeLib [OLEAUT32.186]
325 * Removes information about a type library from the System Registry
326 * NOTES
328 * RETURNS
329 * Success: S_OK
330 * Failure: Status
332 HRESULT WINAPI UnRegisterTypeLib(
333 REFGUID libid, /* [in] Guid of the library */
334 WORD wVerMajor, /* [in] major version */
335 WORD wVerMinor, /* [in] minor version */
336 LCID lcid, /* [in] locale id */
337 SYSKIND syskind)
339 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
340 return S_OK; /* FIXME: pretend everything is OK */
343 /****************************************************************************
344 * OaBuildVersion (TYPELIB.15)
346 * known TYPELIB.DLL versions:
348 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
349 * OLE 2.02 1993-94 02 3002
350 * OLE 2.03 23 730
351 * OLE 2.03 03 3025
352 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
353 * OLE 2.1 NT 1993-95 ?? ???
354 * OLE 2.3.1 W95 23 700
355 * OLE2 4.0 NT4SP6 1993-98 40 4277
357 DWORD WINAPI OaBuildVersion16(void)
359 /* FIXME: I'd like to return the highest currently known version value
360 * in case the user didn't force a --winver, but I don't know how
361 * to retrieve the "versionForced" info from misc/version.c :(
362 * (this would be useful in other places, too) */
363 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
364 switch(GetVersion() & 0x8000ffff) /* mask off build number */
366 case 0x80000a03: /* WIN31 */
367 return MAKELONG(3027, 3); /* WfW 3.11 */
368 case 0x80000004: /* WIN95 */
369 return MAKELONG(700, 23); /* Win95A */
370 case 0x80000a04: /* WIN98 */
371 return MAKELONG(3024, 10); /* W98 SE */
372 case 0x00000004: /* NT4 */
373 return MAKELONG(4277, 40); /* NT4 SP6 */
374 default:
375 FIXME("Version value not known yet. Please investigate it !");
376 return 0;
380 /* for better debugging info leave the static out for the time being */
381 #define static
383 /*======================= ITypeLib implementation =======================*/
385 typedef struct tagTLBCustData
387 GUID guid;
388 VARIANT data;
389 struct tagTLBCustData* next;
390 } TLBCustData;
392 /* data structure for import typelibs */
393 typedef struct tagTLBImpLib
395 int offset; /* offset in the file */
396 GUID guid; /* libid */
397 BSTR name; /* name; */
399 LCID lcid; /* lcid of imported typelib */
401 WORD wVersionMajor; /* major version number */
402 WORD wVersionMinor; /* minor version number */
404 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib */
405 struct tagTLBImpLib * next;
406 } TLBImpLib;
408 /* internal ITypeLib data */
409 typedef struct tagITypeLibImpl
411 ICOM_VFIELD(ITypeLib2);
412 UINT ref;
413 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
415 /* strings can be stored in tlb as multibyte strings BUT they are *always*
416 * exported to the application as a UNICODE string.
418 BSTR Name;
419 BSTR DocString;
420 BSTR HelpFile;
421 BSTR HelpStringDll;
422 unsigned long dwHelpContext;
423 int TypeInfoCount; /* nr of typeinfo's in librarry */
424 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
425 int ctCustData; /* number of items in cust data list */
426 TLBCustData * pCustData; /* linked list to cust data; */
427 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
428 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the libary */
429 } ITypeLibImpl;
431 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
433 /* ITypeLib methods */
434 static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength);
436 /*======================= ITypeInfo implementation =======================*/
438 /* data for refernced types in a coclass, or an inherited interface */
439 typedef struct tagTLBRefType
441 GUID guid; /* guid of the referenced type */
442 /* (important if its a imported type) */
443 HREFTYPE reference;
444 int flags;
445 int ctCustData;
446 TLBCustData * pCustData;/* linked list to custom data; */
447 TLBImpLib *pImpTLInfo;
448 struct tagTLBRefType * next;
449 } TLBRefType;
451 /* internal Parameter data */
452 typedef struct tagTLBParDesc
454 BSTR Name;
455 int ctCustData;
456 TLBCustData * pCustData; /* linked list to cust data; */
457 TLBRefType * pRefType; /* linked list to referenced types */
458 } TLBParDesc;
460 /* internal Function data */
461 typedef struct tagTLBFuncDesc
463 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
464 BSTR Name; /* the name of this function */
465 TLBParDesc *pParamDesc; /* array with name and custom data */
466 int helpcontext;
467 int HelpStringContext;
468 BSTR HelpString;
469 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
470 int ctCustData;
471 TLBCustData * pCustData; /* linked list to cust data; */
472 struct tagTLBFuncDesc * next;
473 } TLBFuncDesc;
475 /* internal Variable data */
476 typedef struct tagTLBVarDesc
478 VARDESC vardesc; /* lots of info on the variable and its attributes. */
479 BSTR Name; /* the name of this variable */
480 int HelpContext;
481 int HelpStringContext; /* fixme: where? */
482 BSTR HelpString;
483 int ctCustData;
484 TLBCustData * pCustData;/* linked list to cust data; */
485 struct tagTLBVarDesc * next;
486 } TLBVarDesc;
488 /* internal TypeInfo data */
489 typedef struct tagITypeInfoImpl
491 ICOM_VFIELD(ITypeInfo2);
492 UINT ref;
493 TYPEATTR TypeAttr ; /* _lots_ of type information. */
494 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
495 int index; /* index in this typelib; */
496 /* type libs seem to store the doc strings in ascii
497 * so why should we do it in unicode?
499 BSTR Name;
500 BSTR DocString;
501 unsigned long dwHelpContext;
502 unsigned long dwHelpStringContext;
504 /* functions */
505 TLBFuncDesc * funclist; /* linked list with function descriptions */
507 /* variables */
508 TLBVarDesc * varlist; /* linked list with variable descriptions */
510 /* Implemented Interfaces */
511 TLBRefType * impltypelist;
512 int ctCustData;
513 TLBCustData * pCustData; /* linked list to cust data; */
514 struct tagITypeInfoImpl * next;
515 } ITypeInfoImpl;
517 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
519 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
521 typedef struct tagTLBContext
523 unsigned int oStart; /* start of TLB in file */
524 unsigned int pos; /* current pos */
525 unsigned int length; /* total length */
526 void *mapping; /* memory mapping */
527 TLBSegDir * pTblDir;
528 ITypeLibImpl* pLibInfo;
529 } TLBContext;
532 static void TLB_DoRefType(TLBContext *pcx, int offset, TLBRefType ** pprtd);
535 debug
537 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
539 while (pfd)
541 TRACE_(typelib)("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
542 pfd = pfd->next;
545 static void dump_TLBVarDesc(TLBVarDesc * pvd)
547 while (pvd)
549 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
550 pvd = pvd->next;
553 static void dump_TLBRefType(TLBRefType * prt)
555 while (prt)
557 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
558 TRACE_(typelib)(" href:0x%08lx\n", prt->reference);
559 prt = prt->next;
563 static void dump_Variant(VARIANT * pvar)
565 char szVarType[15];
567 TRACE("(%p)\n", pvar);
569 if (!pvar) return;
571 ZeroMemory(szVarType, sizeof(szVarType));
573 /* FIXME : we could have better trace here, depending on the VARTYPE
574 * of the variant
576 switch(V_VT(pvar))
578 case VT_UI1:
579 sprintf(szVarType, "VT_UI");
580 break;
582 case VT_I2:
583 sprintf(szVarType, "VT_I2");
584 break;
586 case VT_I4:
587 sprintf(szVarType, "VT_I4");
588 break;
590 case VT_R4:
591 sprintf(szVarType, "VT_R4");
592 break;
594 case VT_R8:
595 sprintf(szVarType, "VT_R8");
596 break;
598 case VT_BOOL:
599 sprintf(szVarType, "VT_BOOL");
600 break;
602 case VT_ERROR:
603 sprintf(szVarType, "VT_ERROR");
604 break;
606 case VT_CY:
607 sprintf(szVarType, "VT_CY");
608 break;
610 case VT_DATE:
611 sprintf(szVarType, "VT_DATE");
612 break;
614 case VT_BSTR:
615 sprintf(szVarType, "VT_BSTR");
616 break;
618 case VT_BYREF:
619 case VT_UNKNOWN:
620 sprintf(szVarType, "VT_BYREF");
621 break;
623 case VT_DISPATCH:
624 sprintf(szVarType, "VT_DISPATCH");
625 break;
627 case VT_ARRAY:
628 sprintf(szVarType, "VT_ARRAY");
629 break;
631 case VT_I1:
632 sprintf(szVarType, "VT_I2");
633 break;
635 case VT_UI2:
636 sprintf(szVarType, "VT_UI2");
637 break;
639 case VT_UI4:
640 sprintf(szVarType, "VT_UI4");
641 break;
643 case VT_INT:
644 sprintf(szVarType, "VT_INT");
645 break;
647 case VT_UINT:
648 sprintf(szVarType, "VT_UINT");
649 break;
652 TRACE("VARTYPE: %s", szVarType);
654 switch (V_VT(pvar))
656 case VT_R4:
657 TRACE("%3.3e\n", V_UNION(pvar, fltVal));
658 break;
660 case VT_R8:
661 TRACE("%3.3e\n", V_UNION(pvar, dblVal));
662 break;
664 default:
665 TRACE("%ld\n", V_UNION(pvar, lVal));
666 break;
669 if (pvar->vt & VT_BYREF)
670 return dump_Variant(pvar->u.pvarVal);
673 static void dump_DispParms(DISPPARAMS * pdp)
675 int index = 0;
677 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
679 while (index < pdp->cArgs)
681 dump_Variant( &pdp->rgvarg[index] );
682 ++index;
686 static char * typekind_desc[] =
688 "TKIND_ENUM",
689 "TKIND_RECORD",
690 "TKIND_MODULE",
691 "TKIND_INTERFACE",
692 "TKIND_DISPATCH",
693 "TKIND_COCLASS",
694 "TKIND_ALIAS",
695 "TKIND_UNION",
696 "TKIND_MAX"
699 static void dump_TypeInfo(ITypeInfoImpl * pty)
701 TRACE("%p ref=%u\n", pty, pty->ref);
702 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
703 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
704 TRACE("fct:%u var:%u impl:%u\n",
705 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
706 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
707 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
708 dump_TLBFuncDesc(pty->funclist);
709 dump_TLBVarDesc(pty->varlist);
710 dump_TLBRefType(pty->impltypelist);
713 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
715 /* VT_LPWSTR is largest type that */
716 /* may appear in type description*/
717 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
718 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
719 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
720 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
721 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
722 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
723 {{0},30},{{0},31}
726 static void TLB_abort()
728 DebugBreak();
730 static void * TLB_Alloc(unsigned size)
732 void * ret;
733 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
734 /* FIXME */
735 ERR("cannot allocate memory\n");
737 return ret;
740 static void TLB_Free(void * ptr)
742 HeapFree(GetProcessHeap(), 0, ptr);
744 /* read function */
745 DWORD TLB_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
747 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
748 pcx->pos, count, pcx->oStart, pcx->length, where);
750 if (where != DO_NOT_SEEK)
752 where += pcx->oStart;
753 if (where > pcx->length)
755 /* FIXME */
756 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
757 TLB_abort();
759 pcx->pos = where;
761 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
762 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
763 pcx->pos += count;
764 return count;
767 static void TLB_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
769 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
771 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
772 memset(pGuid,0, sizeof(GUID));
773 return;
775 TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
778 BSTR TLB_ReadName( TLBContext *pcx, int offset)
780 char * name;
781 TLBNameIntro niName;
782 int lengthInChars;
783 WCHAR* pwstring = NULL;
784 BSTR bstrName = NULL;
786 TLB_Read(&niName, sizeof(niName), pcx,
787 pcx->pTblDir->pNametab.offset+offset);
788 niName.namelen &= 0xFF; /* FIXME: correct ? */
789 name=TLB_Alloc((niName.namelen & 0xff) +1);
790 TLB_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
791 name[niName.namelen & 0xff]='\0';
793 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
794 name, -1, NULL, 0);
796 /* no invalid characters in string */
797 if (lengthInChars)
799 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
801 /* don't check for invalid character since this has been done previously */
802 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
804 bstrName = SysAllocStringLen(pwstring, lengthInChars);
805 lengthInChars = SysStringLen(bstrName);
806 HeapFree(GetProcessHeap(), 0, pwstring);
809 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
810 return bstrName;
813 BSTR TLB_ReadString( TLBContext *pcx, int offset)
815 char * string;
816 INT16 length;
817 int lengthInChars;
818 BSTR bstr = NULL;
820 if(offset<0) return NULL;
821 TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
822 if(length <= 0) return 0;
823 string=TLB_Alloc(length +1);
824 TLB_Read(string, length, pcx, DO_NOT_SEEK);
825 string[length]='\0';
827 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
828 string, -1, NULL, 0);
830 /* no invalid characters in string */
831 if (lengthInChars)
833 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
835 /* don't check for invalid character since this has been done previously */
836 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
838 bstr = SysAllocStringLen(pwstring, lengthInChars);
839 lengthInChars = SysStringLen(bstr);
840 HeapFree(GetProcessHeap(), 0, pwstring);
843 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
844 return bstr;
847 * read a value and fill a VARIANT structure
849 static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
851 int size;
853 TRACE_(typelib)("\n");
855 if(offset <0) { /* data is packed in here */
856 pVar->vt = (offset & 0x7c000000 )>> 26;
857 V_UNION(pVar, iVal) = offset & 0xffff;
858 return;
860 TLB_Read(&(pVar->vt), sizeof(VARTYPE), pcx,
861 pcx->pTblDir->pCustData.offset + offset );
862 TRACE_(typelib)("Vartype = %x\n", pVar->vt);
863 switch(pVar->vt){
864 case VT_EMPTY: /* FIXME: is this right? */
865 case VT_NULL: /* FIXME: is this right? */
866 case VT_I2 : /* this should not happen */
867 case VT_I4 :
868 case VT_R4 :
869 case VT_ERROR :
870 case VT_BOOL :
871 case VT_I1 :
872 case VT_UI1 :
873 case VT_UI2 :
874 case VT_UI4 :
875 case VT_INT :
876 case VT_UINT :
877 case VT_VOID : /* FIXME: is this right? */
878 case VT_HRESULT :
879 size=4; break;
880 case VT_R8 :
881 case VT_CY :
882 case VT_DATE :
883 case VT_I8 :
884 case VT_UI8 :
885 case VT_DECIMAL : /* FIXME: is this right? */
886 case VT_FILETIME :
887 size=8;break;
888 /* pointer types with known behaviour */
889 case VT_BSTR :{
890 char * ptr;
891 TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
892 if(size <= 0) {
893 FIXME("BSTR length = %d?\n", size);
894 } else {
895 ptr=TLB_Alloc(size);/* allocate temp buffer */
896 TLB_Read(ptr, size, pcx, DO_NOT_SEEK); /* read string (ANSI) */
897 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
898 /* FIXME: do we need a AtoW conversion here? */
899 V_UNION(pVar, bstrVal[size])=L'\0';
900 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
901 TLB_Free(ptr);
904 size=-4; break;
905 /* FIXME: this will not work AT ALL when the variant contains a pointer */
906 case VT_DISPATCH :
907 case VT_VARIANT :
908 case VT_UNKNOWN :
909 case VT_PTR :
910 case VT_SAFEARRAY :
911 case VT_CARRAY :
912 case VT_USERDEFINED :
913 case VT_LPSTR :
914 case VT_LPWSTR :
915 case VT_BLOB :
916 case VT_STREAM :
917 case VT_STORAGE :
918 case VT_STREAMED_OBJECT :
919 case VT_STORED_OBJECT :
920 case VT_BLOB_OBJECT :
921 case VT_CF :
922 case VT_CLSID :
923 default:
924 size=0;
925 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
926 pVar->vt);
929 if(size>0) /* (big|small) endian correct? */
930 TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
931 return;
934 * create a linked list with custom data
936 static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
938 TLBCDGuid entry;
939 TLBCustData* pNew;
940 int count=0;
942 TRACE_(typelib)("\n");
944 while(offset >=0){
945 count++;
946 pNew=TLB_Alloc(sizeof(TLBCustData));
947 TLB_Read(&entry, sizeof(entry), pcx,
948 pcx->pTblDir->pCDGuids.offset+offset);
949 TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
950 TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx);
951 /* add new custom data at head of the list */
952 pNew->next=*ppCustData;
953 *ppCustData=pNew;
954 offset = entry.next;
956 return count;
959 static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd )
961 if(type <0)
962 pTd->vt=type & VT_TYPEMASK;
963 else
964 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
966 TRACE_(typelib)("vt type = %X\n", pTd->vt);
969 static void
970 TLB_DoFuncs(TLBContext* pcx,
971 int cFuncs,
972 int cVars,
973 int offset,
974 TLBFuncDesc** pptfd)
977 * member information is stored in a data structure at offset
978 * indicated by the memoffset field of the typeinfo structure
979 * There are several distinctive parts.
980 * the first part starts with a field that holds the total length
981 * of this (first) part excluding this field. Then follow the records,
982 * for each member there is one record.
984 * First entry is always the length of the record (excluding this
985 * length word).
986 * Rest of the record depends on the type of the member. If there is
987 * a field indicating the member type (function variable intereface etc)
988 * I have not found it yet. At this time we depend on the information
989 * in the type info and the usual order how things are stored.
991 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
992 * for each member;
994 * Third is a equal sized array with file offsets to the name entry
995 * of each member.
997 * Forth and last (?) part is an array with offsets to the records in the
998 * first part of this file segment.
1001 int infolen, nameoffset, reclength, nrattributes, i;
1002 int recoffset = offset + sizeof(INT);
1004 char recbuf[512];
1005 TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf;
1007 TRACE_(typelib)("\n");
1009 TLB_Read(&infolen, sizeof(INT), pcx, offset);
1011 for ( i = 0; i < cFuncs ; i++ )
1013 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1015 /* name, eventually add to a hash table */
1016 TLB_Read(&nameoffset,
1017 sizeof(INT),
1018 pcx,
1019 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1021 (*pptfd)->Name = TLB_ReadName(pcx, nameoffset);
1023 /* read the function information record */
1024 TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
1026 reclength &= 0x1ff;
1028 TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1030 /* do the attributes */
1031 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1032 / sizeof(int);
1034 if ( nrattributes > 0 )
1036 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1038 if ( nrattributes > 1 )
1040 (*pptfd)->HelpString = TLB_ReadString(pcx,
1041 pFuncRec->OptAttr[1]) ;
1043 if ( nrattributes > 2 )
1045 if ( pFuncRec->FKCCIC & 0x2000 )
1047 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1049 else
1051 (*pptfd)->Entry = TLB_ReadString(pcx,
1052 pFuncRec->OptAttr[2]);
1054 if( nrattributes > 5 )
1056 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1058 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1060 TLB_CustData(pcx,
1061 pFuncRec->OptAttr[6],
1062 &(*pptfd)->pCustData);
1069 /* fill the FuncDesc Structure */
1070 TLB_Read( & (*pptfd)->funcdesc.memid,
1071 sizeof(INT), pcx,
1072 offset + infolen + ( i + 1) * sizeof(INT));
1074 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1075 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1076 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1077 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1078 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1079 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1080 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1082 TLB_GetTdesc(pcx,
1083 pFuncRec->DataType,
1084 &(*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1086 /* do the parameters/arguments */
1087 if(pFuncRec->nrargs)
1089 int j = 0;
1090 TLBParameterInfo paraminfo;
1092 (*pptfd)->funcdesc.lprgelemdescParam =
1093 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1095 (*pptfd)->pParamDesc =
1096 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1098 TLB_Read(&paraminfo,
1099 sizeof(paraminfo),
1100 pcx,
1101 recoffset + reclength -
1102 pFuncRec->nrargs * sizeof(TLBParameterInfo));
1104 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1106 TYPEDESC* lpArgTypeDesc = 0;
1108 TLB_GetTdesc(pcx,
1109 paraminfo.DataType,
1110 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ;
1112 V_UNION(& ((*pptfd)->funcdesc.lprgelemdescParam[j]),
1113 paramdesc.wParamFlags) = paraminfo.Flags;
1115 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1117 /* SEEK value = jump to offset,
1118 * from there jump to the end of record,
1119 * go back by (j-1) arguments
1121 TLB_Read( &paraminfo ,
1122 sizeof(TLBParameterInfo), pcx,
1123 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1124 * sizeof(TLBParameterInfo)));
1125 lpArgTypeDesc =
1126 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1128 while ( lpArgTypeDesc != NULL )
1130 switch ( lpArgTypeDesc->vt )
1132 case VT_PTR:
1133 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1134 break;
1136 case VT_CARRAY:
1137 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1138 break;
1140 case VT_USERDEFINED:
1141 (*pptfd)->pParamDesc[j].pRefType =
1142 TLB_Alloc(sizeof(TLBRefType));
1144 TLB_DoRefType(pcx,
1145 lpArgTypeDesc->u.hreftype,
1146 & ( (*pptfd)->pParamDesc[j].pRefType ));
1148 lpArgTypeDesc = NULL;
1149 break;
1151 default:
1152 lpArgTypeDesc = NULL;
1158 /* parameter is the return value! */
1159 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1161 TYPEDESC* lpArgTypeDesc;
1163 (*pptfd)->funcdesc.elemdescFunc =
1164 (*pptfd)->funcdesc.lprgelemdescParam[j];
1166 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1168 while ( lpArgTypeDesc != NULL )
1170 switch ( lpArgTypeDesc->vt )
1172 case VT_PTR:
1173 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1174 break;
1175 case VT_CARRAY:
1176 lpArgTypeDesc =
1177 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1179 break;
1181 case VT_USERDEFINED:
1182 (*pptfd)->pParamDesc[j].pRefType
1183 = TLB_Alloc(sizeof(TLBRefType));
1185 TLB_DoRefType(pcx,
1186 lpArgTypeDesc->u.hreftype,
1187 &((*pptfd)->pParamDesc[j].pRefType));
1189 lpArgTypeDesc = NULL;
1190 break;
1192 default:
1193 lpArgTypeDesc = NULL;
1198 /* second time around */
1199 for(j=0;j<pFuncRec->nrargs;j++)
1201 /* name */
1202 (*pptfd)->pParamDesc[j].Name =
1203 TLB_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1205 /* default value */
1206 if ( (PARAMFLAG_FHASDEFAULT &
1207 V_UNION(&((*pptfd)->funcdesc.lprgelemdescParam[j]),
1208 paramdesc.wParamFlags)) &&
1209 ((pFuncRec->FKCCIC) & 0x1000) )
1211 INT* pInt = (INT *)((char *)pFuncRec +
1212 reclength -
1213 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1215 PARAMDESC* pParamDesc = &V_UNION(
1216 & ((*pptfd)->funcdesc.lprgelemdescParam[j]),
1217 paramdesc);
1219 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1220 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1222 TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1223 pInt[j], pcx);
1225 /* custom info */
1226 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1228 TLB_CustData(pcx,
1229 pFuncRec->OptAttr[7+j],
1230 &(*pptfd)->pParamDesc[j].pCustData);
1235 /* scode is not used: archaic win16 stuff FIXME: right? */
1236 (*pptfd)->funcdesc.cScodes = 0 ;
1237 (*pptfd)->funcdesc.lprgscode = NULL ;
1239 pptfd = & ((*pptfd)->next);
1240 recoffset += reclength;
1243 static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars,
1244 int offset, TLBVarDesc ** pptvd)
1246 int infolen, nameoffset, reclength;
1247 char recbuf[256];
1248 TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf;
1249 int i;
1250 int recoffset;
1252 TRACE_(typelib)("\n");
1254 TLB_Read(&infolen,sizeof(INT), pcx, offset);
1255 TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1256 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1257 recoffset += offset+sizeof(INT);
1258 for(i=0;i<cVars;i++){
1259 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1260 /* name, eventually add to a hash table */
1261 TLB_Read(&nameoffset, sizeof(INT), pcx,
1262 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1263 (*pptvd)->Name=TLB_ReadName(pcx, nameoffset);
1264 /* read the variable information record */
1265 TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
1266 reclength &=0xff;
1267 TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1268 /* Optional data */
1269 if(reclength >(6*sizeof(INT)) )
1270 (*pptvd)->HelpContext=pVarRec->HelpContext;
1271 if(reclength >(7*sizeof(INT)) )
1272 (*pptvd)->HelpString = TLB_ReadString(pcx, pVarRec->oHelpString) ;
1273 if(reclength >(8*sizeof(INT)) )
1274 if(reclength >(9*sizeof(INT)) )
1275 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1276 /* fill the VarDesc Structure */
1277 TLB_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1278 offset + infolen + ( i + 1) * sizeof(INT));
1279 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1280 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1281 TLB_GetTdesc(pcx, pVarRec->DataType,
1282 &(*pptvd)->vardesc.elemdescVar.tdesc) ;
1283 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
1284 if(pVarRec->VarKind == VAR_CONST ){
1285 V_UNION(&((*pptvd)->vardesc),lpvarValue)=TLB_Alloc(sizeof(VARIANT));
1286 TLB_ReadValue(V_UNION(&((*pptvd)->vardesc),lpvarValue),
1287 pVarRec->OffsValue, pcx);
1288 }else
1289 V_UNION(&((*pptvd)->vardesc),oInst)=pVarRec->OffsValue;
1290 pptvd=&((*pptvd)->next);
1291 recoffset += reclength;
1294 /* fill in data for a hreftype (offset). When the refernced type is contained
1295 * in the typelib, its just an (file) offset in the type info base dir.
1296 * If comes from import, its an offset+1 in the ImpInfo table
1297 * */
1298 static void TLB_DoRefType(TLBContext *pcx,
1299 int offset, TLBRefType ** pprtd)
1301 int j;
1303 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1305 if(!HREFTYPE_INTHISFILE( offset)) {
1306 /* external typelib */
1307 TLBImpInfo impinfo;
1308 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1310 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1312 TLB_Read(&impinfo, sizeof(impinfo), pcx,
1313 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1314 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1315 if(pImpLib->offset==impinfo.oImpFile) break;
1316 pImpLib=pImpLib->next;
1318 if(pImpLib){
1319 (*pprtd)->reference=offset;
1320 (*pprtd)->pImpTLInfo = pImpLib;
1321 TLB_ReadGuid(&(*pprtd)->guid, impinfo.oGuid, pcx);
1322 }else{
1323 ERR("Cannot find a reference\n");
1324 (*pprtd)->reference=-1;
1325 (*pprtd)->pImpTLInfo=(void *)-1;
1327 }else{
1328 /* in this typelib */
1329 (*pprtd)->reference=offset;
1330 (*pprtd)->pImpTLInfo=(void *)-2;
1334 /* process Implemented Interfaces of a com class */
1335 static void TLB_DoImplTypes(TLBContext *pcx, int count,
1336 int offset, TLBRefType ** pprtd)
1338 int i;
1339 TLBRefRecord refrec;
1341 TRACE_(typelib)("\n");
1343 for(i=0;i<count;i++){
1344 if(offset<0) break; /* paranoia */
1345 *pprtd=TLB_Alloc(sizeof(TLBRefType));
1346 TLB_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1347 TLB_DoRefType(pcx, refrec.reftype, pprtd);
1348 (*pprtd)->flags=refrec.flags;
1349 (*pprtd)->ctCustData=
1350 TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData);
1351 offset=refrec.onext;
1352 pprtd=&((*pprtd)->next);
1356 * process a typeinfo record
1358 ITypeInfoImpl * TLB_DoTypeInfo(
1359 TLBContext *pcx,
1360 int count,
1361 ITypeLibImpl * pLibInfo)
1363 TLBTypeInfoBase tiBase;
1364 ITypeInfoImpl *ptiRet;
1366 TRACE_(typelib)("count=%u\n", count);
1368 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1369 TLB_Read(&tiBase, sizeof(tiBase) ,pcx ,
1370 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1371 /* this is where we are coming from */
1372 ptiRet->pTypeLib = pLibInfo;
1373 ptiRet->index=count;
1374 /* fill in the typeattr fields */
1375 FIXME("Assign constructor/destrutor memid\n");
1377 TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1378 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1379 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1380 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1381 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1382 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1383 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1384 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1385 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1386 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1387 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1388 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1389 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1390 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1391 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1392 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1393 TLB_GetTdesc(pcx, tiBase.datatype1,
1394 &ptiRet->TypeAttr.tdescAlias) ;
1396 /* FIXME: */
1397 /* IDLDESC idldescType; *//* never saw this one != zero */
1399 /* name, eventually add to a hash table */
1400 ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset);
1401 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1402 /* help info */
1403 ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs);
1404 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1405 ptiRet->dwHelpContext=tiBase.helpcontext;
1406 /* note: InfoType's Help file and HelpStringDll come from the containing
1407 * library. Further HelpString and Docstring appear to be the same thing :(
1409 /* functions */
1410 if(ptiRet->TypeAttr.cFuncs >0 )
1411 TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars,
1412 tiBase.memoffset, & ptiRet->funclist);
1413 /* variables */
1414 if(ptiRet->TypeAttr.cVars >0 )
1415 TLB_DoVars(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars,
1416 tiBase.memoffset, & ptiRet->varlist);
1417 if(ptiRet->TypeAttr.cImplTypes >0 ){
1418 switch(ptiRet->TypeAttr.typekind)
1420 case TKIND_COCLASS:
1421 TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes ,
1422 tiBase.datatype1, & ptiRet->impltypelist);
1423 break;
1424 case TKIND_DISPATCH:
1425 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1427 if (tiBase.datatype1 != -1)
1429 TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1431 else
1433 char* szStdOle = "stdole2.tlb\0";
1434 int nStdOleLen = strlen(szStdOle);
1436 ptiRet->impltypelist->guid = IID_IDispatch;
1437 ptiRet->impltypelist->reference = -1;
1438 ptiRet->impltypelist->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1439 ptiRet->impltypelist->pImpTLInfo->guid = IID_StdOle;
1440 ptiRet->impltypelist->pImpTLInfo->name = SysAllocStringLen(NULL, nStdOleLen + 1);
1442 MultiByteToWideChar(CP_ACP,
1443 MB_PRECOMPOSED,
1444 szStdOle,
1446 ptiRet->impltypelist->pImpTLInfo->name,
1447 SysStringLen(ptiRet->impltypelist->pImpTLInfo->name));
1449 ptiRet->impltypelist->pImpTLInfo->lcid = 0;
1450 ptiRet->impltypelist->pImpTLInfo->wVersionMajor = 2;
1451 ptiRet->impltypelist->pImpTLInfo->wVersionMinor = 0;
1453 break;
1454 default:
1455 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1456 TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1457 break;
1460 ptiRet->ctCustData=
1461 TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1463 TRACE_(typelib)("%s guid: %s kind:%s\n",
1464 debugstr_w(ptiRet->Name),
1465 debugstr_guid(&ptiRet->TypeAttr.guid),
1466 typekind_desc[ptiRet->TypeAttr.typekind]);
1468 return ptiRet;
1471 /****************************************************************************
1472 * TLB_ReadTypeLib
1474 * find the type of the typelib file and map the typelib resource into
1475 * the memory
1477 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1478 int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib)
1480 int ret = E_FAIL;
1481 DWORD dwSignature = 0;
1482 HFILE hFile;
1483 int nStrLen = strlen(pszFileName);
1484 int i;
1486 PCHAR pszTypeLibIndex = NULL;
1487 PCHAR pszDllName = NULL;
1489 TRACE_(typelib)("%s\n", pszFileName);
1491 *ppTypeLib = NULL;
1493 /* is it a DLL? */
1494 for (i=0 ; i < nStrLen ; ++i)
1496 pszFileName[i] = tolower(pszFileName[i]);
1498 pszTypeLibIndex = strstr(pszFileName, ".dll");
1500 /* find if there's a back-slash after .DLL (good sign of the presence of a typelib index) */
1501 if (pszTypeLibIndex)
1503 pszTypeLibIndex = strstr(pszTypeLibIndex, "\\");
1506 /* is there any thing after trailing back-slash ? */
1507 if (pszTypeLibIndex && pszTypeLibIndex < pszFileName + nStrLen)
1509 /* yes -> it's a index! store DLL name, without the trailing back-slash */
1510 size_t nMemToAlloc = pszTypeLibIndex - pszFileName;
1512 pszDllName = HeapAlloc(GetProcessHeap(),
1513 HEAP_ZERO_MEMORY,
1514 nMemToAlloc + 1);
1516 strncpy(pszDllName, pszFileName, nMemToAlloc);
1518 /* move index string pointer pass the backslash */
1519 while (*pszTypeLibIndex == '\\')
1520 ++pszTypeLibIndex;
1522 else
1524 /* No index, reset variable to 1 */
1525 pszDllName = HeapAlloc(GetProcessHeap(),
1526 HEAP_ZERO_MEMORY,
1527 nStrLen + 1);
1529 strncpy(pszDllName, pszFileName, nStrLen);
1531 pszTypeLibIndex = "1\0";
1534 TRACE_(typelib)("File name without index %s\n", pszDllName);
1535 TRACE_(typelib)("Index of typelib %s\n", pszTypeLibIndex);
1538 /* check the signature of the file */
1539 hFile = CreateFileA( pszDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1540 if (INVALID_HANDLE_VALUE != hFile)
1542 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1543 if (hMapping)
1545 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1546 if(pBase)
1548 /* first try to load as *.tlb */
1549 dwSignature = *((DWORD*) pBase);
1550 if ( dwSignature == MSFT_SIGNATURE)
1552 /* retrieve file size */
1553 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1555 *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength);
1556 ITypeLib2_AddRef(*ppTypeLib);
1558 UnmapViewOfFile(pBase);
1560 CloseHandle(hMapping);
1562 CloseHandle(hFile);
1565 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1567 /* find the typelibrary resource*/
1568 HINSTANCE hinstDLL = LoadLibraryExA(pszDllName, 0, DONT_RESOLVE_DLL_REFERENCES|
1569 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1570 if (hinstDLL)
1572 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(atoi(pszTypeLibIndex)), "TYPELIB");
1573 if (hrsrc)
1575 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1576 if (hGlobal)
1578 LPVOID pBase = LockResource(hGlobal);
1579 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1581 if (pBase)
1583 /* try to load as incore resource */
1584 dwSignature = *((DWORD*) pBase);
1585 if ( dwSignature == MSFT_SIGNATURE)
1587 *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength);
1588 ITypeLib2_AddRef(*ppTypeLib);
1590 else
1592 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1595 FreeResource( hGlobal );
1598 FreeLibrary(hinstDLL);
1602 HeapFree(GetProcessHeap(), 0, pszDllName);
1604 if(*ppTypeLib)
1605 ret = S_OK;
1606 else
1607 ERR("Loading of typelib %s failed with error 0x%08lx\n", pszFileName, GetLastError());
1609 return ret;
1612 /*================== ITypeLib(2) Methods ===================================*/
1614 /****************************************************************************
1615 * ITypeLib2_Constructor
1617 * loading a typelib from a in-memory image
1619 static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength)
1621 TLBContext cx;
1622 long lPSegDir;
1623 TLB2Header tlbHeader;
1624 TLBSegDir tlbSegDir;
1625 ITypeLibImpl * pTypeLibImpl;
1627 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1629 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1630 if (!pTypeLibImpl) return NULL;
1632 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1633 pTypeLibImpl->ref = 1;
1635 /* get pointer to beginning of typelib data */
1636 cx.pos = 0;
1637 cx.oStart=0;
1638 cx.mapping = pLib;
1639 cx.pLibInfo = pTypeLibImpl;
1640 cx.length = dwTLBLength;
1642 /* read header */
1643 TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1644 TRACE("header:\n");
1645 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1646 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1647 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1648 return NULL;
1650 /* there is a small number of information here until the next important
1651 * part:
1652 * the segment directory . Try to calculate the amount of data */
1653 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1655 /* now read the segment directory */
1656 TRACE("read segment directory (at %ld)\n",lPSegDir);
1657 TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
1658 cx.pTblDir = &tlbSegDir;
1660 /* just check two entries */
1661 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
1663 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
1664 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
1665 return NULL;
1668 /* now fill our internal data */
1669 /* TLIBATTR fields */
1670 TLB_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
1671 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
1672 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
1673 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
1674 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
1675 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
1677 /* name, eventually add to a hash table */
1678 pTypeLibImpl->Name = TLB_ReadName(&cx, tlbHeader.NameOffset);
1680 /* help info */
1681 pTypeLibImpl->DocString = TLB_ReadString(&cx, tlbHeader.helpstring);
1682 pTypeLibImpl->HelpFile = TLB_ReadString(&cx, tlbHeader.helpfile);
1684 if( tlbHeader.varflags & HELPDLLFLAG)
1686 int offset;
1687 TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
1688 pTypeLibImpl->HelpStringDll = TLB_ReadString(&cx, offset);
1691 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
1693 /* custom data */
1694 if(tlbHeader.CustomDataOffset >= 0)
1696 pTypeLibImpl->ctCustData = TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
1699 /* fill in typedescriptions */
1700 if(tlbSegDir.pTypdescTab.length > 0)
1702 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
1703 INT16 td[4];
1704 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
1705 TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
1706 for(i=0; i<cTD; )
1708 /* FIXME: add several sanity checks here */
1709 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
1710 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
1712 /* FIXME: check safearray */
1713 if(td[3] < 0)
1714 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & stndTypeDesc[td[2]];
1715 else
1716 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & pTypeLibImpl->pTypeDesc[td[2]/8];
1718 else if(td[0] == VT_CARRAY)
1720 /* array descr table here */
1721 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = (void *)((int) td[2]); /* temp store offset in*/
1723 else if(td[0] == VT_USERDEFINED)
1725 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),hreftype) = MAKELONG(td[2],td[3]);
1727 if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
1730 /* second time around to fill the array subscript info */
1731 for(i=0;i<cTD;i++)
1733 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
1734 if(tlbSegDir.pArrayDescriptions.offset>0)
1736 TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc));
1737 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
1739 if(td[1]<0)
1740 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem.vt = td[0] & VT_TYPEMASK;
1741 else
1742 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem = stndTypeDesc[td[0]/8];
1744 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->cDims = td[2];
1746 for(j = 0; j<td[2]; j++)
1748 TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements,
1749 sizeof(INT), &cx, DO_NOT_SEEK);
1750 TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].lLbound,
1751 sizeof(INT), &cx, DO_NOT_SEEK);
1754 else
1756 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = NULL;
1757 ERR("didn't find array description data\n");
1762 /* imported type libs */
1763 if(tlbSegDir.pImpFiles.offset>0)
1765 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
1766 int oGuid, offset = tlbSegDir.pImpFiles.offset;
1767 UINT16 size;
1769 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
1771 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
1772 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
1773 TLB_Read(&oGuid, sizeof(INT), &cx, offset);
1775 TLB_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
1776 TLB_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
1777 TLB_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
1778 TLB_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
1780 size >>= 2;
1781 (*ppImpLib)->name = TLB_Alloc(size+1);
1782 TLB_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
1783 TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
1784 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
1786 ppImpLib = &(*ppImpLib)->next;
1790 /* type info's */
1791 if(tlbHeader.nrtypeinfos >= 0 )
1793 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
1794 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
1795 int i;
1797 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
1799 *ppTI = TLB_DoTypeInfo(&cx, i, pTypeLibImpl);
1801 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
1802 ppTI = &((*ppTI)->next);
1803 (pTypeLibImpl->TypeInfoCount)++;
1807 TRACE("(%p)\n", pTypeLibImpl);
1808 return (ITypeLib2*) pTypeLibImpl;
1811 /* ITypeLib::QueryInterface
1813 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
1814 ITypeLib2 * iface,
1815 REFIID riid,
1816 VOID **ppvObject)
1818 ICOM_THIS( ITypeLibImpl, iface);
1820 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
1822 *ppvObject=NULL;
1823 if(IsEqualIID(riid, &IID_IUnknown) ||
1824 IsEqualIID(riid,&IID_ITypeLib)||
1825 IsEqualIID(riid,&IID_ITypeLib2))
1827 *ppvObject = This;
1830 if(*ppvObject)
1832 ITypeLib2_AddRef(iface);
1833 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1834 return S_OK;
1836 TRACE("-- Interface: E_NOINTERFACE\n");
1837 return E_NOINTERFACE;
1840 /* ITypeLib::AddRef
1842 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
1844 ICOM_THIS( ITypeLibImpl, iface);
1846 TRACE("(%p)->ref is %u\n",This, This->ref);
1848 return ++(This->ref);
1851 /* ITypeLib::Release
1853 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
1855 ICOM_THIS( ITypeLibImpl, iface);
1857 --(This->ref);
1859 TRACE("(%p)->(%u)\n",This, This->ref);
1861 if (!This->ref)
1863 /* fixme destroy child objects */
1865 TRACE(" destroying ITypeLib(%p)\n",This);
1867 if (This->Name)
1869 SysFreeString(This->Name);
1870 This->Name = NULL;
1873 if (This->DocString)
1875 SysFreeString(This->DocString);
1876 This->DocString = NULL;
1879 if (This->HelpFile)
1881 SysFreeString(This->HelpFile);
1882 This->HelpFile = NULL;
1885 if (This->HelpStringDll)
1887 SysFreeString(This->HelpStringDll);
1888 This->HelpStringDll = NULL;
1891 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
1892 HeapFree(GetProcessHeap(),0,This);
1893 return 0;
1896 return This->ref;
1899 /* ITypeLib::GetTypeInfoCount
1901 * Returns the number of type descriptions in the type library
1903 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
1905 ICOM_THIS( ITypeLibImpl, iface);
1906 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
1907 return This->TypeInfoCount;
1910 /* ITypeLib::GetTypeInfo
1912 * retrieves the specified type description in the library.
1914 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
1915 ITypeLib2 *iface,
1916 UINT index,
1917 ITypeInfo **ppTInfo)
1919 int i;
1921 ICOM_THIS( ITypeLibImpl, iface);
1922 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
1924 TRACE("(%p)->(index=%d) \n", This, index);
1926 if (!ppTInfo) return E_INVALIDARG;
1928 /* search element n in list */
1929 for(i=0; i < index; i++)
1931 pTypeInfo = pTypeInfo->next;
1932 if (!pTypeInfo)
1934 TRACE("-- element not found\n");
1935 return TYPE_E_ELEMENTNOTFOUND;
1939 *ppTInfo = (ITypeInfo *) pTypeInfo;
1941 ITypeInfo_AddRef(*ppTInfo);
1942 TRACE("-- found (%p)\n",*ppTInfo);
1943 return S_OK;
1947 /* ITypeLibs::GetTypeInfoType
1949 * Retrieves the type of a type description.
1951 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
1952 ITypeLib2 *iface,
1953 UINT index,
1954 TYPEKIND *pTKind)
1956 ICOM_THIS( ITypeLibImpl, iface);
1957 int i;
1958 ITypeInfoImpl *pTInfo = This->pTypeInfo;
1960 TRACE("(%p) index %d \n",This, index);
1962 if(!pTKind) return E_INVALIDARG;
1964 /* search element n in list */
1965 for(i=0; i < index; i++)
1967 if(!pTInfo)
1969 TRACE("-- element not found\n");
1970 return TYPE_E_ELEMENTNOTFOUND;
1972 pTInfo = pTInfo->next;
1975 *pTKind = pTInfo->TypeAttr.typekind;
1976 TRACE("-- found Type (%d)\n", *pTKind);
1977 return S_OK;
1980 /* ITypeLib::GetTypeInfoOfGuid
1982 * Retrieves the type description that corresponds to the specified GUID.
1985 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
1986 ITypeLib2 *iface,
1987 REFGUID guid,
1988 ITypeInfo **ppTInfo)
1990 ICOM_THIS( ITypeLibImpl, iface);
1991 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
1993 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
1995 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
1997 /* search linked list for guid */
1998 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
2000 pTypeInfo = pTypeInfo->next;
2002 if (!pTypeInfo)
2004 /* end of list reached */
2005 TRACE("-- element not found\n");
2006 return TYPE_E_ELEMENTNOTFOUND;
2010 TRACE("-- found (%p, %s)\n",
2011 pTypeInfo,
2012 debugstr_w(pTypeInfo->Name));
2014 *ppTInfo = (ITypeInfo*)pTypeInfo;
2015 ITypeInfo_AddRef(*ppTInfo);
2016 return S_OK;
2019 /* ITypeLib::GetLibAttr
2021 * Retrieves the structure that contains the library's attributes.
2024 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
2025 ITypeLib2 *iface,
2026 LPTLIBATTR *ppTLibAttr)
2028 ICOM_THIS( ITypeLibImpl, iface);
2029 TRACE("(%p)\n",This);
2030 /* FIXME: must do a copy here */
2031 *ppTLibAttr=&This->LibAttr;
2032 return S_OK;
2035 /* ITypeLib::GetTypeComp
2037 * Enables a client compiler to bind to a library's types, variables,
2038 * constants, and global functions.
2041 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
2042 ITypeLib2 *iface,
2043 ITypeComp **ppTComp)
2045 ICOM_THIS( ITypeLibImpl, iface);
2046 FIXME("(%p): stub!\n",This);
2047 return E_NOTIMPL;
2050 /* ITypeLib::GetDocumentation
2052 * Retrieves the library's documentation string, the complete Help file name
2053 * and path, and the context identifier for the library Help topic in the Help
2054 * file.
2057 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
2058 ITypeLib2 *iface,
2059 INT index,
2060 BSTR *pBstrName,
2061 BSTR *pBstrDocString,
2062 DWORD *pdwHelpContext,
2063 BSTR *pBstrHelpFile)
2065 ICOM_THIS( ITypeLibImpl, iface);
2067 HRESULT result = E_INVALIDARG;
2069 ITypeInfo *pTInfo;
2072 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
2073 This, index,
2074 pBstrName, pBstrDocString,
2075 pdwHelpContext, pBstrHelpFile);
2077 if(index<0)
2079 /* documentation for the typelib */
2080 if(pBstrName && This->Name)
2082 *pBstrName = SysAllocString(This->Name);
2084 if (!(*pBstrName)) return STG_E_INSUFFICIENTMEMORY;
2086 if(pBstrDocString && This->DocString)
2088 *pBstrDocString = SysAllocString(This->DocString);
2090 if (!(*pBstrDocString)) return STG_E_INSUFFICIENTMEMORY;
2093 if(pdwHelpContext)
2095 *pdwHelpContext = This->dwHelpContext;
2097 if(pBstrHelpFile && This->HelpFile)
2099 *pBstrHelpFile = SysAllocString(This->HelpFile);
2101 if (!(*pBstrHelpFile)) return STG_E_INSUFFICIENTMEMORY;
2104 result = S_OK;
2106 else
2108 /* for a typeinfo */
2109 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
2111 if(SUCCEEDED(result))
2113 result = ITypeInfo_GetDocumentation(pTInfo,
2114 MEMBERID_NIL,
2115 pBstrName,
2116 pBstrDocString,
2117 pdwHelpContext, pBstrHelpFile);
2119 ITypeInfo_Release(pTInfo);
2122 return result;
2125 /* ITypeLib::IsName
2127 * Indicates whether a passed-in string contains the name of a type or member
2128 * described in the library.
2131 static HRESULT WINAPI ITypeLib2_fnIsName(
2132 ITypeLib2 *iface,
2133 LPOLESTR szNameBuf,
2134 ULONG lHashVal,
2135 BOOL *pfName)
2137 ICOM_THIS( ITypeLibImpl, iface);
2138 ITypeInfoImpl *pTInfo;
2139 TLBFuncDesc *pFInfo;
2140 TLBVarDesc *pVInfo;
2141 int i;
2142 UINT nNameBufLen = SysStringLen(szNameBuf);
2144 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
2145 pfName);
2147 *pfName=TRUE;
2148 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
2149 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2150 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
2151 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2152 for(i=0;i<pFInfo->funcdesc.cParams;i++)
2153 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
2154 goto ITypeLib2_fnIsName_exit;
2156 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
2157 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2160 *pfName=FALSE;
2162 ITypeLib2_fnIsName_exit:
2163 TRACE("(%p)slow! search for %s: %s found!\n", This,
2164 debugstr_w(szNameBuf), *pfName?"NOT":"");
2166 return S_OK;
2169 /* ITypeLib::FindName
2171 * Finds occurrences of a type description in a type library. This may be used
2172 * to quickly verify that a name exists in a type library.
2175 static HRESULT WINAPI ITypeLib2_fnFindName(
2176 ITypeLib2 *iface,
2177 LPOLESTR szNameBuf,
2178 ULONG lHashVal,
2179 ITypeInfo **ppTInfo,
2180 MEMBERID *rgMemId,
2181 UINT16 *pcFound)
2183 ICOM_THIS( ITypeLibImpl, iface);
2184 ITypeInfoImpl *pTInfo;
2185 TLBFuncDesc *pFInfo;
2186 TLBVarDesc *pVInfo;
2187 int i,j = 0;
2189 UINT nNameBufLen = SysStringLen(szNameBuf);
2191 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
2192 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2193 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
2194 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2195 for(i=0;i<pFInfo->funcdesc.cParams;i++)
2196 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
2197 goto ITypeLib2_fnFindName_exit;
2199 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
2200 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2201 continue;
2202 ITypeLib2_fnFindName_exit:
2203 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
2204 ppTInfo[j]=(LPTYPEINFO)pTInfo;
2205 j++;
2207 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
2208 This, *pcFound, debugstr_w(szNameBuf), j);
2210 *pcFound=j;
2212 return S_OK;
2215 /* ITypeLib::ReleaseTLibAttr
2217 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
2220 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
2221 ITypeLib2 *iface,
2222 TLIBATTR *pTLibAttr)
2224 ICOM_THIS( ITypeLibImpl, iface);
2225 TRACE("freeing (%p)\n",This);
2226 /* nothing to do */
2229 /* ITypeLib2::GetCustData
2231 * gets the custom data
2233 static HRESULT WINAPI ITypeLib2_fnGetCustData(
2234 ITypeLib2 * iface,
2235 REFGUID guid,
2236 VARIANT *pVarVal)
2238 ICOM_THIS( ITypeLibImpl, iface);
2239 TLBCustData *pCData;
2241 for(pCData=This->pCustData; pCData; pCData = pCData->next)
2243 if( IsEqualIID(guid, &pCData->guid)) break;
2246 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2248 if(pCData)
2250 VariantInit( pVarVal);
2251 VariantCopy( pVarVal, &pCData->data);
2252 return S_OK;
2254 return E_INVALIDARG; /* FIXME: correct? */
2257 /* ITypeLib2::GetLibStatistics
2259 * Returns statistics about a type library that are required for efficient
2260 * sizing of hash tables.
2263 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
2264 ITypeLib2 * iface,
2265 ULONG *pcUniqueNames,
2266 ULONG *pcchUniqueNames)
2268 ICOM_THIS( ITypeLibImpl, iface);
2270 FIXME("(%p): stub!\n", This);
2272 if(pcUniqueNames) *pcUniqueNames=1;
2273 if(pcchUniqueNames) *pcchUniqueNames=1;
2274 return S_OK;
2277 /* ITypeLib2::GetDocumentation2
2279 * Retrieves the library's documentation string, the complete Help file name
2280 * and path, the localization context to use, and the context ID for the
2281 * library Help topic in the Help file.
2284 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
2285 ITypeLib2 * iface,
2286 INT index,
2287 LCID lcid,
2288 BSTR *pbstrHelpString,
2289 DWORD *pdwHelpStringContext,
2290 BSTR *pbstrHelpStringDll)
2292 ICOM_THIS( ITypeLibImpl, iface);
2293 HRESULT result;
2294 ITypeInfo *pTInfo;
2296 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
2298 /* the help string should be obtained from the helpstringdll,
2299 * using the _DLLGetDocumentation function, based on the supplied
2300 * lcid. Nice to do sometime...
2302 if(index<0)
2304 /* documentation for the typelib */
2305 if(pbstrHelpString)
2306 *pbstrHelpString=SysAllocString(This->DocString);
2307 if(pdwHelpStringContext)
2308 *pdwHelpStringContext=This->dwHelpContext;
2309 if(pbstrHelpStringDll)
2310 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
2312 result = S_OK;
2314 else
2316 /* for a typeinfo */
2317 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
2319 if(SUCCEEDED(result))
2321 ITypeInfo2 * pTInfo2;
2322 result = ITypeInfo_QueryInterface(pTInfo,
2323 &IID_ITypeInfo2,
2324 (LPVOID*) &pTInfo2);
2326 if(SUCCEEDED(result))
2328 result = ITypeInfo2_GetDocumentation2(pTInfo2,
2329 MEMBERID_NIL,
2330 lcid,
2331 pbstrHelpString,
2332 pdwHelpStringContext,
2333 pbstrHelpStringDll);
2335 ITypeInfo2_Release(pTInfo2);
2338 ITypeInfo_Release(pTInfo);
2341 return result;
2344 /* ITypeLib2::GetAllCustData
2346 * Gets all custom data items for the library.
2349 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
2350 ITypeLib2 * iface,
2351 CUSTDATA *pCustData)
2353 ICOM_THIS( ITypeLibImpl, iface);
2354 TLBCustData *pCData;
2355 int i;
2356 TRACE("(%p) returning %d items\n", This, This->ctCustData);
2357 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
2358 if(pCustData->prgCustData ){
2359 pCustData->cCustData=This->ctCustData;
2360 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
2361 pCustData->prgCustData[i].guid=pCData->guid;
2362 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
2364 }else{
2365 ERR(" OUT OF MEMORY! \n");
2366 return E_OUTOFMEMORY;
2368 return S_OK;
2371 static ICOM_VTABLE(ITypeLib2) tlbvt = {
2372 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2373 ITypeLib2_fnQueryInterface,
2374 ITypeLib2_fnAddRef,
2375 ITypeLib2_fnRelease,
2376 ITypeLib2_fnGetTypeInfoCount,
2377 ITypeLib2_fnGetTypeInfo,
2378 ITypeLib2_fnGetTypeInfoType,
2379 ITypeLib2_fnGetTypeInfoOfGuid,
2380 ITypeLib2_fnGetLibAttr,
2381 ITypeLib2_fnGetTypeComp,
2382 ITypeLib2_fnGetDocumentation,
2383 ITypeLib2_fnIsName,
2384 ITypeLib2_fnFindName,
2385 ITypeLib2_fnReleaseTLibAttr,
2387 ITypeLib2_fnGetCustData,
2388 ITypeLib2_fnGetLibStatistics,
2389 ITypeLib2_fnGetDocumentation2,
2390 ITypeLib2_fnGetAllCustData
2393 /*================== ITypeInfo(2) Methods ===================================*/
2394 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
2396 ITypeInfoImpl * pTypeInfoImpl;
2398 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
2399 if (pTypeInfoImpl)
2401 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
2402 pTypeInfoImpl->ref=1;
2404 TRACE("(%p)\n", pTypeInfoImpl);
2405 return (ITypeInfo2*) pTypeInfoImpl;
2408 /* ITypeInfo::QueryInterface
2410 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
2411 ITypeInfo2 *iface,
2412 REFIID riid,
2413 VOID **ppvObject)
2415 ICOM_THIS( ITypeLibImpl, iface);
2417 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2419 *ppvObject=NULL;
2420 if(IsEqualIID(riid, &IID_IUnknown) ||
2421 IsEqualIID(riid,&IID_ITypeInfo)||
2422 IsEqualIID(riid,&IID_ITypeInfo2))
2423 *ppvObject = This;
2425 if(*ppvObject){
2426 ITypeInfo_AddRef(iface);
2427 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2428 return S_OK;
2430 TRACE("-- Interface: E_NOINTERFACE\n");
2431 return E_NOINTERFACE;
2434 /* ITypeInfo::AddRef
2436 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
2438 ICOM_THIS( ITypeInfoImpl, iface);
2440 ++(This->ref);
2442 TRACE("(%p)->ref is %u\n",This, This->ref);
2443 return This->ref;
2446 /* ITypeInfo::Release
2448 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
2450 ICOM_THIS( ITypeInfoImpl, iface);
2452 --(This->ref);
2454 TRACE("(%p)->(%u)\n",This, This->ref);
2456 if (!This->ref)
2458 FIXME("destroy child objects\n");
2460 TRACE("destroying ITypeInfo(%p)\n",This);
2461 if (This->Name)
2463 SysFreeString(This->Name);
2464 This->Name = 0;
2467 if (This->DocString)
2469 SysFreeString(This->DocString);
2470 This->DocString = 0;
2473 if (This->next)
2475 ITypeInfo_Release((ITypeInfo*)This->next);
2478 HeapFree(GetProcessHeap(),0,This);
2479 return 0;
2481 return This->ref;
2484 /* ITypeInfo::GetTypeAttr
2486 * Retrieves a TYPEATTR structure that contains the attributes of the type
2487 * description.
2490 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
2491 LPTYPEATTR *ppTypeAttr)
2493 ICOM_THIS( ITypeInfoImpl, iface);
2494 TRACE("(%p)\n",This);
2495 /* FIXME: must do a copy here */
2496 *ppTypeAttr=&This->TypeAttr;
2497 return S_OK;
2500 /* ITypeInfo::GetTypeComp
2502 * Retrieves the ITypeComp interface for the type description, which enables a
2503 * client compiler to bind to the type description's members.
2506 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
2507 ITypeComp * *ppTComp)
2509 ICOM_THIS( ITypeInfoImpl, iface);
2510 FIXME("(%p) stub!\n", This);
2511 return S_OK;
2514 /* ITypeInfo::GetFuncDesc
2516 * Retrieves the FUNCDESC structure that contains information about a
2517 * specified function.
2520 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
2521 LPFUNCDESC *ppFuncDesc)
2523 ICOM_THIS( ITypeInfoImpl, iface);
2524 int i;
2525 TLBFuncDesc * pFDesc;
2526 TRACE("(%p) index %d\n", This, index);
2527 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
2529 if(pFDesc){
2530 /* FIXME: must do a copy here */
2531 *ppFuncDesc=&pFDesc->funcdesc;
2532 return S_OK;
2534 return E_INVALIDARG;
2537 /* ITypeInfo::GetVarDesc
2539 * Retrieves a VARDESC structure that describes the specified variable.
2542 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
2543 LPVARDESC *ppVarDesc)
2545 ICOM_THIS( ITypeInfoImpl, iface);
2546 int i;
2547 TLBVarDesc * pVDesc;
2548 TRACE("(%p) index %d\n", This, index);
2549 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
2551 if(pVDesc){
2552 /* FIXME: must do a copy here */
2553 *ppVarDesc=&pVDesc->vardesc;
2554 return S_OK;
2556 return E_INVALIDARG;
2559 /* ITypeInfo_GetNames
2561 * Retrieves the variable with the specified member ID (or the name of the
2562 * property or method and its parameters) that correspond to the specified
2563 * function ID.
2565 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
2566 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
2568 ICOM_THIS( ITypeInfoImpl, iface);
2569 TLBFuncDesc * pFDesc;
2570 TLBVarDesc * pVDesc;
2571 int i;
2572 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
2573 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
2574 if(pFDesc)
2576 /* function found, now return function and parameter names */
2577 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
2579 if(!i)
2580 *rgBstrNames=SysAllocString(pFDesc->Name);
2581 else
2582 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
2584 *pcNames=i;
2586 else
2588 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
2589 if(pVDesc)
2591 *rgBstrNames=SysAllocString(pVDesc->Name);
2592 *pcNames=1;
2594 else
2596 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
2598 /* recursive search */
2599 ITypeInfo *pTInfo;
2600 HRESULT result;
2601 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->reference, &pTInfo);
2602 if(SUCCEEDED(result))
2604 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
2605 ITypeInfo_Release(pTInfo);
2606 return result;
2608 WARN("Could not search inherited interface!\n");
2610 else
2612 WARN("no names found\n");
2614 *pcNames=0;
2615 return TYPE_E_ELEMENTNOTFOUND;
2618 return S_OK;
2622 /* ITypeInfo::GetRefTypeOfImplType
2624 * If a type description describes a COM class, it retrieves the type
2625 * description of the implemented interface types. For an interface,
2626 * GetRefTypeOfImplType returns the type information for inherited interfaces,
2627 * if any exist.
2630 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
2631 ITypeInfo2 *iface,
2632 UINT index,
2633 HREFTYPE *pRefType)
2635 ICOM_THIS( ITypeInfoImpl, iface);
2636 int(i);
2637 TLBRefType *pIref = This->impltypelist;
2639 TRACE("(%p) index %d\n", This, index);
2640 dump_TypeInfo(This);
2642 if(index==(UINT)-1)
2644 /* only valid on dual interfaces;
2645 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
2647 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
2649 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
2650 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
2652 *pRefType = -1;
2654 else
2656 if (!pIref) return TYPE_E_ELEMENTNOTFOUND;
2657 *pRefType = pIref->reference;
2660 else
2662 /* get element n from linked list */
2663 for(i=0; pIref && i<index; i++)
2665 pIref = pIref->next;
2668 if (!pIref) return TYPE_E_ELEMENTNOTFOUND;
2670 *pRefType = pIref->reference;
2672 TRACE("-- 0x%08lx %s\n",pIref->reference, debugstr_guid(&pIref->guid) );
2675 return S_OK;
2679 /* ITypeInfo::GetImplTypeFlags
2681 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
2682 * or base interface in a type description.
2684 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
2685 UINT index, INT *pImplTypeFlags)
2687 ICOM_THIS( ITypeInfoImpl, iface);
2688 int(i);
2689 TLBRefType *pIref;
2690 TRACE("(%p) index %d\n", This, index);
2691 for(i=0, pIref=This->impltypelist; i<index && pIref; i++, pIref=pIref->next)
2693 if(i==index && pIref){
2694 *pImplTypeFlags=pIref->flags;
2695 return S_OK;
2697 *pImplTypeFlags=0;
2698 return TYPE_E_ELEMENTNOTFOUND;
2701 /* GetIDsOfNames
2702 * Maps between member names and member IDs, and parameter names and
2703 * parameter IDs.
2705 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
2706 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
2708 ICOM_THIS( ITypeInfoImpl, iface);
2709 TLBFuncDesc * pFDesc;
2710 TLBVarDesc * pVDesc;
2711 HRESULT ret=S_OK;
2712 UINT nNameLen = SysStringLen(*rgszNames);
2714 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
2715 cNames);
2716 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
2717 int i, j;
2718 if( !memcmp(*rgszNames, pFDesc->Name, nNameLen)) {
2719 if(cNames) *pMemId=pFDesc->funcdesc.memid;
2720 for(i=1; i < cNames; i++){
2721 UINT nParamLen = SysStringLen(rgszNames[i]);
2722 for(j=0; j<pFDesc->funcdesc.cParams; j++)
2723 if(memcmp(rgszNames[i],pFDesc->pParamDesc[j].Name, nParamLen))
2724 break;
2725 if( j<pFDesc->funcdesc.cParams)
2726 pMemId[i]=j;
2727 else
2728 ret=DISP_E_UNKNOWNNAME;
2730 return ret;
2733 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
2734 if( !memcmp(*rgszNames, pVDesc->Name, nNameLen)) {
2735 if(cNames) *pMemId=pVDesc->vardesc.memid;
2736 return ret;
2739 /* not found, see if this is and interface with an inheritance */
2740 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
2741 This->TypeAttr.cImplTypes ){
2742 /* recursive search */
2743 ITypeInfo *pTInfo;
2744 ret=ITypeInfo_GetRefTypeInfo(iface,
2745 This->impltypelist->reference, &pTInfo);
2746 if(SUCCEEDED(ret)){
2747 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
2748 ITypeInfo_Release(pTInfo);
2749 return ret;
2751 WARN("Could not search inherited interface!\n");
2752 } else
2753 WARN("no names found\n");
2754 return DISP_E_UNKNOWNNAME;
2757 /* ITypeInfo::Invoke
2759 * Invokes a method, or accesses a property of an object, that implements the
2760 * interface described by the type description.
2762 static HRESULT WINAPI ITypeInfo_fnInvoke(
2763 ITypeInfo2 *iface,
2764 VOID *pIUnk,
2765 MEMBERID memid,
2766 UINT16 dwFlags,
2767 DISPPARAMS *pDispParams,
2768 VARIANT *pVarResult,
2769 EXCEPINFO *pExcepInfo,
2770 UINT *pArgErr)
2772 ICOM_THIS( ITypeInfoImpl, iface);
2773 FIXME("(%p)(%p,id=0x%08lx,0x%08x,%p,%p,%p,%p) stub!\n",
2774 This, pIUnk, memid, dwFlags, pDispParams, pVarResult, pExcepInfo, pArgErr );
2775 dump_DispParms(pDispParams);
2776 return S_OK;
2779 /* ITypeInfo::GetDocumentation
2781 * Retrieves the documentation string, the complete Help file name and path,
2782 * and the context ID for the Help topic for a specified type description.
2784 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
2785 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
2786 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
2788 ICOM_THIS( ITypeInfoImpl, iface);
2789 TLBFuncDesc * pFDesc;
2790 TLBVarDesc * pVDesc;
2791 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
2792 " HelpContext(%p) HelpFile(%p)\n",
2793 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
2794 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
2795 if(pBstrName)
2796 *pBstrName=SysAllocString(This->Name);
2797 if(pBstrDocString)
2798 *pBstrDocString=SysAllocString(This->DocString);
2799 if(pdwHelpContext)
2800 *pdwHelpContext=This->dwHelpContext;
2801 if(pBstrHelpFile)
2802 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
2803 return S_OK;
2804 }else {/* for a member */
2805 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
2806 if(pFDesc->funcdesc.memid==memid){
2807 return S_OK;
2809 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
2810 if(pVDesc->vardesc.memid==memid){
2811 return S_OK;
2814 return TYPE_E_ELEMENTNOTFOUND;
2817 /* ITypeInfo::GetDllEntry
2819 * Retrieves a description or specification of an entry point for a function
2820 * in a DLL.
2822 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
2823 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
2824 WORD *pwOrdinal)
2826 ICOM_THIS( ITypeInfoImpl, iface);
2827 FIXME("(%p) stub!\n", This);
2828 return E_FAIL;
2831 /* ITypeInfo::GetRefTypeInfo
2833 * If a type description references other type descriptions, it retrieves
2834 * the referenced type descriptions.
2836 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
2837 ITypeInfo2 *iface,
2838 HREFTYPE hRefType,
2839 ITypeInfo **ppTInfo)
2841 ICOM_THIS( ITypeInfoImpl, iface);
2842 HRESULT result = E_FAIL;
2844 if(HREFTYPE_INTHISFILE(hRefType))
2846 ITypeLib *pTLib;
2847 int Index;
2848 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
2849 if(SUCCEEDED( result ))
2851 result=ITypeLib2_GetTypeInfo(pTLib, HREFTYPE_INDEX(hRefType), ppTInfo);
2852 ITypeLib2_Release(pTLib );
2855 else if (hRefType == -1 &&
2856 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
2857 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
2859 /* when we meet a DUAL dispinterface, we must create the interface
2860 * version of it.
2862 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
2865 /* the interface version contains the same information as the dispinterface
2866 * copy the contents of the structs.
2868 *pTypeInfoImpl = *This;
2869 pTypeInfoImpl->ref = 1;
2871 /* change the type to interface */
2872 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
2874 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
2876 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
2878 result = S_OK;
2880 else
2882 /* imported type lib */
2883 TLBRefType *pRefType = NULL;
2885 /* search in implemented types */
2886 for( pRefType = This->impltypelist;
2887 pRefType && (pRefType->reference != hRefType);
2888 pRefType = pRefType->next);
2890 if(!pRefType)
2892 TYPEATTR* pMyTypeAttr = &This->TypeAttr;
2893 unsigned short cFuncs = pMyTypeAttr->cFuncs;
2894 unsigned short cVars = pMyTypeAttr->cVars;
2896 /* search in arguments */
2897 if (cFuncs > 0)
2899 unsigned short cFuncIndex = 0;
2901 TLBFuncDesc* pCurrFunc = This->funclist;
2903 for (cFuncIndex = 0; !pRefType && cFuncIndex < cFuncs ; ++cFuncIndex)
2905 FUNCDESC* pCurrFuncDesc = &pCurrFunc->funcdesc;
2907 short cParams = pCurrFuncDesc->cParams;
2908 short cParamIndex = 0;
2910 for (cParamIndex = 0 ;
2911 !pRefType && cParamIndex < cParams ;
2912 ++cParamIndex)
2914 TLBParDesc* pCurrParamDesc = &(pCurrFunc->pParamDesc[cParamIndex]);
2916 if ( pCurrParamDesc->pRefType && pCurrParamDesc->pRefType->reference == hRefType)
2918 pRefType = pCurrParamDesc->pRefType;
2919 break; /* also break from outer loop since pRefType != 0 */
2923 pCurrFunc = pCurrFunc->next;
2926 /* search in variables */
2927 else if (cVars > 0)
2929 FIXME("search hreftype in variables, if any\n");
2930 result = E_INVALIDARG; // FIXME : correct?
2934 /* href-referenced typeinfo found! */
2935 if (pRefType || hRefType == -1)
2937 ITypeLibImpl *pTypeLib = pRefType->pImpTLInfo->pImpTypeLib;
2939 if(pTypeLib)
2941 TRACE("typeinfo in imported typelib that is already loaded\n");
2943 result = ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib,
2944 &pRefType->guid,
2945 ppTInfo);
2947 else
2949 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
2950 pRefType->pImpTLInfo->wVersionMajor,
2951 pRefType->pImpTLInfo->wVersionMinor,
2952 pRefType->pImpTLInfo->lcid,
2953 (LPTYPELIB *)&pTypeLib);
2955 if(!SUCCEEDED(result))
2957 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
2958 TRACE("typeinfo in imported typelib that isn't already loaded\n");
2959 result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib);
2960 SysFreeString(libnam);
2962 if(SUCCEEDED(result))
2964 result=ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
2965 pRefType->pImpTLInfo->pImpTypeLib = pTypeLib;
2966 ITypeLib2_AddRef((ITypeLib*) pTypeLib);
2972 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
2973 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
2974 return result;
2977 /* ITypeInfo::AddressOfMember
2979 * Retrieves the addresses of static functions or variables, such as those
2980 * defined in a DLL.
2982 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
2983 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
2985 ICOM_THIS( ITypeInfoImpl, iface);
2986 FIXME("(%p) stub!\n", This);
2987 return S_OK;
2990 /* ITypeInfo::CreateInstance
2992 * Creates a new instance of a type that describes a component object class
2993 * (coclass).
2995 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
2996 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
2998 ICOM_THIS( ITypeInfoImpl, iface);
2999 FIXME("(%p) stub!\n", This);
3000 return S_OK;
3003 /* ITypeInfo::GetMops
3005 * Retrieves marshaling information.
3007 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
3008 BSTR *pBstrMops)
3010 ICOM_THIS( ITypeInfoImpl, iface);
3011 FIXME("(%p) stub!\n", This);
3012 return S_OK;
3015 /* ITypeInfo::GetContainingTypeLib
3017 * Retrieves the containing type library and the index of the type description
3018 * within that type library.
3020 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
3021 ITypeLib * *ppTLib, UINT *pIndex)
3023 ICOM_THIS( ITypeInfoImpl, iface);
3024 if (!pIndex)
3025 return E_INVALIDARG;
3026 *ppTLib=(LPTYPELIB )(This->pTypeLib);
3027 *pIndex=This->index;
3028 ITypeLib2_AddRef(*ppTLib);
3029 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
3030 return S_OK;
3033 /* ITypeInfo::ReleaseTypeAttr
3035 * Releases a TYPEATTR previously returned by GetTypeAttr.
3038 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
3039 TYPEATTR* pTypeAttr)
3041 ICOM_THIS( ITypeInfoImpl, iface);
3042 TRACE("(%p)->(%p)\n", This, pTypeAttr);
3043 return S_OK;
3046 /* ITypeInfo::ReleaseFuncDesc
3048 * Releases a FUNCDESC previously returned by GetFuncDesc. *
3050 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
3051 ITypeInfo2 *iface,
3052 FUNCDESC *pFuncDesc)
3054 ICOM_THIS( ITypeInfoImpl, iface);
3055 TRACE("(%p)->(%p)\n", This, pFuncDesc);
3056 return S_OK;
3059 /* ITypeInfo::ReleaseVarDesc
3061 * Releases a VARDESC previously returned by GetVarDesc.
3063 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
3064 VARDESC *pVarDesc)
3066 ICOM_THIS( ITypeInfoImpl, iface);
3067 TRACE("(%p)->(%p)\n", This, pVarDesc);
3068 return S_OK;
3071 /* ITypeInfo2::GetTypeKind
3073 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
3076 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
3077 TYPEKIND *pTypeKind)
3079 ICOM_THIS( ITypeInfoImpl, iface);
3080 *pTypeKind=This->TypeAttr.typekind;
3081 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
3082 return S_OK;
3085 /* ITypeInfo2::GetTypeFlags
3087 * Returns the type flags without any allocations. This returns a DWORD type
3088 * flag, which expands the type flags without growing the TYPEATTR (type
3089 * attribute).
3092 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
3093 UINT *pTypeFlags)
3095 ICOM_THIS( ITypeInfoImpl, iface);
3096 *pTypeFlags=This->TypeAttr.wTypeFlags;
3097 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
3098 return S_OK;
3101 /* ITypeInfo2::GetFuncIndexOfMemId
3102 * Binds to a specific member based on a known DISPID, where the member name
3103 * is not known (for example, when binding to a default member).
3106 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
3107 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
3109 ICOM_THIS( ITypeInfoImpl, iface);
3110 TLBFuncDesc *pFuncInfo;
3111 int i;
3112 HRESULT result;
3113 /* FIXME: should check for invKind??? */
3114 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
3115 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
3116 if(pFuncInfo){
3117 *pFuncIndex=i;
3118 result= S_OK;
3119 }else{
3120 *pFuncIndex=0;
3121 result=E_INVALIDARG;
3123 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
3124 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
3125 return result;
3128 /* TypeInfo2::GetVarIndexOfMemId
3130 * Binds to a specific member based on a known DISPID, where the member name
3131 * is not known (for example, when binding to a default member).
3134 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
3135 MEMBERID memid, UINT *pVarIndex)
3137 ICOM_THIS( ITypeInfoImpl, iface);
3138 TLBVarDesc *pVarInfo;
3139 int i;
3140 HRESULT result;
3141 for(i=0, pVarInfo=This->varlist; pVarInfo &&
3142 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
3144 if(pVarInfo){
3145 *pVarIndex=i;
3146 result= S_OK;
3147 }else{
3148 *pVarIndex=0;
3149 result=E_INVALIDARG;
3151 TRACE("(%p) memid 0x%08lx -> %s\n", This,
3152 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
3153 return result;
3156 /* ITypeInfo2::GetCustData
3158 * Gets the custom data
3160 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
3161 ITypeInfo2 * iface,
3162 REFGUID guid,
3163 VARIANT *pVarVal)
3165 ICOM_THIS( ITypeInfoImpl, iface);
3166 TLBCustData *pCData;
3168 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3169 if( IsEqualIID(guid, &pCData->guid)) break;
3171 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3173 if(pCData)
3175 VariantInit( pVarVal);
3176 VariantCopy( pVarVal, &pCData->data);
3177 return S_OK;
3179 return E_INVALIDARG; /* FIXME: correct? */
3182 /* ITypeInfo2::GetFuncCustData
3184 * Gets the custom data
3186 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
3187 ITypeInfo2 * iface,
3188 UINT index,
3189 REFGUID guid,
3190 VARIANT *pVarVal)
3192 ICOM_THIS( ITypeInfoImpl, iface);
3193 TLBCustData *pCData=NULL;
3194 TLBFuncDesc * pFDesc;
3195 int i;
3196 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
3197 pFDesc=pFDesc->next);
3199 if(pFDesc)
3200 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
3201 if( IsEqualIID(guid, &pCData->guid)) break;
3203 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3205 if(pCData){
3206 VariantInit( pVarVal);
3207 VariantCopy( pVarVal, &pCData->data);
3208 return S_OK;
3210 return E_INVALIDARG; /* FIXME: correct? */
3213 /* ITypeInfo2::GetParamCustData
3215 * Gets the custom data
3217 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
3218 ITypeInfo2 * iface,
3219 UINT indexFunc,
3220 UINT indexParam,
3221 REFGUID guid,
3222 VARIANT *pVarVal)
3224 ICOM_THIS( ITypeInfoImpl, iface);
3225 TLBCustData *pCData=NULL;
3226 TLBFuncDesc * pFDesc;
3227 int i;
3229 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
3231 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
3232 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
3233 pCData = pCData->next)
3234 if( IsEqualIID(guid, &pCData->guid)) break;
3236 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3238 if(pCData)
3240 VariantInit( pVarVal);
3241 VariantCopy( pVarVal, &pCData->data);
3242 return S_OK;
3244 return E_INVALIDARG; /* FIXME: correct? */
3247 /* ITypeInfo2::GetVarcCustData
3249 * Gets the custom data
3251 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
3252 ITypeInfo2 * iface,
3253 UINT index,
3254 REFGUID guid,
3255 VARIANT *pVarVal)
3257 ICOM_THIS( ITypeInfoImpl, iface);
3258 TLBCustData *pCData=NULL;
3259 TLBVarDesc * pVDesc;
3260 int i;
3262 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
3264 if(pVDesc)
3266 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
3268 if( IsEqualIID(guid, &pCData->guid)) break;
3272 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3274 if(pCData)
3276 VariantInit( pVarVal);
3277 VariantCopy( pVarVal, &pCData->data);
3278 return S_OK;
3280 return E_INVALIDARG; /* FIXME: correct? */
3283 /* ITypeInfo2::GetImplcCustData
3285 * Gets the custom data
3287 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
3288 ITypeInfo2 * iface,
3289 UINT index,
3290 REFGUID guid,
3291 VARIANT *pVarVal)
3293 ICOM_THIS( ITypeInfoImpl, iface);
3294 TLBCustData *pCData=NULL;
3295 TLBRefType * pRDesc;
3296 int i;
3298 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
3300 if(pRDesc)
3302 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
3304 if( IsEqualIID(guid, &pCData->guid)) break;
3308 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3310 if(pCData)
3312 VariantInit( pVarVal);
3313 VariantCopy( pVarVal, &pCData->data);
3314 return S_OK;
3316 return E_INVALIDARG; /* FIXME: correct? */
3319 /* ITypeInfo2::GetDocumentation2
3321 * Retrieves the documentation string, the complete Help file name and path,
3322 * the localization context to use, and the context ID for the library Help
3323 * topic in the Help file.
3326 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
3327 ITypeInfo2 * iface,
3328 MEMBERID memid,
3329 LCID lcid,
3330 BSTR *pbstrHelpString,
3331 DWORD *pdwHelpStringContext,
3332 BSTR *pbstrHelpStringDll)
3334 ICOM_THIS( ITypeInfoImpl, iface);
3335 TLBFuncDesc * pFDesc;
3336 TLBVarDesc * pVDesc;
3337 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
3338 "HelpStringContext(%p) HelpStringDll(%p)\n",
3339 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
3340 pbstrHelpStringDll );
3341 /* the help string should be obtained from the helpstringdll,
3342 * using the _DLLGetDocumentation function, based on the supplied
3343 * lcid. Nice to do sometime...
3345 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
3346 if(pbstrHelpString)
3347 *pbstrHelpString=SysAllocString(This->Name);
3348 if(pdwHelpStringContext)
3349 *pdwHelpStringContext=This->dwHelpStringContext;
3350 if(pbstrHelpStringDll)
3351 *pbstrHelpStringDll=
3352 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3353 return S_OK;
3354 }else {/* for a member */
3355 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3356 if(pFDesc->funcdesc.memid==memid){
3357 if(pbstrHelpString)
3358 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
3359 if(pdwHelpStringContext)
3360 *pdwHelpStringContext=pFDesc->HelpStringContext;
3361 if(pbstrHelpStringDll)
3362 *pbstrHelpStringDll=
3363 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3364 return S_OK;
3366 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
3367 if(pVDesc->vardesc.memid==memid){
3368 if(pbstrHelpString)
3369 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
3370 if(pdwHelpStringContext)
3371 *pdwHelpStringContext=pVDesc->HelpStringContext;
3372 if(pbstrHelpStringDll)
3373 *pbstrHelpStringDll=
3374 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3375 return S_OK;
3378 return TYPE_E_ELEMENTNOTFOUND;
3381 /* ITypeInfo2::GetAllCustData
3383 * Gets all custom data items for the Type info.
3386 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
3387 ITypeInfo2 * iface,
3388 CUSTDATA *pCustData)
3390 ICOM_THIS( ITypeInfoImpl, iface);
3391 TLBCustData *pCData;
3392 int i;
3394 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3396 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3397 if(pCustData->prgCustData ){
3398 pCustData->cCustData=This->ctCustData;
3399 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3400 pCustData->prgCustData[i].guid=pCData->guid;
3401 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3403 }else{
3404 ERR(" OUT OF MEMORY! \n");
3405 return E_OUTOFMEMORY;
3407 return S_OK;
3410 /* ITypeInfo2::GetAllFuncCustData
3412 * Gets all custom data items for the specified Function
3415 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
3416 ITypeInfo2 * iface,
3417 UINT index,
3418 CUSTDATA *pCustData)
3420 ICOM_THIS( ITypeInfoImpl, iface);
3421 TLBCustData *pCData;
3422 TLBFuncDesc * pFDesc;
3423 int i;
3424 TRACE("(%p) index %d\n", This, index);
3425 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
3426 pFDesc=pFDesc->next)
3428 if(pFDesc){
3429 pCustData->prgCustData =
3430 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
3431 if(pCustData->prgCustData ){
3432 pCustData->cCustData=pFDesc->ctCustData;
3433 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
3434 pCData = pCData->next){
3435 pCustData->prgCustData[i].guid=pCData->guid;
3436 VariantCopy(& pCustData->prgCustData[i].varValue,
3437 & pCData->data);
3439 }else{
3440 ERR(" OUT OF MEMORY! \n");
3441 return E_OUTOFMEMORY;
3443 return S_OK;
3445 return TYPE_E_ELEMENTNOTFOUND;
3448 /* ITypeInfo2::GetAllParamCustData
3450 * Gets all custom data items for the Functions
3453 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
3454 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
3456 ICOM_THIS( ITypeInfoImpl, iface);
3457 TLBCustData *pCData=NULL;
3458 TLBFuncDesc * pFDesc;
3459 int i;
3460 TRACE("(%p) index %d\n", This, indexFunc);
3461 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
3462 pFDesc=pFDesc->next)
3464 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
3465 pCustData->prgCustData =
3466 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
3467 sizeof(CUSTDATAITEM));
3468 if(pCustData->prgCustData ){
3469 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
3470 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
3471 pCData; i++, pCData = pCData->next){
3472 pCustData->prgCustData[i].guid=pCData->guid;
3473 VariantCopy(& pCustData->prgCustData[i].varValue,
3474 & pCData->data);
3476 }else{
3477 ERR(" OUT OF MEMORY! \n");
3478 return E_OUTOFMEMORY;
3480 return S_OK;
3482 return TYPE_E_ELEMENTNOTFOUND;
3485 /* ITypeInfo2::GetAllVarCustData
3487 * Gets all custom data items for the specified Variable
3490 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
3491 UINT index, CUSTDATA *pCustData)
3493 ICOM_THIS( ITypeInfoImpl, iface);
3494 TLBCustData *pCData;
3495 TLBVarDesc * pVDesc;
3496 int i;
3497 TRACE("(%p) index %d\n", This, index);
3498 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
3499 pVDesc=pVDesc->next)
3501 if(pVDesc){
3502 pCustData->prgCustData =
3503 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
3504 if(pCustData->prgCustData ){
3505 pCustData->cCustData=pVDesc->ctCustData;
3506 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
3507 pCData = pCData->next){
3508 pCustData->prgCustData[i].guid=pCData->guid;
3509 VariantCopy(& pCustData->prgCustData[i].varValue,
3510 & pCData->data);
3512 }else{
3513 ERR(" OUT OF MEMORY! \n");
3514 return E_OUTOFMEMORY;
3516 return S_OK;
3518 return TYPE_E_ELEMENTNOTFOUND;
3521 /* ITypeInfo2::GetAllImplCustData
3523 * Gets all custom data items for the specified implementation type
3526 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
3527 ITypeInfo2 * iface,
3528 UINT index,
3529 CUSTDATA *pCustData)
3531 ICOM_THIS( ITypeInfoImpl, iface);
3532 TLBCustData *pCData;
3533 TLBRefType * pRDesc;
3534 int i;
3535 TRACE("(%p) index %d\n", This, index);
3536 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
3537 pRDesc=pRDesc->next)
3539 if(pRDesc){
3540 pCustData->prgCustData =
3541 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
3542 if(pCustData->prgCustData ){
3543 pCustData->cCustData=pRDesc->ctCustData;
3544 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
3545 pCData = pCData->next){
3546 pCustData->prgCustData[i].guid=pCData->guid;
3547 VariantCopy(& pCustData->prgCustData[i].varValue,
3548 & pCData->data);
3550 }else{
3551 ERR(" OUT OF MEMORY! \n");
3552 return E_OUTOFMEMORY;
3554 return S_OK;
3556 return TYPE_E_ELEMENTNOTFOUND;
3559 static ICOM_VTABLE(ITypeInfo2) tinfvt =
3561 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3563 ITypeInfo_fnQueryInterface,
3564 ITypeInfo_fnAddRef,
3565 ITypeInfo_fnRelease,
3567 ITypeInfo_fnGetTypeAttr,
3568 ITypeInfo_fnGetTypeComp,
3569 ITypeInfo_fnGetFuncDesc,
3570 ITypeInfo_fnGetVarDesc,
3571 ITypeInfo_fnGetNames,
3572 ITypeInfo_fnGetRefTypeOfImplType,
3573 ITypeInfo_fnGetImplTypeFlags,
3574 ITypeInfo_fnGetIDsOfNames,
3575 ITypeInfo_fnInvoke,
3576 ITypeInfo_fnGetDocumentation,
3577 ITypeInfo_fnGetDllEntry,
3578 ITypeInfo_fnGetRefTypeInfo,
3579 ITypeInfo_fnAddressOfMember,
3580 ITypeInfo_fnCreateInstance,
3581 ITypeInfo_fnGetMops,
3582 ITypeInfo_fnGetContainingTypeLib,
3583 ITypeInfo_fnReleaseTypeAttr,
3584 ITypeInfo_fnReleaseFuncDesc,
3585 ITypeInfo_fnReleaseVarDesc,
3587 ITypeInfo2_fnGetTypeKind,
3588 ITypeInfo2_fnGetTypeFlags,
3589 ITypeInfo2_fnGetFuncIndexOfMemId,
3590 ITypeInfo2_fnGetVarIndexOfMemId,
3591 ITypeInfo2_fnGetCustData,
3592 ITypeInfo2_fnGetFuncCustData,
3593 ITypeInfo2_fnGetParamCustData,
3594 ITypeInfo2_fnGetVarCustData,
3595 ITypeInfo2_fnGetImplTypeCustData,
3596 ITypeInfo2_fnGetDocumentation2,
3597 ITypeInfo2_fnGetAllCustData,
3598 ITypeInfo2_fnGetAllFuncCustData,
3599 ITypeInfo2_fnGetAllParamCustData,
3600 ITypeInfo2_fnGetAllVarCustData,
3601 ITypeInfo2_fnGetAllImplTypeCustData,