Annotation of mstools/ole20/samples/ole2ui/pastespl.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * PASTESPL.C
                      3:  *
                      4:  * Implements the OleUIPasteSpecial function which invokes the complete
                      5:  * Paste Special dialog.
                      6:  *
                      7:  * Copyright (c)1992 Microsoft Corporation, All Rights Reserved
                      8:  */
                      9: 
                     10: #define STRICT  1
                     11: #include "ole2ui.h"
                     12: #include "pastespl.h"
                     13: #include "common.h"
                     14: #include "utility.h"
                     15: #include "resimage.h"
                     16: #include "iconbox.h"
                     17: #include "geticon.h"
                     18: #include "regdb.h"
                     19: #include <stdlib.h>
                     20: 
                     21: OLEDBGDATA
                     22: 
                     23: /*
                     24:  * OleUIPasteSpecial
                     25:  *
                     26:  * Purpose:
                     27:  *  Invokes the standard OLE Paste Special dialog box which allows the user
                     28:  *  to select the format of the clipboard object to be pasted or paste linked.
                     29:  *
                     30:  * Parameters:
                     31:  *  lpPS         LPOLEUIPasteSpecial pointing to the in-out structure
                     32:  *               for this dialog.
                     33:  *
                     34:  * Return Value:
                     35:  *  UINT        One of the following codes or one of the standard error codes (OLEUI_ERR_*)
                     36:  *              defined in OLE2UI.H, indicating success or error:
                     37:  *              OLEUI_OK                           User selected OK
                     38:  *              OLEUI_CANCEL                       User cancelled the dialog
                     39:  *              OLEUI_IOERR_SRCDATAOBJECTINVALID   lpSrcDataObject field of OLEUIPASTESPECIAL invalid
                     40:  *              OLEUI_IOERR_ARRPASTEENTRIESINVALID arrPasteEntries field of OLEUIPASTESPECIAL invalid
                     41:  *              OLEUI_IOERR_ARRLINKTYPESINVALID    arrLinkTypes field of OLEUIPASTESPECIAL invalid
                     42:  *              OLEUI_PSERR_CLIPBOARDCHANGED       Clipboard contents changed while dialog was up
                     43:  */
                     44: 
                     45: STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL lpPS)
                     46: {
                     47:     UINT        uRet;
                     48:     HGLOBAL     hMemDlg=NULL;
                     49: 
                     50:     uRet=UStandardValidation((LPOLEUISTANDARD)lpPS, sizeof(OLEUIPASTESPECIAL)
                     51:         , &hMemDlg);
                     52: 
                     53:     if (uRet != OLEUI_SUCCESS)
                     54:         return uRet;
                     55: 
                     56:     //Validate PasteSpecial specific fields
                     57:     if (NULL == lpPS->lpSrcDataObj || IsBadReadPtr(lpPS->lpSrcDataObj,  sizeof(IDataObject)))
                     58:         uRet = OLEUI_IOERR_SRCDATAOBJECTINVALID;
                     59:     if (NULL == lpPS->arrPasteEntries || IsBadReadPtr(lpPS->arrPasteEntries,  sizeof(OLEUIPASTEENTRY)))
                     60:         uRet = OLEUI_IOERR_ARRPASTEENTRIESINVALID;
                     61:     if (NULL != lpPS->arrLinkTypes && IsBadReadPtr(lpPS->arrLinkTypes,  sizeof(UINT)))
                     62:         uRet = OLEUI_IOERR_ARRLINKTYPESINVALID;
                     63:     if (uRet >= OLEUI_ERR_STANDARDMIN)
                     64:     {
                     65:         if (NULL != hMemDlg)
                     66:             FreeResource(hMemDlg);
                     67:         return uRet;
                     68:     }
                     69: 
                     70:     //Now that we've validated everything, we can invoke the dialog.
                     71:     uRet = UStandardInvocation(PasteSpecialDialogProc, (LPOLEUISTANDARD)lpPS
                     72:         , hMemDlg, MAKEINTRESOURCE(IDD_PASTESPECIAL));
                     73: 
                     74:     /*
                     75:     * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE.
                     76:     */
                     77: 
                     78:     return uRet;
                     79: }
                     80: 
                     81: 
                     82: /*
                     83:  * PasteSpecialDialogProc
                     84:  *
                     85:  * Purpose:
                     86:  *  Implements the OLE Paste Special dialog as invoked through the
                     87:  *  OleUIPasteSpecial function.
                     88:  *
                     89:  * Parameters:
                     90:  *  Standard
                     91:  *
                     92:  * Return Value:
                     93:  *  Standard
                     94:  */
                     95: 
                     96: BOOL CALLBACK EXPORT PasteSpecialDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
                     97: {
                     98:     LPOLEUIPASTESPECIAL     lpOPS;
                     99:     LPPASTESPECIAL          lpPS;
                    100:     BOOL                    fHook=FALSE;
                    101:     HCURSOR                 hCursorOld;
                    102: 
                    103:     //Declare Win16/Win32 compatible WM_COMMAND parameters.
                    104:     COMMANDPARAMS(wID, wCode, hWndMsg);
                    105: 
                    106:     //This will fail under WM_INITDIALOG, where we allocate it.
                    107:     lpPS=(LPPASTESPECIAL)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &fHook);
                    108: 
                    109:     //If the hook processed the message, we're done.
                    110:     if (0!=fHook)
                    111:         return fHook;
                    112: 
                    113:     // Process help message from Change Icon
                    114:     if (iMsg == uMsgHelp)
                    115:     {
                    116:         PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, wParam, lParam);
                    117:         return FALSE;
                    118:     }
                    119: 
                    120:     //Process the temination message
                    121:     if (iMsg==uMsgEndDialog)
                    122:     {
                    123:         HWND    hwndNextViewer;
                    124: 
                    125:         // Free the icon/icon-title metafile corresponding to Paste/PasteList option which is not selected
                    126:         if (lpPS->fLink)
                    127:             OleUIMetafilePictIconFree(lpPS->hMetaPictOD);
                    128:         else OleUIMetafilePictIconFree(lpPS->hMetaPictLSD);
                    129: 
                    130:         // Free data associated with each list box entry
                    131:         FreeListData(GetDlgItem(hDlg, ID_PS_PASTELIST));
                    132:         FreeListData(GetDlgItem(hDlg, ID_PS_PASTELINKLIST));
                    133: 
                    134:         //Free any specific allocations before calling StandardCleanup
                    135:         if (lpPS->hObjDesc) GlobalFree(lpPS->hObjDesc);
                    136:         if (lpPS->hLinkSrcDesc) GlobalFree(lpPS->hLinkSrcDesc);
                    137:         if (lpPS->hBuff) GlobalFree(lpPS->hBuff);
                    138: 
                    139:         // Change the clipboard notification chain
                    140:         hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
                    141:         if (hwndNextViewer != HWND_BROADCAST)
                    142:         {
                    143:             SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
                    144:             ChangeClipboardChain(hDlg, hwndNextViewer);
                    145:         }
                    146:         RemoveProp(hDlg, NEXTCBVIEWER);
                    147: 
                    148:         StandardCleanup(lpPS, hDlg);
                    149:         EndDialog(hDlg, wParam);
                    150:         return TRUE;
                    151:     }
                    152: 
                    153:     switch (iMsg)
                    154:     {
                    155:         case WM_INITDIALOG:
                    156:             hCursorOld = HourGlassOn();
                    157:             FPasteSpecialInit(hDlg, wParam, lParam);
                    158:             HourGlassOff(hCursorOld);
                    159:             return TRUE;
                    160: 
                    161:         case WM_DRAWCLIPBOARD:
                    162:         {
                    163:             HWND    hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
                    164: 
                    165:             if (hwndNextViewer == HWND_BROADCAST)
                    166:                 break;
                    167: 
                    168:             if (hwndNextViewer)
                    169:             {
                    170:                 SendMessage(hwndNextViewer, iMsg, wParam, lParam);
                    171:                 // Refresh next viewer in case it got modified
                    172:                 //    by the SendMessage() (likely if multiple
                    173:                 //    PasteSpecial dialogs are up simultaneously)
                    174:                 hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
                    175:             }
                    176:             SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
                    177:             ChangeClipboardChain(hDlg, hwndNextViewer);
                    178:             wParam = OLEUI_PSERR_CLIPBOARDCHANGED;
                    179:             goto LCancel;
                    180:         }
                    181: 
                    182:         case WM_CHANGECBCHAIN:
                    183:         {
                    184:             HWND    hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
                    185: 
                    186:             if (wParam == (WORD)hwndNextViewer)
                    187:                 SetProp(hDlg, NEXTCBVIEWER, (hwndNextViewer = (HWND)LOWORD(lParam)));
                    188:             else if (hwndNextViewer && hwndNextViewer != HWND_BROADCAST)
                    189:                 SendMessage(hwndNextViewer, iMsg, wParam, lParam);
                    190:             break;
                    191:         }
                    192: 
                    193:         case WM_COMMAND:
                    194:             switch (wID)
                    195:             {
                    196:                 case ID_PS_PASTE:
                    197:                     FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
                    198:                     break;
                    199: 
                    200:                 case ID_PS_PASTELINK:
                    201:                     FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
                    202:                     break;
                    203: 
                    204:                 case ID_PS_DISPLAYLIST:
                    205:                     switch (wCode)
                    206:                     {
                    207:                         case LBN_SELCHANGE:
                    208:                             ChangeListSelection(hDlg, lpPS, hWndMsg);
                    209:                             break;
                    210: 
                    211:                         case LBN_DBLCLK:
                    212:                             // Same as pressing OK
                    213:                             SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
                    214:                             break;
                    215:                     }
                    216:                     break;
                    217: 
                    218:                 case ID_PS_DISPLAYASICON:
                    219:                     ToggleDisplayAsIcon(hDlg, lpPS);
                    220:                     break;
                    221: 
                    222:                 case ID_PS_CHANGEICON:
                    223:                     ChangeIcon(hDlg, lpPS);
                    224:                     break;
                    225: 
                    226:                 case IDOK:
                    227:                     lpOPS = lpPS->lpOPS;
                    228:                     // Return current flags
                    229:                     lpOPS->dwFlags = lpPS->dwFlags;
                    230:                     // Return index of arrPasteEntries[] corresponding to format selected by user
                    231:                     lpOPS->nSelectedIndex = lpPS->nSelectedIndex;
                    232:                     // Return if user selected Paste or PasteLink
                    233:                     lpOPS->fLink = lpPS->fLink;
                    234:                     // Return metafile with icon and icon title that the user selected
                    235:                     lpOPS->hMetaPict=(HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY,
                    236:                                                     IBXM_IMAGEGET, 0, 0L);
                    237:                     SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
                    238:                     break;
                    239: 
                    240:                 case IDCANCEL:
                    241:                     wParam = OLEUI_CANCEL;
                    242:                   LCancel:
                    243:                     // Free icon and icon title metafile
                    244:                     SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L);
                    245:                     SendMessage(hDlg, uMsgEndDialog, wParam, 0L);
                    246:                     break;
                    247: 
                    248:                 case ID_OLEUIHELP:
                    249:                     PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp,
                    250:                         (WPARAM)hDlg, MAKELPARAM(IDD_PASTESPECIAL, 0));
                    251:                     break;
                    252:             }
                    253:             break;
                    254:     }
                    255:     return FALSE;
                    256: }
                    257: 
                    258: 
                    259: /*
                    260:  * FPasteSpecialInit
                    261:  *
                    262:  * Purpose:
                    263:  *  WM_INITIDIALOG handler for the Paste Special dialog box.
                    264:  *
                    265:  * Parameters:
                    266:  *  hDlg            HWND of the dialog
                    267:  *  wParam          WPARAM of the message
                    268:  *  lParam          LPARAM of the message
                    269:  *
                    270:  * Return Value:
                    271:  *  BOOL            Value to return for WM_INITDIALOG.
                    272:  */
                    273: 
                    274: BOOL FPasteSpecialInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
                    275: {
                    276:     LPPASTESPECIAL              lpPS;
                    277:     LPOLEUIPASTESPECIAL         lpOPS;
                    278:     HFONT                       hFont;
                    279:     BOOL                        fPasteAvailable, fPasteLinkAvailable;
                    280:     STGMEDIUM                   medium;
                    281:     LPOBJECTDESCRIPTOR          lpOD;
                    282:     LPLINKSRCDESCRIPTOR         lpLSD;
                    283:     int                         n;
                    284:     CLIPFORMAT                  cfFormat;
                    285: 
                    286:     // Copy the structure at lParam into our instance memory.
                    287:     lpPS = (LPPASTESPECIAL)LpvStandardInit(hDlg, sizeof(PASTESPECIAL), TRUE, &hFont);
                    288: 
                    289:     // PvStandardInit sent a termination to us already.
                    290:     if (NULL == lpPS)
                    291:         return FALSE;
                    292: 
                    293:     lpOPS=(LPOLEUIPASTESPECIAL)lParam;
                    294: 
                    295:     // Copy other information from lpOPS that we might modify.
                    296:     lpPS->lpOPS = lpOPS;
                    297:     lpPS->dwFlags = lpOPS->dwFlags;
                    298: 
                    299:     // Initialize user selections in the Paste and PasteLink listboxes
                    300:     lpPS->nPasteListCurSel = 0;
                    301:     lpPS->nPasteLinkListCurSel = 0;
                    302: 
                    303:     // If we got a font, send it to the necessary controls.
                    304:     if (NULL!=hFont)
                    305:     {
                    306:         SendDlgItemMessage(hDlg, ID_PS_SOURCETEXT, WM_SETFONT, (WPARAM)hFont, 0L);
                    307:         SendDlgItemMessage(hDlg, ID_PS_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
                    308:     }
                    309: 
                    310:     // Hide the help button if required
                    311:     if (!(lpPS->lpOPS->dwFlags & PSF_SHOWHELP))
                    312:         StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
                    313: 
                    314:     // PSF_CHECKDISPLAYASICON is an OUT flag. Clear it if has been set on the way in.
                    315:     lpPS->dwFlags = lpPS->dwFlags & ~PSF_CHECKDISPLAYASICON;
                    316: 
                    317:     //  Change the caption if required
                    318:     if (NULL != lpOPS->lpszCaption)
                    319:         SetWindowText(hDlg, lpOPS->lpszCaption);
                    320: 
                    321:     // Load 'Unknown Source' and 'Unknown Type' strings
                    322:     n = LoadString(ghInst, IDS_PSUNKNOWNTYPE, lpPS->szUnknownType, PS_UNKNOWNSTRLEN);
                    323:     if (n)
                    324:         n = LoadString(ghInst, IDS_PSUNKNOWNSRC, lpPS->szUnknownSource, PS_UNKNOWNSTRLEN);
                    325:     if (!n)
                    326:     {
                    327:         PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
                    328:         return FALSE;
                    329:     }
                    330:     lpPS->szAppName[0]='\0';
                    331: 
                    332:     // GetData CF_OBJECTDESCRIPTOR. If the object on the clipboard in an OLE1 object (offering CF_OWNERLINK)
                    333:     // or has been copied to clipboard by FileMaager (offering CF_FILENAME), an OBJECTDESCRIPTOR will be
                    334:     // created will be created from CF_OWNERLINK or CF_FILENAME. See OBJECTDESCRIPTOR for more info.
                    335: 
                    336:     if (lpPS->hObjDesc = OleStdFillObjectDescriptorFromData(lpOPS->lpSrcDataObj, &medium, &cfFormat))
                    337:     {
                    338:         lpOD = GlobalLock(lpPS->hObjDesc);
                    339: 
                    340:         // Get FullUserTypeName, SourceOfCopy and CLSID
                    341:         if (lpOD->dwFullUserTypeName)
                    342:             lpPS->szFullUserTypeNameOD = (LPSTR)lpOD+lpOD->dwFullUserTypeName;
                    343:         else lpPS->szFullUserTypeNameOD = lpPS->szUnknownType;
                    344: 
                    345:         if (lpOD->dwSrcOfCopy)
                    346:         {
                    347:             lpPS->szSourceOfDataOD = (LPSTR)lpOD+lpOD->dwSrcOfCopy;
                    348:             // If CF_FILENAME was offered, source of copy is a path name. Fit the path to the
                    349:             // static control that will display it.
                    350:             if (cfFormat == cfFileName)
                    351:                 lpPS->szSourceOfDataOD = ChopText(GetDlgItem(hDlg, ID_PS_SOURCETEXT), 0, lpPS->szSourceOfDataOD);
                    352:         }
                    353:         else lpPS->szSourceOfDataOD = lpPS->szUnknownSource;
                    354: 
                    355:         lpPS->clsidOD = lpOD->clsid;
                    356: 
                    357:         // Does source specify DVASPECT_ICON?
                    358:         if (lpOD->dwDrawAspect & DVASPECT_ICON)
                    359:            lpPS->fSrcAspectIconOD = TRUE;
                    360:         else lpPS->fSrcAspectIconOD = FALSE;
                    361: 
                    362:         // Does source specify OLEMISC_ONLYICONIC?
                    363:         if (lpOD->dwStatus & OLEMISC_ONLYICONIC)
                    364:             lpPS->fSrcOnlyIconicOD = TRUE;
                    365:         else lpPS->fSrcOnlyIconicOD = FALSE;
                    366: 
                    367:         // Get application name of source from auxusertype3 in the registration database
                    368:         if (0==OleStdGetAuxUserType(&lpPS->clsidOD, 3, lpPS->szAppName, OLEUI_CCHKEYMAX, NULL))
                    369:         {
                    370:              // Use "the application which created it" as the name of the application
                    371:              if (0==LoadString(ghInst, IDS_PSUNKNOWNAPP, lpPS->szAppName, PS_UNKNOWNSTRLEN))
                    372:              {
                    373:                  PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
                    374:                  return FALSE;
                    375:              }
                    376:         }
                    377: 
                    378:         // Retrieve an icon from the object
                    379:         if (lpPS->fSrcAspectIconOD)
                    380:         {
                    381:             lpPS->hMetaPictOD = OleStdGetData(
                    382:                 lpOPS->lpSrcDataObj,
                    383:                 CF_METAFILEPICT,
                    384:                 NULL,
                    385:                 DVASPECT_ICON,
                    386:                 &medium
                    387:             );
                    388: 
                    389:         }
                    390:         // If object does not offer icon, obtain it from the CLSID
                    391:         if (NULL == lpPS->hMetaPictOD)
                    392:         {
                    393:             lpPS->hMetaPictOD = GetIconOfClass(
                    394:                     ghInst,
                    395:                     &lpPS->clsidOD,
                    396:                     NULL,
                    397:                     TRUE   // Use the short user type name (auxusertype3)
                    398:             );
                    399: 
                    400: 
                    401:         }
                    402:     }
                    403: 
                    404:     // Does object offer CF_LINKSRCDESCRIPTOR?
                    405:     if (lpPS->hLinkSrcDesc = OleStdGetData(
                    406:             lpOPS->lpSrcDataObj,
                    407:             cfLinkSrcDescriptor,
                    408:             NULL,
                    409:             DVASPECT_CONTENT,
                    410:             &medium))
                    411:     {
                    412:         // Get FullUserTypeName, SourceOfCopy and CLSID
                    413:         lpLSD = GlobalLock(lpPS->hLinkSrcDesc);
                    414:         if (lpLSD->dwFullUserTypeName)
                    415:             lpPS->szFullUserTypeNameLSD = (LPSTR)lpLSD+lpLSD->dwFullUserTypeName;
                    416:         else lpPS->szFullUserTypeNameLSD = lpPS->szUnknownType;
                    417: 
                    418:         if (lpLSD->dwSrcOfCopy)
                    419:             lpPS->szSourceOfDataLSD = (LPSTR)lpLSD+lpLSD->dwSrcOfCopy;
                    420:         else lpPS->szSourceOfDataLSD = lpPS->szUnknownSource;
                    421: 
                    422:         lpPS->clsidLSD = lpLSD->clsid;
                    423: 
                    424:         // Does source specify DVASPECT_ICON?
                    425:         if (lpOD->dwDrawAspect & DVASPECT_ICON)
                    426:            lpPS->fSrcAspectIconLSD = TRUE;
                    427:         else lpPS->fSrcAspectIconLSD = FALSE;
                    428: 
                    429:         // Does source specify OLEMISC_ONLYICONIC?
                    430:         if (lpLSD->dwStatus & OLEMISC_ONLYICONIC)
                    431:             lpPS->fSrcOnlyIconicLSD = TRUE;
                    432:         else lpPS->fSrcOnlyIconicLSD = FALSE;
                    433: 
                    434:         // Retrieve an icon from the object
                    435:         if (lpPS->fSrcAspectIconLSD)
                    436:         {
                    437:             lpPS->hMetaPictLSD = OleStdGetData(
                    438:                 lpOPS->lpSrcDataObj,
                    439:                 CF_METAFILEPICT,
                    440:                 NULL,
                    441:                 DVASPECT_ICON,
                    442:                 &medium
                    443:             );
                    444: 
                    445:         }
                    446:         // If object does not offer icon, obtain it from the CLSID
                    447:         if (NULL == lpPS->hMetaPictLSD)
                    448:         {
                    449:             char szLabel[OLEUI_CCHLABELMAX];
                    450:             HWND hIconWnd;
                    451:             RECT IconRect;
                    452:             int  nWidth;
                    453:             LPSTR lpszLabel;
                    454: 
                    455:             hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY);
                    456: 
                    457:             GetClientRect(hIconWnd, &IconRect);
                    458: 
                    459:             nWidth = (IconRect.right * 3) / 2;   // width is 1.5 times width of iconbox
                    460: 
                    461:             lstrcpyn(szLabel, lpPS->szSourceOfDataLSD, sizeof(szLabel));
                    462:             szLabel[sizeof(szLabel)-1] = '\0';
                    463: 
                    464:             lpszLabel = ChopText(hIconWnd, nWidth, (LPSTR)szLabel);
                    465: 
                    466:             lpPS->hMetaPictLSD = GetIconOfClass(
                    467:                     ghInst,
                    468:                     &lpPS->clsidLSD,
                    469:                     lpszLabel,       // use chopped source string as label
                    470:                     FALSE            // not applicable
                    471:             );
                    472:         }
                    473:     }
                    474:     else if (lpPS->hObjDesc)     // Does not offer CF_LINKSRCDESCRIPTOR but offers CF_OBJECTDESCRIPTOR
                    475:     {
                    476:         // Copy the values of OBJECTDESCRIPTOR
                    477:         lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD;
                    478:         lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD;
                    479:         lpPS->clsidLSD = lpPS->clsidOD;
                    480:         lpPS->fSrcAspectIconLSD = lpPS->fSrcAspectIconOD;
                    481:         lpPS->fSrcOnlyIconicLSD = lpPS->fSrcOnlyIconicOD;
                    482: 
                    483:         // Don't copy the hMetaPict; instead get a separate copy
                    484:         if (lpPS->fSrcAspectIconLSD)
                    485:         {
                    486:             lpPS->hMetaPictLSD = OleStdGetData(
                    487:                 lpOPS->lpSrcDataObj,
                    488:                 CF_METAFILEPICT,
                    489:                 NULL,
                    490:                 DVASPECT_ICON,
                    491:                 &medium
                    492:             );
                    493:         }
                    494:         if (NULL == lpPS->hMetaPictLSD)
                    495:         {
                    496:             char szLabel[OLEUI_CCHLABELMAX];
                    497:             HWND hIconWnd;
                    498:             RECT IconRect;
                    499:             int  nWidth;
                    500:             LPSTR lpszLabel;
                    501: 
                    502:             hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY);
                    503: 
                    504:             GetClientRect(hIconWnd, &IconRect);
                    505: 
                    506:             nWidth = (IconRect.right * 3) / 2;   // width is 1.5 times width of iconbox
                    507: 
                    508:             lstrcpyn(szLabel, lpPS->szSourceOfDataLSD, sizeof(szLabel));
                    509:             szLabel[sizeof(szLabel)-1] = '\0';
                    510: 
                    511:             lpszLabel = ChopText(hIconWnd, nWidth, (LPSTR)szLabel);
                    512: 
                    513:             lpPS->hMetaPictLSD = GetIconOfClass(
                    514:                     ghInst,
                    515:                     &lpPS->clsidLSD,
                    516:                     lpszLabel,   // Use chopped source string as label
                    517:                     FALSE             // Not applicable
                    518:             );
                    519:         }
                    520:     }
                    521: 
                    522:     // Not an OLE object
                    523:     if (lpPS->hObjDesc == NULL && lpPS->hLinkSrcDesc == NULL)
                    524:     {
                    525:          lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD = lpPS->szUnknownType;
                    526:          lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD = lpPS->szUnknownSource;
                    527:          lpPS->hMetaPictLSD = lpPS->hMetaPictOD = NULL;
                    528:     }
                    529: 
                    530:     // Allocate scratch memory to construct item names in the paste and pastelink listboxes
                    531:     lpPS->hBuff = AllocateScratchMem(lpPS);
                    532:     if (lpPS->hBuff == NULL)
                    533:     {
                    534:        PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L);
                    535:        return FALSE;
                    536:     }
                    537: 
                    538:     // Select the Paste Link Button if specified. Otherwise select
                    539:     //      Paste Button by default
                    540:     if (lpPS->dwFlags & PSF_SELECTPASTELINK)
                    541:         lpPS->dwFlags = (lpPS->dwFlags & ~PSF_SELECTPASTE) | PSF_SELECTPASTELINK;
                    542:     else
                    543:         lpPS->dwFlags =(lpPS->dwFlags & ~PSF_SELECTPASTELINK) | PSF_SELECTPASTE;
                    544: 
                    545:     // Mark which PasteEntry formats are available from source data object
                    546:     OleStdMarkPasteEntryList(
                    547:             lpOPS->lpSrcDataObj,lpOPS->arrPasteEntries,lpOPS->cPasteEntries);
                    548: 
                    549:     // Check if items are available to be pasted
                    550:     fPasteAvailable = FFillPasteList(hDlg, lpPS);
                    551:     if (!fPasteAvailable)
                    552:     {
                    553:         lpPS->dwFlags &= ~PSF_SELECTPASTE;
                    554:         EnableWindow(GetDlgItem(hDlg, ID_PS_PASTE), FALSE);
                    555:     }
                    556: 
                    557:     // Check if items are available to be paste-linked
                    558:     fPasteLinkAvailable = FFillPasteLinkList(hDlg, lpPS);
                    559:     if (!fPasteLinkAvailable)
                    560:     {
                    561:         lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
                    562:         EnableWindow(GetDlgItem(hDlg, ID_PS_PASTELINK), FALSE);
                    563:     }
                    564: 
                    565:     // If one of Paste or PasteLink is disabled, select the other one regardless of what
                    566:     //    the input flags say
                    567:     if (fPasteAvailable && !fPasteLinkAvailable)
                    568:         lpPS->dwFlags |= PSF_SELECTPASTE;
                    569:     if (fPasteLinkAvailable && !fPasteAvailable)
                    570:         lpPS->dwFlags |= PSF_SELECTPASTELINK;
                    571: 
                    572:     if (lpPS->dwFlags & PSF_SELECTPASTE)
                    573:     {
                    574:         // FTogglePaste will set the PSF_SELECTPASTE flag, so clear it.
                    575:         lpPS->dwFlags &= ~PSF_SELECTPASTE;
                    576:         CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTE);
                    577:         FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
                    578:     }
                    579:     else if (lpPS->dwFlags & PSF_SELECTPASTELINK)
                    580:     {
                    581:         // FTogglePaste will set the PSF_SELECTPASTELINK flag, so clear it.
                    582:         lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
                    583:         CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTELINK);
                    584:         FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
                    585:     }
                    586:     else  // Items are not available to be be Pasted or Paste-Linked
                    587:     {
                    588:         // Enable or disable DisplayAsIcon and set the result text and image
                    589:         EnableDisplayAsIcon(hDlg, lpPS);
                    590:         SetPasteSpecialHelpResults(hDlg, lpPS);
                    591:     }
                    592: 
                    593:     // Set property to handle clipboard change notifications
                    594:     SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
                    595:     SetProp(hDlg, NEXTCBVIEWER, SetClipboardViewer(hDlg));
                    596: 
                    597:     /*
                    598:      * PERFORM OTHER INITIALIZATION HERE.
                    599:      */
                    600: 
                    601:     // Call the hook with lCustData in lParam
                    602:     UStandardHook(lpPS, hDlg, WM_INITDIALOG, wParam, lpOPS->lCustData);
                    603:     return TRUE;
                    604: }
                    605: 
                    606: /*
                    607:  * FTogglePasteType
                    608:  *
                    609:  * Purpose:
                    610:  *  Toggles between Paste and Paste Link. The Paste list and PasteLink
                    611:  *  list are always invisible. The Display List is filled from either
                    612:  *  the Paste list or the PasteLink list depending on which Paste radio
                    613:  *  button is selected.
                    614:  *
                    615:  * Parameters:
                    616:  *  hDlg            HWND of the dialog
                    617:  *  lpPS             Paste Special Dialog Structure
                    618:  *  dwOption        Paste or PasteSpecial option
                    619:  *
                    620:  * Return Value:
                    621:  *  BOOL            Returns TRUE if the option has already been selected.
                    622:  *                  Otherwise the option is selected and FALSE is returned
                    623:  */
                    624: 
                    625: BOOL FTogglePasteType(HWND hDlg, LPPASTESPECIAL lpPS, DWORD dwOption)
                    626: {
                    627:     DWORD dwTemp;
                    628:     HWND hList, hListDisplay;
                    629:     DWORD dwData;
                    630:     int i, nItems;
                    631:     LPSTR lpsz;
                    632: 
                    633:     // Skip all this if the button is already selected
                    634:     if (lpPS->dwFlags & dwOption)
                    635:         return TRUE;
                    636: 
                    637:     dwTemp = PSF_SELECTPASTE | PSF_SELECTPASTELINK;
                    638:     lpPS->dwFlags = (lpPS->dwFlags & ~dwTemp) | dwOption;
                    639: 
                    640:     // Hide IconDisplay. This prevents flashing if the icon display is changed
                    641:     StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
                    642: 
                    643:     hListDisplay = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
                    644: 
                    645:     // If Paste was selected
                    646:     if (lpPS->dwFlags & PSF_SELECTPASTE)
                    647:     {
                    648:         // Set the Source of the object in the clipboard
                    649:         SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataOD);
                    650: 
                    651:         // If an icon is available
                    652:         if (lpPS->hMetaPictOD)
                    653:             // Set the icon display
                    654:             SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET,
                    655:                   (WPARAM)lpPS->hMetaPictOD, 0L);
                    656: 
                    657: 
                    658:         hList = GetDlgItem(hDlg, ID_PS_PASTELIST);
                    659:         // We are switching from PasteLink to Paste. Remember current selection
                    660:         //    in PasteLink list so it can be restored.
                    661:         lpPS->nPasteLinkListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
                    662:         if (lpPS->nPasteLinkListCurSel == LB_ERR)
                    663:             lpPS->nPasteLinkListCurSel = 0;
                    664:         // Remember if user selected Paste or PasteLink
                    665:         lpPS->fLink = FALSE;
                    666:     }
                    667:     else    // If PasteLink was selected
                    668:     {
                    669:         // Set the Source of the object in the clipboard
                    670:         SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataLSD);
                    671: 
                    672:         // If an icon is available
                    673:         if (lpPS->hMetaPictLSD)
                    674:             // Set the icon display
                    675:             SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET,
                    676:                   (WPARAM)lpPS->hMetaPictLSD, 0L);
                    677: 
                    678: 
                    679:         hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST);
                    680:         // We are switching from Paste to PasteLink. Remember current selection
                    681:         //    in Paste list so it can be restored.
                    682:         lpPS->nPasteListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
                    683:         if (lpPS->nPasteListCurSel == LB_ERR)
                    684:             lpPS->nPasteListCurSel = 0;
                    685:         // Remember if user selected Paste or PasteLink
                    686:         lpPS->fLink = TRUE;
                    687:     }
                    688: 
                    689:     // Turn drawing off while the Display List is being filled
                    690:     SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)FALSE, 0L);
                    691: 
                    692:     // Move data to Display list box
                    693:     SendMessage(hListDisplay, LB_RESETCONTENT, 0, 0L);
                    694:     nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
                    695:     lpsz = (LPSTR)GlobalLock(lpPS->hBuff);
                    696:     for (i = 0; i < nItems; i++)
                    697:     {
                    698:         SendMessage(hList, LB_GETTEXT, (WPARAM)i, (LPARAM)lpsz);
                    699:         dwData = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
                    700:         SendMessage(hListDisplay, LB_INSERTSTRING, (WPARAM)i, (LPARAM)lpsz);
                    701:         SendMessage(hListDisplay, LB_SETITEMDATA, (WPARAM)i, dwData);
                    702:     }
                    703:     GlobalUnlock(lpPS->hBuff);
                    704: 
                    705:     // Restore the selection in the Display List from user's last selection
                    706:     if (lpPS->dwFlags & PSF_SELECTPASTE)
                    707:         SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteListCurSel, 0L);
                    708:     else
                    709:         SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteLinkListCurSel, 0L);
                    710: 
                    711:     // Paint Display List
                    712:     SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)TRUE, 0L);
                    713:     InvalidateRect(hListDisplay, NULL, TRUE);
                    714:     UpdateWindow(hListDisplay);
                    715: 
                    716:     // Enable/Disable DisplayAsIcon and set the help result text and bitmap corresponding to
                    717:     //    the current selection
                    718:     ChangeListSelection(hDlg, lpPS, hListDisplay);
                    719: 
                    720:     return FALSE;
                    721: }
                    722: 
                    723: 
                    724: /*
                    725:  * ChangeListSelection
                    726:  *
                    727:  * Purpose:
                    728:  *  When the user changes the selection in the list, DisplayAsIcon is enabled or disabled,
                    729:  *  Result text and bitmap are updated and the index of the arrPasteEntries[] corresponding
                    730:  *  to the current format selection is saved.
                    731:  *
                    732:  * Parameters:
                    733:  *  hDlg            HWND of the dialog
                    734:  *  lpPS             Paste Special Dialog Structure
                    735:  *  hList           HWND of the List
                    736:  *
                    737:  * Return Value:
                    738:  *  No return value
                    739:  */
                    740: 
                    741: void ChangeListSelection(HWND hDlg, LPPASTESPECIAL lpPS, HWND hList)
                    742: {
                    743:     LPPASTELISTITEMDATA lpItemData;
                    744:     int nCurSel;
                    745: 
                    746:     EnableDisplayAsIcon(hDlg, lpPS);
                    747:     SetPasteSpecialHelpResults(hDlg, lpPS);
                    748: 
                    749:     // Remember index of arrPasteEntries[] corresponding to the current selection
                    750:     nCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
                    751:     if (nCurSel == LB_ERR) return;
                    752:     lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA,
                    753:                 (WPARAM)nCurSel, 0L);
                    754:     if ((LRESULT)lpItemData == LB_ERR) return;
                    755:     lpPS->nSelectedIndex = lpItemData->nPasteEntriesIndex;
                    756: }
                    757: 
                    758: /*
                    759:  * EnableDisplayAsIcon
                    760:  *
                    761:  * Purpose:
                    762:  *  Enable or disable the DisplayAsIcon button depending on whether
                    763:  *  the current selection can be displayed as an icon or not. The following table describes
                    764:  *  the state of DisplayAsIcon. The calling application is termed CONTAINER, the source
                    765:  *  of data on the clipboard is termed SOURCE.
                    766:  *  Y = Yes; N = No; Blank = State does not matter;
                    767:  * =====================================================================
                    768:  * SOURCE          SOURCE             CONTAINER             DisplayAsIcon
                    769:  * specifies       specifies          specifies             Initial State
                    770:  * DVASPECT_ICON   OLEMISC_ONLYICONIC OLEUIPASTE_ENABLEICON
                    771:  *
                    772:  *                                    N                     Unchecked&Disabled
                    773:  *                 Y                  Y                     Checked&Disabled
                    774:  * Y               N                  Y                     Checked&Enabled
                    775:  * N               N                  Y                     Unchecked&Enabled
                    776:  * =====================================================================
                    777:  *
                    778:  * Parameters:
                    779:  *  hDlg            HWND of the dialog
                    780:  *  lpPS             Paste Special Dialog Structure
                    781:  *
                    782:  * Return Value:
                    783:  *  No return value
                    784:  */
                    785: 
                    786: void EnableDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
                    787: {
                    788:     int nIndex;
                    789:     BOOL fCntrEnableIcon;
                    790:     BOOL fSrcOnlyIconic = (lpPS->fLink) ? lpPS->fSrcOnlyIconicLSD : lpPS->fSrcOnlyIconicOD;
                    791:     BOOL fSrcAspectIcon = (lpPS->fLink) ? lpPS->fSrcAspectIconLSD : lpPS->fSrcAspectIconOD;
                    792:     HWND hList;
                    793:     LPPASTELISTITEMDATA lpItemData;
                    794:     HGLOBAL hMetaPict = (lpPS->fLink) ? lpPS->hMetaPictLSD : lpPS->hMetaPictOD;
                    795: 
                    796:     hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
                    797: 
                    798:     // Get data corresponding to the current selection in the listbox
                    799:     nIndex = (int)SendMessage(hList, LB_GETCURSEL, 0, 0);
                    800:     if (nIndex != LB_ERR)
                    801:     {
                    802:         lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nIndex, 0L);
                    803:         if ((LRESULT)lpItemData != LB_ERR)
                    804:             fCntrEnableIcon = lpItemData->fCntrEnableIcon;
                    805:         else fCntrEnableIcon = FALSE;
                    806:     }
                    807:     else fCntrEnableIcon = FALSE;
                    808: 
                    809:     // If there is an icon available
                    810:     if (hMetaPict != NULL)
                    811:     {
                    812:         if (!fCntrEnableIcon)          // Does CONTAINER specify OLEUIPASTE_ENABLEICON?
                    813:         {
                    814:             // Uncheck & Disable DisplayAsIcon
                    815:             lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
                    816:             CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
                    817:             EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
                    818: 
                    819:             // Hide IconDisplay and ChangeIcon button
                    820:             StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
                    821:             StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
                    822:         }
                    823:         else if (fSrcOnlyIconic)       // Does SOURCE specify OLEMISC_ONLYICONIC?
                    824:         {
                    825:             // Check & Disable DisplayAsIcon
                    826:             lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
                    827:             CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE);
                    828:             EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
                    829: 
                    830:             // Show IconDisplay and ChangeIcon button
                    831:             StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL);
                    832:             StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL);
                    833:         }
                    834:         else if (fSrcAspectIcon)       // Does SOURCE specify DVASPECT_ICON?
                    835:         {
                    836:              // Check & Enable DisplayAsIcon
                    837:              lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
                    838:              CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE);
                    839:              EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE);
                    840: 
                    841:              // Show IconDisplay and ChangeIcon button
                    842:              StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL);
                    843:              StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL);
                    844:         }
                    845:         else
                    846:         {
                    847:              //Uncheck and Enable DisplayAsIcon
                    848:              lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
                    849:              CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
                    850:              EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE);
                    851: 
                    852:              // Hide IconDisplay and ChangeIcon button
                    853:              StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
                    854:              StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
                    855: 
                    856:         }
                    857:     }
                    858:     else  // No icon available
                    859:     {
                    860:         // Unchecked & Disabled
                    861:         lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
                    862:         CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
                    863:         EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
                    864: 
                    865:         // Hide IconDisplay and ChangeIcon button
                    866:         StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
                    867:         StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
                    868:     }
                    869: }
                    870: 
                    871: /*
                    872:  * ToggleDisplayAsIcon
                    873:  *
                    874:  * Purpose:
                    875:  *  Toggles the DisplayAsIcon button. Hides or shows the Icon Display and
                    876:  *  the ChangeIcon button and changes the help result text and bitmap.
                    877:  *
                    878:  * Parameters:
                    879:  *  hDlg            HWND of the dialog
                    880:  *  lpPS             Paste Special Dialog Structure
                    881:  *
                    882:  * Return Value:
                    883:  *  None
                    884:  *
                    885:  */
                    886: 
                    887: void ToggleDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
                    888: {
                    889:     BOOL fCheck;
                    890:     int i;
                    891: 
                    892:     fCheck = IsDlgButtonChecked(hDlg, ID_PS_DISPLAYASICON);
                    893: 
                    894:     if (fCheck)
                    895:         lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
                    896:     else lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
                    897: 
                    898:     // Set the help result text and bitmap
                    899:     SetPasteSpecialHelpResults(hDlg, lpPS);
                    900: 
                    901:     // Show or hide the Icon Display and ChangeIcon button depending
                    902:     // on the check state
                    903:     i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE;
                    904:     StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, i);
                    905:     StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, i);
                    906: }
                    907: 
                    908: /*
                    909:  * ChangeIcon
                    910:  *
                    911:  * Purpose:
                    912:  *  Brings up the ChangeIcon dialog which allows the user to change
                    913:  *  the icon and label.
                    914:  *
                    915:  * Parameters:
                    916:  *  hDlg            HWND of the dialog
                    917:  *  lpPS             Paste Special Dialog Structure
                    918:  *
                    919:  * Return Value:
                    920:  *  None
                    921:  *
                    922:  */
                    923: 
                    924: void ChangeIcon(HWND hDlg, LPPASTESPECIAL lpPS)
                    925: {
                    926:     OLEUICHANGEICON ci;
                    927:     UINT uRet;
                    928:     CLSID   clsid     = (lpPS->fLink) ? lpPS->clsidLSD : lpPS->clsidOD;
                    929: 
                    930:     //Initialize the structure
                    931:     _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
                    932: 
                    933:     ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
                    934:     ci.cbStruct = sizeof(ci);
                    935:     ci.hWndOwner = hDlg;
                    936:     ci.clsid = clsid;
                    937:     ci.dwFlags  = CIF_SELECTCURRENT;
                    938: 
                    939:     // Only show help in the ChangeIcon dialog if we're showing it in this dialog.
                    940:     if (lpPS->dwFlags & PSF_SHOWHELP)
                    941:         ci.dwFlags = CIF_SHOWHELP;
                    942: 
                    943:     // Let the hook in to customize Change Icon if desired.
                    944:     uRet = UStandardHook(lpPS, hDlg, uMsgChangeIcon, 0, (LONG)(LPSTR)&ci);
                    945: 
                    946:     if (0 == uRet)
                    947:         uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci));
                    948: 
                    949:     // Update the display if necessary.
                    950:     if (0!=uRet)
                    951:     {
                    952:         /*
                    953:         * OleUIChangeIcon will have already freed our
                    954:         * current hMetaPict that we passed in when OK is
                    955:         * pressed in that dialog.  So we use 0L as lParam
                    956:         * here so the IconBox doesn't try to free the
                    957:         * metafilepict again.
                    958:         */
                    959:         SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)ci.hMetaPict, 0L);
                    960:         // Remember the new icon chosen by the user. Note that Paste and PasteLink have separate
                    961:         //    icons - changing one does not change the other.
                    962:         if (lpPS->fLink)
                    963:             lpPS->hMetaPictLSD = ci.hMetaPict;
                    964:         else lpPS->hMetaPictOD = ci.hMetaPict;
                    965:     }
                    966: }
                    967: 
                    968: /*
                    969:  *SetPasteSpecialHelpResults
                    970:  *
                    971:  * Purpose:
                    972:  *  Sets the help result text and bitmap according to the current
                    973:  *  list selection. The following state table indicates which ResultText
                    974:  *  and ResultImage are selected. If %s in the lpstrFormatName is present,
                    975:  *  it is assumed that an object is being pasted/paste-linked, otherwise it
                    976:  *  is assumed that data is being pasted/paste-linked.
                    977:  *  Y = Yes; N = No; Blank = State does not matter;
                    978:  *  The numbers in the the ResultText and ResultImage columns refer to the table
                    979:  *  entries that follow.
                    980:  * =====================================================================
                    981:  * Paste/       lpstrFormatName in                DisplayAsIcon Result      Result
                    982:  * PasteLink    arrPasteEntry[]contains %s        checked       Text        Image
                    983:  *              (Is Object == Y, Is Data == N)
                    984:  * Paste        N                                               1           1
                    985:  * Paste        Y                                 N             2           2
                    986:  * Paste        Y                                 Y             3           3
                    987:  * PasteLink    N                                               4           4
                    988:  * PasteLink    Y                                 N             5           4
                    989:  * PasteLink    Y                                 Y             6           5
                    990:  * =====================================================================
                    991:  * Result Text:
                    992:  *
                    993:  * 1. "Inserts the contents of the Clipboard into your document as <native type name,
                    994:  *     and optionally an additional help sentence>"
                    995:  * 2. "Inserts the contents of the Clipboard into your document so that you may
                    996:  *     activate it using <object app name>"
                    997:  * 3. "Inserts the contents of the Clipboard into your document so that you may
                    998:  *     activate it using <object app name>.  It will be displayed as an icon."
                    999:  * 4. "Inserts the contents of the Clipboard into your document as <native type name>.
                   1000:  *     Paste Link creates a link to the source file so that changes to the source file
                   1001:  *     will be reflected in your document."
                   1002:  * 5. "Inserts a picture of the Clipboard contents into your document.  Paste Link
                   1003:  *     creates a link to the source file so that changes to the source file will be
                   1004:  *     reflected in your document."
                   1005:  * 6. "Inserts an icon into your document which represents the Clipboard contents.
                   1006:  *     Paste Link creates a link to the source file so that changes to the source file
                   1007:  *     will be reflected in your document."
                   1008:  * =====================================================================
                   1009:  * Result Image:
                   1010:  *
                   1011:  * 1. Clipboard Image
                   1012:  * 2. Paste image, non-iconic.
                   1013:  * 3. Paste image, iconic.
                   1014:  * 4. Paste Link image, non-iconic
                   1015:  * 5. Paste Link image, iconic
                   1016:  * ====================================================================
                   1017:  *
                   1018:  * Parameters:
                   1019:  *  hDlg            HWND of the dialog
                   1020:  *  lpPS             Paste Special Dialog Structure
                   1021:  *
                   1022:  * Return Value:
                   1023:  *  No return value
                   1024:  */
                   1025: void SetPasteSpecialHelpResults(HWND hDlg, LPPASTESPECIAL lpPS)
                   1026: {
                   1027:     LPSTR               psz1, psz2, psz3, psz4;
                   1028:     UINT                i, iString, iImage, cch;
                   1029:     int                 nPasteEntriesIndex;
                   1030:     BOOL                fDisplayAsIcon;
                   1031:     BOOL                fIsObject;
                   1032:     HWND                hList;
                   1033:     LPPASTELISTITEMDATA  lpItemData;
                   1034:     LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
                   1035:     LPSTR       szFullUserTypeName = (lpPS->fLink) ? lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD;
                   1036:     LPSTR       szInsert;
                   1037: 
                   1038:     hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
                   1039: 
                   1040:     i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
                   1041:     if (i != LB_ERR)
                   1042:     {
                   1043:         lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, i, 0L);
                   1044:         if ((LRESULT)lpItemData == LB_ERR) return;
                   1045:         nPasteEntriesIndex = lpItemData->nPasteEntriesIndex;
                   1046:         // Check if there is a '%s' in the lpstrFormatName, then an object is being
                   1047:         //   pasted/pastelinked. Otherwise Data is being pasted-pastelinked.
                   1048:         fIsObject = FHasPercentS(lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
                   1049:                                         lpPS);
                   1050:     }
                   1051:     else return;
                   1052: 
                   1053:     // Is DisplayAsIcon checked?
                   1054:     fDisplayAsIcon=(0L!=(lpPS->dwFlags & PSF_CHECKDISPLAYASICON));
                   1055: 
                   1056:     szInsert = szFullUserTypeName;
                   1057: 
                   1058:     if (lpPS->dwFlags & PSF_SELECTPASTE)     // If user selected Paste
                   1059:     {
                   1060:         if (fIsObject)
                   1061:         {
                   1062:             iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT;
                   1063:             iImage  = fDisplayAsIcon ? RESULTIMAGE_EMBEDICON   : RESULTIMAGE_EMBED;
                   1064:             szInsert = lpPS->szAppName;
                   1065:         }
                   1066:         else
                   1067:         {
                   1068:             iString = IDS_PSPASTEDATA;
                   1069:             iImage  = RESULTIMAGE_PASTE;
                   1070:         }
                   1071:     }
                   1072:     else if (lpPS->dwFlags & PSF_SELECTPASTELINK)   // User selected PasteLink
                   1073:     {
                   1074:         if (fIsObject)
                   1075:         {
                   1076:             iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT;
                   1077:             iImage  = fDisplayAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
                   1078:         }
                   1079:         else
                   1080:         {
                   1081:             iString = IDS_PSPASTELINKDATA;
                   1082:             iImage  = RESULTIMAGE_LINK;
                   1083:         }
                   1084: 
                   1085:     }
                   1086:     else   // Should never occur.
                   1087:     {
                   1088:         iString = IDS_PSNONOLE;
                   1089:         iImage = RESULTIMAGE_PASTE;
                   1090:     }
                   1091: 
                   1092:     // hBuff contains enough space for the 4 buffers required to build up the help
                   1093:     //   result text.
                   1094:     cch = (UINT)GlobalSize(lpPS->hBuff)/4;
                   1095: 
                   1096:     psz1=(LPSTR)GlobalLock(lpPS->hBuff);
                   1097:     psz2=psz1+cch;
                   1098:     psz3=psz2+cch;
                   1099:     psz4=psz3+cch;
                   1100: 
                   1101:     // Default is an empty string.
                   1102:     *psz1=0;
                   1103: 
                   1104:     if (0!=LoadString(ghInst, iString, psz1, cch))
                   1105:     {
                   1106:         // Insert the FullUserTypeName of the source object into the partial result text
                   1107:         //   specified by the container.
                   1108:         wsprintf(psz3, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrResultText,
                   1109:         (LPSTR)szInsert);
                   1110:         // Insert the above partial result text into the standard result text.
                   1111:         wsprintf(psz4, psz1, (LPSTR)psz3);
                   1112:         psz1=psz4;
                   1113:     }
                   1114: 
                   1115:     // If LoadString failed, we simply clear out the results (*psz1=0 above)
                   1116:     SetDlgItemText(hDlg, ID_PS_RESULTTEXT, psz1);
                   1117: 
                   1118:     // Change the result bitmap
                   1119:     SendDlgItemMessage(hDlg, ID_PS_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
                   1120: 
                   1121:     GlobalUnlock(lpPS->hBuff);
                   1122: }
                   1123: 
                   1124: /*
                   1125:  * FAddPasteListItem
                   1126:  *
                   1127:  * Purpose:
                   1128:  *  Adds an item to the list box
                   1129:  *
                   1130:  * Parameters:
                   1131:  *  hList            HWND List into which item is to be added
                   1132:  *  fInsertFirst     BOOL Insert in the beginning of the list?
                   1133:  *  nPasteEntriesIndex int Index of Paste Entry array this list item corresponsds to
                   1134:  *  lpPS             Paste Special Dialog Structure
                   1135:  *  pIMalloc         LPMALLOC  Memory Allocator
                   1136:  *  lpszBuf          LPSTR Scratch buffer to build up string for list entry
                   1137:  *
                   1138:  * Return Value:
                   1139:  *  BOOL            TRUE if sucessful.
                   1140:  *                  FALSE if unsucessful.
                   1141:  */
                   1142: BOOL FAddPasteListItem(
                   1143:         HWND hList, BOOL fInsertFirst, int nPasteEntriesIndex, LPPASTESPECIAL lpPS,
                   1144:         LPMALLOC pIMalloc, LPSTR lpszBuf)
                   1145: {
                   1146:     LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
                   1147:     LPPASTELISTITEMDATA lpItemData;
                   1148:     int                 nIndex;
                   1149:     LPSTR szFullUserTypeName = (lpPS->fLink) ?
                   1150:             lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD;
                   1151: 
                   1152:     // Allocate memory for each list box item
                   1153:     lpItemData = (LPPASTELISTITEMDATA)pIMalloc->lpVtbl->Alloc(
                   1154:             pIMalloc, (DWORD)sizeof(PASTELISTITEMDATA));
                   1155:     if (NULL == lpItemData)
                   1156:         return FALSE;
                   1157: 
                   1158:     // Fill data associated with each list box item
                   1159:     lpItemData->nPasteEntriesIndex = nPasteEntriesIndex;
                   1160:     lpItemData->fCntrEnableIcon = ((lpOPS->arrPasteEntries[nPasteEntriesIndex].dwFlags &
                   1161:             OLEUIPASTE_ENABLEICON) ? TRUE : FALSE);
                   1162: 
                   1163:     // Build list box entry string, insert the string and add the data the corresponds to it
                   1164:     wsprintf(
                   1165:             (LPSTR)lpszBuf,
                   1166:             lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
                   1167:             (LPSTR)szFullUserTypeName
                   1168:     );
                   1169:     nIndex = (int)SendMessage(
                   1170:             hList,
                   1171:             (fInsertFirst ? LB_INSERTSTRING : LB_ADDSTRING),
                   1172:             0,
                   1173:             (LPARAM)(LPSTR)lpszBuf
                   1174:     );
                   1175:     SendMessage(
                   1176:             hList,
                   1177:             LB_SETITEMDATA,
                   1178:             nIndex,
                   1179:             (LPARAM)(LPPASTELISTITEMDATA)lpItemData
                   1180:     );
                   1181:     return TRUE;
                   1182: }
                   1183: 
                   1184: 
                   1185: /*
                   1186:  * FFillPasteList
                   1187:  *
                   1188:  * Purpose:
                   1189:  *  Fills the invisible paste list with the formats offered by the clipboard object and
                   1190:  *  asked for by the container.
                   1191:  *
                   1192:  * Parameters:
                   1193:  *  hDlg            HWND of the dialog
                   1194:  *  lpPS             Paste Special Dialog Structure
                   1195:  *
                   1196:  * Return Value:
                   1197:  *  BOOL            TRUE if sucessful and if formats could be found.
                   1198:  *                  FALSE if unsucessful or if no formats could be found.
                   1199:  */
                   1200: BOOL FFillPasteList(HWND hDlg, LPPASTESPECIAL lpPS)
                   1201: {
                   1202:     LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
                   1203:     LPMALLOC            pIMalloc     = NULL;
                   1204:     LPSTR               lpszBuf      = (LPSTR)GlobalLock(lpPS->hBuff);
                   1205:     HWND                hList;
                   1206:     int                 i;
                   1207:     int                 nItems = 0;
                   1208:     int                 nDefFormat = -1;
                   1209:     BOOL                fTryObjFmt = FALSE;
                   1210:     BOOL                fInsertFirst;
                   1211:     HRESULT             hrErr;
                   1212: 
                   1213:     hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
                   1214:     if (hrErr != NOERROR)
                   1215:         goto error;
                   1216: 
                   1217:     hList = GetDlgItem(hDlg, ID_PS_PASTELIST);
                   1218: 
                   1219:     // Loop over the target's priority list of formats
                   1220:     for (i = 0; i < lpOPS->cPasteEntries; i++)
                   1221:     {
                   1222:         if (lpOPS->arrPasteEntries[i].dwFlags != OLEUIPASTE_PASTEONLY &&
                   1223:                 !(lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_PASTE))
                   1224:             continue;
                   1225: 
                   1226:         fInsertFirst = FALSE;
                   1227: 
                   1228:         if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName
                   1229:                 || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbeddedObject
                   1230:                 || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbedSource) {
                   1231:             if (! fTryObjFmt) {
                   1232:                 fTryObjFmt = TRUE;      // only use 1st object format
                   1233:                 fInsertFirst = TRUE;    // OLE obj format should always be 1st
                   1234:             } else {
                   1235:                 continue;   // already added an object format to list
                   1236:             }
                   1237:         }
                   1238: 
                   1239:         // add to list if entry is marked TRUE
                   1240:         if (lpOPS->arrPasteEntries[i].dwScratchSpace) {
                   1241:             if (nDefFormat < 0)
                   1242:                 nDefFormat = (fInsertFirst ? 0 : nItems);
                   1243:             else if (fInsertFirst)
                   1244:                 nDefFormat++;   // adjust for obj fmt inserted 1st in list
                   1245:             
                   1246:             if (!FAddPasteListItem(hList,fInsertFirst,i,lpPS,pIMalloc,lpszBuf))
                   1247:                 goto error;
                   1248:             nItems++;
                   1249:         }
                   1250:     }
                   1251: 
                   1252:     // initialize selection to first format matched in list
                   1253:     if (nDefFormat >= 0)
                   1254:         lpPS->nPasteListCurSel = nDefFormat;
                   1255: 
                   1256:     // Clean up
                   1257:     if (pIMalloc)
                   1258:         OleStdRelease((LPUNKNOWN)pIMalloc);
                   1259:     if (lpszBuf)
                   1260:        GlobalUnlock(lpPS->hBuff);
                   1261: 
                   1262:     // If no items have been added to the list box (none of the formats
                   1263:     //   offered by the source matched those acceptable to the container),
                   1264:     //   return FALSE
                   1265:     if (nItems > 0)
                   1266:         return TRUE;
                   1267:     else
                   1268:         return FALSE;
                   1269: 
                   1270: error:
                   1271:     if (pIMalloc)
                   1272:         OleStdRelease((LPUNKNOWN)pIMalloc);
                   1273:     if (lpszBuf)
                   1274:        GlobalUnlock(lpPS->hBuff);
                   1275:     FreeListData(hList);
                   1276: 
                   1277:     return FALSE;
                   1278: }
                   1279: 
                   1280: 
                   1281: /*
                   1282:  * FFillPasteLinkList
                   1283:  *
                   1284:  * Purpose:
                   1285:  *  Fills the invisible paste link list with the formats offered by the clipboard object and
                   1286:  *  asked for by the container.
                   1287:  *
                   1288:  * Parameters:
                   1289:  *  hDlg            HWND of the dialog
                   1290:  *  lpPS             Paste Special Dialog Structure
                   1291:  *
                   1292:  * Return Value:
                   1293:  *  BOOL            TRUE if sucessful and if formats could be found.
                   1294:  *                  FALSE if unsucessful or if no formats could be found.
                   1295:  */
                   1296: BOOL FFillPasteLinkList(HWND hDlg, LPPASTESPECIAL lpPS)
                   1297: {
                   1298:     LPOLEUIPASTESPECIAL lpOPS        = lpPS->lpOPS;
                   1299:     LPDATAOBJECT        lpSrcDataObj = lpOPS->lpSrcDataObj;
                   1300:     LPENUMFORMATETC     lpEnumFmtEtc = NULL;
                   1301:     LPMALLOC            pIMalloc     = NULL;
                   1302:     LPSTR               lpszBuf      = (LPSTR)GlobalLock(lpPS->hBuff);
                   1303:     OLEUIPASTEFLAG      pasteFlag;
                   1304:     UINT arrLinkTypesSupported[PS_MAXLINKTYPES];  // Array of flags that
                   1305:                                                   // indicate which link types
                   1306:                                                   // are supported by source.
                   1307:     FORMATETC           fmtetc;
                   1308:     int                 i, j;
                   1309:     int                 nItems = 0;
                   1310:     BOOL                fLinkTypeSupported = FALSE;
                   1311:     HWND                hList;
                   1312:     int                 nDefFormat = -1;
                   1313:     BOOL                fTryObjFmt = FALSE;
                   1314:     BOOL                fInsertFirst;
                   1315:     HRESULT             hrErr;
                   1316: 
                   1317:     hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
                   1318:     if (hrErr != NOERROR)
                   1319:         goto error;
                   1320: 
                   1321:     // Remember which link type formats are offered by lpSrcDataObj.
                   1322:     _fmemset(&fmtetc, 0, sizeof(FORMATETC));
                   1323:     for (i = 0; i < lpOPS->cLinkTypes; i++)
                   1324:     {
                   1325:         if (lpOPS->arrLinkTypes[i] = cfLinkSource) {
                   1326:             OLEDBG_BEGIN2("OleQueryLinkFromData called\r\n")
                   1327:             hrErr = OleQueryLinkFromData(lpSrcDataObj);
                   1328:             OLEDBG_END2
                   1329:             if(NOERROR == hrErr)
                   1330:             {
                   1331:                 arrLinkTypesSupported[i] = 1;
                   1332:                 fLinkTypeSupported = TRUE;
                   1333:             }
                   1334:             else arrLinkTypesSupported[i] = 0;
                   1335:         }
                   1336:         else {
                   1337:             fmtetc.cfFormat = lpOPS->arrLinkTypes[i];
                   1338:             fmtetc.dwAspect = DVASPECT_CONTENT;
                   1339:             fmtetc.tymed    = 0xFFFFFFFF;       // All tymed values
                   1340:             fmtetc.lindex   = -1;
                   1341:             OLEDBG_BEGIN2("IDataObject::QueryGetData called\r\n")
                   1342:             hrErr = lpSrcDataObj->lpVtbl->QueryGetData(lpSrcDataObj,&fmtetc);
                   1343:             OLEDBG_END2
                   1344:             if(NOERROR == hrErr)
                   1345:             {
                   1346:                 arrLinkTypesSupported[i] = 1;
                   1347:                 fLinkTypeSupported = TRUE;
                   1348:             }
                   1349:             else arrLinkTypesSupported[i] = 0;
                   1350:         }
                   1351:     }
                   1352:     // No link types are offered by lpSrcDataObj
                   1353:     if (! fLinkTypeSupported) {
                   1354:         nItems = 0;
                   1355:         goto cleanup;
                   1356:     }
                   1357: 
                   1358:     hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST);
                   1359: 
                   1360:     // Enumerate the formats acceptable to container
                   1361:     for (i = 0; i < lpOPS->cPasteEntries; i++)
                   1362:     {
                   1363:         fLinkTypeSupported = FALSE;
                   1364: 
                   1365:         // If container will accept any link type offered by source object
                   1366:         if (lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_LINKANYTYPE)
                   1367:             fLinkTypeSupported = TRUE;
                   1368:         else
                   1369:         {
                   1370:             // Check if any of the link types offered by the source
                   1371:             //    object are acceptable to the container
                   1372:             // This code depends on the LINKTYPE enum values being powers of 2
                   1373:             for (pasteFlag = OLEUIPASTE_LINKTYPE1, j = 0;
                   1374:                  j < lpOPS->cLinkTypes;
                   1375:                  pasteFlag*=2, j++)
                   1376:             {
                   1377:                 if ((lpOPS->arrPasteEntries[i].dwFlags & pasteFlag) &&
                   1378:                         arrLinkTypesSupported[j])
                   1379:                 {
                   1380:                     fLinkTypeSupported = TRUE;
                   1381:                     break;
                   1382:                 }
                   1383:             }
                   1384:         }
                   1385: 
                   1386:         fInsertFirst = FALSE;
                   1387: 
                   1388:         if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName
                   1389:                 || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfLinkSource) {
                   1390:             if (! fTryObjFmt) {
                   1391:                 fTryObjFmt = TRUE;      // only use 1st object format
                   1392:                 fInsertFirst = TRUE;    // OLE obj format should always be 1st
                   1393:             } else {
                   1394:                 continue;   // already added an object format to list
                   1395:             }
                   1396:         }
                   1397: 
                   1398:         // add to list if entry is marked TRUE
                   1399:         if (fLinkTypeSupported && lpOPS->arrPasteEntries[i].dwScratchSpace) {
                   1400:             if (nDefFormat < 0)
                   1401:                 nDefFormat = (fInsertFirst ? 0 : nItems);
                   1402:             else if (fInsertFirst)
                   1403:                 nDefFormat++;   // adjust for obj fmt inserted 1st in list
                   1404: 
                   1405:             if (!FAddPasteListItem(hList,fInsertFirst,i,lpPS,pIMalloc,lpszBuf))
                   1406:                 goto error;
                   1407:             nItems++;
                   1408:         }
                   1409:     } // end FOR
                   1410: 
                   1411:     nItems = (int)SendMessage(hList, LB_GETCOUNT, 0, 0L);
                   1412: 
                   1413:     // initialize selection to first format matched in list
                   1414:     if (nDefFormat >= 0)
                   1415:         lpPS->nPasteLinkListCurSel = nDefFormat;
                   1416: 
                   1417: cleanup:
                   1418:     // Clean up
                   1419:     if (pIMalloc)
                   1420:         OleStdRelease((LPUNKNOWN)pIMalloc);
                   1421:     if (lpszBuf)
                   1422:        GlobalUnlock(lpPS->hBuff);
                   1423: 
                   1424:     // If no items have been added to the list box (none of the formats
                   1425:     //   offered by the source matched those acceptable to the destination),
                   1426:     //   return FALSE
                   1427:     if (nItems > 0)
                   1428:         return TRUE;
                   1429:     else
                   1430:         return FALSE;
                   1431: 
                   1432: error:
                   1433:     if (pIMalloc)
                   1434:         OleStdRelease((LPUNKNOWN)pIMalloc);
                   1435:     if (lpszBuf)
                   1436:        GlobalUnlock(lpPS->hBuff);
                   1437:     FreeListData(hList);
                   1438: 
                   1439:     return FALSE;
                   1440: }
                   1441: 
                   1442: 
                   1443: /*
                   1444:  * FreeListData
                   1445:  *
                   1446:  * Purpose:
                   1447:  *  Free the local memory associated with each list box item
                   1448:  *
                   1449:  * Parameters:
                   1450:  *  hList           HWND of the list
                   1451:  *
                   1452:  * Return Value:
                   1453:  *  None
                   1454:  */
                   1455: void FreeListData(HWND hList)
                   1456: {
                   1457:     int                nItems, i;
                   1458:     LPPASTELISTITEMDATA lpItemData;
                   1459:     LPMALLOC           pIMalloc;
                   1460:     HRESULT            hrErr;
                   1461: 
                   1462:     hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
                   1463:     if (hrErr != NOERROR)
                   1464:         return;
                   1465: 
                   1466:     nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
                   1467:     for (i = 0; i < nItems; i++)
                   1468:     {
                   1469:         lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
                   1470:         if ((LRESULT)lpItemData != LB_ERR)
                   1471:             pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpItemData);
                   1472:     }
                   1473:     OleStdRelease((LPUNKNOWN)pIMalloc);
                   1474: }
                   1475: 
                   1476: /*
                   1477:  * FHasPercentS
                   1478:  *
                   1479:  * Purpose:
                   1480:  *  Determines if string contains %s.
                   1481:  *
                   1482:  * Parameters:
                   1483:  *  lpsz            LPCSTR string in which occurence of '%s' is looked for
                   1484:  *
                   1485:  * Return Value:
                   1486:  *  BOOL            TRUE if %s is found, else FALSE.
                   1487:  */
                   1488: 
                   1489: BOOL FHasPercentS(LPCSTR lpsz, LPPASTESPECIAL lpPS)
                   1490: {
                   1491:    int n = 0;
                   1492:    LPSTR lpszTmp;
                   1493: 
                   1494:    if (!lpsz) return FALSE;
                   1495:    // Copy input string to buffer. This allows caller to pass a
                   1496:    //   code-based string. Code segments may be swapped out in low memory situations
                   1497:    //   and so code-based strings need to be copied before string elements can be accessed.
                   1498:    lpszTmp = (LPSTR)GlobalLock(lpPS->hBuff);
                   1499:    lstrcpy(lpszTmp, lpsz);
                   1500: 
                   1501:    while (*lpszTmp)
                   1502:    {
                   1503:        if (*lpszTmp == '%')
                   1504:        {
                   1505:            lpszTmp = AnsiNext(lpszTmp);
                   1506:            if (*lpszTmp == 's')            // If %s, return
                   1507:            {
                   1508:                GlobalUnlock(lpPS->hBuff);
                   1509:                return TRUE;
                   1510:            }
                   1511:            else if (*lpszTmp == '%')        // if %%, skip to next character
                   1512:                lpszTmp = AnsiNext(lpszTmp);
                   1513:        }
                   1514:        else lpszTmp = AnsiNext(lpszTmp);
                   1515:    }
                   1516: 
                   1517:    GlobalUnlock(lpPS->hBuff);
                   1518:    return FALSE;
                   1519: }
                   1520: 
                   1521: /*
                   1522:  * AllocateScratchMem
                   1523:  *
                   1524:  * Purpose:
                   1525:  *  Allocates scratch memory for use by the PasteSpecial dialog. The memory is
                   1526:  *  is used as the buffer for building up strings using wsprintf. Strings are built up
                   1527:  *  using the buffer while inserting items into the Paste & PasteLink lists and while
                   1528:  *  setting the help result text. It must be big  enough to handle the string that results after
                   1529:  *  replacing the %s in the lpstrFormatName and lpstrResultText in arrPasteEntries[]
                   1530:  *  by the FullUserTypeName. It must also be big enough to build the dialog's result text
                   1531:  *  after %s substitutions by the FullUserTypeName or the ApplicationName.
                   1532:  *
                   1533:  * Parameters:
                   1534:  *  lpPS             Paste Special Dialog Structure
                   1535:  *
                   1536:  * Return Value:
                   1537:  *  HGLOBAL         Handle to allocated global memory
                   1538:  */
                   1539: 
                   1540: HGLOBAL AllocateScratchMem(LPPASTESPECIAL lpPS)
                   1541: {
                   1542:     LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
                   1543:     int nLen, i;
                   1544:     int nSubstitutedText = 0;
                   1545:     int nAlloc = 0;
                   1546: 
                   1547:     // Get the maximum length of the FullUserTypeNames specified by OBJECTDESCRIPTOR
                   1548:     //   and the LINKSRCDESCRIPTOR and the Application Name. Any of these may be substituted
                   1549:     //   for %s in the result-text/list entries.
                   1550:     if (lpPS->szFullUserTypeNameOD)
                   1551:         nSubstitutedText = lstrlen(lpPS->szFullUserTypeNameOD);
                   1552:     if (lpPS->szFullUserTypeNameLSD)
                   1553:         nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szFullUserTypeNameLSD));
                   1554:     if (lpPS->szAppName)
                   1555:         nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szAppName));
                   1556: 
                   1557:     // Get the maximum length of lpstrFormatNames & lpstrResultText in arrPasteEntries
                   1558:     nLen = 0;
                   1559:     for (i = 0; i < lpOPS->cPasteEntries; i++)
                   1560:     {
                   1561:        nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrFormatName));
                   1562:        nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrResultText));
                   1563:     }
                   1564: 
                   1565:     // Get the maximum length of lpstrFormatNames and lpstrResultText after %s  has
                   1566:     //   been substituted (At most one %s can appear in each string).
                   1567:     //   Add 1 to hold NULL terminator.
                   1568:     nAlloc = nLen+nSubstitutedText+1;
                   1569: 
                   1570:     // Allocate scratch memory to be used to build strings
                   1571:     // nAlloc is big enough to hold any of the lpstrResultText or lpstrFormatName in arrPasteEntries[]
                   1572:     //   after %s substitution.
                   1573:     // We also need space to build up the help result text. 512 is the maximum length of the
                   1574:     //   standard dialog help text before substitutions. 512+nAlloc is the maximum length
                   1575:     //   after %s substition.
                   1576:     // SetPasteSpecialHelpResults() requires 4 such buffers to build up the result text
                   1577:     return GlobalAlloc(GHND, (DWORD)4*(512+nAlloc));
                   1578: }
                   1579: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.