Windows 7 RTM – Go Get It

This is it people. Windows 7 RTM is available for download from MSDN & TechNet sites! If you have a MSDN subscription you can get Windows 7 RTM in English. On October 1st, the remaining languages will be released, for more information read - Windows 7 RTM Available Today for MSDN & TechNet Subscribers. You can also get the Windows 7 SDK  and the RTM version of the Windows API Code Pack for .NET Framework.

Make sure you get them all today to start testing your applications, and to make sure your applications are ready for Windows 7 RTM! Now is the time to work on your applications to make sure they are Windows 7 compatible. On top of that, you can use new Windows 7 features such as the Sensor and Location Platform, Taskbar, Libraries, Multi-Touch, the new Graphics APIs, the Windows Ribbon, and many other important and exciting Windows 7 technologies to make your application shine on Windows 7.

New Windows 7 Training Kit for Developers - Get it NOW!

To help you get your application on Windows 7 as soon as possible, we updated the Windows 7 Training Kit for Developers for the RTM version and gave it a new look and better functionality. You can still find all existing topics such as: Taskbar, Sensor and Location, Libraries and Shell, DirectX, Multi-touch, Ribbon, etc. No dev was left behind! The kit is built for both native Win32 Windows7TrainingKit

C++ developers and .NET developers, so now most topics have multiple labs.We also added 6 new Application Compatibility labs: Version Checking, Data Redirection, UIPI, Installer Detection, Session 0 Isolation, and High DPI, to help you get over the most common application compatibility issues. All the topics in the training kit include additional information like whitepapers, links to MSDN, and links to videos from Channel 9.

 Updated Windows Topic Area on Channel 9

We also gave the Windows topic area on Channel 9 a brand new look and functionality to help you to better choose the right Windows 7 content you need. In the new Windows topic area for Channel 9, you can choose from three main topic areas:

NewC9

While we hope you find all this helpful, this is only the start! We are working on more new and exciting content that will be shipped in the following weeks, so stay tuned.

In the meantime, here is some additional useful information:

  • The Windows page on MSDN is the one-stop shop for Windows client developers
  • At Develop for Windows 7, you can find all the information you need about specific technologies like Direct2D, Taskbar, Sensor and Location, Power Shell 2, Windows Ribbon, and many more
  • Windows Application Compatibility is the one page you want to visit to make sure your application runs properly on Windows 7; it includes content and tools to test and fix many application compatibility issues. Directly accessible from that page, is the Windows 7 Application Quality Cookbook
  • Also still very relevant, is the Windows Vista Application Compatibility Cookbook--most Windows 7 compatibility issues are the direct result of the changes introduced in the Windows Vista timeframe, and are included as topics in this Cookbook (UAC, Session 0 Service Isolation, IE Protected Mode, etc.), which is a great starting point for addressing these issues
  • New Windows 7 videos on the Channel 9 Windows page explore specific features and technologies, and are great “windows” to the Windows engineering team
  • As always, the E7 blog is an amazing source of the engineering back story behind Windows 7
  • Last, but not least, for IT-Pro, we have our SPRINGBOARD SERIES, and edge on TechNet

And, of course, continue to watch for new posts.


Version Checking (Just Don’t Do It)

Version checking is probably one of the most common Application Compatibility issues that both developers and users are facing. This is another post in a series of posts about Getting Ready for Windows 7.

As said, this is probably the most common application compatibility issue that users as well as developers face is when an application fails upon checking the operating system version. A lot can go wrong when version checking is misused. A user might experience a “silent fail” where the application simply fails to load and nothing happens. Or, a user might see a dialog box indicating something to the effect of “you must be running Microsoft Windows XP or later” when in fact, the computer is running Windows 7. Many other consequences to poor version checking can inconvenience users as well.

Applications fail due to version checking for two main reasons:

  • A flaw (bug) in the version checking code, which fails if the minor version is decreased, even if the major version is increased, for example, changing versions from 5.1(Windows XP) to 6.0 (Windows Vista), or if the expected service pack (SP) is not installed, even if you're running a newer operating system (for example, changing versions from Windows XP SP 2 to Windows Vista SP 1). We recommend that you check functionality rather then checking version, as you can read in this post.
  • An intentional blocking that prevents the application from running on operating system versions not tested by its developers. We recommend that you do not block applications from running on future operating systems.

