186 lines
4.7 KiB
C++
186 lines
4.7 KiB
C++
// clip.cpp : Defines the entry point for the application.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <shlobj.h>
|
|
#include <shellapi.h>
|
|
#include <shlwapi.h>
|
|
#include <propidl.h>
|
|
#include "idlist.h"
|
|
|
|
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
#define IID_PPV_ARG(IType, ppType) IID_##IType, reinterpret_cast<void**>(static_cast<IType**>(ppType))
|
|
|
|
LPCTSTR GetCmdLineArg()
|
|
{
|
|
LPTSTR pszCmdLine = GetCommandLine();
|
|
|
|
if ( *pszCmdLine == TEXT('\"') )
|
|
{
|
|
while ( *++pszCmdLine && (*pszCmdLine != TEXT('\"')) );
|
|
if ( *pszCmdLine == TEXT('\"') )
|
|
pszCmdLine++;
|
|
}
|
|
else
|
|
{
|
|
while (*pszCmdLine > TEXT(' '))
|
|
pszCmdLine++;
|
|
}
|
|
|
|
while (*pszCmdLine && (*pszCmdLine <= TEXT(' ')))
|
|
{
|
|
pszCmdLine++;
|
|
}
|
|
|
|
return pszCmdLine;
|
|
}
|
|
|
|
HRESULT GetUIObjectFromCmdLine(REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
IShellFolder *psfDesktop;
|
|
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TCHAR szFolder[MAX_PATH], szSpec[MAX_PATH];
|
|
|
|
GetCurrentDirectory(ARRAYSIZE(szFolder), szFolder);
|
|
|
|
lstrcpyn(szSpec, GetCmdLineArg(), ARRAYSIZE(szSpec));
|
|
PathUnquoteSpaces(szSpec);
|
|
|
|
PathAppend(szFolder, szSpec);
|
|
|
|
WCHAR wszPath[MAX_PATH];
|
|
SHAnsiToUnicode(szFolder, wszPath, ARRAYSIZE(wszPath));
|
|
|
|
LPITEMIDLIST pidl;
|
|
hr = psfDesktop->ParseDisplayName(NULL, NULL, wszPath, NULL, &pidl, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IShellFolder *psf;
|
|
LPCITEMIDLIST pidlChild;
|
|
hr = SHBindToParent(pidl, IID_IShellFolder, (void **)&psf, &pidlChild);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = psf->GetUIObjectOf(NULL, 1, &pidlChild, riid, NULL, ppv);
|
|
}
|
|
CoTaskMemFree(pidl);
|
|
}
|
|
psfDesktop->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT BindToItemByName(LPCWSTR pszFile, REFIID riid, void **ppv)
|
|
{
|
|
IShellFolder *psfDesktop;
|
|
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPITEMIDLIST pidl;
|
|
// cast needed for bad interface def
|
|
hr = psfDesktop->ParseDisplayName(NULL, NULL, (LPWSTR)pszFile, NULL, &pidl, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = psfDesktop->BindToObject(pidl, NULL, riid, ppv);
|
|
CoTaskMemFree(pidl);
|
|
}
|
|
psfDesktop->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CoMarshallToCmdLine(REFIID riid, IUnknown *punk, LPTSTR pszCmdLine, UINT cch)
|
|
{
|
|
*pszCmdLine = 0;
|
|
|
|
IStream *pstm;
|
|
HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pstm);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CoMarshalInterface(pstm, riid, punk, MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_NORMAL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
const LARGE_INTEGER li = {0, 0};
|
|
pstm->Seek(li, STREAM_SEEK_SET, NULL);
|
|
|
|
char buf[255]; // big enough for a standard marshall record
|
|
ULONG cb;
|
|
hr = pstm->Read(buf, sizeof(buf), &cb);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
StrCatBuff(pszCmdLine, TEXT("/DataObject:"), cch);
|
|
pszCmdLine += lstrlen(pszCmdLine);
|
|
// convert binary buffer to hex
|
|
for (ULONG i = 0; i < cb; i++)
|
|
{
|
|
*pszCmdLine++ = 'A' + (0x0F & buf[i]);
|
|
*pszCmdLine++ = 'A' + ((0xF0 & buf[i]) >> 4);
|
|
}
|
|
*pszCmdLine = 0;
|
|
}
|
|
}
|
|
pstm->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
int APIENTRY WinMain(HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
OleInitialize(0);
|
|
|
|
#if 1
|
|
IPropertySetStorage *ppss;
|
|
if (SUCCEEDED(BindToItemByName(L"c:\\foo.jpg", IID_PPV_ARG(IPropertySetStorage, &ppss))))
|
|
{
|
|
ppss->Release();
|
|
}
|
|
#endif
|
|
|
|
IDataObject *pdtobj;
|
|
|
|
if (SUCCEEDED(GetUIObjectFromCmdLine(IID_PPV_ARG(IDataObject, &pdtobj))))
|
|
{
|
|
#if 1
|
|
HRESULT hr = OleSetClipboard(pdtobj);
|
|
OleFlushClipboard(); // seralize it
|
|
#else
|
|
TCHAR szArgs[512];
|
|
if (SUCCEEDED(CoMarshallToCmdLine(IID_IDataObject, pdtobj, szArgs, ARRAYSIZE(szArgs))))
|
|
{
|
|
SHELLEXECUTEINFO ei = {0};
|
|
ei.cbSize = sizeof(ei);
|
|
|
|
ei.lpFile = TEXT("test.exe"); // we have an app name
|
|
ei.lpParameters = szArgs; // and maybe some args
|
|
ei.nShow = SW_SHOW;
|
|
ei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_DOENVSUBST;
|
|
|
|
ShellExecuteEx(&ei);
|
|
}
|
|
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
#endif
|
|
pdtobj->Release();
|
|
}
|
|
|
|
|
|
OleUninitialize();
|
|
return 0;
|
|
}
|
|
|
|
|
|
|