Set the Default Search Engine Provider of IE with IOpenServiceManager::InstallService - c++

I would like to set the Default Search Engine Provider of IE with IOpenServiceManager::InstallService:
Belong to the link http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_elements. I created the SearchProviderInfo.xml like this:
<?xml version="1.0" encoding="UTF-8"?> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>Web Search</ShortName> <Description>Use Example.com to search the Web.</Description> <Tags>example web</Tags> <Contact>admin#example.com</Contact> <Url type="application/atom+xml" template="http://example.com/?q={searchTerms}&pw={startPage?}&format=atom"/> <Url type="application/rss+xml" template="http://example.com/?q={searchTerms}&pw={startPage?}&format=rss"/> <Url type="text/html" template="http://example.com/?q={searchTerms}&pw={startPage?}"/> <LongName>Example.com Web Search</LongName> <Image height="64" width="64" type="image/png">http://example.com/websearch.png</Image> <Image height="16" width="16" type="image/vnd.microsoft.icon">http://example.com/websearch.ico</Image> <Query role="example" searchTerms="cat" /> <Developer>Example.com Development Team</Developer> <Attribution> Search data Copyright 2005, Example.com, Inc., All Rights Reserved </Attribution> <SyndicationRight>open</SyndicationRight> <AdultContent>false</AdultContent> <Language>en-us</Language> <OutputEncoding>UTF-8</OutputEncoding> <InputEncoding>UTF-8</InputEncoding> </OpenSearchDescription>
Belong to the link http://msdn.microsoft.com/en-us/library/cc849088%28v=vs.85%29.aspx. I create the project "SetDefaultHelper" like this:
#include <windows.h>
#include <atlbase.h>
#include <wininet.h>
#include <urlmon.h>
#include <string>
#include "openservice.h"
#pragma comment(lib, "urlmon.lib")
void DisplayUsage()
{
wprintf(L"\r\nSetDefaultHelper.exe -- Call SetDefault API on a search provider");
wprintf(L"\r\n");
wprintf(L"\r\nUSAGE: SetDefaultHelper.exe <option>");
wprintf(L"\r\n");
wprintf(L"\r\nOptions (these are mutually exclusive!):");
wprintf(L"\r\n");
wprintf(L"\r\n /guid <guid> GUID of an installed search provider");
wprintf(L"\r\n /url <url> URL of an OpenSearch Description file");
wprintf(L"\r\n");
}
int __cdecl wmain(__in int argc, __in_ecount(argc) WCHAR* argv[])
{
HRESULT hr = E_FAIL;
BOOL fComInitialized = FALSE;
if (3 != argc)
{
DisplayUsage();
}
else if (SUCCEEDED(CoInitialize(NULL)))
{
fComInitialized = TRUE;
CComPtr<IOpenServiceManager> spManager;
hr = spManager.CoCreateInstance(CLSID_OpenServiceManager);
if (SUCCEEDED(hr))
{
CComPtr<IOpenService> spService;
if (0 == _wcsicmp(argv[1], L"/guid"))
{
// Get an IOpenService pointer from the GUID.
WCHAR szEscaped[INTERNET_MAX_URL_LENGTH] = L"";
DWORD cchEscaped = ARRAYSIZE(szEscaped);
hr = UrlEscape(argv[2], szEscaped, &cchEscaped, URL_ESCAPE_SEGMENT_ONLY);
if (SUCCEEDED(hr))
{
std::wstring wsOsid(L"x-osid:1:search:");
wsOsid += szEscaped;
hr = spManager->GetServiceByID(wsOsid.c_str(), &spService);
}
}
else if (0 == _wcsicmp(argv[1], L"/url"))
{
// Install the provider to get an IOpenService pointer.
//CComPtr<IUri> spUri;
//hr = CreateUri(argv[2], 0, 0, &spUri);
//if (SUCCEEDED(hr))
//{
hr = spManager->InstallService(argv[2], &spService);
//}
}
else
{
DisplayUsage();
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
hr = spService->SetDefault(TRUE, NULL);
}
}
}
if (fComInitialized)
{
CoUninitialize();
}
return hr;
}
I build the project ok. Both file SetDefaultHelper.exe and SearchProviderInfo.xml are same folder. In the project setting, set Configuration Properties > Debugging > Commands Arguments = /url absolutePaht/searchProvider.xml. Then run debug (F10), at line "hr = CreateUri(argv[2], 0, 0, &spUri);", the rusult hr is so stranger. I don't know why. Can you help me?
Thank you very much.
[Resolved]:
1. Don't need CreateUri //commented
2. Use a absolutely path.