When an application runs on an "incompatible" (due to poor version checking) version of Windows, it will generally display an error message, but it may also exit silently or behave erratically. Often, if we work around the version checking, the application will run well. End-users and IT professionals may apply a fix to let the application think it is running on an older version of Windows.

Working Around The Problem (not really solving the bug)

Compatibility mode: Designed for end users (not for developers to not fix their bugs), compatibility mode is an easy way to work around compatibility issues. When enabled, it applies a set of compatibility fixes that provide a runtime environment more compatible with applications written for older versions of Windows. One of those fixes is the "version lie," which makes the version query functions return the operating system version the user chose in the Compatibility tab of the Properties dialog box instead of the actual Windows version.

To enable compatibility mode:

  • Right-click the executable or shortcut to the executable.
  • Click Properties.
  • Click the Compatibility tab.
  • Enable Run this program in compatibility mode for: and select the operating system version you think the application should be able to run on.
    Some applications consist of several executables. You may need to apply this fix to each one.

image

  • Click OK to close the dialog box.
  • Run the application.

Checking for Features Rather Than Version

As mentioned previously, checking the operating system version is not the best way to confirm that a specific operating system feature is available. This is because the operating system may have had new features added in a redistributable DLL. Rather than using GetVersionEx to determine the operating system platform or version number, it is more effective to test for the presence of the feature itself. For example, we plan to make the Direct2D and DirectWrite APIs and the Ribbon API available in Windows Vista, so there is no need to block your application from using these APIs when running on Windows Vista. You just need to check if these features are available on the Operation System that you are running. If possible, your application should still run if the feature is unavailable, though with reduced functionality or performance.

You can use one of the following techniques to find out if a specific features is available on the given OS.

For Win32 developers:

  • Use LoadLibrary() to load a library which is not yet loaded into your application. If you are interested in a new function of a DLL which is already loaded (for example, kernel32.dll), then call GetModuleHandle() to obtain the module handle. If either of these functions return NULL, then this indicates an error.
  • Use GetProcAddress() to obtain a function pointer. If GetProcAddress() returns NULL, then the function may not exist. Cast the pointer to a function pointer of an appropriate prototype. Some functions, although they exist may actually be stubs that return a "not implemented" error. Be such to check for such errors.

Windows 7 introduces a new timer API - SetWaitableTimerEXProc, which adds one more input variable to the regular SetWaitableTimerProc. The TolerableDelay lets you specific a time tolerance window in which the timer can expire. This is a new in Windows 7, that we will use to demonstrate how to check for feature.

      // define function pointer type
    typedef BOOL (WINAPI *SetWaitableTimerExProc)(
      __in  HANDLE hTimer,
      __in  const LARGE_INTEGER *lpDueTime,
      __in  LONG lPeriod,
      __in  PTIMERAPCROUTINE pfnCompletionRoutine,
      __in  LPVOID lpArgToCompletionRoutine,
      __in  PREASON_CONTEXT WakeContext,
      __in  ULONG TolerableDelay
    );

    LARGE_INTEGER liDueTime;
    liDueTime.QuadPart = 0;
    nt period = 1000;
    unsigned int tolerance = 1000;
    HANDLE hTimer = // Get timer handle

    REASON_CONTEXT reasonContext = {0};
    reasonContext.Version = 0;
    reasonContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
    reasonContext.Reason.SimpleReasonString = L"MyTimer";

    // Get module handle to a module which is already loaded
    HMODULE hKernel32Module = GetModuleHandle(_T("kernel32.dll"));
    if (hKernel32Module == NULL)
        return FALSE;

    // Get Address of function
    SetWaitableTimerExProc pFnSetWaitableTimerEx =
    (SetWaitableTimerExProc) ::GetProcAddress(hKernel32Module,     
        "SetWaitableTimerEx");

    // Check if the function exists    
    if (pFnSetWaitableTimerEx == NULL)
        return FALSE;

    // Call function
    if (!pFnSetWaitableTimerEx(hTimer, &liDueTime, period, NULL, NULL,
            &reasonContext, tolerance)
    { // handle error }

Alternatively, you may use DLL delayed loading and call functions in a __try...__except block. (For more information, see Linker Support for Delay-Loaded DLLs.)

For COM APIs, handle errors returned by CoCreateInstance and QueryInterface.NET framework applications that call Win32 APIs via P/Invoke should handle EntryPointNotFoundException and DllNotFoundException exceptions.

 

If You Must Check OS Version Number

Identifying the current operating system is not the best way to determine whether a particular operating system feature is present. However, if you can’t design your application to check for specific feature availability and the only way to ensure compatibility is through version checking, then please consider the following.

For native applications, you will need to ensure your application's logic will work with newer versions of Windows. Please DO NOT BLOCK on version change! The following is a Win32 code example that uses GetVersionEx. If the major version is greater than 5 (Windows Vista, Windows® Server 2008 R2 and Windows 7), the check passes. If it equals 5, then the minor version should be 1 or greater (Windows XP or Windows Server 2003).

#include <windows.h>
#include <stdio.h>

void main()
{
    OSVERSIONINFO osvi;
    BOOL bIsWindowsXPorLater;

    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    GetVersionEx(&osvi);

    bIsWindowsXPorLater = 
 ( (osvi.dwMajorVersion > 5) ||
       ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) ));

    if(bIsWindowsXPorLater)
  printf("The system meets the requirements.\n");
    else printf("The system does not meet the requirements.\n");
}

