2001-09-28 20:14:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
2004-04-18 22:01:16 +00:00
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
1999-03-25 04:38:25 +00:00
|
|
|
*
|
2004-04-18 22:01:16 +00:00
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (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.mozilla.org/MPL/
|
1999-03-25 04:38:25 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
1999-03-25 04:38:25 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2004-04-18 22:01:16 +00:00
|
|
|
* The Initial Developer of the Original Code is
|
2001-09-28 20:14:13 +00:00
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 03:40:37 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Contributor(s):
|
2001-03-31 05:04:57 +00:00
|
|
|
* Sean Echevarria <Sean@Beatnik.com>
|
2002-01-30 23:31:46 +00:00
|
|
|
* Blake Ross <blaker@netscape.com>
|
2004-05-31 19:46:30 +00:00
|
|
|
* Brodie Thiesfield <brofield@jellycan.com>
|
2004-07-16 07:28:10 +00:00
|
|
|
* Masayuki Nakano <masayuki@d-toybox.com>
|
2004-12-07 14:13:54 +00:00
|
|
|
* David Gardiner <david.gardiner@unisa.edu.au>
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
2004-04-18 22:01:16 +00:00
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
2001-09-28 20:14:13 +00:00
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
2004-04-18 22:01:16 +00:00
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
2001-09-28 20:14:13 +00:00
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
2004-04-18 22:01:16 +00:00
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
1999-03-23 15:37:34 +00:00
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
#include <ole2.h>
|
|
|
|
#include <shlobj.h>
|
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
#include "nsDataObj.h"
|
2002-05-01 21:58:38 +00:00
|
|
|
#include "nsClipboard.h"
|
2001-09-29 08:28:41 +00:00
|
|
|
#include "nsReadableUtils.h"
|
1999-03-23 15:37:34 +00:00
|
|
|
#include "nsITransferable.h"
|
1999-08-25 08:35:06 +00:00
|
|
|
#include "nsISupportsPrimitives.h"
|
2008-08-11 19:54:41 +00:00
|
|
|
#include "IEnumFE.h"
|
1999-12-02 23:17:31 +00:00
|
|
|
#include "nsPrimitiveHelpers.h"
|
2000-05-02 22:39:08 +00:00
|
|
|
#include "nsXPIDLString.h"
|
2001-01-23 01:09:58 +00:00
|
|
|
#include "nsIImage.h"
|
|
|
|
#include "nsImageClipboard.h"
|
2002-05-15 18:55:21 +00:00
|
|
|
#include "nsCRT.h"
|
2004-10-25 06:15:52 +00:00
|
|
|
#include "nsPrintfCString.h"
|
2004-05-31 19:46:30 +00:00
|
|
|
#include "nsIStringBundle.h"
|
2006-02-20 20:48:35 +00:00
|
|
|
#include "nsEscape.h"
|
|
|
|
#include "nsIURL.h"
|
|
|
|
#include "nsNetUtil.h"
|
2006-08-15 07:16:10 +00:00
|
|
|
#include "nsXPCOMStrings.h"
|
2008-10-12 16:34:26 +00:00
|
|
|
#include "nscore.h"
|
|
|
|
#include "prtypes.h"
|
2008-11-14 22:23:02 +00:00
|
|
|
#include "nsDirectoryServiceDefs.h"
|
|
|
|
|
|
|
|
// XXX Duped from profile/src/nsProfile.cpp.
|
|
|
|
#include <stdlib.h>
|
|
|
|
#define TABLE_SIZE 36
|
|
|
|
static const char table[] =
|
|
|
|
{ 'a','b','c','d','e','f','g','h','i','j',
|
|
|
|
'k','l','m','n','o','p','q','r','s','t',
|
|
|
|
'u','v','w','x','y','z','0','1','2','3',
|
|
|
|
'4','5','6','7','8','9' };
|
|
|
|
static void
|
|
|
|
MakeRandomString(char *buf, PRInt32 bufLen)
|
|
|
|
{
|
|
|
|
// turn PR_Now() into milliseconds since epoch
|
|
|
|
// and salt rand with that.
|
|
|
|
double fpTime;
|
|
|
|
LL_L2D(fpTime, PR_Now());
|
|
|
|
srand((uint)(fpTime * 1e-6 + 0.5)); // use 1e-6, granularity of PR_Now() on the mac is seconds
|
|
|
|
|
|
|
|
PRInt32 i;
|
|
|
|
for (i=0;i<bufLen;i++) {
|
|
|
|
*buf++ = table[rand()%TABLE_SIZE];
|
|
|
|
}
|
|
|
|
*buf = 0;
|
|
|
|
}
|
|
|
|
// XXX
|
2006-08-15 07:16:10 +00:00
|
|
|
|
|
|
|
// XXX for older version of PSDK where IAsyncOperation and related stuff is not available
|
|
|
|
// but this should be removed when parocles config is updated
|
|
|
|
// IAsyncOperation interface GUID
|
|
|
|
#ifndef __IAsyncOperation_INTERFACE_DEFINED__
|
|
|
|
const IID IID_IAsyncOperation = {0x3D8B0590, 0xF691, 0x11d2, {0x8E, 0xA9, 0x00, 0x60, 0x97, 0xDF, 0x5B, 0xD4}};
|
|
|
|
#endif
|
1999-03-23 15:37:34 +00:00
|
|
|
|
2000-06-07 02:11:40 +00:00
|
|
|
#if 0
|
2000-10-28 22:17:53 +00:00
|
|
|
#define PRNTDEBUG(_x) printf(_x);
|
|
|
|
#define PRNTDEBUG2(_x1, _x2) printf(_x1, _x2);
|
|
|
|
#define PRNTDEBUG3(_x1, _x2, _x3) printf(_x1, _x2, _x3);
|
1999-05-04 22:44:16 +00:00
|
|
|
#else
|
2000-10-28 22:17:53 +00:00
|
|
|
#define PRNTDEBUG(_x) // printf(_x);
|
|
|
|
#define PRNTDEBUG2(_x1, _x2) // printf(_x1, _x2);
|
|
|
|
#define PRNTDEBUG3(_x1, _x2, _x3) // printf(_x1, _x2, _x3);
|
1999-05-04 22:44:16 +00:00
|
|
|
#endif
|
1999-04-30 19:41:14 +00:00
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// CStream implementation
|
|
|
|
nsDataObj::CStream::CStream() : mRefCount(1)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
nsDataObj::CStream::~CStream()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// helper - initializes the stream
|
|
|
|
nsresult nsDataObj::CStream::Init(nsIURI *pSourceURI)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
rv = NS_NewChannel(getter_AddRefs(mChannel), pSourceURI);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = mChannel->Open(getter_AddRefs(mInputStream));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// IUnknown
|
|
|
|
STDMETHODIMP nsDataObj::CStream::QueryInterface(REFIID refiid, void** ppvResult)
|
|
|
|
{
|
|
|
|
*ppvResult = NULL;
|
|
|
|
if (IID_IUnknown == refiid ||
|
|
|
|
refiid == IID_IStream)
|
|
|
|
|
|
|
|
{
|
|
|
|
*ppvResult = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != *ppvResult)
|
|
|
|
{
|
|
|
|
((LPUNKNOWN)*ppvResult)->AddRef();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) nsDataObj::CStream::AddRef(void)
|
|
|
|
{
|
|
|
|
return ++mRefCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) nsDataObj::CStream::Release(void)
|
|
|
|
{
|
|
|
|
ULONG nCount = --mRefCount;
|
|
|
|
if (nCount == 0)
|
|
|
|
{
|
|
|
|
delete this;
|
|
|
|
return (ULONG)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mRefCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// IStream
|
|
|
|
STDMETHODIMP nsDataObj::CStream::Clone(IStream** ppStream)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::Commit(DWORD dwFrags)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::CopyTo(IStream* pDestStream,
|
|
|
|
ULARGE_INTEGER nBytesToCopy,
|
|
|
|
ULARGE_INTEGER* nBytesRead,
|
|
|
|
ULARGE_INTEGER* nBytesWritten)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::LockRegion(ULARGE_INTEGER nStart,
|
|
|
|
ULARGE_INTEGER nBytes,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::Read(void* pvBuffer,
|
|
|
|
ULONG nBytesToRead,
|
|
|
|
ULONG* nBytesRead)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(mInputStream, E_FAIL);
|
|
|
|
|
|
|
|
nsresult rv;
|
2008-08-04 11:00:07 +00:00
|
|
|
PRUint32 read;
|
|
|
|
*nBytesRead = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
read = 0;
|
|
|
|
rv = mInputStream->Read((char*)pvBuffer + *nBytesRead, nBytesToRead - *nBytesRead, &read);
|
|
|
|
NS_ENSURE_SUCCESS(rv, S_FALSE);
|
|
|
|
|
|
|
|
*nBytesRead += read;
|
|
|
|
} while ((*nBytesRead < nBytesToRead) && read);
|
2006-08-15 07:16:10 +00:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::Revert(void)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::Seek(LARGE_INTEGER nMove,
|
|
|
|
DWORD dwOrigin,
|
|
|
|
ULARGE_INTEGER* nNewPos)
|
|
|
|
{
|
2007-10-19 04:30:03 +00:00
|
|
|
if (nNewPos == NULL)
|
|
|
|
return STG_E_INVALIDPOINTER;
|
|
|
|
|
|
|
|
if (nMove.LowPart == 0 && nMove.HighPart == 0 &&
|
|
|
|
(dwOrigin == STREAM_SEEK_SET || dwOrigin == STREAM_SEEK_CUR)) {
|
|
|
|
nNewPos->LowPart = 0;
|
|
|
|
nNewPos->HighPart = 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::SetSize(ULARGE_INTEGER nNewSize)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::Stat(STATSTG* statstg, DWORD dwFlags)
|
|
|
|
{
|
2007-10-19 04:30:03 +00:00
|
|
|
if (statstg == NULL)
|
|
|
|
return STG_E_INVALIDPOINTER;
|
|
|
|
|
|
|
|
if (!mChannel)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
memset((void*)statstg, 0, sizeof(STATSTG));
|
|
|
|
|
|
|
|
if (dwFlags != STATFLAG_NONAME)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIURI> sourceURI;
|
|
|
|
if (NS_FAILED(mChannel->GetURI(getter_AddRefs(sourceURI)))) {
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCAutoString strFileName;
|
|
|
|
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
|
|
|
|
sourceURL->GetFileName(strFileName);
|
|
|
|
|
|
|
|
if (strFileName.IsEmpty())
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
NS_UnescapeURL(strFileName);
|
|
|
|
NS_ConvertUTF8toUTF16 wideFileName(strFileName);
|
|
|
|
|
|
|
|
PRUint32 nMaxNameLength = (wideFileName.Length()*2) + 2;
|
|
|
|
void * retBuf = CoTaskMemAlloc(nMaxNameLength); // freed by caller
|
|
|
|
if (!retBuf)
|
|
|
|
return STG_E_INSUFFICIENTMEMORY;
|
|
|
|
|
|
|
|
ZeroMemory(retBuf, nMaxNameLength);
|
|
|
|
memcpy(retBuf, wideFileName.get(), wideFileName.Length()*2);
|
|
|
|
statstg->pwcsName = (LPOLESTR)retBuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
SYSTEMTIME st;
|
|
|
|
|
|
|
|
statstg->type = STGTY_STREAM;
|
|
|
|
|
|
|
|
GetSystemTime(&st);
|
|
|
|
SystemTimeToFileTime((const SYSTEMTIME*)&st, (LPFILETIME)&statstg->mtime);
|
|
|
|
statstg->ctime = statstg->atime = statstg->mtime;
|
|
|
|
|
|
|
|
PRInt32 nLength = 0;
|
|
|
|
if (mChannel)
|
|
|
|
mChannel->GetContentLength(&nLength);
|
|
|
|
|
|
|
|
if (nLength < 0)
|
|
|
|
nLength = 0;
|
|
|
|
|
|
|
|
statstg->cbSize.LowPart = (DWORD)nLength;
|
|
|
|
statstg->grfMode = STGM_READ;
|
|
|
|
statstg->grfLocksSupported = LOCK_ONLYONCE;
|
|
|
|
statstg->clsid = CLSID_NULL;
|
|
|
|
|
|
|
|
return S_OK;
|
2006-08-15 07:16:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::UnlockRegion(ULARGE_INTEGER nStart,
|
|
|
|
ULARGE_INTEGER nBytes,
|
|
|
|
DWORD dwFlags)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP nsDataObj::CStream::Write(const void* pvBuffer,
|
|
|
|
ULONG nBytesToRead,
|
|
|
|
ULONG* nBytesRead)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
HRESULT nsDataObj::CreateStream(IStream **outStream)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(outStream, E_INVALIDARG);
|
|
|
|
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsAutoString wideFileName;
|
|
|
|
nsCOMPtr<nsIURI> sourceURI;
|
|
|
|
|
|
|
|
rv = GetDownloadDetails(getter_AddRefs(sourceURI),
|
|
|
|
wideFileName);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsDataObj::CStream *pStream = new nsDataObj::CStream();
|
|
|
|
NS_ENSURE_TRUE(pStream, E_OUTOFMEMORY);
|
|
|
|
|
|
|
|
rv = pStream->Init(sourceURI);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
pStream->Release();
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
*outStream = pStream;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-23 21:26:41 +00:00
|
|
|
EXTERN_C GUID CDECL CLSID_nsDataObj =
|
|
|
|
{ 0x1bba7640, 0xdf52, 0x11cf, { 0x82, 0x7b, 0, 0xa0, 0x24, 0x3a, 0xe5, 0x05 } };
|
1999-03-23 15:37:34 +00:00
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
/*
|
|
|
|
* deliberately not using MAX_PATH. This is because on platforms < XP
|
|
|
|
* a file created with a long filename may be mishandled by the shell
|
|
|
|
* resulting in it not being able to be deleted or moved.
|
|
|
|
* See bug 250392 for more details.
|
|
|
|
*/
|
|
|
|
#define NS_MAX_FILEDESCRIPTOR 128 + 1
|
1999-03-23 15:37:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Class nsDataObj
|
|
|
|
*/
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
|
|
|
// construction
|
|
|
|
//-----------------------------------------------------
|
2004-12-07 14:13:54 +00:00
|
|
|
nsDataObj::nsDataObj(nsIURI * uri)
|
2008-10-12 16:34:26 +00:00
|
|
|
: m_cRef(0), mTransferable(nsnull),
|
|
|
|
mIsAsyncMode(FALSE), mIsInOperation(FALSE)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
2008-10-12 16:34:26 +00:00
|
|
|
m_enumFE = new CEnumFormatEtc(32);
|
2004-12-07 14:13:54 +00:00
|
|
|
m_enumFE->AddRef();
|
1999-03-23 15:37:34 +00:00
|
|
|
|
2004-12-07 14:13:54 +00:00
|
|
|
if (uri) {
|
|
|
|
// A URI was obtained, so pass this through to the DataObject
|
|
|
|
// so it can create a SourceURL for CF_HTML flavour
|
|
|
|
uri->GetSpec(mSourceURL);
|
|
|
|
}
|
|
|
|
}
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
|
|
|
// destruction
|
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
nsDataObj::~nsDataObj()
|
|
|
|
{
|
1999-05-04 22:44:16 +00:00
|
|
|
NS_IF_RELEASE(mTransferable);
|
2008-09-06 16:24:45 +00:00
|
|
|
|
2009-03-11 02:26:03 +00:00
|
|
|
mDataFlavors.Clear();
|
1999-05-18 21:40:33 +00:00
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
m_enumFE->Release();
|
|
|
|
|
2007-11-17 04:31:32 +00:00
|
|
|
// Free arbitrary system formats
|
|
|
|
for (PRUint32 idx = 0; idx < mDataEntryList.Length(); idx++) {
|
|
|
|
CoTaskMemFree(mDataEntryList[idx]->fe.ptd);
|
|
|
|
ReleaseStgMedium(&mDataEntryList[idx]->stgm);
|
|
|
|
CoTaskMemFree(mDataEntryList[idx]);
|
|
|
|
}
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
// IUnknown interface methods - see inknown.h for documentation
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::QueryInterface(REFIID riid, void** ppv)
|
|
|
|
{
|
|
|
|
*ppv=NULL;
|
|
|
|
|
|
|
|
if ( (IID_IUnknown == riid) || (IID_IDataObject == riid) ) {
|
|
|
|
*ppv = this;
|
|
|
|
AddRef();
|
2006-08-15 07:16:10 +00:00
|
|
|
return S_OK;
|
|
|
|
} else if (IID_IAsyncOperation == riid) {
|
|
|
|
*ppv = static_cast<IAsyncOperation*>(this);
|
|
|
|
AddRef();
|
|
|
|
return S_OK;
|
|
|
|
}
|
1999-03-23 15:37:34 +00:00
|
|
|
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP_(ULONG) nsDataObj::AddRef()
|
|
|
|
{
|
2002-01-07 23:55:11 +00:00
|
|
|
++m_cRef;
|
|
|
|
NS_LOG_ADDREF(this, m_cRef, "nsDataObj", sizeof(*this));
|
2000-10-28 22:17:53 +00:00
|
|
|
//PRNTDEBUG3("nsDataObj::AddRef >>>>>>>>>>>>>>>>>> %d on %p\n", (m_cRef+1), this);
|
2002-01-07 23:55:11 +00:00
|
|
|
return m_cRef;
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP_(ULONG) nsDataObj::Release()
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
//PRNTDEBUG3("nsDataObj::Release >>>>>>>>>>>>>>>>>> %d on %p\n", (m_cRef-1), this);
|
1999-03-23 15:37:34 +00:00
|
|
|
|
2008-02-07 04:07:15 +00:00
|
|
|
--m_cRef;
|
2002-01-07 23:55:11 +00:00
|
|
|
NS_LOG_RELEASE(this, m_cRef, "nsDataObj");
|
2008-02-07 04:07:15 +00:00
|
|
|
if (0 != m_cRef)
|
1999-03-23 15:37:34 +00:00
|
|
|
return m_cRef;
|
|
|
|
|
|
|
|
delete this;
|
1999-05-04 22:44:16 +00:00
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
BOOL nsDataObj::FormatsMatch(const FORMATETC& source, const FORMATETC& target) const
|
|
|
|
{
|
|
|
|
if ((source.cfFormat == target.cfFormat) &&
|
|
|
|
(source.dwAspect & target.dwAspect) &&
|
|
|
|
(source.tymed & target.tymed)) {
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
// IDataObject methods
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::GetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::GetData\n");
|
2008-11-14 22:23:02 +00:00
|
|
|
PRNTDEBUG3(" format: %d Text: %d\n", pFE->cfFormat, CF_HDROP);
|
2000-05-02 22:39:08 +00:00
|
|
|
if ( !mTransferable )
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(DATA_E_FORMATETC);
|
|
|
|
|
|
|
|
PRUint32 dfInx = 0;
|
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
static CLIPFORMAT fileDescriptorFlavorA = ::RegisterClipboardFormat( CFSTR_FILEDESCRIPTORA );
|
|
|
|
static CLIPFORMAT fileDescriptorFlavorW = ::RegisterClipboardFormat( CFSTR_FILEDESCRIPTORW );
|
|
|
|
static CLIPFORMAT uniformResourceLocatorA = ::RegisterClipboardFormat( CFSTR_INETURLA );
|
|
|
|
static CLIPFORMAT uniformResourceLocatorW = ::RegisterClipboardFormat( CFSTR_INETURLW );
|
2005-08-11 00:37:53 +00:00
|
|
|
static CLIPFORMAT fileFlavor = ::RegisterClipboardFormat( CFSTR_FILECONTENTS );
|
2003-06-06 23:30:47 +00:00
|
|
|
static CLIPFORMAT PreferredDropEffect = ::RegisterClipboardFormat( CFSTR_PREFERREDDROPEFFECT );
|
2000-05-02 22:39:08 +00:00
|
|
|
|
2007-11-17 04:31:32 +00:00
|
|
|
// Arbitrary system formats
|
|
|
|
LPDATAENTRY pde;
|
|
|
|
HRESULT hres = FindFORMATETC(pFE, &pde, FALSE);
|
|
|
|
if (SUCCEEDED(hres)) {
|
|
|
|
return AddRefStgMedium(&pde->stgm, pSTM, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Firefox internal formats
|
1999-03-23 15:37:34 +00:00
|
|
|
ULONG count;
|
|
|
|
FORMATETC fe;
|
|
|
|
m_enumFE->Reset();
|
2009-03-11 02:26:03 +00:00
|
|
|
while (NOERROR == m_enumFE->Next(1, &fe, &count)
|
|
|
|
&& dfInx < mDataFlavors.Length())) {
|
|
|
|
nsCString& df = mDataFlavors.ElementAt(dfInx);
|
|
|
|
if (FormatsMatch(fe, *pFE)) {
|
|
|
|
pSTM->pUnkForRelease = NULL; // caller is responsible for deleting this data
|
|
|
|
CLIPFORMAT format = pFE->cfFormat;
|
|
|
|
switch(format) {
|
|
|
|
|
|
|
|
// Someone is asking for plain or unicode text
|
|
|
|
case CF_TEXT:
|
|
|
|
case CF_UNICODETEXT:
|
|
|
|
return GetText(df, *pFE, *pSTM);
|
|
|
|
|
|
|
|
// Some 3rd party apps that receive drag and drop files from the browser
|
|
|
|
// window require support for this.
|
|
|
|
case CF_HDROP:
|
|
|
|
return GetFile(*pFE, *pSTM);
|
|
|
|
|
|
|
|
// Someone is asking for an image
|
|
|
|
case CF_DIB:
|
|
|
|
return GetDib(df, *pFE, *pSTM);
|
|
|
|
|
|
|
|
// ... not yet implemented ...
|
|
|
|
//case CF_BITMAP:
|
|
|
|
// return GetBitmap(*pFE, *pSTM);
|
|
|
|
//case CF_METAFILEPICT:
|
|
|
|
// return GetMetafilePict(*pFE, *pSTM);
|
|
|
|
|
|
|
|
default:
|
|
|
|
if ( format == fileDescriptorFlavorA )
|
|
|
|
return GetFileDescriptor ( *pFE, *pSTM, PR_FALSE );
|
|
|
|
if ( format == fileDescriptorFlavorW )
|
|
|
|
return GetFileDescriptor ( *pFE, *pSTM, PR_TRUE);
|
|
|
|
if ( format == uniformResourceLocatorA )
|
|
|
|
return GetUniformResourceLocator( *pFE, *pSTM, PR_FALSE);
|
|
|
|
if ( format == uniformResourceLocatorW )
|
|
|
|
return GetUniformResourceLocator( *pFE, *pSTM, PR_TRUE);
|
|
|
|
if ( format == fileFlavor )
|
|
|
|
return GetFileContents ( *pFE, *pSTM );
|
|
|
|
if ( format == PreferredDropEffect )
|
|
|
|
return GetPreferredDropEffect( *pFE, *pSTM );
|
|
|
|
PRNTDEBUG2("***** nsDataObj::GetData - Unknown format %u\n", format);
|
|
|
|
return GetText(df, *pFE, *pSTM);
|
|
|
|
} //switch
|
|
|
|
} // if
|
1999-03-23 15:37:34 +00:00
|
|
|
dfInx++;
|
|
|
|
} // while
|
|
|
|
|
2002-11-05 12:51:39 +00:00
|
|
|
return ResultFromScode(DATA_E_FORMATETC);
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::GetDataHere(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::GetDataHere\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
|
|
|
// Other objects querying to see if we support a
|
|
|
|
// particular format
|
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::QueryGetData(LPFORMATETC pFE)
|
|
|
|
{
|
1999-05-04 22:44:16 +00:00
|
|
|
PRNTDEBUG("nsDataObj::QueryGetData ");
|
2008-11-14 22:23:02 +00:00
|
|
|
PRNTDEBUG2("format: %d\n", pFE->cfFormat);
|
1999-04-17 13:49:39 +00:00
|
|
|
|
2007-11-17 04:31:32 +00:00
|
|
|
// Arbitrary system formats
|
|
|
|
LPDATAENTRY pde;
|
|
|
|
if (SUCCEEDED(FindFORMATETC(pFE, &pde, FALSE)))
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
// Firefox internal formats
|
1999-04-17 13:49:39 +00:00
|
|
|
ULONG count;
|
|
|
|
FORMATETC fe;
|
|
|
|
m_enumFE->Reset();
|
|
|
|
while (NOERROR == m_enumFE->Next(1, &fe, &count)) {
|
|
|
|
if (fe.cfFormat == pFE->cfFormat) {
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
}
|
2008-11-14 22:23:02 +00:00
|
|
|
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG2("***** nsDataObj::QueryGetData - Unknown format %d\n", pFE->cfFormat);
|
1999-04-17 13:49:39 +00:00
|
|
|
return ResultFromScode(E_FAIL);
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::GetCanonicalFormatEtc
|
|
|
|
(LPFORMATETC pFEIn, LPFORMATETC pFEOut)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::GetCanonicalFormatEtc\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
2007-11-17 04:31:32 +00:00
|
|
|
HGLOBAL nsDataObj::GlobalClone(HGLOBAL hglobIn)
|
|
|
|
{
|
|
|
|
HGLOBAL hglobOut = NULL;
|
|
|
|
|
|
|
|
LPVOID pvIn = GlobalLock(hglobIn);
|
|
|
|
if (pvIn) {
|
|
|
|
SIZE_T cb = GlobalSize(hglobIn);
|
|
|
|
HGLOBAL hglobOut = GlobalAlloc(GMEM_FIXED, cb);
|
|
|
|
if (hglobOut) {
|
|
|
|
CopyMemory(hglobOut, pvIn, cb);
|
|
|
|
}
|
|
|
|
GlobalUnlock(hglobIn);
|
|
|
|
}
|
|
|
|
return hglobOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
IUnknown* nsDataObj::GetCanonicalIUnknown(IUnknown *punk)
|
|
|
|
{
|
|
|
|
IUnknown *punkCanonical;
|
|
|
|
if (punk && SUCCEEDED(punk->QueryInterface(IID_IUnknown,
|
|
|
|
(LPVOID*)&punkCanonical))) {
|
|
|
|
punkCanonical->Release();
|
|
|
|
} else {
|
|
|
|
punkCanonical = punk;
|
|
|
|
}
|
|
|
|
return punkCanonical;
|
|
|
|
}
|
1999-03-23 15:37:34 +00:00
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::SetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM, BOOL fRelease)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::SetData\n");
|
2003-06-13 20:38:43 +00:00
|
|
|
static CLIPFORMAT PerformedDropEffect = ::RegisterClipboardFormat( CFSTR_PERFORMEDDROPEFFECT );
|
1999-05-04 22:44:16 +00:00
|
|
|
|
2003-06-13 20:38:43 +00:00
|
|
|
if (pFE && pFE->cfFormat == PerformedDropEffect) {
|
|
|
|
// The drop operation has completed. Delete the temp file if it exists.
|
|
|
|
if (mCachedTempFile) {
|
|
|
|
mCachedTempFile->Remove(PR_FALSE);
|
|
|
|
mCachedTempFile = NULL;
|
|
|
|
}
|
|
|
|
}
|
2007-11-17 04:31:32 +00:00
|
|
|
// Store arbitrary system formats
|
|
|
|
LPDATAENTRY pde;
|
|
|
|
HRESULT hres = FindFORMATETC(pFE, &pde, TRUE); // add
|
|
|
|
if (SUCCEEDED(hres)) {
|
|
|
|
if (pde->stgm.tymed) {
|
|
|
|
ReleaseStgMedium(&pde->stgm);
|
|
|
|
ZeroMemory(&pde->stgm, sizeof(STGMEDIUM));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fRelease) {
|
|
|
|
pde->stgm = *pSTM;
|
|
|
|
hres = S_OK;
|
|
|
|
} else {
|
|
|
|
hres = AddRefStgMedium(pSTM, &pde->stgm, TRUE);
|
|
|
|
}
|
|
|
|
pde->fe.tymed = pde->stgm.tymed;
|
|
|
|
|
|
|
|
// Break circular reference loop (see msdn)
|
|
|
|
if (GetCanonicalIUnknown(pde->stgm.pUnkForRelease) ==
|
|
|
|
GetCanonicalIUnknown(static_cast<IDataObject*>(this))) {
|
|
|
|
pde->stgm.pUnkForRelease->Release();
|
|
|
|
pde->stgm.pUnkForRelease = NULL;
|
|
|
|
}
|
|
|
|
return hres;
|
2003-06-13 20:38:43 +00:00
|
|
|
}
|
|
|
|
|
2007-11-17 04:31:32 +00:00
|
|
|
if (fRelease)
|
|
|
|
ReleaseStgMedium(pSTM);
|
|
|
|
|
2003-06-13 20:38:43 +00:00
|
|
|
return ResultFromScode(S_OK);
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
2007-11-17 04:31:32 +00:00
|
|
|
HRESULT
|
|
|
|
nsDataObj::FindFORMATETC(FORMATETC *pfe, LPDATAENTRY *ppde, BOOL fAdd)
|
|
|
|
{
|
|
|
|
*ppde = NULL;
|
|
|
|
|
|
|
|
if (pfe->ptd != NULL) return DV_E_DVTARGETDEVICE;
|
|
|
|
|
|
|
|
// See if it's in our list
|
|
|
|
for (PRUint32 idx = 0; idx < mDataEntryList.Length(); idx++) {
|
|
|
|
if (mDataEntryList[idx]->fe.cfFormat == pfe->cfFormat &&
|
|
|
|
mDataEntryList[idx]->fe.dwAspect == pfe->dwAspect &&
|
|
|
|
mDataEntryList[idx]->fe.lindex == pfe->lindex) {
|
|
|
|
if (fAdd || (mDataEntryList[idx]->fe.tymed & pfe->tymed)) {
|
|
|
|
*ppde = mDataEntryList[idx];
|
|
|
|
return S_OK;
|
|
|
|
} else {
|
|
|
|
return DV_E_TYMED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fAdd)
|
|
|
|
return DV_E_FORMATETC;
|
|
|
|
|
|
|
|
LPDATAENTRY pde = (LPDATAENTRY)CoTaskMemAlloc(sizeof(DATAENTRY));
|
|
|
|
if (pde) {
|
|
|
|
pde->fe = *pfe;
|
|
|
|
*ppde = pde;
|
|
|
|
ZeroMemory(&pde->stgm, sizeof(STGMEDIUM));
|
|
|
|
|
|
|
|
m_enumFE->AddFE(pfe);
|
|
|
|
mDataEntryList.AppendElement(pde);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
} else {
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
|
|
nsDataObj::AddRefStgMedium(STGMEDIUM *pstgmIn, STGMEDIUM *pstgmOut, BOOL fCopyIn)
|
|
|
|
{
|
|
|
|
HRESULT hres = S_OK;
|
|
|
|
STGMEDIUM stgmOut = *pstgmIn;
|
|
|
|
|
|
|
|
if (pstgmIn->pUnkForRelease == NULL &&
|
|
|
|
!(pstgmIn->tymed & (TYMED_ISTREAM | TYMED_ISTORAGE))) {
|
|
|
|
if (fCopyIn) {
|
|
|
|
// Object needs to be cloned
|
|
|
|
if (pstgmIn->tymed == TYMED_HGLOBAL) {
|
|
|
|
stgmOut.hGlobal = GlobalClone(pstgmIn->hGlobal);
|
|
|
|
if (!stgmOut.hGlobal) {
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hres = DV_E_TYMED;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
stgmOut.pUnkForRelease = static_cast<IDataObject*>(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SUCCEEDED(hres)) {
|
|
|
|
switch (stgmOut.tymed) {
|
|
|
|
case TYMED_ISTREAM:
|
|
|
|
stgmOut.pstm->AddRef();
|
|
|
|
break;
|
|
|
|
case TYMED_ISTORAGE:
|
|
|
|
stgmOut.pstg->AddRef();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (stgmOut.pUnkForRelease) {
|
|
|
|
stgmOut.pUnkForRelease->AddRef();
|
|
|
|
}
|
|
|
|
*pstgmOut = stgmOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hres;
|
|
|
|
}
|
1999-03-23 15:37:34 +00:00
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::EnumFormatEtc(DWORD dwDir, LPENUMFORMATETC *ppEnum)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::EnumFormatEtc\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
|
|
|
|
switch (dwDir) {
|
2008-10-12 16:34:26 +00:00
|
|
|
case DATADIR_GET:
|
|
|
|
m_enumFE->Clone(ppEnum);
|
|
|
|
break;
|
1999-03-23 15:37:34 +00:00
|
|
|
case DATADIR_SET:
|
2008-10-12 16:34:26 +00:00
|
|
|
// fall through
|
1999-03-23 15:37:34 +00:00
|
|
|
default:
|
2008-10-12 16:34:26 +00:00
|
|
|
*ppEnum = NULL;
|
1999-03-23 15:37:34 +00:00
|
|
|
} // switch
|
1999-05-04 22:44:16 +00:00
|
|
|
|
|
|
|
if (NULL == *ppEnum)
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
|
2008-02-07 04:07:15 +00:00
|
|
|
// Clone already AddRefed the result so don't addref it again.
|
1999-03-23 15:37:34 +00:00
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::DAdvise(LPFORMATETC pFE, DWORD dwFlags,
|
1999-05-04 22:44:16 +00:00
|
|
|
LPADVISESINK pIAdviseSink, DWORD* pdwConn)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::DAdvise\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::DUnadvise(DWORD dwConn)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::DUnadvise\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
STDMETHODIMP nsDataObj::EnumDAdvise(LPENUMSTATDATA *ppEnum)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::EnumDAdvise\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
// IAsyncOperation methods
|
|
|
|
STDMETHODIMP nsDataObj::EndOperation(HRESULT hResult,
|
|
|
|
IBindCtx *pbcReserved,
|
|
|
|
DWORD dwEffects)
|
|
|
|
{
|
|
|
|
mIsInOperation = FALSE;
|
|
|
|
Release();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP nsDataObj::GetAsyncMode(BOOL *pfIsOpAsync)
|
|
|
|
{
|
|
|
|
if (!pfIsOpAsync)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
*pfIsOpAsync = mIsAsyncMode;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP nsDataObj::InOperation(BOOL *pfInAsyncOp)
|
|
|
|
{
|
|
|
|
if (!pfInAsyncOp)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
*pfInAsyncOp = mIsInOperation;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP nsDataObj::SetAsyncMode(BOOL fDoOpAsync)
|
|
|
|
{
|
|
|
|
mIsAsyncMode = fDoOpAsync;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP nsDataObj::StartOperation(IBindCtx *pbcReserved)
|
|
|
|
{
|
|
|
|
mIsInOperation = TRUE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
// GetData and SetData helper functions
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
HRESULT nsDataObj::AddSetFormat(FORMATETC& aFE)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::AddSetFormat\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(S_OK);
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
HRESULT nsDataObj::AddGetFormat(FORMATETC& aFE)
|
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::AddGetFormat\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(S_OK);
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
2001-01-23 01:09:58 +00:00
|
|
|
HRESULT
|
2002-03-23 22:26:36 +00:00
|
|
|
nsDataObj::GetBitmap ( const nsACString& , FORMATETC&, STGMEDIUM& )
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::GetBitmap\n");
|
1999-03-23 15:37:34 +00:00
|
|
|
return ResultFromScode(E_NOTIMPL);
|
|
|
|
}
|
|
|
|
|
2001-01-23 01:09:58 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// GetDIB
|
|
|
|
//
|
|
|
|
// Someone is asking for a bitmap. The data in the transferable will be a straight
|
|
|
|
// nsIImage, so just QI it.
|
|
|
|
//
|
|
|
|
HRESULT
|
2002-03-23 22:26:36 +00:00
|
|
|
nsDataObj :: GetDib ( const nsACString& inFlavor, FORMATETC &, STGMEDIUM & aSTG )
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
2000-10-28 22:17:53 +00:00
|
|
|
PRNTDEBUG("nsDataObj::GetDib\n");
|
2001-01-23 01:09:58 +00:00
|
|
|
ULONG result = E_FAIL;
|
|
|
|
PRUint32 len = 0;
|
|
|
|
nsCOMPtr<nsISupports> genericDataWrapper;
|
2001-04-02 19:40:52 +00:00
|
|
|
mTransferable->GetTransferData(PromiseFlatCString(inFlavor).get(), getter_AddRefs(genericDataWrapper), &len);
|
2001-01-23 01:09:58 +00:00
|
|
|
nsCOMPtr<nsIImage> image ( do_QueryInterface(genericDataWrapper) );
|
2002-04-23 14:24:48 +00:00
|
|
|
if ( !image ) {
|
|
|
|
// In the 0.9.4 timeframe, I had some embedding clients put the nsIImage directly into the
|
|
|
|
// transferable. Newer code, however, wraps the nsIImage in a nsISupportsInterfacePointer.
|
|
|
|
// We should be backwards compatibile with code already out in the field. If we can't find
|
|
|
|
// the image directly out of the transferable, unwrap the image from its wrapper.
|
|
|
|
nsCOMPtr<nsISupportsInterfacePointer> ptr(do_QueryInterface(genericDataWrapper));
|
|
|
|
if ( ptr )
|
|
|
|
ptr->GetData(getter_AddRefs(image));
|
|
|
|
}
|
|
|
|
|
2001-01-23 01:09:58 +00:00
|
|
|
if ( image ) {
|
2001-03-27 06:02:54 +00:00
|
|
|
// use a the helper class to build up a bitmap. We now own the bits,
|
|
|
|
// and pass them back to the OS in |aSTG|.
|
2001-01-23 01:09:58 +00:00
|
|
|
nsImageToClipboard converter ( image );
|
|
|
|
HANDLE bits = nsnull;
|
|
|
|
nsresult rv = converter.GetPicture ( &bits );
|
|
|
|
if ( NS_SUCCEEDED(rv) && bits ) {
|
|
|
|
aSTG.hGlobal = bits;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
result = S_OK;
|
|
|
|
}
|
|
|
|
} // if we have an image
|
|
|
|
else
|
2006-02-23 09:36:43 +00:00
|
|
|
NS_WARNING ( "Definitely not an image on clipboard" );
|
2001-01-23 01:09:58 +00:00
|
|
|
return ResultFromScode(result);
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
2000-05-02 22:39:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// GetFileDescriptor
|
|
|
|
//
|
|
|
|
|
|
|
|
HRESULT
|
2004-07-16 07:28:10 +00:00
|
|
|
nsDataObj :: GetFileDescriptor ( FORMATETC& aFE, STGMEDIUM& aSTG, PRBool aIsUnicode )
|
2000-05-02 22:39:08 +00:00
|
|
|
{
|
|
|
|
HRESULT res = S_OK;
|
|
|
|
|
|
|
|
// How we handle this depends on if we're dealing with an internet
|
|
|
|
// shortcut, since those are done under the covers.
|
2006-08-15 07:16:10 +00:00
|
|
|
if (IsFlavourPresent(kFilePromiseMime) ||
|
|
|
|
IsFlavourPresent(kFileMime))
|
|
|
|
{
|
|
|
|
if (aIsUnicode)
|
|
|
|
return GetFileDescriptor_IStreamW(aFE, aSTG);
|
|
|
|
else
|
|
|
|
return GetFileDescriptor_IStreamA(aFE, aSTG);
|
|
|
|
}
|
|
|
|
else if (IsFlavourPresent(kURLMime))
|
|
|
|
{
|
2004-07-16 07:28:10 +00:00
|
|
|
if ( aIsUnicode )
|
|
|
|
res = GetFileDescriptorInternetShortcutW ( aFE, aSTG );
|
|
|
|
else
|
|
|
|
res = GetFileDescriptorInternetShortcutA ( aFE, aSTG );
|
2006-08-15 07:16:10 +00:00
|
|
|
}
|
2000-05-02 22:39:08 +00:00
|
|
|
else
|
2000-10-28 22:17:53 +00:00
|
|
|
NS_WARNING ( "Not yet implemented\n" );
|
2000-05-02 22:39:08 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
} // GetFileDescriptor
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
HRESULT
|
|
|
|
nsDataObj :: GetFileContents ( FORMATETC& aFE, STGMEDIUM& aSTG )
|
|
|
|
{
|
|
|
|
HRESULT res = S_OK;
|
|
|
|
|
|
|
|
// How we handle this depends on if we're dealing with an internet
|
|
|
|
// shortcut, since those are done under the covers.
|
2006-08-15 07:16:10 +00:00
|
|
|
if (IsFlavourPresent(kFilePromiseMime) ||
|
|
|
|
IsFlavourPresent(kFileMime))
|
|
|
|
return GetFileContents_IStream(aFE, aSTG);
|
|
|
|
else if (IsFlavourPresent(kURLMime))
|
|
|
|
return GetFileContentsInternetShortcut ( aFE, aSTG );
|
2000-05-02 22:39:08 +00:00
|
|
|
else
|
2000-10-28 22:17:53 +00:00
|
|
|
NS_WARNING ( "Not yet implemented\n" );
|
2000-05-02 22:39:08 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
} // GetFileContents
|
|
|
|
|
2004-05-31 19:46:30 +00:00
|
|
|
//
|
|
|
|
// Given a unicode string, we ensure that it contains only characters which are valid within
|
|
|
|
// the file system. Remove all forbidden characters from the name, and completely disallow
|
|
|
|
// any title that starts with a forbidden name and extension (e.g. "nul" is invalid, but
|
|
|
|
// "nul." and "nul.txt" are also invalid and will cause problems).
|
|
|
|
//
|
|
|
|
// It would seem that this is more functionality suited to being in nsILocalFile.
|
|
|
|
//
|
|
|
|
static void
|
|
|
|
MangleTextToValidFilename(nsString & aText)
|
|
|
|
{
|
|
|
|
static const char* forbiddenNames[] = {
|
|
|
|
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
|
|
|
|
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
|
|
|
|
"CON", "PRN", "AUX", "NUL", "CLOCK$"
|
|
|
|
};
|
|
|
|
|
|
|
|
aText.StripChars(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS);
|
|
|
|
aText.CompressWhitespace(PR_TRUE, PR_TRUE);
|
2004-12-20 16:27:12 +00:00
|
|
|
PRUint32 nameLen;
|
|
|
|
for (size_t n = 0; n < NS_ARRAY_LENGTH(forbiddenNames); ++n) {
|
|
|
|
nameLen = (PRUint32) strlen(forbiddenNames[n]);
|
2004-05-31 19:46:30 +00:00
|
|
|
if (aText.EqualsIgnoreCase(forbiddenNames[n], nameLen)) {
|
|
|
|
// invalid name is either the entire string, or a prefix with a period
|
|
|
|
if (aText.Length() == nameLen || aText.CharAt(nameLen) == PRUnichar('.')) {
|
|
|
|
aText.Truncate();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Given a unicode string, convert it down to a valid local charset filename
|
|
|
|
// with the supplied extension. This ensures that we do not cut MBCS characters
|
|
|
|
// in the middle.
|
|
|
|
//
|
|
|
|
// It would seem that this is more functionality suited to being in nsILocalFile.
|
|
|
|
//
|
|
|
|
static PRBool
|
2004-07-16 07:28:10 +00:00
|
|
|
CreateFilenameFromTextA(nsString & aText, const char * aExtension,
|
2004-05-31 19:46:30 +00:00
|
|
|
char * aFilename, PRUint32 aFilenameLen)
|
|
|
|
{
|
|
|
|
// ensure that the supplied name doesn't have invalid characters. If
|
|
|
|
// a valid mangled filename couldn't be created then it will leave the
|
|
|
|
// text empty.
|
|
|
|
MangleTextToValidFilename(aText);
|
|
|
|
if (aText.IsEmpty())
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
// repeatably call WideCharToMultiByte as long as the title doesn't fit in the buffer
|
|
|
|
// available to us. Continually reduce the length of the source title until the MBCS
|
|
|
|
// version will fit in the buffer with room for the supplied extension. Doing it this
|
|
|
|
// way ensures that even in MBCS environments there will be a valid MBCS filename of
|
|
|
|
// the correct length.
|
|
|
|
int maxUsableFilenameLen = aFilenameLen - strlen(aExtension) - 1; // space for ext + null byte
|
|
|
|
int currLen, textLen = (int) NS_MIN(aText.Length(), aFilenameLen);
|
2004-07-16 07:28:10 +00:00
|
|
|
char defaultChar = '_';
|
2004-05-31 19:46:30 +00:00
|
|
|
do {
|
2004-07-16 07:28:10 +00:00
|
|
|
currLen = WideCharToMultiByte(CP_ACP,
|
|
|
|
WC_COMPOSITECHECK|WC_DEFAULTCHAR,
|
|
|
|
aText.get(), textLen--, aFilename, maxUsableFilenameLen, &defaultChar, NULL);
|
2004-05-31 19:46:30 +00:00
|
|
|
}
|
|
|
|
while (currLen == 0 && textLen > 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
if (currLen > 0 && textLen > 0) {
|
|
|
|
strcpy(&aFilename[currLen], aExtension);
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// empty names aren't permitted
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
static PRBool
|
|
|
|
CreateFilenameFromTextW(nsString & aText, const wchar_t * aExtension,
|
|
|
|
wchar_t * aFilename, PRUint32 aFilenameLen)
|
|
|
|
{
|
|
|
|
// ensure that the supplied name doesn't have invalid characters. If
|
|
|
|
// a valid mangled filename couldn't be created then it will leave the
|
|
|
|
// text empty.
|
|
|
|
MangleTextToValidFilename(aText);
|
|
|
|
if (aText.IsEmpty())
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
const int extensionLen = wcslen(aExtension);
|
|
|
|
if (aText.Length() + extensionLen + 1 > aFilenameLen)
|
|
|
|
aText.Truncate(aFilenameLen - extensionLen - 1);
|
|
|
|
wcscpy(&aFilename[0], aText.get());
|
|
|
|
wcscpy(&aFilename[aText.Length()], aExtension);
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2004-05-31 19:46:30 +00:00
|
|
|
#define PAGEINFO_PROPERTIES "chrome://navigator/locale/pageInfo.properties"
|
|
|
|
|
|
|
|
static PRBool
|
|
|
|
GetLocalizedString(const PRUnichar * aName, nsXPIDLString & aString)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2006-06-03 23:35:59 +00:00
|
|
|
nsCOMPtr<nsIStringBundleService> stringService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
|
2004-05-31 19:46:30 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIStringBundle> stringBundle;
|
|
|
|
rv = stringService->CreateBundle(PAGEINFO_PROPERTIES, getter_AddRefs(stringBundle));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
rv = stringBundle->GetStringFromName(aName, getter_Copies(aString));
|
|
|
|
return NS_SUCCEEDED(rv);
|
|
|
|
}
|
2000-05-02 22:39:08 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// GetFileDescriptorInternetShortcut
|
|
|
|
//
|
|
|
|
// Create the special format for an internet shortcut and build up the data
|
|
|
|
// structures the shell is expecting.
|
|
|
|
//
|
|
|
|
HRESULT
|
2004-07-16 07:28:10 +00:00
|
|
|
nsDataObj :: GetFileDescriptorInternetShortcutA ( FORMATETC& aFE, STGMEDIUM& aSTG )
|
2000-05-02 22:39:08 +00:00
|
|
|
{
|
2009-01-05 18:17:44 +00:00
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
// get the title of the shortcut
|
|
|
|
nsAutoString title;
|
|
|
|
if ( NS_FAILED(ExtractShortcutTitle(title)) )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
HGLOBAL fileGroupDescHandle = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE,sizeof(FILEGROUPDESCRIPTORA));
|
|
|
|
if (!fileGroupDescHandle)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
LPFILEGROUPDESCRIPTORA fileGroupDescA = reinterpret_cast<LPFILEGROUPDESCRIPTORA>(::GlobalLock(fileGroupDescHandle));
|
2004-07-16 07:28:10 +00:00
|
|
|
if (!fileGroupDescA) {
|
|
|
|
::GlobalFree(fileGroupDescHandle);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get a valid filename in the following order: 1) from the page title,
|
|
|
|
// 2) localized string for an untitled page, 3) just use "Untitled.URL"
|
|
|
|
if (!CreateFilenameFromTextA(title, ".URL",
|
2006-08-15 07:16:10 +00:00
|
|
|
fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
|
2004-07-16 07:28:10 +00:00
|
|
|
nsXPIDLString untitled;
|
|
|
|
if (!GetLocalizedString(NS_LITERAL_STRING("noPageTitle").get(), untitled) ||
|
|
|
|
!CreateFilenameFromTextA(untitled, ".URL",
|
2006-08-15 07:16:10 +00:00
|
|
|
fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
|
2004-07-16 07:28:10 +00:00
|
|
|
strcpy(fileGroupDescA->fgd[0].cFileName, "Untitled.URL");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// one file in the file block
|
|
|
|
fileGroupDescA->cItems = 1;
|
|
|
|
fileGroupDescA->fgd[0].dwFlags = FD_LINKUI;
|
|
|
|
|
|
|
|
::GlobalUnlock( fileGroupDescHandle );
|
|
|
|
aSTG.hGlobal = fileGroupDescHandle;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
} // GetFileDescriptorInternetShortcutA
|
2000-05-02 22:39:08 +00:00
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
HRESULT
|
|
|
|
nsDataObj :: GetFileDescriptorInternetShortcutW ( FORMATETC& aFE, STGMEDIUM& aSTG )
|
|
|
|
{
|
2004-05-31 19:46:30 +00:00
|
|
|
// get the title of the shortcut
|
|
|
|
nsAutoString title;
|
|
|
|
if ( NS_FAILED(ExtractShortcutTitle(title)) )
|
|
|
|
return E_OUTOFMEMORY;
|
2000-05-02 22:39:08 +00:00
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
HGLOBAL fileGroupDescHandle = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE,sizeof(FILEGROUPDESCRIPTORW));
|
2004-05-31 19:46:30 +00:00
|
|
|
if (!fileGroupDescHandle)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
LPFILEGROUPDESCRIPTORW fileGroupDescW = reinterpret_cast<LPFILEGROUPDESCRIPTORW>(::GlobalLock(fileGroupDescHandle));
|
2004-07-16 07:28:10 +00:00
|
|
|
if (!fileGroupDescW) {
|
2004-05-31 19:46:30 +00:00
|
|
|
::GlobalFree(fileGroupDescHandle);
|
|
|
|
return E_OUTOFMEMORY;
|
2000-05-02 22:39:08 +00:00
|
|
|
}
|
2004-05-31 19:46:30 +00:00
|
|
|
|
|
|
|
// get a valid filename in the following order: 1) from the page title,
|
|
|
|
// 2) localized string for an untitled page, 3) just use "Untitled.URL"
|
2004-07-16 07:28:10 +00:00
|
|
|
if (!CreateFilenameFromTextW(title, NS_LITERAL_STRING(".URL").get(),
|
2006-08-15 07:16:10 +00:00
|
|
|
fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
|
2004-05-31 19:46:30 +00:00
|
|
|
nsXPIDLString untitled;
|
|
|
|
if (!GetLocalizedString(NS_LITERAL_STRING("noPageTitle").get(), untitled) ||
|
2004-07-16 07:28:10 +00:00
|
|
|
!CreateFilenameFromTextW(untitled, NS_LITERAL_STRING(".URL").get(),
|
2006-08-15 07:16:10 +00:00
|
|
|
fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
|
2004-07-16 07:28:10 +00:00
|
|
|
wcscpy(fileGroupDescW->fgd[0].cFileName, NS_LITERAL_STRING("Untitled.URL").get());
|
|
|
|
}
|
2004-05-31 19:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// one file in the file block
|
2004-07-16 07:28:10 +00:00
|
|
|
fileGroupDescW->cItems = 1;
|
|
|
|
fileGroupDescW->fgd[0].dwFlags = FD_LINKUI;
|
|
|
|
|
2004-05-31 19:46:30 +00:00
|
|
|
::GlobalUnlock( fileGroupDescHandle );
|
|
|
|
aSTG.hGlobal = fileGroupDescHandle;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
|
|
|
|
return S_OK;
|
2004-07-16 07:28:10 +00:00
|
|
|
} // GetFileDescriptorInternetShortcutW
|
2000-05-02 22:39:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// GetFileContentsInternetShortcut
|
|
|
|
//
|
|
|
|
// Create the special format for an internet shortcut and build up the data
|
|
|
|
// structures the shell is expecting.
|
|
|
|
//
|
|
|
|
HRESULT
|
|
|
|
nsDataObj :: GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG )
|
|
|
|
{
|
2004-05-31 19:46:30 +00:00
|
|
|
nsAutoString url;
|
|
|
|
if ( NS_FAILED(ExtractShortcutURL(url)) )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
// will need to change if we ever support iDNS
|
|
|
|
nsCAutoString asciiUrl;
|
|
|
|
LossyCopyUTF16toASCII(url, asciiUrl);
|
|
|
|
|
2001-10-16 00:27:26 +00:00
|
|
|
static const char* shortcutFormatStr = "[InternetShortcut]\r\nURL=%s\r\n";
|
2001-03-31 05:04:57 +00:00
|
|
|
static const int formatLen = strlen(shortcutFormatStr) - 2; // don't include %s in the len
|
2004-05-31 19:46:30 +00:00
|
|
|
const int totalLen = formatLen + asciiUrl.Length(); // we don't want a null character on the end
|
|
|
|
|
|
|
|
// create a global memory area and build up the file contents w/in it
|
2001-03-31 05:04:57 +00:00
|
|
|
HGLOBAL hGlobalMemory = ::GlobalAlloc(GMEM_SHARE, totalLen);
|
2004-05-31 19:46:30 +00:00
|
|
|
if ( !hGlobalMemory )
|
|
|
|
return E_OUTOFMEMORY;
|
2000-06-09 03:21:01 +00:00
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
char* contents = reinterpret_cast<char*>(::GlobalLock(hGlobalMemory));
|
2004-05-31 19:46:30 +00:00
|
|
|
if ( !contents ) {
|
|
|
|
::GlobalFree( hGlobalMemory );
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
//NOTE: we intentionally use the Microsoft version of snprintf here because it does NOT null
|
|
|
|
// terminate strings which reach the maximum size of the buffer. Since we know that the
|
|
|
|
// formatted length here is totalLen, this call to _snprintf will format the string into
|
|
|
|
// the buffer without appending the null character.
|
|
|
|
_snprintf( contents, totalLen, shortcutFormatStr, asciiUrl.get() );
|
2000-05-02 22:39:08 +00:00
|
|
|
|
2004-05-31 19:46:30 +00:00
|
|
|
::GlobalUnlock(hGlobalMemory);
|
|
|
|
aSTG.hGlobal = hGlobalMemory;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
|
|
|
|
return S_OK;
|
2000-05-02 22:39:08 +00:00
|
|
|
} // GetFileContentsInternetShortcut
|
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
// check if specified flavour is present in the transferable
|
|
|
|
PRBool nsDataObj :: IsFlavourPresent(const char *inFlavour)
|
2000-05-02 22:39:08 +00:00
|
|
|
{
|
|
|
|
PRBool retval = PR_FALSE;
|
2006-08-15 07:16:10 +00:00
|
|
|
NS_ENSURE_TRUE(mTransferable, PR_FALSE);
|
2000-05-02 22:39:08 +00:00
|
|
|
|
|
|
|
// get the list of flavors available in the transferable
|
|
|
|
nsCOMPtr<nsISupportsArray> flavorList;
|
2006-08-15 07:16:10 +00:00
|
|
|
mTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
|
|
|
|
NS_ENSURE_TRUE(flavorList, PR_FALSE);
|
|
|
|
|
|
|
|
// try to find requested flavour
|
2000-05-02 22:39:08 +00:00
|
|
|
PRUint32 cnt;
|
|
|
|
flavorList->Count(&cnt);
|
2006-08-15 07:16:10 +00:00
|
|
|
for (PRUint32 i = 0; i < cnt; ++i) {
|
2000-05-02 22:39:08 +00:00
|
|
|
nsCOMPtr<nsISupports> genericFlavor;
|
|
|
|
flavorList->GetElementAt (i, getter_AddRefs(genericFlavor));
|
2002-08-06 00:53:19 +00:00
|
|
|
nsCOMPtr<nsISupportsCString> currentFlavor (do_QueryInterface(genericFlavor));
|
2000-05-02 22:39:08 +00:00
|
|
|
if (currentFlavor) {
|
2002-08-26 21:20:34 +00:00
|
|
|
nsCAutoString flavorStr;
|
|
|
|
currentFlavor->GetData(flavorStr);
|
2006-08-15 07:16:10 +00:00
|
|
|
if (flavorStr.Equals(inFlavour)) {
|
2000-05-02 22:39:08 +00:00
|
|
|
retval = PR_TRUE; // found it!
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // for each flavor
|
|
|
|
|
|
|
|
return retval;
|
2006-08-15 07:16:10 +00:00
|
|
|
}
|
2000-05-02 22:39:08 +00:00
|
|
|
|
2003-06-06 23:30:47 +00:00
|
|
|
HRESULT nsDataObj::GetPreferredDropEffect ( FORMATETC& aFE, STGMEDIUM& aSTG )
|
|
|
|
{
|
|
|
|
HRESULT res = S_OK;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
aSTG.pUnkForRelease = NULL;
|
|
|
|
HGLOBAL hGlobalMemory = NULL;
|
|
|
|
hGlobalMemory = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(DWORD));
|
|
|
|
if (hGlobalMemory) {
|
2005-08-11 00:37:53 +00:00
|
|
|
DWORD* pdw = (DWORD*) GlobalLock(hGlobalMemory);
|
2003-06-06 23:30:47 +00:00
|
|
|
// The PreferredDropEffect clipboard format is only registered if a drag/drop
|
|
|
|
// of an image happens from Mozilla to the desktop. We want its value
|
|
|
|
// to be DROPEFFECT_MOVE in that case so that the file is moved from the
|
|
|
|
// temporary location, not copied.
|
|
|
|
// This value should, ideally, be set on the data object via SetData() but
|
|
|
|
// our IDataObject implementation doesn't implement SetData. It adds data
|
|
|
|
// to the data object lazily only when the drop target asks for it.
|
|
|
|
*pdw = (DWORD) DROPEFFECT_MOVE;
|
2005-08-11 00:37:53 +00:00
|
|
|
GlobalUnlock(hGlobalMemory);
|
2003-06-06 23:30:47 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
res = E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
aSTG.hGlobal = hGlobalMemory;
|
|
|
|
return res;
|
|
|
|
}
|
2000-05-02 22:39:08 +00:00
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
2002-03-23 22:26:36 +00:00
|
|
|
HRESULT nsDataObj::GetText(const nsACString & aDataFlavor, FORMATETC& aFE, STGMEDIUM& aSTG)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
2006-12-03 10:10:30 +00:00
|
|
|
void* data = NULL;
|
1999-03-23 15:37:34 +00:00
|
|
|
PRUint32 len;
|
1999-08-25 08:35:06 +00:00
|
|
|
|
2000-01-29 20:24:50 +00:00
|
|
|
// if someone asks for text/plain, look up text/unicode instead in the transferable.
|
2001-01-23 01:09:58 +00:00
|
|
|
const char* flavorStr;
|
2001-04-02 19:40:52 +00:00
|
|
|
const nsPromiseFlatCString& flat = PromiseFlatCString(aDataFlavor);
|
2001-01-23 01:09:58 +00:00
|
|
|
if ( aDataFlavor.Equals("text/plain") )
|
2000-01-29 20:24:50 +00:00
|
|
|
flavorStr = kUnicodeMime;
|
|
|
|
else
|
2001-03-08 08:53:58 +00:00
|
|
|
flavorStr = flat.get();
|
1999-03-23 15:37:34 +00:00
|
|
|
|
1999-08-25 08:35:06 +00:00
|
|
|
// NOTE: CreateDataFromPrimitive creates new memory, that needs to be deleted
|
|
|
|
nsCOMPtr<nsISupports> genericDataWrapper;
|
|
|
|
mTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &len);
|
2000-01-29 20:24:50 +00:00
|
|
|
if ( !len )
|
|
|
|
return ResultFromScode(E_FAIL);
|
1999-12-02 23:17:31 +00:00
|
|
|
nsPrimitiveHelpers::CreateDataFromPrimitive ( flavorStr, genericDataWrapper, &data, len );
|
2006-12-03 10:10:30 +00:00
|
|
|
if ( !data )
|
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
HGLOBAL hGlobalMemory = NULL;
|
|
|
|
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
aSTG.pUnkForRelease = NULL;
|
|
|
|
|
2001-02-20 23:27:57 +00:00
|
|
|
// We play games under the hood and advertise flavors that we know we
|
|
|
|
// can support, only they require a bit of conversion or munging of the data.
|
|
|
|
// Do that here.
|
2000-01-29 20:24:50 +00:00
|
|
|
//
|
1999-12-02 23:17:31 +00:00
|
|
|
// The transferable gives us data that is null-terminated, but this isn't reflected in
|
|
|
|
// the |len| parameter. Windoze apps expect this null to be there so bump our data buffer
|
|
|
|
// by the appropriate size to account for the null (one char for CF_TEXT, one PRUnichar for
|
|
|
|
// CF_UNICODETEXT).
|
1999-04-30 19:41:14 +00:00
|
|
|
DWORD allocLen = (DWORD)len;
|
2000-01-29 20:24:50 +00:00
|
|
|
if ( aFE.cfFormat == CF_TEXT ) {
|
2001-02-20 23:27:57 +00:00
|
|
|
// Someone is asking for text/plain; convert the unicode (assuming it's present)
|
|
|
|
// to text with the correct platform encoding.
|
2000-01-29 20:24:50 +00:00
|
|
|
char* plainTextData = nsnull;
|
2007-07-08 07:08:04 +00:00
|
|
|
PRUnichar* castedUnicode = reinterpret_cast<PRUnichar*>(data);
|
2000-01-29 20:24:50 +00:00
|
|
|
PRInt32 plainTextLen = 0;
|
|
|
|
nsPrimitiveHelpers::ConvertUnicodeToPlatformPlainText ( castedUnicode, len / 2, &plainTextData, &plainTextLen );
|
|
|
|
|
|
|
|
// replace the unicode data with our plaintext data. Recall that |plainTextLen| doesn't include
|
|
|
|
// the null in the length.
|
2000-06-03 09:46:12 +00:00
|
|
|
nsMemory::Free(data);
|
2000-01-29 20:24:50 +00:00
|
|
|
if ( plainTextData ) {
|
|
|
|
data = plainTextData;
|
|
|
|
allocLen = plainTextLen + sizeof(char);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_WARNING ( "Oh no, couldn't convert unicode to plain text" );
|
|
|
|
return ResultFromScode(S_OK);
|
|
|
|
}
|
|
|
|
}
|
2002-05-01 21:58:38 +00:00
|
|
|
else if ( aFE.cfFormat == nsClipboard::CF_HTML ) {
|
2001-02-20 23:27:57 +00:00
|
|
|
// Someone is asking for win32's HTML flavor. Convert our html fragment
|
|
|
|
// from unicode to UTF-8 then put it into a format specified by msft.
|
2007-07-08 07:08:04 +00:00
|
|
|
NS_ConvertUTF16toUTF8 converter ( reinterpret_cast<PRUnichar*>(data) );
|
2001-02-20 23:27:57 +00:00
|
|
|
char* utf8HTML = nsnull;
|
|
|
|
nsresult rv = BuildPlatformHTML ( converter.get(), &utf8HTML ); // null terminates
|
|
|
|
|
|
|
|
nsMemory::Free(data);
|
|
|
|
if ( NS_SUCCEEDED(rv) && utf8HTML ) {
|
|
|
|
// replace the unicode data with our HTML data. Don't forget the null.
|
|
|
|
data = utf8HTML;
|
|
|
|
allocLen = strlen(utf8HTML) + sizeof(char);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_WARNING ( "Oh no, couldn't convert to HTML" );
|
|
|
|
return ResultFromScode(S_OK);
|
|
|
|
}
|
|
|
|
}
|
2000-08-17 04:19:14 +00:00
|
|
|
else {
|
2001-02-20 23:27:57 +00:00
|
|
|
// we assume that any data that isn't caught above is unicode. This may
|
2000-08-17 04:19:14 +00:00
|
|
|
// be an erroneous assumption, but is true so far.
|
1999-12-02 23:17:31 +00:00
|
|
|
allocLen += sizeof(PRUnichar);
|
2000-08-17 04:19:14 +00:00
|
|
|
}
|
|
|
|
|
2005-08-11 00:37:53 +00:00
|
|
|
hGlobalMemory = (HGLOBAL)GlobalAlloc(GMEM_MOVEABLE, allocLen);
|
1999-04-30 19:41:14 +00:00
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
// Copy text to Global Memory Area
|
2000-01-29 20:24:50 +00:00
|
|
|
if ( hGlobalMemory ) {
|
2007-07-08 07:08:04 +00:00
|
|
|
char* dest = reinterpret_cast<char*>(GlobalLock(hGlobalMemory));
|
|
|
|
char* source = reinterpret_cast<char*>(data);
|
2000-01-29 20:24:50 +00:00
|
|
|
memcpy ( dest, source, allocLen ); // copies the null as well
|
2005-08-11 00:37:53 +00:00
|
|
|
GlobalUnlock(hGlobalMemory);
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
aSTG.hGlobal = hGlobalMemory;
|
|
|
|
|
2000-01-29 20:24:50 +00:00
|
|
|
// Now, delete the memory that was created by CreateDataFromPrimitive (or our text/plain data)
|
2000-06-03 09:46:12 +00:00
|
|
|
nsMemory::Free(data);
|
1999-07-20 21:02:02 +00:00
|
|
|
|
2000-01-29 20:24:50 +00:00
|
|
|
return ResultFromScode(S_OK);
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
2008-11-14 22:23:02 +00:00
|
|
|
//-----------------------------------------------------
|
|
|
|
HRESULT nsDataObj::GetFile(FORMATETC& aFE, STGMEDIUM& aSTG)
|
|
|
|
{
|
|
|
|
HRESULT res = S_OK;
|
|
|
|
|
|
|
|
// We do not support 'application/x-moz-file-promise' since CF_HDROP does not
|
|
|
|
// allow for delayed rendering of content. We'll need to write the content out emmediately
|
|
|
|
// and return the path to it. Confirm we have support for 'application/x-moz-nativeimage',
|
|
|
|
// if not fail.
|
|
|
|
PRUint32 dfInx = 0;
|
|
|
|
ULONG count;
|
|
|
|
FORMATETC fe;
|
|
|
|
m_enumFE->Reset();
|
|
|
|
PRBool found = PR_FALSE;
|
2009-03-11 02:26:03 +00:00
|
|
|
while (NOERROR == m_enumFE->Next(1, &fe, &count)
|
|
|
|
&& dfInx < mDataFlavors.Length()) {
|
2008-11-14 22:23:02 +00:00
|
|
|
dfInx++;
|
2009-03-11 02:26:03 +00:00
|
|
|
if (mDataFlavors[dfInx].EqualsLiteral(kNativeImageMime)) {
|
2008-11-14 22:23:02 +00:00
|
|
|
found = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
PRUint32 len = 0;
|
|
|
|
nsCOMPtr<nsISupports> genericDataWrapper;
|
|
|
|
|
|
|
|
mTransferable->GetTransferData(kNativeImageMime, getter_AddRefs(genericDataWrapper), &len);
|
|
|
|
nsCOMPtr<nsIImage> image ( do_QueryInterface(genericDataWrapper) );
|
|
|
|
|
|
|
|
if (!image) {
|
|
|
|
// In the 0.9.4 timeframe, I had some embedding clients put the nsIImage directly into the
|
|
|
|
// transferable. Newer code, however, wraps the nsIImage in a nsISupportsInterfacePointer.
|
|
|
|
// We should be backwards compatibile with code already out in the field. If we can't find
|
|
|
|
// the image directly out of the transferable, unwrap the image from its wrapper.
|
|
|
|
nsCOMPtr<nsISupportsInterfacePointer> ptr(do_QueryInterface(genericDataWrapper));
|
|
|
|
if (ptr)
|
|
|
|
ptr->GetData(getter_AddRefs(image));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!image)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
// Use the clipboard helper class to build up a memory bitmap.
|
|
|
|
nsImageToClipboard converter(image);
|
|
|
|
HANDLE bits = nsnull;
|
|
|
|
rv = converter.GetPicture(&bits); // Clipboard routines return a global handle we own.
|
|
|
|
|
|
|
|
if (NS_FAILED(rv) || !bits)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
// We now own these bits!
|
|
|
|
PRUint32 bitmapSize = GlobalSize(bits);
|
|
|
|
if (!bitmapSize) {
|
|
|
|
GlobalFree(bits);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCachedTempFile) {
|
|
|
|
mCachedTempFile->Remove(PR_FALSE);
|
|
|
|
mCachedTempFile = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save the bitmap to a temporary location.
|
|
|
|
nsCOMPtr<nsIFile> dropFile;
|
|
|
|
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(dropFile));
|
|
|
|
if (!dropFile)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
// Filename must be random so as not to confuse apps like Photshop which handle
|
|
|
|
// multiple drags into a single window.
|
|
|
|
char buf[13];
|
|
|
|
nsCString filename;
|
|
|
|
MakeRandomString(buf, 8);
|
|
|
|
memcpy(buf+8, ".bmp", 5);
|
|
|
|
filename.Append(nsDependentCString(buf, 12));
|
|
|
|
dropFile->AppendNative(filename);
|
|
|
|
rv = dropFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0660);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
GlobalFree(bits);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cache the temp file so we can delete it later.
|
|
|
|
dropFile->Clone(getter_AddRefs(mCachedTempFile));
|
|
|
|
|
|
|
|
// Write the data to disk.
|
|
|
|
nsCOMPtr<nsIOutputStream> outStream;
|
|
|
|
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), dropFile);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
GlobalFree(bits);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char * bm = (char *)GlobalLock(bits);
|
|
|
|
|
|
|
|
BITMAPFILEHEADER fileHdr;
|
|
|
|
BITMAPINFOHEADER *bmpHdr = (BITMAPINFOHEADER*)bm;
|
|
|
|
|
|
|
|
fileHdr.bfType = ((WORD) ('M' << 8) | 'B');
|
|
|
|
fileHdr.bfSize = GlobalSize (bits) + sizeof(fileHdr);
|
|
|
|
fileHdr.bfReserved1 = 0;
|
|
|
|
fileHdr.bfReserved2 = 0;
|
|
|
|
fileHdr.bfOffBits = (DWORD) (sizeof(fileHdr) + bmpHdr->biSize);
|
|
|
|
|
|
|
|
PRUint32 writeCount = 0;
|
|
|
|
if (NS_FAILED(outStream->Write((const char *)&fileHdr, sizeof(fileHdr), &writeCount)) ||
|
|
|
|
NS_FAILED(outStream->Write((const char *)bm, bitmapSize, &writeCount)))
|
|
|
|
rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
outStream->Close();
|
|
|
|
|
|
|
|
GlobalUnlock(bits);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
GlobalFree(bits);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobalFree(bits);
|
|
|
|
|
|
|
|
// Pass the file name back to the drop target so that it can access the file.
|
|
|
|
nsAutoString path;
|
|
|
|
rv = mCachedTempFile->GetPath(path);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
// Two null characters are needed to terminate the file name list.
|
|
|
|
HGLOBAL hGlobalMemory = NULL;
|
|
|
|
|
|
|
|
PRUint32 allocLen = path.Length() + 2;
|
|
|
|
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
aSTG.pUnkForRelease = NULL;
|
|
|
|
|
|
|
|
hGlobalMemory = GlobalAlloc(GMEM_MOVEABLE, sizeof(DROPFILES) + allocLen * sizeof(PRUnichar));
|
|
|
|
if (!hGlobalMemory)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
DROPFILES* pDropFile = (DROPFILES*)GlobalLock(hGlobalMemory);
|
|
|
|
|
|
|
|
// First, populate the drop file structure.
|
|
|
|
pDropFile->pFiles = sizeof(DROPFILES); // Offset to start of file name char array.
|
|
|
|
pDropFile->fNC = 0;
|
|
|
|
pDropFile->pt.x = 0;
|
|
|
|
pDropFile->pt.y = 0;
|
|
|
|
pDropFile->fWide = TRUE;
|
|
|
|
|
|
|
|
// Copy the filename right after the DROPFILES structure.
|
|
|
|
PRUnichar* dest = (PRUnichar*)(((char*)pDropFile) + pDropFile->pFiles);
|
|
|
|
memcpy(dest, path.get(), (allocLen - 1) * sizeof(PRUnichar)); // Copies the null character in path as well.
|
|
|
|
|
|
|
|
// Two null characters are needed at the end of the file name.
|
|
|
|
// Lookup the CF_HDROP shell clipboard format for more info.
|
|
|
|
// Add the second null character right after the first one.
|
|
|
|
dest[allocLen - 1] = L'\0';
|
|
|
|
|
|
|
|
GlobalUnlock(hGlobalMemory);
|
|
|
|
|
|
|
|
aSTG.hGlobal = hGlobalMemory;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
HRESULT nsDataObj::GetMetafilePict(FORMATETC&, STGMEDIUM&)
|
|
|
|
{
|
|
|
|
return ResultFromScode(E_NOTIMPL);
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
HRESULT nsDataObj::SetBitmap(FORMATETC&, STGMEDIUM&)
|
|
|
|
{
|
|
|
|
return ResultFromScode(E_NOTIMPL);
|
|
|
|
}
|
1999-05-04 22:44:16 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------
|
2007-11-17 04:31:32 +00:00
|
|
|
HRESULT nsDataObj::SetDib(FORMATETC&, STGMEDIUM&)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
HRESULT nsDataObj::SetText (FORMATETC& aFE, STGMEDIUM& aSTG)
|
|
|
|
{
|
|
|
|
if (aFE.cfFormat == CF_TEXT && aFE.tymed == TYMED_HGLOBAL) {
|
|
|
|
HGLOBAL hString = (HGLOBAL)aSTG.hGlobal;
|
|
|
|
if(hString == NULL)
|
|
|
|
return(FALSE);
|
|
|
|
|
|
|
|
// get a pointer to the actual bytes
|
|
|
|
char * pString = (char *) GlobalLock(hString);
|
|
|
|
if(!pString)
|
|
|
|
return(FALSE);
|
|
|
|
|
|
|
|
GlobalUnlock(hString);
|
2000-04-26 01:13:55 +00:00
|
|
|
nsAutoString str; str.AssignWithConversion(pString);
|
1999-03-23 15:37:34 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
2007-11-17 04:31:32 +00:00
|
|
|
HRESULT nsDataObj::SetMetafilePict(FORMATETC&, STGMEDIUM&)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
|
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
CLSID nsDataObj::GetClassID() const
|
|
|
|
{
|
|
|
|
return CLSID_nsDataObj;
|
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
2008-09-06 16:24:45 +00:00
|
|
|
// Registers the DataFlavor/FE pair.
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
1999-09-04 20:04:26 +00:00
|
|
|
void nsDataObj::AddDataFlavor(const char* aDataFlavor, LPFORMATETC aFE)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
2008-09-06 16:24:45 +00:00
|
|
|
// These two lists are the mapping to and from data flavors and FEs.
|
2008-11-14 22:23:02 +00:00
|
|
|
// Later, OLE will tell us it needs a certain type of FORMATETC (text, unicode, etc)
|
2008-09-06 16:24:45 +00:00
|
|
|
// unicode, etc), so we will look up the data flavor that corresponds to
|
|
|
|
// the FE and then ask the transferable for that type of data.
|
2009-03-11 02:26:03 +00:00
|
|
|
mDataFlavors.AppendElement(aDataFlavor);
|
2008-11-14 22:23:02 +00:00
|
|
|
m_enumFE->AddFE(aFE);
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-05-04 22:44:16 +00:00
|
|
|
//-----------------------------------------------------
|
|
|
|
// Sets the transferable object
|
|
|
|
//-----------------------------------------------------
|
1999-03-23 15:37:34 +00:00
|
|
|
void nsDataObj::SetTransferable(nsITransferable * aTransferable)
|
|
|
|
{
|
1999-05-04 22:44:16 +00:00
|
|
|
NS_IF_RELEASE(mTransferable);
|
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
mTransferable = aTransferable;
|
|
|
|
if (nsnull == mTransferable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ADDREF(mTransferable);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
1999-08-25 08:35:06 +00:00
|
|
|
|
2000-06-05 00:34:11 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// ExtractURL
|
|
|
|
//
|
|
|
|
// Roots around in the transferable for the appropriate flavor that indicates
|
2000-06-09 03:21:01 +00:00
|
|
|
// a url and pulls out the url portion of the data. Used mostly for creating
|
|
|
|
// internet shortcuts on the desktop. The url flavor is of the format:
|
|
|
|
//
|
2001-03-31 05:04:57 +00:00
|
|
|
// <url> <linefeed> <page title>
|
2000-06-05 00:34:11 +00:00
|
|
|
//
|
|
|
|
nsresult
|
2000-06-09 03:21:01 +00:00
|
|
|
nsDataObj :: ExtractShortcutURL ( nsString & outURL )
|
2000-06-05 00:34:11 +00:00
|
|
|
{
|
2006-04-21 15:16:22 +00:00
|
|
|
NS_ASSERTION ( mTransferable, "We don't have a good transferable" );
|
2000-06-05 00:34:11 +00:00
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
PRUint32 len = 0;
|
|
|
|
nsCOMPtr<nsISupports> genericURL;
|
|
|
|
if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL), &len)) ) {
|
2002-08-06 00:53:19 +00:00
|
|
|
nsCOMPtr<nsISupportsString> urlObject ( do_QueryInterface(genericURL) );
|
2000-06-05 00:34:11 +00:00
|
|
|
if ( urlObject ) {
|
2002-08-26 21:20:34 +00:00
|
|
|
nsAutoString url;
|
|
|
|
urlObject->GetData ( url );
|
2000-06-05 00:34:11 +00:00
|
|
|
outURL = url;
|
2000-06-09 03:21:01 +00:00
|
|
|
|
2001-03-31 05:04:57 +00:00
|
|
|
// find the first linefeed in the data, that's where the url ends. trunc the
|
2000-06-09 03:21:01 +00:00
|
|
|
// result string at that point.
|
2001-03-31 05:04:57 +00:00
|
|
|
PRInt32 lineIndex = outURL.FindChar ( '\n' );
|
|
|
|
NS_ASSERTION ( lineIndex > 0, "Format for url flavor is <url> <linefeed> <page title>" );
|
|
|
|
if ( lineIndex > 0 ) {
|
|
|
|
outURL.Truncate ( lineIndex );
|
2000-06-09 03:21:01 +00:00
|
|
|
rv = NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2006-06-12 17:30:22 +00:00
|
|
|
} else if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLDataMime, getter_AddRefs(genericURL), &len)) ||
|
|
|
|
NS_SUCCEEDED(mTransferable->GetTransferData(kURLPrivateMime, getter_AddRefs(genericURL), &len)) ) {
|
2006-04-21 15:16:22 +00:00
|
|
|
nsCOMPtr<nsISupportsString> urlObject ( do_QueryInterface(genericURL) );
|
|
|
|
if ( urlObject ) {
|
|
|
|
nsAutoString url;
|
|
|
|
urlObject->GetData ( url );
|
|
|
|
outURL = url;
|
|
|
|
|
|
|
|
rv = NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // if found flavor
|
2000-06-09 03:21:01 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
} // ExtractShortcutURL
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// ExtractShortcutTitle
|
|
|
|
//
|
|
|
|
// Roots around in the transferable for the appropriate flavor that indicates
|
|
|
|
// a url and pulls out the title portion of the data. Used mostly for creating
|
|
|
|
// internet shortcuts on the desktop. The url flavor is of the format:
|
|
|
|
//
|
2001-03-31 05:04:57 +00:00
|
|
|
// <url> <linefeed> <page title>
|
2000-06-09 03:21:01 +00:00
|
|
|
//
|
|
|
|
nsresult
|
|
|
|
nsDataObj :: ExtractShortcutTitle ( nsString & outTitle )
|
|
|
|
{
|
|
|
|
NS_ASSERTION ( mTransferable, "We'd don't have a good transferable" );
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
PRUint32 len = 0;
|
|
|
|
nsCOMPtr<nsISupports> genericURL;
|
|
|
|
if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL), &len)) ) {
|
2002-08-06 00:53:19 +00:00
|
|
|
nsCOMPtr<nsISupportsString> urlObject ( do_QueryInterface(genericURL) );
|
2000-06-09 03:21:01 +00:00
|
|
|
if ( urlObject ) {
|
2002-08-26 21:20:34 +00:00
|
|
|
nsAutoString url;
|
|
|
|
urlObject->GetData ( url );
|
2000-06-09 03:21:01 +00:00
|
|
|
|
2001-03-31 05:04:57 +00:00
|
|
|
// find the first linefeed in the data, that's where the url ends. we want
|
|
|
|
// everything after that linefeed. FindChar() returns -1 if we can't find
|
2002-08-26 21:20:34 +00:00
|
|
|
PRInt32 lineIndex = url.FindChar ( '\n' );
|
2001-03-31 05:04:57 +00:00
|
|
|
NS_ASSERTION ( lineIndex != -1, "Format for url flavor is <url> <linefeed> <page title>" );
|
|
|
|
if ( lineIndex != -1 ) {
|
2002-08-26 21:20:34 +00:00
|
|
|
url.Mid ( outTitle, lineIndex + 1, (len/2) - (lineIndex + 1) );
|
2000-06-09 03:21:01 +00:00
|
|
|
rv = NS_OK;
|
|
|
|
}
|
2000-06-05 00:34:11 +00:00
|
|
|
}
|
|
|
|
} // if found flavor
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
2000-10-27 22:43:51 +00:00
|
|
|
} // ExtractShortcutTitle
|
2001-02-20 23:27:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// BuildPlatformHTML
|
|
|
|
//
|
|
|
|
// Munge our HTML data to win32's CF_HTML spec. Basically, put the requisite
|
|
|
|
// header information on it. This will null terminate |outPlatformHTML|. See
|
|
|
|
// http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp
|
|
|
|
// for details.
|
|
|
|
//
|
|
|
|
// We assume that |inOurHTML| is already a fragment (ie, doesn't have <HTML>
|
|
|
|
// or <BODY> tags). We'll wrap the fragment with them to make other apps
|
|
|
|
// happy.
|
|
|
|
//
|
|
|
|
nsresult
|
|
|
|
nsDataObj :: BuildPlatformHTML ( const char* inOurHTML, char** outPlatformHTML )
|
|
|
|
{
|
|
|
|
*outPlatformHTML = nsnull;
|
2004-10-25 06:15:52 +00:00
|
|
|
|
|
|
|
nsDependentCString inHTMLString(inOurHTML);
|
|
|
|
const char* const numPlaceholder = "00000000";
|
|
|
|
const char* const startHTMLPrefix = "Version:0.9\r\nStartHTML:";
|
|
|
|
const char* const endHTMLPrefix = "\r\nEndHTML:";
|
|
|
|
const char* const startFragPrefix = "\r\nStartFragment:";
|
|
|
|
const char* const endFragPrefix = "\r\nEndFragment:";
|
2004-12-07 14:13:54 +00:00
|
|
|
const char* const startSourceURLPrefix = "\r\nSourceURL:";
|
2004-10-25 06:15:52 +00:00
|
|
|
const char* const endFragTrailer = "\r\n";
|
|
|
|
|
2004-12-07 14:13:54 +00:00
|
|
|
// Do we already have mSourceURL from a drag?
|
|
|
|
if (mSourceURL.IsEmpty()) {
|
|
|
|
nsAutoString url;
|
|
|
|
ExtractShortcutURL(url);
|
|
|
|
|
|
|
|
AppendUTF16toUTF8(url, mSourceURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
const PRInt32 kSourceURLLength = mSourceURL.Length();
|
2004-10-25 06:15:52 +00:00
|
|
|
const PRInt32 kNumberLength = strlen(numPlaceholder);
|
|
|
|
|
|
|
|
const PRInt32 kTotalHeaderLen = strlen(startHTMLPrefix) +
|
|
|
|
strlen(endHTMLPrefix) +
|
|
|
|
strlen(startFragPrefix) +
|
|
|
|
strlen(endFragPrefix) +
|
|
|
|
strlen(endFragTrailer) +
|
2004-12-07 14:13:54 +00:00
|
|
|
(kSourceURLLength > 0 ? strlen(startSourceURLPrefix) : 0) +
|
|
|
|
kSourceURLLength +
|
2004-10-25 06:15:52 +00:00
|
|
|
(4 * kNumberLength);
|
|
|
|
|
|
|
|
NS_NAMED_LITERAL_CSTRING(htmlHeaderString, "<html><body>\r\n");
|
|
|
|
|
|
|
|
NS_NAMED_LITERAL_CSTRING(fragmentHeaderString, "<!--StartFragment-->");
|
|
|
|
|
|
|
|
nsDependentCString trailingString(
|
2001-02-20 23:27:57 +00:00
|
|
|
"<!--EndFragment-->\r\n"
|
|
|
|
"</body>\r\n"
|
|
|
|
"</html>");
|
|
|
|
|
2004-10-25 06:15:52 +00:00
|
|
|
// calculate the offsets
|
|
|
|
PRInt32 startHTMLOffset = kTotalHeaderLen;
|
|
|
|
PRInt32 startFragOffset = startHTMLOffset
|
|
|
|
+ htmlHeaderString.Length()
|
|
|
|
+ fragmentHeaderString.Length();
|
|
|
|
|
|
|
|
PRInt32 endFragOffset = startFragOffset
|
|
|
|
+ inHTMLString.Length();
|
|
|
|
|
|
|
|
PRInt32 endHTMLOffset = endFragOffset
|
|
|
|
+ trailingString.Length();
|
|
|
|
|
|
|
|
// now build the final version
|
|
|
|
nsCString clipboardString;
|
|
|
|
clipboardString.SetCapacity(endHTMLOffset);
|
|
|
|
|
|
|
|
clipboardString.Append(startHTMLPrefix);
|
|
|
|
clipboardString.Append(nsPrintfCString("%08u", startHTMLOffset));
|
|
|
|
|
|
|
|
clipboardString.Append(endHTMLPrefix);
|
|
|
|
clipboardString.Append(nsPrintfCString("%08u", endHTMLOffset));
|
|
|
|
|
|
|
|
clipboardString.Append(startFragPrefix);
|
|
|
|
clipboardString.Append(nsPrintfCString("%08u", startFragOffset));
|
2001-02-20 23:27:57 +00:00
|
|
|
|
2004-10-25 06:15:52 +00:00
|
|
|
clipboardString.Append(endFragPrefix);
|
|
|
|
clipboardString.Append(nsPrintfCString("%08u", endFragOffset));
|
2001-02-20 23:27:57 +00:00
|
|
|
|
2005-07-25 21:06:35 +00:00
|
|
|
if (kSourceURLLength > 0) {
|
|
|
|
clipboardString.Append(startSourceURLPrefix);
|
|
|
|
clipboardString.Append(mSourceURL);
|
|
|
|
}
|
2004-12-07 14:13:54 +00:00
|
|
|
|
2004-10-25 06:15:52 +00:00
|
|
|
clipboardString.Append(endFragTrailer);
|
2001-02-20 23:27:57 +00:00
|
|
|
|
2004-10-25 06:15:52 +00:00
|
|
|
clipboardString.Append(htmlHeaderString);
|
|
|
|
clipboardString.Append(fragmentHeaderString);
|
|
|
|
clipboardString.Append(inHTMLString);
|
|
|
|
clipboardString.Append(trailingString);
|
2001-02-20 23:27:57 +00:00
|
|
|
|
2004-10-25 06:15:52 +00:00
|
|
|
*outPlatformHTML = ToNewCString(clipboardString);
|
|
|
|
if (!*outPlatformHTML)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2001-02-20 23:27:57 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-11-05 12:51:39 +00:00
|
|
|
|
|
|
|
HRESULT
|
2004-07-16 07:28:10 +00:00
|
|
|
nsDataObj :: GetUniformResourceLocator( FORMATETC& aFE, STGMEDIUM& aSTG, PRBool aIsUnicode )
|
2002-11-05 12:51:39 +00:00
|
|
|
{
|
|
|
|
HRESULT res = S_OK;
|
2006-08-15 07:16:10 +00:00
|
|
|
if (IsFlavourPresent(kURLMime)) {
|
2004-07-16 07:28:10 +00:00
|
|
|
if ( aIsUnicode )
|
|
|
|
res = ExtractUniformResourceLocatorW( aFE, aSTG );
|
|
|
|
else
|
|
|
|
res = ExtractUniformResourceLocatorA( aFE, aSTG );
|
2002-11-05 12:51:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
NS_WARNING ("Not yet implemented\n");
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
2004-07-16 07:28:10 +00:00
|
|
|
nsDataObj::ExtractUniformResourceLocatorA(FORMATETC& aFE, STGMEDIUM& aSTG )
|
2002-11-05 12:51:39 +00:00
|
|
|
{
|
|
|
|
HRESULT result = S_OK;
|
2004-07-16 07:28:10 +00:00
|
|
|
|
2002-11-05 12:51:39 +00:00
|
|
|
nsAutoString url;
|
|
|
|
if (NS_FAILED(ExtractShortcutURL(url)))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
NS_LossyConvertUTF16toASCII asciiUrl(url);
|
|
|
|
const int totalLen = asciiUrl.Length() + 1;
|
2005-08-11 00:37:53 +00:00
|
|
|
HGLOBAL hGlobalMemory = GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE, totalLen);
|
2004-07-16 07:28:10 +00:00
|
|
|
if (!hGlobalMemory)
|
|
|
|
return E_OUTOFMEMORY;
|
2002-11-05 12:51:39 +00:00
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
char* contents = reinterpret_cast<char*>(GlobalLock(hGlobalMemory));
|
2004-07-16 07:28:10 +00:00
|
|
|
if (!contents) {
|
2005-08-11 00:37:53 +00:00
|
|
|
GlobalFree(hGlobalMemory);
|
2004-07-16 07:28:10 +00:00
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(contents, asciiUrl.get());
|
2005-08-11 00:37:53 +00:00
|
|
|
GlobalUnlock(hGlobalMemory);
|
2004-07-16 07:28:10 +00:00
|
|
|
aSTG.hGlobal = hGlobalMemory;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
2002-11-05 12:51:39 +00:00
|
|
|
|
2004-07-16 07:28:10 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
|
|
nsDataObj::ExtractUniformResourceLocatorW(FORMATETC& aFE, STGMEDIUM& aSTG )
|
|
|
|
{
|
|
|
|
HRESULT result = S_OK;
|
|
|
|
|
|
|
|
nsAutoString url;
|
|
|
|
if (NS_FAILED(ExtractShortcutURL(url)))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
const int totalLen = (url.Length() + 1) * sizeof(PRUnichar);
|
2005-08-11 00:37:53 +00:00
|
|
|
HGLOBAL hGlobalMemory = GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE, totalLen);
|
2004-07-16 07:28:10 +00:00
|
|
|
if (!hGlobalMemory)
|
|
|
|
return E_OUTOFMEMORY;
|
2002-11-05 12:51:39 +00:00
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
wchar_t* contents = reinterpret_cast<wchar_t*>(GlobalLock(hGlobalMemory));
|
2004-07-16 07:28:10 +00:00
|
|
|
if (!contents) {
|
2005-08-11 00:37:53 +00:00
|
|
|
GlobalFree(hGlobalMemory);
|
2004-07-16 07:28:10 +00:00
|
|
|
return E_OUTOFMEMORY;
|
2002-11-05 12:51:39 +00:00
|
|
|
}
|
2004-07-16 07:28:10 +00:00
|
|
|
|
|
|
|
wcscpy(contents, url.get());
|
2005-08-11 00:37:53 +00:00
|
|
|
GlobalUnlock(hGlobalMemory);
|
2004-07-16 07:28:10 +00:00
|
|
|
aSTG.hGlobal = hGlobalMemory;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
|
2002-11-05 12:51:39 +00:00
|
|
|
return result;
|
|
|
|
}
|
2006-02-20 20:48:35 +00:00
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
|
2006-02-20 20:48:35 +00:00
|
|
|
// Gets the filename from the kFilePromiseURLMime flavour
|
2006-08-15 07:16:10 +00:00
|
|
|
nsresult nsDataObj::GetDownloadDetails(nsIURI **aSourceURI,
|
2006-02-20 20:48:35 +00:00
|
|
|
nsAString &aFilename)
|
|
|
|
{
|
2008-04-03 11:33:06 +00:00
|
|
|
*aSourceURI = nsnull;
|
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
NS_ENSURE_TRUE(mTransferable, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
// get the URI from the kFilePromiseURLMime flavor
|
|
|
|
nsCOMPtr<nsISupports> urlPrimitive;
|
|
|
|
PRUint32 dataSize = 0;
|
|
|
|
mTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize);
|
|
|
|
nsCOMPtr<nsISupportsString> srcUrlPrimitive = do_QueryInterface(urlPrimitive);
|
|
|
|
NS_ENSURE_TRUE(srcUrlPrimitive, NS_ERROR_FAILURE);
|
|
|
|
|
2008-04-03 11:33:06 +00:00
|
|
|
nsAutoString srcUri;
|
|
|
|
srcUrlPrimitive->GetData(srcUri);
|
|
|
|
if (srcUri.IsEmpty())
|
2006-08-15 07:16:10 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIURI> sourceURI;
|
2008-04-03 11:33:06 +00:00
|
|
|
NS_NewURI(getter_AddRefs(sourceURI), srcUri);
|
|
|
|
|
|
|
|
nsAutoString srcFileName;
|
|
|
|
nsCOMPtr<nsISupports> fileNamePrimitive;
|
|
|
|
mTransferable->GetTransferData(kFilePromiseDestFilename, getter_AddRefs(fileNamePrimitive), &dataSize);
|
|
|
|
nsCOMPtr<nsISupportsString> srcFileNamePrimitive = do_QueryInterface(fileNamePrimitive);
|
|
|
|
if (srcFileNamePrimitive) {
|
|
|
|
srcFileNamePrimitive->GetData(srcFileName);
|
2006-08-15 07:16:10 +00:00
|
|
|
} else {
|
2008-04-03 11:33:06 +00:00
|
|
|
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
|
|
|
|
if (!sourceURL)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsCAutoString urlFileName;
|
|
|
|
sourceURL->GetFileName(urlFileName);
|
|
|
|
NS_UnescapeURL(urlFileName);
|
|
|
|
CopyUTF8toUTF16(urlFileName, srcFileName);
|
2006-08-15 07:16:10 +00:00
|
|
|
}
|
2008-04-03 11:33:06 +00:00
|
|
|
if (srcFileName.IsEmpty())
|
2006-08-15 07:16:10 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2006-07-13 10:30:28 +00:00
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
// make the name safe for the filesystem
|
2008-04-03 11:33:06 +00:00
|
|
|
MangleTextToValidFilename(srcFileName);
|
2006-07-13 10:30:28 +00:00
|
|
|
|
2008-04-03 11:33:06 +00:00
|
|
|
sourceURI.swap(*aSourceURI);
|
|
|
|
aFilename = srcFileName;
|
2006-08-15 07:16:10 +00:00
|
|
|
return NS_OK;
|
2006-07-13 10:30:28 +00:00
|
|
|
}
|
|
|
|
|
2006-08-15 07:16:10 +00:00
|
|
|
HRESULT nsDataObj::GetFileDescriptor_IStreamA(FORMATETC& aFE, STGMEDIUM& aSTG)
|
|
|
|
{
|
|
|
|
HGLOBAL fileGroupDescHandle = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE,sizeof(FILEGROUPDESCRIPTORW));
|
|
|
|
NS_ENSURE_TRUE(fileGroupDescHandle, E_OUTOFMEMORY);
|
|
|
|
|
2008-02-21 20:57:22 +00:00
|
|
|
LPFILEGROUPDESCRIPTORA fileGroupDescA = reinterpret_cast<LPFILEGROUPDESCRIPTORA>(GlobalLock(fileGroupDescHandle));
|
2006-08-15 07:16:10 +00:00
|
|
|
if (!fileGroupDescA) {
|
|
|
|
::GlobalFree(fileGroupDescHandle);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString wideFileName;
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIURI> sourceURI;
|
|
|
|
rv = GetDownloadDetails(getter_AddRefs(sourceURI),
|
|
|
|
wideFileName);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
::GlobalFree(fileGroupDescHandle);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCAutoString nativeFileName;
|
|
|
|
NS_UTF16ToCString(wideFileName, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM, nativeFileName);
|
|
|
|
|
|
|
|
strncpy(fileGroupDescA->fgd[0].cFileName, nativeFileName.get(), NS_MAX_FILEDESCRIPTOR - 1);
|
|
|
|
fileGroupDescA->fgd[0].cFileName[NS_MAX_FILEDESCRIPTOR - 1] = '\0';
|
|
|
|
|
|
|
|
// one file in the file block
|
|
|
|
fileGroupDescA->cItems = 1;
|
|
|
|
fileGroupDescA->fgd[0].dwFlags = FD_PROGRESSUI;
|
|
|
|
|
2008-02-21 20:57:22 +00:00
|
|
|
GlobalUnlock( fileGroupDescHandle );
|
2006-08-15 07:16:10 +00:00
|
|
|
aSTG.hGlobal = fileGroupDescHandle;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT nsDataObj::GetFileDescriptor_IStreamW(FORMATETC& aFE, STGMEDIUM& aSTG)
|
|
|
|
{
|
|
|
|
HGLOBAL fileGroupDescHandle = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE,sizeof(FILEGROUPDESCRIPTORW));
|
|
|
|
NS_ENSURE_TRUE(fileGroupDescHandle, E_OUTOFMEMORY);
|
|
|
|
|
2008-02-21 20:57:22 +00:00
|
|
|
LPFILEGROUPDESCRIPTORW fileGroupDescW = reinterpret_cast<LPFILEGROUPDESCRIPTORW>(GlobalLock(fileGroupDescHandle));
|
2006-08-15 07:16:10 +00:00
|
|
|
if (!fileGroupDescW) {
|
|
|
|
::GlobalFree(fileGroupDescHandle);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString wideFileName;
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIURI> sourceURI;
|
|
|
|
rv = GetDownloadDetails(getter_AddRefs(sourceURI),
|
|
|
|
wideFileName);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
::GlobalFree(fileGroupDescHandle);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
wcsncpy(fileGroupDescW->fgd[0].cFileName, wideFileName.get(), NS_MAX_FILEDESCRIPTOR - 1);
|
|
|
|
fileGroupDescW->fgd[0].cFileName[NS_MAX_FILEDESCRIPTOR - 1] = '\0';
|
|
|
|
// one file in the file block
|
|
|
|
fileGroupDescW->cItems = 1;
|
|
|
|
fileGroupDescW->fgd[0].dwFlags = FD_PROGRESSUI;
|
|
|
|
|
2008-02-21 20:57:22 +00:00
|
|
|
GlobalUnlock(fileGroupDescHandle);
|
2006-08-15 07:16:10 +00:00
|
|
|
aSTG.hGlobal = fileGroupDescHandle;
|
|
|
|
aSTG.tymed = TYMED_HGLOBAL;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT nsDataObj::GetFileContents_IStream(FORMATETC& aFE, STGMEDIUM& aSTG)
|
|
|
|
{
|
|
|
|
IStream *pStream = NULL;
|
|
|
|
|
|
|
|
nsDataObj::CreateStream(&pStream);
|
|
|
|
NS_ENSURE_TRUE(pStream, E_FAIL);
|
|
|
|
|
|
|
|
aSTG.tymed = TYMED_ISTREAM;
|
|
|
|
aSTG.pstm = pStream;
|
|
|
|
aSTG.pUnkForRelease = pStream;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|