Archive for the ‘Programming’ Category

Is GPL software free as in “free love”?

Programming, Software | Posted by AB
Sep 11 2008

I was contemplating the other day how to extend AB Commander to make it able to collaborate with several third-party software products. For example, it would be cool to add some support for the 7z files, which are created by the file compressor 7-Zip . It shouldn’t be too difficult, I thought, because 7-Zip is an open source project, I could examine its source code to see how exactly the 7z files are handled, and maybe reuse some of its code in AB Commander?

Not so fast. 7-Zip is licensed under the GPL license, which strictly forbids the re-use of its source code in the non-GPL’d projects. If I want to use some of the GPL’d code in my own software, I need to convert my whole project to the GPL license and open its whole source code, something I don’t want to do.

After thinking some more, I came up with an idea: I’d make a separate module (a plug-in) that would serve as a bridge between my closed-source project and the GPL’d project. I would make the plug-in GPL’d (because it would need to use some of the GPL’d code), and publish its source code.  My closed source project would link to the plug-in, the plug-in would link to the other GPL’d project’s code, and everyone would be happy: the users of AB Commander would get additional software functionality, the plug-in would be GPL’d, and I would keep the source code of AB Commander closed. Pretty smart, huh?

Again, not so fast. Let’s browse through the GPL FAQ, that explains the issues related to linking between proprietary software and the GPL’d software (or, as they put it, “free” software, where “free” is as in “free speech”). For example, the answer to the question Can I release a non-free program that’s designed to load a GPL-covered plug-in? reads “In order to use the GPL-covered plug-ins, the main program must be released under the GPL or a GPL-compatible free software license…

Huh? I could understand the requirement to GPL any code derived from a GPL’d code, it’s their code and they are free to restrict its re-use anyway they want, but to require two separate modules dynamically linking to each other to be covered by GPL if only one of them is GPL’d? It seems like asking a bit too much. Especially considering that GPL programs have no reservations about linking to proprietary software. Just take any software for Windows, GPL or not, it’s linking to the Microsoft’s proprietory system libraries. Looks like the philosophy of the “free software” is it’s OK to take advantage of the evil and dirty proprietory software, as long as it is not trying to link back to take some advantage of the GPL’d software.

Not fair!

Update: Apparently I am not the only one who thinks so:

http://wpmu.org/wordpress-and-the-gpl/

Another update: Just found the following article with a legal analysis of this very problem, that confirms the “absurdity” of the GPL’s approach to the software plugins:

http://www.law.washington.edu/lct/swp/Law/derivative.html

Vista Elevator 2.0

Programming | Posted by AB
Jul 27 2008

(This post is moved here from the TweakUAC web site, where it was first published on February 27, 2007)

Vista Elevator 2.0 is an updated version of the sample application Vista Elevator that uses a different approach to solving the problem of starting a non-elevated task from an elevated one.

The first version of Vista Elevator used a trick that created a non-elevated process by programming Vista Task Scheduler to start such a process immediately upon its registration. It worked even if the parent process was elevated. However, there were a few problems with that:

  1. It worked well when the process was started by an administrator (that is, by an account with a “split token”). However, if the account was of a standard user (or a Guest account) it did not work as expected: the secondary non-elevated process was created by Task Scheduler to be executed in the administrator’s context, rather than in the original context of the standard user account. The task would launch not when it was registered, but later on, when the administrator logged on to the system.
  2. The target machine could have Task Scheduler disabled. In such a case, this method would fail to start the secondary non-elevated task at all.

To solve these problems, a different approach is necessary. An obvious method of achieving the goal would be to have a separate helper executable that would help the main application launch a non-elevated task, when necessary. Specifically, it would work as follows:

  1. When a user wants to run the application (main.exe), s/he would start by launching the helper executable (helper.exe) first.
  2. The helper process would start non-elevated, but it would launch main.exe, and request it to start elevated (for example, by using the Run Elevated() function).
  3. After the administrator would have approved the launch of main.exe, the user would work with it, as usual. Helper.exe would keep running non-elevated, waiting for a signal from main.exe.
  4. When main.exe would need to start a non-elevated task, it would send a signal to helper.exe, using some sort of inter-process communication, and helper.exe would start a non-elevated process on main.exe’s behalf.

