Contents

Foreword

Most software developers share the same pattern in their professional career of having to deal with projects of similar nature, while few developers manage to jump from one project to a completely different one.

Personally for me, I found one particular area that has always been taking great deal of my time from one project to another, and that’s coding around retrieving and changing information about the system/OS, the current process, threads, various hardware and software configuration of the system, security context, etc... I do hope this all sounds very familiar to many developers.

Not only has one to spend some time trying to figure out how to access the same information required, depending on which development platform is being used, but also this knowledge is very hard to interpolate from one platform to another. For example, VC++, VB6, C#, Delphi, Office – all so different in every way, your code from one may seem totally unusable in the other.

Then, the complexity kicks in. If we can pull just about any trick in C++ in quite a natural way, doing the same things in more restrictive environments is either impossible, or breaks the integrity of the system, like using unmanaged code in .NET, or lots of external procedure imports for VB6, etc.

Out of systematic practice in various development environments came the idea to summarise all my knowledge in this area and offer software developers a simple and unified way in which all such information can be accessed easily, in the same way in any development environment, and with very minimum effort.

This whole article is an introduction to the initiative of writing a library that would allow easy access to the most frequently used information in the system, client’s process, and the program's environment.

It is a very recently started project (July 2008). I am trying to organize all additional information about this project as well as the development efforts for it on this website.

Introduction

There are four ways in which an application can retrieve information from the system:

Standard Windows API

Undocumented Windows API

Direct access to the system via Windows Registry + File system

WMI (Windows Management Interface)

When it comes to choosing which method is best to use, our choice depends mostly on the following criteria (given in the order in which the average developer looks at these things):

Complexity of implementation

Reliability

Speed of execution

Resource consumption

The Professional System Library (ProSysLib) is a project that offers unification in accessing information about process/system/environment where the developer would no longer have to make a tough choice of looking at these criteria, trying to decide which one is most important or which can be sacrificed.

ProSysLib presents all the information using the concept of a root namespace, very much similar to that in .NET, where System is the root namespace for everything. Again, much like it, ProSysLib has its own System root namespace that defines the entry point to all the sub-namespaces and functionality of the library.

The picture in the beginning of this article shows the top hierarchy of namespaces below System. These define the basis for further classification of all the information that can be accessed.

Technology Highlights

The ProSysLib DLL is a Unicode COM in-process server that uses the Neutral memory model. It is thread-safe, and implements automation interfaces only. The protocol (type library) declarations of the 32-bit and 64-bit versions of the component are identical, thus allowing transparent integration with development tools that can mix 32-bit and 64-bit modes, while using the same type library (signature) of the component. ProSysLib is also immune to the DLL Hell problem (read the ProSysLib SDK for details).

Implementation is done entirely in VC++ 2008, using only COM, ATL, STL, and the Windows API.

The entire ProSysLib framework is based on Just-On-Time Activation, which means that each and every namespace and object is instantiated and initialized only when used by the client application for the first time, and until then, ProSysLib is completely weightless resource-wise.

At the moment of publishing this article, only a few objects and namespaces of the library were introduced. As for the rest of the namespaces, properties, and methods, if an application tries to use them, the library will throw a COM exception "NOT IMPLEMENTED", to tell you that you are trying to use something in the library that has been declared but not yet implemented.

Using the Code

Since the library concept is built upon a root namespace, it is the only interface that needs to be created by the client application to have access to everything else, much like the System namespace in .NET. In fact, the fool-proof implementation of the library won’t let you create any other interface of the library even if you try.

Declaring and instantiating a variable in different development environments can look different from each other, while using it will look pretty much the same. In this article, we simplify all our code examples for C# clients only. Any developer should be able to work it out how this would look in his environment of choice.

Now, using this variable, we can access anything we want underneath the root namespace.

While ProSysLib is targeted to implement access to many kinds of information, the project started only recently, and there are not that many features implemented so far. However, I did not want to draw abstractions with finger in the air, one can figure them out by looking at the ProSysLib Documentation, so all the examples provided here below are real ones, i.e., fully functional already.

So, let’s consider a few examples of what we can do with ProSysLib as of today, which is less than one month from the beginning of the project.

Privileges

Many applications need to know and control privileges available to a process. For instance, Debug privilege can be important when accessing some advanced information in the system that’s otherwise unavailable. ProSysLib provides a collection of all the available privileges under the namespace PSLSystem.Security.Privileges. If one needs to enable Debug privilege in a process, the code would be as shown here:

sys.Security.Privileges.Find("SeDebugPrivilege").Enabled = true;

I.e., we access the collection of privileges, locate the privilege of interest, and then enable it. We would normally need to verify that the Find method successfully located the privilege in the list, but since the Debug privilege is always available, we can simplify it here.

Process Enumeration

One of the very popular subjects that can be found on CodeProject is about enumerating all the available processes in the system, or finding a particular process, or how to kill a process by name or ID, etc. ProSysLib enumerates all processes running in the system, under the namespace PSLSystem.Software.Processes. This collection is very flexible to allow any kind of operation one needs to do with processes in the system.