Use absolute path and UrlCreateFromPath to create a file:/// like URL, pass that URL to InstallService.
Between, it seems that your XML has error.
WCHAR szURL[MAX_PATH] = L"";
DWORD cchURL = ARRAYSIZE(szURL);
hr = ::UrlCreateFromPath(argv[2], szURL, &cchURL, 0);
if (SUCCEEDED(hr))
{
hr = spManager->InstallService(argv[2], &spService);
// Now we can set it as the default.
if (SUCCEEDED(hr))
{
hr = spService->SetDefault(TRUE, NULL);
if (hr == OS_E_CANCELLED)
{
hr = E_ACCESSDENIED; // by the user!
}
}
}

Related

WINAPI Network Discovery without SMBv1

I need to get a list of available shared folders on the local network, the way they appear in the "Network" tab in File Explorer. Earlier, I used combination of NetServerEnum/NetShareEnum functions to obtain it, but they are using SMBv1 protocol, which is now disabled by default in windows, so now i'm getting error 1231 from NetServerEnum. But File Explorer still cat obtain this list. I tried use Process Monitor to determine, which API it use, but failed. So, is there any way to get list of available shared folders in local network without using API, that requires SMBv1?
You can use windows shell api and use FOLDERID_NetworkFolder to get the KNOWNFOLDERID of "network".
The following sample can get folders, nonfolders, and hidden items in the "network" folder.
#include <windows.h>
#include <Shobjidl.h>
#include <Shlobj.h>
#include <iostream>
void wmain(int argc, TCHAR* lpszArgv[])
{
IShellItem* pShellItem;
IEnumShellItems* pShellEnum = NULL;
HRESULT hr = S_OK;
hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("CoInitialize error, %x\n", hr);
return;
}
hr = SHGetKnownFolderItem(FOLDERID_NetworkFolder, KF_FLAG_DEFAULT, NULL, IID_PPV_ARGS(&pShellItem));
if (FAILED(hr))
{
printf("SHGetKnownFolderItem error, %x\n", hr);
return;
}
hr = pShellItem->BindToHandler(nullptr, BHID_EnumItems, IID_PPV_ARGS(&pShellEnum));
if (FAILED(hr))
{
printf("BindToHandler error, %x\n", hr);
return;
}
do {
IShellItem* pItem;
LPWSTR szName = NULL;
hr = pShellEnum->Next(1, &pItem, nullptr);
if (hr == S_OK && pItem)
{
HRESULT hres = pItem->GetDisplayName(SIGDN_NORMALDISPLAY, &szName);
std::wcout << szName << std::endl;
CoTaskMemFree(szName);
}
} while (hr == S_OK);
CoUninitialize();
}

How Can I Remove System.Size Property from My Custom File Type On Windows Explorer?

I have been trying lately to get a grasp on the Windows Property System. I implemented a custom file type(Property Handler, Thumbnail Handler, Preview Handler) and I want to hide System.Size property for my file type on Windows Explorer(Details Tab on Properties dialogbox and Size Column on Details View Mode).I used the following code but no result. Is it possible to hide size property? Maybe I should write Shell Folder extension.
#include <shobjidl.h>
#include <propsys.h>
#include <propvarutil.h>
#include <propkey.h>
#include <strsafe.h>
#pragma comment(lib,"propsys.lib")
HRESULT SetPropertyValue(PCWSTR pszFilename, PCWSTR pszCanonicalName, PCWSTR pszValue)
{
// Convert the Canonical name of the property to PROPERTYKEY
PROPERTYKEY key;
HRESULT hr = PSGetPropertyKeyFromName(pszCanonicalName, &key);
if (SUCCEEDED(hr))
{
IPropertyStore* pps = NULL;
hr = SHGetPropertyStoreFromParsingName(pszFilename, NULL, gpsFlags, IID_PPV_ARGS(ppps));
if (SUCCEEDED(hr))
{
PROPVARIANT propvarValue = { 0 };
hr = InitPropVariantFromString(pszValue, &propvarValue);
if (SUCCEEDED(hr))
{
hr = PSCoerceToCanonicalValue(key, &propvarValue);
if (SUCCEEDED(hr))
{
// Set the value to the property store of the item.
hr = pps->SetValue(key, propvarValue);
if (SUCCEEDED(hr))
{
// Commit does the actual writing back to the file stream.
hr = pps->Commit();
if (SUCCEEDED(hr))
{
wprintf(L"Property %s value %s written successfully \n", pszCanonicalName, pszValue);
}
else
{
wprintf(L"Error %x: Commit to the propertystore failed.\n", hr);
}
}
else
{
wprintf(L"Error %x: Set value to the propertystore failed.\n", hr);
}
}
PropVariantClear(&propvarValue);
}
pps->Release();
}
else
{
wprintf(L"Error %x: getting the propertystore for the item.\n", hr);
}
}
else
{
wprintf(L"Invalid property specified: %s\n", pszCanonicalName);
}
return hr;
}
int wmain(int argc, wchar_t* argv[])
{
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)))
{
SetPropertyValue(L"FullFilePath",L"System.Size", L"0");
CoUninitialize();
}
return 0;
}

