MFC add Typelib or ActiveX for OPOS - c++

So at work I have been working for a few months on a OPOS driver for a few different things. I didn't create the project, but I have taken it over and am the only one developing it. So today I got curious about the way that it was done and I think that it may have started off on the wrong foot. I had to do a little bit of digging to find out that it uses the OPOS drivers from a company called MCS (Monroe Consulting Services) I downloaded 1.13 and installed the MSI version. I fired up VS created a new mfc dll. I then went to add a class. This is where I am confused.
It doesn't matter if i choose Typelib or ActiveX it usually gives me the same list of interfaces that I can add/extend from(with one exception that comes to mind with MSR it has an events interface that I can extend) And they both make the same header file (in the case with msr it is COPOSMSR.h) but one extends CCmdTarget, and the other extends CWnd. This is my first question. Which should I choose? what is a typelib/ what is a ActiveX component and how do they differ from one another.
The one i've been working on extends CCmdTarget. For the life of me I can not figure out how the driver knows to use one of the files (USNMSRRFID) but that is where all the development went into. (I broke it up a bit so it wasn't just one huge file) But that file doesn't extend COPOSMSR..it extends CCmdTarget as well. The only time i see anything mention the USN file is in MSRRFID.idl (which confuses me even more) Any one have clarity for this?
Part of me thinks this could make a very big impact when it comes time to deploy. A few of the test apps that have been written that make use of this driver require a somewhat confusing setup process that involves registering different drivers, copying files into a specific folder, setting up the registry and so forth. I think that if i can get a grip on what this all means and how to make a nice application that extends one of these OPOS devices properly that I could save my self further grief in the future.
Any tips or pointers??? Sorry if it is a newb question..but i am new to C++. I started with Java then moved to C# so some of this stuff is WAY over my head....

