4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * --------------------------------------------------------------------------------------
10 * Known problems (2000, Francois Jacques)
12 * - Tested using OLEVIEW (Platform SDK tool) only.
14 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
15 * creating by doing a straight copy of the dispinterface instance and just changing
16 * its typekind. Pointed structures aren't copied - only the address of the pointers.
17 * So when you release the dispinterface, you delete the vtable-interface structures
18 * as well... fortunately, clean up of structures is not implemented.
20 * - locale stuff is partially implemented but hasn't been tested.
22 * - typelib file is still read in its entirety, but it is released now.
23 * - some garbage is read from function names on some very rare occasions.
25 * --------------------------------------------------------------------------------------
26 * Known problems left from previous implementation (1999, Rein Klazes) :
28 * -. Data structures are straightforward, but slow for look-ups.
29 * -. (related) nothing is hashed
30 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
31 * of them I don't know yet how to implement them.
32 * -. Most error return values are just guessed not checked with windows
34 * -. didn't bother with a c++ interface
35 * -. lousy fatal error handling
36 * -. some methods just return pointers to internal data structures, this is
37 * partly laziness, partly I want to check how windows does it.
49 #include "winnls.h" /* for PRIMARYLANGID */
50 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
52 #include "wine/unicode.h"
53 #include "wine/obj_base.h"
57 #include "debugtools.h"
60 DEFAULT_DEBUG_CHANNEL(ole
);
61 DECLARE_DEBUG_CHANNEL(typelib
);
63 /****************************************************************************
64 * QueryPathOfRegTypeLib [TYPELIB.14]
66 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
71 QueryPathOfRegTypeLib16(
72 REFGUID guid
, /* [in] referenced guid */
73 WORD wMaj
, /* [in] major version */
74 WORD wMin
, /* [in] minor version */
75 LCID lcid
, /* [in] locale id */
76 LPBSTR16 path
/* [out] path of typelib */
79 char typelibkey
[100],pathname
[260];
85 sprintf( typelibkey
, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
86 guid
->Data1
, guid
->Data2
, guid
->Data3
,
87 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
88 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
91 sprintf(xguid
,"<guid 0x%08lx>",(DWORD
)guid
);
92 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid
,wMaj
,wMin
,(DWORD
)lcid
,path
);
95 plen
= sizeof(pathname
);
96 if (RegQueryValueA(HKEY_LOCAL_MACHINE
,typelibkey
,pathname
,&plen
)) {
97 /* try again without lang specific id */
99 return QueryPathOfRegTypeLib16(guid
,wMaj
,wMin
,PRIMARYLANGID(lcid
),path
);
100 FIXME("key %s not found\n",typelibkey
);
103 *path
= SysAllocString16(pathname
);
107 /****************************************************************************
108 * QueryPathOfRegTypeLib [OLEAUT32.164]
113 QueryPathOfRegTypeLib(
114 REFGUID guid
, /* [in] referenced guid */
115 WORD wMaj
, /* [in] major version */
116 WORD wMin
, /* [in] minor version */
117 LCID lcid
, /* [in] locale id */
118 LPBSTR path
) /* [out] path of typelib */
120 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
121 string termination character on output strings */
125 DWORD dwPathLen
= _MAX_PATH
;
129 char szTypeLibKey
[100];
130 char szPath
[dwPathLen
];
138 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID
, wMaj
, wMin
, (DWORD
)lcid
, path
);
144 sprintf(szTypeLibKey
,
145 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
146 guid
->Data1
, guid
->Data2
, guid
->Data3
,
147 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
148 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
153 if (RegQueryValueA(HKEY_LOCAL_MACHINE
, szTypeLibKey
, szPath
, &dwPathLen
))
157 else if (myLCID
== lcid
)
159 /* try with sub-langid */
160 myLCID
= SUBLANGID(lcid
);
162 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
164 /* try with system langid */
174 DWORD len
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, szPath
, dwPathLen
, NULL
, 0 );
175 BSTR bstrPath
= SysAllocStringLen(NULL
,len
);
177 MultiByteToWideChar(CP_ACP
,
189 TRACE_(typelib
)("%s not found\n", szTypeLibKey
);
194 /******************************************************************************
195 * CreateTypeLib [OLEAUT32.160] creates a typelib
201 HRESULT WINAPI
CreateTypeLib(
202 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
204 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
207 /******************************************************************************
208 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
210 * Docs: OLECHAR FAR* szFile
211 * Docs: iTypeLib FAR* FAR* pptLib
217 HRESULT WINAPI
LoadTypeLib16(
218 LPOLESTR szFile
, /* [in] Name of file to load from */
219 ITypeLib
** pptLib
) /* [out] Pointer to pointer to loaded type library */
221 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR
)szFile
),pptLib
);
229 /******************************************************************************
230 * LoadTypeLib [OLEAUT32.161]
231 * Loads and registers a type library
233 * Docs: OLECHAR FAR* szFile
234 * Docs: iTypeLib FAR* FAR* pptLib
240 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
242 HRESULT WINAPI
LoadTypeLib(
243 const OLECHAR
*szFile
,/* [in] Name of file to load from */
244 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
247 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
250 /******************************************************************************
251 * LoadTypeLibEx [OLEAUT32.183]
252 * Loads and optionally registers a type library
258 HRESULT WINAPI
LoadTypeLibEx(
259 LPCOLESTR szFile
, /* [in] Name of file to load from */
260 REGKIND regkind
, /* [in] Specify kind of registration */
261 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
263 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
264 const WCHAR
*pFile
, *pIndexStr
;
267 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
270 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
273 /* Look for a trailing '\\' followed by an index */
274 pIndexStr
= strrchrW(szFile
, '\\');
275 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
276 index
= wcstol(pIndexStr
, NULL
, 10);
277 memcpy(szFileCopy
, szFile
,
278 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
279 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
281 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
283 return TYPE_E_CANTLOADLIBRARY
;
285 return TYPE_E_CANTLOADLIBRARY
;
288 TRACE("File %s index %d\n", debugstr_w(pFile
), index
);
290 res
= TLB_ReadTypeLib(pFile
, index
, (ITypeLib2
**)pptLib
);
295 case REGKIND_DEFAULT
:
296 /* FIXME: is this correct? */
297 if (!szFile
|| !szFile
[0] ||
298 (szFile
[0] != '\\' && szFile
[0] != '/' && szFile
[1] != ':'))
300 /* else fall-through */
301 case REGKIND_REGISTER
:
302 /* FIXME: Help path? */
303 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szFile
, NULL
)))
305 IUnknown_Release(*pptLib
);
313 TRACE(" returns %08lx\n",res
);
317 /******************************************************************************
318 * LoadRegTypeLib [OLEAUT32.162]
320 HRESULT WINAPI
LoadRegTypeLib(
321 REFGUID rguid
, /* [in] referenced guid */
322 WORD wVerMajor
, /* [in] major version */
323 WORD wVerMinor
, /* [in] minor version */
324 LCID lcid
, /* [in] locale id */
325 ITypeLib
**ppTLib
) /* [out] path of typelib */
328 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
332 res
= LoadTypeLib(bstr
, ppTLib
);
336 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
342 /******************************************************************************
343 * RegisterTypeLib [OLEAUT32.163]
344 * Adds information about a type library to the System Registry
346 * Docs: ITypeLib FAR * ptlib
347 * Docs: OLECHAR FAR* szFullPath
348 * Docs: OLECHAR FAR* szHelpDir
354 HRESULT WINAPI
RegisterTypeLib(
355 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
356 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
357 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
368 static const char *PSOA
= "{00020424-0000-0000-C000-000000000046}";
370 if (ptlib
== NULL
|| szFullPath
== NULL
)
373 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
376 StringFromGUID2(&attr
->guid
, guid
, 80);
377 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
378 snprintf(keyName
, sizeof(keyName
), "TypeLib\\%s\\%x.%x",
379 guidA
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
380 HeapFree(GetProcessHeap(), 0, guidA
);
383 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
384 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
388 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
390 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
391 (BYTE
*)doc
, lstrlenW(doc
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
399 /* FIXME: This *seems* to be 0 always, not sure though */
400 if (res
== S_OK
&& RegCreateKeyExA(key
, "0\\win32", 0, NULL
, 0,
401 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
403 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
404 (BYTE
*)szFullPath
, lstrlenW(szFullPath
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
412 if (res
== S_OK
&& RegCreateKeyExA(key
, "FLAGS", 0, NULL
, 0,
413 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
416 /* FIXME: is %u correct? */
417 snprintf(buf
, sizeof(buf
), "%u", attr
->wLibFlags
);
418 if (RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
419 buf
, lstrlenA(buf
) + 1) != ERROR_SUCCESS
)
427 /* register OLE Automation-compatible interfaces for this typelib */
428 types
= ITypeLib_GetTypeInfoCount(ptlib
);
429 for (tidx
=0; tidx
<types
; tidx
++) {
430 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
431 LPOLESTR name
= NULL
;
432 ITypeInfo
*tinfo
= NULL
;
434 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
436 case TKIND_INTERFACE
:
437 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
438 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
441 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
442 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
445 TRACE_(typelib
)("%d: coclass %s\n", tidx
, debugstr_w(name
));
446 /* coclasses should probably not be registered? */
449 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
453 TYPEATTR
*tattr
= NULL
;
454 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
456 TRACE_(typelib
)("guid=%s, flags=%04x\n",
457 debugstr_guid(&tattr
->guid
),
459 if (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
) {
460 /* register interface<->typelib coupling */
461 StringFromGUID2(&tattr
->guid
, guid
, 80);
462 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
463 snprintf(keyName
, sizeof(keyName
), "Interface\\%s", guidA
);
464 HeapFree(GetProcessHeap(), 0, guidA
);
466 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
467 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
469 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
470 (BYTE
*)name
, lstrlenW(name
) * sizeof(OLECHAR
));
472 if (RegCreateKeyExA(key
, "ProxyStubClsid", 0, NULL
, 0,
473 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
474 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
478 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
479 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
480 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
485 if (RegCreateKeyExA(key
, "TypeLib", 0, NULL
, 0,
486 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
488 StringFromGUID2(&attr
->guid
, guid
, 80);
489 snprintf(ver
, sizeof(ver
), "%x.%x",
490 attr
->wMajorVerNum
, attr
->wMinorVerNum
);
491 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
492 (BYTE
*)guid
, lstrlenW(guid
) * sizeof(OLECHAR
));
493 RegSetValueExA(subKey
, "Version", 0, REG_SZ
,
500 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
502 ITypeInfo_Release(tinfo
);
509 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
515 /******************************************************************************
516 * UnRegisterTypeLib [OLEAUT32.186]
517 * Removes information about a type library from the System Registry
524 HRESULT WINAPI
UnRegisterTypeLib(
525 REFGUID libid
, /* [in] Guid of the library */
526 WORD wVerMajor
, /* [in] major version */
527 WORD wVerMinor
, /* [in] minor version */
528 LCID lcid
, /* [in] locale id */
531 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
532 return S_OK
; /* FIXME: pretend everything is OK */
535 /****************************************************************************
536 * OaBuildVersion (TYPELIB.15)
538 * known TYPELIB.DLL versions:
540 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
541 * OLE 2.02 1993-94 02 3002
544 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
545 * OLE 2.1 NT 1993-95 ?? ???
546 * OLE 2.3.1 W95 23 700
547 * OLE2 4.0 NT4SP6 1993-98 40 4277
549 DWORD WINAPI
OaBuildVersion16(void)
551 /* FIXME: I'd like to return the highest currently known version value
552 * in case the user didn't force a --winver, but I don't know how
553 * to retrieve the "versionForced" info from misc/version.c :(
554 * (this would be useful in other places, too) */
555 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
556 switch(GetVersion() & 0x8000ffff) /* mask off build number */
558 case 0x80000a03: /* WIN31 */
559 return MAKELONG(3027, 3); /* WfW 3.11 */
560 case 0x80000004: /* WIN95 */
561 return MAKELONG(700, 23); /* Win95A */
562 case 0x80000a04: /* WIN98 */
563 return MAKELONG(3024, 10); /* W98 SE */
564 case 0x00000004: /* NT4 */
565 return MAKELONG(4277, 40); /* NT4 SP6 */
567 FIXME("Version value not known yet. Please investigate it!\n");
572 /* for better debugging info leave the static out for the time being */
575 /*======================= ITypeLib implementation =======================*/
577 typedef struct tagTLBCustData
581 struct tagTLBCustData
* next
;
584 /* data structure for import typelibs */
585 typedef struct tagTLBImpLib
587 int offset
; /* offset in the file (MSFT)
588 offset in nametable (SLTG)
589 just used to identify library while reading
591 GUID guid
; /* libid */
592 BSTR name
; /* name */
594 LCID lcid
; /* lcid of imported typelib */
596 WORD wVersionMajor
; /* major version number */
597 WORD wVersionMinor
; /* minor version number */
599 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
600 NULL if not yet loaded */
601 struct tagTLBImpLib
* next
;
604 /* internal ITypeLib data */
605 typedef struct tagITypeLibImpl
607 ICOM_VFIELD(ITypeLib2
);
609 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
611 /* strings can be stored in tlb as multibyte strings BUT they are *always*
612 * exported to the application as a UNICODE string.
618 unsigned long dwHelpContext
;
619 int TypeInfoCount
; /* nr of typeinfo's in librarry */
620 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
621 int ctCustData
; /* number of items in cust data list */
622 TLBCustData
* pCustData
; /* linked list to cust data */
623 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
624 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
625 libary. Only used while read MSFT
629 static struct ICOM_VTABLE(ITypeLib2
) tlbvt
;
631 /* ITypeLib methods */
632 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
633 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
635 /*======================= ITypeInfo implementation =======================*/
637 /* data for refernced types */
638 typedef struct tagTLBRefType
640 INT index
; /* Type index for internal ref or for external ref
641 it the format is SLTG. -2 indicates to
644 GUID guid
; /* guid of the referenced type */
645 /* if index == TLB_REF_USE_GUID */
647 HREFTYPE reference
; /* The href of this ref */
648 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
649 TLB_REF_INTERNAL for internal refs
650 TLB_REF_NOT_FOUND for broken refs */
652 struct tagTLBRefType
* next
;
655 #define TLB_REF_USE_GUID -2
657 #define TLB_REF_INTERNAL (void*)-2
658 #define TLB_REF_NOT_FOUND (void*)-1
660 /* internal Parameter data */
661 typedef struct tagTLBParDesc
665 TLBCustData
* pCustData
; /* linked list to cust data */
668 /* internal Function data */
669 typedef struct tagTLBFuncDesc
671 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
672 BSTR Name
; /* the name of this function */
673 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
675 int HelpStringContext
;
677 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
679 TLBCustData
* pCustData
; /* linked list to cust data; */
680 struct tagTLBFuncDesc
* next
;
683 /* internal Variable data */
684 typedef struct tagTLBVarDesc
686 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
687 BSTR Name
; /* the name of this variable */
689 int HelpStringContext
; /* fixme: where? */
692 TLBCustData
* pCustData
;/* linked list to cust data; */
693 struct tagTLBVarDesc
* next
;
696 /* internal implemented interface data */
697 typedef struct tagTLBImplType
699 HREFTYPE hRef
; /* hRef of interface */
700 int implflags
; /* IMPLFLAG_*s */
702 TLBCustData
* pCustData
;/* linked list to custom data; */
703 struct tagTLBImplType
*next
;
706 /* internal TypeInfo data */
707 typedef struct tagITypeInfoImpl
709 ICOM_VFIELD(ITypeInfo2
);
711 TYPEATTR TypeAttr
; /* _lots_ of type information. */
712 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
713 int index
; /* index in this typelib; */
714 /* type libs seem to store the doc strings in ascii
715 * so why should we do it in unicode?
719 unsigned long dwHelpContext
;
720 unsigned long dwHelpStringContext
;
723 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
726 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
728 /* Implemented Interfaces */
729 TLBImplType
* impltypelist
;
731 TLBRefType
* reflist
;
733 TLBCustData
* pCustData
; /* linked list to cust data; */
734 struct tagITypeInfoImpl
* next
;
737 static struct ICOM_VTABLE(ITypeInfo2
) tinfvt
;
739 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor();
741 typedef struct tagTLBContext
743 unsigned int oStart
; /* start of TLB in file */
744 unsigned int pos
; /* current pos */
745 unsigned int length
; /* total length */
746 void *mapping
; /* memory mapping */
747 MSFT_SegDir
* pTblDir
;
748 ITypeLibImpl
* pLibInfo
;
752 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
757 static void dump_VarType(VARTYPE vt
,char *szVarType
) {
758 /* FIXME : we could have better trace here, depending on the VARTYPE
762 case VT_UI1
: sprintf(szVarType
, "VT_UI"); break;
763 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
764 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
765 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
766 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
767 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
768 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
769 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
770 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
771 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
772 case VT_BYREF
: case VT_UNKNOWN
: sprintf(szVarType
, "VT_BYREF"); break;
773 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
774 case VT_ARRAY
: sprintf(szVarType
, "VT_ARRAY"); break;
775 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
776 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
777 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
778 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
779 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
780 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED\n"); break;
781 default: sprintf(szVarType
, "unknown");break;
785 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
787 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
788 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
789 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
790 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
791 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
792 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
793 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
794 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
795 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
796 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
797 case VT_BYREF
: case VT_UNKNOWN
: sprintf(szVarType
, "VT_BYREF"); break;
798 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
799 case VT_ARRAY
: sprintf(szVarType
, "VT_ARRAY"); break;
800 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
801 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
802 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
803 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
804 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
805 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
806 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
807 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
808 pTD
->u
.hreftype
); break;
809 case VT_PTR
: sprintf(szVarType
, "ptr to ");
810 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
812 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
813 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
815 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
816 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
817 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
820 default: sprintf(szVarType
, "unknown");break;
824 static void dump_ELEMDESC(ELEMDESC
*edesc
) {
826 dump_TypeDesc(&edesc
->tdesc
,buf
);
827 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
828 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
829 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
831 static void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
833 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
834 for (i
=0;i
<funcdesc
->cParams
;i
++) {
835 MESSAGE("Param %d:\n",i
);
836 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
838 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
839 switch (funcdesc
->funckind
) {
840 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
841 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
842 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
843 case FUNC_STATIC
: MESSAGE("static");break;
844 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
845 default: MESSAGE("unknown");break;
847 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
848 switch (funcdesc
->invkind
) {
849 case INVOKE_FUNC
: MESSAGE("func");break;
850 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
851 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
852 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
854 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
855 switch (funcdesc
->callconv
) {
856 case CC_CDECL
: MESSAGE("cdecl");break;
857 case CC_PASCAL
: MESSAGE("pascal");break;
858 case CC_STDCALL
: MESSAGE("stdcall");break;
859 case CC_SYSCALL
: MESSAGE("syscall");break;
862 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
863 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
864 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
866 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
869 if (!TRACE_ON(typelib
))
871 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
872 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
873 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
876 dump_FUNCDESC(&(pfd
->funcdesc
));
878 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
879 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
881 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
885 dump_TLBFuncDescOne(pfd
);
889 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
893 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
898 static void dump_TLBImpLib(TLBImpLib
*import
)
900 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
901 debugstr_w(import
->name
));
902 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
903 import
->wVersionMinor
, import
->lcid
, import
->offset
);
906 static void dump_TLBRefType(TLBRefType
* prt
)
910 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
912 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
914 TRACE_(typelib
)("type no: %d\n", prt
->index
);
916 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
917 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
918 TRACE_(typelib
)("in lib\n");
919 dump_TLBImpLib(prt
->pImpTLInfo
);
925 static void dump_TLBImplType(TLBImplType
* impl
)
929 "implementing/inheriting interface hRef = %lx implflags %x\n",
930 impl
->hRef
, impl
->implflags
);
935 static void dump_Variant(VARIANT
* pvar
)
939 TRACE("(%p)\n", pvar
);
943 ZeroMemory(szVarType
, sizeof(szVarType
));
945 /* FIXME : we could have better trace here, depending on the VARTYPE
948 dump_VarType(V_VT(pvar
),szVarType
);
950 TRACE("VARTYPE: %s\n", szVarType
);
955 TRACE("%3.3e\n", V_UNION(pvar
, fltVal
));
959 TRACE("%3.3e\n", V_UNION(pvar
, dblVal
));
963 TRACE("%ld\n", V_UNION(pvar
, lVal
));
967 if (V_VT(pvar
) & VT_BYREF
)
968 return dump_Variant(V_UNION(pvar
,pvarVal
));
971 static void dump_DispParms(DISPPARAMS
* pdp
)
975 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
977 while (index
< pdp
->cArgs
)
979 dump_Variant( &pdp
->rgvarg
[index
] );
984 static char * typekind_desc
[] =
997 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
999 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1000 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1001 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1002 TRACE("fct:%u var:%u impl:%u\n",
1003 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1004 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1005 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1006 dump_TLBFuncDesc(pty
->funclist
);
1007 dump_TLBVarDesc(pty
->varlist
);
1008 dump_TLBImplType(pty
->impltypelist
);
1011 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1013 /* VT_LPWSTR is largest type that */
1014 /* may appear in type description*/
1015 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1016 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1017 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1018 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1019 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1020 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1024 static void TLB_abort()
1028 static void * TLB_Alloc(unsigned size
)
1031 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1033 ERR("cannot allocate memory\n");
1038 static void TLB_Free(void * ptr
)
1040 HeapFree(GetProcessHeap(), 0, ptr
);
1044 /**********************************************************************
1046 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1049 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1051 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1052 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1054 if (where
!= DO_NOT_SEEK
)
1056 where
+= pcx
->oStart
;
1057 if (where
> pcx
->length
)
1060 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1065 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1066 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1071 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1073 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1075 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1076 memset(pGuid
,0, sizeof(GUID
));
1079 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1082 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1085 MSFT_NameIntro niName
;
1087 WCHAR
* pwstring
= NULL
;
1088 BSTR bstrName
= NULL
;
1090 MSFT_Read(&niName
, sizeof(niName
), pcx
,
1091 pcx
->pTblDir
->pNametab
.offset
+offset
);
1092 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1093 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1094 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1095 name
[niName
.namelen
& 0xff]='\0';
1097 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1100 /* no invalid characters in string */
1103 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1105 /* don't check for invalid character since this has been done previously */
1106 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1108 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1109 lengthInChars
= SysStringLen(bstrName
);
1110 HeapFree(GetProcessHeap(), 0, pwstring
);
1113 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1117 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1124 if(offset
<0) return NULL
;
1125 MSFT_Read(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1126 if(length
<= 0) return 0;
1127 string
=TLB_Alloc(length
+1);
1128 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1129 string
[length
]='\0';
1131 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1132 string
, -1, NULL
, 0);
1134 /* no invalid characters in string */
1137 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1139 /* don't check for invalid character since this has been done previously */
1140 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1142 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1143 lengthInChars
= SysStringLen(bstr
);
1144 HeapFree(GetProcessHeap(), 0, pwstring
);
1147 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1151 * read a value and fill a VARIANT structure
1153 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1157 TRACE_(typelib
)("\n");
1159 if(offset
<0) { /* data are packed in here */
1160 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1161 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1164 MSFT_Read(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1165 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1166 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1167 switch (V_VT(pVar
)){
1168 case VT_EMPTY
: /* FIXME: is this right? */
1169 case VT_NULL
: /* FIXME: is this right? */
1170 case VT_I2
: /* this should not happen */
1181 case VT_VOID
: /* FIXME: is this right? */
1189 case VT_DECIMAL
: /* FIXME: is this right? */
1192 /* pointer types with known behaviour */
1195 MSFT_Read(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1197 FIXME("BSTR length = %d?\n", size
);
1199 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1200 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1201 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1202 /* FIXME: do we need a AtoW conversion here? */
1203 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1204 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1209 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1216 case VT_USERDEFINED
:
1222 case VT_STREAMED_OBJECT
:
1223 case VT_STORED_OBJECT
:
1224 case VT_BLOB_OBJECT
:
1229 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1233 if(size
>0) /* (big|small) endian correct? */
1234 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1238 * create a linked list with custom data
1240 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1246 TRACE_(typelib
)("\n");
1250 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1251 MSFT_Read(&entry
, sizeof(entry
), pcx
,
1252 pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1253 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1254 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1255 /* add new custom data at head of the list */
1256 pNew
->next
=*ppCustData
;
1258 offset
= entry
.next
;
1263 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1267 pTd
->vt
=type
& VT_TYPEMASK
;
1269 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1271 if(pTd
->vt
== VT_USERDEFINED
)
1272 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1274 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1278 MSFT_DoFuncs(TLBContext
* pcx
,
1283 TLBFuncDesc
** pptfd
)
1286 * member information is stored in a data structure at offset
1287 * indicated by the memoffset field of the typeinfo structure
1288 * There are several distinctive parts.
1289 * the first part starts with a field that holds the total length
1290 * of this (first) part excluding this field. Then follow the records,
1291 * for each member there is one record.
1293 * First entry is always the length of the record (excluding this
1295 * Rest of the record depends on the type of the member. If there is
1296 * a field indicating the member type (function variable intereface etc)
1297 * I have not found it yet. At this time we depend on the information
1298 * in the type info and the usual order how things are stored.
1300 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1303 * Third is a equal sized array with file offsets to the name entry
1306 * Forth and last (?) part is an array with offsets to the records in the
1307 * first part of this file segment.
1310 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1311 int recoffset
= offset
+ sizeof(INT
);
1314 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1316 TRACE_(typelib
)("\n");
1318 MSFT_Read(&infolen
, sizeof(INT
), pcx
, offset
);
1320 for ( i
= 0; i
< cFuncs
; i
++ )
1322 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1324 /* name, eventually add to a hash table */
1325 MSFT_Read(&nameoffset
,
1328 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1330 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1332 /* read the function information record */
1333 MSFT_Read(&reclength
, sizeof(INT
), pcx
, recoffset
);
1337 MSFT_Read(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
) ;
1339 /* do the attributes */
1340 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1343 if ( nrattributes
> 0 )
1345 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1347 if ( nrattributes
> 1 )
1349 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1350 pFuncRec
->OptAttr
[1]) ;
1352 if ( nrattributes
> 2 )
1354 if ( pFuncRec
->FKCCIC
& 0x2000 )
1356 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1360 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1361 pFuncRec
->OptAttr
[2]);
1363 if( nrattributes
> 5 )
1365 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1367 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1370 pFuncRec
->OptAttr
[6],
1371 &(*pptfd
)->pCustData
);
1378 /* fill the FuncDesc Structure */
1379 MSFT_Read( & (*pptfd
)->funcdesc
.memid
,
1381 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1383 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1384 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1385 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1386 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1387 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1388 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1389 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1393 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1396 /* do the parameters/arguments */
1397 if(pFuncRec
->nrargs
)
1400 MSFT_ParameterInfo paraminfo
;
1402 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1403 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1405 (*pptfd
)->pParamDesc
=
1406 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1408 MSFT_Read(¶minfo
,
1411 recoffset
+ reclength
-
1412 pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1414 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1416 TYPEDESC
* lpArgTypeDesc
= 0;
1420 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1423 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1425 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1427 /* SEEK value = jump to offset,
1428 * from there jump to the end of record,
1429 * go back by (j-1) arguments
1431 MSFT_Read( ¶minfo
,
1432 sizeof(MSFT_ParameterInfo
), pcx
,
1433 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1434 * sizeof(MSFT_ParameterInfo
)));
1436 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1438 while ( lpArgTypeDesc
!= NULL
)
1440 switch ( lpArgTypeDesc
->vt
)
1443 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1447 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1450 case VT_USERDEFINED
:
1451 MSFT_DoRefType(pcx
, pTI
,
1452 lpArgTypeDesc
->u
.hreftype
);
1454 lpArgTypeDesc
= NULL
;
1458 lpArgTypeDesc
= NULL
;
1464 /* parameter is the return value! */
1465 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1467 TYPEDESC
* lpArgTypeDesc
;
1469 (*pptfd
)->funcdesc
.elemdescFunc
=
1470 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1472 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1474 while ( lpArgTypeDesc
!= NULL
)
1476 switch ( lpArgTypeDesc
->vt
)
1479 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1483 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1487 case VT_USERDEFINED
:
1490 lpArgTypeDesc
->u
.hreftype
);
1492 lpArgTypeDesc
= NULL
;
1496 lpArgTypeDesc
= NULL
;
1501 /* second time around */
1502 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1505 (*pptfd
)->pParamDesc
[j
].Name
=
1506 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1509 if ( (PARAMFLAG_FHASDEFAULT
&
1510 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1511 ((pFuncRec
->FKCCIC
) & 0x1000) )
1513 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1515 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1517 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1519 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1520 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1522 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1526 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1529 pFuncRec
->OptAttr
[7+j
],
1530 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1535 /* scode is not used: archaic win16 stuff FIXME: right? */
1536 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1537 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1539 pptfd
= & ((*pptfd
)->next
);
1540 recoffset
+= reclength
;
1543 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1544 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1546 int infolen
, nameoffset
, reclength
;
1548 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1552 TRACE_(typelib
)("\n");
1554 MSFT_Read(&infolen
,sizeof(INT
), pcx
, offset
);
1555 MSFT_Read(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1556 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1557 recoffset
+= offset
+sizeof(INT
);
1558 for(i
=0;i
<cVars
;i
++){
1559 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1560 /* name, eventually add to a hash table */
1561 MSFT_Read(&nameoffset
, sizeof(INT
), pcx
,
1562 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1563 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1564 /* read the variable information record */
1565 MSFT_Read(&reclength
, sizeof(INT
), pcx
, recoffset
);
1567 MSFT_Read(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
) ;
1569 if(reclength
>(6*sizeof(INT
)) )
1570 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1571 if(reclength
>(7*sizeof(INT
)) )
1572 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1573 if(reclength
>(8*sizeof(INT
)) )
1574 if(reclength
>(9*sizeof(INT
)) )
1575 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1576 /* fill the VarDesc Structure */
1577 MSFT_Read(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1578 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1579 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1580 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1581 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1582 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1583 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
1584 if(pVarRec
->VarKind
== VAR_CONST
){
1585 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1586 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1587 pVarRec
->OffsValue
, pcx
);
1589 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1590 pptvd
=&((*pptvd
)->next
);
1591 recoffset
+= reclength
;
1594 /* fill in data for a hreftype (offset). When the refernced type is contained
1595 * in the typelib, it's just an (file) offset in the type info base dir.
1596 * If comes from import, it's an offset+1 in the ImpInfo table
1598 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1602 TLBRefType
**ppRefType
= &pTI
->reflist
;
1604 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1607 if((*ppRefType
)->reference
== offset
)
1609 ppRefType
= &(*ppRefType
)->next
;
1612 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1613 sizeof(**ppRefType
));
1615 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1616 /* external typelib */
1617 MSFT_ImpInfo impinfo
;
1618 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1620 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1622 MSFT_Read(&impinfo
, sizeof(impinfo
), pcx
,
1623 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1624 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1625 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1626 pImpLib
=pImpLib
->next
;
1629 (*ppRefType
)->reference
=offset
;
1630 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1631 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1632 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1634 ERR("Cannot find a reference\n");
1635 (*ppRefType
)->reference
=-1;
1636 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1639 /* in this typelib */
1640 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1641 (*ppRefType
)->reference
=offset
;
1642 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1646 /* process Implemented Interfaces of a com class */
1647 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1651 MSFT_RefRecord refrec
;
1652 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1654 TRACE_(typelib
)("\n");
1656 for(i
=0;i
<count
;i
++){
1657 if(offset
<0) break; /* paranoia */
1658 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1659 MSFT_Read(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1660 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1661 (*ppImpl
)->hRef
= refrec
.reftype
;
1662 (*ppImpl
)->implflags
=refrec
.flags
;
1663 (*ppImpl
)->ctCustData
=
1664 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1665 offset
=refrec
.onext
;
1666 ppImpl
=&((*ppImpl
)->next
);
1670 * process a typeinfo record
1672 ITypeInfoImpl
* MSFT_DoTypeInfo(
1675 ITypeLibImpl
* pLibInfo
)
1677 MSFT_TypeInfoBase tiBase
;
1678 ITypeInfoImpl
*ptiRet
;
1680 TRACE_(typelib
)("count=%u\n", count
);
1682 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1683 MSFT_Read(&tiBase
, sizeof(tiBase
) ,pcx
,
1684 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1685 /* this is where we are coming from */
1686 ptiRet
->pTypeLib
= pLibInfo
;
1687 ptiRet
->index
=count
;
1688 /* fill in the typeattr fields */
1689 FIXME("Assign constructor/destructor memid\n");
1691 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
1692 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
1693 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
1694 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
1695 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
1696 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
1697 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
1698 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
1699 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
1700 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
1701 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
1702 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
1703 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
1704 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
1705 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
1706 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
1707 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
1708 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
1711 /* IDLDESC idldescType; *//* never saw this one != zero */
1713 /* name, eventually add to a hash table */
1714 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
1715 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
1717 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
1718 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
1719 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
1720 /* note: InfoType's Help file and HelpStringDll come from the containing
1721 * library. Further HelpString and Docstring appear to be the same thing :(
1724 if(ptiRet
->TypeAttr
.cFuncs
>0 )
1725 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1726 ptiRet
->TypeAttr
.cVars
,
1727 tiBase
.memoffset
, & ptiRet
->funclist
);
1729 if(ptiRet
->TypeAttr
.cVars
>0 )
1730 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1731 ptiRet
->TypeAttr
.cVars
,
1732 tiBase
.memoffset
, & ptiRet
->varlist
);
1733 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
1734 switch(ptiRet
->TypeAttr
.typekind
)
1737 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
1740 case TKIND_DISPATCH
:
1741 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1743 if (tiBase
.datatype1
!= -1)
1745 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1746 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1749 { /* FIXME: This is a really bad hack to add IDispatch */
1750 char* szStdOle
= "stdole2.tlb\0";
1751 int nStdOleLen
= strlen(szStdOle
);
1752 TLBRefType
**ppRef
= &ptiRet
->reflist
;
1755 if((*ppRef
)->reference
== -1)
1757 ppRef
= &(*ppRef
)->next
;
1760 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
1761 (*ppRef
)->guid
= IID_IDispatch
;
1762 (*ppRef
)->reference
= -1;
1763 (*ppRef
)->index
= TLB_REF_USE_GUID
;
1764 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
1765 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
1766 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
1769 MultiByteToWideChar(CP_ACP
,
1773 (*ppRef
)->pImpTLInfo
->name
,
1774 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
1776 (*ppRef
)->pImpTLInfo
->lcid
= 0;
1777 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
1778 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
1783 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1784 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1785 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1790 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
1792 TRACE_(typelib
)("%s guid: %s kind:%s\n",
1793 debugstr_w(ptiRet
->Name
),
1794 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
1795 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
1800 /****************************************************************************
1803 * find the type of the typelib file and map the typelib resource into
1806 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1807 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1808 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
1810 int ret
= TYPE_E_CANTLOADLIBRARY
;
1811 DWORD dwSignature
= 0;
1814 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
1818 /* check the signature of the file */
1819 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
1820 if (INVALID_HANDLE_VALUE
!= hFile
)
1822 HANDLE hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
1825 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
1828 /* retrieve file size */
1829 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
1831 /* first try to load as *.tlb */
1832 dwSignature
= *((DWORD
*) pBase
);
1833 if ( dwSignature
== MSFT_SIGNATURE
)
1835 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
1836 ITypeLib2_AddRef(*ppTypeLib
);
1838 else if ( dwSignature
== SLTG_SIGNATURE
)
1840 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
1841 ITypeLib2_AddRef(*ppTypeLib
);
1843 UnmapViewOfFile(pBase
);
1845 CloseHandle(hMapping
);
1850 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
1852 /* find the typelibrary resource*/
1853 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
1854 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
1857 HRSRC hrsrc
= FindResourceA(hinstDLL
, MAKEINTRESOURCEA(index
),
1861 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
1864 LPVOID pBase
= LockResource(hGlobal
);
1865 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
1869 /* try to load as incore resource */
1870 dwSignature
= *((DWORD
*) pBase
);
1871 if ( dwSignature
== MSFT_SIGNATURE
)
1873 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
1874 ITypeLib2_AddRef(*ppTypeLib
);
1876 else if ( dwSignature
== SLTG_SIGNATURE
)
1878 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
1879 ITypeLib2_AddRef(*ppTypeLib
);
1883 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
1886 FreeResource( hGlobal
);
1889 FreeLibrary(hinstDLL
);
1896 ERR("Loading of typelib %s failed with error 0x%08lx\n",
1897 debugstr_w(pszFileName
), GetLastError());
1902 /*================== ITypeLib(2) Methods ===================================*/
1904 /****************************************************************************
1905 * ITypeLib2_Constructor_MSFT
1907 * loading an MSFT typelib from an in-memory image
1909 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
1913 MSFT_Header tlbHeader
;
1914 MSFT_SegDir tlbSegDir
;
1915 ITypeLibImpl
* pTypeLibImpl
;
1917 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
1919 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
1920 if (!pTypeLibImpl
) return NULL
;
1922 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
1923 pTypeLibImpl
->ref
= 1;
1925 /* get pointer to beginning of typelib data */
1929 cx
.pLibInfo
= pTypeLibImpl
;
1930 cx
.length
= dwTLBLength
;
1933 MSFT_Read((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
1935 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
1936 if (memcmp(&tlbHeader
.magic1
,TLBMAGIC2
,4)) {
1937 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
1940 /* there is a small amount of information here until the next important
1942 * the segment directory . Try to calculate the amount of data */
1943 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
1945 /* now read the segment directory */
1946 TRACE("read segment directory (at %ld)\n",lPSegDir
);
1947 MSFT_Read((void*)&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
1948 cx
.pTblDir
= &tlbSegDir
;
1950 /* just check two entries */
1951 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
1953 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
1954 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
1958 /* now fill our internal data */
1959 /* TLIBATTR fields */
1960 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
1961 pTypeLibImpl
->LibAttr
.lcid
= tlbHeader
.lcid
;
1962 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
1963 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
1964 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
1965 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
1967 /* name, eventually add to a hash table */
1968 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
1971 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
1972 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
1974 if( tlbHeader
.varflags
& HELPDLLFLAG
)
1977 MSFT_Read(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
1978 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
1981 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
1984 if(tlbHeader
.CustomDataOffset
>= 0)
1986 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
1989 /* fill in typedescriptions */
1990 if(tlbSegDir
.pTypdescTab
.length
> 0)
1992 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
1994 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
1995 MSFT_Read(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
1998 /* FIXME: add several sanity checks here */
1999 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2000 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2002 /* FIXME: check safearray */
2004 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2006 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2008 else if(td
[0] == VT_CARRAY
)
2010 /* array descr table here */
2011 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2013 else if(td
[0] == VT_USERDEFINED
)
2015 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2017 if(++i
<cTD
) MSFT_Read(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2020 /* second time around to fill the array subscript info */
2023 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2024 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2026 MSFT_Read(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2027 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2030 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2032 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2034 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2036 for(j
= 0; j
<td
[2]; j
++)
2038 MSFT_Read(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2039 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2040 MSFT_Read(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2041 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2046 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2047 ERR("didn't find array description data\n");
2052 /* imported type libs */
2053 if(tlbSegDir
.pImpFiles
.offset
>0)
2055 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2056 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2059 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2061 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2062 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2063 MSFT_Read(&oGuid
, sizeof(INT
), &cx
, offset
);
2065 MSFT_Read(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2066 MSFT_Read(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2067 MSFT_Read(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2068 MSFT_Read(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2071 (*ppImpLib
)->name
= TLB_Alloc(size
+1);
2072 MSFT_Read((*ppImpLib
)->name
, size
, &cx
, DO_NOT_SEEK
);
2073 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2074 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & 0xfffffffc;
2076 ppImpLib
= &(*ppImpLib
)->next
;
2081 if(tlbHeader
.nrtypeinfos
>= 0 )
2083 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2084 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2087 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2089 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2091 ITypeInfo_AddRef((ITypeInfo
*) *ppTI
);
2092 ppTI
= &((*ppTI
)->next
);
2093 (pTypeLibImpl
->TypeInfoCount
)++;
2097 TRACE("(%p)\n", pTypeLibImpl
);
2098 return (ITypeLib2
*) pTypeLibImpl
;
2102 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2108 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2109 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2110 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2111 ret
= SysAllocString(nameW
);
2112 HeapFree(GetProcessHeap(), 0, nameW
);
2116 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2122 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2123 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2127 guid
->Data4
[0] = s
>> 8;
2128 guid
->Data4
[1] = s
& 0xff;
2131 for(i
= 0; i
< 6; i
++) {
2132 memcpy(b
, str
+ 24 + 2 * i
, 2);
2133 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2138 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2145 bytelen
= *(WORD
*)ptr
;
2146 if(bytelen
== 0xffff) return 2;
2147 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2148 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2149 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2150 *pBstr
= SysAllocStringLen(nameW
, len
);
2151 HeapFree(GetProcessHeap(), 0, nameW
);
2155 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2160 bytelen
= *(WORD
*)ptr
;
2161 if(bytelen
== 0xffff) return 2;
2162 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2163 memcpy(*str
, ptr
+ 2, bytelen
);
2164 (*str
)[bytelen
] = '\0';
2168 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2170 char *ptr
= pLibBlk
;
2173 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2174 FIXME("libblk magic = %04x\n", w
);
2179 if((w
= *(WORD
*)ptr
) != 0xffff) {
2180 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2185 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2187 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2189 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2192 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2195 pTypeLibImpl
->LibAttr
.lcid
= *(WORD
*)ptr
;
2198 ptr
+= 4; /* skip res12 */
2200 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2203 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2206 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2209 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2210 ptr
+= sizeof(GUID
);
2212 return ptr
- (char*)pLibBlk
;
2215 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2218 TYPEDESC
*pTD
= &pElem
->tdesc
;
2220 /* Handle [in/out] first */
2221 if((*pType
& 0xc000) == 0xc000)
2222 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2223 else if(*pType
& 0x8000)
2224 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2225 else if(*pType
& 0x4000)
2226 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2228 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2231 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2234 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2237 if((*pType
& 0xe00) == 0xe00) {
2239 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2241 pTD
= pTD
->u
.lptdesc
;
2243 switch(*pType
& 0x7f) {
2246 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2248 pTD
= pTD
->u
.lptdesc
;
2251 case VT_USERDEFINED
:
2252 pTD
->vt
= VT_USERDEFINED
;
2253 pTD
->u
.hreftype
= *(++pType
) / 4;
2259 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2262 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2264 pTD
->vt
= VT_CARRAY
;
2265 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2267 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2268 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2269 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2270 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2272 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2278 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2282 pTD
->vt
= VT_SAFEARRAY
;
2283 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2285 pTD
= pTD
->u
.lptdesc
;
2289 pTD
->vt
= *pType
& 0x7f;
2299 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2304 TLBRefType
**ppRefType
;
2306 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2307 FIXME("Ref magic = %x\n", pRef
->magic
);
2310 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2312 ppRefType
= &pTI
->reflist
;
2313 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2315 unsigned int lib_offs
, type_num
;
2317 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2318 sizeof(**ppRefType
));
2320 name
+= SLTG_ReadStringA(name
, &refname
);
2321 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2322 FIXME("Can't sscanf ref\n");
2323 if(lib_offs
!= 0xffff) {
2324 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2327 if((*import
)->offset
== lib_offs
)
2329 import
= &(*import
)->next
;
2332 char fname
[MAX_PATH
+1];
2335 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2337 (*import
)->offset
= lib_offs
;
2338 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2340 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2341 &(*import
)->wVersionMajor
,
2342 &(*import
)->wVersionMinor
,
2343 &(*import
)->lcid
, fname
) != 4) {
2344 FIXME("can't sscanf ref %s\n",
2345 pNameTable
+ lib_offs
+ 40);
2347 len
= strlen(fname
);
2348 if(fname
[len
-1] != '#')
2349 FIXME("fname = %s\n", fname
);
2350 fname
[len
-1] = '\0';
2351 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2353 (*ppRefType
)->pImpTLInfo
= *import
;
2354 } else { /* internal ref */
2355 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2357 (*ppRefType
)->reference
= ref
;
2358 (*ppRefType
)->index
= type_num
;
2360 HeapFree(GetProcessHeap(), 0, refname
);
2361 ppRefType
= &(*ppRefType
)->next
;
2363 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2364 FIXME("End of ref block magic = %x\n", *name
);
2365 dump_TLBRefType(pTI
->reflist
);
2368 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2371 SLTG_ImplInfo
*info
;
2372 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2373 /* I don't really get this structure, usually it's 0x16 bytes
2374 long, but iuser.tlb contains some that are 0x18 bytes long.
2375 That's ok because we can use the next ptr to jump to the next
2376 one. But how do we know the length of the last one? The WORD
2377 at offs 0x8 might be the clue. For now I'm just assuming that
2378 the last one is the regular 0x16 bytes. */
2380 info
= (SLTG_ImplInfo
*)pBlk
;
2382 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2383 sizeof(**ppImplType
));
2384 (*ppImplType
)->hRef
= info
->ref
;
2385 (*ppImplType
)->implflags
= info
->impltypeflags
;
2386 pTI
->TypeAttr
.cImplTypes
++;
2387 ppImplType
= &(*ppImplType
)->next
;
2389 if(info
->next
== 0xffff)
2392 FIXME("Interface inheriting more than one interface\n");
2393 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2395 info
++; /* see comment at top of function */
2399 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2402 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2403 SLTG_MemberHeader
*pMemHeader
;
2404 char *pFirstItem
, *pNextItem
;
2406 if(pTIHeader
->href_table
!= 0xffffffff) {
2407 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2412 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2414 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2416 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2417 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2420 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2424 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2427 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2428 SLTG_MemberHeader
*pMemHeader
;
2429 SLTG_Function
*pFunc
;
2430 char *pFirstItem
, *pNextItem
;
2431 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2434 if(pTIHeader
->href_table
!= 0xffffffff) {
2435 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2439 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2441 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2443 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2444 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2447 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2448 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2453 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2454 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2455 FIXME("func magic = %02x\n", pFunc
->magic
);
2458 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2459 sizeof(**ppFuncDesc
));
2460 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2462 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2463 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2464 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2465 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2466 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2467 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2469 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2470 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2472 if(pFunc
->retnextopt
& 0x80)
2473 pType
= &pFunc
->rettype
;
2475 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2478 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2480 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2481 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2482 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2483 (*ppFuncDesc
)->pParamDesc
=
2484 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2485 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2487 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2489 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2490 char *paramName
= pNameTable
+ *pArg
;
2492 /* If arg type follows then paramName points to the 2nd
2493 letter of the name, else the next WORD is an offset to
2494 the arg type and paramName points to the first letter.
2495 So let's take one char off paramName and see if we're
2496 pointing at an alpha-numeric char. However if *pArg is
2497 0xffff or 0xfffe then the param has no name, the former
2498 meaning that the next WORD is the type, the latter
2499 meaning the the next WORD is an offset to the type. */
2504 else if(*pArg
== 0xfffe) {
2508 else if(!isalnum(*(paramName
-1)))
2513 if(HaveOffs
) { /* the next word is an offset to type */
2514 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2515 SLTG_DoType(pType
, pFirstItem
,
2516 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2521 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2522 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2525 /* Are we an optional param ? */
2526 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2527 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2528 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2531 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2532 TLB_MultiByteToBSTR(paramName
);
2536 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2537 if(pFunc
->next
== 0xffff) break;
2539 pTI
->TypeAttr
.cFuncs
= num
;
2540 dump_TLBFuncDesc(pTI
->funclist
);
2541 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2544 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2547 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2548 SLTG_MemberHeader
*pMemHeader
;
2549 SLTG_RecordItem
*pItem
;
2551 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2556 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2558 pFirstItem
= (char*)(pMemHeader
+ 1);
2559 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2560 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2561 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2562 FIXME("record magic = %02x\n", pItem
->magic
);
2565 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2566 sizeof(**ppVarDesc
));
2567 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2568 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2569 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2570 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2572 if(pItem
->typepos
== 0x02)
2573 pType
= &pItem
->type
;
2574 else if(pItem
->typepos
== 0x00)
2575 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2577 FIXME("typepos = %02x\n", pItem
->typepos
);
2581 SLTG_DoType(pType
, pFirstItem
,
2582 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2584 /* FIXME("helpcontext, helpstring\n"); */
2586 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2588 ppVarDesc
= &((*ppVarDesc
)->next
);
2589 if(pItem
->next
== 0xffff) break;
2591 pTI
->TypeAttr
.cVars
= num
;
2592 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2595 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
2598 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2599 SLTG_MemberHeader
*pMemHeader
;
2600 SLTG_EnumItem
*pItem
;
2602 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2605 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2607 pFirstItem
= (char*)(pMemHeader
+ 1);
2608 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
2609 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2610 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
2611 FIXME("enumitem magic = %04x\n", pItem
->magic
);
2614 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2615 sizeof(**ppVarDesc
));
2616 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2617 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2618 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2620 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2621 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2622 *(INT
*)(pItem
->value
+ pFirstItem
);
2623 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
2624 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2625 /* FIXME("helpcontext, helpstring\n"); */
2627 ppVarDesc
= &((*ppVarDesc
)->next
);
2628 if(pItem
->next
== 0xffff) break;
2630 pTI
->TypeAttr
.cVars
= num
;
2631 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2634 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2635 managable copy of it into this */
2648 } SLTG_InternalOtherTypeInfo
;
2650 /****************************************************************************
2651 * ITypeLib2_Constructor_SLTG
2653 * loading a SLTG typelib from an in-memory image
2655 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
2657 ITypeLibImpl
*pTypeLibImpl
;
2658 SLTG_Header
*pHeader
;
2659 SLTG_BlkEntry
*pBlkEntry
;
2663 LPVOID pBlk
, pFirstBlk
;
2664 SLTG_LibBlk
*pLibBlk
;
2665 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
2666 char *pAfterOTIBlks
= NULL
;
2667 char *pNameTable
, *ptr
;
2670 ITypeInfoImpl
**ppTypeInfoImpl
;
2672 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2674 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2675 if (!pTypeLibImpl
) return NULL
;
2677 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
2678 pTypeLibImpl
->ref
= 1;
2683 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
2684 pHeader
->nrOfFileBlks
);
2685 if (memcmp(&pHeader
->SLTG_magic
, TLBMAGIC1
, 4)) {
2686 FIXME("Header type magic 0x%08lx not supported.\n",
2687 pHeader
->SLTG_magic
);
2691 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2692 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
2694 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2695 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
2697 /* Next we have a magic block */
2698 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
2700 /* Let's see if we're still in sync */
2701 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
2702 sizeof(SLTG_COMPOBJ_MAGIC
))) {
2703 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
2706 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
2707 sizeof(SLTG_DIR_MAGIC
))) {
2708 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
2712 pIndex
= (SLTG_Index
*)(pMagic
+1);
2714 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
2716 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
2718 /* We'll set up a ptr to the main library block, which is the last one. */
2720 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2721 pBlkEntry
[order
].next
!= 0;
2722 order
= pBlkEntry
[order
].next
- 1, i
++) {
2723 pBlk
+= pBlkEntry
[order
].len
;
2727 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
2729 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2734 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2736 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2737 sizeof(*pOtherTypeInfoBlks
) *
2738 pTypeLibImpl
->TypeInfoCount
);
2741 ptr
= (char*)pLibBlk
+ len
;
2743 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
2747 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
2749 w
= *(WORD
*)(ptr
+ 2);
2752 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
2754 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
2755 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
2757 w
= *(WORD
*)(ptr
+ 4 + len
);
2759 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
2761 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
2763 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
2764 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
2766 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
2767 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
2768 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
2770 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
2772 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
2775 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
2776 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
2777 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
2778 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
2779 len
+= sizeof(SLTG_OtherTypeInfo
);
2783 pAfterOTIBlks
= ptr
;
2785 /* Skip this WORD and get the next DWORD */
2786 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
2788 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2789 magic dust and we should be pointing at the beginning of the name
2792 pNameTable
= (char*)pLibBlk
+ len
+ 0x216;
2796 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
2798 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
2801 /* Hopefully we now have enough ptrs set up to actually read in
2802 some TypeInfos. It's not clear which order to do them in, so
2803 I'll just follow the links along the BlkEntry chain and read
2804 them in in the order in which they're in the file */
2806 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
2808 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2809 pBlkEntry
[order
].next
!= 0;
2810 order
= pBlkEntry
[order
].next
- 1, i
++) {
2812 SLTG_TypeInfoHeader
*pTIHeader
;
2813 SLTG_TypeInfoTail
*pTITail
;
2815 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
2816 pOtherTypeInfoBlks
[i
].index_name
)) {
2817 FIXME("Index strings don't match\n");
2822 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
2823 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
2826 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
2827 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
2828 (*ppTypeInfoImpl
)->index
= i
;
2829 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
2830 pOtherTypeInfoBlks
[i
].name_offs
+
2832 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
2833 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
2835 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
2836 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
2837 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
2838 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
2839 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
2841 if((pTIHeader
->typeflags1
& 7) != 2)
2842 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
2843 if(pTIHeader
->typeflags3
!= 2)
2844 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
2846 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2847 debugstr_w((*ppTypeInfoImpl
)->Name
),
2848 typekind_desc
[pTIHeader
->typekind
],
2849 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
2850 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
2852 switch(pTIHeader
->typekind
) {
2854 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2858 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2861 case TKIND_INTERFACE
:
2862 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2866 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2870 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
2876 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
2877 but we've already set those */
2878 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
2879 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
2880 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
2882 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
2883 pBlk
+= pBlkEntry
[order
].len
;
2886 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
2887 FIXME("Somehow processed %d TypeInfos\n", i
);
2891 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
2892 return (ITypeLib2
*)pTypeLibImpl
;
2895 /* ITypeLib::QueryInterface
2897 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
2902 ICOM_THIS( ITypeLibImpl
, iface
);
2904 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
2907 if(IsEqualIID(riid
, &IID_IUnknown
) ||
2908 IsEqualIID(riid
,&IID_ITypeLib
)||
2909 IsEqualIID(riid
,&IID_ITypeLib2
))
2916 ITypeLib2_AddRef(iface
);
2917 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
2920 TRACE("-- Interface: E_NOINTERFACE\n");
2921 return E_NOINTERFACE
;
2926 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
2928 ICOM_THIS( ITypeLibImpl
, iface
);
2930 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
2932 return ++(This
->ref
);
2935 /* ITypeLib::Release
2937 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
2939 ICOM_THIS( ITypeLibImpl
, iface
);
2943 TRACE("(%p)->(%u)\n",This
, This
->ref
);
2947 /* fixme destroy child objects */
2949 TRACE(" destroying ITypeLib(%p)\n",This
);
2953 SysFreeString(This
->Name
);
2957 if (This
->DocString
)
2959 SysFreeString(This
->DocString
);
2960 This
->DocString
= NULL
;
2965 SysFreeString(This
->HelpFile
);
2966 This
->HelpFile
= NULL
;
2969 if (This
->HelpStringDll
)
2971 SysFreeString(This
->HelpStringDll
);
2972 This
->HelpStringDll
= NULL
;
2975 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
2976 HeapFree(GetProcessHeap(),0,This
);
2983 /* ITypeLib::GetTypeInfoCount
2985 * Returns the number of type descriptions in the type library
2987 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
2989 ICOM_THIS( ITypeLibImpl
, iface
);
2990 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
2991 return This
->TypeInfoCount
;
2994 /* ITypeLib::GetTypeInfo
2996 * retrieves the specified type description in the library.
2998 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3001 ITypeInfo
**ppTInfo
)
3005 ICOM_THIS( ITypeLibImpl
, iface
);
3006 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3008 TRACE("(%p)->(index=%d) \n", This
, index
);
3010 if (!ppTInfo
) return E_INVALIDARG
;
3012 /* search element n in list */
3013 for(i
=0; i
< index
; i
++)
3015 pTypeInfo
= pTypeInfo
->next
;
3018 TRACE("-- element not found\n");
3019 return TYPE_E_ELEMENTNOTFOUND
;
3023 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3025 ITypeInfo_AddRef(*ppTInfo
);
3026 TRACE("-- found (%p)\n",*ppTInfo
);
3031 /* ITypeLibs::GetTypeInfoType
3033 * Retrieves the type of a type description.
3035 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3040 ICOM_THIS( ITypeLibImpl
, iface
);
3042 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3044 TRACE("(%p) index %d \n",This
, index
);
3046 if(!pTKind
) return E_INVALIDARG
;
3048 /* search element n in list */
3049 for(i
=0; i
< index
; i
++)
3053 TRACE("-- element not found\n");
3054 return TYPE_E_ELEMENTNOTFOUND
;
3056 pTInfo
= pTInfo
->next
;
3059 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3060 TRACE("-- found Type (%d)\n", *pTKind
);
3064 /* ITypeLib::GetTypeInfoOfGuid
3066 * Retrieves the type description that corresponds to the specified GUID.
3069 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3072 ITypeInfo
**ppTInfo
)
3074 ICOM_THIS( ITypeLibImpl
, iface
);
3075 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3077 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3079 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3081 /* search linked list for guid */
3082 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3084 pTypeInfo
= pTypeInfo
->next
;
3088 /* end of list reached */
3089 TRACE("-- element not found\n");
3090 return TYPE_E_ELEMENTNOTFOUND
;
3094 TRACE("-- found (%p, %s)\n",
3096 debugstr_w(pTypeInfo
->Name
));
3098 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3099 ITypeInfo_AddRef(*ppTInfo
);
3103 /* ITypeLib::GetLibAttr
3105 * Retrieves the structure that contains the library's attributes.
3108 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3110 LPTLIBATTR
*ppTLibAttr
)
3112 ICOM_THIS( ITypeLibImpl
, iface
);
3113 TRACE("(%p)\n",This
);
3114 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3115 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3119 /* ITypeLib::GetTypeComp
3121 * Enables a client compiler to bind to a library's types, variables,
3122 * constants, and global functions.
3125 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3127 ITypeComp
**ppTComp
)
3129 ICOM_THIS( ITypeLibImpl
, iface
);
3130 FIXME("(%p): stub!\n",This
);
3134 /* ITypeLib::GetDocumentation
3136 * Retrieves the library's documentation string, the complete Help file name
3137 * and path, and the context identifier for the library Help topic in the Help
3141 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3145 BSTR
*pBstrDocString
,
3146 DWORD
*pdwHelpContext
,
3147 BSTR
*pBstrHelpFile
)
3149 ICOM_THIS( ITypeLibImpl
, iface
);
3151 HRESULT result
= E_INVALIDARG
;
3156 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3158 pBstrName
, pBstrDocString
,
3159 pdwHelpContext
, pBstrHelpFile
);
3163 /* documentation for the typelib */
3164 if(pBstrName
&& This
->Name
)
3166 *pBstrName
= SysAllocString(This
->Name
);
3168 if (!(*pBstrName
)) return STG_E_INSUFFICIENTMEMORY
;
3170 if(pBstrDocString
&& This
->DocString
)
3172 *pBstrDocString
= SysAllocString(This
->DocString
);
3174 if (!(*pBstrDocString
)) return STG_E_INSUFFICIENTMEMORY
;
3179 *pdwHelpContext
= This
->dwHelpContext
;
3181 if(pBstrHelpFile
&& This
->HelpFile
)
3183 *pBstrHelpFile
= SysAllocString(This
->HelpFile
);
3185 if (!(*pBstrHelpFile
)) return STG_E_INSUFFICIENTMEMORY
;
3192 /* for a typeinfo */
3193 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3195 if(SUCCEEDED(result
))
3197 result
= ITypeInfo_GetDocumentation(pTInfo
,
3201 pdwHelpContext
, pBstrHelpFile
);
3203 ITypeInfo_Release(pTInfo
);
3211 * Indicates whether a passed-in string contains the name of a type or member
3212 * described in the library.
3215 static HRESULT WINAPI
ITypeLib2_fnIsName(
3221 ICOM_THIS( ITypeLibImpl
, iface
);
3222 ITypeInfoImpl
*pTInfo
;
3223 TLBFuncDesc
*pFInfo
;
3226 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3228 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3232 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3233 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3234 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3235 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3236 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3237 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3238 goto ITypeLib2_fnIsName_exit
;
3240 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3241 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3246 ITypeLib2_fnIsName_exit
:
3247 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3248 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3253 /* ITypeLib::FindName
3255 * Finds occurrences of a type description in a type library. This may be used
3256 * to quickly verify that a name exists in a type library.
3259 static HRESULT WINAPI
ITypeLib2_fnFindName(
3263 ITypeInfo
**ppTInfo
,
3267 ICOM_THIS( ITypeLibImpl
, iface
);
3268 ITypeInfoImpl
*pTInfo
;
3269 TLBFuncDesc
*pFInfo
;
3273 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3275 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3276 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3277 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3278 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3279 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3280 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3281 goto ITypeLib2_fnFindName_exit
;
3283 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3284 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3286 ITypeLib2_fnFindName_exit
:
3287 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3288 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3291 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3292 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3299 /* ITypeLib::ReleaseTLibAttr
3301 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3304 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3306 TLIBATTR
*pTLibAttr
)
3308 ICOM_THIS( ITypeLibImpl
, iface
);
3309 TRACE("freeing (%p)\n",This
);
3310 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3314 /* ITypeLib2::GetCustData
3316 * gets the custom data
3318 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3323 ICOM_THIS( ITypeLibImpl
, iface
);
3324 TLBCustData
*pCData
;
3326 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3328 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3331 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3335 VariantInit( pVarVal
);
3336 VariantCopy( pVarVal
, &pCData
->data
);
3339 return E_INVALIDARG
; /* FIXME: correct? */
3342 /* ITypeLib2::GetLibStatistics
3344 * Returns statistics about a type library that are required for efficient
3345 * sizing of hash tables.
3348 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3350 ULONG
*pcUniqueNames
,
3351 ULONG
*pcchUniqueNames
)
3353 ICOM_THIS( ITypeLibImpl
, iface
);
3355 FIXME("(%p): stub!\n", This
);
3357 if(pcUniqueNames
) *pcUniqueNames
=1;
3358 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3362 /* ITypeLib2::GetDocumentation2
3364 * Retrieves the library's documentation string, the complete Help file name
3365 * and path, the localization context to use, and the context ID for the
3366 * library Help topic in the Help file.
3369 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3373 BSTR
*pbstrHelpString
,
3374 DWORD
*pdwHelpStringContext
,
3375 BSTR
*pbstrHelpStringDll
)
3377 ICOM_THIS( ITypeLibImpl
, iface
);
3381 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3383 /* the help string should be obtained from the helpstringdll,
3384 * using the _DLLGetDocumentation function, based on the supplied
3385 * lcid. Nice to do sometime...
3389 /* documentation for the typelib */
3391 *pbstrHelpString
=SysAllocString(This
->DocString
);
3392 if(pdwHelpStringContext
)
3393 *pdwHelpStringContext
=This
->dwHelpContext
;
3394 if(pbstrHelpStringDll
)
3395 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3401 /* for a typeinfo */
3402 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3404 if(SUCCEEDED(result
))
3406 ITypeInfo2
* pTInfo2
;
3407 result
= ITypeInfo_QueryInterface(pTInfo
,
3409 (LPVOID
*) &pTInfo2
);
3411 if(SUCCEEDED(result
))
3413 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3417 pdwHelpStringContext
,
3418 pbstrHelpStringDll
);
3420 ITypeInfo2_Release(pTInfo2
);
3423 ITypeInfo_Release(pTInfo
);
3429 /* ITypeLib2::GetAllCustData
3431 * Gets all custom data items for the library.
3434 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3436 CUSTDATA
*pCustData
)
3438 ICOM_THIS( ITypeLibImpl
, iface
);
3439 TLBCustData
*pCData
;
3441 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3442 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3443 if(pCustData
->prgCustData
){
3444 pCustData
->cCustData
=This
->ctCustData
;
3445 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3446 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3447 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3450 ERR(" OUT OF MEMORY! \n");
3451 return E_OUTOFMEMORY
;
3456 static ICOM_VTABLE(ITypeLib2
) tlbvt
= {
3457 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3458 ITypeLib2_fnQueryInterface
,
3460 ITypeLib2_fnRelease
,
3461 ITypeLib2_fnGetTypeInfoCount
,
3462 ITypeLib2_fnGetTypeInfo
,
3463 ITypeLib2_fnGetTypeInfoType
,
3464 ITypeLib2_fnGetTypeInfoOfGuid
,
3465 ITypeLib2_fnGetLibAttr
,
3466 ITypeLib2_fnGetTypeComp
,
3467 ITypeLib2_fnGetDocumentation
,
3469 ITypeLib2_fnFindName
,
3470 ITypeLib2_fnReleaseTLibAttr
,
3472 ITypeLib2_fnGetCustData
,
3473 ITypeLib2_fnGetLibStatistics
,
3474 ITypeLib2_fnGetDocumentation2
,
3475 ITypeLib2_fnGetAllCustData
3478 /*================== ITypeInfo(2) Methods ===================================*/
3479 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
3481 ITypeInfoImpl
* pTypeInfoImpl
;
3483 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
3486 ICOM_VTBL(pTypeInfoImpl
) = &tinfvt
;
3487 pTypeInfoImpl
->ref
=1;
3489 TRACE("(%p)\n", pTypeInfoImpl
);
3490 return (ITypeInfo2
*) pTypeInfoImpl
;
3493 /* ITypeInfo::QueryInterface
3495 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
3500 ICOM_THIS( ITypeLibImpl
, iface
);
3502 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3505 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3506 IsEqualIID(riid
,&IID_ITypeInfo
)||
3507 IsEqualIID(riid
,&IID_ITypeInfo2
))
3511 ITypeInfo_AddRef(iface
);
3512 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3515 TRACE("-- Interface: E_NOINTERFACE\n");
3516 return E_NOINTERFACE
;
3519 /* ITypeInfo::AddRef
3521 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
3523 ICOM_THIS( ITypeInfoImpl
, iface
);
3527 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3531 /* ITypeInfo::Release
3533 static ULONG WINAPI
ITypeInfo_fnRelease( ITypeInfo2
*iface
)
3535 ICOM_THIS( ITypeInfoImpl
, iface
);
3539 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3543 FIXME("destroy child objects\n");
3545 TRACE("destroying ITypeInfo(%p)\n",This
);
3548 SysFreeString(This
->Name
);
3552 if (This
->DocString
)
3554 SysFreeString(This
->DocString
);
3555 This
->DocString
= 0;
3560 ITypeInfo_Release((ITypeInfo
*)This
->next
);
3563 HeapFree(GetProcessHeap(),0,This
);
3569 /* ITypeInfo::GetTypeAttr
3571 * Retrieves a TYPEATTR structure that contains the attributes of the type
3575 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
3576 LPTYPEATTR
*ppTypeAttr
)
3578 ICOM_THIS( ITypeInfoImpl
, iface
);
3579 TRACE("(%p)\n",This
);
3580 /* FIXME: must do a copy here */
3581 *ppTypeAttr
=&This
->TypeAttr
;
3585 /* ITypeInfo::GetTypeComp
3587 * Retrieves the ITypeComp interface for the type description, which enables a
3588 * client compiler to bind to the type description's members.
3591 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
3592 ITypeComp
* *ppTComp
)
3594 ICOM_THIS( ITypeInfoImpl
, iface
);
3595 FIXME("(%p) stub!\n", This
);
3599 /* ITypeInfo::GetFuncDesc
3601 * Retrieves the FUNCDESC structure that contains information about a
3602 * specified function.
3605 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
3606 LPFUNCDESC
*ppFuncDesc
)
3608 ICOM_THIS( ITypeInfoImpl
, iface
);
3610 TLBFuncDesc
* pFDesc
;
3611 TRACE("(%p) index %d\n", This
, index
);
3612 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
3615 /* FIXME: must do a copy here */
3616 *ppFuncDesc
=&pFDesc
->funcdesc
;
3619 return E_INVALIDARG
;
3622 /* ITypeInfo::GetVarDesc
3624 * Retrieves a VARDESC structure that describes the specified variable.
3627 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
3628 LPVARDESC
*ppVarDesc
)
3630 ICOM_THIS( ITypeInfoImpl
, iface
);
3632 TLBVarDesc
* pVDesc
;
3633 TRACE("(%p) index %d\n", This
, index
);
3634 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
3637 /* FIXME: must do a copy here */
3638 *ppVarDesc
=&pVDesc
->vardesc
;
3641 return E_INVALIDARG
;
3644 /* ITypeInfo_GetNames
3646 * Retrieves the variable with the specified member ID (or the name of the
3647 * property or method and its parameters) that correspond to the specified
3650 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
3651 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
3653 ICOM_THIS( ITypeInfoImpl
, iface
);
3654 TLBFuncDesc
* pFDesc
;
3655 TLBVarDesc
* pVDesc
;
3657 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
3658 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
3661 /* function found, now return function and parameter names */
3662 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
3665 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
3667 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
3673 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
3676 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
3681 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
)
3683 /* recursive search */
3686 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
3688 if(SUCCEEDED(result
))
3690 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
3691 ITypeInfo_Release(pTInfo
);
3694 WARN("Could not search inherited interface!\n");
3698 WARN("no names found\n");
3701 return TYPE_E_ELEMENTNOTFOUND
;
3708 /* ITypeInfo::GetRefTypeOfImplType
3710 * If a type description describes a COM class, it retrieves the type
3711 * description of the implemented interface types. For an interface,
3712 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3716 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
3721 ICOM_THIS( ITypeInfoImpl
, iface
);
3723 TLBImplType
*pImpl
= This
->impltypelist
;
3725 TRACE("(%p) index %d\n", This
, index
);
3726 dump_TypeInfo(This
);
3730 /* only valid on dual interfaces;
3731 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3733 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
3735 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
3736 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
3742 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
3743 *pRefType
= pImpl
->hRef
;
3748 /* get element n from linked list */
3749 for(i
=0; pImpl
&& i
<index
; i
++)
3751 pImpl
= pImpl
->next
;
3754 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
3756 *pRefType
= pImpl
->hRef
;
3758 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
3765 /* ITypeInfo::GetImplTypeFlags
3767 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3768 * or base interface in a type description.
3770 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
3771 UINT index
, INT
*pImplTypeFlags
)
3773 ICOM_THIS( ITypeInfoImpl
, iface
);
3777 TRACE("(%p) index %d\n", This
, index
);
3778 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
3779 i
++, pImpl
=pImpl
->next
)
3781 if(i
==index
&& pImpl
){
3782 *pImplTypeFlags
=pImpl
->implflags
;
3786 return TYPE_E_ELEMENTNOTFOUND
;
3790 * Maps between member names and member IDs, and parameter names and
3793 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
3794 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
3796 ICOM_THIS( ITypeInfoImpl
, iface
);
3797 TLBFuncDesc
* pFDesc
;
3798 TLBVarDesc
* pVDesc
;
3801 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
3803 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
3805 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
3806 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
3807 for(i
=1; i
< cNames
; i
++){
3808 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
3809 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
3811 if( j
<pFDesc
->funcdesc
.cParams
)
3814 ret
=DISP_E_UNKNOWNNAME
;
3819 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
3820 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
3821 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
3825 /* not found, see if this is and interface with an inheritance */
3826 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&&
3827 This
->TypeAttr
.cImplTypes
){
3828 /* recursive search */
3830 ret
=ITypeInfo_GetRefTypeInfo(iface
,
3831 This
->impltypelist
->hRef
, &pTInfo
);
3833 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
3834 ITypeInfo_Release(pTInfo
);
3837 WARN("Could not search inherited interface!\n");
3839 WARN("no names found\n");
3840 return DISP_E_UNKNOWNNAME
;
3843 /* ITypeInfo::Invoke
3845 * Invokes a method, or accesses a property of an object, that implements the
3846 * interface described by the type description.
3848 static DWORD
_invoke(LPVOID func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
3851 if (TRACE_ON(ole
)) {
3853 MESSAGE("Calling %p(",func
);
3854 for (i
=0;i
<nrargs
;i
++) MESSAGE("%08lx,",args
[i
]);
3863 DWORD (WINAPI
*xfunc
)() = func
;
3868 DWORD (WINAPI
*xfunc
)(DWORD
) = func
;
3869 res
= xfunc(args
[0]);
3873 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
) = func
;
3874 res
= xfunc(args
[0],args
[1]);
3878 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
) = func
;
3879 res
= xfunc(args
[0],args
[1],args
[2]);
3883 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
3889 FIXME("unsupported calling convention %d\n",callconv
);
3893 TRACE("returns %08lx\n",res
);
3897 static HRESULT WINAPI
ITypeInfo_fnInvoke(
3902 DISPPARAMS
*pDispParams
,
3903 VARIANT
*pVarResult
,
3904 EXCEPINFO
*pExcepInfo
,
3907 ICOM_THIS( ITypeInfoImpl
, iface
);
3908 TLBFuncDesc
* pFDesc
;
3909 TLBVarDesc
* pVDesc
;
3912 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
3913 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
3915 dump_DispParms(pDispParams
);
3917 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
3918 if (pFDesc
->funcdesc
.memid
== memid
) {
3919 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
3923 dump_TLBFuncDescOne(pFDesc
);
3924 switch (pFDesc
->funcdesc
.funckind
) {
3925 case FUNC_PUREVIRTUAL
:
3926 case FUNC_VIRTUAL
: {
3928 DWORD
*args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*(pFDesc
->funcdesc
.cParams
+1));
3929 DWORD
*args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
)*(pFDesc
->funcdesc
.cParams
));
3930 args
[0] = (DWORD
)pIUnk
;
3932 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
3933 if (i
<pDispParams
->cArgs
) {
3934 TRACE("set %d to disparg type %d vs %d\n",i
,
3935 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1]),
3936 pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
3938 args
[i
+1] = V_UNION(&pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1],lVal
);
3940 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
3941 TRACE("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
3942 /*FIXME: give pointers for the rest, so propertyget works*/
3943 args
[i
+1] = (DWORD
)&args2
[i
];
3945 /* If pointer to variant, pass reference to variant
3946 * in result variant array.
3948 if ((tdesc
->vt
== VT_PTR
) &&
3949 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
3952 args
[i
+1] = (DWORD
)(pVarResult
+(i
-pDispParams
->cArgs
));
3955 if (pFDesc
->funcdesc
.cParamsOpt
)
3956 FIXME("Does not support optional parameters (%d)\n",
3957 pFDesc
->funcdesc
.cParamsOpt
3960 res
= _invoke((*(DWORD
***)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
3961 pFDesc
->funcdesc
.callconv
,
3962 pFDesc
->funcdesc
.cParams
+1,
3965 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
3966 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
3967 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
3968 /* If we are a pointer to a variant, we are done already */
3969 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
3972 VariantInit(&pVarResult
[i
]);
3973 V_UNION(pVarResult
+i
,intVal
) = args2
[i
];
3975 if (tdesc
->vt
== VT_PTR
)
3976 tdesc
= tdesc
->u
.lptdesc
;
3977 V_VT(pVarResult
+i
) = tdesc
->vt
;
3979 /* HACK: VB5 likes this.
3980 * I do not know why. There is 1 example in MSDN which uses
3981 * this which appears broken (mixes int vals and
3984 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
3985 V_VT(pVarResult
+i
) = VT_DISPATCH
;
3986 TRACE("storing into variant: [%d] type %d, val %08x\n",
3987 i
,V_VT(pVarResult
+i
),V_UNION(pVarResult
+i
,intVal
)
3991 HeapFree(GetProcessHeap(),0,args2
);
3992 HeapFree(GetProcessHeap(),0,args
);
3995 case FUNC_DISPATCH
: {
3999 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4001 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4004 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4005 hr
= IDispatch_Invoke(
4006 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4007 pVarResult
,pExcepInfo
,pArgErr
4010 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4011 IDispatch_Release(disp
);
4015 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4019 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4020 if (pVDesc
->vardesc
.memid
== memid
) {
4021 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4022 dump_TLBVarDesc(pVDesc
);
4027 /* not found, look for it in inherited interfaces */
4028 if (This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
) {
4029 /* recursive search */
4032 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4034 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4035 ITypeInfo_Release(pTInfo
);
4038 WARN("Could not search inherited interface!\n");
4040 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4041 return DISP_E_MEMBERNOTFOUND
;
4044 /* ITypeInfo::GetDocumentation
4046 * Retrieves the documentation string, the complete Help file name and path,
4047 * and the context ID for the Help topic for a specified type description.
4049 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4050 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4051 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4053 ICOM_THIS( ITypeInfoImpl
, iface
);
4054 TLBFuncDesc
* pFDesc
;
4055 TLBVarDesc
* pVDesc
;
4056 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4057 " HelpContext(%p) HelpFile(%p)\n",
4058 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4059 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4061 *pBstrName
=SysAllocString(This
->Name
);
4063 *pBstrDocString
=SysAllocString(This
->DocString
);
4065 *pdwHelpContext
=This
->dwHelpContext
;
4067 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4069 }else {/* for a member */
4070 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4071 if(pFDesc
->funcdesc
.memid
==memid
){
4073 *pBstrName
= SysAllocString(pFDesc
->Name
);
4075 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4077 *pdwHelpContext
=pFDesc
->helpcontext
;
4080 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4081 if(pVDesc
->vardesc
.memid
==memid
){
4082 FIXME("Not implemented\n");
4086 return TYPE_E_ELEMENTNOTFOUND
;
4089 /* ITypeInfo::GetDllEntry
4091 * Retrieves a description or specification of an entry point for a function
4094 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4095 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4098 ICOM_THIS( ITypeInfoImpl
, iface
);
4099 FIXME("(%p) stub!\n", This
);
4103 /* ITypeInfo::GetRefTypeInfo
4105 * If a type description references other type descriptions, it retrieves
4106 * the referenced type descriptions.
4108 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
4111 ITypeInfo
**ppTInfo
)
4113 ICOM_THIS( ITypeInfoImpl
, iface
);
4114 HRESULT result
= E_FAIL
;
4117 if (hRefType
== -1 &&
4118 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4119 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4121 /* when we meet a DUAL dispinterface, we must create the interface
4124 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
4127 /* the interface version contains the same information as the dispinterface
4128 * copy the contents of the structs.
4130 *pTypeInfoImpl
= *This
;
4131 pTypeInfoImpl
->ref
= 1;
4133 /* change the type to interface */
4134 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
4136 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
4138 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
4143 TLBRefType
*pRefType
;
4144 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
4145 if(pRefType
->reference
== hRefType
)
4149 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
4150 if(pRefType
&& hRefType
!= -1) {
4153 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
4155 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
4157 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
4158 TRACE("typeinfo in imported typelib that is already loaded\n");
4159 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
4160 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
4163 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4164 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
4165 pRefType
->pImpTLInfo
->wVersionMajor
,
4166 pRefType
->pImpTLInfo
->wVersionMinor
,
4167 pRefType
->pImpTLInfo
->lcid
,
4170 if(!SUCCEEDED(result
)) {
4171 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
4172 result
=LoadTypeLib(libnam
, &pTLib
);
4173 SysFreeString(libnam
);
4175 if(SUCCEEDED(result
)) {
4176 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
4177 ITypeLib2_AddRef(pTLib
);
4181 if(SUCCEEDED(result
)) {
4182 if(pRefType
->index
== TLB_REF_USE_GUID
)
4183 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
4187 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
4193 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
4194 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
4198 /* ITypeInfo::AddressOfMember
4200 * Retrieves the addresses of static functions or variables, such as those
4203 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
4204 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
4206 ICOM_THIS( ITypeInfoImpl
, iface
);
4207 FIXME("(%p) stub!\n", This
);
4211 /* ITypeInfo::CreateInstance
4213 * Creates a new instance of a type that describes a component object class
4216 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
4217 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
4219 ICOM_THIS( ITypeInfoImpl
, iface
);
4220 FIXME("(%p) stub!\n", This
);
4224 /* ITypeInfo::GetMops
4226 * Retrieves marshaling information.
4228 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
4231 ICOM_THIS( ITypeInfoImpl
, iface
);
4232 FIXME("(%p) stub!\n", This
);
4236 /* ITypeInfo::GetContainingTypeLib
4238 * Retrieves the containing type library and the index of the type description
4239 * within that type library.
4241 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
4242 ITypeLib
* *ppTLib
, UINT
*pIndex
)
4244 ICOM_THIS( ITypeInfoImpl
, iface
);
4246 return E_INVALIDARG
;
4247 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
4248 *pIndex
=This
->index
;
4249 ITypeLib2_AddRef(*ppTLib
);
4250 TRACE("(%p) returns (%p) index %d!\n", This
, *ppTLib
, *pIndex
);
4254 /* ITypeInfo::ReleaseTypeAttr
4256 * Releases a TYPEATTR previously returned by GetTypeAttr.
4259 static HRESULT WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
4260 TYPEATTR
* pTypeAttr
)
4262 ICOM_THIS( ITypeInfoImpl
, iface
);
4263 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
4267 /* ITypeInfo::ReleaseFuncDesc
4269 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4271 static HRESULT WINAPI
ITypeInfo_fnReleaseFuncDesc(
4273 FUNCDESC
*pFuncDesc
)
4275 ICOM_THIS( ITypeInfoImpl
, iface
);
4276 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
4280 /* ITypeInfo::ReleaseVarDesc
4282 * Releases a VARDESC previously returned by GetVarDesc.
4284 static HRESULT WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
4287 ICOM_THIS( ITypeInfoImpl
, iface
);
4288 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
4292 /* ITypeInfo2::GetTypeKind
4294 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4297 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
4298 TYPEKIND
*pTypeKind
)
4300 ICOM_THIS( ITypeInfoImpl
, iface
);
4301 *pTypeKind
=This
->TypeAttr
.typekind
;
4302 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
4306 /* ITypeInfo2::GetTypeFlags
4308 * Returns the type flags without any allocations. This returns a DWORD type
4309 * flag, which expands the type flags without growing the TYPEATTR (type
4313 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
* iface
,
4316 ICOM_THIS( ITypeInfoImpl
, iface
);
4317 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
4318 TRACE("(%p) flags 0x%04x\n", This
,*pTypeFlags
);
4322 /* ITypeInfo2::GetFuncIndexOfMemId
4323 * Binds to a specific member based on a known DISPID, where the member name
4324 * is not known (for example, when binding to a default member).
4327 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
4328 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
4330 ICOM_THIS( ITypeInfoImpl
, iface
);
4331 TLBFuncDesc
*pFuncInfo
;
4334 /* FIXME: should check for invKind??? */
4335 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
4336 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
4342 result
=E_INVALIDARG
;
4344 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
4345 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4349 /* TypeInfo2::GetVarIndexOfMemId
4351 * Binds to a specific member based on a known DISPID, where the member name
4352 * is not known (for example, when binding to a default member).
4355 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
4356 MEMBERID memid
, UINT
*pVarIndex
)
4358 ICOM_THIS( ITypeInfoImpl
, iface
);
4359 TLBVarDesc
*pVarInfo
;
4362 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
4363 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
4370 result
=E_INVALIDARG
;
4372 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
4373 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4377 /* ITypeInfo2::GetCustData
4379 * Gets the custom data
4381 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
4386 ICOM_THIS( ITypeInfoImpl
, iface
);
4387 TLBCustData
*pCData
;
4389 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4390 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4392 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4396 VariantInit( pVarVal
);
4397 VariantCopy( pVarVal
, &pCData
->data
);
4400 return E_INVALIDARG
; /* FIXME: correct? */
4403 /* ITypeInfo2::GetFuncCustData
4405 * Gets the custom data
4407 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
4413 ICOM_THIS( ITypeInfoImpl
, iface
);
4414 TLBCustData
*pCData
=NULL
;
4415 TLBFuncDesc
* pFDesc
;
4417 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4418 pFDesc
=pFDesc
->next
);
4421 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4422 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4424 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4427 VariantInit( pVarVal
);
4428 VariantCopy( pVarVal
, &pCData
->data
);
4431 return E_INVALIDARG
; /* FIXME: correct? */
4434 /* ITypeInfo2::GetParamCustData
4436 * Gets the custom data
4438 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
4445 ICOM_THIS( ITypeInfoImpl
, iface
);
4446 TLBCustData
*pCData
=NULL
;
4447 TLBFuncDesc
* pFDesc
;
4450 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
4452 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
4453 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
4454 pCData
= pCData
->next
)
4455 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4457 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4461 VariantInit( pVarVal
);
4462 VariantCopy( pVarVal
, &pCData
->data
);
4465 return E_INVALIDARG
; /* FIXME: correct? */
4468 /* ITypeInfo2::GetVarCustData
4470 * Gets the custom data
4472 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
4478 ICOM_THIS( ITypeInfoImpl
, iface
);
4479 TLBCustData
*pCData
=NULL
;
4480 TLBVarDesc
* pVDesc
;
4483 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
4487 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4489 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4493 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4497 VariantInit( pVarVal
);
4498 VariantCopy( pVarVal
, &pCData
->data
);
4501 return E_INVALIDARG
; /* FIXME: correct? */
4504 /* ITypeInfo2::GetImplCustData
4506 * Gets the custom data
4508 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
4514 ICOM_THIS( ITypeInfoImpl
, iface
);
4515 TLBCustData
*pCData
=NULL
;
4516 TLBImplType
* pRDesc
;
4519 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
4523 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4525 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4529 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4533 VariantInit( pVarVal
);
4534 VariantCopy( pVarVal
, &pCData
->data
);
4537 return E_INVALIDARG
; /* FIXME: correct? */
4540 /* ITypeInfo2::GetDocumentation2
4542 * Retrieves the documentation string, the complete Help file name and path,
4543 * the localization context to use, and the context ID for the library Help
4544 * topic in the Help file.
4547 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
4551 BSTR
*pbstrHelpString
,
4552 DWORD
*pdwHelpStringContext
,
4553 BSTR
*pbstrHelpStringDll
)
4555 ICOM_THIS( ITypeInfoImpl
, iface
);
4556 TLBFuncDesc
* pFDesc
;
4557 TLBVarDesc
* pVDesc
;
4558 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4559 "HelpStringContext(%p) HelpStringDll(%p)\n",
4560 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
4561 pbstrHelpStringDll
);
4562 /* the help string should be obtained from the helpstringdll,
4563 * using the _DLLGetDocumentation function, based on the supplied
4564 * lcid. Nice to do sometime...
4566 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4568 *pbstrHelpString
=SysAllocString(This
->Name
);
4569 if(pdwHelpStringContext
)
4570 *pdwHelpStringContext
=This
->dwHelpStringContext
;
4571 if(pbstrHelpStringDll
)
4572 *pbstrHelpStringDll
=
4573 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4575 }else {/* for a member */
4576 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4577 if(pFDesc
->funcdesc
.memid
==memid
){
4579 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
4580 if(pdwHelpStringContext
)
4581 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
4582 if(pbstrHelpStringDll
)
4583 *pbstrHelpStringDll
=
4584 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4587 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4588 if(pVDesc
->vardesc
.memid
==memid
){
4590 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
4591 if(pdwHelpStringContext
)
4592 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
4593 if(pbstrHelpStringDll
)
4594 *pbstrHelpStringDll
=
4595 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4599 return TYPE_E_ELEMENTNOTFOUND
;
4602 /* ITypeInfo2::GetAllCustData
4604 * Gets all custom data items for the Type info.
4607 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
4609 CUSTDATA
*pCustData
)
4611 ICOM_THIS( ITypeInfoImpl
, iface
);
4612 TLBCustData
*pCData
;
4615 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4617 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4618 if(pCustData
->prgCustData
){
4619 pCustData
->cCustData
=This
->ctCustData
;
4620 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4621 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4622 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4625 ERR(" OUT OF MEMORY! \n");
4626 return E_OUTOFMEMORY
;
4631 /* ITypeInfo2::GetAllFuncCustData
4633 * Gets all custom data items for the specified Function
4636 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
4639 CUSTDATA
*pCustData
)
4641 ICOM_THIS( ITypeInfoImpl
, iface
);
4642 TLBCustData
*pCData
;
4643 TLBFuncDesc
* pFDesc
;
4645 TRACE("(%p) index %d\n", This
, index
);
4646 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4647 pFDesc
=pFDesc
->next
)
4650 pCustData
->prgCustData
=
4651 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4652 if(pCustData
->prgCustData
){
4653 pCustData
->cCustData
=pFDesc
->ctCustData
;
4654 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
4655 pCData
= pCData
->next
){
4656 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4657 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4661 ERR(" OUT OF MEMORY! \n");
4662 return E_OUTOFMEMORY
;
4666 return TYPE_E_ELEMENTNOTFOUND
;
4669 /* ITypeInfo2::GetAllParamCustData
4671 * Gets all custom data items for the Functions
4674 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
4675 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
4677 ICOM_THIS( ITypeInfoImpl
, iface
);
4678 TLBCustData
*pCData
=NULL
;
4679 TLBFuncDesc
* pFDesc
;
4681 TRACE("(%p) index %d\n", This
, indexFunc
);
4682 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
4683 pFDesc
=pFDesc
->next
)
4685 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
4686 pCustData
->prgCustData
=
4687 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
4688 sizeof(CUSTDATAITEM
));
4689 if(pCustData
->prgCustData
){
4690 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
4691 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
4692 pCData
; i
++, pCData
= pCData
->next
){
4693 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4694 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4698 ERR(" OUT OF MEMORY! \n");
4699 return E_OUTOFMEMORY
;
4703 return TYPE_E_ELEMENTNOTFOUND
;
4706 /* ITypeInfo2::GetAllVarCustData
4708 * Gets all custom data items for the specified Variable
4711 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
4712 UINT index
, CUSTDATA
*pCustData
)
4714 ICOM_THIS( ITypeInfoImpl
, iface
);
4715 TLBCustData
*pCData
;
4716 TLBVarDesc
* pVDesc
;
4718 TRACE("(%p) index %d\n", This
, index
);
4719 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
4720 pVDesc
=pVDesc
->next
)
4723 pCustData
->prgCustData
=
4724 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4725 if(pCustData
->prgCustData
){
4726 pCustData
->cCustData
=pVDesc
->ctCustData
;
4727 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
4728 pCData
= pCData
->next
){
4729 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4730 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4734 ERR(" OUT OF MEMORY! \n");
4735 return E_OUTOFMEMORY
;
4739 return TYPE_E_ELEMENTNOTFOUND
;
4742 /* ITypeInfo2::GetAllImplCustData
4744 * Gets all custom data items for the specified implementation type
4747 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
4750 CUSTDATA
*pCustData
)
4752 ICOM_THIS( ITypeInfoImpl
, iface
);
4753 TLBCustData
*pCData
;
4754 TLBImplType
* pRDesc
;
4756 TRACE("(%p) index %d\n", This
, index
);
4757 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
4758 pRDesc
=pRDesc
->next
)
4761 pCustData
->prgCustData
=
4762 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4763 if(pCustData
->prgCustData
){
4764 pCustData
->cCustData
=pRDesc
->ctCustData
;
4765 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
4766 pCData
= pCData
->next
){
4767 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4768 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4772 ERR(" OUT OF MEMORY! \n");
4773 return E_OUTOFMEMORY
;
4777 return TYPE_E_ELEMENTNOTFOUND
;
4780 static ICOM_VTABLE(ITypeInfo2
) tinfvt
=
4782 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4784 ITypeInfo_fnQueryInterface
,
4786 ITypeInfo_fnRelease
,
4788 ITypeInfo_fnGetTypeAttr
,
4789 ITypeInfo_fnGetTypeComp
,
4790 ITypeInfo_fnGetFuncDesc
,
4791 ITypeInfo_fnGetVarDesc
,
4792 ITypeInfo_fnGetNames
,
4793 ITypeInfo_fnGetRefTypeOfImplType
,
4794 ITypeInfo_fnGetImplTypeFlags
,
4795 ITypeInfo_fnGetIDsOfNames
,
4797 ITypeInfo_fnGetDocumentation
,
4798 ITypeInfo_fnGetDllEntry
,
4799 ITypeInfo_fnGetRefTypeInfo
,
4800 ITypeInfo_fnAddressOfMember
,
4801 ITypeInfo_fnCreateInstance
,
4802 ITypeInfo_fnGetMops
,
4803 ITypeInfo_fnGetContainingTypeLib
,
4804 ITypeInfo_fnReleaseTypeAttr
,
4805 ITypeInfo_fnReleaseFuncDesc
,
4806 ITypeInfo_fnReleaseVarDesc
,
4808 ITypeInfo2_fnGetTypeKind
,
4809 ITypeInfo2_fnGetTypeFlags
,
4810 ITypeInfo2_fnGetFuncIndexOfMemId
,
4811 ITypeInfo2_fnGetVarIndexOfMemId
,
4812 ITypeInfo2_fnGetCustData
,
4813 ITypeInfo2_fnGetFuncCustData
,
4814 ITypeInfo2_fnGetParamCustData
,
4815 ITypeInfo2_fnGetVarCustData
,
4816 ITypeInfo2_fnGetImplTypeCustData
,
4817 ITypeInfo2_fnGetDocumentation2
,
4818 ITypeInfo2_fnGetAllCustData
,
4819 ITypeInfo2_fnGetAllFuncCustData
,
4820 ITypeInfo2_fnGetAllParamCustData
,
4821 ITypeInfo2_fnGetAllVarCustData
,
4822 ITypeInfo2_fnGetAllImplTypeCustData
,