| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_dtrans.hxx" |
| |
| #define INCL_DOSERRORS |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include <rtl/string.hxx> |
| |
| #include "OTransferable.hxx" |
| #include "globals.hxx" |
| |
| |
| OTransferable::OTransferable( HWND hwndTarget, PDRAGINFO dragInfo) |
| : m_aFlavorList( 1), |
| mHwndTarget( hwndTarget), |
| mDragInfo( dragInfo), |
| removeOnExit( false), |
| pDTShare( NULL), |
| renderDRM( DRM_NULL), |
| mimeType( MIMETYPE_NULL) |
| { |
| USHORT cItems; |
| PDRAGITEM dragItem; |
| PSZ pNativeRMF; |
| |
| strcpy( fullpath, ""); |
| |
| cItems = DrgQueryDragitemCount(dragInfo); |
| if (cItems > 1) { |
| debug_printf("OTransferable::OTransferable multiple drop not supported"); |
| return; |
| } |
| |
| ULONG ulLength; |
| PSZ pBuffer; |
| |
| // get 1st item |
| dragItem = DrgQueryDragitemPtr(dragInfo, 0); |
| |
| // dump true type |
| ulLength = DrgQueryTrueTypeLen( dragItem) + 1; |
| pBuffer = (PSZ) malloc( ulLength); |
| DrgQueryTrueType( dragItem, ulLength, pBuffer); |
| debug_printf("DrgQueryTrueType %s", pBuffer); |
| free( pBuffer); |
| |
| // get native RMF format |
| ulLength = DrgQueryNativeRMFLen( dragItem) + 1; |
| pNativeRMF = (PSZ) malloc( ulLength); |
| DrgQueryNativeRMF( dragItem, ulLength, pNativeRMF); |
| debug_printf("OTransferable::OTransferable DrgQueryNativeRMF %s", pNativeRMF); |
| |
| debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_ATOM %d", DrgVerifyRMF( dragItem, "DRM_ATOM", NULL)); |
| debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_OS2FILE %d", DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL)); |
| debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_PRINTOBJECT %d", DrgVerifyRMF( dragItem, "DRM_PRINTOBJECT", NULL)); |
| debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_SHAREDMEM %d", DrgVerifyRMF( dragItem, "DRM_SHAREDMEM", NULL)); |
| debug_printf("OTransferable::OTransferable DrgVerifyRMF DRM_DTSHARE %d", DrgVerifyRMF( dragItem, "DRM_DTSHARE", NULL)); |
| |
| DataFlavor df; |
| |
| if (strstr( pNativeRMF, "<DRM_ATOM") != 0 |
| || strstr( pNativeRMF, "<DRM_DTSHARE") != 0 |
| || strstr( pNativeRMF, "<DRM_SHAREDMEM") != 0) { |
| |
| df.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" ); |
| df.DataType = getCppuType( static_cast<rtl::OUString*>(0)); |
| m_aFlavorList[0] = df; |
| mimeType = MIMETYPE_TEXT; |
| |
| } else if (strstr( pNativeRMF, "<DRM_OS2FILE") != 0) { |
| |
| df.MimeType = OUString::createFromAscii( |
| "application/x-openoffice-file;windows_formatname=\"FileName\""); |
| df.DataType = getCppuType( static_cast<OUString*>(0)); |
| m_aFlavorList[0] = df; |
| mimeType = MIMETYPE_FILE; |
| |
| } else { |
| |
| mimeType = MIMETYPE_NULL; |
| debug_printf("OTransferable::OTransferable UNKNOWN native RMF"); |
| |
| } |
| |
| free( pNativeRMF); |
| |
| } |
| |
| OTransferable::~OTransferable() |
| { |
| if (removeOnExit) { |
| int rc; |
| rc = unlink( fullpath); |
| debug_printf( "OTransferable::~OTransferable unlink rc=%d", rc); |
| } |
| } |
| |
| |
| // |
| // a generic request dispatcher |
| // |
| bool OTransferable::RequestFileRendering( PDRAGITEM pditem, HWND hwnd, |
| PCSZ pRMF, PCSZ pName) |
| { |
| PDRAGTRANSFER pdxfer; |
| |
| pdxfer = DrgAllocDragtransfer( 1); |
| if (!pdxfer) |
| return true; |
| |
| pdxfer->cb = sizeof(DRAGTRANSFER); |
| pdxfer->hwndClient = hwnd; |
| pdxfer->pditem = pditem; |
| pdxfer->hstrSelectedRMF = DrgAddStrHandle( pRMF); |
| pdxfer->hstrRenderToName = 0; |
| pdxfer->ulTargetInfo = pditem->ulItemID; |
| pdxfer->usOperation = (USHORT)DO_COPY; |
| pdxfer->fsReply = 0; |
| |
| // send the msg before setting a render-to name |
| if (pditem->fsControl & DC_PREPAREITEM) |
| DrgSendTransferMsg( pditem->hwndItem, DM_RENDERPREPARE, (MPARAM)pdxfer, 0); |
| |
| if (pName) |
| pdxfer->hstrRenderToName = DrgAddStrHandle( pName); |
| else |
| pdxfer->hstrRenderToName = 0; |
| |
| // send the msg after setting a render-to name |
| if ((pditem->fsControl & (DC_PREPARE | DC_PREPAREITEM)) == DC_PREPARE) |
| DrgSendTransferMsg( pditem->hwndItem, DM_RENDERPREPARE, (MPARAM)pdxfer, 0); |
| |
| // ask the source to render the selected item |
| if (!DrgSendTransferMsg( pditem->hwndItem, DM_RENDER, (MPARAM)pdxfer, 0)) |
| return true; |
| |
| return false; |
| } |
| |
| // currently, the same filename is used for every render request; |
| // it is deleted when the drag session ends |
| // |
| bool OTransferable::RenderToOS2File( PDRAGITEM pditem, HWND hwnd) |
| { |
| bool rv = true; |
| |
| const char * pszRMF; |
| if (DrgVerifyRMF(pditem, "DRM_OS2FILE", "DRF_TEXT")) |
| pszRMF = OS2FILE_TXTRMF; |
| else |
| pszRMF = OS2FILE_UNKRMF; |
| |
| // create temp name |
| strcpy( fullpath, tempnam( NULL, "AOO")); |
| debug_printf("OTransferable::RenderToOS2File to %s", fullpath); |
| |
| rv = RequestFileRendering( pditem, hwnd, pszRMF, fullpath); |
| |
| return rv; |
| } |
| |
| // DTShare uses 1mb of uncommitted named-shared memory |
| // (next time I'll do it differently - rw) |
| // |
| bool OTransferable::RenderToDTShare( PDRAGITEM pditem, HWND hwnd) |
| { |
| bool rv; |
| |
| APIRET rc = DosAllocSharedMem( &pDTShare, DTSHARE_NAME, 0x100000, |
| PAG_WRITE | PAG_READ | OBJ_ANY); |
| if (rc != NO_ERROR && |
| rc != ERROR_ALREADY_EXISTS) { // Did the kernel handle OBJ_ANY? |
| // Try again without OBJ_ANY and if the first failure was not caused |
| // by OBJ_ANY then we will get the same failure, else we have taken |
| // care of pre-FP13 systems where the kernel couldn't handle it. |
| rc = DosAllocSharedMem( &pDTShare, DTSHARE_NAME, 0x100000, |
| PAG_WRITE | PAG_READ); |
| } |
| |
| if (rc == ERROR_ALREADY_EXISTS) |
| rc = DosGetNamedSharedMem( &pDTShare, DTSHARE_NAME, |
| PAG_WRITE | PAG_READ); |
| if (rc) |
| rv = true; // error |
| else |
| rv = RequestFileRendering( pditem, hwnd, DTSHARE_RMF, DTSHARE_NAME); |
| |
| return rv; |
| } |
| |
| // SharedMem rendering, memory is allocated by source window |
| // |
| bool OTransferable::RenderToSharedMem( PDRAGITEM pditem, HWND hwnd) |
| { |
| bool rv; |
| |
| rv = RequestFileRendering( pditem, hwnd, SHAREDMEM_RMF, NULL); |
| |
| return rv; |
| } |
| |
| bool OTransferable::requestRendering( void) |
| { |
| char path[CCHMAXPATH]; |
| char file[CCHMAXPATH]; |
| PDRAGITEM dragItem; |
| |
| // unknown rendering |
| renderDRM = DRM_NULL; |
| |
| // only 1st item supported |
| dragItem = DrgQueryDragitemPtr( mDragInfo, 0); |
| |
| // check if we already have all necessary fields or a rendering |
| // request must be sent to source window |
| |
| switch( mimeType) { |
| case MIMETYPE_NULL: |
| debug_printf("OTransferable::requestRendering INTERNAL ERROR, mimetype undef"); |
| break; |
| |
| case MIMETYPE_FILE: |
| if (DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL) |
| && dragItem->hstrSourceName == NULLHANDLE) { |
| |
| // if hstrSourceName is NULL we need to ask source for rendering |
| bool rv; |
| debug_printf("OTransferable::requestRendering request rendering"); |
| rv = RenderToOS2File( dragItem, mHwndTarget); |
| debug_printf("OTransferable::requestRendering requested rendering rv=%d", rv); |
| renderDRM = DRM_OS2FILE; |
| |
| // notify rendering request ongoing |
| return true; |
| |
| } else if (DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL)) { |
| |
| // we have hstrSourceName, no need for rendering, |
| // we already have enough data for rendering path now |
| |
| // get full path |
| DrgQueryStrName(dragItem->hstrContainerName, sizeof(path), path); |
| debug_printf("OTransferable::getTransferData hstrSourceName %x", dragItem->hstrSourceName); |
| debug_printf("OTransferable::getTransferData hstrTargetName %x", dragItem->hstrTargetName); |
| DrgQueryStrName(dragItem->hstrSourceName, sizeof(file), file); |
| sprintf( fullpath, "%s%s", path, file); |
| debug_printf("OTransferable::getTransferData fullpath %s", fullpath); |
| renderDRM = DRM_OS2FILE; |
| |
| } else { |
| debug_printf("OTransferable::requestRendering UNKNOWN request for FILE mimetype"); |
| } |
| break; |
| |
| case MIMETYPE_TEXT: |
| if (DrgVerifyRMF( dragItem, "DRM_ATOM", NULL)) { |
| |
| DrgQueryStrName(dragItem->ulItemID, sizeof(fullpath), fullpath); |
| debug_printf("OTransferable::requestRendering DRM_ATOM '%s'", fullpath); |
| renderDRM = DRM_ATOM; |
| |
| // no request rendering necessary |
| return false; |
| |
| } else if (DrgVerifyRMF( dragItem, "DRM_DTSHARE", NULL)) { |
| |
| bool rv; |
| debug_printf("OTransferable::requestRendering request DRM_DTSHARE rendering"); |
| rv = RenderToDTShare( dragItem, mHwndTarget); |
| debug_printf("OTransferable::requestRendering requested DRM_DTSHARE rendering rv=%d", rv); |
| renderDRM = DRM_DTSHARE; |
| |
| // notify rendering request ongoing |
| return true; |
| |
| } else if (DrgVerifyRMF( dragItem, "DRM_SHAREDMEM", NULL)) { |
| |
| bool rv; |
| debug_printf("OTransferable::requestRendering request DRM_SHAREDMEM rendering"); |
| rv = RenderToSharedMem( dragItem, mHwndTarget); |
| debug_printf("OTransferable::requestRendering requested DRM_SHAREDMEM rendering rv=%d", rv); |
| renderDRM = DRM_SHAREDMEM; |
| |
| // notify rendering request ongoing |
| return true; |
| |
| } else { |
| debug_printf("OTransferable::requestRendering UNKNOWN request for TEXT mimetype"); |
| } |
| break; |
| } |
| |
| // request rendering not necessary |
| return false; |
| |
| } |
| |
| // |
| // AOO window received DM_RENDERCOMPLETE message |
| // |
| bool OTransferable::renderComplete( PDRAGTRANSFER pdxfer) |
| { |
| switch( renderDRM) { |
| case DRM_NULL: |
| // already handled in requestRendering() |
| break; |
| case DRM_ATOM: |
| // set full path from source rendered name string |
| DrgQueryStrName( pdxfer->hstrRenderToName, sizeof(fullpath), fullpath); |
| debug_printf("OTransferable::setDragTransfer fullpath %s", fullpath); |
| break; |
| case DRM_DTSHARE: |
| // handled in getTransferData() |
| break; |
| case DRM_SHAREDMEM: |
| // save pointer |
| pSharedMem = (char *) pdxfer->hstrRenderToName; |
| // extraction handled in getTransferData() |
| break; |
| case DRM_OS2FILE: |
| // we already know the path, no need to use hstrRenderToName |
| debug_printf("OTransferable::setDragTransfer fullpath %s", fullpath); |
| // remove tmp file on destruction |
| removeOnExit = true; |
| break; |
| } |
| |
| // send success to source window |
| DrgSendTransferMsg( pdxfer->hwndClient, DM_ENDCONVERSATION, |
| (MPARAM) pdxfer->ulTargetInfo, |
| (MPARAM) DMFL_TARGETSUCCESSFUL); |
| |
| // free resources |
| DrgDeleteStrHandle( pdxfer->hstrSelectedRMF); |
| DrgDeleteStrHandle( pdxfer->hstrRenderToName); |
| DrgFreeDragtransfer( pdxfer); |
| |
| return false; |
| } |
| |
| Any SAL_CALL OTransferable::getTransferData( const DataFlavor& df) |
| throw(UnsupportedFlavorException, IOException, RuntimeException) |
| { |
| OUString m_aData; |
| char * pszText = 0; |
| int pszLen; |
| ULONG size = ~0; |
| ULONG flags = 0; |
| APIRET rc; |
| bool renderOk = false; |
| |
| debug_printf("OTransferable::getTransferData MimeType %s", |
| ::rtl::OUStringToOString( df.MimeType, RTL_TEXTENCODING_UTF8 ).getStr()); |
| |
| // handle shared memory cases |
| switch( renderDRM) { |
| case DRM_DTSHARE: |
| |
| pszLen = ((ULONG*)pDTShare)[0]; |
| pszText = (char*) malloc( pszLen + 1); |
| if (pszText) { |
| strcpy(pszText, &((char*)pDTShare)[sizeof(ULONG)] ); |
| } |
| // using DosGetNamedSharedMem() on memory we allocated appears |
| // to increment its usage ctr, so we have to free it 2x |
| DosFreeMem(pDTShare); |
| DosFreeMem(pDTShare); |
| // reset pointer |
| pDTShare = NULL; |
| |
| // prepare data for AOO |
| m_aData = OUString( pszText, pszLen, RTL_TEXTENCODING_UTF8); |
| break; |
| |
| case DRM_SHAREDMEM: |
| rc = DosQueryMem((PVOID) pSharedMem, &size, &flags); |
| renderOk = rc == 0; |
| if (renderOk) { |
| renderOk = (flags & (PAG_COMMIT | PAG_READ | PAG_BASE)) == |
| (PAG_COMMIT | PAG_READ | PAG_BASE); |
| } |
| if (renderOk) { |
| ULONG realSize = *(ULONG *) pSharedMem; |
| renderOk = realSize <= size; |
| if (renderOk) { |
| // prepare data for AOO |
| m_aData = OUString( pSharedMem + sizeof(ULONG), realSize, RTL_TEXTENCODING_UTF8); |
| } |
| } |
| // free memory only if it is given by another process, |
| // otherwise DefaultDragWorker will free it |
| if (flags & PAG_SHARED) |
| DosFreeMem((PVOID) pSharedMem); |
| break; |
| |
| case DRM_ATOM: |
| case DRM_OS2FILE: |
| // data is in fullpath string |
| // prepare data for AOO |
| m_aData = OUString( fullpath, strlen(fullpath), RTL_TEXTENCODING_UTF8); |
| break; |
| |
| default: |
| debug_printf( "OTransferable::getTransferData unsupported DRM_* type %d", |
| renderDRM); |
| break; |
| } |
| |
| // return data |
| return makeAny( m_aData ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Sequence< DataFlavor > SAL_CALL OTransferable::getTransferDataFlavors( ) |
| throw(RuntimeException) |
| { |
| return m_aFlavorList; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool SAL_CALL OTransferable::isDataFlavorSupported( const DataFlavor& ) |
| throw(RuntimeException) |
| { |
| return sal_True; |
| } |