Such an approach would solve both problems described above: it would not require Task Scheduler to be running on the target system, and it would launch the non-elevated task in the context of the original user, whether it is an administrator, a standard user, or a guest.

What is not good about this approach, it requires a separate helper process to be running all the time, wasting the CPU cycles. It also requires to design a communication protocol between the helper and the main executable, which is not a trivial task and is subject to errors. Wouldn’t it be better if we could use some other non-elevated process already running on the target system to launch a non-elevated process on the main.exe’s behalf? Let’s see… There actually is a process that is guaranteed to run all the time while the user is logged on to the system: the Windows shell! And it runs non-elevated, just what we need. Seems like a perfect candidate for our helper process. But how can we ask Windows shell to launch a process on our behalf? Simply calling ShellExecute() or Start Process() would not work, because they would be executed by our process, not by the shell. What we need to do is inject our code into the shell process and make it launch a process on our behalf!

So, the plan of the attack could be as follows:

  1. Our process would find a window that belongs to the shell, and that is guaranteed to be available at any time. A good window for this purpose is Progman, that is responsible for displaying the desktop. We can call the FindWindow() API to obtain a handle to this window.
  2. Our process would call RegisterWindowsMessage() API to register a unique message that we would use to communicate with the shell’s window. It must be unique to avoid possible conflicts and side effects if we would have accidentally picked a message that is already used by the shell for some purpose.
  3. Our elevated process would call SetWindowsHookEx() API to install a global hook, to be invoked when a windows message gets processed by any process running on the system.
  4. Once the hook is installed we would send our unique message to the shell’s window, and that would make our hook procedure to get invoked. (That’s how we inject our code into the shell’s process!)
  5. When the hook procedure is called (in the context of the shell process), it would call ShellExecute() API to launch the non-elevated process that we need. The process would start non-elevated because the shell’s process is not elevated, and our process would inherit the shell’s elevation level.
  6. Finally, we would remove the hook, as we no longer need it and it should no longer be called and waste system resources and CPU cycles.

That’s the plan that is implemented as the RunNonElevated() function in the VistaTools.cxx file that VistaElevator 2.0 uses. To make it work, the design of the VistaElevator application had to be changed significantly:

Firstly, in order to be able to install a global hook, the hook procedure must reside in a DLL. It means that we can no longer have a single executable, we must create a DLL to go with it, as well.

Secondly, in order to be able to pass data from our process to our code injected in the shell’s process, we must set up a special code section to be shared between several processes.

Finally, to be able to use this method with both 32-bit and 64-bit versions of Vista, we must produce two separate builds, one 32-bit and another one 64-bit. The reason for that is that on a 64-bit Vista the shell is a native 64-bit process, and in order to be able to hook it, we need to use 64-bit code, too.

To see the details, use the download links below:

THIS CODE AND INFORMATION IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

VistaElevator2.zip

(the compiled executables only, without the source code)

VistaElevator2-src.zip

(the source code, a Visual Studio 2005 project)

Note: If you want to compile the source code on your own, make sure you have the latest Windows SDK (see msdn.microsoft.com for more information).

Did you know? Our USB Encryption Software can protect any USB flash drive or any other external drive with a password and strong encryption. Try it free for 30 days! Read more…

Quick and dirty way of cleaning the Windows icon cache

Programming, Software | Posted by AB
Jun 17 2008

When developing my software, sometimes I need to try a few changes to the application icon, to see which image looks better. Unfortunately, replacing the icon within the application file does not make Windows recognize the new icon when displaying a shortcut to the file: it displays the old icon no matter what: pressing the F5 key to refresh the desktop, using the shortcut Properties window to force it to use the new icon, nothing has an effect.

The problem, of course, is the icon cache: turns out that Windows keeps each icon in its memory (the icon cache), and when it needs to draw the icon, it uses the copy from the cache rather than retrieving the icon image from the original application file. It makes Windows draw the icons faster, but the negative side effect is the inability of Windows to detect the change of the icon.

