Why is my windows shell extension being invoked when I run an executable as administrator? - c++

I'm working on a project that integrates with the Windows 10 file explorer to allow users to open selected files in our program. The shell extension I made works fine for the most part, but the problem I'm having is that my extension's IShellExtInit::Initialize(...) and IContextMenu::InvokeCommand(...) are being invoked when I right click an executable in my start menu results and click "Run as administrator". As far as I can tell, the only point in my code where I can confirm that my extension should actually be running when it is invoked is in DllGetClassObject(...) by checking that rclsid and my extension's GUID are equal.
For the basic setup of the shell extension, I followed this video series. The example extension in the videos only appeared for text files, but I changed mine to work on all file types.
Does anyone have any idea where this problem could be coming from? Here are the relevant parts of my code: https://gist.github.com/caevrobe/2865b5f472d668352a7a91fb5c66953a

I found a solution to this issue here. My fix was to return E_INVALIDARG if pici->lpVerb != NULL in my IContextMenu::InvokeCommand(...). When invoking "Run as administrator" pici->lpVerb was "runas". When using my extension through the context menu normally, it was null.
HRESULT MyContextMenuHandler::InvokeCommand(LPCMINVOKECOMMANDINFO pici) {
if (pici->lpVerb != NULL)
return E_INVALIDARG;
// rest of your code...
}
I'll leave the question up in case anyone else has the same issue.

Related

Can't find COM object from C++, although Guid it's registered

First of all happy new year to everyone, hope you're doing well!
I'm working on a C++ project in which I need to call a C# DLL I created following the first answer of this post. Once I have the DLL, I need to call it from Qt, so by using dumpcpp and the .tlb file generated by regasm, I managed to get the .cpp and .h files to use my classes. Just as a reference, the namespace of the classes is Wrapper, and the main class is Device with guid {DD4A4896-C105-4C60-839B-B18C99C8FE15}.
Once I have the generated files to use the DLL, if I try to create a Wrapper:: Device instance on Qt, I get the following error:
QAxBase::setControl: requested control {dd4a4896-c105-4c60-839b-b18c99c8fe15} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed
It doesn't give any more information, so I tried to check if the guid was stored on the system registry (I used the regasm command explained on the previously quoted post, and It said that it was successful, but you never know). Opening Registry editor and searching for the Guid revealed that it's present at: Computer\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{DD4A4896-C105-4C60-839B-B18C99C8FE15}, which, as far as I know, is the right route for these guids, and it points to the right DLL.
I though It may be due to some kind ActiveQt problem, and as the previously quoted post explained how to use that DLL from VS C++, I decided to give it a try, using this as an another reference. I've finished with this code, which is supposed to create an instance of my Device object
#include <iostream>
#include <atlstr.h>
#import "C:\Users\javie\Documents\Wrapper\Wrapper\bin\x86\Release\netstandard2.0\Wrapper.tlb" named_guids raw_interfaces_only
inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };
int main()
{
try
{
TESTHR(CoInitialize(0));
Wrapper::IDevicePtr devPtr = nullptr;
TESTHR(devPtr.CreateInstance("{DD4A4896-C105-4c60-839B-B18C99C8FE15}"));
}
catch (const _com_error& e)
{
CStringW out;
out.Format(L"Exception occurred. HR = %lx, error = %s", e.Error(), e.ErrorMessage());
MessageBoxW(NULL, out, L"Error", MB_OK);
}
CoUninitialize();// Uninitialize COM
std::cout << "Hello World!\n";
}
However, this doesn't work either, the createInstance method throws an exception of Class not registered and HR=80040154. Again, according to Registry editor, the class is registered, so I don't understand the error. I've also tried with devPtr.CreateInstance("Wrapper.Device"), devPtr.CreateInstance("Wrapper::Device") or `devPtr.CreateInstance("Wrapper::CLSID_Device") as the links I posted suggest, but in those cases I get another exception with HR=800401f3 and message Invalid class string.
It doesn't matter whether VS or Qt Creator are opened as administrator or not, I get the exact same error.
I have run out of ideas, and I really need to be able to use that DLL from Qt using the files generated by dumpcpp.
Does any one know what could be happening? It feels quite strange to me.
If your C++ application is 64-bit, that's the answer right there, because your C# component is 32-bit (or MSIL but registered to the 32-bit hive). In situations like these, a simple test using VBScript is always useful.
Write a simple VB Script (test.vbs)
Dim obj
Set obj = CreateObject("Wrapper.Device") ' or whatever your ProgID is
MsgBox TypeName(obj)
Now, run this macro 2 ways: with 32-bit and 64-bit versions of VBScript:
32-bit > c:\windows\SysWow64\cscript.exe test.vbs
64-bit > c:\windows\system32\cscript.exe test.vbs
This is assuming your C# component is dispatch compatible. If it's not, then it will still give you differing results that you can use to debug.
Assuming automation/IDispatch compatible, one will work and one won't if you have registered your component correctly.
Have you registered correctly? When I use regasm, I always use the the switches /tlb /codebase when registering the C# component for COM.
Ok, in case someone find the same error, I'll explain the solution I found.
The problem was that in my case, the C# class I developed depended on another 32 bits dll which was not registered on my PC. Once I registered the other dll, everything worked fine.
I don't know why VS kept telling me that the class was not registered when my class itselft was registered, it was one of its dependencies that wasn't registered.
Anyway, I discovered this thanks to Joseph's comments, so thanks a lot for your help.

