oleview: Add safearray type.
[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 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 wszPropPut[] = { 'p','r','o','p','p','u','t','\0' };
85 static const WCHAR wszPropGet[] = { 'p','r','o','p','g','e','t','\0' };
86 static const WCHAR wszPropPutRef[] = { 'p','r','o','p','p','u','t','r','e','f','\0' };
87 static const WCHAR wszPARAMFLAG_FIN[] = { 'i','n','\0' };
88 static const WCHAR wszPARAMFLAG_FOUT[] = { 'o','u','t','\0' };
89 static const WCHAR wszPARAMFLAG_FLCID[] = { 'c','i','d','\0' };
90 static const WCHAR wszPARAMFLAG_FRETVAL[] = { 'r','e','t','v','a','l','\0' };
91 static const WCHAR wszPARAMFLAG_FOPT[] = { 'o','p','t','i','o','n','a','l','\0' };
92 static const WCHAR wszPARAMFLAG_FHASCUSTDATA[]
93     = { 'h','a','s','c','u','s','t','d','a','t','a','\0' };
94 static const WCHAR wszDefaultValue[]
95     = { 'd','e','f','a','u','l','t','v','a','l','u','e','\0' };
96
97 static const WCHAR wszReadOnly[] = { 'r','e','a','d','o','n','l','y','\0' };
98
99 void ShowLastError(void)
100 {
101     DWORD error = GetLastError();
102     LPWSTR lpMsgBuf;
103     WCHAR wszTitle[MAX_LOAD_STRING];
104
105     LoadString(globals.hMainInst, IDS_TYPELIBTITLE, wszTitle,
106             sizeof(WCHAR[MAX_LOAD_STRING]));
107     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
108             NULL, error, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
109     MessageBox(NULL, lpMsgBuf, wszTitle, MB_OK | MB_ICONERROR);
110     LocalFree(lpMsgBuf);
111     return;
112 }
113
114 void SaveIdl(WCHAR *wszFileName)
115 {
116     HTREEITEM hIDL;
117     TVITEM tvi;
118     HANDLE hFile;
119     DWORD dwNumWrite;
120     char *wszIdl;
121
122     hIDL = TreeView_GetChild(typelib.hTree, TVI_ROOT);
123
124     memset(&tvi, 0, sizeof(TVITEM));
125     tvi.hItem = hIDL;
126
127     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
128
129     hFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
130             NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
131     if(hFile == INVALID_HANDLE_VALUE)
132     {
133         ShowLastError();
134         return;
135     }
136
137     wszIdl = HeapAlloc(GetProcessHeap(), 0,
138             sizeof(WCHAR)*((TYPELIB_DATA *)(tvi.lParam))->idlLen);
139     wine_utf8_wcstombs(((TYPELIB_DATA *)(tvi.lParam))->idl,
140             ((TYPELIB_DATA *)(tvi.lParam))->idlLen, wszIdl,
141             ((TYPELIB_DATA *)(tvi.lParam))->idlLen);
142
143     if(!WriteFile(hFile, wszIdl, ((TYPELIB_DATA *)(tvi.lParam))->idlLen,
144                 &dwNumWrite, NULL))
145     {
146                 ShowLastError();
147                 HeapFree(GetProcessHeap(), 0, wszIdl);
148                 return;
149     }
150
151     HeapFree(GetProcessHeap(), 0, wszIdl);
152     SetEndOfFile(hFile);
153     CloseHandle(hFile);
154 }
155
156 void GetSaveIdlAsPath(void)
157 {
158     OPENFILENAME saveidl;
159     WCHAR *pFileName;
160     WCHAR wszPath[MAX_LOAD_STRING];
161     WCHAR wszDir[MAX_LOAD_STRING];
162     static const WCHAR wszDefaultExt[] = { 'i','d','l',0 };
163     static const WCHAR wszIdlFiles[] = { '*','.','i','d','l','\0','\0' };
164
165     memset(&saveidl, 0, sizeof(saveidl));
166
167     lstrcpyW(wszDir, typelib.wszFileName);
168     pFileName = wszDir + lstrlenW(wszDir);
169     while(*pFileName != '.' && *pFileName != '\\' && *pFileName != '/'
170             && pFileName > wszDir) pFileName -= 1;
171     if(*pFileName == '.')
172     {
173         *pFileName = '\0';
174         while(*pFileName != '\\' && *pFileName != '/' && pFileName > wszDir)
175             pFileName -= 1;
176     }
177     if(*pFileName == '\\' || *pFileName == '/') pFileName += 1;
178     lstrcpyW(wszPath, pFileName);
179
180     GetCurrentDirectory(MAX_LOAD_STRING, wszDir);
181
182     saveidl.lStructSize = sizeof(OPENFILENAME);
183     saveidl.hwndOwner = globals.hTypeLibWnd;
184     saveidl.hInstance = globals.hMainInst;
185     saveidl.lpstrFilter = wszIdlFiles;
186     saveidl.lpstrFile = wszPath;
187     saveidl.nMaxFile = MAX_LOAD_STRING;
188     saveidl.lpstrInitialDir = wszDir;
189     saveidl.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
190     saveidl.lpstrDefExt = wszDefaultExt;
191
192     if (GetSaveFileName(&saveidl))
193         SaveIdl(wszPath);
194 }
195
196 void AddToStrW(WCHAR *wszDest, const WCHAR *wszSource)
197 {
198     lstrcpyW(&wszDest[lstrlenW(wszDest)], wszSource);
199 }
200
201 void AddToTLDataStrW(TYPELIB_DATA *pTLData, const WCHAR *wszSource)
202 {
203     int SourceLen = lstrlenW(wszSource);
204
205     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
206             sizeof(WCHAR)*(pTLData->idlLen+SourceLen+1));
207
208     memcpy(&pTLData->idl[pTLData->idlLen], wszSource, sizeof(WCHAR)*(SourceLen+1));
209     pTLData->idlLen += SourceLen;
210 }
211
212 void AddToTLDataStrWithTabsW(TYPELIB_DATA *pTLData, WCHAR *wszSource)
213 {
214     int lineLen = lstrlenW(wszSource);
215     int newLinesNo = 0;
216     WCHAR *pSourcePos = (WCHAR *)wszSource;
217     WCHAR *pSourceBeg;
218
219     if(!lineLen) return;
220     while(*pSourcePos)
221     {
222         if(*pSourcePos == *wszNewLine) newLinesNo++;
223         pSourcePos += 1;
224     }
225     if(*(pSourcePos - 1) != *wszNewLine) newLinesNo++;
226
227     pTLData->idl = HeapReAlloc(GetProcessHeap(), 0, pTLData->idl,
228             sizeof(WCHAR)*(pTLData->idlLen+lineLen+4*newLinesNo+1));
229
230     pSourcePos = (WCHAR *)wszSource;
231     pSourceBeg = (WCHAR *)wszSource;
232     while(newLinesNo)
233     {
234         if(*pSourcePos != *wszNewLine && *pSourcePos)
235         {
236             pSourcePos += 1;
237             continue;
238         }
239         newLinesNo--;
240
241         if(*pSourcePos)
242         {
243             *pSourcePos = '\0';
244             lineLen = lstrlenW(pSourceBeg)+1;
245             *pSourcePos = '\n';
246             pSourcePos += 1;
247         }
248         else lineLen = lstrlenW(pSourceBeg);
249
250         pTLData->idl[pTLData->idlLen] = *wszSpace;
251         pTLData->idl[pTLData->idlLen+1] = *wszSpace;
252         pTLData->idl[pTLData->idlLen+2] = *wszSpace;
253         pTLData->idl[pTLData->idlLen+3] = *wszSpace;
254         memcpy(&pTLData->idl[pTLData->idlLen+4], pSourceBeg, sizeof(WCHAR)*lineLen);
255         pTLData->idlLen += lineLen + 4;
256         pTLData->idl[pTLData->idlLen] = '\0';
257
258         pSourceBeg = pSourcePos;
259     }
260 }
261
262 static TYPELIB_DATA *InitializeTLData(void)
263 {
264     TYPELIB_DATA *pTLData;
265
266     pTLData = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPELIB_DATA));
267
268     memset(pTLData, 0, sizeof(TYPELIB_DATA));
269     pTLData->idl = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR));
270     pTLData->idl[0] = '\0';
271
272     return pTLData;
273 }
274
275 void AddSpaces(TYPELIB_DATA *pTLData, int tabSize)
276 {
277     for(; tabSize>0; tabSize--)
278         AddToTLDataStrW(pTLData, wszSpace);
279 }
280
281 void AddChildrenData(HTREEITEM hParent, TYPELIB_DATA *pData)
282 {
283     HTREEITEM hCur;
284     TVITEM tvi;
285
286     memset(&tvi, 0, sizeof(&tvi));
287
288     hCur = TreeView_GetChild(typelib.hTree, hParent);
289     if(!hCur) return;
290
291     do
292     {
293         tvi.hItem = hCur;
294         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
295         if(tvi.lParam && ((TYPELIB_DATA *)(tvi.lParam))->idlLen)
296             AddToTLDataStrWithTabsW(pData, ((TYPELIB_DATA *)(tvi.lParam))->idl);
297     }while((hCur = TreeView_GetNextSibling(typelib.hTree, hCur)));
298 }
299
300 void CreateTypeInfo(WCHAR *wszAddTo, WCHAR *wszAddAfter, TYPEDESC tdesc, ITypeInfo *pTypeInfo)
301 {
302     int i;
303     BSTR bstrData;
304     HRESULT hRes;
305     ITypeInfo *pRefTypeInfo;
306     WCHAR wszBuf[MAX_LOAD_STRING];
307     WCHAR wszFormat[] = { '[','%','l','u',']','\0' };
308
309     switch(tdesc.vt&VT_TYPEMASK)
310     {
311 #define VTADDTOSTR(x) case x:\
312         AddToStrW(wszAddTo, wsz##x);\
313         break
314         VTADDTOSTR(VT_BOOL);
315         VTADDTOSTR(VT_UI1);
316         VTADDTOSTR(VT_UI2);
317         VTADDTOSTR(VT_UI4);
318         VTADDTOSTR(VT_UI8);
319         VTADDTOSTR(VT_UINT);
320         VTADDTOSTR(VT_I1);
321         VTADDTOSTR(VT_I2);
322         VTADDTOSTR(VT_I4);
323         VTADDTOSTR(VT_I8);
324         VTADDTOSTR(VT_R4);
325         VTADDTOSTR(VT_INT);
326         VTADDTOSTR(VT_BSTR);
327         VTADDTOSTR(VT_CY);
328         VTADDTOSTR(VT_VARIANT);
329         VTADDTOSTR(VT_VOID);
330         VTADDTOSTR(VT_ERROR);
331         VTADDTOSTR(VT_LPSTR);
332         VTADDTOSTR(VT_LPWSTR);
333         VTADDTOSTR(VT_HRESULT);
334         VTADDTOSTR(VT_UNKNOWN);
335         VTADDTOSTR(VT_DISPATCH);
336         VTADDTOSTR(VT_DATE);
337         VTADDTOSTR(VT_R8);
338         case VT_CARRAY:
339         for(i=0; i<U(tdesc).lpadesc->cDims; i++)
340         {
341             wsprintfW(wszBuf, wszFormat, U(tdesc).lpadesc->rgbounds[i].cElements);
342             AddToStrW(wszAddAfter, wszBuf);
343         }
344         CreateTypeInfo(wszAddTo, wszAddAfter, U(tdesc).lpadesc->tdescElem, pTypeInfo);
345         break;
346         case VT_SAFEARRAY:
347         AddToStrW(wszAddTo, wszVT_SAFEARRAY);
348         AddToStrW(wszAddTo, wszOpenBrackets2);
349         CreateTypeInfo(wszAddTo, wszAddAfter, *U(tdesc).lptdesc, pTypeInfo);
350         AddToStrW(wszAddTo, wszCloseBrackets2);
351         break;
352         case VT_PTR:
353         CreateTypeInfo(wszAddTo, wszAddAfter, *U(tdesc).lptdesc, pTypeInfo);
354         AddToStrW(wszAddTo, wszAsterix);
355         break;
356         case VT_USERDEFINED:
357         hRes = ITypeInfo_GetRefTypeInfo(pTypeInfo,
358                 U(tdesc).hreftype, &pRefTypeInfo);
359         if(SUCCEEDED(hRes))
360         {
361             ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL,
362                     &bstrData, NULL, NULL, NULL);
363             AddToStrW(wszAddTo, bstrData);
364             SysFreeString(bstrData);
365             ITypeInfo_Release(pRefTypeInfo);
366         }
367         else AddToStrW(wszAddTo, wszFailed);
368         break;
369         default:
370         WINE_FIXME("tdesc.vt&VT_TYPEMASK == %d not supported\n",
371                 tdesc.vt&VT_TYPEMASK);
372     }
373 }
374
375 int EnumVars(ITypeInfo *pTypeInfo, int cVars, HTREEITEM hParent)
376 {
377     int i;
378     TVINSERTSTRUCT tvis;
379     VARDESC *pVarDesc;
380     BSTR bstrName;
381     WCHAR wszText[MAX_LOAD_STRING];
382     WCHAR wszAfter[MAX_LOAD_STRING];
383
384     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
385     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
386     U(tvis).item.pszText = wszText;
387     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
388     tvis.hParent = hParent;
389
390     for(i=0; i<cVars; i++)
391     {
392         TYPELIB_DATA *tld;
393
394         if(FAILED(ITypeInfo_GetVarDesc(pTypeInfo, i, &pVarDesc))) continue;
395         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pVarDesc->memid, &bstrName,
396                 NULL, NULL, NULL))) continue;
397
398         tld = InitializeTLData();
399         U(tvis).item.lParam = (LPARAM) tld;
400         if(pVarDesc->memid < MIN_VAR_ID)
401         {
402
403             AddToTLDataStrW(tld, wszOpenBrackets1);
404             AddToTLDataStrW(tld, wszId);
405             AddToTLDataStrW(tld, wszOpenBrackets2);
406             wsprintfW(wszText, wszFormat, pVarDesc->memid);
407             AddToTLDataStrW(tld, wszText);
408             memset(wszText, 0, sizeof(wszText));
409             AddToTLDataStrW(tld, wszCloseBrackets2);
410
411             if(pVarDesc->wVarFlags & VARFLAG_FREADONLY)
412             {
413                 AddToTLDataStrW(tld, wszComa);
414                 AddToTLDataStrW(tld, wszSpace);
415                 AddToTLDataStrW(tld, wszReadOnly);
416             }
417             AddToTLDataStrW(tld, wszCloseBrackets1);
418             AddToTLDataStrW(tld, wszNewLine);
419         }
420
421         memset(wszText, 0, sizeof(wszText));
422         memset(wszAfter, 0, sizeof(wszAfter));
423         CreateTypeInfo(wszText, wszAfter, pVarDesc->elemdescVar.tdesc, pTypeInfo);
424         AddToStrW(wszText, wszSpace);
425         AddToStrW(wszText, bstrName);
426         AddToStrW(wszText, wszAfter);
427         AddToTLDataStrW(tld, wszText);
428         AddToTLDataStrW(tld, wszSemicolon);
429         AddToTLDataStrW(tld, wszNewLine);
430
431         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
432         SysFreeString(bstrName);
433         ITypeInfo_ReleaseVarDesc(pTypeInfo, pVarDesc);
434     }
435
436     return 0;
437 }
438
439 int EnumEnums(ITypeInfo *pTypeInfo, int cVars, HTREEITEM hParent)
440 {
441     int i;
442     TVINSERTSTRUCT tvis;
443     VARDESC *pVarDesc;
444     BSTR bstrName;
445     WCHAR wszText[MAX_LOAD_STRING];
446
447     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
448     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
449     U(tvis).item.pszText = wszText;
450     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
451     tvis.hParent = hParent;
452
453     for(i=0; i<cVars; i++)
454     {
455         TYPELIB_DATA *tld;
456
457         if(FAILED(ITypeInfo_GetVarDesc(pTypeInfo, i, &pVarDesc))) continue;
458         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pVarDesc->memid, &bstrName,
459                 NULL, NULL, NULL))) continue;
460
461         tld = InitializeTLData();
462         U(tvis).item.lParam = (LPARAM) tld;
463
464         memset(wszText, 0, sizeof(wszText));
465         AddToStrW(wszText, bstrName);
466
467         if (pVarDesc->varkind == VAR_CONST)
468         {
469             VARIANT var;
470             VariantInit(&var);
471             if (VariantChangeType(&var, pVarDesc->lpvarValue, 0, VT_BSTR) == S_OK)
472             {
473                 AddToStrW(wszText, wszSpace);
474                 AddToStrW(wszText, wszEquals);
475                 AddToStrW(wszText, wszSpace);
476                 AddToStrW(wszText, V_BSTR(&var));
477             }
478         }
479
480         AddToTLDataStrW(tld, wszText);
481         if (i<cVars-1)
482             AddToTLDataStrW(tld, wszComa);
483         AddToTLDataStrW(tld, wszNewLine);
484
485         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
486         SysFreeString(bstrName);
487         ITypeInfo_ReleaseVarDesc(pTypeInfo, pVarDesc);
488     }
489
490     return 0;
491 }
492
493 int EnumFuncs(ITypeInfo *pTypeInfo, int cFuncs, HTREEITEM hParent)
494 {
495     int i, j, tabSize;
496     unsigned namesNo;
497     TVINSERTSTRUCT tvis;
498     FUNCDESC *pFuncDesc;
499     BSTR bstrName, *bstrParamNames;
500     WCHAR wszText[MAX_LOAD_STRING];
501     WCHAR wszAfter[MAX_LOAD_STRING];
502     WCHAR szRhs[] = {'r','h','s',0};    /* Right-hand side of a propput */
503     BOOL bFirst;
504
505     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
506     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
507     tvis.hParent = hParent;
508
509     for(i=0; i<cFuncs; i++)
510     {
511         TYPELIB_DATA *tld;
512
513         if(FAILED(ITypeInfo_GetFuncDesc(pTypeInfo, i, &pFuncDesc))) continue;
514         if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstrName,
515                 NULL, NULL, NULL))) continue;
516
517         bstrParamNames = HeapAlloc(GetProcessHeap(), 0,
518                 sizeof(BSTR*)*(pFuncDesc->cParams+1));
519         if(FAILED(ITypeInfo_GetNames(pTypeInfo, pFuncDesc->memid, bstrParamNames,
520                 pFuncDesc->cParams+1, &namesNo)))
521         {
522             HeapFree(GetProcessHeap(), 0, bstrParamNames);
523             continue;
524         }
525         SysFreeString(bstrParamNames[0]);
526
527         memset(wszText, 0, sizeof(wszText));
528         memset(wszAfter, 0, sizeof(wszAfter));
529         tld = InitializeTLData();
530         U(tvis).item.cchTextMax = SysStringLen(bstrName);
531         U(tvis).item.pszText = bstrName;
532         U(tvis).item.lParam = (LPARAM) tld;
533         bFirst = TRUE;
534         if(pFuncDesc->memid < MIN_FUNC_ID)
535         {
536             AddToTLDataStrW(tld, wszOpenBrackets1);
537             bFirst = FALSE;
538             AddToTLDataStrW(tld, wszId);
539             AddToTLDataStrW(tld, wszOpenBrackets2);
540             wsprintfW(wszText, wszFormat, pFuncDesc->memid);
541             AddToTLDataStrW(tld, wszText);
542             AddToTLDataStrW(tld, wszCloseBrackets2);
543             memset(wszText, 0, sizeof(wszText));
544         }
545         CreateTypeInfo(wszText, wszAfter, pFuncDesc->elemdescFunc.tdesc, pTypeInfo);
546         switch(pFuncDesc->invkind)
547         {
548             case INVOKE_PROPERTYGET:
549                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
550                 else
551                 {
552                     AddToTLDataStrW(tld, wszComa);
553                     AddToTLDataStrW(tld, wszSpace);
554                 }
555                 bFirst = FALSE;
556                 AddToTLDataStrW(tld, wszPropGet);
557                 break;
558             case INVOKE_PROPERTYPUT:
559                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
560                 else
561                 {
562                     AddToTLDataStrW(tld, wszComa);
563                     AddToTLDataStrW(tld, wszSpace);
564                 }
565                 bFirst = FALSE;
566                 AddToTLDataStrW(tld, wszPropPut);
567                 break;
568             case INVOKE_PROPERTYPUTREF:
569                 if(bFirst) AddToTLDataStrW(tld, wszOpenBrackets1);
570                 else
571                 {
572                     AddToTLDataStrW(tld, wszComa);
573                     AddToTLDataStrW(tld, wszSpace);
574                 }
575                 bFirst = FALSE;
576                 AddToTLDataStrW(tld, wszPropPutRef);
577                 break;
578             default:;
579         }
580         if(!bFirst)
581         {
582             AddToTLDataStrW(tld, wszCloseBrackets1);
583             AddToTLDataStrW(tld, wszNewLine);
584         }
585         AddToTLDataStrW(tld, wszText);
586         AddToTLDataStrW(tld, wszAfter);
587         AddToTLDataStrW(tld, wszSpace);
588         if(pFuncDesc->memid >= MIN_FUNC_ID)
589         {
590             AddToTLDataStrW(tld, wszStdCall);
591             AddToTLDataStrW(tld, wszSpace);
592         }
593         tabSize = tld->idlLen;
594         AddToTLDataStrW(tld, bstrName);
595         AddToTLDataStrW(tld, wszOpenBrackets2);
596
597         for(j=0; j<pFuncDesc->cParams; j++)
598         {
599             if(j != 0) AddToTLDataStrW(tld, wszComa);
600             if(pFuncDesc->cParams != 1)
601             {
602                 AddToTLDataStrW(tld, wszNewLine);
603                 AddSpaces(tld, tabSize);
604             }
605             bFirst = TRUE;
606 #define ENUM_PARAM_FLAG(x)\
607             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & x) \
608             {\
609                 if(bFirst) AddToTLDataStrW(tld,\
610                         wszOpenBrackets1);\
611                 else\
612                 {\
613                     AddToTLDataStrW(tld, wszComa);\
614                     AddToTLDataStrW(tld, wszSpace);\
615                 }\
616                 bFirst = FALSE;\
617                 AddToTLDataStrW(tld, wsz##x);\
618             }
619             ENUM_PARAM_FLAG(PARAMFLAG_FIN);
620             ENUM_PARAM_FLAG(PARAMFLAG_FOUT);
621             ENUM_PARAM_FLAG(PARAMFLAG_FLCID);
622             ENUM_PARAM_FLAG(PARAMFLAG_FRETVAL);
623             ENUM_PARAM_FLAG(PARAMFLAG_FOPT);
624             ENUM_PARAM_FLAG(PARAMFLAG_FHASCUSTDATA);
625
626             if(U(pFuncDesc->lprgelemdescParam[j]).paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
627             {
628                 VARIANT var, *param=&U(pFuncDesc->lprgelemdescParam[j]).paramdesc.pparamdescex->varDefaultValue;
629                 VariantInit(&var);
630                 if(bFirst) AddToTLDataStrW(tld,
631                         wszOpenBrackets1);
632                 else
633                 {
634                     AddToTLDataStrW(tld, wszComa);
635                     AddToTLDataStrW(tld, wszSpace);
636                 }
637                 bFirst = FALSE;
638                 AddToTLDataStrW(tld, wszDefaultValue);
639                 AddToTLDataStrW(tld, wszOpenBrackets2);
640                 if (V_VT(param) == VT_BSTR)
641                 {
642                     AddToTLDataStrW(tld, wszInvertedComa);
643                     AddToTLDataStrW(tld, V_BSTR(&var));
644                     AddToTLDataStrW(tld, wszInvertedComa);
645                 } else if (VariantChangeType(&var, param, 0, VT_BSTR) == S_OK)
646                     AddToTLDataStrW(tld, V_BSTR(&var));
647                 AddToTLDataStrW(tld, wszCloseBrackets2);
648             }
649
650             if(!bFirst)
651             {
652                 AddToTLDataStrW(tld, wszCloseBrackets1);
653                 AddToTLDataStrW(tld, wszSpace);
654             }
655
656             memset(wszText, 0, sizeof(wszText));
657             memset(wszAfter, 0, sizeof(wszAfter));
658             CreateTypeInfo(wszText, wszAfter, pFuncDesc->lprgelemdescParam[j].tdesc,
659                     pTypeInfo);
660             AddToTLDataStrW(tld, wszText);
661             AddToTLDataStrW(tld, wszAfter);
662             AddToTLDataStrW(tld, wszSpace);
663             if (j+1 < namesNo) {
664                 AddToTLDataStrW(tld, bstrParamNames[j+1]);
665                 SysFreeString(bstrParamNames[j+1]);
666             } else {
667                 AddToTLDataStrW(tld, szRhs);
668             }
669         }
670         AddToTLDataStrW(tld, wszCloseBrackets2);
671         AddToTLDataStrW(tld, wszSemicolon);
672         AddToTLDataStrW(tld, wszNewLine);
673
674         SendMessage(typelib.hTree, TVM_INSERTITEM, 0, (LPARAM)&tvis);
675         HeapFree(GetProcessHeap(), 0, bstrParamNames);
676         SysFreeString(bstrName);
677         ITypeInfo_ReleaseFuncDesc(pTypeInfo, pFuncDesc);
678     }
679
680     return 0;
681 }
682
683 int EnumImplTypes(ITypeInfo *pTypeInfo, int cImplTypes, HTREEITEM hParent)
684 {
685     int i;
686     TVINSERTSTRUCT tvis;
687     ITypeInfo *pRefTypeInfo;
688     HREFTYPE hRefType;
689     TYPEATTR *pTypeAttr;
690     BSTR bstrName;
691     WCHAR wszInheritedInterfaces[MAX_LOAD_STRING];
692
693     if(!cImplTypes) return 0;
694
695     LoadString(globals.hMainInst, IDS_INHERITINTERFACES, wszInheritedInterfaces,
696             sizeof(WCHAR[MAX_LOAD_STRING]));
697
698     U(tvis).item.mask = TVIF_TEXT;
699     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
700     U(tvis).item.pszText = wszInheritedInterfaces;
701     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
702     tvis.hParent = hParent;
703
704     tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
705
706     for(i=0; i<cImplTypes; i++)
707     {
708         if(FAILED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, i, &hRefType))) continue;
709         if(FAILED(ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo)))
710             continue;
711         if(FAILED(ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
712                 NULL, NULL, NULL))) continue;
713         if(FAILED(ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr))) continue;
714
715         U(tvis).item.cchTextMax = SysStringLen(bstrName);
716         U(tvis).item.pszText = bstrName;
717
718         hParent = TreeView_InsertItem(typelib.hTree, &tvis);
719         EnumVars(pRefTypeInfo, pTypeAttr->cVars, hParent);
720         EnumFuncs(pRefTypeInfo, pTypeAttr->cFuncs, hParent);
721         EnumImplTypes(pRefTypeInfo, pTypeAttr->cImplTypes, hParent);
722
723         SysFreeString(bstrName);
724         ITypeInfo_ReleaseTypeAttr(pRefTypeInfo, pTypeAttr);
725         ITypeInfo_Release(pRefTypeInfo);
726     }
727
728     return 0;
729 }
730
731 void AddIdlData(HTREEITEM hCur, TYPELIB_DATA *pTLData)
732 {
733     TVITEM tvi;
734
735     hCur = TreeView_GetChild(typelib.hTree, hCur);
736     memset(&tvi, 0, sizeof(TVITEM));
737     tvi.mask = TVIF_PARAM;
738
739     while(hCur)
740     {
741         tvi.hItem = hCur;
742         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
743         AddToTLDataStrW(pTLData, wszNewLine);
744         AddToTLDataStrWithTabsW(pTLData, ((TYPELIB_DATA*)(tvi.lParam))->idl);
745         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
746     }
747 }
748
749 void AddPredefinitions(HTREEITEM hFirst, TYPELIB_DATA *pTLData)
750 {
751     HTREEITEM hCur;
752     TVITEM tvi;
753     WCHAR wszText[MAX_LOAD_STRING];
754     WCHAR wszPredefinition[] = { '/','/',' ','T','L','i','b',' ',':','\n',
755         '/','/',' ','F','o','r','w','a','r','d',' ','d','e','c','l','a','r','e',' ',
756         'a','l','l',' ','t','y','p','e','s',' ','d','e','f','i','n','e','d',' ',
757         'i','n',' ','t','h','i','s',' ','t','y','p','e','l','i','b','\0' };
758
759     hFirst = TreeView_GetChild(typelib.hTree, hFirst);
760
761     AddToTLDataStrWithTabsW(pTLData, wszPredefinition);
762     AddToTLDataStrW(pTLData, wszNewLine);
763
764     hCur = hFirst;
765     memset(&tvi, 0, sizeof(TVITEM));
766     tvi.mask = TVIF_TEXT|TVIF_PARAM;
767     tvi.cchTextMax = MAX_LOAD_STRING;
768     tvi.pszText = wszText;
769     while(hCur)
770     {
771         tvi.hItem = hCur;
772         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
773         if(((TYPELIB_DATA*)(tvi.lParam))->bPredefine)
774         {
775             AddToStrW(wszText, wszSemicolon);
776             AddToTLDataStrWithTabsW(pTLData, wszText);
777             AddToTLDataStrW(pTLData, wszNewLine);
778         }
779         hCur = TreeView_GetNextSibling(typelib.hTree, hCur);
780     }
781 }
782
783 void CreateInterfaceInfo(ITypeInfo *pTypeInfo, int cImplTypes, WCHAR *wszName,
784         WCHAR *wszHelpString, unsigned long ulHelpContext, TYPEATTR *pTypeAttr,
785         TYPELIB_DATA *pTLData)
786 {
787     ITypeInfo *pRefTypeInfo;
788     HREFTYPE hRefType;
789     BSTR bstrName;
790     WCHAR wszGuid[MAX_LOAD_STRING];
791     WCHAR wszHelpContext[MAX_LOAD_STRING];
792
793     const WCHAR wszInterface[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
794     const WCHAR wszDispinterface[]
795         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
796     const WCHAR wszHelpstring[] = { 'h','e','l','p','s','t','r','i','n','g','\0' };
797     const WCHAR wszHelpcontext[] = { 'h','e','l','p','c','o','n','t','e','x','t','\0' };
798     const WCHAR wszTYPEFLAG_FAPPOBJECT[] = { 'a','p','p','o','b','j','e','c','t','\0' };
799     const WCHAR wszTYPEFLAG_FCANCREATE[] = { 'c','a','n','c','r','e','a','t','e','\0' };
800     const WCHAR wszTYPEFLAG_FLICENSED[] = { 'l','i','c','e','n','s','e','d','\0' };
801     const WCHAR wszTYPEFLAG_FPREDECLID[] = { 'p','r','e','d','e','c','l','i','d','\0' };
802     const WCHAR wszTYPEFLAG_FHIDDEN[] = { 'h','i','d','d','e','n','\0' };
803     const WCHAR wszTYPEFLAG_FCONTROL[] = { 'c','o','n','t','r','o','l','\0' };
804     const WCHAR wszTYPEFLAG_FDUAL[] = { 'd','u','a','l','\0' };
805     const WCHAR wszTYPEFLAG_FNONEXTENSIBLE[]
806         = { 'n','o','n','e','x','t','e','n','s','i','b','l','e','\0' };
807     const WCHAR wszTYPEFLAG_FOLEAUTOMATION[]
808         = { 'o','l','e','a','u','t','o','m','a','t','i','o','n','\0' };
809     const WCHAR wszTYPEFLAG_FRESTRICTED[]
810         = { 'r','e','s','t','r','i','c','t','e','d','\0' };
811     const WCHAR wszTYPEFLAG_FAGGREGATABLE[]
812         = { 'a','g','g','r','e','g','a','t','a','b','l','e','\0' };
813     const WCHAR wszTYPEFLAG_FREPLACEABLE[]
814         = { 'r','e','p','l','a','c','a','b','l','e','\0' };
815     const WCHAR wszTYPEFLAG_FREVERSEBIND[]
816         = { 'r','e','v','e','r','s','e','b','i','n','d','\0' };
817     const WCHAR wszTYPEFLAG_FPROXY[] = { 'p','r','o','x','y','\0' };
818
819     AddToTLDataStrW(pTLData, wszOpenBrackets1);
820     AddToTLDataStrW(pTLData, wszNewLine);
821     if(pTypeAttr->typekind != TKIND_DISPATCH)
822     {
823         AddSpaces(pTLData, 4);
824         AddToTLDataStrW(pTLData, wszOdl);
825         AddToTLDataStrW(pTLData, wszComa);
826         AddToTLDataStrW(pTLData, wszNewLine);
827     }
828     AddSpaces(pTLData, 4);
829     AddToTLDataStrW(pTLData, wszUUID);
830     AddToTLDataStrW(pTLData, wszOpenBrackets2);
831     StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
832     wszGuid[lstrlenW(wszGuid)-1] = '\0';
833     AddToTLDataStrW(pTLData, &wszGuid[1]);
834     AddToTLDataStrW(pTLData, wszCloseBrackets2);
835     if(wszHelpString)
836     {
837         AddToTLDataStrW(pTLData, wszComa);
838         AddToTLDataStrW(pTLData, wszNewLine);
839         AddSpaces(pTLData, 4);
840         AddToTLDataStrW(pTLData, wszHelpstring);
841         AddToTLDataStrW(pTLData, wszOpenBrackets2);
842         AddToTLDataStrW(pTLData, wszInvertedComa);
843         AddToTLDataStrW(pTLData, wszHelpString);
844         AddToTLDataStrW(pTLData, wszInvertedComa);
845         AddToTLDataStrW(pTLData, wszCloseBrackets2);
846     }
847     if(ulHelpContext)
848     {
849         AddToTLDataStrW(pTLData, wszComa);
850         AddToTLDataStrW(pTLData, wszNewLine);
851         AddSpaces(pTLData, 4);
852         AddToTLDataStrW(pTLData, wszHelpcontext);
853         AddToTLDataStrW(pTLData, wszOpenBrackets2);
854         wsprintfW(wszHelpContext, wszFormat, ulHelpContext);
855         AddToTLDataStrW(pTLData, wszHelpContext);
856         AddToTLDataStrW(pTLData, wszCloseBrackets2);
857     }
858     if(pTypeAttr->wTypeFlags)
859     {
860 #define ENUM_FLAGS(x) if(pTypeAttr->wTypeFlags & x &&\
861         (pTypeAttr->typekind != TKIND_DISPATCH || x != TYPEFLAG_FDISPATCHABLE))\
862         {\
863             AddToTLDataStrW(pTLData, wszComa);\
864             AddToTLDataStrW(pTLData, wszNewLine);\
865             AddSpaces(pTLData, 4);\
866             AddToTLDataStrW(pTLData, wsz##x);\
867         }
868         ENUM_FLAGS(TYPEFLAG_FAPPOBJECT);
869         ENUM_FLAGS(TYPEFLAG_FCANCREATE);
870         ENUM_FLAGS(TYPEFLAG_FLICENSED);
871         ENUM_FLAGS(TYPEFLAG_FPREDECLID);
872         ENUM_FLAGS(TYPEFLAG_FHIDDEN);
873         ENUM_FLAGS(TYPEFLAG_FCONTROL);
874         ENUM_FLAGS(TYPEFLAG_FDUAL);
875         ENUM_FLAGS(TYPEFLAG_FNONEXTENSIBLE);
876         ENUM_FLAGS(TYPEFLAG_FOLEAUTOMATION);
877         ENUM_FLAGS(TYPEFLAG_FRESTRICTED);
878         ENUM_FLAGS(TYPEFLAG_FAGGREGATABLE);
879         ENUM_FLAGS(TYPEFLAG_FREPLACEABLE);
880         ENUM_FLAGS(TYPEFLAG_FREVERSEBIND);
881         ENUM_FLAGS(TYPEFLAG_FPROXY);
882     }
883     AddToTLDataStrW(pTLData, wszNewLine);
884     AddToTLDataStrW(pTLData, wszCloseBrackets1);
885     AddToTLDataStrW(pTLData, wszNewLine);
886     if(pTypeAttr->typekind != TKIND_DISPATCH) AddToTLDataStrW(pTLData, wszInterface);
887     else AddToTLDataStrW(pTLData, wszDispinterface);
888     AddToTLDataStrW(pTLData, wszName);
889     AddToTLDataStrW(pTLData, wszSpace);
890     if(cImplTypes && pTypeAttr->typekind != TKIND_DISPATCH)
891     {
892         AddToTLDataStrW(pTLData, wszColon);
893         AddToTLDataStrW(pTLData, wszSpace);
894
895         ITypeInfo_GetRefTypeOfImplType(pTypeInfo, 0, &hRefType);
896         ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo);
897         ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
898                 NULL, NULL, NULL);
899         AddToTLDataStrW(pTLData, bstrName);
900         AddToTLDataStrW(pTLData, wszSpace);
901
902         SysFreeString(bstrName);
903         ITypeInfo_Release(pRefTypeInfo);
904     }
905     AddToTLDataStrW(pTLData, wszOpenBrackets3);
906     AddToTLDataStrW(pTLData, wszNewLine);
907
908     AddToStrW(pTLData->wszInsertAfter, wszCloseBrackets3);
909     AddToStrW(pTLData->wszInsertAfter, wszSemicolon);
910     AddToStrW(pTLData->wszInsertAfter, wszNewLine);
911 }
912
913 void CreateTypedefHeader(ITypeInfo *pTypeInfo,
914         TYPEATTR *pTypeAttr, TYPELIB_DATA *pTLData)
915 {
916     BOOL bFirst = TRUE;
917     WCHAR wszGuid[MAX_LOAD_STRING];
918     const WCHAR wszTypedef[] = { 't','y','p','e','d','e','f',' ','\0' };
919     const WCHAR wszPublic[] = { 'p','u','b','l','i','c','\0' };
920
921     AddToTLDataStrW(pTLData, wszTypedef);
922     if(memcmp(&pTypeAttr->guid, &GUID_NULL, sizeof(GUID)))
923     {
924         AddToTLDataStrW(pTLData, wszOpenBrackets1);
925         bFirst = FALSE;
926         AddToTLDataStrW(pTLData, wszUUID);
927         AddToTLDataStrW(pTLData, wszOpenBrackets2);
928         StringFromGUID2(&(pTypeAttr->guid), wszGuid, MAX_LOAD_STRING);
929         wszGuid[lstrlenW(wszGuid)-1] = '\0';
930         AddToTLDataStrW(pTLData, &wszGuid[1]);
931         AddToTLDataStrW(pTLData, wszCloseBrackets2);
932     }
933     if(pTypeAttr->typekind == TKIND_ALIAS)
934     {
935         if(bFirst) AddToTLDataStrW(pTLData, wszOpenBrackets1);
936         else
937         {
938             AddToTLDataStrW(pTLData, wszComa);
939             AddToTLDataStrW(pTLData, wszSpace);
940         }
941         bFirst = FALSE;
942         AddToTLDataStrW(pTLData, wszPublic);
943     }
944     if(!bFirst)
945     {
946         AddToTLDataStrW(pTLData, wszCloseBrackets1);
947         AddToTLDataStrW(pTLData, wszNewLine);
948     }
949 }
950
951 int PopulateTree(void)
952 {
953     TVINSERTSTRUCT tvis;
954     TVITEM tvi;
955     ITypeLib *pTypeLib;
956     TLIBATTR *pTLibAttr;
957     ITypeInfo *pTypeInfo, *pRefTypeInfo;
958     HREFTYPE hRefType;
959     TYPEATTR *pTypeAttr;
960     INT count, i;
961     ULONG ulHelpContext;
962     BSTR bstrName;
963     BSTR bstrData;
964     WCHAR wszText[MAX_LOAD_STRING];
965     WCHAR wszAfter[MAX_LOAD_STRING];
966     HRESULT hRes;
967     HTREEITEM hParent;
968     HTREEITEM hMain;
969     BOOL bInsert;
970     TYPELIB_DATA *tldDispatch;
971     TYPELIB_DATA *tld;
972
973     const WCHAR wszGeneratedInfo[] = { '/','/',' ','G','e','n','e','r','a','t','e','d',
974         ' ','.','I','D','L',' ','f','i','l','e',' ','(','b','y',' ','t','h','e',' ',
975         'O','L','E','/','C','O','M',' ','O','b','j','e','c','t',' ',
976         'V','i','e','w','e','r',')','\n','/','/','\n','/','/',' ',
977         't','y','p','e','l','i','b',' ','f','i','l','e','n','a','m','e',':',' ','\0'};
978
979     const WCHAR wszFormat[] = { '%','s',' ','(','%','s',')','\0' };
980     const WCHAR wszFormat2[] = { 'v','e','r','s','i','o','n',
981         '(','%','l','d','.','%','l','d',')','\0' };
982
983     const WCHAR wszTKIND_ENUM[] = { 't','y','p','e','d','e','f',' ','e','n','u','m',' ','\0' };
984     const WCHAR wszTKIND_RECORD[]
985         = { 't','y','p','e','d','e','f',' ','s','t','r','u','c','t',' ','\0' };
986     const WCHAR wszTKIND_MODULE[] = { 'm','o','d','u','l','e',' ','\0' };
987     const WCHAR wszTKIND_INTERFACE[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
988     const WCHAR wszTKIND_DISPATCH[]
989         = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
990     const WCHAR wszTKIND_COCLASS[] = { 'c','o','c','l','a','s','s',' ','\0' };
991     const WCHAR wszTKIND_ALIAS[] = { 't','y','p','e','d','e','f',' ','\0' };
992     const WCHAR wszTKIND_UNION[]
993         = { 't','y','p','e','d','e','f',' ','u','n','i','o','n',' ','\0' };
994
995     const WCHAR wszHelpString[] = { 'h','e','l','p','s','t','r','i','n','g','\0' };
996     const WCHAR wszLibrary[] = { 'l','i','b','r','a','r','y',' ','\0' };
997     const WCHAR wszTag[] = { 't','a','g','\0' };
998
999     WCHAR wszProperties[] = { 'p','r','o','p','e','r','t','i','e','s','\0' };
1000     WCHAR wszMethods[] = { 'm','e','t','h','o','d','s','\0' };
1001
1002     U(tvis).item.mask = TVIF_TEXT|TVIF_PARAM;
1003     U(tvis).item.cchTextMax = MAX_LOAD_STRING;
1004     U(tvis).item.pszText = wszText;
1005     tvis.hInsertAfter = (HTREEITEM)TVI_LAST;
1006     tvis.hParent = TVI_ROOT;
1007
1008     if(FAILED((hRes = LoadTypeLib(typelib.wszFileName, &pTypeLib))))
1009     {
1010         WCHAR wszMessage[MAX_LOAD_STRING];
1011         WCHAR wszError[MAX_LOAD_STRING];
1012
1013         LoadString(globals.hMainInst, IDS_ERROR_LOADTYPELIB,
1014                 wszError, sizeof(WCHAR[MAX_LOAD_STRING]));
1015         wsprintfW(wszMessage, wszError, typelib.wszFileName, hRes);
1016         MessageBox(globals.hMainWnd, wszMessage, NULL, MB_OK|MB_ICONEXCLAMATION);
1017         return 1;
1018     }
1019     count = ITypeLib_GetTypeInfoCount(pTypeLib);
1020
1021     ITypeLib_GetDocumentation(pTypeLib, -1, &bstrName, &bstrData, NULL, NULL);
1022     ITypeLib_GetLibAttr(pTypeLib, &pTLibAttr);
1023
1024     tld = InitializeTLData();
1025     U(tvis).item.lParam = (LPARAM) tld;
1026     AddToTLDataStrW(tld, wszGeneratedInfo);
1027     AddToTLDataStrW(tld, typelib.wszFileName);
1028     AddToTLDataStrW(tld, wszNewLine);
1029     AddToTLDataStrW(tld, wszNewLine);
1030     AddToTLDataStrW(tld, wszOpenBrackets1);
1031     AddToTLDataStrW(tld, wszNewLine);
1032     AddSpaces(tld, 4);
1033     AddToTLDataStrW(tld, wszUUID);
1034     AddToTLDataStrW(tld, wszOpenBrackets2);
1035     StringFromGUID2(&(pTLibAttr->guid), wszText, MAX_LOAD_STRING);
1036     wszText[lstrlenW(wszText)-1] = '\0';
1037     AddToTLDataStrW(tld, &wszText[1]);
1038     AddToTLDataStrW(tld, wszCloseBrackets2);
1039     AddToTLDataStrW(tld, wszComa);
1040     AddToTLDataStrW(tld, wszNewLine);
1041     AddSpaces(tld, 4);
1042     wsprintfW(wszText, wszFormat2, pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum);
1043     AddToTLDataStrW(tld, wszText);
1044     AddToTLDataStrW(tld, wszComa);
1045     AddToTLDataStrW(tld, wszNewLine);
1046     AddSpaces(tld, 4);
1047     AddToTLDataStrW(tld, wszHelpString);
1048     AddToTLDataStrW(tld, wszOpenBrackets2);
1049     AddToTLDataStrW(tld, wszInvertedComa);
1050     AddToTLDataStrW(tld, bstrData);
1051     AddToTLDataStrW(tld, wszInvertedComa);
1052     AddToTLDataStrW(tld, wszCloseBrackets2);
1053     AddToTLDataStrW(tld, wszNewLine);
1054     AddToTLDataStrW(tld, wszCloseBrackets1);
1055     AddToTLDataStrW(tld, wszNewLine);
1056     AddToTLDataStrW(tld, wszLibrary);
1057     AddToTLDataStrW(tld, bstrName);
1058     AddToTLDataStrW(tld, wszNewLine);
1059     AddToTLDataStrW(tld, wszOpenBrackets3);
1060     AddToTLDataStrW(tld, wszNewLine);
1061
1062     AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1063     AddToStrW(tld->wszInsertAfter, wszSemicolon);
1064
1065     wsprintfW(wszText, wszFormat, bstrName, bstrData);
1066     SysFreeString(bstrName);
1067     SysFreeString(bstrData);
1068     tvis.hParent = (HTREEITEM)SendMessage(typelib.hTree,
1069             TVM_INSERTITEM, 0, (LPARAM)&tvis);
1070
1071     for(i=0; i<count; i++)
1072     {
1073         bInsert = TRUE;
1074         ITypeLib_GetTypeInfo(pTypeLib, i, &pTypeInfo);
1075
1076         ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, &bstrName, &bstrData,
1077                 &ulHelpContext, NULL);
1078         ITypeInfo_GetTypeAttr(pTypeInfo, &pTypeAttr);
1079
1080         memset(wszText, 0, sizeof(wszText));
1081         memset(wszAfter, 0, sizeof(wszAfter));
1082         tld = InitializeTLData();
1083         U(tvis).item.lParam = (LPARAM)tld;
1084         switch(pTypeAttr->typekind)
1085         {
1086             case TKIND_ENUM:
1087                 AddToStrW(wszText, wszTKIND_ENUM);
1088                 AddToStrW(wszText, bstrName);
1089
1090                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1091                 AddToTLDataStrW(tld, &wszTKIND_ENUM[lstrlenW(wszTKIND_ALIAS)]);
1092                 AddToTLDataStrW(tld, wszOpenBrackets3);
1093                 AddToTLDataStrW(tld,wszNewLine);
1094                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1095                 AddToStrW(tld->wszInsertAfter, wszSpace);
1096                 AddToStrW(tld->wszInsertAfter, bstrName);
1097                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1098                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1099
1100                 bInsert = FALSE;
1101                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1102                 EnumEnums(pTypeInfo, pTypeAttr->cVars, hParent);
1103                 AddChildrenData(hParent, tld);
1104                 AddToTLDataStrW(tld, tld->wszInsertAfter);
1105                 break;
1106             case TKIND_RECORD:
1107                 AddToTLDataStrW(tld, wszTKIND_RECORD);
1108                 AddToTLDataStrW(tld, wszTag);
1109                 AddToTLDataStrW(tld, bstrName);
1110                 AddToTLDataStrW(tld, wszSpace);
1111                 AddToTLDataStrW(tld, wszOpenBrackets3);
1112                 AddToTLDataStrW(tld, wszNewLine);
1113
1114                 AddToStrW(tld->wszInsertAfter, wszCloseBrackets3);
1115                 AddToStrW(tld->wszInsertAfter, wszSpace);
1116                 AddToStrW(tld->wszInsertAfter, bstrName);
1117                 AddToStrW(tld->wszInsertAfter, wszSemicolon);
1118                 AddToStrW(tld->wszInsertAfter, wszNewLine);
1119
1120                 AddToStrW(wszText, wszTKIND_RECORD);
1121                 AddToStrW(wszText, bstrName);
1122                 break;
1123             case TKIND_MODULE:
1124                 AddToStrW(wszText, wszTKIND_MODULE);
1125                 AddToStrW(wszText, bstrName);
1126                 break;
1127             case TKIND_INTERFACE:
1128                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1129                         bstrData, ulHelpContext, pTypeAttr, tld);
1130                 tld->bPredefine = TRUE;
1131
1132                 AddToStrW(wszText, wszTKIND_INTERFACE);
1133                 AddToStrW(wszText, bstrName);
1134                 break;
1135             case TKIND_COCLASS:
1136                 AddToStrW(wszText, wszTKIND_COCLASS);
1137                 AddToStrW(wszText, bstrName);
1138                 break;
1139             case TKIND_UNION:
1140                 AddToStrW(wszText, wszTKIND_UNION);
1141                 AddToStrW(wszText, bstrName);
1142                 break;
1143             case TKIND_DISPATCH:
1144                 CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1145                         bstrData, ulHelpContext, pTypeAttr, tld);
1146                 tld->bPredefine = TRUE;
1147                 AddToStrW(wszText, wszTKIND_DISPATCH);
1148                 AddToStrW(wszText, bstrName);
1149
1150                 hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1151                 hMain = tvis.hParent;
1152                 tldDispatch = tld;
1153
1154                 lstrcpyW(wszText, wszProperties);
1155                 tvis.hParent = hParent;
1156                 tld = InitializeTLData();
1157                 U(tvis).item.lParam = (LPARAM) tld;
1158                 AddToTLDataStrW(tld, wszProperties);
1159                 AddToTLDataStrW(tld, wszColon);
1160                 AddToTLDataStrW(tld, wszNewLine);
1161                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1162                 EnumVars(pTypeInfo, pTypeAttr->cVars, tvis.hParent);
1163                 AddChildrenData(tvis.hParent, tld);
1164
1165                 lstrcpyW(wszText, wszMethods);
1166                 tvis.hParent = hParent;
1167                 tld = InitializeTLData();
1168                 U(tvis).item.lParam = (LPARAM) tld;
1169                 AddToTLDataStrW(tld, wszMethods);
1170                 AddToTLDataStrW(tld, wszColon);
1171                 AddToTLDataStrW(tld, wszNewLine);
1172                 tvis.hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1173                 EnumFuncs(pTypeInfo, pTypeAttr->cFuncs, tvis.hParent);
1174                 AddChildrenData(tvis.hParent, tld);
1175
1176                 EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1177                 AddChildrenData(hParent, tldDispatch);
1178                 AddToTLDataStrW(tldDispatch, tldDispatch->wszInsertAfter);
1179
1180                 bInsert = FALSE;
1181                 tvis.hParent = hMain;
1182
1183                 if(SUCCEEDED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo, -1, &hRefType)))
1184                 {
1185                     bInsert = TRUE;
1186
1187                     ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1188                     SysFreeString(bstrName);
1189                     SysFreeString(bstrData);
1190
1191                     memset(wszText, 0, sizeof(wszText));
1192                     tld = InitializeTLData();
1193                     U(tvis).item.lParam = (LPARAM) tld;
1194
1195                     ITypeInfo_GetRefTypeInfo(pTypeInfo, hRefType, &pRefTypeInfo);
1196                     ITypeInfo_GetDocumentation(pRefTypeInfo, MEMBERID_NIL, &bstrName,
1197                                 &bstrData, &ulHelpContext, NULL);
1198                     ITypeInfo_GetTypeAttr(pRefTypeInfo, &pTypeAttr);
1199
1200                     CreateInterfaceInfo(pTypeInfo, pTypeAttr->cImplTypes, bstrName,
1201                             bstrData, ulHelpContext, pTypeAttr, tld);
1202                     tld->bPredefine = TRUE;
1203
1204                     AddToStrW(wszText, wszTKIND_INTERFACE);
1205                     AddToStrW(wszText, bstrName);
1206                     ITypeInfo_Release(pRefTypeInfo);
1207                 }
1208                 break;
1209             case TKIND_ALIAS:
1210                 AddToStrW(wszText, wszTKIND_ALIAS);
1211                 CreateTypeInfo(wszText, wszAfter, pTypeAttr->tdescAlias, pTypeInfo);
1212                 AddToStrW(wszText, wszSpace);
1213                 AddToStrW(wszText, bstrName);
1214                 AddToStrW(wszText, wszAfter);
1215
1216                 CreateTypedefHeader(pTypeInfo, pTypeAttr, tld);
1217                 AddToTLDataStrW(tld, &wszText[lstrlenW(wszTKIND_ALIAS)]);
1218                 AddToTLDataStrW(tld, wszSemicolon);
1219                 AddToTLDataStrW(tld, wszNewLine);
1220                 break;
1221             default:
1222                 lstrcpyW(wszText, bstrName);
1223                 WINE_FIXME("pTypeAttr->typekind == %d not supported\n",
1224                         pTypeAttr->typekind);
1225         }
1226
1227         if(bInsert)
1228         {
1229             hParent = TreeView_InsertItem(typelib.hTree, &tvis);
1230
1231             EnumVars(pTypeInfo, pTypeAttr->cVars, hParent);
1232             EnumFuncs(pTypeInfo, pTypeAttr->cFuncs, hParent);
1233             EnumImplTypes(pTypeInfo, pTypeAttr->cImplTypes, hParent);
1234
1235             if(memcmp(bstrName, wszVT_UNKNOWN, sizeof(wszVT_UNKNOWN)))
1236                 AddChildrenData(hParent, tld);
1237             AddToTLDataStrW(tld, tld->wszInsertAfter);
1238         }
1239
1240         ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
1241         ITypeInfo_Release(pTypeInfo);
1242         SysFreeString(bstrName);
1243         SysFreeString(bstrData);
1244     }
1245     SendMessage(typelib.hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
1246
1247     memset(&tvi, 0, sizeof(TVITEM));
1248     tvi.mask = TVIF_PARAM;
1249     tvi.hItem = tvis.hParent;
1250
1251     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1252     AddPredefinitions(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1253     AddIdlData(tvi.hItem, (TYPELIB_DATA*)(tvi.lParam));
1254     AddToTLDataStrW((TYPELIB_DATA*)(tvi.lParam),
1255             ((TYPELIB_DATA*)(tvi.lParam))->wszInsertAfter);
1256
1257     ITypeLib_Release(pTypeLib);
1258     return 0;
1259 }
1260
1261 void UpdateData(HTREEITEM item)
1262 {
1263     TVITEM tvi;
1264
1265     memset(&tvi, 0, sizeof(TVITEM));
1266     tvi.mask = TVIF_PARAM;
1267     tvi.hItem = item;
1268
1269     SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1270     if(!tvi.lParam)
1271     {
1272         SetWindowText(typelib.hEdit, wszSpace);
1273         return;
1274     }
1275
1276     SetWindowText(typelib.hEdit, ((TYPELIB_DATA*)tvi.lParam)->idl);
1277 }
1278
1279 void TypeLibResizeChild(void)
1280 {
1281     RECT client, stat;
1282
1283     MoveWindow(typelib.hStatusBar, 0, 0, 0, 0, TRUE);
1284
1285     if(IsWindowVisible(typelib.hStatusBar))
1286         GetClientRect(typelib.hStatusBar, &stat);
1287     else stat.bottom = 0;
1288
1289     GetClientRect(globals.hTypeLibWnd, &client);
1290     MoveWindow(typelib.hPaneWnd, 0, 0,
1291             client.right, client.bottom-stat.bottom, TRUE);
1292 }
1293
1294 void TypeLibMenuCommand(WPARAM wParam, HWND hWnd)
1295 {
1296     BOOL vis;
1297
1298     switch(wParam)
1299     {
1300         case IDM_SAVEAS:
1301             GetSaveIdlAsPath();
1302             break;
1303         case IDM_STATUSBAR:
1304             vis = IsWindowVisible(typelib.hStatusBar);
1305             ShowWindow(typelib.hStatusBar, vis ? SW_HIDE : SW_SHOW);
1306             CheckMenuItem(GetMenu(hWnd), LOWORD(wParam),
1307                     vis ? MF_UNCHECKED : MF_CHECKED);
1308             TypeLibResizeChild();
1309             break;
1310         case IDM_CLOSE:
1311             DestroyWindow(hWnd);
1312             break;
1313     }
1314 }
1315
1316 void UpdateTypeLibStatusBar(int itemID)
1317 {
1318     WCHAR info[MAX_LOAD_STRING];
1319
1320     if(!LoadString(globals.hMainInst, itemID, info, sizeof(WCHAR[MAX_LOAD_STRING])))
1321         LoadString(globals.hMainInst, IDS_READY, info, sizeof(WCHAR[MAX_LOAD_STRING]));
1322
1323     SendMessage(typelib.hStatusBar, SB_SETTEXT, 0, (LPARAM)info);
1324 }
1325
1326 void EmptyTLTree(void)
1327 {
1328     HTREEITEM cur, del;
1329     TVITEM tvi;
1330
1331     tvi.mask = TVIF_PARAM;
1332     cur = TreeView_GetChild(typelib.hTree, TVI_ROOT);
1333
1334     while(TRUE)
1335     {
1336         del = cur;
1337         cur = TreeView_GetChild(typelib.hTree, del);
1338
1339         if(!cur) cur = TreeView_GetNextSibling(typelib.hTree, del);
1340         if(!cur) cur = TreeView_GetParent(typelib.hTree, del);
1341
1342         tvi.hItem = del;
1343         SendMessage(typelib.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1344         if(tvi.lParam)
1345         {
1346             HeapFree(GetProcessHeap(), 0, ((TYPELIB_DATA *)tvi.lParam)->idl);
1347             HeapFree(GetProcessHeap(), 0, (TYPELIB_DATA *)tvi.lParam);
1348         }
1349
1350         SendMessage(typelib.hTree, TVM_DELETEITEM, 0, (LPARAM)del);
1351
1352         if(!cur) break;
1353     }
1354 }
1355
1356 LRESULT CALLBACK TypeLibProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1357 {
1358     switch(uMsg)
1359     {
1360         case WM_CREATE:
1361         {
1362             if(!CreatePanedWindow(hWnd, &typelib.hPaneWnd, globals.hMainInst))
1363                 DestroyWindow(hWnd);
1364             typelib.hTree = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
1365                     WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,
1366                     0, 0, 0, 0, typelib.hPaneWnd, (HMENU)TYPELIB_TREE,
1367                     globals.hMainInst, NULL);
1368             typelib.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL,
1369                     WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY|WS_HSCROLL|WS_VSCROLL,
1370                     0, 0, 0, 0, typelib.hPaneWnd, NULL, globals.hMainInst, NULL);
1371
1372             SetLeft(typelib.hPaneWnd, typelib.hTree);
1373             SetRight(typelib.hPaneWnd, typelib.hEdit);
1374
1375             if(PopulateTree()) DestroyWindow(hWnd);
1376             else SetFocus(typelib.hTree);
1377             break;
1378         }
1379         case WM_COMMAND:
1380             TypeLibMenuCommand(LOWORD(wParam), hWnd);
1381         case WM_MENUSELECT:
1382             UpdateTypeLibStatusBar(LOWORD(wParam));
1383             break;
1384         case WM_SETFOCUS:
1385             SetFocus(typelib.hTree);
1386             break;
1387         case WM_SIZE:
1388             if(wParam == SIZE_MINIMIZED) break;
1389             TypeLibResizeChild();
1390             break;
1391         case WM_DESTROY:
1392             EmptyTLTree();
1393             break;
1394         default:
1395             return DefWindowProc(hWnd, uMsg, wParam, lParam);
1396     }
1397     return 0;
1398 }
1399
1400 BOOL TypeLibRegisterClass(void)
1401 {
1402     WNDCLASS wcc;
1403
1404     memset(&wcc, 0, sizeof(WNDCLASS));
1405     wcc.lpfnWndProc = TypeLibProc;
1406     wcc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1407     wcc.lpszMenuName = MAKEINTRESOURCE(IDM_TYPELIB);
1408     wcc.lpszClassName = wszTypeLib;
1409
1410     if(!RegisterClass(&wcc))
1411         return FALSE;
1412
1413     return TRUE;
1414 }
1415
1416 BOOL CreateTypeLibWindow(HINSTANCE hInst, WCHAR *wszFileName)
1417 {
1418     WCHAR wszTitle[MAX_LOAD_STRING];
1419     LoadString(hInst, IDS_TYPELIBTITLE, wszTitle, sizeof(WCHAR[MAX_LOAD_STRING]));
1420
1421     if(wszFileName) lstrcpyW(typelib.wszFileName, wszFileName);
1422     else
1423     {
1424         TVITEM tvi;
1425
1426         memset(&tvi, 0, sizeof(TVITEM));
1427         tvi.hItem = TreeView_GetSelection(globals.hTree);
1428
1429         SendMessage(globals.hTree, TVM_GETITEM, 0, (LPARAM)&tvi);
1430         lstrcpyW(typelib.wszFileName, ((ITEM_INFO*)tvi.lParam)->path);
1431     }
1432
1433     globals.hTypeLibWnd = CreateWindow(wszTypeLib, wszTitle,
1434             WS_OVERLAPPEDWINDOW|WS_VISIBLE,
1435             CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInst, NULL);
1436     if(!globals.hTypeLibWnd) return FALSE;
1437
1438     typelib.hStatusBar = CreateStatusWindow(WS_VISIBLE|WS_CHILD,
1439             (LPWSTR)wszTitle, globals.hTypeLibWnd, 0);
1440
1441     TypeLibResizeChild();
1442     return TRUE;
1443 }