mirror of
https://github.com/reactos/reactos.git
synced 2025-04-05 21:21:33 +00:00
[BROWSEUI] Implement CLSID_ACListISF (#3298)
Implement enumeration of IShellFolder items of auto-completion. CORE-9281
This commit is contained in:
parent
1b45d9ee4b
commit
24833a6dde
2 changed files with 380 additions and 34 deletions
|
@ -2,6 +2,7 @@
|
|||
* Shell AutoComplete list
|
||||
*
|
||||
* Copyright 2015 Thomas Faber
|
||||
* Copyright 2020 Katayama Hirofumi MZ
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -20,8 +21,10 @@
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
CACListISF::CACListISF() :
|
||||
m_dwOptions(0)
|
||||
CACListISF::CACListISF()
|
||||
: m_dwOptions(ACLO_CURRENTDIR | ACLO_MYCOMPUTER)
|
||||
, m_iNextLocation(LT_DIRECTORY)
|
||||
, m_fShowHidden(FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -29,26 +32,290 @@ CACListISF::~CACListISF()
|
|||
{
|
||||
}
|
||||
|
||||
// *** IEnumString methods ***
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
|
||||
{
|
||||
TRACE("(%p, %d, %p, %p)\n", this, celt, rgelt, pceltFetched);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::Reset()
|
||||
HRESULT CACListISF::NextLocation()
|
||||
{
|
||||
TRACE("(%p)\n", this);
|
||||
return E_NOTIMPL;
|
||||
HRESULT hr;
|
||||
switch (m_iNextLocation)
|
||||
{
|
||||
case LT_DIRECTORY:
|
||||
m_iNextLocation = LT_DESKTOP;
|
||||
if (!ILIsEmpty(m_pidlCurDir) && (m_dwOptions & ACLO_CURRENTDIR))
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST> pidl(ILClone(m_pidlCurDir));
|
||||
hr = SetLocation(pidl.Detach());
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
TRACE("LT_DIRECTORY\n");
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
// FALL THROUGH
|
||||
case LT_DESKTOP:
|
||||
m_iNextLocation = LT_MYCOMPUTER;
|
||||
if (m_dwOptions & ACLO_DESKTOP)
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST> pidl;
|
||||
hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return S_FALSE;
|
||||
hr = SetLocation(pidl.Detach());
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
TRACE("LT_DESKTOP\n");
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
// FALL THROUGH
|
||||
case LT_MYCOMPUTER:
|
||||
m_iNextLocation = LT_FAVORITES;
|
||||
if (m_dwOptions & ACLO_MYCOMPUTER)
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST> pidl;
|
||||
hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidl);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return S_FALSE;
|
||||
hr = SetLocation(pidl.Detach());
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
TRACE("LT_MYCOMPUTER\n");
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
// FALL THROUGH
|
||||
case LT_FAVORITES:
|
||||
m_iNextLocation = LT_MAX;
|
||||
if (m_dwOptions & ACLO_FAVORITES)
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST> pidl;
|
||||
hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return S_FALSE;
|
||||
hr = SetLocation(pidl.Detach());
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
TRACE("LT_FAVORITES\n");
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
// FALL THROUGH
|
||||
case LT_MAX:
|
||||
default:
|
||||
TRACE("LT_MAX\n");
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::Skip(ULONG celt)
|
||||
HRESULT CACListISF::SetLocation(LPITEMIDLIST pidl)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pidl);
|
||||
|
||||
m_pEnumIDList.Release();
|
||||
m_pShellFolder.Release();
|
||||
m_pidlLocation.Free();
|
||||
|
||||
if (!pidl)
|
||||
return E_FAIL;
|
||||
|
||||
m_pidlLocation.Attach(pidl);
|
||||
|
||||
CComPtr<IShellFolder> pFolder;
|
||||
HRESULT hr = SHGetDesktopFolder(&pFolder);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!ILIsEmpty(pidl))
|
||||
{
|
||||
hr = pFolder->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &m_pShellFolder));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pShellFolder.Attach(pFolder.Detach());
|
||||
}
|
||||
|
||||
SHCONTF Flags = SHCONTF_FOLDERS | SHCONTF_INIT_ON_FIRST_NEXT;
|
||||
if (m_fShowHidden)
|
||||
Flags |= SHCONTF_INCLUDEHIDDEN;
|
||||
if (!(m_dwOptions & ACLO_FILESYSDIRS))
|
||||
Flags |= SHCONTF_NONFOLDERS;
|
||||
|
||||
hr = m_pShellFolder->EnumObjects(NULL, Flags, &m_pEnumIDList);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
ERR("EnumObjects failed: 0x%lX\n", hr);
|
||||
hr = E_FAIL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CACListISF::GetDisplayName(LPCITEMIDLIST pidlChild, CComHeapPtr<WCHAR>& pszChild)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pidlChild);
|
||||
pszChild.Free();
|
||||
|
||||
STRRET StrRet;
|
||||
DWORD dwFlags = SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
|
||||
HRESULT hr = m_pShellFolder->GetDisplayNameOf(pidlChild, dwFlags, &StrRet);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dwFlags = SHGDN_INFOLDER | SHGDN_FORPARSING;
|
||||
hr = m_pShellFolder->GetDisplayNameOf(pidlChild, dwFlags, &StrRet);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = StrRetToStrW(&StrRet, NULL, &pszChild);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
TRACE("pszChild: '%S'\n", static_cast<LPCWSTR>(pszChild));
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CACListISF::GetPathName(LPCITEMIDLIST pidlChild, CComHeapPtr<WCHAR>& pszPath)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pidlChild);
|
||||
|
||||
CComHeapPtr<WCHAR> pszChild;
|
||||
HRESULT hr = GetDisplayName(pidlChild, pszChild);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
CStringW szPath;
|
||||
if (m_szExpand.GetLength() && m_iNextLocation == LT_DIRECTORY)
|
||||
{
|
||||
INT cchExpand = m_szExpand.GetLength();
|
||||
if (StrCmpNIW(pszChild, m_szExpand, cchExpand) != 0 ||
|
||||
pszChild[0] != L'\\' || pszChild[1] != L'\\')
|
||||
{
|
||||
szPath = m_szExpand;
|
||||
}
|
||||
}
|
||||
szPath += pszChild;
|
||||
|
||||
INT cchMax = szPath.GetLength() + 1;
|
||||
CComHeapPtr<WCHAR> pszFullPath;
|
||||
if (!pszFullPath.Allocate(cchMax))
|
||||
{
|
||||
ERR("Out of memory\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
StringCchCopyW(pszFullPath, cchMax, szPath);
|
||||
pszPath.Attach(pszFullPath.Detach());
|
||||
TRACE("pszPath: '%S'\n", static_cast<LPCWSTR>(pszPath));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// *** IEnumString methods ***
|
||||
STDMETHODIMP CACListISF::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
|
||||
{
|
||||
TRACE("(%p, %d, %p, %p)\n", this, celt, rgelt, pceltFetched);
|
||||
|
||||
if (celt == 0)
|
||||
return S_OK;
|
||||
if (!rgelt)
|
||||
return S_FALSE;
|
||||
|
||||
*rgelt = NULL;
|
||||
if (pceltFetched)
|
||||
*pceltFetched = 0;
|
||||
|
||||
if (!m_pEnumIDList)
|
||||
{
|
||||
NextLocation();
|
||||
if (!m_pEnumIDList)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
CComHeapPtr<ITEMIDLIST> pidlChild;
|
||||
CComHeapPtr<WCHAR> pszPathName;
|
||||
|
||||
do
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
pidlChild.Free();
|
||||
hr = m_pEnumIDList->Next(1, &pidlChild, NULL);
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
pszPathName.Free();
|
||||
GetPathName(pidlChild, pszPathName);
|
||||
if (!pszPathName)
|
||||
continue;
|
||||
|
||||
if (m_dwOptions & (ACLO_FILESYSONLY | ACLO_FILESYSDIRS))
|
||||
{
|
||||
DWORD attrs = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
|
||||
hr = m_pShellFolder->GetAttributesOf(1, const_cast<LPCITEMIDLIST *>(&pidlChild), &attrs);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (!(attrs & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_dwOptions & ACLO_FILESYSDIRS) && !PathIsDirectoryW(pszPathName))
|
||||
continue;
|
||||
|
||||
hr = S_OK;
|
||||
break;
|
||||
}
|
||||
} while (hr == S_FALSE && NextLocation() == S_OK);
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
*rgelt = pszPathName.Detach();
|
||||
if (pceltFetched)
|
||||
*pceltFetched = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
|
||||
TRACE("*rgelt: %S\n", *rgelt);
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CACListISF::Reset()
|
||||
{
|
||||
TRACE("(%p)\n", this);
|
||||
|
||||
m_iNextLocation = LT_DIRECTORY;
|
||||
m_szExpand = L"";
|
||||
|
||||
SHELLSTATE ss = { 0 };
|
||||
SHGetSetSettings(&ss, SSF_SHOWALLOBJECTS, FALSE);
|
||||
m_fShowHidden = ss.fShowAllObjects;
|
||||
|
||||
if (m_dwOptions & ACLO_CURRENTDIR)
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST> pidl;
|
||||
if (m_pBrowserService)
|
||||
{
|
||||
m_pBrowserService->GetPidl(&pidl);
|
||||
if (pidl)
|
||||
Initialize(pidl);
|
||||
}
|
||||
HRESULT hr = SetLocation(pidl.Detach());
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CACListISF::Skip(ULONG celt)
|
||||
{
|
||||
TRACE("(%p, %d)\n", this, celt);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::Clone(IEnumString **ppOut)
|
||||
STDMETHODIMP CACListISF::Clone(IEnumString **ppOut)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, ppOut);
|
||||
*ppOut = NULL;
|
||||
|
@ -56,36 +323,54 @@ HRESULT STDMETHODCALLTYPE CACListISF::Clone(IEnumString **ppOut)
|
|||
}
|
||||
|
||||
// *** IACList methods ***
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::Expand(LPCOLESTR pszExpand)
|
||||
STDMETHODIMP CACListISF::Expand(LPCOLESTR pszExpand)
|
||||
{
|
||||
TRACE("(%p, %ls)\n", this, pszExpand);
|
||||
return E_NOTIMPL;
|
||||
|
||||
m_szExpand = pszExpand;
|
||||
|
||||
m_iNextLocation = LT_DIRECTORY;
|
||||
CComHeapPtr<ITEMIDLIST> pidl;
|
||||
HRESULT hr = SHParseDisplayName(m_szExpand, NULL, &pidl, NULL, NULL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = SetLocation(pidl.Detach());
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
m_szExpand = L"";
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// *** IACList2 methods ***
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::SetOptions(DWORD dwFlag)
|
||||
STDMETHODIMP CACListISF::SetOptions(DWORD dwFlag)
|
||||
{
|
||||
TRACE("(%p, %lu)\n", this, dwFlag);
|
||||
m_dwOptions = dwFlag;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::GetOptions(DWORD* pdwFlag)
|
||||
STDMETHODIMP CACListISF::GetOptions(DWORD* pdwFlag)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pdwFlag);
|
||||
*pdwFlag = m_dwOptions;
|
||||
return S_OK;
|
||||
if (pdwFlag)
|
||||
{
|
||||
*pdwFlag = m_dwOptions;
|
||||
return S_OK;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// *** IShellService methods ***
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::SetOwner(IUnknown *punkOwner)
|
||||
STDMETHODIMP CACListISF::SetOwner(IUnknown *punkOwner)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, punkOwner);
|
||||
return E_NOTIMPL;
|
||||
m_pBrowserService.Release();
|
||||
punkOwner->QueryInterface(IID_PPV_ARG(IBrowserService, &m_pBrowserService));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// *** IPersist methods ***
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::GetClassID(CLSID *pClassID)
|
||||
STDMETHODIMP CACListISF::GetClassID(CLSID *pClassID)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pClassID);
|
||||
if (pClassID == NULL)
|
||||
|
@ -95,8 +380,39 @@ HRESULT STDMETHODCALLTYPE CACListISF::GetClassID(CLSID *pClassID)
|
|||
}
|
||||
|
||||
// *** IPersistFolder methods ***
|
||||
HRESULT STDMETHODCALLTYPE CACListISF::Initialize(PCIDLIST_ABSOLUTE pidl)
|
||||
STDMETHODIMP CACListISF::Initialize(PCIDLIST_ABSOLUTE pidl)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pidl);
|
||||
m_pidlCurDir.Free();
|
||||
if (!pidl)
|
||||
return S_OK;
|
||||
|
||||
LPITEMIDLIST pidlClone = ILClone(pidl);
|
||||
if (!pidlClone)
|
||||
{
|
||||
ERR("Out of memory\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
m_pidlCurDir.Attach(pidlClone);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// *** ICurrentWorkingDirectory methods ***
|
||||
STDMETHODIMP CACListISF::GetDirectory(LPWSTR pwzPath, DWORD cchSize)
|
||||
{
|
||||
TRACE("(%p, %p, %ld)\n", this, pwzPath, cchSize);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CACListISF::SetDirectory(LPCWSTR pwzPath)
|
||||
{
|
||||
TRACE("(%p, %ls, %ld)\n", this, pwzPath);
|
||||
LPITEMIDLIST pidl = ILCreateFromPathW(pwzPath);
|
||||
if (!pidl)
|
||||
{
|
||||
ERR("Out of memory\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
m_pidlCurDir.Attach(pidl);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Shell AutoComplete list
|
||||
*
|
||||
* Copyright 2015 Thomas Faber
|
||||
* Copyright 2020 Katayama Hirofumi MZ
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -25,40 +26,68 @@ class CACListISF :
|
|||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IEnumString,
|
||||
public IACList2,
|
||||
public ICurrentWorkingDirectory,
|
||||
public IShellService,
|
||||
public IPersistFolder
|
||||
{
|
||||
private:
|
||||
enum LOCATION_TYPE
|
||||
{
|
||||
LT_DIRECTORY,
|
||||
LT_DESKTOP,
|
||||
LT_MYCOMPUTER,
|
||||
LT_FAVORITES,
|
||||
LT_MAX
|
||||
};
|
||||
|
||||
DWORD m_dwOptions;
|
||||
LOCATION_TYPE m_iNextLocation;
|
||||
BOOL m_fShowHidden;
|
||||
CStringW m_szExpand;
|
||||
CComHeapPtr<ITEMIDLIST> m_pidlLocation;
|
||||
CComHeapPtr<ITEMIDLIST> m_pidlCurDir;
|
||||
CComPtr<IEnumIDList> m_pEnumIDList;
|
||||
CComPtr<IShellFolder> m_pShellFolder;
|
||||
CComPtr<IBrowserService> m_pBrowserService;
|
||||
|
||||
public:
|
||||
CACListISF();
|
||||
~CACListISF();
|
||||
|
||||
HRESULT NextLocation();
|
||||
HRESULT SetLocation(LPITEMIDLIST pidl);
|
||||
HRESULT GetDisplayName(LPCITEMIDLIST pidlChild, CComHeapPtr<WCHAR>& pszChild);
|
||||
HRESULT GetPathName(LPCITEMIDLIST pidlChild, CComHeapPtr<WCHAR>& pszPath);
|
||||
|
||||
// *** IEnumString methods ***
|
||||
virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
|
||||
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
|
||||
virtual HRESULT STDMETHODCALLTYPE Reset();
|
||||
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumString **ppenum);
|
||||
STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched) override;
|
||||
STDMETHODIMP Skip(ULONG celt) override;
|
||||
STDMETHODIMP Reset() override;
|
||||
STDMETHODIMP Clone(IEnumString **ppenum) override;
|
||||
|
||||
// *** IACList methods ***
|
||||
virtual HRESULT STDMETHODCALLTYPE Expand(LPCOLESTR pszExpand);
|
||||
STDMETHODIMP Expand(LPCOLESTR pszExpand) override;
|
||||
|
||||
// *** IACList2 methods ***
|
||||
virtual HRESULT STDMETHODCALLTYPE SetOptions(DWORD dwFlag);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetOptions(DWORD* pdwFlag);
|
||||
STDMETHODIMP SetOptions(DWORD dwFlag) override;
|
||||
STDMETHODIMP GetOptions(DWORD* pdwFlag) override;
|
||||
|
||||
// FIXME: These virtual keywords below should be removed.
|
||||
|
||||
// *** IShellService methods ***
|
||||
virtual HRESULT STDMETHODCALLTYPE SetOwner(IUnknown *);
|
||||
virtual STDMETHODIMP SetOwner(IUnknown *punkOwner) override;
|
||||
|
||||
// *** IPersist methods ***
|
||||
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
|
||||
virtual STDMETHODIMP GetClassID(CLSID *pClassID) override;
|
||||
|
||||
// *** IPersistFolder methods ***
|
||||
virtual HRESULT STDMETHODCALLTYPE Initialize(PCIDLIST_ABSOLUTE pidl);
|
||||
virtual STDMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidl) override;
|
||||
|
||||
// *** ICurrentWorkingDirectory methods ***
|
||||
STDMETHODIMP GetDirectory(LPWSTR pwzPath, DWORD cchSize) override;
|
||||
STDMETHODIMP SetDirectory(LPCWSTR pwzPath) override;
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_REGISTRY_RESOURCEID(IDR_ACLISTISF)
|
||||
DECLARE_NOT_AGGREGATABLE(CACListISF)
|
||||
|
||||
|
@ -72,5 +101,6 @@ public:
|
|||
// Windows doesn't return this
|
||||
//COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_ICurrentWorkingDirectory, ICurrentWorkingDirectory)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue