mirror of https://github.com/tongzx/nt5src
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.
1423 lines
36 KiB
1423 lines
36 KiB
#include "regnotif.h"
|
|
|
|
#include "svcsync.h"
|
|
#include "mtpts.h"
|
|
#include "vol.h"
|
|
|
|
#include "namellst.h"
|
|
|
|
#include "users.h"
|
|
#include "sfstr.h"
|
|
#include "tfids.h"
|
|
#include "dbg.h"
|
|
|
|
#include <shpriv.h>
|
|
|
|
#define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
|
|
|
|
#define MAGICTOKENOFFSET ((DWORD)0x57EF57EF)
|
|
|
|
LONG CHardwareDevicesImpl::_lAdviseToken = MAGICTOKENOFFSET;
|
|
DWORD CHardwareDevicesImpl::_chwdevcb = 0;
|
|
|
|
#define MAX_ADVISETOKEN 11
|
|
|
|
#pragma warning(disable: 4700 4701)
|
|
HRESULT _VolumeAddedOrUpdatedHelper(IHardwareDeviceCallback* pdevchngcb, CVolume* pvol,
|
|
BOOL fAdded)
|
|
{
|
|
DWORD cchReq;
|
|
HRESULT hr;
|
|
|
|
WCHAR szVolName[MAX_DEVICEID];
|
|
WCHAR szVolGUID[50];
|
|
WCHAR szLabel[MAX_LABEL];
|
|
WCHAR szFileSystem[MAX_FILESYSNAME];
|
|
WCHAR szAutorunIconLocation[MAX_ICONLOCATION];
|
|
WCHAR szAutorunLabel[MAX_LABEL];
|
|
WCHAR szIconLocationFromService[MAX_ICONLOCATION];
|
|
WCHAR szNoMediaIconLocationFromService[MAX_ICONLOCATION];
|
|
// We can now have a @%SystemRoot%\system32\shell32.dll,-1785 for MUI stuff
|
|
WCHAR szLabelFromService[MAX_ICONLOCATION];
|
|
|
|
VOLUMEINFO volinfo = {0};
|
|
|
|
ASSERT(pvol);
|
|
|
|
volinfo.pszDeviceIDVolume = szVolName;
|
|
volinfo.pszVolumeGUID = szVolGUID;
|
|
volinfo.pszLabel = szLabel;
|
|
volinfo.pszFileSystem = szFileSystem;
|
|
|
|
volinfo.dwState = pvol->_dwState;
|
|
|
|
hr = pvol->GetName(szVolName, ARRAYSIZE(szVolName), &cchReq);
|
|
|
|
TRACE(TF_ADVISE,
|
|
TEXT("Called _VolumeAddedOrUpdatedHelper for Vol = %s, CB = 0x%08X, Added = %d"),
|
|
szVolName, pdevchngcb, fAdded);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pvol->GetVolumeConstInfo(szVolGUID,
|
|
ARRAYSIZE(szVolGUID), &(volinfo.dwVolumeFlags), &(volinfo.dwDriveType),
|
|
&(volinfo.dwDriveCapability));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pvol->GetVolumeMediaInfo(szLabel, ARRAYSIZE(szLabel),
|
|
szFileSystem, ARRAYSIZE(szFileSystem), &(volinfo.dwFileSystemFlags),
|
|
&(volinfo.dwMaxFileNameLen), &(volinfo.dwRootAttributes), &(volinfo.dwSerialNumber),
|
|
&(volinfo.dwDriveState), &(volinfo.dwMediaState), &(volinfo.dwMediaCap));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pvol->GetIconAndLabelInfo(szAutorunIconLocation,
|
|
ARRAYSIZE(szAutorunIconLocation), szAutorunLabel,
|
|
ARRAYSIZE(szAutorunLabel), szIconLocationFromService,
|
|
ARRAYSIZE(szIconLocationFromService), szNoMediaIconLocationFromService,
|
|
ARRAYSIZE(szNoMediaIconLocationFromService), szLabelFromService,
|
|
ARRAYSIZE(szLabelFromService));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (*szAutorunIconLocation)
|
|
{
|
|
volinfo.pszAutorunIconLocation = szAutorunIconLocation;
|
|
}
|
|
|
|
if (*szAutorunLabel)
|
|
{
|
|
volinfo.pszAutorunLabel = szAutorunLabel;
|
|
}
|
|
|
|
if (*szIconLocationFromService)
|
|
{
|
|
volinfo.pszIconLocationFromService = szIconLocationFromService;
|
|
}
|
|
|
|
if (*szNoMediaIconLocationFromService)
|
|
{
|
|
volinfo.pszNoMediaIconLocationFromService = szNoMediaIconLocationFromService;
|
|
}
|
|
|
|
if (*szLabelFromService)
|
|
{
|
|
volinfo.pszLabelFromService = szLabelFromService;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pdevchngcb->VolumeAddedOrUpdated(fAdded, &volinfo);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
#pragma warning(default: 4700 4701)
|
|
|
|
STDMETHODIMP CHardwareDevicesImpl::EnumVolumes(
|
|
DWORD dwFlags, IHardwareDevicesVolumesEnum** ppenum)
|
|
{
|
|
HRESULT hr;
|
|
|
|
*ppenum = NULL;
|
|
|
|
if ((HWDEV_GETCUSTOMPROPERTIES == dwFlags) || (0 == dwFlags))
|
|
{
|
|
CHardwareDevicesVolumesEnum* phwdve = new CHardwareDevicesVolumesEnum(NULL);
|
|
|
|
if (phwdve)
|
|
{
|
|
hr = phwdve->_Init(dwFlags);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppenum = phwdve;
|
|
}
|
|
else
|
|
{
|
|
phwdve->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
ASSERT((*ppenum && SUCCEEDED(hr)) || (!*ppenum && FAILED(hr)));
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CHardwareDevicesImpl::EnumMountPoints(
|
|
IHardwareDevicesMountPointsEnum** ppenum)
|
|
{
|
|
HRESULT hr;
|
|
CHardwareDevicesMountPointsEnum* phwdmtpte = new CHardwareDevicesMountPointsEnum(NULL);
|
|
|
|
*ppenum = NULL;
|
|
|
|
if (phwdmtpte)
|
|
{
|
|
hr = phwdmtpte->_Init();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppenum = phwdmtpte;
|
|
}
|
|
else
|
|
{
|
|
phwdmtpte->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
ASSERT((*ppenum && SUCCEEDED(hr)) || (!*ppenum && FAILED(hr)));
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CHardwareDevicesImpl::EnumDevices(IHardwareDevicesEnum** /*ppenum*/)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT _GetStringAdviseToken(LONG lAdviseToken, LPWSTR szAdviseToken, DWORD cchAdviseToken)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (cchAdviseToken >= MAX_ADVISETOKEN)
|
|
{
|
|
// 0x12345678
|
|
wsprintf(szAdviseToken, TEXT("0x%08X"), lAdviseToken);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CHardwareDevicesImpl::Advise(DWORD dwProcessID,
|
|
ULONG_PTR hThread, ULONG_PTR pfctCallback, DWORD* pdwToken)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TRACE(TF_ADVISE, TEXT(">>>Called ") TEXT(__FUNCTION__) TEXT(", 0x%08X, 0x%08X, 0x%08X"),
|
|
dwProcessID, hThread, pfctCallback);
|
|
|
|
if (dwProcessID && hThread && pfctCallback && pdwToken)
|
|
{
|
|
LONG lAdviseToken = InterlockedIncrement(&_lAdviseToken);
|
|
WCHAR szAdviseToken[MAX_ADVISETOKEN];
|
|
|
|
hr = _GetStringAdviseToken(lAdviseToken, szAdviseToken,
|
|
ARRAYSIZE(szAdviseToken));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CNamedElemList* pnel;
|
|
hr = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
CNamedElem* pelem;
|
|
|
|
hr = pnel->GetOrAdd(szAdviseToken, &pelem);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CAdviseClient* pac = (CAdviseClient*)pelem;
|
|
|
|
hr = pac->_Init(dwProcessID,
|
|
hThread, pfctCallback);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pdwToken = lAdviseToken;
|
|
}
|
|
else
|
|
{
|
|
pnel->Remove(szAdviseToken);
|
|
}
|
|
|
|
pelem->RCRelease();
|
|
}
|
|
|
|
pnel->RCRelease();
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(">>>Advise SUCCEEDED, token = 0x%08X"), lAdviseToken);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(">>>Advise FAILED"));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CHardwareDevicesImpl::Unadvise(DWORD dwToken)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (dwToken >= (MAGICTOKENOFFSET))
|
|
{
|
|
WCHAR szAdviseToken[MAX_ADVISETOKEN];
|
|
|
|
hr = _GetStringAdviseToken(dwToken, szAdviseToken,
|
|
ARRAYSIZE(szAdviseToken));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CNamedElemList* pnel;
|
|
hr = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
pnel->Remove(szAdviseToken);
|
|
|
|
pnel->RCRelease();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(">>>UNAdvise SUCCEEDED, token = 0x%08X"),
|
|
dwToken);
|
|
}
|
|
else
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(">>>UNAdvise FAILED, token = 0x%08X"),
|
|
dwToken);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
class CThreadTaskBroadcastEvent : public CThreadTask
|
|
{
|
|
public:
|
|
CThreadTaskBroadcastEvent() : _pshhe(NULL)
|
|
{}
|
|
|
|
virtual ~CThreadTaskBroadcastEvent()
|
|
{
|
|
if (_pshhe)
|
|
{
|
|
_FreeMemoryChunk<SHHARDWAREEVENT*>(_pshhe);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
HRESULT _Broadcast()
|
|
{
|
|
CNamedElemList* pnel;
|
|
HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
CNamedElemEnum* penum;
|
|
|
|
hr = pnel->GetEnum(&penum);
|
|
|
|
if (SUCCEEDED(hr) && (S_FALSE != hr))
|
|
{
|
|
CNamedElem* pelem;
|
|
|
|
while (SUCCEEDED(hr) && SUCCEEDED(hr = penum->Next(&pelem)) &&
|
|
(S_FALSE != hr))
|
|
{
|
|
CAdviseClient* pac = (CAdviseClient*)pelem;
|
|
void* pv;
|
|
|
|
HRESULT hrTmp = pac->WriteMemoryChunkInOtherProcess(_pshhe,
|
|
_pshhe->cbSize, &pv);
|
|
|
|
if (SUCCEEDED(hrTmp))
|
|
{
|
|
hrTmp = pac->QueueUserAPC(pv);
|
|
}
|
|
|
|
if (FAILED(hrTmp))
|
|
{
|
|
WCHAR szAdviseToken[MAX_ADVISETOKEN];
|
|
DWORD cchReq;
|
|
|
|
TRACE(TF_ADVISE,
|
|
TEXT(__FUNCTION__) TEXT(": Trying to removed token because failed CB, hr = 0x%08X"),
|
|
hrTmp);
|
|
|
|
if (SUCCEEDED(pelem->GetName(szAdviseToken, ARRAYSIZE(szAdviseToken),
|
|
&cchReq)))
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(" ") TEXT(__FUNCTION__) TEXT(": Token = %s"),
|
|
szAdviseToken);
|
|
|
|
pnel->Remove(szAdviseToken);
|
|
}
|
|
}
|
|
|
|
pelem->RCRelease();
|
|
}
|
|
|
|
penum->RCRelease();
|
|
}
|
|
|
|
pnel->RCRelease();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
protected:
|
|
SHHARDWAREEVENT* _pshhe;
|
|
};
|
|
|
|
class CThreadTaskMountPointEvent : public CThreadTaskBroadcastEvent
|
|
{
|
|
public:
|
|
HRESULT InitAdded(LPCWSTR pszMtPt, LPCWSTR pszDeviceIDVolume)
|
|
{
|
|
ASSERT(!_pshhe);
|
|
DWORD cbSize = sizeof(SHHARDWAREEVENT) + sizeof(MTPTADDED);
|
|
HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
MTPTADDED* pmtptadded = (MTPTADDED*)_pshhe->rgbPayLoad;
|
|
|
|
_pshhe->cbSize = cbSize;
|
|
_pshhe->dwEvent = SHHARDWAREEVENT_MOUNTPOINTARRIVED;
|
|
|
|
hr = SafeStrCpyN(pmtptadded->szMountPoint, pszMtPt,
|
|
ARRAYSIZE(pmtptadded->szMountPoint));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SafeStrCpyN(pmtptadded->szDeviceIDVolume, pszDeviceIDVolume,
|
|
ARRAYSIZE(pmtptadded->szDeviceIDVolume));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// We give the Shell AllowSetForegroundWindow privilege
|
|
_GiveAllowForegroundToConsoleShell();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT InitRemoved(LPCWSTR pszMtPt)
|
|
{
|
|
ASSERT(!_pshhe);
|
|
DWORD cbSize = sizeof(SHHARDWAREEVENT) + MAX_PATH * sizeof(WCHAR);
|
|
HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_pshhe->cbSize = cbSize;
|
|
_pshhe->dwEvent = SHHARDWAREEVENT_MOUNTPOINTREMOVED;
|
|
|
|
hr = SafeStrCpyN((LPWSTR)_pshhe->rgbPayLoad, pszMtPt,
|
|
MAX_PATH);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _DoStuff()
|
|
{
|
|
return _Broadcast();
|
|
}
|
|
};
|
|
|
|
class CThreadTaskCheckClients : public CThreadTask
|
|
{
|
|
public:
|
|
HRESULT _DoStuff()
|
|
{
|
|
CNamedElemList* pnel;
|
|
|
|
//
|
|
// Get the list of notify clients.
|
|
//
|
|
|
|
HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
|
|
if (S_OK == hres)
|
|
{
|
|
CNamedElemEnum* penum;
|
|
|
|
hres = pnel->GetEnum(&penum);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
CNamedElem* pelem;
|
|
|
|
//
|
|
// Enumerate the advised clients.
|
|
//
|
|
|
|
while (SUCCEEDED(hres = penum->Next(&pelem)) && (S_FALSE != hres))
|
|
{
|
|
CAdviseClient* pac = (CAdviseClient*)pelem;
|
|
|
|
//
|
|
// Is the process still alive?
|
|
//
|
|
|
|
HRESULT hrTmp = pac->IsProcessStillAlive( );
|
|
if (S_OK != hrTmp)
|
|
{
|
|
WCHAR szAdviseToken[MAX_ADVISETOKEN];
|
|
DWORD cchReq;
|
|
|
|
//
|
|
// Nope (or there is some problem with it)... so remove it from the list.
|
|
//
|
|
|
|
TRACE(TF_ADVISE, TEXT(__FUNCTION__) TEXT(": Trying to removed token because process died, pac = %p"), pac);
|
|
|
|
hrTmp = pelem->GetName(szAdviseToken, ARRAYSIZE(szAdviseToken), &cchReq);
|
|
if (SUCCEEDED(hrTmp))
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(" ") TEXT(__FUNCTION__) TEXT(": Token = %s"), szAdviseToken);
|
|
|
|
pnel->Remove(szAdviseToken);
|
|
}
|
|
}
|
|
|
|
pelem->RCRelease();
|
|
}
|
|
|
|
//
|
|
// Reset the HRESULT if it is the expected exit condition.
|
|
//
|
|
|
|
if ( S_FALSE == hres )
|
|
{
|
|
hres = S_OK;
|
|
}
|
|
|
|
penum->RCRelease();
|
|
}
|
|
|
|
pnel->RCRelease();
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
};
|
|
|
|
class CThreadTaskVolumeEvent : public CThreadTaskBroadcastEvent
|
|
{
|
|
public:
|
|
HRESULT InitAdded(VOLUMEINFO2* pvolinfo2, LPCWSTR pszMtPts, DWORD cchMtPts)
|
|
{
|
|
ASSERT(!_pshhe);
|
|
DWORD cbSize = sizeof(SHHARDWAREEVENT) + pvolinfo2->cbSize;
|
|
HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_pshhe->cbSize = cbSize;
|
|
_pshhe->dwEvent = SHHARDWAREEVENT_VOLUMEARRIVED;
|
|
|
|
CopyMemory(_pshhe->rgbPayLoad, pvolinfo2, pvolinfo2->cbSize);
|
|
|
|
_pszDeviceIDVolume = ((VOLUMEINFO2*)_pshhe->rgbPayLoad)->szDeviceIDVolume;
|
|
|
|
if (SUCCEEDED(hr) && pszMtPts)
|
|
{
|
|
hr = _DupMemoryChunk<LPCWSTR>(pszMtPts, cchMtPts * sizeof(WCHAR),
|
|
&_pszMtPts);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT InitUpdated(VOLUMEINFO2* pvolinfo2)
|
|
{
|
|
ASSERT(!_pshhe);
|
|
DWORD cbSize = sizeof(SHHARDWAREEVENT) + pvolinfo2->cbSize;
|
|
HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_pshhe->cbSize = cbSize;
|
|
_pshhe->dwEvent = SHHARDWAREEVENT_VOLUMEUPDATED;
|
|
|
|
CopyMemory(_pshhe->rgbPayLoad, pvolinfo2, pvolinfo2->cbSize);
|
|
|
|
_pszDeviceIDVolume = ((VOLUMEINFO2*)_pshhe->rgbPayLoad)->szDeviceIDVolume;
|
|
|
|
// We give the Shell AllowSetForegroundWindow privilege
|
|
_GiveAllowForegroundToConsoleShell();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT InitRemoved(LPCWSTR pszDeviceIDVolume, LPCWSTR pszMtPts, DWORD cchMtPts)
|
|
{
|
|
ASSERT(!_pshhe);
|
|
DWORD cbSize = sizeof(SHHARDWAREEVENT) + MAX_DEVICEID * sizeof(WCHAR);
|
|
HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_pshhe->cbSize = cbSize;
|
|
_pshhe->dwEvent = SHHARDWAREEVENT_VOLUMEREMOVED;
|
|
_pszDeviceIDVolume = ((VOLUMEINFO2*)_pshhe->rgbPayLoad)->szDeviceIDVolume;
|
|
|
|
hr = SafeStrCpyN((LPWSTR)_pshhe->rgbPayLoad, pszDeviceIDVolume,
|
|
MAX_DEVICEID);
|
|
|
|
if (SUCCEEDED(hr) && pszMtPts)
|
|
{
|
|
hr = _DupMemoryChunk<LPCWSTR>(pszMtPts, cchMtPts * sizeof(WCHAR),
|
|
&_pszMtPts);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _DoStuff()
|
|
{
|
|
HRESULT hr;
|
|
|
|
switch (_pshhe->dwEvent)
|
|
{
|
|
case SHHARDWAREEVENT_VOLUMEARRIVED:
|
|
case SHHARDWAREEVENT_VOLUMEUPDATED:
|
|
{
|
|
hr = _SendVolumeInfo();
|
|
|
|
if (SUCCEEDED(hr) && (SHHARDWAREEVENT_VOLUMEARRIVED == _pshhe->dwEvent))
|
|
{
|
|
// We need to enum the mountpoints too. We were not
|
|
// registered to get the notif since this volume was not there
|
|
hr = _SendMtPtsInfo();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SHHARDWAREEVENT_VOLUMEREMOVED:
|
|
{
|
|
hr = _SendMtPtsInfo();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _SendVolumeInfo();
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
TRACE(TF_ADVISE, TEXT("DoStuff with unknown SHHARDWAREEVENT_* value"));
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
private:
|
|
HRESULT _SendMtPtsInfo()
|
|
{
|
|
if (_pszMtPts)
|
|
{
|
|
for (LPCWSTR psz = _pszMtPts; *psz; psz += (lstrlen(psz) + 1))
|
|
{
|
|
CThreadTaskMountPointEvent task;
|
|
HRESULT hr;
|
|
|
|
if (SHHARDWAREEVENT_VOLUMEREMOVED == _pshhe->dwEvent)
|
|
{
|
|
hr = task.InitRemoved(psz);
|
|
}
|
|
else
|
|
{
|
|
hr = task.InitAdded(psz, _pszDeviceIDVolume);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
task.RunSynchronously();
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT _SendVolumeInfo()
|
|
{
|
|
return _Broadcast();
|
|
}
|
|
|
|
public:
|
|
CThreadTaskVolumeEvent() : _pszMtPts(NULL)
|
|
{}
|
|
|
|
~CThreadTaskVolumeEvent()
|
|
{
|
|
if (_pszMtPts)
|
|
{
|
|
_FreeMemoryChunk<LPCWSTR>(_pszMtPts);
|
|
}
|
|
}
|
|
|
|
private:
|
|
LPCWSTR _pszMtPts;
|
|
LPCWSTR _pszDeviceIDVolume;
|
|
};
|
|
|
|
class CThreadTaskGenericEvent : public CThreadTaskBroadcastEvent
|
|
{
|
|
public:
|
|
HRESULT Init(LPCWSTR pszPayload, DWORD dwEvent)
|
|
{
|
|
ASSERT(!_pshhe);
|
|
// maybe use lstrlen()?
|
|
DWORD cbSize = (DWORD)(sizeof(SHHARDWAREEVENT) + (pszPayload ? MAX_DEVICEID * sizeof(WCHAR) : 0));
|
|
HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPWSTR pszPayloadLocal = (LPWSTR)_pshhe->rgbPayLoad;
|
|
|
|
_pshhe->cbSize = cbSize;
|
|
_pshhe->dwEvent = dwEvent;
|
|
|
|
if (pszPayload)
|
|
{
|
|
hr = SafeStrCpyN(pszPayloadLocal, pszPayload, MAX_DEVICEID);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _DoStuff()
|
|
{
|
|
return _Broadcast();
|
|
}
|
|
};
|
|
|
|
class CThreadTaskDeviceEvent : public CThreadTaskBroadcastEvent
|
|
{
|
|
public:
|
|
HRESULT Init(LPCWSTR pszDeviceIntfID, GUID* pguidInterface,
|
|
DWORD dwDeviceFlags, DWORD dwEvent)
|
|
{
|
|
ASSERT(!_pshhe);
|
|
|
|
DWORD cbSize = (DWORD)(sizeof(SHHARDWAREEVENT) + (sizeof(HWDEVICEINFO)));
|
|
HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
HWDEVICEINFO* phwdevinfo = (HWDEVICEINFO*)_pshhe->rgbPayLoad;
|
|
|
|
_pshhe->cbSize = cbSize;
|
|
_pshhe->dwEvent = dwEvent;
|
|
|
|
hr = SafeStrCpyN(phwdevinfo->szDeviceIntfID, pszDeviceIntfID,
|
|
ARRAYSIZE(phwdevinfo->szDeviceIntfID));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
phwdevinfo->cbSize = sizeof(*phwdevinfo);
|
|
phwdevinfo->guidInterface = *pguidInterface;
|
|
phwdevinfo->dwDeviceFlags = dwDeviceFlags;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _DoStuff()
|
|
{
|
|
return _Broadcast();
|
|
}
|
|
};
|
|
|
|
HRESULT CHardwareDevicesImpl::_AdviseDeviceArrivedOrRemoved(
|
|
LPCWSTR pszDeviceIntfID, GUID* pguidInterface, DWORD dwDeviceFlags,
|
|
LPCWSTR pszEventType)
|
|
{
|
|
HRESULT hr;
|
|
CThreadTaskDeviceEvent* pTask = new CThreadTaskDeviceEvent();
|
|
|
|
if (pTask)
|
|
{
|
|
DWORD dwEvent;
|
|
|
|
if (!lstrcmpi(pszEventType, TEXT("DeviceArrival")))
|
|
{
|
|
dwEvent = SHHARDWAREEVENT_DEVICEARRIVED;
|
|
}
|
|
else
|
|
{
|
|
dwEvent = SHHARDWAREEVENT_DEVICEREMOVED;
|
|
}
|
|
|
|
hr = pTask->Init(pszDeviceIntfID, pguidInterface, dwDeviceFlags,
|
|
dwEvent);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pTask->Run();
|
|
}
|
|
else
|
|
{
|
|
delete pTask;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//static
|
|
HRESULT CHardwareDevicesImpl::_AdviseVolumeArrivedOrUpdated(
|
|
VOLUMEINFO2* pvolinfo2, LPCWSTR pszMtPts, DWORD cchMtPts, BOOL fAdded)
|
|
{
|
|
HRESULT hr;
|
|
TRACE(TF_ADVISE, TEXT(">>>_AdviseVolumeArrivedOrUpdated: fAdded = %d"), fAdded);
|
|
|
|
CThreadTaskVolumeEvent* pTask = new CThreadTaskVolumeEvent();
|
|
|
|
if (pTask)
|
|
{
|
|
if (fAdded)
|
|
{
|
|
hr = pTask->InitAdded(pvolinfo2, pszMtPts, cchMtPts);
|
|
}
|
|
else
|
|
{
|
|
hr = pTask->InitUpdated(pvolinfo2);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pTask->Run();
|
|
}
|
|
else
|
|
{
|
|
delete pTask;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// static
|
|
HRESULT CHardwareDevicesImpl::_AdviseVolumeRemoved(LPCWSTR pszDeviceIDVolume,
|
|
LPCWSTR pszMtPts, DWORD cchMtPts)
|
|
{
|
|
HRESULT hr;
|
|
TRACE(TF_ADVISE, TEXT(">>>_AdviseVolumeRemoved"));
|
|
|
|
CThreadTaskVolumeEvent* pTask = new CThreadTaskVolumeEvent();
|
|
|
|
if (pTask)
|
|
{
|
|
hr = pTask->InitRemoved(pszDeviceIDVolume, pszMtPts, cchMtPts);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pTask->Run();
|
|
}
|
|
else
|
|
{
|
|
delete pTask;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//static
|
|
HRESULT CHardwareDevicesImpl::_AdviseVolumeMountingEvent(
|
|
LPCWSTR pszDeviceIDVolume, DWORD dwEvent)
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(">>>_AdviseVolumeMountingEvent: %s, dwEvent = 0x%08X"),
|
|
pszDeviceIDVolume, dwEvent);
|
|
|
|
HRESULT hr;
|
|
CThreadTaskGenericEvent* pTask = new CThreadTaskGenericEvent();
|
|
|
|
if (pTask)
|
|
{
|
|
hr = pTask->Init(pszDeviceIDVolume, dwEvent);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pTask->Run();
|
|
}
|
|
else
|
|
{
|
|
delete pTask;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//static
|
|
HRESULT CHardwareDevicesImpl::_AdviseMountPointHelper(LPCWSTR pszMtPt,
|
|
LPCWSTR pszDeviceIDVolume, BOOL fAdded)
|
|
{
|
|
TRACE(TF_ADVISE, TEXT(">>>_AdviseMountPointHelper: %s, fAdded = %d"),
|
|
pszMtPt, fAdded);
|
|
|
|
HRESULT hr;
|
|
CThreadTaskMountPointEvent* pTask = new CThreadTaskMountPointEvent();
|
|
|
|
if (pTask)
|
|
{
|
|
if (fAdded)
|
|
{
|
|
hr = pTask->InitAdded(pszMtPt, pszDeviceIDVolume);
|
|
}
|
|
else
|
|
{
|
|
hr = pTask->InitRemoved(pszMtPt);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pTask->Run();
|
|
}
|
|
else
|
|
{
|
|
delete pTask;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//static
|
|
HRESULT CHardwareDevicesImpl::_AdviseCheckClients(void)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CThreadTaskCheckClients* pTask = new CThreadTaskCheckClients();
|
|
|
|
if (pTask)
|
|
{
|
|
pTask->Run( );
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Impl
|
|
CHardwareDevicesImpl::CHardwareDevicesImpl()
|
|
{
|
|
_CompleteShellHWDetectionInitialization();
|
|
}
|
|
|
|
CHardwareDevicesImpl::~CHardwareDevicesImpl()
|
|
{}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
STDMETHODIMP CHardwareDevicesEnumImpl::Next(
|
|
LPWSTR* /*ppszDeviceID*/,
|
|
GUID* /*pguidDeviceID*/)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
CHardwareDevicesEnumImpl::CHardwareDevicesEnumImpl()
|
|
{}
|
|
|
|
CHardwareDevicesEnumImpl::~CHardwareDevicesEnumImpl()
|
|
{}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
HRESULT CHardwareDevicesVolumesEnumImpl::_Init(DWORD dwFlags)
|
|
{
|
|
CNamedElemList* pnel;
|
|
HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_VOLUME, &pnel);
|
|
|
|
_dwFlags = dwFlags;
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = pnel->GetEnum(&_penum);
|
|
|
|
pnel->RCRelease();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CHardwareDevicesVolumesEnumImpl::Next(VOLUMEINFO* pvolinfo)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (pvolinfo)
|
|
{
|
|
if (_penum)
|
|
{
|
|
CNamedElem* pelem;
|
|
|
|
hr = _penum->Next(&pelem);
|
|
|
|
if (SUCCEEDED(hr) && (S_FALSE != hr))
|
|
{
|
|
// Const Info
|
|
WCHAR szVolName[MAX_DEVICEID];
|
|
WCHAR szVolGUID[50];
|
|
WCHAR szLabel[MAX_LABEL];
|
|
WCHAR szFileSystem[MAX_FILESYSNAME];
|
|
WCHAR szAutorunIconLocation[MAX_ICONLOCATION];
|
|
WCHAR szAutorunLabel[MAX_LABEL];
|
|
WCHAR szIconLocationFromService[MAX_ICONLOCATION];
|
|
WCHAR szNoMediaIconLocationFromService[MAX_ICONLOCATION];
|
|
// We can now have a @%SystemRoot%\system32\shell32.dll,-1785 for MUI stuff
|
|
WCHAR szLabelFromService[MAX_ICONLOCATION];
|
|
CVolume* pvol = (CVolume*)pelem;
|
|
|
|
// Misc
|
|
DWORD cchReq;
|
|
|
|
ZeroMemory(pvolinfo, sizeof(VOLUMEINFO));
|
|
|
|
hr = pvol->GetName(szVolName, ARRAYSIZE(szVolName), &cchReq);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pvol->GetVolumeConstInfo(szVolGUID,
|
|
ARRAYSIZE(szVolGUID), &(pvolinfo->dwVolumeFlags),
|
|
&(pvolinfo->dwDriveType),
|
|
&(pvolinfo->dwDriveCapability));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pvol->GetVolumeMediaInfo(szLabel, ARRAYSIZE(szLabel),
|
|
szFileSystem, ARRAYSIZE(szFileSystem),
|
|
&(pvolinfo->dwFileSystemFlags),
|
|
&(pvolinfo->dwMaxFileNameLen),
|
|
&(pvolinfo->dwRootAttributes),
|
|
&(pvolinfo->dwSerialNumber), &(pvolinfo->dwDriveState),
|
|
&(pvolinfo->dwMediaState), &(pvolinfo->dwMediaCap));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (HWDEV_GETCUSTOMPROPERTIES & _dwFlags)
|
|
{
|
|
szAutorunIconLocation[0] = 0;
|
|
szAutorunLabel[0] = 0;
|
|
szIconLocationFromService[0] = 0;
|
|
szNoMediaIconLocationFromService[0] = 0;
|
|
szLabelFromService[0] = 0;
|
|
|
|
hr = pvol->GetIconAndLabelInfo(szAutorunIconLocation,
|
|
ARRAYSIZE(szAutorunIconLocation), szAutorunLabel,
|
|
ARRAYSIZE(szAutorunLabel),
|
|
szIconLocationFromService,
|
|
ARRAYSIZE(szIconLocationFromService),
|
|
szNoMediaIconLocationFromService,
|
|
ARRAYSIZE(szNoMediaIconLocationFromService),
|
|
szLabelFromService,
|
|
ARRAYSIZE(szLabelFromService));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (*szAutorunIconLocation)
|
|
{
|
|
hr = _CoTaskMemCopy(szAutorunIconLocation,
|
|
&(pvolinfo->pszAutorunIconLocation));
|
|
}
|
|
if (SUCCEEDED(hr) && *szAutorunLabel)
|
|
{
|
|
hr = _CoTaskMemCopy(szAutorunLabel,
|
|
&(pvolinfo->pszAutorunLabel));
|
|
}
|
|
if (SUCCEEDED(hr) && *szIconLocationFromService)
|
|
{
|
|
hr = _CoTaskMemCopy(szIconLocationFromService,
|
|
&(pvolinfo->pszIconLocationFromService));
|
|
}
|
|
if (SUCCEEDED(hr) && *szNoMediaIconLocationFromService)
|
|
{
|
|
hr = _CoTaskMemCopy(szNoMediaIconLocationFromService,
|
|
&(pvolinfo->pszNoMediaIconLocationFromService));
|
|
}
|
|
if (SUCCEEDED(hr) && *szLabelFromService)
|
|
{
|
|
hr = _CoTaskMemCopy(szLabelFromService,
|
|
&(pvolinfo->pszLabelFromService));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _CoTaskMemCopy(szVolName, &(pvolinfo->pszDeviceIDVolume));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _CoTaskMemCopy(szVolGUID, &(pvolinfo->pszVolumeGUID));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _CoTaskMemCopy(szLabel, &(pvolinfo->pszLabel));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _CoTaskMemCopy(szFileSystem, &(pvolinfo->pszFileSystem));
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
_CoTaskMemFree(pvolinfo->pszDeviceIDVolume);
|
|
_CoTaskMemFree(pvolinfo->pszVolumeGUID);
|
|
_CoTaskMemFree(pvolinfo->pszLabel);
|
|
_CoTaskMemFree(pvolinfo->pszFileSystem);
|
|
|
|
_CoTaskMemFree(pvolinfo->pszAutorunIconLocation);
|
|
_CoTaskMemFree(pvolinfo->pszAutorunLabel);
|
|
_CoTaskMemFree(pvolinfo->pszIconLocationFromService);
|
|
_CoTaskMemFree(pvolinfo->pszNoMediaIconLocationFromService);
|
|
_CoTaskMemFree(pvolinfo->pszLabelFromService);
|
|
|
|
ZeroMemory(pvolinfo, sizeof(VOLUMEINFO));
|
|
}
|
|
|
|
pelem->RCRelease();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CHardwareDevicesVolumesEnumImpl::CHardwareDevicesVolumesEnumImpl() :
|
|
_penum(NULL)
|
|
{}
|
|
|
|
CHardwareDevicesVolumesEnumImpl::~CHardwareDevicesVolumesEnumImpl()
|
|
{
|
|
if (_penum)
|
|
{
|
|
_penum->RCRelease();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
HRESULT CHardwareDevicesMountPointsEnumImpl::_Init()
|
|
{
|
|
CNamedElemList* pnel;
|
|
HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_MTPT, &pnel);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = pnel->GetEnum(&_penum);
|
|
|
|
pnel->RCRelease();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CHardwareDevicesMountPointsEnumImpl::Next(
|
|
LPWSTR* ppszMountPoint, // "c:\", or "d:\MountFolder\"
|
|
LPWSTR* ppszDeviceIDVolume) // \\?\STORAGE#Volume#...{...GUID...}
|
|
{
|
|
HRESULT hr;
|
|
|
|
*ppszMountPoint = NULL;
|
|
*ppszDeviceIDVolume = NULL;
|
|
|
|
if (_penum)
|
|
{
|
|
CNamedElem* pelem;
|
|
|
|
hr = _penum->Next(&pelem);
|
|
|
|
if (SUCCEEDED(hr) && (S_FALSE != hr))
|
|
{
|
|
// Const Info
|
|
WCHAR szMtPtName[MAX_PATH];
|
|
WCHAR szVolName[MAX_DEVICEID];
|
|
CMtPt* pmtpt = (CMtPt*)pelem;
|
|
|
|
// Misc
|
|
DWORD cchReq;
|
|
|
|
hr = pmtpt->GetName(szMtPtName, ARRAYSIZE(szMtPtName), &cchReq);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pmtpt->GetVolumeName(szVolName, ARRAYSIZE(szVolName));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _CoTaskMemCopy(szMtPtName, ppszMountPoint);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _CoTaskMemCopy(szVolName, ppszDeviceIDVolume);
|
|
}
|
|
else
|
|
{
|
|
CoTaskMemFree(*ppszMountPoint);
|
|
*ppszMountPoint = NULL;
|
|
}
|
|
}
|
|
|
|
pelem->RCRelease();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CHardwareDevicesMountPointsEnumImpl::CHardwareDevicesMountPointsEnumImpl() :
|
|
_penum(NULL)
|
|
{}
|
|
|
|
CHardwareDevicesMountPointsEnumImpl::~CHardwareDevicesMountPointsEnumImpl()
|
|
{
|
|
if (_penum)
|
|
{
|
|
_penum->RCRelease();
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdviseClient::Init(LPCWSTR pszElemName)
|
|
{
|
|
ASSERT(pszElemName);
|
|
|
|
return _SetName(pszElemName);
|
|
}
|
|
|
|
HRESULT CAdviseClient::_Cleanup()
|
|
{
|
|
if (_hProcess)
|
|
{
|
|
CloseHandle(_hProcess);
|
|
_hProcess = NULL;
|
|
}
|
|
|
|
if (_hThread)
|
|
{
|
|
CloseHandle(_hThread);
|
|
_hThread = NULL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CAdviseClient::_Init(DWORD dwProcessID, ULONG_PTR hThread,
|
|
ULONG_PTR pfctCallback)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
_Cleanup();
|
|
|
|
_pfct = (PAPCFUNC)pfctCallback;
|
|
|
|
// rename hProcess!
|
|
_hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | SYNCHRONIZE |
|
|
PROCESS_DUP_HANDLE, FALSE, dwProcessID);
|
|
|
|
if (_hProcess)
|
|
{
|
|
if (DuplicateHandle(_hProcess, (HANDLE)hThread,
|
|
GetCurrentProcess(), &_hThread, THREAD_ALL_ACCESS, FALSE, 0))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdviseClient::WriteMemoryChunkInOtherProcess(SHHARDWAREEVENT* pshhe,
|
|
DWORD cbSize, void** ppv)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
void* pv = VirtualAllocEx(_hProcess, NULL, cbSize,
|
|
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
|
|
PAGE_READWRITE);
|
|
|
|
*ppv = NULL;
|
|
|
|
if (pv)
|
|
{
|
|
SIZE_T cbWritten;
|
|
|
|
if (WriteProcessMemory(_hProcess, pv, pshhe, cbSize, &cbWritten)
|
|
&& (cbWritten == cbSize))
|
|
{
|
|
*ppv = pv;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
VirtualFreeEx(_hProcess, pv, 0, MEM_RELEASE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Out of mem, but in the other process...
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdviseClient::QueueUserAPC(void* pv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (::QueueUserAPC(_pfct, _hThread, (ULONG_PTR)pv))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdviseClient::IsProcessStillAlive(void)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DWORD dwResult = WaitForSingleObject( _hProcess, 0 );
|
|
switch (dwResult)
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
hr = S_FALSE; // process has died.
|
|
break;
|
|
|
|
case WAIT_TIMEOUT:
|
|
hr = S_OK; // process is still alive
|
|
break;
|
|
|
|
default:
|
|
{
|
|
// problem with handle
|
|
DWORD dwErr = GetLastError( );
|
|
hr = HRESULT_FROM_WIN32( dwErr );
|
|
}
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
CAdviseClient::CAdviseClient() : _hProcess(NULL), _hThread(NULL), _pfct(NULL)
|
|
{}
|
|
|
|
CAdviseClient::~CAdviseClient()
|
|
{
|
|
_Cleanup();
|
|
}
|
|
// static
|
|
HRESULT CAdviseClient::Create(CNamedElem** ppelem)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
*ppelem = new CAdviseClient();
|
|
|
|
if (!(*ppelem))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|