May 2009
Security: An Introduction to Security in Windows 7
Windows 7 includes many new features and enhancements to help improve security. Here’s an overview of everything you’ll find, from the new Biometric Framework and AppLocker to improvements for BitLocker and UAC. Chris Corio
Security: PKI Enhancements in Windows 7 and Windows Server 2008 R2
Windows 7 and Windows Server 2008 R2 introduce PKI enhancements that greatly improve the deployment and operational experience for users, enabling powerful new scenarios while decreasing operational costs. Learn about all the changes to PKI. John Morello
Security: Common SQL Server Security Issues and Solutions
Have you found yourself inadvertently in charge of a SQL Server database and don’t know all the best practices for making it secure? Paul Randal covers the top 10 security areas you should worry about, detailing common problems and their solutions. Paul S. Randal
Security: Protect Instant Messaging with Forefront Security
As IM becomes ever more popular, it is increasingly important that administrators have a way to keep it secure. Forefront Security for Office Communication Server provides effective protection against instant messaging-targeted malware or other prohibited content within an OCS 2007 environment. Molly Gilmore
Security: Protect E-Mail with Forefront Security
Neetu Rajpal introduces the next generation of Forefront Security for Exchange, a premium anti-malware product that protects e-mail that flows through Exchange server environments. Neetu Rajpal
Microsoft Office: A Guide to Customizing the Office 2007 Ribbon
The Microsoft Offi ce Ribbon makes it extremely easy to customize the interface of Offi ce applications for users in your environment— and all you need is Notepad. Here is everything you need to know to start customizing the Offi ce Ribbon today. Stephanie Krieger
Microsoft Excel: Using Excel and Visual Basic for Applications to Create a Game
A look at how you can use Visual Basic for Applications to create a game in Excel 2007. It's the perfect way to prep for OfficePalooza! Greg Stemp and Jean Ross
Columns
From the Editor: The Perennial Issue: | Toolbox: New Products for IT Pros: Greg Steen looks at using Admin Script Editor Enterprise Edition and finding SQL Server instances with Quest Discovery Wizard for SQL Server. He also discusses the book "Windows PowerShell Scripting Guide".Greg Steen | Exchange Queue & A: Recovering a Clustered Mailbox Server, Offline Address Book Issues, and More: Exchange Online and Exchange 2010Henrik Walther
Utility Spotlight: User Profile Deletion Utility: Delprof is a command-line utility that lets you free up disk space by deleting user profiles that are no longer required on both local or remote computers.Lance Whitney | Inside SharePoint: Integrate Information Rights Management into SharePoint: Continuing last month’s discussion about SharePoint integration with AD RMS, this column show you how to establish an AD RMS pre-production development environment, compile the IRM protectors, and integrate the compiled components into WSS 3.0.Pav Cherny | Windows PowerShell: Automating User Provisioning, Part 3: Don Jones continues his four-part series that explains how you can create an automated provisioning function in Windows PowerShellDon Jones
Geek of all Trades: Control Network Access Using DHCP Enforcement: NAP monitors the health of specified computers when they attempt to connect to a network and includes a number of mechanisms to enforce health requirements. This article gives readers an overview of these enforcement mechanisms and, as an example, takes a closer look at setting up DHCP enforcementGreg Shields | Hey, Scripting Guy!: Working with Access Databases in Windows PowerShell: Automating data entry is more important than ever, and today’s automation language is Windows PowerShell. This article uses Windows PowerShell to collect some data about the local computer and write it to an Office Access database.The Microsoft Scripting Guys | Desktop Files: Revisiting the Microsoft Desktop Optimization Pack: Wes Miller updates his 2007 article on the Microsoft Desktop Optimization Pack, a collection of valuable components that can can save your IT department a lot of time and effort. All of the components have been enhanced—and something new has been added.Wes Miller
Field Notes: IT Does Matter: Romi Mahajan notes the reasons people sometimes doubt the value of IT, then discusses why those reasons have little validity.Romi Mahajan | Cable Guy: DirectAccess and the Thin Edge Network: DirectAccess is a new feature of Windows 7 and Windows Server 2008 R2 that enables transparent, concurrent intranet and Internet remote access and eases the management of remote computers by combining a number of technologies and components, facilitating the transition to a thin edge network.Joseph Davies | Business of IT: Reinventing IT in Difficult Times: IT organizations have more intrinsic value than is immediately apparent. They need to find ways to demonstrate that value in order to reclaim their rightful standing in their companies. This article discusses five approaches they can take.Romi Mahajan
Business of IT: Lowering the Cost of IT: Of course you want to lower the cost of IT—without hurting either your company or the IT department itself. That may seem impossible at first, but if you step back and look at your entire IT infrastructure and business needs, you can find unexpected ways to save money without causing too much pain. This article presents a number of suggestions that can help you identify ways to reduce IT costs while increasing IT’s value to your business.Karen Forster | Utility Spotlight: Faster CPU Utilization Reports Using Multithreading: This edition of Utility Spotlight is a little different than the usual, in that it involves scripts instead of executables, and so the column is dual-purpose: not only does it give you a nice way to build a report on CPU utilization in your organization, it also serves as a mini-tutorial to explain how the script works and how to use it.James Turner | Windows Confidential: Finding the Right Volume: Raymond Chen discusses the difficult job of satisfying audiophiles and those who just want the sound to work.Raymond Chen


Security
An Introduction to Security in Windows 7
Chris Corio
Parts of this article are based on prerelease code. All information herein is subject to change.
At a Glance:
  • Windows Biometric Framework
  • Extending Authentication Profiles
  • Bitlocker To Go
  • UAC Improvements
Contents
Windows Biometric Framework
Extending Authentication Protocols
BitLocker Core Enhancements
BitLocker To Go
UAC Improvements
AppLocker
Global SACLs and Granular Auditing
Wrapping Up
Windows Vista introduced a variety of new security technologies that had a significant impact on the Windows ecosystem. User Account Control made it clear that Microsoft wanted to make easy for users to run Windows without being in the Administrators group. BitLocker introduced full volume encryption for the Windows client. Protected Mode Internet Explorer helped to make browsing the Internet a safer experience.
In Windows 7, Microsoft has continued its investment in security by adding new technologies as well as enhancing many of the technologies introduced in Windows Vista. In this article, I will provide an overview of the new security features and enhancements you'll find in Windows 7.

Windows Biometric Framework
Windows Vista included a redesign of the Winlogon experience. This experience removed the GINA (Graphical Identification and Authentication) infrastructure and added the Credential Provider extension model. The Credential Provider infrastructure was a set of interfaces that allowed consistency when third parties extended the user experience around users entering credentials, and it integrates into the common Windows credential dialog.
For Windows 7, Microsoft has added the new Windows Biometric Framework (WBF). With fingerprint readers becoming far more common, it became clear that defining a common framework for exposing, managing, and using these technologies was necessary to drive development and reliability. The WBF is intended to make it easier to support biometric authentication devices. In Windows 7, WBF supports only fingerprint readers, but it can be expanded in the future.
The WBF core platform consists of these main components:
  • Windows Biometric Driver Interface (WBDI)
  • Windows Biometric Service (WBS)
  • WBF API
  • WBF User Experience and Integration Points
  • WBF Management
The Windows Biometric Driver Interface (WBDI) is meant to provide a common driver interface for biometric devices. It consists of a variety of interfaces that expose the appropriate data structures and IOCTLs (Input/output controls) for biometric devices to integrate into the biometric framework. Drivers can be implemented in any of the common driver frameworks, including Windows Driver Model, Kernel Mode Driver Framework, and User-Mode Driver Framework (UMDF). UMDF, however, is the recommended driver framework for biometric devices because it provides the additional benefit of greater reliability for Windows in case a crash occurs in the biometric device driver.
The Windows Biometric Service (WBS) is the key component that ties together WBF. WBS interfaces with the biometric device drivers and also exposes the Windows Biometric Framework APIs, allowing applications to interact with these devices.
An important feature of WBS is that it never reveals a user's actual biometric data to unprivileged applications. This is important because, unlike a password, it's very difficult for someone to change their biometric signature once it's been compromised. Instead, the WBS exposes a handle (typically a GUID or a SID) that allows applications to work with the biometric data indirectly.
WBS also manages pools of biometric authentication devices. This enables you to control how biometric devices are used. Certain devices can be used with any Credential Dialog, such as the logon prompt or a UAC prompt. For example, you can set up Parental Controls on your home system, and when elevation is required on the system, you can simply swipe your finger to provide elevation. This pool of biometric devices is referred to as the System pool. There are two other pools of devices. There is the Private pool, which allows applications to offer authentication that is not integrated with the Windows authentication infrastructure. And there is the Unassigned pool, which is for devices that, as you might have guessed, fit neither of the previous two pools.
Each device that is part of a device pool is actually abstracted away by the WBS using a data class called a Biometric Unit. The Biometric Unit plugs into the WBS's Biometric Service Provider (BSP), which implements policies and behaviors specific to a set of biometric devices. The Biometric Unit allows the BSP to provide any facilities that a particular device might not support, such as storing fingerprint data or processing fingerprint data after it's been acquired by a device.
The third major component of the WBF is the set of APIs, also known as the WinBio* APIs, that can be used by applications and user mode components to directly interact with the devices. This includes interacting with a device during the original enrollment process for obtaining a user's fingerprint and correlating it with a particular user account, as well as the task of verifying a user for logon or UAC. These APIs also expose data about the specific biometric device and its characteristics. In addition, the WBF APIs can be extended to allow an application to interact with proprietary aspects of a particular device.
The WBF exposes two main ways to configure the use of biometric devices. For end users, there is a Control Panel applet, which is exposed in a few locations. You can find the Biometric Devices Control Panel under Hardware and Sound. From this location, the user can launch a third party fingerprint management application. Windows 7 does not provide a built-in fingerprint management application, so any third party vendor or OEM will have to write its own. (Note that the Windows Biometric Framework supports local and domain logon, as well as fingerprint-based UAC through the built-in Biometrics Credential Provider.)
The Windows Biometric Framework can also be managed through Group Policy. An administrator can enable or disable the entire framework, as well as manage what types of logons can use biometrics (for example, local and domain logons can be configured differently).

Extending Authentication Protocols
Windows 7 enhances the home and small network experience with a feature called Homegroup. Users can share data, such as media files, between computers in a home and use an online ID to authenticate between these computers. Users must explicitly link their Windows user account to an online ID in order for this functionality to work. Authentication is enabled by a new protocol called Public Key-based User to User or PKU2U.
Windows 7 also introduces an extension to the Negotiate authentication package, Spnego.dll. SpNego is the feature that decides which authentication protocol should be used when authenticating. Before Windows 7, it was typically a choice between Kerberos and NTLM (Windows Challenge/Response). The NegoEx extension is treated as an authentication protocol by Windows and it supports two Microsoft security support providers: PKU2U and Live. It's also extensible to allow for development of other security support providers.
Both of these features work when connecting to another computer in the Homegroup using an online ID. When one machine connects to another, the negotiate extension calls the PKU2U security support provider on the login computer. The PKU2U security support provider obtains a certificate from the certificate authority policy engine and exchanges the policy (along with other metadata) between the peer computers. When validated on the peer computer, the certificate is sent to the logon peer for validation, the user's certificate is mapped to a security token, and the logon process is completed.

BitLocker Core Enhancements
With Windows Vista, Microsoft introduced BitLocker. This is a full volume encryption solution designed to protect the data on laptops and desktop machines, such as branch office servers, even if the machine is lost or falls into the wrong hands. In Windows 7, many enhancements have been made to the management of BitLocker. These include consistent enforcement through all interfaces (the UI, the manage-bde command line tool, and the WMI provider) and separate Group Policy settings for fixed data drives. There are also new Group Policy settings that allow you to update your passwords and integrate with Smart Cards on non-OS drives, and you can also change the behavior related to automatic unlocking.
In Windows Vista, there have been complaints about it being difficult to partition the OS drive to prepare for a BitLocker installation—especially when the operating system is already installed. This problem has been addressed with two enhancements found in Windows 7. First, by default during Windows 7 setup, users will get a separate active system partition, which is required for BitLocker to work on OS drives. This eliminates a second step that was required in many environments. In addition, you can partition a drive for BitLocker as part of BitLocker setup if you do not already have a separate system partition.(see Figure 1).
Figure 1 Preparing a Drive for BitLocker

BitLocker To Go
One of the most visible and most important additions is BitLocker To Go, which is designed to protect data on removable data drives. It allows you to configure BitLocker Drive Encryption on USB flash drives and external hard drives. Design goals for BitLocker To Go called for the feature to be easy to use, for it to work on existing drives, to allow for the recovery of data if necessary, and to enable the data to be usable on Windows Vista and Windows XP systems.
There are many management enhancements for IT managers to take advantage of with this feature. The most notable is a new Group Policy setting that lets you configure removable drives as Read Only unless they are encrypted with BitLocker To Go. This is an excellent step forward in ensuring that critical corporate data is protected when a USB flash drive is misplaced by an employee.
Also notable is the ability to recover data from any BitLocker To Go device when the data is inaccessible. This technology, called a Data Recovery Agent, was ported from the Encrypted File System (EFS) feature and allows easy recovery of corporate data on a portable drive using the key created by the enterprise.
Getting BitLocker To Go functionality to work on Windows XP and Windows Vista required some reengineering of the core BitLocker feature. To do this, the team refactored the method by which BitLocker protects FAT volumes. BitLocker behavior was modified to overlay a "discovery volume" onto the physical, original volume and virtualize the blocks overwritten. The discovery volume contains the BitLocker To Go Reader as well as a readme file. This is called a Hybrid BitLocker drive. By default, when a FAT drive is encrypted, a hybrid BitLocker drive is created. The discovery drive is visible only on the Windows XP and Windows Vista operating systems.
The reader will also be available on the Microsoft download center after Windows 7 is released. The application provides read-only access to BitLocker drives that utilize the password key protector. Note that smart card authentication is not available when using the BitLocker To Go Reader.

UAC Improvements
User Account Control (UAC) is an often misunderstood technology. First off, it's actually a collection of features rather than just a prompt. These features include File and Registry Redirection, Installer Detection, the UAC prompt, the ActiveX Installer Service, and more. These features are all designed to allow Windows users to run with user accounts that are not members of the Administrators group. These accounts are generally referred to as Standard Users and are broadly described as running with least privilege. The key is that when users run with Standard User accounts, the experience is typically much more secure and reliable.
Many developers have started to target their applications to work well for Standard Users. Businesses now have a clearer path toward deploying Standard User accounts, allowing these businesses to reduce support costs and the overall TCO (total cost of ownership) of its computers. In the home, families can use Standard User accounts for children along with Parental Controls to create a safer environment.
Windows 7 includes numerous enhancements to improve the Standard User experience, and new configuration settings provide more control over the User Account Control prompt when run in Administrator Approval Mode. The goal is to improve usability while continuing to make it clear to independent software vendors that the default security context they should be targeting is that of a Standard User. In practice, these changes mean that users are not prompted for common administrative tasks in Windows 7. This is the setting that says "Notify me only when programs try to make changes to my computer."
The way this works is fairly straightforward. During process creation, the policy is checked to see if this setting is enabled. If the process being created is part of Windows, which is verified by checking the Windows catalog files for its signature, the process is created without a prompt. This setting does not prompt when you change Windows settings but instead enables you to focus on administrative changes being requested by non-Windows applications (such as installing new software). For people who want greater control changing Windows settings frequently, without the additional notifications, this setting results in fewer overall prompts and enables users to zero in on the key remaining notifications that they do see.
The other significant change is that several components no longer require Administrator privileges. For example, users can configure whether their desktops should be displayed in High DPI mode, a commonly used feature as computer screens get larger and pixel sizes get smaller. Another example is that Standard Users can now reset their network connection when physically logged into the computer, a common request Microsoft has heard from both home users and enterprises.
Figure 2 User Account Control When Installing an ActiveX Control
Reducing prompts also means streamlining areas where multiple prompts were encountered for a single user action. On Windows 7, for instance, installing ActiveX controls in Internet Explorer is much smoother. On Windows Vista, Internet Explorer 7 would create the IEInstal.exe process to perform the installation of an ActiveX control. This resulted in a UAC prompt that asked if you wanted "Install an IE Add On" to run with Administrator privileges. This prompt didn't provide much context about exactly what was being installed and Internet Explorer would immediately prompt you to approve a particular control. On Windows 7 with Internet Explorer 8, the install process has been modified to use the ActiveX Installer Service, which will extract the ActiveX control's publisher information and display it during the installation experience (see Figure 2). The new approach also removes the second prompt during the installation of an ActiveX control.

AppLocker
The ability to control which applications a user, or set of users, can run offers significant increases in the reliability and security of enterprise desktops. Overall, an application lockdown policy can lower the TCO of computers in an enterprise. Windows 7 adds AppLocker, a new feature that controls application execution and makes it even easier to author an enterprise application lockdown policy.
Durga Prasad Sayana and I discussed application lockdown policies in last year's security issue in an article titled "Application Lockdown with Software Restriction Policies." In the article, we detailed a number of challenges that an enterprise must overcome when creating such a policy. Some of these challenges include the following:
  • Understanding what software is used in your environment
  • Knowing which applications various users should be allowed to run
  • Knowing how to author the necessary policy
  • Determining whether a policy will work correctly when deployed
To address these hurdles, AppLocker offers a new approach that can audit how an application lockdown policy will work. It provides the ability to control how users run all types of applications—executables, scripts, Windows Installer files, and DLLs. And it offers new application lockdown policy primitives that are more specific and are not subject to break as easily when an application is updated. Windows 7 also includes support for legacy Software Restriction Policy (SRP) rules, but there is no support for the new AppLocker rules on Windows XP and Windows Vista.
The enforcement modes are all implemented on top of AppLocker's underlying enforcement agent, which is implemented in the appid.sys driver. This driver offers the ability to have kernel mode rule checking for such events as process creation and DLL loading. For applications that implement enforcement in User Mode, the legacy SaferIdentifyLevel API is used to determine whether an application can run. But Safer- IdentifyLevel will now hand the enforcement check over to a service to perform the actual verification of the binary and policy. This is a significant architectural enhancement over the legacy Software Restriction Policies feature.
AppLocker is meant to make it easy for IT pros to author a simple set of rules that express all of the applications that are allowed to run and ensure that the rules are resilient to application updates.
To author AppLocker policy, there is a new AppLocker MMC snap-in UX in the Group Policy Object Editor snap-in UX, which offers an incredible improvement in the process of creating AppLocker rules. There is a wizard that allows you to create a single rule, and another wizard automatically generates rules for you based on your rule preferences and the folder that you select (see Figure 3).
Figure 3 Automatically generate rules for AppLocker policy.
You can review the files analyzed and remove them from the list before rules are created for them. You can even get useful statistics about how often a file has been blocked or test AppLocker policy for a given computer.
In the previous Software Restriction Policies, it was particularly difficult to create policies that were secure but also wouldn't break from software updates. This was due to the lack of granularity of certificate rules and the fragility of hash rules that would break when an application binary was updated. To address this issue, AppLocker lets you author a rule that combines a certificate and a product name, file name, and file version. This makes it easy to specify that anything signed by a particular vendor for a specific product name can run.
AppLocker policies in Windows 7 have other benefits, as well, including separation between different types of execution (namely EXEs, DLLs, and MSI or script hosts). These file types are fit into four buckets called rule collections, and enforcement is configured separately for each. For example, administrators can enable AppLocker checks for executables without enabling checks of script files.
The AppLocker policy is stored under the HKLM\Software\Policies\Microsoft\Windows\SrpV2 key. The policy is stored in an XML format and is translated by the Application Identity (AppID) service. When policy is processed, the appid.sys driver is notified about new policy by the service through the IOCTL_SRP_POLICY and the driver will reload the policy.
The first task when approaching changes to your IT environment is to assess how the environment is currently functioning. Then you can carefully plan and test any changes to ensure they can be implemented smoothly. This is the purpose of the Audit only enforcement mode.
Auditing the enforcement of the App-Locker policy is extremely important. Not only does this let you test a policy before it's enforced, but it also offers you the ability to watch how the policy performs during its lifetime. You'd definitely want to know if a certain set of users needed an application to work at some point. This can be determined by connecting to a system and reviewing the AppLocker audit information to see whether an application lockdown policy was preventing a particular app from running.
The primary channel for AppLocker events is in the Applications and Service Logs that can be viewed in the Event Viewer (eventvwr.msc) application. In order to view these log entries, look for the EXE and DLL and the MSI and Script logs under the Microsoft\Windows\AppLocker\ event channel. Many different events can be generated, including whether an application was allowed or blocked and whether a policy was applied to a system.

DNSSec Validation
Over the past couple years, DNS-related exploits have become a more common problem on the Internet. There is a better understanding of how to poison DNS servers, and attackers are starting to make use of that information. What this means is that a user can potentially visit a Web site and not be absolutely sure that he isn't visiting a different, malicious Web site.
Windows Server 2008 R2 and Windows 7 introduce support for DNSSEC as per the current standards (RFC 4033, RFC 4034, and RFC 4035). Windows Server 2008 R2 will allow the DNS Server to provide origin authority and data integrity artifacts. Basically, a server will be able to attach digital signatures to DNS data in responses as well as validate data received from other DNS servers.
Windows 7 is the first client operating system to include the necessary pieces to allow the client to verify that it is communicating securely with a DNS server and verify that the server has performed DNSSEC validation on its behalf. This technology is currently being tested to ensure the maximum compatibility with current Internet infrastructure and aims to play a continuing role in securing DNS data in the future.
Global SACLs and Granular Auditing
Windows 7 extends previous auditing mechanisms to offer new features that let you manage auditing for users rather than just objects and to provide more information about AccessCheck failures for file objects. This enables new auditing scenarios and provides a significant paradigm change related to auditing.
In other versions of Windows, determining whether to audit object access was based on whether the security descriptor of an object included an access control entry (ACE) in its SACL specifying that it should be audited. This made it very easy to monitor a certain registry key or file to see what access was occurring on that object. Unfortunately, there was no method to watch what a particular user was accessing. If you wanted this scenario, you'd likely need to turn on auditing for every resource that the user could possibly interact with and thus every access by any user of the resource would end up in the audit log.
Enabling auditing on a wide enough data set to capture what a user could access is an incredibly arduous process. Each resource needs to be updated to include the audit policy within the SACL and any changes to this policy would require each SACL to be updated. To overcome this limitation, Windows 7 introduces Global Object Access Auditing, which is managed by auditpol.exe and is configurable using Group Policy.
The Global Ojbect Access Auditing includes a "Global SACL" that is an SDDL string stored in the registry with other data related to auditing. Two new APIs have been added to manage the Global SACL: AuditSetGlobalSacl and AuditQueryGlobalSacl. Updating the Global SACL requires the SeSecurityPrivilege, which protects the Global SACL from being updated by a user without administrator privileges.
Security auditing in Windows 7 also provides the ability to understand why access to an object failed or succeeded. This is important information if you're debugging an application failure or trying to understand whether your security policy is effective. Both the Global Object Access Auditing functionality and the inclusion of additional access audit data are implemented in a new kernel mode security API, SeAccessCheckEx. The two resource managers to consume this API will be NTFS and the Detailed File Share in Windows 7, and when enabled, the API will put information in the audit log about why an access attempt succeeded or failed. Thus these features apply to the file system and file shares for now and can be expanded to other resources managers in future versions of Windows.

Wrapping Up
Windows 7 enables new scenarios and makes using Windows a more secure experience. Many of these features have a strong focus on the user experience (for home users, business users, and IT professionals) and allow Windows 7 systems to work even better.

Chris Corio was a member of the Windows Security team at Microsoft for more than five years. His primary focus at Microsoft was application security technologies and management technologies for securing Windows. You can reach Chris at winsecurity@chriscorio.com.


Security
PKI Enhancements in Windows 7 and Windows Server 2008 R2
John Morello
This article is based on pre-release code. All information herein is subject to change.
At a Glance:
  • Server Consolidation
  • Improved Existing Scenarios
  • Software + Services
  • Strong Authentication

Contents
Server Consolidation
Improved Existing Scenarios
Software + Services
Strong Authentication
Wrapping Up
It seems like just yesterday I was writing an article titled “PKI Enhancements in Windows.” That article, which ran in the August 2007 issue of TechNet Magazine, focused on some of the innovations that shipped in Windows Vista and Windows Server 2008. These innovations included such things as enrollment UI improvements and OCSP (Online Certificate Status Protocol) capabilities. While those enhancements were valuable and well received by users, you could argue that the changes were really incremental changes from an IT professional's perspective. Windows 7, however, will deliver PKI enhancements that greatly improve the deployment and operational experience for users, enabling powerful new scenarios while decreasing operational costs.
The improvements in Windows 7 and Windows Server 2008 R2 are focused around four core areas (shown in Figure 1):
Server consolidation. This allows organizations to reduce the total number of certificate authorities (CAs) required to meet their business objectives.
Improved existing scenarios. This focus is on such elements as offering more complete SCEP (Simple Certificate Enrollment Protocol) support and including a Best Practices Analyzer (BPA).
Software + Services. This is to enable autonomous enrollment of users and devices for certificates regardless of network boundaries and certificate providers.
Strong authentication. This area focuses on improvements to the smart card experience, the introduction of the Windows Biometric Framework, and so on.
Figure 1 The four core areas of PKI improvements
In this article, I explore some of the major changes in these areas from the perspective of an IT professional.

Server Consolidation
One of the predominant themes in IT over the past few years has been server consolidation. Simply put, this is about reducing the total footprint of your server computing environment while still meeting, or even expanding, your business objectives. The current global economy has made cost savings a top priority for many IT groups, and server consolidation can certainly be one component of that general strategy. While most organizations do not have large, absolute numbers of CAs, many do have more than they need solely based on certificate creation throughput. In other words, many organizations have CAs that are vastly underutilized.
There are two primary reasons for this underutilization. First, some organizations may require separate CAs for regulatory or security policy reasons. For example, some customers have chosen to issue certificates to external parties from a completely separate CA than the ones that issue certificates to internal users and machines. In these cases, virtualizing the CA on Hyper-V can eliminate the need for separate server hardware (though the CA itself must still be managed, even as a VM).
The second common reason is that autoenrollment has only been supported in intra-forest scenarios. Specifically, a CA has only been able to automatically enroll entities for certificates when those entities are part of the same forest that it is joined to. Even in cases where bi-directional forest level trusts exist, separate CAs have been required for each forest where autoenrollment is used.
One of the key new features in Windows Server 2008 R2 is the ability to perform autoenrollment across-forest trust relationships, creating the potential to drastically reduce the total number of CAs required in an enterprise. Consider a typical enterprise network that has already done some consolidation work and now has four forests: production, development, test, and edge. Prior to R2, if you wanted to provide autoenrollment on each forest, at least four issuing CAs were required, even though all the forests trusted each other. With R2, you can reduce the total number of CAs in this scenario down to one, having a single CA in one of the forests issue certificates to entities in all the other forests.
For environments with more complex multi-forest designs, the total reduction in CAs can be even more dramatic and provide an immediate return on investment for the upgrade to R2.
Cross-forest enrollment also makes it easier to extend a PKI during mergers and acquisitions, since certificates can start being provisioned to the newly acquired assets as soon as a forest trust is put into place. And since cross-forest enrollment is a purely server-side change, the enrollment can start without making any changes to the client machines and it works with older client operating systems, such as Windows XP.
So how does cross-forest enrollment work? To the end user, the experience is completely seamless. As with any other autoenrollment scenario, the user just gets the certificates with little or no interaction required on his part. End users will likely never know from what forest the CAs have come and they will not need to take any special actions to obtain the certificates.
For an IT pro, the basic building blocks are mostly the same as with traditional intra-forest autoenrollment. The key difference is that the CA is now able to process requests received from an external forest and retrieve metadata about the request from a trusted Active Directory.
This ability to receive and properly process a request from a trusted forest is the key new capability in R2 that enables this scenario to work. In addition to having an R2 CA and the bi-directional forest trust, certificate templates must be replicated between the forest holding the CA and all other forests that will enroll against it. Microsoft will provide a Windows PowerShell script to automate this replication, which should be done after every change to a template. In many cases, it will be a good idea to have this script run automatically as a scheduled task.
There are a few other smaller features that can help with server consolidation. One is that the CA now supports non-persistent requests—these are requests for certificates, typically short lived, that are not written into the CA's database. For example, consider Network Access Protection Health Registration Authorities. These systems may issue thousands of certificates each day that are only valid for a few hours. Maintaining all these requests in the CA database adds little value, but greatly increases the storage required. With R2, these requests can be configured to not be written to the database and this configuration can be made at either the CA or template level (see Figure 2).
Figure 2 Choosing not to store certificates in the database
Another feature designed to make server consolidation easier is support for Server Core. With R2, the CA role can be installed on Server Core, though no other AD CS (Active Directory Certificate Services) role service is available on Server Core. When installed on Server Core, the CA can be managed with either local command-line utilities, such as certutil, or by using the standard MMCs from a remote system. Note that if hardware security modules (HSMs) are used, you should ensure that the HSM vendor supports running their integration components on Server Core.

Improved Existing Scenarios
Windows 7 and R2 include a number of incremental improvements to existing features. First is a change to SKU differentiation for Certificate Templates. In prior releases of AD CS, advanced (version 2 and 3) Certificate Templates that enable the autoenrollment functionality required Enterprise edition CAs. In Windows Server 2008 R2, a Standard edition CA will support all template versions. R2 also introduces some improvements to the Simple Certificate Enrollment Protocol support. In R2, the SCEP component will support device renewal requests and password reuse.
New to AD CS in R2 is a Best Practices Analyzer (see Figure 3). BPAs were created to provide an easy way for administrators to check their configurations against a database of best practices created and maintained by Microsoft feature teams. Data from customer support services indicate the majority of support calls on AD CS are caused by incorrect configurations, so the BPA should improve customer experiences by making it easier to verify that a CA is configured properly. The analyzer will check for such issues as missing AIA (Authority Information Access) or OCSP pointers, certificates near expiration, and trust chaining problems.
Figure 3 Running the new Best Practices Analyzer
In current releases of Windows, choosing a certificate for client authentication can be difficult for end users. When multiple certificates are valid for authentication, Windows doesn't make it easy for users to determine which one is the right one for a given usage. This leads to more help desk calls and increased customer support costs. In Windows 7, the certificate selection interface has been greatly enhanced to make it much easier to choose the right certificate for a given scenario. The list ordering has also been changed in order to assist in making smarter decisions by presenting the most likely certificate for a given scenario as the default choice. Finally, the selection UI now differentiates between certificates on smart cards and those stored on the file system and presents smart card certificates highest in the selection list, since they're more likely to be used. The differences are illustrated in the screenshots shown in Figure 4. Note that Internet Explorer 8 will make the improved filtering (but not UI changes) available on downlevel operating systems as well.
Figure 4 A smarter way to present certificates

Software + Services
During the Windows 7 design process, the team hosted a meeting with many of the top PKI users to brainstorm which areas should get attention in the new release. An overwhelming number of users indicated that it's too hard to manage certificates across organizational boundaries, such as between two separate companies that are business partners. Many also said that they see PKI as an ideal target for outsourcing, since it requires a specialized skill set to manage effectively. Windows 7 and Windows Server 2008 R2 will deliver a new technology that satisfies both these needs, making it easier to provision certificates across boundaries and opening new business models for hosted PKI solutions. This technology is HTTP enrollment.
Figure 5 The new enrollment model
HTTP enrollment is a replacement for the traditional RPC/DCOM-based protocol used for autoenrollment in previous releases (note that the RPC approach is still available in R2). However, HTTP enrollment is more than just an enrollment protocol—it's really a completely new approach to providing certificates to end entities, regardless of where they're located or whether they're a managed machine and with flexible authentication options. This new model eliminates many of the barriers found in traditional autoenrollment across organizational boundaries and provides a framework for third parties to easily provide autoenrollment services without requiring additional software on the clients.
HTTP enrollment implements two new HTTP-based protocols. The first protocol, known as Certificate Enrollment Policy Protocol, makes certificate templates available to users over HTTPS sessions. The end entities can come from machines in separate forests with no trust relationships and machines not even joined to a domain. Authentication uses Kerberos, user names/passwords, or certificates. The Enrollment Policy Protocol allows users to poll for templates and determine when to request certificates based on new or updated templates.
The Certificate Enrollment Service Protocol is an extension to WS-Trust. The protocol is used for obtaining certificates once the template information has been determined. It supports flexible authentication methods and uses HTTPS as its transport.
The example shown in Figure 5 illustrates how this new enrollment model works.
  • In Step 1, Certificate Templates are published from Active Directory to a server running the Certificate Enrollment Policy Web Service (a role service new to R2). The administrator publishing these templates is using the same MMCs and other tools with which they're already familiar.
  • In Step 2, a client has polled the Web service via HTTPS to determine the list of templates available to enroll against. The client learns the URL for the Web service via Group Policy, script, or manual configuration. The client could be a domain-joined system, a system at a business partner, or a user's home system.
  • In Step 3, the client has determined what templates he wants to enroll for and sends a request to the Certificate Enrollment Web Service to perform the actual enrollment.
  • In Step 4, the server running the Enrollment Web Service sends the request to a CA for processing.
  • In Step 5, the CA has looked up data about the requestor from Active Directory (such as his e-mail address or DNS name) that will be included in the issued certificate.
  • In Step 6, the CA returns the completed certificate to the Enrollment Web Service.
  • In Step 7, the Enrollment Web Service completes the transaction with the client via HTTPS and sends the signed certificate.
Flexibility was one of the key design principles in this new service and it's important to note how the design can be adapted to fit a diverse set of scenarios. Because the enrollment protocol is HTTPS, clients can easily enroll for certificates from anywhere, including behind corporate firewalls or from home ISP connections, without requiring a VPN. Because three different authentication methods are supported, clients can be joined to an organization's internal domain, an untrusted domain of an external organization, or no domain at all. Finally, because the server-side components are implemented as Web services, they can be installed separately from the CA and support segmented environments.
In addition to the classic scenario of enrolling end entities like users and desktops for certificates, HTTP enrollment also enables opportunities for provisioning certificates from trusted root CAs. Scenarios such as user S/MIME certificates, publicly facing Web servers, and other systems where implicit trust of certificates is important could all benefit from more autonomous enrollment. For example, many organizations with large numbers of Web servers maintain certificates manually, using lists of server names and expiration dates stored in Microsoft Office Excel workbooks. With HTTP enrollment, trusted root CAs can offer a service in which they provide certificates directly to these Web servers automatically, freeing the administrator from having to manually maintain the certificates on them. This combination of software and services allows organizations to choose the deployment models that fit their needs best, without having to design around network or organizational boundaries.

References
Introduction to the Windows Biometric Framework (WBF)
microsoft.com/whdc/device/input/smartcard/WBFIntro.mspx
About Personal Identity Verification (PIV) of Federal Employees and Contractors
csrc.nist.gov/groups/SNS/piv/index.html
Windows Server PKI Home
microsoft.com/pki
Windows PKI Blog
blogs.technet.com/pki
Strong Authentication
Windows 7 includes the first in-box support for biometric devices with the Windows Biometric Framework (WBF). Initially focused on fingerprint-based authentication for consumer scenarios, WBF is designed to make biometrics an easier and more integrated experience for users. A unified driver model provides consistent user experiences across device types with support for Windows logon (both local and domain), User Account Control (UAC), and autonomous device discovery. For enterprises, WBF provides a Group Policy–driven method to disable the framework for organizations that choose not to use biometrics. Enterprises can also choose to allow biometrics for applications, but not for domain logon. Finally, the enhanced device management can prevent device use in addition to simply preventing driver installation.
In addition to the biometrics improvements, Windows 7 also enhances user and administrator experiences for smart card scenarios. Smart cards are now treated as Plug and Play devices with Windows Update–based driver installation. The Plug and Play detection and installation process takes place before logon, meaning users who are required to log on with smart cards will be able to log on even in cases where the card has not been previously detected. Additionally, the installation does not require administrative privileges, making it suitable in least-privilege environments.
The smart card class mini-driver now includes NIST SP 800-73-1 support, so Federal agencies can use their PIV (Personal Identity Verification) cards without having to use additional middleware. The mini-driver also includes support for the emerging INCITS GICS (Butterfly) standard, providing a Plug and Play experience for those cards.
Windows 7 also introduces support for biometric-based smart card unlocking and includes new APIs to enable secure key injection. Finally, Windows 7 adds support for Elliptic Curve Cryptography (ECC) smart card certificates for both ECC certificate enrollment and for utilizing those ECC certificates for logon.

Wrapping Up
Windows 7 and Windows Server 2008 R2 contain some of the most important new PKI technology since Windows 2000 introduced automatic certificate requests. This new functionality makes PKIs easier and more efficient to manage, delivering a better experience for end users.
Windows 7 and Windows Server 2008 R2 include powerful new capabilities that make running a PKI more efficient while greatly enhancing the autoenrollment function. Cross-forest enrollment can dramatically reduce the total number of CAs required by an organization and make it easier to manage PKI operations during mergers, acquisitions, and divestitures. The new Best Practices Analyzer makes it easy for administrators to check for common configuration problems before outages occur. Capabilities such as support for Server Core and nonpersistent requests make it easier to tailor CA operations to specific organizational needs. And HTTP enrollment opens up new methods to automatically provision certificates across organizational and network boundaries.
End users will also benefit from Windows 7 PKI features that make it easier to use certificates in their daily work. The improved certificate selection interface makes it easier for users to choose the right certificate for a given purpose and successfully authenticate more quickly. Smart card improvements like Plug and Play–based driver installation and native support for card standards mean less time needs to be spent getting cards to work on user systems. Finally, the inclusion of native support for biometrics will provide a more consistent and seamless experience for both end users and administrators.
Check out the Beta if you haven't already and let us know what you think via the Feedback Tool or on our blog at blogs.technet.com/pki.

John Morello has been with Microsoft since 2000. He spent five years in Microsoft Consulting Services where he designed security solutions for Fortune 500 corporations, governments, and militaries around the world. He's currently a Principal Lead Program Manager in the Windows Server Group. John has written numerous articles for TechNet Magazine, he has contributed to several Microsoft Press books, and he speaks regularly at conferences such as TechEd and IT Forum. You can read his team's blog at blogs.technet.com/WinCAT.


Security
Common SQL Server Security Issues and Solutions
Paul S. Randal
At a Glance:
  • Physical and network security
  • Attack surface, service accounts, and least privilege
  • Authentication, authorization, and SQL injection
  • Disaster recovery and auditing

Contents
Physical Security
Network Security
Attack Surface Minimization
Service Accounts
Restricting Use of Administrator Privileges
Authentication
Authorization
SQL Injection
Disaster Recovery
Auditing
Summary
Anyone who's been around the IT industry knows that security is a hot topic. After all, a company's data is one of the most precious assets it has and protecting that data is critical. As I was planning what to write for this security issue, I tried to determine which security feature should have an entire article dedicated to it. But then I started to think about the burgeoning numbers of "involuntary DBAs" (those IT pros who inadvertently wind up responsible for a SQL Server instance) and the great response we had to the Top Tips for Effective Database Maintenance article from the August 2008 issue. It struck me that what I should do is write an article that covers common SQL Server security issues—a sort of primer to better security for your SQL Server instances.
An article that describes all the security problems you should be looking at would be a whole magazine in itself, so I canvassed my fellow SQL Server MVPs (and my wife) for input as to what I should include. I settled on providing the top 10 security areas I think you should worry about if you're not a security-savvy DBA and suddenly find yourself responsible for a SQL Server instance and associated application. (Remember that this is by no means an exhaustive list.) For each issue, I've given a short overview of the problem, advice on how to mitigate it, and a link to more detailed information.
All the links to Books Online are for the SQL Server 2008 versions, but each Web page links to the SQL Server 2005 version as well. Wrapping up the article, I provide links to the main white papers and Books Online sections for security for SQL Server 2005 and SQL Server 2008.

Physical Security
It's imperative that you don't just consider SQL Server security itself, but all the layers that must be traversed to get to SQL Server in the first place. For this concept of layered security, often called "defense in depth," you don't just secure one layer, but consider the entire system.
The most obvious first consideration is the physical security of the machine running SQL Server—this layer, however, is often overlooked or is the subject of complacency. I'm not referring simply to whether the machine can be stolen or not, but also to physical access to things like the storage system hosting the database files, the backup tapes, and any servers hosting redundant copies of the database. Only those people with an actual need to physically touch these objects should have access to them; anyone who needs temporary access should be accompanied and monitored.
A less obvious consideration is the security of the desktops of the people who have high-privileged access to SQL Server. If someone has sysadmin access to SQL Server but they leave their Windows desktop unlocked, then all the security in the world isn't going to prevent someone walking past the unattended system from potentially accessing sensitive data. A more insidious problem would be if someone walked past and changed some data—for instance, a dishonest employee who knows the schema of the human resources database and tries to undetectably change a salary.
There's a very interesting TechNet white paper (including a slide-deck and webcasts), titled "Physical Security at Microsoft," which describes how Microsoft manages the physical security of its many servers.

Network Security
Although your servers may be physically inaccessible, they're most likely connected to a network of some kind. This could be just an isolated company LAN with no outside connections, or it could be a direct connection to the Internet. No matter what the situation, there are some things you need to consider:
  • Ensure that the Windows server has proper network security configured.
  • Decide which network protocols to allow, and disable any that are not required.
  • Ensure there is a firewall set up (such as Windows Firewall) and configure it to allow access to SQL Server (as shown in Figure 1).
  • Decide whether to encrypt connections to SQL Server and configure appropriately.
  • If Kerberos will be used, register a Server Principal Name. Kerberos is an authentication mechanism that underpins Windows authentication (which I describe later in this article), but it is poorly understood. A clear and concise explanation was provided by Rob Greene, a Support Escalation Engineer, in the blog post "Kerberos for the Busy Admin." I recommend checking it out.
  • Decide whether to use the SQL Server Browser Service to help clients find installed SQL Server instances, and decide whether you want to hide some instances. Hiding an instance means client applications and users will need to know the connection details of the SQL Server instance, but it prevents people from trawling the network to look for SQL Server instances.
Figure 1 Configure Windows Firewall to allow TCP access to SQL Server
All these tasks (and more) are explained in SQL Server 2008 Books Online, starting with the topic Server Network Configuration. There's also a good section on Client Network Configuration.

Attack Surface Minimization
The more services and features that are enabled, the more attack surface or surface area there is for bad guys to attack. SQL Server 2005 took the "off by default" strategy—features with security implications are disabled by default and are only enabled by the DBA when required. (This process of enabling and disabling services is commonly called surface area configuration.)
A prime example of a feature that you may want disabled is xp_cmdshell, which provides a way of executing commands on the host Windows system from within the context of a SQL Server instance. If an intruder compromises the SQL Server instance, and the SQL Server service account has elevated Windows privileges, xp_cmdshell can be used to gain access to the Windows system, too.
There are a variety of methods for surface area configuration. Both SQL Server 2005 and SQL Server 2008 support the SQL Server Configuration Manager for configuring services and network protocols. Both also support the sp_configure stored procedure for configuring database engine features and options. As an example, this code will disable the xp_cmdshell feature:
-- To allow advanced options to be changed
EXEC sp_configure 'show advanced options', 1;
GO
-- To update the currently configured value for -- advanced options
RECONFIGURE;
GO
-- To disable xp_cmdshell
EXEC sp_configure 'xp_cmdshell', 0;
GO
-- To update the currently configured value for this -- feature
RECONFIGURE;
GO
The graphical methods of configuring database engine options and features are quite different between the two versions. SQL Server 2005 introduced the SQL Server Surface Area Configuration (SAC) tool. This allows you to easily make changes. Figure 2, for instance, shows how you can disable xp_cmdshell using SAC.
Figure 2 Disabling xp_cmdshell using SAC in SQL Server 2005
In SQL Server 2008, SAC was completely removed and the functionality subsumed by the Policy-Based Management feature. You can find more information on this in the SQL Server 2008 Books Online topic "Administering Servers by Using Policy-Based Management." Figure 3 illustrates creating a condition to check that xp_cmdshell is disabled. Once configured, policies can target both SQL Server 2005 and SQL Server 2008 instances and can even be "applied," allowing you to essentially change the setting with one click.
Figure 3 Creating a Policy-Based Management condition in SQL Server 2008

Service Accounts
SQL Server runs as one or more services on Windows, and each service needs to have a Windows account that is used to run the service. The account needs to have access to various resources on the Windows system (such as the network and various file system directories). The best practice is for the account to have the least possible privileges required to allow SQL Server to operate correctly. This is part of what is called the principle of least privilege, which states that a system can be made more secure by granting a user or process only those privileges required and nothing more.
As such, a SQL Server service account should not be a high-privileged account (such as Local System or Local Administrator) because if SQL Server is compromised, there is the potential for the Windows system to also be compromised. The services typically run under a built-in account called Network Service, but if SQL Server requires access to other domain resources, a new domain user account should be created with the minimum privileges and resource accesses required. The SQL Server 2008 Books Online topic "Setting Up Windows Service Accounts" provides a comprehensive list of service accounts, required privileges, and resources. Note that if you must change a service account (or anything about it), you should always use the SQL Server Configuration Manager to ensure that all the necessary configuration changes are properly made.

