windows-nt/Source/XPSP1/NT/shell/services/hdsrv/shhwdtct/setenum.cpp
2020-09-26 16:20:57 +08:00

305 lines
8.5 KiB
C++

#include "setenum.h"
#include "dtctreg.h"
#include "cmmn.h"
#include "misc.h"
#include "reg.h"
#include "sfstr.h"
#include "tfids.h"
#include "dbg.h"
#define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
STDMETHODIMP CEnumAutoplayHandlerImpl::Next(LPWSTR* ppszHandler,
LPWSTR* ppszAction, LPWSTR* ppszProvider, LPWSTR* ppszIconLocation)
{
HRESULT hr;
*ppszHandler = NULL;
*ppszAction = NULL;
*ppszProvider = NULL;
*ppszIconLocation = NULL;
if (!_fTakeNoActionDone)
{
LPCWSTR pszHandler = TEXT("MSTakeNoAction");
WCHAR szAction[MAX_ACTION];
WCHAR szProvider[MAX_PROVIDER];
WCHAR szIconLocation[MAX_ICONLOCATION];
if (_rghkiHandlers)
{
if (_dwIndex < _cHandlers)
{
pszHandler = _rghkiHandlers[_dwIndex].szHandler;
}
else
{
_fTakeNoActionDone = TRUE;
}
}
else
{
_fTakeNoActionDone = TRUE;
}
hr = _GetActionFromHandler(pszHandler, szAction, ARRAYSIZE(szAction));
if (SUCCEEDED(hr))
{
hr = _GetIconLocationFromHandler(pszHandler, szIconLocation,
ARRAYSIZE(szIconLocation));
if (SUCCEEDED(hr))
{
hr = _GetProviderFromHandler(pszHandler, szProvider,
ARRAYSIZE(szProvider));
if (SUCCEEDED(hr))
{
hr = _CoTaskMemCopy(pszHandler, ppszHandler);
if (SUCCEEDED(hr))
{
hr = _CoTaskMemCopy(szAction,
ppszAction);
if (SUCCEEDED(hr))
{
hr = _CoTaskMemCopy(szIconLocation,
ppszIconLocation);
if (SUCCEEDED(hr))
{
hr = _CoTaskMemCopy(szProvider,
ppszProvider);
}
}
}
}
}
}
if (FAILED(hr))
{
if (*ppszHandler)
{
CoTaskMemFree((PVOID)*ppszHandler);
*ppszHandler = NULL;
}
if (*ppszAction)
{
CoTaskMemFree((PVOID)*ppszAction);
*ppszAction = NULL;
}
if (*ppszProvider)
{
CoTaskMemFree((PVOID)*ppszProvider);
*ppszProvider = NULL;
}
if (*ppszIconLocation)
{
CoTaskMemFree((PVOID)*ppszIconLocation);
*ppszIconLocation = NULL;
}
}
}
else
{
hr = S_FALSE;
}
++_dwIndex;
return hr;
}
HRESULT _GetKeyLastWriteTime(LPCWSTR pszHandler, FILETIME* pft)
{
WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("Handlers\\"));
HRESULT hr = SafeStrCatN(szKeyName, pszHandler, ARRAYSIZE(szKeyName));
if (SUCCEEDED(hr))
{
HKEY hkey;
hr = _RegOpenKey(HKEY_LOCAL_MACHINE, szKeyName, &hkey);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
if (ERROR_SUCCESS != RegQueryInfoKey(hkey,
NULL, // class buffer
0, // size of class buffer
NULL, // reserved
NULL, // number of subkeys
NULL, // longest subkey name
NULL, // longest class string
NULL, // number of value entries
NULL, // longest value name
NULL, // longest value data
NULL, // descriptor length
pft // last write time
))
{
// Bad. Set it to right now
GetSystemTimeAsFileTime(pft);
}
hr = S_OK;
_RegCloseKey(hkey);
}
}
return hr;
}
HRESULT CEnumAutoplayHandlerImpl::_Init(LPWSTR pszEventHandler)
{
WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("EventHandlers\\"));
HRESULT hr = SafeStrCatN(szKeyName, pszEventHandler,
ARRAYSIZE(szKeyName));
if (SUCCEEDED(hr))
{
HKEY hkey;
hr = _RegOpenKey(HKEY_LOCAL_MACHINE, szKeyName, &hkey);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
if (ERROR_SUCCESS == RegQueryInfoKey(hkey,
NULL, // class buffer
0, // size of class buffer
NULL, // reserved
NULL, // number of subkeys
NULL, // longest subkey name
NULL, // longest class string
&_cHandlers, // number of value entries
NULL, // longest value name
NULL, // longest value data
NULL, // descriptor length
NULL // last write time
))
{
hr = _AllocMemoryChunk<_HANDLERKEYINFO*>(_cHandlers *
sizeof(_HANDLERKEYINFO), &_rghkiHandlers);
if (SUCCEEDED(hr))
{
for (DWORD dw = 0; SUCCEEDED(hr) && (dw < _cHandlers); ++dw)
{
hr = _RegEnumStringValue(hkey, dw, _rghkiHandlers[dw].szHandler,
ARRAYSIZE(_rghkiHandlers[dw].szHandler));
if (SUCCEEDED(hr))
{
if (S_FALSE != hr)
{
hr = _GetKeyLastWriteTime(
_rghkiHandlers[dw].szHandler,
&(_rghkiHandlers[dw].ftLastWriteTime));
}
else
{
// There's less then there was when we queried for it...
_cHandlers = dw;
break;
}
}
}
if (SUCCEEDED(hr))
{
// We don't care if this fails
_SortHandlers();
}
else
{
_FreeMemoryChunk<_HANDLERKEYINFO*>(_rghkiHandlers);
_rghkiHandlers = NULL;
_cHandlers = 0;
}
}
else
{
_cHandlers = 0;
}
}
else
{
hr = S_FALSE;
}
_RegCloseKey(hkey);
}
}
return hr;
}
HRESULT CEnumAutoplayHandlerImpl::_SwapHandlerKeyInfo(DWORD dwLeft,
DWORD dwRight)
{
_HANDLERKEYINFO hkiTmp = _rghkiHandlers[dwLeft];
_rghkiHandlers[dwLeft] = _rghkiHandlers[dwRight];
_rghkiHandlers[dwRight] = hkiTmp;
return S_OK;
}
HRESULT CEnumAutoplayHandlerImpl::_SortHandlers()
{
HRESULT hr;
if (_rghkiHandlers)
{
hr = S_OK;
for (DWORD dwOuter = 0; dwOuter < _cHandlers; ++dwOuter)
{
_HANDLERKEYINFO* phkiOuter = &(_rghkiHandlers[dwOuter]);
ULARGE_INTEGER ulOuter;
ulOuter.LowPart = phkiOuter->ftLastWriteTime.dwLowDateTime;
ulOuter.HighPart = phkiOuter->ftLastWriteTime.dwHighDateTime;
for (DWORD dwInner = dwOuter + 1; dwInner < _cHandlers; ++dwInner)
{
_HANDLERKEYINFO* phkiInner = &(_rghkiHandlers[dwInner]);
ULARGE_INTEGER ulInner;
ulInner.LowPart = phkiInner->ftLastWriteTime.dwLowDateTime;
ulInner.HighPart = phkiInner->ftLastWriteTime.dwHighDateTime;
if (ulOuter.QuadPart > ulInner.QuadPart)
{
hr = _SwapHandlerKeyInfo(dwOuter, dwInner);
}
}
}
}
else
{
hr = S_FALSE;
}
return hr;
}
CEnumAutoplayHandlerImpl::CEnumAutoplayHandlerImpl() : _dwIndex(0), _rghkiHandlers(NULL),
_cHandlers(0), _fTakeNoActionDone(FALSE)
{}
CEnumAutoplayHandlerImpl::~CEnumAutoplayHandlerImpl()
{
if (_rghkiHandlers)
{
_FreeMemoryChunk<_HANDLERKEYINFO*>(_rghkiHandlers);
}
}