|
|
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.