Hi guys,

We've created patch for common pasteboard for the Additions.

If the host is MacOSX and guest is Windows, the picture from Mac to the guest paste buffer comes as BMP with DIB header version 3, and this picture puts to buffer also with DIB header version 3. Some applications, for example Paint, are able to work with this format, but some, for example Wordpad and IBM Lotus Notes - don't and crashes. There was no solution for now.

Despite Windows documentation about formats and its automatic conversion, really its work only with DIB header version 1 (BITMAPINFOHEADER)
and field biHeight must be positive.

Therefore we are changing header and coordinate axes orientation and flipping the image so that it was not inverted.

We modified VBoxClipboard.cpp. We were used VirtualBox-4.2.12 guests for tests.

Author: Sibers/HireRussians LLC <[email protected]>
License: Patch is under MIT License

----------------------------------
Sergey Staroletov
Senior UNIX C++ developer
Sibers (HireRussians/former Key-Soft Ltd.)
131a132,228
> static HANDLE vboxRgbDibToDibV1(HANDLE dibHandle)
> {
>     PBITMAPINFOHEADER dibHeaderData = NULL;
>     void *dibRawData = 0;
> 
>     bool changeOrientation = false;
>     bool changeHeader = false;
> 
>     HANDLE dibv1Handle = NULL;
>     void *dibv1Data = NULL;
>     PBITMAPINFOHEADER dibv1Header = NULL;
> 
>     DWORD oldHeaderSize = 0;
>     LONG width;
>     LONG height;
>     SIZE_T rawDataLineSize = 0;
>     SIZE_T rawDataLinePadding = 0;
> 
>     if(dibHandle == NULL){
>         return dibHandle;
>     }
> 
>     dibHeaderData = static_cast<PBITMAPINFOHEADER>(GlobalLock(dibHandle));
> 
>     if(dibHeaderData == NULL){
>         return dibHandle;
>     }
> 
>     if((dibHeaderData->biCompression != BI_RGB) && 
> (dibHeaderData->biCompression != BI_BITFIELDS)){
>         //Leave compressed images as is
>         //BI_BITFIELDS can be added too (with some work)
>         return dibHandle;
>     }
> 
>     if((height = dibHeaderData->biHeight) < 0){
>         changeOrientation = true;
>         height *= -1;
>     }
> 
>     if(dibHeaderData->biSize != sizeof(BITMAPINFOHEADER)){
>         changeHeader = true;
>     }
> 
>     if( (!changeOrientation) && (!changeHeader) ){
>         return dibHandle;
>     }
> 
>     if( (dibHeaderData->biBitCount < 8)
>         || ((width = dibHeaderData->biWidth) <= 0) || 
> (dibHeaderData->biHeight == 0) ){
>         return dibHandle;
>     }
> 
>     rawDataLineSize = (dibHeaderData->biBitCount/8)*(dibHeaderData->biWidth);
> 
>     if((rawDataLinePadding = (rawDataLineSize%4)) > 0){
>         rawDataLineSize += 4 - rawDataLinePadding;
>     }
> 
>     dibv1Handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 
> sizeof(BITMAPINFOHEADER) + rawDataLineSize*height);
> 
>     if(dibv1Handle == NULL){
>         return dibHandle;
>     }
> 
>     dibv1Data = GlobalLock(dibv1Handle);
> 
>     if(dibv1Data == NULL){
>         GlobalFree(dibv1Handle);
>         return dibHandle;
>     }
> 
>     dibv1Header = static_cast<PBITMAPINFOHEADER>(dibv1Data);
> 
>     memcpy((void*)dibv1Header, (void*)dibHeaderData, 
> sizeof(BITMAPINFOHEADER));
>     dibv1Header->biSize = sizeof(BITMAPINFOHEADER);
>     dibv1Header->biHeight = height;
> 
>     if(changeOrientation){
>         char *psIter = (char*)dibHeaderData + dibHeaderData->biSize + 
> rawDataLineSize*(height - 1) ;
>         char *pdIter = (char*)dibv1Data + sizeof(BITMAPINFOHEADER);
>         for(int i = 0; i < height; ++i){
>             memcpy(pdIter, psIter, rawDataLineSize);
>             psIter -= rawDataLineSize;
>             pdIter += rawDataLineSize;
>         }
>     }else{
>         memcpy((void*)((char*)dibv1Data + sizeof(BITMAPINFOHEADER))
>                , (void*)((char*)dibHeaderData + dibHeaderData->biSize)
>                , rawDataLineSize*height);
>     }
> 
>     GlobalUnlock(dibHandle);
>     GlobalUnlock(dibv1Handle);
> 
>     return dibv1Handle;
> }
> 
353c450,457
<                                     HANDLE hClip = SetClipboardData(format, 
hMem);
---
>                                     HANDLE dataMem = hMem;
>                                     if(format == CF_DIB){
>                                         dataMem = vboxRgbDibToDibV1(hMem);
>                                         if(dataMem == NULL){
>                                             dataMem = hMem;
>                                         }
>                                     }
>                                     HANDLE hClip = SetClipboardData(format, 
> dataMem/*hMem*/);
358c462,467
<                                         /* The hMem ownership has gone to the 
system. Finish the processing. */
---
>                                         /* The dataMem ownership has gone to 
> the system. Finish the processing. */
> 
>                                         if(hMem != dataMem){
>                                             //cleanup hMem if new Dib data 
> created
>                                             GlobalFree(hMem);
>                                         }
359a469,473
>                                     }else{
>                                         //Clean up dib dataMem if needed
>                                         if(hMem != dataMem){
>                                             GlobalFree(dataMem);
>                                         }
_______________________________________________
vbox-dev mailing list
[email protected]
https://www.virtualbox.org/mailman/listinfo/vbox-dev

Reply via email to