Enumerate Upgrade Codes of installed products? - c++

I'd like to get list of all Upgrade codes of all installed products on Windows box. The question is: is there a dedicated MSI function to address this request?
There is MsiEnumProducts() that enumerates all installed products and MsiEnumRelatedProducts() to enumerate all products for the given Upgrade code. But I can't find a function to get all Upgrade codes in the system.
The workaround I can imagine is use MsiEnumProducts() to get list of all installed products, open each with MsiOpenProduct() function and read "UpgradeCode" property with MsiGetProductProperty(). But this should be very slow due to multiple MsiOpenProduct() calls.

I believe MsiEnumProducts loop with MsiOpenProduct and then MsiGetProductProperty is the correct official sequence. If you really need faster and are willing to bypass the API's you could read the registry directly at HKCR\Installer\UpgradeCodes. You'll have to reverse the Darwin Descriptors though. This isn't technically supported but the reality is these keys have been there for 16 years and MSFT has been doing ZERO development on The Windows Installer. Ok, maybe they updated the version number and removed ARM support in Windows 10 LOL.
FWIW, I like to use C# not C++ but the concept is the same. The following snippet ran on my developer machine in about 2 seconds.
using System;
using Microsoft.Deployment.WindowsInstaller;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
foreach (var productInstallation in ProductInstallation.AllProducts)
{
using(var database = new Database(productInstallation.LocalPackage, DatabaseOpenMode.ReadOnly))
{
Console.WriteLine(database.ExecutePropertyQuery("UpgradeCode"));
}
}
}
}
}
According to the DTF documentation, ProductInstallation.AllProducts uses MsiEnumProducts. The Database class constructor is using MsiOpenDatabase and ExecutePropertyQuery is a higher level call that basically abstracts doing a SELECT Value from Property WHERE Property = '%s'. So it'll be calling APIs to create, execute and fetch results from views. All these classes implement IDisposable to call the correct APIs to free resources also.
Ya... that's why I love managed code. :)

Related

C++ generate new EC_KEY using OpenSSL 1.1.1n

I'm very new to this OpenSSL stuff and trying to learn my way through it. I want to generate an ec key but its keep failing to generate. I'm currently using OpenSSL 1.1.1n and here's a snippet based on understaning of EC_Key through documentation and from other people's example online:
EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp521r1);
if (!key)
{
ERROR
}
EC_GROUP* ecgroup = EC_GROUP_new_by_curve_name(NID_secp521r1);
if (ecgroup)
{
printf("ECGROUP IS NOT NULL!\n");
if (EC_KEY_set_group(key, ecgroup) != 1)
{
ERROR
}
}
if (EC_KEY_generate_key(key) != 1) //<-- fails at this function
{
ERROR
}
Maybe this piece of code is from an older version of OpenSSL but I don't see that function being mentioned in a change log. Any help would be really appreciated! Thanks in advance!
Edit:
Thanks for Jakob's answer I was able to get some more information about the failure by using ERR_get_error() function. The error I see now is
error:2406C06E:random number generator:RAND_DRBG_instantiate:error retrieving entropy
The manual states:
EC_KEY_generate_key() generates a new public and private key for the
supplied eckey object. eckey must have an EC_GROUP object associated
with it before calling this function. [...]
Did you associate an EC_GROUP with the key before calling the function? There is a function called EC_KEY_set_group() which can be used to add a group object. Such an object can be created with the EC_GROUP_new().
By the way is there a reason, why you are still using OpenSSL 1.1.1. I would recommend using the latest version of the library OpenSSL 3.0. Even if you only want to learn stuff, it is probably more useful, if you immediately learn the newer version.
Edit
I do not know, what is behind your ERROR macro, but it might be a good idea to learn the OpenSSL error handling system. There are functions like ERR_print_errors() that maybe could have given you a hint about what was going wrong.
Answering myself in case someone is having this same issue.
I was able to get around this problem by building OpenSSl with no-shared flag. I'm not sure how that is affecting the lib in getting an entropy but that's the parameter that made the EC_KEY_generate_key() work.
Here's my working configuration command:
perl Configure no-shared VC-WIN32

Accessing Sqlite Database from Windows Forms Application in C++

