Posts Tagged ‘c++’

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…

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