However there is a better way to verify the minimum OS version required using VerifiyVersionInfo(). This function compares a set of operating system version requirements to the corresponding values for the currently running version of the system. The following code example uses VerifyVersionInfo to check the operating system version against minimal requirements (Windows XP SP2):

#include <windows.h>
BOOL Is_WinXP_SP2_or_Later () 
{
   OSVERSIONINFOEX osvi;
   DWORDLONG dwlConditionMask = 0;
   int op=VER_GREATER_EQUAL;

   // Initialize the OSVERSIONINFOEX structure.

   ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
   osvi.dwMajorVersion = 5;
   osvi.dwMinorVersion = 1;
   osvi.wServicePackMajor = 2;
   osvi.wServicePackMinor = 0;

   // Initialize the condition mask.

   VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );
   VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op );
   VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op );
   VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op );

   // Perform the test.

   return VerifyVersionInfo(
      &osvi, 
      VER_MAJORVERSION | VER_MINORVERSION | 
      VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
      dwlConditionMask);
}

In this code you can see how we use the VerifyVersion with a set of conditions to return TRUE incase we run on any OS grater than Windows XP Service Pack 2.

 

For .NET Framework developers, use the ==, !=, <=, <, >, >= operators of the Version object returned by Environment.OSVersion.Version:

// This code checks if the OS is at least Windows XP
  if (Environment.OSVersion.Version < new Version(5, 1))
  {
        MessageBox.Show("Windows XP or later required.",
         "Incompatible Operating System", MessageBoxButtons.OK,
                MessageBoxIcon.Error);
        return;
  }

It is highly recommended that you don’t check for version at all and try looking to work with features. It will prove valuable for the future…

Just incase you want to read more, here are some useful links

You can also download a HOL and code sample for this topic.


User Account Control Data Redirection

To making sure your application is ready (compatible) for Windows 7, I am going to start providing additional information about the few compatibility topics we introduced in the “Is Your Application Ready for Windows 7 RTM?” post. This post focuses UAC Virtualization or more known as Data Redirection.

What Are You Talking About?

Today, many applications are still designed to write files to the Program Files, Windows directories, or system root (typically the C drive) folders. Some applications are designed to update Microsoft® Windows registry values, specifically values in HKLM/Software. But there is one problem: the files or registry values are not created or updated. You may ask, “What’s going on? My application goes through the code and does not report an error. So where are my files?”

To be specific, you may experience one or more of the following symptoms:

  • Your application writes to Program Files, Windows directories, or the system root (typically the C drive) folders, but you can't find your files in these locations
  • Your application writes to the Windows registry, specifically to HKLM/Software, but you can't see the registry updates
  • You switch to another user account, and your application is unable to find files that were written to Program Files, Windows directories, or the system root (typically the C drive) folders, or it finds older versions of these files
  • After turning User Account Control (UAC) on or off, your application is unable to find files in the Program Files or Windows directories

