Source code of Windows XP (NT5)
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.

185 lines
4.7 KiB

  1. // clip.cpp : Defines the entry point for the application.
  2. //
  3. #include "stdafx.h"
  4. #include <shlobj.h>
  5. #include <shellapi.h>
  6. #include <shlwapi.h>
  7. #include <propidl.h>
  8. #include "idlist.h"
  9. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  10. #define IID_PPV_ARG(IType, ppType) IID_##IType, reinterpret_cast<void**>(static_cast<IType**>(ppType))
  11. LPCTSTR GetCmdLineArg()
  12. {
  13. LPTSTR pszCmdLine = GetCommandLine();
  14. if ( *pszCmdLine == TEXT('\"') )
  15. {
  16. while ( *++pszCmdLine && (*pszCmdLine != TEXT('\"')) );
  17. if ( *pszCmdLine == TEXT('\"') )
  18. pszCmdLine++;
  19. }
  20. else
  21. {
  22. while (*pszCmdLine > TEXT(' '))
  23. pszCmdLine++;
  24. }
  25. while (*pszCmdLine && (*pszCmdLine <= TEXT(' ')))
  26. {
  27. pszCmdLine++;
  28. }
  29. return pszCmdLine;
  30. }
  31. HRESULT GetUIObjectFromCmdLine(REFIID riid, void **ppv)
  32. {
  33. *ppv = NULL;
  34. IShellFolder *psfDesktop;
  35. HRESULT hr = SHGetDesktopFolder(&psfDesktop);
  36. if (SUCCEEDED(hr))
  37. {
  38. TCHAR szFolder[MAX_PATH], szSpec[MAX_PATH];
  39. GetCurrentDirectory(ARRAYSIZE(szFolder), szFolder);
  40. lstrcpyn(szSpec, GetCmdLineArg(), ARRAYSIZE(szSpec));
  41. PathUnquoteSpaces(szSpec);
  42. PathAppend(szFolder, szSpec);
  43. WCHAR wszPath[MAX_PATH];
  44. SHAnsiToUnicode(szFolder, wszPath, ARRAYSIZE(wszPath));
  45. LPITEMIDLIST pidl;
  46. hr = psfDesktop->ParseDisplayName(NULL, NULL, wszPath, NULL, &pidl, NULL);
  47. if (SUCCEEDED(hr))
  48. {
  49. IShellFolder *psf;
  50. LPCITEMIDLIST pidlChild;
  51. hr = SHBindToParent(pidl, IID_IShellFolder, (void **)&psf, &pidlChild);
  52. if (SUCCEEDED(hr))
  53. {
  54. hr = psf->GetUIObjectOf(NULL, 1, &pidlChild, riid, NULL, ppv);
  55. }
  56. CoTaskMemFree(pidl);
  57. }
  58. psfDesktop->Release();
  59. }
  60. return hr;
  61. }
  62. HRESULT BindToItemByName(LPCWSTR pszFile, REFIID riid, void **ppv)
  63. {
  64. IShellFolder *psfDesktop;
  65. HRESULT hr = SHGetDesktopFolder(&psfDesktop);
  66. if (SUCCEEDED(hr))
  67. {
  68. LPITEMIDLIST pidl;
  69. // cast needed for bad interface def
  70. hr = psfDesktop->ParseDisplayName(NULL, NULL, (LPWSTR)pszFile, NULL, &pidl, NULL);
  71. if (SUCCEEDED(hr))
  72. {
  73. hr = psfDesktop->BindToObject(pidl, NULL, riid, ppv);
  74. CoTaskMemFree(pidl);
  75. }
  76. psfDesktop->Release();
  77. }
  78. return hr;
  79. }
  80. HRESULT CoMarshallToCmdLine(REFIID riid, IUnknown *punk, LPTSTR pszCmdLine, UINT cch)
  81. {
  82. *pszCmdLine = 0;
  83. IStream *pstm;
  84. HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pstm);
  85. if (SUCCEEDED(hr))
  86. {
  87. hr = CoMarshalInterface(pstm, riid, punk, MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_NORMAL);
  88. if (SUCCEEDED(hr))
  89. {
  90. const LARGE_INTEGER li = {0, 0};
  91. pstm->Seek(li, STREAM_SEEK_SET, NULL);
  92. char buf[255]; // big enough for a standard marshall record
  93. ULONG cb;
  94. hr = pstm->Read(buf, sizeof(buf), &cb);
  95. if (SUCCEEDED(hr))
  96. {
  97. StrCatBuff(pszCmdLine, TEXT("/DataObject:"), cch);
  98. pszCmdLine += lstrlen(pszCmdLine);
  99. // convert binary buffer to hex
  100. for (ULONG i = 0; i < cb; i++)
  101. {
  102. *pszCmdLine++ = 'A' + (0x0F & buf[i]);
  103. *pszCmdLine++ = 'A' + ((0xF0 & buf[i]) >> 4);
  104. }
  105. *pszCmdLine = 0;
  106. }
  107. }
  108. pstm->Release();
  109. }
  110. return hr;
  111. }
  112. int APIENTRY WinMain(HINSTANCE hInstance,
  113. HINSTANCE hPrevInstance,
  114. LPSTR lpCmdLine,
  115. int nCmdShow)
  116. {
  117. OleInitialize(0);
  118. #if 1
  119. IPropertySetStorage *ppss;
  120. if (SUCCEEDED(BindToItemByName(L"c:\\foo.jpg", IID_PPV_ARG(IPropertySetStorage, &ppss))))
  121. {
  122. ppss->Release();
  123. }
  124. #endif
  125. IDataObject *pdtobj;
  126. if (SUCCEEDED(GetUIObjectFromCmdLine(IID_PPV_ARG(IDataObject, &pdtobj))))
  127. {
  128. #if 1
  129. HRESULT hr = OleSetClipboard(pdtobj);
  130. OleFlushClipboard(); // seralize it
  131. #else
  132. TCHAR szArgs[512];
  133. if (SUCCEEDED(CoMarshallToCmdLine(IID_IDataObject, pdtobj, szArgs, ARRAYSIZE(szArgs))))
  134. {
  135. SHELLEXECUTEINFO ei = {0};
  136. ei.cbSize = sizeof(ei);
  137. ei.lpFile = TEXT("test.exe"); // we have an app name
  138. ei.lpParameters = szArgs; // and maybe some args
  139. ei.nShow = SW_SHOW;
  140. ei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_DOENVSUBST;
  141. ShellExecuteEx(&ei);
  142. }
  143. MSG msg;
  144. while (GetMessage(&msg, NULL, 0, 0))
  145. {
  146. TranslateMessage(&msg);
  147. DispatchMessage(&msg);
  148. }
  149. #endif
  150. pdtobj->Release();
  151. }
  152. OleUninitialize();
  153. return 0;
  154. }