The naĂŻve approach to this problem seems to be to delete the icon cache, and thus force Windows to recreate it from scratch. Browsing the user profile folder (such as C:\Users\Username on Vista, or C:\Documents and Settings\Username on XP) reveals the file named suspiciously IconCache.db (located in the subfolder AppData/Local on Vista or Local Settings\Application Data on XP. Note that this file usually has the SYSTEM and HIDDEN attributes, so you may need to change your Windows folder settings to see this file). However, deleting this file causes no effect: Windows keeps displaying the old icon. (Which is not very surprising, because the very fact that Windows did not stop us from deleting this file kind of tells us that the file was not in use by Windows). Even restarting the computer does not help: Windows simply recreates the IconCache.db file with the old icon in it, and keeps displaying the old icon!

Nevertheless, it is possible to delete the icon cache and force Windows to rebuild it. Turns out, Windows recreates the IconCache.db file when the user logs off from his or her account. When the user logs back on, Windows loads the IconCache.db file back intro its memory. This gives us the idea when could be the proper time to delete the IconCache.db file: when the user is logged off. But how to delete the file if the user is not logged on and there is no way to start Windows Explorer or some other file management tool (such as my AB Commander, sorry for the plug, couldn’t resist :-) ) Easy: log in to another user account (such as the administrator’s one) and delete the IconCache.db file that exists in your own profile (you do use separate accounts for the day-to-day work and for the administrative tasks, do you?) Another way is to log off from your account and then connect to your computer from another computer on your LAN (you do have both a desktop and a laptop, do you? And they can talk to each other over the local network, can they? If not, what are you doing reading this blog? Just kidding…) Anyway, from another networked computer navigate to your profile over the network, delete IconCache.db, then go back to the first computer and log back into your account. This time Windows will recreate its cache and start displaying the new icon.

P.S. There is a couple of other methods of forcing Windows to rebuild the icon cache. For example, in Vista, you can change the size of the desktop icons (by right-clicking on the desktop and using the View menu), and then change it back. Or, if you have Windows XP, open the Display Properties window from Control Panel, select the Appearance tab, and click on Effect. Now change the Use large icons option, click OK, Apply to have it take effect. Then repeat the procedure to change the option back to what it was before.

The advantage of these methods is that you don’t need to log off from your account to rebuild the icon cache. The disadvantage is that Windows may mess up the layout of your icons on the desktop, and you may need to rearrange them after the icon cache is updated.

Vista tools

Programming | Posted by AB
Feb 24 2008

(This article was originally published at the TweakUAC site.)

Version 2.1 (Updated 2008-Feb-24)

While porting our applications to Windows Vista, we had to overcome quite a few challenges related to the new security features of Vista (such as the User Account Control). We decided to make public several functions we’ve developed, to make it easier for other developers to solve such problems, too.

The functions we’ve developed are written in C++ (using Microsoft Visual Studio 2005), and packaged in the file VistaTools.cxx. Please note:

THIS CODE AND INFORMATION IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

TERMS OF USE: You are free to use this file in any way you like, for both the commercial and non-commercial purposes, royalty-free, AS LONG AS you agree with the warranty disclaimer above, EXCEPT that you may not remove or modify the warranty statement and the copyright notice the file contains.

The file VistaTools.cxx contains the following functions:

BOOL IsVista();

Use IsVista() to determine whether the current process is running under Windows Vista (or a later version of Windows, whatever it will be).

Return Values:

If the function succeeds, and the current version of Windows is Vista or later, the return value is TRUE.

If the function fails, or if the current version of Windows is older than Vista (that is, if it is Windows XP, Windows 2000, Windows Server 2003, Windows 98, etc.) the return value is FALSE.

BOOL IsWow64();

Use IsWow64() to determine whether the current 32-bit process is running under 64-bit Windows (Vista or XP).

Return Values:

If the function succeeds, and the current version of Windows is x64, the return value is TRUE.

