windows-nt/Source/XPSP1/NT/shell/ext/shimgvw/autoplay.cpp
2020-09-26 16:20:57 +08:00

217 lines
5.6 KiB
C++

#include "precomp.h"
#pragma hdrstop
#include "prevwnd.h"
#include <shpriv.h>
DWORD g_dwThreadID = 0;
class CAutoplayForSlideShow : public IHWEventHandler,
public IDropTarget,
public NonATLObject
{
public:
CAutoplayForSlideShow() : _cRef(1) {}
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
// IHWEventHandler
STDMETHOD(Initialize)(LPCWSTR pszParams);
STDMETHOD(HandleEvent)(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID,
LPCWSTR pszEventType);
STDMETHOD(HandleEventWithContent)(LPCWSTR pszDeviceID,
LPCWSTR pszAltDeviceID, LPCWSTR pszEventType,
LPCWSTR pszContentTypeHandler, IDataObject* pdtobj);
// IDropTarget ***
STDMETHODIMP DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
STDMETHODIMP DragLeave(void);
STDMETHODIMP Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
private:
LONG _cRef;
};
STDMETHODIMP CAutoplayForSlideShow::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(CAutoplayForSlideShow, IHWEventHandler),
QITABENT(CAutoplayForSlideShow, IDropTarget),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) CAutoplayForSlideShow::AddRef()
{
return InterlockedIncrement(&_cRef);
}
STDMETHODIMP_(ULONG) CAutoplayForSlideShow::Release()
{
if (InterlockedDecrement(&_cRef))
return _cRef;
delete this;
return 0;
}
STDAPI CAutoplayForSlideShow_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
{
CAutoplayForSlideShow* pass = new CAutoplayForSlideShow();
if (!pass)
{
*ppunk = NULL; // incase of failure
return E_OUTOFMEMORY;
}
HRESULT hr = pass->QueryInterface(IID_PPV_ARG(IUnknown, ppunk));
pass->Release();
return hr;
}
STDMETHODIMP CAutoplayForSlideShow::Initialize(LPCWSTR)
{
// We don't care about params a this point
return S_OK;
}
STDMETHODIMP CAutoplayForSlideShow::HandleEvent(LPCWSTR pszDeviceID,
LPCWSTR pszAltDeviceID, LPCWSTR pszEventType)
{
return E_NOTIMPL;
}
DWORD WINAPI SlideShowThread(void* pv)
{
IStream *pstm = (IStream *)pv;
IDataObject* pdtobj;
HRESULT hr = CoGetInterfaceAndReleaseStream(pstm, IID_PPV_ARG(IDataObject, &pdtobj));
if (SUCCEEDED(hr))
{
CPreviewWnd cwndPreview;
hr = cwndPreview.Initialize(NULL, SLIDESHOW_MODE, TRUE);
if (SUCCEEDED(hr))
{
// 4 is the walk depth, make sure we pick up pictures
if (cwndPreview.CreateSlideshowWindow(4))
{
hr = cwndPreview.StartSlideShow(pdtobj);
if (SUCCEEDED(hr))
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
::PostThreadMessage(g_dwThreadID, WM_QUIT, 0, 0);
}
}
else
{
hr = E_FAIL;
}
}
pdtobj->Release();
}
return hr;
}
HRESULT _StartSlideShowThread(IDataObject *pdo)
{
IStream *pstm;
HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pdo, &pstm);
if (SUCCEEDED(hr))
{
// maybe do threadref?
if (!SHCreateThread(SlideShowThread, pstm, CTF_COINIT, NULL))
{
pstm->Release();
hr = E_FAIL;
}
}
return hr;
}
STDMETHODIMP CAutoplayForSlideShow::HandleEventWithContent(
LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType,
LPCWSTR pszContentTypeHandler, IDataObject* pdtobj)
{
return _StartSlideShowThread(pdtobj);
}
// IDropTarget::DragEnter
HRESULT CAutoplayForSlideShow::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
{
*pdwEffect = DROPEFFECT_COPY;
return S_OK;;
}
// IDropTarget::DragOver
HRESULT CAutoplayForSlideShow::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
{
*pdwEffect = DROPEFFECT_COPY;
return S_OK;;
}
// IDropTarget::DragLeave
HRESULT CAutoplayForSlideShow::DragLeave(void)
{
return S_OK;
}
// IDropTarget::DragDrop
HRESULT CAutoplayForSlideShow::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
*pdwEffect = DROPEFFECT_COPY;
return _StartSlideShowThread(pdtobj);
}
void WINAPI ImageView_COMServer(HWND hwnd, HINSTANCE hAppInstance, LPTSTR pszCmdLine, int nCmdShow)
{
HRESULT hrOle = SHCoInitialize();
if (SUCCEEDED(hrOle))
{
g_dwThreadID = GetCurrentThreadId();
IUnknown* punkFact;
// the preview window will init GDI+
HRESULT hr = DllGetClassObject(CLSID_AutoplayForSlideShow, IID_PPV_ARG(IUnknown, &punkFact));
if (SUCCEEDED(hr))
{
DWORD dwROC;
hr = CoRegisterClassObject(CLSID_AutoplayForSlideShow, punkFact, CLSCTX_LOCAL_SERVER,
REGCLS_SINGLEUSE, &dwROC);
if (SUCCEEDED(hr))
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
CoRevokeClassObject(dwROC);
}
punkFact->Release();
}
SHCoUninitialize(hrOle);
}
}