You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
709 lines
18 KiB
709 lines
18 KiB
#include "shellprv.h"
|
|
#include "ids.h"
|
|
|
|
#include "hwcmmn.h"
|
|
#include "apdlglog.h"
|
|
#include "mtptl.h"
|
|
|
|
BOOL _AreHandlersDifferent(LPCWSTR /*pszOriginal*/, LPCWSTR /*pszNew*/)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
CHandlerDataArray::~CHandlerDataArray()
|
|
{
|
|
if (IsDPASet())
|
|
{
|
|
DestroyCallback(_ReleaseHandler, NULL);
|
|
}
|
|
}
|
|
|
|
BOOL CHandlerDataArray::_IsDemotedHandler(PCWSTR pszHandler)
|
|
{
|
|
return ((0 == StrCmpIW(pszHandler, L"MSTakeNoAction"))
|
|
|| (0 == StrCmpIW(pszHandler, L"MSOpenFolder")));
|
|
}
|
|
|
|
HRESULT CHandlerDataArray::AddHandler(CHandlerData *pdata)
|
|
{
|
|
// always insert ahead of TakeNoAction and OpenFolder
|
|
int iInsert;
|
|
if (!_IsDemotedHandler(pdata->_pszHandler))
|
|
{
|
|
int c = GetPtrCount();
|
|
for (iInsert = 0; iInsert < c; iInsert++)
|
|
{
|
|
if (_IsDemotedHandler(GetPtr(iInsert)->_pszHandler))
|
|
{
|
|
// insert here
|
|
break;
|
|
}
|
|
}
|
|
iInsert = InsertPtr(iInsert, pdata);
|
|
}
|
|
else
|
|
{
|
|
iInsert = AppendPtr(pdata);
|
|
}
|
|
|
|
return DPA_ERR != iInsert ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
|
|
BOOL CHandlerDataArray::IsDuplicateCommand(PCWSTR pszCommand)
|
|
{
|
|
WCHAR sz[MAX_PATH * 2];
|
|
BOOL fRet = FALSE;
|
|
int c = GetPtrCount();
|
|
for (int i = 0; i < c; i++)
|
|
{
|
|
CHandlerData *pdata = GetPtr(i);
|
|
if (SUCCEEDED(pdata->_GetCommand(sz, ARRAYSIZE(sz))))
|
|
{
|
|
fRet = (0 == StrCmpIW(pszCommand, sz));
|
|
if (fRet)
|
|
break;
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
// We are erring on the side of safety here by giving FALSE positives
|
|
// sometimes. This could be optimized to consider if we have diff handler
|
|
// just because one is missing.
|
|
void CContentTypeData::UpdateDirty()
|
|
{
|
|
BOOL fDirty = _AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
|
|
(HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags);
|
|
|
|
_SetDirty(fDirty);
|
|
}
|
|
|
|
#define SOFTPREFIX TEXT("[soft]")
|
|
|
|
HRESULT CContentTypeData::CommitChangesToStorage()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (_AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
|
|
(HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags))
|
|
{
|
|
// Yep, changed
|
|
IAutoplayHandler* piah;
|
|
|
|
hr = _GetAutoplayHandler(_szDrive, TEXT("ContentArrival"), _szContentTypeHandler, &piah);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!_fSoftCommit)
|
|
{
|
|
hr = piah->SetDefaultHandler(_pszHandlerDefault);
|
|
}
|
|
else
|
|
{
|
|
WCHAR szHandler[MAX_HANDLER + ARRAYSIZE(SOFTPREFIX)];
|
|
|
|
lstrcpyn(szHandler, SOFTPREFIX, ARRAYSIZE(szHandler));
|
|
StrCatBuff(szHandler, _pszHandlerDefault, ARRAYSIZE(szHandler));
|
|
|
|
hr = piah->SetDefaultHandler(szHandler);
|
|
}
|
|
|
|
piah->Release();
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_SetHandlerDefault(&_pszHandlerDefaultOriginal, _pszHandlerDefault);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CContentTypeData::~CContentTypeData()
|
|
{
|
|
if (_pszHandlerDefaultOriginal)
|
|
{
|
|
CoTaskMemFree(_pszHandlerDefaultOriginal);
|
|
}
|
|
|
|
if (_pszHandlerDefault)
|
|
{
|
|
CoTaskMemFree(_pszHandlerDefault);
|
|
}
|
|
}
|
|
|
|
HRESULT _MakeActionString(LPCWSTR pszAction, LPWSTR* ppszAction2)
|
|
{
|
|
*ppszAction2 = NULL;
|
|
|
|
WCHAR szAction[250];
|
|
HRESULT hr = SHLoadIndirectString(pszAction, szAction, ARRAYSIZE(szAction), NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SHStrDup(szAction, ppszAction2);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _MakeProviderString(LPCWSTR pszProvider, LPWSTR* ppszProvider2)
|
|
{
|
|
WCHAR szProviderNonMUI[250];
|
|
HRESULT hr = SHLoadIndirectString(pszProvider, szProviderNonMUI, ARRAYSIZE(szProviderNonMUI), NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR szUsing[50];
|
|
|
|
if (LoadString(g_hinst, IDS_AP_USING, szUsing, ARRAYSIZE(szUsing)))
|
|
{
|
|
WCHAR szProvider2[250];
|
|
|
|
hr = StringCchPrintf(szProvider2, ARRAYSIZE(szProvider2), szUsing, szProviderNonMUI);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SHStrDup(szProvider2, ppszProvider2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
inline void _CoTaskMemFree(void* pv)
|
|
{
|
|
if (pv)
|
|
{
|
|
CoTaskMemFree(pv);
|
|
}
|
|
}
|
|
|
|
HRESULT _CreateHandlerData( PCWSTR pszAction,
|
|
PCWSTR pszProvider,
|
|
PWSTR *ppszHandler, // IN/OUT
|
|
PWSTR *ppszIcon, // IN/OUT
|
|
CHandlerData **ppdata)
|
|
{
|
|
*ppdata = 0;
|
|
LPWSTR pszAction2 = NULL;
|
|
HRESULT hr = _MakeActionString(pszAction, &pszAction2);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPWSTR pszProvider2 = NULL;
|
|
// Special case this guy, we don't want to say:
|
|
// "Take no action, using Microsoft Windows"
|
|
if (lstrcmp(*ppszHandler, TEXT("MSTakeNoAction")))
|
|
{
|
|
hr = _MakeProviderString(pszProvider, &pszProvider2);
|
|
}
|
|
// else this is NULL, and ignored
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppdata = new CHandlerData();
|
|
if (*ppdata)
|
|
{
|
|
// give away ownership of these allocations
|
|
(*ppdata)->Init(*ppszHandler, pszAction2,
|
|
*ppszIcon, pszProvider2);
|
|
|
|
*ppszHandler = NULL;
|
|
*ppszIcon = NULL;
|
|
pszAction2 = NULL;
|
|
pszProvider2 = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
CoTaskMemFree(pszProvider2);
|
|
}
|
|
|
|
}
|
|
CoTaskMemFree(pszAction2);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CContentBase::_EnumHandlerHelper(IAutoplayHandler* piah)
|
|
{
|
|
IEnumAutoplayHandler* penum;
|
|
if (S_OK == piah->EnumHandlers(&penum))
|
|
{
|
|
LPWSTR pszHandler;
|
|
LPWSTR pszAction;
|
|
LPWSTR pszProvider;
|
|
LPWSTR pszIconLocation;
|
|
while (S_OK == penum->Next(&pszHandler, &pszAction, &pszProvider,
|
|
&pszIconLocation))
|
|
{
|
|
// Do not free the strings from EnumHandlers
|
|
// CHandlerData will free them in its destructor
|
|
CHandlerData *pdata;
|
|
HRESULT hr = _CreateHandlerData(pszAction, pszProvider, &pszHandler, &pszIconLocation, &pdata);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _dpaHandlerData.AddHandler(pdata);
|
|
if (FAILED(hr))
|
|
{
|
|
pdata->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CoTaskMemFree(pszHandler);
|
|
CoTaskMemFree(pszIconLocation);
|
|
}
|
|
CoTaskMemFree(pszProvider);
|
|
CoTaskMemFree(pszAction);
|
|
}
|
|
|
|
penum->Release();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT _CreateLegacyHandler(IAssociationElement *pae, PCWSTR pszAction, CHandlerData **ppdata)
|
|
{
|
|
*ppdata = 0;
|
|
PWSTR pszIcon;
|
|
HRESULT hr = pae->QueryString(AQVS_APPLICATION_PATH, NULL, &pszIcon);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
PWSTR pszFriendly;
|
|
hr = pae->QueryString(AQVS_APPLICATION_FRIENDLYNAME, NULL, &pszFriendly);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
PWSTR pszHandler;
|
|
hr = SHStrDup(TEXT("AutoplayLegacyHandler"), &pszHandler);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _CreateHandlerData(pszAction, pszFriendly, &pszHandler, &pszIcon, ppdata);
|
|
CoTaskMemFree(pszHandler);
|
|
}
|
|
CoTaskMemFree(pszFriendly);
|
|
}
|
|
CoTaskMemFree(pszIcon);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CHandlerData* CContentBase::GetHandlerData(int i)
|
|
{
|
|
CHandlerData* phandlerdata = _dpaHandlerData.GetPtr(i);
|
|
|
|
if (phandlerdata)
|
|
{
|
|
phandlerdata->AddRef();
|
|
}
|
|
|
|
return phandlerdata;
|
|
}
|
|
|
|
HRESULT CContentBase::_AddLegacyHandler(DWORD dwContentType)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if (dwContentType & (CT_CDAUDIO | CT_DVDMOVIE))
|
|
{
|
|
LPCWSTR pszProgID;
|
|
LPCWSTR pszAction;
|
|
|
|
if (dwContentType & CT_CDAUDIO)
|
|
{
|
|
pszProgID = TEXT("AudioCD");
|
|
pszAction = TEXT("@%SystemRoot%\\system32\\shell32.dll,-17171");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(dwContentType & CT_DVDMOVIE);
|
|
pszProgID = TEXT("DVD");
|
|
pszAction = TEXT("@%SystemRoot%\\system32\\shell32.dll,-17172");
|
|
}
|
|
|
|
IAssociationElement * pae;
|
|
hr = AssocElemCreateForClass(&CLSID_AssocProgidElement, pszProgID, &pae);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PWSTR pszCommand;
|
|
hr = pae->QueryString(AQVS_COMMAND, NULL, &pszCommand);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// legacy guys have a command or we dont add them
|
|
// we expect new guys to be responsible and add themselves
|
|
// to the autoplay handlers key
|
|
if (!_dpaHandlerData.IsDuplicateCommand(pszCommand))
|
|
{
|
|
CHandlerData* pdata;
|
|
hr = _CreateLegacyHandler(pae, pszAction, &pdata);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _dpaHandlerData.AddHandler(pdata);
|
|
if (FAILED(hr))
|
|
{
|
|
pdata->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
CoTaskMemFree(pszCommand);
|
|
}
|
|
pae->Release();
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CContentTypeData::Init(LPCWSTR pszDrive, DWORD dwContentType)
|
|
{
|
|
HRESULT hr;
|
|
|
|
_dwContentType = dwContentType;
|
|
|
|
hr = _GetContentTypeHandler(_dwContentType, _szContentTypeHandler,
|
|
ARRAYSIZE(_szContentTypeHandler));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _GetContentTypeInfo(_dwContentType, _szIconLabel, ARRAYSIZE(_szIconLabel),
|
|
_szIconLocation, ARRAYSIZE(_szIconLocation));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = StringCchCopy(_szDrive, ARRAYSIZE(_szDrive), pszDrive);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IAutoplayHandler* piah;
|
|
|
|
hr = _GetAutoplayHandler(_szDrive, TEXT("ContentArrival"),
|
|
_szContentTypeHandler, &piah);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = piah->GetDefaultHandler(&_pszHandlerDefaultOriginal);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (S_FALSE != hr)
|
|
{
|
|
_dwHandlerDefaultFlags = HANDLERDEFAULT_GETFLAGS(hr);
|
|
}
|
|
|
|
// SHStrDup (we want CoTaskMemAlloc)
|
|
hr = SHStrDup(_pszHandlerDefaultOriginal, &_pszHandlerDefault);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (_dpaHandlerData.Create(4))
|
|
{
|
|
hr = _EnumHandlerHelper(piah);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_AddLegacyHandler(dwContentType);
|
|
}
|
|
}
|
|
}
|
|
|
|
piah->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CContentTypeCBItem::GetText(LPWSTR pszText, DWORD cchText)
|
|
{
|
|
HRESULT hr;
|
|
CContentTypeData* pdata = GetData();
|
|
if (pdata)
|
|
{
|
|
hr = StringCchCopy(pszText, cchText, pdata->_szIconLabel);
|
|
pdata->Release();
|
|
}
|
|
else
|
|
{
|
|
*pszText = NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CContentTypeCBItem::GetIconLocation(LPWSTR pszIconLocation, DWORD cchIconLocation)
|
|
{
|
|
HRESULT hr;
|
|
CContentTypeData* pdata = GetData();
|
|
if (pdata)
|
|
{
|
|
hr = StringCchCopy(pszIconLocation, cchIconLocation, pdata->_szIconLocation);
|
|
pdata->Release();
|
|
}
|
|
else
|
|
{
|
|
*pszIconLocation = NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CHandlerData::~CHandlerData()
|
|
{
|
|
if (_pszHandler)
|
|
{
|
|
CoTaskMemFree((void*)_pszHandler);
|
|
}
|
|
if (_pszHandlerFriendlyName)
|
|
{
|
|
CoTaskMemFree((void*)_pszHandlerFriendlyName);
|
|
}
|
|
if (_pszIconLocation)
|
|
{
|
|
CoTaskMemFree((void*)_pszIconLocation);
|
|
}
|
|
if (_pszTileText)
|
|
{
|
|
CoTaskMemFree(_pszTileText);
|
|
}
|
|
}
|
|
|
|
void CHandlerData::Init(PWSTR pszHandler, PWSTR pszHandlerFriendlyName,
|
|
PWSTR pszIconLocation, PWSTR pszTileText)
|
|
{
|
|
_pszHandler = pszHandler;
|
|
_pszHandlerFriendlyName = pszHandlerFriendlyName;
|
|
_pszIconLocation = pszIconLocation;
|
|
_pszTileText = pszTileText;
|
|
// WE CANT FAIL
|
|
}
|
|
|
|
void CHandlerData::UpdateDirty()
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
HRESULT CHandlerLVItem::GetText(LPWSTR pszText, DWORD cchText)
|
|
{
|
|
HRESULT hr;
|
|
CHandlerData* pdata = GetData();
|
|
if (pdata)
|
|
{
|
|
hr = StringCchCopy(pszText, cchText, pdata->_pszHandlerFriendlyName);
|
|
pdata->Release();
|
|
}
|
|
else
|
|
{
|
|
*pszText = NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CHandlerLVItem::GetIconLocation(LPWSTR pszIconLocation, DWORD cchIconLocation)
|
|
{
|
|
HRESULT hr;
|
|
CHandlerData* pdata = GetData();
|
|
if (pdata)
|
|
{
|
|
hr = StringCchCopy(pszIconLocation, cchIconLocation, pdata->_pszIconLocation);
|
|
pdata->Release();
|
|
}
|
|
else
|
|
{
|
|
*pszIconLocation = NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CHandlerLVItem::GetTileText(int i, LPWSTR pszTileText, DWORD cchTileText)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
CHandlerData* pdata = GetData();
|
|
|
|
*pszTileText = NULL;
|
|
hr = S_FALSE;
|
|
|
|
// we dont support anything but zero
|
|
ASSERT(0 == i);
|
|
if (pdata)
|
|
{
|
|
if (pdata->_pszTileText)
|
|
{
|
|
hr = StringCchCopy(pszTileText, cchTileText, pdata->_pszTileText);
|
|
}
|
|
pdata->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// We are erring on the side of safety here by giving FALSE positives
|
|
// sometimes. This could be optimized to consider if we have diff handler
|
|
// just because one is missing.
|
|
void CNoContentData::UpdateDirty()
|
|
{
|
|
BOOL fDirty = _AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
|
|
(HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags);
|
|
|
|
_SetDirty(fDirty);
|
|
}
|
|
|
|
HRESULT CNoContentData::CommitChangesToStorage()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (_AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
|
|
(HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags))
|
|
{
|
|
// Yep, changed
|
|
IAutoplayHandler* piah;
|
|
|
|
hr = _GetAutoplayHandlerNoContent(_szDeviceID, TEXT("DeviceArrival"), &piah);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!_fSoftCommit)
|
|
{
|
|
hr = piah->SetDefaultHandler(_pszHandlerDefault);
|
|
}
|
|
else
|
|
{
|
|
WCHAR szHandler[MAX_HANDLER + ARRAYSIZE(SOFTPREFIX)];
|
|
|
|
lstrcpyn(szHandler, SOFTPREFIX, ARRAYSIZE(szHandler));
|
|
StrCatBuff(szHandler, _pszHandlerDefault, ARRAYSIZE(szHandler));
|
|
|
|
hr = piah->SetDefaultHandler(szHandler);
|
|
}
|
|
|
|
piah->Release();
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_SetHandlerDefault(&_pszHandlerDefaultOriginal, _pszHandlerDefault);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CNoContentData::~CNoContentData()
|
|
{
|
|
if (_pszHandlerDefaultOriginal)
|
|
{
|
|
CoTaskMemFree(_pszHandlerDefaultOriginal);
|
|
}
|
|
|
|
if (_pszHandlerDefault)
|
|
{
|
|
CoTaskMemFree(_pszHandlerDefault);
|
|
}
|
|
|
|
if (_pszIconLabel)
|
|
{
|
|
CoTaskMemFree((void*)_pszIconLabel);
|
|
}
|
|
|
|
if (_pszIconLocation)
|
|
{
|
|
CoTaskMemFree((void*)_pszIconLocation);
|
|
}
|
|
}
|
|
|
|
HRESULT _MakeDeviceLabel(LPCWSTR pszSource, LPWSTR* ppszDest)
|
|
{
|
|
WCHAR szDeviceName[250];
|
|
|
|
HRESULT hr = SHLoadIndirectString(pszSource, szDeviceName, ARRAYSIZE(szDeviceName), NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SHStrDup(szDeviceName, ppszDest);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CNoContentData::Init(LPCWSTR pszDeviceID)
|
|
{
|
|
HRESULT hr = StringCchCopy(_szDeviceID, ARRAYSIZE(_szDeviceID), pszDeviceID);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IAutoplayHandler* piah;
|
|
hr = _GetAutoplayHandlerNoContent(_szDeviceID, TEXT("DeviceArrival"), &piah);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = piah->GetDefaultHandler(&_pszHandlerDefaultOriginal);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (S_FALSE != hr)
|
|
{
|
|
_dwHandlerDefaultFlags = HANDLERDEFAULT_GETFLAGS(hr);
|
|
}
|
|
|
|
// SHStrDup (we want CoTaskMemAlloc)
|
|
hr = SHStrDup(_pszHandlerDefaultOriginal, &_pszHandlerDefault);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (_dpaHandlerData.Create(4))
|
|
{
|
|
hr = _EnumHandlerHelper(piah);
|
|
}
|
|
}
|
|
|
|
piah->Release();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IHWDeviceCustomProperties* pihwdevcp;
|
|
hr = GetDeviceProperties(_szDeviceID, &pihwdevcp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPWSTR pszIconLabel;
|
|
hr = pihwdevcp->GetStringProperty(TEXT("Label"), &pszIconLabel);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _MakeDeviceLabel(pszIconLabel, &_pszIconLabel);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WORD_BLOB* pblob;
|
|
|
|
hr = pihwdevcp->GetMultiStringProperty(TEXT("Icons"), TRUE, &pblob);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SHStrDup(pblob->asData, &_pszIconLocation);
|
|
|
|
CoTaskMemFree(pblob);
|
|
}
|
|
|
|
CoTaskMemFree(pszIconLabel);
|
|
}
|
|
}
|
|
|
|
pihwdevcp->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|