Well so I've done TONS of digging, and it is like searching for dinosaurs. Not easy, and hard to find. I will end up writing a nice little how to on this, but for now I will put up my findings. Although I still don't have this 100% i know I am close.
Turns out the typelib and activeX things are not a big concern but come into play after you've gotten started. ActiveX is for Control objects, and Typelib is for the Service Object. The most important thing is to get started correctly. I found a article on some Chinese website that offers some OK tips after figuring out the translation errors. To start with you will want to make a C++ project with Automation. It can be ATL or MFC. My preference is MFC. In the UPOS 1.13 pdf (or newer) in Appendix A section 8 it describes the responsibilities of the Service object. It has the main methods you need to implement. There are 16 methods you have to add, and at least 4 methods that get/set the properties for your OPOS device.
So to get started you will need to open up the add class wizard (for MFC classes) and click Add MFC class. You wil want your base class to be CCmdTarget. Come up with a classy Class name (I chose PinpadSOCPP) Then in the automation radio buttons select Creatable by type ID. It should fill in your type id as [Project Name].[Class name] so mine was PinpadSO.PinpadSOCPP. hit finish. This makes a nice interface file that you can use Class view to add methods and so forth to it.
As for adding the methods there are 2 things to note about this, and one of them I haven't figured out 100% yet. The first is that you have to implement all the methods in that section with the correct parameters and return values. Most of them return LONG (32bit signed number). and the 2 most common parameters are LONG and BSTR. (there is the occasional pointers for when you have "out" parameters) This is the part that I think that I am currently failing as I don't know if I have them all implemented correctly and that is why I am getting error 104/305 (which from the Chinese article says that I am missing something from my methods) I'm not sure if it is case sensitive, and I'm not sure of the 7 properties that look to need to have get/set which ones need to be implemented because the MSR SO that i am working on from work doesn't use them all and that SO is working. The other is that after you implement the base OPOS methods you have to also implement the extra methods from your specific OPOS device. Since I am doing PINPad there are 6 additional methods I have to implement.
Now this is a lot of time consuming work because you have to open up class view, navigate to the name of your project class. Expand it and go to the Interface portion. My Project name is PinpadSO, and the file that I am implementing this in is PinpadSOCPP (which means the interface name is IPinpadSOCPP) right click on IPinpadSOCPP and click add > add method. This brings you to a 2 step process. You fill in your return value, name of your function, add in all your parameters. Hit next and fill out some help string info (if you want) and hit finish. Now after you do that 20+ times it gets old and slow...and if you are like me you type Computer instead of Compute and flip flop letters, or forget to hit add on all your parameters. A person could make a nice little program to edit the 3 files that get changed each time you add a method and that would speed it up considerably. If you make a mistake you will need to open up [project name].idl, [class name].h, and [class name].cpp those are the 3 files that get the methods added to it directly. I recommend not making a mistake.
so now that all that hard work is out of the way. Compile your program. If you want to save your self an extra step you could turn on Auto Register in the linker project settings (NOTE: if you do that you'll need to run Visual Studio as admin if you program in vista or higher) this would save you of having to open a command window (admin) navigate to your DLL and use the command regsvr32 on that DLL. Nice thing is that you don't have to do that over and over again, just the once will do. I have no hard facts that it works like that every time but the MSR SO that I am working on, I'll make changes to it, compile it, then open up my OPOS tester program and the changes have taken affect.
After that you need to make your registry additions. navigate to HKLM\software\OLEforRetail\ServiceOPOS
(NOTE if you have a x64 machine you'll do this twice. One there, and again at HKLM\software\Wow6432Node\OLEforRetail\ServiceOPOS )
You'll need to add a Key for whatever OPOS device you are working with. I am making a pinpad SO so I made a Key called PINPad (check your UPOS document to see what name you should give it) Lastly choose a name for your device. I chose the model type of the from the vendor as my device name (C100) and made a sub key in PINPad. The default REG_SZ value needs to be your registered SO Device TypeID. in my case it is PinpadSO.PinpadSOCPP
if you don't have a OPOS test program (which I just made my own as a console program) then you can use the Microsoft OPOS test app (I couldn't get it to work on my x64 machine...but maybe you'll have better luck with it) If you do decide to make your own OPOS test app make sure you compile it for x86 machines (even if you have x64) OPOS does not like x64 for some reason (probably the pointers length I'd assume)..at any rate. Once you got it all setup run your test app (for my case I am just running OPOSPinpadClass pin = new OPOSPinpadClass(); Console.WriteLine(pin.Open("C100")); and hope for 0 :)
I am currently getting 104 (E_NOSERVICE)..and like i said before i think it is because I don't have all my methods correct. If that turns out to be the case I'll edit this response, or I'll report back and say what it really was.
Anywho, i hope this helps anyone else who decides they want to make their own SO. Good luck
UPDATE
OPOS checks a couple of properties when you call the Open command. One of the properties that is a must to implement is the in the GetPropertyNumber, and it is PIDX_ServiceObjectVersion. You will need to set this number to return (1000000 * majorVersion) + (1000 * minorVersion) + revision since I am making a OPOS 1.13 compatible SO my returned ServiceObjectVersion is 1013000. You will also want to implement 3 properties in GetPropertyString:
PIDX_DeviceDescription
PIDX_DeviceName
PIDX_ServiceObjectDescription
For all other values you can return a empty string or 0 until you start hooking all those things up.
As a side note if you don't want to make it in C++ you don't have to. You can make it in any language that you can write a ActiveX object in (such as a COM visible .NET class library)

Related

How to detect if QT main class is already present in memory

During the last ten years, we have programmed different functional extensions (as DLLs) using the API of a CAD program, all use QT. All serve other purposes and are individual projects in various IDEs (QTCreator / VS2010 / VS2015).
Apparently, for the first time now, a customer needs to run two or three of these extension DLLs concurrently.
We have no control over which DLL gets loaded (the individual user determines this) or in which order these are loaded (the CAD application determines this).
With the secondly loaded DLL, we get runtime errors as the QT main object can only exist once. Strange things happen.
Question: How can a DLL at its start inquire about the presence of the global QT object (without having a reference to it) and then either create a new one or attach to the existing one?
Sorry, but we could not find a solution in the QT doc or by asking Ma Google; the QT support was of no help, too.
Why not check the value returned by QCoreApplication::instance() before you create a new one?

Run own code elevated at will from non-elevated plugin DLL

I am making a suite of 64-bit plugin DLLs for a Windows host application using Visual Studio/C++, and from the current version onward, the setup.exe that they come in creates a single shared user-writable folder under ProgramData in which I cache all sorts of (non-user specific) data files. Older versions didn't have that folder yet.
However, the distribution of my plugin binaries is often out of my hands too. They are repackaged by a 3rd party bundle which can only do dumb file copies of the DLLs (so no real setup.exe functionality I need like creating folder + set permissions). And since my binary DLLs are all 100% self-contained, users also historically have a hand of just copying the DLLs around to other machines as they see fit, but that ofc also lacks the new folder setup phase.
I am looking into a workaround to have my DLLs create the folder at runtime if it is missing. I know I can't elevate the host process in-place whenever I want, but I thought of the following ways:
Have an extra "FixSetup" entry point in my DLL, and when the need arises, start an elevated RunDLL32.exe and let it use this entry point in my DLL.However, I see all sorts of people all over the place talking about RunDLL being as good as deprecated and advising against using it, but then again that was already since Windows XP and it's still with us. I also hear of RunDLL having it's own runtime context which can change with every Windows release (like switching to high-DPI aware when that came available), and that it thus is a 'hostile' environment to run in (read it on Raymond Chan's blog IIRC). Should I really be afraid of using it, or is my use case so simple it can barely break? (no GUI, just a wrapped CreateDirectory call)
Create a small "FixSetup.exe" which just does the folder creation, package it into my DLL's resources, and extract-to-temp + run-elevated it at runtime.While this would bloat my DLLs (depending on how small I can get the .exe), I feel like it's also a more fragile + convoluted solution than 1. above (with file extraction and all; prob. best to sign the utility exe too to keep HIPS / antivirus from acting funny etc?).
Alter my DLLs so that they're actually .exes in disguise which happen to export the host-expected DLL entry points, so that I can call them directly (elevated).I know there are some major caveats here (like conflicts between the C runtime being included in DLL or non-DLL mode, Visual Studio prob. not approving of these shenanigans, etc.), and honestly I already feel I need a shower just after talking about this one. So while theoretically maybe feasible, it is my last resort.
Does anyone have any advise on my uncertainties above? Or maybe an even better suggestion?
EDIT
I've already managed to get option 1. working, and while it works seamlessly there's one drawback I spotted: the UAC prompt (understandably) asks whether the user wants to run RunDLL32.exe, signed by Microsoft. This might confuse/scare people no end (that is: if they even read these prompts...). I'd rather have the UAC prompt asking about MyPluginSetup.exe signed by MyCompany, so now I'm more inclined to go with option 2. instead.

Trying to hook to MessageBeep system API

I've been asked by a client to solve the following pesky issue. They have a custom software that has a tendency of displaying message boxes "left and right" without any apparent reason. For instance, the software itself is an accounting program, and when they take a customer's payment, the message box may be displayed about 3 or 4 times in a row. Each message box plays Windows default sound. Unfortunately the way this software was programmed, the type of sounds it plays is completely wrong. For instance, it may display a warning message box and play the warning system sound when the message itself is just an information. All this is quite annoying for the staff who uses the software.
I tried to contact the vendor who distributes the software, but I hit a deadend with them. So now I am looking for ways to mitigate this issue.
My easiest solution was to suggest to mute the speakers, but unfortunately, they require sound to be present to be able to hear incoming emails, and most importantly, be able to play voice mail from them later. So my solution was to somehow mute message box sounds just for a single process.
From my experience, I know that there're two APIs that may be producing these sounds: MessageBeep and an older Beep.
I also found this article that explains how to use AppInit_DLLs to hook to system APIs. It works great, except that both of the APIs that I need to hook to come from User32.dll and not from kernel32.dll like the author suggests.
There's also this post in the questions section that kinda gives approximate steps to hooking to an API from User32.dll, but when I tried to implement them, there's not enough information (for my knowledge to do it.)
So my questions is, does anyone know how to hook to an API in the User32.dll module?
EDIT: PS. Forgot to mention. This software is installed on Windows 7 Professional, with UAC disabled -- because it is not compatible with UAC :)
As an alternative you can patch you application. Find calls to MessageBeep and overwrite them with nop.
This is the hard way of doing it: if your app is supposed to be running as Administrator on a pre-Vista Windows, you could get the address of the API via ::GetProcAddress(), give yourself privileges to write to its memory page, and overwrite the beginning of the API's code with a "jmp" assembly instruction jumping into the address of your override function. Make sure your overwrite function takes the same arguments and is declared as __cdecl.
Expanded answer follows.
The "standard" technique for API hooking involves the following steps:
1: Inject your DLL into the target process
This is usually accomplished by first allocating memory in the target process for a string containing the name/path of your DLL (e.g. "MyHook.dll"), and then creating a remote thread in the target process whose entry point is kernel32::LoadLibraryA() passing the name of your DLL as argument. This page has an implementation of this technique. You'll have to wrestle a bit with privileges, but it's guaranteed to work 100% on Windows XP and earlier OSes. I'm not sure about Vista and post-Vista, Address Space Layout Randomization might make this tricky.
2. Hook the API
Once your DLL is loaded into the target process, its DllMain() will be executed automatically, giving you a chance to run anything you want in the target process. From within your DllMain, use ::LoadLibraryA() to get the HMODULE of the library containing the API you want to hook (e.g. "user32.dll") and pass it to ::GetProcAddress() together with the name of the API you want to hook (e.g. "MessageBeep") to get the address of the API itself. Eventaully give yourself privileges to write to that address' page, and overwrite the beginning of the API with a jmp instruction jumping into your detour (i.e. into your "version" of the API to hook). Note that your detour needs to have the same signature and calling convention (usually _cdecl) as the API you want to hook, or else monsters will be awakened.
As described here, this technique is somewhat destructive: you can't call back into the original API from the detour, as the original API has been modified to jump into yours and you'll end up with a very tight and nice infinite loop. There are many different techniques that would allow you to preserve and/or call back into the original API, one of which is hooking the ...A() versions of the API and then calling into the ...W() versions (most if not all of the ...A() Windows API's convert ASCII strings into UNICODE strings and end up calling into their ...W() counterparts).
No need to spend time on a custom program to do this.
You can mute a particular application when it's running, and that setting will be remembered the next time you open the application. See https://superuser.com/questions/37281/how-to-disable-sound-of-certain-applications.
There's also the Windows Sound Sentry that will turn off most system sounds, although I'm not aware of any per-application settings for Sound Sentry.
You can use Deviare API hook and solve the hook in a couple of C# lines. Or you can use EasyHook that is a bit more difficult and less stable.

Determining what memory/values a remote application accesses/changes?

Lets take an example here which is known everywhere in the IT world:
We have a game, for example solitaire, and someone makes and releases a trainer for it that your moves are always '0'.
How do I programatically determine which adresses and what values that "hack" changes?
What way would be the best, if this is possible?
From within the game [injecting/loading my own dll?]
By intercepting traffic between the hack and target process with my own process?
I ask this question because of 2 things:
Protect an application from being "hacked" (at least by the script kiddies)
Reverse engineer a trainer (so you don't have to reinvent the wheel / avoid NIH syndrome)
You can't. Some broken attempts may be setting two addresses and then comparing them (they will find the other address though). Or they can simply remove your compare call.
They can alter any protection function that you use to "programatically determine" to always return false results. They can do anything to your executable, so there is no way.
Unless you hook the kernel functions that open your process to modify the memory. But that is also breakable and if I am not wrong you need to get your "protection kernel driver" digitally signed now.
There is another way in which you load a DLL in every running and newly spawned processes (which will probably alert antiviruses about your program being a virus), with that DLL you hook OpenProcess (and if there is another alternative to it, that too) functions in each process and check if its targeted at your program, and prevent it if so. Search about function hooking. I believe there was something called "MS Detour" or something for it.
And still, the game will not even be close to safe.
To sum up, no way is good to protect your game locally. If you are storing scores or something you should create a server program and client should report every move to server.
Even then, they can create a bot to automatically respond to server. Then the best you can do is somehow verify it is a human that is playing. (maybe captcha or comparing the solving speed with human avarage?)

Is MsiOpenProduct the correct way to read properties from an installed product?

Given an MSI product code I want to get the upgrade code (among other properties) from an already installed product. I have tried this by calling the MsiOpenProduct method, followed by MsiGetProductProperty(). An (abbreviated) example looks like this:
MSIHANDLE handle = NULL;
MsiOpenProduct(strProductCode,&handle);
CString strUpgradeCode;
MsiGetProductProperty(handle,_T("UpgradeCode"), strUpgradeCode.GetBuffer(GUID_LENGTH), &dwSize);
strUpgradeCode.ReleaseBuffer();
MsiCloseHandle(handle);
This gets me the desired value, and judging from the MSDN documentation this seems like a valid way to do this:
The MsiOpenProduct function opens a
product for use with the functions
that access the product database. The
MsiCloseHandle function must be called
with the handle when the handle is no
longer needed.
However the call to MsiOpenProduct() pops up the "Windows installer is preparing the installation..." dialog. The call to MsiCloseHandle() makes it disappear again.
This left me wondering:
What does the call to MsiOpenProduct() do under the hood? I do not want to trigger any actions, I just want to read properties.
I don't mind the dialog popping up, as this is only for unit test code as long as this has no side effects. And as there are many unit tests that do this, it must still work when opening and closing handles in rapid succession.
Although I stumbled over the MsiGetProductInfo method, there seems to be no way to get the upgrade code. Am I right?
Is MsiOpenProduct the correct way to read properties like the upgrade code?
MsiOpenProduct should be fine So long as you don't run any sequences or actions, it won't do anything. If you want to silence the dialog, you can with careful use of either MsiSetInternalUI() or MsiSetExternalUI().
Another approach you can take, as long as the ProductCode and UpgradeCode are safely static (i.e. as long as they aren't changed by transforms), is to locate the database using MsiGetProductInfo() and call MsiOpenDatabase() on that. The difference is that MsiOpenProduct() (or similarly MsiOpenPackage) applies the transforms that were used at installation time and prepares a session, whereas MsiOpenDatabase() does neither.
There is a comprehensive answer with information on how to get the UpgradeCode using Powershell or VBScript and WMI here: How can I find the Upgrade Code for an installed MSI file?
Below is a quick, basic example using VBScript / COM automation (MSI API, not WMI) and the approach discussed by OP (using the OpenProduct method - the COM equivalent to the Win32 installer function).
As discussed in my comment above, I will just add this little VBScript to do the same as OP does in C++. Note that Windows Installer can be accessed via WMI (Win32_Product object), COM automation and Win32 C++ installer functions.
For some reason the UpgradeCode for a package appears to not be available directly from the COM API or the Win32 API. Very strange indeed, especially since it is an input parameter to functions like Installer.RelatedProducts - it is not clear in the documentation that the actual call should be RelatedProducts(UpgradeCode), but looking in the msi.IDL you see: StringList* RelatedProducts([in] BSTR UpgradeCode);
The WMI option works, but so does this OpenProduct call demonstrated below (which is significantly faster and appears safe - WMI is completely read-only as far as I know though - but heaven knows what they are doing "under the hood". Are they spinning up a session object? Or are they reading from a WMI database? WMI does "feels" safer somehow).
The beauty of the below method is that it will apply all transforms that were applied to the product in question at installation time. If you want to write to disk instead of showing message boxes and can't be bothered looking up the docs, here is a similar VBScript that writes package info to a desktop text file: How can I find the product GUID of an installed MSI setup? - quite a bit down the page, just copy a couple of lines and you are message box free).
Note! The script below will create one log file per opened MSI if automatic logging is enabled on the system. As it stands the script will only open one MSI before it exists though (the Exit For construct).
On Error Resume Next ' This "tersified" script has no error handling
Const msiUILevelNone = 2
Set installer = CreateObject("WindowsInstaller.Installer")
Set products = installer.ProductsEx("", "", 7)
installer.UILevel = msiUILevelNone ' Suppress GUI (MSI progress dialog)
'Iterate over all MSI packages on the box
For Each product In products
' productcode = product.ProductCode
' name = product.InstallProperty("ProductName")
' version = product.InstallProperty("VersionString")
' pkgcode = product.InstallProperty("PackageCode")
Set session = installer.OpenProduct(product.ProductCode)
upgradecode = session.ProductProperty("UpgradeCode")
MsgBox upgradecode
Set session = Nothing ' Important, close the session (doesn't work in Javascript btw)
Exit For ' End after one iteration (so you don't get a million message boxes)
' Alternatively something like: If i > 4 Then Exit For
Next
Set installer = Nothing
MsgBox "Finished"
I have tried to look in the C++ Win32 installer functions for any other way to retrieve the UpgradeCode, but I can't see anything obvious. The session approach should work in C++ as well, but I am a little apprehensive about the release of handles and resources. I am not properly potty-trained with C++, but know more than enough to be dangerous. Fire In The Hole. Etc...
I wonder if the OP retrieved all packages on the box, or just a single one. I wonder if the timing issues and concurrent session object problems seen with Javascript would strike in C++ as well? I will give it a go I think - someday.
For the information you want, it sounds like you can just call ::MsiGetProductInfo(). ::MsiOpenDatabase() is a very slow operation while ::MsiGetProductInfo() is (IIRC) more on par with registry look ups.