GETICON.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:31k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*************************************************************************
  2. **
  3. ** The following API's are now OBSOLETE because equivalent API's have been
  4. ** added to the OLE2.DLL library
  5. **      GetIconOfFile       superceeded by OleGetIconOfFile
  6. **      GetIconOfClass      superceeded by OleGetIconOfClass
  7. **      OleUIMetafilePictFromIconAndLabel
  8. **                          superceeded by OleMetafilePictFromIconAndLabel
  9. *************************************************************************/
  10. /*
  11.  *  GETICON.C
  12.  *
  13.  *  Functions to create DVASPECT_ICON metafile from filename or classname.
  14.  *
  15.  *  GetIconOfFile
  16.  *  GetIconOfClass
  17.  *  OleUIMetafilePictFromIconAndLabel
  18.  *  HIconAndSourceFromClass Extracts the first icon in a class's server path
  19.  *                          and returns the path and icon index to caller.
  20.  *  FIconFileFromClass      Retrieves the path to the exe/dll containing the
  21.  *                           default icon, and the index of the icon.
  22.  *  OleStdIconLabelTextOut  Draw icon label text (line break if necessary)
  23.  *
  24.  *    (c) Copyright Microsoft Corp. 1992-1996 All Rights Reserved
  25.  */
  26. /*******
  27.  *
  28.  * ICON (DVASPECT_ICON) METAFILE FORMAT:
  29.  *
  30.  * The metafile generated with OleUIMetafilePictFromIconAndLabel contains
  31.  * the following records which are used by the functions in DRAWICON.C
  32.  * to draw the icon with and without the label and to extract the icon,
  33.  * label, and icon source/index.
  34.  *
  35.  *  SetWindowOrg
  36.  *  SetWindowExt
  37.  *  DrawIcon:
  38.  *      Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the
  39.  *      AND mask, one for the image bits.
  40.  *  Escape with the comment "IconOnly"
  41.  *      This indicates where to stop record enumeration to draw only
  42.  *      the icon.
  43.  *  SetTextColor
  44.  *  SetTextAlign
  45.  *  SetBkColor
  46.  *  CreateFont
  47.  *  SelectObject on the font.
  48.  *  ExtTextOut
  49.  *      One or more ExtTextOuts occur if the label is wrapped.  The
  50.  *      text in these records is used to extract the label.
  51.  *  SelectObject on the old font.
  52.  *  DeleteObject on the font.
  53.  *  Escape with a comment that contains the path to the icon source.
  54.  *  Escape with a comment that is the ASCII of the icon index.
  55.  *
  56.  *******/
  57. #define STRICT  1
  58. #include "olestd.h"
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <ctype.h>
  62. #include <commdlg.h>
  63. #include <memory.h>
  64. #include <cderr.h>
  65. #include "common.h"
  66. #include "utility.h"
  67. static char szSeparators[] = " t\/!:";
  68. #define IS_SEPARATOR(c)         ( (c) == ' ' || (c) == '\' || (c) == '/' || (c) == 't' || (c) == '!' || (c) == ':' )
  69. #define IS_FILENAME_DELIM(c)    ( (c) == '\' || (c) == '/' || (c) == ':' )
  70. #if defined( OBSOLETE )
  71. static HINSTANCE  s_hInst;
  72. static char szMaxWidth[] ="WWWWWWWWWW";
  73. //Strings for metafile comments.
  74. static OLECHAR szIconOnly[]= OLESTR("IconOnly");        //Where to stop to exclude label.
  75. static char szOLE2DLL[] = "ole2.dll";   // name of OLE 2.0 library
  76. #define ICONINDEX              0
  77. #define AUXUSERTYPE_SHORTNAME  USERCLASSTYPE_SHORT  // short name
  78. #define HIMETRIC_PER_INCH   2540      // number HIMETRIC units per inch
  79. #define PTS_PER_INCH          72      // number points (font size) per inch
  80. #define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
  81. #define MAP_LOGHIM_TO_PIX(x,ppli)   MulDiv((ppli), (x), HIMETRIC_PER_INCH)
  82. static char szVanillaDocIcon[] = "DefIcon";
  83. static char szDocument[40] = "";
  84. /*
  85.  * GetIconOfFile(HINSTANCE hInst, LPSTR lpszPath, BOOL fUseFileAsLabel)
  86.  *
  87.  * Purpose:
  88.  *  Returns a hMetaPict containing an icon and label (filename) for the
  89.  *  specified filename.
  90.  *
  91.  * Parameters:
  92.  *  hinst
  93.  *  lpszPath        LPSTR path including filename to use
  94.  *  fUseFileAsLabel BOOL TRUE if the icon's label is the filename, FALSE if
  95.  *                  there should be no label.
  96.  *
  97.  * Return Value:
  98.  *  HGLOBAL         hMetaPict containing the icon and label - if there's no
  99.  *                  class in reg db for the file in lpszPath, then we use
  100.  *                  Document.  If lpszPath is NULL, then we return NULL.
  101.  */
  102. STDAPI_(HGLOBAL) GetIconOfFile(HINSTANCE hInst, LPSTR lpszPath, BOOL fUseFileAsLabel)
  103. {
  104.   char     szIconFile[OLEUI_CCHPATHMAX];
  105.   char     szLabel[OLEUI_CCHLABELMAX];
  106.   LPSTR    lpszClsid = NULL;
  107.   CLSID    clsid;
  108.   HICON    hDefIcon = NULL;
  109.   UINT     IconIndex = 0;
  110.   HGLOBAL  hMetaPict;
  111.   HRESULT  hResult;
  112.   if (NULL == lpszPath)  // even if fUseFileAsLabel is FALSE, we still
  113.    return NULL;             // need a valid filename to get the class.
  114.   s_hInst = hInst;
  115.   hResult = GetClassFile(lpszPath, &clsid);
  116.   if (NOERROR == hResult)  // use the clsid we got to get to the icon
  117.   {
  118.      hDefIcon = HIconAndSourceFromClass(&clsid,
  119.                                szIconFile,
  120.                                &IconIndex);
  121.   }
  122.   if ( (NOERROR != hResult) || (NULL == hDefIcon) )
  123.   {
  124.     // Here, either GetClassFile failed or HIconAndSourceFromClass failed.
  125.     LPSTR lpszTemp;
  126.     lpszTemp = lpszPath;
  127.     while ((*lpszTemp != '.') && (*lpszTemp != ''))
  128.       lpszTemp++;
  129.     if ('.' != *lpszTemp)
  130.       goto UseVanillaDocument;
  131.     if (FALSE == GetAssociatedExecutable(lpszTemp, szIconFile))
  132.       goto UseVanillaDocument;
  133.     hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
  134.   }
  135.   if (hDefIcon <= (HICON)1) // ExtractIcon returns 1 if szExecutable is not exe,
  136.   {                         // 0 if there are no icons.
  137. UseVanillaDocument:
  138.    OLESTRCPY(szIconFile, szOLE2DLL);
  139.    IconIndex = ICONINDEX;
  140.    hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
  141.   }
  142.   // Now let's get the label we want to use.
  143.   if (fUseFileAsLabel)   // strip off path, so we just have the filename.
  144.   {
  145.     int istrlen;
  146.     LPSTR lpszBeginFile;
  147.     istrlen = lstrlen(lpszPath);
  148.     // set pointer to END of path, so we can walk backwards through it.
  149.     lpszBeginFile = lpszPath + istrlen -1;
  150.     while ( (lpszBeginFile >= lpszPath)
  151.           && (!IS_FILENAME_DELIM(*lpszBeginFile)) )
  152.      lpszBeginFile--;
  153.     lpszBeginFile++;  // step back over the delimiter
  154.     LSTRCPYN(szLabel, lpszBeginFile, OLEUI_CCHLABELMAX);
  155.   }
  156.   else   // use the short user type (AuxUserType2) for the label
  157.   {
  158.      if (0 == OleStdGetAuxUserType(&clsid, AUXUSERTYPE_SHORTNAME,
  159.                            szLabel, OLEUI_CCHLABELMAX, NULL)) {
  160.        if (''==szDocument[0]) {
  161.           LoadString(
  162.              s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument));
  163.        }
  164.        lstrcpy(szLabel, szDocument);
  165.      }
  166.   }
  167.   hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon,
  168.                                     szLabel,
  169.                                     szIconFile,
  170.                                     IconIndex);
  171.   DestroyIcon(hDefIcon);
  172.   return hMetaPict;
  173. }
  174. /*
  175.  * GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel)
  176.  *
  177.  * Purpose:
  178.  *  Returns a hMetaPict containing an icon and label (human-readable form
  179.  *  of class) for the specified clsid.
  180.  *
  181.  * Parameters:
  182.  *  hinst
  183.  *  rclsid          REFCLSID pointing to clsid to use.
  184.  *  lpszLabel       label to use for icon.
  185.  *  fUseTypeAsLabel Use the clsid's user type name as the icon's label.
  186.  *
  187.  * Return Value:
  188.  *  HGLOBAL         hMetaPict containing the icon and label - if we
  189.  *                  don't find the clsid in the reg db then we
  190.  *                  return NULL.
  191.  */
  192. STDAPI_(HGLOBAL)    GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel)
  193. {
  194.   char    szLabel[OLEUI_CCHLABELMAX];
  195.   char    szIconFile[OLEUI_CCHPATHMAX];
  196.   HICON   hDefIcon;
  197.   UINT    IconIndex;
  198.   HGLOBAL hMetaPict;
  199.   s_hInst = hInst;
  200.   if (!fUseTypeAsLabel)  // Use string passed in as label
  201.   {
  202.    if (NULL != lpszLabel)
  203.       LSTRCPYN(szLabel, lpszLabel, sizeof(szLabel));
  204.    else
  205.       *szLabel = '';
  206.   }
  207.   else   // Use AuxUserType2 (short name) as label
  208.   {
  209.      if (0 == OleStdGetAuxUserType(rclsid,
  210.                            AUXUSERTYPE_SHORTNAME,
  211.                            szLabel,
  212.                            OLEUI_CCHLABELMAX,
  213.                            NULL))
  214.       // If we can't get the AuxUserType2, then try the long name
  215.       if (0 == OleStdGetUserTypeOfClass(rclsid, szLabel, OLEUI_CCHKEYMAX, NULL)) {
  216.        if (''==szDocument[0]) {
  217.           LoadString(
  218.              s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument));
  219.        }
  220.        lstrcpy(szLabel, szDocument);  // last resort
  221.       }
  222.   }
  223.   // Get the icon, icon index, and path to icon file
  224.   hDefIcon = HIconAndSourceFromClass(rclsid,
  225.               szIconFile,
  226.               &IconIndex);
  227.   if (NULL == hDefIcon)  // Use Vanilla Document
  228.   {
  229.    OLESTRCPY(szIconFile, szOLE2DLL);
  230.    IconIndex = ICONINDEX;
  231.    hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
  232.   }
  233.   // Create the metafile
  234.   hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon, szLabel,
  235.                                     szIconFile, IconIndex);
  236.   DestroyIcon(hDefIcon);
  237.   return hMetaPict;
  238. }
  239. /*
  240.  * OleUIMetafilePictFromIconAndLabel
  241.  *
  242.  * Purpose:
  243.  *  Creates a METAFILEPICT structure that container a metafile in which
  244.  *  the icon and label are drawn.  A comment record is inserted between
  245.  *  the icon and the label code so our special draw function can stop
  246.  *  playing before the label.
  247.  *
  248.  * Parameters:
  249.  *  hIcon           HICON to draw into the metafile
  250.  *  pszLabel        LPSTR to the label string.
  251.  *  pszSourceFile   LPSTR containing the local pathname of the icon
  252.  *                  as we either get from the user or from the reg DB.
  253.  *  iIcon           UINT providing the index into pszSourceFile where
  254.  *                  the icon came from.
  255.  *
  256.  * Return Value:
  257.  *  HGLOBAL         Global memory handle containing a METAFILEPICT where
  258.  *                  the metafile uses the MM_ANISOTROPIC mapping mode.  The
  259.  *                  extents reflect both icon and label.
  260.  */
  261. STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON hIcon, LPSTR pszLabel
  262.    , LPSTR pszSourceFile, UINT iIcon)
  263.    {
  264.    HDC             hDC, hDCScreen;
  265.    HMETAFILE       hMF;
  266.    HGLOBAL         hMem;
  267.    LPMETAFILEPICT  pMF;
  268.    UINT            cxIcon, cyIcon;
  269.    UINT            cxText, cyText;
  270.    UINT            cx, cy;
  271.    UINT            cchLabel = 0;
  272.    HFONT           hFont, hFontT;
  273.    int             cyFont;
  274.    char            szIndex[10];
  275.    RECT            TextRect;
  276.    SIZE            size;
  277.    POINT           point;
  278.    UINT            fuAlign;
  279.    if (NULL==hIcon)  // null label is valid but NOT a null icon
  280.       return NULL;
  281.    //Create a memory metafile
  282.    hDC=(HDC)CreateMetaFile(NULL);
  283.    if (NULL==hDC)
  284.       return NULL;
  285.    //Allocate the metafilepict
  286.    hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT));
  287.    if (NULL==hMem)
  288.       {
  289.       hMF=CloseMetaFile(hDC);
  290.       DeleteMetaFile(hMF);
  291.       return NULL;
  292.       }
  293.    if (NULL!=pszLabel)
  294.       {
  295.       cchLabel=lstrlen(pszLabel);
  296.       if (cchLabel >= OLEUI_CCHLABELMAX)
  297.          pszLabel[cchLabel] = '';   // truncate string
  298.       }
  299.    //Need to use the screen DC for these operations
  300.    hDCScreen=GetDC(NULL);
  301.    cyFont=-(8*GetDeviceCaps(hDCScreen, LOGPIXELSY))/72;
  302.    //cyFont was calculated to give us 8 point.
  303.    hFont=CreateFont(cyFont, 5, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET
  304.       , OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY
  305.       , FF_SWISS, "MS Sans Serif");
  306.    hFontT=SelectObject(hDCScreen, hFont);
  307.    GetTextExtentPoint(hDCScreen,szMaxWidth,lstrlen(szMaxWidth),&size);
  308.    SelectObject(hDCScreen, hFontT);
  309.    cxText = size.cx;
  310.    cyText = size.cy * 2;
  311.    cxIcon = GetSystemMetrics(SM_CXICON);
  312.    cyIcon = GetSystemMetrics(SM_CYICON);
  313.    // If we have no label, then we want the metafile to be the width of
  314.    // the icon (plus margin), not the width of the fattest string.
  315.    if ( (NULL == pszLabel) || ('' == *pszLabel) )
  316.       cx = cxIcon + cxIcon / 4;
  317.    else
  318.       cx = max(cxText, cxIcon);
  319.    cy=cyIcon+cyText+4;
  320.    //Set the metafile size to fit the icon and label
  321.    SetWindowOrgEx(hDC, 0, 0, &point);
  322.    SetWindowExtEx(hDC, cx, cy, &size);
  323.    //Set up rectangle to pass to OleStdIconLabelTextOut
  324.    SetRectEmpty(&TextRect);
  325.    TextRect.right = cx;
  326.    TextRect.bottom = cy;
  327.    //Draw the icon and the text, centered with respect to each other.
  328.    DrawIcon(hDC, (cx-cxIcon)/2, 0, hIcon);
  329.    //String that indicates where to stop if we're only doing icons
  330.    Escape(hDC, MFCOMMENT, lstrlen(szIconOnly)+1, szIconOnly, NULL);
  331.    SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  332.    SetBkMode(hDC, TRANSPARENT);
  333.    fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP);
  334.    OleStdIconLabelTextOut(hDC,
  335.                      hFont,
  336.                      0,
  337.                      cy - cyText,
  338.                      ETO_CLIPPED,
  339.                      &TextRect,
  340.                      pszLabel,
  341.                      cchLabel,
  342.                      NULL);
  343.    //Write comments containing the icon source file and index.
  344.    if (NULL!=pszSourceFile)
  345.       {
  346.       //+1 on string lengths insures the null terminator is embedded.
  347.       Escape(hDC, MFCOMMENT, lstrlen(pszSourceFile)+1, pszSourceFile, NULL);
  348.       cchLabel=wsprintf(szIndex, "%u", iIcon);
  349.       Escape(hDC, MFCOMMENT, cchLabel+1, szIndex, NULL);
  350.       }
  351.    SetTextAlign(hDC, fuAlign);
  352.    //All done with the metafile, now stuff it all into a METAFILEPICT.
  353.    hMF=CloseMetaFile(hDC);
  354.    if (NULL==hMF)
  355.       {
  356.       GlobalFree(hMem);
  357.       ReleaseDC(NULL, hDCScreen);
  358.       return NULL;
  359.       }
  360.    //Fill out the structure
  361.    pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  362.    //Transform to HIMETRICS
  363.    cx=XformWidthInPixelsToHimetric(hDCScreen, cx);
  364.    cy=XformHeightInPixelsToHimetric(hDCScreen, cy);
  365.    ReleaseDC(NULL, hDCScreen);
  366.    pMF->mm=MM_ANISOTROPIC;
  367.    pMF->xExt=cx;
  368.    pMF->yExt=cy;
  369.    pMF->hMF=hMF;
  370.    GlobalUnlock(hMem);
  371.    DeleteObject(hFont);
  372.    return hMem;
  373.    }
  374. #endif  // OBSOLETE
  375. /*
  376.  * GetAssociatedExecutable
  377.  *
  378.  * Purpose:  Finds the executable associated with the provided extension
  379.  *
  380.  * Parameters:
  381.  *   lpszExtension   LPSTR points to the extension we're trying to find
  382.  *                   an exe for. Does **NO** validation.
  383.  *
  384.  *   lpszExecutable  LPSTR points to where the exe name will be returned.
  385.  *                   No validation here either - pass in 128 char buffer.
  386.  *
  387.  * Return:
  388.  *   BOOL            TRUE if we found an exe, FALSE if we didn't.
  389.  *
  390.  */
  391. BOOL FAR PASCAL GetAssociatedExecutable(LPSTR lpszExtension, LPSTR lpszExecutable)
  392. {
  393.    HKEY    hKey;
  394.    LONG    dw;
  395.    LRESULT lRet;
  396.    char    szValue[OLEUI_CCHKEYMAX];
  397.    char    szKey[OLEUI_CCHKEYMAX];
  398.    LPSTR   lpszTemp, lpszExe;
  399.    lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
  400.    if (ERROR_SUCCESS != lRet)
  401.      return FALSE;
  402.    dw = OLEUI_CCHPATHMAX;
  403.    lRet = RegQueryValue(hKey, lpszExtension, szValue, &dw);  //ProgId
  404.    if (ERROR_SUCCESS != lRet)
  405.    {
  406.      RegCloseKey(hKey);
  407.      return FALSE;
  408.    }
  409.    // szValue now has ProgID
  410.    lstrcpy(szKey, szValue);
  411.    lstrcat(szKey, "\Shell\Open\Command");
  412.    dw = OLEUI_CCHPATHMAX;
  413.    lRet = RegQueryValue(hKey, szKey, szValue, &dw);
  414.    if (ERROR_SUCCESS != lRet)
  415.    {
  416.      RegCloseKey(hKey);
  417.      return FALSE;
  418.    }
  419.    // szValue now has an executable name in it.  Let's null-terminate
  420.    // at the first post-executable space (so we don't have cmd line
  421.    // args.
  422.    lpszTemp = szValue;
  423.    while (('' != *lpszTemp) && (isspace(*lpszTemp)))
  424.      lpszTemp++;     // Strip off leading spaces
  425.    lpszExe = lpszTemp;
  426.    while (('' != *lpszTemp) && (!isspace(*lpszTemp)))
  427.      lpszTemp++;     // Step through exe name
  428.    *lpszTemp = '';  // null terminate at first space (or at end).
  429.    lstrcpy(lpszExecutable, lpszExe);
  430.    return TRUE;
  431. }
  432. /*
  433.  * HIconAndSourceFromClass
  434.  *
  435.  * Purpose:
  436.  *  Given an object class name, finds an associated executable in the
  437.  *  registration database and extracts the first icon from that
  438.  *  executable.  If none is available or the class has no associated
  439.  *  executable, this function returns NULL.
  440.  *
  441.  * Parameters:
  442.  *  rclsid          pointer to clsid to look up.
  443.  *  pszSource       LPSTR in which to place the source of the icon.
  444.  *                  This is assumed to be OLEUI_CCHPATHMAX
  445.  *  puIcon          UINT FAR * in which to store the index of the
  446.  *                  icon in pszSource.
  447.  *
  448.  * Return Value:
  449.  *  HICON           Handle to the extracted icon if there is a module
  450.  *                  associated to pszClass.  NULL on failure to either
  451.  *                  find the executable or extract and icon.
  452.  */
  453. HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPSTR pszSource, UINT FAR *puIcon)
  454.    {
  455.    HICON           hIcon;
  456.    UINT            IconIndex;
  457.    if (NULL==rclsid || NULL==pszSource || IsEqualCLSID(rclsid,&CLSID_NULL))
  458.       return NULL;
  459.    if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX, &IconIndex))
  460.       return NULL;
  461.    hIcon=ExtractIcon(ghInst, pszSource, IconIndex);
  462.    if ((HICON)32 > hIcon)
  463.       hIcon=NULL;
  464.    else
  465.       *puIcon= IconIndex;
  466.    return hIcon;
  467.    }
  468. /*
  469.  * PointerToNthField
  470.  *
  471.  * Purpose:
  472.  *  Returns a pointer to the beginning of the nth field.
  473.  *  Assumes null-terminated string.
  474.  *
  475.  * Parameters:
  476.  *  lpszString        string to parse
  477.  *  nField            field to return starting index of.
  478.  *  chDelimiter       char that delimits fields
  479.  *
  480.  * Return Value:
  481.  *  LPSTR             pointer to beginning of nField field.
  482.  *                    NOTsE: If the null terminator is found
  483.  *                          Before we find the Nth field, then
  484.  *                          we return a pointer to the null terminator -
  485.  *                          calling app should be sure to check for
  486.  *                          this case.
  487.  *
  488.  */
  489. LPSTR FAR PASCAL PointerToNthField(LPSTR lpszString, int nField, char chDelimiter)
  490. {
  491.    LPSTR lpField = lpszString;
  492.    int   cFieldFound = 1;
  493.    if (1 ==nField)
  494.      return lpszString;
  495.    while (*lpField != '')
  496.    {
  497.      if (*lpField++ == chDelimiter)
  498.      {
  499.        cFieldFound++;
  500.        if (nField == cFieldFound)
  501.          return lpField;
  502.      }
  503.    }
  504.    return lpField;
  505. }
  506. /*
  507.  * FIconFileFromClass
  508.  *
  509.  * Purpose:
  510.  *  Looks up the path to executable that contains the class default icon.
  511.  *
  512.  * Parameters:
  513.  *  rclsid          pointer to CLSID to look up.
  514.  *  pszEXE          LPSTR at which to store the server name
  515.  *  cch             UINT size of pszEXE
  516.  *  lpIndex         LPUINT to index of icon within executable
  517.  *
  518.  * Return Value:
  519.  *  BOOL            TRUE if one or more characters were loaded into pszEXE.
  520.  *                  FALSE otherwise.
  521.  */
  522. BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPSTR pszEXE, UINT cch, UINT FAR *lpIndex)
  523. {
  524.    LONG          dw;
  525.    LONG          lRet;
  526.    HKEY          hKey;
  527.    LPMALLOC      lpIMalloc;
  528.    HRESULT       hrErr;
  529.    LPSTR         lpBuffer;
  530.    LPSTR         lpIndexString;
  531.    UINT          cBufferSize = 136;// room for 128 char path and icon's index
  532.    char          szKey[64];
  533.    char          pszClass[256];
  534.    LPOLESTR      pszUniClass;
  535.    if (NULL==rclsid || NULL==pszEXE || 0==cch || IsEqualCLSID(rclsid,&CLSID_NULL))
  536.       return FALSE;
  537.    //Here, we use CoGetMalloc and alloc a buffer (maxpathlen + 8) to
  538.    //pass to RegQueryValue.  Then, we copy the exe to pszEXE and the
  539.    //index to *lpIndex.
  540.    hrErr = CoGetMalloc(MEMCTX_TASK, &lpIMalloc);
  541.    if (NOERROR != hrErr)
  542.      return FALSE;
  543.    lpBuffer = /*(LPSTR)*/lpIMalloc->lpVtbl->Alloc(lpIMalloc, cBufferSize);
  544.    if (NULL == lpBuffer)
  545.    {
  546.      lpIMalloc->lpVtbl->Release(lpIMalloc);
  547.      return FALSE;
  548.    }
  549.    if (CoIsOle1Class(rclsid))
  550.    {
  551.      LPOLESTR lpszUniProgID;
  552.      char lpszProgID[256];
  553.      // we've got an ole 1.0 class on our hands, so we look at
  554.      // progIDprotocolstdfileedtingserver to get the
  555.      // name of the executable.
  556.      ProgIDFromCLSID(rclsid, &lpszUniProgID);
  557.      W2A (lpszUniProgID, lpszProgID, 256);
  558.      //Open up the class key
  559.      lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey);
  560.      if (ERROR_SUCCESS != lRet)
  561.      {
  562.        lpIMalloc->lpVtbl->Free(lpIMalloc, lpszUniProgID);
  563.        lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  564.        lpIMalloc->lpVtbl->Release(lpIMalloc);
  565.        return FALSE;
  566.      }
  567.      dw=(LONG)cBufferSize;
  568.      lRet = RegQueryValue(hKey, "Protocol\StdFileEditing\Server", lpBuffer, &dw);
  569.      if (ERROR_SUCCESS != lRet)
  570.      {
  571.        RegCloseKey(hKey);
  572.        lpIMalloc->lpVtbl->Free(lpIMalloc, lpszUniProgID);
  573.        lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  574.        lpIMalloc->lpVtbl->Release(lpIMalloc);
  575.        return FALSE;
  576.      }
  577.      // Use server and 0 as the icon index
  578.      LSTRCPYN(pszEXE, lpBuffer, cch);
  579.      *lpIndex = 0;
  580.      RegCloseKey(hKey);
  581.      lpIMalloc->lpVtbl->Free(lpIMalloc, lpszUniProgID);
  582.      lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  583.      lpIMalloc->lpVtbl->Release(lpIMalloc);
  584.      return TRUE;
  585.    }
  586.    /*
  587.     * We have to go walking in the registration database under the
  588.     * classname, so we first open the classname key and then check
  589.     * under "\DefaultIcon" to get the file that contains the icon.
  590.     */
  591.    StringFromCLSID(rclsid, &pszUniClass);
  592.    W2A (pszUniClass, pszClass, 256);
  593.    lstrcpy(szKey, "CLSID\");
  594.    lstrcat(szKey, pszClass);
  595.    //Open up the class key
  596.    lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey);
  597.    if (ERROR_SUCCESS != lRet)
  598.    {
  599.       lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  600.       lpIMalloc->lpVtbl->Free(lpIMalloc, pszUniClass);
  601.       lpIMalloc->lpVtbl->Release(lpIMalloc);
  602.       return FALSE;
  603.    }
  604.    //Get the executable path and icon index.
  605.    dw=(LONG)cBufferSize;
  606.    lRet=RegQueryValue(hKey, "DefaultIcon", lpBuffer, &dw);
  607.    if (ERROR_SUCCESS != lRet)
  608.    {
  609.      // no DefaultIcon  key...try LocalServer
  610.      dw=(LONG)cBufferSize;
  611. #ifdef WIN32
  612.      lRet=RegQueryValue(hKey, "LocalServer32", lpBuffer, &dw);
  613. #else
  614.      lRet=RegQueryValue(hKey, "LocalServer", lpBuffer, &dw);
  615. #endif
  616.      if (ERROR_SUCCESS != lRet)
  617.      {
  618.        // no LocalServer entry either...they're outta luck.
  619.        RegCloseKey(hKey);
  620.        lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  621.        lpIMalloc->lpVtbl->Free(lpIMalloc, pszUniClass);
  622.        lpIMalloc->lpVtbl->Release(lpIMalloc);
  623.        return FALSE;
  624.      }
  625.      // Use server from LocalServer or Server and 0 as the icon index
  626.      LSTRCPYN(pszEXE, lpBuffer, cch);
  627.      *lpIndex = 0;
  628.      RegCloseKey(hKey);
  629.      lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  630.      lpIMalloc->lpVtbl->Free(lpIMalloc, pszUniClass);
  631.      lpIMalloc->lpVtbl->Release(lpIMalloc);
  632.      return TRUE;
  633.    }
  634.    RegCloseKey(hKey);
  635.    // lpBuffer contains a string that looks like "<pathtoexe>,<iconindex>",
  636.    // so we need to separate the path and the icon index.
  637.    lpIndexString = PointerToNthField(lpBuffer, 2, ',');
  638.    if ('' == *lpIndexString)  // no icon index specified - use 0 as default.
  639.    {
  640.       *lpIndex = 0;
  641.    }
  642.    else
  643.    {
  644.       LPSTR lpTemp;
  645.       static char  szTemp[16];
  646.       lstrcpy(szTemp, lpIndexString);
  647.       // Put the icon index part into *pIconIndex
  648.       *lpIndex = atoi((const char *)szTemp);
  649.       // Null-terminate the exe part.
  650.       lpTemp = AnsiPrev(lpBuffer, lpIndexString);
  651.       *lpTemp = '';
  652.    }
  653.    if (!LSTRCPYN(pszEXE, lpBuffer, cch))
  654.    {
  655.       lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  656.       lpIMalloc->lpVtbl->Free(lpIMalloc, pszUniClass);
  657.       lpIMalloc->lpVtbl->Release(lpIMalloc);
  658.       return FALSE;
  659.    }
  660.    // Free the memory we alloc'd and leave.
  661.    lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
  662.    lpIMalloc->lpVtbl->Free(lpIMalloc, pszUniClass);
  663.    lpIMalloc->lpVtbl->Release(lpIMalloc);
  664.    return TRUE;
  665. }
  666. /*
  667.  * OleStdIconLabelTextOut
  668.  *
  669.  * Purpose:
  670.  *  Replacement for DrawText to be used in the "Display as Icon" metafile.
  671.  *  Uses ExtTextOut to output a string center on (at most) two lines.
  672.  *  Uses a very simple word wrap algorithm to split the lines.
  673.  *
  674.  * Parameters:  (same as for ExtTextOut, except for hFont)
  675.  *  hDC           device context to draw into; if this is NULL, then we don't
  676.  *                ETO the text, we just return the index of the beginning
  677.  *                of the second line
  678.  *  hFont         font to use
  679.  *  nXStart       x-coordinate of starting position
  680.  *  nYStart       y-coordinate of starting position
  681.  *  fuOptions     rectangle type
  682.  *  lpRect        rect far * containing rectangle to draw text in.
  683.  *  lpszString    string to draw
  684.  *  cchString     length of string (truncated if over OLEUI_CCHLABELMAX)
  685.  *  lpDX          spacing between character cells
  686.  *
  687.  * Return Value:
  688.  *  UINT          Index of beginning of last line (0 if there's only one
  689.  *                line of text).
  690.  *
  691.  */
  692. STDAPI_(UINT) OleStdIconLabelTextOut(HDC        hDC,
  693.                             HFONT      hFont,
  694.                             int        nXStart,
  695.                             int        nYStart,
  696.                             UINT       fuOptions,
  697.                             RECT FAR * lpRect,
  698.                             LPOLESTR   lpszString,
  699.                             UINT       cchString,
  700.                             int FAR *  lpDX)
  701. {
  702.   HDC          hDCScreen;
  703.   static char  szTempBuff[OLEUI_CCHLABELMAX];
  704.   int          cxString, cyString, cxMaxString;
  705.   int          cxFirstLine, cyFirstLine, cxSecondLine;
  706.   int          index;
  707.   int          cch = cchString;
  708.   char         chKeep;
  709.   LPSTR        lpszSecondLine;
  710.   HFONT        hFontT;
  711.   BOOL         fPrintText = TRUE;
  712.   UINT         iLastLineStart = 0;
  713.   SIZE         size;
  714.   // Initialization stuff...
  715.   if (NULL == hDC)  // If we got NULL as the hDC, then we don't actually call ETO
  716.    fPrintText = FALSE;
  717.   // Make a copy of the string (NULL or non-NULL) that we're using
  718.   if (NULL == lpszString)
  719.    *szTempBuff = '';
  720.   else
  721.   {
  722.      W2A (lpszString, szTempBuff, OLEUI_CCHLABELMAX);
  723.   }
  724.   // set maximum width
  725.   cxMaxString = lpRect->right - lpRect->left;
  726.   // get screen DC to do text size calculations
  727.   hDCScreen = GetDC(NULL);
  728.   hFontT=SelectObject(hDCScreen, hFont);
  729.   // get the extent of our label
  730.   GetTextExtentPoint(hDCScreen, szTempBuff, cch, &size);
  731.   cxString = size.cx;
  732.   cyString = size.cy;
  733.   // Select in the font we want to use
  734.   if (fPrintText)
  735.     SelectObject(hDC, hFont);
  736.   // String is smaller than max string - just center, ETO, and return.
  737.   if (cxString <= cxMaxString)
  738.   {
  739.    if (fPrintText)
  740.       ExtTextOut(hDC,
  741.               nXStart + (lpRect->right - cxString) / 2,
  742.               nYStart,
  743.               fuOptions,
  744.               lpRect,
  745.               szTempBuff,
  746.               cch,
  747.               NULL);
  748.    iLastLineStart = 0;  // only 1 line of text
  749.    goto CleanupAndLeave;
  750.   }
  751.   // String is too long...we've got to word-wrap it.
  752.   // Are there any spaces, slashes, tabs, or bangs in string?
  753.   if (lstrlen(szTempBuff) != (int)strcspn(szTempBuff, szSeparators))
  754.   {
  755.     // Yep, we've got spaces, so we'll try to find the largest
  756.     // space-terminated string that will fit on the first line.
  757.     index = cch;
  758.     while (index >= 0)
  759.     {
  760.       char cchKeep;
  761.       // scan the string backwards for spaces, slashes, tabs, or bangs
  762.       while (!IS_SEPARATOR(szTempBuff[index]) )
  763.        index--;
  764.       if (index <= 0)
  765.        break;
  766.       cchKeep = szTempBuff[index];  // remember what char was there
  767.       szTempBuff[index] = '';  // just for now
  768.       GetTextExtentPoint(
  769.             hDCScreen, szTempBuff,lstrlen(szTempBuff),&size);
  770.       cxFirstLine = size.cx;
  771.       cyFirstLine = size.cy;
  772.       szTempBuff[index] = cchKeep;   // put the right char back
  773.       if (cxFirstLine <= cxMaxString)
  774.       {
  775.          iLastLineStart = index + 1;
  776.          if (!fPrintText)
  777.           goto CleanupAndLeave;
  778.          ExtTextOut(hDC,
  779.                  nXStart +  (lpRect->right - cxFirstLine) / 2,
  780.                  nYStart,
  781.                  fuOptions,
  782.                  lpRect,
  783.                  szTempBuff,
  784.                  index + 1,
  785.                  lpDX);
  786.          lpszSecondLine = szTempBuff;
  787.          lpszSecondLine += index + 1;
  788.          GetTextExtentPoint(hDCScreen,
  789.                            lpszSecondLine,
  790.                            lstrlen(lpszSecondLine),
  791.                            &size);
  792.          // If the second line is wider than the rectangle, we
  793.          // just want to clip the text.
  794.          cxSecondLine = min(size.cx, cxMaxString);
  795.          ExtTextOut(hDC,
  796.                  nXStart + (lpRect->right - cxSecondLine) / 2,
  797.                  nYStart + cyFirstLine,
  798.                  fuOptions,
  799.                  lpRect,
  800.                  lpszSecondLine,
  801.                  lstrlen(lpszSecondLine),
  802.                  lpDX);
  803.          goto CleanupAndLeave;
  804.       }  // end if
  805.       index--;
  806.     }  // end while
  807.   }  // end if
  808.   // Here, there are either no spaces in the string (strchr(szTempBuff, ' ')
  809.   // returned NULL), or there spaces in the string, but they are
  810.   // positioned so that the first space terminated string is still
  811.   // longer than one line. So, we walk backwards from the end of the
  812.   // string until we find the largest string that will fit on the first
  813.   // line , and then we just clip the second line.
  814.   cch = lstrlen(szTempBuff);
  815.   chKeep = szTempBuff[cch];
  816.   szTempBuff[cch] = '';
  817.   GetTextExtentPoint(hDCScreen, szTempBuff, lstrlen(szTempBuff),&size);
  818.   cxFirstLine = size.cx;
  819.   cyFirstLine = size.cy;
  820.   while (cxFirstLine > cxMaxString)
  821.   {
  822.     // We allow 40 characters in the label, but the metafile is
  823.     // only as wide as 10 W's (for aesthetics - 20 W's wide looked
  824.     // dumb.  This means that if we split a long string in half (in
  825.     // terms of characters), then we could still be wider than the
  826.     // metafile.  So, if this is the case, we just step backwards
  827.     // from the halfway point until we get something that will fit.
  828.     // Since we just let ETO clip the second line
  829.     szTempBuff[cch--] = chKeep;
  830.     if (0 == cch)
  831.       goto CleanupAndLeave;
  832.     chKeep = szTempBuff[cch];
  833.     szTempBuff[cch] = '';
  834.     GetTextExtentPoint(
  835.           hDCScreen, szTempBuff, lstrlen(szTempBuff), &size);
  836.     cxFirstLine = size.cx;
  837.   }
  838.   iLastLineStart = cch;
  839.   if (!fPrintText)
  840.    goto CleanupAndLeave;
  841.   ExtTextOut(hDC,
  842.           nXStart + (lpRect->right - cxFirstLine) / 2,
  843.           nYStart,
  844.           fuOptions,
  845.           lpRect,
  846.           szTempBuff,
  847.           lstrlen(szTempBuff),
  848.           lpDX);
  849.   szTempBuff[cch] = chKeep;
  850.   lpszSecondLine = szTempBuff;
  851.   lpszSecondLine += cch;
  852.   GetTextExtentPoint(
  853.         hDCScreen, lpszSecondLine, lstrlen(lpszSecondLine), &size);
  854.   // If the second line is wider than the rectangle, we
  855.   // just want to clip the text.
  856.   cxSecondLine = min(size.cx, cxMaxString);
  857.   ExtTextOut(hDC,
  858.           nXStart + (lpRect->right - cxSecondLine) / 2,
  859.           nYStart + cyFirstLine,
  860.           fuOptions,
  861.           lpRect,
  862.           lpszSecondLine,
  863.           lstrlen(lpszSecondLine),
  864.           lpDX);
  865. CleanupAndLeave:
  866.   SelectObject(hDCScreen, hFontT);
  867.   ReleaseDC(NULL, hDCScreen);
  868.   return iLastLineStart;
  869. }