2025-11-28 00:35:46 +09:00

120 lines
4.1 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//
// This demonstrates how implement a shell verb using the CreateProcess method
// CreateProcess based verbs depend on running a .exe and passing it a command line.
// This method is not as powerful as the DropTarget and DelegateExecute methods
// but it does achieve the desirable out of process behavior.
#include <windows.h>
#include <shlwapi.h>
#include <shlobj.h>
#include "RegisterExtension.h"
#include <strsafe.h>
HRESULT GetShellItemFromCommandLine(REFIID riid, void **ppv)
{
*ppv = NULL;
HRESULT hr = E_FAIL;
int cArgs;
PWSTR *ppszCmd = CommandLineToArgvW(GetCommandLineW(), &cArgs);
if (ppszCmd && cArgs > 1)
{
WCHAR szSpec[MAX_PATH];
szSpec[0] = 0;
// skip all parameters that begin with "-" or "/" to try to find the
// file name. this enables parameters to be present on the cmd line
// and not get in the way of this function
for (int i = 1; (szSpec[0] == 0) && (i < cArgs); i++)
{
if ((*ppszCmd[i] != L'-') && (*ppszCmd[i] != L'/'))
{
StringCchCopyW(szSpec, ARRAYSIZE(szSpec), ppszCmd[i]);
PathUnquoteSpacesW(szSpec);
}
}
hr = szSpec[0] ? S_OK : E_FAIL; // protect against empty
if (SUCCEEDED(hr))
{
hr = SHCreateItemFromParsingName(szSpec, NULL, riid, ppv);
if (FAILED(hr))
{
WCHAR szFolder[MAX_PATH];
GetCurrentDirectoryW(ARRAYSIZE(szFolder), szFolder);
hr = PathAppendW(szFolder, szSpec) ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
hr = SHCreateItemFromParsingName(szFolder, NULL, riid, ppv);
}
}
}
}
return hr;
}
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, PWSTR pszCmdLine, int)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
if (StrStrI(pszCmdLine, L"-Verb"))
{
IShellItem2 *psi;
hr = GetShellItemFromCommandLine(IID_PPV_ARGS(&psi));
if (SUCCEEDED(hr))
{
PWSTR pszName;
hr = psi->GetDisplayName(SIGDN_PARENTRELATIVEPARSING, &pszName);
if (SUCCEEDED(hr))
{
WCHAR szMsg[128];
StringCchPrintf(szMsg, ARRAYSIZE(szMsg), L"Item passed via command line is named %s", pszName);
MessageBox(NULL, szMsg, L"Create Process Sample Verb", MB_OK);
CoTaskMemFree(pszName);
}
psi->Release();
}
}
else
{
CRegisterExtension re(CLSID_NULL);
WCHAR const c_szProgID[] = L"txtfile";
WCHAR const c_szVerb[] = L"CreateProcessVerb";
WCHAR const c_szVerbName[] = L"Create Process Verb";
WCHAR szModule[MAX_PATH];
GetModuleFileName(NULL, szModule, ARRAYSIZE(szModule));
// register this verb on .txt files ProgID
WCHAR szCmdLine[MAX_PATH + 10];
StringCchPrintf(szCmdLine, ARRAYSIZE(szCmdLine), L"%s -Verb \"%%1\"", szModule);
hr = re.RegisterCreateProcessVerb(c_szProgID, c_szVerb, szCmdLine, c_szVerbName);
if (SUCCEEDED(hr))
{
hr = re.RegisterVerbAttribute(c_szProgID, c_szVerb, L"NeverDefault");
if (SUCCEEDED(hr))
{
MessageBox(NULL,
L"Installed Create Process Verb Sample for .txt files\n\n"
L"right click on a .txt file and choose 'Create Process Verb Sample' to see this in action"
, PathFindFileName(szModule), MB_OK);
}
}
}
CoUninitialize();
}
return 0;
}