#include "private.h" #include "globals.h" #include "osver.h" #include "transmit.h" #include "cmydc.h" #define MAXFILEMAPSIZE 0x1000 #define DATA_MARKER 0x0001 #define HANDLE_MARKER 0x0002 #define IS_DATA_MARKER( x) (x == DATA_MARKER) #define IS_HANDLE_MARKER( x) (x == HANDLE_MARKER) #define GDI_DATA_PASSING() (IsOnNT()) #define POINTER_CAST(x) *(x **)& #define ICON_DATA_PASSING() (IsOnNT()) //+--------------------------------------------------------------------------- // // GetIconBitmaps // //---------------------------------------------------------------------------- BOOL Cic_GetIconBitmaps(HICON hIcon, HBITMAP *phbmp, HBITMAP *phbmpMask, SIZE *psize) { CBitmapDC hdcSrc(TRUE); CBitmapDC hdcMask(TRUE); SIZE size; size = *psize; hdcSrc.SetDIB(size.cx, size.cy); hdcMask.SetBitmap(size.cx, size.cy, 1, 1); RECT rc = {0, 0, size.cx, size.cy}; FillRect(hdcSrc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); DrawIconEx(hdcSrc, 0, 0, hIcon, size.cx, size.cy, 0, NULL, DI_NORMAL); DrawIconEx(hdcMask, 0, 0, hIcon, size.cx, size.cy, 0, NULL, DI_MASK); *phbmp = hdcSrc.GetBitmapAndKeep(); *phbmpMask = hdcMask.GetBitmapAndKeep(); return TRUE; } //+--------------------------------------------------------------------------- // // CreateDIB // //---------------------------------------------------------------------------- HBITMAP CreateDIB(int cx, int cy, int nWidthByte, BYTE *pMyBits, ULONG_PTR nBitsSize) { CBitmapDC hdc(TRUE); HBITMAP hBmp; BITMAPINFO bi = {0}; bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = cx; bi.bmiHeader.biHeight = cy; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; BYTE *pDibBits; hBmp = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&pDibBits, NULL, 0); if (hBmp) { int y; for (y = 0; y < cy; y++) { int nyDibBites = (cy - y - 1) * nWidthByte; int nyMyBites = y * nWidthByte; memcpy(&pDibBits[nyDibBites], &pMyBits[nyMyBites], nWidthByte); } } return hBmp; } //+--------------------------------------------------------------------------- // // MARSHAL_HDR // //---------------------------------------------------------------------------- template struct MARSHAL_HDR { DWORD dwDataType; CAlignWinHandle h; }; // ######################################################################### // // HBITMAP // See transmit.h for explanation of gdi data/handle passing. // // ######################################################################### struct BITMAP_WOW64 { // Identical BITMAP structure. LONG bmType; LONG bmWidth; LONG bmHeight; LONG bmWidthBytes; WORD bmPlanes; WORD bmBitsPixel; CAlignPointer bmBits; void operator = (BITMAP& a) { bmType = a.bmType; bmWidth = a.bmWidth; bmHeight = a.bmHeight; bmWidthBytes = a.bmWidthBytes; bmPlanes = a.bmPlanes; bmBitsPixel = a.bmBitsPixel; bmBits = a.bmBits; } void operator = (int a) { memset(this, a, sizeof(BITMAP_WOW64)); } }; struct MARSHAL_HBITMAP { MARSHAL_HDR hdr; MARSHAL_HDR hdr_2; struct { DWORD dwCount; BITMAP_WOW64 bm; } bitmap_1; struct { DWORD dwCount; BITMAP_WOW64 bm; } bitmap_2; BYTE bits[1]; }; //+------------------------------------------------------------------------- // // UserSize // //-------------------------------------------------------------------------- ULONG Cic_HBITMAP_UserSize (HBITMAP *pHBitmap, HBITMAP *pHBitmap_2) { ULONG Offset = 0; if ( !pHBitmap ) return 0; BITMAP bm, bm_2; HBITMAP hBitmap, hBitmap_2; hBitmap = *pHBitmap; hBitmap_2 = pHBitmap_2 ? *pHBitmap_2 : NULL; memset(&bm, 0, sizeof(BITMAP)); memset(&bm_2, 0, sizeof(BITMAP)); // // The encapsulated union. // Discriminant and then handle or pointer from the union arm. // Union discriminant is 4 bytes + handle is represented by a long. // if ( GDI_DATA_PASSING() ) { Offset += sizeof(struct MARSHAL_HBITMAP); if (hBitmap) { // Get information about the bitmap if (!GetObject(hBitmap, sizeof(BITMAP), &bm)) return 0; Offset += (bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes); } if (hBitmap_2) { // Get information about the bitmap if (!GetObject(hBitmap_2, sizeof(BITMAP), &bm_2)) return 0; Offset += (bm_2.bmPlanes * bm_2.bmHeight * bm_2.bmWidthBytes); } Offset = Align( Offset ); } else { if (pHBitmap) Offset += Align( sizeof(struct MARSHAL_HDR) ); if (pHBitmap_2) Offset += Align( sizeof(struct MARSHAL_HDR) ); } return( Offset ) ; } //+------------------------------------------------------------------------- // // HBITMAP_UserMarshall // //-------------------------------------------------------------------------- BYTE *Cic_HBITMAP_UserMarshal(BYTE *pBuffer, BYTE *pBufferEnd, HBITMAP *pHBitmap, HBITMAP *pHBitmap_2) { if ( !pHBitmap ) return pBuffer; // Discriminant of the encapsulated union and union arm. struct MARSHAL_HBITMAP* pdata = (struct MARSHAL_HBITMAP*) pBuffer; if ( GDI_DATA_PASSING() ) { if (!pHBitmap) { pdata->hdr.dwDataType = 0; pdata->hdr.h = NULL; } else { pdata->hdr.dwDataType = DATA_MARKER; pdata->hdr.h = *pHBitmap; } if (!pHBitmap_2) { pdata->hdr_2.dwDataType = 0; pdata->hdr_2.h = NULL; } else { pdata->hdr_2.dwDataType = DATA_MARKER; pdata->hdr_2.h = *pHBitmap_2; } // // Get information about the bitmap // BITMAP bm, bm_2; HBITMAP hBitmap = *pHBitmap; HBITMAP hBitmap_2 = pHBitmap_2 ? *pHBitmap_2 : NULL; // // Bitmap object 1 // if (!hBitmap) { pdata->bitmap_1.bm = 0; pdata->bitmap_1.dwCount = 0; } else { if (!GetObject(hBitmap, sizeof(BITMAP), &bm)) return pBuffer + Align( sizeof(struct MARSHAL_HDR) ); pdata->bitmap_1.dwCount = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes; // // Get the bm structure fields. // pdata->bitmap_1.bm = bm; } // // Bitmap object 2 // if (!hBitmap_2) { pdata->bitmap_2.bm = 0; pdata->bitmap_2.dwCount = 0; } else { if (!GetObject(hBitmap_2, sizeof(BITMAP), &bm_2)) return pBuffer + Align( sizeof(struct MARSHAL_HDR) ); pdata->bitmap_2.dwCount = bm_2.bmPlanes * bm_2.bmHeight * bm_2.bmWidthBytes; pdata->bitmap_2.bm = bm_2; } // // Get the raw bits. // if (hBitmap) { BYTE *pbTemp = pdata->bits; if (pbTemp + pdata->bitmap_1.dwCount > pBufferEnd) { Assert(0); pdata->bitmap_1.bm = 0; pdata->bitmap_1.dwCount = 0; } else { GetBitmapBits( hBitmap, pdata->bitmap_1.dwCount, pdata->bits ); } } if (hBitmap_2) { BYTE *pbTemp = &pdata->bits[pdata->bitmap_1.dwCount]; if (pbTemp + pdata->bitmap_2.dwCount > pBufferEnd) { Assert(0); pdata->bitmap_2.bm = 0; pdata->bitmap_2.dwCount = 0; } else { GetBitmapBits( hBitmap_2, pdata->bitmap_2.dwCount, &pdata->bits[pdata->bitmap_1.dwCount]); } } pBuffer += Align( sizeof(struct MARSHAL_HBITMAP) + pdata->bitmap_1.dwCount + pdata->bitmap_2.dwCount); } else { // Sending a handle. pdata->hdr.dwDataType = 0; pdata->hdr.h = NULL; pdata->hdr_2.dwDataType = 0; pdata->hdr_2.h = NULL; if (pHBitmap) { pdata->hdr.dwDataType = HANDLE_MARKER; pdata->hdr.h = *pHBitmap; pBuffer += Align( sizeof(struct MARSHAL_HDR) ); } if (pHBitmap_2) { pdata->hdr_2.dwDataType = HANDLE_MARKER; pdata->hdr_2.h = *pHBitmap_2; pBuffer += Align( sizeof(struct MARSHAL_HDR) ); } } return( pBuffer ); } //+------------------------------------------------------------------------- // // HBITMAP_UserUnmarshallWorker // //-------------------------------------------------------------------------- BYTE *Cic_HBITMAP_UserUnmarshal(BYTE *pBuffer, HBITMAP *pHBitmap, HBITMAP *pHBitmap_2) { HBITMAP hBitmap, hBitmap_2; // Get Discriminant and handle. Caller checked for EOB. struct MARSHAL_HBITMAP* pdata = (struct MARSHAL_HBITMAP*) pBuffer; DWORD UnionDisc = pdata->hdr.dwDataType; hBitmap = pdata->hdr.h; if (!hBitmap) { if (!pHBitmap_2) { *pHBitmap = NULL; return pBuffer; } UnionDisc = pdata->hdr_2.dwDataType; } hBitmap_2 = pdata->hdr_2.h ? (HBITMAP)pdata->hdr_2.h : NULL; if ( IS_DATA_MARKER( UnionDisc) ) { ULONG_PTR dwCount = 0; ULONG_PTR dwCount_2 = 0; if ( hBitmap ) { dwCount = pdata->bitmap_1.dwCount; // verify dwCount matches the bitmap. if ( dwCount != (DWORD) pdata->bitmap_1.bm.bmPlanes * pdata->bitmap_1.bm.bmHeight * pdata->bitmap_1.bm.bmWidthBytes ) { Assert(0); return NULL; } // Create a bitmap based on the BITMAP structure and the raw bits in // the transmission buffer if (pdata->bitmap_1.bm.bmBitsPixel == 0x20) hBitmap = CreateDIB( pdata->bitmap_1.bm.bmWidth, pdata->bitmap_1.bm.bmHeight, pdata->bitmap_1.bm.bmWidthBytes, pdata->bits, dwCount); else hBitmap = CreateBitmap( pdata->bitmap_1.bm.bmWidth, pdata->bitmap_1.bm.bmHeight, pdata->bitmap_1.bm.bmPlanes, pdata->bitmap_1.bm.bmBitsPixel, pdata->bits); } if (hBitmap_2) { dwCount_2 = pdata->bitmap_2.dwCount; // verify dwCount_2 matches the bitmap. if ( dwCount_2 != (DWORD) pdata->bitmap_2.bm.bmPlanes * pdata->bitmap_2.bm.bmHeight * pdata->bitmap_2.bm.bmWidthBytes ) { Assert(0); return NULL; } // Create a bitmap based on the BITMAP structure and the raw bits in // the transmission buffer if (pdata->bitmap_2.bm.bmBitsPixel == 0x20) hBitmap_2 = CreateDIB( pdata->bitmap_2.bm.bmWidth, pdata->bitmap_2.bm.bmHeight, pdata->bitmap_2.bm.bmWidthBytes, &pdata->bits[dwCount], dwCount_2); else hBitmap_2 = CreateBitmap( pdata->bitmap_2.bm.bmWidth, pdata->bitmap_2.bm.bmHeight, pdata->bitmap_2.bm.bmPlanes, pdata->bitmap_2.bm.bmBitsPixel, &pdata->bits[dwCount]); } pBuffer += Align( sizeof(struct MARSHAL_HBITMAP) + dwCount + dwCount_2 ); } else if ( !IS_HANDLE_MARKER( UnionDisc ) ) { Assert(0); } // A new bitmap handle is ready, destroy the old one, if needed. if ( *pHBitmap ) DeleteObject( *pHBitmap ); *pHBitmap = hBitmap; if ( pHBitmap_2 ) { if ( *pHBitmap_2 ) DeleteObject( *pHBitmap_2 ); *pHBitmap_2 = hBitmap_2; } return( pBuffer ); } //+------------------------------------------------------------------------- // // HBITMAP_UserFree // //-------------------------------------------------------------------------- void Cic_HBITMAP_UserFree(HBITMAP *pHBitmap, HBITMAP *pHBitmap_2) { if( pHBitmap && *pHBitmap ) { if ( GDI_DATA_PASSING() ) { DeleteObject( *pHBitmap ); } } if( pHBitmap_2 && *pHBitmap_2 ) { if ( GDI_DATA_PASSING() ) { DeleteObject( *pHBitmap_2 ); } } } ////////////////////////////////////////////////////////////////////////////// // // TF_LBBALLOON // ////////////////////////////////////////////////////////////////////////////// //+------------------------------------------------------------------------- // // UserSize // //-------------------------------------------------------------------------- ULONG Cic_TF_LBBALLOONINFO_UserSize(TF_LBBALLOONINFO *pInfo) { ULONG ulRet; ulRet = sizeof(TF_LBBALLOONINFO); LENGTH_ALIGN(ulRet, CIC_ALIGNMENT); if (pInfo->bstrText) ulRet += (SysStringByteLen(pInfo->bstrText) + 2); else ulRet += 2; LENGTH_ALIGN(ulRet, CIC_ALIGNMENT); return ulRet; } //+------------------------------------------------------------------------- // // UserMarshal // //-------------------------------------------------------------------------- BYTE *Cic_TF_LBBALLOONINFO_UserMarshal(BYTE *pBuf, TF_LBBALLOONINFO *pInfo) { if (!pInfo) return pBuf; memcpy(pBuf, pInfo, sizeof(TF_LBBALLOONINFO)); pBuf += sizeof(TF_LBBALLOONINFO); POINTER_ALIGN( pBuf, CIC_ALIGNMENT); if (pInfo->bstrText) wcscpy((WCHAR *)pBuf, pInfo->bstrText); pBuf += ((pInfo->bstrText ? wcslen(pInfo->bstrText) : 0) + 2); POINTER_ALIGN( pBuf, CIC_ALIGNMENT); return pBuf; } //+------------------------------------------------------------------------- // // UserUnMarshal // //-------------------------------------------------------------------------- HRESULT Cic_TF_LBBALLOONINFO_UserUnmarshal(BYTE *pBuf, TF_LBBALLOONINFO *pInfo) { HRESULT hr;; if (!pInfo) return S_OK; hr = S_OK; memcpy(pInfo, pBuf, sizeof(TF_LBBALLOONINFO)); if (pInfo->bstrText) { BYTE *pTmp = pBuf + sizeof(TF_LBBALLOONINFO); POINTER_ALIGN( pTmp, CIC_ALIGNMENT); pInfo->bstrText = SysAllocString((WCHAR *)pTmp); hr = (pInfo->bstrText != NULL) ? S_OK : E_OUTOFMEMORY; } return hr; } //+------------------------------------------------------------------------- // // UserFree // //-------------------------------------------------------------------------- void Cic_TF_LBBALLOONINFO_UserFree(TF_LBBALLOONINFO *pInfo) { if (pInfo->bstrText) { SysFreeString(pInfo->bstrText); pInfo->bstrText = NULL; } } // ######################################################################### // // HICON // See transmit.h for explanation of gdi data/handle passing. // // ######################################################################### struct ICONINFO_WOW64 { // Identical ICONINFO structure. BOOL fIcon; DWORD xHotspot; DWORD yHotspot; CAlignWinHandle hbmMask; CAlignWinHandle hbmColor; void operator = (ICONINFO& a) { fIcon = a.fIcon; xHotspot = a.xHotspot; yHotspot = a.yHotspot; hbmMask = a.hbmMask; hbmColor = a.hbmColor; } }; struct MARSHAL_HICON { MARSHAL_HDR hdr; ICONINFO_WOW64 ic; MARSHAL_HBITMAP bm; }; //+------------------------------------------------------------------------- // // UserSize // //-------------------------------------------------------------------------- ULONG Cic_HICON_UserSize (HICON *pHIcon) { ULONG Offset = 0; if ( !pHIcon ) return 0; HICON hIcon = *pHIcon; // // The encapsulated union. // Discriminant and then handle or pointer from the union arm. // Union discriminant is 4 bytes + handle is represented by a long. // if ( ! *pHIcon ) return Align( sizeof(struct MARSHAL_HDR) ); if ( ICON_DATA_PASSING() ) { ICONINFO IconInfo; ULONG ulBmpUserSize = 0; if (!GetIconInfo(hIcon, &IconInfo)) return 0; Offset += Align( sizeof(struct MARSHAL_HICON) ); // // On NT4, CreateBitmap() can not create different device type // bitmap. We convert the dc bitmap by calling DrawIconEx(). // // We may want to use DIB section to marshal but marshaling and // unmarshaling happens in same device so it does not have to // convert bitmaps to DIB. // if (!IsOnNT5()) { HBITMAP hbmp = NULL; HBITMAP hbmpMask = NULL; SIZE size; BITMAP bmp; if (!GetObject( IconInfo.hbmColor, sizeof(bmp), &bmp )) { Offset = 0; goto DeleteAndExit; } size.cx = bmp.bmWidth; size.cy = bmp.bmHeight; Cic_GetIconBitmaps(*pHIcon, &hbmp, &hbmpMask, &size); ulBmpUserSize = Cic_HBITMAP_UserSize(&hbmp, &hbmpMask); if (!ulBmpUserSize) { Offset = 0; goto DeleteAndExit; } Offset += ulBmpUserSize; Offset = Align( Offset ); DeleteAndExit: if (hbmp) DeleteObject(hbmp); if (hbmpMask) DeleteObject(hbmpMask); } else { ulBmpUserSize = Cic_HBITMAP_UserSize(&IconInfo.hbmColor, &IconInfo.hbmMask); if (!ulBmpUserSize) { Offset = 0; goto Exit; } Offset += ulBmpUserSize; Offset = Align( Offset ); } Exit: if (IconInfo.hbmColor) DeleteObject(IconInfo.hbmColor); if (IconInfo.hbmMask) DeleteObject(IconInfo.hbmMask); } else { Offset += Align( sizeof(struct MARSHAL_HDR) ); } return( Offset ) ; } //+------------------------------------------------------------------------- // // HICON_UserMarshall // //-------------------------------------------------------------------------- BYTE *Cic_HICON_UserMarshal(BYTE *pBuffer, BYTE *pBufferEnd, HICON *pHIcon) { if ( !pHIcon ) return pBuffer; // Discriminant of the encapsulated union and union arm. struct MARSHAL_HICON* pdata = (struct MARSHAL_HICON*) pBuffer; if ( ICON_DATA_PASSING() ) { pdata->hdr.dwDataType = DATA_MARKER; pdata->hdr.h = *pHIcon; if ( ! *pHIcon ) return pBuffer + Align( sizeof(struct MARSHAL_HDR) ); // // Get information about the bitmap // ICONINFO IconInfo; if (!GetIconInfo(*pHIcon, &IconInfo)) memset(&IconInfo, 0, sizeof(IconInfo)); // // Get the ic structure fields. // pdata->ic = IconInfo; // // On NT4, CreateBitmap() can not create different device type // bitmap. We convert the dc bitmap by calling DrawIconEx(). // // We may want to use DIB section to marshal but marshaling and // unmarshaling happens in same device so it does not have to // convert bitmaps to DIB. // if (!IsOnNT5()) { HBITMAP hbmp = NULL; HBITMAP hbmpMask = NULL; SIZE size; BITMAP bmp; GetObject( IconInfo.hbmColor, sizeof(bmp), &bmp ); size.cx = bmp.bmWidth; size.cy = bmp.bmHeight; Cic_GetIconBitmaps(*pHIcon, &hbmp, &hbmpMask, &size); pBuffer = Cic_HBITMAP_UserMarshal((BYTE*) &pdata->bm, pBufferEnd, &hbmp, &hbmpMask); if (hbmp) DeleteObject(hbmp); if (hbmpMask) DeleteObject(hbmpMask); } else { pBuffer = Cic_HBITMAP_UserMarshal((BYTE*) &pdata->bm, pBufferEnd, &IconInfo.hbmColor, &IconInfo.hbmMask); } if (IconInfo.hbmColor) DeleteObject(IconInfo.hbmColor); if (IconInfo.hbmColor) DeleteObject(IconInfo.hbmMask); } else { // // we need to make sure this pointer of the Icon is // not a resource. // HICON hIcon = CopyIcon(*pHIcon); if (hIcon) DestroyIcon(*pHIcon); else hIcon = *pHIcon; // Sending a handle. pdata->hdr.dwDataType = HANDLE_MARKER; pdata->hdr.h = hIcon; pBuffer += Align( sizeof(struct MARSHAL_HDR) ); } return( pBuffer ); } //+------------------------------------------------------------------------- // // HICON_UserUnmarshallWorker // //-------------------------------------------------------------------------- BYTE *Cic_HICON_UserUnmarshal(BYTE *pBuffer, HICON *pHIcon) { HICON hIcon = NULL; // Get Discriminant and handle. Caller checked for EOB. struct MARSHAL_HICON* pdata = (struct MARSHAL_HICON*) pBuffer; DWORD UnionDisc = pdata->hdr.dwDataType; hIcon = pdata->hdr.h; if ( IS_DATA_MARKER( UnionDisc) ) { if ( hIcon ) { ICONINFO IconInfo; IconInfo.fIcon = pdata->ic.fIcon; IconInfo.xHotspot = pdata->ic.xHotspot; IconInfo.yHotspot = pdata->ic.yHotspot; IconInfo.hbmMask = pdata->ic.hbmMask; IconInfo.hbmColor = pdata->ic.hbmColor; // // We just get the bitmap handle from marshaling buffer. // And the marshaling buffer does not have a valid bitmap handle. // IconInfo.hbmColor = NULL; IconInfo.hbmMask = NULL; pBuffer = Cic_HBITMAP_UserUnmarshal((BYTE*) &pdata->bm, &IconInfo.hbmColor, &IconInfo.hbmMask); if (pBuffer) { hIcon = CreateIconIndirect(&IconInfo); } if (IconInfo.hbmColor) DeleteObject(IconInfo.hbmColor); if (IconInfo.hbmMask) DeleteObject(IconInfo.hbmMask); } } else if ( !IS_HANDLE_MARKER( UnionDisc ) ) { Assert(0); } // A new bitmap handle is ready, destroy the old one, if needed. if ( *pHIcon ) DestroyIcon( *pHIcon ); *pHIcon = hIcon; return( pBuffer ); } //+------------------------------------------------------------------------- // // HICON_UserFree // //-------------------------------------------------------------------------- void Cic_HICON_UserFree(HICON *pHIcon) { if( pHIcon && *pHIcon ) { if ( ICON_DATA_PASSING() ) { DestroyIcon( *pHIcon ); } } }