|
|
1.1 root 1: /***
2: *tibrowse.cpp
3: *
4: * Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
5: * Information Contained Herein Is Proprietary and Confidential.
6: *
7: *Purpose:
8: * Type Information Browser
9: *
10: *
11: *Implementation Notes:
12: *
13: *****************************************************************************/
14:
15: #include <windows.h>
16: #include <ole2.h>
17: #include <dispatch.h>
18:
19: #include <stdlib.h>
20: #include <string.h>
21: #include <malloc.h>
22: #include <commdlg.h>
23:
24: #include "resource.h"
25:
26: void OpenTypeLib(char FAR*);
27: void SetSelectedType(DWORD);
28: void FillMemberList(ITypeInfo FAR *, TYPEATTR FAR *, HWND);
29: void SetSelectedMember(DWORD);
30: void SetSelectedParam(DWORD dwIndex);
31: void UpdateMemberInfo(MEMBERID memid);
32: void AssertFail(char FAR*, WORD);
33: void MethodError(HRESULT hresult);
34: void Cleanup(void);
35: void MemFree(void FAR*);
36:
37: #define CHECKRESULT(X) \
38: {HRESULT hresult = (X); \
39: if(hresult != NOERROR && FAILED(GetScode(hresult))) MethodError(hresult); }
40:
41: #ifdef _DEBUG
42: # define Assert(expr) if (!(expr)) AssertFail(__FILE__, __LINE__);
43: # define SideAssert(expr) Assert(expr)
44: #else
45: # define Assert(expr)
46: # define SideAssert(expr) (expr)
47: #endif
48:
49: #ifdef WIN32
50: #define EXPORT
51: #else
52: #define EXPORT _export
53: #endif
54:
55: static HWND g_hwndMain;
56: static char g_szAppName[] = "TiBrowse" ;
57:
58: static ITypeLib FAR *g_ptlib;
59: static ITypeInfo FAR *g_ptinfoCur;
60: static TYPEATTR FAR *g_ptypeattrCur;
61:
62: static char * g_rgszTKind[] = {
63: "Enum", /* TKIND_ENUM */
64: "Struct", /* TKIND_RECORD */
65: "Module", /* TKIND_MODULE */
66: "Interface", /* TKIND_INTERFACE */
67: "Dispinterface", /* TKIND_DISPATCH */
68: "Coclass", /* TKIND_COCLASS */
69: "Typedef", /* TKIND_ALIAS */
70:
71: /* NOTE: the following aren't supported in typeinfo yet */
72: "Union", /* TKIND_UNION */
73: "Encap Union" /* TKIND_ENCUNION */
74: };
75:
76: long FAR PASCAL EXPORT WndProc (HWND, UINT, WPARAM, LPARAM) ;
77:
78: int PASCAL
79: WinMain(
80: HANDLE hInstance,
81: HANDLE hPrevInstance,
82: LPSTR lpszCmdLine,
83: int nCmdShow)
84: {
85: MSG msg;
86: WNDCLASS wndclass;
87: OPENFILENAME ofn;
88:
89: if(!hPrevInstance){
90: wndclass.style = CS_HREDRAW | CS_VREDRAW;
91: wndclass.lpfnWndProc = WndProc ;
92: wndclass.cbClsExtra = 0 ;
93: wndclass.cbWndExtra = DLGWINDOWEXTRA ;
94: wndclass.hInstance = hInstance ;
95: wndclass.hIcon = LoadIcon (hInstance, g_szAppName) ;
96: wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
97: wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
98: wndclass.lpszMenuName = NULL ;
99: wndclass.lpszClassName = g_szAppName ;
100:
101: RegisterClass (&wndclass) ;
102: }
103:
104: if(OleInitialize(NULL) != NOERROR){
105: MessageBox(NULL, "unable to initialize Ole", g_szAppName, MB_OK);
106: return 0;
107: }
108:
109: g_hwndMain = CreateDialog(hInstance, g_szAppName, 0, NULL);
110:
111: /* Open up the type library, and add the names of all the types to
112: * the list box. If command line parameter given, assume it is a
113: * valid file name. Otherwise, use COMMDLG.DLL to put up a file open
114: * dialog and query the user for a filename.
115: */
116: if(!lstrcmp(lpszCmdLine, "")){
117: char FileBuf[128];
118:
119: memset(&ofn, 0, sizeof(OPENFILENAME));
120: ofn.lStructSize = sizeof(OPENFILENAME);
121: ofn.hwndOwner = g_hwndMain;
122: ofn.lpstrFile = (LPSTR)&FileBuf;
123: ofn.nMaxFile = sizeof(FileBuf);
124: *FileBuf = '\0';
125: ofn.lpstrFilter = "Type Libraries\0*.tlb\0\0";
126: ofn.nFilterIndex = 1;
127: ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
128: if(GetOpenFileName(&ofn) == 0){
129: DWORD dwerr;
130:
131: dwerr = CommDlgExtendedError();
132: /* CONSIDER: do something with this error code */
133: Cleanup();
134: exit(1);
135: }
136: lpszCmdLine = ofn.lpstrFile; /* get file user selected */
137: }
138:
139: OpenTypeLib(lpszCmdLine);
140:
141: ShowWindow(g_hwndMain, nCmdShow);
142:
143: while(GetMessage (&msg, NULL, 0, 0)){
144: TranslateMessage (&msg);
145: DispatchMessage (&msg);
146: }
147:
148: Cleanup();
149:
150: return msg.wParam;
151: }
152:
153:
154: void Cleanup()
155: {
156: if(g_ptinfoCur != NULL)
157: g_ptinfoCur->Release();
158: if(g_ptlib != NULL)
159: g_ptlib->Release();
160: OleUninitialize();
161: }
162:
163:
164: long FAR PASCAL EXPORT
165: WndProc(
166: HWND hwnd,
167: UINT message,
168: WPARAM wParam,
169: LPARAM lParam)
170: {
171: DWORD dwIndex;
172:
173: switch(message){
174: case WM_COMMAND:
175: /* We deal with the following events:
176: * The selection changes on the type list and we have
177: * to update the member list & type info.
178: * The selection changes on the member list and we have
179: * to update the param list & member info.
180: * Selection changes on a parameter and we have to
181: * update the param info.
182: */
183: #ifdef WIN32
184: #define wParamX LOWORD(wParam)
185: #define notifyMsg HIWORD(wParam)
186: #else
187: #define wParamX wParam
188: #define notifyMsg HIWORD(lParam)
189: #endif
190: switch(wParamX){
191: case IDC_TYPELIST:
192: if(notifyMsg == LBN_SELCHANGE){
193: dwIndex = SendDlgItemMessage(hwnd, IDC_TYPELIST, LB_GETCURSEL, 0, 0L);
194: SetSelectedType(dwIndex);
195: }
196: break;
197: case IDC_MEMBERLIST:
198: if(notifyMsg == LBN_SELCHANGE){
199: dwIndex = SendDlgItemMessage(hwnd, IDC_MEMBERLIST, LB_GETCURSEL,0,0L);
200: SetSelectedMember(dwIndex);
201: }
202: break;
203: case IDC_PARAMLIST:
204: if(notifyMsg == LBN_SELCHANGE){
205: dwIndex = SendDlgItemMessage(hwnd, IDC_PARAMLIST, LB_GETCURSEL, 0,0L);
206: SetSelectedParam(dwIndex);
207: }
208: break;
209: }
210: return 0;
211:
212: case WM_DESTROY:
213: PostQuitMessage(0);
214: return 0 ;
215: }
216: return DefWindowProc (hwnd, message, wParam, lParam) ;
217: }
218:
219:
220: void OpenTypeLib (char FAR *sztlib)
221: {
222: UINT utypeinfoCount, i;
223: BSTR bstrName;
224: TLIBATTR FAR* ptlibattr;
225:
226: /* load the type library */
227: CHECKRESULT(LoadTypeLib(sztlib, &g_ptlib));
228:
229: /* get library attributes for the fun of it */
230: CHECKRESULT(g_ptlib->GetLibAttr(&ptlibattr));
231:
232: /* release library attributes */
233: g_ptlib->ReleaseTLibAttr(ptlibattr);
234:
235: /* Now add each of the names to the type list */
236: utypeinfoCount = g_ptlib->GetTypeInfoCount();
237: for(i = 0; i < utypeinfoCount; i++){
238: CHECKRESULT(g_ptlib->GetDocumentation(i, &bstrName, NULL, NULL, NULL));
239: Assert(bstrName);
240: SendDlgItemMessage(g_hwndMain, IDC_TYPELIST, LB_ADDSTRING, 0, (LPARAM)bstrName);
241: SysFreeString(bstrName);
242: }
243: }
244:
245: /*
246: * SetSelectedType
247: *
248: * When the user changes the selection of a type, this function updates the
249: * dialog by changing the member list and the help for the type. It also sets
250: * g_ptinfoCur to refer to the typeinfo.
251: */
252: void SetSelectedType (DWORD dwIndex)
253: {
254: BSTR bstrDoc;
255: LPSTR szData;
256: char szBuf[40];
257: HRESULT hresult;
258: DWORD dwHelpContext;
259:
260: if(g_ptinfoCur != NULL){
261: g_ptinfoCur->ReleaseTypeAttr(g_ptypeattrCur);
262: g_ptinfoCur->Release();
263: }
264:
265: /* Clear out the member list */
266: SendDlgItemMessage(g_hwndMain, IDC_MEMBERLIST, LB_RESETCONTENT,0,0L);
267: if(dwIndex != LB_ERR)
268: {
269: /* Note that the index in the list box is conveniently the
270: * same as the one to pass to GetTypeInfo.
271: */
272:
273: CHECKRESULT(g_ptlib->GetTypeInfo((UINT) dwIndex, &g_ptinfoCur));
274: CHECKRESULT(g_ptinfoCur->GetTypeAttr(&g_ptypeattrCur));
275:
276: // TypeKind
277: szData = g_rgszTKind[g_ptypeattrCur->typekind];
278: SendDlgItemMessage(g_hwndMain, IDC_TYPEKIND, WM_SETTEXT, 0, (LPARAM)szData);
279:
280: // GUID
281: hresult = StringFromCLSID(g_ptypeattrCur->guid, &szData);
282: if(hresult != NOERROR)
283: szData = "error!";
284: SendDlgItemMessage(g_hwndMain, IDC_GUID, WM_SETTEXT, 0, (LPARAM)szData);
285: MemFree(szData);
286:
287: // Version
288: wsprintf(szBuf, "%u.%02u",
289: g_ptypeattrCur->wMajorVerNum, g_ptypeattrCur->wMinorVerNum);
290: SendDlgItemMessage(
291: g_hwndMain, IDC_VERSION, WM_SETTEXT, 0, (LPARAM)(LPSTR)szBuf);
292:
293:
294: CHECKRESULT(
295: g_ptlib->GetDocumentation(
296: (UINT)dwIndex, NULL, &bstrDoc, &dwHelpContext, NULL));
297:
298: // Help Context
299: _ltoa((long)dwHelpContext, szBuf, 10);
300: SendDlgItemMessage(
301: g_hwndMain, IDC_HELPCONTEXT, WM_SETTEXT, 0, (LPARAM)(LPSTR)szBuf);
302:
303: // Documentation string
304: szData = (bstrDoc != NULL) ? (LPSTR)bstrDoc : "<none>";
305: SendDlgItemMessage(g_hwndMain, IDC_HELP, WM_SETTEXT, 0, (LPARAM)szData);
306: SysFreeString(bstrDoc);
307:
308: FillMemberList(g_ptinfoCur, g_ptypeattrCur, GetDlgItem(g_hwndMain, IDC_MEMBERLIST));
309: }
310: else /* no item is selected -- NULL out the pointers */
311: {
312: g_ptinfoCur = NULL;
313: g_ptypeattrCur = NULL;
314: }
315:
316: SendDlgItemMessage(g_hwndMain, IDC_PARAMLIST, LB_RESETCONTENT, 0, 0L);
317: }
318:
319: /*
320: * FillMemberList.
321: *
322: * Sets the current typeinfo to the typeinfo indexed by dwIndex, and then
323: * fills in the list box with the members of the type.
324: */
325:
326: void
327: FillMemberList(
328: ITypeInfo FAR *ptypeinfo,
329: TYPEATTR FAR *ptypeattr,
330: HWND hwndMemberList)
331: {
332: MEMBERID memid;
333: BSTR bstrName;
334: UINT i;
335: FUNCDESC FAR *pfuncdesc;
336: VARDESC FAR *pvardesc;
337:
338: /* Now add all of the functions and all of the vars.
339: * This is somewhat roundabout.
340: * For each one, we need to get the funcdesc, or the vardesc.
341: * From that we get the MEMBERID, and finally can get to the name.
342: */
343: for(i = 0; i < ptypeattr->cFuncs; i++){
344: CHECKRESULT(ptypeinfo->GetFuncDesc(i, &pfuncdesc));
345: memid = pfuncdesc->memid;
346: CHECKRESULT(ptypeinfo->GetDocumentation(memid, &bstrName, NULL, NULL, NULL));
347: ptypeinfo->ReleaseFuncDesc(pfuncdesc);
348: pfuncdesc = NULL;
349:
350: Assert(bstrName);
351: SendMessage(hwndMemberList, LB_ADDSTRING, 0, (LPARAM) bstrName);
352: SysFreeString(bstrName);
353: }
354:
355: for(i = 0; i < ptypeattr->cVars; i++)
356: {
357: CHECKRESULT(ptypeinfo->GetVarDesc(i, &pvardesc));
358: memid = pvardesc->memid;
359: CHECKRESULT(ptypeinfo->GetDocumentation(memid, &bstrName, NULL, NULL, NULL));
360: ptypeinfo->ReleaseVarDesc(pvardesc);
361: pvardesc = NULL;
362:
363: Assert(bstrName);
364: SendMessage(hwndMemberList, LB_ADDSTRING, 0, (LPARAM) bstrName);
365: SysFreeString(bstrName);
366: }
367: }
368:
369: /*
370: * SetSelectedMember
371: *
372: * When a member of a type is selected, update the help to be the help of the member, and
373: * if the member is a function update the parameter list to reflect that it is a function.
374: *
375: */
376:
377: void SetSelectedMember(DWORD dwIndex)
378: {
379: MEMBERID memid;
380: HWND hwndParamList;
381:
382: /* In any case, we'll need to clear out the parameter list. */
383: hwndParamList = GetDlgItem(g_hwndMain, IDC_PARAMLIST);
384: SendMessage(hwndParamList, LB_RESETCONTENT, 0, 0L);
385:
386: if (dwIndex == LB_ERR)
387: return;
388:
389: /* if this is a function, fill the param list, otherwise just fill
390: * in the item info.
391: */
392: if(dwIndex < g_ptypeattrCur->cFuncs){
393: FUNCDESC FAR *pfuncdesc;
394: USHORT i;
395: UINT cNames;
396: const UINT MAX_NAMES = 40;
397: BSTR rgNames[MAX_NAMES];
398:
399: CHECKRESULT(g_ptinfoCur->GetFuncDesc((UINT) dwIndex, &pfuncdesc));
400: memid = pfuncdesc->memid;
401: UpdateMemberInfo(memid);
402:
403: CHECKRESULT(g_ptinfoCur->GetNames(memid, rgNames, MAX_NAMES,&cNames));
404: for(i = 1; i < cNames; i++){
405: Assert(rgNames[i])
406: SendMessage(hwndParamList, LB_ADDSTRING, 0, (LPARAM) rgNames[i]);
407: SysFreeString(rgNames[i]);
408: }
409: Assert(rgNames[0]);
410: SysFreeString(rgNames[0]);
411: g_ptinfoCur->ReleaseFuncDesc(pfuncdesc);
412: }
413: else
414: {
415: VARDESC FAR *pvardesc;
416:
417: CHECKRESULT(
418: g_ptinfoCur->GetVarDesc(
419: (UINT)(dwIndex - g_ptypeattrCur->cFuncs), &pvardesc));
420: memid = pvardesc->memid;
421: UpdateMemberInfo(memid);
422: g_ptinfoCur->ReleaseVarDesc(pvardesc);
423: }
424:
425: }
426:
427:
428: /* sets fields on the dialog (such as help string and help context) from
429: the type information.
430: */
431: void
432: UpdateMemberInfo(MEMBERID memid)
433: {
434: BSTR bstrDoc;
435: LPSTR szData;
436: DWORD dwHelpContext;
437: char szBuf[40];
438:
439: /* get the member information */
440: CHECKRESULT(g_ptinfoCur->GetDocumentation(memid, NULL, &bstrDoc, &dwHelpContext, NULL));
441:
442: /* update the help string displayed in the dialog */
443: if (bstrDoc)
444: szData = (LPSTR)bstrDoc;
445: else /* no help string for this item */
446: szData = "<none>";
447:
448: SendDlgItemMessage(g_hwndMain, IDC_HELP, WM_SETTEXT, 0, (LPARAM)szData);
449: SysFreeString(bstrDoc);
450:
451: /* update the help context displayed in the dialog */
452: _ltoa((long)dwHelpContext, szBuf, 10);
453: SendDlgItemMessage(g_hwndMain, IDC_HELPCONTEXT, WM_SETTEXT, 0, (LPARAM)((LPSTR)szBuf));
454: }
455:
456: /*
457: * SetSelectedParam
458: *
459: * CONSIDER: Enhance to show parameter type information here.
460: */
461: void SetSelectedParam(DWORD dwIndex)
462: {
463: }
464:
465: void
466: AssertFail(char FAR * szFile, WORD lineNo)
467: {
468: char szAssert[255];
469: int id;
470:
471: wsprintf(szAssert, "Assertion failed. File %s, line %d.", szFile, lineNo);
472:
473: id = MessageBox(NULL, szAssert, "TiBrowse Assertion. OK to continue, CANCEL to quit.", MB_OKCANCEL | MB_TASKMODAL);
474: if (id == IDCANCEL)
475: exit(1);
476: }
477:
478: void
479: MethodError(HRESULT hresult)
480: {
481:
482: /* CONSIDER: add code to figure out what specific error this is */
483:
484: MessageBox(NULL, "Error returned from TYPELIB.DLL", g_szAppName, MB_OK);
485:
486: Cleanup();
487:
488: exit(1);
489: }
490:
491: /* free using the task allocator */
492: void
493: MemFree(void FAR* pv)
494: {
495: HRESULT hresult;
496: IMalloc FAR* pmalloc;
497:
498: hresult = CoGetMalloc(MEMCTX_TASK, &pmalloc);
499:
500: if(hresult != NOERROR){
501: MessageBox(NULL, "error accessing task allocator", g_szAppName, MB_OK);
502: return;
503: }
504:
505: pmalloc->Free(pv);
506: pmalloc->Release();
507: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.