Loading VCL-Styles from Reources

Does anyone have experience with using resource for styles. I'm working on a program for which we created a custom Style. We saved it as .style and as .vsf. Because we don't want the user to see/change the style of the programm we want to include it in our resource file (.res) This is done as explained in next Link: Customizing and Creating VCL Styles Afterwards the created file (Tested with .style and .vsf) is placed in the Resourcefile as RC Data.
Thats the preparation, now what didn't work. (tWinMain)
TStyleManager::SetStyle(TStyleManager::LoadFromResource((unsigned int)HInstance, "StyleName", RT_RCDATA));
This also doesn't work:
TStyleManager::LoadFromResource((unsigned int)HInstance, "StyleName", RT_RCDATA);
TStyleManager::SetStyle("StyleName");
also not working
TStyleManager_TStyleServicesHandle MyStyle;
MyStyle = TStyleManager::LoadFromResource((unsigned int)HInstance, "StyleName", RT_RCDATA);
TStyleManager::SetStyle(MyStyle);
All three methodes resulting in the error message: Invalid Style-handle
Loading the same style from a file works:
TStyleManager::LoadFromFile(stylePath + "StyleName.vsf");
TStyleManager::SetStyle("StyleName");
I had the same problem in Delphi (DX10.3) and the following worked for me
Basically the same call of "TStyleManager::LoadFromResource", but without the specification of the optional parameter "RT_RCDATA".
MyStyle = TStyleManager::LoadFromResource((unsigned int)HInstance, "StyleName");
TStyleManager::SetStyle(MyStyle);
But then the resource type "VCLSTYLE" is necessary to load the style correctly. When adding the resource in the IDE, with [Project] > [Resources and Pics...] you can only specify RCDATA in the dialog, which is bad. But you can enter the resource type directly manual with the keyboard as "VCLSTYLE". The IDE remembers this setting and now the resource is available as the correct type. As said before, it works with Delphi 10.3, with the Builder it depends on one try.
Resource-type manual input in IDE dialog
Best regards, Matthias

Can't open database using SQLite on an UWP written in C++

I am making an UWP in which I need to access a database. To do so I first downloaded and installed the SQL Universal Windows Platform from this link:
https://sqlite.org/download.html
After this was done I added it as a reference and included it in my code with:
#include <sqlite3.h> //Not sure if I need to make any other changes for this to work
To troubleshoot I have just a button and a textbox. This is the code that it's been run when the button is clicked:
int rc;
sqlite3 *testDB;
if (SQLITE_OK == (rc = sqlite3_open("signers.db", &testDB))) {
Message->Text = "It worked!";
}
else {
Message->Text = "Can't open Database";
}
signers.db it's a database that I created using SQLite so I could have some data to read from my program. Everytime I run the program the text "Can't open Database" appears. I've tried every solution that I see online but none seem to work for me thus I think that I overseeing something. I am fairly new at UWP and also at using databases.
If you need any additional information feel free to ask for it.
If you have the database in your package folder, then it is read-only. You need to use sqlite3_open_v2 and pass the SQLITE_OPEN_READONLY flag.
If you want to open the database for read / write then you need to copy it to your local folder first.
(Also make sure you actually have the database set to deploy; in the Properties window make sure it is set to Content and that it will be copied to the output directory).
According to
https://learn.microsoft.com/en-us/windows/uwp/files/file-access-permissions
you have some limitations to the location where the db file you want to open is located. sqlite itself should work. Try opening a db in a folder specified in the article.
Could also be just a corrupted db file. Did you try to create an empty one?

Unable to get a custom helpfile to work from inside a Qt Application using Qt Assistant

