summaryrefslogtreecommitdiffstats
path: root/private/oleutest/letest/ole2ui/geticon.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/oleutest/letest/ole2ui/geticon.c')
-rw-r--r--private/oleutest/letest/ole2ui/geticon.c1177
1 files changed, 1177 insertions, 0 deletions
diff --git a/private/oleutest/letest/ole2ui/geticon.c b/private/oleutest/letest/ole2ui/geticon.c
new file mode 100644
index 000000000..0bf1e13b3
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/geticon.c
@@ -0,0 +1,1177 @@
+/*************************************************************************
+**
+** The following API's are now OBSOLETE because equivalent API's have been
+** added to the OLE2.DLL library
+** GetIconOfFile superceeded by OleGetIconOfFile
+** GetIconOfClass superceeded by OleGetIconOfClass
+** OleUIMetafilePictFromIconAndLabel
+** superceeded by OleMetafilePictFromIconAndLabel
+*************************************************************************/
+
+/*
+ * GETICON.C
+ *
+ * Functions to create DVASPECT_ICON metafile from filename or classname.
+ *
+ * GetIconOfFile
+ * GetIconOfClass
+ * OleUIMetafilePictFromIconAndLabel
+ * HIconAndSourceFromClass Extracts the first icon in a class's server path
+ * and returns the path and icon index to caller.
+ * FIconFileFromClass Retrieves the path to the exe/dll containing the
+ * default icon, and the index of the icon.
+ * OleStdIconLabelTextOut Draw icon label text (line break if necessary)
+ *
+ * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved
+ */
+
+
+/*******
+ *
+ * ICON (DVASPECT_ICON) METAFILE FORMAT:
+ *
+ * The metafile generated with OleUIMetafilePictFromIconAndLabel contains
+ * the following records which are used by the functions in DRAWICON.C
+ * to draw the icon with and without the label and to extract the icon,
+ * label, and icon source/index.
+ *
+ * SetWindowOrg
+ * SetWindowExt
+ * DrawIcon:
+ * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the
+ * AND mask, one for the image bits.
+ * Escape with the comment "IconOnly"
+ * This indicates where to stop record enumeration to draw only
+ * the icon.
+ * SetTextColor
+ * SetTextAlign
+ * SetBkColor
+ * CreateFont
+ * SelectObject on the font.
+ * ExtTextOut
+ * One or more ExtTextOuts occur if the label is wrapped. The
+ * text in these records is used to extract the label.
+ * SelectObject on the old font.
+ * DeleteObject on the font.
+ * Escape with a comment that contains the path to the icon source.
+ * Escape with a comment that is the ASCII of the icon index.
+ *
+ *******/
+
+#define STRICT 1
+#include "ole2ui.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <commdlg.h>
+#include <memory.h>
+#include <cderr.h>
+#include "common.h"
+#include "utility.h"
+
+static TCHAR szSeparators[] = TEXT(" \t\\/!:");
+
+#define IS_SEPARATOR(c) ( (c) == TEXT(' ') || (c) == TEXT('\\') \
+ || (c) == TEXT('/') || (c) == TEXT('\t') \
+ || (c) == TEXT('!') || (c) == TEXT(':') )
+#define IS_FILENAME_DELIM(c) ( (c) == TEXT('\\') || (c) == TEXT('/') \
+ || (c) == TEXT(':') )
+
+
+#if defined( OBSOLETE )
+static HINSTANCE s_hInst;
+
+static TCHAR szMaxWidth[] =TEXT("WWWWWWWWWW");
+
+//Strings for metafile comments.
+static TCHAR szIconOnly[]=TEXT("IconOnly"); //Where to stop to exclude label.
+
+#ifdef WIN32
+static TCHAR szOLE2DLL[] = TEXT("ole2w32.dll"); // name of OLE 2.0 library
+#else
+static TCHAR szOLE2DLL[] = TEXT("ole2.dll"); // name of OLE 2.0 library
+#endif
+
+#define ICONINDEX 0
+
+#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name
+#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
+#define PTS_PER_INCH 72 // number points (font size) per inch
+
+#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
+
+static TCHAR szVanillaDocIcon[] = TEXT("DefIcon");
+
+static TCHAR szDocument[40] = TEXT("");
+
+
+/*
+ * GetIconOfFile(HINSTANCE hInst, LPSTR lpszPath, BOOL fUseFileAsLabel)
+ *
+ * Purpose:
+ * Returns a hMetaPict containing an icon and label (filename) for the
+ * specified filename.
+ *
+ * Parameters:
+ * hinst
+ * lpszPath LPTSTR path including filename to use
+ * fUseFileAsLabel BOOL TRUE if the icon's label is the filename, FALSE if
+ * there should be no label.
+ *
+ * Return Value:
+ * HGLOBAL hMetaPict containing the icon and label - if there's no
+ * class in reg db for the file in lpszPath, then we use
+ * Document. If lpszPath is NULL, then we return NULL.
+ */
+
+STDAPI_(HGLOBAL) GetIconOfFile(HINSTANCE hInst, LPTSTR lpszPath, BOOL fUseFileAsLabel)
+{
+ TCHAR szIconFile[OLEUI_CCHPATHMAX];
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ LPTSTR lpszClsid = NULL;
+ CLSID clsid;
+ HICON hDefIcon = NULL;
+ UINT IconIndex = 0;
+ HGLOBAL hMetaPict;
+ HRESULT hResult;
+
+ if (NULL == lpszPath) // even if fUseFileAsLabel is FALSE, we still
+ return NULL; // need a valid filename to get the class.
+
+ s_hInst = hInst;
+
+ hResult = GetClassFileA(lpszPath, &clsid);
+
+ if (NOERROR == hResult) // use the clsid we got to get to the icon
+ {
+ hDefIcon = HIconAndSourceFromClass(&clsid,
+ (LPTSTR)szIconFile,
+ &IconIndex);
+ }
+
+ if ( (NOERROR != hResult) || (NULL == hDefIcon) )
+ {
+ // Here, either GetClassFile failed or HIconAndSourceFromClass failed.
+
+ LPTSTR lpszTemp;
+
+ lpszTemp = lpszPath;
+
+ while ((*lpszTemp != TEXT('.')) && (*lpszTemp != TEXT('\0')))
+ lpszTemp++;
+
+
+ if (TEXT('.') != *lpszTemp)
+ goto UseVanillaDocument;
+
+
+ if (FALSE == GetAssociatedExecutable(lpszTemp, (LPTSTR)szIconFile))
+ goto UseVanillaDocument;
+
+ hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
+ }
+
+ if (hDefIcon <= (HICON)1) // ExtractIcon returns 1 if szExecutable is not exe,
+ { // 0 if there are no icons.
+UseVanillaDocument:
+
+ lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL);
+ IconIndex = ICONINDEX;
+ hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
+
+ }
+
+ // Now let's get the label we want to use.
+
+ if (fUseFileAsLabel) // strip off path, so we just have the filename.
+ {
+ int istrlen;
+ LPTSTR lpszBeginFile;
+
+ istrlen = lstrlen(lpszPath);
+
+ // set pointer to END of path, so we can walk backwards through it.
+ lpszBeginFile = lpszPath + istrlen -1;
+
+ while ( (lpszBeginFile >= lpszPath)
+ && (!IS_FILENAME_DELIM(*lpszBeginFile)) )
+ lpszBeginFile--;
+
+
+ lpszBeginFile++; // step back over the delimiter
+
+
+ LSTRCPYN(szLabel, lpszBeginFile, sizeof(szLabel)/sizeof(TCHAR));
+ }
+
+ else // use the short user type (AuxUserType2) for the label
+ {
+
+ if (0 == OleStdGetAuxUserType(&clsid, AUXUSERTYPE_SHORTNAME,
+ (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, NULL)) {
+
+ if ('\0'==szDocument[0]) {
+ LoadString(
+ s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR));
+ }
+ lstrcpy(szLabel, szDocument);
+ }
+ }
+
+
+ hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon,
+ szLabel,
+ (LPTSTR)szIconFile,
+ IconIndex);
+
+ DestroyIcon(hDefIcon);
+
+ return hMetaPict;
+
+}
+
+
+
+/*
+ * GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel)
+ *
+ * Purpose:
+ * Returns a hMetaPict containing an icon and label (human-readable form
+ * of class) for the specified clsid.
+ *
+ * Parameters:
+ * hinst
+ * rclsid REFCLSID pointing to clsid to use.
+ * lpszLabel label to use for icon.
+ * fUseTypeAsLabel Use the clsid's user type name as the icon's label.
+ *
+ * Return Value:
+ * HGLOBAL hMetaPict containing the icon and label - if we
+ * don't find the clsid in the reg db then we
+ * return NULL.
+ */
+
+STDAPI_(HGLOBAL) GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPTSTR lpszLabel, BOOL fUseTypeAsLabel)
+{
+
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ TCHAR szIconFile[OLEUI_CCHPATHMAX];
+ HICON hDefIcon;
+ UINT IconIndex;
+ HGLOBAL hMetaPict;
+
+
+ s_hInst = hInst;
+
+ if (!fUseTypeAsLabel) // Use string passed in as label
+ {
+ if (NULL != lpszLabel)
+ LSTRCPYN(szLabel, lpszLabel, OLEUI_CCHLABELMAX_SIZE);
+ else
+ *szLabel = TEXT('\0');
+ }
+ else // Use AuxUserType2 (short name) as label
+ {
+
+ if (0 == OleStdGetAuxUserType(rclsid,
+ AUXUSERTYPE_SHORTNAME,
+ (LPTSTR)szLabel,
+ OLEUI_CCHLABELMAX_SIZE,
+ NULL))
+
+ // If we can't get the AuxUserType2, then try the long name
+ if (0 == OleStdGetUserTypeOfClass(rclsid, szLabel, OLEUI_CCHKEYMAX_SIZE, NULL)) {
+ if (TEXT('\0')==szDocument[0]) {
+ LoadString(
+ s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR));
+ }
+ lstrcpy(szLabel, szDocument); // last resort
+ }
+ }
+
+ // Get the icon, icon index, and path to icon file
+ hDefIcon = HIconAndSourceFromClass(rclsid,
+ (LPTSTR)szIconFile,
+ &IconIndex);
+
+ if (NULL == hDefIcon) // Use Vanilla Document
+ {
+ lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL);
+ IconIndex = ICONINDEX;
+ hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
+ }
+
+ // Create the metafile
+ hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon, szLabel,
+ (LPTSTR)szIconFile, IconIndex);
+
+ DestroyIcon(hDefIcon);
+
+ return hMetaPict;
+
+}
+
+
+/*
+ * OleUIMetafilePictFromIconAndLabel
+ *
+ * Purpose:
+ * Creates a METAFILEPICT structure that container a metafile in which
+ * the icon and label are drawn. A comment record is inserted between
+ * the icon and the label code so our special draw function can stop
+ * playing before the label.
+ *
+ * Parameters:
+ * hIcon HICON to draw into the metafile
+ * pszLabel LPTSTR to the label string.
+ * pszSourceFile LPTSTR containing the local pathname of the icon
+ * as we either get from the user or from the reg DB.
+ * iIcon UINT providing the index into pszSourceFile where
+ * the icon came from.
+ *
+ * Return Value:
+ * HGLOBAL Global memory handle containing a METAFILEPICT where
+ * the metafile uses the MM_ANISOTROPIC mapping mode. The
+ * extents reflect both icon and label.
+ */
+
+STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON hIcon, LPTSTR pszLabel
+ , LPTSTR pszSourceFile, UINT iIcon)
+ {
+ HDC hDC, hDCScreen;
+ HMETAFILE hMF;
+ HGLOBAL hMem;
+ LPMETAFILEPICT pMF;
+ UINT cxIcon, cyIcon;
+ UINT cxText, cyText;
+ UINT cx, cy;
+ UINT cchLabel = 0;
+ HFONT hFont, hFontT;
+ int cyFont;
+ TCHAR szIndex[10];
+ RECT TextRect;
+ SIZE size;
+ POINT point;
+ UINT fuAlign;
+
+ if (NULL==hIcon) // null label is valid but NOT a null icon
+ return NULL;
+
+ //Create a memory metafile
+ hDC=(HDC)CreateMetaFile(NULL);
+
+ if (NULL==hDC)
+ return NULL;
+
+ //Allocate the metafilepict
+ hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT));
+
+ if (NULL==hMem)
+ {
+ hMF=CloseMetaFile(hDC);
+ DeleteMetaFile(hMF);
+ return NULL;
+ }
+
+
+ if (NULL!=pszLabel)
+ {
+ cchLabel=lstrlen(pszLabel);
+
+ if (cchLabel >= OLEUI_CCHLABELMAX)
+ pszLabel[cchLabel] = TEXT('\0'); // truncate string
+ }
+
+ //Need to use the screen DC for these operations
+ hDCScreen=GetDC(NULL);
+ cyFont=-(8*GetDeviceCaps(hDCScreen, LOGPIXELSY))/72;
+
+ //cyFont was calculated to give us 8 point.
+ hFont=CreateFont(cyFont, 5, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET
+ , OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY
+ , FF_SWISS, TEXT("MS Sans Serif"));
+
+ hFontT=SelectObject(hDCScreen, hFont);
+
+ GetTextExtentPoint(hDCScreen,szMaxWidth,lstrlen(szMaxWidth),&size);
+ SelectObject(hDCScreen, hFontT);
+
+ cxText = size.cx;
+ cyText = size.cy * 2;
+
+ cxIcon = GetSystemMetrics(SM_CXICON);
+ cyIcon = GetSystemMetrics(SM_CYICON);
+
+
+ // If we have no label, then we want the metafile to be the width of
+ // the icon (plus margin), not the width of the fattest string.
+ if ( (NULL == pszLabel) || (TEXT('\0') == *pszLabel) )
+ cx = cxIcon + cxIcon / 4;
+ else
+ cx = max(cxText, cxIcon);
+
+ cy=cyIcon+cyText+4;
+
+ //Set the metafile size to fit the icon and label
+ SetWindowOrgEx(hDC, 0, 0, &point);
+ SetWindowExtEx(hDC, cx, cy, &size);
+
+ //Set up rectangle to pass to OleStdIconLabelTextOut
+ SetRectEmpty(&TextRect);
+
+ TextRect.right = cx;
+ TextRect.bottom = cy;
+
+ //Draw the icon and the text, centered with respect to each other.
+ DrawIcon(hDC, (cx-cxIcon)/2, 0, hIcon);
+
+ //String that indicates where to stop if we're only doing icons
+ Escape(hDC, MFCOMMENT, lstrlen(szIconOnly)+1, szIconOnly, NULL);
+
+ SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+ SetBkMode(hDC, TRANSPARENT);
+ fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP);
+
+ OleStdIconLabelTextOut(hDC,
+ hFont,
+ 0,
+ cy - cyText,
+ ETO_CLIPPED,
+ &TextRect,
+ pszLabel,
+ cchLabel,
+ NULL);
+
+ //Write comments containing the icon source file and index.
+ if (NULL!=pszSourceFile)
+ {
+ //+1 on string lengths insures the null terminator is embedded.
+ Escape(hDC, MFCOMMENT, lstrlen(pszSourceFile)+1, pszSourceFile, NULL);
+
+ cchLabel=wsprintf(szIndex, TEXT("%u"), iIcon);
+ Escape(hDC, MFCOMMENT, cchLabel+1, szIndex, NULL);
+ }
+
+ SetTextAlign(hDC, fuAlign);
+
+ //All done with the metafile, now stuff it all into a METAFILEPICT.
+ hMF=CloseMetaFile(hDC);
+
+ if (NULL==hMF)
+ {
+ GlobalFree(hMem);
+ ReleaseDC(NULL, hDCScreen);
+ return NULL;
+ }
+
+ //Fill out the structure
+ pMF=(LPMETAFILEPICT)GlobalLock(hMem);
+
+ //Transform to HIMETRICS
+ cx=XformWidthInPixelsToHimetric(hDCScreen, cx);
+ cy=XformHeightInPixelsToHimetric(hDCScreen, cy);
+ ReleaseDC(NULL, hDCScreen);
+
+ pMF->mm=MM_ANISOTROPIC;
+ pMF->xExt=cx;
+ pMF->yExt=cy;
+ pMF->hMF=hMF;
+
+ GlobalUnlock(hMem);
+
+ DeleteObject(hFont);
+
+ return hMem;
+ }
+
+#endif // OBSOLETE
+
+
+/*
+ * GetAssociatedExecutable
+ *
+ * Purpose: Finds the executable associated with the provided extension
+ *
+ * Parameters:
+ * lpszExtension LPSTR points to the extension we're trying to find
+ * an exe for. Does **NO** validation.
+ *
+ * lpszExecutable LPSTR points to where the exe name will be returned.
+ * No validation here either - pass in 128 char buffer.
+ *
+ * Return:
+ * BOOL TRUE if we found an exe, FALSE if we didn't.
+ *
+ */
+
+BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR lpszExtension, LPTSTR lpszExecutable)
+
+{
+ HKEY hKey;
+ LONG dw;
+ LRESULT lRet;
+ TCHAR szValue[OLEUI_CCHKEYMAX];
+ TCHAR szKey[OLEUI_CCHKEYMAX];
+ LPTSTR lpszTemp, lpszExe;
+
+
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ return FALSE;
+
+ dw = OLEUI_CCHPATHMAX_SIZE;
+ lRet = RegQueryValue(hKey, lpszExtension, (LPTSTR)szValue, &dw); //ProgId
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+
+ // szValue now has ProgID
+ lstrcpy(szKey, szValue);
+ lstrcat(szKey, TEXT("\\Shell\\Open\\Command"));
+
+
+ dw = OLEUI_CCHPATHMAX_SIZE;
+ lRet = RegQueryValue(hKey, (LPTSTR)szKey, (LPTSTR)szValue, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // szValue now has an executable name in it. Let's null-terminate
+ // at the first post-executable space (so we don't have cmd line
+ // args.
+
+ lpszTemp = (LPTSTR)szValue;
+
+ while ((TEXT('\0') != *lpszTemp) && (iswspace(*lpszTemp)))
+ lpszTemp++; // Strip off leading spaces
+
+ lpszExe = lpszTemp;
+
+ while ((TEXT('\0') != *lpszTemp) && (!iswspace(*lpszTemp)))
+ lpszTemp++; // Step through exe name
+
+ *lpszTemp = TEXT('\0'); // null terminate at first space (or at end).
+
+
+ lstrcpy(lpszExecutable, lpszExe);
+
+ return TRUE;
+
+}
+
+
+/*
+ * HIconAndSourceFromClass
+ *
+ * Purpose:
+ * Given an object class name, finds an associated executable in the
+ * registration database and extracts the first icon from that
+ * executable. If none is available or the class has no associated
+ * executable, this function returns NULL.
+ *
+ * Parameters:
+ * rclsid pointer to clsid to look up.
+ * pszSource LPSTR in which to place the source of the icon.
+ * This is assumed to be OLEUI_CCHPATHMAX
+ * puIcon UINT FAR * in which to store the index of the
+ * icon in pszSource.
+ *
+ * Return Value:
+ * HICON Handle to the extracted icon if there is a module
+ * associated to pszClass. NULL on failure to either
+ * find the executable or extract and icon.
+ */
+
+HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPTSTR pszSource, UINT FAR *puIcon)
+ {
+ HICON hIcon;
+ UINT IconIndex;
+
+ if (NULL==rclsid || NULL==pszSource || IsEqualCLSID(rclsid,&CLSID_NULL))
+ return NULL;
+
+ if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX_SIZE, &IconIndex))
+ return NULL;
+
+ hIcon=ExtractIcon(ghInst, pszSource, IconIndex);
+
+ if ((HICON)32 > hIcon)
+ hIcon=NULL;
+ else
+ *puIcon= IconIndex;
+
+ return hIcon;
+ }
+
+
+/*
+ * PointerToNthField
+ *
+ * Purpose:
+ * Returns a pointer to the beginning of the nth field.
+ * Assumes null-terminated string.
+ *
+ * Parameters:
+ * lpszString string to parse
+ * nField field to return starting index of.
+ * chDelimiter char that delimits fields
+ *
+ * Return Value:
+ * LPSTR pointer to beginning of nField field.
+ * NOTE: If the null terminator is found
+ * Before we find the Nth field, then
+ * we return a pointer to the null terminator -
+ * calling app should be sure to check for
+ * this case.
+ *
+ */
+LPTSTR FAR PASCAL PointerToNthField(LPTSTR lpszString, int nField, TCHAR chDelimiter)
+{
+ LPTSTR lpField = lpszString;
+ int cFieldFound = 1;
+
+ if (1 ==nField)
+ return lpszString;
+
+ while (*lpField != TEXT('\0'))
+ {
+
+ if (*lpField++ == chDelimiter)
+ {
+
+ cFieldFound++;
+
+ if (nField == cFieldFound)
+ return lpField;
+ }
+ }
+
+ return lpField;
+
+}
+
+
+/*
+ * FIconFileFromClass
+ *
+ * Purpose:
+ * Looks up the path to executable that contains the class default icon.
+ *
+ * Parameters:
+ * rclsid pointer to CLSID to look up.
+ * pszEXE LPSTR at which to store the server name
+ * cch UINT size of pszEXE
+ * lpIndex LPUINT to index of icon within executable
+ *
+ * Return Value:
+ * BOOL TRUE if one or more characters were loaded into pszEXE.
+ * FALSE otherwise.
+ */
+
+BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPTSTR pszEXE, UINT cchBytes, UINT FAR *lpIndex)
+{
+
+ LONG dw;
+ LONG lRet;
+ HKEY hKey;
+ LPMALLOC lpIMalloc;
+ HRESULT hrErr;
+ LPTSTR lpBuffer;
+ LPTSTR lpIndexString;
+ UINT cBufferSize = 136;// room for 128 char path and icon's index
+ TCHAR szKey[64];
+ LPSTR pszClass;
+ UINT cch=cchBytes / sizeof(TCHAR); // number of characters
+
+
+ if (NULL==rclsid || NULL==pszEXE || 0==cch || IsEqualCLSID(rclsid,&CLSID_NULL))
+ return FALSE;
+
+ //Here, we use CoGetMalloc and alloc a buffer (maxpathlen + 8) to
+ //pass to RegQueryValue. Then, we copy the exe to pszEXE and the
+ //index to *lpIndex.
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &lpIMalloc);
+
+ if (NOERROR != hrErr)
+ return FALSE;
+
+ lpBuffer = (LPTSTR)lpIMalloc->lpVtbl->Alloc(lpIMalloc, cBufferSize);
+
+ if (NULL == lpBuffer)
+ {
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+
+ if (CoIsOle1Class(rclsid))
+ {
+
+ LPOLESTR lpszProgID;
+
+ // we've got an ole 1.0 class on our hands, so we look at
+ // progID\protocol\stdfileedting\server to get the
+ // name of the executable.
+
+ ProgIDFromCLSID(rclsid, &lpszProgID);
+
+ //Open up the class key
+#ifdef UNICODE
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey);
+#else
+ {
+ char szTemp[255];
+
+ wcstombs(szTemp, lpszProgID, 255);
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, szTemp, &hKey);
+ }
+#endif
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+ dw=(LONG)cBufferSize;
+ lRet = RegQueryValue(hKey, TEXT("Protocol\\StdFileEditing\\Server"), lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+
+ // Use server and 0 as the icon index
+ LSTRCPYN(pszEXE, lpBuffer, cch);
+
+ *lpIndex = 0;
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return TRUE;
+
+ }
+
+
+
+ /*
+ * We have to go walking in the registration database under the
+ * classname, so we first open the classname key and then check
+ * under "\\DefaultIcon" to get the file that contains the icon.
+ */
+
+ StringFromCLSIDA(rclsid, &pszClass);
+
+ lstrcpy(szKey, TEXT("CLSID\\"));
+
+ lstrcat(szKey, pszClass);
+
+ //Open up the class key
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+ //Get the executable path and icon index.
+
+ dw=(LONG)cBufferSize;
+ lRet=RegQueryValue(hKey, TEXT("DefaultIcon"), lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no DefaultIcon key...try LocalServer
+
+ dw=(LONG)cBufferSize;
+ lRet=RegQueryValue(hKey, TEXT("LocalServer"), lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no LocalServer entry either...they're outta luck.
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+
+ // Use server from LocalServer or Server and 0 as the icon index
+ LSTRCPYN(pszEXE, lpBuffer, cch);
+
+ *lpIndex = 0;
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return TRUE;
+ }
+
+ RegCloseKey(hKey);
+
+ // lpBuffer contains a string that looks like "<pathtoexe>,<iconindex>",
+ // so we need to separate the path and the icon index.
+
+ lpIndexString = PointerToNthField(lpBuffer, 2, TEXT(','));
+
+ if (TEXT('\0') == *lpIndexString) // no icon index specified - use 0 as default.
+ {
+ *lpIndex = 0;
+
+ }
+ else
+ {
+ LPTSTR lpTemp;
+ static TCHAR szTemp[16];
+
+ lstrcpy((LPTSTR)szTemp, lpIndexString);
+
+ // Put the icon index part into *pIconIndex
+#ifdef UNICODE
+ {
+ char szTEMP1[16];
+
+ wcstombs(szTEMP1, szTemp, 16);
+ *lpIndex = atoi((const char *)szTEMP1);
+ }
+#else
+ *lpIndex = atoi((const char *)szTemp);
+#endif
+
+ // Null-terminate the exe part.
+#ifdef WIN32
+ lpTemp = CharPrev(lpBuffer, lpIndexString);
+#else
+ lpTemp = AnsiPrev(lpBuffer, lpIndexString);
+#endif
+ *lpTemp = TEXT('\0');
+ }
+
+ if (!LSTRCPYN(pszEXE, lpBuffer, cch))
+ {
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+ // Free the memory we alloc'd and leave.
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return TRUE;
+}
+
+
+
+/*
+ * OleStdIconLabelTextOut
+ *
+ * Purpose:
+ * Replacement for DrawText to be used in the "Display as Icon" metafile.
+ * Uses ExtTextOut to output a string center on (at most) two lines.
+ * Uses a very simple word wrap algorithm to split the lines.
+ *
+ * Parameters: (same as for ExtTextOut, except for hFont)
+ * hDC device context to draw into; if this is NULL, then we don't
+ * ETO the text, we just return the index of the beginning
+ * of the second line
+ * hFont font to use
+ * nXStart x-coordinate of starting position
+ * nYStart y-coordinate of starting position
+ * fuOptions rectangle type
+ * lpRect rect far * containing rectangle to draw text in.
+ * lpszString string to draw
+ * cchString length of string (truncated if over OLEUI_CCHLABELMAX)
+ * lpDX spacing between character cells
+ *
+ * Return Value:
+ * UINT Index of beginning of last line (0 if there's only one
+ * line of text).
+ *
+ */
+
+STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC,
+ HFONT hFont,
+ int nXStart,
+ int nYStart,
+ UINT fuOptions,
+ RECT FAR * lpRect,
+ LPTSTR lpszString,
+ UINT cchString,
+ int FAR * lpDX)
+{
+
+ HDC hDCScreen;
+ static TCHAR szTempBuff[OLEUI_CCHLABELMAX];
+ int cxString, cyString, cxMaxString;
+ int cxFirstLine, cyFirstLine, cxSecondLine;
+ int index;
+ int cch = cchString;
+ TCHAR chKeep;
+ LPTSTR lpszSecondLine;
+ HFONT hFontT;
+ BOOL fPrintText = TRUE;
+ UINT iLastLineStart = 0;
+ SIZE size;
+
+ // Initialization stuff...
+
+ if (NULL == hDC) // If we got NULL as the hDC, then we don't actually call ETO
+ fPrintText = FALSE;
+
+
+ // Make a copy of the string (NULL or non-NULL) that we're using
+ if (NULL == lpszString)
+ *szTempBuff = TEXT('\0');
+
+ else
+ LSTRCPYN(szTempBuff, lpszString, sizeof(szTempBuff)/sizeof(TCHAR));
+
+ // set maximum width
+ cxMaxString = lpRect->right - lpRect->left;
+
+ // get screen DC to do text size calculations
+ hDCScreen = GetDC(NULL);
+
+ hFontT=SelectObject(hDCScreen, hFont);
+
+ // get the extent of our label
+#ifdef WIN32
+ // GetTextExtentPoint32 has fixed the off-by-one bug.
+ GetTextExtentPoint32(hDCScreen, szTempBuff, cch, &size);
+#else
+ GetTextExtentPoint(hDCScreen, szTempBuff, cch, &size);
+#endif
+
+ cxString = size.cx;
+ cyString = size.cy;
+
+ // Select in the font we want to use
+ if (fPrintText)
+ SelectObject(hDC, hFont);
+
+ // String is smaller than max string - just center, ETO, and return.
+ if (cxString <= cxMaxString)
+ {
+
+ if (fPrintText)
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxString) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ szTempBuff,
+ cch,
+ NULL);
+
+ iLastLineStart = 0; // only 1 line of text
+ goto CleanupAndLeave;
+ }
+
+ // String is too long...we've got to word-wrap it.
+
+
+ // Are there any spaces, slashes, tabs, or bangs in string?
+
+ if (lstrlen(szTempBuff) != (int)
+#ifdef UNICODE
+ wcscspn(szTempBuff, szSeparators)
+#else
+ strcspn(szTempBuff, szSeparators)
+#endif
+ )
+ {
+ // Yep, we've got spaces, so we'll try to find the largest
+ // space-terminated string that will fit on the first line.
+
+ index = cch;
+
+
+ while (index >= 0)
+ {
+
+ TCHAR cchKeep;
+
+ // scan the string backwards for spaces, slashes, tabs, or bangs
+
+ while (!IS_SEPARATOR(szTempBuff[index]) )
+ index--;
+
+
+ if (index <= 0)
+ break;
+
+ cchKeep = szTempBuff[index]; // remember what char was there
+
+ szTempBuff[index] = TEXT('\0'); // just for now
+
+#ifdef WIN32
+ GetTextExtentPoint32(
+ hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size);
+#else
+ GetTextExtentPoint(
+ hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size);
+#endif
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ szTempBuff[index] = cchKeep; // put the right char back
+
+ if (cxFirstLine <= cxMaxString)
+ {
+
+ iLastLineStart = index + 1;
+
+ if (!fPrintText)
+ goto CleanupAndLeave;
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxFirstLine) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ (LPTSTR)szTempBuff,
+ index + 1,
+ lpDX);
+
+ lpszSecondLine = (LPTSTR)szTempBuff;
+
+ lpszSecondLine += (index + 1) ;
+
+ GetTextExtentPoint(hDCScreen,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ &size);
+
+ // If the second line is wider than the rectangle, we
+ // just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxSecondLine) / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ lpDX);
+
+ goto CleanupAndLeave;
+
+ } // end if
+
+ index--;
+
+ } // end while
+
+ } // end if
+
+ // Here, there are either no spaces in the string (strchr(szTempBuff, ' ')
+ // returned NULL), or there spaces in the string, but they are
+ // positioned so that the first space terminated string is still
+ // longer than one line. So, we walk backwards from the end of the
+ // string until we find the largest string that will fit on the first
+ // line , and then we just clip the second line.
+
+ cch = lstrlen((LPTSTR)szTempBuff);
+
+ chKeep = szTempBuff[cch];
+ szTempBuff[cch] = TEXT('\0');
+
+ GetTextExtentPoint(hDCScreen, szTempBuff, lstrlen(szTempBuff),&size);
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ while (cxFirstLine > cxMaxString)
+ {
+ // We allow 40 characters in the label, but the metafile is
+ // only as wide as 10 W's (for aesthetics - 20 W's wide looked
+ // dumb. This means that if we split a long string in half (in
+ // terms of characters), then we could still be wider than the
+ // metafile. So, if this is the case, we just step backwards
+ // from the halfway point until we get something that will fit.
+ // Since we just let ETO clip the second line
+
+ szTempBuff[cch--] = chKeep;
+ if (0 == cch)
+ goto CleanupAndLeave;
+
+ chKeep = szTempBuff[cch];
+ szTempBuff[cch] = TEXT('\0');
+
+ GetTextExtentPoint(
+ hDCScreen, szTempBuff, lstrlen(szTempBuff), &size);
+ cxFirstLine = size.cx;
+ }
+
+ iLastLineStart = cch;
+
+ if (!fPrintText)
+ goto CleanupAndLeave;
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxFirstLine) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ (LPTSTR)szTempBuff,
+ lstrlen((LPTSTR)szTempBuff),
+ lpDX);
+
+ szTempBuff[cch] = chKeep;
+ lpszSecondLine = szTempBuff;
+ lpszSecondLine += cch ;
+
+ GetTextExtentPoint(
+ hDCScreen, (LPTSTR)lpszSecondLine, lstrlen(lpszSecondLine), &size);
+
+ // If the second line is wider than the rectangle, we
+ // just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxSecondLine) / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ lpDX);
+
+CleanupAndLeave:
+ SelectObject(hDCScreen, hFontT);
+ ReleaseDC(NULL, hDCScreen);
+ return iLastLineStart;
+
+}
+