
|
Code Corner - Source Code
I often get asked how to do something like persisting a window's placement information, or how to get the top-level window handle for a process. Here I present small projects that demonstrate such thing, but don't really constitute a useful tool or application in and of themselves.
The Kerr.Windows Assembly (17 July 2002) Resource Management in an Unmanaged World (Jan 2002) High-Resolution Timer (4 Nov 2001) Reverse Byte Order (3 Nov 2001)
The Kerr.Windows Assembly (17 July 2002)Download the code: Kerr.Windows.zip In May I talked about some security related classes I had written in C#. I've since improved these classes quite a bit and I've also rewritten them in managed C++. After doing a lot of interoperability work in C#, and even writing an article about it, I've come to the conclusion that C# is just not the best language for this kind of thing (writing low-level system code). As you can mix managed and unmanaged code so well in C++, it turns out that writing it in managed C++ is a much better choice in most cases (except that the generated IL is much more verbose). Anyway, here is my expanded Windows library. The target audience for this assembly is still C# so all my examples below reflect this (you can of course use these classes from managed C++ too). I've improved most of the classes and added a few more. I'll touch on just a few of them. ImpersonateUser This class creates a new logon session for the specified user and sets the thread token to the token for the logon session. This is more commonly referred to as impersonation. It implements IDisposable so you can easily impersonate a user for the duration of an execution block and the class (with the help of the using keyword) will safely stop the impersonation and reset the thread token. If I run the following code on my machine:
I get the following output:
So the ImpersonateUser class is handy if you want to perform some action on behalf of a user. UserName One of the interesting things to notice about the code sample above is that I specified the principal to impersonate using the User Principal Name (UPN) format or the Internet-style name, rather than the traditional SAM or Windows NT form. This is achieved through the UserName class I wrote that easily converts been the two formats. The following code illustrates its use:
Process The Process class replaces my old UserProcess class. The Process class is used in much the same way as the .NET Framework's Process class, with its own ProcessStartInfo class. My ProcesStartInfo class has a few more properties related to security, such as a UserName and Password property as well as other properties that allow you to control how the logon session for the specified principal is created. It also supports the main features of the .NET Framework's Process class like being able to redirect the standard streams. There is quite a lot to this class (which I won't go into here) but the interface is real simple, making this class very useful. There are also a few other classes that you might find useful such as the UserAccount class and the EnablePrivilege class. Feel free to browse through the code. Let me know if you find any bugs or have any comments or suggestions.
Resource Management in an Unmanaged World (Jan 2002)After writing about resource management in the managed world of .NET, I thought it would be useful to talk a little bit about resource management in unmanaged C++ programming. In my Icon Browser article I illustrated why resource management is still vitally important in a world where the garbage collector reigns. When writing code in C++, resource management is just as important (if not more so), but rather more visible and obvious. Despite popular belief, C++ is designed to avoid direct access to resources such as heap-allocated memory. More...
High-Resolution Timer (4 Nov 2001)Download the code: HighResolutionTimer.zip It is sometimes useful to be able to get an idea of the execution time for some code. For that you need a high-resolution timer. The Win32 API includes a handy set of functions for implementing just that. However the .NET framework has no such thing the last time I checked. So I wrote the HighResolutionTimer class in C#. It makes use of the QueryPerformanceFrequency and QueryPerformanceCounter Win32 API functions. Using the class is very straight forward.
Process Window (3 Nov 2001)Download the code: PocessWindow.zip A friend of mine was looking for a way to send a message to the main window of another application. Although I don't think this is a good, general purpose way of performing inter-process communication, if you really want to do this then this is how. The first problem is that a process may have many windows and specifically many top-level windows. If you have a simple situation where you have a process with a single top-level window then it is simple enough. The EnumWindows Win32 API will allow you to enumerate the top-level windows. Then its just a matter of writing a callback that will check each window's process ID and compare it with the process you specify. To illustrate this I wrote a set of C++ functions wrapped in the ProcessWindow namespace. The following code snippet illustrates their use:
To test it, simply replace 1036 with a process ID on your machine. For example you can fire up Notepad and get its process ID from the Windows Task Manager. Again, this is not a very reliable way of performing inter-process communication. For example an application may elect to ignore your WM_CLOSE message. It has every right to do this. Prefer a reliable mechanism such as COM. Some of you may be wondering how Windows can allow this. After all, doesn't this violate security? The thing to remember is that window handles are user-mode objects and as such don't have any security attributes associated with them. The security boundary for the user interface is the WindowStation. This implies that you trust the applications that you allow to run on your machine, or more specifically in your WindowStation. For more information about Windows security please see Brown.
Reverse Byte Order (3 Nov 2001)Download the code: ReverseByteOrder.zip In the last year I've been working as part of the core development team for MobileQ's XMLEdge product. XMLEdge runs on both Windows and Solaris. There are tons of pitfalls when trying to port a product from one platform to another. One of them is byte ordering. Different microprocessors use different endian schemes. For example the Intel microprocessors use little-endian, but most of the microprocessors used with Unix such as the RISC designs use big-endian. If this is sounding a bit confusing let me explain what endian is. Byte order refers to the order in which multi-byte numbers are stored in memory. Little-endian means that the low-order byte is stored at the lowest address in memory. Big-endian means that the high-order byte is stored at the lowest address in memory. The low-order byte is the least significant byte and the high-order byte is the most significant byte. So if you have a 32-bit number (4 bytes) such as 0x11223344, it would be laid out in memory like this:
The problem comes in when you want to share some data between applications running on different platforms using different byte ordering schemes. Basically you need to settle on a single scheme. Once you've made your choice you need to verify that everywhere where shared data is written it is done so using that scheme. For example if your application has its own file format and you chose little-endian then you must ensure that when your application is running on big-endian platforms that it correctly converts numbers before writing them to file. To make your life easier I've written a little function that will convert your numbers (variables) for you.
This is a template function and will handle variables of any size. It makes use of the Standard C++ Library reverse function. Obviously if performance was paramount you would want to specialize ReverseByteOrder for the size of your choice. The following code demonstrates how to use the ReverseByteOrder function.
Enjoy!
ATL 7 (3 Nov 2001)Download the code: ComTest.zip I've been so focused on .NET and C# that I nearly forgot about my favorite compiler, Visual C++! I've just started playing with VC7 and in particular the support for attributes in the C++ compiler. I thought you might find this interesting. Even if you've already had a look at it I think its so great I had to share. To write a simple COM server using VC6 (and ATL), as a minimum you need the following:
With ATL7 you can write a fully functioning COM server in a single file in about 30 lines of code! The following code will generate the exports, the IDL file and the type library. It will also add all the ATL plumbing code like CComObjectRootEx and CComCoClass. But you never have to see all that.
Just to make sure this is still COM you can access the COM server using vanilla COM client code:
At first I hated it as its not C++ but if you think of it as a preprocessor on steroids you can kind of fool yourself into thinking its ok. Now managed C++ is another things altogether. That's totally pillaging the C++ language. :-)
|