user32/tests: Remove some explicit LPARAM/WPARAM casts.
[wine] / programs / oleview / typelib.c
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[] = { '0','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(wszTitle)/sizeof(wszTitle[0]));
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 static void AddToStrW(WCHAR *wszDest, const WCHAR *wszSource)
193 {
194     lstrcpyW(&wszDest[lstrlenW(wszDest)], wszSource);
195 }
196
197 static 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 static void AddToTLDataStrWithTabsW(TYPELIB_DATA *pTLData, WCHAR *wszSource)
209 {
210     int lineLen = lstrlenW(wszSource);
211     int newLinesNo = 0;
212     WCHAR *pSourcePos = 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 = wszSource;
227     pSourceBeg = 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 = 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 = 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 = 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(wszInheritedInterfaces)/sizeof(wszInheritedInterfaces[0]));
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 = 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, wszSemicolon);
848         AddToTLDataStrW(pTLData, wszNewLine);
849
850         SysFreeString(bstrName);
851         ITypeInfo_ReleaseTypeAttr(pRefTypeInfo, pTypeAttr);
852         ITypeInfo_Release(pRefTypeInfo);
853     }
854 }
855
856 static void AddIdlData(HTREEITEM hCur, TYPELIB_DATA *pTLData)
857 {
858     TVITEM tvi;
859
860     hCur = TreeView_GetChild(typelib.hTree, hCur);
861     memset(&tvi, 0, sizeof(TVITEM));
862     tvi.mask = TVIF_PARAM;
863
864     while(hCur)
865     {
866         tvi.hItem = hCur;
867         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
868         if(!((TYPELIB_DATA*)(tvi.lParam))->bHide) {
869             AddToTLDataStrW(pTLData, wszNewLine);
870             AddToTLDataStrWithTabsW(pTLData, ((TYPELIB_DATA*)(tvi.lParam))->idl);
871         }
872         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
873     }
874 }
875
876 static void AddPredefinitions(HTREEITEM hFirst, TYPELIB_DATA *pTLData)
877 {
878     HTREEITEM hCur;
879     TVITEM tvi;
880     WCHAR wszText[MAX_LOAD_STRING];
881     WCHAR wszPredefinition[] = { '/','/',' ','T','L','i','b',' ',':','\n',
882         '/','/',' ','F','o','r','w','a','r','d',' ','d','e','c','l','a','r','e',' ',
883         'a','l','l',' ','t','y','p','e','s',' ','d','e','f','i','n','e','d',' ',
884         'i','n',' ','t','h','i','s',' ','t','y','p','e','l','i','b','\0' };
885
886     hFirst = TreeView_GetChild(typelib.hTree, hFirst);
887
888     AddToTLDataStrWithTabsW(pTLData, wszPredefinition);
889     AddToTLDataStrW(pTLData, wszNewLine);
890
891     hCur = hFirst;
892     memset(&tvi, 0, sizeof(TVITEM));
893     tvi.mask = TVIF_TEXT|TVIF_PARAM;
894     tvi.cchTextMax = MAX_LOAD_STRING;
895     tvi.pszText = wszText;
896     while(hCur)
897     {
898         tvi.hItem = hCur;
899         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
900         if(((TYPELIB_DATA*)(tvi.lParam))->bPredefine &&
901                 !((TYPELIB_DATA*)(tvi.lParam))->bHide)
902         {
903             AddToStrW(wszText, wszSemicolon);
904             AddToTLDataStrWithTabsW(pTLData, wszText);
905             AddToTLDataStrW(pTLData, wszNewLine);
906         }
907         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
908     }
909 }
910
911 static void CreateInterfaceInfo(ITypeInfo *pTypeInfo, int cImplTypes, WCHAR *wszName,
912         WCHAR *wszHelpString, unsigned long ulHelpContext, TYPEATTR *pTypeAttr,
913         TYPELIB_DATA *pTLData)
914 {
915     ITypeInfo *pRefTypeInfo;
916     HREFTYPE hRefType;
917     BSTR bstrName;
918     WCHAR wszGuid[MAX_LOAD_STRING];
919     WCHAR wszHelpContext[MAX_LOAD_STRING];
920
921     const WCHAR wszInterface[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
922     const WCHAR wszDispinterface[]
923         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
924     const WCHAR wszHelpcontext[] = { 'h','e','l','p','c','o','n','t','e','x','t','\0' };
925     const WCHAR wszTYPEFLAG_FAPPOBJECT[] = { 'a','p','p','o','b','j','e','c','t','\0' };
926     const WCHAR wszTYPEFLAG_FCANCREATE[] = { 'c','a','n','c','r','e','a','t','e','\0' };
927     const WCHAR wszTYPEFLAG_FLICENSED[] = { 'l','i','c','e','n','s','e','d','\0' };
928     const WCHAR wszTYPEFLAG_FPREDECLID[] = { 'p','r','e','d','e','c','l','i','d','\0' };
929     const WCHAR wszTYPEFLAG_FHIDDEN[] = { 'h','i','d','d','e','n','\0' };
930     const WCHAR wszTYPEFLAG_FCONTROL[] = { 'c','o','n','t','r','o','l','\0' };
931     const WCHAR wszTYPEFLAG_FDUAL[] = { 'd','u','a','l','\0' };
932     const WCHAR wszTYPEFLAG_FNONEXTENSIBLE[]
933         = { 'n','o','n','e','x','t','e','n','s','i','b','l','e','\0' };
934     const WCHAR wszTYPEFLAG_FOLEAUTOMATION[]
935         = { 'o','l','e','a','u','t','o','m','a','t','i','o','n','\0' };
936     const WCHAR wszTYPEFLAG_FRESTRICTED[]
937         = { 'r','e','s','t','r','i','c','t','e','d','\0' };
938     const WCHAR wszTYPEFLAG_FAGGREGATABLE[]
939         = { 'a','g','g','r','e','g','a','t','a','b','l','e','\0' };
940     const WCHAR wszTYPEFLAG_FREPLACEABLE[]
941         = { 'r','e','p','l','a','c','a','b','l','e','\0' };
942     const WCHAR wszTYPEFLAG_FREVERSEBIND[]
943         = { 'r','e','v','e','r','s','e','b','i','n','d','\0' };
944     const WCHAR wszTYPEFLAG_FPROXY[] = { 'p','r','o','x','y','\0' };
945
946     AddToTLDataStrW(pTLData, wszOpenBrackets1);
947     AddToTLDataStrW(pTLData, wszNewLine);
948     if(pTypeAttr->typekind != TKIND_DISPATCH)
949     {
950         AddSpaces(pTLData, TAB_SIZE);
951         AddToTLDataStrW(pTLData, wszOdl);
952         AddToTLDataStrW(pTLData, wszComa);
953         AddToTLDataStrW(pTLData, wszNewLine);
954     }
955     AddSpaces(pTLData, TAB_SIZE);
956     AddToTLDataStrW(pTLData, wszUUID);
957     AddToTLDataStrW(pTLData, wszOpenBrackets2);
958     StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
959     wszGuid[lstrlenW(wszGuid)-1] = '\0';
960     AddToTLDataStrW(pTLData, &wszGuid[1]);
961     AddToTLDataStrW(pTLData, wszCloseBrackets2);
962     if(wszHelpString)
963     {
964         AddToTLDataStrW(pTLData, wszComa);
965         AddToTLDataStrW(pTLData, wszNewLine);
966         AddSpaces(pTLData, TAB_SIZE);
967         AddToTLDataStrW(pTLData, wszHelpstring);
968         AddToTLDataStrW(pTLData, wszOpenBrackets2);
969         AddToTLDataStrW(pTLData, wszInvertedComa);
970         AddToTLDataStrW(pTLData, wszHelpString);
971         AddToTLDataStrW(pTLData, wszInvertedComa);
972         AddToTLDataStrW(pTLData, wszCloseBrackets2);
973     }
974     if(ulHelpContext)
975     {
976         AddToTLDataStrW(pTLData, wszComa);
977         AddToTLDataStrW(pTLData, wszNewLine);
978         AddSpaces(pTLData, TAB_SIZE);
979         AddToTLDataStrW(pTLData, wszHelpcontext);
980         AddToTLDataStrW(pTLData, wszOpenBrackets2);
981         wsprintfW(wszHelpContext, wszFormat, ulHelpContext);
982         AddToTLDataStrW(pTLData, wszHelpContext);
983         AddToTLDataStrW(pTLData, wszCloseBrackets2);
984     }
985     if(pTypeAttr->wTypeFlags)
986     {
987 #define ENUM_FLAGS(x) if(pTypeAttr->wTypeFlags & x)\
988         {\
989             AddToTLDataStrW(pTLData, wszComa);\
990             AddToTLDataStrW(pTLData, wszNewLine);\
991             AddSpaces(pTLData, TAB_SIZE);\
992             AddToTLDataStrW(pTLData, wsz##x);\
993         }
994         ENUM_FLAGS(TYPEFLAG_FAPPOBJECT);
995         ENUM_FLAGS(TYPEFLAG_FCANCREATE);
996         ENUM_FLAGS(TYPEFLAG_FLICENSED);
997         ENUM_FLAGS(TYPEFLAG_FPREDECLID);
998         ENUM_FLAGS(TYPEFLAG_FHIDDEN);
999         ENUM_FLAGS(TYPEFLAG_FCONTROL);
1000         ENUM_FLAGS(TYPEFLAG_FDUAL);
1001         ENUM_FLAGS(TYPEFLAG_FNONEXTENSIBLE);
1002         ENUM_FLAGS(TYPEFLAG_FOLEAUTOMATION);
1003         ENUM_FLAGS(TYPEFLAG_FRESTRICTED);
1004         ENUM_FLAGS(TYPEFLAG_FAGGREGATABLE);
1005         ENUM_FLAGS(TYPEFLAG_FREPLACEABLE);
1006         ENUM_FLAGS(TYPEFLAG_FREVERSEBIND);
1007         ENUM_FLAGS(TYPEFLAG_FPROXY);
1008     }
1009     AddToTLDataStrW(pTLData, wszNewLine);
1010     AddToTLDataStrW(pTLData, wszCloseBrackets1);
1011     AddToTLDataStrW(pTLData, wszNewLine);
1012     if(pTypeAttr->typekind != TKIND_DISPATCH) AddToTLDataStrW(pTLData, wszInterface);
1013     else AddToTLDataStrW(pTLData, wszDispinterface);
1014     AddToTLDataStrW(pTLData, wszName);
1015     AddToTLDataStrW(pTLData, wszSpace);
1016     if(cImplTypes && pTypeAttr->typekind != TKIND_DISPATCH)
1017     {
1018         AddToTLDataStrW(pTLData, wszColon);
1019         AddToTLDataStrW(pTLData, wszSpace);
1020
1021         ITypeInfo_GetRefTypeOfImplType(pTypeInfo, 0, &hRefType);
1022         if (SUCCEEDED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
1023         {
1024             ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
1025                 NULL, NULL, NULL);
1026             AddToTLDataStrW(pTLData, bstrName);
1027             AddToTLDataStrW(pTLData, wszSpace);
1028
1029             SysFreeString(bstrName);
1030             ITypeInfo_Release(pRefTypeInfo);
1031         }
1032         else
1033             AddToTLDataStrW(pTLData, wszFailed);
1034     }
1035     AddToTLDataStrW(pTLData, wszOpenBrackets3);
1036     AddToTLDataStrW(pTLData, wszNewLine);
1037
1038     AddToStrW(pTLData->wszInsertAfter, wszCloseBrackets3);
1039     AddToStrW(pTLData->wszInsertAfter, wszSemicolon);
1040     AddToStrW(pTLData->wszInsertAfter, wszNewLine);
1041 }
1042
1043 static void CreateTypedefHeader(ITypeInfo *pTypeInfo,
1044         TYPEATTR *pTypeAttr, TYPELIB_DATA *pTLData)
1045 {
1046     BOOL bFirst = TRUE;
1047     WCHAR wszGuid[MAX_LOAD_STRING];
1048     const WCHAR wszTypedef[] = { 't','y','p','e','d','e','f',' ','\0' };
1049     const WCHAR wszPublic[] = { 'p','u','b','l','i','c','\0' };
1050
1051     AddToTLDataStrW(pTLData, wszTypedef);
1052     if(memcmp(&pTypeAttr->guid, &GUID_NULL, sizeof(GUID)))
1053     {
1054         AddToTLDataStrW(pTLData, wszOpenBrackets1);
1055         bFirst = FALSE;
1056         AddToTLDataStrW(pTLData, wszUUID);
1057         AddToTLDataStrW(pTLData, wszOpenBrackets2);
1058         StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
1059         wszGuid[lstrlenW(wszGuid)-1] = '\0';
1060         AddToTLDataStrW(pTLData, &wszGuid[1]);
1061         AddToTLDataStrW(pTLData, wszCloseBrackets2);
1062     }
1063     if(pTypeAttr->typekind == TKIND_ALIAS)
1064     {
1065         if(bFirst) AddToTLDataStrW(pTLData, wszOpenBrackets1);
1066         else
1067         {
1068             AddToTLDataStrW(pTLData, wszComa);
1069             AddToTLDataStrW(pTLData, wszSpace);
1070         }
1071         bFirst = FALSE;
1072         AddToTLDataStrW(pTLData, wszPublic);
1073     }
1074     if(!bFirst)
1075     {
1076         AddToTLDataStrW(pTLData, wszCloseBrackets1);
1077         AddToTLDataStrW(pTLData, wszNewLine);
1078     }
1079 }
1080
1081 static void CreateCoclassHeader(ITypeInfo *pTypeInfo,
1082         TYPEATTR *pTypeAttr, TYPELIB_DATA *pTLData)
1083 {
1084     WCHAR wszGuid[MAX_LOAD_STRING];
1085     BSTR bstrHelpString;
1086     const WCHAR wszNoncreatable[]
1087         = { 'n','o','n','c','r','e','a','t','a','b','l','e','\0' };
1088
1089     AddToTLDataStrW(pTLData, wszOpenBrackets1);
1090     AddToTLDataStrW(pTLData, wszNewLine);
1091
1092     AddSpaces(pTLData, TAB_SIZE);
1093     AddToTLDataStrW(pTLData, wszUUID);
1094     AddToTLDataStrW(pTLData, wszOpenBrackets2);
1095     StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
1096     wszGuid[lstrlenW(wszGuid)-1] = '\0';
1097     AddToTLDataStrW(pTLData, &wszGuid[1]);
1098     AddToTLDataStrW(pTLData, wszCloseBrackets2);
1099
1100     if(SUCCEEDED(ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, NULL,
1101             &bstrHelpString, NULL, NULL)))
1102     {
1103         if(SysStringLen(bstrHelpString))
1104         {
1105             AddToTLDataStrW(pTLData, wszComa);
1106             AddToTLDataStrW(pTLData, wszNewLine);
1107             AddSpaces(pTLData, TAB_SIZE);
1108             AddToTLDataStrW(pTLData, wszHelpstring);
1109             AddToTLDataStrW(pTLData, wszOpenBrackets2);
1110             AddToTLDataStrW(pTLData, wszInvertedComa);
1111             AddToTLDataStrW(pTLData, bstrHelpString);
1112             AddToTLDataStrW(pTLData, wszInvertedComa);
1113             AddToTLDataStrW(pTLData, wszCloseBrackets2);
1114         }
1115         SysFreeString(bstrHelpString);
1116     }
1117
1118     if(!(pTypeAttr->wTypeFlags & TYPEFLAG_FCANCREATE))
1119     {
1120         AddToTLDataStrW(pTLData, wszComa);
1121         AddToTLDataStrW(pTLData, wszNewLine);
1122         AddSpaces(pTLData, TAB_SIZE);
1123         AddToTLDataStrW(pTLData, wszNoncreatable);
1124     }
1125
1126     AddToTLDataStrW(pTLData, wszNewLine);
1127     AddToTLDataStrW(pTLData, wszCloseBrackets1);
1128     AddToTLDataStrW(pTLData, wszNewLine);
1129 }
1130
1131 static int PopulateTree(void)
1132 {
1133     TVINSERTSTRUCT tvis;
1134     TVITEM tvi;
1135     ITypeLib *pTypeLib;
1136     TLIBATTR *pTLibAttr;
1137     ITypeInfo *pTypeInfo, *pRefTypeInfo;
1138     HREFTYPE hRefType;
1139     TYPEATTR *pTypeAttr;
1140     INT count, i;
1141     ULONG ulHelpContext;
1142     BSTR bstrName;
1143     BSTR bstrData;
1144     WCHAR wszText[MAX_LOAD_STRING];
1145     WCHAR wszAfter[MAX_LOAD_STRING];
1146     HRESULT hRes;
1147     HTREEITEM hParent;
1148     HTREEITEM hMain;
1149     BOOL bInsert;
1150     TYPELIB_DATA *tldDispatch;
1151     TYPELIB_DATA *tld;
1152
1153     const WCHAR wszGeneratedInfo[] = { '/','/',' ','G','e','n','e','r','a','t','e','d',
1154         ' ','.','I','D','L',' ','f','i','l','e',' ','(','b','y',' ','t','h','e',' ',
1155         'O','L','E','/','C','O','M',' ','O','b','j','e','c','t',' ',
1156         'V','i','e','w','e','r',')','\n','/','/','\n','/','/',' ',
1157         't','y','p','e','l','i','b',' ','f','i','l','e','n','a','m','e',':',' ','\0'};
1158
1159     const WCHAR wszFormat[] = { '%','s',' ','(','%','s',')','\0' };
1160     const WCHAR wszFormat2[] = { 'v','e','r','s','i','o','n',
1161         '(','%','l','d','.','%','l','d',')','\0' };
1162
1163     const WCHAR wszTKIND_ENUM[] = { 't','y','p','e','d','e','f',' ','e','n','u','m',' ','\0' };
1164     const WCHAR wszTKIND_RECORD[]
1165         = { 't','y','p','e','d','e','f',' ','s','t','r','u','c','t',' ','\0' };
1166     const WCHAR wszTKIND_MODULE[] = { 'm','o','d','u','l','e',' ','\0' };
1167     const WCHAR wszTKIND_INTERFACE[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
1168     const WCHAR wszTKIND_DISPATCH[]
1169         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
1170     const WCHAR wszTKIND_COCLASS[] = { 'c','o','c','l','a','s','s',' ','\0' };
1171     const WCHAR wszTKIND_ALIAS[] = { 't','y','p','e','d','e','f',' ','\0' };
1172     const WCHAR wszTKIND_UNION[]
1173         = { 't','y','p','e','d','e','f',' ','u','n','i','o','n',' ','\0' };
1174
1175     const WCHAR wszLibrary[] = { 'l','i','b','r','a','r','y',' ','\0' };
1176     const WCHAR wszTag[] = { 't','a','g','\0' };
1177
1178     WCHAR wszProperties[] = { 'p','r','o','p','e','r','t','i','e','s','\0' };
1179     WCHAR wszMethods[] = { 'm','e','t','h','o','d','s','\0' };
1180
1181     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
1182     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
1183     U(tvis).item.pszText = wszText;
1184     tvis.hInsertAfter = TVI_LAST;
1185     tvis.hParent = TVI_ROOT;
1186
1187     if(FAILED((hRes = LoadTypeLib(typelib.wszFileName, &pTypeLib))))
1188     {
1189         WCHAR wszMessage[MAX_LOAD_STRING];
1190         WCHAR wszError[MAX_LOAD_STRING];
1191
1192         LoadString(globals.hMainInst, IDS_ERROR_LOADTYPELIB,
1193                 wszError, sizeof(wszError)/sizeof(wszError[0]));
1194         wsprintfW(wszMessage, wszError, typelib.wszFileName, hRes);
1195         MessageBox(globals.hMainWnd, wszMessage, NULL, MB_OK|MB_ICONEXCLAMATION);
1196         return 1;
1197     }
1198     count = ITypeLib_GetTypeInfoCount(pTypeLib);
1199
1200     ITypeLib_GetDocumentation(pTypeLib, -1, &bstrName, &bstrData, NULL, NULL);
1201     ITypeLib_GetLibAttr(pTypeLib, &pTLibAttr);
1202
1203     tld = InitializeTLData();
1204     U(tvis).item.lParam = (LPARAM) tld;
1205     AddToTLDataStrW(tld, wszGeneratedInfo);
1206     AddToTLDataStrW(tld, typelib.wszFileName);
1207     AddToTLDataStrW(tld, wszNewLine);
1208     AddToTLDataStrW(tld, wszNewLine);
1209     AddToTLDataStrW(tld, wszOpenBrackets1);
1210     AddToTLDataStrW(tld, wszNewLine);
1211     AddSpaces(tld, TAB_SIZE);
1212     AddToTLDataStrW(tld, wszUUID);
1213     AddToTLDataStrW(tld, wszOpenBrackets2);
1214     StringFromGUID2(&(pTLibAttr->guid), wszText, MAX_LOAD_STRING);
1215     wszText[lstrlenW(wszText)-1] = '\0';
1216     AddToTLDataStrW(tld, &wszText[1]);
1217     AddToTLDataStrW(tld, wszCloseBrackets2);
1218     AddToTLDataStrW(tld, wszComa);
1219     AddToTLDataStrW(tld, wszNewLine);
1220     AddSpaces(tld, TAB_SIZE);
1221     wsprintfW(wszText, wszFormat2, pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum);
1222     AddToTLDataStrW(tld, wszText);
1223     AddToTLDataStrW(tld, wszComa);
1224     AddToTLDataStrW(tld, wszNewLine);
1225     AddSpaces(tld, TAB_SIZE);
1226     AddToTLDataStrW(tld, wszHelpstring);
1227     AddToTLDataStrW(tld, wszOpenBrackets2);
1228     AddToTLDataStrW(tld, wszInvertedComa);
1229     AddToTLDataStrW(tld, bstrData);
1230     AddToTLDataStrW(tld, wszInvertedComa);
1231     AddToTLDataStrW(tld, wszCloseBrackets2);
1232     AddToTLDataStrW(tld, wszNewLine);
1233     AddToTLDataStrW(tld, wszCloseBrackets1);
1234     AddToTLDataStrW(tld, wszNewLine);
1235     AddToTLDataStrW(tld, wszLibrary);
1236     AddToTLDataStrW(tld, bstrName);
1237     AddToTLDataStrW(tld, wszNewLine);
1238     AddToTLDataStrW(tld, wszOpenBrackets3);
1239     AddToTLDataStrW(tld, wszNewLine);
1240
1241     AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1242     AddToStrW(tld->wszInsertAfter, wszSemicolon);
1243
1244     wsprintfW(wszText, wszFormat, bstrName, bstrData);
1245     SysFreeString(bstrName);
1246     SysFreeString(bstrData);
1247     tvis.hParent = (HTREEITEM)SendMessage(typelib.hTree,
1248             TVM_INSERTITEM, 0, (LPARAM)&tvis);
1249
1250     for(i=0; i<count; i++)
1251     {
1252         bInsert = TRUE;
1253         ITypeLib_GetTypeInfo(pTypeLib, i, &pTypeInfo);
1254
1255         ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, &bstrName, &bstrData,
1256                 &ulHelpContext, NULL);
1257         ITypeInfo_GetTypeAttr(pTypeInfo, &pTypeAttr);
1258
1259         memset(wszText, 0, sizeof(wszText));
1260         memset(wszAfter, 0, sizeof(wszAfter));
1261         tld = InitializeTLData();
1262         U(tvis).item.lParam = (LPARAM)tld;
1263         switch(pTypeAttr->typekind)
1264         {
1265             case TKIND_ENUM:
1266                 AddToStrW(wszText, wszTKIND_ENUM);
1267                 AddToStrW(wszText, bstrName);
1268
1269                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1270                 AddToTLDataStrW(tld, &wszTKIND_ENUM[lstrlenW(wszTKIND_ALIAS)]);
1271                 AddToTLDataStrW(tld, wszOpenBrackets3);
1272                 AddToTLDataStrW(tld,wszNewLine);
1273                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1274                 AddToStrW(tld->wszInsertAfter, wszSpace);
1275                 AddToStrW(tld->wszInsertAfter, bstrName);
1276                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1277                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1278
1279                 bInsert = FALSE;
1280                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1281                 EnumEnums(pTypeInfo, pTypeAttr->cVars, hParent);
1282                 AddChildrenData(hParent, tld);
1283                 AddToTLDataStrW(tld, tld->wszInsertAfter);
1284                 break;
1285             case TKIND_RECORD:
1286                 AddToTLDataStrW(tld, wszTKIND_RECORD);
1287                 AddToTLDataStrW(tld, wszTag);
1288                 AddToTLDataStrW(tld, bstrName);
1289                 AddToTLDataStrW(tld, wszSpace);
1290                 AddToTLDataStrW(tld, wszOpenBrackets3);
1291                 AddToTLDataStrW(tld, wszNewLine);
1292
1293                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1294                 AddToStrW(tld->wszInsertAfter, wszSpace);
1295                 AddToStrW(tld->wszInsertAfter, bstrName);
1296                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1297                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1298
1299                 AddToStrW(wszText, wszTKIND_RECORD);
1300                 AddToStrW(wszText, bstrName);
1301                 break;
1302             case TKIND_MODULE:
1303                 AddToStrW(wszText, wszTKIND_MODULE);
1304                 AddToStrW(wszText, bstrName);
1305                 break;
1306             case TKIND_INTERFACE:
1307                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1308                         bstrData, ulHelpContext, pTypeAttr, tld);
1309                 tld->bPredefine = TRUE;
1310
1311                 AddToStrW(wszText, wszTKIND_INTERFACE);
1312                 AddToStrW(wszText, bstrName);
1313                 break;
1314             case TKIND_COCLASS:
1315                 AddToStrW(wszText, wszTKIND_COCLASS);
1316                 AddToStrW(wszText, bstrName);
1317
1318                 CreateCoclassHeader(pTypeInfo, pTypeAttr, tld);
1319                 AddToTLDataStrW(tld, wszTKIND_COCLASS);
1320                 AddToTLDataStrW(tld, bstrName);
1321                 AddToTLDataStrW(tld, wszSpace);
1322                 AddToTLDataStrW(tld, wszOpenBrackets3);
1323                 AddToTLDataStrW(tld, wszNewLine);
1324
1325                 EnumCoclassImplTypes(pTypeInfo, pTypeAttr->cImplTypes, tld);
1326
1327                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1328                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1329                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1330
1331                 bInsert = FALSE;
1332                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1333                 AddToTLDataStrW(tld, tld->wszInsertAfter);
1334                 break;
1335             case TKIND_UNION:
1336                 AddToStrW(wszText, wszTKIND_UNION);
1337                 AddToStrW(wszText, bstrName);
1338                 break;
1339             case TKIND_DISPATCH:
1340                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1341                         bstrData, ulHelpContext, pTypeAttr, tld);
1342                 tld->bPredefine = TRUE;
1343                 if(pTypeAttr->wTypeFlags & TYPEFLAG_FDUAL)
1344                     tld->bHide = TRUE;
1345                 AddToStrW(wszText, wszTKIND_DISPATCH);
1346                 AddToStrW(wszText, bstrName);
1347
1348                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1349                 hMain = tvis.hParent;
1350                 tldDispatch = tld;
1351
1352                 lstrcpyW(wszText, wszProperties);
1353                 tvis.hParent = hParent;
1354                 tld = InitializeTLData();
1355                 U(tvis).item.lParam = (LPARAM) tld;
1356                 AddToTLDataStrW(tld, wszProperties);
1357                 AddToTLDataStrW(tld, wszColon);
1358                 AddToTLDataStrW(tld, wszNewLine);
1359                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1360                 EnumVars(pTypeInfo, pTypeAttr->cVars, tvis.hParent);
1361                 AddChildrenData(tvis.hParent, tld);
1362
1363                 lstrcpyW(wszText, wszMethods);
1364                 tvis.hParent = hParent;
1365                 tld = InitializeTLData();
1366                 U(tvis).item.lParam = (LPARAM) tld;
1367                 AddToTLDataStrW(tld, wszMethods);
1368                 AddToTLDataStrW(tld, wszColon);
1369                 AddToTLDataStrW(tld, wszNewLine);
1370                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1371                 EnumFuncs(pTypeInfo, pTypeAttr, tvis.hParent);
1372                 AddChildrenData(tvis.hParent, tld);
1373
1374                 EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1375                 AddChildrenData(hParent, tldDispatch);
1376                 AddToTLDataStrW(tldDispatch, tldDispatch->wszInsertAfter);
1377
1378                 bInsert = FALSE;
1379                 tvis.hParent = hMain;
1380
1381                 if(SUCCEEDED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, -1, &hRefType)))
1382                 {
1383                     bInsert = TRUE;
1384
1385                     ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1386                     SysFreeString(bstrName);
1387                     SysFreeString(bstrData);
1388
1389                     memset(wszText, 0, sizeof(wszText));
1390                     tld = InitializeTLData();
1391                     U(tvis).item.lParam = (LPARAM) tld;
1392
1393                     ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo);
1394                     ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
1395                                 &bstrData, &ulHelpContext, NULL);
1396                     ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr);
1397
1398                     CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1399                             bstrData, ulHelpContext, pTypeAttr, tld);
1400                     tld->bPredefine = TRUE;
1401
1402                     AddToStrW(wszText, wszTKIND_INTERFACE);
1403                     AddToStrW(wszText, bstrName);
1404                     ITypeInfo_Release(pRefTypeInfo);
1405                 }
1406                 break;
1407             case TKIND_ALIAS:
1408                 AddToStrW(wszText, wszTKIND_ALIAS);
1409                 CreateTypeInfo(wszText, wszAfter, pTypeAttr->tdescAlias, pTypeInfo);
1410                 AddToStrW(wszText, wszSpace);
1411                 AddToStrW(wszText, bstrName);
1412                 AddToStrW(wszText, wszAfter);
1413
1414                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1415                 AddToTLDataStrW(tld, &wszText[lstrlenW(wszTKIND_ALIAS)]);
1416                 AddToTLDataStrW(tld, wszSemicolon);
1417                 AddToTLDataStrW(tld, wszNewLine);
1418                 break;
1419             default:
1420                 lstrcpyW(wszText, bstrName);
1421                 WINE_FIXME("pTypeAttr->typekind == %d not supported\n",
1422                         pTypeAttr->typekind);
1423         }
1424
1425         if(bInsert)
1426         {
1427             hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1428
1429             EnumVars(pTypeInfo, pTypeAttr->cVars, hParent);
1430             EnumFuncs(pTypeInfo, pTypeAttr, hParent);
1431             EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1432
1433             if(memcmp(bstrName, wszVT_UNKNOWN, sizeof(wszVT_UNKNOWN)))
1434                 AddChildrenData(hParent, tld);
1435             AddToTLDataStrW(tld, tld->wszInsertAfter);
1436         }
1437
1438         ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1439         ITypeInfo_Release(pTypeInfo);
1440         SysFreeString(bstrName);
1441         SysFreeString(bstrData);
1442     }
1443     SendMessage(typelib.hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
1444
1445     memset(&tvi, 0, sizeof(TVITEM));
1446     tvi.mask = TVIF_PARAM;
1447     tvi.hItem = tvis.hParent;
1448
1449     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1450     AddPredefinitions(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1451     AddIdlData(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1452     AddToTLDataStrW((TYPELIB_DATA*)(tvi.lParam),
1453             ((TYPELIB_DATA*)(tvi.lParam))->wszInsertAfter);
1454
1455     ITypeLib_Release(pTypeLib);
1456     return 0;
1457 }
1458
1459 void UpdateData(HTREEITEM item)
1460 {
1461     TVITEM tvi;
1462
1463     memset(&tvi, 0, sizeof(TVITEM));
1464     tvi.mask = TVIF_PARAM;
1465     tvi.hItem = item;
1466
1467     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1468     if(!tvi.lParam)
1469     {
1470         SetWindowText(typelib.hEdit, wszSpace);
1471         return;
1472     }
1473
1474     SetWindowText(typelib.hEdit, ((TYPELIB_DATA*)tvi.lParam)->idl);
1475 }
1476
1477 static void TypeLibResizeChild(void)
1478 {
1479     RECT client, stat;
1480
1481     MoveWindow(typelib.hStatusBar, 0, 0, 0, 0, TRUE);
1482
1483     if(IsWindowVisible(typelib.hStatusBar))
1484         GetClientRect(typelib.hStatusBar, &stat);
1485     else stat.bottom = 0;
1486
1487     GetClientRect(globals.hTypeLibWnd, &client);
1488     MoveWindow(typelib.hPaneWnd, 0, 0,
1489             client.right, client.bottom-stat.bottom, TRUE);
1490 }
1491
1492 static void TypeLibMenuCommand(WPARAM wParam, HWND hWnd)
1493 {
1494     BOOL vis;
1495
1496     switch(wParam)
1497     {
1498         case IDM_SAVEAS:
1499             GetSaveIdlAsPath();
1500             break;
1501         case IDM_STATUSBAR:
1502             vis = IsWindowVisible(typelib.hStatusBar);
1503             ShowWindow(typelib.hStatusBar, vis ? SW_HIDE : SW_SHOW);
1504             CheckMenuItem(GetMenu(hWnd), LOWORD(wParam),
1505                     vis ? MF_UNCHECKED : MF_CHECKED);
1506             TypeLibResizeChild();
1507             break;
1508         case IDM_CLOSE:
1509             DestroyWindow(hWnd);
1510             break;
1511     }
1512 }
1513
1514 static void UpdateTypeLibStatusBar(int itemID)
1515 {
1516     WCHAR info[MAX_LOAD_STRING];
1517
1518     if(!LoadString(globals.hMainInst, itemID, info, sizeof(info)/sizeof(info[0])))
1519         LoadString(globals.hMainInst, IDS_READY, info, sizeof(info)/sizeof(info[0]));
1520
1521     SendMessage(typelib.hStatusBar, SB_SETTEXT, 0, (LPARAM)info);
1522 }
1523
1524 static void EmptyTLTree(void)
1525 {
1526     HTREEITEM cur, del;
1527     TVITEM tvi;
1528
1529     tvi.mask = TVIF_PARAM;
1530     cur = TreeView_GetChild(typelib.hTree, TVI_ROOT);
1531
1532     while(TRUE)
1533     {
1534         del = cur;
1535         cur = TreeView_GetChild(typelib.hTree, del);
1536
1537         if(!cur) cur = TreeView_GetNextSibling(typelib.hTree, del);
1538         if(!cur) cur = TreeView_GetParent(typelib.hTree, del);
1539
1540         tvi.hItem = del;
1541         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1542         if(tvi.lParam)
1543         {
1544             HeapFree(GetProcessHeap(), 0, ((TYPELIB_DATA *)tvi.lParam)->idl);
1545             HeapFree(GetProcessHeap(), 0, (TYPELIB_DATA *)tvi.lParam);
1546         }
1547
1548         SendMessage(typelib.hTree, TVM_DELETEITEM, 0, (LPARAM)del);
1549
1550         if(!cur) break;
1551     }
1552 }
1553
1554 static LRESULT CALLBACK TypeLibProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1555 {
1556     switch(uMsg)
1557     {
1558         case WM_CREATE:
1559         {
1560             if(!CreatePanedWindow(hWnd, &typelib.hPaneWnd, globals.hMainInst))
1561                 DestroyWindow(hWnd);
1562             typelib.hTree = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
1563                     WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,
1564                     0, 0, 0, 0, typelib.hPaneWnd, (HMENU)TYPELIB_TREE,
1565                     globals.hMainInst, NULL);
1566             typelib.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL,
1567                     WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY|WS_HSCROLL|WS_VSCROLL,
1568                     0, 0, 0, 0, typelib.hPaneWnd, NULL, globals.hMainInst, NULL);
1569
1570             SetLeft(typelib.hPaneWnd, typelib.hTree);
1571             SetRight(typelib.hPaneWnd, typelib.hEdit);
1572
1573             if(PopulateTree()) DestroyWindow(hWnd);
1574             else SetFocus(typelib.hTree);
1575             break;
1576         }
1577         case WM_COMMAND:
1578             TypeLibMenuCommand(LOWORD(wParam), hWnd);
1579         case WM_MENUSELECT:
1580             UpdateTypeLibStatusBar(LOWORD(wParam));
1581             break;
1582         case WM_SETFOCUS:
1583             SetFocus(typelib.hTree);
1584             break;
1585         case WM_SIZE:
1586             if(wParam == SIZE_MINIMIZED) break;
1587             TypeLibResizeChild();
1588             break;
1589         case WM_DESTROY:
1590             EmptyTLTree();
1591             break;
1592         default:
1593             return DefWindowProc(hWnd, uMsg, wParam, lParam);
1594     }
1595     return 0;
1596 }
1597
1598 BOOL TypeLibRegisterClass(void)
1599 {
1600     WNDCLASS wcc;
1601
1602     memset(&wcc, 0, sizeof(WNDCLASS));
1603     wcc.lpfnWndProc = TypeLibProc;
1604     wcc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1605     wcc.lpszMenuName = MAKEINTRESOURCE(IDM_TYPELIB);
1606     wcc.lpszClassName = wszTypeLib;
1607
1608     if(!RegisterClass(&wcc))
1609         return FALSE;
1610
1611     return TRUE;
1612 }
1613
1614 BOOL CreateTypeLibWindow(HINSTANCE hInst, WCHAR *wszFileName)
1615 {
1616     WCHAR wszTitle[MAX_LOAD_STRING];
1617     LoadString(hInst, IDS_TYPELIBTITLE, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0]));
1618
1619     if(wszFileName) lstrcpyW(typelib.wszFileName, wszFileName);
1620     else
1621     {
1622         TVITEM tvi;
1623
1624         memset(&tvi, 0, sizeof(TVITEM));
1625         tvi.hItem = TreeView_GetSelection(globals.hTree);
1626
1627         SendMessage(globals.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1628         lstrcpyW(typelib.wszFileName, ((ITEM_INFO*)tvi.lParam)->path);
1629     }
1630
1631     globals.hTypeLibWnd = CreateWindow(wszTypeLib, wszTitle,
1632             WS_OVERLAPPEDWINDOW|WS_VISIBLE,
1633             CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInst, NULL);
1634     if(!globals.hTypeLibWnd) return FALSE;
1635
1636     typelib.hStatusBar = CreateStatusWindow(WS_VISIBLE|WS_CHILD,
1637             wszTitle, globals.hTypeLibWnd, 0);
1638
1639     TypeLibResizeChild();
1640     return TRUE;
1641 }