I am new to C++ (was previously into Java) and I am trying to find my way around it for the past few days. I am having a Sqlite DB in my local Machine which I am trying to access in order to display the results of a query on a Windows Application Form using DataGridView.
I was able to locate a good place to start here but later discovered that this was more concentrated towards SQL server and not SQLite and the code failed when I tried to replace this part of code
String^ connectionString =
"Integrated Security=SSPI;Persist Security Info=False;" +
"Initial Catalog=Northwind;Data Source=localhost";
with this
String^ connectionString = "Data Source=C:\\data\\test.db"
to point to my local Sqlite DB (test.db).
Upon more digging I found that I was able to find C# examples for linking SQLite DB to Windows Form Application here. Next I tried to convert the C# code provided into a C++ one but failed.
I have been looking all around for simple C++ examples which would help me understand how to link a Sqlite DB to a Windows Form Application but am not able to do so yet.
I would appreciate it greatly if anyone could point me to one such example.
To access SQLite DB from managed code use System.Data.SQLite library. It's a managed library supported by SQLite Development Team and you can use it with managed C++ also. Here is the sample:
using namespace System::Data::SQLite;
using namespace System::Text;
void Test()
{
SQLiteConnection ^db = gcnew SQLiteConnection();
try
{
db->ConnectionString = "Data Source=C:\\data\\test.db";
db->Open();
// Do the job here
db->Close();
}
finally
{
delete (IDisposable^)db;
}
}

How to get list of files opened by a process in Windows? [duplicate]

How do I get the list of open file handles by process id in C#?
I'm interested in digging down and getting the file names as well.
Looking for the programmatic equivalent of what process explorer does.
Most likely this will require interop.
Considering adding a bounty on this, the implementation is nasty complicated.
Ouch this is going to be hard to do from managed code.
There is a sample on codeproject
Most of the stuff can be done in interop, but you need a driver to get the filename cause it lives in the kernel's address space. Process Explorer embeds the driver in its resources. Getting this all hooked up from C# and supporting 64bit as well as 32, is going to be a major headache.
You can also run the command line app, Handle, by Mark Rusinovich, and parse the output.
Have a look at this file :
http://vmccontroller.codeplex.com/SourceControl/changeset/view/47386#195318
And use:
DetectOpenFiles.GetOpenFilesEnumerator(processID);
Demo:
using System;
using System.Diagnostics;
namespace OpenFiles
{
class Program
{
static void Main(string[] args)
{
using (var openFiles = VmcController.Services.DetectOpenFiles.GetOpenFilesEnumerator(Process.GetCurrentProcess().Id))
{
while (openFiles.MoveNext())
{
Console.WriteLine(openFiles.Current);
}
}
Console.WriteLine();
Console.ReadKey();
}
}
}
It has dependency over assembly System.EnterpriseServices
You can P/INVOKE into the NtQuerySystemInformation function to query for all handles and then go from there. This Google groups discussion has details.
Take a look at wj32's Process Hacker version 1, which can do what you asked, and more.
Handle is great program, and the link to codeproject is good.
#Brian
The reason for the code is that handle.exe is NOT redistributable. Nor do they release their source.
It looks as if .Net will not easily do this since it appears that an embedded device drive is requried to access the information. This cannot be done in .net without an unmanged DLL. It's relatviely deep kernel code when compared to typical .net coding. I'm surprised that WMI does not expose this.
Perhaps using command line tool:
OpenedFilesView v1.50 - View opened/locked files in your system (sharing violation issues)
http://www.nirsoft.net/utils/opened_files_view.html

Can I use all the functionally I see exposed by the .TLH file?

Background:
I have an existing code that uses functionality provided by Microsoft, to post XML data over HTTP. Specifically, IServerXMLHTTPRequest (included in MSXML3 and up) from msxml4.dll (COM). I am moving to msxml6.dll as msxml4.dll is not supported anymore (superseded by MSXML6). More information about MSXML versions.
Code:
#import "msxml6.dll"
using namespace MSXML2;
…
IServerXMLHTTPRequestPtr spIXMLHTTPRequest = NULL;
hr = spIXMLHTTPRequest.CreateInstance(__uuidof(ServerXMLHTTP40));
Problem:
When building my app with msxml4.dll as well as msxml6.dll the following is included in the msxml4.tlh and msxml6.tlh respectively:
struct __declspec(uuid("88d969c6-f192-11d4-a65f-0040963251e5"))
ServerXMLHTTP40;
// [ default ] interface IServerXMLHTTPRequest2
As I understand, looking at msxml6.tlh, I can use ServerXMLHTTP40 (and not change the code to ServerXMLHTTP60) with msxml6.dll (same for DOMDocument40, FreeThreadedDOMDocument40, XMLSchemaCache40 etc.).
Now, searching the registry in a fresh Windows 7 Ultimate installation, I cannot find the uuid above. As a result, this code fails on this machine:
hr = spIXMLHTTPRequest.CreateInstance(__uuidof(ServerXMLHTTP40));
Questions:
If msxml6 is exposing ServerXMLHTTP40, why is it that I cannot find it in the registry? Can I use ServerXMLHTTP40 when msxml6 is installed (msxml4 is not installed)?
Need additional information? Just let me know. Thank you!
.TLH file (as a product of import from .TLB, which is in turn a compiled version of .IDL file) is a description of interfaces, structures, methods etc. which ones uses to talk through COM to another object. There is no guarantee or promise that the other party implementing these interfaces is installed or otherwise available, or even exists at all.
Yes you have the signatures defined for you convenience. You might need to install runtime that implements the functionality. MSXML 4 might need a separate install regardless of where you obtained the development details from.

