~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/oleview/typelib.c

Version: ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * OleView (typelib.c)
  3  *
  4  * Copyright 2006 Piotr Caban
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "main.h"
 22 
 23 #include "wine/debug.h"
 24 #include "wine/unicode.h"
 25 
 26 WINE_DEFAULT_DEBUG_CHANNEL(oleview);
 27 
 28 TYPELIB typelib;
 29 static const WCHAR wszTypeLib[] = { 'T','Y','P','E','L','I','B','\0' };
 30 
 31 static const WCHAR wszFailed[] = { '<','f','a','i','l','e','d','>','\0' };
 32 static const WCHAR wszSpace[] = { ' ','\0' };
 33 static const WCHAR wszAsterix[] = { '*','\0' };
 34 static const WCHAR wszComa[] = { ',','\0' };
 35 static const WCHAR wszEquals[] = { '=','\0' };
 36 static const WCHAR wszSemicolon[] = { ';','\0' };
 37 static const WCHAR wszNewLine[] = { '\n','\0' };
 38 static const WCHAR wszOpenBrackets1[] = { '[','\0' };
 39 static const WCHAR wszCloseBrackets1[] = { ']','\0' };
 40 static const WCHAR wszOpenBrackets2[] = { '(','\0' };
 41 static const WCHAR wszCloseBrackets2[] = { ')','\0' };
 42 static const WCHAR wszOpenBrackets3[] = { '{','\0' };
 43 static const WCHAR wszCloseBrackets3[] = { '}','\0' };
 44 static const WCHAR wszInvertedComa[] = { '"','\0' };
 45 static const WCHAR wszColon[] = { ':','\0' };
 46 
 47 static const WCHAR wszUUID[] = { 'u','u','i','d','\0' };
 48 static const WCHAR wszOdl[] = { 'o','d','l','\0' };
 49 
 50 static const WCHAR wszVT_BOOL[]
 51     = { 'V','A','R','I','A','N','T','_','B','O','O','L','\0' };
 52 static const WCHAR wszVT_UI1[]
 53     = { 'u','n','s','i','g','n','e','d',' ','c','h','a','r','\0' };
 54 static const WCHAR wszVT_UI2[]
 55     = { 'u','n','s','i','g','n','e','d',' ','s','h','o','r','t','\0' };
 56 static const WCHAR wszVT_UI4[]
 57     = { 'u','n','s','i','g','n','e','d',' ','l','o','n','g','\0' };
 58 static const WCHAR wszVT_UI8[] = { 'u','i','n','t','6','4','\0' };
 59 static const WCHAR wszVT_UINT[]
 60     = { 'u','n','s','i','g','n','e','d',' ','i','n','t','\0' };
 61 static const WCHAR wszVT_I1[] = { 'c','h','a','r','\0' };
 62 static const WCHAR wszVT_I2[] = { 's','h','o','r','t','\0' };
 63 static const WCHAR wszVT_I4[] = { 'l','o','n','g','\0' };
 64 static const WCHAR wszVT_I8[] = { 'i','n','t','6','4','\0' };
 65 static const WCHAR wszVT_R4[] = { 's','i','n','g','l','e','\0' };
 66 static const WCHAR wszVT_INT[] = { 'i','n','t','\0' };
 67 static const WCHAR wszVT_BSTR[] = { 'B','S','T','R','\0' };
 68 static const WCHAR wszVT_CY[] = { 'C','U','R','R','E','N','C','Y','\0' };
 69 static const WCHAR wszVT_VARIANT[] = { 'V','A','R','I','A','N','T','\0' };
 70 static const WCHAR wszVT_VOID[] = { 'v','o','i','d','\0' };
 71 static const WCHAR wszVT_ERROR[] = { 'S','C','O','D','E','\0' };
 72 static const WCHAR wszVT_LPSTR[] = { 'L','P','S','T','R','\0' };
 73 static const WCHAR wszVT_LPWSTR[] = { 'L','P','W','S','T','R','\0' };
 74 static const WCHAR wszVT_HRESULT[] = { 'H','R','E','S','U','L','T','\0' };
 75 static const WCHAR wszVT_UNKNOWN[] = { 'I','U','n','k','n','o','w','n','\0' };
 76 static const WCHAR wszVT_DISPATCH[] = { 'I','D','i','s','p','a','t','c','h','\0' };
 77 static const WCHAR wszVT_DATE[] = { 'D','A','T','E','\0' };
 78 static const WCHAR wszVT_R8[] = { 'd','o','u','b','l','e','\0' };
 79 static const WCHAR wszVT_SAFEARRAY[] = { 'S','A','F','E','A','R','R','A','Y','\0' };
 80 
 81 static const WCHAR wszFormat[] = { '','x','%','.','8','l','x','\0' };
 82 static const WCHAR wszStdCall[] = { '_','s','t','d','c','a','l','l','\0' };
 83 static const WCHAR wszId[] = { 'i','d','\0' };
 84 static const WCHAR wszHelpstring[] = { 'h','e','l','p','s','t','r','i','n','g','\0' };
 85 static const WCHAR wszPropPut[] = { 'p','r','o','p','p','u','t','\0' };
 86 static const WCHAR wszPropGet[] = { 'p','r','o','p','g','e','t','\0' };
 87 static const WCHAR wszPropPutRef[] = { 'p','r','o','p','p','u','t','r','e','f','\0' };
 88 static const WCHAR wszPARAMFLAG_FIN[] = { 'i','n','\0' };
 89 static const WCHAR wszPARAMFLAG_FOUT[] = { 'o','u','t','\0' };
 90 static const WCHAR wszPARAMFLAG_FLCID[] = { 'c','i','d','\0' };
 91 static const WCHAR wszPARAMFLAG_FRETVAL[] = { 'r','e','t','v','a','l','\0' };
 92 static const WCHAR wszPARAMFLAG_FOPT[] = { 'o','p','t','i','o','n','a','l','\0' };
 93 static const WCHAR wszPARAMFLAG_FHASCUSTDATA[]
 94     = { 'h','a','s','c','u','s','t','d','a','t','a','\0' };
 95 static const WCHAR wszDefaultValue[]
 96     = { 'd','e','f','a','u','l','t','v','a','l','u','e','\0' };
 97 
 98 static const WCHAR wszReadOnly[] = { 'r','e','a','d','o','n','l','y','\0' };
 99 static const WCHAR wszConst[] = { 'c','o','n','s','t','\0' };
