4 * Copyright 2006 Piotr Caban
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.
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.
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
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(oleview
);
28 static const WCHAR wszTypeLib
[] = { 'T','Y','P','E','L','I','B','\0' };
30 static const WCHAR wszFailed
[] = { '<','f','a','i','l','e','d','>','\0' };
31 static const WCHAR wszSpace
[] = { ' ','\0' };
32 static const WCHAR wszAsterix
[] = { '*','\0' };
34 static const WCHAR wszVT_BOOL
[]
35 = { 'V','A','R','I','A','N','T','_','B','O','O','L','\0' };
36 static const WCHAR wszVT_UI1
[]
37 = { 'u','n','s','i','g','n','e','d',' ','c','h','a','r','\0' };
38 static const WCHAR wszVT_UI2
[]
39 = { 'u','n','s','i','g','n','e','d',' ','s','h','o','r','t','\0' };
40 static const WCHAR wszVT_UI4
[]
41 = { 'u','n','s','i','g','n','e','d',' ','l','o','n','g','\0' };
42 static const WCHAR wszVT_UI8
[] = { 'u','i','n','t','6','4','\0' };
43 static const WCHAR wszVT_UINT
[]
44 = { 'u','n','s','i','g','n','e','d',' ','i','n','t','\0' };
45 static const WCHAR wszVT_I1
[] = { 'c','h','a','r','\0' };
46 static const WCHAR wszVT_I2
[] = { 's','h','o','r','t','\0' };
47 static const WCHAR wszVT_I4
[] = { 'l','o','n','g','\0' };
48 static const WCHAR wszVT_I8
[] = { 'i','n','t','6','4','\0' };
49 static const WCHAR wszVT_R4
[] = { 's','i','n','g','l','e','\0' };
50 static const WCHAR wszVT_INT
[] = { 'i','n','t','\0' };
51 static const WCHAR wszVT_BSTR
[] = { 'B','S','T','R','\0' };
52 static const WCHAR wszVT_CY
[] = { 'C','U','R','R','E','N','C','Y','\0' };
53 static const WCHAR wszVT_VARIANT
[] = { 'V','A','R','I','A','N','T','\0' };
54 static const WCHAR wszVT_VOID
[] = { 'v','o','i','d','\0' };
55 static const WCHAR wszVT_ERROR
[] = { 'S','C','O','D','E','\0' };
56 static const WCHAR wszVT_LPSTR
[] = { 'L','P','S','T','R','\0' };
57 static const WCHAR wszVT_LPWSTR
[] = { 'L','P','W','S','T','R','\0' };
59 void AddToStrW(WCHAR
*wszDest
, const WCHAR
*wszSource
)
61 lstrcpyW(&wszDest
[lstrlenW(wszDest
)], wszSource
);
64 void CreateTypeInfo(WCHAR
*wszAddTo
, WCHAR
*wszAddAfter
, TYPEDESC tdesc
, ITypeInfo
*pTypeInfo
)
69 ITypeInfo
*pRefTypeInfo
;
70 WCHAR wszBuf
[MAX_LOAD_STRING
];
71 WCHAR wszFormat
[] = { '[','%','l','u',']','\0' };
73 switch(tdesc
.vt
&VT_TYPEMASK
)
75 #define VTADDTOSTR(x) case x:\
76 AddToStrW(wszAddTo, wsz##x);\
92 VTADDTOSTR(VT_VARIANT
);
96 VTADDTOSTR(VT_LPWSTR
);
98 for(i
=0; i
<U(tdesc
).lpadesc
->cDims
; i
++)
100 wsprintfW(wszBuf
, wszFormat
, U(tdesc
).lpadesc
->rgbounds
[i
].cElements
);
101 AddToStrW(wszAddAfter
, wszBuf
);
103 CreateTypeInfo(wszAddTo
, wszAddAfter
, U(tdesc
).lpadesc
->tdescElem
, pTypeInfo
);
106 CreateTypeInfo(wszAddTo
, wszAddAfter
, *U(tdesc
).lptdesc
, pTypeInfo
);
107 AddToStrW(wszAddTo
, wszAsterix
);
110 hRes
= ITypeInfo_GetRefTypeInfo(pTypeInfo
,
111 U(tdesc
).hreftype
, &pRefTypeInfo
);
114 ITypeInfo_GetDocumentation(pRefTypeInfo
, MEMBERID_NIL
,
115 &bstrData
, NULL
, NULL
, NULL
);
116 AddToStrW(wszAddTo
, bstrData
);
117 SysFreeString(bstrData
);
118 ITypeInfo_Release(pRefTypeInfo
);
120 else AddToStrW(wszAddTo
, wszFailed
);
123 WINE_FIXME("tdesc.vt&VT_TYPEMASK == %d not supported\n",
124 tdesc
.vt
&VT_TYPEMASK
);
128 int EnumVars(ITypeInfo
*pTypeInfo
, int cVars
, HTREEITEM hParent
)
134 WCHAR wszText
[MAX_LOAD_STRING
];
135 WCHAR wszAfter
[MAX_LOAD_STRING
];
137 U(tvis
).item
.mask
= TVIF_TEXT
;
138 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
139 U(tvis
).item
.pszText
= wszText
;
140 tvis
.hInsertAfter
= (HTREEITEM
)TVI_LAST
;
141 tvis
.hParent
= hParent
;
143 for(i
=0; i
<cVars
; i
++)
145 if(FAILED(ITypeInfo_GetVarDesc(pTypeInfo
, i
, &pVarDesc
))) continue;
146 if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo
, pVarDesc
->memid
, &bstrName
,
147 NULL
, NULL
, NULL
))) continue;
149 memset(wszText
, 0, sizeof(wszText
));
150 memset(wszAfter
, 0, sizeof(wszAfter
));
151 CreateTypeInfo(wszText
, wszAfter
, pVarDesc
->elemdescVar
.tdesc
, pTypeInfo
);
152 AddToStrW(wszText
, wszSpace
);
153 AddToStrW(wszText
, bstrName
);
154 AddToStrW(wszText
, wszAfter
);
156 SendMessage(typelib
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
157 SysFreeString(bstrName
);
158 ITypeInfo_ReleaseVarDesc(pTypeInfo
, pVarDesc
);
164 int EnumFuncs(ITypeInfo
*pTypeInfo
, int cFuncs
, HTREEITEM hParent
)
171 U(tvis
).item
.mask
= TVIF_TEXT
;
172 tvis
.hInsertAfter
= (HTREEITEM
)TVI_LAST
;
173 tvis
.hParent
= hParent
;
175 for(i
=0; i
<cFuncs
; i
++)
177 if(FAILED(ITypeInfo_GetFuncDesc(pTypeInfo
, i
, &pFuncDesc
))) continue;
178 if(FAILED(ITypeInfo_GetDocumentation(pTypeInfo
, pFuncDesc
->memid
, &bstrName
,
179 NULL
, NULL
, NULL
))) continue;
181 U(tvis
).item
.cchTextMax
= SysStringLen(bstrName
);
182 U(tvis
).item
.pszText
= bstrName
;
184 SendMessage(typelib
.hTree
, TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
185 SysFreeString(bstrName
);
186 ITypeInfo_ReleaseFuncDesc(pTypeInfo
, pFuncDesc
);
192 int EnumImplTypes(ITypeInfo
*pTypeInfo
, int cImplTypes
, HTREEITEM hParent
)
196 ITypeInfo
*pRefTypeInfo
;
200 WCHAR wszInheritedInterfaces
[MAX_LOAD_STRING
];
202 if(!cImplTypes
) return 0;
204 LoadString(globals
.hMainInst
, IDS_INHERITINTERFACES
, wszInheritedInterfaces
,
205 sizeof(WCHAR
[MAX_LOAD_STRING
]));
207 U(tvis
).item
.mask
= TVIF_TEXT
;
208 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
209 U(tvis
).item
.pszText
= wszInheritedInterfaces
;
210 tvis
.hInsertAfter
= (HTREEITEM
)TVI_LAST
;
211 tvis
.hParent
= hParent
;
213 tvis
.hParent
= TreeView_InsertItem(typelib
.hTree
, &tvis
);
215 for(i
=0; i
<cImplTypes
; i
++)
217 if(FAILED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo
, i
, &hRefType
))) continue;
218 if(FAILED(ITypeInfo_GetRefTypeInfo(pTypeInfo
, hRefType
, &pRefTypeInfo
)))
220 if(FAILED(ITypeInfo_GetDocumentation(pRefTypeInfo
, MEMBERID_NIL
, &bstrName
,
221 NULL
, NULL
, NULL
))) continue;
222 if(FAILED(ITypeInfo_GetTypeAttr(pRefTypeInfo
, &pTypeAttr
))) continue;
224 U(tvis
).item
.cchTextMax
= SysStringLen(bstrName
);
225 U(tvis
).item
.pszText
= bstrName
;
227 hParent
= TreeView_InsertItem(typelib
.hTree
, &tvis
);
228 EnumVars(pRefTypeInfo
, pTypeAttr
->cVars
, hParent
);
229 EnumFuncs(pRefTypeInfo
, pTypeAttr
->cFuncs
, hParent
);
230 EnumImplTypes(pRefTypeInfo
, pTypeAttr
->cImplTypes
, hParent
);
232 SysFreeString(bstrName
);
233 ITypeInfo_ReleaseTypeAttr(pRefTypeInfo
, pTypeAttr
);
234 ITypeInfo_Release(pRefTypeInfo
);
240 int PopulateTree(void)
244 ITypeInfo
*pTypeInfo
, *pRefTypeInfo
;
250 WCHAR wszText
[MAX_LOAD_STRING
];
251 WCHAR wszAfter
[MAX_LOAD_STRING
];
255 const WCHAR wszFormat
[] = { '%','s',' ','(','%','s',')','\0' };
257 const WCHAR wszTKIND_ENUM
[] = { 't','y','p','e','d','e','f',' ','e','n','u','m',' ','\0' };
258 const WCHAR wszTKIND_RECORD
[]
259 = { 't','y','p','e','d','e','f',' ','s','t','r','u','c','t',' ','\0' };
260 const WCHAR wszTKIND_MODULE
[] = { 'm','o','d','u','l','e',' ','\0' };
261 const WCHAR wszTKIND_INTERFACE
[] = { 'i','n','t','e','r','f','a','c','e',' ','\0' };
262 const WCHAR wszTKIND_DISPATCH
[]
263 = { 'd','i','s','p','i','n','t','e','r','f','a','c','e',' ','\0' };
264 const WCHAR wszTKIND_COCLASS
[] = { 'c','o','c','l','a','s','s',' ','\0' };
265 const WCHAR wszTKIND_ALIAS
[] = { 't','y','p','e','d','e','f',' ','\0' };
266 const WCHAR wszTKIND_UNION
[]
267 = { 't','y','p','e','d','e','f',' ','u','n','i','o','n',' ','\0' };
269 U(tvis
).item
.mask
= TVIF_TEXT
;
270 U(tvis
).item
.cchTextMax
= MAX_LOAD_STRING
;
271 U(tvis
).item
.pszText
= wszText
;
272 tvis
.hInsertAfter
= (HTREEITEM
)TVI_LAST
;
273 tvis
.hParent
= TVI_ROOT
;
275 if(FAILED((hRes
= LoadTypeLib(typelib
.wszFileName
, &pTypeLib
))))
277 WCHAR wszMessage
[MAX_LOAD_STRING
];
278 WCHAR wszError
[MAX_LOAD_STRING
];
280 LoadString(globals
.hMainInst
, IDS_ERROR_LOADTYPELIB
,
281 wszError
, sizeof(WCHAR
[MAX_LOAD_STRING
]));
282 wsprintfW(wszMessage
, wszError
, typelib
.wszFileName
, hRes
);
283 MessageBox(globals
.hMainWnd
, wszMessage
, NULL
, MB_OK
|MB_ICONEXCLAMATION
);
286 count
= ITypeLib_GetTypeInfoCount(pTypeLib
);
288 ITypeLib_GetDocumentation(pTypeLib
, -1, &bstrName
, &bstrData
, NULL
, NULL
);
289 wsprintfW(wszText
, wszFormat
, bstrName
, bstrData
);
290 SysFreeString(bstrName
);
291 SysFreeString(bstrData
);
292 tvis
.hParent
= (HTREEITEM
)SendMessage(typelib
.hTree
,
293 TVM_INSERTITEM
, 0, (LPARAM
)&tvis
);
295 for(i
=0; i
<count
; i
++)
297 ITypeLib_GetTypeInfo(pTypeLib
, i
, &pTypeInfo
);
299 ITypeInfo_GetDocumentation(pTypeInfo
, MEMBERID_NIL
, &bstrName
, NULL
, NULL
, NULL
);
300 ITypeInfo_GetTypeAttr(pTypeInfo
, &pTypeAttr
);
302 memset(wszText
, 0, sizeof(wszText
));
303 memset(wszAfter
, 0, sizeof(wszAfter
));
304 switch(pTypeAttr
->typekind
)
306 #define TKINDADDTOSTR(x) case x:\
307 AddToStrW(wszText, wsz##x);\
308 AddToStrW(wszText, bstrName);\
310 TKINDADDTOSTR(TKIND_ENUM
);
311 TKINDADDTOSTR(TKIND_RECORD
);
312 TKINDADDTOSTR(TKIND_MODULE
);
313 TKINDADDTOSTR(TKIND_INTERFACE
);
314 TKINDADDTOSTR(TKIND_COCLASS
);
315 TKINDADDTOSTR(TKIND_UNION
);
317 AddToStrW(wszText
, wszTKIND_DISPATCH
);
318 AddToStrW(wszText
, bstrName
);
319 if(SUCCEEDED(ITypeInfo_GetRefTypeOfImplType(pTypeInfo
, -1, &hRefType
)))
321 hParent
= TreeView_InsertItem(typelib
.hTree
, &tvis
);
322 EnumImplTypes(pTypeInfo
, pTypeAttr
->cImplTypes
, hParent
);
323 memset(wszText
, 0, sizeof(wszText
));
325 ITypeInfo_GetRefTypeInfo(pTypeInfo
, hRefType
, &pRefTypeInfo
);
326 ITypeInfo_GetDocumentation(pRefTypeInfo
, MEMBERID_NIL
, &bstrName
,
328 AddToStrW(wszText
, wszTKIND_INTERFACE
);
329 AddToStrW(wszText
, bstrName
);
330 ITypeInfo_Release(pRefTypeInfo
);
334 AddToStrW(wszText
, wszTKIND_ALIAS
);
335 CreateTypeInfo(wszText
, wszAfter
, pTypeAttr
->tdescAlias
, pTypeInfo
);
336 AddToStrW(wszText
, wszSpace
);
337 AddToStrW(wszText
, bstrName
);
338 AddToStrW(wszText
, wszAfter
);
341 lstrcpyW(wszText
, bstrName
);
342 WINE_FIXME("pTypeAttr->typekind == %d\n not supported",
343 pTypeAttr
->typekind
);
345 hParent
= TreeView_InsertItem(typelib
.hTree
, &tvis
);
347 EnumVars(pTypeInfo
, pTypeAttr
->cVars
, hParent
);
348 EnumFuncs(pTypeInfo
, pTypeAttr
->cFuncs
, hParent
);
349 EnumImplTypes(pTypeInfo
, pTypeAttr
->cImplTypes
, hParent
);
351 ITypeInfo_ReleaseTypeAttr(pTypeInfo
, pTypeAttr
);
352 ITypeInfo_Release(pTypeInfo
);
353 SysFreeString(bstrName
);
355 SendMessage(typelib
.hTree
, TVM_EXPAND
, TVE_EXPAND
, (LPARAM
)tvis
.hParent
);
357 ITypeLib_Release(pTypeLib
);
361 void TypeLibResizeChild(void)
365 MoveWindow(typelib
.hStatusBar
, 0, 0, 0, 0, TRUE
);
367 if(IsWindowVisible(typelib
.hStatusBar
))
368 GetClientRect(typelib
.hStatusBar
, &stat
);
369 else stat
.bottom
= 0;
371 GetClientRect(globals
.hTypeLibWnd
, &client
);
372 MoveWindow(typelib
.hPaneWnd
, 0, 0,
373 client
.right
, client
.bottom
-stat
.bottom
, TRUE
);
376 void TypeLibMenuCommand(WPARAM wParam
, HWND hWnd
)
383 vis
= IsWindowVisible(typelib
.hStatusBar
);
384 ShowWindow(typelib
.hStatusBar
, vis
? SW_HIDE
: SW_SHOW
);
385 CheckMenuItem(GetMenu(hWnd
), LOWORD(wParam
),
386 vis
? MF_UNCHECKED
: MF_CHECKED
);
387 TypeLibResizeChild();
395 void UpdateTypeLibStatusBar(int itemID
)
397 WCHAR info
[MAX_LOAD_STRING
];
399 if(!LoadString(globals
.hMainInst
, itemID
, info
, sizeof(WCHAR
[MAX_LOAD_STRING
])))
400 LoadString(globals
.hMainInst
, IDS_READY
, info
, sizeof(WCHAR
[MAX_LOAD_STRING
]));
402 SendMessage(typelib
.hStatusBar
, SB_SETTEXT
, 0, (LPARAM
)info
);
405 LRESULT CALLBACK
TypeLibProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
411 if(!CreatePanedWindow(hWnd
, &typelib
.hPaneWnd
, globals
.hMainInst
))
413 typelib
.hTree
= CreateWindowEx(WS_EX_CLIENTEDGE
, WC_TREEVIEW
, NULL
,
414 WS_CHILD
|WS_VISIBLE
|TVS_HASLINES
|TVS_HASBUTTONS
|TVS_LINESATROOT
,
415 0, 0, 0, 0, typelib
.hPaneWnd
, NULL
, globals
.hMainInst
, NULL
);
416 typelib
.hEdit
= CreateWindowEx(WS_EX_CLIENTEDGE
, WC_EDIT
, NULL
,
417 WS_CHILD
|WS_VISIBLE
|ES_MULTILINE
|ES_READONLY
|WS_HSCROLL
|WS_VSCROLL
,
418 0, 0, 0, 0, typelib
.hPaneWnd
, NULL
, globals
.hMainInst
, NULL
);
420 SetLeft(typelib
.hPaneWnd
, typelib
.hTree
);
421 SetRight(typelib
.hPaneWnd
, typelib
.hEdit
);
423 if(PopulateTree()) DestroyWindow(hWnd
);
424 else SetFocus(typelib
.hTree
);
428 TypeLibMenuCommand(LOWORD(wParam
), hWnd
);
430 UpdateTypeLibStatusBar(LOWORD(wParam
));
433 SetFocus(typelib
.hTree
);
436 if(wParam
== SIZE_MINIMIZED
) break;
437 TypeLibResizeChild();
442 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
447 BOOL
TypeLibRegisterClass(void)
451 memset(&wcc
, 0, sizeof(WNDCLASS
));
452 wcc
.lpfnWndProc
= TypeLibProc
;
453 wcc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
454 wcc
.lpszMenuName
= MAKEINTRESOURCE(IDM_TYPELIB
);
455 wcc
.lpszClassName
= wszTypeLib
;
457 if(!RegisterClass(&wcc
))
463 BOOL
CreateTypeLibWindow(HINSTANCE hInst
, WCHAR
*wszFileName
)
465 WCHAR wszTitle
[MAX_LOAD_STRING
];
466 LoadString(hInst
, IDS_TYPELIBTITLE
, wszTitle
, sizeof(WCHAR
[MAX_LOAD_STRING
]));
468 if(wszFileName
) lstrcpyW(typelib
.wszFileName
, wszFileName
);
473 memset(&tvi
, 0, sizeof(TVITEM
));
474 tvi
.hItem
= TreeView_GetSelection(globals
.hTree
);
476 SendMessage(globals
.hTree
, TVM_GETITEM
, 0, (LPARAM
)&tvi
);
477 lstrcpyW(typelib
.wszFileName
, ((ITEM_INFO
*)tvi
.lParam
)->path
);
480 globals
.hTypeLibWnd
= CreateWindow(wszTypeLib
, wszTitle
,
481 WS_OVERLAPPEDWINDOW
|WS_VISIBLE
,
482 CW_USEDEFAULT
, CW_USEDEFAULT
, 800, 600, NULL
, NULL
, hInst
, NULL
);
483 if(!globals
.hTypeLibWnd
) return FALSE
;
485 typelib
.hStatusBar
= CreateStatusWindow(WS_VISIBLE
|WS_CHILD
,
486 (LPWSTR
)wszTitle
, globals
.hTypeLibWnd
, 0);
488 TypeLibResizeChild();