Restricting Use of Administrator Privileges
The more exposure the SA login or the sysadmin fixed server role has, the more potential there is for a security breach—or an accident. There are a few best practices to follow.
Minimize the number of people who have access to the SA account and restrict the membership of the sysadmin role (and other privileged roles) so only those people who really need sysadmin privileges have them. Don't give out the SA password to anyone who wants temporary access to SQL Server or to a SQL user who wants to perform some quick task. In these situations, create a new SQL login and grant whatever privilege is required.
It's better to have people as members of the sysadmin role rather than using the SA account. This way, you can remove a user's login without having to change the SA account password. If you take over an old server and you have no idea who had access to it before, change the SA password so you're in control.
One issue that provokes debate is whether to remove the Windows BUILTIN/Administrators group from the sysadmin role (it's added by default). Should a Windows admin be able to query the HR database? Or does your company explicitly trust all administrators to have integrity and honesty? If you decide to remove it, proceed with care. This is especially true in a clustered environment where if you don't take the correct steps, your SQL Server may not start. For more information on this and other clustering issues, see the Knowledge Base article "Clustered SQL Server Dos, Don'ts, and Basic Warnings."
For those who do have sysadmin access, encourage them not to log in with high privileges unless absolutely necessary—give each of these users two logins, one privileged and one not. Using the nonprivileged account by default helps minimize the potential for costly mistakes, and also reduces the likelihood that an unlocked Windows terminal will have a window with sysadmin privileges open on it. Remember: defense in depth!
The last point I'll make here is to avoid having applications that require sysadmin privileges. Unfortunately, this is a common and unavoidable bad practice with some applications, but you should avoid this practice in homegrown applications and complain to any application developers that require sysadmin privileges.

Authentication
There are two authentication modes available: Windows Authentication and mixed-mode (which is Windows authentication combined with SQL Server Authentication).
Windows Authentication uses network/domain accounts to validate the Windows account being used to connect to SQL Server. If this is selected during setup, the SA account is created with a randomly generated password but effectively disabled. Immediately after installation, you should change the SA password to a strong and secure password but continue to leave the account disabled unless absolutely necessary.
SQL Server Authentication relies on each user having a defined SQL Server account and password stored in SQL Server. And, of course, this means that the SA account is enabled and must have a defined password. With SQL Server authentication, users have at least two user names and passwords (one for the network and one for SQL Server). It is generally recommended that you only use Windows Authentication when possible, as it is a more secure solution. The Books Online topic "Choosing an Authentication Mode" explains this in more detail, along with how to change the authentication mode.
If SQL Authentication is used, then all users should have a strong password—one that is complex enough to be resistant to being guessed by a password-cracking program. This is especially important for high-privileged accounts, such as SA and members of the sysadmin role. (One of the most common yet worst practices used to be to have a blank SA password. Fortunately, as of SQL Server 2000 SP3, that is not possible.)
Passwords should also be changed regularly and your company should publish corporate policies to help employees use secure and strong password best practices. For an overview of best practices for creating and protecting strong password, see the article "Strong Passwords: How to Create and Use Them." You can incorporate these policies into a corporate policy.
If SQL Server 2005 or SQL Server 2008 is running on Windows Server 2003 or later, it can make use of the Windows password policy mechanisms to enforce complexity and expiration policies. The SQL Server 2008 Books Online section called "Password Policy" has information about support for strong passwords and various password policies in SQL Server.

Authorization
As I've already mentioned, one of the tenets of securing systems is to use the principle of least privilege. While this applies directly to admin-level privileges, it also applies to permissions for regular database users. A user in one database should (probably) not be able to access data in another database. The owner of one set of tables should not be able to mess with someone else's tables. Users should only be able to access the data they are supposed to access, and even then they should only be able to perform required actions on the data (for instance, SELECT but not UPDATE or DELETE).
All of this can be accomplished within SQL Server by a comprehensive, hierarchical permissions system where users or roles (called principals) are granted or denied certain specific permissions on certain resources (called securables) such as an object, schema, or database. An overview of the SQL Server permissions hierarchy is illustrated in Figure 4. This also implies that you follow the principle of least privilege. For example, don't make all database developers members of the db_owner role. Restrict permissions to the public role and only grant permissions to the lowest level (user or role) to minimize direct access. A full discussion of best practices for permissions is beyond the scope of this article, but SQL Server 2008 Books Online includes a section called "Identity and Access Control (Database Engine)" that offers drill-downs into all the concepts.
Figure 4 The SQL Server permissions hierarchy
To allow more granular permissions and better separation of roles within a database, SQL Server 2005 introduced user-schema separation, where schemas are independent of database users and are just containers of objects. This allows many behavioral changes, including more fine-grained precision for managing permissions. (Four-part naming follows the format server.database.schema.object in SQL Server 2005 and SQL Server 2008—the format was previously server.database.owner.object.)
For example, a schema can be created with database developers given CONTROL permissions. They can CREATE, ALTER, and DROP any objects within the schemas they control but they have no implied permissions to any other schemas within the database and they no longer need db_owner rights for database development. In addition, user-schema separation allows database users to be dropped without having to recode all of the related objects or the application with a new user name—the objects are members of a schema and they are no longer tied to the object's creator.
It's a best practice to use schemas for object ownership because of these reasons. More information can be found in SQL Server 2008 Books Online in the topic "User-Schema Separation."
Another way of preventing users from doing things they're not supposed to do is to disallow direct access to your base tables. This can be done by providing stored procedures and functions that are used to encapsulate, control, and isolate operations like updates and deletes, and by providing views that allow controlled and optimal selects.

SQL Injection
One of the most common methods of gaining unauthorized access to data is to use a SQL injection attack. SQL injection can take many forms, but the primary approach takes advantage of code that uses dynamically constructed strings and "injects" unexpected code into the construct. For example, the following injection attack takes advantage of poorly written logic for validating user input to trick SQL Server into accepting input by including escape characters in the input string. Although contrived, this example highlights what can happen when code dynamically constructs strings using input that is not thoroughly validated:
DECLARE @password VARCHAR (20);
DECLARE @input    VARCHAR (20);
DECLARE @ExecStr  VARCHAR (1000);

SELECT @password = 'SecretSecret';

-- assume application gets input 'OR''='
SELECT @input = '''OR''''=''';

SELECT @ExecStr = 'IF ''' + @password + ''' LIKE ''' + @input + ''' PRINT ''Password Accepted''';

EXEC (@ExecStr);
GO
If you run this code, it will print the phrase "Password Accepted" even though the user input clearly did not match the password string. The user input contained an escape sequence that changed the Transact-SQL logic because the input was not properly parsed and checked.
SQL injection should not be a problem for a well-written application and there are some specific tricks (like using QUOTENAME to delimited identifiers). But if you inherit an old application (or maybe a homebrew project that became a corporate application), you should specifically test to see whether it is vulnerable to SQL injection attacks. There are a variety of techniques available to mitigate SQL injection attacks. SQL Server 2008 Books Online has a comprehensive section, starting with the aptly named topic "SQL Injection."

Disaster Recovery
How much you need to worry about this depends on what your downtime and data loss requirements are. (If you haven't already defined these requirements, you should!) Security problems can occur at many levels. There are some concerns when disaster recovery involves failover to another SQL Server or the need to restore a database containing encrypted data.
In the first case, problems occur when the logins necessary to access the database have not been duplicated on the failover server—for instance, when using log shipping or database mirroring. If the database fails over to the mirror instance and the application tries to connect using a specific login that does not exist on the mirror server, the application will receive the 18456 error "login failed". The logins are part of the application ecosystem and must be defined on the instance hosting the database. Knowledge Base article 918992 "How to Transfer the Logins and the Passwords Between Instances of SQL Server 2005" explains how to do this, and I will discuss troubleshooting error 18456 in a moment.
In the second case, problems occur when the database backup contains encrypted data and the encryption key (or keys) used to encrypt the data were not backed up or are not available in the SQL Server instance where the database is being restored. The best case here is that only some of the data in the database is encrypted and so only that subset of data cannot be accessed. The worst case scenario is that the entire database has been encrypted using Transparent Data Encryption (TDE) in SQL Server 2008. In that case, if the server certificate used to protect the database encryption key was not backed up or is not available, the entire database cannot be restored and the following errors will be returned:
Msg 33111, Level 16, State 3, Line 1
Cannot find server certificate with thumbprint
'0xFBFF1103AF133C22231AE2DD1D0CC6777366AAF1'.
Msg 3013, Level 16, State 1, Line 1
RESTORE DATABASE is terminating abnormally.
Of course, that's the point of TDE—that someone happening across a stray backup of the encrypted database can't restore it and access the sensitive data. But if the data is yours, and you need to access it, then you must have the server certificate available or the data is lost.
Encryption is a huge topic in itself and has comprehensive coverage in SQL Server 2008 Books Online, starting with the "SQL Server Encryption" section. You can also watch me demonstrate TDE and successfully restore to a second instance in an accompanying video screencast available at .com/tips.

Auditing
One of the most important things you should do to improve the security of a system is to implement auditing. With this, you'll know who's doing what. This may even be mandatory, depending on the nature of your business.
At the very least, you should audit both failed and successful logins so that you can tell if, for instance, five failed login attempts were followed by a successful one. Then you know when someone is trying to break into your SQL Server instance (and with which login). Figure 5 shows configuring login auditing through the Server Properties dialog box in SQL Server 2005 Management Studio. Failed logins are audited as message 18456 in the error log and the error state gives the reason for the failure. The best description I could find of the different states, as well as a long discussion about troubleshooting them, is in a post from Il-Sung Lee on the SQL Protocols blog titled "Understanding 'Login Failed' (Error 18456) Error Messages in SQL Server 2005."
Figure 5 Confi guring login auditing in SQL Server 2005 Management Studio
Comprehensive auditing of all actions is difficult in SQL Server 2005 (and well beyond the scope of this article). It involves various triggers and SQL Trace. In SQL Server 2008, auditing was vastly simplified with the introduction of a new feature: SQL Server Audit. This is covered in a recent, very detailed white paper titled "Auditing in SQL Server 2008." In the accompanying video screencast, I demonstrate SQL Server Audit. You can get details on the other auditing tools in the SQL Server 2008 Books Online "Auditing (Database Engine)" section.

Summary
That's a lot of topics and a lot of links, but that was the point of this article. I wanted to provide an overview of important security topics that you must consider when you're a DBA who isn't used to dealing with security.
There are some tools that can help you check your system for common security vulnerabilities. The first is the Microsoft Baseline Security Analyzer (MBSA) utility that will check for Windows, network, file system, and even some SQL Server 2000 and SQL Server 2005 security issues. The latest version is Microsoft Baseline Security Analyzer 2.1. Again for SQL Server 2000 and SQL Server 2005 only, there is a SQL Server–specific tool called the Best Practices Analyzer (BPA). This uses a pre-defined list of rules to check your SQL Server configuration and flags any problems (for instance, a blank SA password).
Neither of these tools works with SQL Server 2008. In fact, BPA will not be released for SQL Server 2008 at all and has been replaced, along with the short-lived SQL Server 2005 Surface Area Configuration tool, by the new Policy-Based Management feature I discussed earlier. Part of the reason for this replacement is that BPA and SAC were read-only tools to help you find problems—they could not fix problems. Policy-Based Management offers many corrective choices and it can even be used to target SQL Server 2000 and SQL Server 2005 servers.
Of course, you should always be using Windows Update to ensure that new security patches and service packs are downloaded for you to install at an appropriate time—this is the best way to stay up to date with the latest updates. Installing these without taking downtime is beyond the scope of this article, but some ideas were presented in the December 2006 SQL Q&A column.
If you're trying to find general Microsoft resources on security, there are many destinations that will show up in your favorite search engine. To save you some time clicking around, I'll suggest two key white papers you should read.
"SQL Server 2005 Security Best Practices–Operational and Administrative Tasks" and "SQL Server 2008: Security Overview for Database Administrators."
For SQL Server 2005, the entry point into the security section of Books Online is the topic "Security Considerations for Databases and Database Applications." For SQL Server 2008, the equivalent Books Online entry point is the "Security and Protection (Database Engine)."
As far as takeaways from this article are concerned, I want you to realize that there are some steps you need to go through to ensure the data you are storing in SQL Server is as secure as you need it to be. This is especially important when you inherit a SQL Server instance that someone else has been managing. It's just like buying a house from someone—you need to ask if the alarm works, if the yard is fenced in, and who has copies of the keys. Running through the list I've given in this article is a good start, but make sure you dig deeper in areas that are relevant to you. And as always, if you have any feedback or questions, drop me a line at Paul@SQLskills.com.

Paul S. Randal is the Managing Director of SQLskills.com and a SQL Server MVP. He worked on the SQL Server Storage Engine team at Microsoft from 1999 to 2007. Paul wrote DBCC CHECKDB/repair for SQL Server 2005 and was responsible for the Core Storage Engine during SQL Server 2008 development. Paul is an expert on disaster recovery, high-availability, and database maintenance and is a regular presenter at conferences around the world. He blogs at SQLskills.com/blogs/paul.


Security
Protect Instant Messaging with Forefront Security
Molly Gilmore
At a Glance:
  • Protecting IM with FSOCS
  • Deploying FSOCS in an OCS environment
  • IM message flow and throughput
  • Managing and protecting IM content

Contents
Optimal Antivirus Protection of IM
Deploying FSOCS in an OCS Environment
Securing IM-based File Transfers
File Transfers with External Users
Message Stamping
IM Message Flow within OCS
Managing Message Scan Throughput
Managing and Protecting IM Content
Configuration Examples
Take Away
Forefront Security for Office Communications Server (FSOCS) is a server-based antivirus product that is part of the Forefront Server product line. FSOCS provides effective protection against instant messaging—targeted malware within OCS 2007 and OCS 2007 R2 environments.
FSOCS scans all IM activity—including instant messaging content as well as IM-based transferred files—for viruses and prohibited content. Fine-grained control over where and how this is accomplished is exposed to the administrator through easy to use product configuration options. Real-time notifications of virus threat detections and breaches of policies set around IM content can be enabled within FSOCS so administrators can monitor the security activity within the system. In addition, FSOCS reports and performance counters are available for administrators to evaluate the ongoing health and performance of FSOCS and the security of the Instant Messaging flowing through the OCS infrastructure .

Optimal Antivirus Protection of IM
FSOCS integrates with leading third-party antivirus engines to ensure rapid and consistent responses to new and evolving IM-borne threats. Each instance of FSOCS can have up to five antivirus engines enabled; the OCS Standard Edition, Access Edge, Director, and Front-End servers are all protected by the Forefront Server multi-engine solution.
The antivirus engines are installed on the server with each install of FSOCS, and FSOCS interacts with each engine for IM virus scanning. FSOCS has the logic to evaluate the detection information each antivirus engine provides and to choose the scanning sequence most likely to result in an early, accurate detection of a virus. Administrators decide if they want to virus scan with all five antivirus engines or a subset of the available engines. Administrators do not have to configure or interact with these engines individually, as this is accomplished by FSOCS.
FSOCS includes components to manage the continual updating of antivirus signatures, as well as engine binary updates, so that real-time response to evolving threats is achieved. These update components communicate with a Microsoft-hosted system that constantly polls antivirus partner downloads sites to retrieve, test, and package engine and signature updates 24 hours a day, every day of the year. FCOCS administrators can determine how frequently their installations attempt to retrieve engine updates, but FCOCS handles the process of checking for downloads and installing the updates seamlessly.
In environments where the Forefront Server for Exchange or Forefront Server for SharePoint products are installed, FSOCS can be configured to retrieve updates from a previously configured redistribution server.

Deploying FSOCS in an OCS Environment
FSOCS can be deployed in both OCS 2007 and OCS 2007 R2 environments, and it supports the server specifications recommended for each OCS version. OCS 2007 deployments require Windows Server 2003 SP1 at the minimum, and Windows Server 2003 R2 is recommended. OCS 2007 and FSOCS will run on 64-bit versions of the Windows Server 2003 operating system when running in WOW64 mode. OCS 2007 R2 deployments require 64-bit hardware, as well as Windows Server 2008, Windows Server 2003 (SP2), or Windows Server 2003 R2 (SP2).
FSOCS should be installed on each instance of the OCS Standard Edition, Front-End, Access Edge, and Director server roles in both OCS 2007 and OCS 2007 R2 environments. In Enterprise Edition topologies, FSOCS should be installed on every server located within a Front-End, Director, or Access Edge Server Pool. The diagram in Figure 1 shows FSOCS components installed on each supported OCS server role.
Figure 1 FSOCS Components deployed on each supported OCS server role
The ForefrontRTCProxy integrates with OCS 2007 and OCS 2007 R2 through the Office Communications Server 2007 Server Application API. When FSOCS registers with OCS, it instantiates an MSFT_SIPApplicationSetting object (defined in the .Net Microsoft.RTC.Sip namespace) and sets the "Critical" attribute to true so that OCS will not start up without the ForefrontRTCProxy service running.
The ForefrontRTCProxy communicates with the FSCController to instantiate the FSOCScanner processes. It is the FSOCScanner that manages the virus-scanning calls to the enabled antivirus engines. In the FSOCS Administrative Console on the SETTINGS…General Options panel, the IM Process Count setting determines how many instances of the FSOCScanner get created. Additional instances increase scanning throughput, though at the cost of using more system resources.
Each IM message is routed through the ForefrontRTCProxy and onto an available FSOCScanner, which applies filtering rules first, then passes the message onto the configured antivirus engines to look for any viruses within the IM message or IM-transferred file.
If a filter rule is triggered or a virus detected, the FSOCS IM Notification Agent alerts the IM user that an IM message or file they attempted to send or receive contained a virus or restricted keyword or file type. Notifications are optionally sent to the sender and recipient via an IM session. The notification message content is customizable.
The Forefront IM Notification Agent is itself a client of OCS so that it can establish an IM session with the recipient of the IM notification. (For security reasons, FSOCS cannot insert SIP messages into the IM session it is filtering so it creates its own session with the user).

Securing IM-based File Transfers
By default, IM-based file transfers occur as a peer-to-peer TCP/FTP file copy between two instances of Office Communicator. The SIP messaging used to negotiate the file transfer is routed between the sending and receiving Office Communicators through OCS. Figure 2 shows the sequence of SIP messaging used to set up a file transfer.
Figure 2 Default OCS SIP messaging used to negotiate a file transfer through Office Communicator
The recipient uses the sender's IP address to initiate the TCP connection that will allow the FTP file transfer to occur.
As Figure 3 shows, when FSOCS is installed, the sequence is a bit different. FSOCS filters the SIP messaging in order to redirect the file transfer through the server by storing the original sender IP address and replacing it with the FSOCS IP address.
Figure 3 Modifications to SIP messaging for file transfers once FSOCS is installed
FSOCS uses the stored IP address to connect to the sender's computer and then copies the file to the server. FSOCS scans the file and if the file is clean, allows the recipient to transfer the file from the server to the desktop. If the file transfer fails as a result of a detect action, configured notifications will be sent to the sender, recipient, and/or administrator. No additional configuration to OCS or Office Communicator is needed to enable scanning of IM-based file transfers for internal users.

File Transfers with External Users
If the connection necessary to transfer files between internal and external users is successfully made, IM-transferred files will be protected by FSOCS across the Access Edge. At least one Access Edge server role needs to be available to allow IM with external users and each instance of the Access Edge server role needs to have FSOCS installed. If the administrator wants to facilitate file transfers across the Edge, the firewall should be configured to allow inbound connections to the Forefront application running on each Access Edge server. By default, this uses ports 6891-6900, but the port range can also be configured via two Registry keys: FileTransferStartPortRange and FileTransferMaxPorts

Message Stamping
In an Enterprise Edition topology, a SIP message could be routed across multiple instances of OCS and FSOCS. The first instance of FSOCS that determines a message is clean will add a message stamp to the SIP Message. It does this using the Message.Stamp property of the Message class in the Microsoft.RTC.Sip namespace. The Message.Stamp property can be updated, stored in the SIP message and subsequently passed forward through the SIP message routing sequence. FSOCS uses this property to indicate that a SIP message has already been scanned.

IM Message Flow within OCS
At the core of each OCS server role is an implementation of a SIP Server with Proxy, Redirect, and Registrar services. These services allow the OCS server to receive SIP messages bearing IM content, locate target User Agent End Points such as Office Communicator, and route or forward SIP messages accordingly. FSOCS secures all IM by inserting itself into the SIP message routing flow to scan and filter IM for viruses or other prohibited content so it can block compromised IM from being transmitted. By inserting itself right into the SIP message flow, FSOCS can secure IM with minimal impact on OCS performance.
Figure 4 shows the typical SIP message flow as it is routed across an OCS Enterprise Edition topology with FSOCS installed. IM has been enabled for a federated partner. In this scenario, a user belonging to the federated organization initiates an IM to an internal user. Here is the sequence of events:
  1. 1.The IM entry point is the Access Edge server. The instance of FSOCS on the Access Edge server receives the IM, scans it for viruses and filtering rules and determines it is safe. The IM is stamped as clean and is routed through to the Director server role on its way to the intended recipient's computer on the internal network.
  2. 2.The Director server role has been deployed as recommended to offload user authentication from the front-end servers. This server role is typically deployed on the internal network so that it can access the Active Directory instance storing OCS user configuration information. The IM is routed to this server from the Access Edge. Typically, the internally facing next hop server for an Access Edge is the Director server role. FSOCS checks to see if the IM has already been stamped as clean by an earlier instance of FSOCS and if so, it will avoid processing the message further and will let OCS route it forward.
  3. 3.The IM is routed next to the Front-End server pool. The intended recipient will be homed to one of the Front-End servers in the pool. The instance of FSOCS on the Front-End server that receives the IM will also bypass the IM as it has already been stamped as clean. The Front-End server locates the recipient and routes the IM forward.
Figure 4 SIP message flow in an OCS Enterprise Edition topology
All of this activity is transparent to the end user.

Managing Message Scan Throughput
When deployed within an OCS Enterprise Edition environment, FSOCS provides a mechanism to handle unexpectedly heavy IM activity. In these rare situations, the depth of the queue storing the IM messages to be scanned by FSOCS on a server can increase to the point that an IM message at the end of the queue will not be scanned within an acceptable amount of time.
There are default actions FSOCS will take if this occurs, as well as configuration options available to the administrator for managing the actions FSOCS will take. Since FSOCS is sensitive to the length of the IM message queue waiting to be scanned, a default threshold for maximum IM queue depth has been established to indicate when a queue has grown too large. The action FSOCS takes in response to a queue length threshold exceeded event depends on the server role where FSOCS is deployed. Here are the default actions taken on the indicated server role.
Access Edge FSOCS routes the IM forward unscanned to the next instance of FSOCS, without applying any message stamp.
Director FSOCS routes the IM forward unscanned and unstamped to the Front-End server role. The recipient will not receive the IM unless it has passed through an instance of the Front-End server role.
Front-End FSOCS scans the IM. In the unlikely event that the IM queue exceeds the threshold on this server role, FSOCS will take additional measures to resolve the situation but in the end will drop the message rather than letting it through unscanned.
Note that threshold values can be set on each server role through the MessageOverloadWatermark registry key. The value is stored as a DWORD with the following defaults: 1,000 for Access Edge, 3, 000 for Director, and 10,000 for Front-End server roles.
Message stamping can also be turned off by setting the DisableMessageStamp registry key. This is stored as a DWORD value; the default is 0 but can be set to 1 to disable message stamping.

Managing and Protecting IM Content
FSOCS provides an additional layer of control over the flow of information via IM both internally (between employees within the internal network) and across the network perimeter to external users. Within FSOCS, these controls are put into effect via three different filter types.
File Filters can be configured to prevent certain files from being sent between IM users. Administrators can identify the files they want restricted by specifying file names, file extensions, file sizes, or file types (true file-type detection is included). For example, FSOCS can be configured to block all executable files from being transferred via IM, even if the file extension has been changed from .exe to .txt.
Administrators can further control IM-based file transfers by identifying where a file filter rule is put into effect. File filter rules can be applied to all IM-transferred files or specifically to files sent between internal users, files heading outbound from internal users to external users, or files coming inbound from an external user across the network perimeter to an internal user. For example, FSOCS can be configured to allow all file types to be transferred via IM between internal users but to block all executable files coming from external users to internal users.
Keyword filters can be configured to block IM message content or text-based transferred files from being sent when they contain restricted words or phrases. Keywords or phrases can be defined in any language. In addition, FSOCS comes with an installable profanity list that administrators can optionally use to block offensive language within IM. Keyword filters can also be associated with the direction of the IM or transferred file; internal, inbound, or outbound.
Content filters allow the administrator to block IM or IM-transferred files based on the domain or SIP URI of the IM sender or recipient. By using a wildcard character, IM and transferred files can be blocked for all users of a specified domain.
For example, by configuring "*.unknown.com" within a content filter, all IM from or to users associated with the unknown.com domain will be blocked. IM can also be blocked at the user level by configuring an individual user's SIP URI.
Certain concepts are relevant to all filters within FSOCS:
Detect Actions determine the processing FSOCS will perform on any IM message or transferred file that matches configured filter criteria. For example, a keyword filter in FSOCS can be configured with a detect action of block so that an IM message that contains a restricted keyword will be prevented from reaching any user.
Notifications are the optional alerts generated by FSOCS when a detect action takes place. Alerts can be configured per filter and can always be sent to the administrator. Depending upon the filter type, the IM sender, the recipient, or both can be alerted about a detect action. For example, if a sender attempts to IM a restricted word or phrase, FSOCS can be configured to send an alert to the administrator and to the sender indicating that the IM was blocked due to the restricted keyword.
Notifications are always sent to the administrator via e-mail; senders and recipients receive the notification through an IM conversation initiated by FSOCS.
Quarantine is the repository for IM messages and transferred files that are blocked as a result of a detect action. Administrators have the opportunity to evaluate the quarantined items and resend them through e-mail to the original recipient and others if they deem the content or file to be appropriate.

Configuration Examples
Now let's consider how an administrator can ensure that sensitive or private information that is openly discussed by some employees does not get sent to anyone outside of the company through IM. This is important as OCS has been configured to allow IM with federated organizations and several public IM networks.
One way to accomplish this goal is to configure each instance of FSOCS that is deployed on the OCS Access Edge server role with a keyword filter that blocks any IM message or text-based transferred file containing the restricted words or phrases from being sent from an internal user to an external user. As noted earlier, all IM messages sent from an internal user to an external user are routed across the Access Edge server role before reaching the external user, so FSOCS will block this information at the network perimeter.
On the other hand, if the administrator wants to block offensive information from coming into the internal network from external users that could be transmitted through an IM message or transferred file, the keyword filters should be configured on the instances of FSOCS installed in the internal network on either the OCS Standard Edition or Front-End server roles.
Administrators gain even more control via Allowed User Lists, which provide the option of configuring FSOCS to exclude a set of users from having their IM evaluated against configured filters. Administrator can associate an Allowed User List with the type of filter they wish to bypass. For example, an administrator can configure FSOCS to block all IM from a public IM domain using a content filter, then identify a subset of users (through an Allowed User List) of that public IM domain that are allowed to send and receive IM from internal employees.

Take Away
As IM becomes ever more popular, it is increasingly important that administrators have a way to keep it secure. We hope the summary information presented on what Forefront Security for OCS does, and the additional details around configuration and performance, give insight into how FSOCS can provide confidence to administrators that IM in their organization is secure and within policy.

Molly Gilmore is a program manager working on the Forefront Security Rapid Response Engineering team located on Long Island, New York. In addition to working on the first release of Forefront Security for Office Communications Server, she also works directly with the software vendors who develop the antivirus and antispam engines distributed with the Forefront Server Security product line. Molly holds a Master of Engineering in Engineering Management and a graduate certificate in Quantitative Software Engineering from Stevens Institute of Technology. She started as a software developer in 1991 and worked in different roles and technologies before joining Microsoft in 2006.


Security
Protect E-Mail with Forefront Security
Neetu Rajpal
At a Glance:
  • Installing and configuring Forefront Security for Exchange Server
  • Multiple scanning engines and scanning policies
  • Fighting spam with connection and content filtering
  • Configuring and managing FSE using Windows PowerShell

Contents
Getting Started
Antimalware
Antispam
Show Me the Results
Windows PowerShell
Wrapping Up
The next generation release of Forefront Security for Exchange Server (from here on referred to as FSE) is a premium antimalware (antispam, antivirus, and content filtering) product for protecting e-mail that flows through Exchange server environments. It is integrated with Exchange Server and can scan all e-mail messages that are in transit (moving in, out, or within the enterprise), in use (being read), or at rest (stored in the user's mailbox). The product ships with a default configuration to allow immediate use after installation but can be modified to meet the exact needs of the enterprise.
More information, case studies, and an evaluation version of the product will be available from the Microsoft Forefront Server Security TechCenter after FSE is released later this year.
In this article, I will walk through the features of FSE. I will assume you are familiar with Exchange Server 2007 and look only at the security and content filtering capabilities of FSE installed on the local Exchange Server. I will discuss how you can protect your enterprise from unwanted spam and malware, as well as how to restrict content in your enterprise e-mail using various types of filtering. To navigate through all that technical content, I will use the new simplified management experience for FSE, which is integrated with the upcoming Microsoft Forefront (codename "Stirling") management server. I will not, however, cover Stirling or FSE integration with it.

Getting Started
If you already have Exchange Server set up for your organization, installing FSE is simple. You install the product on the same machine as the Exchange Server; FSE supports the Exchange Edge Transport, Exchange Hub Transport, and Exchange Mailbox server roles. FSE seamlessly plugs into the Exchange environment using the publicly accessible agent architecture and virus scanning API ( VSAPI ). Once installed, the security and filtering policies can be edited via the Forefront Server Security Administrator console, shown in Figure 1. The Navigation pane on the left lets you move to a particular area of the UI to view or edit. The Details pane in the middle displays the configuration information, and the Actions pane on the right is used for executing actions.
Figure 1 The Forefront Server Security Administrator console
Let's look at the Antimalware settings (on the left in Figure 1). In this example, the Antimalware node has three subnodes that can be used to configure the security settings for e-mail at different points:
Mailbox Realtime These settings are for e-mail in use (as it is read). This section is disabled when the local Exchange Server that FSE is installed on is not the Mailbox role. It has been a design assumption for these settings that e-mail is always scanned on its way to the Mailbox, (in transit) using the Hub Transport or the Edge Transport scan settings. But the Mailbox Realtime scan is useful when there is a large lag between the time the e-mail comes into the system and the time the e-mail is read. Since FSE scans malware using AV signatures and heuristics built into the engines, updated engines and updated signatures can make a significant difference in what malware is caught
Hub Transport This section is used for configuring the settings for e-mail in transit (inbound, outbound, and internal). You will see this section only when the underlying local Exchange server has the Hub Transport role deployed. Some enterprises make a decision to forgo the Edge server role and deploy the Hub server role only. Starting with Exchange 2007, all e-mail (inbound, outbound, and internal) is routed through a Hub server. Enterprises that deploy only a Hub server can set all the security settings for e-mail in transit in the Hub Transport section of the Administrator console. Enterprises that deploy both Edge and Hub servers can choose to not rescan e-mail when it gets to the Hub server after passing through the Edge server.
Mailbox Scheduled These are malware security settings for e-mail at rest (e-mail received previously and stored in the user's mailbox). This section is visible only when the local Exchange Server is the Mailbox role. This scan is useful for catching any malware that has slipped through the scans for in-transit mail, as well as for measuring the effectiveness of proposed keyword filter policies. For example, suppose the fictional enterprise Contoso introduces a new policy that prohibits profanity in e-mail. They aren't sure, however, whether this policy is really needed or whether it will be effective. To measure the effectiveness of the policy, the company sets up a keyword filter with FSE and runs a Mailbox Scheduled scan. Then, using this scan, the IT admin scans the e-mail in a few (or many, or all) selected users' mailboxes and generates a report of all the e-mail that would have been in violation of this policy if it was implemented. With this data in hand, Contoso can make a more informed decision regarding the keyword filtering policies for its organization.
Note that there's no Edge Transport node in Figure 1. The Edge Transport section, for configuring the antimalware settings for e-mail in transit (inbound and outbound), is only available when the underlying local Exchange server is the Edge Transport role. In the example in Figure 1, the underlying Exchange server is the Hub Transport role and Mailbox role so the Edge Transport settings are not available. The Exchange Edge role is primarily deployed in the DMZ and used for e-mail hygiene; it is recommended that the security settings be set to the max on this role.

Antimalware
Forefront Security for Exchange uses multiple antimalware engines to find viruses, worms, and spyware. Some engines are signature-based while others have heuristic capabilities. A common request from customers is for guidance on selecting which engines to run for the best detection and performance. With new pre-set options, FSE now makes the process much simpler while also maintaining all the previously available advanced settings for customers who want a higher level of control. You can choose one of the engine-selection policies based on your security vs. performance needs—and all the other engine management settings are automatically decided. Figure 2 describes the different types of scans that the Intelligent Engine Selection section makes available.
Figure 2 The different scanning policy offerings
Policy | Description
Always scan with all selected engines | This is the most secure setting. When this is selected, FSE will scan all e-mail with all the engines that are part of the product. In the likely case that any of the engines or signatures for the engines are updating, FSE will block all e-mail until the updates have finished and FSE is able to use the new engine or signature.
Scan with the subset of selected engines that are available | This setting is slightly less secure. When this is chosen, FSE will scan all e-mail with all engines that are currently available. If all selected engines are available, the e-mail will be scanned by all of them. However, if one of the selected engines is being updated, e-mail will be scanned with the remaining engines and allowed to pass through if determined to be free of malware.
Scan with a dynamically chosen subset of the selected engines | This setting balances between performance and security. A subset of engines will be selected by FSE to scan the e-mail. Choose this setting when you want some extra protection and the value of using multiple engines, but need to take performance into consideration.
Scan with only one of the selected engines | This setting should be picked only when performance is critical and the e-mail has been previously scanned. With this choice, FSE will dynamically select one engine to scan the e-mail.
Enterprises that need precise control over which engines are used for scanning can use the Advanced Engine Management setting at the bottom of the policy page.

Antispam
Spam continues to be one of the most egregious resource taxes for enterprises in terms of e-mail. A disproportionately large number of e-mails received by most enterprises are spam. FSE offers a new premium antispam solution that takes a two-pronged approach—filtering based on both connection and content.
Connection Filtering Before e-mail gets into the enterprise, FSE can make a reputation assessment based on the IP address of the sender. If the IP address is marked as a known spam sender, the connection is refused and the e-mail never enters the enterprise. The reputation-based assessment is supported by an online service that Microsoft maintains. FSE also recognizes that IT and messaging administrators need to be able to overwrite the reputation assessments that FSE makes, so it provides an IP Allow List and an IP Block List. Any IP address on the IP Allow List will not be assessed and will actually be passed straight to the recipient's Inbox. Any e-mail connections from IP addresses on the IP Block List will be rejected without any reputation analysis. Figure 3 shows the Protection Settings for FSE's connection-based antispam filtering.
Figure 3 Antispam connection fi ltering
Content Filtering After the e-mail goes through the FSE Connection Filtering, it gets a second-level spam evaluation based on the content of the e-mail. FSE integrates an industry-leading third-party antispam engine. When content filtering is enabled, FSE assigns a Spam Confidence Level to each e-mail message it scans. Based on the spam confidence level, enterprises can decide to delete the e-mail, quarantine it, or just mark it and deliver it to the user's mailbox where it will end up in the Junk Mail folder.
There are several types of content filters that can be specified via the FSE administrative console. Figure 4 shows what you would see when specifying the file filter policy, which lets enterprises block e-mails with a specific file type. FSE will detect the file type based on binary inspection rather than the filename to avoid danger if a file extension has been changed. Thus, if the enterprise sets a policy for not sharing executables through e-mail, FSE can block executables—even if the sender attempts to bypass detection by changing the name of the file to something like NotExecutable.txt. In addition to file type filtering, FSE can also block files based on the name of the file or a combination of both.
Figure 4 Configuring the file filter

Show Me the Results
Once your settings are configured, FSE will work in the background. The Monitoring section of the Navigation pane can be used to see everything that has been going on with FSE. The Incident pane (Figure 5) lists of all the security incidents and filtering policy matches. There is also a Quarantine pane that shows all the e-mail quarantined by FSE. You can use this pane not only to see which e-mail was blocked but also to deliver e-mail that was previously quarantined.
Figure 5 Displaying security incidents

Windows PowerShell
FSE implements a new, extensive Windows PowerShell layer. All configuration settings, reports, and other options accessible through the UI are also accessible through this layer. The FSE PowershellSnapIn is available from the Forefront Management Shell. You can view the commands available for FSE by typing
Get-Help *FSE*
One of the most useful aspects of using Windows PowerShell it that the commands make it easy to establish the configuration settings for FSE on one server and then transfer them to any other server. After configuring one server, you can export the settings using the Export-FSESettings command, then import to another server using the Import-FSESettings.

Wrapping Up
This article introduces some of the capabilities of the next generation Forefront Security for Exchange Server. With multiple scanning engines and filtering capabilities, the product protects e-mail while allowing you to take performance into consideration. You can also handle configuration and management as you prefer, using either the administration console or Windows PowerShell. I hope this article encourages you to evaluate FSE for yourself.

Neetu Rajpal is the Group Program Manager for the Forefront Sever Security team based in Hauppauge, NY. She has been a software professional for over 13 years and loves building cool software. She spent the early part of her career on all things XML and now works on server-based security software.


Microsoft Office
A Guide to Customizing the Office 2007 Ribbon
Stephanie Krieger
At a Glance:
  • Architecture of an Office Open XML file
  • Steps to creating a custom Ribbon tab
  • Adding VBA macros to the Ribbon
Contents
What's involved in creating a customized Ribbon?
What tools do you need to get started?
Create a custom Ribbon tab
Adding the customUI File to the ZIP Package
Adding VBA Macros to the Ribbon
Getting Creative
Sharing your customizations
Whether you manage a 2007 Microsoft Office system environment, you're a Microsoft Office power user who likes to customize the environment, or you write Visual Basic for Applications (VBA) macros, you'll want to see just how easy it can be to customize the Ribbon for 2007 Office system documents, templates, and add-ins. And all you need is Windows Notepad. In this article, I'm going to show you how.
In order to jump right into creating a custom UI, I am making certain assumptions about your familiarity with the Office Open XML Formats and with VBA. You probably already know that an Office Open XML document is a ZIP package comprised of XML files (known as document parts), other files (such as any media files included in the document), and a handful of folders to organize all these elements. And you've probably seen Office Open XML markup or something similar (even if you've never actually written it). So, you already know that Office Open XML is written in fairly plain language—that is, you don't have to be a developer to get it. Note that I will also discuss VBA in this article because you will probably want to add your own macros (and not just built-in commands) to your custom Ribbon.
If you are not yet familiar with Office Open XML documents, take a look at the structure before you begin customizing the Ribbon:
  1. Create a simple Office Word 2007 document, save the file and close it.
  2. Change the file extension for your new document to .zip.
  3. Open that ZIP package and take a look around. When you first open the package, it should look pretty much like Figure 1.
  4. Open the _rels folder and you'll see a file named .rels. This defines the relationships between the top-level document components that you see here. I'll be editing the .rels file later in this article.
  5. Now open the word folder; you'll see that it contains such items as document.xml (that's the main document body), styles.xml, and other parts that are probably familiar.
Figure 1 The Structure of an Office Open XML Document
You might also see some additional files and folder names depending on the content in your file. For example, you'll see a media folder if your document contains pictures, sound files, or other media.

What's involved in creating a customized Ribbon?
You can make this much more complicated than what I'm about to discuss. But I'm a big fan of using the simplest solution for any task. To add customization to the Ribbon in a 2007 Office system Word, Excel, or PowerPoint file, all you need to do is the following:
  1. Create a file named customUI.xml and add the markup to that file for your customization.
  2. Create a file folder named customUI, place your customUI.xml file there, and then drop the folder into the top-level of your document's ZIP package.
  3. Open the file named .rels and add one line of markup to it to tell the document about your customized Ribbon.
  4. Open the document and bask in the beauty of your creation.
That's all there is to it and I'll show you how to do all of it by the end of this article.

What tools do you need to get started?
You can write your customUI.xml file using Windows Notepad.
There are also two downloads you should grab from the Microsoft Web site for reference: The first is the "2007 Office System Document: Lists of Control IDs", which contains the Ribbon control ID workbooks for all built-in commands in the Ribbon-enabled 2007 Office system programs. The second download is the "2007 Office System Add-In: Icons Gallery", which is a macro-driven workbook that contains the IDs for all of the Office 2007 built-in Ribbon icons.
After you've edited the contents of the package, you need to change the file extension back from .zip to its original extension. But you don't have to keep changing the extension to .zip each time you want to edit the underlying package. Instead, you can use a utility that will recognize your Office Open XML Format document as a ZIP package without ever changing the extension in the first place. There are at least a few of these. One open source option that I like is 7-zip. After you install it, just right-click your Office Open XML Format document, point to 7-zip, and then click Open Archive. You can even edit XML document parts directly in the package, and the archive utility will prompt you to update the package after you save your changes.
Before you begin, there is one more thing you might want to do. There's a setting in the Office applications that you can enable to prompt you if you open a file containing UI errors. Sometimes an error prevents the custom Ribbon from displaying, but not always, so it's helpful to get a warning right away. The error message you see tells you where the error is located, which can also be a timesaver. You can enable this setting in Word, Excel, or PowerPoint (or even Access) and it will apply to all.
  1. In Word, Excel, or PowerPoint, click the Microsoft Office button and then, at the bottom of the menu, click <Program> Options.
  2. On the Advanced tab, scroll to the bottom to find the General settings. Check the box labeled Show add-in user interface errors, and then click OK.
Now go ahead and open Notepad to follow along with this article. Notepad is all you'll need to follow along with the rest of this article. But, if you happen to have Microsoft Visual Studio 2008 handy, don't be afraid to use that. You don't have to write any managed code (or even know what managed code is) to get some pretty cool benefits from using that software to edit Office Open XML document parts. I use Visual Studio 2008 because Visual Studio knows the customUI schema, so it provides IntelliSense menus and automatic syntax checking. This can save a lot of time, and the IntelliSense menus are handy when you're learning the terminology.

Create a custom Ribbon tab
The Ribbon in each applicable 2007 Office system application contains several tabs, each tab contains several groups, and each group may display several commands. Many types of controls are used to display commands, including buttons, galleries, split-buttons, menus, and others.
You can customize any built-in tab (as well as the Microsoft Office Button menu), create your own custom tabs, or even start your own completely custom Ribbon from scratch. Of course, I can't explore every possible type of Ribbon customization in one article, but I will show you quite a lot of the things you can do.
I'll start by creating a simple custom tab for Word that displays a few controls that run built-in commands. In this scenario, I need to create a document template for users and want to start the custom Ribbon with a group of commands that I know the users will frequently need. Of course, I could put them on the Quick Access Toolbar for the template without writing any XML, but I want these commands to be as large as any on the Ribbon and side-by-side with some other custom commands that I'll add to the tab in a bit. Figure 2 shows what the new custom group will look like. Here's the customUI.xml markup I used to create it:
<?xml version="1.0" encoding="utf-8"?>
<customUI xmlns="http://schemas.microsoft.com/
office/2006/01/customui">
<Ribbon>
<tabs>
<tab id="customTab" label="My Custom Tab">
<group id="customGroup1"
label="Helpful Tools">
  <gallery idMso="QuickStylesGallery"
  visible="true" size="large" />
  <button idMso="PasteSpecialDialog"
  visible="true" size="large"
  imageMso="Paste"/>
  <button idMso="CrossReferenceInsert"
  visible="true" size="large" label="Insert a
  Cross-Reference" />
</group>
</tab>
</tabs>
</Ribbon>
</customUI>
Figure 2 A Simple Custom Tab
Let's take a look at the XML structure in this markup.
  1. If you open any Office Open XML document part, you'll see the same first line shown here (see the red markup). It's an indicator of the format being used. Just type it as you see it here. That second line is the tag that defines what type of data is being provided here. That's the customUI tag, and the underlined attribute (xmlns) is a namespace definition that indicates the schema being used. Again, just type it exactly as you see it.
  2. Notice that many of the tags shown here are paired (see the blue markup). You have the start tags near the top: customUI, followed by ribbon, followed by tabs (referring to the set of all tabs on the Ribbon), tab (referring to the individual tab you're working on), and group (the group you are creating). Then, beneath the data for the commands in the new group, you see the end tags in reverse order for each. The paired tags are nested inside one another. Note that each tag is enclosed in angled brackets, the end tag for each pair of tags begins with a slash after the open bracket, and each attribute is followed immediately by an equal sign and then its value inside quotation marks. A small syntax error, such as a missing slash, can keep your UI customization from being displayed.
  3. The commands in this custom group are each inside a standalone tag (see the green markup). They don't require end tags because all the data you need for the command is in this tag—there are no additional tags nested inside of them. So, the slash that indicates the end of the data for the tag comes at the end of each of these tags. Keep in mind, however, that not all Ribbon controls are standalone tags. For instance, if I create a custom gallery to which I add other controls, that would require a paired tag in order to nest other tags. Similarly, a custom menu control is a paired tag inside of which you can add buttons and other controls.
Okay, let's look a bit closer. Every element you add to the structure of your custom UI needs a way to be uniquely identified:
<tab id="customTab" label="My Custom Tab">
<group id="customGroup1" label="Helpful Tools">
Notice that the tag for my custom tab and the tag for the group I created each have an id attribute. You can name it just about whatever you like (but no spaces, please) as long as it's unique within the file. The only other attribute I customized for each of these tags was its label.
Because the three commands on this custom tab are built-in Office 2007 commands, I needed to use the idMso attribute as identifiers, rather than id:
<gallery idMso="QuickStylesGallery" visible="true" size="large" />
<button idMso="PasteSpecialDialog" visible="true" size="large" imageMso="Paste" />
<button idMso="CrossReferenceInsert" visible="true" size="large" label="Insert a Cross-Reference" />
I found these control IDs in the Word Ribbon Controls workbook. There are a few things worth noting about these tags and their attributes.
The first command is a gallery, the other two are buttons. I know this because I've used the features, but you can also find this information in the Ribbon control workbooks for each program (the command type is listed right next to its ID).
The visible attribute is true by default, so technically you don't have to add it, but it's a good idea. You may want to control visibility of commands at some point.
The size command, on the other hand, defaults to "normal" (which looks, for example, like the Cut, Copy, or Format Painter commands on the Home tab in Word, Excel, and PowerPoint). If you want the commands to appear large, you have to add this attribute.
If you take a look at the Paste Special command in one of the 2007 Office system programs, you'll see that it's a normal size command by default. Some commands displayed this way have icons that still look correct when displayed larger, but this isn't one of those. If you leave the custom icon for this control, it will look fuzzy. So, I added the image for the Paste command that you see on the Paste split button on the Home tab. That's the imageMso attribute that you see in the button tag for the Paste Special command.
I also chose to adjust the label for Cross-Reference a bit, as you see in the button tag for that control. By default, it's just Cross-reference, but I wanted to add a bit more information since it doesn't appear on a tab that provides context.

Adding the customUI File to the ZIP Package
Now is the time, if you haven't already, to create a folder named customUI and place the customUI.xml file inside it. I'm going to add this customUI folder to a Word template. Because I also want to include macros in this template that I'll add to the Ribbon, I saved my template as a .dotm file (a macro-enabled Word 2007 template). Keep in mind that you can add a custom UI using the same steps shown here to any Office 2007 Open XML Format Word, Excel, or PowerPoint document, template, or add-in file.
Open the Office Open XML package to which you're going to add your customUI folder and drop it right in. It goes on the top level, alongside the _rels, docProps, and program-specific document folder (i.e., word, xl, or ppt, depending on the document type you're customizing), and the [Content_Types].xml file.
Now open the _rels folder and then open the file named .rels. (If you are not using a utility that enables you to edit the file while it's in the package, you may have to copy it out of the package first.) In this file, you see a nested structure similar to the one in the customUI.xml file. There is a set of relationships in the paired <Relationships … > tag and a standalone tag for each relationship. Each relationship tag contains three attributes: the Id, the Type, and the Target.
Add the following tag for your customUI content to the .rels file, making sure that it falls between the start and end tag for the group of <Relationships …>:
<Relationship Id="rId5"
Type="http://schemas.microsoft.com/office/2006/relationships/
ui/extensibility" Target="customUI/customUI.xml"/>
If the .rels file already contains a relationship tag with the ID rId5, use a different number. The ID needs to be unique.
After you add that information to your file, the file should look something like that shown in Figure 3. If you're using Notepad as an editor and want to view your markup with structure (as shown in Figure 3), you can open the file in Internet Explorer.
Figure 3 My Edited .rels File
If you had to copy the .rels file out of the ZIP package to edit it, copy it back in. Then open the file in Word and check out your work. The new tab (named "My Custom Tab" if you used my example) appears at the end of the Ribbon.

Adding VBA Macros to the Ribbon
It was easy to add built-in commands to the ribbon, but what if you need to add your own tools? Here's what you do.
Open that template file and press ALT+F11 to open the Visual Basic Editor (VBE). If you have not already done so, select your template in the Project Explorer that appears on the left side of the VBE. Then, on the Insert menu, click Module to add a code module to your template. You can then add a simple message box, as shown in Figure 4. (Of course, you can use whatever macro you want.)
Figure 4 Adding a Code Module to the Template
For those of you with more VBA experience, and those who plan to acquire it, note that there are other elements we really should add here for best practices. But none of those elements are critical for the task at hand (which is adding this macro to the ribbon), so I'll skip those tasks for simplicity.
Before leaving the VBE, there is one more thing to add to this macro so that the Ribbon will recognize it. You have to declare it as a Ribbon control. To do that, just add the following text inside the parentheses that follow the procedure name:
ByVal Control as IRibbonControl
Now, the macro looks like this:
Sub TakeABreak(ByVal control As
  IRibbonControl)
MsgBox "Go get some coffee! You deserve it."
End Sub
Note the macro name, because you need to add that to the customUI.xml file. Then, save and close the template.
You can now add this command to your customUI.xml file by adding the following markup wherever you'd like on your custom tab. I've created a new group for this command, which I'm going to place after the first group.
<group id="customGroup2" label="Break Time" >
  <button id="myBreak" visible="true"
  size="large" label="Take a Break"
  imageMso="HappyFace"
  onAction="TakeABreak" />
</group>
When you add this content, be sure to add it after the end tag for the previous group and before the end tag for the custom tab. Or, if you don't want to create a new group, you can just add the button information in its own tag within your existing group.
There are a few things worth noting here.
  • Remember that if you're creating a new group, it needs its own unique ID. I also gave this group a unique label.
  • My new button uses a custom command, so the id attribute is used instead of idMso. In addition to the attributes you know from creating the first group, I've added an onAction attribute. That's the attribute I use to call my macro. The value for that attribute is the macro name.
  • The capitalization you see of any Office Open XML tag names, attribute names, and built-in 2007 Office control names is usually as much a requirement as any other part of the syntax.
  • I selected the HappyFace icon from the Icons Gallery workbook.
After you add your new button, update the customUI.xml file in your ZIP package. There's no need to edit any other files in the package—just open your template. (You will likely need to enable macros when you do this.) Then go ahead and click your new button to give the macro a try.

Getting Creative
Once you have the basics down and have created a custom tab with built-in and custom commands, you can do quite a bit more just by adding various attributes. Here are some examples.
If you want your tab to fall somewhere other than the end of the ribbon, specify that in the tab's start tag, with the attribute insertBeforeMso. For example, to make the tab you've just created the first tab in the Ribbon, place it before the Home tab, like so:
<tab id="customTab" label="My Custom Tab"
insertBeforeMso="TabHome">
You can find the correct name of any built-in tab in the Ribbon Control workbooks for the applicable program.
To add a group to a built-in tab, just add the markup for that tab to your customUI.xml file. It doesn't matter which tab appears first in the customUI file; just be sure to nest the new markup properly. For example, if you place it after your custom tab, it should fall after the end tag for your custom tab and before the end tag for the group of tags ( between </tab> and </tabs>). Here I've added the Break Time group to the Insert tab:
<tab idMso="TabInsert">
<group id="customGroup2" label="Break
Time" insertAfterMso="GroupInsertTa
bles" >
  <button id="myBreak" visible="true"
  size="large" label="Take a Break"
  imageMso="HappyFace"
  onAction="TakeABreak" />
</group>
</tab>
If you're creating a unique template with special requirements and you want to provide only custom commands to the user, you may want to create an entirely custom Ribbon for that template. To do this, in the start tag for the Ribbon (the <ribbon> tag) in customUI.xml, just add the attribute startFromScratch="True" as you see here.
<ribbon startFromScratch="true">
To add a custom command other than a button, the syntax is always the same. If you want to add a split button menu, for example, just keep the rules for paired tags and nesting tags in mind and this customization will be very easy. Say you want to put all of the commands you've added so far onto a single split button menu instead of separate buttons. Try this:
<splitButton id="customSplit1" visible="true"
size="large">
  <menu id="customMenu1" visible="true" >
    <button id="myBreak" visible="true"
    label="Take a Break" imageMso="HappyFace"
    onAction="TakeABreak" />
    <button idMso="PasteSpecialDialog"
    visible="true" imageMso="Paste" />
    <button idMso="CrossReferenceInsert"
    visible="true" label="Insert a
    Cross-Reference" />
    <gallery idMso="QuickStylesGallery"
    visible="true" />
  </menu>
</splitButton>
The result of this is shown in Figure 5. Note that the first button command in the menu becomes the split button default. That's why I reordered the commands for my happy face to be on top. The split button has to be a button control. If Quick Styles (which uses a gallery control) was first, it would have been skipped over for the split button control and that control would have used the first button control in the menu.
Figure 5 A Single Split Button Menu
This is just a sample of what you can do to customize the UI. You can find plenty of help online to take this further, like adding your own custom image to a command or using a VBA macro to conditionally control the behavior of some commands. Check out the Office Developer Center on MSDN for ideas.
To search for help on conditionally controlling the Ribbon behavior, look up attributes such as getVisible and getLabel. The 'get' prefix is used before the attribute you already know when you want the Ribbon to look at a macro for direction on how to behave (referred to as a callback).

Sharing your customizations
You can save UI customizations in any 2007 Office system Word, Excel, or PowerPoint document, template, or add-in. What if you want to install your custom UI so it's available regardless of the document or template being used? This is also quite easy.
In Word, just save the .dotm file that contains your macros and related customUI to the Word Startup folder and it will load automatically when Word starts.
In Excel or PowerPoint, you need to save the file that contains your macros and custom UI settings as an add-in, and then load that add-in. Open the file in the applicable program (enable macros if prompted) and then use the Save As command to save a copy as an add-in. (The add-in file type for an Excel 2007 add-in is .xlam and for PowerPoint 2007 it is .ppam.) When you save the file with that format, it's automatically saved in the Microsoft AddIns folder. Now load it through the <Program> AddIns dialog box, which you find via the bottom of the <Program> Options, AddIns tab. You may be prompted to enable macros the first time you load your add-in–just click Enable Macros. After that, it should load automatically when the program opens.

Stephanie Krieger is a Microsoft Office System MVP and the author of two books, Advanced Microsoft Office Documents 2007 Edition Inside Out and Microsoft Office Document Designer. She also frequently writes, presents, and creates content for Microsoft. You can reach Stephanie through her blog, arouet.net.


Microsoft Excel
Using Excel and Visual Basic for Applications to Create a Game
Greg Stemp and Jean Ross
At a Glance:
  • Using Visual Basic for Applications
  • Intercepting Events
  • Launching Subroutines from Custom Buttons
  • Cheats for Solitaire and FreeCell
Code download available at: StempRossExcel2009_05.exe (817 KB)

Contents
Gaming in Excel
How Word Maker Works
Protected and Unprotected
Within Range
Making a Change
Submitting a Word
Getting Hands-On
For better or worse, people often do things that they'd rather no one else know about. What sorts of things? To tell you the truth, those are things that we'd rather no one else know about.
Wait, here's an example: playing computer games at work. We've all played computer games at work one time or another.
There's a reason why Solitaire has been dubbed the "most-used program in the Windows universe."
Note: You may be wondering if there is any way to cheat in Windows Solitaire. As a matter a fact, there are several ways. For example, if you're playing the "draw three" version, you can hold down Ctrl+Shift+Alt and then click on the deck. Doing that allows you to draw just one card at a time. Or, you can press Shift+Alt+2. This will cause the cards to begin cascading as if you'd actually won the game. (Unless you're running Windows Vista—it looks like the available cheats went away in Windows Vista.) Anyone walking by will think you're a Solitaire master. Assuming, of course, they don't fire you for playing computer games at work.
Speaking of being fired (something that crosses our minds when we're supposed to be writing an article for TechNet Magazine and end up telling people how to cheat at Solitaire), being caught—and then fired—is a common concern for people who play computer games at work. As you might expect, a lot of companies frown on employees playing games during office hours. (Interestingly enough, this doesn't apply to either Jean or Greg. Microsoft believes they do less damage to the company by playing games than they would do if they actually did some work.)
Because of the inherent danger of being caught (and then fired), computer games often feature a "boss button" or "boss key." The idea here is sheer genius—when you hear the boss coming, you press the boss key and the game immediately disappears, being replaced by a bogus ( but very real-looking) Excel spreadsheet. As soon as the boss is gone, you press the key a second time and the game is restored. ( Yes, it would be better if you could click press a key and your boss would disappear. Someday…)
Note: To be fair, we should acknowledge that not everyone plays Solitaire at work. Some people play FreeCell. If you want to cheat in FreeCell, try this. At any point in the game, press Ctrl+Shift+F10. In the dialog box, click Abort. Move any card anywhere (even if it's not a valid move) and you'll automatically win. Or if you're running Windows Vista, try this instead: Press F3, enter -3 in the dialog box, and click OK. Then double-click on any card to win the game.

Gaming in Excel
The boss button is certainly one of the great innovations in the history of computing. But that doesn't mean there isn't room for improvement. We think it's great that a computer game can make a fake copy of Excel pop up on screen. However, we can do better than that—we can write our computer games in Excel. Do that and you won't have to figure out a way to pop up a fake copy of Excel. Instead, a real-live version of Microsoft Excel will already be up and running. And playing your game to boot!
Why would you want to write computer games using Microsoft Excel? Good question. It's possible you might need to create a game to be used for employee training. To be perfectly honest, though, the odds are pretty good that you'll never have a valid business reason for creating a computer game in Microsoft Excel.
On the other hand, computer games do provide a fun way to learn techniques that might be useful to someone who needs to develop a business application of some kind. For example, computer games often have to do things like the following:
  • Respond appropriately when the user clicks on a button or (in the case of a spreadsheet) a particular cell.
  • Prevent a user from typing in data, except when the user is given the OK to do so and that data is typed into a specified location.
  • Keep track of information, both during a session and between sessions.
  • Look up information stored elsewhere, such as in a spreadsheet, a database, or a text file.
That's standard gaming stuff; it's also pretty standard for a business application.
We see that some of you are skeptical. Couldn't you learn how to do these things while writing an Excel application that does a cost/benefit analysis of international hedge fund investment possibilities? Probably, but it wouldn't be anywhere near as much fun. And we don't think it would be as easy, either; after all, you'd likely spend so much time worrying about the hedge fund investment algorithm that you would never get around to figuring out how to carry out some of these other activities.
When you first learn how to play basketball, you don't spend all your time working on double-teaming the dribbler out of a 1-3-1 zone. Instead, you start out by just throwing the ball at the basket. The best way to learn something is to start out by doing simple and fun things.
OK, that makes sense. But why Excel? Wouldn't it be better to learn a true programming language, like C# or C++?
Well, maybe. But to learn a language like C++ you pretty much have to be a full-time developer. If you just want to write simple little applications Visual Basic for Applications ( VBA), the development language included with most Microsoft Office products, is often good enough. On top of that, if you write an application from scratch using C++ or C#, you'll have to figure out how to display items in a table, apply formulas and calculate values, change font sizes and colors, and graph selected data. One cool thing about Excel is that it already knows how to do these things. You don't have to figure out how to draw a graph in Excel. All you really have to do is figure out how to tell Excel to draw a graph then tell it which type of graph you'd like it to draw.
In other words, Microsoft Excel, along with VBA, makes for an excellent environment for simple development projects. And writing a simple computer game makes for an excellent introduction to that environment.
To show you what we mean, we've created a simple word game, which we've dubbed Word Maker 2009. When you start a new game of Word Maker 2009, a random set of 64 letters are displayed onscreen. At that point, your task is to click on some of those letters and create a word. As soon as you've done that, you click the Check Word button and the program checks to see if you've created a valid word. If you have, you're awarded a specified number of points.
Note: In the game, different point totals are assigned to each letter in the word. The points for a given letter are determined by the value of the letter's row times the letter's column. For example, a letter in row 3 column 4 is worth 3 x 4, or 12 points.
If you don't have a valid word, those points are subtracted from your score. You keep making words until you can't make any more. At that point, you click the Done! button and you're, well, done.
Note: Yes, this is way more fun than Halo 3. But let's keep that between ourselves; we don't want the Xbox people to feel bad.
The game, which is designed to run under Excel 2007 (we can't promise it will run under any other version of Excel), looks an awful lot like the screen shown in Figure 1. This doesn't look anything at all like Excel? Well, that was the whole idea.
Figure 1 Word Maker 2009 runs under Excel 2007

How Word Maker Works
That's Word Maker 2009 in a nutshell. We don't have space to walk you through each line of code in the game (even though there aren't all that many lines of code in the thing). However, we've made the game available as a download. You can play the game and, even better, view the fully-commented code.
Still, we can walk you through a few of the more interesting parts of the code, beginning with the subroutine shown in Figure 2. Before we go much further, though, we should note this isn't the complete subroutine. If you download and look at the code, you'll see that we've edited out a few lines. We did that simply so we could focus on one particular task: when you click on one of the letter squares (and only when you click on one of the letter squares) the clicked-on square becomes green. (We told you this was way better than Halo 3!)
Figure 2 Subroutine for selecting a cell
Public Sub Worksheet_SelectionChange(ByVal ObjTarget As Range)
    Sheet1.Unprotect
    Set objRange = Range(ObjTarget.Address)
    Set objRange2 = Range("C5:J12")

    Set objIntersection = Application.Intersect(objRange2, objRange)

    If Not objIntersection Is Nothing Then
If objTarget.Cells.Value = "" Or objTarget.Cells.Interior.ColorIndex = 4 Then
            Sheet1.Protect
            Exit Sub
        End If
ObjTarget.Cells.Interior.ColorIndex = 4
        strCurrentWord = strCurrentWord &ObjTarget.Cells.Value
    Else
        Exit Sub
    End If

    Sheet1.Protect
End Sub
What happens if you click on a cell that isn't a letter square? Nothing. We'll explain how we manage to do that in just a moment.
What if you click on more than one cell at a time? For example, what happens if you drag your mouse across a whole range of cells? Well, that could create problems, especially if some of those cells are letter squares and some aren't. We probably could have written code to separate the valid cells (that is, the letter squares) from the invalid cells. However, that sounded like way too much work. Therefore, we decided to make it so you can't click on more than one cell at a time. If you drag the pointer across a range of cells, nothing will happen. The full subroutine includes these three lines of code:
If Selection.Cells.Count > 1 Then
    Exit Sub
End If
Without going into too much detail, this code simply uses the Count property to see how many cells have been selected. If the Count is greater than 1 (meaning we've selected/clicked on more than one cell), the Exit Sub command exits the subroutine. The net result is like a typical day at Greg's desk: nothing happens.
See? We haven't even started and you've already learned a useful Excel technique you might not have known about.
As for the subroutine itself, you might notice that we named our chunk of code Worksheet_SelectionChange. This just happens to be the same name Greg gave his son. However, we didn't choose this name solely for sentimental reasons; we chose it because Worksheet_SelectionChange is also the name of an event that gets fired each time you click on a new cell in an Excel worksheet. ( In other words, each time the selection changes.) By giving our subroutine the same name as the event, we can effectively "intercept" that event: each time the selection changes, our subroutine runs.
Note: You might be wondering what other events you can intercept in Excel? To tell you the truth, there are too many for us to list in this article. However, you can find information on all the Excel events—as well as all of the Excel objects, properties, and methods—by taking a peek at the Excel 2007 Developer Reference.
Each time the selection changes on the worksheet, our subroutine is called. But we don't just get notified that the selection has change; we also get some detailed information about what has been selected—that's what the parameter (ByVal ObjTarget As Range) is all about. When the Worksheet_SelectionChange event fires, the selected cells are passed to the subroutine as a Range object. What we're doing here is grabbing that Range object and assigning it to a variable named objTarget. Why do we do that? Because that's how we can determine which cell has been clicked on. That, in turn, enables us to tell whether the user clicked on one of the letter squares or not.

Protected and Unprotected
If that's not entirely clear, it will be in a minute. In the meantime, let's take a momentary side trip and talk about this line of code:
Sheet1.Unprotect
Our game has a number of subroutines, including one named Workbook_Open. (As the name implies, this subroutine automatically runs each time the workbook is opened.) We do several things in this subroutine, including randomly assigning letters to the letter squares and hiding UI elements, such as the ribbon, scroll bars, and the status bar. ( Hiding UI elements is another technique you might be interested in, but have had no idea how to do.)
In addition, we also run this line of code:
Sheet1.Protect
What does the Protect method do? Pretty much what you'd expect from something called the Protect method—it protects the worksheet by locking all the cells. This prevents anyone from typing values into the cells, changing the formatting of the cells, or doing much beyond simply clicking on a cell. If you try to type something in a cell, you get a message box telling you the cell "is protected and therefore read-only." (see Figure 3).
Figure 3 Message telling you the cell is read-only
That is how we can prevent people from messing around with our game interface. They can't type data into our game, they can't delete items from our game, they can't do anything that we don't want them to do.
Of course, while we don't want the user doing things like changing the background color of a cell, we do want the game itself to be able to make changes like that. If nothing ever happened, it wouldn't be much of a game. Although, it would be a lot like soccer, wouldn't it?
Note: Jean would like to point out that all you angry soccer fans should send your comments to Greg and not to her. She happens to like soccer. She also says she'd be perfectly happy to have a computer game that didn't do anything.
When a worksheet is protected, even our subroutine can't make any changes to that worksheet. That's why we kick things off by calling the Unprotect method: that method enables us to temporarily unlock the worksheet and make some changes.

Within Range
What kind of changes are we going to make? We'll get to that in just a minute. First, however, we need to talk about these two lines of code:
Set objRange = Range(ObjTarget.Address)
Set objRange2 = Range("C5:J12")
What we're doing here is creating a pair of Range objects. Our first object (objRange) represents the cell that was clicked on; we retrieve that by retrieving the value of the Address property of our object reference ObjTarget. The second object (objRange2) encompasses cells C5 through J12, a set of cells that represents our 64 letter squares.
That brings us to this line of code:
Set objIntersection = Application.Intersect(objRange2, objRange)
Here we're using the Intersect method to determine if our two ranges intersect. ( In other words, is there at least one cell in objRange that is also in objRange2?) If the ranges intersect, a new Range object (representing that intersection) is created. Otherwise, a new Range object is not created.
If you're still confused by the Intersect method, suppose you have a range that contains cells A1, B1, and C1 and another range that contains cells C1, D2, and E1. The intersection is cell C1 because it appears in both ranges.
This line of code (with its admittedly clumsy grammar) checks to see if a new Range object has been created:
If Not objIntersection Is Nothing Then
Suppose a new Range object has been created. That means our two ranges intersect at some point. If the two ranges intersect, that means the user clicked on one of the letter squares—that's the only way the two ranges could intersect.

Making a Change
If we discover that a new Range object has been created, meaning a cell was selected, we run this block of code:
If objTarget.Cells.Value = "" Or objTarget.Cells.Interior.ColorIndex = 4 Then
    Sheet1.Protect
    Exit Sub
End If
objTarget.Cells.Interior.ColorIndex = 4
strCurrentWord = strCurrentWord & objTarget.Cells.  Value
Our first task here is to check to see if the cell has a Value (does it have a letter typed into it?) or if the background color of the cell is green (ColorIndex = 4):
If objTarget.Cells.Value = "" Or objTarget.Cells.Interior.ColorIndex = 4 Then
Why do we make this check? Well, if the cell has no value that means the letter that used to be in that letter square has already been used. It makes no sense to add a blank letter to a word so we skip cells that have no value. Likewise, if a cell has a green background, that means it is already selected. We don't want to allow a player to keep clicking on a cell a million times to add a million copies of that letter to the current word. Therefore, we ignore any cells that have a green background (which we almost always do, game or no game).
If the cell is a valid letter square, we then do two things: we change the color of the cell to green and we add the letter to the end of the current word. After making the changes, we do a little bookkeeping (for example, updating the value of the current word, a task we didn't include in the edited version of our edited subroutine), re-lock the worksheet, and then exit the subroutine.
What if the two ranges don't intersect? Well, that means the user didn't click on one of the letter squares. In that case, we call the Protect method to re-lock the worksheet and then exit our subroutine, all without changing a single cell. The moral of the story: Unless the user clicks on a valid letter square, you shouldn't expect much to happen.

Submitting a Word
After the user has a word spelled out, he should click the Check Word button to see if it spelled a real word.
Note: How did we manage to get a subroutine to run when we clicked a button? In Office 2007, that's a piece of cake. From the Insert tab, we simply clicked Shapes, selected the desired shape, and then drew a button onscreen. After that, we right-clicked the button, clicked Assign Macro, and then selected the desired subroutine.
When the Check Word button is clicked, we run a subroutine named, well, CheckWord. The primary task of that subroutine is to run these two lines of code:
Set objRange = Sheet2.Range("A1").EntireColumn
Set strChecker = objRange.Find(strCurrentWord, , ,  xlWhole)
In the first line, we create a Range object that represents all the cells in column A on Sheet2. In the second line, we use the Find method to search that column for the word. (The word is stored in a global variable named strCurrentWord.) Why would we search column A on Sheet 2? You got it: because column A on Sheet 2 just happens to contain our list of valid words.
You could easily customize this game so that users had to spell Spanish words or Portuguese words, or maybe words associated with an academic subject like biology or chemistry. All you'd have to do is replace the words in column A on Sheet 2 with your own set of words. You could even put different lists in different columns. Column A could hold Spanish words, column B could hold Portuguese words, and so on. A player could then choose which word list they want to use and—well, we're getting a little ahead of ourselves here.
Incidentally, we also make use of Sheet3 in the workbook. That's where we keep track of the 10 highest scores. Each time a game ends we execute this block of code:
Set objRange = Worksheets("Sheet3").Range("B1:B10")
intAnswer = Application.WorksheetFunction. Min(objRange)
What we're doing here is creating a Range encompassing cells B1 through B10 on Sheet3. We then use the WorksheetFunction.Min method to retrieve the minimum value from that set of cells; that's going to be the lowest of our ten highest scores. After that we check to see if the new score is higher than the minimum score. If it is, we have a new entry for the top 10 and we ask the user to enter her name. Then we replace the lowest score in the top 10 with the new score, re-sort the list of top 10 scores, and update the top 10 scores listed on the game page.
That's right: just like a real computer game. And if you're a little more ambitious than we are, you could get really fancy here. For example, you could keep the 10 highest scores per person as well as the ten highest scores overall. You could track the ten lowest scores. You could track the average score. You get the idea.

Getting Hands-On
It looks like we're about out of time for today, even though we've barely covered half of the techniques used in our little word game. But don't despair. Download the fully-commented code and take a look at what we've done—or just play a little. Keep in mind, though, that the game is designed to be played as a game: that means that, when you start it up, it will open in full game-play mode. You won't see anything but Sheet1 and you won't have access to the code. But that's OK.
Here's another useful little tip: If you hold down the Shift key when you open the game, the Workbook_Open subroutine won't be called. Then you'll be able to edit the game to your heart's content. (This also prevents the worksheet from being locked.)
Alternatively, you can start the game in the usual fashion, and then press Alt+F11. That will open up the Visual Basic Editor, and give you a chance to look at—or even modify—the code. Even if that means adding a way to cheat.
Before you ask, here's one way to cheat. Add this code to the beginning of the CheckWord subroutine:
If strCurrentWord = "u" Then
        intWordScore = 1000
End If
Now, click just the letter U and then click Check Word. Just like that, 1,000 points have been added to your score!
Still skeptical? Well, here's one final reason you might want to write games using Microsoft Excel: learning some of these techniques will help you master the gauntlet of challenges you'll face as part of OfficePalooza, the online VBA extravaganza scheduled for April 20th through May 1st, 2009. See the OfficePalooza homepage for details.

Against all odds, Greg Stemp and Jean Ross work for Microsoft.


From the Editor The Perennial Issue
Joshua Hoffman

When have we had a year in the history of Information Technology that we haven't had to talk about security? For that matter, when have we had an issue in the history of TechNet Magazine where we didn't talk about security? It is the one ever-persistent theme. Products, features, technology trends—they all come and go. But security is here to stay.
Of course, just because it's a persistent theme doesn't mean that it's static. The subtleties and nuances of information security are constantly changing with the times, and an argument can be made that they are becoming ever more complex. As the volume of data grows and the lines between our computers and "the cloud" blur, it becomes increasingly difficult to put a fence around the information that's important to you or critical to your business.
But we've never shied away from complexity! This month we present our annual security issue. To start us off, Chris Corio, a veteran of the Windows Security team at Microsoft, takes an exciting look at the security features and enhancements coming with the impending release of Windows 7, and John Morello walks us through the changes to the Public Key Infrastructure (PKI) in Windows 7 and Windows Server 2008 R2. By the way, this is just the beginning of our Windows 7 and Windows Server 2008 R2 coverage. You'll find much more over the coming months at .com, and through the Microsoft Springboard Series at microsoft.com/springboard.
Clearly, security issues aren't confined to the operating system, so there's plenty more. Paul Randal, one of our contributing editors and our resident SQL expert, highlights 10 common security issues in SQL, and of course, their solutions. We also learn about securing what are probably our most common forms of communication—e-mail and instant messaging—with the new Microsoft Forefront line of security software.
And though I know I've just gotten you ramped up to dive into this great security content, I want to take a moment to welcome a new magazine to our fold. The Architecture Journal, along with its editor-in-chief Diego Degum, has joined the MSDN and TechNet Magazine group here at Microsoft. The Architecture Journal covers all matters related to software and IT architecture, so you may well already be familiar with them. But just in case, head over to msdn.microsoft.com/architecture to have a look at their most recent content (which includes some great material on Green Computing). We're excited to have them on board, and you'll surely be hearing more from the Architecture Journal team as our groups continue to work even more closely.
In the meantime, enjoy the annual security issue. As always, feel free to drop us a line anytime with your questions, comments, and feedback at tnmag@microsoft.com.
—Joshua Hoffman
Thanks to the following Microsoft technical experts: Karri Alexion-Tiernan, Niamh Coleman, Eran Dvir, Lambert Green, Devrim Iyigun, Brita Jenquin, Amith Krishnan, Michel LaFantano, Anthony Leibovitz, Michael Murgulo, Sanjeev Nair, Scott Schnoll, Oded Shekel, Sean Siler, Kimberly L. Tripp, and Winni Verhoef.


Toolbox New Products for IT Pros
Greg Steen

The opinions expressed in this column are solely those of the author and do not necessarily reflect the opinions of Microsoft. All prices were confirmed at the time of writing, and are subject to change.

Find SQL Server Instances
Quest Discovery Wizard for SQL Server
quest.com/landing/?ID=1305
There are a number of ways to mitigate your infrastructure's exposure to foreign systems and applications. It can help to hunt down rogue SQL servers (here's hoping you know where your own deployments are) and perform some basic penetration testing against a known set of servers. For this, a simple, free tool from Quest Software can help you out.
In Beta at the time of this writing, the Quest Discovery Wizard for SQL Server is a free graphical utility that lets you scan your network segments for SQL Server instances through a variety of "fingerprinting" techniques. Discovery of SQL Server instances can be done via Active Directory domain or by network segment, and you can specify multiple domains and subnets before starting your search to tackle the network in one go if you so desire. In terms of discovery, you can select from four different attempts: network registry connection, WMI connection, SQL Server login, and general TCP connect. Quest Discovery Wizard allows you to specify and store a list of Windows as well as SQL Server credentials to try against each instance it discovers.
In regard to penetration testing, you can also have the application test for the basic blank SA password as well as try brute force logins from a password list of your choosing. As it detects a server, it tries to glean information about the instance, which it then shows you in the Server Baseline view. Here you see the servers' instance names, domain affiliations, IP addresses, and running port, as well as the version, build, and operating system for the instance. It also indicates the discovery method and whether the server's status has changed since the last time you ran the utility.
As you might have guessed from the name of this view, Server Baseline, you can run the utility for an initial baseline of your environment and then schedule it to scan on a periodic basis. This view will also show you differences through four subviews—Unchanged, Changed, New, and Lost—so you can really keep tabs on changes as they happen.
Once your discovery session has been completed, you can export the results to CSV, XML, or PDF for sharing, reuse, and further analysis. So if you are looking for a simple way to keep tabs on your current SQL Server instances or if you are concerned about new rogue instances popping up in your environment, you might want to take a look at the free Quest Discovery Wizard.

Price: Free
Quest Discovery Wizard for SQL Server

A Scripting IDE
Admin Script Editor Enterprise Edition
adminscripteditor.com
Whether you like it or not, as a Windows system administrator you also have to be a bit of a developer. UIs are great and can simplify tasks, but there are many times when the Windows PowerShell command line (along with a Windows Sever 2008 Server Core installation) can add a lot of power and efficiency. Even if you could achieve the same tasks with a GUI, you wouldn't want to waste the time repeating all the tedious tasks that a well-written script can do at the click of a button. But you may want some help putting together these scripts. One tool that can help you get your scripts up and running quickly is the Admin Script Editor from iTripoli.
Admin Script Editor definitely has the feel of an Integrated Development Environment (IDE). At the center is a script editing text editor. This is surrounded by toolbar actions, tools, links, output panels, and the like. When creating a new script, you can choose from a number of templates based on the type of script you wish to create. There are templates for VBScript HTAs and WSFs, Windows PowerShell, KiXtart, AutoIt, batch files, INI files, registry files, and more. You can also add your own templates, which is handy if there is a particular format you like and repeatedly use.
Once your file is started, you can use another cool feature called ScriptBits to help you quickly generate the tasks you need. ScriptBits are template code snippets that cover control of flow (such as loops and If statements) as well as commonly used tasks such as executing a stored procedure on your database server. Here, too, the ScriptBits are customizable and you can add your own.
Admin Script Editor Enterprise Edition also supports script debugging and break points so you can test your scripts line by line. The output is piped to the UI for verification, allowing you to stay within the editor while verifying the functionality. Another nice feature for systems management is the WMI Wizard, which generates code stubs to update or enumerate the various features of a system that are WMI enabled—which, these days, is everything from performance counters to processors.
As you type your script, the application's ScriptSense feature gives you basic code-assistance and in-line completion so you don't have to remember or look up the exact details of every command as you edit. The application also automatically indents and formats your scripts so you can keep things tidy, making them more maintainable over time.
If you would like to distribute your script in a user-friendly format, you will probably want to use the ScriptPackager feature, which wraps your script in an executable for portability. Then you can use the ScriptDeploy feature to remotely deploy and execute that package (or script) from within the IDE. The Enterprise edition also has the ScriptForm Designer, which lets you create interactive graphical dialogs (otherwise known as forms) by dragging and dropping elements to the form base within the IDE.
For those of you who manage end users in your environment, you will like the Logon Script Build. This gives you that same drag and drop designing for building logon scripts to map printers and shares or show disclaimers and the like to your users as they log on. Meanwhile, the handy XML Wizard can help you connect to and generate code for XML files (such as an exported Event Log).
Admin Script Editor Enterprise Edition is $299 direct. If you don't need the remote script deployment features offered by ScriptDeploy, the ScriptForm Designer, or the direct XML connect capabilities offered by the XML Wizard, you can opt for the $199 Professional Edition. The Standard Edition, available for $99, also strips out the script debugging and ScriptPackager features—both of these, however, can be very useful for testing and designing your administrative scripts.

Price: $299 (direct)
Admin Script Editor Enterprise Edition

Book Review
Windows PowerShell Scripting Guide
microsoft.com/learning/books
Windows PowerShell is a very powerful and extensible administrative interface for dealing with Windows systems in your environment. But it is also very different from the VBScript you may be accustomed to. To help you get up to speed with this command line tool, you might want to take a look at Ed Wilson's book, Windows PowerShell Scripting Guide (2008). More than a guide for the Windows PowerShell beginner, this book gives you a reference that you will be able to go back to even as your skills grow. It covers a breadth of real world tasks suitable for scripted systems management, covering topics from log management to network configuration using Windows PowerShell.
The book starts out with the basics of the Windows PowerShell environment, showing you how to install the shell, giving an overview of the cmdlets and parameterization thereof, and detailing the handy Get-Help, Get-Command, and Get-Member cmdlets. The next chapter covers control of flow for your Windows PowerShell scripts, demonstrating how to use If/Then/Else, Switch, and ForEach type statements, as well as how to define and use variables, constants, and other data types within your scripts.
The book then jumps into real world scenarios and tasks in the next 17 chapters, which provides a good reference for when you need to address various common tasks in your own environment. It teaches you how to manage event logs, services, and shares, delving into how you can enumerate, administer, and document each. It also shows you how to install drivers and manage printers remotely. Then it covers desktop maintenance, exploring how to manage logical and physical disks, monitor disk space, and utilize the performance counters, as well as audit and set (or unset) screensavers and power schemes. It details how to shut down or reboot machines. And it discusses how to report on and manage network adapter settings and the Windows Firewall via remote PowerShell scripts.
The book then shifts into user management, explaining how to create, disable, and modify the attributes of both local and domain users and groups. In addition, it explores managing user data, covering backups, offline files, and system restore.
In regard to servers, the book covers configuration and management of the Windows Cluster Service for high availability. And it explains how to manage App Pools, Web sites, and virtual directories in IIS via scripts.
Then the book delves into managing terminal services, certificate stores, and network services (such as DNS and DHCP).Finally, the last chapter covers the new Windows Server 2008 Server Core configuration and some of the basic management features offered for that cool new option. Throughout these chapters, you will pick up basic skills that you can reuse on almost any script, such as how to read and write files, connect to databases, and use WMI.
The appendices of the book are also worth reading. There is a nice overview on how to structure your scripts so they don't become unmanageable "spaghetti-code," a helpful FAQ for script basics, and a view into the patterned naming conventions of cmdlets. Windows PowerShell Scripting Guide includes a companion CD that contains 317 scripts, many of which you will see referenced throughout the book. These give you a great foundation on which you can create tailored scripts to meet your administrative needs in your own environment.
Whether you're looking to get up to speed on managing your systems with Windows PowerShell or you know how to script but just want a task-oriented reference for managing systems, you should consider Ed Wilson's book, Windows PowerShell Scripting Guide

Price: $49.99 (list)

If you have a favorite tool or utility you would like to see featured here, please write to the author at tntools@microsoft.com.

Greg Steen is a technology professional, entrepreneur, and enthusiast. He is always on the hunt for new tools to help make operations, QA, and development easier for the IT professional.


Exchange Queue & A Recovering a Clustered Mailbox Server, Offline Address Book Issues, and More
Henrik Walther

QOur messaging infrastructure is based on Exchange 2007 SP1. All Exchange 2007 SP1 servers have been installed on Windows Server 2008. We have two datacenters—the primary datacenter and a backup where we can failover should a disaster strike the primary. In our primary datacenter, all Mailbox servers are based on cluster continuous replication (CCR) in order to provide a local high availability solution. For Mailbox server failovers from the primary datacenter to the backup datacenter, we use standby continuous replication (SCR). This means all the CCR-based clustered Mailbox servers (CMSs) in the primary datacenters also act as SCR sources. Each SCR source has corresponding SCR targets in the backup datacenter in the form of standby clusters on which only the passive Mailbox server role has been installed
Recently we did a site failover test between the two datacenters and, unfortunately, we ran into an issue when we tried to recover the CMSs to the standby clusters. When running Setup.com with the /RecoverCMS switch, we got the error message shown in Figure 1.
Figure 1 Setup error when recovering CMS to a standby cluster
I was wondering if you have seen this error while recovering a CMS to a standby cluster and, more importantly, whether you have a resolution for it.
AYes, I had the misfortune of encountering this issue while trying to recover a CMS to a standby cluster. Luckily, this was also during a site level failover test. (Do I need to explain why testing your failover solutions is important?)
One thing that got me thinking was that I had tested the same setup many times before without issues. However, all the previous recovery tests were with Exchange 2007 SP1 installed on Windows Server 2003 and not Windows Server 2008 as was the case when I hit this issue.
This led me to discover how Windows Server 2008 failover clusters work compared to Windows Server 2003-based clusters. In Windows Server 2003, you created and dedicated a cluster service account to the cluster. In Windows Server 2008, you no longer do this; instead, the failover cluster runs under the "Local System." After examining the application and system logs on the standby cluster on which I tried to recover the CMS, I found the error shown in Figure 2.
Figure 2 Recovery error due to inadequate permissions
This event id error explains that the Windows Failover cluster doesn't have the permissions necessary to update the CMS computer account in Active Directory. It also lists three possible reasons. Since we're recovering an existing CMS on a standby cluster, we can ignore the first one. Since we haven't reached any quotas for the number of computer objects, we can ignore number two as well. The last item, however, is quite interesting. It tells us to verify that the Windows Failover cluster on which we recover the CMS has "Full Control" permissions to the CMS computer account object.
A look under the Security tab on the property page of the CMS computer object in the Active Directory Users and Computers reveals that the standby cluster does not have "Full Control" permissions (Figure 3).
Figure 3 The standby cluster does not have “Full Control” permissions
Adding the standby cluster with "Full Control" permissions to the CMS computer object resolved the issue for me and it should do the same in your environment.
At the time of this writing (the end of February), there's no information about this issue at public places like TechNet or in any KnowledgeBase articles. However, my good friend Tim McMichael from Microsoft Customer Support Services has written a blog post on this topic that goes into far more detail than I'm able to do here. So please go check out Tim's blog for more information ("Permissions recommended for the CNO (Cluster Name Object) in Windows 2008 for Exchange 2007 SP1 setup operations.").
QWe're currently in the process of crafting a site-level failover solution. For our Exchange 2007 SP1-based messaging infrastructure, we're going to use standby continuous replication (SCR) as the disaster recovery solution between our primary and backup datacenter. Since only some of our end-users have been upgraded to Office Outlook 2007 with the rest still on Outlook 2003, we've got a question. When a failover of the Exchange 2007 SP1 servers occurs from the primary datacenter to the backup datacenter, will both Outlook versions simply pickup the changes after performing the required SCR site failover steps?
AVery good question and, actually, the answer depends on whether you're using RecoverCMS or Database portability to failover your mailbox servers to the backup datacenter. If you have standalone Mailbox servers in the primary datacenter and replicate these to standalone Mailbox servers in the backup datacenter using SCR, then you would use database portability in order to failover the Mailbo x databases. If you have single copy cluster (SCC) or CCR Mailbox servers in your primary backup datacenter and standby clusters in your backup datacenter, you would use the RecoverCMS switch to recover the whole CMS to the backup datacenter. When using RecoverCMS as the failover mechanism, you typically don't need to worry about Outlook client connectivity after the failover. Do bear in mind that the IP address of the CMS will change. But if you have configured the DNS Time to Live (TTL) value to five minutes according to best practice recommendations, note that there will be a slight delay before the Outlook clients will be able to reconnect to the CMS.
If you're using database portability as the recovery mechanism, the situation is a bit different, depending on the Outlook client version. Outlook 2007 clients will reflect the changes automatically via the Autodiscover service that runs on the Client Access servers. This means you don't have to do any manual changes for this Outlook version. However, that's not necessarily the case with Outlook 2003 clients. When a mailbox has been recovered on another server, the name of the server storing the Mailbox database(s) will obviously be different.
You might wonder, does this matter when you use the Move-Mailbox cmdlet with the –ConfigurationOnly switch after the failover? Yes, it still matters because Outlook 2003 doesn't support the Autodiscover service. This means that the original server where the Mailboxes were stored before the failover must be online so that the server name in the Outlook MAPI profile can be updated. If the original server is offline, the server name can't be updated automatically.
So, if you're facing a disaster where all servers in your primary datacenter are offline, you must reconfigure the Outlook 2003 MAPI profiles using a tool such as the Microsoft Exchange Server Profile Redirector (ExProfre) in combination with a login script to reflect the changes. It's worth noting that if all your clients were located in the primary datacenter, you would need to rebuild them anyway.
QIn our Exchange 2007 SP1-based messaging infrastructure, all our Mailbox servers are cluster continuous replication (CCR)-enabled. We have installed four network interface cards (NICs) in each cluster node. Two NICs have been teamed and are connected to the public network, which accepts Outlook client requests and so forth. The third NIC is used for the heartbeat network between the two cluster nodes in the CCR. The fourth NIC is there specifically for log shipping purposes. Using the Enable-ContinuousReplicationHostName cmdlet introduced in Exchange 2007 SP1, we have (in order to achieve log shipping redundancy) specified that both the heartbeat and the dedicated log shipping network can be used to ship logfiles from the active to the passive node. This works great and really reduces the traffic on the public network, especially in situations where a reseed of one or more Mailbox databases are required (though this should be pretty rare).
We also have SCR enabled between these CCR-based Mailbox servers and multiple SCR targets in our backup datacenter. This leads to our question. Is it possible to use the Enable-ContinuousReplicationHostName cmdlet with SCR?
AI'm glad that the EnableContinuousReplicationName cmdlet has been helpful to you. However, since this cmdlet was specifically created for CCR solutions, the answer to your question is, unfortunately, no, currently this is not supported in an SCR solution.
QWe have just transitioned from Exchange 2003 to Exchange 2007 SP1. All Exchange 2007 SP1 server roles are running on Window Server 2008 and our Exchange 2007 Mailbox servers are based on CCR.
Things work very well so far but we have observed an issue with the Offline Address Book (OAB). When it's updated with new mail objects, the updates aren't reflected in Outlook 2007 at the end users. We have been troubleshooting the issue and have found Event ID 1021 in the Application log on the Client Access Servers with the following description:
Process MSExchangeFDS.exe (PID=xxxx). Could not find directory <OAB share location>
This is normal if the directory has never been generated. Otherwise, make sure this directory
and share has read permission for the "Exchange Servers" group.
We have tried to copy the OAB manually from the CCR-based Mailbox server where it is hosted to the Client Access Server. This results in updates in Outlook, but we would like to get the issue fixed permanently. Do you have the recipe?
AI've been down that road, too. The reason for this problem is because of the way Windows 2008 Failover Clusters behave. Windows 2008 Failover Clusters introduces a new concept called shared scoping. Basically, shared scoping means that a file share is specific to either the node name or to one of the cluster name objects that the share hosts. When a share is shared by the node name, it cannot be accessed by the Clustered Mailbox Server (CMS) name. For more geeky details about file share scoping, see this post on the Ask the Core Team blog ("File Share 'Scoping' in Windows Server 2008 Failover Clusters").
To resolve the issue, you need to install Exchange 2007 SP1 Rollup Update 5 or later, which includes the required bug fix. Also see the article "Exchange 2007 CAS cannot copy the OAB from the OAB share on Windows Server 2008-based Exchange 2007 CCR clusters." Because this Rollup Update brings some regressions with it, it's important you read the Rollup Update 5 KB article closely before using this solution.

Henrik Walther is a Microsoft Certified Master: Exchange 2007 and Exchange MVP with more than 15 years of experience in the IT business. He works as a Technology Architect for Trifork Infrastructure Consulting (a Microsoft Gold partner based in Denmark) and as a Technical writer for Biblioso Corporation (a US based company that specializes in managed documentation and localization services).


Utility Spotlight User Profile Deletion Utility
Lance Whitney

Code download available at: WhitneyUtility2009_05.exe (150 KB)

Over time, the network PCs in your organization may become cluttered with multiple user profiles, especially if they're shared computers used by many people. These profiles and their associated files and documents can easily eat up a sizable chunk of disk space. This is particularly true for accounts that are no longer active or in use. To remove inactive local profiles from computers in your environment, Microsoft offers the User Profile Deletion Utility, which is part of the Windows Server 2003 Resource Kit.
Install the User Profile Deletion Utility by running the downloaded delprof.msi file. No shortcuts are created. Instead you'll find the program installed in the directory C:\Program Files\Windows Resource Kits\Tools. Three files reside there: delprof.exe (the program's executable file), tooldownloadreadme.htm (documentation on how to install and uninstall the software), and delprof.mht (documentation on how to run the program itself).
You can launch the utility directly from its executable in Windows or from the command line. Double-clicking on the delprof.exe file opens a console window that asks if you want to delete all inactive profiles on the PC. Be aware that if you answer yes, the utility will remove all inactive profiles without requiring confirmation for each one. Obviously, that can have unforeseen consequences. Running the program from a command line and using specific options, in contrast, may be preferable as it gives you greater control. From the command line, you can also point the tool to any network PC, so there's no need for sneakernet to run it on your remote clients.
Launching the User Profile Deletion Utility from the command line lets you pass any of the following parameters:
/q—runs the tool in quiet mode so you're not prompted to confirm the deletion of each profile.
/i—does not inform you of any errors that occur.
/p—displays a message prompting you to confirm the deletion of each profile.
/r—removes only cached roaming profiles on the PC but leaves the local profiles alone.
/c:\\computer name—lets you launch the tool remotely by specifying the name of a network PC on which to run it.
/d:days—lets you specify the number of days after which the tool considers the profiles inactive and thereby deletes them.
You can view a list of all parameters by typing delprof /? at the command prompt, as shown in Figure 1. Whichever options you choose, I recommend always running the program with the /p parameter so that you'll be prompted for confirmation. Otherwise, the utility will attempt to delete all inactive profiles, including the admin account and any system accounts. For this reason, you should also exercise caution when deciding which accounts to remove and which to leave alone.
Figure 1 Options you can set for Delprof
The tool will remove all directories and files associated with a specific profile, including desktop icons and settings, Internet Explorer Favorites, program-specific files stored in the Application Data directory, and the My Documents directory. Since the program is run from a console window, the deleted files are not stored in the Recycle Bin. Once removed, the files cannot be undeleted, except possibly by a third-party recovery utility.
You can run the User Profile Deletion Utility on Windows 2000, Windows XP, and Windows 2003 Server. You'll find more details and a download link on the User Profile Deletion Utility (Delprof.exe) page on Microsoft downloads.

Lance Whitney is an IT consultant, trainer, and technical writer. He has spent countless hours tweaking Windows workstations and servers. Originally a journalist, he took a blind leap into the IT world 15 years ago.


Inside SharePoint Integrate Information Rights Management into SharePoint
Pav Cherny

Code download available at: ChernySharePoint2009_05.exe (871 KB)

Contents
AD RMS Production and Preproduction Hierarchies
AD RMS Preproduction Topology
Preproduction Server Configuration
SharePoint IRM Configuration Issues
Preproduction-Specific Issues
Compilation and Registration
IRM Protector Testing
Deploying Custom IRM Document Protectors
Conclusion
Microsoft Office SharePoint Server (MOSS) 2007 ships with protectors based on the Information Rights Management (IRM) framework. These provide Microsoft Office users with the benefit of SharePoint integration with Active Directory Rights Management Services (AD RMS). Unfortunately, Windows SharePoint Services ( WSS ) 3.0 does not include IRM protectors out of the box. However, there is a solution. If you browse the sample applications and code snippets on the MSDN Code Gallery, among the gems you'll find is the Microsoft Office File Format Protectors source code, which Microsoft published in August 2008. The source code comes with a non-exclusive, worldwide, royalty-free "as-is" Microsoft Public License (Ms-PL). This is a great find because it means you can compile the source code and add these components to WSS 3.0 as well. In this way, you can benefit from AD RMS-based security and compliance features in any SharePoint environment.
In this column, I continue last month's discussion about SharePoint integration with AD RMS by showing you how to establish an AD RMS preproduction development environment, compile the IRM protectors, and integrate the compiled components into WSS 3.0. You don't actually need a preproduction environment to compile the IRM protectors, but it's an interesting exercise because it highlights some typical AD RMS configuration issues that you might encounter in a production environment. You don't need to be a C/C++ developer to understand the concepts around AD RMS production and preproduction hierarchies and how they affect the deployment of AD RMS, Microsoft Office, and WSS 3.0. And you don't need C/C++ development skills to compile and test IRM protectors. Developer topics, such as extending the source code or converting integrated protectors into autonomous protectors, are beyond the scope of this article. The only developer task you will encounter concerns the creation of a setup project with a few mouse clicks to simplify the deployment of the compiled protector components on your WSS 3.0 production servers. The May companion material (available on the code download page of TechNet Magazine) includes worksheets and tools that guide you through the deployment, compilation, and test procedures on computers running the x64 version of Windows Server 2008.

AD RMS Production and Preproduction Hierarchies
SharePoint, like any other application that wants to use AD RMS to encrypt or decrypt content, must have a digitally signed manifest that signs the application into the AD RMS hierarchy. This manifest defines those modules that can and cannot be loaded into the address space of the application in order to create a secure environment and protect the unencrypted content in memory. For a manifest to be valid, it must be digitally signed by a certificate authority (CA) that belongs to an AD RMS certificate hierarchy. This can be the production hierarchy with an application-signing CA controlled exclusively by Microsoft, or it can be the preproduction hierarchy that enables developers to self-sign application manifests. Note that a manifest can belong to either hierarchy, but not both. A manifest signed by a production CA is invalid in the preproduction hierarchy and vice versa because the hierarchies have different root authorities. Application manifests are covered in detail in the AD RMS SDK.
When you install the first AD RMS server in an Active Directory forest, you implicitly establish the AD RMS hierarchy. By default, the AD RMS installation routine uses a Microsoft DRM Server Self Enrollment Service CA to issue the Server Licensor Certificate (SLC), which is part of the hierarchy that leads back to the Microsoft DRM Production Root at the root of trust. Figure 1 shows this certification chain, derived from the SLC of a production AD RMS server. If you want to examine the AD RMS hierarchy in your own environment, check out the companion material, which includes the AD RMS Certificate Chain tool (CertificateChain.exe).
Figure 1 The AD RMS Application Signing Certifi cate belongs to the AD RMS preproduction hierarchy.
The Microsoft DRM Production Root establishes the production hierarchy, and Microsoft requires all software vendors to sign a Production License Agreement as a prerequisite to obtaining a production certificate and signing applications into the production hierarchy. The purpose of the production certificate is to create and sign manifests for released applications. For development purposes, you should use a preproduction certificate instead. Originally, Microsoft also required software vendors to sign a Development License Agreement to obtain a preproduction certificate, but a public key (ISVTier5AppSIgningPubKey.dat), private key (ISVTier5AppSigningPrivKey.dat), and the corresponding preproduction certificate (ISVTier5AppSignSDK_Client.xml) are now included in the AD RMS SDK so that you can sign manifests during development without having to contact Microsoft. As a side note, the keys and preproduction certificate are also included in the Microsoft Office File Format Protectors source code package.
Signing an application manifest using the preproduction certificate implies that you can't use the application in conjunction with a production AD RMS server. As Figure 1 reveals, the root issuer in the certificate chain of isvtier5appsignsdk_client.xml is Microsoft DRM ISV Root, which is clearly not the root of a production server. You can examine isvtier5appsignsdk_client.xml using my AD RMS Certificate Chain tool. It follows that you need an AD RMS server with a different SLC that has the Microsoft DRM ISV Root at the root of trust (see Figure 1). To deploy such an AD RMS server, you must establish a separate Active Directory forest for your development environment.

AD RMS Preproduction Topology
With a separate Active Directory forest, it is a good idea to give some thought to the AD RMS preproduction topology. Specifically, you must decide whether you want to install AD RMS on a standalone server or directly on the domain controller. In most cases, a domain controller deployment is sufficient for development purposes. Note that this is not a recommendation for production environments. In a production environment, you must not deploy AD RMS on a domain controller because the domain user account that you specify as the AD RMS network identity would then require domain administrator permissions to log on locally. Logging on locally is an administrator privilege on domain controllers. On a member server, the domain user account doesn't need elevated permissions at all. If you are unsure about the domain controller question in production environments, read Jason Tyler's blog article "The DOs and DON'Ts of RMS." Regarding the idea of putting RMS on a domain controller, Jason says, "This is such a bad idea, that every time I see it, I want to go tell the person to go pick a switch and meet me behind the toolshed."
The next question is whether to install WSS 3.0, Office 2007, and Microsoft Visual Studio 2008 on the domain controller. Here you should definitely use a separate server, even in a development environment. As with the AD RMS issue, the security configuration of WSS 3.0 differs on domain controllers in comparison with member servers. By using a member server, you retain a configuration comparable to a WSS 3.0 production environment, which delivers more reliable results when testing compiled components. Of course, you can keep the domain controller and the member server on a single physical computer if you use Microsoft Hyper-V Server 2008, as illustrated in Figure 2. Hyper-V is 64-bit virtualization technology, so you can use the x64 edition of Windows Server 2008 on both virtual machines. Note that Hyper-V Server 2008 doesn't include graphical management tools, but you can install Hyper-V Server Remote Management Tools on a separate Windows Vista workstation, as outlined in the companion worksheet "Installing Hyper-V Server Remote Management on a Windows Vista Workstation."
Figure 2 A small-scale AD RMS development environment on a Hyper-V host.

Preproduction Server Configuration
Before installing the Active Directory Rights Management Services role, you must configure certain registry settings on the server so that the AD RMS installation enrolls the server in the preproduction hierarchy. If you skip this configuration step, you'll end up with the wrong hierarchy. Keep in mind that you cannot move an AD RMS server between hierarchies. If your server is enrolled in the production hierarchy, you must uninstall AD RMS, delete the AD RMS service connection point (SCP) in Active Directory, configure the registry, and then install the Active Directory Rights Management Services role again.
Figure 3 lists the registry setting that determines the AD RMS hierarchy on a computer running Windows Server 2008. Setting the Hierarchy parameter to 1 enables the preproduction hierarchy. A value of 0 or the absence of this parameter indicates that AD RMS should deploy in the production hierarchy. Additional registry settings exist for backward compatibility, but this is not a requirement in our development environment. For details, see the topic "Configure the Registry" in the AD RMS SDK. The following code can be saved as a registry (.reg) file to enable the preproduction hierarchy on an AD RMS server.
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DRMS\2.0]
"Hierarchy"=dword:00000001
Figure 3 The AD RMS client can’t access the AD RMS server.

SharePoint IRM Configuration Issues
The AD RMS server deployment and configuration is relatively uncomplicated. Trickier is the configuration of the member server running WSS 3.0 to sign SharePoint into the preproduction hierarchy. You can't just start SharePoint 3.0 Central Administration, switch to the Operations tab, click on Information Rights Management, and then select the option Use the default RMS server specified in Active Directory. Clicking OK would result only in the error message displayed in Figure 3. As the message reveals, the AD RMS client (msdrm.dll) is present; it is installed with Windows Server 2008 by default, but the AD RMS server is inaccessible.
Unfortunately, neither error message, nor trace log, nor application event log reveal the true nature of the issue. One option to get more detailed information is to access the URL specified in the Trace log directly in Internet Explorer, for example, https://adrms.litware.com:443/_wmcs/certification. Most likely, Internet Explorer reports a "problem with this website's security certificate" if the preproduction AD RMS server uses a self-signed secure sockets layer (SSL) certificate that the client doesn't trust. To trust the server's SSL certificate, you must install the SSL certificate in the Trusted Root Certification Authorities store on the local computer. Make sure you place the certificate in the physical store of the local computer because you must make the certificate available to all SharePoint security accounts, not just your own user account. The companion worksheet "Deploying WSS01 in the AD RMS Preproduction Environment" describes the steps.
Sometimes, it can be difficult to deal with self-signed SSL certificates. SharePoint determines the URL of the AD RMS Certification Web Service by means of the AD RMS SCP in Active Directory. If that SCP specifies a URL with a host name that differs from the host name in the Web server's SSL certificate, the Web server remains not trusted even after you install the SSL certificate in the Trusted Root Certification Authorities store. Figure 4 shows a common configuration scenario that leads to this issue. The configuration uses an alias in the AD RMS URL that differs from the actual host name. This facilitates server maintenance and disaster recovery because you can't change the AD RMS URL after the deployment of an AD RMS server, yet the CNAME record enables you to point the URL at a different server if necessary. As the four steps in Figure 4 indicate, first, the SharePoint server looks up the serviceBindingInformation attribute of the AD RMS SCP to determine the AD RMS URL. Next, it resolves the host name adrms.litware.com to dc01.litware.com based on the CNAME record. SharePoint then connects to dc01.litware.com, which returns the SSL certificate for dc01.litware.com, and this causes the mismatched address conflict.
Figure 4 The SSL certificate is not trusted due to a name mismatch.
To solve this conflict, issue an SSL certificate for adrms.litware.com on the AD RMS server by using the SelfSSL tool available in the Internet Information Services (IIS) 6.0 Resource Kit. The companion worksheet "Deploying DC01 in the AD RMS Preproduction Environment" includes download information and step-by-step instructions.
Fixing SSL certificate issues is the first step toward a functioning configuration, but a trusted SSL certificate isn't the only requirement. If you attempt to configure IRM without first granting the security account of the Central Administration application pool read and execute access, you receive the error message IRM will not work until the server grants permission. Domain account name used: WSS01$@litware.com. You get this error because the client must call the Certify method of the AD RMS Certification Web Service to obtain a Rights Account Certificate (RAC), which fails due to missing access permissions to the ServerCertification.asmx file. By default, only the AD RMS server's SYSTEM account has access. The recommended solution is to inherit permissions from the certification folder on ServerCertification.asmx and then add the computer accounts of your WSS 3.0 server(s) with read and execute permissions as well. This ensures that all potential application pool accounts have the required permissions. See the companion worksheet "Deploying DC01 in the AD RMS Preproduction Environment" for details.

Preproduction-Specific Issues
At this point, the IRM framework should be functional, except when you are in a preproduction environment. Remember that AD RMS client and applications must use a different certificate chain here. If you attempt to configure the IRM framework in the original configuration, you receive the error "The required Windows Rights Management client is present but could not be configured properly," and the trace log includes another useful hint, "The machine was not activated." This is an indicator that the AD RMS client is still in the production hierarchy. You can verify this in Registry Editor. Check the registry keys HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\uDRM\Hierarchy and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\uDRM\Hierarchy. A value of 0 designates the production hierarchy. Changing these values to 1 activates the preproduction hierarchy. The following code lists a .reg file to apply the configuration changes conveniently.
Windows Registry Editor Version 5.00

 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\uDRM]
"Hierarchy"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\uDRM]
"Hierarchy"=dword:00000001
However, don't be surprised that the registry changes aren't effective immediately. The error remains because the AD RMS client has already generated an incorrect machine certificate during the first unsuccessful attempt and continues to use this certificate. On your WSS server, open the C:\ProgramData\Microsoft\DRM\Server folder and delete all subfolders and files. You might also want to check the %LOCALAPPDATA%\Microsoft folder. If it includes a \DRM subfolder, delete the subfolder because it stores client licenses that aren't usable anymore in the preproduction hierarchy. The AD RMS client recreates these subfolders and certificate files within them as necessary.
Switching back to SharePoint 3.0 Central Administration, try again to configure IRM and don't let the next error message fool you: It's the same error message as before but the error reason is actually different. Check the trace log and you'll find that "There was a problem while creating and initializing a secure environment…" Now this is a manifest issue! SharePoint still uses the production manifest as the AD RMS Certificate Chain tool reveals if you open the Stsprtid.xml file located in the %PROGRAMFILES%\Common Files\Microsoft Shared\Web Server Extensions\12\Bin folder (see Figure 5).
Figure 5 The production manifest doesn’t work in the preproduction hierarchy.
You must delete (or rename) the production Stsprtid.xml file, generate a new manifest by using the Genmanifest.exe tool included in the AD RMS SDK as well as in the Microsoft Office File Format Protectors download package, and then restart IIS. The download package even comes with a SharePoint configuration file (sharepoint.mcf) and batch files (genmft.bat and genmft.64.bat) to simplify this task. Still, the batch file for 64-bit environments only signs Microsoft Office applications into the preproduction hierarchy and skips SharePoint. To sign in SharePoint on a 64-bit server, use the Sharepoint.bat file included in the companion material or use the Genmanifest.exe tool directly. The command syntax is
Genmanifest.exe -chain isvtier5appsignsdk_client.xml sharepoint.mcf
 Stsprtid.xml
See also the Genmanifest.exe page at msdn.microsoft.com/en-us/library/aa362621(VS.85).aspx.

Compilation and Registration
Having replaced the SharePoint manifest file, you can successfully complete the IRM configuration. We have finished the hard part. Now it's time to reap the rewards by compiling and testing the protector components. This is a straightforward undertaking. The source code comes with Visual Studio 2005 projects that you can upgrade to Visual Studio 2008 without problems. However, keep in mind that you are working on a 64-bit server. The Visual Studio projects are configured for a 32-bit environment. You must change this configuration to compile the components for the x64 platform, as illustrated in Figure 6. See also the companion worksheet "Compiling, Testing, and Deploying Microsoft Office File Format Protectors."
Figure 6 To use IRM protectors on a 64-bit WSS server, compile the source code for the x64 platform.
Visual Studio takes care of the COM component registration at build time, but you still must register the IRM protectors in WSS 3.0. Register the components with their class identifiers (CLSID) under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0\IrmProtectors. Here is a registry file that accomplishes this step:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server
 Extensions\12.0\IrmProtectors]
"{2E4402B2-F2DA-4BC8-BB2C-41BECF0BDDDB}"="MsoIrmProtector"
"{81273702-956F-4CBD-9B16-43790558EE29}"="OpcIrmProtector"
You can also check the content of the IrmProtectors.reg file in the companion material. It contains additional keys for informational purposes. I included these keys because the IRM protectors of MOSS 2007 have similar entries. The only difference is that MOSS protectors actually use their settings while our IRM protectors use hard-coded values instead.

IRM Protector Testing
Now that WSS is aware of the IRM protectors, you can restart IIS, open your SharePoint site, configure an AD RMS policy for a document library, and then create, upload, and download documents to verify that the IRM protectors work. However, this can be time-consuming if you are struggling with basic COM registration issues. For example, if you forgot to activate the x64-bit platform in Visual Studio, the compilation process completes without errors, but the COM registration remains incomplete, WSS cannot load the protectors, and you will not be able to test AD RMS protection. You can save time by checking the COM registration first and performing tests in SharePoint only if the registration check shows complete success. Figure 7 shows a basic script to check the COM registration. It simply loads the COM components and displays a message box with the results.
On Error Resume Next
set MsoIrmProtector=NOTHING
set OpcIrmProtector=NOTHING

set MsoIrmProtector=CreateObject("MsoIrmProtector.MsoIrmProtector")
set OpcIrmProtector=CreateObject("OpcIrmProtector.OpcIrmProtector")

IF MsoIrmProtector IS NOTHING AND OpcIrmProtector IS NOTHING THEN
   Wscript.Echo "Unable to load MsoIrmProtector and OpcIrmProtector."
ELSEIF MsoIrmProtector IS NOTHING THEN
          Wscript.Echo "OpcIrmProtector loaded successfully, but
           unable to load MsoIrmProtector."
ELSEIF OpcIrmProtector IS NOTHING THEN
          Wscript.Echo "MsoIrmProtector loaded successfully, but
           unable to load OpcIrmProtector."
ELSE
Wscript.Echo "MsoIrmProtector and OpcIrmProtector loaded
           successfully."
END IF
Figure 7 Make sure IRM protectors are properly registered as COM components before testing the protectors in SharePoint.
On Error Resume Next
set MsoIrmProtector=NOTHING
set OpcIrmProtector=NOTHING

set MsoIrmProtector=CreateObject("MsoIrmProtector.MsoIrmProtector")
set OpcIrmProtector=CreateObject("OpcIrmProtector.OpcIrmProtector")

IF MsoIrmProtector IS NOTHING AND OpcIrmProtector IS NOTHING THEN
   Wscript.Echo "Unable to load MsoIrmProtector and OpcIrmProtector."
ELSEIF MsoIrmProtector IS NOTHING THEN
          Wscript.Echo "OpcIrmProtector loaded successfully, but
           unable to load MsoIrmProtector."
ELSEIF OpcIrmProtector IS NOTHING THEN
          Wscript.Echo "MsoIrmProtector loaded successfully, but
           unable to load OpcIrmProtector."
ELSE
Wscript.Echo "MsoIrmProtector and OpcIrmProtector loaded
           successfully."
END IF
With proper registration settings, the OpcIrmProtector component for Office 2007 document formats is immediately functional. However, the MsoIrmProtector component for legacy Office formats has an additional requirement. The folder that contains the MsoIrmProtector.dll must also contain a \1033 subfolder with template files. The template files come with the source code and are located in the \MsoIrmProtector\Templates folder. You must copy these files into the \1033 subfolder so that the MsoIrmProtector component can include them into AD RMS–protected documents for backward compatibility with Office applications that do not support AD RMS, such as Office 2000 and Office XP. Otherwise, you will not be able to open legacy Office documents. For example, you'll receive the error displayed in Figure 8 when you attempt to create a new Word document in a document library.
Figure 8 Word can’t read this document because the MsoIrmProtector is unable to create the document in proper format without the template files.

Deploying Custom IRM Document Protectors
Congratulations! You have successfully built, registered, and tested custom IRM protectors for WSS 3.0. Now, how do you get these components onto your WSS 3.0 production servers? After all, you must install the IRM protectors on all your servers if you want to use these components in your production environment. Performing the deployment manually would be tedious and error-prone. It's better to build a Setup project, include the DLLs and template documents within the required file structure, import the necessary registry settings to integrate the components into WSS 3.0, and then use the resulting Microsoft Windows Installer (.msi) file for deployment.
It is also a good idea to test the deployment on a reference system. Among other things, such testing reveals important prerequisites you must meet before deploying the components. Specifically, Visual Studio 2008 adds Microsoft .NET Framework 3.5 SP1 dependencies to Setup.exe and the protector components require a Microsoft Visual C++ redistributable package. This is a standard requirement for executables and DLLs compiled with Visual C++. Make sure the redistributable package matches the version you use in your development environment. For example, if you use Microsoft Visual Studio 2008 SP1, then deploy the Microsoft Visual C++ 2008 SP1 Redistributable Package (x64). The companion worksheet "Testing the Microsoft Office File Format Protectors Deployment" demonstrates how to test the IRM protector deployment on a single server.

Conclusion
IRM-based protection of Microsoft Office documents used to require MOSS 2007, but by compiling the Microsoft Office File Format Protectors source code available on the MSDN Code Gallery you can integrate appropriate IRM protector components into WSS 3.0 as well. You can also modify the source code to implement custom features if you have C/C++ skills and have deployed SharePoint in an AD RMS preproduction environment. Keep in mind that your modifications affect all AD RMS–enabled document libraries. I recommend leaving the source code unaltered and checking the MSDN Code Gallery on a regular basis for updates and perhaps new versions with additional features, unless you are a developer looking for a great sample to integrate your own applications with the IRM framework. In this case, the source code is an excellent starting point.
Remember that Microsoft did not design the IRM framework to protect content items in SharePoint databases. You should not change the decryption routines, for example, or your SharePoint users might not be able to open the documents because the IRM framework grants only the application pool account and the current user AD RMS access permissions when protecting the content. Also keep in mind that certain protectors require other protectors to create a fully functional system. For example, the MsoIrmProtector protector for legacy Office document formats and the OpcIrmProtector protector for Office 2007 formats belong together. If you deployed the MsoIrmProtector protector without the OpcIrmProtector, a Word 2007 user might create a new document by using the template.doc content template in SharePoint, while saving the file as Doc1.docx. The MsoIrmProtector protector applies AD RMS protection to template.doc, so Doc1.docx would end up in the document library in rights-protected form because there is no OpcIrmProtector protector to decrypt the content upon upload. The application pool account and the current user would remain the only entities that can open this document. There are other ways to protect documents in SharePoint content databases through AD RMS, such as by using the ISPExternalBinaryStorage COM interface.

Pav Cherny is an IT expert and author specializing in Microsoft technologies for collaboration and unified communication. His publications include white papers, product manuals, and books with a focus on IT operations and system administration. Pav is President of Biblioso Corporation, a company that specializes in managed documentation and localization services.


Windows PowerShell Automating User Provisioning, Part 3
Don Jones

Contents
The Sample Environment
Creating the Folder
Assigning Permissions
In this installment of Windows PowerShell, I am picking up where I left off last month, and continuing to create a script that helps provision new users in an Active Directory environment. If you haven't read the previous installment yet, I recommend that you first read that column before continuing on here.
At this point, I have a master provisioning function that contains four sub functions. The master function looks like this:
Function Provision {
  PROCESS {
    CreateUser $_
    CreateHomeFolder $_
    AddToGroups $_
    UpdateAttributes $_
  }
}
I've already created variations of the CreateUser function. In this installment, I am focusing on the CreateHomeFolder function. I will use this function to create the user's home folder and apply the appropriate access control list (ACL) entries to it.

Windows PowerShell Q&A
Q Does Windows PowerShell distinguish between single quotes and double quotes around strings of characters?
A Yes. With all but one exception, single and double quotes behave identically. That is, both of these commands will assign the string "Microsoft" to the variable $var:
$var = 'Microsoft'
$var = "Microsoft"
However, within double quotes only, the shell looks for the dollar sign ($) character. If it finds it, the shell assumes that the characters following the dollar sign are a variable name, and it'll replace the variable with that variable's contents:
$var1 = 'Windows'
$var2 = "Microsoft $var1"
After running these two commands, $var2 would contain "Microsoft Windows" ($var1 was replaced with its contents). As a best practice, stick with single quotes unless you explicitly need this variable-replacement feature.
The Sample Environment
Like all of the child functions called by the Provision function, CreateHomeFolder is accepting a hashtable as its input. Since creating a home folder only really requires me to know the user's logon name, I can use the ['samAccountName'] hashtable key. I used this key in last month's article, as well, since the samAccountName attribute is required when creating a new Active Directory user account.
I also need to know where the home folder will be created, and I need to have network access to that location. For this example, I will assume that user home folders are all stored on a specific server, based upon the user's logon name. For example, everything starting with A through D is on server HomeFolders1, while folders for E through H are on HomeFolders2. Using this structure, my example should provide a structure that you can expand on to work within your own environment. For this discussion, I'm not going to worry about users whose names start with I through Z—the pattern will be evident, and I'd like to keep the example simple and conserve some space.
In my sample environment, each of these servers has an administrative share called $Homes, which includes all of the user home folders. And I'll assume that administrators have the ability to create new folders and that my script is being run by an administrator. Finally, I'll assume that all of the servers involved are either in the same domain, or are in trusting domains, so that they will trust the administrator account that is being used to run the script.

Creating the Folder
Creating the folder is relatively easy. First, I need to decide which server I will create the folder on, like so:
Function CreateHomeFolder {
  Param($userinfo)
  $server1 = 'a','b','c','d'
  $server2 = 'e','f','g','h'
  Switch ($userinfo['samAccountName'].    substring(0,1).tolower()) {
    { $server1 –contains $_ }
      { $homeserver = '\\homeserver1\'; break; }
    { $server2 –contains $_ }
      { $homeserver = '\\homeserver2\'; break; }
  }
}
So what exactly is happening here?
  • First, I create an array of letters that each home folder server supports. For this example, I've created two arrays, $server1 and $server2, and assigned them the letters I've decided they will host. This approach makes it easy for me to change letter assignments in the future, as well as to add more servers if necessary.
  • I then use the Switch construct to evaluate a series of possible conditions. I evaluate the first character of the user's samAccountName attribute, after converting the character to lowercase.
  • For each home server that I have, I add a condition to the Switch construct. The condition checks to see if the first letter of the user's samAccountName (which is contained in the special $_ variable at this point) exists within that server's array of letters. If it does, then the $homeserver variable is populated with the start of a Universal Naming Convention (UNC) path for that server. The "break" keyword prevents further conditions from being evaluated once I've found the correct server. Note that, as written, this example will not work for users whose names start with letters I to Z—you would need to add conditions for that range of letters.
Next, I simply have Windows PowerShell create the folder, so the function now looks like this:
Function CreateHomeFolder {
  Param($userinfo)
  $server1 = 'a','b','c','d'
  $server2 = 'e','f','g','h'
  Switch ($userinfo['samAccountName'].
    substring(0,1).tolower()) {
    { $server1 –contains $_ }
      { $homeserver = '\\homeserver1\'; break; }
    { $server2 –contains $_ }
      { $homeserver = '\\homeserver2\'; break; }
  }
  Mkdir ($homeserver + '\$Homes\' + $userinfo['samAccountName'])
}
The MkDir command—which is actually a built-in function that utilizes the New-Itemcmdlet—accepts UNC paths. So I'm combining the correct home folder server name with the $Homes administrative share and the user's samAccountName. If the user's samAccountName is DonJ, then MkDir will create \\server1\$Homes\DonJ.

Assigning Permissions
The new folder will, by default, inherit the permissions of its parent folder. So for this example, I'm assuming that the parent folder has the proper base permissions that I would want to assign to any new user home folder. For example, that permission might assign Full Control to the built-in System account, as well as to the Domain Admins group or the local Administrators group, but that permission probably would not include any other users. So all I need to do now is make sure that my new user account has permissions for the home directory I just created.
Now, please don't get mad, but I have to say that this is not a task for which Windows PowerShell is currently well-suited. I know, I'm sorry. It's just that Windows file permissions are terrifically complicated little beasts. You have an access control list (ACL), which contains access control entries (ACEs). Each ACE combines an allow/deny flag, permissions (such as Read or Write), and the GUID of a security principal (such as a user or group). This is a lot of information that has to work together.
The shell does offer Get-ACL and Set-ACL cmdlets, but modifying an ACL requires you to get the ACL, mess around with Microsoft .NET Framework objects to modify the ACL, and then drop the modified ACL back onto the file or folder. It's a little too low-level for my tastes. I could potentially use Windows Management Instrumentation (WMI), but that would work in pretty much the same way.
Fortunately, Microsoft has wrapped up a lot of that complexity into a convenient, easier-to-use tool called Cacls.exe, which I bet you're familiar with, as it's been around forever. Using it will not only save me some unnecessary effort, but will also demonstrate how Windows PowerShell works perfectly well with external command-line tools (Cacls, Ping, Ipconfig, and so forth). If you already know how to use one of these tools, please keep using it in Windows PowerShell. One of the most important concepts with Windows PowerShell is that you don't have to relearn everything from scratch.
(By the way, I know Cacls.exe is deprecated. It just has a slightly simpler syntax than the replacement ICacls.exe, so I'm using it. You can tweak this to use ICacls.exe if you like.)
Going by the help file for Cacls.exe, I find that I need a command that looks something like this:
cacls \\server1\homes\DonJ /e /g DOMAIN\DonJ:R
cacls \\server1\homes\DonJ /e /g DOMAIN\DonJ:W
This will assign Read and Write permissions to our new user, without overwriting the other permissions already on the folder.
One problem, however, is that I want to use variables in this command, rather than static values. Putting shell variables into external commands can be tricky sometimes. There are a number of approaches, but the one I like is to create the entire command string in a shell variable and then use Cmd.exe to execute that string. It looks like this:
$cacls1 = "cacls "+$homeserver+"$Homes\"
  +$userinfo['samAccountName']+" /E /G "
  +$user+":W"
$cacls2 = "cacls "+$homeserver+"$Homes\"
  +$userinfo['samAccountName']+" /E /G "
  +$user+":W"
cmd /c $cacls1
cmd /c $cacls2
Granted, this may not be the prettiest thing in the world, but it gets the job done. It also accomplishes my ulterior motive of demonstrating how complex external command-line tools can be parameterized using shell variables. I can drop these four lines of code right into my function after the MkDir command and the function is complete.
All I have left to do at this point is to create the last two functions in my master Provision function: AddToGroups and UpdateAttributes. I will show you how to do that in the next installment of the Windows PowerShell column.

Don Jones is a co-founder of Concentrated Technology (ConcentratedTech.com), where he blogs weekly about Windows PowerShell, SQL Server, App-V, and other topics. Contact him through his Web site.


Geek of all Trades Control Network Access Using DHCP Enforcement
Greg Shields

Contents
The Goals for a NAP
Implementing DHCP NAP to Enforce WSUS Updates
Those darn users are getting smarter all the time. They've figured out how to turn off their firewalls—always on the nastiest of coffee-shop networks. They keep their laptops away from the office during your monthly patch cycle, because they believe your patches caused their last blue screen. They even disable antivirus and anti-spyware utilities at the slightest hint of a slowdown in performance. Your users take these steps because they think they're helping themselves, when in fact they're hurting the security of your business' network.
A correctly configured and patched computer is a healthy computer, but keeping those computers healthy is a hassle. If only there was a way you could enforce your security policies. Enforcement guarantees that your desktops and laptops have the right firewall configuration. Enforcement assures that computers that lack the right patches can't access your network. Enforcement means that not running antivirus or anti-malware means not connecting to your pristine LAN.
That kind of security policy enforcement is available today with Network Access Protection ( NAP ). NAP is a component that arrives with Windows Server 2008 Network Policy and Access Services. It uses services on both servers and clients to routinely check the status of a client's compliance to your security policies. If those clients aren't configured properly, NAP can automatically restrict their network access until they are remediated. Even better, NAP can automatically remediate the bad clients, forcing those with bad configurations back into line with established security policies.
NAP is a powerful tool that is considered a best-in-class solution by independent analysts like Forrester, who positions NAP in its upper-right "leaders" quadrant. It is a cost-effective solution, because implementing NAP in your network today requires no extra software purchase as it is already a part of your Windows and Active Directory investment. NAP's functionality is already available with every edition of Windows Server 2008. It is designed for massive scalability and is capable of supporting large enterprises with complex needs and scores of clients.
But if NAP is so great, why don't more small environments take advantage of it? Likely, many jack-of-all-trades administrators either aren't aware of what it can do, or are put off by its apparent complexity. That's understandable. If you read through the documentation on NAP, you could be overwhelmed by all the moving parts required for its different mechanisms for enforcing security configurations. IPSec, 802.1x, VPN, and TS Web Access are all NAP enforcement mechanisms that require extra components you might not have in your environment today. However, it is likely that you already have what you need to implement its DHCP-based enforcement.
It is that easy-to-install and easy-to-use DHCP enforcement mechanism I want to show you in this month's column. While each of the others are admittedly more powerful in how they assure client configurations, each also requires more-complex technologies, such as certificate services infrastructures, or deep knowledge of network devices to implement successfully.
Let's start small, and work our way up.

The Goals for a NAP
Before we get into the click-by-click, let's consider some of the goals you probably have for securing your network. You want to ensure that computers are updated with the right patches. You want your on-the-road laptops to get the right security settings when they return. And you certainly need to defend against rogue computers plugging into your network and infecting your servers and workstations.
If all of these goals are met, if your computers are correctly patched and have the right firewall and anti-malware settings, you can generally consider the machines to be healthy. Healthy computers tend to have the right protections in place to stay healthy, and they probably aren't spreading malware around your network.
NAP's job is to monitor and enforce the health of the machines on your network. When a computer plugs in, NAP asks the question, "Are you healthy?" If the computer responds in the affirmative, NAP grants that computer full access to your network. If the client can't answer or answers in the negative, it is instead relocated to a special "remediation" network. There, the only resources available to the computer are those necessary to make it healthy again: a Windows Server Update Services (WSUS) server for applying patches, an antivirus server for downloading the most-recent signature files, and so forth. NAP can also watch the computers on your network, recognize when their health degrades, and quickly fix them when it does.
NAP's enforcement mechanisms are related to the ways in which computers gain access to your network. Computers connect to your 802.1x-capable network switches or wireless access points for a physical connection. They then request an address from your DHCP server. Outside computers may connect through a VPN server or a TS Web Access Web site. Communicating with your domain may require IPSec authentication.
As noted, NAP's DHCP enforcement mechanism is the easiest to configure and use; essentially, your DHCP server becomes NAP's gatekeeper. Computers that connect to your network must first request an address from DHCP. This is where the "Are you healthy?" question is asked by the NAP-enabled DHCP server. If the computer responds correctly, DHCP gives it an address with full network access. If the computer doesn't know how to answer or if it answers incorrectly, DHCP instead gives it a special address for remediation.
To further simplify our example, I'll instruct NAP to only monitor clients for WSUS patches. In this case, clients will be considered unhealthy only when they aren't talking to WSUS or don't have the right patches. As you'll discover later on, I can do this because Microsoft includes a built-in Security Health Validator that enables these checks to be run.
Determining a computer's health with that built-in Security Health Validator requires that two client components work together, the NAP client, which is natively available with Windows Vista, Windows Server 2008, and Windows XP Service Pack 3, and the Windows Security Center, which is available in the Control Panel (see Figure 1). Whereas the NAP client's job is to interface with the NAP server infrastructure, determine the client's state, and do the actual enforcement, it is the job of the Windows Security Center to identify and report when security configurations are out of whack. We'll configure both client pieces as well as the server components in the next section.
Figure 1 The Windows Security Center

Implementing DHCP NAP to Enforce WSUS Updates
Let's assume your network and domain are already in place, and your environment includes a Domain Controller named \\server1. You also have a Windows Vista laptop named \\client1 to use in testing your NAP implementation. You have just built a Windows Server 2008 computer named \\nps that will host your DHCP and NAP services. It will also host your WSUS database, as it will later operate as the remediation server for computers that are missing patches. In this example, I am collocating each of these services on the same computer, but it is possible to locate each on its own computer. For DHCP enforcement to work, you must run it on top of Windows Server 2008.
On the server \\nps, use Server Manager to install the DHCP Server, Network Policy and Access Services, and WSUS roles. Configure DHCP with a small scope for testing and configure WSUS with the necessary configuration that makes sense for your environment.
Next, create a Global Group in your domain called NAP Client Computers. In this group you will later add the names of the computers whose health you want NAP to monitor. For this example, that computer will be \\client1.
NAP's DHCP enforcement can hand out addresses in a completely different and isolated subnet to unhealthy computers, but for simplicity we will only change the computer's DNS domain name. Here, DHCP will tell healthy computers their DNS suffix is contoso.com, while unhealthy computers will instead get unhealthy.contoso.com. Be aware that this keeps the example simple, but doesn't necessarily isolate unhealthy computers. Once you understand the basic concepts, you can later go back and implement subnet isolation.
Configure your DHCP scopes with the above DNS suffixes. Do this in the DHCP console by right-clicking on Scope Options and choosing Configure Options. In the resulting window, click the Advanced tab where you'll see two user classes of interest. The Default User Class represents your set of healthy computers. These computers should get full access and the contoso.com DNS suffix under option 15. The Default Network Access Protection Class represents your unhealthy computers, and should get the DNS suffix unhealthy.contoso.com for option 15. You should probably also enter information for your DNS server under option 6 and default gateway information in option 3. When all that's done, the result should look similar to Figure 2. At this point you can NAP-enable the DHCP scope by right-clicking the scope itself and viewing Properties. Under the Network Access Protection tab, click Enable for this scope.
Figure 2 DHCP’sDefault NAP Class must be confi gured
This completes your configuration of DHCP services. The next step is to configure NAP itself using the Configure NAP wizard. Find the link of the same name in Server Manager's right-pane when you navigate to Network Policy and Access | NPS ( Local ). For this example, configure the wizard's multiple pages as follows:
Select Network Connection Method for Use with NAP. Select DHCP for your Network connection method. The wizard will then automatically populate the Policy name box with NAP DHCP.
Specify NAP Enforcement Servers Running DHCP Server. If your DHCP services were on different servers than your NAP server, you would enter those server names here. For our example, NAP and DHCP are collocated, so you can safely leave this box empty.
Specify DHCP Scopes. Enter the DHCP scopes you intend to enable for NAP. By leaving this box blank, all DHCP scopes are used.
Configure User Groups and Machine Groups. In this dialog box, add the NAP Client Computers Global Group you created earlier. This instructs the NAP policy to manage enforcement for only the computers in this group. Other computers are left alone.
Specify a NAP Remediation Server and URL. This page accomplishes two things. First, it identifies the remediation servers charged with fixing unhealthy clients. In this example, the remediation servers will be \\server1 for domain services and \\npsfor WSUS services. Click the New Group button and create a new group that includes these servers. Second, the page exposes a Troubleshooting URL. This URL is displayed in a balloon tip on unhealthy computers that are remanded to your isolated network for remediation. The Web site, which you must build yourself, can contain instructions on what is happening to the client or instructions for manual remediation. For this example, we'll leave the URL blank.
Define NAP Health Policy. This final screen displays a link to the Windows Security Health Validator, which will be customized next, and provides settings for auto-remediation and network access restrictions. Leave the default settings for each of these here.
The next step is the fun part. Here, you need to configure the components of the Windows Security Health Validator ( WSHV ) you want to use for enforcement. The default WSHV includes a number of Windows Security Center components that can be monitored.
Windows firewall. Is there a firewall on the system that has registered with the Windows Security Center? Is that firewall enabled for all network connections?
Virus and Spyware Protection. Are antivirus and anti-spyware applications installed on the computer, and have they been registered with the Windows Security Center? Are their applications turned on and currently using up-to-date signatures? The WSHA treats antivirus and anti-spyware applications separately, allowing you to enforce either or both on targeted systems.
Microsoft Updates. Has the computer been configured to check for automatic updates either through Windows Update or a local WSUS server? If so, how many hours ago did the computer check for updates? Are all available updates installed? What level of update criticality—important, critical, and so on—must be installed for a computer to be considered healthy?
In Server Manager, navigate to Network Policy and Access Services | NPS (Local) | Network Access Protection | System Health Validators and double-click the Windows Security Health Validator. In the resulting screen, click Configure to see a screen like the one in Figure 3.
Figure 3 The default Windows Security Health Validator
Select the areas you want NAP to manage. Note that any third-party firewalls, antivirus, or anti-spyware applications must register with the Windows Security Center or provide their own add-on components to be monitored by NAP. For this example, we'll check only the boxes indicated in Figure 3. This instructs NAP to ensure that Automatic Updating is turned on for all client systems and that all Critical updates are installed. If a client cannot meet both conditions, it will be automatically moved to the remediation network where the WSUS server can automatically resolve the problem and bring the computer back to health.
Finally, there are three settings to be configured that are applied through Group Policy. Create a new Group Policy Object (GPO), link it to the domain, and open it for editing.
  • Enable the Network Access Protection Agent and set it to Automatic. Do this under Computer Configuration | Policies | Windows Settings | Security Settings | System Services.
  • Enable NAP's DHCP Quarantine Enforcement Agent, which you'll find under Computer Configuration | Policies | Windows Settings | Security Settings | Network Access Protection | NAP Client Configuration | Enforcement Clients. Double-click the agent and in the resulting screen choose to Enable this enforcement client. To apply this setting, right-click on the NAP Client Configuration node and choose Apply.
  • Enable the Windows Security Center found in Computer Configuration | Policies | Administrative Templates | Windows Components | Security Center.
One final step: Close the Group Policy Management Editor and in the policy's Security Filtering, replace Authenticated Users with the NAP Client Computers group created earlier. You can now begin adding domain computers to the NAP Client Computers group to start their participation in NAP enforcement. Once Group Policy applies to the computers, their interactions with DHCP will involve the NAP health checks we discussed here.
You can verify NAP client status using napstat.exe. Running this tool from a command line results in a system tray icon as well as a balloon tip that provides information about the client's enforcement status. Clicking that balloon displays a status window like the one in Figure 4, which indicates that the client is not compliant because it has not installed the proper security updates. At this point, because NAP has identified the client as unhealthy, DHCP will have renegotiated its lease and changed the DNS suffix to unhealthy.contoso.com.
Figure 4 An unhealthy NAP client without the proper security updates installed
There are obviously many more ways in which you can tailor your NAP implementation to provide additional security. Creating a completely isolated remediation network for unhealthy clients is one option. Configuring additional enforcement parameters in the WSHV or adding new third-party SHVs are others. If you dig around in the Network Policy and Access Services node in Server Manager, you'll find a host of additional options for customizing NAP to meet your needs.

Greg Shields, MVP, is a partner at Concentrated Technology. Get more of Greg's Jack-of-all-Trades tips and tricks at www.ConcentratedTech.com.


Hey, Scripting Guy! Working with Access Databases in Windows PowerShell
The Microsoft Scripting Guys

Databases are mysterious pieces of software. In their simplest form they are nothing more than filing cabinets for storing information. The real magic begins with the application of this stored information. Of course, the most beautifully designed database without any records is nothing more than an academic exercise. It is the data that makes the database. Whenever we hear about someone who has a huge database, people react with awe. Not due to the database, but for the data it contains.
How does all that data get into a database? Manual entry of data into a database is for the birds, and it went out with key punch cards. To build a database large enough to impress your friends and provide the potential to unlock the mysteries of your network, you must automate. Today, that means Windows PowerShell, and in this article, that's what we will use to collect some data about the local computer and write it to an Office Access database called ComputerData.mdb. This database can be created by hand, or you can use the script found in the article "How Can I Create a Database with More Than One Table?." We will call our script WriteToAccessDatabase.ps1 so we will know what it does.
We'll start by creating the Check-Path function, which will be used to ensure that the database exists. To create the function, we use the Function keyword, give the function a name, and define any input variables it may need to receive. The first thing Check-Path does is use the Test-Path cmdlet to see if the directory in the database path exists. To do this, it uses the Split-Path cmdlet to break the path into a parent portion and a child portion. We only need the parent portion of the path to verify the directory's existence. Here's how we use Split-Path to retrieve the parent path:
PS C:\> Split-Path C:\fso\ComputerData.mdb -Parent
C:\fso
Instead of checking for the presence of the path, we use the Not operator (!) to look for its absence. If the folder does not exist, the Throw keyword is used to raise an error:
Function Check-Path($Db)
{
 If(!(Test-Path -path (Split-Path -path $Db -parent)))
   {
     Throw "$(Split-Path -path $Db -parent) Does not Exist"
   }
Even if the folder exists, the database file might be missing. We use the ELSE keyword to introduce that alternate condition. Once again, we use the IF statement to look for the presence of the database file, and the Throw keyword to raise an error if it doesn't exist:
ELSE
  {
   If(!(Test-Path -Path $Db))
     {
      Throw "$db does not exist"
     }
  }
} #End Check-Path
We really don't need to use the IF…ELSE construction to verify the existence of the database. A simple call to the cmdlet Test-Path using the –path parameter would work. However, using IF…ELSE provides a higher level of feedback. We want to know if the directory exists and, if so, does the file exist? It is certainly possible the database might be missing from the folder, but it is also possible the folder itself could be missing. This gives more granular feedback and can aid in troubleshooting.
When we have ensured the database exists, we create the Get-Bios function to obtain the BIOS information from the Win32_Bios WMI class. Here's the Get-Bios function:
Function Get-Bios
{
 Get-WmiObject -Class Win32_Bios
} #End Get-Bios
By encapsulating the WMI call into a function, we gain the ability to easily change the function, such as adding remote capability or accepting credentials. The modification could be made here without impacting the rest of the script. In fact, from a testing perspective, if it doesn't work, you simply comment out the function code and the remaining script continues to work. For help in finding information related to the WMI classes, you can use the Windows PowerShell Scriptomatic shown in Figure 1. This tool lets you easily explore WMI namespaces and classes, and even creates the Windows PowerShell script to retrieve the information.
Figure 1 Windows PowerShell version of the Scriptomatic utility
Next, we'll create the Get-Video function to retrieve video information from the Win32_VideoController WMI class. As you can see, this function is similar to the Get-Bios function:
Function Get-Video
{
 Get-WmiObject -Class Win32_VideoController
} #End Get-Video
Now we need to make a connection to the database. To do this, we use the Connect-Database function. We create two input parameters for the Connect-Database function: –DB and –Tables whose values are stored in the $Db and $Tables variables inside the function. The first thing we do inside the Connect-Database function is to assign values to a couple of variables that are used to control the way the RecordSet is opened. The Open method of the RecordSet object can accept up to five different parameters, as follows:
RecordSet.Open Source, ActiveConnection, CursorType, LockType, Options
The first is the source parameter, which evaluates to a valid command object, a SQL statement, a table name, a stored procedure call, a URL, or the name of a file or stream object containing a persistently stored Recordset. The second parameter is the ActiveConnection, a string that evaluates to a valid connection object, or a string that contains connectionstring parameters. The CursorType parameter is used to determine the type of cursor that will be used when opening the RecordSet. Allowable values for the cursor type are shown in Figure 2.
Figure 2 ADO cursor type enumeration constants and values
Constant | Value | Description
adOpenDynamic | 2 | Uses a dynamic cursor. Additions, changes, and deletions by other users are visible, and all types of movement through the Recordset are allowed, except for bookmarks, if the provider doesn't support them.
adOpenForwardOnly | 0 | Default. Uses a forward-only cursor. Identical to a static cursor, except that you can only scroll forward through records. This improves performance when you need to make only one pass through a Recordset.
adOpenKeyset | 1 | Uses a keyset cursor. Like a dynamic cursor, except that you can't see records that other users add and records that other users delete are inaccessible from your Recordset. Data changes by other users are still visible.
adOpenStatic | 3 | Uses a static cursor, which is a static copy of a set of records that you can use to find data or generate reports. Additions, changes, or deletions by other users are not visible.
adOpenUnspecified | -1 | Does not specify the type of cursor.
The LockType parameter is used to govern the type of lock to be used when updating records, and the options parameter is used to tell the provider how to evaluate the source parameter. The allowable values for the LockType parameter are shown in Figure 3.
Figure 3 ADO Lock type enumeration constants and values
Constant | Value | Description
AdLockBatchOptimistic | 4 | Indicates optimistic batch updates. Required for batch update mode.
AdLockOptimistic | 3 | Indicates optimistic locking, record by record. The provider uses optimistic locking, which locks records only when you call the Update method.
AdLockPessimistic | 2 | Indicates pessimistic locking, record by record. The provider does what is necessary to ensure successful editing of the records, usually by locking records at the data source immediately after editing.
adLockReadOnly | 1 | Indicates read-only records. You cannot alter the data.
adLockUnspecified | -1 | Does not specify a type of lock. For clones, the clone is created with the same lock type as the original.
All five of the parameters for the Open method of the RecordSet object are optional; generally, we use only the first four. After we have assigned values to use for the cursor enumeration and the lock type, we use the New-Object cmdlet to create a new ADODB.Connection object that we store in the $connection variable. We then use the Open method from the Connection object, which needs the provider name and the data source. We then call the Update-Records function and pass the $Tables variable. Here's the Connect-DataBase function:
Function Connect-Database($Db, $Tables)
{
  $OpenStatic = 3
  $LockOptimistic = 3
  $connection = New-Object -ComObject ADODB.Connection
  $connection.Open("Provider = Microsoft.Jet.OLEDB.4.0;Data Source=$Db" )
  Update-Records($Tables)
} #End Connect-DataBase
In the Update-Records function, the first thing we do is create an instance of the ADODB.RecordSet object. We use the New-Object cmdlet to do this and store the newly created RecordSet object in the $RecordSet variable. Next, we use the For Each statement to walk through our array of tables. The table names are stored in the $Tables variable and are assigned at the start of the script. Inside the ForEach loop, we first create our query, which is a rather generic Select * from $Table. The advantage of using a variable for the table name is we only need to write the code once; the table name in the query gets changed each time we loop through the array of table names.
We now come to the open method of the RecordSet object. We specify the query that is stored in the $Query variable, the connection object in the $Connection variable, the $OpenStatic value, and the $LockOptimistic value to control the way the RecordSet is opened. We then use the Invoke-Expression cmdlet to execute the value of a string. We do this because we have created two functions that are designed to update the different database tables. We named the functions after the tables that they update. We are not allowed to call a function name when half of it is a variable, so we need to resolve the variable and then call the function.
But that does not work either—at least not directly. What we want to do is to treat the function name as if it were a string and not a command. But we want to execute it like a command. To do this, we use Invoke-Expression. This cmdlet calls each of the different update functions. Inside the loop that goes through the array of table names, we close each of the RecordSet objects, then return to the next item in the array of table names, create a new query, open a new RecordSet object, and call a new function. This continues for each of the table names in the array of tables, like so:
Function Update-Records($Tables)
{
  $RecordSet = new-object -ComObject ADODB.Recordset
   ForEach($Table in $Tables)
     {
      $Query = "Select * from $Table"
      $RecordSet.Open($Query, $Connection, $OpenStatic, $LockOptimistic)
      Invoke-Expression "Update-$Table"
      $RecordSet.Close()
     }
After the records are updated, we can close the connection. To do this, we use the Close method from the Connection object:
$connection.Close()
} #End Update-Records
The Update-Records function calls two support functions, Update-Bios and Update-Video, which are designed to update the appropriate fields in the respective database table. If you were to add additional tables to your database, you would need to add an additional Update* function to update the new tables. As a best practice, we recommend keeping the database field names the same as the WMI property names. It makes things much easier to keep track of. When writing a script to update an existing database, you may want to look at the database schema for the tables, columns, and data types contained in the fields. The database schema for the ComputerData database is shown in Figure 4. This view was generated by the script from the article "How Can I Tell Which Tables and Columns Are in a Database without Opening It?"
Figure 4 The database schema for the ComputerData database
In the Update-Bios function, we first post a message stating we are updating the BIOS information. We then call the Get-Bios function and store the returned WMI Win32_Bios object in the variable $BiosInfo. Now we need to add a record to the database table. To do this, we call the AddNew method from the RecordSet object. After we have a new record, we add information to each of the fields in the table. When all the fields have been updated, we call the Update method to commit the record to the table. The complete Update-Bios function is shown here:
Function Update-Bios
{
 "Updating Bios"
 $BiosInfo = Get-Bios
 $RecordSet.AddNew()
 $RecordSet.Fields.Item("DateRun") = Get-Date
 $RecordSet.Fields.Item("Manufacturer") = $BiosInfo.Manufacturer
 $RecordSet.Fields.Item("SerialNumber") = $BiosInfo.SerialNumber
 $RecordSet.Fields.Item("SMBIOSBIOSVersion") = $BiosInfo.SMBIOSBIOSVersion
 $RecordSet.Fields.Item("Version") = $BiosInfo.Version
 $RecordSet.Update()
} #End Update-Bios
When the BIOS table has been updated, we need to update the video table. To do this, we can call the Update-Video function, which is exactly the same as the Update-Bios function. We present a message stating we are updating the video, call the Get-Video function to retrieve the video information, call the AddNew method to add a new record to the Video table, and write all of the information to the appropriate fields. When we are done, we call the Update method.
A potential issue in collecting the video information is the number of video controllers on the computer. My personal computer has a daughter card and reports multiple video controllers. To handle this eventuality, we use the ForEach statement to iterate through a collection of Win32_VideoControllers. If you are not interested in the daughter card configuration information or if your video card is dual channel and reports the same information twice, you could remove the ForEach loop and select $VideoInfo[0] to index directly into the first record that is reported. The problem with this approach is that if the query returns a singleton, you will generate an error because you cannot index into a single record:
Function Update-Video
{ "Updating video" $VideoInformation = Get-Video
Foreach($VideoInfo in $VideoInformation)
  {
   $RecordSet.AddNew()   $RecordSet.Fields.Item("DateRun") = Get-Date
   $RecordSet.Fields.Item("AdapterCompatibility") = $VideoInfo.AdapterCompatibility
   $RecordSet.Fields.Item("AdapterDACType") = $VideoInfo.AdapterDACType
   $RecordSet.Fields.Item("AdapterRAM") = $VideoInfo.AdapterRAM
   $RecordSet.Fields.Item("Description") = $VideoInfo.Description
   $RecordSet.Fields.Item("DriverDate") = $VideoInfo.DriverDate
   $RecordSet.Fields.Item("DriverVersion") = $VideoInfo.DriverVersion
   $RecordSet.Update()
  }
}
#End Update-Video
The entry point to the script points to the database, lists the tables, and then calls the connect-DataBase function, as shown here:
$Db = "C:\FSO\ComputerData.mdb"+
$Tables = "Bios","Video"
Check-Path -db $Db
Connect-DataBase -db $Db -tables $Tables
After the script is run, new records are written to the ComputerData.mdb database as shown in Figure 5. The complete WriteToAccessDatabase.ps1 script can be seen in Figure 6.
Figure 5 New records added to the ComputerData.mdb database
Figure 6 WriteToAccessDataBase.ps1
Function Check-Path($Db)
{
 If(!(Test-Path -path (Split-Path -path $Db -parent)))
   {
     Throw "$(Split-Path -path $Db -parent) Does not Exist"
   }
  ELSE
  {
   If(!(Test-Path -Path $Db))
     {
      Throw "$db does not exist"
     }
  }
} #End Check-Path

Function Get-Bios
{
 Get-WmiObject -Class Win32_Bios
} #End Get-Bios

Function Get-Video
{
 Get-WmiObject -Class Win32_VideoController
} #End Get-Video

Function Connect-Database($Db, $Tables)
{
  $OpenStatic = 3
  $LockOptimistic = 3
  $connection = New-Object -ComObject ADODB.Connection
  $connection.Open("Provider = Microsoft.Jet.OLEDB.4.0;Data Source=$Db" )
  Update-Records($Tables)
} #End Connect-DataBase

Function Update-Records($Tables)
{
  $RecordSet = new-object -ComObject ADODB.Recordset
   ForEach($Table in $Tables)
     {
      $Query = "Select * from $Table"
      $RecordSet.Open($Query, $Connection, $OpenStatic, $LockOptimistic)
      Invoke-Expression "Update-$Table"
      $RecordSet.Close()
     }
   $connection.Close()
} #End Update-Records

Function Update-Bios
{
 "Updating Bios"
 $BiosInfo = Get-Bios

 $RecordSet.AddNew()
 $RecordSet.Fields.Item("DateRun") = Get-Date
 $RecordSet.Fields.Item("Manufacturer") = $BiosInfo.Manufacturer
 $RecordSet.Fields.Item("SerialNumber") = $BiosInfo.SerialNumber
 $RecordSet.Fields.Item("SMBIOSBIOSVersion") = $BiosInfo.SMBIOSBIOSVersion
 $RecordSet.Fields.Item("Version") = $BiosInfo.Version
 $RecordSet.Update()
} #End Update-Bios

Function Update-Video
{
 "Updating video"
 $VideoInformation = Get-Video
 Foreach($VideoInfo in $VideoInformation)
  {
   $RecordSet.AddNew()
   $RecordSet.Fields.Item("DateRun") = Get-Date
   $RecordSet.Fields.Item("AdapterCompatibility") = $VideoInfo.AdapterCompatibility
   $RecordSet.Fields.Item("AdapterDACType") = $VideoInfo.AdapterDACType
   $RecordSet.Fields.Item("AdapterRAM") = $VideoInfo.AdapterRAM
   $RecordSet.Fields.Item("Description") = $VideoInfo.Description
   $RecordSet.Fields.Item("DriverDate") = $VideoInfo.DriverDate
   $RecordSet.Fields.Item("DriverVersion") = $VideoInfo.DriverVersion
   $RecordSet.Update()
  }
} #End Update-Video

# *** Entry Point to Script ***

$Db = "C:\FSO\ComputerData.mdb"
$Tables = "Bios","Video"
Check-Path -db $Db
Connect-DataBase -db $Db -tables $Tables
If you would like to learn more about working with Office Access databases from within Windows PowerShell, check out the "Hey, Scripting Guy!" archive for the week of February 20, 2009. Also, the 2009 Summer Scripting Games are coming soon! Visit scriptingguys.com for more information.

Ed Wilson, a well-known scripting expert, is the author of eight books, including Windows PowerShell Scripting Guide (2008) and Microsoft Windows PowerShell Step by Step (2007). Ed holds more than 20 industry certifications, including Microsoft Certified Systems Engineer (MCSE) and Certified Information Systems Security Professional (CISSP). In his spare time, he enjoys woodworking, underwater photography, and scuba diving. And tea.

Craig Liebendorfer is a wordsmith and longtime Microsoft Web editor. Craig still can't believe there's a job that pays him to work with words every day. One of his favorite things is irreverent humor, so he should fit right in here. He considers his greatest accomplishment in life to be his magnificent daughter.


Desktop Files Revisiting the Microsoft Desktop Optimization Pack
Wes Miller

Contents
Application Virtualization
Advanced Group Policy Management
Asset Inventory Service
Diagnostics and Recovery Toolset
System Center Desktop Error Monitoring
But Wait—There's More
MDOP Licensing
Conclusion
It’s been just under two years since I first covered the Microsoft Desktop Optimization Pack (MDOP) and the five technologies it included: SoftGrid Application Virtualization, Asset Inventory Service, Diagnostics and Recovery Toolset, Advanced Group Policy Management, and System Center Desktop Error Monitoring. Since then, Microsoft has released two updates—MDOP 2008 and then MDOP 2008 R2 (see Figure 1). The latest release includes numerous enhancements to all of the key components, as well as support for additional locales for most of the components. Another update due by mid-2009 will include support for Microsoft Enterprise Desktop Virtualization (MED-V), which I'll cover in detail at the end of this month's article. Let's take a look at how each of the technologies included in MDOP have been improved.
Figure 1 The new Microsoft Desktop Optimization Pack 2008 R2

Application Virtualization
The MDOP component originally named SoftGrid Application Virtualization is now Microsoft Application Virtualization 4.5 (APP-V), and it has been considerably enhanced to make using it within a Microsoft Windows–based organization faster and easier. Among the reliability features that have been improved are:
  • A memory-locked cache that enables applications to be retained on client systems in the local application cache, even when the system shuts down suddenly;
  • Background streaming, which allows for auto-caching of the application, where applications are downloaded in the background while a user is performing other tasks;
  • Application check-pointing, which allows the state of applications, such as user preferences and settings, to be backed up so that they may be rapidly restored later.
Supporting a Microsoft infrastructure in a manageable way is now easier with APP-V, as it lets you create an MSI file from virtualized packages—meaning your existing application publishing tools can be used to quickly and reliably push out APP-V packages as well. Similarly, System Center Configuration Manager (SCCM) and SMS customers can push out a pre-cache of applications, even to new systems with no local users installed yet. With SCCM 2007 R2, App-V and SCCM are integrated, allowing you to leverage one management console, perform well-known workflows for managing applications, and take advantage of SCCM core functionality to inventory, distribute, manage, and report on virtual applications just like physical applications. You also get a WMI provider that allows managed monitoring of APP-V usage, whether online or offline.
In order to improve the performance and convenience of APP-V, the product now supports streaming from any existing HTTP server in your infrastructure. The sequencing process has been optimized to speed up the creation of virtualized applications. Moreover, you can now virtualize .NET-based applications. More information on .NET virtualization is available in the article "Support for .NET in Microsoft Application Virtualization 4.5 (App-V)".
From a usability perspective, APP-V now supports 11 localized languages, and it can now virtualize an application in any language except those that use "Complex Script," such as Thai, Hebrew, Arabic, Vietnamese, and Indic languages. It also supports Section 508 (of the Rehabilitation Act of 1973) accessibility compliance.
APP-V is supported on 32-bit Windows XP (APP-V 4.2) and Windows Vista (APP-V 4.5). Support for x64 versions of Windows Vista is expected in a beta form in late 2009, with a release during calendar year 2010 (see the article "MDOP Makes Some Noise in Spain "). Support for 64-bit versions of Windows is a frequently requested feature for APP-V, but making APP-V compatible with Windows Vista and Windows Server 2008 requires significant modifications to the APP-V infrastructure; this will be supported in due time.

Advanced Group Policy Management
Two versions of Microsoft Advanced Group Policy Management (AGPM) are supplied—2.5 and 3.0. If your server infrastructure is running Windows Server 2003 or your clients are still running the original RTM version of Windows Vista, you must use the earlier 2.5 release of AGPM. In order to use AGPM 3.0, your server must be running Windows Server 2008, and your clients used for managing AGPM must be running Windows Vista Service Pack 1. The new release also adds support for x64 versions of Windows Vista Service Pack 1 and Windows Server 2008. However, note that AGPM can be used to manage Group Policy on systems running Windows 2000 SP4 or newer.
In addition to the platform and architecture support, AGPM 3.0 now offers the ability to apply permissions to group policies—meaning that you can control who modifies group policy within your organization (see Figure 2). It also has enhanced change tracking in order to monitor when a policy was changed, how, and by whom (and who approved or rejected it), as shown in Figure 3. The user interface of AGPM 3 has also been significantly enhanced, and like APP-V, is available in additional languages (11 in total).
Figure 2 AGPM integrated into the Group Policy Management Console
Figure 3 Policy revision control viewed through AGPM

Asset Inventory Service
The Microsoft Asset Inventory Service (AIS) 1.5 component is the sole "Software as a Service" piece of the MDOP. It is available from an easily used online site, and retrieves information from managed systems using a lightweight client installer. Originally designed to provide software management details (quickly and easily retrieving details on installed applications from client systems), AIS now also provides license tracking. So in addition to telling you what software is installed in your infrastructure, AIS will correlate that inventory with your Microsoft License Statement information. That's crucial in this day and age to make sure that you are not only compliant from a legal perspective, but also that you aren't wasting money on unused licenses. AIS incorporates data normalization based on a catalog of many application titles. The resulting reports provide information that is complete, easy to understand, and not cluttered by repetitive entries.

Diagnostics and Recovery Toolset
As with AGPM, there are two versions of the Microsoft Diagnostics and Recovery Toolset (DaRT) included in MDOP now—5.0 and 6.0. The 5.0 version that previously shipped with the release of MDOP I discussed in 2007 is still available and is unchanged. That's the version you need if you are trying to recover a Windows XP system.
For organizations using Windows Vista, however, MDOP now includes all of the functionality of the 5.0 release, and then some. The 6.0 release supports Windows Vista, both 32-bit and 64-bit. In fact, the process of creating your ERD Commander ISO uses a Windows Vista DVD to complete its work. As I've mentioned before, you shouldn't ever use a Windows PE 1.x CD (which DaRT 5 is) to boot a Windows Vista system as it will cause your Restore Point data to be lost, thus the move to Windows PE 2 for DaRT 6.
Unlike DaRT 5, which had its own unique user interface, DaRT 6 integrates into the Microsoft Windows Recovery Environment (WinRE) interface and provides a quick-launch menu upon startup to launch the appropriate tool.
New to this release is the Standalone System Sweeper (Figure 4), which provides anti-malware functionality in an offline scan. It uses a signature that is up to date when the ISO image is initially created; updates can also be provided via a USB Flash Drive (UFD) when using ERD Commander. If Internet connectivity is available, updates can be downloaded in real-time for offline scanning.
Figure 4 Standalone System Sweeper retrieving signature updates
Also new is System Boot File Repair, part of WinRE, which provides the ability to repair critical system boot files to get a system bootable again.
While DaRT 6 no longer has the ability to share out the local system drive for recovery, you can still connect to remote shares and copy data as needed using ERD's Explorer-like interface.
DaRT has also been enhanced to support BitLocker-encrypted volumes. Previously, you would have had to manually hack in support for disk/volume encryption tools, and BitLocker was not supported at all. That's changed now with the rest of the Windows Vista support.

System Center Desktop Error Monitoring
Microsoft System Center Desktop Error Monitoring (DEM) 3.0 SP1 lets organizations centralize and diagnose Windows crashes and application hangs. It has been enhanced to improve performance and reliability plus better reporting functionality (the ability to see the top demographics, for example). DEM 3.0 SP1 also can be easily upgraded to a full System Center Operations Manager implementation.
DEM is useful for organizations because it provides insight into the lifecycle of systems in the organization—events that would previously have gone undetected or resulted in strange system failures can now be seen ahead of time. Thus, DEM allows more proactive handling of troublesome applications or drivers to deliver a more reliable desktop experience for an organization's end users. It also helps to close the loop with application and driver developers who may not be aware of how and why their software is failing.

But Wait—There's More
So now we have covered all of the key components of the MDOP that were in the product when I discussed it in 2007. While these components have all improved significantly, what I think you will find most interesting about the MDOP is what's new. As with most of the other MDOP components, Microsoft Enterprise Desktop Virtualization (or MED-V for short), is comprised of technology that Microsoft acquired and is turning into technology that can really enhance the enterprise Windows world.
In 2008, Microsoft acquired Kidaro, a small virtualization company. What made Kidaro products interesting is that they were not strictly virtualization products like Virtual PC, VMware, Citrix XEN, and so forth. Instead, Kidaro's technology worked to make existing virtual machines much more dynamic and manageable—and that's exactly the direction Microsoft has continued to take with it.
MED-V, available in a public beta form as I write this, is designed to allow an organization to keep legacy applications around, as needed, but offer them in a managed, virtual environment. Instead of providing a full "desktop in a window," which can be confusing to end users and hard for administrators to maintain, MED-V contains needed legacy applications on a standardized image that is centrally maintained. And it does this in a way that—for all but administrators and power users— looks convincingly like they are native applications running on the actual host OS. Instead, of course, they are actually running on a guest under Microsoft Virtual PC.
MED-V begins with the packaging process, where it provides a console to help administrators create and test images and store them on an IIS Web server, and then create an MSI that is capable of pulling the images down from a the repository.
The images can be deployed via removable storage (UFD, DVD, and so on), via a MED-V internal delivery mechanism called TrimTransfer that provides a bandwidth-optimized delivery mechanism for deployment and updates to images. You can, of course, also distribute the images via SCCM if you have the infrastructure.
The central management server of MED-V supports up to 5,000 endpoints and allows you to use Active Directory to assign images and require authentication based on Active Direct Users or Groups.
During deployment, MED-V provides the means to automatically configure the network of the guest OS and join it to the domain, as well as to apportion RAM to the guest based upon the host's RAM. Once deployed, MED-V enables monitoring and centralized remote administration of the guest OS.
Authentication of the image can be governed via Active Directory, and you can restrict images to only allow access for a certain timeframe, with a set expiration point, or for a certain window of hours, say, during business hours.
Instead of the traditional "floating desktop" displayed by traditional virtualization systems—which can throw nontechnical users—MED-V places a small icon in the Windows notification area. The virtual machine is essentially invisible to the end user, and any applications that are installed on the guest display shortcuts in the end user's host Start Menu. When these applications run, unless they are configured to display the full desktop, they will run as freestanding applications (as if they were running on the host). Optionally, MED-V can frame these apps with a colored border to help users discern "where" the application is. This is useful for users, and it also lets a help desk see that a user is running MED-V. This option is available to administrators via the MED-V management console.
Just as with Virtual PC, printer redirection to a host printer, file transfers, and copy and paste all typically work as configured. Effectively, the user can print from and copy or past to or from MED-V-hosted applications as if they were applications on the host itself. MED-V can also specify URLs that should always be opened from within the MED-V guest, while others will use the host OS's Web browser instead. Finally, the images can be configured to either retain state, or to be reversible (revert to a snapshot in time) if no user state needs to be retained.
Thus, MED-V can best be thought of as a means to provide a managed, secured, and easily updated environment to end-users. Whether the goal is to provide a managed environment to access legacy applications, to provide controlled access to information for security or compliance reasons, or simply to provide an enterprise application in a managed environment, MED-V provides a new and exciting way to offer the necessary applications to your end-users. It does this in a low-impact, high-performance, secure, and manageable way.
MED-V is an eagerly anticipated update to the MDOP platform, and will undoubtedly help Microsoft customers optimize their Windows investment.

MDOP Licensing
The licensing requirements for MDOP have not changed. To license MDOP, customers must have an existing Microsoft Software Assurance (SA) agreement covering the desktops that MDOP is to be used on. Once Software Assurance is in place, the licensing costs begin at approximately $10 per desktop per year. Volume discounts and educational pricing are available.
As before, the MDOP is not generally available for use on servers. However, you can license Application Virtualization 4.5 for Terminal Services. More information is available at Microsoft Application Virtualization for Terminal Services site.

Conclusion
With the MDOP 2008 R2 release, and the impending release that supports MED-V, Microsoft continues to add valuable new tools to the product to help Microsoft SA customers make the most of their Windows investment, and do so in a way that optimizes the investments customers have made in other Microsoft management technologies, including operations that require support for other languages.
More information about MDOP is available on the Windows Desktop Management and Deployment site, which is updated with each MDOP release to include new components and updates.
If you currently have Software Assurance and are considering licensing MDOP, you may want to visit the free MDOP Return on Investment (ROI) tool MDOP ROI tool, which can help you visualize the estimated cost savings of deploying MDOP on your desktop systems.

Wes Miller is the Director of Product Management at CoreTrace (CoreTrace.com) in Austin, Texas. Previously, he worked at Winternals Software and as a Program Manager at Microsoft. Wes can be reached at technet@getwired.com


Field Notes IT Does Matter
Romi Mahajan

In The Rebel, Albert Camus wrote, "...through a curious transposition peculiar to our times, it is innocence that is called upon to justify itself." Though he was writing about the scourge of colonialism, the theme is resonant today in a far different context: Why must IT always be called on to justify itself with regard to investment, people, value, and strategy? Is the skepticism deserved, or is it the product of ignorance or malfeasance? I am bothered because it just shouldn't be this way. What other parts of the company (well, except perhaps Marketing) are questioned all the time and scrutinized to their very essence?
Let's examine these perspectives, starting with the view that any skepticism directed at IT is deserved. According to some folks, business was conducted very well and with some precision before IT was even a dream. Business is about relationships, and relationships are lived and realized through human contact. The hearts and minds of employees are the assets and all things external to them are far less relevant.
Further, as Nicholas Carr suggests (Harvard Business Review, May 2003), IT is a commodity and confers no comparative advantage, and therefore doesn't matter. In a capitalist enterprise, not mattering is equivalent to being scorned.
Finally, IT doesn't make money for the company. In fact, the situation is worse than making no money; the accoutrements of IT—computers, servers, software, and IT pros—cost money. Since companies are in business to make money, IT therefore should be viewed with some suspicion.
These arguments are fairly easy to deflect, however. Yes, business is about humans, but it's not only about humans. It's also about what they make, where they go, how they interact, and how quickly they do all of this. The role IT plays in these areas is unambiguous.
Is IT a commodity? Not exactly. Though some of the pieces may be fungible, the whole certainly is not. Have you ever worked for or with a company that didn't do IT well? If so, you know that good IT may not be sufficient for a great business, but it sure is necessary.
Finally, it is a mistake to think that the "last mile transaction" is the only step that matters in the process of making money. That step can't happen without a whole lot of preliminary effort. Moreover, e-commerce has emerged as a core means of transaction and, without IT, there is no e-commerce.
Now, what about the idea that the lack of respect for IT is a function of lack of knowledge, or worse? You could argue that it's the very skill of IT organization that's the problem. Enterprises are geographically dispersed, as are their customers and partners. IT allows them all to communicate and transact with amazing speed and clarity and, in this way, is a fundamental enabler of business. Because IT is so much part of the infrastructure in many industries, it is considered a given and therefore accorded no respect. It's to the credit of most IT organizations, of course, that they are invisible to the end user. That fact should engender reward, not disdain.
The idea that IT has no value because it doesn't produce money is disingenuous—ultimately that idea dismisses every single thing that actually enables sales to happen. You might as well question the value of the building the business is quartered in or the desks people sit at. Does this perspective result from competition among various parts of the organization, or from lack of vision? No matter; those who cannot see how other parts of the body economic contribute to the whole are simply being petty.
It's not hard to figure out where I stand. In my view, IT plays an important role in business today, more important in some cases than in others. In some scenarios, IT is axiomatically relevant and in others, its role is on the periphery. Ultimately, however, IT does indeed matter and so, therefore, do you.

Romi Mahajan is Chief Marketing Officer of Ascentium Corporation. Before joining Ascentium, he spent 7+ years at Microsoft where his last role was as Director of Technical Audience and Platform Marketing. Romi is widely published in the areas of technology, politics, economics, and sociology.


Cable Guy DirectAccess and the Thin Edge Network
Joseph Davies

Parts of this article are based on prerelease code. All information herein is subject to change.

Contents
Protected Traffic across the Internet
End-to-End Addressing and Connectivity
Bidirectional Connectivity and Remote Client Management
Firewall and Web Proxy Traversal
Determination of on-Intranet vs. on-Internet
Separating Intranet from Internet Traffic
Summary
To provide intranet resource availability to remote users, typical organization networks today employ some sort of edge network containing servers for various types of remote access. These servers can be virtual private network ( VPN ) servers or concentrators, Terminal Server ( TS ) Gateway servers, or a variety of application edge servers, such as Microsoft's Outlook Web Access (OWA).
The edge network exists to separate the intranet from the Internet because the Internet is an extraordinarily hostile networking environment. An IT architect who directly connects his or her intranet to the Internet without this separation—and sufficient security systems—will soon be looking for another line of work. However, the separation introduces complexity for the remote user.
If directly connecting the intranet to the Internet for seamless access to both intranet and Internet resources for remote users is not a practical option, then the solution lies in seamlessly connecting the remote user to both the intranet and the Internet.
Current remote access VPN solutions, including Routing and Remote Access in Windows Server 2008, attempt this solution through a user-initiated Layer 2 connection to the intranet. However, remote access VPN connections are hardly seamless because they require user action to connect and reconnect. Moreover, for most VPN deployments, the VPN client computer is either connected to the Internet (when the VPN connection is not active) or connected to the intranet (when the VPN connection is active), but not both simultaneously.
It is possible to address the issue of concurrent Internet and intranet access for VPN connections by sending Internet traffic through the intranet or by configuring split-tunnel routing so that Internet and intranet traffic are separated. However, sending Internet traffic through the intranet makes Internet access for connected VPN clients slow, and setting up and maintaining split-tunnel routes can be administratively difficult.
Another issue for current VPN solutions is that the remote computer is connected to the intranet only intermittently. The model of user- initiated connections makes it difficult for IT administrators to manage remote computers with the latest updates or security policies. Remote computer management can be mitigated by checking for and requiring system health updates before completing the VPN connection. However, such requirements can add substantial wait times to the VPN connection process.
Now a new feature of Windows 7 and Windows Server 2008 R2 called DirectAccess brings us a step closer to the solution; remote clients have seamless and concurrent access to both intranet and Internet resources without adding ongoing administrative overhead and without sacrificing performance or security.
With DirectAccess, you can reduce your dependence on remote access and application edge servers, leading to the notion of the thin edge network. For example, your VPN infrastructure can be reduced because DirectAccess clients can now directly access the resource servers on the intranet. As Figure 1 shows, DirectAccess can transform your edge network. To achieve this, however, a number of engineering problems had to be solved.
Figure 1 Transforming Your Edge Network with DirectAccess

Protected Traffic across the Internet
DirectAccess uses Internet Protocol security ( IPsec) in tunnel and transport mode to authenticate the computer that is connecting and to protect the traffic that is being exchanged with the DirectAccess server over the Internet. Existing VPN solutions also use IPsec encryption. You can specify IPsec protection for computers running Windows 7 with connection security rules, which can be centrally configured through Windows Firewall with Advanced Security Group Policy settings.

End-to-End Addressing and Connectivity
Due to a lack of public IPv4 address space and the reuse of the private IPv4 address space by ISPs and intranets, providing end-to-end connectivity for remote clients with globally unique addresses is not possible with IPv4. The solution is IPv6, which provides globally unique addressing and simplifies the separation of Internet and intranet traffic. IPv6 connectivity is a requirement for DirectAccess. The only resources that DirectAccess clients can access are those that are reachable with IPv6. Therefore, your intranet must be IPv6-capable, either natively or by deploying the Intra-Site Automatic Tunnel Addressing Protocol ( ISATAP ). Alternatively, DirectAccess clients can reach IPv4-only resources on your intranet through a Network Address Translation-Protocol Translation (NAT-PT) device.

Directing Traffic
Let's suppose that for the fictional Contoso Corporation, the DNS namespace for all intranet resource names is corp.contoso.com, with intranet DNS servers FDA5:2C09:1F3C:E215::1 and FDA5:2C09:1F3C:E215::2.
In this case, the NRPT for Contoso's DirectAccess clients would contain the entry: namespace is .corp.contoso.com and DNS servers are FDA5:2C09:1F3C:E215::1, FDA5:2C09:1F3C:E215::2. Namespace
When a user runs Microsoft Outlook and attempts to connect to the EXCHNG071 email server, the TCP/IP stack will append the domain suffix for the computer (corp.contoso.com.) to the e-mail server name to get exchng071.corp.contoso.com. This name is compared against the NRPT. Because the name matches the entry for .corp.contoso.com, the DirectAccess client sends the DNS name query request to the intranet DNS servers at FDA5:2C09:1F3C:E215::1 and FDA5:2C09:1F3C:E215::2. Microsoft Outlook uses the IPv6 addresses that are returned in the DNS name query response and directly connects to its intranet Exchange server.
Let's assume that during the transition of users to Windows 7 and DirectAccess, the Contoso IT department has kept their OWA servers in their edge network. When a user on a DirectAccess client uses Internet Explorer to access the OWA server at the address https://exmail.contoso.com/exchange/, the TCP/IP stack will attempt to resolve the DNS name exmail.contoso.com. This name is compared against the NRPT. Because the name does not match the entry in the NRPT, the DNS name query request is sent to Internet DNS servers and Internet Explorer makes a connection directly to the OWA server in the edge network.
Bidirectional Connectivity and Remote Client Management
A DirectAccess client tries to connect to a DirectAccess server when the computer starts. When the user logs on, a different set of credentials is used for connecting to intranet resources. The key difference with DirectAccess over typical VPN connections is that the DirectAccess client computer is always connected to, registered with, and logged on to the intranet domain. IT departments can now manage remote computers just like intranet-connected computers and install updates, propagate Group Policy settings, and make other changes on an ongoing basis, ensuring the system configuration and health of remote computers.

Firewall and Web Proxy Traversal
Because IPv6 is the initial Layer 3 transport and most remote computers are communicating across the IPv4 Internet, a DirectAccess client computer will attempt to use the 6to4 and Teredo IPv6 transition technologies to communicate with the DirectAccess server. However, Web proxy servers and some firewalls will not forward 6to4 and Teredo-encapsulated traffic. In this case, the DirectAccess client uses IP-HTTPS, a new protocol in Windows 7 and Windows Server 2008 R2 that tunnels IPv6 packets inside an IPv4-based HTTPS session.

Determination of on-Intranet vs. on-Internet
A DirectAccess client uses a network location server that is reachable only with a direct connection to the intranet, to determine whether it is connected to the intranet. When a DirectAccess client starts up, it attempts to connect to a specified URL on the network location server. If the Web page for the URL can be successfully obtained, the DirectAccess client is on the intranet and DirectAccess is not used.

Separating Intranet from Internet Traffic
As previously described, some VPN solutions use Network layer routing table entries to separate intranet from Internet traffic. DirectAccess solves this problem in the Application layer through more intelligent name resolution and in the Network layer by summarizing the IPv6 address space of an entire organization with a single IPv6 address prefix. Rather than directing traffic solely based on a destination address, DirectAccess clients also direct traffic based on the name needed by the application. DirectAccess clients use a Name Resolution Policy Table ( NRPT ) that contains DNS namespace entries and a corresponding set of intranet DNS servers that resolve names for that DNS namespace.
When an application on a DirectAccess client attempts to resolve a name, it first compares the name with the entries in the NRPT. If there is a match, the DirectAccess client uses the specified intranet DNS servers to resolve the name. If there are no matches, the DirectAccess client uses the DNS servers configured on its Internet connection, which are typically Internet DNS servers. See the "Directing Traffic" sidebar for an example of how this works.

Summary
DirectAccess enables transparent, concurrent intranet and Internet remote access and eases the management of remote computers by combining a number of technologies and components: end-to-end connectivity ( IPv6 ), security ( IPsec), Web proxy and firewall traversal ( IP-HTTPS), location determination (network location server), and traffic separation ( NRPT ) technologies and components. With DirectAccess, you can replace some of your remote access and application edge servers with DirectAccess servers, reducing the number of servers on your edge network devoted to remote access connectivity.

Joseph Davies is a Principal Technical Writer on the Windows networking writing team at Microsoft. He is author or coauthor of a number of books published by Microsoft Press, including Windows Server 2008 Networking and Network Access Protection (NAP), Understanding IPv6, Second Edition, and Windows Server 2008 TCP/IP Protocols and Services.


Business of IT Reinventing IT in Difficult Times
Romi Mahajan

IT organizations are in a difficult era. The neo-Taylorist push for efficiency (Frederick Winslow Taylor was among the first efficiency experts), coupled with an unprecedented downturn in the economy, has delivered a one-two punch to already struggling organizations. The flight-towards-mediocrity ethos, driven by a semi-religious obsession with overhead reduction, has driven the IT organization—which never quite made it into the limelight it had been seeking—to its current nadir. For the first time in recent memory, IT professionals find themselves hard-pressed to find jobs, despite the fact that they have high-barrier-to-entry skills compared to those in many other professions, my own (marketing) included. For this, the blame has to be laid at many doors, some of which are internal to the IT organization and some of which are external. Notions that IT doesn't matter, that commoditization defines IT, and that the cloud makes IT less important have all served to further push the nail into the perception coffin. Given this, how best should IT organizations go about reclaiming the ground they have given up over the past decade, to reveal their true value that is often hidden? There are a number of approaches they can take.
The Beat-Chest Approach: For most of the industrialized world, IT is as fundamental to the smooth workings of business and government as is plumbing. In the process, however, IT has become thought of much as the Facilities Department is—people are only aware of them when there is a problem and, during those crises, the need for their services fosters resentment. How should IT deal with this? Through marketing, of course. Simply put: tell your story. Communicate frequently with your internal customers. At Ascentium, our IT organization is well-known for its amazing throughput and customer service. It is well-known because it tells its own story often and well, and through this process of education, others grow to understand the complexities and rigors of their jobs. We have an internal alias called "kudos" and our IT organization gets more kudos than any other department in the company. Our IT organization moved our datacenter into a new facility two months ago. They did it on a Saturday. E-mail and other shared services were down for only four hours. Anticipating that even that a small outage would be an issue, our Director of IT sent out weekly e-mails four weeks before the move and daily e-mails in the last three days telling the company EXACTLY what they were doing and EXACTLY how we would all be affected. Lo and behold, they completed the move without a glitch and won rave reviews. In a down economy, people are even less willing to forgive; communicate your way into the hearts and minds of your internal customers. Lack of communication will result in further peril.
The Bolshevik Approach: Crisis breeds revolution and revolution breeds change. Thus the cloud of economic doom enveloping us has a silver lining: organizations are seeking ways to redefine themselves in order to, well, survive. There is desire for change and from this crucible emerges a revolutionary cadre of those who seek to overturn the current state. IT organizations have to be part of this revolutionary wave in order to prosper. To participate, IT organizations must first of all make common cause with other internal organizations caught in the same vise. In the December 2008 Field Notes column in TechNet Magazine, I wrote an article called "Mark{IT}ing: Synergy in the Shadows" about the enormous potential of linking IT-and Marketing (technet.microsoft.com/en-us/magazine/2008.12.fieldnotessynergy.aspx). Both of these organizations have been asked to justify themselves in ways they never had to before. Both are asked to do more with less. Marketing can learn a lot from the customer-service orientation and throughput efficiency of IT, and IT can learn from the "visibility" approach of Marketing. In practice, both organizations must reject the myopic notions of efficiency engendered by the corporate genuflection to the fixed ideas of Accounting and turn, instead, to defining the terms of their own trade. Revolution through innovation is a key pillar in the resurgence of IT. No revolution succeeds, however, without numbers, so build bridges now. Tomorrow is too late.
The Borg Approach: If the key "enemy" of IT is Accounting, why not kill the Accounting Department with kindness? Why not absorb Accounting into the fold of IT by providing more value to the company than any CFO possibly could? The key here is for IT professionals to ally themselves with people in Corporate Systems who, frankly, increasingly need allies as much as IT or Marketing folks do. As Corporate Systems teams (who usually report into a CFO or CFO-like structure) are tasked with finding efficiencies in operations and analyzing reams of sometimes-useful-sometimes-not data in order to cut costs and work out redundancies, they will find it useful to team with IT folks.. Together, Corporate Systems and IT can work with business groups and other horizontal departments to determine new areas for investment or areas to redeploy key personnel who are doing overlapping jobs. All large enterprises have massive overlaps. The usual managerial response is to cut people; the best response (should a company have even a modicum of staying power) is to quickly expose redundancies and put the resources to new use, in particular to find new areas of growth. IT folks do this sort of thing every day. True, the objects of their study are often inanimate objects like servers or data, but that doesn't change the point. IT organizations analyze reams of data constantly and can be very helpful to the process of reinvention-through-redeployment of talent that many enterprises sorely need. To do so, however, IT must assimilate Accounting into its own body.
The Betterment Approach: Difficult times call for extreme measures. Often these measures are enacted externally; equally often, these measures are inward facing as we each seek to find ways to excel. IT professionals have to take this process very seriously if they are to thrive. Some suggestions:
  • Don't eschew learning new things, new paradigms, new products, and new methods; don't think your current knowledge base as an endpoint. In fact, there is always more to learn.
  • Gather skills outside of your job area. Be ready for the sea-changes that very well might hit IT and technology in general at any time.
  • Learn to read a balance sheet. Understand the underlying economics of industries your company is in, works with, and depends on. Make job bets only after knowing the numbers.
  • Expand your worldview. Be that person who is marked as strategic and eclectic in intellect, not simply narrowly intelligent.
  • Write. Write your thoughts and hone them. Make them crisp. Express them. Gain both clarity and credence simultaneously.
  • Read widely. Bring complex knowledge to bear on even simple tasks.
The Buffet Approach: The new economy will demand versatility. IT professionals will thus have to embrace elements of each of the approaches. The key is to make sure all the dishes you select make for a good meal. If you are an IT manager, you should immediately set up meetings with peers and managers in other organizations to find out how your team can help the overall cause better. If you are a working IT professional without management responsibility, you should do the same with five of your customers. Through this process, you will inevitably be given feedback hewing to the approaches above. What you do with that feedback, of course, will determine your longevity and happiness in the IT of the new economy.
I have always felt that IT professionals are misunderstood but that they make matters worse by not telling their stories and proactively adding value in non-IT spaces. These days, when you can't escape the barrage of bad news, and the fear of layoffs and salary reductions looms large, all people, IT professionals and others alike, have to find ways to reinvent themselves and their organizations in order to maintain an edge.
IT organizations have a great deal of potential. Indeed, they have many surprises inside. The key is making them known to the world.

Romi Mahajan is Chief Marketing Officer of Ascentium Corporation. Before joining Ascentium, he spent over 7 years at Microsoft, where his last role was as Director of Technical Audience and Platform Marketing. Romi is widely published in the areas of technology, politics, economics, and sociology.


Business of IT Lowering the Cost of IT
Karen Forster

The idea of IT cost reduction raises images of a huge, dark jungle of unpleasant options. But if you step back and look at your entire IT infrastructure and business needs, you can find unexpected ways to save money without causing too much pain either for IT or for your business. Based on data gathered in Advaiya's Business Value Assessment (BVA) engagements with large, multinational companies, here are a number of suggestions that can help you identify ways to reduce IT costs while increasing IT's value to your business.
Reduce technology redundancy How many directories does your IT organization maintain? Advaiya's BVAs in very large enterprises found most companies had no fewer than 18 directories! You might not have that many, but I'd be shocked if you didn't have a handful. How much support time could you save by consolidating directories?
Do your company's business units sometimes take technology into their own hands and purchase solutions that IT might not even be aware of, let alone support? For example, do some business units purchase business intelligence (BI) front-end software, despite the fact that Microsoft Office and SharePoint, which are probably already available, provide the BI functionality most users need? You might be surprised at how much money rogue solutions represent when you add up technology spending throughout the organization.
How many Web meeting solutions are in use across your company? Would standardization save licensing and support costs?
Leverage investments across your IT platform When you evaluate technology purchases, how deeply do you consider the solution's prerequisites, dependencies, and repercussions throughout your platform stack? For example, when you research a virtualization solution—say, VMware versus Hyper-V—do you investigate whether you'll need to buy additional management technology to support the product you choose? The cost of additional management products might be the tipping point that pushes your decision to go with one or the other.
What about training? Would you or your staff need to learn new skills to deploy, operate, and support any solution you might buy? If so, that purchase has hidden costs for your company.
What about software or hardware that's deployed but never used? When users refuse to adopt deployed technology, your business pays all the total cost of ownership (TCO) but gets no return on investment (ROI). Try adding up the cost of all the products that are going unused, and then look for ways to make those solutions crucial to the users' day-to-day success. By integrating new deployments into existing workflow, you can ensure that you're getting business value from the deployed software. For example, I know of a company that had deployed InfoPath but found that users were ignoring it. Adoption only occurred when InfoPath was integrated into the organization's expense-reporting workflow. Everyone wanted to be reimbursed for expenses, so adoption of InfoPath became a given.
On the other hand, don't forget shelfware. Are there products your company paid for but never deployed? Keep an eye out for solutions that are so complex that no one will ever get around to installing—let alone using—them.
Understand options and pitfalls If it looks too good to be true, it probably is. That's a cliché, but there's a reason why it persists. In an economy that makes options suddenly attractive that would never previously have been considered, you have to be very careful to thoroughly understand what you're getting. Watch out for deals that claim you can save IT costs by reducing staff and hiring a third party to manage and run your infrastructure. Do such "deals" really save the company money? Often, they do nothing more than move expenditures from the IT budget into other cost centers. And once you've bought into such a deal, will your company be maneuvered into purchasing additional expensive services and solutions made by the service provider? It might be true that nobody ever got fired for buying from certain large technology companies, but some of those technology companies might have a vested interest in replacing existing IT infrastructure and staff with their own services.
Match Service Level Agreements (SLAs) to business realities Managing by SLA is an accepted way to ensure that IT meets the business needs. But have you thought through the implications of the extent of your SLAs? For example, are users active 24 hours per day? If not, do you really need a 99.999 percent uptime SLA? Suppose a server goes down at 2:00 A.M. If you're managing to that 99.999 SLA, somebody has to get out of bed and go to the office to fix the problem, or you need someone onsite at all times. Such SLAs are absolutely necessary in many organizations, but consider your specific needs and determine whether you might save money for the company by tailoring SLAs for specific needs.
Find ways to save energy Green IT is the buzzword of the year, and the green suggestion I hear most often is that you should virtualize everything you possibly can. Virtualization helps you consolidate servers so you have fewer machines doing work more efficiently, consuming less electricity, and saving floor space so you can reduce the physical size of the datacenter. Virtualization is indeed an excellent way to get greener for all those reasons. However, you can save power in lots of other ways, too.
Reduce the number of printers by 50% on each floor and in each department so that you don't have several sitting idle while consuming electricity. In addition, you can dedicate one printer per floor or department to high-quality print jobs to save on ink and toner.
Make sure no lights are on in the datacenter when no one is present. Consider investing in motion detectors, and create lighting zones so that only part of the datacenter is lighted at a time.
Encourage your company to adopt a work-at-home policy. Some companies are even eliminating office space for all employees and providing only a few shared workspaces for employees to use when they need to be in the office. Think about how much money your company could save by supporting workers at home and using technologies such as presentation virtualization (formerly known as terminal services), unified communications, voice over IP (VoIP), and Web conferencing solutions such as LiveMeeting.
Here's one of the most interesting ideas I've heard: companies are beginning to explore using all the heat generated in a datacenter to heat and cool entire buildings.
Software and hardware makers are finding more and more ways to help manage power. The Group Policy–enabled power management features in Windows Vista were some of the first steps in this direction. Windows 7 and Windows Server 2008 R2 provide several new power-management features.
  • Windows 7 includes improved Wake on LAN (WoL), which enables Windows 7 machines to sleep longer.
  • You get fine-grained control over wake-up packets.
  • Network management tools can reach sleeping computers by taking advantage of protocol offload to the network adapter.
  • The Wake on Wireless LAN (WoWLAN) feature extends sleep scenarios to wireless client devices.
  • Windows 7 lets you turn off power to the network adapter when the cable is disconnected and automatically restores power when you reconnect the cable.
Windows Server 2008 R2 introduces several power consumption improvements, including
  • Reduced multicore processor power consumption. Core Parking is a feature you configure through Group Policy settings in the Active Directory Domain Services. It consolidates processing power so that the computer uses as few processor cores as possible. Inactive processor cores are suspended until you need more power. At that point, Core Parking activates as many processor cores as are necessary for the processing you need.
  • Reduced processor power consumption, which works by adjusting processor speed. You use Group Policy settings to configure this feature.
  • Reduced storage power consumption. With Windows Server 2008 R2, you can boot from a Storage Area Network (SAN), so that individual servers don't need local hard disks. With fewer hard disks, power consumption decreases.
Just the Beginning
These suggestions represent just a fraction of the possible ways that you can reduce IT costs just by taking a close look at the efficiency of your existing infrastructure. The ideas are fairly obvious, but they do represent a lot of savings when taken all together. I know this is true because my colleagues at Advaiya have shown companies that have participated in BVAs how to save millions of dollars by following such practices.
Once you start thinking about all the ways you can tighten IT spending without losing staff or reducing the value of IT to the business, you begin to notice all sorts of things you hadn't thought of before. In just a few minutes of brainstorming with Eric Zinn, a former IT manager who now works with me at Advaiya, we came up with a huge list, including effective change control processes, centralized software and hardware procurement, monthly capacity management tracking reports, automated monitoring, effective help desk processes, having and implementing a sunset list of technology you no longer need, and just having regular operations meetings. Use these ideas as a jumping-off place to begin examining your organization's infrastructure.

Karen Forster is Director of Community and Media at Advaiya, Inc. She has more than 20 years' experience in publishing and technology. In 1996, she was asked to take the editorial lead on the start-up Windows NT Magazine (now Windows IT Pro). She launched SQL Server Magazine and its Web site in 1999. In 2002, Microsoft recruited Karen to serve as Director of Windows Server User Assistance, bringing her from Colorado to the Seattle area.


Utility Spotlight Faster CPU Utilization Reports Using Multithreading
James Turner

Code download available at: UtilityOnlineAprTurner2009_05.exe (153 KB)

Contents
Script Prep
Creating the Server List
Multithreading
Wrapping It Up
This edition of Utility Spotlight is a little different than the usual, in that it involves scripts instead of executables, and so the column is dual-purpose: not only does it give you a nice way to build a report on CPU utilization in your organization, it also serves as a mini-tutorial to explain how the script works and how to use it.
If you're a system administrator, you may be familiar with trying to determine a server's CPU utilization remotely by querying the LoadPercentage property of the Win32_Processor Class. I recently wrote such a script to retrieve readings from a list of all of my domain servers. The script satisfied an immediate need to scan and report on all of my servers during a period when we were experiencing an overall server slowdown across our domain.
There was, however, an obvious limitation to the script in that only one server could be evaluated at a time, which meant that it took quite a while to get completely through the entire list of the servers.
To speed up the process, I decided to use multithreading, which resulted in a remarkable improvement—instead of taking close to 15 minutes to complete the scan of over 100 servers, the new process finished in just a few minutes.
That improvement did come at a bit of a cost, however. Instead of using one simple Visual Basic script, the new process requires two scripts, the recording of individual server CPU results to individual text files, a Data folder to hold those files, a routine to monitor the number of consecutive running threads, another routine to monitor the completion of all of the threads, and a process to read all of the text files into a Microsoft Office Excel spreadsheet.
Was it worth the extra work? I think so, because the new process helps improve reaction and response time to possible critical problems that might exist on your servers.

Script Prep
You can download the scripts at the Code Downloads section of our Web site. The main script for this process, CPUloadpercentageMultiThread.vbs, is listed in Figure 1. It runs a separate script called CPUThread.vbs (see Figure 2) that evaluates the CPULoadPercentage for each server in your domain.
Figure 1 CPUloadpercentageMultiThread.vbs
'***********************************************************************************************
'*** CPUloadpercentageMultiThread.vbs - Jim Turner
'*** Report on CPU Load Percentage for Domain Servers
'***  Adjust variables at Call Out A
'*** Uses MultiThreaded approach to speed up process by Calling CPUThread.vbs
'*** Requires Excel
'***********************************************************************************************
On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
CONST ForReading = 1
CONST xlAscending = 1 : CONST xlDescending = 2
Const xlHeader = 1 : Const xlNoHeader = 2

'Call Out A
'*** Set these variables
TotalActiveThreads=20
NumberOfSamples = 5
ThreadVBSPath = "C:\scripts\CPUrefresher\"
DataPath = "C:\scripts\CPUrefresher\DATA\"
'*** Set these Variables
'End Call Out A

strMessage = "Excel Spreadsheet will open when process completes"
strScriptName = "CPU LoadPercentage Script"
CreateObject("WScript.Shell").Popup strMessage,5,strScriptName,vbInformation

'*** Call Out B
DNC = GetObject("LDAP://RootDSE").Get("defaultNamingContext")
QueryStr = "SELECT cn FROM 'LDAP://" & DNC & "' where objectcategory='computer' and operatingSystem='*server*'"
'End Call Out B

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Sort On") = "CN"
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommand.CommandText = QueryStr
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst

'Call Out C
Set oShell = CreateObject("WSCript.shell")
Do Until objRecordset.EOF
 Err.Clear
 strComputer = ""
 strComputer = objRecordSet.Fields("CN").Value
 cmd = ThreadVBSPath & "CPUThread.vbs " & strComputer & " " & NumberOfSamples & " " & DataPath

 ThreadAvailable = False
 Do Until ThreadAvailable
  Set Processes = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * from Win32_Process where name ='wscript.exe'")
  If Processes.count < (TotalActiveThreads + 1) Then
   ThreadAvailable = True
   oShell.Run cmd,1,False
  End If
  Set Processes = Nothing
 Loop
 objRecordset.MoveNext
Loop
'End Call Out C

'Call Out D
MarkTime = Now()
ThreadAvailable = False
Do Until ThreadAvailable
 Set Processes = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * from Win32_Process where name ='wscript.exe'")

'*** Wait until all wscript processes are done or 120 seconds, whichever occurs first
'*** possible that other unrelated scripts may be running
 If Processes.Count < 2 Or DateDiff("s",MarkTime,Now()) > 120 Then
  ThreadAvailable = True
 Else
  Set Processes = Nothing
 End If
Loop
'End Call Out D

Set XL = CreateObject("Excel.Application")
XL.WorkBooks.Add
XL.Cells(1,1).Value = "Server"
XL.Cells(1,2).Value = "Processor"
XL.Cells(1,3).Value = "Load Average"

Row = 2

strPath = "C:\scripts\CPUrefresher\DATA\"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = FSO.GetFolder(strPath)
For Each objFile In objFolder.Files
 aray = ""
 strFile = strPath & objFile.Name
 Set fsoRead = fso.OpenTextFile(strFile,ForReading,False)
 CPUinfo = fsoRead.ReadAll
 fsoRead.Close
 aray = Split(CPUinfo,VBCRLF)

'Call Out E
 Set UniqCPU = CreateObject("Scripting.Dictionary")
 Set CPUAverage = CreateObject("Scripting.Dictionary")
'End Call Out E

'Call Out F
 For Each arItem In aray

  UniqCPU.RemoveAll
  CPUAverage.RemoveAll

  If Trim(arItem) <> "" Then
   ArFields = Split(arItem," ")
   If Instr(ArFields(1),"CPU") <> 0 Then
    UniqCPU.Add ArFields(1),0
   End If
  End If
 Next
'End Call Out F

'Call Out G
 For Each arItem In aray
  If Trim(arItem) <> "" Then
   ArFields = Split(arItem," ")
   If IsNumeric(ArFields(2)) Then

    UniqCPU.Item(ArFields(1)) = clng(UniqCPU.Item(ArFields(1))) + Clng(ArFields(2))

   End If
  End If
 Next
'End Call Out G

'Call Out H
 For Each arItem In aray
  If Trim(arItem) <> "" Then

   If Not CPUAverage.Exists(ArFields(1)) Then
    CPUAverage.Add ArFields(1),ArFields(1)
    ArFields = Split(arItem," ")
    XL.Cells(Row,1).Value = ArFields(0)
    XL.Cells(Row,2).Value = ArFields(1)

    XL.Cells(Row,3).Value = Round(UniqCPU.Item(ArFields(1)) / NumberOfSamples)

    Row = Row + 1
   End If
  End If
 Next
'End Call Out H
Next

XL.Cells.Select
XL.Selection.Sort XL.Range("c1"),xlDescending,XL.Range("A1"),,xlAscending,XL.Range("B1"),xlAscending,XLHeader,1,False
XL.Cells.EntireColumn.AutoFit
XL.Rows("2:2").Select
XL.ActiveWindow.FreezePanes = True
XL.Range("A1").Select
XL.Visible = TRUE
Figure 2 CPUThread.vbs
On Error Resume Next
If WScript.Arguments.Count < 1 Then
 Wscript.Quit
Else
 strComputer = WScript.Arguments.Item(0)
 NumberOfSamples = Clng(WScript.Arguments.Item(1))
 Datapath = WScript.Arguments.Item(2)
End If

Set fso = CreateObject("Scripting.FileSystemObject")

txtfile= Datapath & strComputer & ".txt"
Set TextFile = fso.CreateTextFile(txtfile,True)

Set objWMIService = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
If Err.Number <> 0 Then
 TextFile.WriteLine strComputer & " " & "ConnectionProblem"
 Set objWMIService = nothing
 Err.Clear
Else
 Set OSItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48)
 For Each OpSys in OSItems
  OS = OpSys.Caption
 Next
 Set OSItems = nothing
 If instr(OS,"Windows 2000") <> 0 Then
  For i = 1 to NumberOfSamples
   Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
   Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor",,48)
   For Each objItem in colItems
    TextFile.WriteLine strComputer & " " & objItem.DeviceID & " " & objItem.LoadPercentage
   Next
  Next
 Else
  Set objWMIService = nothing
  Set RefreshingObject = CreateObject("WbemScripting.SWbemRefresher")
  Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
  If Err.Number <> 0 Then
   TextFile.WriteLine strComputer & " " &  "ConnectionProblem"
   Err.Clear
  Else
   Set ItemObjects = RefreshingObject.AddEnum(objWMIService,"Win32_Processor")
   RefreshingObject.Refresh
   For i = 1 to NumberOfSamples
    RefreshingObject.Refresh
    For Each Sampling in ItemObjects.ObjectSet
     TextFile.WriteLine strComputer & " " & Sampling.DeviceID & " " & Sampling.LoadPercentage
    Next
   Next
  End If
 End If
End If
TextFile.Close
Before you can run the main script, there are a few variables you will need to adjust. These can be found at Call Out A in the main script:
TotalActiveThreads=20
NumberOfSamples = 3
ThreadVBSPath = "C:\scripts\  CPUrefresher\"
DataPath = "C:\scripts\CPUrefresher\DATA\"
TotalActiveThread represents the number of separate scripts you will allow to run at any one time on your computer. You can change TotalActiveThreads to any number you desire. Keep in mind, however, that though setting this value higher means you'll see results for all of your servers quicker, you'll also be using more memory and increasing the CPU processing load on your local computer. I suggest keeping the value for this variable between 15 and 30.
NumberOfSamples represents the number of times you want to take a CPU Load Percentage reading for each processor on a given server. Simply change the value of this variable to the number of CPU readings you want to take for each processor. Three to five should provide an accurate overall average.
ThreadVBSPath, as its name suggests, needs to point to the folder location of the CPUThread.vbs script. And you'll also need to point the DataPath variable value to the location where you want the resulting CPU load text files stored. Be sure this folder is empty or contains only text files produced by this script. The script attempts to open and read all files within this folder.
Note that you must manually create the folders specified in the ThreadVBSPath and DataPath variables before running the script.

Creating the Server List
Instead of trying to acquire a collection of servers by hardcoding a specific Active Directory OU, I chose a slightly different approach so I wouldn't have to change the code should an OU get changed, renamed, or moved, or should there be multiple OUs that contain Server objects.
At Call Out B in the main script, you'll see that I use a very generic query to produce my collection of servers from Active Directory:
QueryStr = "SELECT cn FROM 'LDAP://" & DNC & "' where
 objectcategory='computer' and operatingSystem='*server*'"
As you can see, the key to this query is to simply look for objects where the operating system contains the word "Server". This helps make the script even more generic, so the only mandatory changes you initially need to make are creating the Script and Data folders and initializing the variables for those two folders.

Multithreading
After setting up my ADO connection object, the script cycles through the returned collection of servers at Call Out C. Within this loop, I set up the command statement I will use to perform the multithreading, with this statement:
cmd = ThreadVBSPath & "CPUThread.vbs " & strComputer & " " &
 NumberOfSamples & " " & DataPath
Here's an example of what the concatenated command might actually look like:
C:\Scripts\CPUrefresher\CPUThread.vbs
  ServerOne 5
 C:\Scripts\CPUrefresher\Data\
Here you can see that the CPUThread script will be executed with arguments representing the name of the server, ServerOne, the number of samples to take, 5, and a reference to where the resulting text files should be written, C:\Scripts\CPUrefresher\Data\. The variable strComputer, which contains the servername, is the only piece of this command string that actually changes as each item in the server collection loop is iterated.
After setting the cmd variable, the following snippet of code controls the multithreading portion of the script:
ThreadAvailable = False
 Do Until ThreadAvailable
  Set Processes = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * from Win32_Process where name ='wscript.exe'")
  If Processes.count < (TotalActiveThreads + 1) Then
   ThreadAvailable = True
   oShell.Run cmd,1,False
  End If
  Set Processes = Nothing
 Loop
I start by creating a Boolean Flag variable called ThreadAvailable and set it to False. This Boolean value is used within a Do Until loop to restrict the number of wscript.exe processes that can be running at one time. As you'll soon see, this restriction is directly related to the value of the TotalActiveThreads variable, and as long as the total number of active wscript.exe threads is under a set value, the Boolean value of ThreadAvailable is set to True.
The next two lines of code determine whether a thread is available.
Set Processes = GetObject("winmgmts:\\.\root\cimv2").
      ExecQuery("Select * from Win32_Process where name ='wscript.exe'")
  If Processes.count < (TotalActiveThreads + 1) Then
The WMI query returns a collection of processes named wscript.exe, and Process.count indicates how many of those processes are currently running. If that number is less than the number you've set as TotalActiveThreads (plus one to account for this main script itself), then the ThreadAvailable variable is set to True and a multithreaded script is spawned via the following statement:
oShell.Run cmd,1,False
This statement is essentially running the CPUThread script (with the three arguments). As you recall, the assignment of the cmd variable looked something like this:
cmd = ThreadVBSPath & "CPUThread.vbs " & strComputer & " " &
  NumberOfSamples & " " & DataPath
The number 1 that follows cmd indicates that the resulting command window will run in a minimized state. The False parameter says you don't want to wait for the command to complete before moving on to the next line of code. This is basically the magic line of code that provides the multithreading functionality.
When the number of wscript.exe processes currently running is greater than or equal to TotalActiveThreads (plus one), the script stays within the Do Until loop until the number of wscript.exe processes drops and becomes less than TotalActiveThreads (plus one). Obviously, as the multithreaded scripts (CPUThread.vbs) finish, the number of wscript.exes drop and in essence open up a slot for another multithreaded script to be spawned.
Then, after all of the items in the server collection have been enumerated, the script goes into a waiting state that begins at Call Out D. This part of the code is designed to wait for all of the spawned multithreaded scripts to finish up before moving on to the final step that collects the data and creates the report.
The code for the wait state is very much like the code used in the Do Until loop just described, except that I only want to wait until the number of wscript.exe processes is less than two or until two minutes have passed. The reason for the added two-minute condition is that you could have other unrelated scripts running. I know that I need to account for this possibility because I have several local scheduled tasks that launch periodically throughout the day. Two minutes should be enough time to allow the remaining spawned processes finish up. If it's not, simply increase the number 120 to a higher value.
When either of these two conditions is met, the script begins its descent in which it opens up the files created by all of the CPUThread scripts and reads them into a spreadsheet. Much of this section is pretty basic stuff—opening files and reading them—but there is a bit of complexity involved that keeps track of multiple CPU load totals and averages that I'd like to touch upon.
At Call Out E, I set up two Dictionary objects, UniqCPU and CPUAverage. UniqCPU is used to keep track of each individual CPU and the combined sampling total CPU Loadpercentages for that CPU. The key portion of this dictionary element is the CPU device Id (CPU0, CPU1…), and the item portion of the dictionary element is a combined total of the cpuloadpercentage samples taken.
The other dictionary object, CPUAverage, is used as a Flag of sorts. I use it to determine if I've already reported on a specific CPU. I'll explain that in more detail shortly.
To understand how dictionary objects are put to use, you need to have an idea of what the data looks like in one of the text files created by the process. Here's an example:
SERVER3 CPU0 56
SERVER3 CPU1 94
SERVER3 CPU0 88
SERVER3 CPU1 57
SERVER3 CPU0 43
SERVER3 CPU1 54
Here, Server3 is simply the name of the server. CPU0 is the Device ID of the first processor on that server. 56 represents the return value of the first CPULoadPercentage sample taken. The next line represents the second CPU (device ID CPU1) and the first CPULoadPercentage sample (94) for that processor. The third line represents the second sampling of CPU0 and its CPULoadpercentage and so on and so on. So from this example, you can tell that there are two processors and three CPULoadpercentage samples for each. By the way, each line is subsequently converted into an array using the split function, making it easier to reference the CPU and CPULoadpercentage.
To set up my UniqCPU dictionary so that it contains just one key entry for each CPU, I run through the code at Call Out F, which creates the keys and initially sets the item value to zero.
If the sample data above were the actual data, my UniqCPU dictionary would have two entries, one key named for each CPU and an item element for each that would be a combined total of that CPU's loadpercentages. So for instance, UniqCPU key CPU0 would have an item value of 187. The process that adds the loadpercentage to each key can be viewed at Call Out G.
At this point in the code, I am ready to write results to Excel. As you can see at Call Out H, I cycle through the data once again and use my second dictionary CPUAverage to calculate the average for each CPU.
Figure 3 The Excel Report Showing CPU Load Average
After reading all of the text file data into the spreadsheet, I simply do a little Excel housekeeping and sort the spreadsheet so that the "hottest" CPUs are listed first.
As you'll recall, the other piece of this process involves the CPUThread script. It is in this script that the actual CPU Load Percentages are gathered. The CPULoadPercentage is an averaged percentage of the load on a particular CPU over a one-second time period.
As noted earlier, the main script passes three arguments to the CPUThread script, Server Name, Number Of Samples, and the Location of the Data files. These three arguments tell the CPUThread script which server to perform the WMI processor query on, how many times to refresh the query to accommodate the number of samples I want, and finally, where to write the results to.
The only twist is that this script uses a method of refreshing the processor collection information by utilizing the WbemScripting.SWbemRefresher class, and thereby eliminating the need to re-instantiate the WMI Win32_Processor class each time it needs to get a new CPU Load reading.
Note that I've added some simple logic to this script to make accommodations for Windows 2000, which is not compatible with the refresh class. If the operating system is Windows 2000, the WIN32_Processor class is repeatedly used to create a new instance of the processor object for as many times as you specify in the NumberOfSamples variable.

Wrapping It Up
When everything has completed, the Excel report lists each CPU's average in a single row, as you can see in Figure 3. This lets you sort to on the CPU Average Column and quickly see all of the "hot" CPU loads.

James Turner is a Domain Administrator for Computer Sciences Corporation and an Active Directory scripting applications and tools developer. He's been developing PC and server-based tools and applications using VBScript for nearly 10 years, and he has also authored many HTA applications, VBScripts, and scripting articles for Windows IT Pro Magazine. He specializes in Active Directory scripting and using Excel as his scripting reporting medium.


Windows Confidential Finding the Right Volume
Raymond Chen

When you left-click on the volume control icon in the notification area, a miniature volume control appears. If you have music playing, you will see two different volume levels whose heights change with the volume of the music—one gray and one green. What do they mean?
The gray bar represents the volume the music would be at if the volume slider were set to maximum. The green bar represents the actual volume of the music after applying the volume control at its current level.
OK, so why display the two different levels?
The audio folks learned that the volume control is the starting point for most users when troubleshooting the "I can't hear anything" problems. So they wanted to include the most common diagnostic information in an unobtrusive manner. While perhaps not entirely obvious at first, how this data is presented makes sense once you play with it for a few seconds.
So let's look at some scenarios.
Common reason #1 for no sound: Nothing is actually playing. This happens, for instance, when the user has forgotten to click Play. The clue for this is that the volume control slider doesn't show any moving bars at all—neither green nor gray. Your speaker is silent because you're not actually playing anything.
Common reason #2 for no sound: The volume is turned down too low. When you see the gray bar moving, that tells you that, well, something is playing, but the green bar is barely visible because your volume is set so low that the final result is a whisper. If you slide the slider upward, the green bar should get bigger and your music louder.
Common reason #3 for no sound: The speakers are not plugged in or the physical volume knob is set too low.
The gray bar is moving, the green bar is moving (and is a decent size), but you still can't hear anything. The computer thinks it is playing music—look at all that color and motion—so the next thing to look at is the connection between your computer and your speakers. Are the speakers plugged in? Did you plug them into the line-in jack by mistake? Is the volume knob on the speakers turned up sufficiently?
The audio folks on the Windows Team have a very difficult balancing act to manage. They need to make the sound experience simple for beginners who just want the sound to work (when they use cheap speakers and watch funny online videos of cats) while still satisfying the hard-core audiophiles (when they play back lossless audio recordings over expensive stereo systems). If you tinker too much to get those Internet videos to sound better (for example, automatically fixing volume levels), you end up alienating the audiophiles. As a result, a lot of potentially useful features are off by default to avoid upsetting those who take their audio playback very, very seriously.
By the way, if you want to turn on one of the potentially useful audio features, go to Control Panel | Sound | Playback | Properties | Enhancements and turn on Loudness Equalization. This tells Windows, "I want to set my volume control just once to a comfortable level and never touch it again." Then it doesn't matter whether you're watching recorded TV, watching a DVD, listening to a CD, or just being interrupted by a Windows beep—Windows will play them all at that volume. Note, however, that some programs do their own loudness equalization, and too many cooks can spoil the broth—or, in this case, degrade the signal quality.
Of course, many of the hard-core audiophiles would explode if the loudness equalization feature were on by default. "How dare you touch my finely tuned audio samples!"
I want to give a special thanks to Larry Osterman, Steve Ball, and other members of the Windows audio team for unwittingly providing the raw material that went into this article.

Raymond Chen's Web site, "The Old New Thing," and identically titled book (Addison-Wesley, 2007) deal with Windows history and Win32 programming. He listens to music on cheap speakers.