// clip.cpp : Defines the entry point for the application. // #include "stdafx.h" #include #include #include #include #include "idlist.h" #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) #define IID_PPV_ARG(IType, ppType) IID_##IType, reinterpret_cast(static_cast(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; }