If the function fails, or if the current version of Windows is 32-bit, the return value is FALSE.

NOTE: While this function is not Vista specific (it works under XP as well), we include it here to be able to prevent execution of the 32-bit code under 64-bit Windows, when required.

HRESULT
GetElevationType( __out TOKEN_ELEVATION_TYPE * ptet );

Use GetElevationType() to determine the elevation type of the current process.

Parameters:

ptet – [out] Pointer to a variable that receives the elevation type of the current process.

The possible values are:

TokenElevationTypeDefault – User is not using a “split” token. This value indicates that either UAC is disabled, or the process is started by a standard user (not a member of the Administrators group).

The following two values can be returned only if both the UAC is enabled and the user is a member of the Administrator’s group (that is, the user has a “split” token):

TokenElevationTypeFull – the process is running elevated.

TokenElevationTypeLimited – the process is not running elevated.

Return Values:

If the function succeeds, the return value is S_OK. If the function fails, the return value is E_FAIL. To get extended error information, call GetLastError().

HRESULT
IsElevated( __out_opt BOOL * pbElevated = NULL );

Use IsElevated() to determine whether the current process is elevated or not.

Parameters:

pbElevated – [out] [optional] Pointer to a BOOL variable that, if non-NULL, receives the result.

The possible values are:

TRUE – the current process is elevated. This value indicates that either UAC is enabled, and the process was elevated by the administrator, or that UAC is disabled and the process was started by a user who is a member of the Administrators group.

FALSE – the current process is not elevated (limited). This value indicates that either UAC is enabled, and the process was started normally, without the elevation, or that UAC is disabled and the process was started by a standard user.

Return Values

If the function succeeds, and the current process is elevated, the return value is S_OK. If the function succeeds, and the current process is not elevated, the return value is S_FALSE. If the function fails, the return value is E_FAIL. To get extended error information, call GetLastError().

BOOL
RunElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters = NULL,
__in_opt LPCTSTR pszDirectory = NULL );

Use RunElevated() to start an elevated process. This function calls ShellExecEx() with the verb “runas” to start the elevated process.

Parameters:

hwnd – [in] Window handle to any message boxes that the system might produce while executing this function.

pszPath -[in] Address of a null-terminated string that specifies the name of the executable file that should be used to start the process.

pszParameters – [in] [optional] Address of a null-terminated string that contains the command-line parameters for the process. If NULL, no parameters are passed to the process.

pszDirectory – [in] [optional] Address of a null-terminated string that specifies the name of the working directory. If NULL, the current directory is used as the working directory.

Return Values

If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call GetLastError().

NOTE: This function will start a process elevated no matter which attribute (asInvoker, highestAvailable, or requireAdministrator) is specified in its manifest, and even if there is no such attribute at all.

BOOL
RunNonElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters = NULL,
__in_opt LPCTSTR pszDirectory = NULL );

Use RunNonElevated() to start a non-elevated process. If the current process is not elevated, it calls ShellExecuteEx() to start the new process. If the current process is elevated, it injects itself into the (non-elevated) shell process, and starts a non-elevated process from there.

Parameters:

hwnd – [in] Window handle to any message boxes that the system might produce while executing this function.

pszPath – [in] Address of a null-terminated string that specifies the executable file that should be used to start the process.

pszParameters – [in] [optional] Address of a null-terminated string that contains the command-line parameters for the process. If NULL, no parameters are passed to the process.

pszDirectory – [in] [optional] Address of a null-terminated string that specifies the name of the working directory. If NULL, the current directory is used as the working directory.

Return Values

If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call GetLastError().

NOTE: For this function to work, the application must be marked with the asInvoker or highestAvailable attributes in its manifest. If the executable to be started is marked as requireAdministrator, it will be started elevated!

How to use the file VistaTools.cxx

Make sure you have the latest Windows SDK (see msdn.microsoft.com for more information) or this file may not compile!

This file contains the Win32 stuff only, it can be used with or without other frameworks, such as MFC, ATL, etc.

