|
|
1.1 ! root 1: /* ! 2: * UTILITY.C ! 3: * ! 4: * Utility routines for functions inside OLE2UI.DLL ! 5: * ! 6: * General: ! 7: * ---------------------- ! 8: * HourGlassOn Displays the hourglass ! 9: * HourGlassOff Hides the hourglass ! 10: * ! 11: * Misc Tools: ! 12: * ---------------------- ! 13: * Browse Displays the "File..." or "Browse..." dialog. ! 14: * ReplaceCharWithNull Used to form filter strings for Browse. ! 15: * ErrorWithFile Creates an error message with embedded filename ! 16: * OpenFileError Give error message for OpenFile error return ! 17: * ChopText Chop a file path to fit within a specified width ! 18: * ! 19: * Registration Database: ! 20: * ---------------------- ! 21: * HIconFromClass Extracts the first icon in a class's server path ! 22: * FServerFromClass Retrieves the server path for a class name (fast) ! 23: * UClassFromDescription Finds the classname given a description (slow) ! 24: * UDescriptionFromClass Retrieves the description for a class name (fast) ! 25: * FGetVerb Retrieves a specific verb for a class (fast) ! 26: * ! 27: * ! 28: * Copyright (c)1992 Microsoft Corporation, All Right Reserved ! 29: */ ! 30: ! 31: #define STRICT 1 ! 32: #include "ole2ui.h" ! 33: #include <stdlib.h> ! 34: #include <commdlg.h> ! 35: #include <memory.h> ! 36: #include <cderr.h> ! 37: #include "common.h" ! 38: #include "utility.h" ! 39: #include "geticon.h" ! 40: ! 41: OLEDBGDATA ! 42: ! 43: /* ! 44: * HourGlassOn ! 45: * ! 46: * Purpose: ! 47: * Shows the hourglass cursor returning the last cursor in use. ! 48: * ! 49: * Parameters: ! 50: * None ! 51: * ! 52: * Return Value: ! 53: * HCURSOR Cursor in use prior to showing the hourglass. ! 54: */ ! 55: ! 56: HCURSOR WINAPI HourGlassOn(void) ! 57: { ! 58: HCURSOR hCur; ! 59: ! 60: hCur=SetCursor(LoadCursor(NULL, IDC_WAIT)); ! 61: ShowCursor(TRUE); ! 62: ! 63: return hCur; ! 64: } ! 65: ! 66: ! 67: ! 68: /* ! 69: * HourGlassOff ! 70: * ! 71: * Purpose: ! 72: * Turns off the hourglass restoring it to a previous cursor. ! 73: * ! 74: * Parameters: ! 75: * hCur HCURSOR as returned from HourGlassOn ! 76: * ! 77: * Return Value: ! 78: * None ! 79: */ ! 80: ! 81: void WINAPI HourGlassOff(HCURSOR hCur) ! 82: { ! 83: ShowCursor(FALSE); ! 84: SetCursor(hCur); ! 85: return; ! 86: } ! 87: ! 88: ! 89: ! 90: ! 91: /* ! 92: * Browse ! 93: * ! 94: * Purpose: ! 95: * Displays the standard GetOpenFileName dialog with the title of ! 96: * "Browse." The types listed in this dialog are controlled through ! 97: * iFilterString. If it's zero, then the types are filled with "*.*" ! 98: * Otherwise that string is loaded from resources and used. ! 99: * ! 100: * Parameters: ! 101: * hWndOwner HWND owning the dialog ! 102: * lpszFile LPSTR specifying the initial file and the buffer in ! 103: * which to return the selected file. If there is no ! 104: * initial file the first character of this string should ! 105: * be NULL. ! 106: * lpszInitialDir LPSTR specifying the initial directory. If none is to ! 107: * set (ie, the cwd should be used), then this parameter ! 108: * should be NULL. ! 109: * cchFile UINT length of pszFile ! 110: * iFilterString UINT index into the stringtable for the filter string. ! 111: * dwOfnFlags DWORD flags to OR with OFN_HIDEREADONLY ! 112: * ! 113: * Return Value: ! 114: * BOOL TRUE if the user selected a file and pressed OK. ! 115: * FALSE otherwise, such as on pressing Cancel. ! 116: */ ! 117: ! 118: BOOL WINAPI Browse(HWND hWndOwner, LPSTR lpszFile, LPSTR lpszInitialDir, UINT cchFile, UINT iFilterString, DWORD dwOfnFlags) ! 119: { ! 120: UINT cch; ! 121: char szFilters[256]; ! 122: OPENFILENAME ofn; ! 123: BOOL fStatus; ! 124: DWORD dwError; ! 125: char szDlgTitle[128]; // that should be big enough ! 126: ! 127: if (NULL==lpszFile || 0==cchFile) ! 128: return FALSE; ! 129: ! 130: /* ! 131: * REVIEW: Exact contents of the filter combobox is TBD. One idea ! 132: * is to take all the extensions in the RegDB and place them in here ! 133: * with the descriptive class name associate with them. This has the ! 134: * extra step of finding all extensions of the same class handler and ! 135: * building one extension string for all of them. Can get messy quick. ! 136: * UI demo has only *.* which we do for now. ! 137: */ ! 138: ! 139: if (0!=iFilterString) ! 140: cch=LoadString(ghInst, iFilterString, (LPSTR)szFilters, sizeof(szFilters)); ! 141: else ! 142: { ! 143: szFilters[0]=0; ! 144: cch=1; ! 145: } ! 146: ! 147: if (0==cch) ! 148: return FALSE; ! 149: ! 150: ReplaceCharWithNull(szFilters, szFilters[cch-1]); ! 151: ! 152: //Prior string must also be initialized, if there is one. ! 153: _fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn)); ! 154: ofn.lStructSize =sizeof(ofn); ! 155: ofn.hwndOwner =hWndOwner; ! 156: ofn.lpstrFile =lpszFile; ! 157: ofn.nMaxFile =cchFile; ! 158: ofn.lpstrFilter =(LPSTR)szFilters; ! 159: ofn.nFilterIndex=1; ! 160: if (LoadString(ghInst, IDS_BROWSE, (LPSTR)szDlgTitle, sizeof(szDlgTitle))) ! 161: ofn.lpstrTitle =(LPSTR)szDlgTitle; ! 162: ofn.hInstance = ghInst; ! 163: ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN); ! 164: if (NULL != lpszInitialDir) ! 165: ofn.lpstrInitialDir = lpszInitialDir; ! 166: ! 167: ofn.Flags= OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | (dwOfnFlags) ; ! 168: ! 169: //On success, copy the chosen filename to the static display ! 170: fStatus = GetOpenFileName((LPOPENFILENAME)&ofn); ! 171: dwError = CommDlgExtendedError(); ! 172: return fStatus; ! 173: ! 174: } ! 175: ! 176: ! 177: ! 178: ! 179: ! 180: /* ! 181: * ReplaceCharWithNull ! 182: * ! 183: * Purpose: ! 184: * Walks a null-terminated string and replaces a given character ! 185: * with a zero. Used to turn a single string for file open/save ! 186: * filters into the appropriate filter string as required by the ! 187: * common dialog API. ! 188: * ! 189: * Parameters: ! 190: * psz LPSTR to the string to process. ! 191: * ch int character to replace. ! 192: * ! 193: * Return Value: ! 194: * int Number of characters replaced. -1 if psz is NULL. ! 195: */ ! 196: ! 197: int WINAPI ReplaceCharWithNull(LPSTR psz, int ch) ! 198: { ! 199: int cChanged=-1; ! 200: ! 201: if (NULL!=psz) ! 202: { ! 203: while (0!=*psz) ! 204: { ! 205: if (ch==*psz) ! 206: { ! 207: *psz=0; ! 208: cChanged++; ! 209: } ! 210: psz++; ! 211: } ! 212: } ! 213: return cChanged; ! 214: } ! 215: ! 216: ! 217: ! 218: ! 219: ! 220: ! 221: /* ! 222: * ErrorWithFile ! 223: * ! 224: * Purpose: ! 225: * Displays a message box built from a stringtable string containing ! 226: * one %s as a placeholder for a filename and from a string of the ! 227: * filename to place there. ! 228: * ! 229: * Parameters: ! 230: * hWnd HWND owning the message box. The caption of this ! 231: * window is the caption of the message box. ! 232: * hInst HINSTANCE from which to draw the idsErr string. ! 233: * idsErr UINT identifier of a stringtable string containing ! 234: * the error message with a %s. ! 235: * lpszFile LPSTR to the filename to include in the message. ! 236: * uFlags UINT flags to pass to MessageBox, like MB_OK. ! 237: * ! 238: * Return Value: ! 239: * int Return value from MessageBox. ! 240: */ ! 241: ! 242: int WINAPI ErrorWithFile(HWND hWnd, HINSTANCE hInst, UINT idsErr ! 243: , LPSTR pszFile, UINT uFlags) ! 244: { ! 245: int iRet=0; ! 246: HANDLE hMem; ! 247: const UINT cb=(2*OLEUI_CCHPATHMAX); ! 248: LPSTR psz1, psz2, psz3; ! 249: ! 250: if (NULL==hInst || NULL==pszFile) ! 251: return iRet; ! 252: ! 253: //Allocate three 2*OLEUI_CCHPATHMAX byte work buffers ! 254: hMem=GlobalAlloc(GHND, (DWORD)(3*cb)); ! 255: ! 256: if (NULL==hMem) ! 257: return iRet; ! 258: ! 259: psz1=GlobalLock(hMem); ! 260: psz2=psz1+cb; ! 261: psz3=psz2+cb; ! 262: ! 263: if (0!=LoadString(hInst, idsErr, psz1, cb)) ! 264: { ! 265: wsprintf(psz2, psz1, pszFile); ! 266: ! 267: //Steal the caption of the dialog ! 268: GetWindowText(hWnd, psz3, cb); ! 269: iRet=MessageBox(hWnd, psz2, psz3, uFlags); ! 270: } ! 271: ! 272: GlobalUnlock(hMem); ! 273: GlobalFree(hMem); ! 274: return iRet; ! 275: } ! 276: ! 277: ! 278: ! 279: ! 280: ! 281: ! 282: ! 283: ! 284: ! 285: /* ! 286: * HIconFromClass ! 287: * ! 288: * Purpose: ! 289: * Given an object class name, finds an associated executable in the ! 290: * registration database and extracts the first icon from that ! 291: * executable. If none is available or the class has no associated ! 292: * executable, this function returns NULL. ! 293: * ! 294: * Parameters: ! 295: * pszClass LPSTR giving the object class to look up. ! 296: * ! 297: * Return Value: ! 298: * HICON Handle to the extracted icon if there is a module ! 299: * associated to pszClass. NULL on failure to either ! 300: * find the executable or extract and icon. ! 301: */ ! 302: ! 303: HICON WINAPI HIconFromClass(LPSTR pszClass) ! 304: { ! 305: HICON hIcon; ! 306: char szEXE[OLEUI_CCHPATHMAX]; ! 307: UINT Index; ! 308: CLSID clsid; ! 309: ! 310: if (NULL==pszClass) ! 311: return NULL; ! 312: ! 313: CLSIDFromString(pszClass, &clsid); ! 314: ! 315: if (!FIconFileFromClass((REFCLSID)&clsid, szEXE, sizeof(szEXE), &Index)) ! 316: return NULL; ! 317: ! 318: hIcon=ExtractIcon(ghInst, szEXE, Index); ! 319: ! 320: if ((HICON)32 > hIcon) ! 321: hIcon=NULL; ! 322: ! 323: return hIcon; ! 324: } ! 325: ! 326: ! 327: ! 328: ! 329: ! 330: /* ! 331: * FServerFromClass ! 332: * ! 333: * Purpose: ! 334: * Looks up the classname in the registration database and retrieves ! 335: * the name undet protocol\StdFileEditing\server. ! 336: * ! 337: * Parameters: ! 338: * pszClass LPSTR to the classname to look up. ! 339: * pszEXE LPSTR at which to store the server name ! 340: * cch UINT size of pszEXE ! 341: * ! 342: * Return Value: ! 343: * BOOL TRUE if one or more characters were loaded into pszEXE. ! 344: * FALSE otherwise. ! 345: */ ! 346: ! 347: BOOL WINAPI FServerFromClass(LPSTR pszClass, LPSTR pszEXE, UINT cch) ! 348: { ! 349: ! 350: DWORD dw; ! 351: LONG lRet; ! 352: HKEY hKey; ! 353: ! 354: if (NULL==pszClass || NULL==pszEXE || 0==cch) ! 355: return FALSE; ! 356: ! 357: /* ! 358: * We have to go walking in the registration database under the ! 359: * classname, so we first open the classname key and then check ! 360: * under "\\LocalServer" to get the .EXE. ! 361: */ ! 362: ! 363: //Open up the class key ! 364: lRet=RegOpenKey(HKEY_CLASSES_ROOT, pszClass, &hKey); ! 365: ! 366: if ((LONG)ERROR_SUCCESS!=lRet) ! 367: return FALSE; ! 368: ! 369: //Get the executable path. ! 370: dw=(DWORD)cch; ! 371: lRet=RegQueryValue(hKey, "LocalServer", pszEXE, &dw); ! 372: ! 373: RegCloseKey(hKey); ! 374: ! 375: return ((ERROR_SUCCESS == lRet) && (dw > 0)); ! 376: } ! 377: ! 378: ! 379: ! 380: /* ! 381: * UClassFromDescription ! 382: * ! 383: * Purpose: ! 384: * Looks up the actual OLE class name in the registration database ! 385: * for the given descriptive name chosen from a listbox. ! 386: * ! 387: * Parameters: ! 388: * psz LPSTR to the descriptive name. ! 389: * pszClass LPSTR in which to store the class name. ! 390: * cb UINT maximum length of pszClass. ! 391: * ! 392: * Return Value: ! 393: * UINT Number of characters copied to pszClass. 0 on failure. ! 394: */ ! 395: ! 396: UINT WINAPI UClassFromDescription(LPSTR psz, LPSTR pszClass, UINT cb) ! 397: { ! 398: DWORD dw; ! 399: HKEY hKey; ! 400: char szClass[OLEUI_CCHKEYMAX]; ! 401: LONG lRet; ! 402: UINT i; ! 403: ! 404: //Open up the root key. ! 405: lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); ! 406: ! 407: if ((LONG)ERROR_SUCCESS!=lRet) ! 408: return 0; ! 409: ! 410: i=0; ! 411: lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX); ! 412: ! 413: //Walk the available keys ! 414: while ((LONG)ERROR_SUCCESS==lRet) ! 415: { ! 416: dw=(DWORD)cb; ! 417: lRet=RegQueryValue(hKey, szClass, pszClass, &dw); ! 418: ! 419: //Check if the description matches the one just enumerated ! 420: if ((LONG)ERROR_SUCCESS==lRet) ! 421: { ! 422: if (!lstrcmp(pszClass, psz)) ! 423: break; ! 424: } ! 425: ! 426: //Continue with the next key. ! 427: lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX); ! 428: } ! 429: ! 430: //If we found it, copy to the return buffer ! 431: if ((LONG)ERROR_SUCCESS==lRet) ! 432: lstrcpy(pszClass, szClass); ! 433: else ! 434: dw=0L; ! 435: ! 436: RegCloseKey(hKey); ! 437: return (UINT)dw; ! 438: } ! 439: ! 440: ! 441: ! 442: ! 443: ! 444: ! 445: ! 446: ! 447: /* ! 448: * UDescriptionFromClass ! 449: * ! 450: * Purpose: ! 451: * Looks up the actual OLE descriptive name name in the registration ! 452: * database for the given class name. ! 453: * ! 454: * Parameters: ! 455: * pszClass LPSTR to the class name. ! 456: * psz LPSTR in which to store the descriptive name. ! 457: * cb UINT maximum length of psz. ! 458: * ! 459: * Return Value: ! 460: * UINT Number of characters copied to pszClass. 0 on failure. ! 461: */ ! 462: ! 463: UINT WINAPI UDescriptionFromClass(LPSTR pszClass, LPSTR psz, UINT cb) ! 464: { ! 465: DWORD dw; ! 466: HKEY hKey; ! 467: LONG lRet; ! 468: ! 469: if (NULL==pszClass || NULL==psz) ! 470: return 0; ! 471: ! 472: //Open up the root key. ! 473: lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); ! 474: ! 475: if ((LONG)ERROR_SUCCESS!=lRet) ! 476: return 0; ! 477: ! 478: //Get the descriptive name using the class name. ! 479: dw=(DWORD)cb; ! 480: lRet=RegQueryValue(hKey, pszClass, psz, &dw); ! 481: ! 482: RegCloseKey(hKey); ! 483: ! 484: psz+=lstrlen(psz)+1; ! 485: *psz=0; ! 486: ! 487: if ((LONG)ERROR_SUCCESS!=lRet) ! 488: return 0; ! 489: ! 490: return (UINT)dw; ! 491: } ! 492: ! 493: ! 494: ! 495: ! 496: ! 497: /* ! 498: * FVerbGet ! 499: * ! 500: * Purpose: ! 501: * Function to retrieve the verb of a given index from the registration ! 502: * database from a given classname. ! 503: * ! 504: * Parameters: ! 505: * lpszClass LPSTR of the class to look up. ! 506: * iVerb UINT index of the verb to retrieve ! 507: * lpszVerb LPSTR where to store the retrieved verb. ! 508: * ! 509: * Return Value ! 510: * BOOL TRUE if the verb was retrieved, FALSE otherwise. ! 511: */ ! 512: ! 513: BOOL WINAPI FVerbGet(LPSTR lpszClass, UINT iVerb, LPSTR lpszVerb) ! 514: { ! 515: static char szVerb [OLEUI_CCHVERBMAX]; ! 516: ! 517: wsprintf((LPSTR)szVerb, "VERB %d", iVerb); ! 518: ! 519: return GetPrivateProfileString(lpszClass, (LPSTR)szVerb, NULL ! 520: , lpszVerb, OLEUI_CCHVERBMAX, "ole2.ini"); ! 521: } ! 522: ! 523: ! 524: // returns height of line of text. this is a support routine for ChopText ! 525: static LONG GetTextHSize(HDC hDC, LPSTR lpsz) ! 526: { ! 527: SIZE size; ! 528: ! 529: if (GetTextExtentPoint(hDC, lpsz, lstrlen(lpsz), (LPSIZE)&size)) ! 530: return size.cy; ! 531: else { ! 532: return 0; ! 533: } ! 534: } ! 535: ! 536: ! 537: /* ! 538: * ChopText ! 539: * ! 540: * Purpose: ! 541: * Parse a string (pathname) and convert it to be within a specified ! 542: * length by chopping the least significant part ! 543: * ! 544: * Parameters: ! 545: * hWnd window handle in which the string resides ! 546: * nWidth max width of string in pixels ! 547: * use width of hWnd if zero ! 548: * lpch pointer to beginning of the string ! 549: * ! 550: * Return Value: ! 551: * pointer to the modified string ! 552: */ ! 553: LPSTR WINAPI ChopText(HWND hWnd, int nWidth, LPSTR lpch) ! 554: { ! 555: #define PREFIX_SIZE 7 + 1 ! 556: #define PREFIX_FORMAT "%c%c%c...\\" ! 557: ! 558: char szPrefix[PREFIX_SIZE]; ! 559: BOOL fDone = FALSE; ! 560: int i; ! 561: RECT rc; ! 562: HDC hdc; ! 563: HFONT hfont; ! 564: HFONT hfontOld = NULL; ! 565: ! 566: if (!hWnd || !lpch) ! 567: return NULL; ! 568: ! 569: /* Get length of static field. */ ! 570: if (!nWidth) { ! 571: GetClientRect(hWnd, (LPRECT)&rc); ! 572: nWidth = rc.right - rc.left; ! 573: } ! 574: ! 575: /* Set up DC appropriately for the static control */ ! 576: hdc = GetDC(hWnd); ! 577: hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L); ! 578: ! 579: if (NULL != hfont) // WM_GETFONT returns NULL if window uses system font ! 580: hfontOld = SelectObject(hdc, hfont); ! 581: ! 582: /* check horizontal extent of string */ ! 583: if (GetTextHSize(hdc, lpch) > nWidth) { ! 584: ! 585: /* string is too long to fit in static control; chop it */ ! 586: /* set up new prefix & determine remaining space in control */ ! 587: wsprintf((LPSTR) szPrefix, PREFIX_FORMAT, lpch[0], lpch[1], lpch[2]); ! 588: nWidth -= (int)GetTextHSize(hdc, (LPSTR) szPrefix); ! 589: ! 590: /* ! 591: ** advance a directory at a time until the remainder of the ! 592: ** string fits into the static control after the "x:\...\" prefix ! 593: */ ! 594: while (!fDone) { ! 595: ! 596: #ifdef DBCS ! 597: while (*lpch && (*lpch != '\\')) ! 598: lpch = AnsiNext(lpch); ! 599: if (*lpch) ! 600: lpch = AnsiNext(lpch); ! 601: #else ! 602: while (*lpch && (*lpch++ != '\\')); ! 603: #endif ! 604: ! 605: if (!*lpch || GetTextHSize(hdc, lpch) <= nWidth) { ! 606: if (!*lpch) ! 607: /* ! 608: ** Nothing could fit after the prefix; remove the ! 609: ** final "\" from the prefix ! 610: */ ! 611: szPrefix[lstrlen((LPSTR) szPrefix) - 1] = 0; ! 612: ! 613: /* rest or string fits -- stick prefix on front */ ! 614: for (i = lstrlen((LPSTR) szPrefix) - 1; i >= 0; --i) ! 615: *--lpch = szPrefix[i]; ! 616: fDone = TRUE; ! 617: } ! 618: } ! 619: } ! 620: ! 621: if (NULL != hfont) ! 622: SelectObject(hdc, hfontOld); ! 623: ReleaseDC(hWnd, hdc); ! 624: ! 625: return(lpch); ! 626: ! 627: #undef PREFIX_SIZE ! 628: #undef PREFIX_FORMAT ! 629: } ! 630: ! 631: ! 632: /* ! 633: * OpenFileError ! 634: * ! 635: * Purpose: ! 636: * display message for error returned from OpenFile ! 637: * ! 638: * Parameters: ! 639: * hDlg HWND of the dialog. ! 640: * nErrCode UINT error code returned in OFSTRUCT passed to OpenFile ! 641: * lpszFile LPSTR file name passed to OpenFile ! 642: * ! 643: * Return Value: ! 644: * None ! 645: */ ! 646: void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPSTR lpszFile) ! 647: { ! 648: switch (nErrCode) { ! 649: case 0x0005: // Access denied ! 650: ErrorWithFile(hDlg, ghInst, IDS_CIFILEACCESS, lpszFile, MB_OK); ! 651: break; ! 652: ! 653: case 0x0020: // Sharing violation ! 654: ErrorWithFile(hDlg, ghInst, IDS_CIFILESHARE, lpszFile, MB_OK); ! 655: break; ! 656: ! 657: case 0x0002: // File not found ! 658: case 0x0003: // Path not found ! 659: ErrorWithFile(hDlg, ghInst, IDS_CIINVALIDFILE, lpszFile, MB_OK); ! 660: break; ! 661: ! 662: default: ! 663: ErrorWithFile(hDlg, ghInst, IDS_CIFILEOPENFAIL, lpszFile, MB_OK); ! 664: break; ! 665: } ! 666: } ! 667:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.