100 
101 static void ShowLastError(void)
102 {
103     DWORD error = GetLastError();
104     LPWSTR lpMsgBuf;
105     WCHAR wszTitle[MAX_LOAD_STRING];
106 
107     LoadString(globals.hMainInst, IDS_TYPELIBTITLE, wszTitle,
108             sizeof(WCHAR[MAX_LOAD_STRING]));
109     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
110             NULL, error, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
111     MessageBox(NULL, lpMsgBuf, wszTitle, MB_OK | MB_ICONERROR);
112     LocalFree(lpMsgBuf);
113     return;
114 }
115 
116 static void SaveIdl(WCHAR *wszFileName)
117 {
118     HTREEITEM hIDL;
119     TVITEM tvi;
120     HANDLE hFile;
121     DWORD len, dwNumWrite;
122     char *wszIdl;
123     TYPELIB_DATA *data;
124 
125     hIDL = TreeView_GetChild(typelib.hTree, TVI_ROOT);
126 
127     memset(&tvi, 0, sizeof(TVITEM));
128     tvi.hItem = hIDL;
129 
130     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
131     data = (TYPELIB_DATA *)tvi.lParam;
132 
133     hFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
134                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
135     if(hFile == INVALID_HANDLE_VALUE)
136     {
137         ShowLastError();
138         return;
139     }
140 
141     len = WideCharToMultiByte( CP_UTF8, 0, data->idl, data->idlLen, NULL, 0, NULL, NULL );
142     wszIdl = HeapAlloc(GetProcessHeap(), 0, len);
143     WideCharToMultiByte( CP_UTF8, 0, data->idl, data->idlLen, wszIdl, len, NULL, NULL );
144 
145     if(!WriteFile(hFile, wszIdl, len, &dwNumWrite, NULL))
146         ShowLastError();
147 
148     HeapFree(GetProcessHeap(), 0, wszIdl);
149     CloseHandle(hFile);
150 }
151 
152 static void GetSaveIdlAsPath(void)
153 {
154     OPENFILENAME saveidl;
155     WCHAR *pFileName;
156     WCHAR wszPath[MAX_LOAD_STRING];
157     WCHAR wszDir[MAX_LOAD_STRING];
158     static const WCHAR wszDefaultExt[] = { 'i','d','l',0 };
159     static const WCHAR wszIdlFiles[] = { '*','.','i','d','l','\0','\0' };
160 
161     memset(&saveidl, 0, sizeof(saveidl));
162 
163     lstrcpyW(wszDir, typelib.wszFileName);
164     pFileName = wszDir + lstrlenW(wszDir);
165     while(*pFileName != '.' && *pFileName != '\\' && *pFileName != '/'
166             && pFileName > wszDir) pFileName -= 1;
167     if(*pFileName == '.')
168     {
169         *pFileName = '\0';
170         while(*pFileName != '\\' && *pFileName != '/' && pFileName > wszDir)
171             pFileName -= 1;
172     }
173     if(*pFileName == '\\' || *pFileName == '/') pFileName += 1;
174     lstrcpyW(wszPath, pFileName);
175 
176     GetCurrentDirectory(MAX_LOAD_STRING, wszDir);
177 
178     saveidl.lStructSize = sizeof(OPENFILENAME);
179     saveidl.hwndOwner = globals.hTypeLibWnd;
180     saveidl.hInstance = globals.hMainInst;
181     saveidl.lpstrFilter = wszIdlFiles;
182     saveidl.lpstrFile = wszPath;
183     saveidl.nMaxFile = MAX_LOAD_STRING;
184     saveidl.lpstrInitialDir = wszDir;
185     saveidl.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
186     saveidl.lpstrDefExt = wszDefaultExt;
187 
188     if (GetSaveFileName(&saveidl))
189         SaveIdl(wszPath);
190 }
191 
192 void AddToStrW(WCHAR *wszDest, const WCHAR *wszSource)
193 {
194     lstrcpyW(&wszDest[lstrlenW(wszDest)], wszSource);
195 }
196 
197 void AddToTLDataStrW(TYPELIB_DATA *pTLData, const WCHAR *wszSource)
198 {
199     int SourceLen = lstrlenW(wszSource);
200 
201     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
202             sizeof(WCHAR)*(pTLData->idlLen+SourceLen+1));
203 
204     memcpy(&pTLData->idl[pTLData->idlLen], wszSource, sizeof(WCHAR)*(SourceLen+1));
205     pTLData->idlLen += SourceLen;
206 }
207 
208 void AddToTLDataStrWithTabsW(TYPELIB_DATA *pTLData, WCHAR *wszSource)
209 {
210     int lineLen = lstrlenW(wszSource);
211     int newLinesNo = 0;
212     WCHAR *pSourcePos = (WCHAR *)wszSource;
213     WCHAR *pSourceBeg;
214 
215     if(!lineLen) return;
216     while(*pSourcePos)
217     {
218         if(*pSourcePos == *wszNewLine) newLinesNo++;
219         pSourcePos += 1;
220     }
221     if(*(pSourcePos - 1) != *wszNewLine) newLinesNo++;
222 
223     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
224             sizeof(WCHAR)*(pTLData->idlLen+lineLen+4*newLinesNo+1));
225 
226     pSourcePos = (WCHAR *)wszSource;
227     pSourceBeg = (WCHAR *)wszSource;
228     while(newLinesNo)
229     {
230         if(*pSourcePos != *wszNewLine && *pSourcePos)
231         {
232             pSourcePos += 1;
233             continue;
234         }
235         newLinesNo--;
236 
237         if(*pSourcePos)
238         {
239             *pSourcePos = '\0';
240             lineLen = lstrlenW(pSourceBeg)+1;
241             *pSourcePos = '\n';
242             pSourcePos += 1;
243         }
244         else lineLen = lstrlenW(pSourceBeg);
245 
246         pTLData->idl[pTLData->idlLen] = *wszSpace;
247         pTLData->idl[pTLData->idlLen+1] = *wszSpace;
248         pTLData->idl[pTLData->idlLen+2] = *wszSpace;
249         pTLData->idl[pTLData->idlLen+3] = *wszSpace;
250         memcpy(&pTLData->idl[pTLData->idlLen+4], pSourceBeg, sizeof(WCHAR)*lineLen);
251         pTLData->idlLen += lineLen + 4;
252         pTLData->idl[pTLData->idlLen] = '\0';
253 
254         pSourceBeg = pSourcePos;
255     }
256 }
257 
258 static TYPELIB_DATA *InitializeTLData(void)
259 {
260     TYPELIB_DATA *pTLData;
261 
262     pTLData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TYPELIB_DATA));
263 
264     pTLData->idl = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR));
265     pTLData->idl[0] = '\0';
266 
267     return pTLData;
268 }
269 
270 static void AddSpaces(TYPELIB_DATA *pTLData, int tabSize)
271 {
272     for(; tabSize>0; tabSize--)
273         AddToTLDataStrW(pTLData, wszSpace);
274 }
275 
276 static void AddChildrenData(HTREEITEM hParent, TYPELIB_DATA *pData)
277 {
278     HTREEITEM hCur;
279     TVITEM tvi;
280 
281     memset(&tvi, 0, sizeof(&tvi));
282 
283     hCur = TreeView_GetChild(typelib.hTree, hParent);
284     if(!hCur) return;
285 
286     do
287     {
288         tvi.hItem = hCur;
289         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
290         if(tvi.lParam && ((TYPELIB_DATA *)(tvi.lParam))->idlLen)
291             AddToTLDataStrWithTabsW(pData, ((TYPELIB_DATA *)(tvi.lParam))->idl);
292     }while((hCur = TreeView_GetNextSibling(typelib.hTree, hCur)));
293 }
294 
295 static void CreateTypeInfo(WCHAR *wszAddTo, WCHAR *wszAddAfter, TYPEDESC tdesc, ITypeInfo *pTypeInfo)
296 {
297     int i;
298     BSTR bstrData;
299     HRESULT hRes;
300     ITypeInfo *pRefTypeInfo;
301     WCHAR wszBuf[MAX_LOAD_STRING];
302     WCHAR wszFormat[] = { '[','%','l','u',']','\0' };
303 
304     switch(tdesc.vt&VT_TYPEMASK)
305     {
306 #define VTADDTOSTR(x) case x:\
307         AddToStrW(wszAddTo, wsz##x);\
308         break
309         VTADDTOSTR(VT_BOOL);
310         VTADDTOSTR(VT_UI1);
311         VTADDTOSTR(VT_UI2);
312         VTADDTOSTR(VT_UI4);
313         VTADDTOSTR(VT_UI8);
314         VTADDTOSTR(VT_UINT);
315         VTADDTOSTR(VT_I1);
316         VTADDTOSTR(VT_I2);
317         VTADDTOSTR(VT_I4);
318         VTADDTOSTR(VT_I8);
319         VTADDTOSTR(VT_R4);
320         VTADDTOSTR(VT_INT);
321         VTADDTOSTR(VT_BSTR);
322         VTADDTOSTR(VT_CY);
323         VTADDTOSTR(VT_VARIANT);
324         VTADDTOSTR(VT_VOID);
325         VTADDTOSTR(VT_ERROR);
326         VTADDTOSTR(VT_LPSTR);
327         VTADDTOSTR(VT_LPWSTR);
328         VTADDTOSTR(VT_HRESULT);
329         VTADDTOSTR(VT_UNKNOWN);
330         VTADDTOSTR(VT_DISPATCH);
331         VTADDTOSTR(VT_DATE);
332         VTADDTOSTR(VT_R8);
333         case VT_CARRAY:
334         for(i=0; i<U(tdesc).lpadesc->cDims; i++)
335         {
336             wsprintfW(wszBuf, wszFormat, U(tdesc).lpadesc->rgbounds[i].cElements);
337             AddToStrW(wszAddAfter, wszBuf);
338         }
339         CreateTypeInfo(wszAddTo, wszAddAfter, U(tdesc).lpadesc->tdescElem, pTypeInfo);
340         break;
341         case VT_SAFEARRAY:
342         AddToStrW(wszAddTo, wszVT_SAFEARRAY);
343         AddToStrW(wszAddTo, wszOpenBrackets2);
344         CreateTypeInfo(wszAddTo, wszAddAfter, *U(tdesc).lptdesc, pTypeInfo);
345         AddToStrW(wszAddTo, wszCloseBrackets2);
346         break;
347         case VT_PTR:
348         CreateTypeInfo(wszAddTo, wszAddAfter, *U(tdesc).lptdesc, pTypeInfo);
349         AddToStrW(wszAddTo, wszAsterix);
350         break;
351         case VT_USERDEFINED:
352         hRes = ITypeInfo_GetRefTypeInfo(pTypeInfo,
353                 U(tdesc).hreftype, &pRefTypeInfo);
354         if(SUCCEEDED(hRes))
355         {
356             ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL,
357                     &bstrData, NULL, NULL, NULL);
358             AddToStrW(wszAddTo, bstrData);
359             SysFreeString(bstrData);
360             ITypeInfo_Release(pRefTypeInfo);
361         }
362         else AddToStrW(wszAddTo, wszFailed);
363         break;
364         default:
365         WINE_FIXME("tdesc.vt&VT_TYPEMASK == %d not supported\n",
366                 tdesc.vt&VT_TYPEMASK);
367     }
368 }
369 
370 static int EnumVars(ITypeInfo *pTypeInfo, int cVars, HTREEITEM hParent)
371 {
372     int i;
373     TVINSERTSTRUCT tvis;
374     VARDESC *pVarDesc;
375     BSTR bstrName;
376     WCHAR wszText[MAX_LOAD_STRING];
377     WCHAR wszAfter[MAX_LOAD_STRING];
378 
379     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
380     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
381     U(tvis).item.pszText = wszText;
382     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
383     tvis.hParent = hParent;
384 
385     for(i=0; i<cVars; i++)
386     {
387         TYPELIB_DATA *tld;
388 
389         if(FAILED(ITypeInfo_GetVarDesc(pTypeInfo, i, &pVarDesc))) continue;
390         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pVarDesc->memid, &bstrName,
391                 NULL, NULL, NULL))) continue;
392 
393         tld = InitializeTLData();
394         U(tvis).item.lParam = (LPARAM) tld;
395         if(pVarDesc->memid < MIN_VAR_ID)
396         {
397 
398             AddToTLDataStrW(tld, wszOpenBrackets1);
399             AddToTLDataStrW(tld, wszId);
400             AddToTLDataStrW(tld, wszOpenBrackets2);
401             wsprintfW(wszText, wszFormat, pVarDesc->memid);
402             AddToTLDataStrW(tld, wszText);
403             memset(wszText, 0, sizeof(wszText));
404             AddToTLDataStrW(tld, wszCloseBrackets2);
405 
406             if(pVarDesc->wVarFlags & VARFLAG_FREADONLY)
407             {
408                 AddToTLDataStrW(tld, wszComa);
409                 AddToTLDataStrW(tld, wszSpace);
410                 AddToTLDataStrW(tld, wszReadOnly);
411             }
412             AddToTLDataStrW(tld, wszCloseBrackets1);
413             AddToTLDataStrW(tld, wszNewLine);
414         }
415 
416         memset(wszText, 0, sizeof(wszText));
417         memset(wszAfter, 0, sizeof(wszAfter));
418         CreateTypeInfo(wszText, wszAfter, pVarDesc->elemdescVar.tdesc, pTypeInfo);
419         AddToStrW(wszText, wszSpace);
420         AddToStrW(wszText, bstrName);
421         AddToStrW(wszText, wszAfter);
422         AddToTLDataStrW(tld, wszText);
423         AddToTLDataStrW(tld, wszSemicolon);
424         AddToTLDataStrW(tld, wszNewLine);
425 
426         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
427         SysFreeString(bstrName);
428         ITypeInfo_ReleaseVarDesc(pTypeInfo, pVarDesc);
429     }
430 
431     return 0;
432 }
433 
434 static int EnumEnums(ITypeInfo *pTypeInfo, int cVars, HTREEITEM hParent)
435 {
436     int i;
437     TVINSERTSTRUCT tvis;
438     VARDESC *pVarDesc;
439     BSTR bstrName;
440     WCHAR wszText[MAX_LOAD_STRING];
441     WCHAR wszAfter[MAX_LOAD_STRING];
442 
443     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
444     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
445     U(tvis).item.pszText = wszText;
446     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
447     tvis.hParent = hParent;
448 
449     for(i=0; i<cVars; i++)
450     {
451         TYPELIB_DATA *tld;
452 
453         if(FAILED(ITypeInfo_GetVarDesc(pTypeInfo, i, &pVarDesc))) continue;
454         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pVarDesc->memid, &bstrName,
455                 NULL, NULL, NULL))) continue;
456 
457         tld = InitializeTLData();
458         U(tvis).item.lParam = (LPARAM) tld;
459 
460         memset(wszText, 0, sizeof(wszText));
461         memset(wszAfter, 0, sizeof(wszAfter));
462 
463         if (pVarDesc->varkind == VAR_CONST)
464         {
465             VARIANT var;
466             VariantInit(&var);
467             if (VariantChangeType(&var, U(*pVarDesc).lpvarValue, 0, VT_BSTR) == S_OK)
468             {
469                 AddToStrW(wszText, wszConst);
470                 AddToStrW(wszText, wszSpace);
471                 AddToStrW(wszAfter, wszSpace);
472                 AddToStrW(wszAfter, wszEquals);
473                 AddToStrW(wszAfter, wszSpace);
474                 AddToStrW(wszAfter, V_BSTR(&var));
475             }
476         }
477 
478         CreateTypeInfo(wszText, wszAfter, pVarDesc->elemdescVar.tdesc, pTypeInfo);
479         AddToStrW(wszText, wszSpace);
480         AddToStrW(wszText, bstrName);
481         AddToStrW(wszText, wszAfter);
482         AddToTLDataStrW(tld, bstrName);
483         AddToTLDataStrW(tld, wszAfter);
484         if (i<cVars-1)
485             AddToTLDataStrW(tld, wszComa);
486         AddToTLDataStrW(tld, wszNewLine);
487 
488         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
489         SysFreeString(bstrName);
490         ITypeInfo_ReleaseVarDesc(pTypeInfo, pVarDesc);
491     }
492 
493     return 0;
494 }
495 
496 static int EnumFuncs(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, HTREEITEM hParent)
497 {
498     int i, j;
499     int cFuncs;
500     unsigned namesNo;
501     TVINSERTSTRUCT tvis;
502     FUNCDESC *pFuncDesc;
503     BSTR bstrName, bstrHelpString, *bstrParamNames;
504     WCHAR wszText[MAX_LOAD_STRING];
505     WCHAR wszAfter[MAX_LOAD_STRING];
506     WCHAR szRhs[] = {'r','h','s',0};    /* Right-hand side of a propput */
507     BOOL bFirst;
508 
509     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
510     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
511     tvis.hParent = hParent;
512 
513     cFuncs = pTypeAttr->cFuncs;
514 
515     i = 0;
516     if(pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL) { /* skip 7 members of IDispatch */
517         cFuncs += 7;
518         i += 7;
519     }
520 
521     for(; i<cFuncs; i++)
522     {
523         TYPELIB_DATA *tld;
524 
525         if(FAILED(ITypeInfo_GetFuncDesc(pTypeInfo, i, &pFuncDesc))) continue;
526 
527         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstrName,
528                 &bstrHelpString, NULL, NULL))) continue;
529 
530         memset(wszText, 0, sizeof(wszText));
531         memset(wszAfter, 0, sizeof(wszAfter));
532         tld = InitializeTLData();
533         U(tvis).item.cchTextMax = SysStringLen(bstrName);
534         U(tvis).item.pszText = bstrName;
535         U(tvis).item.lParam = (LPARAM) tld;
536         bFirst = TRUE;
537         if(pFuncDesc->memid < MIN_FUNC_ID || pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL)
538         {
539             AddToTLDataStrW(tld, wszOpenBrackets1);
540             bFirst = FALSE;
541             AddToTLDataStrW(tld, wszId);
542             AddToTLDataStrW(tld, wszOpenBrackets2);
543             wsprintfW(wszText, wszFormat, pFuncDesc->memid);
544             AddToTLDataStrW(tld, wszText);
545             AddToTLDataStrW(tld, wszCloseBrackets2);
546             memset(wszText, 0, sizeof(wszText));
547         }
548 
549         CreateTypeInfo(wszText, wszAfter, pFuncDesc->elemdescFunc.tdesc, pTypeInfo);
550         switch(pFuncDesc->invkind)
551         {
552             case INVOKE_PROPERTYGET:
553                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
554                 else
555                 {
556                     AddToTLDataStrW(tld, wszComa);
557                     AddToTLDataStrW(tld, wszSpace);
558                 }
559                 bFirst = FALSE;
560                 AddToTLDataStrW(tld, wszPropGet);
561                 break;
562             case INVOKE_PROPERTYPUT:
563                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
564                 else
565                 {
566                     AddToTLDataStrW(tld, wszComa);
567                     AddToTLDataStrW(tld, wszSpace);
568                 }
569                 bFirst = FALSE;
570                 AddToTLDataStrW(tld, wszPropPut);
571                 break;
572             case INVOKE_PROPERTYPUTREF:
573                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
574                 else
575                 {
576                     AddToTLDataStrW(tld, wszComa);
577                     AddToTLDataStrW(tld, wszSpace);
578                 }
579                 bFirst = FALSE;
580                 AddToTLDataStrW(tld, wszPropPutRef);
581                 break;
582             default:;
583         }
584         if(SysStringLen(bstrHelpString))
585         {
586             if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
587             else
588             {
589                 AddToTLDataStrW(tld, wszComa);
590                 AddToTLDataStrW(tld, wszSpace);
591             }
592             bFirst = FALSE;
593             AddToTLDataStrW(tld, wszHelpstring);
594             AddToTLDataStrW(tld, wszOpenBrackets2);
595             AddToTLDataStrW(tld, wszInvertedComa);
596             AddToTLDataStrW(tld, bstrHelpString);
597             AddToTLDataStrW(tld, wszInvertedComa);
598             AddToTLDataStrW(tld, wszCloseBrackets2);
599         }
600         if(!bFirst)
601         {
602             AddToTLDataStrW(tld, wszCloseBrackets1);
603             AddToTLDataStrW(tld, wszNewLine);
604         }
605 
606         if(pTypeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION) {
607             AddToTLDataStrW(tld, wszVT_HRESULT);
608             if(strcmpW(wszText, wszVT_VOID)) pFuncDesc->cParams++;
609         }
610         else {
611             AddToTLDataStrW(tld, wszText);
612             AddToTLDataStrW(tld, wszAfter);
613         }
614 
615         bstrParamNames = HeapAlloc(GetProcessHeap(), 0,
616                 sizeof(BSTR*)*(pFuncDesc->cParams+1));
617         if(FAILED(ITypeInfo_GetNames(pTypeInfo, pFuncDesc->memid, bstrParamNames,
618                 pFuncDesc->cParams+1, &namesNo)))
619         {
620             HeapFree(GetProcessHeap(), 0, bstrParamNames);
621             continue;
622         }
623         SysFreeString(bstrParamNames[0]);
624 
625         AddToTLDataStrW(tld, wszSpace);
626         if(pFuncDesc->memid >= MIN_FUNC_ID)
627         {
628             AddToTLDataStrW(tld, wszStdCall);
629             AddToTLDataStrW(tld, wszSpace);
630         }
631         AddToTLDataStrW(tld, bstrName);
632         AddToTLDataStrW(tld, wszOpenBrackets2);
633 
634         for(j=0; j<pFuncDesc->cParams; j++)
635         {
636             if(j != 0) AddToTLDataStrW(tld, wszComa);
637             if(pFuncDesc->cParams != 1)
638             {
639                 AddToTLDataStrW(tld, wszNewLine);
640                 AddSpaces(tld, TAB_SIZE);
641             }
642             bFirst = TRUE;
643 #define ENUM_PARAM_FLAG(x)\
644             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & x) \
645             {\
646                 if(bFirst) AddToTLDataStrW(tld,\
647                         wszOpenBrackets1);\
648                 else\
649                 {\
650                     AddToTLDataStrW(tld, wszComa);\
651                     AddToTLDataStrW(tld, wszSpace);\
652                 }\
653                 bFirst = FALSE;\
654                 AddToTLDataStrW(tld, wsz##x);\
655             }
656             ENUM_PARAM_FLAG(PARAMFLAG_FIN);
657             ENUM_PARAM_FLAG(PARAMFLAG_FOUT);
658             ENUM_PARAM_FLAG(PARAMFLAG_FLCID);
659             ENUM_PARAM_FLAG(PARAMFLAG_FRETVAL);
660             ENUM_PARAM_FLAG(PARAMFLAG_FOPT);
661             ENUM_PARAM_FLAG(PARAMFLAG_FHASCUSTDATA);
662 
663             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
664             {
665                 VARIANT var, *param=&U(pFuncDesc->lprgelemdescParam[j]).paramdesc.pparamdescex->varDefaultValue;
666                 VariantInit(&var);
667                 if(bFirst) AddToTLDataStrW(tld,
668                         wszOpenBrackets1);
669                 else
670                 {
671                     AddToTLDataStrW(tld, wszComa);
672                     AddToTLDataStrW(tld, wszSpace);
673                 }
674                 bFirst = FALSE;
675                 AddToTLDataStrW(tld, wszDefaultValue);
676                 AddToTLDataStrW(tld, wszOpenBrackets2);
677                 if (V_VT(param) == VT_BSTR)
678                 {
679                     AddToTLDataStrW(tld, wszInvertedComa);
680                     AddToTLDataStrW(tld, V_BSTR(param));
681                     AddToTLDataStrW(tld, wszInvertedComa);
682                 } else if (VariantChangeType(&var, param, 0, VT_BSTR) == S_OK)
683                     AddToTLDataStrW(tld, V_BSTR(&var));
684                 AddToTLDataStrW(tld, wszCloseBrackets2);
685             }
686 
687             if(!bFirst)
688             {
689                 AddToTLDataStrW(tld, wszCloseBrackets1);
690                 AddToTLDataStrW(tld, wszSpace);
691             }
692 
693             memset(wszText, 0, sizeof(wszText));
694             memset(wszAfter, 0, sizeof(wszAfter));
695             CreateTypeInfo(wszText, wszAfter, pFuncDesc->lprgelemdescParam[j].tdesc,
696                     pTypeInfo);
697             AddToTLDataStrW(tld, wszText);
698             AddToTLDataStrW(tld, wszAfter);
699             AddToTLDataStrW(tld, wszSpace);
700             if (j+1 < namesNo) {
701                 AddToTLDataStrW(tld, bstrParamNames[j+1]);
702                 SysFreeString(bstrParamNames[j+1]);
703             } else {
704                 AddToTLDataStrW(tld, szRhs);
705             }
706         }
707         AddToTLDataStrW(tld, wszCloseBrackets2);
708         AddToTLDataStrW(tld, wszSemicolon);
709         AddToTLDataStrW(tld, wszNewLine);
710 
711         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
712         HeapFree(GetProcessHeap(), 0, bstrParamNames);
713         SysFreeString(bstrName);
714         SysFreeString(bstrHelpString);
715         ITypeInfo_ReleaseFuncDesc(pTypeInfo, pFuncDesc);
716     }
717 
718     return 0;
719 }
720 
721 static int EnumImplTypes(ITypeInfo *pTypeInfo, int cImplTypes, HTREEITEM hParent)
722 {
723     int i;
724     TVINSERTSTRUCT tvis;
725     ITypeInfo *pRefTypeInfo;
726     HREFTYPE hRefType;
727     TYPEATTR *pTypeAttr;
728     BSTR bstrName;
729     WCHAR wszInheritedInterfaces[MAX_LOAD_STRING];
730 
731     if(!cImplTypes) return 0;
732 
733     LoadString(globals.hMainInst, IDS_INHERITINTERFACES, wszInheritedInterfaces,
734             sizeof(WCHAR[MAX_LOAD_STRING]));
735 
736     U(tvis).item.mask = TVIF_TEXT;
737     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
738     U(tvis).item.pszText = wszInheritedInterfaces;
739     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
740     tvis.hParent = hParent;
741 
742     tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
743 
744     for(i=0; i<cImplTypes; i++)
745     {
746         if(FAILED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, i, &hRefType))) continue;
747         if(FAILED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
748             continue;
749         if(FAILED(ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
750                 NULL, NULL, NULL)))
751         {
752             ITypeInfo_Release(pRefTypeInfo);
753             continue;
754         }
755         if(FAILED(ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr)))
756         {
757             ITypeInfo_Release(pRefTypeInfo);
758             continue;
759         }
760 
761         U(tvis).item.cchTextMax = SysStringLen(bstrName);
762         U(tvis).item.pszText = bstrName;
763 
764         hParent = TreeView_InsertItem(typelib.hTree, &tvis);
765         EnumVars(pRefTypeInfo, pTypeAttr->cVars, hParent);
766         EnumFuncs(pRefTypeInfo, pTypeAttr, hParent);
767         EnumImplTypes(pRefTypeInfo, pTypeAttr->cImplTypes, hParent);
768 
769         SysFreeString(bstrName);
770         ITypeInfo_ReleaseTypeAttr(pRefTypeInfo, pTypeAttr);
771         ITypeInfo_Release(pRefTypeInfo);
772     }
773 
774     return 0;
775 }
776 
777 static void EnumCoclassImplTypes(ITypeInfo *pTypeInfo,
778         int cImplTypes, TYPELIB_DATA *pTLData)
779 {
780     int i;
781     ITypeInfo *pRefTypeInfo;
782     HREFTYPE hRefType;
783     TYPEATTR *pTypeAttr;
784     BSTR bstrName;
785     BOOL bFirst;
786     INT flags;
787     const WCHAR wszTKIND_INTERFACE[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
788     const WCHAR wszTKIND_DISPATCH[]
789         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
790     const WCHAR wszIMPLTYPEFLAG_FDEFAULT[]
791         = { 'd','e','f','a','u','l','t','\0' };
792     const WCHAR wszIMPLTYPEFLAG_FSOURCE[]
793         = { 's','o','u','r','c','e','\0' };
794     const WCHAR wszIMPLTYPEFLAG_FRESTRICTED[]
795         = { 'r','e','s','t','r','i','c','t','e','d','\0' };
796 
797     for(i=0; i<cImplTypes; i++)
798     {
799         if(FAILED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, i, &hRefType))) continue;
800         if(FAILED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
801             continue;
802         if(FAILED(ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
803                         NULL, NULL, NULL)))
804         {
805             ITypeInfo_Release(pRefTypeInfo);
806             continue;
807         }
808         if(FAILED(ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr)))
809         {
810             ITypeInfo_Release(pRefTypeInfo);
811             continue;
812         }
813 
814         AddSpaces(pTLData, TAB_SIZE);
815         ITypeInfo_GetImplTypeFlags(pTypeInfo, i, &flags);
816         bFirst = TRUE;
817 #define ENUM_IMPLTYPEFLAG(x)\
818         if(flags & x) \
819         {\
820             if(bFirst) AddToTLDataStrW(pTLData,\
821                     wszOpenBrackets1);\
822             else\
823             {\
824                 AddToTLDataStrW(pTLData, wszComa);\
825                 AddToTLDataStrW(pTLData, wszSpace);\
826             }\
827             bFirst = FALSE;\
828             AddToTLDataStrW(pTLData, wsz##x);\
829         }
830         ENUM_IMPLTYPEFLAG(IMPLTYPEFLAG_FDEFAULT);
831         ENUM_IMPLTYPEFLAG(IMPLTYPEFLAG_FSOURCE);
832         ENUM_IMPLTYPEFLAG(IMPLTYPEFLAG_FRESTRICTED);
833         if(!bFirst)
834         {
835             AddToTLDataStrW(pTLData, wszCloseBrackets1);
836             AddToTLDataStrW(pTLData, wszSpace);
837         }
838 
839         if(pTypeAttr->typekind == TKIND_INTERFACE ||
840                 (pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL))
841             AddToTLDataStrW(pTLData, wszTKIND_INTERFACE);
842         else if(pTypeAttr->typekind == TKIND_DISPATCH)
843             AddToTLDataStrW(pTLData, wszTKIND_DISPATCH);
844         AddToTLDataStrW(pTLData, wszSpace);
845 
846         AddToTLDataStrW(pTLData, bstrName);
847         AddToTLDataStrW(pTLData, wszSemicol