If this happens to your application, it is experiencing UAC Virtualization (AKA Data Redirection). The following information provides you with everything you need to know in order to detect this application compatibility problem, offers some solutions, and provides additional information about the specific nature of the compatibility problem.

The Real Issue: UAC Virtualization

Prior to Windows Vista, administrators typically ran applications. As a result, applications could freely read and write system files and registry keys. If standard users ran these applications, they would fail due to insufficient access. Windows Vista improved application compatibility for standard users by redirecting writes (and subsequent file or registry operations) to a per-user location within the user’s profile.

For example, if an application attempts to write to C:\Program Files\Contoso\Settings.ini, and the user does not have permissions to write to that directory (the Program Files), the write operation will be redirected to C:\Users\Username\AppData\Local\VirtualStore\Program Files\Contoso\settings.ini. If an application attempts to write to HKEY_LOCAL_MACHINE\Software\Contoso\ in the registry, it will automatically be redirected to HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software\Contoso or HKEY_USERS\UserSID_Classes\VirtualStore\Machine\Software\Contoso.

The following figure illustrates the two components of the Windows Virtualization process: file virtualization and registry virtualization:

image To learn more about UAC virtualization and new UAC technologies, see “New UAC Technologies for Windows Vista” at http://msdn.microsoft.com/en-us/library/bb756960.aspx.

Solution

Virtualization is intended only to assist in application compatibility with existing programs. New applications designed for Microsoft Windows 7 should NOT perform write operations to sensitive system areas, nor should they rely on virtualization to provide redress for incorrect application behavior. Always develop applications for use with standard user privileges and don’t count on the application running under administrator privileges. Test your application with standard user privileges and not administrator privileges.

If you are experiencing UAC virtualization with applications developed prior to Windows 7, re-design your applications to write files to the appropriate locations. When updating existing code to run on Windows 7, you should:

  • Ensure that during run-time, applications store data only in per-user locations or in computer locations within %alluserprofile% that have properly set access control list (ACL) settings. For more information about ACLs, see Access Control Lists.
  • Determine the known folder to which you want to write the data files. Generic data used by all users should be written to a global public location that is shared by all users. All other data should be written to a per-user location.
    • Generic data files can include, but are not limited to log files, settings files (INI/XML), saved state applications such as saved games, and so on
    • User documents are different; they should be saved to the Documents folder (or to a location the user specifies)
  • Ensure that you do not hard-code paths once you have determined the appropriate locations. Instead, use one of the following programming models and APIs to retrieve the correct paths of specific Windows known folders:
    • C/C++ native applications: Use the SHGetKnownFolderPath function that retrieves the full path of a known folder identified by the folder's KNOWNFOLDERID, a GUID parameter indicating the known location you would like to obtain:
      • FOLDERID_ProgramData – Shared program data directory for all users
      • FOLDERID_LocalAppData – Per-user program data directory (non-roaming)
      • FOLDERID_RoamingAppData – Per-user program data directory (roaming)
    • Managed Code: Use the System.Environment.GetFolderPath function. GetFolderPath takes a parameter indicating the Known Location you would like to obtain
      • Environment.SpecialFolder.CommonApplicationData – Shared program data directory for all users
      • Environment.SpecialFolder.LocalApplicationData – Per-user program data directory (non-roaming)
      • Environment.SpecialFolder.ApplicationData – Per-user program data directory (roaming)
    • If none of the above-mentioned options are available, use the environment variable:
      • %ALLUSERSPROFILE% – Shared program data directory for all users
      • %LOCALAPPDATA% – Per-user program data directory (non-roaming) - Windows Vista or later
      • %APPDATA% – Per-user program data directory (roaming) - Windows Vista or later

Steps to Determine the Most Appropriate Solution

So far, we have presented the symptoms associated with UAC virtualization, explained why redirection is taking place, and suggested a solution. This section contains tests and procedures you should perform in order to pinpoint the real problem and plot a way to resolve it.

Test #1:

  • Launch the application with standard user privileges
  • Run through the scenario that results in a write operation to any given protected folder such as the Program Files or system root (C:\) directories
  • Expected results: The application “succeeds” in writing the file to the protected folder; however, you can't find the file in the expected location
  • Conclusion: This suggests that UAC data virtualization is redirecting the file to a different location

