diff --git a/mozilla/widget/src/windows/nsDataObj.cpp b/mozilla/widget/src/windows/nsDataObj.cpp index 55154fe5294..650af724589 100644 --- a/mozilla/widget/src/windows/nsDataObj.cpp +++ b/mozilla/widget/src/windows/nsDataObj.cpp @@ -68,6 +68,14 @@ #include "nsEscape.h" #include "nsIURL.h" #include "nsNetUtil.h" +#include "nsXPCOMStrings.h" + +// 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 #if 0 #define PRNTDEBUG(_x) printf(_x); @@ -79,6 +87,186 @@ #define PRNTDEBUG3(_x1, _x2, _x3) // printf(_x1, _x2, _x3); #endif +//----------------------------------------------------------------------------- +// 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; + PRUint32 read = 0; + rv = mInputStream->Read((char*)pvBuffer, nBytesToRead, &read); + *nBytesRead = read; + NS_ENSURE_SUCCESS(rv, S_FALSE); + + return S_OK; +} + +//----------------------------------------------------------------------------- +STDMETHODIMP nsDataObj::CStream::Revert(void) +{ + return E_NOTIMPL; +} + +//----------------------------------------------------------------------------- +STDMETHODIMP nsDataObj::CStream::Seek(LARGE_INTEGER nMove, + DWORD dwOrigin, + ULARGE_INTEGER* nNewPos) +{ + return E_NOTIMPL; +} + +//----------------------------------------------------------------------------- +STDMETHODIMP nsDataObj::CStream::SetSize(ULARGE_INTEGER nNewSize) +{ + return E_NOTIMPL; +} + +//----------------------------------------------------------------------------- +STDMETHODIMP nsDataObj::CStream::Stat(STATSTG* statstg, DWORD dwFlags) +{ + return E_NOTIMPL; +} + +//----------------------------------------------------------------------------- +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 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; +} + ULONG nsDataObj::g_cRef = 0; EXTERN_C GUID CDECL CLSID_nsDataObj = @@ -113,6 +301,9 @@ nsDataObj::nsDataObj(nsIURI * uri) // so it can create a SourceURL for CF_HTML flavour uri->GetSpec(mSourceURL); } + + mIsAsyncMode = FALSE; + mIsInOperation = FALSE; } //----------------------------------------------------- // destruction @@ -144,8 +335,12 @@ STDMETHODIMP nsDataObj::QueryInterface(REFIID riid, void** ppv) if ( (IID_IUnknown == riid) || (IID_IDataObject == riid) ) { *ppv = this; AddRef(); - return NOERROR; - } + return S_OK; + } else if (IID_IAsyncOperation == riid) { + *ppv = static_cast(this); + AddRef(); + return S_OK; + } return ResultFromScode(E_NOINTERFACE); } @@ -225,11 +420,7 @@ STDMETHODIMP nsDataObj::GetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM) case CF_TEXT: case CF_UNICODETEXT: return GetText(*df, *pFE, *pSTM); - -#ifndef WINCE - case CF_HDROP: - return GetFile(*df, *pFE, *pSTM); -#endif + // Someone is asking for an image case CF_DIB: return GetDib(*df, *pFE, *pSTM); @@ -382,6 +573,48 @@ STDMETHODIMP nsDataObj::EnumDAdvise(LPENUMSTATDATA *ppEnum) return ResultFromScode(E_FAIL); } +// 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; +} + //----------------------------------------------------- // other methods //----------------------------------------------------- @@ -480,12 +713,21 @@ nsDataObj :: GetFileDescriptor ( FORMATETC& aFE, STGMEDIUM& aSTG, PRBool aIsUnic // How we handle this depends on if we're dealing with an internet // shortcut, since those are done under the covers. - if ( IsInternetShortcut() ) { + if (IsFlavourPresent(kFilePromiseMime) || + IsFlavourPresent(kFileMime)) + { + if (aIsUnicode) + return GetFileDescriptor_IStreamW(aFE, aSTG); + else + return GetFileDescriptor_IStreamA(aFE, aSTG); + } + else if (IsFlavourPresent(kURLMime)) + { if ( aIsUnicode ) res = GetFileDescriptorInternetShortcutW ( aFE, aSTG ); else res = GetFileDescriptorInternetShortcutA ( aFE, aSTG ); - } + } else NS_WARNING ( "Not yet implemented\n" ); @@ -502,8 +744,11 @@ nsDataObj :: GetFileContents ( FORMATETC& aFE, STGMEDIUM& aSTG ) // How we handle this depends on if we're dealing with an internet // shortcut, since those are done under the covers. - if ( IsInternetShortcut() ) - res = GetFileContentsInternetShortcut ( aFE, aSTG ); + if (IsFlavourPresent(kFilePromiseMime) || + IsFlavourPresent(kFileMime)) + return GetFileContents_IStream(aFE, aSTG); + else if (IsFlavourPresent(kURLMime)) + return GetFileContentsInternetShortcut ( aFE, aSTG ); else NS_WARNING ( "Not yet implemented\n" ); @@ -654,11 +899,11 @@ nsDataObj :: GetFileDescriptorInternetShortcutA ( FORMATETC& aFE, STGMEDIUM& aST // 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", - fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { + fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { nsXPIDLString untitled; if (!GetLocalizedString(NS_LITERAL_STRING("noPageTitle").get(), untitled) || !CreateFilenameFromTextA(untitled, ".URL", - fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { + fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { strcpy(fileGroupDescA->fgd[0].cFileName, "Untitled.URL"); } } @@ -700,11 +945,11 @@ nsDataObj :: GetFileDescriptorInternetShortcutW ( FORMATETC& aFE, STGMEDIUM& aST // 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 (!CreateFilenameFromTextW(title, NS_LITERAL_STRING(".URL").get(), - fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { + fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { nsXPIDLString untitled; if (!GetLocalizedString(NS_LITERAL_STRING("noPageTitle").get(), untitled) || !CreateFilenameFromTextW(untitled, NS_LITERAL_STRING(".URL").get(), - fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { + fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) { wcscpy(fileGroupDescW->fgd[0].cFileName, NS_LITERAL_STRING("Untitled.URL").get()); } } @@ -771,39 +1016,28 @@ nsDataObj :: GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG ) #endif } // GetFileContentsInternetShortcut - -// -// IsInternetShortcut -// -// Is the data that we're handling destined for an internet shortcut if -// dragged to the desktop? We can tell because there will be a mime type -// of |kURLMime| present in the transferable -// -PRBool -nsDataObj :: IsInternetShortcut ( ) +// check if specified flavour is present in the transferable +PRBool nsDataObj :: IsFlavourPresent(const char *inFlavour) { PRBool retval = PR_FALSE; - - if ( !mTransferable ) - return PR_FALSE; + NS_ENSURE_TRUE(mTransferable, PR_FALSE); // get the list of flavors available in the transferable nsCOMPtr flavorList; - mTransferable->FlavorsTransferableCanExport ( getter_AddRefs(flavorList) ); - if ( !flavorList ) - return PR_FALSE; - - // go spelunking for the url flavor + mTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList)); + NS_ENSURE_TRUE(flavorList, PR_FALSE); + + // try to find requested flavour PRUint32 cnt; flavorList->Count(&cnt); - for ( PRUint32 i = 0;i < cnt; ++i ) { + for (PRUint32 i = 0; i < cnt; ++i) { nsCOMPtr genericFlavor; flavorList->GetElementAt (i, getter_AddRefs(genericFlavor)); nsCOMPtr currentFlavor (do_QueryInterface(genericFlavor)); if (currentFlavor) { nsCAutoString flavorStr; currentFlavor->GetData(flavorStr); - if ( flavorStr.Equals(kURLMime) ) { + if (flavorStr.Equals(inFlavour)) { retval = PR_TRUE; // found it! break; } @@ -811,8 +1045,7 @@ nsDataObj :: IsInternetShortcut ( ) } // for each flavor return retval; - -} // IsInternetShortcut +} HRESULT nsDataObj::GetPreferredDropEffect ( FORMATETC& aFE, STGMEDIUM& aSTG ) { @@ -935,93 +1168,6 @@ HRESULT nsDataObj::GetText(const nsACString & aDataFlavor, FORMATETC& aFE, STGME return ResultFromScode(S_OK); } -//----------------------------------------------------- -HRESULT nsDataObj::GetFile(const nsACString & aDataFlavor, FORMATETC& aFE, STGMEDIUM& aSTG) -{ - HRESULT res = S_OK; - if (strcmp(PromiseFlatCString(aDataFlavor).get(), kFilePromiseMime) == 0) { - // If we have a cached file just pass it to HGLOBAL - // otherwise create an empty file in the temp location. - // The download will start after the user drops the file. - nsresult rv; - if (!mCachedTempFile) { - // Get system temp directory - nsCOMPtr dropDirectory; - nsCOMPtr directoryService = - do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); - if (!directoryService || NS_FAILED(rv)) - return ResultFromScode(E_FAIL); - directoryService->Get(NS_OS_TEMP_DIR, - NS_GET_IID(nsIFile), - getter_AddRefs(dropDirectory)); - - nsCOMPtr destFile = do_QueryInterface(dropDirectory); - if (!destFile) - return E_FAIL; - - // Get the filename form the kFilePromiseURLFlavour - nsAutoString wideFileName; - nsCOMPtr sourceURI; - rv = nsDataObj::GetDownloadDetails(mTransferable, - getter_AddRefs(sourceURI), - wideFileName); - if (NS_FAILED(rv)) - return rv; - - rv = destFile->Append(wideFileName); - if (NS_FAILED(rv)) - return rv; - - // Try to create the file. - rv = destFile->Create(nsIFile::NORMAL_FILE_TYPE, 0600); - // Bail out if it fails for a reason other than the existence of the file. - if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) - return rv; - - mCachedTempFile = do_QueryInterface(destFile); - if (!mCachedTempFile) - return ResultFromScode(E_FAIL); - } - - // Pass the file name back to the drop target so that it can copy to the drop location - nsAutoString path; - rv = mCachedTempFile->GetPath(path); - if (NS_FAILED(rv)) return ResultFromScode(E_FAIL); - // Two null characters are needed to terminate the file name list - PRUint32 allocLen = path.Length() + 2; - HGLOBAL hGlobalMemory = NULL; - aSTG.tymed = TYMED_HGLOBAL; - aSTG.pUnkForRelease = NULL; - hGlobalMemory = GlobalAlloc(GMEM_MOVEABLE, sizeof(DROPFILES) + allocLen * sizeof(PRUnichar)); - if (hGlobalMemory) { - DROPFILES* pDropFile = NS_REINTERPRET_CAST(DROPFILES*, GlobalLock(hGlobalMemory)); - - // First, populate 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 = NS_REINTERPRET_CAST(PRUnichar*, NS_REINTERPRET_CAST(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); - } - else { - res = E_OUTOFMEMORY; - } - aSTG.hGlobal = hGlobalMemory; - } - return res; -} - //----------------------------------------------------- HRESULT nsDataObj::GetMetafilePict(FORMATETC&, STGMEDIUM&) { @@ -1085,14 +1231,11 @@ void nsDataObj::AddDataFlavor(const char* aDataFlavor, LPFORMATETC aFE) // so we will look up data flavor that corresponds to the FE // and then ask the transferable for that type of data - // Add CF_HDROP to the head of the list so that it is returned first - // when the drop target calls EnumFormatEtc to enumerate through the FE list - // We use the CF_HDROP format to copy file contents when an image is dragged - // from Mozilla to a drop target. + // Just ignore the CF_HDROP here + // all file drags are now hangled by CFSTR_FileContents format #ifndef WINCE if (aFE->cfFormat == CF_HDROP) { - mDataFlavors->InsertElementAt(new nsCAutoString(aDataFlavor), 0); - m_enumFE->InsertFEAt(aFE, 0); + return; } else #endif @@ -1316,7 +1459,7 @@ HRESULT nsDataObj :: GetUniformResourceLocator( FORMATETC& aFE, STGMEDIUM& aSTG, PRBool aIsUnicode ) { HRESULT res = S_OK; - if ( IsInternetShortcut() ) { + if (IsFlavourPresent(kURLMime)) { if ( aIsUnicode ) res = ExtractUniformResourceLocatorW( aFE, aSTG ); else @@ -1384,58 +1527,145 @@ nsDataObj::ExtractUniformResourceLocatorW(FORMATETC& aFE, STGMEDIUM& aSTG ) return result; } + // Gets the filename from the kFilePromiseURLMime flavour -nsresult nsDataObj::GetDownloadDetails(nsITransferable *aTransferable, - nsIURI **aSourceURI, +nsresult nsDataObj::GetDownloadDetails(nsIURI **aSourceURI, nsAString &aFilename) { - if (!aTransferable) - return NS_ERROR_FAILURE; + NS_ENSURE_TRUE(mTransferable, NS_ERROR_FAILURE); - // get the URI from the kFilePromiseURLMime flavor - nsCOMPtr urlPrimitive; - PRUint32 dataSize = 0; - aTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize); - nsCOMPtr srcUrlPrimitive = do_QueryInterface(urlPrimitive); - if (!srcUrlPrimitive) - return NS_ERROR_FAILURE; + // get the URI from the kFilePromiseURLMime flavor + nsCOMPtr urlPrimitive; + PRUint32 dataSize = 0; + mTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize); + nsCOMPtr srcUrlPrimitive = do_QueryInterface(urlPrimitive); + NS_ENSURE_TRUE(srcUrlPrimitive, NS_ERROR_FAILURE); + + // Get data for flavor + // The format of the data is (URLSTRING\nFILENAME) + nsAutoString strData; + srcUrlPrimitive->GetData(strData); + if (strData.IsEmpty()) + return NS_ERROR_FAILURE; - // Get data for flavor - // The format of the data is (URLSTRING\nFILENAME) - nsAutoString strData; - srcUrlPrimitive->GetData(strData); - if (strData.IsEmpty()) - return NS_ERROR_FAILURE; + // Now figure if there is a "\n" delimiter in the data string. + // If there is, the string after the "\n" is a filename. + // If there is no delimiter then just get the filename from the url. + nsCAutoString strFileName; + nsCOMPtr sourceURI; + // New line char is used as a delimiter (hardcoded) + PRInt32 nPos = strData.FindChar('\n'); + // Store source uri + NS_NewURI(aSourceURI, Substring(strData, 0, nPos)); + if (nPos != -1) { + // if there is delimiter + CopyUTF16toUTF8(Substring(strData, nPos + 1, strData.Length()), strFileName); + } else { + // no filename was supplied - try to get it from a URL + nsCOMPtr sourceURL = do_QueryInterface(*aSourceURI); + sourceURL->GetFileName(strFileName); + } + // check for an error; the URL must point to a file + if (strFileName.IsEmpty()) + return NS_ERROR_FAILURE; - // Now figure if there is a "\n" delimiter in the data string. - // If there is, the string after the "\n" is a filename. - // If there is no delimiter then just get the filename from the url. - nsCAutoString strFileName; - nsCOMPtr sourceURI; - // New line char is used as a delimiter (hardcoded) - PRInt32 nPos = strData.FindChar('\n'); - // Store source uri - NS_NewURI(aSourceURI, Substring(strData, 0, nPos)); - if (nPos != -1) { - // if there is delimiter - CopyUTF16toUTF8(Substring(strData, nPos + 1, strData.Length()), strFileName); - } else { - // no filename was supplied - try to get it from a URL - nsCOMPtr sourceURL = do_QueryInterface(*aSourceURI); - sourceURL->GetFileName(strFileName); - } - // check for an error; the URL must point to a file - if (strFileName.IsEmpty()) - return NS_ERROR_FAILURE; + NS_UnescapeURL(strFileName); + NS_ConvertUTF8toUTF16 wideFileName(strFileName); - NS_UnescapeURL(strFileName); - NS_ConvertUTF8toUTF16 wideFileName(strFileName); + // make the name safe for the filesystem + MangleTextToValidFilename(wideFileName); - // make the name safe for the filesystem - MangleTextToValidFilename(wideFileName); + aFilename = wideFileName; - aFilename = wideFileName; - - return NS_OK; + return NS_OK; } +HRESULT nsDataObj::GetFileDescriptor_IStreamA(FORMATETC& aFE, STGMEDIUM& aSTG) +{ + HGLOBAL fileGroupDescHandle = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE,sizeof(FILEGROUPDESCRIPTORW)); + NS_ENSURE_TRUE(fileGroupDescHandle, E_OUTOFMEMORY); + + LPFILEGROUPDESCRIPTORA fileGroupDescA = NS_REINTERPRET_CAST(LPFILEGROUPDESCRIPTORA, + ::GlobalLock(fileGroupDescHandle)); + if (!fileGroupDescA) { + ::GlobalFree(fileGroupDescHandle); + return E_OUTOFMEMORY; + } + + nsAutoString wideFileName; + nsresult rv; + nsCOMPtr 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; + + ::GlobalUnlock( fileGroupDescHandle ); + 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); + + LPFILEGROUPDESCRIPTORW fileGroupDescW = NS_REINTERPRET_CAST(LPFILEGROUPDESCRIPTORW, + ::GlobalLock(fileGroupDescHandle)); + if (!fileGroupDescW) { + ::GlobalFree(fileGroupDescHandle); + return E_OUTOFMEMORY; + } + + nsAutoString wideFileName; + nsresult rv; + nsCOMPtr 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; + + ::GlobalUnlock(fileGroupDescHandle); + 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; +} diff --git a/mozilla/widget/src/windows/nsDataObj.h b/mozilla/widget/src/windows/nsDataObj.h index 79c10ffd857..5dcd35f60b1 100644 --- a/mozilla/widget/src/windows/nsDataObj.h +++ b/mozilla/widget/src/windows/nsDataObj.h @@ -48,9 +48,35 @@ #include "nsString.h" #include "nsILocalFile.h" #include "nsIURI.h" +#include "nsIInputStream.h" +#include "nsIChannel.h" #define MAX_FORMATS 32 +// XXX for older version of PSDK where IAsyncOperation and related stuff is not available +// but thisdefine should be removed when parocles config is updated +#ifndef __IAsyncOperation_INTERFACE_DEFINED__ +// IAsyncOperation inerface definition +EXTERN_C const IID IID_IAsyncOperation; + +MIDL_INTERFACE("3D8B0590-F691-11d2-8EA9-006097DF5BD4") +IAsyncOperation : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE SetAsyncMode(BOOL fDoOpAsync) = 0; + virtual HRESULT STDMETHODCALLTYPE GetAsyncMode(BOOL *pfIsOpAsync) = 0; + virtual HRESULT STDMETHODCALLTYPE StartOperation(IBindCtx *pbcReserved) = 0; + virtual HRESULT STDMETHODCALLTYPE InOperation(BOOL *pfInAsyncOp) = 0; + virtual HRESULT STDMETHODCALLTYPE EndOperation(HRESULT hResult, + IBindCtx *pbcReserved, + DWORD dwEffects) = 0; +}; +// this is not defined in the old headers for some reason +#ifndef FD_PROGRESSUI + #define FD_PROGRESSUI 0x4000 +#endif + +#endif // __IAsyncOperation_INTERFACE_DEFINED__ + /* * CFSTR_SHELLURL is deprecated and doesn't have a Unicode version. * Therefore we are using CFSTR_INETURL instead of CFSTR_SHELLURL. @@ -112,7 +138,8 @@ class nsITransferable; * can be adapted by an object derived from CfDragDrop. The CfDragDrop is * associated with instances via SetDragDrop(). */ -class nsDataObj : public IDataObject +class nsDataObj : public IDataObject, + public IAsyncOperation { public: // construction, destruction nsDataObj(nsIURI *uri = nsnull); @@ -177,6 +204,13 @@ class nsDataObj : public IDataObject // object. STDMETHODIMP EnumDAdvise (LPENUMSTATDATA *ppEnum); + // IAsyncOperation methods + STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects); + STDMETHOD(GetAsyncMode)(BOOL *pfIsOpAsync); + STDMETHOD(InOperation)(BOOL *pfInAsyncOp); + STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync); + STDMETHOD(StartOperation)(IBindCtx *pbcReserved); + public: // other methods // Return the total reference counts of all instances of this class. @@ -187,20 +221,17 @@ class nsDataObj : public IDataObject ULONG GetRefCount() const; // Gets the filename from the kFilePromiseURLMime flavour - static nsresult GetDownloadDetails(nsITransferable *aTransferable, - nsIURI **aSourceURI, - nsAString &aFilename); + nsresult GetDownloadDetails(nsIURI **aSourceURI, + nsAString &aFilename); protected: - - // Help determine if the drag should create an internet shortcut - PRBool IsInternetShortcut ( ) ; + // help determine the kind of drag + PRBool IsFlavourPresent(const char *inFlavour); virtual HRESULT AddSetFormat(FORMATETC& FE); virtual HRESULT AddGetFormat(FORMATETC& FE); virtual HRESULT GetText ( const nsACString& aDF, FORMATETC& aFE, STGMEDIUM & aSTG ); - virtual HRESULT GetFile ( const nsACString& aDF, FORMATETC& aFE, STGMEDIUM& aSTG ); virtual HRESULT GetBitmap ( const nsACString& inFlavor, FORMATETC& FE, STGMEDIUM& STM); virtual HRESULT GetDib ( const nsACString& inFlavor, FORMATETC &, STGMEDIUM & aSTG ); virtual HRESULT GetMetafilePict(FORMATETC& FE, STGMEDIUM& STM); @@ -222,6 +253,11 @@ class nsDataObj : public IDataObject virtual HRESULT GetFileDescriptorInternetShortcutW ( FORMATETC& aFE, STGMEDIUM& aSTG ) ; virtual HRESULT GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG ) ; + // IStream implementation + virtual HRESULT GetFileDescriptor_IStreamA ( FORMATETC& aFE, STGMEDIUM& aSTG ) ; + virtual HRESULT GetFileDescriptor_IStreamW ( FORMATETC& aFE, STGMEDIUM& aSTG ) ; + virtual HRESULT GetFileContents_IStream ( FORMATETC& aFE, STGMEDIUM& aSTG ) ; + nsresult ExtractShortcutURL ( nsString & outURL ) ; nsresult ExtractShortcutTitle ( nsString & outTitle ) ; @@ -247,6 +283,47 @@ class nsDataObj : public IDataObject // nsDataObj owns and ref counts CEnumFormatEtc, nsCOMPtr mCachedTempFile; + + BOOL mIsAsyncMode; + BOOL mIsInOperation; + /////////////////////////////////////////////////////////////////////////////// + // CStream class implementation + // this class is used in Drag and drop with download sample + // called from IDataObject::GetData + class CStream : public IStream + { + ULONG mRefCount; // reference counting + nsCOMPtr mInputStream; + nsCOMPtr mChannel; + + protected: + virtual ~CStream(); + // TODO: forbid copying and assignment + + public: + CStream(); + nsresult Init(nsIURI *pSourceURI); + + // IUnknown + STDMETHOD(QueryInterface)(REFIID refiid, void** ppvResult); + STDMETHOD_(ULONG, AddRef)(void); + STDMETHOD_(ULONG, Release)(void); + + // IStream + STDMETHOD(Clone)(IStream** ppStream); + STDMETHOD(Commit)(DWORD dwFrags); + STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten); + STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags); + STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead); + STDMETHOD(Revert)(void); + STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos); + STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize); + STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags); + STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags); + STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead); + }; + + HRESULT CreateStream(IStream **outStream); }; diff --git a/mozilla/widget/src/windows/nsDragService.cpp b/mozilla/widget/src/windows/nsDragService.cpp index c08a8617e9a..0f3787daaba 100644 --- a/mozilla/widget/src/windows/nsDragService.cpp +++ b/mozilla/widget/src/windows/nsDragService.cpp @@ -41,6 +41,7 @@ #include #include #include +#include // shellapi.h is needed to build with WIN32_LEAN_AND_MEAN #include @@ -71,10 +72,6 @@ #include "nsDirectoryServiceDefs.h" #include "nsUnicharUtils.h" -// Static member declaration -PRUnichar *nsDragService::mDropPath; -PRUnichar *nsDragService::mFileName; - //------------------------------------------------------------------------- // // DragService constructor @@ -92,11 +89,6 @@ nsDragService::nsDragService() //------------------------------------------------------------------------- nsDragService::~nsDragService() { - if (mFileName) - NS_Free(mFileName); - if (mDropPath) - NS_Free(mDropPath); - NS_IF_RELEASE(mNativeDragSrc); NS_IF_RELEASE(mNativeDragTarget); NS_IF_RELEASE(mDataObject); @@ -166,110 +158,8 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, } } // else dragging a single object - // Before starting get the file name to monitor if there is any - nsAutoString strData; // holds kFilePromiseURLMime flavour data - PRBool bDownload = PR_FALSE; // Used after drag ends to fugure if the download should start - - nsCOMPtr sourceURI; - nsCOMPtr urlPrimitive; - nsCOMPtr transSupports; - anArrayTransferables->GetElementAt(0, getter_AddRefs(transSupports)); - nsCOMPtr trans = (do_QueryInterface(transSupports)); - if (trans) { - // Get the filename form the kFilePromiseURLFlavour - nsAutoString wideFileName; - // if this fails there is no kFilePromiseMime flavour or no filename - rv = nsDataObj::GetDownloadDetails(trans, - getter_AddRefs(sourceURI), - wideFileName); - if (SUCCEEDED(rv)) - { - // Start listening to the shell notifications - if (StartWatchingShell(wideFileName)) { - // Set download flag if all went ok so far - bDownload = PR_TRUE; - } - } - } - // Kick off the native drag session - rv = StartInvokingDragSession(itemToDrag, aActionType); - - // Check if the download flag was set - // if not then we are done - if (!bDownload) - return rv; - - if (NS_FAILED(rv)) // See if dragsession failed - { - ::DestroyWindow(mHiddenWnd); - return rv; - } - - // Construct target URI from nsILocalFile - // Init file for the download - nsCOMPtr dropLocalFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID)); - if (!dropLocalFile) - { - ::DestroyWindow(mHiddenWnd); - return NS_ERROR_FAILURE; - } - - // init with path we get from GetDropPath - // if it fails then there is no target path. - // This could happen if the drag operation was cancelled. - nsAutoString fileName; - if (!GetDropPath(fileName)) - return NS_OK; - - // hidden window is destroyed by now - rv = dropLocalFile->InitWithPath(fileName); - if (NS_FAILED(rv)) - return rv; - - // set the directory promise flavour - // if this fails it won't affect the drag so we can just continue - trans->SetTransferData(kFilePromiseDirectoryMime, - dropLocalFile, - sizeof(nsILocalFile*)); - - // Create a new FileURI to pass to the nsIDownload - nsCOMPtr targetURI; - - nsCOMPtr file = do_QueryInterface(dropLocalFile); - if (!file) - return NS_ERROR_FAILURE; - - rv = NS_NewFileURI(getter_AddRefs(targetURI), file); - if (NS_FAILED(rv)) - return rv; - - // Start download - nsCOMPtr fileAsSupports = do_QueryInterface(dropLocalFile); - - nsCOMPtr persist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr transfer = do_CreateInstance("@mozilla.org/transfer;1", &rv); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr listener = do_QueryInterface(transfer); - rv = persist->SetProgressListener(listener); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr cancelable = do_QueryInterface(persist); - rv = transfer->Init(sourceURI, targetURI, NS_LITERAL_STRING(""), nsnull, PR_Now(), nsnull, cancelable); - if (NS_FAILED(rv)) - return rv; - - rv = persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull, fileAsSupports); - if (NS_FAILED(rv)) - return rv; - - return rv; + return StartInvokingDragSession(itemToDrag, aActionType); } //------------------------------------------------------------------------- @@ -307,9 +197,34 @@ nsDragService::StartInvokingDragSession(IDataObject * aDataObj, // Start dragging StartDragSession(); + // check shell32.dll version and do async drag if it is >= 5.0 + PRUint64 lShellVersion = GetShellVersion(); + IAsyncOperation *pAsyncOp = NULL; + PRBool isAsyncAvailable = LL_UCMP(lShellVersion, >=, LL_INIT(5, 0)); + if (isAsyncAvailable) + { + // do async drag + if (SUCCEEDED(aDataObj->QueryInterface(IID_IAsyncOperation, + (void**)&pAsyncOp))) + pAsyncOp->SetAsyncMode(TRUE); + } + // Call the native D&D method HRESULT res = ::DoDragDrop(aDataObj, mNativeDragSrc, effects, &dropRes); + if (isAsyncAvailable) + { + // if dragging async + // check for async operation + BOOL isAsync = FALSE; + if (pAsyncOp) + { + pAsyncOp->InOperation(&isAsync); + if (!isAsync) + aDataObj->Release(); + } + } + // We're done dragging EndDragSession(); @@ -575,189 +490,37 @@ nsDragService::EndDragSession() return NS_OK; } -// Start monitoring shell events - when user drops we'll get a notification from shell -// containing drop location -// aFileName is a filename to monitor -// returns true if all went ok -// if hidden window was created and shell is watching out for files being created -PRBool nsDragService::StartWatchingShell(const nsAString& aFileName) +// Gets shell version as packed 64 bit int +PRUint64 nsDragService::GetShellVersion() { - // init member varable with the file name to watch - if (mFileName) - NS_Free(mFileName); + PRUint64 lVersion = LL_INIT(0, 0); - mFileName = ToNewUnicode(aFileName); + // shell32.dll should be loaded already, so we ae not actually loading the library here + PRLibrary *libShell = PR_LoadLibrary("shell32.dll"); + if (libShell == NULL) + return lVersion; - // Create hidden window to process shell notifications - WNDCLASS wc; + do + { + DLLGETVERSIONPROC versionProc = NULL; + versionProc = (DLLGETVERSIONPROC)PR_FindFunctionSymbol(libShell, "DllGetVersion"); + if (versionProc == NULL) + break; - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)HiddenWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = NULL; - wc.hIcon = NULL; - wc.hCursor = NULL; - wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wc.lpszMenuName = NULL; - wc.lpszClassName = TEXT("DHHidden"); + DLLVERSIONINFO versionInfo; + ::ZeroMemory(&versionInfo, sizeof(DLLVERSIONINFO)); + versionInfo.cbSize = sizeof(DLLVERSIONINFO); + if (FAILED(versionProc(&versionInfo))) + break; - unsigned short res = RegisterClass(&wc); + // why is this? + PRUint32 maji64 = versionInfo.dwMajorVersion; + PRUint32 mini64 = versionInfo.dwMinorVersion; + lVersion = LL_INIT(maj, min); + } while (false); - mHiddenWnd = CreateWindowEx(WS_EX_TOOLWINDOW, - TEXT("DHHidden"), - TEXT("DHHidden"), - WS_POPUP, - 0, - 0, - 100, - 100, - NULL, - NULL, - NULL, - NULL); - if (mHiddenWnd == NULL) - return PR_FALSE; + PR_UnloadLibrary(libShell); + libShell = NULL; - // Now let the explorer know what we want - // Get My Computer PIDL - LPITEMIDLIST pidl; - HRESULT hr = ::SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl); - - if (SUCCEEDED(hr)) { - SHChangeNotifyStruct notify; - notify.pidl = pidl; - notify.fRecursive = TRUE; - - HMODULE hShell32 = ::GetModuleHandleA("SHELL32.DLL"); - - if (hShell32 == NULL) { - ::DestroyWindow(mHiddenWnd); - return PR_FALSE; - } - - // Have to use ordinals in the call to GetProcAddress instead of function names. - // The reason for this is because on some older systems (prior to WinXP) - // this function has no name in shell32.dll. - DWORD dwOrdinal = 2; - // get reg func - SHCNRegPtr reg; - reg = (SHCNRegPtr)::GetProcAddress(hShell32, (LPCSTR)dwOrdinal); - if (reg == NULL) { - ::DestroyWindow(mHiddenWnd); - return PR_FALSE; - } - - mNotifyHandle = (reg)(mHiddenWnd, - 0x2, - 0x1, - WM_USER, - 1, - ¬ify); - } - - // destroy hidden window if failed to register notification handle - if (mNotifyHandle == 0) { - ::DestroyWindow(mHiddenWnd); - } - - return (mNotifyHandle != 0); -} - -// Get the drop path if there is one:) -// returns true if there is a drop path -PRBool nsDragService::GetDropPath(nsAString& aDropPath) const -{ - // we failed to create window so there is no drop path - if (mHiddenWnd == NULL) - return PR_FALSE; - - // If we get 0 for this that means we failed to register notification callback - if (mNotifyHandle == 0) - return PR_FALSE; - - // Do clean up stuff (reverses all that's been done in Start) - HMODULE hShell32 = ::GetModuleHandleA("SHELL32.DLL"); - - if (hShell32 == NULL) - return PR_FALSE; - - // Have to use ordinals in the call to GetProcAddress instead of function names. - // The reason for this is because on some older systems (prior to WinXP) - // this function has no name in shell32.dll. - DWORD dwOrdinal = 4; - SHCNDeregPtr dereg; - dereg = (SHCNDeregPtr)::GetProcAddress(hShell32, (LPCSTR)dwOrdinal); - if (dereg == NULL) - return PR_FALSE; - (dereg)(mNotifyHandle); - - ::DestroyWindow(mHiddenWnd); - - // if drop path is too short then there is no drop location - if (!mDropPath) - return PR_FALSE; - - aDropPath.Assign(mDropPath); - - return PR_TRUE; -} - -// Hidden window procedure - this is where shell sends notifications -// When notification is received, perform some checking and copy path to the member variable -LRESULT WINAPI nsDragService::HiddenWndProc(HWND aWnd, UINT aMsg, WPARAM awParam, LPARAM alParam) -{ - switch (aMsg) { - case WM_USER: - if (alParam == SHCNE_RENAMEITEM) { - // we got notification from shell - // as wParam we get 2 PIDL - LPCITEMIDLIST* ppidl = (LPCITEMIDLIST*)awParam; - // Get From path (where the file is comming from) - WCHAR szPathFrom[MAX_PATH + 1]; - WCHAR szPathTo[MAX_PATH + 1]; - ::SHGetPathFromIDListW(ppidl[0], szPathFrom); - // Get To path (where the file is going to) - ::SHGetPathFromIDListW(ppidl[1], szPathTo); - - // first is from where the file is coming - // and the second is where the file is going - nsAutoString pathFrom(szPathFrom); // where the file is comming from - nsAutoString pathTo(szPathTo); // where the file is going to - // Get OS Temp directory - // Get system temp directory - nsresult rv; - nsCOMPtr tempDir; - nsCOMPtr directoryService = - do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); - if (!directoryService || NS_FAILED(rv)) - return ResultFromScode(E_FAIL); - directoryService->Get(NS_OS_TEMP_DIR, - NS_GET_IID(nsIFile), - getter_AddRefs(tempDir)); - - // append file name to Temp directory string - nsAutoString tempPath; - tempDir->Append(nsDependentString(mFileName)); - tempDir->GetPath(tempPath); - - // Now check if there is our filename in the path - // and also check for the source directory - it should be OS Temp dir - // this way we can ensure that this is the file that we need - PRInt32 pathToLength = pathTo.Length(); - if (Substring(pathTo, pathToLength - NS_strlen(mFileName), pathToLength).Equals(mFileName) && - tempPath.Equals(pathFrom, nsCaseInsensitiveStringComparator())) - { - // This is what we wanted to get - if (mDropPath) - NS_Free(mDropPath); - - mDropPath = ToNewUnicode(pathTo); - } - return 0; - } - break; - } - - return ::DefWindowProc(aWnd, aMsg, awParam, alParam); + return lVersion; } diff --git a/mozilla/widget/src/windows/nsDragService.h b/mozilla/widget/src/windows/nsDragService.h index e44c6e18469..3458d758bac 100644 --- a/mozilla/widget/src/windows/nsDragService.h +++ b/mozilla/widget/src/windows/nsDragService.h @@ -48,30 +48,6 @@ class nsNativeDragTarget; class nsDataObjCollection; class nsString; -// some older versions of MS PSDK do not have definitions for these, even though -// the functions are there and exported from the shell32.dll, -// so I had to add them manually. For example if one tries to build without those -// using VC6 standard libs one will get an error. -#ifndef SHCNE_RENAMEITEM_DEF -#define SHCNE_RENAMEITEM_DEF 0x00000001 - -// Structure -typedef struct { - LPCITEMIDLIST pidl; - BOOL fRecursive; -} SHChangeNotifyStruct; -#endif // SHCNE_RENAMEITEM_DEF - -// Register for shell notifications func ptr -typedef WINSHELLAPI ULONG (WINAPI *SHCNRegPtr)(HWND hWnd, // Ordinal of 2 - int fSources, - LONG fEvents, - UINT wMsg, - int cEntries, - SHChangeNotifyStruct *pschn); -// Unregister form from the shell notifications func ptr -typedef WINSHELLAPI BOOL (WINAPI *SHCNDeregPtr)(ULONG ulID); // Ordinal of 4 - /** * Native Win32 DragService wrapper */ @@ -106,23 +82,12 @@ protected: // collections PRBool IsCollectionObject(IDataObject* inDataObj); - // Begin monitoring the shell for events (this would allow to figure drop location) - PRBool StartWatchingShell(const nsAString& aFileName); - - // Should be called after drag is over to get the drop path (if any) - PRBool GetDropPath(nsAString& aDropPath) const; - - // Hidden window procedure - here we shall receive notification from the shell - static LRESULT WINAPI HiddenWndProc(HWND aWnd, UINT aMsg, WPARAM awParam, LPARAM alParam); + // gets shell version + PRUint64 GetShellVersion(); IDropSource * mNativeDragSrc; nsNativeDragTarget * mNativeDragTarget; IDataObject * mDataObject; - - static PRUnichar *mFileName; // File name to look for - static PRUnichar *mDropPath; // Drop path - HWND mHiddenWnd; // Handle to a hidden window for notifications - PRInt32 mNotifyHandle; // Handle to installed hook (SHChangeNotify) }; #endif // nsDragService_h__