I am trying to learn how to use Qt Assistant for displaying a custom help in an application.
I found an example on Qt site:
http://qt-project.org/doc/qt-4.7/help-simpletextviewer.html
(using Qt 4.7.3)
All the source files needed are at the site above. I created html and png files and placed them in a "help" folder inside the project folder.
Running Qt Assistant from command line works great.
Loading the help file in the Assistant also works. What I can't get to do is to load the start page in the help file, as explained in this section:
http://qt-project.org/doc/qt-4.7/assistant-custom-help-viewer.html#id-0c628592-dd04-4465-94b1-e5d4a91d7cd4
void Assistant::showDocumentation(const QString &page)
{
if (!startAssistant())
return;
QByteArray ba("SetSource ");
ba.append("qthelp://com.trolltech.examples.simpletextviewer/doc/");
proc->write(ba + page.toLocal8Bit() + '\n');
}
With the detailed explanation of SetSource showing
setSource <Url> Displays the given <Url>. The URL can be absolute or relative
to the currently displayed page. If the URL is absolute, it has to be
a valid Qt help system URL; i.e., starting with "qthelp://".
I don't have a web page... but i tried to display the index from the local set of files, and i always get
a 404 error saying "cannot load page blahblah/help/index.html"
How can I create a local path as they say, or how can I create a "valid Qt help system URL" ?``
Note: SetSource and setSource have exactly the same results... and documentation and their own examples use them both... are these options not case sensitive ?
I answered my own question with a solution that doesn't seem right though... I would appreciate a better answer.
There must be something wrong with either my solution or the documentation...
I was able to get the page to display by changing an option...
replace QByteArray ba("SetSource ");
with QByteArray ba("Set Source ");

Thumbnail Provider not working

I'm trying to write a Windows Explorer thumbnail handler for our custom file type. I've got this working fine for the preview pane, but am having trouble getting it to work for the thumbnails.
Windows doesn't even seem to be trying to call the DllGetClassObject entry point.
Before I continue, note that I'm using Windows 7 and unmanaged C++.
I've registered the following values in the registry:
HKCR\CLSID\<my guid>
HKCR\CLSID\<my guid>\InprocServer32 (default value = path to my DLL)
HKCR\CLSID\<my guid>\InprocServer32\ThreadingModel (value = "Apartment")
HKCR\.<my ext>\shellex\{E357FCCD-A995-4576-B01F-234630154E96} (value = my guid)
I've also tried using the Win SDK sample, and that doesn't work. And also the sample project in this article (http://www.codemonkeycodes.com/2010/01/11/ithumbnailprovider-re-visited/), and that doesn't work.
I'm new to shell programming, so not really sure the best way of debugging this. I've tried attaching the debugger to explorer.exe, but that doesn't seem to work (breakpoints get disabled, and none of my OutputDebugStrings get displayed in the output window). Note that I tried setting the "DesktopProcess" in the registry as described in the WinSDK docs for debugging the shell, but I'm still only seeing one explorer.exe in the task manager - so that "may" be why I can't debug it??
Any help with this would be greatly appreciated!
Regards,
Dan.
I stumbled across this since you mentioned my blog ( codemonkeycodes.com ).
What problem are you having with my sample? Did you register you DLL using regsvr32? What version of Windows 7 are you on, 32 or 64?
Update:
I can't say what is or isn't working for you. I just downloaded the sample from my site, followed the directions and change the function
STDMETHODIMP CThumbnailProvider::GetThumbnail... to look like
{
*phbmp = NULL;
*pdwAlpha = WTSAT_UNKNOWN;
ULONG_PTR token;
GdiplusStartupInput input;
if (Ok == GdiplusStartup(&token, &input, NULL))
{
//gcImage.LogBuffer();
Bitmap * pBitmap = new Bitmap(188, 141);
if( pBitmap )
{
Color color(0, 0, 0);
pBitmap->GetHBITMAP(color, phbmp);
}
}
GdiplusShutdown(token);
if( *phbmp != NULL )
return NOERROR;
return E_NOTIMPL;
}
I registered the DLL and then created a new file with the proper extension, and tada, I had a nice black thumbnail.
I wish I could help you. Maybe you want to email me your code?
I've exactly the same problem. I cant make SDK or any sample works. I need COM sample because I must call Microsoft.Jet.OLEDB.4.0 which works only on 32 bits system.
I couldnt make this work: link
This works if AnyCPU is specified when compiling. Cant make it works for x86: link
This was nice under XP works like a charm: link
This show Adobe had problems with thumbnail An MS with Office 2007 (32 bits): link