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 }

Generated on Sat May 15 19:39:25 2004 for test by doxygen 1.3.7