// dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" #include #include #include #include #include #include #include #include #include using namespace Microsoft::WRL; std::wstring g_path; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { wchar_t path[MAX_PATH]; GetModuleFileName(hModule, path, MAX_PATH); wchar_t* ptr = wcsrchr(path, L'\\'); *ptr = L'\0'; g_path = std::wstring(path); break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } class TestExplorerCommandBase : public RuntimeClass, IExplorerCommand, IObjectWithSite> { public: virtual const wchar_t* Title() = 0; virtual const EXPCMDFLAGS Flags() { return ECF_DEFAULT; } virtual const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) { return ECS_ENABLED; } // IExplorerCommand IFACEMETHODIMP GetTitle(_In_opt_ IShellItemArray* items, _Outptr_result_nullonfailure_ PWSTR* name) { *name = nullptr; auto title = wil::make_cotaskmem_string_nothrow(Title()); RETURN_IF_NULL_ALLOC(title); *name = title.release(); return S_OK; } IFACEMETHODIMP GetIcon(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* icon)// { *icon = nullptr; return E_NOTIMPL; } { std::wstring bpPath = g_path + L"\\SandMan.exe,-0"; auto iconPath = wil::make_cotaskmem_string_nothrow(bpPath.c_str()); RETURN_IF_NULL_ALLOC(iconPath); *icon = iconPath.release(); return S_OK; } IFACEMETHODIMP GetToolTip(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* infoTip) { *infoTip = nullptr; return E_NOTIMPL; } IFACEMETHODIMP GetCanonicalName(_Out_ GUID* guidCommandName) { *guidCommandName = GUID_NULL; return S_OK; } IFACEMETHODIMP GetState(_In_opt_ IShellItemArray* selection, _In_ BOOL okToBeSlow, _Out_ EXPCMDSTATE* cmdState) { *cmdState = State(selection); return S_OK; } enum ECommand { eExplore, eOpen, }; virtual ECommand GetCommand() = 0; IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept try { /*HWND parent = nullptr; if (m_site) { ComPtr oleWindow; RETURN_IF_FAILED(m_site.As(&oleWindow)); RETURN_IF_FAILED(oleWindow->GetWindow(&parent)); } std::wostringstream title; title << Title(); if (selection) { DWORD count; RETURN_IF_FAILED(selection->GetCount(&count)); title << L" (" << count << L" selected items)"; } else { title << L"(no selected items)"; } MessageBox(parent, title.str().c_str(), L"TestCommand", MB_OK);*/ if (selection) { DWORD fileCount = 0; RETURN_IF_FAILED(selection->GetCount(&fileCount)); for (DWORD i = 0; i < fileCount; i++) { IShellItem* shellItem = nullptr; selection->GetItemAt(i, &shellItem); LPWSTR itemName = nullptr; shellItem->GetDisplayName(SIGDN_FILESYSPATH, &itemName); if (itemName) { std::wstring file = g_path + L"\\SandMan.exe"; std::wstring params = L"/box:__ask__"; if(GetCommand() == eExplore) params += L" C:\\WINDOWS\\explorer.exe"; params += L" \""; params += itemName; params += L"\""; SHELLEXECUTEINFO shExecInfo = { sizeof(SHELLEXECUTEINFO) }; shExecInfo.hwnd = nullptr; shExecInfo.lpVerb = L"open"; shExecInfo.lpFile = file.c_str(); shExecInfo.lpParameters = params.c_str(); shExecInfo.nShow = SW_NORMAL; ShellExecuteEx(&shExecInfo); CoTaskMemFree(itemName); } } } return S_OK; } CATCH_RETURN(); IFACEMETHODIMP GetFlags(_Out_ EXPCMDFLAGS* flags) { *flags = Flags(); return S_OK; } IFACEMETHODIMP EnumSubCommands(_COM_Outptr_ IEnumExplorerCommand** enumCommands) { *enumCommands = nullptr; return E_NOTIMPL; } // IObjectWithSite IFACEMETHODIMP SetSite(_In_ IUnknown* site) noexcept { m_site = site; return S_OK; } IFACEMETHODIMP GetSite(_In_ REFIID riid, _COM_Outptr_ void** site) noexcept { return m_site.CopyTo(riid, site); } protected: ComPtr m_site; }; class __declspec(uuid("EA3E972D-62C7-4309-8F15-883263041E99")) ExploreCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"Explore Sandboxed"; } ECommand GetCommand() { return eExplore; } }; class __declspec(uuid("3FD2D9EE-DAF9-404A-9B7E-13B2DCD63950")) OpenCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"Open Sandboxed"; } ECommand GetCommand() { return eOpen; } }; CoCreatableClass(ExploreCommandHandler) CoCreatableClass(OpenCommandHandler) CoCreatableClassWrlCreatorMapInclude(ExploreCommandHandler) CoCreatableClassWrlCreatorMapInclude(OpenCommandHandler) /* class TestExplorerCommandBase : public RuntimeClass, IExplorerCommand, IObjectWithSite> { public: virtual const wchar_t* Title() = 0; virtual const EXPCMDFLAGS Flags() { return ECF_DEFAULT; } virtual const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) { return ECS_ENABLED; } // IExplorerCommand IFACEMETHODIMP GetTitle(_In_opt_ IShellItemArray* items, _Outptr_result_nullonfailure_ PWSTR* name) { *name = nullptr; auto title = wil::make_cotaskmem_string_nothrow(Title()); RETURN_IF_NULL_ALLOC(title); *name = title.release(); return S_OK; } IFACEMETHODIMP GetIcon(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* icon) { *icon = nullptr; return E_NOTIMPL; } IFACEMETHODIMP GetToolTip(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* infoTip) { *infoTip = nullptr; return E_NOTIMPL; } IFACEMETHODIMP GetCanonicalName(_Out_ GUID* guidCommandName) { *guidCommandName = GUID_NULL; return S_OK; } IFACEMETHODIMP GetState(_In_opt_ IShellItemArray* selection, _In_ BOOL okToBeSlow, _Out_ EXPCMDSTATE* cmdState) { *cmdState = State(selection); return S_OK; } IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept try { HWND parent = nullptr; if (m_site) { ComPtr oleWindow; RETURN_IF_FAILED(m_site.As(&oleWindow)); RETURN_IF_FAILED(oleWindow->GetWindow(&parent)); } std::wostringstream title; title << Title(); if (selection) { DWORD count; RETURN_IF_FAILED(selection->GetCount(&count)); title << L" (" << count << L" selected items)"; } else { title << L"(no selected items)"; } MessageBox(parent, title.str().c_str(), L"TestCommand", MB_OK); return S_OK; } CATCH_RETURN(); IFACEMETHODIMP GetFlags(_Out_ EXPCMDFLAGS* flags) { *flags = Flags(); return S_OK; } IFACEMETHODIMP EnumSubCommands(_COM_Outptr_ IEnumExplorerCommand** enumCommands) { *enumCommands = nullptr; return E_NOTIMPL; } // IObjectWithSite IFACEMETHODIMP SetSite(_In_ IUnknown* site) noexcept { m_site = site; return S_OK; } IFACEMETHODIMP GetSite(_In_ REFIID riid, _COM_Outptr_ void** site) noexcept { return m_site.CopyTo(riid, site); } protected: ComPtr m_site; }; class __declspec(uuid("3282E233-C5D3-4533-9B25-44B8AAAFACFA")) TestExplorerCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"ShellDemo Command1"; } const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) override { return ECS_DISABLED; } }; class __declspec(uuid("817CF159-A4B5-41C8-8E8D-0E23A6605395")) TestExplorerCommand2Handler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"ShellDemo ExplorerCommand2"; } }; class SubExplorerCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"SubCommand"; } }; class CheckedSubExplorerCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"CheckedSubCommand"; } const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) override { return ECS_CHECKBOX | ECS_CHECKED; } }; class RadioCheckedSubExplorerCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"RadioCheckedSubCommand"; } const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) override { return ECS_CHECKBOX | ECS_RADIOCHECK; } }; class HiddenSubExplorerCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"HiddenSubCommand"; } const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) override { return ECS_HIDDEN; } }; class EnumCommands : public RuntimeClass, IEnumExplorerCommand> { public: EnumCommands() { m_commands.push_back(Make()); m_commands.push_back(Make()); m_commands.push_back(Make()); m_commands.push_back(Make()); m_current = m_commands.cbegin(); } // IEnumExplorerCommand IFACEMETHODIMP Next(ULONG celt, __out_ecount_part(celt, *pceltFetched) IExplorerCommand** apUICommand, __out_opt ULONG* pceltFetched) { ULONG fetched{ 0 }; wil::assign_to_opt_param(pceltFetched, 0ul); for (ULONG i = 0; (i < celt) && (m_current != m_commands.cend()); i++) { m_current->CopyTo(&apUICommand[0]); m_current++; fetched++; } wil::assign_to_opt_param(pceltFetched, fetched); return (fetched == celt) ? S_OK : S_FALSE; } IFACEMETHODIMP Skip(ULONG celt) { return E_NOTIMPL; } IFACEMETHODIMP Reset() { m_current = m_commands.cbegin(); return S_OK; } IFACEMETHODIMP Clone(__deref_out IEnumExplorerCommand** ppenum) { *ppenum = nullptr; return E_NOTIMPL; } private: std::vector> m_commands; std::vector>::const_iterator m_current; }; class __declspec(uuid("1476525B-BBC2-4D04-B175-7E7D72F3DFF8")) TestExplorerCommand3Handler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"ShellDemo CommandWithSubCommands"; } const EXPCMDFLAGS Flags() override { return ECF_HASSUBCOMMANDS; } IFACEMETHODIMP EnumSubCommands(_COM_Outptr_ IEnumExplorerCommand** enumCommands) { *enumCommands = nullptr; auto e = Make(); return e->QueryInterface(IID_PPV_ARGS(enumCommands)); } }; class __declspec(uuid("30DEEDF6-63EA-4042-A7D8-0A9E1B17BB99")) TestExplorerCommand4Handler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"ShellDemo Command4"; } }; class __declspec(uuid("50419A05-F966-47BA-B22B-299A95492348")) TestExplorerHiddenCommandHandler final : public TestExplorerCommandBase { public: const wchar_t* Title() override { return L"ShellDemo HiddenCommand"; } const EXPCMDSTATE State(_In_opt_ IShellItemArray* selection) override { return ECS_HIDDEN; } }; CoCreatableClass(TestExplorerCommandHandler) CoCreatableClass(TestExplorerCommand2Handler) CoCreatableClass(TestExplorerCommand3Handler) CoCreatableClass(TestExplorerCommand4Handler) CoCreatableClass(TestExplorerHiddenCommandHandler) CoCreatableClassWrlCreatorMapInclude(TestExplorerCommandHandler) CoCreatableClassWrlCreatorMapInclude(TestExplorerCommand2Handler) CoCreatableClassWrlCreatorMapInclude(TestExplorerCommand3Handler) CoCreatableClassWrlCreatorMapInclude(TestExplorerCommand4Handler) CoCreatableClassWrlCreatorMapInclude(TestExplorerHiddenCommandHandler) */ STDAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ IActivationFactory** factory) { return Module::GetModule().GetActivationFactory(activatableClassId, factory); } STDAPI DllCanUnloadNow() { return Module::GetModule().GetObjectCount() == 0 ? S_OK : S_FALSE; } STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _COM_Outptr_ void** instance) { return Module::GetModule().GetClassObject(rclsid, riid, instance); } /////////////////////////////////////////////////////////////////////////////////////////////////////////7 // #include #include #include #pragma comment(lib, "windowsapp.lib") int RegisterSparsePackage(const std::wstring& sparseExtPath, const std::wstring& sparsePackagePath) { winrt::Windows::Management::Deployment::PackageManager manager; winrt::Windows::Management::Deployment::AddPackageOptions options; winrt::Windows::Foundation::Uri externalUri(sparseExtPath.c_str()); winrt::Windows::Foundation::Uri packageUri(sparsePackagePath.c_str()); options.ExternalLocationUri(externalUri); auto deploymentOperation = manager.AddPackageByUriAsync(packageUri, options); auto deployResult = deploymentOperation.get(); if (!SUCCEEDED(deployResult.ExtendedErrorCode())) { // Deployment failed std::wstring error = L"AddPackageByUriAsync failed (Errorcode: "; error += std::to_wstring(deployResult.ExtendedErrorCode()); error += L"):\n"; error += deployResult.ErrorText(); return -1; } return 0; } int UnregisterSparsePackage(const std::wstring& sparsePackageName) { winrt::Windows::Management::Deployment::PackageManager manager; winrt::Windows::Foundation::Collections::IIterable packages; try { packages = manager.FindPackagesForUser(L""); } catch (winrt::hresult_error const& ex) { std::wstring error = L"FindPackagesForUser failed (Errorcode: "; error += std::to_wstring(ex.code().value); error += L"):\n"; error += ex.message(); return -1; } for (const auto& package : packages) { if (package.Id().Name() != sparsePackageName) continue; winrt::hstring fullName = package.Id().FullName(); auto deploymentOperation = manager.RemovePackageAsync(fullName, winrt::Windows::Management::Deployment::RemovalOptions::None); auto deployResult = deploymentOperation.get(); if (SUCCEEDED(deployResult.ExtendedErrorCode())) break; // Undeployment failed std::wstring error = L"RemovePackageAsync failed (Errorcode: "; error += std::to_wstring(deployResult.ExtendedErrorCode()); error += L"):\n"; error += deployResult.ErrorText(); return -1; } return 0; } extern "C" __declspec(dllexport) int RegisterPackage() { std::wstring sparseExtPath = g_path; std::wstring sparsePackagePath = g_path + L"\\SbieShellPkg.msix"; return RegisterSparsePackage(sparseExtPath, sparsePackagePath); } extern "C" __declspec(dllexport) int RemovePackage() { std::wstring sparsePackageName = L"SandboxieShell"; return UnregisterSparsePackage(sparsePackageName); }