Attached to this article is a simple C# application that shows just one example of how ProSysLib can be used. The example enumerates either all the processes or the ones that were launched under the current user account. It displays just some of the available information about each process, and allows killing any process with the press of a button.

Here is just a small code snippet from the example, where we populate a list view object with information about processes:

The demo application binary is provided both in 32-bit and 64-bit versions.

One of the quite interesting things about ProSysLib that you might notice from the demo application is that it doesn't require anything to register on your PC in order to run successfully. If somebody assumes that this is COM Isolation for .NET, he would be wrong. This is implementation of Stealth Deployment for COM, which I came up with in my long practice of distributing COM projects. A full description of the idea is given in the ProSysLib SDK, chapter Deployment.

Access Rights/Mask of a Named Object

Another typical task for many applications is to find out what access rights the current process has to a particular object in the system. Usually, it is either a file or folder that we want to know what we can do with. I know for a fact that getting this information isn't that straightforward in C++, and can be even more cumbersome in other environments.

The namespace PSLSystem.Security offers the function GetNamedObjectAccess that allows getting Access Mask for any Named Object in the system (file, folder, printer, service, reg-key, network share) in just one line of code:

Process Affinity

Just one other small feature that I had a chance to implement in the library by now is how to control Process Affinity. The namespace PSLSystem.Process contains all the properties about the current process (or will, eventually). One of them is AffinityMask, which can be changed very easily. For instance, if you have a Dual-Core system, and would like to execute your process on the second core only, your code for that would be:

sys.Process.AffinityMask = 2;
// 2 in binary corresponds to the second core;

In the same way, for each process in the collection PSLSystem.Software.Processes, we have an AffinityMask to get/set the Affinity Mask for any other process in the system like the TaskManager can do. I didn't use this in the demo, because I can't show all at once anyway.

WMI

Windows Management Interface is one of those hereditary technologies that sometimes could have been better dead than alive. In the case of WMI, we are talking about a number of problems caused by, though very necessary, yet poorly thought out technology. This was one more reason for writing ProSysLib, to be an alternative to getting information from the system in a much easier and faster way.

Below is a list of perhaps the main problems found in WMI:

It is based on obsolete DCOM, which is very slow on its own, not to mention when we try to use it over the network. The Microsoft layer for WMI in .NET 2.0 - 3.5 looks more like a joke, because they are trying to merge the good and the bad into one;

WMI is very much resource-consuming;

WMI equipment vendors often make mistakes/bugs in their WMI providers, and using which results in application crash;

WMI is supported only by a minority of equipment vendors, and as a result, lots of hardware information is not available via WMI;

WMI usage can be quite complex for low-level languages like C++.

Unfortunately, regardless of all the flaws that WMI carries with it, some details about the system just seem impossible to acquire in any other way, or require too much effort. My personal suggestion - only use WMI when you really have to.

For those situations, ProSysLib offers a much simplified access to WMI functionality via the namespace PSLSystem.Tools.WMI. It has a few methods to get information from WMI in the simplest possible way.

Let’s consider an example of getting the property Caption from the WMI class Win32_OperatingSystem, which is the title of the current operational system.

In this example, we passed null for the namespace because the class Win32_OperatingSystem typically resides in the default namespace of "root\\cimv2" (also the property DefaultNamespace of the interface).

The WMI namespace offers a few methods to get information from it in the simplest possible way. And, while using it simplifies WMI coding under .NET by twice at best, for C++ developers, this simplifies WMI usage by 90%.

If, for instance, you wanted to get information for the properties "BuildNumber", "CountryCode", and "Locale" from the same class, you could use the following method:

This method returns an object PSLTable that simplifies access to the data using an array type of addressing as {row, column}. Plus, it has what a recordset object has, the ability to always get the list of columns, using:

This is particularly useful when you issue a WQL query using SELECT *, i.e., selecting all columns, so you don't know which column is where.

Error and Exception Handling

ProSysLib lives up to its name in the area of handling errors and exceptions as well. Any error/exception is handled gracefully, and exposed to the client via COM Exceptions, providing both numerical and verbal interpretation of any problem in functionality.

COM Exceptions are easy to handle, and supported automatically in any environment. For instance, in .NET, COM exceptions are handled by the object System.Runtime.InteropServices.COMException, while in C++, they are handled via the type _com_error that's generated by the type library import mechanism.

The ProSysLib root namespace contains a method DecodeException that allows easy interpretation of numerical COM errors as an enumerated type. Let's consider an example of exception handling in which we try to access a collection object with an index beyond what's reasonable, expecting an Index-Out-Of-Range type of exception:

Summary

These were just a few examples of what has been already implemented within the ProSysLib architecture, and it has much more currently in progress. If you look at the tree of namespaces and the ProSysLib SDK Documentation, you can find how far this project is meant to stretch. This article, again, just scratches the surface of the project. And, I do hope it finds developers who would like to join in to work on this project, providing their unique C++ experience to make their knowledge available to developers in all software platforms.