TaskScheduler RegisterTaskDefinition fails with NULL path in Win10

According to this MSDN doc, we may pass NULL for the path argument:
path [in]
The name of the task. If this value is NULL, the task will be registered in the root task folder and the task name will be a GUID value created by the Task Scheduler service.
I have a code that use this behavior. The code works fine in Win7 and 8.1, but not in my Win10 box (ver 1709 64-bit, build 16299). In Win10, it will return 0x80070005 aka "Access Denied" when path is NULL. If I specify a name like "Foobar", it will work fine.
Test code:
// Link comsuppw.lib and taskschd.lib.
#include <stdio.h>
#include <windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <shlobj.h>
#include <taskschd.h>
#include <comutil.h>
class AutoHR {
HRESULT hr;
public:
void operator=(HRESULT hr)
{
this->hr = hr;
if (FAILED(hr)) {throw *this;}
}
HRESULT GetHR() const { return hr; }
};
static void TestTaskSched()
{
AutoHR hr;
CComPtr<ITaskService> taskSvc;
CComPtr<ITaskFolder> taskFol;
CComPtr<ITaskDefinition> taskDef;
CComPtr<IActionCollection> taskAC;
CComPtr<IAction> taskAction;
CComPtr<IExecAction> taskEA;
CComPtr<IRegisteredTask> registeredTask;
try {
hr = taskSvc.CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_ALL);
hr = taskSvc->Connect(CComVariant(),CComVariant(),CComVariant(),CComVariant());
hr = taskSvc->GetFolder(_bstr_t(L""), &taskFol);
hr = taskSvc->NewTask(0, &taskDef);
hr = taskDef->get_Actions(&taskAC);
hr = taskAC->Create(TASK_ACTION_EXEC, &taskAction);
hr = taskAction.QueryInterface<IExecAction>(&taskEA);
hr = taskEA->put_Path(_bstr_t(L"C:\\Windows\\System32\\cmd.exe"));
hr = taskEA->put_Arguments(_bstr_t(L"/k echo Testing"));
// Note that NULL is passed as the first argument.
hr = taskFol->RegisterTaskDefinition(nullptr, taskDef,
TASK_CREATE_OR_UPDATE, CComVariant(), CComVariant(),
TASK_LOGON_NONE, CComVariant(), &registeredTask);
MessageBoxW(nullptr, L"Succeeded!", L"OK", MB_ICONINFORMATION);
}
catch (AutoHR const &autohr) {
WCHAR buf[99] = {0};
wsprintfW(buf, L"HRESULT error 0x%.8X\n", autohr.GetHR());
MessageBoxW(nullptr, buf, nullptr, MB_ICONERROR);
}
}
int main()
{
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
TestTaskSched();
CoUninitialize();
}
return 0;
}
Test result:
Questions:
1) Is there a behavior change between Win10 and older Windows? I suspect there is, but I cannot find any doc that mentions it.
2) Any good alternative for this behavior? I hope I don't have to generate GUID by myself for temporary task creation.

How open the new tab from IE