Test #2:

  • Using Windows Explorer, search for your files in the VirtualStore folder
    • The VirtualStore folder is a folder in your profile which stores redirected files
    • The VirtualStore folder’s name and location are subject to change in later versions of Windows
  • First, attempt to find it under %localappdata%\VirtualStore
  • If you are unable to find it there, try issuing dir %userprofile%\yourfile.dat /s /a at a command line (usually found C:\Users\<user name>\AppData\Local\VirtualStore)
  • Expected results: You should find your file at the virtual store folder or sub folders
  • Conclusion: This is proof that UAC virtualization is taking place

Test #3

  • Log in as an administrator and launch your application with administrator privileges.
    • To launch the application with administrator privileges, right-click the file executable and select Run as Administrator
    • When an application runs with administrator privileges, virtualization is turned off, and the application now has sufficient privileges to write to the protected folders
  • Do not rely on permanently marking your application to require administrator privileges as a way to bypass virtualization, as doing so will leave the system more vulnerable to attack, will prevent the application from running with limited or standard user privileges, and will needlessly annoy users with a UAC prompt
  • Expected results: The application succeeds in writing the file to the protected folder, and you can find the file at the expected location
  • Conclusion: Running the application with administrator privileges turns off virtualization and grants privileges

Test #4

  • Launch Process Monitor (ProcMon)
  • Configure filtering to show only file operations and only those operations performed by your process
    • When you launch Process Monitor, the Process Monitor Filter dialog box appears
  • Add the following entry to the filter: "Column=Process Name, Relation=is, Value=YourApp.exe, Action=Include"image
  • To invoke the Process Monitor Filter dialog box again, click this toolbar button image
  • After clicking OK, configure Process Monitor to log only file events by enabling the following toolbar buttons as shown: image
  • Press CTRL-X to clear the log; press CTRL-E to toggle logging on/off
  • Expected results: You will see file operations whose results are REPARSE; the next line (with result SUCCESS) will usually be the redirected operation:

image

 

 

  • Double-click the line representing the operation with REPARSE as the result and click the Stack tab to show the call stack at the time of the operation:

image

  • The pink K and blue U letters on the left of each stack frame show whether the stack frame is in kernel mode (K) or in user mode (U);in this case, we are interested only in user-mode stack frames
  • In this example, the SaveFile function (at frame 21) in BrokenAppNative.exe is the one performing the operation which will be redirected
  • You should configure symbols for a more meaningful display' for more information about configuring symbols, refer to the Debugging Tools for Windows Web site
  • Conclusion: This test proves that UAC Virtualization did take place and shows you what operations in your application need to be corrected

Task #5

  • Add a manifest to your application which contains a UAC directive
    • This will mark your application as UAC-aware and will disable UAC virtualization
    • A manifest is an XML document that developers embed as a resource in a DLL or .exe file, but can be a standalone file named YourApp.exe.manifest or YourDLL.dll.manifest
    • Manifests can contain a variety of information that usually pertains to application compatibility, such as the exact version of Visual C++ runtime to load, the version of Common Controls Library to load, as well as UAC settings
    • Read more about UAC settings in the manifest in the Windows Vista Developer Story: Create and Embed an Application Manifest (UAC)
  • Expected results: The application now fails to write to any of the protected folders, returning an “access denied” error
    • This is a GOOD result, because the UAC data virtualization didn’t kick into action
    • As the developer, you should be able to recognize this (because you marked the application as UAC-aware in the manifest) and avoid writing to any of the protected areas
  • Conclusion: Windows enables virtualization because the application isn’t marked as UAC-aware. Marking your application as UAC-aware disables virtualization. If your app tries to write to protected store while marked as UAC-aware, you will get an access denied exception

Hands On Labs and Additional Material

you can download this doc, a presentation describing UAC Virtualization, and two full hands on labs on this topic, one for managed code and one for native, from here.

Tools

In order to detect UAC virtualization we use the following tools:

  • Process Monitor, a free and advanced Microsoft tool that monitors and logs file system, registry, network, and process activity
  • Standard User Analyzer, part of the Microsoft Application Compatibility Toolkit, is a free tool that monitors resource (file, registry, and others) usage of a given application and reports activity that is responsible for Standard User problems

Additional Resources