C++\IronPython integration example code?

I'm looking for a simple example code for C++\IronPython integration, i.e. embedding python code inside a C++, or better yet, Visual C++ program.
The example code should include: how to share objects between the languages, how to call functions\methods back and forth etc...
Also, an explicit setup procedure would help too. (How to include the Python runtime dll in Visual Studio etc...)
I've found a nice example for C#\IronPython here, but couldn't find C++\IronPython example code.
UPDATE - I've written a more generic example (plus a link to a zip file containing the entire VS2008 project) as entry on my blog here.
Sorry, I am so late to the game, but here is how I have integrated IronPython into a C++/cli app in Visual Studio 2008 - .net 3.5. (actually mixed mode app with C/C++)
I write add-ons for a map making applicaiton written in Assembly. The API is exposed so that C/C++ add-ons can be written. I mix C/C++ with C++/cli. Some of the elements from this example are from the API (such as XPCALL and CmdEnd() - please just ignore them)
///////////////////////////////////////////////////////////////////////
void XPCALL PythonCmd2(int Result, int Result1, int Result2)
{
if(Result==X_OK)
{
try
{
String^ filename = gcnew String(txtFileName);
String^ path = Assembly::GetExecutingAssembly()->Location;
ScriptEngine^ engine = Python::CreateEngine();
ScriptScope^ scope = engine->CreateScope();
ScriptSource^ source = engine->CreateScriptSourceFromFile(String::Concat(Path::GetDirectoryName(path), "\\scripts\\", filename + ".py"));
scope->SetVariable("DrawingList", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingList::typeid));
scope->SetVariable("DrawingElement", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingElement::typeid));
scope->SetVariable("DrawingPath", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingPath::typeid));
scope->SetVariable("Node", DynamicHelpers::GetPythonTypeFromType(AddIn::Node::typeid));
source->Execute(scope);
}
catch(Exception ^e)
{
Console::WriteLine(e->ToString());
CmdEnd();
}
}
else
{
CmdEnd();
}
}
///////////////////////////////////////////////////////////////////////////////
As you can see, I expose to IronPython some objects (DrawingList, DrawingElement, DrawingPath & Node). These objects are C++/cli objects that I created to expose "things" to IronPython.
When the C++/cli source->Execute(scope) line is called, the only python line
to run is the DrawingList.RequestData.
RequestData takes a delegate and a data type.
When the C++/cli code is done, it calls the delegate pointing to the
function "diamond"
In the function diamond it retrieves the requested data with the call to
DrawingList.RequestedValue() The call to DrawingList.AddElement(dp) adds the
new element to the Applications visual Database.
And lastly the call to DrawingList.EndCommand() tells the FastCAD engine to
clean up and end the running of the plugin.
import clr
def diamond(Result1, Result2, Result3):
if(Result1 == 0):
dp = DrawingPath()
dp.drawingStuff.EntityColor = 2
dp.drawingStuff.SecondEntityColor = 2
n = DrawingList.RequestedValue()
dp.Nodes.Add(Node(n.X-50,n.Y+25))
dp.Nodes.Add(Node(n.X-25,n.Y+50))
dp.Nodes.Add(Node(n.X+25,n.Y+50))
dp.Nodes.Add(Node(n.X+50,n.Y+25))
dp.Nodes.Add(Node(n.X,n.Y-40))
DrawingList.AddElement(dp)
DrawingList.EndCommand()
DrawingList.RequestData(diamond, DrawingList.RequestType.PointType)
I hope this is what you were looking for.
If you don't need .NET functionality, you could rely on embedding Python instead of IronPython. See Python's documentation on Embedding Python in Another Application for more info and an example. If you don't mind being dependent on BOOST, you could try out its Python integration library.