I want to open the html file from IE.
So, I use the ShellExecute API like this.
ShellExecute(NULL, L"open", html file path, NULL, NULL, SW_SHOW);
but, My Default Browser is Chrome.
Html file is open to the Chrome new tab.
So, I try like this.
ShellExecute(NULL, L"open", IE file path, html file path, NULL, SW_SHOW);
I set parameter to the html file path.
but, That method is create new window.
I want to open the html file from IE.(new tab!)
Thanks.
Instead of ShellExecute, you have to use an instace of IShellWindows to open a new tab in Internet Explorer. Check the code taken from Warwick Systems to accomplish this:
void OutputToWebBrowser(const CString & path)
{
IShellWindows *psw;
HRESULT hr = CoCreateInstance(CLSID_ShellWindows,NULL,CLSCTX_ALL,IID_IShellWindows,(void**)&psw);
if (!SUCCEEDED(hr))
return;
IWebBrowser2* pBrowser2 = 0;
bool found = false;
long nCount = 0;
hr = psw->get_Count(&nCount);
if (SUCCEEDED(hr))
{
for (long i = nCount - 1; (i >= 0) && (!found); i--) {
// get interface to item no i
_variant_t va(i, VT_I4);
IDispatch * spDisp;
hr = psw->Item(va,&spDisp);
hr = spDisp->QueryInterface(IID_IWebBrowserApp,(void **)&pBrowser2);
if (SUCCEEDED(hr))
{
BSTR name;
pBrowser2->get_FullName(&name);
CString n(name);
if (n.Find("IEXPLORE") == -1)
pBrowser2->Release();
else
found = true;
}
}
psw->Release();
}
if (!found)
hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER,IID_IWebBrowser2,(void**)&pBrowser2);
if (SUCCEEDED(hr))
{
VARIANT vEmpty;
VariantInit(&vEmpty);
_variant_t URL, Flag, TargetFrameName, PostData, Headers;
Flag.ChangeType(VT_I4, &Flag);
if (found)
Flag.intVal = 0x800;
URL.SetString(path);
hr = pBrowser2->Navigate2(&URL, &Flag, &vEmpty, &vEmpty, &vEmpty);
if (SUCCEEDED(hr))
{
pBrowser2->put_Visible(TRUE);
}
else
{
pBrowser2->Quit();
}
pBrowser2->Release();
}
}

Play Audio Stream Using Windows APIs in C++

To play an .mp3 file in Windows using (in this case) DirectShow you only need:
#include <dshow.h>
#include <cstdio>
// For IID_IGraphBuilder, IID_IMediaControl, IID_IMediaEvent
#pragma comment(lib, "strmiids.lib")
const wchar_t* filePath = L"C:/Users/Public/Music/Sample Music/Sleep Away.mp3";
int main()
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = ::CoInitialize(NULL);
if (FAILED(hr))
{
::printf("ERROR - Could not initialize COM library");
return 0;
}
// Create the filter graph manager and query for interfaces.
hr = ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
::printf("ERROR - Could not create the Filter Graph Manager.");
return 0;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph.
hr = pGraph->RenderFile(filePath, NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
// Clean up in reverse order.
pEvent->Release();
pControl->Release();
pGraph->Release();
::CoUninitialize();
}
I can't find a way to have something like this, but to be able to play an .asx instead, like for example: http://listen.radiotunes.com/public5/solopiano.asx
In MSDN I can only find ways to do this in C# making a Forms application and inserting a WindowsMediaPlayer control in a form.
Any ideas?
An .asx file is actually a playlist. See here some information about the format.
.asx is not supported by DirectShow. See here for the supported formats.
You might parse the file, as it is XML, and find the actual URL of the stream, and then play it, or you could use the Windows Media Player SDK. You can see some sample code for WM SDK here.
OK, got it to work with this example taken from here and adding this extra line: hr = spPlayer->put_URL(L"http://listen.radiotunes.com/public5/solopiano.asx");:
#include "atlbase.h"
#include "atlwin.h"
#include "wmp.h"
#include <cstdio>
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
HRESULT hr = S_OK;
CComBSTR bstrVersionInfo; // Contains the version string.
CComPtr<IWMPPlayer> spPlayer; // Smart pointer to IWMPPlayer interface.
hr = spPlayer.CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER);
if (SUCCEEDED(hr))
{
hr = spPlayer->get_versionInfo(&bstrVersionInfo);
hr = spPlayer->put_URL(L"http://listen.radiotunes.com/public5/solopiano.asx");
}
if (SUCCEEDED(hr))
{
// Show the version in a message box.
COLE2T pStr(bstrVersionInfo);
MessageBox(NULL, (LPCSTR)pStr, _T("Windows Media Player Version"), MB_OK);
}
// Clean up.
spPlayer.Release();
CoUninitialize();
return 0;
}