test: clipbrd.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# clipbrd.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: clipbrd.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * Clipboard code.
    00007 *
    00008 * History:
    00009 * 18-Nov-1990 ScottLu   Ported from Win3.
    00010 * 18-Nov-1990 ScottLu   Added revalidation code
    00011 * 11-Feb-1991 JimA      Added access checks
    00012 * 20-Jun-1995 ChrisWil  Merged Chicago functionality.
    00013 \***************************************************************************/
    00014
    00015 #include "precomp.h"
    00016 #pragma hdrstop
    00017
    00018 #undef DUMMY_TEXT_HANDLE
    00019 #define DUMMY_TEXT_HANDLE       (HANDLE)0x0001        // must be first dummy
    00020 #define DUMMY_DIB_HANDLE        (HANDLE)0x0002
    00021 #define DUMMY_METARENDER_HANDLE (HANDLE)0x0003
    00022 #define DUMMY_METACLONE_HANDLE  (HANDLE)0x0004
    00023 #define DUMMY_MAX_HANDLE        (HANDLE)0x0004        // must be last dummy
    00024
    00025 #define PRIVATEFORMAT       0
    00026 #define GDIFORMAT           1
    00027 #define HANDLEFORMAT        2
    00028 #define METAFILEFORMAT      3
    00029
    00030 #define IsTextHandle(fmt, hdata)       \
    00031     (((hdata) != DUMMY_TEXT_HANDLE) && \
    00032      (((fmt) == CF_TEXT) || ((fmt) == CF_OEMTEXT) || ((fmt) == CF_UNICODETEXT)))
    00033
    00034 #define IsDibHandle(fmt, hdata)      \
    00035     (((fmt) == CF_DIB) && ((hdata) != DUMMY_DIB_HANDLE))
    00036 #define IsMetaDummyHandle(hdata)     \
    00037     ((hdata == DUMMY_METACLONE_HANDLE) || (hdata == DUMMY_METARENDER_HANDLE))
    00038
    00039 /**************************************************************************\
    00040 * CheckClipboardAccess
    00041 *
    00042 * Perform access check on the clipboard.  Special case CSRSS threads
    00043 * so that console windows on multiple windowstations will have
    00044 * the correct access.
    00045 *
    00046 * 04-Jul-1995 JimA  Created
    00047 \**************************************************************************/
    00048
    00049 PWINDOWSTATION CheckClipboardAccess(void)
    00050 {
    00051     NTSTATUS Status;
    00052     PWINDOWSTATION pwinsta;
    00053     BOOL fUseDesktop;
    00054     PTHREADINFO pti;
    00055
    00056     pti = PtiCurrentShared();
    00057
    00058     /*
    00059      * CSR process use to have NULL pwinsta. Now that it's assigned to
    00060      * the services windowstation we have to explicitly use the desktop
    00061      * for checking the access.
    00062      */
    00063     fUseDesktop = (pti->TIF_flags & TIF_CSRSSTHREAD) ? TRUE : FALSE;
    00064
    00065     Status =  ReferenceWindowStation(PsGetCurrentThread(),
    00066                                      NULL,
    00067                                      WINSTA_ACCESSCLIPBOARD,
    00068                                      &pwinsta,
    00069                                      fUseDesktop);
    00070     if (!NT_SUCCESS(Status)) {
    00071         RIPNTERR0(Status, RIP_WARNING,"Access to clipboard denied.");
    00072         return NULL;
    00073     }
    00074
    00075     return pwinsta;
    00076 }
    00077
    00078 /**************************************************************************\
    00079 * ConvertMemHandle
    00080 *
    00081 * Converts data to a clipboard-memory-handle.  This special handle
    00082 * contains the size-of-data in the first DWORD.  The second DWORD points
    00083 * back to the block.
    00084 *
    00085 * History:
    00086 \**************************************************************************/
    00087
    00088 HANDLE _ConvertMemHandle(
    00089     LPBYTE ccxlpData,
    00090     int    cbData)
    00091 {
    00092     PCLIPDATA pClipData;
    00093
    00094     pClipData = HMAllocObject(NULL,
    00095                               NULL,
    00096                               TYPE_CLIPDATA,
    00097                               FIELD_OFFSET(CLIPDATA, abData) + cbData);
    00098
    00099     if (pClipData == NULL)
    00100         return NULL;
    00101
    00102     pClipData->cbData = cbData;
    00103
    00104     try {
    00105         RtlCopyMemory(&pClipData->abData, ccxlpData, cbData);
    00106     } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
    00107         HMFreeObject(pClipData);
    00108         return NULL;
    00109     }
    00110
    00111     return PtoHq(pClipData);
    00112 }
    00113
    00114 /***************************************************************************\
    00115 * _xxxOpenClipboard (API)
    00116 *
    00117 * External routine. Opens the clipboard for reading/writing, etc.
    00118 *
    00119 * History:
    00120 * 18-Nov-1990 ScottLu   Ported from Win3.
    00121 * 11-Feb-1991 JimA      Added access checks.
    00122 \***************************************************************************/
    00123
    00124 BOOL xxxOpenClipboard(
    00125     PWND   pwnd,
    00126     LPBOOL lpfEmptyClient)
    00127 {
    00128     PTHREADINFO    pti;
    00129     PWINDOWSTATION pwinsta;
    00130
    00131     CheckLock(pwnd);
    00132
    00133     if (lpfEmptyClient != NULL)
    00134         *lpfEmptyClient = FALSE;
    00135
    00136     /*
    00137      * Blow it off is the caller does not have the proper access rights
    00138      */
    00139     if ((pwinsta = CheckClipboardAccess()) == NULL)
    00140         return FALSE;
    00141
    00142     pti = PtiCurrent();
    00143
    00144     /*
    00145      * If this thread already has the clipboard open, then there's no
    00146      * need to proceed further.
    00147      */
    00148     if ((pwnd == pwinsta->spwndClipOpen) && (pti == pwinsta->ptiClipLock))
    00149         return TRUE;
    00150
    00151     if ((pwnd != pwinsta->spwndClipOpen) && (pwinsta->ptiClipLock != NULL)) {
    00152
    00153 #if DBG
    00154         /*
    00155          * Only rip if the current-thread doesn't have the clipboard
    00156          * open.
    00157          */
    00158         if (pti != pwinsta->ptiClipLock) {
    00159
    00160             RIPMSG0(RIP_VERBOSE,
    00161                   "Clipboard: OpenClipboard already out by another thread");
    00162         }
    00163 #endif
    00164         return FALSE;
    00165     }
    00166
    00167     /*
    00168      * If the window is already destroyed, then the clipboard will not
    00169      * get disowned when the window is finally unlocked.  FritzS
    00170      */
    00171
    00172     UserAssert((pwnd == NULL ) || (!TestWF(pwnd, WFDESTROYED)));
    00173
    00174     Lock(&pwinsta->spwndClipOpen, pwnd);
    00175     pwinsta->ptiClipLock = pti;
    00176
    00177     /*
    00178      * The client side clipboard cache needs to be emptied if this thread
    00179      * doesn't own the data in the clipboard.
    00180      * Note: We only empty the 16bit clipboard if a 32bit guy owns the
    00181      * clipboard.
    00182      * Harvard graphics uses a handle put into the clipboard
    00183      * by another app, and it expects that handle to still be good after the
    00184      * clipboard has opened and closed mutilple times
    00185      * There may be a problem here if app A puts in format foo and app B opens
    00186      * the clipboard for format foo and then closes it and opens it again
    00187      * format foo client side handle may not be valid.  We may need some
    00188      * sort of uniqueness counter to tell if the client side handle is
    00189      * in sync with the server and always call the server or put the data
    00190      * in share memory with some semaphore.
    00191      *
    00192      * pwinsta->spwndClipOwner: window that last called EmptyClipboard
    00193      * pwinsta->ptiClipLock   : thread that currently has the clipboard open
    00194      */
    00195     if (lpfEmptyClient != NULL) {
    00196
    00197         if (!(pti->TIF_flags & TIF_16BIT) ||
    00198             (pti->ppi->iClipSerialNumber != pwinsta->iClipSerialNumber)) {
    00199
    00200             *lpfEmptyClient = (pwinsta->spwndClipOwner == NULL) ||
    00201                     (pwinsta->ptiClipLock->ppi !=
    00202                     GETPTI(pwinsta->spwndClipOwner)->ppi);
    00203
    00204             pti->ppi->iClipSerialNumber = pwinsta->iClipSerialNumber;
    00205         }
    00206     }
    00207
    00208     return TRUE;
    00209 }
    00210
    00211 /***************************************************************************\
    00212 * xxxDrawClipboard
    00213 *
    00214 * Tells the clipboard viewers to redraw.
    00215 *
    00216 * History:
    00217 * 18-Nov-1990 ScottLu   Ported from Win3.
    00218 \***************************************************************************/
    00219
    00220 VOID xxxDrawClipboard(
    00221     PWINDOWSTATION pwinsta)
    00222 {
    00223     /*
    00224      * This is what pwinsta->fClipboardChanged is for - to tell us to
    00225      * update the clipboard viewers.
    00226      */
    00227     pwinsta->fClipboardChanged = FALSE;
    00228
    00229     if (pwinsta->ptiDrawingClipboard == NULL && pwinsta->spwndClipViewer != NULL) {
    00230
    00231         TL tlpwndClipViewer;
    00232
    00233         /*
    00234          * Send the message that causes clipboard viewers to redraw.
    00235          * Remember that we're sending this message so we don't send
    00236          * this message twice.
    00237          */
    00238         pwinsta->ptiDrawingClipboard = PtiCurrent();
    00239         ThreadLockAlways(pwinsta->spwndClipViewer, &tlpwndClipViewer);
    00240
    00241         if (!(PtiCurrent()->TIF_flags & TIF_16BIT)) {
    00242             /*
    00243              * Desynchronize 32 bit apps.
    00244              */
    00245             xxxSendNotifyMessage(pwinsta->spwndClipViewer,
    00246                                  WM_DRAWCLIPBOARD,
    00247                                  (WPARAM)HW(pwinsta->spwndClipOwner),
    00248                                  0L);
    00249         } else {
    00250             xxxSendMessage(pwinsta->spwndClipViewer,
    00251                            WM_DRAWCLIPBOARD,
    00252                            (WPARAM)HW(pwinsta->spwndClipOwner),
    00253                            0L);
    00254         }
    00255
    00256         ThreadUnlock(&tlpwndClipViewer);
    00257         pwinsta->ptiDrawingClipboard = NULL;
    00258     }
    00259 }
    00260
    00261 /***************************************************************************\
    00262 * PasteScreenPalette
    00263 *
    00264 * Creates temp palette with all colors of screen, and sticks it on
    00265 * clipboard.
    00266 *
    00267 * 20-Jun-1995 ChrisWil  Ported from Chicago.
    00268 \***************************************************************************/
    00269
    00270 VOID PasteScreenPalette(
    00271     PWINDOWSTATION pwinsta)
    00272 {
    00273     int          irgb;
    00274     int          crgbPal;
    00275     LPLOGPALETTE lppal;
    00276     HPALETTE     hpal = NULL;
    00277     int          crgbFixed;
    00278
    00279     UserAssert(TEST_PUSIF(PUSIF_PALETTEDISPLAY));
    00280
    00281     /*
    00282      * Use current state of screen.
    00283      */
    00284     crgbPal = GreGetDeviceCaps(gpDispInfo->hdcScreen, SIZEPALETTE);
    00285
    00286     if (GreGetSystemPaletteUse(gpDispInfo->hdcScreen) == SYSPAL_STATIC) {
    00287         crgbFixed = GreGetDeviceCaps(gpDispInfo->hdcScreen, NUMRESERVED) / 2;
    00288     } else {
    00289         crgbFixed = 1;
    00290     }
    00291
    00292     lppal = (LPLOGPALETTE)UserAllocPool(sizeof(LOGPALETTE) +
    00293                                               (sizeof(PALETTEENTRY) * crgbPal),
    00294                                               TAG_CLIPBOARD);
    00295
    00296     if (lppal == NULL)
    00297         return;
    00298
    00299     lppal->palVersion    = 0x300;
    00300     lppal->palNumEntries = (WORD)crgbPal;
    00301
    00302     if (GreGetSystemPaletteEntries(gpDispInfo->hdcScreen, 0, crgbPal, lppal->palPalEntry)) {
    00303
    00304         crgbPal -= crgbFixed;
    00305
    00306         for (irgb = crgbFixed; irgb < crgbPal; irgb++) {
    00307
    00308             /*
    00309              * Any non-system palette entries need to have PC_NOCOLLAPSE
    00310              * flag set.
    00311              */
    00312             lppal->palPalEntry[irgb].peFlags = PC_NOCOLLAPSE;
    00313         }
    00314
    00315         hpal = GreCreatePalette(lppal);
    00316     }
    00317
    00318     UserFreePool((HANDLE)lppal);
    00319
    00320     if (hpal) {
    00321         InternalSetClipboardData(pwinsta, CF_PALETTE, hpal, FALSE, TRUE);
    00322         GreSetPaletteOwner(hpal, OBJECT_OWNER_PUBLIC);
    00323     }
    00324 }
    00325
    00326 /***************************************************************************\
    00327 * MungeClipData
    00328 *
    00329 * When clipboard is closed, we translate data to more independent format
    00330 * and pastes dummy handles if necessary.
    00331 *
    00332 * 20-Jun-1995 ChrisWil  Ported from Chicago.
    00333 \***************************************************************************/
    00334
    00335 VOID MungeClipData(
    00336     PWINDOWSTATION pwinsta)
    00337 {
    00338     PCLIP  pOEM;
    00339     PCLIP  pTXT;
    00340     PCLIP  pUNI;
    00341     PCLIP  pBMP;
    00342     PCLIP  pDIB;
    00343     PCLIP  pDV5;
    00344
    00345     PCLIP pClip;
    00346
    00347     /*
    00348      * If only CF_OEMTEXT, CF_TEXT or CF_UNICODE are available, make the
    00349      * other formats available too.
    00350      */
    00351     pTXT = FindClipFormat(pwinsta, CF_TEXT);
    00352     pOEM = FindClipFormat(pwinsta, CF_OEMTEXT);
    00353     pUNI = FindClipFormat(pwinsta, CF_UNICODETEXT);
    00354
    00355     if (pTXT != NULL || pOEM != NULL || pUNI != NULL) {
    00356
    00357         /*
    00358          * Make dummy text formats.
    00359          */
    00360         if (!FindClipFormat(pwinsta, CF_LOCALE)) {
    00361
    00362             /*
    00363              * CF_LOCALE not currently stored.  Save the locale
    00364              * information while it's still available.
    00365              */
    00366             PTHREADINFO ptiCurrent = PtiCurrent();
    00367             DWORD       lcid;
    00368             DWORD       lang;
    00369             HANDLE      hLocale;
    00370
    00371             /*
    00372              * The LOCALE format is an HGLOBAL to a DWORD lcid.  The
    00373              * spklActive->hkl actually stores more than just the locale,
    00374              * so we need to mask the value.
    00375              * (#99321 spklActive is NULL before winlogon loads kbd layouts)
    00376              */
    00377             if (ptiCurrent->spklActive) {
    00378                 lang = HandleToUlong(ptiCurrent->spklActive->hkl);
    00379
    00380                 lcid = MAKELCID(LOWORD(lang), SORT_DEFAULT);
    00381
    00382                 if (hLocale = _ConvertMemHandle((LPBYTE)&lcid, sizeof(DWORD))) {
    00383                     if (!InternalSetClipboardData(pwinsta,
    00384                                                   CF_LOCALE,
    00385                                                   hLocale,
    00386                                                   FALSE,
    00387                                                   TRUE)) {
    00388                         PVOID pObj;
    00389
    00390                         pObj = HMValidateHandleNoRip(hLocale, TYPE_CLIPDATA);
    00391                         if (pObj != NULL) {
    00392                             HMFreeObject(pObj);
    00393                         }
    00394                     }
    00395                 }
    00396             }
    00397         }
    00398
    00399         if (pTXT == NULL)
    00400             InternalSetClipboardData(pwinsta,
    00401                                      CF_TEXT,
    00402                                      (HANDLE)DUMMY_TEXT_HANDLE,
    00403                                      FALSE,
    00404                                      TRUE);
    00405
    00406         if (pOEM == NULL)
    00407             InternalSetClipboardData(pwinsta,
    00408                                      CF_OEMTEXT,
    00409                                      (HANDLE)DUMMY_TEXT_HANDLE,
    00410                                      FALSE,
    00411                                      TRUE);
    00412
    00413         if (pUNI == NULL)
    00414             InternalSetClipboardData(pwinsta,
    00415                                      CF_UNICODETEXT,
    00416                                      (HANDLE)DUMMY_TEXT_HANDLE,
    00417                                      FALSE,
    00418                                      TRUE);
    00419     }
    00420
    00421     /*
    00422      * For the metafile formats we also want to add its cousin if its
    00423      * not alread present.  We pass the same data because GDI knows
    00424      * how to convert between the two.
    00425      */
    00426     if (!FindClipFormat(pwinsta, CF_METAFILEPICT) &&
    00427         (pClip = FindClipFormat(pwinsta, CF_ENHMETAFILE))) {
    00428
    00429         InternalSetClipboardData(pwinsta,
    00430                                 CF_METAFILEPICT,
    00431                                 pClip->hData ? DUMMY_METACLONE_HANDLE :
    00432                                     DUMMY_METARENDER_HANDLE,
    00433                                 FALSE,
    00434                                 TRUE);
    00435
    00436     } else if (!FindClipFormat(pwinsta, CF_ENHMETAFILE) &&
    00437                (pClip = FindClipFormat(pwinsta, CF_METAFILEPICT))) {
    00438
    00439         InternalSetClipboardData(pwinsta,
    00440                                  CF_ENHMETAFILE,
    00441                                  pClip->hData ? DUMMY_METACLONE_HANDLE :
    00442                                      DUMMY_METARENDER_HANDLE,
    00443                                  FALSE,
    00444                                  TRUE);
    00445     }
    00446
    00447     /*
    00448      * Convert bitmap formats.
    00449      *
    00450      * If only CF_BITMAP, CF_DIB or CF_DIBV5 are available, make the
    00451      * other formats available too. And check palette if screen is
    00452      * palette managed.
    00453      */
    00454     pBMP = FindClipFormat(pwinsta, CF_BITMAP);
    00455     pDIB = FindClipFormat(pwinsta, CF_DIB);
    00456     pDV5 = FindClipFormat(pwinsta, CF_DIBV5);
    00457
    00458     if (pBMP != NULL || pDIB != NULL || pDV5 != NULL) {
    00459
    00460         /*
    00461          * If there is no CF_BITMAP, set dummy.
    00462          */
    00463         if (pBMP == NULL) {
    00464             InternalSetClipboardData(pwinsta,
    00465                                      CF_BITMAP,
    00466                                      DUMMY_DIB_HANDLE,
    00467                                      FALSE,
    00468                                      TRUE);
    00469         }
    00470
    00471         /*
    00472          * If there is no CF_DIB, set dummy.
    00473          */
    00474         if (pDIB == NULL) {
    00475             InternalSetClipboardData(pwinsta,
    00476                                      CF_DIB,
    00477                                      DUMMY_DIB_HANDLE,
    00478                                      FALSE,
    00479                                      TRUE);
    00480         }
    00481
    00482         /*
    00483          * If there is no CF_DIBV5, set dummy.
    00484          */
    00485         if (pDV5 == NULL) {
    00486             InternalSetClipboardData(pwinsta,
    00487                                      CF_DIBV5,
    00488                                      DUMMY_DIB_HANDLE,
    00489                                      FALSE,
    00490                                      TRUE);
    00491         }
    00492
    00493         if (TEST_PUSIF(PUSIF_PALETTEDISPLAY) &&
    00494             !FindClipFormat(pwinsta, CF_PALETTE)) {
    00495
    00496             /*
    00497              * Displays are palettized and there is no palette data in clipboard, yet.
    00498              */
    00499             if (pDIB != NULL || pDV5 != NULL)
    00500             {
    00501                 /*
    00502                  * Store a dummy dib and palette (if one not already there).
    00503                  */
    00504                 InternalSetClipboardData(pwinsta,
    00505                                          CF_PALETTE,
    00506                                          DUMMY_DIB_HANDLE,
    00507                                          FALSE,
    00508                                          TRUE);
    00509             } else {
    00510                 /*
    00511                  * if only CF_BITMAP is avalilable, perserve Screen palette.
    00512                  */
    00513                 PasteScreenPalette(pwinsta);
    00514             }
    00515         }
    00516     }
    00517
    00518     return;
    00519 }
    00520
    00521 /***************************************************************************\
    00522 * xxxCloseClipboard (API)
    00523 *
    00524 * External routine. Closes the clipboard.
    00525 *
    00526 * Note: we do not delete any client side handle at this point.  Many apps,
    00527 * WordPerfectWin, incorrectly use handles after they have put them in the
    00528 * clipboard.  They also put things in the clipboard without becoming the
    00529 * clipboard owner because they want to add RichTextFormat to the normal
    00530 * text that is already in the clipboard from another app.
    00531 *
    00532 * History:
    00533 * 18-Nov-1990 ScottLu   Ported from Win3.
    00534 * 22-Aug-1991 EichiM    Unicode enabling
    00535 * 20-Jun-1995 ChrisWil  Merged Chicago functionality.
    00536 \***************************************************************************/
    00537
    00538 BOOL xxxCloseClipboard(
    00539     PWINDOWSTATION pwinsta)
    00540 {
    00541     PTHREADINFO ptiCurrent;
    00542     TL          tlpwinsta;
    00543
    00544     if ((pwinsta == NULL) && ((pwinsta = CheckClipboardAccess()) == NULL)) {
    00545         return FALSE;
    00546     }
    00547
    00548     /*
    00549      * If the current thread does not have the clipboard open, return
    00550      * FALSE.
    00551      */
    00552     ptiCurrent = PtiCurrent();
    00553
    00554     if (pwinsta->ptiClipLock != ptiCurrent) {
    00555         RIPERR0(ERROR_CLIPBOARD_NOT_OPEN, RIP_WARNING, "xxxCloseClipboard not open");
    00556         return FALSE;
    00557     }
    00558
    00559     ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
    00560
    00561     /*
    00562      * Convert data to independent formats.
    00563      */
    00564     if (pwinsta->fClipboardChanged)
    00565         MungeClipData(pwinsta);
    00566
    00567     /*
    00568      * Release the clipboard explicitly after we're finished calling
    00569      * SetClipboardData().
    00570      */
    00571     Unlock(&pwinsta->spwndClipOpen);
    00572     pwinsta->ptiClipLock = NULL;
    00573
    00574     /*
    00575      * Notify any clipboard viewers that the clipboard contents have
    00576      * changed.
    00577      */
    00578     if (pwinsta->fClipboardChanged)
    00579         xxxDrawClipboard(pwinsta);
    00580
    00581     ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
    00582
    00583     return TRUE;
    00584 }
    00585
    00586 /***************************************************************************\
    00587 * _EnumClipboardFormats (API)
    00588 *
    00589 * This routine takes a clipboard format and gives the next format back to
    00590 * the application. This should only be called while the clipboard is open
    00591 * and locked so the formats don't change around.
    00592 *
    00593 * History:
    00594 * 18-Nov-1990 ScottLu   Ported from Win3.
    00595 \***************************************************************************/
    00596
    00597 UINT _EnumClipboardFormats(
    00598     UINT fmt)
    00599 {
    00600     PWINDOWSTATION pwinsta;
    00601     UINT           fmtRet;
    00602
    00603     if ((pwinsta = CheckClipboardAccess()) == NULL)
    00604         return 0;
    00605
    00606     /*
    00607      * If the current thread doesn't have the clipboard open or if there
    00608      * is no clipboard, return 0 for no formats.
    00609      */
    00610     if (pwinsta->ptiClipLock != PtiCurrent()) {
    00611         RIPERR0(ERROR_CLIPBOARD_NOT_OPEN, RIP_WARNING, "EnumClipboardFormat: clipboard not open");
    00612         return 0;
    00613     }
    00614
    00615     fmtRet = 0;
    00616
    00617     if (pwinsta->pClipBase != NULL) {
    00618
    00619         PCLIP pClip;
    00620
    00621         /*
    00622          * Find the next clipboard format.  If the format is 0, start from
    00623          * the beginning.
    00624          */
    00625         if (fmt != 0) {
    00626
    00627             /*
    00628              * Find the next clipboard format.  NOTE that this routine locks
    00629              * the clipboard handle and updates pwinsta->pClipBase with the
    00630              * starting address of the clipboard.
    00631              */
    00632             if ((pClip = FindClipFormat(pwinsta, fmt)) != NULL)
    00633                 pClip++;
    00634
    00635         } else {
    00636             pClip = pwinsta->pClipBase;
    00637         }
    00638
    00639         /*
    00640          * Find the new format before unlocking the clipboard.
    00641          */
    00642         if (pClip && (pClip < &pwinsta->pClipBase[pwinsta->cNumClipFormats])) {
    00643
    00644             fmtRet = pClip->fmt;
    00645         }
    00646     }
    00647
    00648     /*
    00649      * Return the new clipboard format.
    00650      */
    00651     return fmtRet;
    00652 }
    00653
    00654 /***************************************************************************\
    00655 * UT_GetFormatType
    00656 *
    00657 * Given the clipboard format, return the handle type.
    00658 *
    00659 * Warning:  Private formats, eg CF_PRIVATEFIRST, return PRIVATEFORMAT
    00660 * unlike Win 3.1 which has a bug and returns HANDLEFORMAT.  And they
    00661 * would incorrectly free the handle.  Also they would NOT free GDIOBJFIRST
    00662 * objects.
    00663 *
    00664 * History:
    00665 * 18-Nov-1990 ScottLu   Ported from Win3.
    00666 \***************************************************************************/
    00667
    00668 int UT_GetFormatType(
    00669     PCLIP pClip)
    00670 {
    00671     switch (pClip->fmt) {
    00672
    00673     case CF_BITMAP:
    00674     case CF_DSPBITMAP:
    00675     case CF_PALETTE:
    00676         return GDIFORMAT;
    00677
    00678     case CF_METAFILEPICT:
    00679     case CF_DSPMETAFILEPICT:
    00680     case CF_ENHMETAFILE:
    00681     case CF_DSPENHMETAFILE:
    00682         return METAFILEFORMAT;
    00683
    00684     case CF_OWNERDISPLAY:
    00685         return PRIVATEFORMAT;
    00686
    00687     default:
    00688         return HANDLEFORMAT;
    00689     }
    00690 }
    00691
    00692 /***************************************************************************\
    00693 * UT_FreeCBFormat
    00694 *
    00695 * Free the data in the pass clipboard structure.
    00696 *
    00697 * History:
    00698 * 18-Nov-1990 ScottLu   Ported from Win3.
    00699 \***************************************************************************/
    00700
    00701 VOID UT_FreeCBFormat(
    00702     PCLIP pClip)
    00703 {
    00704     PVOID pObj;
    00705
    00706     /*
    00707      * No Data, then no point.
    00708      */
    00709     if (pClip->hData == NULL)
    00710         return;
    00711
    00712     /*
    00713      * Free the object given the type.
    00714      */
    00715     switch (UT_GetFormatType(pClip)) {
    00716
    00717     case METAFILEFORMAT:
    00718
    00719         /*
    00720          * GDI stores the metafile on the server side for the clipboard.
    00721          * Notify the GDI server to free the metafile data.
    00722          */
    00723         if (!IsMetaDummyHandle(pClip->hData)) {
    00724             GreDeleteServerMetaFile(pClip->hData);
    00725         }
    00726         break;
    00727
    00728     case HANDLEFORMAT:
    00729
    00730         /*
    00731          * It's a simple global object.  Text/Dib handles can be
    00732          * dummy handles, so check for those first.  We need to
    00733          * perform extra-checks on the format since HANDLEFORMATS
    00734          * are the default-type.  We only want to delete those obects
    00735          * we can quarentee are handle-types.
    00736          */
    00737         if ((pClip->hData != DUMMY_TEXT_HANDLE) &&
    00738             (pClip->hData != DUMMY_DIB_HANDLE)) {
    00739
    00740             pObj = HMValidateHandleNoRip(pClip->hData, TYPE_CLIPDATA);
    00741             if (pObj) {
    00742                 HMFreeObject(pObj);
    00743             }
    00744         }
    00745         break;
    00746
    00747     case GDIFORMAT:
    00748
    00749         /*
    00750          * Bitmaps can be marked as dummy-handles.
    00751          */
    00752         if (pClip->hData != DUMMY_DIB_HANDLE) {
    00753             GreDeleteObject(pClip->hData);
    00754         }
    00755         break;
    00756
    00757     case PRIVATEFORMAT:
    00758
    00759         /*
    00760          * Destroy the private data here if it is a global handle: we
    00761          * aren't destroying the client's copy here, only the server's,
    00762          * which nobody wants (including the server!)
    00763          */
    00764         if (pClip->fGlobalHandle) {
    00765             pObj = HMValidateHandleNoRip(pClip->hData, TYPE_CLIPDATA);
    00766             if (pObj) {
    00767                 HMFreeObject(pObj);
    00768             }
    00769         }
    00770         break;
    00771     }
    00772 }
    00773
    00774 /***************************************************************************\
    00775 * xxxSendClipboardMessage
    00776 *
    00777 * Helper routine that sends a notification message to the clipboard owner.
    00778 *
    00779 * History:
    00780 * 18-Nov-1990 ScottLu   Ported from Win3.
    00781 \***************************************************************************/
    00782
    00783 VOID xxxSendClipboardMessage(
    00784     PWINDOWSTATION pwinsta,
    00785     UINT           message)
    00786 {
    00787     TL      tlpwndClipOwner;
    00788     LONG_PTR dwResult;
    00789     LRESULT lRet;
    00790
    00791     if (pwinsta->spwndClipOwner != NULL) {
    00792
    00793         PWND    pwndClipOwner = pwinsta->spwndClipOwner;
    00794
    00795         ThreadLockAlways(pwndClipOwner, &tlpwndClipOwner);
    00796
    00797         /*
    00798          * We use SendNotifyMessage so the apps don't have to synchronize
    00799          * but some 16 bit apps break because of the different message
    00800          * ordering so we allow 16 bit apps to synchronize to other apps
    00801          * Word 6 and Excel 5 with OLE.  Do a copy in Word and then another
    00802          * copy in Excel and Word faults.
    00803          */
    00804         if ((message == WM_DESTROYCLIPBOARD) &&
    00805             !(PtiCurrent()->TIF_flags & TIF_16BIT)) {
    00806
    00807             /*
    00808              * Let the app think it's the clipboard owner during
    00809              * the processing of this message by waiting for it
    00810              * to be processed before setting the new owner.
    00811              */
    00812             lRet = xxxSendMessageTimeout(
    00813                     pwndClipOwner,
    00814                     WM_DESTROYCLIPBOARD,
    00815                     0,
    00816                     0L,
    00817                     SMTO_ABORTIFHUNG | SMTO_NORMAL,
    00818                     5 * 1000,
    00819                     &dwResult);
    00820
    00821             if (lRet == 0) {
    00822
    00823                 /*
    00824                  * The message timed out and wasn't sent, so
    00825                  * let the app handle it when it's ready.
    00826                  */
    00827                 RIPMSG0(RIP_WARNING, "Sending WM_DESTROYCLIPBOARD timed-out, resending via SendNotifyMessage");
    00828                 xxxSendNotifyMessage(pwndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
    00829             }
    00830
    00831         } else {
    00832
    00833             xxxSendMessage(pwndClipOwner, message, 0, 0L);
    00834         }
    00835
    00836         ThreadUnlock(&tlpwndClipOwner);
    00837     }
    00838
    00839 }
    00840
    00841 /***************************************************************************\
    00842 * xxxEmptyClipboard (API)
    00843 *
    00844 * Empties the clipboard contents if the current thread has the clipboard
    00845 * open.
    00846 *
    00847 * History:
    00848 * 18-Nov-1990 ScottLu   Ported from Win3.
    00849 \***************************************************************************/
    00850
    00851 BOOL xxxEmptyClipboard(
    00852     PWINDOWSTATION pwinsta)
    00853 {
    00854     TL          tlpwinsta;
    00855     PCLIP       pClip;
    00856     int         cFmts;
    00857     BOOL        fDying;
    00858     PTHREADINFO ptiCurrent = (PTHREADINFO)(W32GetCurrentThread());
    00859     BOOL bInternal = !(pwinsta == NULL);
    00860
    00861     /*
    00862      * Check access.
    00863      */
    00864     if ((pwinsta == NULL) && ((pwinsta = CheckClipboardAccess()) == NULL))
    00865         return FALSE;
    00866
    00867     /*
    00868      * If the current thread doesn't have the clipboard open, it can't be
    00869      * be emptied!
    00870      */
    00871
    00872     if (ptiCurrent == NULL) {
    00873         UserAssert(bInternal);
    00874     }
    00875
    00876     if (!bInternal) {
    00877         if (pwinsta->ptiClipLock != ptiCurrent) {
    00878             RIPERR0(ERROR_CLIPBOARD_NOT_OPEN, RIP_WARNING, "xxxEmptyClipboard: clipboard not open");
    00879             return FALSE;
    00880         }
    00881     }
    00882
    00883     /*
    00884      * Only send messages at logoff.
    00885      */
    00886     fDying = pwinsta->dwWSF_Flags & WSF_DYING;
    00887
    00888     if (!fDying && ptiCurrent) {
    00889         ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
    00890
    00891         /*
    00892          * Let the clipboard owner know that the clipboard is
    00893          * being destroyed.
    00894          */
    00895         xxxSendClipboardMessage(pwinsta, WM_DESTROYCLIPBOARD);
    00896     }
    00897
    00898     if ((pClip = pwinsta->pClipBase) != NULL) {
    00899
    00900         /*
    00901          * Loop through all the clipboard entries and free their data
    00902          * objects.  Only call DeleteAtom for real atoms.
    00903          */
    00904         for (cFmts = pwinsta->cNumClipFormats; cFmts-- != 0;) {
    00905
    00906             if ((ATOM)pClip->fmt >= MAXINTATOM)
    00907                 UserDeleteAtom((ATOM)pClip->fmt);
    00908
    00909             UT_FreeCBFormat(pClip++);
    00910         }
    00911
    00912         /*
    00913          * Free the clipboard itself.
    00914          */
    00915         UserFreePool((HANDLE)pwinsta->pClipBase);
    00916         pwinsta->pClipBase       = NULL;
    00917         pwinsta->cNumClipFormats = 0;
    00918     }
    00919
    00920     /*
    00921      * The "empty" succeeds.  The owner is now the thread that has the
    00922      * clipboard open.  Remember the clipboard has changed; this will
    00923      * cause the viewer to redraw at CloseClipboard time.
    00924      */
    00925     pwinsta->fClipboardChanged = TRUE;
    00926     Lock(&pwinsta->spwndClipOwner, pwinsta->spwndClipOpen);
    00927
    00928     /*
    00929      * Change the clipboard serial number so that the client-side
    00930      * clipboard caches of all the processes will get
    00931      * flushed on the next OpenClipboard.
    00932      */
    00933     pwinsta->iClipSerialNumber++;
    00934     pwinsta->iClipSequenceNumber++;
    00935     pwinsta->fInDelayedRendering = FALSE;
    00936
    00937     if (!fDying && ptiCurrent)
    00938         ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
    00939
    00940     return TRUE;
    00941 }
    00942
    00943 /***************************************************************************\
    00944 * _SetClipboardData
    00945 *
    00946 * This routine sets data into the clipboard. Does validation against
    00947 * DUMMY_TEXT_HANDLE only.
    00948 *
    00949 * History:
    00950 * 18-Nov-1990 ScottLu   Ported from Win3.
    00951 \***************************************************************************/
    00952
    00953 BOOL _SetClipboardData(
    00954     UINT   fmt,
    00955     HANDLE hData,
    00956     BOOL   fGlobalHandle,
    00957     BOOL   fIncSerialNumber)
    00958 {
    00959     PWINDOWSTATION pwinsta;
    00960     BOOL fRet;
    00961
    00962     if ((pwinsta = CheckClipboardAccess()) == NULL)
    00963         return FALSE;
    00964
    00965     /*
    00966      * Check if the Data handle is DUMMY_TEXT_HANDLE; If so, return an
    00967      * error.  DUMMY_TEXT_HANDLE will be used as a valid clipboard handle
    00968      * only by USER.  If any app tries to pass it as a handle, it should
    00969      * get an error!
    00970      */
    00971     if ((hData >= DUMMY_TEXT_HANDLE) && (hData <= DUMMY_MAX_HANDLE)) {
    00972         RIPMSG0(RIP_WARNING, "Clipboard: SetClipboardData called with dummy-handle");
    00973         return FALSE;
    00974     }
    00975
    00976     if (fRet = InternalSetClipboardData(pwinsta, fmt, hData, fGlobalHandle, fIncSerialNumber)) {
    00977
    00978         /*
    00979          * The set object must remain PUBLIC, so that other processes
    00980          * can view/manipulate the handles when requested.
    00981          */
    00982         switch (fmt) {
    00983         case CF_BITMAP:
    00984             GreSetBitmapOwner(hData, OBJECT_OWNER_PUBLIC);
    00985             break;
    00986
    00987         case CF_PALETTE:
    00988             GreSetPaletteOwner(hData, OBJECT_OWNER_PUBLIC);
    00989             break;
    00990         }
    00991     }
    00992
    00993     return fRet;
    00994 }
    00995
    00996 /***************************************************************************\
    00997 * InternalSetClipboardData
    00998 *
    00999 * Internal routine to set data into the clipboard.
    01000 *
    01001 * History:
    01002 * 18-Nov-1990 ScottLu   Ported from Win3.
    01003 \***************************************************************************/
    01004
    01005 #define CCHFORMATNAME 256
    01006
    01007 BOOL InternalSetClipboardData(
    01008     PWINDOWSTATION pwinsta,
    01009     UINT           fmt,
    01010     HANDLE         hData,
    01011     BOOL           fGlobalHandle,
    01012     BOOL           fIncSerialNumber)
    01013 {
    01014     PCLIP pClip;
    01015     WCHAR achFormatName[CCHFORMATNAME];
    01016
    01017     /*
    01018      * Just check for pwinsta->ptiClipLock being NULL instead of checking
    01019      * against PtiCurrent because an app needs to call SetClipboardData if
    01020      * he's rendering data while another app has the clipboard open.
    01021      */
    01022     if ((pwinsta->ptiClipLock == NULL) || (fmt == 0)) {
    01023         RIPERR0(ERROR_CLIPBOARD_NOT_OPEN, RIP_WARNING, "SetClipboardData: Clipboard not open");
    01024         return FALSE;
    01025     }
    01026
    01027     if ((pClip = FindClipFormat(pwinsta, fmt)) != NULL) {
    01028
    01029         /*
    01030          * If data already exists, free it before we replace it.
    01031          */
    01032         UT_FreeCBFormat(pClip);
    01033
    01034     } else {
    01035
    01036         if (pwinsta->pClipBase == NULL) {
    01037             pClip = (PCLIP)UserAllocPool(sizeof(CLIP), TAG_CLIPBOARD);
    01038         } else {
    01039             DWORD dwSize = sizeof(CLIP) * pwinsta->cNumClipFormats;
    01040
    01041             pClip = (PCLIP)UserReAllocPool(pwinsta->pClipBase,
    01042                                            dwSize,
    01043                                            dwSize + sizeof(CLIP),
    01044                                            TAG_CLIPBOARD);
    01045         }
    01046
    01047         /*
    01048          * Out of memory...  return.
    01049          */
    01050         if (pClip == NULL) {
    01051             RIPMSG0(RIP_WARNING, "SetClipboardData: Out of memory");
    01052             return FALSE;
    01053         }
    01054
    01055         /*
    01056          * Just in case the data moved
    01057          */
    01058         pwinsta->pClipBase = pClip;
    01059
    01060         /*
    01061          * Increment the reference count of this atom format so that if
    01062          * the application frees this atom we don't get stuck with a
    01063          * bogus atom. We call DeleteAtom in the EmptyClipboard() code,
    01064          * which decrements this count when we're done with this clipboard
    01065          * data.
    01066          */
    01067         if (UserGetAtomName((ATOM)fmt, achFormatName, CCHFORMATNAME) != 0)
    01068             UserAddAtom(achFormatName, FALSE);
    01069
    01070         /*
    01071          * Point to the new entry in the clipboard.
    01072          */
    01073         pClip += pwinsta->cNumClipFormats++;
    01074         pClip->fmt = fmt;
    01075     }
    01076
    01077     /*
    01078      * Start updating the new entry in the clipboard.
    01079      */
    01080     pClip->hData         = hData;
    01081     pClip->fGlobalHandle = fGlobalHandle;
    01082
    01083     if (fIncSerialNumber)
    01084         pwinsta->fClipboardChanged = TRUE;
    01085
    01086     if (fIncSerialNumber && !pwinsta->fInDelayedRendering) {
    01087         pwinsta->iClipSequenceNumber++;
    01088     }
    01089
    01090     /*
    01091      * If the thread didn't bother emptying the clipboard before
    01092      * writing to it, change the clipboard serial number
    01093      * so that the client-side clipboard caches of all the
    01094      * processes will get flushed on the next OpenClipboard.
    01095      */
    01096     if ((pwinsta->spwndClipOwner == NULL) ||
    01097         (GETPTI(pwinsta->spwndClipOwner) != PtiCurrent())) {
    01098
    01099         RIPMSG0(RIP_VERBOSE, "Clipboard: SetClipboardData called without emptying clipboard");
    01100
    01101         if (fIncSerialNumber)
    01102             pwinsta->iClipSerialNumber++;
    01103     }
    01104
    01105     return TRUE;
    01106 }
    01107
    01108 /***************************************************************************\
    01109 * CreateScreenBitmap
    01110 *
    01111 *
    01112 \***************************************************************************/
    01113
    01114 HBITMAP CreateScreenBitmap(
    01115     int  cx,
    01116     int  cy,
    01117     UINT bpp)
    01118 {
    01119     if (bpp == 1)
    01120         return GreCreateBitmap(cx, cy, 1, 1, NULL);
    01121
    01122     return GreCreateCompatibleBitmap(gpDispInfo->hdcScreen, cx, cy);
    01123 }
    01124
    01125 /***************************************************************************\
    01126 * SizeOfDib
    01127 *
    01128 * Returns the size of a packed-dib.
    01129 *
    01130 \***************************************************************************/
    01131
    01132 DWORD SizeOfDib(
    01133     LPBITMAPINFOHEADER lpDib)
    01134 {
    01135     DWORD dwColor;
    01136     DWORD dwBits;
    01137
    01138     /*
    01139      * Calculate size of bitmap bits.
    01140      */
    01141     dwBits = WIDTHBYTES(lpDib->biWidth * lpDib->biBitCount) * abs(lpDib->biHeight);
    01142
    01143     /*
    01144      * Calculate size of color table.
    01145      */
    01146     if ((lpDib->biCompression == BI_RGB) ||
    01147         (lpDib->biCompression == BI_BITFIELDS)) {
    01148
    01149         if (lpDib->biClrUsed) {
    01150             dwColor = lpDib->biClrUsed * sizeof(DWORD);
    01151         } else {
    01152             if (lpDib->biBitCount <= 8) {
    01153                 dwColor = (1 << lpDib->biBitCount) * sizeof(RGBQUAD);
    01154             } else if ((lpDib->biBitCount == 16) || (lpDib->biBitCount == 32)) {
    01155                 if (lpDib->biCompression == BI_BITFIELDS) {
    01156                     dwColor = (3 * sizeof(DWORD));
    01157                 } else {
    01158                     dwColor = 0;
    01159                 }
    01160             } else {
    01161                 dwColor = 0;
    01162             }
    01163         }
    01164
    01165     } else if (lpDib->biCompression == BI_RLE4) {
    01166
    01167         dwColor = 16 * sizeof(DWORD);
    01168
    01169     } else if (lpDib->biCompression == BI_RLE8) {
    01170
    01171         dwColor = 256 * sizeof(DWORD);
    01172
    01173     } else {
    01174
    01175         dwColor = 0;
    01176
    01177     }
    01178
    01179     return (lpDib->biSize + dwColor + dwBits);
    01180 }
    01181
    01182 /***************************************************************************\
    01183 * DIBtoBMP
    01184 *
    01185 * Creates a bitmap from a DIB spec.
    01186 *
    01187 \***************************************************************************/
    01188
    01189 HBITMAP DIBtoBMP(
    01190     LPBITMAPINFOHEADER lpbih,
    01191     HPALETTE           hpal)
    01192 {
    01193     HDC      hdc;
    01194     int      cx;
    01195     int      cy;
    01196     int      bpp;
    01197     LPSTR    lpbits;
    01198     HBITMAP  hbmp;
    01199
    01200     #define lpbch ((LPBITMAPCOREHEADER)lpbih)
    01201
    01202     /*
    01203      * Gather the dib-info for the convert.
    01204      */
    01205     if (lpbih->biSize == sizeof(BITMAPINFOHEADER)) {
    01206
    01207         cx  = (int)lpbih->biWidth;
    01208         cy  = (int)lpbih->biHeight;
    01209         bpp = (int)lpbih->biBitCount;
    01210
    01211         lpbits = ((PBYTE)lpbih) + sizeof(BITMAPINFOHEADER);
    01212
    01213         if (lpbih->biClrUsed) {
    01214             lpbits += (lpbih->biClrUsed * sizeof(RGBQUAD));
    01215         } else if (bpp <= 8) {
    01216             lpbits += ((1 << bpp) * sizeof(RGBQUAD));
    01217         } else if ((bpp == 16) || (bpp == 32)) {
    01218             lpbits += (3 * sizeof(RGBQUAD));
    01219         }
    01220
    01221     } else if (lpbch->bcSize == sizeof(BITMAPCOREHEADER)) {
    01222
    01223         cx  = (int)lpbch->bcWidth;
    01224         cy  = (int)lpbch->bcHeight;
    01225         bpp = (int)lpbch->bcBitCount;
    01226
    01227         lpbits = ((PBYTE)lpbch) + sizeof(BITMAPCOREHEADER);
    01228
    01229         if (lpbch->bcBitCount <= 8)
    01230             lpbits += (1 << bpp);
    01231
    01232     } else {
    01233         return NULL;
    01234     }
    01235
    01236     hbmp = NULL;
    01237
    01238     if (hdc = GreCreateCompatibleDC(gpDispInfo->hdcScreen)) {
    01239
    01240         if (hbmp = CreateScreenBitmap(cx, cy, bpp)) {
    01241
    01242             HBITMAP  hbmT;
    01243             HPALETTE hpalT = NULL;
    01244
    01245             hbmT = GreSelectBitmap(hdc, hbmp);
    01246
    01247             if (hpal) {
    01248                 hpalT = _SelectPalette(hdc, hpal, FALSE);
    01249                 xxxRealizePalette(hdc);
    01250             }
    01251
    01252             GreSetDIBits(hdc,
    01253                          hbmp,
    01254                          0,
    01255                          cy,
    01256                          lpbits,
    01257                          (LPBITMAPINFO)lpbih,
    01258                          DIB_RGB_COLORS);
    01259
    01260             if (hpalT) {
    01261                 _SelectPalette(hdc, hpalT, FALSE);
    01262                 xxxRealizePalette(hdc);
    01263             }
    01264
    01265             GreSelectBitmap(hdc, hbmT);
    01266         }
    01267
    01268         GreDeleteDC(hdc);
    01269     }
    01270
    01271     #undef lpbch
    01272
    01273     return hbmp;
    01274 }
    01275
    01276 /***************************************************************************\
    01277 * BMPtoDIB
    01278 *
    01279 * Creates a memory block with DIB information from a physical bitmap tagged
    01280 * to a specific DC.
    01281 *
    01282 * A DIB block consists of a BITMAPINFOHEADER + RGB colors + DIB bits.
    01283 *
    01284 \***************************************************************************/
    01285
    01286 LPBITMAPINFOHEADER BMPtoDIB(
    01287     HBITMAP  hbmp,
    01288     HPALETTE hpal,
    01289     DWORD*   pcbSize)
    01290 {
    01291     BITMAP             bmp;
    01292     BITMAPINFOHEADER   bi;
    01293     LPBITMAPINFOHEADER lpbi;
    01294     DWORD              cbBits;
    01295     DWORD              cbPalette;
    01296     DWORD              cbTotal;
    01297     WORD               cBits;
    01298     HDC                hdc;
    01299
    01300     UserAssert(hbmp);
    01301
    01302     /*
    01303      * Get physical information
    01304      */
    01305     if (!GreExtGetObjectW(hbmp, sizeof(BITMAP), &bmp)) {
    01306         UserAssert(FALSE);
    01307         return NULL;
    01308     }
    01309
    01310     /*
    01311      * Adjust the bit count since we only allow DIBS with 1,4,8,16,24 and
    01312      * 32 bits.
    01313      */
    01314     cBits = ((WORD)bmp.bmPlanes * (WORD)bmp.bmBitsPixel);
    01315
    01316     if (cBits <= 1) {
    01317
    01318         cBits = 1;
    01319
    01320     } else if (cBits <= 4) {
    01321
    01322         cBits = 4;
    01323
    01324     } else if (cBits <= 8) {
    01325
    01326         cBits = 8;
    01327
    01328     } else {
    01329
    01330         /*
    01331          * We're not going to recognize 16/32bpp formats for
    01332          * apps that are not 4.00 or greater.  Paint-Shop has
    01333          * a bug in it where they only recognize (1,4,8,24).  This
    01334          * really stinks that we need to do this type of thing as
    01335          * not to break them bad-apps.
    01336          */
    01337         if (LOWORD(PtiCurrent()->dwExpWinVer) >= VER40) {
    01338
    01339             if (cBits <= 16)
    01340                 cBits = 16;
    01341             else if (cBits <= 24)
    01342                 cBits = 24;
    01343             else
    01344                 cBits = 32;
    01345
    01346         } else {
    01347             cBits = 24;
    01348         }
    01349     }
    01350
    01351     /*
    01352      * Fill in BITMAPINFOHEADER with DIB data
    01353      */
    01354     RtlZeroMemory(&bi, sizeof(bi));
    01355
    01356     bi.biSize        = sizeof(bi);
    01357     bi.biWidth       = bmp.bmWidth;
    01358     bi.biHeight      = bmp.bmHeight;
    01359     bi.biPlanes      = 1;
    01360     bi.biBitCount    = cBits;
    01361     bi.biCompression = BI_RGB;
    01362
    01363     /*
    01364      * DWORD align the bits-size since dibs must be so.
    01365      */
    01366     cbBits = (DWORD)WIDTHBYTES((WORD)bi.biWidth * cBits) * (DWORD)bi.biHeight;
    01367
    01368     /*
    01369      * How big is the palette color table?
    01370      */
    01371     cbPalette = 0;
    01372
    01373     if (cBits <= 8) {
    01374
    01375         cbPalette = (1 << cBits) * sizeof(RGBQUAD);
    01376
    01377     } else if ((cBits == 16) || (cBits == 32)) {
    01378
    01379         cbPalette = (3 * sizeof(DWORD));
    01380         bi.biCompression = BI_BITFIELDS;
    01381     }
    01382
    01383     /*
    01384      * How much space do we need for the entire DIB?
    01385      */
    01386     cbTotal = bi.biSize + cbPalette + cbBits;
    01387
    01388     lpbi = (LPBITMAPINFOHEADER)UserAllocPool(cbTotal, TAG_CLIPBOARD);
    01389     if (lpbi == NULL) {
    01390         return NULL;
    01391     }
    01392
    01393     /*
    01394      * Have the total allocated size returned in pcbSize
    01395      */
    01396     if (pcbSize != NULL) {
    01397         *pcbSize = cbTotal;
    01398     }
    01399
    01400     /*
    01401      * Setup DIB header
    01402      */
    01403     memcpy(lpbi, &bi, sizeof(bi));
    01404
    01405     if (hdc = GreCreateCompatibleDC(gpDispInfo->hdcScreen)) {
    01406         HPALETTE           hpalT = NULL;
    01407         TL tlPool;
    01408
    01409         ThreadLockPool(PtiCurrent(), lpbi, &tlPool);
    01410
    01411         if (hpal) {
    01412             hpalT = _SelectPalette(hdc, hpal, FALSE);
    01413             xxxRealizePalette(hdc);
    01414         }
    01415
    01416         /*
    01417          * Get old bitmap's DIB bits, using the current DC.
    01418          */
    01419         GreGetDIBitsInternal(hdc,
    01420                              hbmp,
    01421                              0,
    01422                              (WORD)bi.biHeight,
    01423                              (LPSTR)((LPSTR)lpbi + lpbi->biSize + cbPalette),
    01424                              (LPBITMAPINFO)lpbi,
    01425                              DIB_RGB_COLORS,
    01426                              cbBits,
    01427                              lpbi->biSize + cbPalette);
    01428
    01429
    01430         if (hpalT) {
    01431             _SelectPalette(hdc, hpalT, FALSE);
    01432             xxxRealizePalette(hdc);
    01433         }
    01434
    01435         GreDeleteDC(hdc);
    01436
    01437         ThreadUnlockPool(PtiCurrent(), &tlPool);
    01438     }
    01439
    01440     return lpbi;
    01441 }
    01442
    01443 /***************************************************************************\
    01444 * DIBtoDIBV5
    01445 *
    01446 * History:
    01447 * 18-Dec-1997 HideyukN  Created.
    01448 \***************************************************************************/
    01449
    01450 LPBITMAPV5HEADER DIBtoDIBV5(
    01451     LPBITMAPINFOHEADER lpDib,
    01452     DWORD              cbSize)
    01453 {
    01454     LPBITMAPV5HEADER lpV5h;
    01455     ULONG            cjBits;
    01456     ULONG            cjColor, cjColorV5;
    01457     BOOL             bBitMasks = FALSE;
    01458
    01459     if (cbSize < sizeof(BITMAPINFOHEADER)) {
    01460         RIPMSG2(RIP_WARNING, "DIBtoDIBV5: buffer %d too small for header %d",
    01461                 cbSize, sizeof(BITMAPINFOHEADER));
    01462         return NULL;
    01463     }
    01464
    01465     /*
    01466      * Support only convert from BITMAPINFOHEADER
    01467      */
    01468     if (lpDib->biSize != sizeof(BITMAPINFOHEADER))
    01469         return NULL;
    01470
    01471     /*
    01472      * Calculate size of bitmap bits.
    01473      */
    01474     cjBits = WIDTHBYTES(lpDib->biWidth * lpDib->biBitCount) * abs(lpDib->biHeight);
    01475
    01476     /*
    01477      * Calculate size of color table.
    01478      */
    01479     if (lpDib->biCompression == BI_BITFIELDS) {
    01480
    01481         if ((lpDib->biBitCount == 16) || (lpDib->biBitCount == 32)) {
    01482             /*
    01483              * Color bit masks for R,G,B.
    01484              */
    01485             cjColor   = (3 * sizeof(DWORD));
    01486
    01487             /*
    01488              * Bit fields data is a part of BITMAPV5HEADER
    01489              */
    01490             cjColorV5 = 0;
    01491             bBitMasks = TRUE;
    01492         } else {
    01493             /*
    01494              * Actually, thi shouldn't happen.
    01495              */
    01496             RIPMSG0(RIP_ERROR,"Bad BITMAPINFOHEADER.");
    01497             cjColor = cjColorV5 = 0;
    01498         }
    01499
    01500     } else if (lpDib->biCompression == BI_RGB) {
    01501
    01502         if (lpDib->biClrUsed) {
    01503             cjColor = cjColorV5 = lpDib->biClrUsed * sizeof(DWORD);
    01504         } else {
    01505             if (lpDib->biBitCount <= 8) {
    01506                 cjColor = cjColorV5 = (1 << lpDib->biBitCount) * sizeof(RGBQUAD);
    01507             } else {
    01508                 cjColor = cjColorV5 = 0;
    01509             }
    01510         }
    01511
    01512     } else if (lpDib->biCompression == BI_RLE4) {
    01513
    01514         cjColor = cjColorV5 = 16 * sizeof(DWORD);
    01515
    01516     } else if (lpDib->biCompression == BI_RLE8) {
    01517
    01518         cjColor = cjColorV5 = 256 * sizeof(DWORD);
    01519
    01520     } else {
    01521
    01522         cjColor = cjColorV5 = 0;
    01523
    01524     }
    01525
    01526     if (cbSize < sizeof(BITMAPINFOHEADER) + cjColorV5 + cjBits) {
    01527         RIPMSG5(RIP_WARNING, "DIBtoDIBV5: buffer %d too small for bitmap %d Header"
    01528                              " %d cjColorV5 %d cjBits %d",
    01529                 cbSize,
    01530                 sizeof(BITMAPINFOHEADER) + cjColorV5 + cjBits,
    01531                 sizeof(BITMAPINFOHEADER),
    01532                 cjColorV5,
    01533                 cjBits);
    01534         return NULL;
    01535     }
    01536
    01537     /*
    01538      * Allocate memory for BITMAPV5HEADER
    01539      */
    01540     lpV5h = (LPBITMAPV5HEADER)UserAllocPool(sizeof(BITMAPV5HEADER) + cjColorV5 + cjBits,
    01541                                             TAG_CLIPBOARD);
    01542
    01543     if (lpV5h == NULL)
    01544         return NULL;
    01545
    01546     /*
    01547      * fill allocated memory with zero.
    01548      */
    01549     RtlZeroMemory((PVOID)lpV5h,sizeof(BITMAPV5HEADER));
    01550
    01551     try {
    01552
    01553         /*
    01554          * Copy BITMAPINFOHEADER to BITMAPV5HEADER
    01555          */
    01556         RtlCopyMemory((PVOID)lpV5h,(PVOID)lpDib,sizeof(BITMAPINFOHEADER));
    01557
    01558     } except (W32ExceptionHandler(FALSE, RIP_ERROR)) {
    01559         UserFreePool(lpV5h);
    01560         return NULL;
    01561     }
    01562
    01563     /*
    01564      * Adjust the header size to BITMAPV5HEADER.
    01565      */
    01566     lpV5h->bV5Size = sizeof(BITMAPV5HEADER);
    01567
    01568     /*
    01569      * Bitmap is in sRGB color space.
    01570      */
    01571     lpV5h->bV5CSType = LCS_sRGB;
    01572
    01573     /*
    01574      * Set rendering intent.
    01575      */
    01576     lpV5h->bV5Intent = LCS_GM_IMAGES;
    01577
    01578     if (bBitMasks) {
    01579
    01580         /*
    01581          * If there is bitfields mask, copy it to BITMAPV5HEADER.
    01582          */
    01583         lpV5h->bV5RedMask = *(DWORD *)&(((BITMAPINFO *)lpDib)->bmiColors[0]);
    01584         lpV5h->bV5GreenMask = *(DWORD *)&(((BITMAPINFO *)lpDib)->bmiColors[1]);
    01585         lpV5h->bV5BlueMask = *(DWORD *)&(((BITMAPINFO *)lpDib)->bmiColors[2]);
    01586
    01587     } else {
    01588
    01589         /*
    01590          * Otherwise, copy color table if there is.
    01591          */
    01592         if (cjColorV5) {
    01593             RtlCopyMemory((BYTE *)lpV5h + sizeof(BITMAPV5HEADER),
    01594                           (BYTE *)lpDib + sizeof(BITMAPINFOHEADER),
    01595                           cjColorV5);
    01596         }
    01597     }
    01598
    01599     /*
    01600      * Copy bitmap bits
    01601      */
    01602     RtlCopyMemory((BYTE *)lpV5h + sizeof(BITMAPV5HEADER) + cjColorV5,
    01603                   (BYTE *)lpDib + sizeof(BITMAPINFOHEADER) + cjColorV5,
    01604                   cjBits);
    01605
    01606     return lpV5h;
    01607 }
    01608
    01609 /***************************************************************************\
    01610 * BMPtoDIBV5
    01611 *
    01612 * History:
    01613 * 18-Dec-1997 HideyukN  Created.
    01614 \***************************************************************************/
    01615
    01616 LPBITMAPV5HEADER BMPtoDIBV5(
    01617     HBITMAP  hbmp,
    01618     HPALETTE hpal)
    01619 {
    01620     LPBITMAPV5HEADER   lpV5h;
    01621     LPBITMAPINFOHEADER lpbih;
    01622     DWORD              cbSize;
    01623
    01624     /*
    01625      * Convert bitmap handle to BITMAPINFOHEADER first.
    01626      */
    01627     lpbih = BMPtoDIB(hbmp, hpal, &cbSize);
    01628
    01629     if (lpbih) {
    01630
    01631         /*
    01632          * Then, convert BITMAPINFOHEADER to BITMAPV5HEADER.
    01633          */
    01634         lpV5h = DIBtoDIBV5(lpbih, cbSize);
    01635
    01636         /*
    01637          * Free memory which contains BITMAPINFOHEADER temporary.
    01638          */
    01639         UserFreePool(lpbih);
    01640
    01641         return (lpV5h);
    01642     } else {
    01643
    01644         RIPMSG0(RIP_ERROR,"Failed on BMPtoDIB(), Why ??");
    01645         return NULL;
    01646     }
    01647 }
    01648
    01649 /***************************************************************************\
    01650 * xxxGetDummyBitmap
    01651 *
    01652 * Returns a real-bitmap from a dummy-format.
    01653 *
    01654 * History:
    01655 * 24-Oct-1995 ChrisWil  Created.
    01656 \***************************************************************************/
    01657
    01658 HANDLE xxxGetDummyBitmap(
    01659     PWINDOWSTATION pwinsta,
    01660     PGETCLIPBDATA  pgcd)
    01661 {
    01662     HANDLE             hData = NULL;
    01663     PCLIPDATA          pData;
    01664     HBITMAP            hBitmap;
    01665     LPBITMAPINFOHEADER lpbih;
    01666     ULONG              cjBitmap;
    01667     HPALETTE           hPal = NULL;
    01668
    01669     PCLIP              pClipT;
    01670
    01671     /*
    01672      * If palette display, then first attempt to get the palette
    01673      * for this bitmap.
    01674      */
    01675     if (TEST_PUSIF(PUSIF_PALETTEDISPLAY)) {
    01676         hPal = xxxGetClipboardData(pwinsta, CF_PALETTE, pgcd);
    01677     }
    01678
    01679     /*
    01680      * The convertion priority is CF_DIBV5 and then CF_DIB,
    01681      * so, check we have CF_DIBV5 first.
    01682      */
    01683     pClipT = FindClipFormat(pwinsta, CF_DIBV5);
    01684     if (pClipT && (pClipT->hData != DUMMY_DIB_HANDLE)) {
    01685
    01686         /*
    01687          * Ok, we have *real* CF_DIBV5 data, At this moment, just
    01688          * go back to client side, then create bitmap handle for
    01689          * CF_BITMAP. Since color conversion only can do it on
    01690          * user-mode.
    01691          */
    01692         if (hData = xxxGetClipboardData(pwinsta, CF_DIBV5, pgcd)) {
    01693
    01694             /*
    01695              * Return the type of the returned data.
    01696              * Again, convertion will happen in client side.
    01697              */
    01698             pgcd->uFmtRet  = CF_DIBV5;
    01699             pgcd->hPalette = hPal;
    01700
    01701             return (hData);
    01702         }
    01703     }
    01704
    01705     /*
    01706      * If the bitmap is a dummy, then we have a problem.  We can't
    01707      * retrieve a bitmap if we only have dummys to work with.
    01708      */
    01709     pClipT = FindClipFormat(pwinsta, CF_DIB);
    01710     if (pClipT && (pClipT->hData != DUMMY_DIB_HANDLE)) {
    01711         hData = xxxGetClipboardData(pwinsta, CF_DIB, pgcd);
    01712
    01713     }
    01714     if (hData == NULL)
    01715         return NULL;
    01716
    01717     /*
    01718      * Since dibs (memory-handles) are stored in a special
    01719      * format (size,base,data), we need to offet the pointer
    01720      * to the right offset (2 uints).
    01721      */
    01722     if (pData = (PCLIPDATA)HMValidateHandleNoRip(hData, TYPE_CLIPDATA)) {
    01723         lpbih = (LPBITMAPINFOHEADER)&pData->abData;
    01724         cjBitmap = pData->cbData;
    01725     } else {
    01726         UserAssert(pData != NULL);
    01727         return NULL;
    01728     }
    01729
    01730     /*
    01731      * Convert the dib to a bitmap.
    01732      */
    01733     /*
    01734      * The buffer size for bitmap should be larger than
    01735      * bitmap header + color table + bitmap bits data.
    01736      */
    01737     if ((cjBitmap >= sizeof(BITMAPCOREHEADER)) &&
    01738         (cjBitmap >= (GreGetBitmapSize((CONST BITMAPINFO *)lpbih,DIB_RGB_COLORS) +
    01739                       GreGetBitmapBitsSize((CONST BITMAPINFO *)lpbih)))) {
    01740
    01741         if (hBitmap = DIBtoBMP(lpbih, hPal)) {
    01742             /*
    01743              * Once, we create *real* bitmap, overwrite dummy handle.
    01744              */
    01745
    01746             pClipT = FindClipFormat(pwinsta, CF_BITMAP);
    01747             if (pClipT) {
    01748                 UT_FreeCBFormat(pClipT);
    01749                 pClipT->hData = hBitmap;
    01750                 GreSetBitmapOwner(hBitmap, OBJECT_OWNER_PUBLIC);
    01751
    01752                 /*
    01753                  * Let callee know we can obtain CF_BITMAP
    01754                  */
    01755                 pgcd->uFmtRet = CF_BITMAP;
    01756             } else {
    01757                 /*
    01758                  * Bleh -- now we can't find the BITMAP entry anymore.  Bail.
    01759                  */
    01760                 RIPMSG0(RIP_WARNING,
    01761                       "Clipboard: CF_BITMAP format not available");
    01762                 GreDeleteObject(hBitmap);
    01763                 hBitmap = NULL;
    01764             }
    01765         }
    01766         return (HANDLE)hBitmap;
    01767     } else {
    01768         RIPMSG0(RIP_WARNING, "GetClipboardData, bad DIB format\n");
    01769         return NULL;
    01770     }
    01771
    01772 }
    01773
    01774 /***************************************************************************\
    01775 * xxxGetDummyDib
    01776 *
    01777 * Returns a real-dib (in special clipboard-handle format) from a
    01778 * dummy format.
    01779 *
    01780 * History:
    01781 * 24-Oct-1995 ChrisWil  Created.
    01782 \***************************************************************************/
    01783
    01784 HANDLE xxxGetDummyDib(
    01785     PWINDOWSTATION pwinsta,
    01786     PGETCLIPBDATA  pgcd)
    01787 {
    01788     HANDLE             hData = NULL;
    01789     HBITMAP            hBitmap = NULL;
    01790     LPBITMAPINFOHEADER lpDib;
    01791     HANDLE             hDib;
    01792     HPALETTE           hPal = NULL;
    01793
    01794     PCLIP              pClipT;
    01795
    01796     /*
    01797      * If palette display, then first attempt to get the palette
    01798      * for this bitmap.  For palette devices, we must have a palette.
    01799      */
    01800     if (TEST_PUSIF(PUSIF_PALETTEDISPLAY)) {
    01801         hPal = xxxGetClipboardData(pwinsta, CF_PALETTE, pgcd);
    01802
    01803         if (hPal == NULL)
    01804             return NULL;
    01805     }
    01806
    01807     /*
    01808      * The convertion priority is CF_DIBV5 and then CF_BITMAP,
    01809      * so, check we have CF_DIBV5 first.
    01810      */
    01811     pClipT = FindClipFormat(pwinsta, CF_DIBV5);
    01812     if (pClipT && (pClipT->hData != DUMMY_DIB_HANDLE)) {
    01813
    01814         /*
    01815          * Ok, we have *real* CF_DIBV5 data, At this moment, just
    01816          * go back to client side, then create bitmap data for
    01817          * CF_DIB. Since color conversion only can do it on
    01818          * user-mode.
    01819          */
    01820         if (hData = xxxGetClipboardData(pwinsta, CF_DIBV5, pgcd)) {
    01821
    01822             /*
    01823              * Return the type of the returned data.
    01824              * Again, convertion will happen in client side.
    01825              */
    01826             pgcd->uFmtRet  = CF_DIBV5;
    01827             pgcd->hPalette = hPal;
    01828
    01829             return (hData);
    01830         }
    01831     }
    01832
    01833     /*
    01834      * Get the real-bitmap.  We must have one in order to convert
    01835      * to the dib.  If there's no bitmap, then we have something
    01836      * wrong.
    01837      */
    01838     pClipT = FindClipFormat(pwinsta, CF_BITMAP);
    01839     if (pClipT && (pClipT->hData != DUMMY_DIB_HANDLE)) {
    01840         hBitmap = xxxGetClipboardData(pwinsta, CF_BITMAP, pgcd);
    01841     }
    01842
    01843     if (hBitmap == NULL) {
    01844         return NULL;
    01845     }
    01846
    01847     /*
    01848      * Convert the bitmap to a dib-spec.
    01849      */
    01850     hDib = NULL;
    01851     if (lpDib = BMPtoDIB(hBitmap, hPal, NULL)) {
    01852
    01853         DWORD cbData = SizeOfDib(lpDib);;
    01854
    01855         /*
    01856          * Convert the dib-spec to the special-clipboard
    01857          * memory-handle (size,base,data).  This so
    01858          * the client is able to convert properly when
    01859          * handled a dib.
    01860          */
    01861         hDib = _ConvertMemHandle((LPBYTE)lpDib, cbData);
    01862         UserFreePool(lpDib);
    01863
    01864         if (hDib != NULL) {
    01865             /*
    01866              * Once, we create *real* bitmap, overwrite dummy handle.
    01867              */
    01868
    01869             pClipT = FindClipFormat(pwinsta, CF_DIB);
    01870             if (pClipT) {
    01871                 UT_FreeCBFormat(pClipT);
    01872                 pClipT->hData = hDib;
    01873
    01874                 /*
    01875                  * Let callee know we can obtain CF_DIB
    01876                  */
    01877                 pgcd->uFmtRet = CF_DIB;
    01878             } else {
    01879                 PVOID pObj;
    01880                 /*
    01881                  * Bleh -- now we can't find the DIB entry anymore.  Bail.
    01882                  */
    01883                 RIPMSG0(RIP_WARNING,
    01884                       "Clipboard: CF_PDIB format not available");
    01885                 pObj = HMValidateHandleNoRip(hDib, TYPE_CLIPDATA);
    01886                 if (pObj) {
    01887                     HMFreeObject(pObj);
    01888                 }
    01889                 hDib = NULL;
    01890             }
    01891         }
    01892     }
    01893
    01894     return hDib;
    01895 }
    01896
    01897 /***************************************************************************\
    01898 * xxxGetDummyDibV5
    01899 *
    01900 * Returns a real-dib (in special clipboard-handle format) from a
    01901 * dummy format.
    01902 *
    01903 * History:
    01904 * 18-Dec-1997 HideyukN  Created.
    01905 \***************************************************************************/
    01906
    01907 HANDLE xxxGetDummyDibV5(
    01908     PWINDOWSTATION pwinsta,
    01909     PGETCLIPBDATA  pgcd)
    01910 {
    01911     HANDLE             hData;
    01912     PCLIPDATA          pData;
    01913     LPBITMAPV5HEADER   lpDibV5 = NULL;
    01914     HANDLE             hDibV5 = NULL;
    01915
    01916     PCLIP              pClipT;
    01917
    01918     /*
    01919      * The convertion priority is CF_DIB and then CF_BITMAP,
    01920      * so, check we have CF_DIB first.
    01921      */
    01922     pClipT = FindClipFormat(pwinsta, CF_DIB);
    01923     if (pClipT && (pClipT->hData != DUMMY_DIB_HANDLE)) {
    01924
    01925         /*
    01926          * Ok, we have *real* CF_DIB data, get it.
    01927          */
    01928         if (hData = xxxGetClipboardData(pwinsta, CF_DIB, pgcd)) {
    01929
    01930             /*
    01931              * Since dibs (memory-handles) are stored in a special
    01932              * format (size,base,data), we need to offet the pointer
    01933              * to the right offset (2 uints).
    01934              */
    01935             if (pData = (PCLIPDATA)HMValidateHandleNoRip(hData, TYPE_CLIPDATA)) {
    01936
    01937                 LPBITMAPINFOHEADER lpDib = (LPBITMAPINFOHEADER)&pData->abData;
    01938
    01939                 /*
    01940                  * Convert the BITMAPINFOHEADER to BITMAPV5HEADER.
    01941                  */
    01942                 lpDibV5 = DIBtoDIBV5(lpDib, pData->cbData);
    01943
    01944             } else {
    01945                 UserAssert(pData != NULL);
    01946             }
    01947         }
    01948     }
    01949
    01950     if (lpDibV5 == NULL) {
    01951
    01952         /*
    01953          * Try CF_BITMAP, here
    01954          */
    01955         pClipT = FindClipFormat(pwinsta, CF_BITMAP);
    01956         if ((pClipT) &&
    01957             (pClipT->hData != DUMMY_DIB_HANDLE) &&
    01958             (hData = xxxGetClipboardData(pwinsta, CF_BITMAP, pgcd))) {
    01959
    01960             HPALETTE hPal = NULL;
    01961
    01962             /*
    01963              * If palette display, then first attempt to get the palette
    01964              * for this bitmap.  For palette devices, we must have a palette.
    01965              */
    01966             if (TEST_PUSIF(PUSIF_PALETTEDISPLAY)) {
    01967
    01968                 hPal = xxxGetClipboardData(pwinsta, CF_PALETTE, pgcd);
    01969
    01970                 if (hPal == NULL)
    01971                     return NULL;
    01972             }
    01973
    01974             /*
    01975              * hData is GDI bitmap handle, Convert the bitmap to a dib-spec.
    01976              */
    01977             lpDibV5 = BMPtoDIBV5((HBITMAP)hData, hPal);
    01978         }
    01979     }
    01980
    01981     if (lpDibV5 != NULL) {
    01982
    01983         DWORD cbData = SizeOfDib((LPBITMAPINFOHEADER)lpDibV5);
    01984
    01985         /*
    01986          * Convert the dib-spec to the special-clipboard
    01987          * memory-handle (size,base,data).  This so
    01988          * the client is able to convert properly when
    01989          * handled a dib.
    01990          */
    01991         hDibV5 = _ConvertMemHandle((LPBYTE)lpDibV5, cbData);
    01992         UserFreePool(lpDibV5);
    01993
    01994         if (hDibV5 != NULL) {
    01995
    01996             /*
    01997              * Once, we create *real* bitmap, overwrite dummy handle.
    01998              */
    01999
    02000             pClipT = FindClipFormat(pwinsta, CF_DIBV5);
    02001             if (pClipT) {
    02002                 UT_FreeCBFormat(pClipT);
    02003                 pClipT->hData = hDibV5;
    02004
    02005                 /*
    02006                  * Let callee know we can obtain CF_DIBV5
    02007                  */
    02008                 pgcd->uFmtRet = CF_DIBV5;
    02009             } else {
    02010                 PVOID pObj;
    02011                 /*
    02012                  * Bleh -- now we can't find the DIB entry anymore.  Bail.
    02013                  */
    02014                 RIPMSG0(RIP_WARNING,
    02015                       "Clipboard: CF_DIBV5 format not available");
    02016                 pObj = HMValidateHandleNoRip(hDibV5, TYPE_CLIPDATA);
    02017                 if (pObj) {
    02018                     HMFreeObject(pObj);
    02019                 }
    02020                 hDibV5 = NULL;
    02021             }
    02022         }
    02023     }
    02024
    02025     return hDibV5;
    02026 }
    02027
    02028 /***************************************************************************\
    02029 * CreateDIBPalette
    02030 *
    02031 * This creates a palette with PC_NOCOLLAPSE entries since we require the
    02032 * palette-entries and bitmap-indexes to map exactly.  Otherwise, we could
    02033 * end up selecting a palette where a color collapses to an index not
    02034 * where the bitmap thinks it is.  This would cause slower drawing since
    02035 * the Blt would go through color translation.
    02036 *
    02037 * History:
    02038 * 31-Jan-1992 MikeKe    From win31
    02039 \***************************************************************************/
    02040
    02041 HPALETTE CreateDIBPalette(
    02042    LPBITMAPINFOHEADER pbmih,
    02043    UINT               colors)
    02044 {
    02045     HPALETTE hpal;
    02046
    02047     if (colors != 0) {
    02048
    02049         int         i;
    02050         BOOL        fOldDIB = (pbmih->biSize == sizeof(BITMAPCOREHEADER));
    02051         RGBTRIPLE   *pColorTable;
    02052         PLOGPALETTE plp;
    02053
    02054         /*
    02055          * Allocate memory for palette creation.
    02056          */
    02057         plp = (PLOGPALETTE)UserAllocPoolWithQuota(sizeof(LOGPALETTE) +
    02058                                                   (sizeof(PALETTEENTRY) * 256),
    02059                                                   TAG_CLIPBOARDPALETTE);
    02060
    02061         if (plp == NULL) {
    02062             return NULL;
    02063         }
    02064
    02065         pColorTable = (RGBTRIPLE *)((LPSTR)pbmih + (WORD)pbmih->biSize);
    02066         plp->palVersion = 0x300;
    02067
    02068         if (fOldDIB || (pbmih->biClrUsed == 0)) {
    02069             UserAssert(colors <= 0xFFFF);
    02070             plp->palNumEntries = (WORD)colors;
    02071         } else {
    02072             UserAssert(pbmih->biClrUsed <= 0xFFFF);
    02073             plp->palNumEntries = (WORD)pbmih->biClrUsed;
    02074         }
    02075
    02076         for (i = 0; i < (int)(plp->palNumEntries); i++) {
    02077
    02078             plp->palPalEntry[i].peRed   = pColorTable->rgbtRed;
    02079             plp->palPalEntry[i].peGreen = pColorTable->rgbtGreen;
    02080             plp->palPalEntry[i].peBlue  = pColorTable->rgbtBlue;
    02081             plp->palPalEntry[i].peFlags = (BYTE)PC_NOCOLLAPSE;
    02082
    02083             if (fOldDIB) {
    02084                 pColorTable++;
    02085             } else {
    02086                 pColorTable = (RGBTRIPLE *)((LPSTR)pColorTable+sizeof(RGBQUAD));
    02087             }
    02088         }
    02089
    02090         hpal = GreCreatePalette((LPLOGPALETTE)plp);
    02091         UserFreePool(plp);
    02092
    02093     } else {
    02094         hpal = GreCreateHalftonePalette(HDCBITS());
    02095     }
    02096
    02097     GreSetPaletteOwner(hpal, OBJECT_OWNER_PUBLIC);
    02098
    02099     return hpal;
    02100 }
    02101
    02102 /***************************************************************************\
    02103 * xxxGetDummyPalette
    02104 *
    02105 * Returns a real-palette from a dummy-format.  Derives it from a real-dib.
    02106 *
    02107 * History:
    02108 * 24-Oct-1995 ChrisWil  Created.
    02109 \***************************************************************************/
    02110
    02111 HANDLE xxxGetDummyPalette(
    02112     PWINDOWSTATION pwinsta,
    02113     PGETCLIPBDATA  pgcd)
    02114 {
    02115     HANDLE             hData;
    02116     PCLIPDATA          pData;
    02117     LPBITMAPINFOHEADER lpbih;
    02118     HPALETTE           hPal;
    02119
    02120     PCLIP              pClipT;
    02121
    02122     /*
    02123      * Since CF_DIBV5 has higher priority than CF_DIB, so look into
    02124      * CF_DIBV5 first, to find DIB palette.
    02125      */
    02126     UINT               uFmt = CF_DIBV5;
    02127
    02128     if ((pClipT = FindClipFormat(pwinsta, uFmt)) != NULL)
    02129     {
    02130         if (pClipT->hData != DUMMY_DIB_HANDLE) {
    02131
    02132             /*
    02133              * Ok, we have real CF_DIBV5, let extract palette from DIBV5.
    02134              */
    02135         } else {
    02136
    02137             /*
    02138              * Otherwise, try CF_DIB.
    02139              */
    02140             uFmt = CF_DIB;
    02141         }
    02142     }
    02143
    02144     /*
    02145      * Get the DIB by which we derive the palette.  If the DIB comes
    02146      * back as a dummy, then there's something wrong.  Me must have
    02147      * a real dib at this point.
    02148      */
    02149     hData = (HANDLE)xxxGetClipboardData(pwinsta, uFmt, pgcd);
    02150     UserAssert(hData > DUMMY_MAX_HANDLE);
    02151
    02152     if (hData == NULL)
    02153         return NULL;
    02154
    02155     /*
    02156      * Since dibs (memory-handles) are stored in a special
    02157      * format (size,base,data), we need to offet the pointer
    02158      * to the right offset (2 uints).
    02159      */
    02160     if (pData = (PCLIPDATA)HMValidateHandle(hData, TYPE_CLIPDATA)) {
    02161         lpbih = (LPBITMAPINFOHEADER)&pData->abData;
    02162     } else {
    02163         UserAssert(pData != NULL);
    02164         return NULL;
    02165     }
    02166
    02167     if ((pClipT = FindClipFormat(pwinsta, CF_PALETTE)) == NULL) {
    02168         RIPMSG0(RIP_WARNING,
    02169               "Clipboard: CF_PALETTE format not available");
    02170         return NULL;
    02171     }
    02172
    02173     /*
    02174      * Note -- if CreateDIBPalette ever changes to leave the crit sect,
    02175      * we will need to move the above FindClipFormat to after the create
    02176      * call and deal with gracefully freeing hPal on failure.  pClipT
    02177      * can change during callbacks.
    02178      */
    02179
    02180     hPal = CreateDIBPalette(lpbih, lpbih->biClrUsed);
    02181
    02182     if (hPal != NULL) {
    02183         UT_FreeCBFormat(pClipT);
    02184         pClipT->hData = hPal;
    02185         GreSetPaletteOwner(hPal, OBJECT_OWNER_PUBLIC);
    02186     }
    02187
    02188     return (HANDLE)hPal;
    02189 }
    02190
    02191 /***************************************************************************\
    02192 * xxxGetDummyText
    02193 *
    02194 * Returns a handle to text from a dummy-format.
    02195 *
    02196 * History:
    02197 * 24-Oct-1995 ChrisWil  Created.
    02198 \***************************************************************************/
    02199
    02200 HANDLE xxxGetDummyText(
    02201     PWINDOWSTATION pwinsta,
    02202     UINT           fmt,
    02203     PGETCLIPBDATA  pgcd)
    02204 {
    02205     HANDLE hText;
    02206     PCLIP  pClipT;
    02207     UINT   uFmtMain;
    02208     UINT   uFmtAlt;
    02209     BOOL  bMain = TRUE;
    02210
    02211     /*
    02212      * Get the handle of the other text format available.
    02213      */
    02214     switch (fmt) {
    02215     case CF_TEXT:
    02216         uFmtMain = CF_UNICODETEXT;
    02217         uFmtAlt  = CF_OEMTEXT;
    02218         goto GetRealText;
    02219
    02220     case CF_OEMTEXT:
    02221         uFmtMain = CF_UNICODETEXT;
    02222         uFmtAlt  = CF_TEXT;
    02223         goto GetRealText;
    02224
    02225     case CF_UNICODETEXT:
    02226         uFmtMain = CF_TEXT;
    02227         uFmtAlt  = CF_OEMTEXT;
    02228
    02229 GetRealText:
    02230
    02231         if ((pClipT = FindClipFormat(pwinsta, uFmtMain)) == NULL)
    02232             return NULL;
    02233
    02234         if (pClipT->hData != DUMMY_TEXT_HANDLE) {
    02235
    02236             if (xxxGetClipboardData(pwinsta, uFmtMain, pgcd))
    02237                 break;
    02238
    02239             return NULL;
    02240         }
    02241
    02242         if ((pClipT = FindClipFormat(pwinsta, uFmtAlt)) == NULL)
    02243             return NULL;
    02244
    02245         if (pClipT->hData != DUMMY_TEXT_HANDLE) {
    02246             bMain = FALSE;
    02247
    02248             if (xxxGetClipboardData(pwinsta, uFmtAlt, pgcd))
    02249                 break;
    02250         }
    02251
    02252         /*
    02253          * Fall through to return a dummy handle.
    02254          */
    02255
    02256     default:
    02257         return NULL;
    02258     }
    02259
    02260     /*
    02261      * Since xxxGetClipboardData leaves the critsect, we need to
    02262      * reacquire pClipT.
    02263      */
    02264
    02265     pClipT = FindClipFormat(pwinsta, bMain? uFmtMain:uFmtAlt);
    02266
    02267     if (pClipT == NULL) {
    02268         RIPMSG1(RIP_WARNING,
    02269               "Clipboard: GetDummyText, format 0x%lX not available", bMain? uFmtMain:uFmtAlt);
    02270         return NULL;
    02271     }
    02272
    02273     /*
    02274      * Return the type of the returned data.
    02275      */
    02276     pgcd->uFmtRet = pClipT->fmt;
    02277     hText         = pClipT->hData;
    02278
    02279     /*
    02280      * Set the locale, since the text will need to be
    02281      * converted to another format.
    02282      */
    02283     if(pClipT = FindClipFormat(pwinsta, CF_LOCALE)) {
    02284         pgcd->hLocale = pClipT->hData;
    02285     } else {
    02286         pgcd->hLocale = NULL;
    02287     }
    02288
    02289     return hText;
    02290 }
    02291
    02292 /***************************************************************************\
    02293 * xxxGetRenderData
    02294 *
    02295 * Returns a handle to delayed rendered data.  This requires a call to the
    02296 * client to supply the data.  This causes us to regenerate our pointer
    02297 * to pClip.
    02298 *
    02299 * History:
    02300 * 24-Oct-1995 ChrisWil  Created.
    02301 \***************************************************************************/
    02302
    02303 HANDLE xxxGetRenderData(
    02304     PWINDOWSTATION pwinsta,
    02305     UINT           fmt)
    02306 {
    02307     BOOL   fClipboardChangedOld;
    02308     TL     tlpwndClipOwner;
    02309     PCLIP          pClip;
    02310
    02311     /*
    02312      * If the handle is NULL, the data is delay rendered.  This means
    02313      * we send a message to the current clipboard owner and have
    02314      * it render the data for us.
    02315      */
    02316     if (pwinsta->spwndClipOwner != NULL) {
    02317
    02318         /*
    02319          * Preserve the pwinsta->fClipboardChanged flag before SendMessage
    02320          * and restore the flag later; Thus we ignore the changes
    02321          * done to the pwinsta->fClipboardChanged flag by apps while
    02322          * rendering data in the delayed rendering scheme; This
    02323          * avoids clipboard viewers from painting twice.
    02324          */
    02325         fClipboardChangedOld = pwinsta->fClipboardChanged;
    02326         pwinsta->fInDelayedRendering = TRUE;
    02327         ThreadLockAlways(pwinsta->spwndClipOwner, &tlpwndClipOwner);
    02328         xxxSendMessage(pwinsta->spwndClipOwner, WM_RENDERFORMAT, fmt, 0L);
    02329         ThreadUnlock(&tlpwndClipOwner);
    02330         pwinsta->fClipboardChanged = fClipboardChangedOld;
    02331         pwinsta->fInDelayedRendering = FALSE;
    02332
    02333     }
    02334
    02335     if ((pClip = FindClipFormat(pwinsta, fmt)) == NULL) {
    02336         RIPMSG1(RIP_WARNING,
    02337               "Clipboard: Meta Render/Clone format 0x%lX not available", fmt);
    02338         return NULL;
    02339     }
    02340     /*
    02341      * We should have the handle now since it has been rendered.
    02342      */
    02343     return pClip->hData;
    02344 }
    02345
    02346 /***************************************************************************\
    02347 * xxxGetClipboardData (API)
    02348 *
    02349 * Grabs a particular data object out of the clipboard.
    02350 *
    02351 * History:
    02352 * 18-Nov-1990 ScottLu   Ported from Win3.
    02353 * 20-Aug-1991 EichiM    UNICODE enabling
    02354 \***************************************************************************/
    02355
    02356 HANDLE xxxGetClipboardData(
    02357     PWINDOWSTATION pwinsta,
    02358     UINT           fmt,
    02359     PGETCLIPBDATA  pgcd)
    02360 {
    02361     PCLIP  pClip;
    02362     HANDLE hData;
    02363
    02364     /*
    02365      * Check the clipboard owner.
    02366      */
    02367     if (pwinsta->ptiClipLock != PtiCurrent()) {
    02368         RIPERR0(ERROR_CLIPBOARD_NOT_OPEN, RIP_VERBOSE, "GetClipboardData: clipboard not open");
    02369         return NULL;
    02370     }
    02371
    02372     /*
    02373      * Make sure the format is available.
    02374      */
    02375     if ((pClip = FindClipFormat(pwinsta, fmt)) == NULL) {
    02376         RIPMSG1(RIP_VERBOSE, "Clipboard: Requested format 0x%lX not available", fmt);
    02377         return NULL;
    02378     }
    02379
    02380     /*
    02381      * If this is a DUMMY_META*_HANDLE it means that the other
    02382      * metafile format was set in as a delay render format and we should
    02383      * as for that format to get the metafile because the app has not told
    02384      * us they now about this format.
    02385      */
    02386     if (IsMetaDummyHandle(pClip->hData)) {
    02387
    02388         if (fmt == CF_ENHMETAFILE) {
    02389             fmt = CF_METAFILEPICT;
    02390         } else if (fmt == CF_METAFILEPICT) {
    02391             fmt = CF_ENHMETAFILE;
    02392         } else {
    02393             RIPMSG0(RIP_WARNING,
    02394                   "Clipboard: Meta Render/Clone expects a metafile type");
    02395         }
    02396
    02397         if ((pClip = FindClipFormat(pwinsta, fmt)) == NULL) {
    02398             RIPMSG1(RIP_WARNING,
    02399                   "Clipboard: Meta Render/Clone format 0x%lX not available", fmt);
    02400             return NULL;
    02401         }
    02402     }
    02403
    02404     /*
    02405      * This is the data we're returning, unless it's a dummy or
    02406      * render handle.
    02407      */
    02408     hData = pClip->hData;
    02409
    02410     /*
    02411      * We are dealing with non-handles.  Retrieve the real data
    02412      * through these inline-routines.  NOTE: these make recursive
    02413      * calls to xxxGetClipboardData().  So care must be taken to
    02414      * assure the pClip is pointing to what we think it's pointing
    02415      * to.
    02416      */
    02417     if ((hData == NULL) || (hData == DUMMY_METARENDER_HANDLE)) {
    02418
    02419         hData = xxxGetRenderData(pwinsta, fmt);
    02420
    02421     } else if (hData == DUMMY_DIB_HANDLE) {
    02422
    02423         switch (fmt) {
    02424         case CF_DIB:
    02425             hData = xxxGetDummyDib(pwinsta, pgcd);
    02426             break;
    02427         case CF_DIBV5:
    02428             hData = xxxGetDummyDibV5(pwinsta, pgcd);
    02429             break;
    02430         case CF_BITMAP:
    02431             hData = xxxGetDummyBitmap(pwinsta, pgcd);
    02432             break;
    02433         case CF_PALETTE:
    02434             hData = xxxGetDummyPalette(pwinsta, pgcd);
    02435             break;
    02436         }
    02437
    02438     } else if (hData == DUMMY_TEXT_HANDLE) {
    02439
    02440         hData = xxxGetDummyText(pwinsta, fmt, pgcd);
    02441     } else {
    02442         /*
    02443          * This path took no callbacks, so we know pClip is OK.
    02444          */
    02445         if (pgcd)
    02446             pgcd->fGlobalHandle = pClip->fGlobalHandle;
    02447
    02448         return hData;
    02449     }
    02450
    02451     /*
    02452      * The callbacks for dummy handle resolution have possibly
    02453      * invalidated pClip -- recreate it.
    02454      */
    02455
    02456     if ((pClip = FindClipFormat(pwinsta, fmt)) == NULL) {
    02457         RIPMSG1(RIP_VERBOSE, "Clipboard: Requested format 0x%lX not available", fmt);
    02458         return NULL;
    02459     }
    02460
    02461     /*
    02462      * Return if this is a global-handle.
    02463      */
    02464     if (pgcd)
    02465         pgcd->fGlobalHandle = pClip->fGlobalHandle;
    02466
    02467     return hData;
    02468 }
    02469
    02470 /***************************************************************************\
    02471 * FindClipFormat
    02472 *
    02473 * Finds a particular clipboard format in the clipboard, returns a pointer
    02474 * to it, or NULL. If a pointer is found, on return the clipboard is locked
    02475 * and pwinsta->pClipBase has been updated to point to the beginning of the
    02476 * clipboard.
    02477 *
    02478 * History:
    02479 * 18-Nov-1990 ScottLu   Ported from Win3.
    02480 \***************************************************************************/
    02481
    02482 PCLIP FindClipFormat(
    02483     PWINDOWSTATION pwinsta,
    02484     UINT           format)
    02485 {
    02486     PCLIP pClip;
    02487     int   iFmt;
    02488
    02489     if ((format != 0) && ((pClip = pwinsta->pClipBase) != NULL)) {
    02490
    02491         for (iFmt = pwinsta->cNumClipFormats; iFmt-- != 0;) {
    02492
    02493             if (pClip->fmt == format)
    02494                 return pClip;
    02495
    02496             pClip++;
    02497         }
    02498     }
    02499
    02500     return NULL;
    02501 }
    02502
    02503 /***************************************************************************\
    02504 * _GetPriorityClipboardFormat (API)
    02505 *
    02506 * This api allows an application to look for any one of a range of
    02507 * clipboard formats in a predefined search order.
    02508 *
    02509 * History:
    02510 * 18-Nov-1990 ScottLu   Ported from Win3.
    02511 * 11-Feb-1991 JimA      Added access checks.
    02512 \***************************************************************************/
    02513
    02514 int _GetPriorityClipboardFormat(
    02515     PUINT lpPriorityList,
    02516     int   cfmts)
    02517 {
    02518     PWINDOWSTATION pwinsta;
    02519     PCLIP          pClip;
    02520     int            iFmt;
    02521     UINT           fmt;
    02522
    02523     /*
    02524      * Blow it off is the caller does not have the proper access rights
    02525      */
    02526     if ((pwinsta = CheckClipboardAccess()) == NULL)
    02527         return 0;
    02528
    02529     /*
    02530      * If there is no clipboard or no objects in the clipboard, return 0.
    02531      */
    02532     if ((pwinsta->cNumClipFormats == 0) || (pwinsta->pClipBase == NULL))
    02533         return 0;
    02534
    02535     /*
    02536      * Look through the list for any of the formats in lpPriorityList.
    02537      */
    02538     while (cfmts-- > 0) {
    02539
    02540         fmt = *lpPriorityList;
    02541
    02542         if (fmt != 0) {
    02543
    02544             pClip = pwinsta->pClipBase;
    02545
    02546             for (iFmt = pwinsta->cNumClipFormats; iFmt-- != 0; pClip++) {
    02547
    02548                 if (pClip->fmt == fmt)
    02549                     return fmt;
    02550             }
    02551         }
    02552
    02553         lpPriorityList++;
    02554     }
    02555
    02556     /*
    02557      * There is no matching format.  Return -1.
    02558      */
    02559     return -1;
    02560 }
    02561
    02562 /***************************************************************************\
    02563 * xxxSetClipboardViewer (API)
    02564 *
    02565 * Sets the clipboard viewer window.
    02566 *
    02567 * History:
    02568 * 18-Nov-1990 ScottLu   Ported from Win3.
    02569 * 11-Feb-1991 JimA      Added access checks.
    02570 \***************************************************************************/
    02571
    02572 PWND xxxSetClipboardViewer(
    02573     PWND pwndClipViewerNew)
    02574 {
    02575     TL             tlpwinsta;
    02576     PWINDOWSTATION pwinsta;
    02577     HWND           hwndClipViewerOld;
    02578     PTHREADINFO    ptiCurrent;
    02579
    02580     CheckLock(pwndClipViewerNew);
    02581
    02582     /*
    02583      * Blow it off is the caller does not have the proper access rights.
    02584      * The NULL return really doesn't indicate an error but the
    02585      * supposed viewer will never receive any clipboard messages, so
    02586      * it shouldn't cause any problems.
    02587      */
    02588     if ((pwinsta = CheckClipboardAccess()) == NULL)
    02589         return NULL;
    02590
    02591     ptiCurrent = PtiCurrent();
    02592
    02593     ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
    02594
    02595     hwndClipViewerOld = HW(pwinsta->spwndClipViewer);
    02596     Lock(&pwinsta->spwndClipViewer, pwndClipViewerNew);
    02597
    02598     xxxDrawClipboard(pwinsta);
    02599
    02600     ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
    02601
    02602     if (hwndClipViewerOld != NULL)
    02603         return RevalidateHwnd(hwndClipViewerOld);
    02604
    02605     return NULL;
    02606 }
    02607
    02608 /***************************************************************************\
    02609 * xxxChangeClipboardChain (API)
    02610 *
    02611 * Changes the clipboard viewer chain.
    02612 *
    02613 * History:
    02614 * 18-Nov-1990 ScottLu   Ported from Win3.
    02615 * 11-Feb-1991 JimA      Added access checks.
    02616 \***************************************************************************/
    02617
    02618 BOOL xxxChangeClipboardChain(
    02619     PWND pwndRemove,
    02620     PWND pwndNewNext)
    02621 {
    02622     TL             tlpwinsta;
    02623     PWINDOWSTATION pwinsta;
    02624     BOOL           result;
    02625     TL             tlpwndClipViewer;
    02626     PTHREADINFO    ptiCurrent;
    02627
    02628     CheckLock(pwndRemove);
    02629     CheckLock(pwndNewNext);
    02630
    02631     /*
    02632      * Blow it off is the caller does not have the proper access rights.
    02633      */
    02634     if ((pwinsta = CheckClipboardAccess()) == NULL)
    02635         return FALSE;
    02636
    02637     /*
    02638      * pwndRemove should be this thread's window, pwndNewNext will
    02639      * either be NULL or another thread's window.
    02640      */
    02641     ptiCurrent = PtiCurrent();
    02642
    02643     if (GETPTI(pwndRemove) != ptiCurrent) {
    02644         RIPMSG0(RIP_WARNING, "Clipboard: ChangeClipboardChain will not remove cross threads");
    02645         return FALSE;
    02646     }
    02647
    02648     if (pwinsta->spwndClipViewer == NULL) {
    02649         RIPMSG0(RIP_WARNING, "Clipboard: ChangeClipboardChain has no viewer window");
    02650         return FALSE;
    02651     }
    02652
    02653     ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
    02654
    02655     if (pwndRemove == pwinsta->spwndClipViewer) {
    02656
    02657         Lock(&pwinsta->spwndClipViewer, pwndNewNext);
    02658         result = TRUE;
    02659
    02660     } else {
    02661
    02662         ThreadLockAlways(pwinsta->spwndClipViewer, &tlpwndClipViewer);
    02663         result = (BOOL)xxxSendMessage(pwinsta->spwndClipViewer,
    02664                                       WM_CHANGECBCHAIN,
    02665                                       (WPARAM)HW(pwndRemove),
    02666                                       (LPARAM)HW(pwndNewNext));
    02667         ThreadUnlock(&tlpwndClipViewer);
    02668     }
    02669
    02670     ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
    02671
    02672     return result;
    02673 }
    02674
    02675 /***************************************************************************\
    02676 * DisownClipboard
    02677 *
    02678 * Disowns the clipboard so someone else can grab it.
    02679 *
    02680 * pwndClipOwner is the pwnd that is the reason for disowning the clipboard
    02681 * when that window is deleted
    02682 *
    02683 * History:
    02684 * 18-Jun-1991 DarrinM   Ported from Win3.
    02685 \***************************************************************************/
    02686
    02687 VOID DisownClipboard(PWND pwndClipOwner)
    02688 {
    02689     TL             tlpwinsta;
    02690     PWINDOWSTATION pwinsta;
    02691     int            iFmt;
    02692     int            cFmts;
    02693     PCLIP          pClip;
    02694     PCLIP          pClipOut;
    02695     BOOL           fKeepDummyHandle;
    02696     PTHREADINFO    ptiCurrent;
    02697
    02698     if ((pwinsta = CheckClipboardAccess()) == NULL)
    02699         return;
    02700
    02701     ptiCurrent = PtiCurrent();
    02702
    02703     ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
    02704
    02705     xxxSendClipboardMessage(pwinsta, WM_RENDERALLFORMATS);
    02706
    02707     pClipOut = pClip = pwinsta->pClipBase;
    02708     fKeepDummyHandle = FALSE;
    02709
    02710     for (cFmts = 0, iFmt = pwinsta->cNumClipFormats; iFmt-- != 0;) {
    02711
    02712         /*
    02713          * We have to remove the Dummy handles also if the corresponding
    02714          * valid handles are NULL; We should not remove the dummy handles if
    02715          * the corresponding valid handles are not NULL;
    02716          * The following code assumes that only one dummy handle is possible
    02717          * and that can appear only after the corresponding valid handle in
    02718          * the pClip linked list;
    02719          * Fix for Bug #???? --SANKAR-- 10-19-89 --OPUS BUG #3252--
    02720          */
    02721         if (pClip->hData != NULL) {
    02722
    02723             if ((pClip->hData != DUMMY_TEXT_HANDLE) ||
    02724                 ((pClip->hData == DUMMY_TEXT_HANDLE) && fKeepDummyHandle)) {
    02725
    02726                 cFmts++;
    02727                 *pClipOut++ = *pClip;
    02728
    02729                 if (IsTextHandle(pClip->fmt, pClip->hData)) {
    02730                     fKeepDummyHandle  = TRUE;
    02731                 }
    02732             }
    02733         }
    02734
    02735         pClip++;
    02736     }
    02737
    02738     /*
    02739      * Unlock the clipboard owner if the owner is still the window we were cleaning
    02740      * up for.
    02741      */
    02742     if (pwndClipOwner == pwinsta->spwndClipOwner) {
    02743         Unlock(&pwinsta->spwndClipOwner);
    02744     } else {
    02745         RIPMSG2(RIP_WARNING, "DisownClipboard: pwndClipOwner changed from %#p to %#p",
    02746                 pwndClipOwner, pwinsta->spwndClipOwner);
    02747     }
    02748
    02749     /*
    02750      * If number of formats changed, redraw.
    02751      */
    02752     if (cFmts != pwinsta->cNumClipFormats) {
    02753         pwinsta->fClipboardChanged = TRUE;
    02754         pwinsta->iClipSequenceNumber++;
    02755     }
    02756
    02757     pwinsta->cNumClipFormats = cFmts;
    02758
    02759     /*
    02760      * If anything changed, redraw.  And make sure the data type munging is done.  Or else we will lose
    02761      * them when xxxDrawClipboard clears the fClipboardChanged flag
    02762      */
    02763     if (pwinsta->fClipboardChanged) {
    02764         xxxDrawClipboard(pwinsta);
    02765         MungeClipData(pwinsta);
    02766     }
    02767
    02768     ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
    02769 }
    02770
    02771 /***************************************************************************\
    02772 * ForceEmptyClipboard
    02773 *
    02774 * We're logging off. Force the clipboard contents to go away.
    02775 *
    02776 * 23-Jul-1992 ScottLu   Created.
    02777 \***************************************************************************/
    02778
    02779 VOID ForceEmptyClipboard(
    02780     PWINDOWSTATION pwinsta)
    02781 {
    02782
    02783     pwinsta->ptiClipLock =  ((PTHREADINFO)(W32GetCurrentThread())); /*
    02784                                                                      * This will be NULL
    02785                                                                      *   for a non-GUI thread.
    02786                                                                      */
    02787     Unlock(&pwinsta->spwndClipOwner);
    02788     Unlock(&pwinsta->spwndClipViewer);
    02789     Unlock(&pwinsta->spwndClipOpen);
    02790
    02791     xxxEmptyClipboard(pwinsta);
    02792
    02793     /*
    02794      * If the windowstation is dying, don't bother closing
    02795      * the clipboard.
    02796      */
    02797     if (!(pwinsta->dwWSF_Flags & WSF_DYING))
    02798         xxxCloseClipboard(pwinsta);
    02799 }