This is a “combo” file that contains both the declarations (usually placed in the .h files) as well as the definitions (usually placed in the .cpp files) of the functions. To get the declarations only, include it as you would any .h file. To get both the declarations and definitions, define IMPLEMENT_VISTA_TOOLS before including the file. (The latter should be done once and only once per project).

For example, to use this file in a MFC project, create a file MyVistaTools.cpp that contains the following:

#include “StdAfx.h”

#define IMPLEMENT_VISTA_TOOLS
#include “VistaTools.cxx”

This would make MyVistaTools.cpp the implementation file of the VistaTools function for your project. Don’t forget to add MyVistaTools.cpp to your project! You can add VistaTools.cxx to your project, as well, but it should be excluded from the build, because its contents is compiled when it is included in MyVistaTools.cpp file with IMPLEMENT_VISTA_TOOLS defined, as shown above.

In other files of your project, where you need to use the functions declared in VistaTools.cxx, include it without defining IMPLEMENT_VISTA_TOOLS, just as you would include a .h file:

#include “VistaTools.cxx”

To use the function RunNonElevated(), this file must be compiled into a DLL. In such a case, define DLL_EXPORTS when compiling the DLL, and do not define DLL_EXPORTS when compiling the projects linking to the DLL.

If you don’t need to use RunNonElevated(), then this file may be a part of an EXE project. In such a case, define DONTWANT_RunNonElevated and NO_DLL_IMPORTS to make this file compile properly.

For an example of using VistaTools.cxx in a real project, see VistaElevator 2.0.

How do I download the file VistaTools.cxx?

Simply right-click on the link below and choose the Save target as command (or similar) to save it to your hard drive:

Download VistaTools.cxx

If you use this file in your own project, an acknowledgment will be appreciated, although it’s not required.

Enjoy!

Did you know? Our USB Encryption Software can protect any USB flash drive or any other external drive with a password and strong encryption. Try it free for 30 days! Read more…

A handy macro for Visual C++ developers: BuildStartupProject

Productivity, Programming | Posted by AB
Jan 26 2008

I can’t believe I did not know this before: it’s possible to set up Visual Studio to use F7 to build the startup project rather than the selected one!

As a matter of fact, that was the default behavior of the F7 key in Visual Studio 6.0, but then in Visual Studio .NET 2003 (or maybe even in 2002?) Microsoft decided to change it to build the selected project rather than the startup one. This change made the build process somewhat inconvenient: if I happened to work with a file that belonged to a DLL and pressed F7, that would build that particular DLL only, while I wanted to build the whole thing – the executable that links to the DLL. In order to do that, I would need to select the EXE project first, then press the F7 key. I don’t know how many microseconds I’ve wasted doing that.

I could have changed the behavior of the F7 key by binding it to the Build.BuildStartupProject command, but the problem was, Visual Studio did not have such a command! The only choices available were: BuildSelection, BuildSolution, and similar, but there was no command to build the startup project. That’s one more thing I cannot believe, that Microsoft has not added such a command for such a long time: it’s still not present in Visual Studio 2008, the latest version as of this writing.

Today, for some reason I got very annoyed by my inability to use the F7 key the way I wanted, so I decided to search for a solution on the Internet, and (miracle!) I’ve found it. I’ll kick myself for a long time for not trying to find it before.

Anyway, the solution is a simple three-line macro I found in the BorisJ’s blog:

Sub BuildStartupProject()

    Dim sb As SolutionBuild = DTE.Solution.SolutionBuild

    Dim projName As String = sb.StartupProjects(0)

    sb.BuildProject(sb.ActiveConfiguration.Name, projName, False)

End Sub

As soon as I added it to my custom macros list in Visual Studio, and assigned F7 to run that macro, I could build the current startup project no matter what file I was working with.

One problem I had with the macro was that it did not bring the output window to the foreground when starting the build process, so I added a line that does that.

Another problem was that when I wanted to build for a different platform (such as x64), the macro still compiled for Win32. So I fixed it a bit to make it compile for the correct platform.

Here is the resultant macro :

Sub BuildStartupProject()

    DTE.ExecuteCommand("View.Output")

    Dim sb As SolutionBuild = DTE.Solution.SolutionBuild

    Dim projName As String = sb.StartupProjects(0)

    sb.BuildProject(sb.ActiveConfiguration.Name + "|" + _
                    sb.ActiveConfiguration.PlatformName, projName, False)

End Sub

Hope this helps someone. Did I mention I can’t believe I have not found this solution long ago? :-)

Did you know? Our USB Encryption Software can protect any USB flash drive or any other external drive with a password and strong encryption. Try it free for 30 days! Read more…

WinUnit and Structured Exception Handling (SEH)

Programming | Posted by AB
Jan 22 2008

Recently I was working on a native C/C++ library, and I was searching for a good unit testing framework to use with it. I took a look at TUT, CppUnit, and a couple of others, and was trying to decide which one to choose, when a new issue (February 2008) of the MSDN Magazine arrived. Turned out it came just in time because of the little gem it contained: an article by Maria Blees describing WinUnit, a unit testing framework she developed.

I downloaded the code, compiled the WinUnit.exe program from it, gave it a try, and immediately liked what I saw. Most of all I was impressed by how easy it was to get started: all I needed to do was create an empty DLL project, specify WinUnit.exe in its command line for the debugging, and presto, I was ready to add unit tests to my library!

Of course, designing the unit tests themselves was not that easy, but WinUnit made the process painless and even fun (if unit tests can be fun at all :-) ) Let me give a small example: suppose that for some reason you want to have your own version of the strlen() function, let’s call it MyStrLen(). It should accept a pointer to a TCHAR string and return the number of characters it contains:

size_t 
MyStrLen( LPCTSTR psz ) 
{ 
    size_t nLen = 0;           

    if ( psz == NULL ) 
        throw _T("Null pointer!"); 

    while( *psz++ ) 
         nLen++;            

    return nLen; 
}

How would you test this function with WinUnit? Here is how I would do it:

#include <WinUnit.h> 
#include "MyStrLen.h"           

BEGIN_TEST( MyStrLen_ShouldReturnZeroForEmptyString ) 
{ 
    WIN_ASSERT_ZERO( MyStrLen( _T("") ) ); 
} 
END_TEST           

BEGIN_TEST( MyStrLen_ShouldReturnCorrectLengthForNotEmptyStrings ) 
{ 
    WIN_ASSERT_EQUAL( 1, MyStrLen( _T("a") ) ); 
    WIN_ASSERT_EQUAL( 2, MyStrLen( _T("ab") ) ); 
    WIN_ASSERT_EQUAL( 26, MyStrLen( _T("abcdefghijklmnopqrstuvwxyz") ) ); 
} 
END_TEST           

BEGIN_TEST( MyStrLen_ShouldThrowForNullPointer ) 
{ 
    WIN_ASSERT_THROWS( MyStrLen( NULL ), LPCTSTR ); 
} 
END_TEST

Pretty self-explanatory, isn’t it? Each test gets a name, starts with the macro BEGIN_TEST, and ends with the macro END_TEST. The tests call the function being tested and verify the results using various WIN_ASSERT… macros provided by WinUnit. For the more complex tests one can also use the “fixtures”, and the macros that go with them: FIXTURE, SETUP, TEARDOWN, BEGIN_TESTF, and END_TESTF. See the article for the details.

To run the tests, you just press the F5 key in Visual Studio IDE, and WinUnit.exe loads your test DLL, executes all the tests it finds in it, and sends the output directly to the output window of Visual Studio. If a test does not check, you can double click on the “failed” message in the output window and it takes you right to the line that failed the verification, letting you see what’s going on. In short, it works just the way I would expect it to work.

One problem I encountered was when trying to write tests for functions that were using the Structured Exception Handling (SEH) mechanism instead of the C++ exceptions. (Why did I need that? Because the library I’ve been writing contains quite a few of pure C code (not C++), and you cannot use C++ exceptions in the C files). When trying to compile tests for such C files, the compiler complained that it couldn’t mix the SEH and C++ exceptions in the same function. Having looked into the WinUnit.h file, I’ve come up with the following macros that can be used instead of the usual ones:

BEGIN_TEST_SEH( TestName ) 
END_TEST_SEH 
FIXTURE_SEH( FixtureName ) 
SETUP_SEH( FixtureName ) 
TEARDOWN_SEH( FixtureName ) 
BEGIN_TESTF_SEH( TestName, FixtureName ) 
END_TESTF_SEH( FixtureName ) 
WIN_ASSERT_THROWS_SEH( expression, ... )

(I’ve put them in a separate file, WinUnitSEH.h).

Now, if the MyStrLen() function were throwing a SEH exception, for example by calling the RaiseException() function instead of using the throw operator, the last test could be rewritten as follows:

#include <WinUnitSEH.h>          

BEGIN_TEST_SEH( MyStrLen_ShouldThrowForNullPointerSEH ) 
{ 
    WIN_ASSERT_THROWS_SEH( MyStrLen( NULL ) ); 
} 
END_TEST_SEH

Hope this helps someone. Download WinUnitSEH.h

Virtually everything

Productivity, Programming | Posted by AB
Jan 15 2008

Being in the software business, I have to upgrade my main development machine rather often. When switching to a new computer, the most frustrating part of the process is setting it up just the way I like it. That means not only moving the source code and other files over, but also installing the applications I need, configuring their settings, fine-tuning their options to make they work just right. I used to spend at least a couple of days doing such tedious tasks, before I could start to actually work with the new computer.

A couple of years ago, when preparing to move to a yet another new computer, and remembering how depressing it was the previous time, I decided to try something new: instead of reinstalling all my development tools directly, I created a virtual machine in the new computer first, and then installed the applications and utilities inside of that virtual computer. From that time on, I work from within the virtual machine, using the real computer just as the host of the virtual one.

Now, a couple of years later, I can say that that was one of the best moves I’ve done that reduced my stress level and increased my productivity. I had to move to a new computer a couple of times after that, and when I did that, all I needed to do to recreate my familiar development environment was to install the virtual machine software, copy the virtual machine to the new computer, and presto – I was back in the game in no time at all. Another convenience was that whenever I went on a trip, all I needed to do to take my development shop with me was copy the virtual machine to the laptop, and I could keep working on my software projects while on the go!

Of course, going virtual for software development requires the host computer to have a fast processor and plenty of RAM (a fast hard drive does not hurt, too). My current host computer has 2 GB of RAM and uses a Core 2 Duo processor that provides hardware support for virtualization. That makes my software development application (Microsoft Visual Studio) to work within the virtual machine just as fast as within the real one. (At least that’s how it feels, I did not do any special timings).

I liked having an independent virtual machine for the software development so much that a bit later I’ve created a few more dedicated virtual machines to run other parts of my software business as well: one such machine contains all my web site development tools and applications, including a local web server running the local copy of my web sites. Another virtual machine is dedicated to keeping the database of the customers, bookkeeping software, and other related tools.

In case you’ve spent the last few years on the moon and are not familiar with the virtual machine software, you can get started by taking a look at Microsoft Virtual PC and/or VMWare Server: both are easy to set up and use, both are free, both have good performance. VMWare Server offers more flexibility in the virtual machine configuration, and it provides support for the USB devices, while Virtual PC is easier to setup and use. I use both Virtual PC and VMWare Server, but I could not get them both to work on the same computer at the same time: if one of them was running, then an attempt to start the other one caused the host computer to crash. However, using them one at a time or on different host computers caused no problems.

One drawback of setting up the virtual machines is that many software vendors treat them like separate physical computers, and if you have purchased a one-computer license, you may not be allowed to install separate copies of the software in several virtual machines, even if they operate on the same physical host computer. I find such restrictions quite annoying. (They are the relicts from the old pre-virtual computing days). If you have a software tool that you must install in more than one virtual machine, check its license agreement, and if you find that you are not allowed to use the software in several virtual machines, contact the vendor and ask them to reconsider their license terms. If enough of us start demanding it, they may actually do that.