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