4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
64 #include "winnls.h" /* for PRIMARYLANGID */
65 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
68 #include "wine/unicode.h"
69 #include "wine/obj_base.h"
73 #include "wine/debug.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
79 /****************************************************************************
82 * Takes p_iVal (which is in little endian) and returns it
83 * in the host machine's byte order.
85 #ifdef WORDS_BIGENDIAN
86 static WORD
FromLEWord(WORD p_iVal
)
88 return (((p_iVal
& 0x00FF) << 8) |
89 ((p_iVal
& 0xFF00) >> 8));
93 static DWORD
FromLEDWord(DWORD p_iVal
)
95 return (((p_iVal
& 0x000000FF) << 24) |
96 ((p_iVal
& 0x0000FF00) << 8) |
97 ((p_iVal
& 0x00FF0000) >> 8) |
98 ((p_iVal
& 0xFF000000) >> 24));
101 #define FromLEWord(X) (X)
102 #define FromLEDWord(X) (X)
106 /****************************************************************************
109 * Fix byte order in any structure if necessary
111 #ifdef WORDS_BIGENDIAN
112 static void FromLEWords(void *p_Val
, int p_iSize
)
116 p_iSize
/= sizeof(WORD
);
119 *Val
= FromLEWord(*Val
);
126 static void FromLEDWords(void *p_Val
, int p_iSize
)
130 p_iSize
/= sizeof(DWORD
);
133 *Val
= FromLEDWord(*Val
);
139 #define FromLEWords(X,Y) /*nothing*/
140 #define FromLEDWords(X,Y) /*nothing*/
144 /****************************************************************************
145 * QueryPathOfRegTypeLib [TYPELIB.14]
147 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
152 QueryPathOfRegTypeLib16(
153 REFGUID guid
, /* [in] referenced guid */
154 WORD wMaj
, /* [in] major version */
155 WORD wMin
, /* [in] minor version */
156 LCID lcid
, /* [in] locale id */
157 LPBSTR16 path
/* [out] path of typelib */
160 char typelibkey
[100],pathname
[260];
166 sprintf( typelibkey
, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
167 guid
->Data1
, guid
->Data2
, guid
->Data3
,
168 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
169 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
172 sprintf(xguid
,"<guid 0x%08lx>",(DWORD
)guid
);
173 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid
,wMaj
,wMin
,(DWORD
)lcid
,path
);
176 plen
= sizeof(pathname
);
177 if (RegQueryValueA(HKEY_LOCAL_MACHINE
,typelibkey
,pathname
,&plen
)) {
178 /* try again without lang specific id */
180 return QueryPathOfRegTypeLib16(guid
,wMaj
,wMin
,PRIMARYLANGID(lcid
),path
);
181 FIXME("key %s not found\n",typelibkey
);
184 *path
= SysAllocString16(pathname
);
188 /****************************************************************************
189 * QueryPathOfRegTypeLib [OLEAUT32.164]
194 QueryPathOfRegTypeLib(
195 REFGUID guid
, /* [in] referenced guid */
196 WORD wMaj
, /* [in] major version */
197 WORD wMin
, /* [in] minor version */
198 LCID lcid
, /* [in] locale id */
199 LPBSTR path
) /* [out] path of typelib */
201 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
202 string termination character on output strings */
209 char szTypeLibKey
[100];
210 char szPath
[MAX_PATH
];
211 DWORD dwPathLen
= sizeof(szPath
);
219 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID
, wMaj
, wMin
, (DWORD
)lcid
, path
);
225 sprintf(szTypeLibKey
,
226 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
227 guid
->Data1
, guid
->Data2
, guid
->Data3
,
228 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
229 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
234 if (RegQueryValueA(HKEY_LOCAL_MACHINE
, szTypeLibKey
, szPath
, &dwPathLen
))
238 else if (myLCID
== lcid
)
240 /* try with sub-langid */
241 myLCID
= SUBLANGID(lcid
);
243 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
245 /* try with system langid */
255 DWORD len
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, szPath
, dwPathLen
, NULL
, 0 );
256 BSTR bstrPath
= SysAllocStringLen(NULL
,len
);
258 MultiByteToWideChar(CP_ACP
,
270 TRACE_(typelib
)("%s not found\n", szTypeLibKey
);
275 /******************************************************************************
276 * CreateTypeLib [OLEAUT32.160] creates a typelib
282 HRESULT WINAPI
CreateTypeLib(
283 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
285 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
288 /******************************************************************************
289 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
291 * Docs: OLECHAR FAR* szFile
292 * Docs: iTypeLib FAR* FAR* pptLib
298 HRESULT WINAPI
LoadTypeLib16(
299 LPOLESTR szFile
, /* [in] Name of file to load from */
300 ITypeLib
** pptLib
) /* [out] Pointer to pointer to loaded type library */
302 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR
)szFile
),pptLib
);
310 /******************************************************************************
311 * LoadTypeLib [OLEAUT32.161]
312 * Loads and registers a type library
314 * Docs: OLECHAR FAR* szFile
315 * Docs: iTypeLib FAR* FAR* pptLib
321 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
323 HRESULT WINAPI
LoadTypeLib(
324 const OLECHAR
*szFile
,/* [in] Name of file to load from */
325 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
328 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
331 /******************************************************************************
332 * LoadTypeLibEx [OLEAUT32.183]
333 * Loads and optionally registers a type library
339 HRESULT WINAPI
LoadTypeLibEx(
340 LPCOLESTR szFile
, /* [in] Name of file to load from */
341 REGKIND regkind
, /* [in] Specify kind of registration */
342 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
344 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
348 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
350 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
353 /* Look for a trailing '\\' followed by an index */
354 pIndexStr
= strrchrW(szFile
, '\\');
355 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
356 index
= atoiW(pIndexStr
);
357 memcpy(szFileCopy
, szFile
,
358 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
359 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
360 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
362 return TYPE_E_CANTLOADLIBRARY
;
363 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
364 return TYPE_E_CANTLOADLIBRARY
;
366 return TYPE_E_CANTLOADLIBRARY
;
369 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
371 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
376 case REGKIND_DEFAULT
:
377 /* FIXME: is this correct? */
378 if (!szFile
|| !szFile
[0] ||
379 (szFile
[0] != '\\' && szFile
[0] != '/' && szFile
[1] != ':'))
381 /* else fall-through */
382 case REGKIND_REGISTER
:
383 /* FIXME: Help path? */
384 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szFile
, NULL
)))
386 IUnknown_Release(*pptLib
);
394 TRACE(" returns %08lx\n",res
);
398 /******************************************************************************
399 * LoadRegTypeLib [OLEAUT32.162]
401 HRESULT WINAPI
LoadRegTypeLib(
402 REFGUID rguid
, /* [in] referenced guid */
403 WORD wVerMajor
, /* [in] major version */
404 WORD wVerMinor
, /* [in] minor version */
405 LCID lcid
, /* [in] locale id */
406 ITypeLib
**ppTLib
) /* [out] path of typelib */
409 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
413 res
= LoadTypeLib(bstr
, ppTLib
);
417 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
423 /******************************************************************************
424 * RegisterTypeLib [OLEAUT32.163]
425 * Adds information about a type library to the System Registry
427 * Docs: ITypeLib FAR * ptlib
428 * Docs: OLECHAR FAR* szFullPath
429 * Docs: OLECHAR FAR* szHelpDir
435 HRESULT WINAPI
RegisterTypeLib(
436 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
437 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
438 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
449 static const char *PSOA
= "{00020424-0000-0000-C000-000000000046}";
451 if (ptlib
== NULL
|| szFullPath
== NULL
)
454 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
457 StringFromGUID2(&attr
->guid
, guid
, 80);
458 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
459 snprintf(keyName
, sizeof(keyName
), "TypeLib\\%s\\%x.%x",
460 guidA
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
461 HeapFree(GetProcessHeap(), 0, guidA
);
464 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
465 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
469 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
471 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
472 (BYTE
*)doc
, lstrlenW(doc
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
480 /* FIXME: This *seems* to be 0 always, not sure though */
481 if (res
== S_OK
&& RegCreateKeyExA(key
, "0\\win32", 0, NULL
, 0,
482 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
484 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
485 (BYTE
*)szFullPath
, lstrlenW(szFullPath
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
493 if (res
== S_OK
&& RegCreateKeyExA(key
, "FLAGS", 0, NULL
, 0,
494 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
497 /* FIXME: is %u correct? */
498 snprintf(buf
, sizeof(buf
), "%u", attr
->wLibFlags
);
499 if (RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
500 buf
, lstrlenA(buf
) + 1) != ERROR_SUCCESS
)
508 /* register OLE Automation-compatible interfaces for this typelib */
509 types
= ITypeLib_GetTypeInfoCount(ptlib
);
510 for (tidx
=0; tidx
<types
; tidx
++) {
511 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
512 LPOLESTR name
= NULL
;
513 ITypeInfo
*tinfo
= NULL
;
515 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
517 case TKIND_INTERFACE
:
518 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
519 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
522 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
523 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
526 TRACE_(typelib
)("%d: coclass %s\n", tidx
, debugstr_w(name
));
527 /* coclasses should probably not be registered? */
530 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
534 TYPEATTR
*tattr
= NULL
;
535 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
537 TRACE_(typelib
)("guid=%s, flags=%04x (",
538 debugstr_guid(&tattr
->guid
),
540 if (TRACE_ON(typelib
)) {
541 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
561 * FIXME: The 1 is just here until we implement rpcrt4
562 * stub/proxy handling. Until then it helps IShield
565 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
567 /* register interface<->typelib coupling */
568 StringFromGUID2(&tattr
->guid
, guid
, 80);
569 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
570 snprintf(keyName
, sizeof(keyName
), "Interface\\%s", guidA
);
571 HeapFree(GetProcessHeap(), 0, guidA
);
573 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
574 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
576 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
577 (BYTE
*)name
, lstrlenW(name
) * sizeof(OLECHAR
));
579 if (RegCreateKeyExA(key
, "ProxyStubClsid", 0, NULL
, 0,
580 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
581 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
585 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
586 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
587 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
592 if (RegCreateKeyExA(key
, "TypeLib", 0, NULL
, 0,
593 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
595 StringFromGUID2(&attr
->guid
, guid
, 80);
596 snprintf(ver
, sizeof(ver
), "%x.%x",
597 attr
->wMajorVerNum
, attr
->wMinorVerNum
);
598 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
599 (BYTE
*)guid
, lstrlenW(guid
) * sizeof(OLECHAR
));
600 RegSetValueExA(subKey
, "Version", 0, REG_SZ
,
607 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
609 ITypeInfo_Release(tinfo
);
616 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
622 /******************************************************************************
623 * UnRegisterTypeLib [OLEAUT32.186]
624 * Removes information about a type library from the System Registry
631 HRESULT WINAPI
UnRegisterTypeLib(
632 REFGUID libid
, /* [in] Guid of the library */
633 WORD wVerMajor
, /* [in] major version */
634 WORD wVerMinor
, /* [in] minor version */
635 LCID lcid
, /* [in] locale id */
638 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
639 return S_OK
; /* FIXME: pretend everything is OK */
642 /****************************************************************************
643 * OaBuildVersion (TYPELIB.15)
645 * known TYPELIB.DLL versions:
647 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
648 * OLE 2.02 1993-94 02 3002
651 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
652 * OLE 2.1 NT 1993-95 ?? ???
653 * OLE 2.3.1 W95 23 700
654 * OLE2 4.0 NT4SP6 1993-98 40 4277
656 DWORD WINAPI
OaBuildVersion16(void)
658 /* FIXME: I'd like to return the highest currently known version value
659 * in case the user didn't force a --winver, but I don't know how
660 * to retrieve the "versionForced" info from misc/version.c :(
661 * (this would be useful in other places, too) */
662 FIXME("If you get version error messages, please report them\n");
663 switch(GetVersion() & 0x8000ffff) /* mask off build number */
665 case 0x80000a03: /* WIN31 */
666 return MAKELONG(3027, 3); /* WfW 3.11 */
667 case 0x80000004: /* WIN95 */
668 return MAKELONG(700, 23); /* Win95A */
669 case 0x80000a04: /* WIN98 */
670 return MAKELONG(3024, 10); /* W98 SE */
671 case 0x00000004: /* NT4 */
672 return MAKELONG(4277, 40); /* NT4 SP6 */
674 FIXME("Version value not known yet. Please investigate it!\n");
679 /* for better debugging info leave the static out for the time being */
682 /*======================= ITypeLib implementation =======================*/
684 typedef struct tagTLBCustData
688 struct tagTLBCustData
* next
;
691 /* data structure for import typelibs */
692 typedef struct tagTLBImpLib
694 int offset
; /* offset in the file (MSFT)
695 offset in nametable (SLTG)
696 just used to identify library while reading
698 GUID guid
; /* libid */
699 BSTR name
; /* name */
701 LCID lcid
; /* lcid of imported typelib */
703 WORD wVersionMajor
; /* major version number */
704 WORD wVersionMinor
; /* minor version number */
706 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
707 NULL if not yet loaded */
708 struct tagTLBImpLib
* next
;
711 /* internal ITypeLib data */
712 typedef struct tagITypeLibImpl
714 ICOM_VFIELD(ITypeLib2
);
716 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
718 /* strings can be stored in tlb as multibyte strings BUT they are *always*
719 * exported to the application as a UNICODE string.
725 unsigned long dwHelpContext
;
726 int TypeInfoCount
; /* nr of typeinfo's in librarry */
727 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
728 int ctCustData
; /* number of items in cust data list */
729 TLBCustData
* pCustData
; /* linked list to cust data */
730 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
731 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
732 libary. Only used while read MSFT
736 static struct ICOM_VTABLE(ITypeLib2
) tlbvt
;
738 /* ITypeLib methods */
739 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
740 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
742 /*======================= ITypeInfo implementation =======================*/
744 /* data for refernced types */
745 typedef struct tagTLBRefType
747 INT index
; /* Type index for internal ref or for external ref
748 it the format is SLTG. -2 indicates to
751 GUID guid
; /* guid of the referenced type */
752 /* if index == TLB_REF_USE_GUID */
754 HREFTYPE reference
; /* The href of this ref */
755 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
756 TLB_REF_INTERNAL for internal refs
757 TLB_REF_NOT_FOUND for broken refs */
759 struct tagTLBRefType
* next
;
762 #define TLB_REF_USE_GUID -2
764 #define TLB_REF_INTERNAL (void*)-2
765 #define TLB_REF_NOT_FOUND (void*)-1
767 /* internal Parameter data */
768 typedef struct tagTLBParDesc
772 TLBCustData
* pCustData
; /* linked list to cust data */
775 /* internal Function data */
776 typedef struct tagTLBFuncDesc
778 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
779 BSTR Name
; /* the name of this function */
780 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
782 int HelpStringContext
;
784 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
786 TLBCustData
* pCustData
; /* linked list to cust data; */
787 struct tagTLBFuncDesc
* next
;
790 /* internal Variable data */
791 typedef struct tagTLBVarDesc
793 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
794 BSTR Name
; /* the name of this variable */
796 int HelpStringContext
; /* FIXME: where? */
799 TLBCustData
* pCustData
;/* linked list to cust data; */
800 struct tagTLBVarDesc
* next
;
803 /* internal implemented interface data */
804 typedef struct tagTLBImplType
806 HREFTYPE hRef
; /* hRef of interface */
807 int implflags
; /* IMPLFLAG_*s */
809 TLBCustData
* pCustData
;/* linked list to custom data; */
810 struct tagTLBImplType
*next
;
813 /* internal TypeInfo data */
814 typedef struct tagITypeInfoImpl
816 ICOM_VFIELD(ITypeInfo2
);
818 TYPEATTR TypeAttr
; /* _lots_ of type information. */
819 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
820 int index
; /* index in this typelib; */
821 /* type libs seem to store the doc strings in ascii
822 * so why should we do it in unicode?
826 unsigned long dwHelpContext
;
827 unsigned long dwHelpStringContext
;
830 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
833 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
835 /* Implemented Interfaces */
836 TLBImplType
* impltypelist
;
838 TLBRefType
* reflist
;
840 TLBCustData
* pCustData
; /* linked list to cust data; */
841 struct tagITypeInfoImpl
* next
;
844 static struct ICOM_VTABLE(ITypeInfo2
) tinfvt
;
846 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor();
848 typedef struct tagTLBContext
850 unsigned int oStart
; /* start of TLB in file */
851 unsigned int pos
; /* current pos */
852 unsigned int length
; /* total length */
853 void *mapping
; /* memory mapping */
854 MSFT_SegDir
* pTblDir
;
855 ITypeLibImpl
* pLibInfo
;
859 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
864 static void dump_VarType(VARTYPE vt
,char *szVarType
) {
865 /* FIXME : we could have better trace here, depending on the VARTYPE
868 if (vt
& VT_RESERVED
)
869 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
871 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
873 szVarType
+= strlen(strcpy(szVarType
, "array of "));
875 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
876 switch(vt
& VT_TYPEMASK
) {
877 case VT_UI1
: sprintf(szVarType
, "VT_UI"); break;
878 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
879 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
880 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
881 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
882 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
883 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
884 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
885 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
886 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
887 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
888 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
889 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
890 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
891 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
892 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
893 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
894 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
895 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
896 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED\n"); break;
897 default: sprintf(szVarType
, "unknown(%d)", vt
& VT_TYPEMASK
); break;
901 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
902 if (pTD
->vt
& VT_RESERVED
)
903 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
904 if (pTD
->vt
& VT_BYREF
)
905 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
906 if (pTD
->vt
& VT_ARRAY
)
907 szVarType
+= strlen(strcpy(szVarType
, "array of "));
908 if (pTD
->vt
& VT_VECTOR
)
909 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
910 switch(pTD
->vt
& VT_TYPEMASK
) {
911 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
912 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
913 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
914 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
915 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
916 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
917 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
918 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
919 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
920 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
921 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
922 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
923 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
924 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
925 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
926 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
927 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
928 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
929 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
930 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
931 pTD
->u
.hreftype
); break;
932 case VT_PTR
: sprintf(szVarType
, "ptr to ");
933 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
935 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
936 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
938 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
939 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
940 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
943 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
947 void dump_ELEMDESC(ELEMDESC
*edesc
) {
949 dump_TypeDesc(&edesc
->tdesc
,buf
);
950 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
951 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
952 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
954 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
956 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
957 for (i
=0;i
<funcdesc
->cParams
;i
++) {
958 MESSAGE("Param %d:\n",i
);
959 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
961 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
962 switch (funcdesc
->funckind
) {
963 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
964 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
965 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
966 case FUNC_STATIC
: MESSAGE("static");break;
967 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
968 default: MESSAGE("unknown");break;
970 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
971 switch (funcdesc
->invkind
) {
972 case INVOKE_FUNC
: MESSAGE("func");break;
973 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
974 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
975 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
977 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
978 switch (funcdesc
->callconv
) {
979 case CC_CDECL
: MESSAGE("cdecl");break;
980 case CC_PASCAL
: MESSAGE("pascal");break;
981 case CC_STDCALL
: MESSAGE("stdcall");break;
982 case CC_SYSCALL
: MESSAGE("syscall");break;
985 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
986 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
987 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
990 void dump_IDLDESC(IDLDESC
*idl
) {
991 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
994 static char * typekind_desc
[] =
1007 void dump_TYPEATTR(TYPEATTR
*tattr
) {
1009 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
1010 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
1011 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
1012 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
1013 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
1014 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
1015 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
1016 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
1017 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
1018 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
1019 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
1020 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
1021 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
1022 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
1023 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
1024 MESSAGE("\ttypedesc: %s\n", buf
);
1025 dump_IDLDESC(&tattr
->idldescType
);
1028 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1031 if (!TRACE_ON(typelib
))
1033 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1034 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1035 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1038 dump_FUNCDESC(&(pfd
->funcdesc
));
1040 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1041 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1043 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1047 dump_TLBFuncDescOne(pfd
);
1051 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1055 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1060 static void dump_TLBImpLib(TLBImpLib
*import
)
1062 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1063 debugstr_w(import
->name
));
1064 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1065 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1068 static void dump_TLBRefType(TLBRefType
* prt
)
1072 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1073 if(prt
->index
== -1)
1074 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1076 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1078 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1079 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1080 TRACE_(typelib
)("in lib\n");
1081 dump_TLBImpLib(prt
->pImpTLInfo
);
1087 static void dump_TLBImplType(TLBImplType
* impl
)
1091 "implementing/inheriting interface hRef = %lx implflags %x\n",
1092 impl
->hRef
, impl
->implflags
);
1097 void dump_Variant(VARIANT
* pvar
)
1102 TRACE("(%p)\n", pvar
);
1106 ZeroMemory(szVarType
, sizeof(szVarType
));
1108 /* FIXME : we could have better trace here, depending on the VARTYPE
1111 dump_VarType(V_VT(pvar
),szVarType
);
1113 TRACE("VARTYPE: %s\n", szVarType
);
1115 if (V_VT(pvar
) & VT_BYREF
) {
1116 ref
= V_UNION(pvar
, byref
);
1119 else ref
= &V_UNION(pvar
, cVal
);
1121 if (V_VT(pvar
) & VT_ARRAY
) {
1125 if (V_VT(pvar
) & VT_VECTOR
) {
1130 switch (V_VT(pvar
) & VT_TYPEMASK
)
1133 TRACE("%d\n", *(short*)ref
);
1137 TRACE("%d\n", *(INT
*)ref
);
1141 TRACE("%3.3e\n", *(float*)ref
);
1145 TRACE("%3.3e\n", *(double*)ref
);
1149 TRACE("%s\n", *(VARIANT_BOOL
*)ref
? "TRUE" : "FALSE");
1153 TRACE("%s\n", debugstr_w(*(BSTR
*)ref
));
1158 TRACE("%p\n", *(LPVOID
*)ref
);
1162 if (V_VT(pvar
) & VT_BYREF
) dump_Variant(ref
);
1168 memset( &TM
, 0, sizeof(TM
) );
1170 if( DateToTm( *(DATE
*)ref
, 0, &TM
) == FALSE
) {
1171 TRACE("invalid date? (?)%ld %f\n", *(long*)ref
, *(double *)ref
);
1173 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1174 TM
.tm_year
, TM
.tm_mon
+1, TM
.tm_mday
,
1175 TM
.tm_hour
, TM
.tm_min
, TM
.tm_sec
, *(double *)ref
);
1181 TRACE("%ld (hi), %lu (lo)\n", ((CY
*)ref
)->s
.Hi
, ((CY
*)ref
)->s
.Lo
);
1186 TRACE("(?)%ld\n", *(long*)ref
);
1191 static void dump_DispParms(DISPPARAMS
* pdp
)
1195 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1197 while (index
< pdp
->cArgs
)
1199 dump_Variant( &pdp
->rgvarg
[index
] );
1204 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1206 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1207 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1208 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1209 TRACE("fct:%u var:%u impl:%u\n",
1210 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1211 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1212 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1213 dump_TLBFuncDesc(pty
->funclist
);
1214 dump_TLBVarDesc(pty
->varlist
);
1215 dump_TLBImplType(pty
->impltypelist
);
1218 void dump_VARDESC(VARDESC
*v
)
1220 MESSAGE("memid %ld\n",v
->memid
);
1221 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1222 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1223 dump_ELEMDESC(&(v
->elemdescVar
));
1224 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1225 MESSAGE("varkind %d\n",v
->varkind
);
1228 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1230 /* VT_LPWSTR is largest type that */
1231 /* may appear in type description*/
1232 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1233 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1234 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1235 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1236 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1237 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1241 static void TLB_abort()
1245 static void * TLB_Alloc(unsigned size
)
1248 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1250 ERR("cannot allocate memory\n");
1255 static void TLB_Free(void * ptr
)
1257 HeapFree(GetProcessHeap(), 0, ptr
);
1261 /**********************************************************************
1263 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1266 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1268 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1269 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1271 if (where
!= DO_NOT_SEEK
)
1273 where
+= pcx
->oStart
;
1274 if (where
> pcx
->length
)
1277 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1282 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1283 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1288 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1293 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1294 FromLEDWords(buffer
, ret
);
1299 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1304 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1305 FromLEWords(buffer
, ret
);
1310 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1312 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1313 memset(pGuid
,0, sizeof(GUID
));
1316 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1317 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1318 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1319 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1320 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1323 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1326 MSFT_NameIntro niName
;
1328 WCHAR
* pwstring
= NULL
;
1329 BSTR bstrName
= NULL
;
1331 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1332 pcx
->pTblDir
->pNametab
.offset
+offset
);
1333 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1334 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1335 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1336 name
[niName
.namelen
& 0xff]='\0';
1338 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1341 /* no invalid characters in string */
1344 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1346 /* don't check for invalid character since this has been done previously */
1347 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1349 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1350 lengthInChars
= SysStringLen(bstrName
);
1351 HeapFree(GetProcessHeap(), 0, pwstring
);
1354 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1358 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1365 if(offset
<0) return NULL
;
1366 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1367 if(length
<= 0) return 0;
1368 string
=TLB_Alloc(length
+1);
1369 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1370 string
[length
]='\0';
1372 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1373 string
, -1, NULL
, 0);
1375 /* no invalid characters in string */
1378 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1380 /* don't check for invalid character since this has been done previously */
1381 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1383 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1384 lengthInChars
= SysStringLen(bstr
);
1385 HeapFree(GetProcessHeap(), 0, pwstring
);
1388 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1392 * read a value and fill a VARIANT structure
1394 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1398 TRACE_(typelib
)("\n");
1400 if(offset
<0) { /* data are packed in here */
1401 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1402 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1405 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1406 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1407 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1408 switch (V_VT(pVar
)){
1409 case VT_EMPTY
: /* FIXME: is this right? */
1410 case VT_NULL
: /* FIXME: is this right? */
1411 case VT_I2
: /* this should not happen */
1422 case VT_VOID
: /* FIXME: is this right? */
1430 case VT_DECIMAL
: /* FIXME: is this right? */
1433 /* pointer types with known behaviour */
1436 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1438 FIXME("BSTR length = %d?\n", size
);
1440 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1441 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1442 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1443 /* FIXME: do we need a AtoW conversion here? */
1444 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1445 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1450 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1457 case VT_USERDEFINED
:
1463 case VT_STREAMED_OBJECT
:
1464 case VT_STORED_OBJECT
:
1465 case VT_BLOB_OBJECT
:
1470 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1474 if(size
>0) /* (big|small) endian correct? */
1475 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1479 * create a linked list with custom data
1481 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1487 TRACE_(typelib
)("\n");
1491 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1492 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1493 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1494 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1495 /* add new custom data at head of the list */
1496 pNew
->next
=*ppCustData
;
1498 offset
= entry
.next
;
1503 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1507 pTd
->vt
=type
& VT_TYPEMASK
;
1509 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1511 if(pTd
->vt
== VT_USERDEFINED
)
1512 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1514 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1518 MSFT_DoFuncs(TLBContext
* pcx
,
1523 TLBFuncDesc
** pptfd
)
1526 * member information is stored in a data structure at offset
1527 * indicated by the memoffset field of the typeinfo structure
1528 * There are several distinctive parts.
1529 * the first part starts with a field that holds the total length
1530 * of this (first) part excluding this field. Then follow the records,
1531 * for each member there is one record.
1533 * First entry is always the length of the record (excluding this
1535 * Rest of the record depends on the type of the member. If there is
1536 * a field indicating the member type (function variable intereface etc)
1537 * I have not found it yet. At this time we depend on the information
1538 * in the type info and the usual order how things are stored.
1540 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1543 * Third is a equal sized array with file offsets to the name entry
1546 * Forth and last (?) part is an array with offsets to the records in the
1547 * first part of this file segment.
1550 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1551 int recoffset
= offset
+ sizeof(INT
);
1554 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1556 TRACE_(typelib
)("\n");
1558 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1560 for ( i
= 0; i
< cFuncs
; i
++ )
1562 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1564 /* name, eventually add to a hash table */
1565 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1566 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1568 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1570 /* read the function information record */
1571 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1575 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1577 /* do the attributes */
1578 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1581 if ( nrattributes
> 0 )
1583 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1585 if ( nrattributes
> 1 )
1587 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1588 pFuncRec
->OptAttr
[1]) ;
1590 if ( nrattributes
> 2 )
1592 if ( pFuncRec
->FKCCIC
& 0x2000 )
1594 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1598 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1599 pFuncRec
->OptAttr
[2]);
1601 if( nrattributes
> 5 )
1603 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1605 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1608 pFuncRec
->OptAttr
[6],
1609 &(*pptfd
)->pCustData
);
1616 /* fill the FuncDesc Structure */
1617 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1618 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1620 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1621 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1622 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1623 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1624 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1625 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1626 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1630 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1633 /* do the parameters/arguments */
1634 if(pFuncRec
->nrargs
)
1637 MSFT_ParameterInfo paraminfo
;
1639 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1640 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1642 (*pptfd
)->pParamDesc
=
1643 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1645 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1646 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1648 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1650 TYPEDESC
* lpArgTypeDesc
= 0;
1654 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1657 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1659 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1661 /* SEEK value = jump to offset,
1662 * from there jump to the end of record,
1663 * go back by (j-1) arguments
1665 MSFT_ReadLEDWords( ¶minfo
,
1666 sizeof(MSFT_ParameterInfo
), pcx
,
1667 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1668 * sizeof(MSFT_ParameterInfo
)));
1670 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1672 while ( lpArgTypeDesc
!= NULL
)
1674 switch ( lpArgTypeDesc
->vt
)
1677 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1681 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1684 case VT_USERDEFINED
:
1685 MSFT_DoRefType(pcx
, pTI
,
1686 lpArgTypeDesc
->u
.hreftype
);
1688 lpArgTypeDesc
= NULL
;
1692 lpArgTypeDesc
= NULL
;
1698 /* parameter is the return value! */
1699 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1701 TYPEDESC
* lpArgTypeDesc
;
1703 (*pptfd
)->funcdesc
.elemdescFunc
=
1704 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1706 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1708 while ( lpArgTypeDesc
!= NULL
)
1710 switch ( lpArgTypeDesc
->vt
)
1713 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1717 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1721 case VT_USERDEFINED
:
1724 lpArgTypeDesc
->u
.hreftype
);
1726 lpArgTypeDesc
= NULL
;
1730 lpArgTypeDesc
= NULL
;
1735 /* second time around */
1736 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1739 (*pptfd
)->pParamDesc
[j
].Name
=
1740 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1743 if ( (PARAMFLAG_FHASDEFAULT
&
1744 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1745 ((pFuncRec
->FKCCIC
) & 0x1000) )
1747 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1749 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1751 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1753 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1754 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1756 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1760 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1763 pFuncRec
->OptAttr
[7+j
],
1764 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1769 /* scode is not used: archaic win16 stuff FIXME: right? */
1770 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1771 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1773 pptfd
= & ((*pptfd
)->next
);
1774 recoffset
+= reclength
;
1777 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1778 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1780 int infolen
, nameoffset
, reclength
;
1782 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1786 TRACE_(typelib
)("\n");
1788 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1789 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1790 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1791 recoffset
+= offset
+sizeof(INT
);
1792 for(i
=0;i
<cVars
;i
++){
1793 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1794 /* name, eventually add to a hash table */
1795 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1796 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1797 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1798 /* read the variable information record */
1799 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1801 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1803 if(reclength
>(6*sizeof(INT
)) )
1804 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1805 if(reclength
>(7*sizeof(INT
)) )
1806 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1807 if(reclength
>(8*sizeof(INT
)) )
1808 if(reclength
>(9*sizeof(INT
)) )
1809 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1810 /* fill the VarDesc Structure */
1811 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1812 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1813 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1814 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1815 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1816 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1817 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1818 if(pVarRec
->VarKind
== VAR_CONST
){
1819 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1820 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1821 pVarRec
->OffsValue
, pcx
);
1823 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1824 pptvd
=&((*pptvd
)->next
);
1825 recoffset
+= reclength
;
1828 /* fill in data for a hreftype (offset). When the refernced type is contained
1829 * in the typelib, it's just an (file) offset in the type info base dir.
1830 * If comes from import, it's an offset+1 in the ImpInfo table
1832 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1836 TLBRefType
**ppRefType
= &pTI
->reflist
;
1838 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1841 if((*ppRefType
)->reference
== offset
)
1843 ppRefType
= &(*ppRefType
)->next
;
1846 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1847 sizeof(**ppRefType
));
1849 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1850 /* external typelib */
1851 MSFT_ImpInfo impinfo
;
1852 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1854 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1856 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1857 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1858 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1859 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1860 pImpLib
=pImpLib
->next
;
1863 (*ppRefType
)->reference
=offset
;
1864 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1865 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1866 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1868 ERR("Cannot find a reference\n");
1869 (*ppRefType
)->reference
=-1;
1870 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1873 /* in this typelib */
1874 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1875 (*ppRefType
)->reference
=offset
;
1876 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1880 /* process Implemented Interfaces of a com class */
1881 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1885 MSFT_RefRecord refrec
;
1886 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1888 TRACE_(typelib
)("\n");
1890 for(i
=0;i
<count
;i
++){
1891 if(offset
<0) break; /* paranoia */
1892 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1893 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1894 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1895 (*ppImpl
)->hRef
= refrec
.reftype
;
1896 (*ppImpl
)->implflags
=refrec
.flags
;
1897 (*ppImpl
)->ctCustData
=
1898 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1899 offset
=refrec
.onext
;
1900 ppImpl
=&((*ppImpl
)->next
);
1904 * process a typeinfo record
1906 ITypeInfoImpl
* MSFT_DoTypeInfo(
1909 ITypeLibImpl
* pLibInfo
)
1911 MSFT_TypeInfoBase tiBase
;
1912 ITypeInfoImpl
*ptiRet
;
1914 TRACE_(typelib
)("count=%u\n", count
);
1916 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1917 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
1918 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1919 /* this is where we are coming from */
1920 ptiRet
->pTypeLib
= pLibInfo
;
1921 ITypeLib2_AddRef((ITypeLib2
*)pLibInfo
);
1922 ptiRet
->index
=count
;
1923 /* fill in the typeattr fields */
1924 FIXME("Assign constructor/destructor memid\n");
1926 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
1927 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
1928 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
1929 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
1930 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
1931 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
1932 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
1933 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
1934 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
1935 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
1936 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
1937 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
1938 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
1939 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
1940 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
1941 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
1942 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
1943 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
1946 /* IDLDESC idldescType; *//* never saw this one != zero */
1948 /* name, eventually add to a hash table */
1949 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
1950 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
1952 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
1953 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
1954 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
1955 /* note: InfoType's Help file and HelpStringDll come from the containing
1956 * library. Further HelpString and Docstring appear to be the same thing :(
1959 if(ptiRet
->TypeAttr
.cFuncs
>0 )
1960 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1961 ptiRet
->TypeAttr
.cVars
,
1962 tiBase
.memoffset
, & ptiRet
->funclist
);
1964 if(ptiRet
->TypeAttr
.cVars
>0 )
1965 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1966 ptiRet
->TypeAttr
.cVars
,
1967 tiBase
.memoffset
, & ptiRet
->varlist
);
1968 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
1969 switch(ptiRet
->TypeAttr
.typekind
)
1972 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
1975 case TKIND_DISPATCH
:
1976 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1978 if (tiBase
.datatype1
!= -1)
1980 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1981 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1984 { /* FIXME: This is a really bad hack to add IDispatch */
1985 char* szStdOle
= "stdole2.tlb\0";
1986 int nStdOleLen
= strlen(szStdOle
);
1987 TLBRefType
**ppRef
= &ptiRet
->reflist
;
1990 if((*ppRef
)->reference
== -1)
1992 ppRef
= &(*ppRef
)->next
;
1995 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
1996 (*ppRef
)->guid
= IID_IDispatch
;
1997 (*ppRef
)->reference
= -1;
1998 (*ppRef
)->index
= TLB_REF_USE_GUID
;
1999 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2000 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2001 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2004 MultiByteToWideChar(CP_ACP
,
2008 (*ppRef
)->pImpTLInfo
->name
,
2009 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2011 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2012 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2013 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2018 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2019 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2020 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2025 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2027 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2028 debugstr_w(ptiRet
->Name
),
2029 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2030 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2035 /****************************************************************************
2038 * find the type of the typelib file and map the typelib resource into
2041 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2042 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2043 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2045 int ret
= TYPE_E_CANTLOADLIBRARY
;
2046 DWORD dwSignature
= 0;
2049 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2053 /* check the signature of the file */
2054 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2055 if (INVALID_HANDLE_VALUE
!= hFile
)
2057 HANDLE hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2060 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2063 /* retrieve file size */
2064 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2066 /* first try to load as *.tlb */
2067 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2068 if ( dwSignature
== MSFT_SIGNATURE
)
2070 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2072 else if ( dwSignature
== SLTG_SIGNATURE
)
2074 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2076 UnmapViewOfFile(pBase
);
2078 CloseHandle(hMapping
);
2083 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
2085 /* find the typelibrary resource*/
2086 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2087 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2090 HRSRC hrsrc
= FindResourceA(hinstDLL
, MAKEINTRESOURCEA(index
),
2094 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2097 LPVOID pBase
= LockResource(hGlobal
);
2098 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2102 /* try to load as incore resource */
2103 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2104 if ( dwSignature
== MSFT_SIGNATURE
)
2106 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2108 else if ( dwSignature
== SLTG_SIGNATURE
)
2110 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2114 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2117 FreeResource( hGlobal
);
2120 FreeLibrary(hinstDLL
);
2127 ERR("Loading of typelib %s failed with error %ld\n",
2128 debugstr_w(pszFileName
), GetLastError());
2133 /*================== ITypeLib(2) Methods ===================================*/
2135 /****************************************************************************
2136 * ITypeLib2_Constructor_MSFT
2138 * loading an MSFT typelib from an in-memory image
2140 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2144 MSFT_Header tlbHeader
;
2145 MSFT_SegDir tlbSegDir
;
2146 ITypeLibImpl
* pTypeLibImpl
;
2148 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2150 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2151 if (!pTypeLibImpl
) return NULL
;
2153 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
2154 pTypeLibImpl
->ref
= 1;
2156 /* get pointer to beginning of typelib data */
2160 cx
.pLibInfo
= pTypeLibImpl
;
2161 cx
.length
= dwTLBLength
;
2164 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2166 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2167 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2168 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2171 /* there is a small amount of information here until the next important
2173 * the segment directory . Try to calculate the amount of data */
2174 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2176 /* now read the segment directory */
2177 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2178 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2179 cx
.pTblDir
= &tlbSegDir
;
2181 /* just check two entries */
2182 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2184 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2185 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2189 /* now fill our internal data */
2190 /* TLIBATTR fields */
2191 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2193 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2194 /* Windows seems to have zero here, is this correct? */
2195 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2196 pTypeLibImpl
->LibAttr
.lcid
= PRIMARYLANGID(tlbHeader
.lcid
);
2198 pTypeLibImpl
->LibAttr
.lcid
= 0;
2200 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2201 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2202 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2203 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2205 /* name, eventually add to a hash table */
2206 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2209 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2210 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2212 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2215 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2216 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2219 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2222 if(tlbHeader
.CustomDataOffset
>= 0)
2224 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2227 /* fill in typedescriptions */
2228 if(tlbSegDir
.pTypdescTab
.length
> 0)
2230 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2232 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2233 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2236 /* FIXME: add several sanity checks here */
2237 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2238 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2240 /* FIXME: check safearray */
2242 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2244 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2246 else if(td
[0] == VT_CARRAY
)
2248 /* array descr table here */
2249 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2251 else if(td
[0] == VT_USERDEFINED
)
2253 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2255 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2258 /* second time around to fill the array subscript info */
2261 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2262 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2264 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2265 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2268 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2270 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2272 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2274 for(j
= 0; j
<td
[2]; j
++)
2276 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2277 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2278 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2279 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2284 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2285 ERR("didn't find array description data\n");
2290 /* imported type libs */
2291 if(tlbSegDir
.pImpFiles
.offset
>0)
2293 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2294 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2297 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2299 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2300 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2301 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2303 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2304 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2305 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2306 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2309 (*ppImpLib
)->name
= TLB_Alloc(size
+1);
2310 MSFT_Read((*ppImpLib
)->name
, size
, &cx
, DO_NOT_SEEK
);
2311 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2312 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & 0xfffffffc;
2314 ppImpLib
= &(*ppImpLib
)->next
;
2319 if(tlbHeader
.nrtypeinfos
>= 0 )
2321 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2322 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2325 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2327 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2329 ITypeInfo_AddRef((ITypeInfo
*) *ppTI
);
2330 ppTI
= &((*ppTI
)->next
);
2331 (pTypeLibImpl
->TypeInfoCount
)++;
2335 TRACE("(%p)\n", pTypeLibImpl
);
2336 return (ITypeLib2
*) pTypeLibImpl
;
2340 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2346 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2347 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2348 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2349 ret
= SysAllocString(nameW
);
2350 HeapFree(GetProcessHeap(), 0, nameW
);
2354 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2360 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2361 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2365 guid
->Data4
[0] = s
>> 8;
2366 guid
->Data4
[1] = s
& 0xff;
2369 for(i
= 0; i
< 6; i
++) {
2370 memcpy(b
, str
+ 24 + 2 * i
, 2);
2371 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2376 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2383 bytelen
= *(WORD
*)ptr
;
2384 if(bytelen
== 0xffff) return 2;
2385 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2386 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2387 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2388 *pBstr
= SysAllocStringLen(nameW
, len
);
2389 HeapFree(GetProcessHeap(), 0, nameW
);
2393 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2398 bytelen
= *(WORD
*)ptr
;
2399 if(bytelen
== 0xffff) return 2;
2400 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2401 memcpy(*str
, ptr
+ 2, bytelen
);
2402 (*str
)[bytelen
] = '\0';
2406 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2408 char *ptr
= pLibBlk
;
2411 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2412 FIXME("libblk magic = %04x\n", w
);
2417 if((w
= *(WORD
*)ptr
) != 0xffff) {
2418 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2423 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2425 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2427 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2430 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2433 pTypeLibImpl
->LibAttr
.lcid
= *(WORD
*)ptr
;
2436 ptr
+= 4; /* skip res12 */
2438 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2441 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2444 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2447 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2448 ptr
+= sizeof(GUID
);
2450 return ptr
- (char*)pLibBlk
;
2453 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2456 TYPEDESC
*pTD
= &pElem
->tdesc
;
2458 /* Handle [in/out] first */
2459 if((*pType
& 0xc000) == 0xc000)
2460 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2461 else if(*pType
& 0x8000)
2462 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2463 else if(*pType
& 0x4000)
2464 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2466 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2469 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2472 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2475 if((*pType
& 0xe00) == 0xe00) {
2477 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2479 pTD
= pTD
->u
.lptdesc
;
2481 switch(*pType
& 0x7f) {
2484 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2486 pTD
= pTD
->u
.lptdesc
;
2489 case VT_USERDEFINED
:
2490 pTD
->vt
= VT_USERDEFINED
;
2491 pTD
->u
.hreftype
= *(++pType
) / 4;
2497 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2500 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2502 pTD
->vt
= VT_CARRAY
;
2503 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2505 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2506 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2507 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2508 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2510 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2516 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2520 pTD
->vt
= VT_SAFEARRAY
;
2521 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2523 pTD
= pTD
->u
.lptdesc
;
2527 pTD
->vt
= *pType
& 0x7f;
2537 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2542 TLBRefType
**ppRefType
;
2544 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2545 FIXME("Ref magic = %x\n", pRef
->magic
);
2548 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2550 ppRefType
= &pTI
->reflist
;
2551 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2553 unsigned int lib_offs
, type_num
;
2555 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2556 sizeof(**ppRefType
));
2558 name
+= SLTG_ReadStringA(name
, &refname
);
2559 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2560 FIXME("Can't sscanf ref\n");
2561 if(lib_offs
!= 0xffff) {
2562 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2565 if((*import
)->offset
== lib_offs
)
2567 import
= &(*import
)->next
;
2570 char fname
[MAX_PATH
+1];
2573 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2575 (*import
)->offset
= lib_offs
;
2576 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2578 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2579 &(*import
)->wVersionMajor
,
2580 &(*import
)->wVersionMinor
,
2581 &(*import
)->lcid
, fname
) != 4) {
2582 FIXME("can't sscanf ref %s\n",
2583 pNameTable
+ lib_offs
+ 40);
2585 len
= strlen(fname
);
2586 if(fname
[len
-1] != '#')
2587 FIXME("fname = %s\n", fname
);
2588 fname
[len
-1] = '\0';
2589 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2591 (*ppRefType
)->pImpTLInfo
= *import
;
2592 } else { /* internal ref */
2593 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2595 (*ppRefType
)->reference
= ref
;
2596 (*ppRefType
)->index
= type_num
;
2598 HeapFree(GetProcessHeap(), 0, refname
);
2599 ppRefType
= &(*ppRefType
)->next
;
2601 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2602 FIXME("End of ref block magic = %x\n", *name
);
2603 dump_TLBRefType(pTI
->reflist
);
2606 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2609 SLTG_ImplInfo
*info
;
2610 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2611 /* I don't really get this structure, usually it's 0x16 bytes
2612 long, but iuser.tlb contains some that are 0x18 bytes long.
2613 That's ok because we can use the next ptr to jump to the next
2614 one. But how do we know the length of the last one? The WORD
2615 at offs 0x8 might be the clue. For now I'm just assuming that
2616 the last one is the regular 0x16 bytes. */
2618 info
= (SLTG_ImplInfo
*)pBlk
;
2620 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2621 sizeof(**ppImplType
));
2622 (*ppImplType
)->hRef
= info
->ref
;
2623 (*ppImplType
)->implflags
= info
->impltypeflags
;
2624 pTI
->TypeAttr
.cImplTypes
++;
2625 ppImplType
= &(*ppImplType
)->next
;
2627 if(info
->next
== 0xffff)
2630 FIXME("Interface inheriting more than one interface\n");
2631 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2633 info
++; /* see comment at top of function */
2637 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2640 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2641 SLTG_MemberHeader
*pMemHeader
;
2642 char *pFirstItem
, *pNextItem
;
2644 if(pTIHeader
->href_table
!= 0xffffffff) {
2645 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2650 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2652 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2654 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2655 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2658 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2662 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2665 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2666 SLTG_MemberHeader
*pMemHeader
;
2667 SLTG_Function
*pFunc
;
2668 char *pFirstItem
, *pNextItem
;
2669 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2672 if(pTIHeader
->href_table
!= 0xffffffff) {
2673 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2677 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2679 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2681 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2682 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2685 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2686 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2691 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2692 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2693 FIXME("func magic = %02x\n", pFunc
->magic
);
2696 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2697 sizeof(**ppFuncDesc
));
2698 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2700 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2701 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2702 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2703 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2704 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2705 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2707 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2708 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2710 if(pFunc
->retnextopt
& 0x80)
2711 pType
= &pFunc
->rettype
;
2713 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2716 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2718 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2719 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2720 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2721 (*ppFuncDesc
)->pParamDesc
=
2722 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2723 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2725 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2727 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2728 char *paramName
= pNameTable
+ *pArg
;
2730 /* If arg type follows then paramName points to the 2nd
2731 letter of the name, else the next WORD is an offset to
2732 the arg type and paramName points to the first letter.
2733 So let's take one char off paramName and see if we're
2734 pointing at an alpha-numeric char. However if *pArg is
2735 0xffff or 0xfffe then the param has no name, the former
2736 meaning that the next WORD is the type, the latter
2737 meaning the the next WORD is an offset to the type. */
2742 else if(*pArg
== 0xfffe) {
2746 else if(!isalnum(*(paramName
-1)))
2751 if(HaveOffs
) { /* the next word is an offset to type */
2752 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2753 SLTG_DoType(pType
, pFirstItem
,
2754 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2759 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2760 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2763 /* Are we an optional param ? */
2764 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2765 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2766 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2769 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2770 TLB_MultiByteToBSTR(paramName
);
2774 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2775 if(pFunc
->next
== 0xffff) break;
2777 pTI
->TypeAttr
.cFuncs
= num
;
2778 dump_TLBFuncDesc(pTI
->funclist
);
2779 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2782 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2785 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2786 SLTG_MemberHeader
*pMemHeader
;
2787 SLTG_RecordItem
*pItem
;
2789 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2794 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2796 pFirstItem
= (char*)(pMemHeader
+ 1);
2797 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2798 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2799 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2800 FIXME("record magic = %02x\n", pItem
->magic
);
2803 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2804 sizeof(**ppVarDesc
));
2805 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2806 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2807 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2808 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2810 if(pItem
->typepos
== 0x02)
2811 pType
= &pItem
->type
;
2812 else if(pItem
->typepos
== 0x00)
2813 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2815 FIXME("typepos = %02x\n", pItem
->typepos
);
2819 SLTG_DoType(pType
, pFirstItem
,
2820 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2822 /* FIXME("helpcontext, helpstring\n"); */
2824 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2826 ppVarDesc
= &((*ppVarDesc
)->next
);
2827 if(pItem
->next
== 0xffff) break;
2829 pTI
->TypeAttr
.cVars
= num
;
2830 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2833 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
2836 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2837 SLTG_MemberHeader
*pMemHeader
;
2838 SLTG_EnumItem
*pItem
;
2840 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2843 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2845 pFirstItem
= (char*)(pMemHeader
+ 1);
2846 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
2847 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2848 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
2849 FIXME("enumitem magic = %04x\n", pItem
->magic
);
2852 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2853 sizeof(**ppVarDesc
));
2854 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2855 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2856 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2858 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2859 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2860 *(INT
*)(pItem
->value
+ pFirstItem
);
2861 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
2862 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2863 /* FIXME("helpcontext, helpstring\n"); */
2865 ppVarDesc
= &((*ppVarDesc
)->next
);
2866 if(pItem
->next
== 0xffff) break;
2868 pTI
->TypeAttr
.cVars
= num
;
2869 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2872 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2873 managable copy of it into this */
2886 } SLTG_InternalOtherTypeInfo
;
2888 /****************************************************************************
2889 * ITypeLib2_Constructor_SLTG
2891 * loading a SLTG typelib from an in-memory image
2893 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
2895 ITypeLibImpl
*pTypeLibImpl
;
2896 SLTG_Header
*pHeader
;
2897 SLTG_BlkEntry
*pBlkEntry
;
2901 LPVOID pBlk
, pFirstBlk
;
2902 SLTG_LibBlk
*pLibBlk
;
2903 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
2904 char *pAfterOTIBlks
= NULL
;
2905 char *pNameTable
, *ptr
;
2908 ITypeInfoImpl
**ppTypeInfoImpl
;
2910 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2912 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2913 if (!pTypeLibImpl
) return NULL
;
2915 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
2916 pTypeLibImpl
->ref
= 1;
2921 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
2922 pHeader
->nrOfFileBlks
);
2923 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
2924 FIXME("Header type magic 0x%08lx not supported.\n",
2925 pHeader
->SLTG_magic
);
2929 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2930 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
2932 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2933 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
2935 /* Next we have a magic block */
2936 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
2938 /* Let's see if we're still in sync */
2939 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
2940 sizeof(SLTG_COMPOBJ_MAGIC
))) {
2941 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
2944 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
2945 sizeof(SLTG_DIR_MAGIC
))) {
2946 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
2950 pIndex
= (SLTG_Index
*)(pMagic
+1);
2952 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
2954 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
2956 /* We'll set up a ptr to the main library block, which is the last one. */
2958 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2959 pBlkEntry
[order
].next
!= 0;
2960 order
= pBlkEntry
[order
].next
- 1, i
++) {
2961 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
2965 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
2967 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2972 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2974 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2975 sizeof(*pOtherTypeInfoBlks
) *
2976 pTypeLibImpl
->TypeInfoCount
);
2979 ptr
= (char*)pLibBlk
+ len
;
2981 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
2985 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
2987 w
= *(WORD
*)(ptr
+ 2);
2990 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
2992 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
2993 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
2995 w
= *(WORD
*)(ptr
+ 4 + len
);
2997 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
2999 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3001 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3002 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3004 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3005 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3006 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3008 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3010 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3013 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3014 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3015 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3016 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3017 len
+= sizeof(SLTG_OtherTypeInfo
);
3021 pAfterOTIBlks
= ptr
;
3023 /* Skip this WORD and get the next DWORD */
3024 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3026 /* Now add this to pLibBLk look at what we're pointing at and
3027 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3028 dust and we should be pointing at the beginning of the name
3031 pNameTable
= (char*)pLibBlk
+ len
;
3033 switch(*(WORD
*)pNameTable
) {
3040 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3044 pNameTable
+= 0x216;
3048 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3050 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3053 /* Hopefully we now have enough ptrs set up to actually read in
3054 some TypeInfos. It's not clear which order to do them in, so
3055 I'll just follow the links along the BlkEntry chain and read
3056 them in in the order in which they're in the file */
3058 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3060 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3061 pBlkEntry
[order
].next
!= 0;
3062 order
= pBlkEntry
[order
].next
- 1, i
++) {
3064 SLTG_TypeInfoHeader
*pTIHeader
;
3065 SLTG_TypeInfoTail
*pTITail
;
3067 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3068 pOtherTypeInfoBlks
[i
].index_name
)) {
3069 FIXME("Index strings don't match\n");
3074 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3075 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3078 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3079 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3080 ITypeLib2_AddRef((ITypeLib2
*)pTypeLibImpl
);
3081 (*ppTypeInfoImpl
)->index
= i
;
3082 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3083 pOtherTypeInfoBlks
[i
].name_offs
+
3085 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3086 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3088 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3089 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3090 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3091 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3092 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3094 if((pTIHeader
->typeflags1
& 7) != 2)
3095 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3096 if(pTIHeader
->typeflags3
!= 2)
3097 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3099 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3100 debugstr_w((*ppTypeInfoImpl
)->Name
),
3101 typekind_desc
[pTIHeader
->typekind
],
3102 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3103 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3105 switch(pTIHeader
->typekind
) {
3107 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3111 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3114 case TKIND_INTERFACE
:
3115 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3119 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3123 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3129 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3130 but we've already set those */
3131 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3132 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3133 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3135 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3136 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3139 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3140 FIXME("Somehow processed %d TypeInfos\n", i
);
3144 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3145 return (ITypeLib2
*)pTypeLibImpl
;
3148 /* ITypeLib::QueryInterface
3150 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3155 ICOM_THIS( ITypeLibImpl
, iface
);
3157 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3160 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3161 IsEqualIID(riid
,&IID_ITypeLib
)||
3162 IsEqualIID(riid
,&IID_ITypeLib2
))
3169 ITypeLib2_AddRef(iface
);
3170 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3173 TRACE("-- Interface: E_NOINTERFACE\n");
3174 return E_NOINTERFACE
;
3179 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3181 ICOM_THIS( ITypeLibImpl
, iface
);
3183 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3185 return ++(This
->ref
);
3188 /* ITypeLib::Release
3190 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3192 ICOM_THIS( ITypeLibImpl
, iface
);
3196 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3200 /* FIXME destroy child objects */
3202 TRACE(" destroying ITypeLib(%p)\n",This
);
3206 SysFreeString(This
->Name
);
3210 if (This
->DocString
)
3212 SysFreeString(This
->DocString
);
3213 This
->DocString
= NULL
;
3218 SysFreeString(This
->HelpFile
);
3219 This
->HelpFile
= NULL
;
3222 if (This
->HelpStringDll
)
3224 SysFreeString(This
->HelpStringDll
);
3225 This
->HelpStringDll
= NULL
;
3228 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3229 HeapFree(GetProcessHeap(),0,This
);
3236 /* ITypeLib::GetTypeInfoCount
3238 * Returns the number of type descriptions in the type library
3240 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3242 ICOM_THIS( ITypeLibImpl
, iface
);
3243 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3244 return This
->TypeInfoCount
;
3247 /* ITypeLib::GetTypeInfo
3249 * retrieves the specified type description in the library.
3251 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3254 ITypeInfo
**ppTInfo
)
3258 ICOM_THIS( ITypeLibImpl
, iface
);
3259 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3261 TRACE("(%p)->(index=%d) \n", This
, index
);
3263 if (!ppTInfo
) return E_INVALIDARG
;
3265 /* search element n in list */
3266 for(i
=0; i
< index
; i
++)
3268 pTypeInfo
= pTypeInfo
->next
;
3271 TRACE("-- element not found\n");
3272 return TYPE_E_ELEMENTNOTFOUND
;
3276 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3278 ITypeInfo_AddRef(*ppTInfo
);
3279 TRACE("-- found (%p)\n",*ppTInfo
);
3284 /* ITypeLibs::GetTypeInfoType
3286 * Retrieves the type of a type description.
3288 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3293 ICOM_THIS( ITypeLibImpl
, iface
);
3295 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3297 TRACE("(%p) index %d \n",This
, index
);
3299 if(!pTKind
) return E_INVALIDARG
;
3301 /* search element n in list */
3302 for(i
=0; i
< index
; i
++)
3306 TRACE("-- element not found\n");
3307 return TYPE_E_ELEMENTNOTFOUND
;
3309 pTInfo
= pTInfo
->next
;
3312 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3313 TRACE("-- found Type (%d)\n", *pTKind
);
3317 /* ITypeLib::GetTypeInfoOfGuid
3319 * Retrieves the type description that corresponds to the specified GUID.
3322 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3325 ITypeInfo
**ppTInfo
)
3327 ICOM_THIS( ITypeLibImpl
, iface
);
3328 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3330 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3332 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3334 /* search linked list for guid */
3335 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3337 pTypeInfo
= pTypeInfo
->next
;
3341 /* end of list reached */
3342 TRACE("-- element not found\n");
3343 return TYPE_E_ELEMENTNOTFOUND
;
3347 TRACE("-- found (%p, %s)\n",
3349 debugstr_w(pTypeInfo
->Name
));
3351 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3352 ITypeInfo_AddRef(*ppTInfo
);
3356 /* ITypeLib::GetLibAttr
3358 * Retrieves the structure that contains the library's attributes.
3361 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3363 LPTLIBATTR
*ppTLibAttr
)
3365 ICOM_THIS( ITypeLibImpl
, iface
);
3366 TRACE("(%p)\n",This
);
3367 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3368 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3372 /* ITypeLib::GetTypeComp
3374 * Enables a client compiler to bind to a library's types, variables,
3375 * constants, and global functions.
3378 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3380 ITypeComp
**ppTComp
)
3382 ICOM_THIS( ITypeLibImpl
, iface
);
3383 FIXME("(%p): stub!\n",This
);
3387 /* ITypeLib::GetDocumentation
3389 * Retrieves the library's documentation string, the complete Help file name
3390 * and path, and the context identifier for the library Help topic in the Help
3393 * On a successful return all non-null BSTR pointers will have been set,
3396 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3400 BSTR
*pBstrDocString
,
3401 DWORD
*pdwHelpContext
,
3402 BSTR
*pBstrHelpFile
)
3404 ICOM_THIS( ITypeLibImpl
, iface
);
3406 HRESULT result
= E_INVALIDARG
;
3411 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3413 pBstrName
, pBstrDocString
,
3414 pdwHelpContext
, pBstrHelpFile
);
3418 /* documentation for the typelib */
3422 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3428 if (This
->DocString
)
3429 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3430 else if (This
->Name
)
3431 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3433 *pBstrDocString
= NULL
;
3437 *pdwHelpContext
= This
->dwHelpContext
;
3442 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3444 *pBstrHelpFile
= NULL
;
3451 /* for a typeinfo */
3452 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3454 if(SUCCEEDED(result
))
3456 result
= ITypeInfo_GetDocumentation(pTInfo
,
3460 pdwHelpContext
, pBstrHelpFile
);
3462 ITypeInfo_Release(pTInfo
);
3467 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3469 if (pBstrName
) SysFreeString (*pBstrName
);
3471 return STG_E_INSUFFICIENTMEMORY
;
3476 * Indicates whether a passed-in string contains the name of a type or member
3477 * described in the library.
3480 static HRESULT WINAPI
ITypeLib2_fnIsName(
3486 ICOM_THIS( ITypeLibImpl
, iface
);
3487 ITypeInfoImpl
*pTInfo
;
3488 TLBFuncDesc
*pFInfo
;
3491 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3493 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3497 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3498 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3499 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3500 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3501 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3502 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3503 goto ITypeLib2_fnIsName_exit
;
3505 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3506 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3511 ITypeLib2_fnIsName_exit
:
3512 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3513 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3518 /* ITypeLib::FindName
3520 * Finds occurrences of a type description in a type library. This may be used
3521 * to quickly verify that a name exists in a type library.
3524 static HRESULT WINAPI
ITypeLib2_fnFindName(
3528 ITypeInfo
**ppTInfo
,
3532 ICOM_THIS( ITypeLibImpl
, iface
);
3533 ITypeInfoImpl
*pTInfo
;
3534 TLBFuncDesc
*pFInfo
;
3538 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3540 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3541 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3542 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3543 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3544 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3545 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3546 goto ITypeLib2_fnFindName_exit
;
3548 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3549 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3551 ITypeLib2_fnFindName_exit
:
3552 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3553 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3556 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3557 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3564 /* ITypeLib::ReleaseTLibAttr
3566 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3569 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3571 TLIBATTR
*pTLibAttr
)
3573 ICOM_THIS( ITypeLibImpl
, iface
);
3574 TRACE("freeing (%p)\n",This
);
3575 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3579 /* ITypeLib2::GetCustData
3581 * gets the custom data
3583 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3588 ICOM_THIS( ITypeLibImpl
, iface
);
3589 TLBCustData
*pCData
;
3591 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3593 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3596 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3600 VariantInit( pVarVal
);
3601 VariantCopy( pVarVal
, &pCData
->data
);
3604 return E_INVALIDARG
; /* FIXME: correct? */
3607 /* ITypeLib2::GetLibStatistics
3609 * Returns statistics about a type library that are required for efficient
3610 * sizing of hash tables.
3613 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3615 ULONG
*pcUniqueNames
,
3616 ULONG
*pcchUniqueNames
)
3618 ICOM_THIS( ITypeLibImpl
, iface
);
3620 FIXME("(%p): stub!\n", This
);
3622 if(pcUniqueNames
) *pcUniqueNames
=1;
3623 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3627 /* ITypeLib2::GetDocumentation2
3629 * Retrieves the library's documentation string, the complete Help file name
3630 * and path, the localization context to use, and the context ID for the
3631 * library Help topic in the Help file.
3634 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3638 BSTR
*pbstrHelpString
,
3639 DWORD
*pdwHelpStringContext
,
3640 BSTR
*pbstrHelpStringDll
)
3642 ICOM_THIS( ITypeLibImpl
, iface
);
3646 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3648 /* the help string should be obtained from the helpstringdll,
3649 * using the _DLLGetDocumentation function, based on the supplied
3650 * lcid. Nice to do sometime...
3654 /* documentation for the typelib */
3656 *pbstrHelpString
=SysAllocString(This
->DocString
);
3657 if(pdwHelpStringContext
)
3658 *pdwHelpStringContext
=This
->dwHelpContext
;
3659 if(pbstrHelpStringDll
)
3660 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3666 /* for a typeinfo */
3667 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3669 if(SUCCEEDED(result
))
3671 ITypeInfo2
* pTInfo2
;
3672 result
= ITypeInfo_QueryInterface(pTInfo
,
3674 (LPVOID
*) &pTInfo2
);
3676 if(SUCCEEDED(result
))
3678 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3682 pdwHelpStringContext
,
3683 pbstrHelpStringDll
);
3685 ITypeInfo2_Release(pTInfo2
);
3688 ITypeInfo_Release(pTInfo
);
3694 /* ITypeLib2::GetAllCustData
3696 * Gets all custom data items for the library.
3699 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3701 CUSTDATA
*pCustData
)
3703 ICOM_THIS( ITypeLibImpl
, iface
);
3704 TLBCustData
*pCData
;
3706 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3707 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3708 if(pCustData
->prgCustData
){
3709 pCustData
->cCustData
=This
->ctCustData
;
3710 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3711 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3712 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3715 ERR(" OUT OF MEMORY! \n");
3716 return E_OUTOFMEMORY
;
3721 static ICOM_VTABLE(ITypeLib2
) tlbvt
= {
3722 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3723 ITypeLib2_fnQueryInterface
,
3725 ITypeLib2_fnRelease
,
3726 ITypeLib2_fnGetTypeInfoCount
,
3727 ITypeLib2_fnGetTypeInfo
,
3728 ITypeLib2_fnGetTypeInfoType
,
3729 ITypeLib2_fnGetTypeInfoOfGuid
,
3730 ITypeLib2_fnGetLibAttr
,
3731 ITypeLib2_fnGetTypeComp
,
3732 ITypeLib2_fnGetDocumentation
,
3734 ITypeLib2_fnFindName
,
3735 ITypeLib2_fnReleaseTLibAttr
,
3737 ITypeLib2_fnGetCustData
,
3738 ITypeLib2_fnGetLibStatistics
,
3739 ITypeLib2_fnGetDocumentation2
,
3740 ITypeLib2_fnGetAllCustData
3743 /*================== ITypeInfo(2) Methods ===================================*/
3744 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
3746 ITypeInfoImpl
* pTypeInfoImpl
;
3748 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
3751 ICOM_VTBL(pTypeInfoImpl
) = &tinfvt
;
3752 pTypeInfoImpl
->ref
=1;
3754 TRACE("(%p)\n", pTypeInfoImpl
);
3755 return (ITypeInfo2
*) pTypeInfoImpl
;
3758 /* ITypeInfo::QueryInterface
3760 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
3765 ICOM_THIS( ITypeLibImpl
, iface
);
3767 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3770 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3771 IsEqualIID(riid
,&IID_ITypeInfo
)||
3772 IsEqualIID(riid
,&IID_ITypeInfo2
))
3776 ITypeInfo_AddRef(iface
);
3777 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3780 TRACE("-- Interface: E_NOINTERFACE\n");
3781 return E_NOINTERFACE
;
3784 /* ITypeInfo::AddRef
3786 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
3788 ICOM_THIS( ITypeInfoImpl
, iface
);
3792 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3796 /* ITypeInfo::Release
3798 static ULONG WINAPI
ITypeInfo_fnRelease( ITypeInfo2
*iface
)
3800 ICOM_THIS( ITypeInfoImpl
, iface
);
3804 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3808 FIXME("destroy child objects\n");
3810 TRACE("destroying ITypeInfo(%p)\n",This
);
3813 SysFreeString(This
->Name
);
3817 if (This
->DocString
)
3819 SysFreeString(This
->DocString
);
3820 This
->DocString
= 0;
3825 ITypeInfo_Release((ITypeInfo
*)This
->next
);
3828 HeapFree(GetProcessHeap(),0,This
);
3834 /* ITypeInfo::GetTypeAttr
3836 * Retrieves a TYPEATTR structure that contains the attributes of the type
3840 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
3841 LPTYPEATTR
*ppTypeAttr
)
3843 ICOM_THIS( ITypeInfoImpl
, iface
);
3844 TRACE("(%p)\n",This
);
3845 /* FIXME: must do a copy here */
3846 *ppTypeAttr
=&This
->TypeAttr
;
3850 /* ITypeInfo::GetTypeComp
3852 * Retrieves the ITypeComp interface for the type description, which enables a
3853 * client compiler to bind to the type description's members.
3856 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
3857 ITypeComp
* *ppTComp
)
3859 ICOM_THIS( ITypeInfoImpl
, iface
);
3860 FIXME("(%p) stub!\n", This
);
3864 /* ITypeInfo::GetFuncDesc
3866 * Retrieves the FUNCDESC structure that contains information about a
3867 * specified function.
3870 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
3871 LPFUNCDESC
*ppFuncDesc
)
3873 ICOM_THIS( ITypeInfoImpl
, iface
);
3875 TLBFuncDesc
* pFDesc
;
3876 TRACE("(%p) index %d\n", This
, index
);
3877 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
3880 /* FIXME: must do a copy here */
3881 *ppFuncDesc
=&pFDesc
->funcdesc
;
3884 return E_INVALIDARG
;
3887 /* ITypeInfo::GetVarDesc
3889 * Retrieves a VARDESC structure that describes the specified variable.
3892 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
3893 LPVARDESC
*ppVarDesc
)
3895 ICOM_THIS( ITypeInfoImpl
, iface
);
3897 TLBVarDesc
* pVDesc
;
3898 TRACE("(%p) index %d\n", This
, index
);
3899 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
3902 /* FIXME: must do a copy here */
3903 *ppVarDesc
=&pVDesc
->vardesc
;
3906 return E_INVALIDARG
;
3909 /* ITypeInfo_GetNames
3911 * Retrieves the variable with the specified member ID (or the name of the
3912 * property or method and its parameters) that correspond to the specified
3915 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
3916 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
3918 ICOM_THIS( ITypeInfoImpl
, iface
);
3919 TLBFuncDesc
* pFDesc
;
3920 TLBVarDesc
* pVDesc
;
3922 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
3923 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
3926 /* function found, now return function and parameter names */
3927 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
3930 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
3932 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
3938 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
3941 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
3946 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
)
3948 /* recursive search */
3951 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
3953 if(SUCCEEDED(result
))
3955 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
3956 ITypeInfo_Release(pTInfo
);
3959 WARN("Could not search inherited interface!\n");
3963 WARN("no names found\n");
3966 return TYPE_E_ELEMENTNOTFOUND
;
3973 /* ITypeInfo::GetRefTypeOfImplType
3975 * If a type description describes a COM class, it retrieves the type
3976 * description of the implemented interface types. For an interface,
3977 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3981 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
3986 ICOM_THIS( ITypeInfoImpl
, iface
);
3988 TLBImplType
*pImpl
= This
->impltypelist
;
3990 TRACE("(%p) index %d\n", This
, index
);
3991 dump_TypeInfo(This
);
3995 /* only valid on dual interfaces;
3996 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3998 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4000 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4001 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4007 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4008 *pRefType
= pImpl
->hRef
;
4013 /* get element n from linked list */
4014 for(i
=0; pImpl
&& i
<index
; i
++)
4016 pImpl
= pImpl
->next
;
4019 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4021 *pRefType
= pImpl
->hRef
;
4023 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4030 /* ITypeInfo::GetImplTypeFlags
4032 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4033 * or base interface in a type description.
4035 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4036 UINT index
, INT
*pImplTypeFlags
)
4038 ICOM_THIS( ITypeInfoImpl
, iface
);
4042 TRACE("(%p) index %d\n", This
, index
);
4043 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4044 i
++, pImpl
=pImpl
->next
)
4046 if(i
==index
&& pImpl
){
4047 *pImplTypeFlags
=pImpl
->implflags
;
4051 return TYPE_E_ELEMENTNOTFOUND
;
4055 * Maps between member names and member IDs, and parameter names and
4058 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4059 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4061 ICOM_THIS( ITypeInfoImpl
, iface
);
4062 TLBFuncDesc
* pFDesc
;
4063 TLBVarDesc
* pVDesc
;
4066 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4068 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4070 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4071 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4072 for(i
=1; i
< cNames
; i
++){
4073 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4074 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4076 if( j
<pFDesc
->funcdesc
.cParams
)
4079 ret
=DISP_E_UNKNOWNNAME
;
4084 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4085 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4086 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4090 /* not found, see if this is and interface with an inheritance */
4091 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&&
4092 This
->TypeAttr
.cImplTypes
){
4093 /* recursive search */
4095 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4096 This
->impltypelist
->hRef
, &pTInfo
);
4098 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4099 ITypeInfo_Release(pTInfo
);
4102 WARN("Could not search inherited interface!\n");
4104 WARN("no names found\n");
4105 return DISP_E_UNKNOWNNAME
;
4108 /* ITypeInfo::Invoke
4110 * Invokes a method, or accesses a property of an object, that implements the
4111 * interface described by the type description.
4114 _invoke(LPVOID func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4117 if (TRACE_ON(ole
)) {
4119 MESSAGE("Calling %p(",func
);
4120 for (i
=0;i
<nrargs
;i
++) MESSAGE("%08lx,",args
[i
]);
4129 DWORD (WINAPI
*xfunc
)() = func
;
4134 DWORD (WINAPI
*xfunc
)(DWORD
) = func
;
4135 res
= xfunc(args
[0]);
4139 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
) = func
;
4140 res
= xfunc(args
[0],args
[1]);
4144 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
) = func
;
4145 res
= xfunc(args
[0],args
[1],args
[2]);
4149 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4150 res
= xfunc(args
[0],args
[1],args
[2],args
[3]);
4154 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4155 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4]);
4159 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4160 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4164 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4165 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4169 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4170 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4174 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4175 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4179 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4185 FIXME("unsupported calling convention %d\n",callconv
);
4189 TRACE("returns %08lx\n",res
);
4193 extern int const _argsize(DWORD vt
);
4195 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4200 DISPPARAMS
*pDispParams
,
4201 VARIANT
*pVarResult
,
4202 EXCEPINFO
*pExcepInfo
,
4205 ICOM_THIS( ITypeInfoImpl
, iface
);
4206 TLBFuncDesc
* pFDesc
;
4207 TLBVarDesc
* pVDesc
;
4210 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4211 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4213 dump_DispParms(pDispParams
);
4215 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4216 if (pFDesc
->funcdesc
.memid
== memid
) {
4217 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
4221 dump_TLBFuncDescOne(pFDesc
);
4222 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4223 switch (pFDesc
->funcdesc
.funckind
) {
4224 case FUNC_PUREVIRTUAL
:
4225 case FUNC_VIRTUAL
: {
4227 int numargs
, numargs2
, argspos
, args2pos
;
4228 DWORD
*args
, *args2
;
4231 numargs
= 1; numargs2
= 0;
4232 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4233 if (i
<pDispParams
->cArgs
)
4234 numargs
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4236 numargs
+= 1; /* sizeof(lpvoid) */
4237 numargs2
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4241 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4242 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4244 args
[0] = (DWORD
)pIUnk
;
4245 argspos
= 1; args2pos
= 0;
4246 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4247 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4248 if (i
<pDispParams
->cArgs
) {
4249 VARIANT
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1];
4250 TYPEDESC
*tdesc
= &pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
;
4252 if (V_VT(arg
) == tdesc
->vt
) {
4253 memcpy(&args
[argspos
],&V_UNION(arg
,lVal
), arglen
*sizeof(DWORD
));
4255 if (tdesc
->vt
== VT_VARIANT
) {
4256 memcpy(&args
[argspos
],arg
, arglen
*sizeof(DWORD
));
4258 ERR("Set arg %d to disparg type %d vs %d\n",i
,
4265 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
4266 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4267 /*FIXME: give pointers for the rest, so propertyget works*/
4268 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4270 /* If pointer to variant, pass reference it. */
4271 if ((tdesc
->vt
== VT_PTR
) &&
4272 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4275 args
[argspos
]= (DWORD
)pVarResult
;
4280 if (pFDesc
->funcdesc
.cParamsOpt
)
4281 FIXME("Does not support optional parameters (%d)\n",
4282 pFDesc
->funcdesc
.cParamsOpt
4285 res
= _invoke((*(DWORD
***)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
4286 pFDesc
->funcdesc
.callconv
,
4290 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4292 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
4293 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4294 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
+pDispParams
->cArgs
].tdesc
);
4295 /* If we are a pointer to a variant, we are done already */
4296 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4299 VariantInit(pVarResult
);
4300 memcpy(&V_UNION(pVarResult
,intVal
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4302 if (tdesc
->vt
== VT_PTR
)
4303 tdesc
= tdesc
->u
.lptdesc
;
4304 V_VT(pVarResult
) = tdesc
->vt
;
4306 /* HACK: VB5 likes this.
4307 * I do not know why. There is 1 example in MSDN which uses
4308 * this which appears broken (mixes int vals and
4311 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4312 V_VT(pVarResult
) = VT_DISPATCH
;
4313 TRACE("storing into variant:\n");
4314 dump_Variant(pVarResult
);
4318 HeapFree(GetProcessHeap(),0,args2
);
4319 HeapFree(GetProcessHeap(),0,args
);
4322 case FUNC_DISPATCH
: {
4326 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4328 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4331 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4332 hr
= IDispatch_Invoke(
4333 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4334 pVarResult
,pExcepInfo
,pArgErr
4337 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4338 IDispatch_Release(disp
);
4342 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4346 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4347 if (pVDesc
->vardesc
.memid
== memid
) {
4348 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4349 dump_TLBVarDesc(pVDesc
);
4354 /* not found, look for it in inherited interfaces */
4355 if (This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
) {
4356 /* recursive search */
4359 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4361 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4362 ITypeInfo_Release(pTInfo
);
4365 WARN("Could not search inherited interface!\n");
4367 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4368 return DISP_E_MEMBERNOTFOUND
;
4371 /* ITypeInfo::GetDocumentation
4373 * Retrieves the documentation string, the complete Help file name and path,
4374 * and the context ID for the Help topic for a specified type description.
4376 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4377 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4378 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4380 ICOM_THIS( ITypeInfoImpl
, iface
);
4381 TLBFuncDesc
* pFDesc
;
4382 TLBVarDesc
* pVDesc
;
4383 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4384 " HelpContext(%p) HelpFile(%p)\n",
4385 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4386 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4388 *pBstrName
=SysAllocString(This
->Name
);
4390 *pBstrDocString
=SysAllocString(This
->DocString
);
4392 *pdwHelpContext
=This
->dwHelpContext
;
4394 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4396 }else {/* for a member */
4397 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4398 if(pFDesc
->funcdesc
.memid
==memid
){
4400 *pBstrName
= SysAllocString(pFDesc
->Name
);
4402 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4404 *pdwHelpContext
=pFDesc
->helpcontext
;
4407 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4408 if(pVDesc
->vardesc
.memid
==memid
){
4409 FIXME("Not implemented\n");
4413 return TYPE_E_ELEMENTNOTFOUND
;
4416 /* ITypeInfo::GetDllEntry
4418 * Retrieves a description or specification of an entry point for a function
4421 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4422 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4425 ICOM_THIS( ITypeInfoImpl
, iface
);
4426 FIXME("(%p) stub!\n", This
);
4430 /* ITypeInfo::GetRefTypeInfo
4432 * If a type description references other type descriptions, it retrieves
4433 * the referenced type descriptions.
4435 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
4438 ITypeInfo
**ppTInfo
)
4440 ICOM_THIS( ITypeInfoImpl
, iface
);
4441 HRESULT result
= E_FAIL
;
4444 if (hRefType
== -1 &&
4445 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4446 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4448 /* when we meet a DUAL dispinterface, we must create the interface
4451 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
4454 /* the interface version contains the same information as the dispinterface
4455 * copy the contents of the structs.
4457 *pTypeInfoImpl
= *This
;
4458 pTypeInfoImpl
->ref
= 1;
4460 /* change the type to interface */
4461 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
4463 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
4465 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
4470 TLBRefType
*pRefType
;
4471 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
4472 if(pRefType
->reference
== hRefType
)
4476 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
4477 if(pRefType
&& hRefType
!= -1) {
4478 ITypeLib
*pTLib
= NULL
;
4480 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
4482 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
4484 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
4485 TRACE("typeinfo in imported typelib that is already loaded\n");
4486 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
4487 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
4490 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4491 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
4492 pRefType
->pImpTLInfo
->wVersionMajor
,
4493 pRefType
->pImpTLInfo
->wVersionMinor
,
4494 pRefType
->pImpTLInfo
->lcid
,
4497 if(!SUCCEEDED(result
)) {
4498 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
4499 result
=LoadTypeLib(libnam
, &pTLib
);
4500 SysFreeString(libnam
);
4502 if(SUCCEEDED(result
)) {
4503 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
4504 ITypeLib2_AddRef(pTLib
);
4508 if(SUCCEEDED(result
)) {
4509 if(pRefType
->index
== TLB_REF_USE_GUID
)
4510 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
4514 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
4518 ITypeLib2_Release(pTLib
);
4522 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
4523 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
4527 /* ITypeInfo::AddressOfMember
4529 * Retrieves the addresses of static functions or variables, such as those
4532 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
4533 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
4535 ICOM_THIS( ITypeInfoImpl
, iface
);
4536 FIXME("(%p) stub!\n", This
);
4540 /* ITypeInfo::CreateInstance
4542 * Creates a new instance of a type that describes a component object class
4545 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
4546 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
4548 ICOM_THIS( ITypeInfoImpl
, iface
);
4549 FIXME("(%p) stub!\n", This
);
4553 /* ITypeInfo::GetMops
4555 * Retrieves marshaling information.
4557 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
4560 ICOM_THIS( ITypeInfoImpl
, iface
);
4561 FIXME("(%p) stub!\n", This
);
4565 /* ITypeInfo::GetContainingTypeLib
4567 * Retrieves the containing type library and the index of the type description
4568 * within that type library.
4570 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
4571 ITypeLib
* *ppTLib
, UINT
*pIndex
)
4573 ICOM_THIS( ITypeInfoImpl
, iface
);
4575 return E_INVALIDARG
;
4576 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
4577 *pIndex
=This
->index
;
4578 ITypeLib2_AddRef(*ppTLib
);
4579 TRACE("(%p) returns (%p) index %d!\n", This
, *ppTLib
, *pIndex
);
4583 /* ITypeInfo::ReleaseTypeAttr
4585 * Releases a TYPEATTR previously returned by GetTypeAttr.
4588 static HRESULT WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
4589 TYPEATTR
* pTypeAttr
)
4591 ICOM_THIS( ITypeInfoImpl
, iface
);
4592 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
4596 /* ITypeInfo::ReleaseFuncDesc
4598 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4600 static HRESULT WINAPI
ITypeInfo_fnReleaseFuncDesc(
4602 FUNCDESC
*pFuncDesc
)
4604 ICOM_THIS( ITypeInfoImpl
, iface
);
4605 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
4609 /* ITypeInfo::ReleaseVarDesc
4611 * Releases a VARDESC previously returned by GetVarDesc.
4613 static HRESULT WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
4616 ICOM_THIS( ITypeInfoImpl
, iface
);
4617 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
4621 /* ITypeInfo2::GetTypeKind
4623 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4626 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
4627 TYPEKIND
*pTypeKind
)
4629 ICOM_THIS( ITypeInfoImpl
, iface
);
4630 *pTypeKind
=This
->TypeAttr
.typekind
;
4631 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
4635 /* ITypeInfo2::GetTypeFlags
4637 * Returns the type flags without any allocations. This returns a DWORD type
4638 * flag, which expands the type flags without growing the TYPEATTR (type
4642 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
* iface
,
4645 ICOM_THIS( ITypeInfoImpl
, iface
);
4646 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
4647 TRACE("(%p) flags 0x%04x\n", This
,*pTypeFlags
);
4651 /* ITypeInfo2::GetFuncIndexOfMemId
4652 * Binds to a specific member based on a known DISPID, where the member name
4653 * is not known (for example, when binding to a default member).
4656 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
4657 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
4659 ICOM_THIS( ITypeInfoImpl
, iface
);
4660 TLBFuncDesc
*pFuncInfo
;
4663 /* FIXME: should check for invKind??? */
4664 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
4665 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
4671 result
=E_INVALIDARG
;
4673 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
4674 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4678 /* TypeInfo2::GetVarIndexOfMemId
4680 * Binds to a specific member based on a known DISPID, where the member name
4681 * is not known (for example, when binding to a default member).
4684 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
4685 MEMBERID memid
, UINT
*pVarIndex
)
4687 ICOM_THIS( ITypeInfoImpl
, iface
);
4688 TLBVarDesc
*pVarInfo
;
4691 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
4692 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
4699 result
=E_INVALIDARG
;
4701 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
4702 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4706 /* ITypeInfo2::GetCustData
4708 * Gets the custom data
4710 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
4715 ICOM_THIS( ITypeInfoImpl
, iface
);
4716 TLBCustData
*pCData
;
4718 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4719 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4721 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4725 VariantInit( pVarVal
);
4726 VariantCopy( pVarVal
, &pCData
->data
);
4729 return E_INVALIDARG
; /* FIXME: correct? */
4732 /* ITypeInfo2::GetFuncCustData
4734 * Gets the custom data
4736 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
4742 ICOM_THIS( ITypeInfoImpl
, iface
);
4743 TLBCustData
*pCData
=NULL
;
4744 TLBFuncDesc
* pFDesc
;
4746 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4747 pFDesc
=pFDesc
->next
);
4750 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4751 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4753 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4756 VariantInit( pVarVal
);
4757 VariantCopy( pVarVal
, &pCData
->data
);
4760 return E_INVALIDARG
; /* FIXME: correct? */
4763 /* ITypeInfo2::GetParamCustData
4765 * Gets the custom data
4767 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
4774 ICOM_THIS( ITypeInfoImpl
, iface
);
4775 TLBCustData
*pCData
=NULL
;
4776 TLBFuncDesc
* pFDesc
;
4779 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
4781 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
4782 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
4783 pCData
= pCData
->next
)
4784 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4786 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4790 VariantInit( pVarVal
);
4791 VariantCopy( pVarVal
, &pCData
->data
);
4794 return E_INVALIDARG
; /* FIXME: correct? */
4797 /* ITypeInfo2::GetVarCustData
4799 * Gets the custom data
4801 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
4807 ICOM_THIS( ITypeInfoImpl
, iface
);
4808 TLBCustData
*pCData
=NULL
;
4809 TLBVarDesc
* pVDesc
;
4812 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
4816 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4818 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4822 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4826 VariantInit( pVarVal
);
4827 VariantCopy( pVarVal
, &pCData
->data
);
4830 return E_INVALIDARG
; /* FIXME: correct? */
4833 /* ITypeInfo2::GetImplCustData
4835 * Gets the custom data
4837 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
4843 ICOM_THIS( ITypeInfoImpl
, iface
);
4844 TLBCustData
*pCData
=NULL
;
4845 TLBImplType
* pRDesc
;
4848 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
4852 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4854 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4858 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4862 VariantInit( pVarVal
);
4863 VariantCopy( pVarVal
, &pCData
->data
);
4866 return E_INVALIDARG
; /* FIXME: correct? */
4869 /* ITypeInfo2::GetDocumentation2
4871 * Retrieves the documentation string, the complete Help file name and path,
4872 * the localization context to use, and the context ID for the library Help
4873 * topic in the Help file.
4876 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
4880 BSTR
*pbstrHelpString
,
4881 DWORD
*pdwHelpStringContext
,
4882 BSTR
*pbstrHelpStringDll
)
4884 ICOM_THIS( ITypeInfoImpl
, iface
);
4885 TLBFuncDesc
* pFDesc
;
4886 TLBVarDesc
* pVDesc
;
4887 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4888 "HelpStringContext(%p) HelpStringDll(%p)\n",
4889 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
4890 pbstrHelpStringDll
);
4891 /* the help string should be obtained from the helpstringdll,
4892 * using the _DLLGetDocumentation function, based on the supplied
4893 * lcid. Nice to do sometime...
4895 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4897 *pbstrHelpString
=SysAllocString(This
->Name
);
4898 if(pdwHelpStringContext
)
4899 *pdwHelpStringContext
=This
->dwHelpStringContext
;
4900 if(pbstrHelpStringDll
)
4901 *pbstrHelpStringDll
=
4902 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4904 }else {/* for a member */
4905 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4906 if(pFDesc
->funcdesc
.memid
==memid
){
4908 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
4909 if(pdwHelpStringContext
)
4910 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
4911 if(pbstrHelpStringDll
)
4912 *pbstrHelpStringDll
=
4913 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4916 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4917 if(pVDesc
->vardesc
.memid
==memid
){
4919 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
4920 if(pdwHelpStringContext
)
4921 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
4922 if(pbstrHelpStringDll
)
4923 *pbstrHelpStringDll
=
4924 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4928 return TYPE_E_ELEMENTNOTFOUND
;
4931 /* ITypeInfo2::GetAllCustData
4933 * Gets all custom data items for the Type info.
4936 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
4938 CUSTDATA
*pCustData
)
4940 ICOM_THIS( ITypeInfoImpl
, iface
);
4941 TLBCustData
*pCData
;
4944 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4946 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4947 if(pCustData
->prgCustData
){
4948 pCustData
->cCustData
=This
->ctCustData
;
4949 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4950 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4951 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4954 ERR(" OUT OF MEMORY! \n");
4955 return E_OUTOFMEMORY
;
4960 /* ITypeInfo2::GetAllFuncCustData
4962 * Gets all custom data items for the specified Function
4965 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
4968 CUSTDATA
*pCustData
)
4970 ICOM_THIS( ITypeInfoImpl
, iface
);
4971 TLBCustData
*pCData
;
4972 TLBFuncDesc
* pFDesc
;
4974 TRACE("(%p) index %d\n", This
, index
);
4975 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4976 pFDesc
=pFDesc
->next
)
4979 pCustData
->prgCustData
=
4980 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4981 if(pCustData
->prgCustData
){
4982 pCustData
->cCustData
=pFDesc
->ctCustData
;
4983 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
4984 pCData
= pCData
->next
){
4985 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4986 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4990 ERR(" OUT OF MEMORY! \n");
4991 return E_OUTOFMEMORY
;
4995 return TYPE_E_ELEMENTNOTFOUND
;
4998 /* ITypeInfo2::GetAllParamCustData
5000 * Gets all custom data items for the Functions
5003 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5004 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5006 ICOM_THIS( ITypeInfoImpl
, iface
);
5007 TLBCustData
*pCData
=NULL
;
5008 TLBFuncDesc
* pFDesc
;
5010 TRACE("(%p) index %d\n", This
, indexFunc
);
5011 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5012 pFDesc
=pFDesc
->next
)
5014 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5015 pCustData
->prgCustData
=
5016 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5017 sizeof(CUSTDATAITEM
));
5018 if(pCustData
->prgCustData
){
5019 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5020 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5021 pCData
; i
++, pCData
= pCData
->next
){
5022 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5023 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5027 ERR(" OUT OF MEMORY! \n");
5028 return E_OUTOFMEMORY
;
5032 return TYPE_E_ELEMENTNOTFOUND
;
5035 /* ITypeInfo2::GetAllVarCustData
5037 * Gets all custom data items for the specified Variable
5040 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5041 UINT index
, CUSTDATA
*pCustData
)
5043 ICOM_THIS( ITypeInfoImpl
, iface
);
5044 TLBCustData
*pCData
;
5045 TLBVarDesc
* pVDesc
;
5047 TRACE("(%p) index %d\n", This
, index
);
5048 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5049 pVDesc
=pVDesc
->next
)
5052 pCustData
->prgCustData
=
5053 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5054 if(pCustData
->prgCustData
){
5055 pCustData
->cCustData
=pVDesc
->ctCustData
;
5056 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5057 pCData
= pCData
->next
){
5058 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5059 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5063 ERR(" OUT OF MEMORY! \n");
5064 return E_OUTOFMEMORY
;
5068 return TYPE_E_ELEMENTNOTFOUND
;
5071 /* ITypeInfo2::GetAllImplCustData
5073 * Gets all custom data items for the specified implementation type
5076 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5079 CUSTDATA
*pCustData
)
5081 ICOM_THIS( ITypeInfoImpl
, iface
);
5082 TLBCustData
*pCData
;
5083 TLBImplType
* pRDesc
;
5085 TRACE("(%p) index %d\n", This
, index
);
5086 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5087 pRDesc
=pRDesc
->next
)
5090 pCustData
->prgCustData
=
5091 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5092 if(pCustData
->prgCustData
){
5093 pCustData
->cCustData
=pRDesc
->ctCustData
;
5094 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5095 pCData
= pCData
->next
){
5096 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5097 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5101 ERR(" OUT OF MEMORY! \n");
5102 return E_OUTOFMEMORY
;
5106 return TYPE_E_ELEMENTNOTFOUND
;
5109 static ICOM_VTABLE(ITypeInfo2
) tinfvt
=
5111 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5113 ITypeInfo_fnQueryInterface
,
5115 ITypeInfo_fnRelease
,
5117 ITypeInfo_fnGetTypeAttr
,
5118 ITypeInfo_fnGetTypeComp
,
5119 ITypeInfo_fnGetFuncDesc
,
5120 ITypeInfo_fnGetVarDesc
,
5121 ITypeInfo_fnGetNames
,
5122 ITypeInfo_fnGetRefTypeOfImplType
,
5123 ITypeInfo_fnGetImplTypeFlags
,
5124 ITypeInfo_fnGetIDsOfNames
,
5126 ITypeInfo_fnGetDocumentation
,
5127 ITypeInfo_fnGetDllEntry
,
5128 ITypeInfo_fnGetRefTypeInfo
,
5129 ITypeInfo_fnAddressOfMember
,
5130 ITypeInfo_fnCreateInstance
,
5131 ITypeInfo_fnGetMops
,
5132 ITypeInfo_fnGetContainingTypeLib
,
5133 ITypeInfo_fnReleaseTypeAttr
,
5134 ITypeInfo_fnReleaseFuncDesc
,
5135 ITypeInfo_fnReleaseVarDesc
,
5137 ITypeInfo2_fnGetTypeKind
,
5138 ITypeInfo2_fnGetTypeFlags
,
5139 ITypeInfo2_fnGetFuncIndexOfMemId
,
5140 ITypeInfo2_fnGetVarIndexOfMemId
,
5141 ITypeInfo2_fnGetCustData
,
5142 ITypeInfo2_fnGetFuncCustData
,
5143 ITypeInfo2_fnGetParamCustData
,
5144 ITypeInfo2_fnGetVarCustData
,
5145 ITypeInfo2_fnGetImplTypeCustData
,
5146 ITypeInfo2_fnGetDocumentation2
,
5147 ITypeInfo2_fnGetAllCustData
,
5148 ITypeInfo2_fnGetAllFuncCustData
,
5149 ITypeInfo2_fnGetAllParamCustData
,
5150 ITypeInfo2_fnGetAllVarCustData
,
5151 ITypeInfo2_fnGetAllImplTypeCustData
,