Drop ComPtr and use sal::systools::COMReference
Change-Id: I9eb6d99d883b44943ad69c2c28d4e55716dc34f9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111673 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
parent
f3fab0832b
commit
ed40d477b2
11 changed files with 137 additions and 320 deletions
|
@ -17,22 +17,14 @@
|
|||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_IVISTAFILEPICKERINTERNALNOTIFY_HXX
|
||||
#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_IVISTAFILEPICKERINTERNALNOTIFY_HXX
|
||||
#pragma once
|
||||
|
||||
#include "vistatypes.h"
|
||||
#include <systools/win32/uwinapi.h>
|
||||
|
||||
#include <cppuhelper/basemutex.hxx>
|
||||
#include <osl/interlck.h>
|
||||
|
||||
#include <shobjidl.h>
|
||||
|
||||
namespace fpicker{
|
||||
namespace win32{
|
||||
namespace vista{
|
||||
namespace fpicker::win32::vista{
|
||||
|
||||
|
||||
// types, const etcpp.
|
||||
// types, const etc.
|
||||
|
||||
|
||||
/** todo document me
|
||||
|
@ -51,8 +43,6 @@ class IVistaFilePickerInternalNotify
|
|||
~IVistaFilePickerInternalNotify() {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif // INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_IVISTAFILEPICKERINTERNALNOTIFY_HXX
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
|
@ -229,7 +229,7 @@ void VistaFilePickerEventHandler::stopListening()
|
|||
if (m_pDialog.is())
|
||||
{
|
||||
m_pDialog->Unadvise(m_nListenerHandle);
|
||||
m_pDialog.release();
|
||||
m_pDialog.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
|
||||
#include <com/sun/star/lang/SystemDependent.hpp>
|
||||
#include <comphelper/sequence.hxx>
|
||||
#include <comphelper/windowserrorstring.hxx>
|
||||
#include <fpicker/strings.hrc>
|
||||
#include <fpsofficeResMgr.hxx>
|
||||
#include <osl/file.hxx>
|
||||
|
@ -56,7 +55,8 @@ static HWND choose_parent_window()
|
|||
|
||||
namespace {
|
||||
|
||||
bool createFolderItem(OUString const & url, ComPtr<IShellItem> & folder) {
|
||||
bool createFolderItem(OUString const& url, sal::systools::COMReference<IShellItem>& folder)
|
||||
{
|
||||
OUString path;
|
||||
if (osl::FileBase::getSystemPathFromFileURL(url, path)
|
||||
!= osl::FileBase::E_None)
|
||||
|
@ -97,54 +97,53 @@ const GUID CLIENTID_FILEOPEN_LINK = {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE
|
|||
class TDialogImplBase
|
||||
{
|
||||
public:
|
||||
template <class ComPtrDialog> TDialogImplBase(ComPtrDialog&& iDialog)
|
||||
TDialogImplBase(IFileDialog* iDialog)
|
||||
: m_iDialog(iDialog)
|
||||
{
|
||||
HRESULT hResult = iDialog.create();
|
||||
if (FAILED(hResult))
|
||||
throw css::uno::RuntimeException(WindowsErrorStringFromHRESULT(hResult));
|
||||
hResult = iDialog.query(&m_iDialog);
|
||||
if (FAILED(hResult))
|
||||
throw css::uno::RuntimeException(WindowsErrorStringFromHRESULT(hResult));
|
||||
}
|
||||
|
||||
TFileDialog getComPtr() { return m_iDialog; };
|
||||
virtual ComPtr<IShellItemArray> getResult(bool bInExecute)
|
||||
TFileDialog getComPtr() { return m_iDialog; }
|
||||
virtual sal::systools::COMReference<IShellItemArray> getResult(bool bInExecute)
|
||||
{
|
||||
ComPtr<IShellItem> iItem;
|
||||
sal::systools::COMReference<IShellItem> iItem;
|
||||
if (bInExecute)
|
||||
m_iDialog->GetCurrentSelection(&iItem);
|
||||
else
|
||||
m_iDialog->GetResult(&iItem);
|
||||
void* iItems = nullptr;
|
||||
SHCreateShellItemArrayFromShellItem(iItem, IID_IShellItemArray, &iItems);
|
||||
return ComPtr<IShellItemArray>(reinterpret_cast<IShellItemArray*>(iItems));
|
||||
if (iItem.is())
|
||||
SHCreateShellItemArrayFromShellItem(iItem.get(), IID_IShellItemArray, &iItems);
|
||||
return static_cast<IShellItemArray*>(iItems);
|
||||
}
|
||||
|
||||
private:
|
||||
TFileDialog m_iDialog;
|
||||
};
|
||||
|
||||
template <class ComPtrDialog> class TDialogImpl : public TDialogImplBase
|
||||
template <class ComPtrDialog, REFCLSID CLSID> class TDialogImpl : public TDialogImplBase
|
||||
{
|
||||
public:
|
||||
TDialogImpl() : TDialogImplBase(ComPtrDialog()) {}
|
||||
TDialogImpl()
|
||||
: TDialogImplBase(ComPtrDialog().CoCreateInstance(CLSID).get())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class TOpenDialogImpl : public TDialogImpl<TFileOpenDialog>
|
||||
class TOpenDialogImpl : public TDialogImpl<TFileOpenDialog, CLSID_FileOpenDialog>
|
||||
{
|
||||
public:
|
||||
ComPtr<IShellItemArray> getResult(bool bInExecute) override
|
||||
sal::systools::COMReference<IShellItemArray> getResult(bool bInExecute) override
|
||||
{
|
||||
ComPtr<IShellItemArray> iItems;
|
||||
TFileOpenDialog iDialog{ getComPtr() };
|
||||
sal::systools::COMReference<IShellItemArray> iItems;
|
||||
TFileOpenDialog iDialog(getComPtr(), sal::systools::COM_QUERY_THROW);
|
||||
if (FAILED(bInExecute ? iDialog->GetSelectedItems(&iItems) : iDialog->GetResults(&iItems)))
|
||||
iItems = TDialogImplBase::getResult(bInExecute);
|
||||
return iItems;
|
||||
}
|
||||
};
|
||||
|
||||
using TSaveDialogImpl = TDialogImpl<TFileSaveDialog>;
|
||||
using TFolderPickerDialogImpl = TDialogImpl<TFolderPickerDialog>;
|
||||
using TSaveDialogImpl = TDialogImpl<TFileSaveDialog, CLSID_FileSaveDialog>;
|
||||
using TFolderPickerDialogImpl = TDialogImpl<TFileOpenDialog, CLSID_FileOpenDialog>;
|
||||
|
||||
|
||||
static OUString lcl_getURLFromShellItem (IShellItem* pItem)
|
||||
|
@ -384,9 +383,11 @@ void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef& rRequ
|
|||
aLock.clear();
|
||||
// <- SYNCHRONIZED
|
||||
|
||||
VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
|
||||
if (pHandlerImpl)
|
||||
if (iHandler.is())
|
||||
{
|
||||
auto* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
|
||||
pHandlerImpl->addFilePickerListener(xListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -403,9 +404,11 @@ void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef& rR
|
|||
aLock.clear();
|
||||
// <- SYNCHRONIZED
|
||||
|
||||
VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
|
||||
if (pHandlerImpl)
|
||||
if (iHandler.is())
|
||||
{
|
||||
auto* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
|
||||
pHandlerImpl->removeFilePickerListener(xListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -534,9 +537,11 @@ void VistaFilePickerImpl::impl_sta_InitDialog(const RequestRef& rRequest, DWORD
|
|||
::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, ::sal_Int32(0));
|
||||
impl_sta_enableFeatures(nFeatures, nTemplate);
|
||||
|
||||
VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
|
||||
if (pHandlerImpl)
|
||||
if (iHandler.is())
|
||||
{
|
||||
auto* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
|
||||
pHandlerImpl->startListening(iDialog);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -794,21 +799,21 @@ void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef& rRequest)
|
|||
aLock.clear();
|
||||
// <- SYNCHRONIZED
|
||||
|
||||
ComPtr< IShellItem > pFolder;
|
||||
sal::systools::COMReference<IShellItem> pFolder;
|
||||
if ( !createFolderItem(sDirectory, pFolder) )
|
||||
return;
|
||||
|
||||
iDialog->SetFolder(pFolder);
|
||||
iDialog->SetFolder(pFolder.get());
|
||||
}
|
||||
|
||||
OUString VistaFilePickerImpl::GetDirectory()
|
||||
{
|
||||
TFileDialog iDialog = impl_getBaseDialogInterface();
|
||||
ComPtr< IShellItem > pFolder;
|
||||
sal::systools::COMReference<IShellItem> pFolder;
|
||||
HRESULT hResult = iDialog->GetFolder( &pFolder );
|
||||
if ( FAILED(hResult) )
|
||||
return OUString();
|
||||
return lcl_getURLFromShellItem(pFolder);
|
||||
return lcl_getURLFromShellItem(pFolder.get());
|
||||
}
|
||||
|
||||
void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef& rRequest)
|
||||
|
@ -902,8 +907,8 @@ void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef& rRequest)
|
|||
|
||||
// ask dialog for results
|
||||
// we must react different if dialog is in execute or not .-(
|
||||
ComPtr<IShellItemArray> iItems = pDialog->getResult(bInExecute);
|
||||
if (!iItems)
|
||||
sal::systools::COMReference<IShellItemArray> iItems = pDialog->getResult(bInExecute);
|
||||
if (!iItems.is())
|
||||
return;
|
||||
|
||||
// convert and pack results
|
||||
|
@ -912,9 +917,10 @@ void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef& rRequest)
|
|||
{
|
||||
for (DWORD i = 0; i < nCount; ++i)
|
||||
{
|
||||
if (ComPtr<IShellItem> iItem; SUCCEEDED(iItems->GetItemAt(i, &iItem)))
|
||||
if (sal::systools::COMReference<IShellItem> iItem;
|
||||
SUCCEEDED(iItems->GetItemAt(i, &iItem)))
|
||||
{
|
||||
if (const OUString sURL = lcl_getURLFromShellItem(iItem); !sURL.isEmpty())
|
||||
if (const OUString sURL = lcl_getURLFromShellItem(iItem.get()); !sURL.isEmpty())
|
||||
lFiles.push_back(sURL);
|
||||
}
|
||||
}
|
||||
|
@ -948,7 +954,7 @@ void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest)
|
|||
// according to its client guid.
|
||||
if( m_sDirectory.getLength())
|
||||
{
|
||||
ComPtr< IShellItem > pFolder;
|
||||
sal::systools::COMReference<IShellItem> pFolder;
|
||||
if ( createFolderItem(m_sDirectory, pFolder) )
|
||||
{
|
||||
if (m_sFilename.getLength())
|
||||
|
@ -988,14 +994,14 @@ void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest)
|
|||
WIN32_FIND_DATAW aFindFileData;
|
||||
HANDLE hFind = FindFirstFileW( o3tl::toW(aSystemPath.getStr()), &aFindFileData );
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
iDialog->SetFolder(pFolder);
|
||||
iDialog->SetFolder(pFolder.get());
|
||||
else
|
||||
hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
|
||||
hResult = iDialog->AddPlace(pFolder.get(), FDAP_TOP);
|
||||
|
||||
FindClose( hFind );
|
||||
}
|
||||
else
|
||||
iDialog->AddPlace(pFolder, FDAP_TOP);
|
||||
iDialog->AddPlace(pFolder.get(), FDAP_TOP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1044,15 +1050,13 @@ TFileDialog VistaFilePickerImpl::impl_getBaseDialogInterface()
|
|||
|
||||
TFileDialogCustomize VistaFilePickerImpl::impl_getCustomizeInterface()
|
||||
{
|
||||
TFileDialogCustomize iCustom;
|
||||
|
||||
// SYNCHRONIZED->
|
||||
osl::MutexGuard aLock(m_aMutex);
|
||||
|
||||
if (m_pDialog)
|
||||
m_pDialog->getComPtr().query(&iCustom);
|
||||
return { m_pDialog->getComPtr(), sal::systools::COM_QUERY_THROW };
|
||||
|
||||
return iCustom;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <shobjidl.h>
|
||||
|
||||
#include "asyncrequests.hxx"
|
||||
#include "comptr.hxx"
|
||||
#include "vistatypes.h"
|
||||
#include "FilterContainer.hxx"
|
||||
#include "VistaFilePickerEventHandler.hxx"
|
||||
|
|
|
@ -1,212 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_COMPTR_HXX
|
||||
#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_COMPTR_HXX
|
||||
|
||||
#include <sal/types.h>
|
||||
#include <osl/diagnose.h>
|
||||
#include <shobjidl.h>
|
||||
|
||||
template< class T_INTERFACE ,
|
||||
REFIID P_IID = IID_NULL ,
|
||||
REFCLSID P_CLSID = CLSID_NULL >
|
||||
class ComPtr
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
/** initialize com ptr with null.
|
||||
*/
|
||||
ComPtr()
|
||||
{
|
||||
m_pInterface = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/** initialize com ptr with given interface.
|
||||
*/
|
||||
explicit ComPtr(T_INTERFACE* pInterface)
|
||||
{
|
||||
m_pInterface = pInterface;
|
||||
if (m_pInterface)
|
||||
m_pInterface->AddRef();
|
||||
}
|
||||
|
||||
|
||||
/** copy ctor.
|
||||
*/
|
||||
ComPtr(const ComPtr< T_INTERFACE, P_IID, P_CLSID >& aCopy)
|
||||
{
|
||||
m_pInterface = aCopy.m_pInterface;
|
||||
if (m_pInterface)
|
||||
m_pInterface->AddRef();
|
||||
}
|
||||
|
||||
|
||||
/** initialize object by querying external object for the right interface.
|
||||
*/
|
||||
explicit ComPtr(IUnknown* pIUnknown)
|
||||
{
|
||||
if (pIUnknown)
|
||||
pIUnknown->QueryInterface(P_IID, (void**)&m_pInterface);
|
||||
}
|
||||
|
||||
|
||||
/** deinitialize com object right.
|
||||
*/
|
||||
~ComPtr()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
HRESULT create()
|
||||
{
|
||||
return CoCreateInstance(P_CLSID, nullptr, CLSCTX_ALL, P_IID, reinterpret_cast<void**>(&m_pInterface));
|
||||
}
|
||||
|
||||
|
||||
operator T_INTERFACE*() const
|
||||
{
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE& operator*() const
|
||||
{
|
||||
return *m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE** operator&()
|
||||
{
|
||||
return &m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE* operator->() const
|
||||
{
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE* operator=(T_INTERFACE* pInterface)
|
||||
{
|
||||
if ( equals(pInterface) )
|
||||
return m_pInterface;
|
||||
|
||||
m_pInterface->Release();
|
||||
m_pInterface = pInterface;
|
||||
if (m_pInterface)
|
||||
m_pInterface->AddRef();
|
||||
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE* operator=(IUnknown* pIUnknown)
|
||||
{
|
||||
if (pIUnknown)
|
||||
pIUnknown->QueryInterface(P_IID, (void**)&m_pInterface);
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE* operator=(const ComPtr< T_INTERFACE, P_IID, P_CLSID >& aCopy)
|
||||
{
|
||||
m_pInterface = aCopy.m_pInterface;
|
||||
if (m_pInterface)
|
||||
m_pInterface->AddRef();
|
||||
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE* get() const
|
||||
{
|
||||
return m_pInterface;
|
||||
}
|
||||
|
||||
|
||||
void attach(T_INTERFACE* pInterface)
|
||||
{
|
||||
if (pInterface)
|
||||
{
|
||||
m_pInterface->Release();
|
||||
m_pInterface = pInterface;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
T_INTERFACE* detach()
|
||||
{
|
||||
T_INTERFACE* pInterface = m_pInterface;
|
||||
m_pInterface = NULL;
|
||||
return pInterface;
|
||||
}
|
||||
|
||||
|
||||
void release()
|
||||
{
|
||||
if (m_pInterface)
|
||||
{
|
||||
m_pInterface->Release();
|
||||
m_pInterface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template< class T_QUERYINTERFACE >
|
||||
HRESULT query(T_QUERYINTERFACE** pQuery)
|
||||
{
|
||||
return m_pInterface->QueryInterface(__uuidof(T_QUERYINTERFACE), reinterpret_cast<void**>(pQuery));
|
||||
}
|
||||
|
||||
bool equals(IUnknown* pCheck)
|
||||
{
|
||||
if (
|
||||
( ! m_pInterface ) &&
|
||||
( ! pCheck )
|
||||
)
|
||||
return sal_True;
|
||||
|
||||
IUnknown* pCurrent = NULL;
|
||||
m_pInterface->QueryInterface(IID_IUnknown, (void**)&pCurrent);
|
||||
|
||||
sal_Bool bEquals = (pCheck == pCurrent);
|
||||
pCurrent->Release();
|
||||
|
||||
return bEquals;
|
||||
}
|
||||
|
||||
|
||||
bool is()
|
||||
{
|
||||
return (m_pInterface != nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
T_INTERFACE* m_pInterface;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -20,8 +20,8 @@
|
|||
#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTATYPES_H
|
||||
#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTATYPES_H
|
||||
|
||||
#include "comptr.hxx"
|
||||
#include <shobjidl.h>
|
||||
#include <systools/win32/comtools.hxx>
|
||||
|
||||
namespace fpicker{
|
||||
namespace win32{
|
||||
|
@ -31,12 +31,11 @@ namespace vista{
|
|||
// types, const etcpp.
|
||||
|
||||
|
||||
typedef ComPtr< IFileDialog , IID_IFileDialog > TFileDialog;
|
||||
typedef ComPtr< IFileOpenDialog , IID_IFileOpenDialog , CLSID_FileOpenDialog > TFileOpenDialog;
|
||||
typedef ComPtr< IFileSaveDialog , IID_IFileSaveDialog , CLSID_FileSaveDialog > TFileSaveDialog;
|
||||
typedef ComPtr< IFileDialogEvents , IID_IFileDialogEvents > TFileDialogEvents;
|
||||
typedef ComPtr< IFileDialogCustomize, IID_IFileDialogCustomize > TFileDialogCustomize;
|
||||
typedef TFileOpenDialog TFolderPickerDialog;
|
||||
typedef sal::systools::COMReference<IFileDialog> TFileDialog;
|
||||
typedef sal::systools::COMReference<IFileOpenDialog> TFileOpenDialog;
|
||||
typedef sal::systools::COMReference<IFileSaveDialog> TFileSaveDialog;
|
||||
typedef sal::systools::COMReference<IFileDialogEvents> TFileDialogEvents;
|
||||
typedef sal::systools::COMReference<IFileDialogCustomize> TFileDialogCustomize;
|
||||
|
||||
} // namespace vista
|
||||
} // namespace win32
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <objbase.h>
|
||||
|
||||
namespace sal::systools
|
||||
|
@ -40,6 +41,12 @@ namespace sal::systools
|
|||
HRESULT hr_;
|
||||
};
|
||||
|
||||
struct COM_QUERY_TAG {} constexpr COM_QUERY;
|
||||
struct COM_QUERY_THROW_TAG {} constexpr COM_QUERY_THROW;
|
||||
template <typename TAG>
|
||||
constexpr bool is_COM_query_tag
|
||||
= std::is_same_v<TAG, COM_QUERY_TAG> || std::is_same_v<TAG, COM_QUERY_THROW_TAG>;
|
||||
|
||||
/* A simple COM smart pointer template */
|
||||
template <typename T>
|
||||
class COMReference
|
||||
|
@ -59,6 +66,13 @@ namespace sal::systools
|
|||
addRef();
|
||||
}
|
||||
|
||||
// Query from IUnknown*, using COM_QUERY or COM_QUERY_THROW tags
|
||||
template <typename T2, typename TAG>
|
||||
COMReference(const COMReference<T2>& p, TAG t)
|
||||
: COMReference(p.QueryInterface<T>(t))
|
||||
{
|
||||
}
|
||||
|
||||
COMReference<T>& operator=(const COMReference<T>& other)
|
||||
{
|
||||
other.addRef();
|
||||
|
@ -77,18 +91,31 @@ namespace sal::systools
|
|||
|
||||
~COMReference() { release(); }
|
||||
|
||||
template<typename InterfaceType>
|
||||
COMReference<InterfaceType> QueryInterface(REFIID iid)
|
||||
template <typename T2, typename TAG, std::enable_if_t<is_COM_query_tag<TAG>, int> = 0>
|
||||
COMReference<T2> QueryInterface(TAG) const
|
||||
{
|
||||
COMReference<InterfaceType> ip;
|
||||
void* ip = nullptr;
|
||||
HRESULT hr = E_FAIL;
|
||||
if (com_ptr_)
|
||||
hr = com_ptr_->QueryInterface(iid, reinterpret_cast<LPVOID*>(&ip));
|
||||
hr = com_ptr_->QueryInterface(__uuidof(T2), &ip);
|
||||
|
||||
if constexpr (std::is_same_v<TAG, COM_QUERY_THROW_TAG>)
|
||||
if (FAILED(hr))
|
||||
throw ComError("QueryInterface failed: Interface not supported!", hr);
|
||||
|
||||
return { static_cast<T2*>(ip), false };
|
||||
}
|
||||
|
||||
COMReference<T>& CoCreateInstance(REFCLSID clsid, IUnknown* pOuter = nullptr,
|
||||
DWORD nCtx = CLSCTX_ALL)
|
||||
{
|
||||
clear();
|
||||
HRESULT hr = ::CoCreateInstance(clsid, pOuter, nCtx, __uuidof(T),
|
||||
reinterpret_cast<void**>(&com_ptr_));
|
||||
if (FAILED(hr))
|
||||
throw ComError("QueryInterface failed: Interface not supported!", hr);
|
||||
throw ComError("CoCreateInstance failed!", hr);
|
||||
|
||||
return ip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* operator->() const { return com_ptr_; }
|
||||
|
@ -105,11 +132,10 @@ namespace sal::systools
|
|||
|
||||
T* get() const { return com_ptr_; }
|
||||
|
||||
COMReference<T>& clear()
|
||||
void clear()
|
||||
{
|
||||
release();
|
||||
com_ptr_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is() const { return (com_ptr_ != nullptr); }
|
||||
|
|
|
@ -17,4 +17,8 @@ $(eval $(call gb_CppunitTest_use_libraries,sal_comtools,\
|
|||
sal \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_system_win32_libs,sal_comtools,\
|
||||
ole32 \
|
||||
))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/plugin/TestPlugIn.h>
|
||||
#include <systools/win32/comtools.hxx>
|
||||
#include <shobjidl.h>
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -183,30 +184,36 @@ namespace test_comtools
|
|||
|
||||
void test_query_interface()
|
||||
{
|
||||
try
|
||||
{
|
||||
sal::systools::COMReference<IUnknown> r1 = comObjectSource();
|
||||
sal::systools::COMReference<IUnknown> r2 = r1.QueryInterface<IUnknown>(IID_IUnknown);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong reference count, 2 is expected", ULONG(2), reinterpret_cast<COMObject*>(r2.get())->GetRefCount());
|
||||
}
|
||||
catch(const sal::systools::ComError&)
|
||||
{
|
||||
CPPUNIT_ASSERT_MESSAGE("Exception should not have been thrown", false);
|
||||
}
|
||||
sal::systools::COMReference<IUnknown> r1 = comObjectSource();
|
||||
sal::systools::COMReference<IUnknown> r2;
|
||||
CPPUNIT_ASSERT_NO_THROW_MESSAGE(
|
||||
"Exception should not have been thrown",
|
||||
r2 = r1.QueryInterface<IUnknown>(sal::systools::COM_QUERY_THROW));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong reference count, 2 is expected", ULONG(2),
|
||||
reinterpret_cast<COMObject*>(r2.get())->GetRefCount());
|
||||
}
|
||||
|
||||
void test_query_interface_throw()
|
||||
{
|
||||
try
|
||||
{
|
||||
sal::systools::COMReference<IUnknown> r1 = comObjectSource();
|
||||
sal::systools::COMReference<IPersistFile> r2 = r1.QueryInterface<IPersistFile>(IID_IPersistFile);
|
||||
}
|
||||
catch(const sal::systools::ComError&)
|
||||
{
|
||||
sal::systools::COMReference<IUnknown> r1 = comObjectSource();
|
||||
CPPUNIT_ASSERT_THROW_MESSAGE("Exception should have been thrown",
|
||||
auto r2 = r1.QueryInterface<IPersistFile>(sal::systools::COM_QUERY_THROW),
|
||||
sal::systools::ComError);
|
||||
}
|
||||
|
||||
void test_CoCreateInstance()
|
||||
{
|
||||
if (FAILED(CoInitialize(nullptr)))
|
||||
return;
|
||||
{
|
||||
// Use scope to destroy the reference before calling CoUninitialize
|
||||
sal::systools::COMReference<IFileOpenDialog> r;
|
||||
CPPUNIT_ASSERT_NO_THROW(r.CoCreateInstance(__uuidof(FileOpenDialog)));
|
||||
// Immediately after CoCreateInstance, refcount must be 1; increasing once gives 2
|
||||
CPPUNIT_ASSERT_EQUAL(ULONG(2), r->AddRef());
|
||||
r->Release();
|
||||
}
|
||||
CPPUNIT_ASSERT_MESSAGE("Exception should have been thrown", false);
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
// Change the following lines only, if you add, remove or rename
|
||||
|
@ -227,6 +234,7 @@ namespace test_comtools
|
|||
CPPUNIT_TEST(test_clear);
|
||||
CPPUNIT_TEST(test_query_interface);
|
||||
CPPUNIT_TEST(test_query_interface_throw);
|
||||
CPPUNIT_TEST(test_CoCreateInstance);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
};
|
||||
|
||||
|
|
|
@ -278,25 +278,27 @@ void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aPa
|
|||
break;
|
||||
}
|
||||
sal::systools::COMReference<IShellLinkW> link;
|
||||
auto e2 = CoCreateInstance(
|
||||
CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
|
||||
reinterpret_cast<LPVOID *>(&link));
|
||||
if (FAILED(e2)) {
|
||||
try
|
||||
{
|
||||
link.CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER);
|
||||
}
|
||||
catch (sal::systools::ComError& e)
|
||||
{
|
||||
throw css::lang::IllegalArgumentException(
|
||||
("XSystemShellExecute.execute, CoCreateInstance failed with "
|
||||
+ OUString::number(e2)),
|
||||
+ OUString::number(e.GetHresult())),
|
||||
{}, 0);
|
||||
}
|
||||
sal::systools::COMReference<IPersistFile> file;
|
||||
try {
|
||||
file = link.QueryInterface<IPersistFile>(IID_IPersistFile);
|
||||
file = link.QueryInterface<IPersistFile>(sal::systools::COM_QUERY_THROW);
|
||||
} catch(sal::systools::ComError & e3) {
|
||||
throw css::lang::IllegalArgumentException(
|
||||
("XSystemShellExecute.execute, QueryInterface failed with: "
|
||||
+ o3tl::runtimeToOUString(e3.what())),
|
||||
{}, 0);
|
||||
}
|
||||
e2 = file->Load(path, STGM_READ);
|
||||
HRESULT e2 = file->Load(path, STGM_READ);
|
||||
if (FAILED(e2)) {
|
||||
throw css::lang::IllegalArgumentException(
|
||||
("XSystemShellExecute.execute, IPersistFile.Load failed with "
|
||||
|
|
|
@ -308,15 +308,12 @@ static std::wstring getShellLinkTarget(const std::wstring& aLnkFile)
|
|||
try
|
||||
{
|
||||
sal::systools::COMReference<IShellLinkW> pIShellLink;
|
||||
HRESULT hr = CoCreateInstance(
|
||||
CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW, reinterpret_cast<LPVOID*>(&pIShellLink));
|
||||
if (FAILED(hr))
|
||||
return target;
|
||||
pIShellLink.CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER);
|
||||
|
||||
sal::systools::COMReference<IPersistFile> pIPersistFile =
|
||||
pIShellLink.QueryInterface<IPersistFile>(IID_IPersistFile);
|
||||
sal::systools::COMReference<IPersistFile> pIPersistFile(pIShellLink,
|
||||
sal::systools::COM_QUERY_THROW);
|
||||
|
||||
hr = pIPersistFile->Load(aLnkFile.c_str(), STGM_READ);
|
||||
HRESULT hr = pIPersistFile->Load(aLnkFile.c_str(), STGM_READ);
|
||||
if (FAILED(hr))
|
||||
return target;
|
||||
|
||||
|
|
Loading…
Reference in a new issue