As I continue development of the project, I will be publishing more articles here with focus on particular features as they become available, without considering the whole thing again.

Points of Interest

I always enjoy writing professional COM servers that make intense use of COM collections, internal COM instantiations, automated event marshallers, and many other neat tricks with COM, coverage for which in the Internet is typically poor. There were, in fact, plenty that I learnt with this project.

For example, a great deal of code for the project is based on either undocumented Windows API or poorly documented API, learning of which is a good challenge. It was fun digging out the truth about 64-bit implementations of the API function ZwQuerySystemInformation, which required code debugging to see what the reality was. All information in the Internet about ZwQuerySystemInformation classes is for 32-bit only, but seems like nobody knows that, even Microsoft published misleading information about it in MSDN :)

Anyways, I am planning to publish these tricks and many others in the implementation of ProSysLib when I get around it, for I believe, this is all a separate subject, and for now, just trying to keep it simple for this article.

History

July 29, 2008: First draft of the article

August 1, 2008: Updated the downloads with the latest version of the ProSysLib SDK that now installs the complete source code of the project itself

August 5, 2008. Changed the project's website from prosyslib.com into prosyslib.org to make it easier for first-time readers to see the free open-source nature of the project. Also, updated links in this article.

August 20, 2008. Many small updates in the article, like rephrasing, adding table of contents, simplifying the download list, etc. Also, I find it necessary to add that a new article in the sequence is available: ProSysLib: Dissecting the Process.

Comments and Discussions

Like I said before. First, about having single instance of PSLSystem, that's only a suggestion, use as many as you like, actually. And I did mention in many places that the component is fully thread-safe, so if you go for single instance, it will work perfectly. It's all your choice!

Vitaly, I am ashamed and apologize for not fully reading the description. I usually do RTFM, but I just wanted to jump in and try to help summarize what the other guy was saying.

Anyways, if you don't mind me asking, i saw you used STL in your project, and ATL, and started only a few weeks ago. Thats quite impressive! I haven't worked much with WMI in C++, but I have heard it's quite a bear. How has development been treating you? Also, do you have any plans to allow for any type of extensible api?

I've had my plate full every hour for the last 3 weeks to get as much accomplished in this project, I can't believe it myself... ))

WMI, yes, that's a good challenge for C++ developers, and hopefully i'm fixing it for 90% of all WMI usage. What i mean is, in 90% of cases WMI is used only to retrieve information. If you are into the other 10% of digging into things like event subscription or writing providers - you're on your own, this is outside the purpose of ProSysLib project.

Right now, from the top of my head, extensible API doesn't ring any bells, what's that? Anyways, the project is open-source, and it's very core idea is to absorb efforts and ideas from all developers who wants to contribute, so i hope this answers your question... ))

Professional System Library on www.prosyslib.com, making it simple for software developers.

Sorry, really hope you don't get offended, and you've really done a good work here. NOTE: I'm not complaining, I'm just giving suggestion

I'm not that familiar with COM programming, but I'm familiar with .Net. Basically it's what "evolved" had mentioned. In .Net we can declare a static class and a static constructor which will be initialized when the class is first access. By then all the function can be called freely without further call to the constructor.

The reason I prefer this is that I might need to call those functions from 2 different library. For example, I had a main.exe as my main executable which access lib.dll as my common library which is used in all my project. If need to access say WMI in your ProSysLib in main.exe and lib.dll, then I need 2 instance in each part. But if ProSysLib had a static class on WMI or static functions, then both main.exe and lib.dll is accessing the same instance. At least this work in .Net.

Another scenario might be parent-child setup. If the child need to access the ProSysLib, I need to pass the instance from the parent to the child, either when it need it or when I initialize the child.

As you have mention, I could have put the instance in global variable. That's more or less like wrapping it in a static class. Why can't it be static to start with.

I understand now what you meant there. However, this library is COM, and the same static logic doesn't work there, not for the root namespace, which you have to create because it is COM, this is the core of the COM technology, and cannot be avoided.

Please note, this library doesn't target just at .NET platform, it covers all existing development platforms. After all, having to initiate the root namespace is not really a problem.

Professional System Library on www.prosyslib.com, making it simple for software developers.

For me I don't really like COM as you need to register (regsvr32) it before you can use it. Is there any reason why you wouldn't implement it as ordinary dll, where it it can be call via P/Invoke from .Net, which also works well with C++. It also simplified installation as it can be xcopied over. COM just seems to complicate things for me.

Did you try to run any of the binary examples? If you did, you'd see that they worked just fine without you registering anything on the PC.

So no, you do not need to register anything when distributing your application with ProSysLib. I did refer to this in the article as Stealth Deployment, which is also well documented in ProSysLib SDK, and this is what I used for the binary examples here.

I do not understand what you mean by ordinary DLL to call it via Invoke, etc. This is not a .NET project, this is a COM C++ project.

Professional System Library on www.prosyslib.com, making it simple for software developers.