<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Windows Portable Devices Team Blog : WDK</title><link>http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx</link><description>Tags: WDK</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Sensors and Windows</title><link>http://blogs.msdn.com/wpdblog/archive/2009/12/17/sensors-and-windows.aspx</link><pubDate>Thu, 17 Dec 2009 20:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9938364</guid><dc:creator>wpdblog</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/9938364.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=9938364</wfw:commentRss><description>&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;Prior to the introduction of WPD, developers wrote a significant amount of code to integrate data from sensors into their Windows applications. But, with the release of WPD, it was possible to create a driver that handled communications between the operating system and the remote device. And, once the driver was written, a developer could write an application with a minimal code footprint—200 lines or less—to retrieve sensor data. For an example, refer to the downloadable whitepaper and code at: &lt;A href="http://wpdtempsensor.codeplex.com/" mce_href="http://wpdtempsensor.codeplex.com/"&gt;http://wpdtempsensor.codeplex.com/&lt;/A&gt;. (For an example WPD driver, refer to the WpdBasicHardwareDriver that ships in the Windows Driver Kit.)&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;For Windows 7, Microsoft introduced the Sensors and Location platform. This platform includes both a driver model for IHVs and an API for application developers. Microsoft recently released a sample driver, sample firmware, and a sample application on the MSDN Code Gallery to demonstrate the use of this new platform. See: &lt;A href="http://code.msdn.microsoft.com/motionsensor" mce_href="http://code.msdn.microsoft.com/motionsensor"&gt;http://code.msdn.microsoft.com/motionsensor&lt;/A&gt;. This sample, like the WPD sample above, interacts with the Parallax BS2 microcontroller; and, it’s intended as an enhancement (or replacement) of the WPD sample.&lt;SPAN style="COLOR: #1f497d"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;So, you may be wondering: “When should I use WPD to support my sensors and when should I use the Sensors and Location Platform?” Good question. The answer is straightforward. If you’re targeting Microsoft Windows XP or Microsoft Windows Vista: Use WPD. If you’re targeting Windows 7, use the new Sensors and Location Platform.&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;One of the key enhancements of the Sensor Platform is its class extension. The sample sensor driver uses the extension to fire both state-change events and data-update events. So, if the sensor is powered-down or disconnected, the driver calls a single class extension method: PostStateChange. And, each time the sensor sends new data, the driver calls the class extension’s &amp;nbsp;PostEvent method. The class extension, and these methods, make it very easy to support a “push” model for applications where the app registers to receive event notifications. &lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;Another enhancement is the platform’s “organization” of the sensor universe. The platform identifies specific categories and subcategories of sensors. So, for example, an application can retrieve all of the connected Passive Infrared sensors by invoking GetSensorsByCategory and specifying “BioMetric” as the specific category of interest. (The application developer doesn’t need to look for an identifier supplied by a hardware vendor for a particular passive infrared sensor.) &lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;By the way, if you were to compare the source code for the WpdBasicHardwareDriver and the SensorParallaxSample driver, you’d notice a number of similarities. This is by-design&lt;SPAN style="COLOR: #1f497d"&gt; &lt;/SPAN&gt;because the WPD and Sensor platform drivers are built on top of the User Mode Driver Framework (WUDF).&lt;SPAN style="COLOR: #1f497d"&gt; &lt;/SPAN&gt;&amp;nbsp;The code which configures the serial port, the code that creates the I/O Target, and the code that parses the packets returned by the sensor originated in the WpdBasicHardwareDriver and was ported to the Sensors and Location Platform.&lt;SPAN style="COLOR: #1f497d"&gt; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&lt;EM&gt;This posting is provided "AS IS" with no warranties and confers no rights.&lt;/EM&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;/o:p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9938364" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Windows+7/default.aspx">Windows 7</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Windows+Portable+Devices/default.aspx">Windows Portable Devices</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Sensors/default.aspx">Sensors</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Sensor+Application/default.aspx">Sensor Application</category></item><item><title>Windows 7 Driver Samples</title><link>http://blogs.msdn.com/wpdblog/archive/2009/09/18/windows-7-driver-samples.aspx</link><pubDate>Sat, 19 Sep 2009 00:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9896984</guid><dc:creator>wpdblog</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/9896984.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=9896984</wfw:commentRss><description>&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;The Windows Portable Devices Driver Kit in the Windows Driver Kit (WDK) comes bundled with five WPD sample drivers. Two of these drivers, WpdHelloWorldDriver and WpdWudfSampleDriver, were available in previous versions of the WDK. The remaining three drivers, WpdBasicHardwareDriver, WpdServiceSampleDriver, and WpdMultiTransportDriver, are new additions in the Windows 7 WDK. Together, these samples illustrate how to build a WPD driver for the different scenarios that WPD enables, including interaction with basic hardware, media synchronization, device services, and multi-transport. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;We had mentioned these samples in a previous post on the &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/wpdblog/archive/2009/09/11/windows-7-portable-device-development-kits.aspx" mce_href="http://blogs.msdn.com/wpdblog/archive/2009/09/11/windows-7-portable-device-development-kits.aspx"&gt;&lt;FONT size=2&gt;Windows 7 Portable Devices Development Kits&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=2&gt;. The purpose of this post is to spend some time covering each sample in greater detail. Hopefully, this will help driver developers navigate the various WPD samples, and figure out which sample(s) best fit their driver requirements. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;The following sections will describe each driver, the &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd434932.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd434932.aspx"&gt;&lt;FONT size=2&gt;WPD commands&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=2&gt; that each implements, and the operating systems that each supports. In addition, we will provide the links to instructions for building and installing.&lt;/FONT&gt;&lt;/P&gt;
&lt;H2&gt;WpdHelloWorldDriver&lt;/H2&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;SPAN&gt;Of all the sample drivers, the WpdHelloWorldDriver is the most simple. This driver supports and emulates four objects in software: a device object, a storage object, a folder object, and a text file object. WpdHelloWorldDriver was designed to provide the most basic scaffolding or skeleton required for developing a WPD driver; similar to the canonical "Hello World" program used for introducing a framework or programming language. If you are new to WPD driver development and need a kick start, we recommend starting with this sample.&lt;/SPAN&gt; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;The WpdHelloWorldDriver sample supports 22 commands. These commands cover the basic functionality that enables a WPD device to be browsed in Windows Explorer as a read-only device. The commands fall into four categories: object enumeration, object properties, object resources, and device capabilities. Like all WPD drivers, when this driver is installed and a WPD application calls a method to enumerate objects, set a property, open a resource, and so on, the driver will invoke a corresponding command handler for one of these supported commands. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;This driver is supported on Windows XP, Windows Vista (x86, amd64), and Windows 7 (x86, amd64). &lt;/P&gt;
&lt;P&gt;For instructions on how to build and install this driver, see: &lt;A href="http://msdn.microsoft.com/en-us/library/dd573842.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd573842.aspx"&gt;http://msdn.microsoft.com/en-us/library/dd573842.aspx&lt;/A&gt;&lt;/P&gt;
&lt;H2&gt;WpdBasicHardwareDriver&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;The WpdBasicHardwareDriver sample is new for Windows 7 and builds upon the WpdHelloWorldDriver. This sample stands apart from the other WPD samples in that it accesses real device hardware instead of emulating a software-only device. We provided this sample to demonstrate how a basic WPD driver can be built to interact with simple devices. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;For our demonstration device, we targetted a “hobbyist” microcontroller that reads data from a variety of sensors. The sensors include: a 2-axis accelerometer, a 3-axis accelerometer, a temperature/humidity sensor, a pressure sensor, a distance sensor, a passive infrared sensor, a compass, a vibration sensor, and a light sensor. These sensor devices are controlled by a Parallax BS2 microcontroller attached to the PC via an RS232 port. In addition to the driver source code, we also provided some sample firmware code that retrieves the sensor data and sends them over the serial port to the PC.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;The WpdBasicHardwareDriver sample supports an even smaller set of commands than the WpdHelloWorldDriver. In the interests of only providing the code that is necessary to demontrate the concepts, we removed some commands for object resources because the WpdBasicHardwareDriver does not need to support reading of files from the device. The remaining commands fall under these three categories: object enumeration, object properties, and device capabilities. To see this driver in action, you can use WpdMon to view the events corresponding to each sensor reading.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;This sample also showcases how WPP Software Tracing can be used for error checking macros. A while ago, we had a post &lt;FONT size=2&gt;that describes how you can &lt;A href="http://blogs.msdn.com/wpdblog/archive/2007/04/01/driver-dev-guide-using-wpp-tracing-in-your-wpd-driver.aspx" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/04/01/driver-dev-guide-using-wpp-tracing-in-your-wpd-driver.aspx"&gt;migrate your existing WPD driver from OutputDebugString to WPP Tracing&lt;/A&gt;. The WpdBasicHardwareDriver is now bundled with the macros.&lt;/FONT&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;This driver is supported on Windows XP, Windows Vista (x86, amd64), and Windows 7 (x86, amd64). If you plan to develop drivers that integrate sensors with Windows 7, we recommend using the &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd318953%28VS.85%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd318953(VS.85).aspx"&gt;&lt;FONT size=2&gt;Sensor API&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=2&gt; and &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/cc974537.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc974537.aspx"&gt;&lt;FONT size=2&gt;Sensor Driver Model&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=2&gt;. If you need to develop drivers to integrate sensors with Windows Vista or Windows XP, WPD provides a viable solution.&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;For instructions on how to build and install this driver, see: &lt;A href="http://msdn.microsoft.com/en-us/library/dd573829.aspx"&gt;http://msdn.microsoft.com/en-us/library/dd573829.aspx&lt;/A&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H2&gt;WpdWudfSampleDriver&lt;/H2&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;SPAN&gt;The WpdWudfSampleDriver is a comprehensive driver sample that demonstrates using the WPD DDI for media transfer scenarios.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;In addition to file browsing and transfer via Windows Explorer, this sample contains additional functionality that supports media synchronization with Windows Media Device Manager (WMDM) applications (e.g. Windows Media Player), and photo acquisition with Windows Image Acquisition (WIA) applications (e.g. Paint). All interactions with hardware are emulated in software (meaning that this driver talks to a "fake" device).&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;To enable the media transfer scenarios, the WpdWudfSampleDriver sample had to support a large set of commands, including the commands supported by the WpdHelloWorldDriver. These commands can be divided into eight categories: object enumeration, object management, object properties, bulk properties, object resources, capabilities, and storage.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;In this version, we fixed &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/wpdblog/archive/2007/05/08/getting-a-wpd-sample-driver-working-with-windows-media-player-11.aspx" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/05/08/getting-a-wpd-sample-driver-working-with-windows-media-player-11.aspx"&gt;&lt;FONT size=2&gt;a compatibility issue&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=2&gt; in the Vista WDK version of the sample driver code that prevents it from being properly enumerated in Windows Media Player.&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;This driver is supported on Windows XP, Windows Vista (x86, amd64), and Windows 7 (x86, amd64).&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;For instructions on how to build and install this driver, see: &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd573843.aspx"&gt;http://msdn.microsoft.com/en-us/library/dd573843.aspx&lt;/A&gt; &lt;/P&gt;
&lt;H2&gt;WpdMultiTransportDriver&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;The WpdMultiTransportDriver builds upon the WpdHelloWorldDriver and demonstrates how driver developers can take advantage of the Windows 7 support for Multiple Transports. For an overview on what multi transport is all about, check out our post two weeks ago about &lt;A href="http://blogs.msdn.com/wpdblog/archive/2009/09/04/multi-transport-devices-in-windows-7.aspx" mce_href="http://blogs.msdn.com/wpdblog/archive/2009/09/04/multi-transport-devices-in-windows-7.aspx"&gt;Multi-Transport support in Windows 7&lt;/A&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: small" class=Apple-style-span&gt;This driver emulates a transport driver and illustrates how to set the relevant multi-transport settings and generate the Functional Unique Identifier (FUID) during device arrival, in order to perform handshaking with the WPD Composite Driver. In addition, this sample supports multiple Windows Driver Framework I/O queues, where all the other WPD samples only support a single I/O queue.&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: small" class=Apple-style-span&gt;Other than the multi-transport support, the WpdMultiTransportDriver sample is virtually identical as the WpdHelloWorldDriver, and supports the same set of WPD commands. A quick way to zero-in on the code modifications needed to support Multi-Transport is to use your favorite diff program to compare the WpdHelloWorldDriver and WpdMultiTransportDriver source folders.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Because multi-transport support is a new feature in Windows 7, this sample driver is only supported on Windows 7 (x86, amd64). &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;For instructions on how to build and install this driver, see: &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd573843.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd573843.aspx"&gt;&lt;FONT size=2&gt;http://msdn.microsoft.com/en-us/library/dd573843.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;SPAN&gt;
&lt;H2&gt;WpdServiceSampleDriver&lt;/H2&gt;&lt;/SPAN&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;The WpdServiceSampleDriver demonstrates how a driver can support Windows 7 Device Services. &lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;We covered an &lt;A href="http://blogs.msdn.com/wpdblog/archive/2009/08/15/introducing-device-services.aspx" mce_href="http://blogs.msdn.com/wpdblog/archive/2009/08/15/introducing-device-services.aspx"&gt;introduction to Device Services&lt;/A&gt; in another recent post&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;. This driver emulates a basic Contacts device service that uses the Full Enumeration Sync device service. To support Device Services, this driver implements device services-specific WPD command sets: WPD_CATEGORY_SERVICE_COMMON, WPD_CATEGORY_SERVICE_CAPABILITIES, and WPD_CATEGORY_SERVICE_METHODS. These commands would allow an application to determine the capabilities of a service and invoke methods supported by the service. This driver also uses the new functionality in the WPD Class Extension (IPortableDeviceClassExtension) to register and unregister the Contacts device service interface. Last but not the least, to support object and property management, this sample also supports commands for object enumeration, object properties, bulk properties, object resources, and device capabilities.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;The WpdServiceSampleDriver does not emulate a Media Transfer Protocol (MTP) device. Like most of the other WPD samples, it simulates a software-only device that is not tied to a specific protocol or transport. If you are looking to build firmware for an MTP device that supports device services, you should start with the &lt;/FONT&gt;&lt;/SPAN&gt;&lt;A href="http://www.microsoft.com/whdc/device/wpd/MTP-DEK_Win7.mspx" mce_href="http://www.microsoft.com/whdc/device/wpd/MTP-DEK_Win7.mspx"&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;Device Enabling Kit&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: small" class=Apple-style-span&gt;Device Services is a new feature we introduced in Windows 7, therefore this sample is only supported on Windows 7 (x86, amd64).&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;For instructions on how to build and install this driver, see: &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd573846.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd573846.aspx"&gt;&lt;FONT size=2&gt;http://msdn.microsoft.com/en-us/library/dd573846.aspx&lt;/FONT&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;I&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; FONT-SIZE: 10pt"&gt;This posting is provided "AS IS" with no warranties and confers no rights.&lt;/SPAN&gt;&lt;/I&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9896984" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WMDM/default.aspx">WMDM</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WIA/default.aspx">WIA</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Device+Services/default.aspx">Device Services</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/multi-transport/default.aspx">multi-transport</category></item><item><title>Driver Dev Guide: Client Context Management</title><link>http://blogs.msdn.com/wpdblog/archive/2007/06/06/driver-dev-guide-client-context-management.aspx</link><pubDate>Wed, 06 Jun 2007 02:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3105948</guid><dc:creator>wpdblog</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/3105948.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=3105948</wfw:commentRss><description>&lt;b&gt;Client Context Management in WPD Drivers&lt;/b&gt;
&lt;p&gt;A WPD driver provides the communication channel between applications and the physical device.&amp;nbsp;&amp;nbsp;&amp;nbsp;There&amp;nbsp;can be multiple WPD applications running&amp;nbsp;at any time, and the driver&amp;nbsp;needs to handle requests from different clients and identify the clients based on the queued requests.&amp;nbsp;&amp;nbsp; In other words, the driver needs an efficient and easy way to&amp;nbsp;store client data&amp;nbsp;on a per-connection basis, and retrieve the data per request.&amp;nbsp;&amp;nbsp;&amp;nbsp; Fortunately, UMDF supports &lt;b&gt;context areas&lt;/b&gt;, a generic&amp;nbsp;mechanism to save data with a framework object.&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/b&gt;A WPD driver can allocate a data structure or object to hold the data, assign it to the framework object's context area, and retrieve the context at a later time.&amp;nbsp; The appropriate per-connection WDF framework object to use is the WDF file object.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Step 1: Assigning the Context&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The driver assigns the context when the client opens a connection to it.&amp;nbsp;&amp;nbsp; When a WPD&amp;nbsp;application calls &lt;a href="http://msdn.microsoft.com/en-us/library/dd375690%28VS.85%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd375690(VS.85).aspx"&gt;IPortableDevice::Open&lt;/a&gt;, the WPD API creates a handle to the driver using Win32 &lt;b&gt;CreateFile&lt;/b&gt;.&amp;nbsp;&amp;nbsp; Under the hood, UMDF initializes an &lt;a href="http://msdn2.microsoft.com/en-us/library/aa511202.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511202.aspx"&gt;IWDFFile&lt;/a&gt; object and&amp;nbsp;forwards it, along with the Creation request, to the driver's&amp;nbsp;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa511424.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511424.aspx"&gt;IQueueCallbackCreate::OnCreateFile&lt;/a&gt;&amp;nbsp;method.&amp;nbsp;&amp;nbsp; The IWDFFile in this case represents&amp;nbsp;a Win32&amp;nbsp;HANDLE&amp;nbsp;that is used for subsequent communication from this client to the driver.&amp;nbsp;&amp;nbsp; &lt;/p&gt;

&lt;p&gt;A example of a CreateFile callback&amp;nbsp;implementation is WpdWudfSampleDriver's &lt;b&gt;CQueue::OnCreateFile&lt;/b&gt;.&amp;nbsp; A driver-specific&amp;nbsp;&lt;b&gt;ContextMap&lt;/b&gt; COM object is used to store client data (application name, version, in-progress enumeration and resource contexts, etc).&amp;nbsp;&amp;nbsp; Note that the use of COM objects as context data is&amp;nbsp;NOT required by UMDF -&amp;nbsp;UMDF&amp;nbsp;sees the&amp;nbsp;context data&amp;nbsp;as an opaque&amp;nbsp;PVOID.&amp;nbsp;&amp;nbsp; If you are&amp;nbsp;using a COM object for storing context data, your driver needs to maintain the reference count for that COM object, and ensure that its resources are freed in the appropriate cleanup methods.&lt;/p&gt;
&lt;p&gt;To save context data, the driver initializes a new ContextMap object, and calls&amp;nbsp;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa511074.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511074.aspx"&gt;IWDFObject::AssignContext&lt;/a&gt;&amp;nbsp;for&amp;nbsp;the IWDFFile object handed in by UMDF.&amp;nbsp; &amp;nbsp; The parameters&amp;nbsp;for AssignContext are the pointers to an &lt;a href="http://msdn2.microsoft.com/en-us/library/aa511214.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511214.aspx"&gt;IObjectCleanup&lt;/a&gt;&amp;nbsp;object [containing the context cleanup code], and the newly-created ContextMap [containing the data to store].&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn2.microsoft.com/en-us/library/aa511068.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511068.aspx"&gt;IObjectCleanup::OnCleanup&lt;/a&gt; will be called when the file object is destroyed during CloseHandle.&amp;nbsp;&amp;nbsp; See "Step 3" for further details on how to implement OnCleanup.&amp;nbsp;&amp;nbsp; &lt;/p&gt;

&lt;p&gt;In addition, only one context can be assigned to the file object (or any&amp;nbsp;UMDF&amp;nbsp;framework object).&amp;nbsp;&amp;nbsp;Subsequent calls to AssignContext will fail if a context has already been assigned.&amp;nbsp;&amp;nbsp; To add/remove&amp;nbsp;client-specific data dynamically,&amp;nbsp;one way is to implement a mapping object for managing the data (e.g.&amp;nbsp;WpdWudfSampleDriver's ContextMap object), and assign a pointer to that mapping object as file object's context.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Step 2: Retrieving and Saving Context Information&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;To access the client data during requests, the WPD driver gets the context from the&amp;nbsp;IWDFFile object. &amp;nbsp;&lt;/p&gt;

&lt;p&gt;The sequence is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Call &lt;a href="http://msdn2.microsoft.com/en-us/library/aa511217.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511217.aspx"&gt;IWDFIoRequest::GetFileObject&lt;/a&gt; to get the IWDFFile object. 
&lt;/li&gt;
&lt;li&gt;Call &lt;a href="http://msdn2.microsoft.com/en-us/library/aa511428.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511428.aspx"&gt;IWDFObject::RetrieveContext&lt;/a&gt;&amp;nbsp;on the IWDFFile object to access the context area.&amp;nbsp;&amp;nbsp; In the sample driver, this&amp;nbsp;will be&amp;nbsp;the pointer to the&amp;nbsp;ContextMap object that was created in CQueue::OnCreateFile during IPortableDevice::Open. 
&lt;/li&gt;
&lt;li&gt;Add/remove data to the ContextMap object directly when processing the WPD commands.&amp;nbsp; Each client connection (i.e. IPortableDevice::Open) will have its own IWDFFile object and ContextMap object.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
Example code from WpdWudfSampleDriver:&amp;nbsp; 
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;CQueue::OnDeviceIoControl &lt;/b&gt;- Retrieving the context map from the&amp;nbsp;WDF request's file object 
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;WpdBaseDriver::OnSaveClientInfo&lt;/b&gt; - Adding client information to the context&amp;nbsp;map when processing the&amp;nbsp;WPD_COMMAND_COMMON_SAVE_CLIENT_INFORMATION command&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Step 3: Cleaning up the Context&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;When the client application calls &lt;a href="http://msdn.microsoft.com/en-us/library/dd375687%28VS.85%29.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd375687(VS.85).aspx"&gt;IPortableDevice::Close&lt;/a&gt;, the WPD API will in turn call CloseHandle on the Win32 handle associated with that open connection.&amp;nbsp;&amp;nbsp; Before destroying the&amp;nbsp;IWDFFile object in response to the CloseHandle,&amp;nbsp;UMDF calls the file object's &lt;b&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa511068.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa511068.aspx"&gt;IObjectCleanup::OnCleanup&lt;/a&gt;&lt;/b&gt; method that the driver passed into AssignContext during OnCreateFile.&lt;/p&gt;

&lt;p&gt;An example implementation of the IQueueCleanup callback is WpdWudfSampleDriver's &lt;b&gt;CQueue::OnCleanup&lt;/b&gt;.&amp;nbsp;&amp;nbsp; This method retrieves the&amp;nbsp;ContextMap stored in the IWDFObject object&amp;nbsp;(in this case,&amp;nbsp;the instance of&amp;nbsp;IWDFFile from OnCreateFile) and frees the allocated memory, including the objects that the ContextMap holds.&amp;nbsp;&amp;nbsp; To avoid memory leaks, ensure that the objects are properly cleaned up, and (if applicable) decrement the reference count.&lt;br&gt;&lt;/p&gt;

&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;References&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;A great WDF book is &lt;a href="http://www.microsoft.com/whdc/driver/wdf/wdfbook.mspx" mce_href="http://www.microsoft.com/whdc/driver/wdf/wdfbook.mspx"&gt;Developing Drivers with WDF&lt;/a&gt;&amp;nbsp;by Orwick/Smith.&amp;nbsp;Chapter 5 (pages 124-125) covers techniques for object-specific context data storage using UMDF.&amp;nbsp;&amp;nbsp;&amp;nbsp; The WpdWudfSampleDriver sample code is available in the Windows Driver Kit.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;&lt;/i&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3105948" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category></item><item><title>Which version of the WDK do I download?</title><link>http://blogs.msdn.com/wpdblog/archive/2007/05/16/which-version-of-the-wdk-do-i-download.aspx</link><pubDate>Wed, 16 May 2007 22:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2678855</guid><dc:creator>wpdblog</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/2678855.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=2678855</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;To develop&amp;nbsp;WPD&amp;nbsp;drivers for Vista SP1:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;-&amp;nbsp;Build them using the Vista WDK (version 6000) or from the Longhorn Server Beta 3 WDK build environments.&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;-&amp;nbsp;WPD drivers built using Longhorn Server WDK Beta 3 will &lt;STRONG&gt;not run&lt;/STRONG&gt; on Vista RTM or Windows XP, this is because the version 1.7&amp;nbsp;WDF Co-installer shipped in the Beta 3 release does not support downlevel operating systems (Vista RTM, XP, Server 2003).&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;To develop WPD drivers for Vista RTM:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;-&amp;nbsp;Build&amp;nbsp;them from the Vista WDK (version 6000)&amp;nbsp;&lt;/P&gt;
&lt;P&gt;- The drivers can run on Windows XP with &lt;A class="" title="Installing the Sample Drivers on XP and Vista" href="http://blogs.msdn.com/wpdblog/archive/2007/04/03/installing-the-sample-drivers-on-xp-and-vista.aspx" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/04/03/installing-the-sample-drivers-on-xp-and-vista.aspx"&gt;INF changes&lt;/A&gt;&amp;nbsp;and Windows Media Player 11 or Format SDK&amp;nbsp;Redistributable 11&amp;nbsp;installed&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/EM&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2678855" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category></item><item><title>Getting a WPD Sample Driver working with Windows Media Player 11</title><link>http://blogs.msdn.com/wpdblog/archive/2007/05/08/getting-a-wpd-sample-driver-working-with-windows-media-player-11.aspx</link><pubDate>Tue, 08 May 2007 22:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2485116</guid><dc:creator>wpdblog</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/2485116.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=2485116</wfw:commentRss><description>&lt;p&gt;We mentioned in a &lt;a href="http://blogs.msdn.com/wpdblog/archive/2007/01/31/building-driver-samples-from-the-wdk.aspx" class="" title="Building WPD Driver Samples from the WDK" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/01/31/building-driver-samples-from-the-wdk.aspx"&gt;previous post&lt;/a&gt;&amp;nbsp;that the WPD sample drivers are not designed to enumerate in Windows Media Player 11 (WMP11) due to compatibility issues.&amp;nbsp;&amp;nbsp; This post covers the changes needed to enable the WPD Comprehensive Sample Driver (WpdWudfSampleDriver) to&amp;nbsp;appear&amp;nbsp;as a&amp;nbsp;portable device in WMP11 and simulate a sync.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The WpdWudfSampleDriver is featured in this post because it contains a lot more functionality than the WpdHelloWorldDriver,&amp;nbsp;and is closer to meeting the requirements of WMP11 than the WpdHelloWorldDriver.&amp;nbsp;&amp;nbsp;&amp;nbsp; More specifically, the WpdWudfSampleDriver &lt;b&gt;simulates&lt;/b&gt; the following additional functionality:&lt;/p&gt;
&lt;p&gt;1. Creating and transferring data objects on the device.&lt;/p&gt;
&lt;p&gt;2. &lt;a href="http://msdn.microsoft.com/en-us/library/dd435167.aspx" title="Rendering Information" mce_href="http://msdn.microsoft.com/en-us/library/dd435167.aspx"&gt;Rendering information&lt;/a&gt; profiles for creating content to the device.&lt;/p&gt;
&lt;p&gt;3. Setting properties on objects.&lt;/p&gt;
&lt;p&gt;4. &lt;a href="http://blogs.msdn.com/wpdblog/archive/2007/03/16/how-to-post-events-from-your-wpd-driver.aspx" class="" title="Posting Events from a WPD Driver" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/03/16/how-to-post-events-from-your-wpd-driver.aspx"&gt;Posting device events&lt;/a&gt;.&lt;/p&gt;
&lt;p mce_keep="true"&gt;5. &lt;a href="http://msdn.microsoft.com/en-us/library/dd419971.aspx" title="An example of a Bulk Property Operation" mce_href="http://msdn.microsoft.com/en-us/library/dd419971.aspx"&gt;Bulk property operations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the list above, items 1-3&amp;nbsp;provide basic&amp;nbsp;compatibility with WMP11.&amp;nbsp; Device events&amp;nbsp;are a "good to have" feature,&amp;nbsp;for application responsiveness to changes in the device content and device state.&amp;nbsp; Bulk property operations are optional, but also provide improved application responsiveness -&amp;nbsp;multiple properties for objects can be sent in batches, instead of&amp;nbsp;multiple per-object "GetProperty" requests.&lt;/p&gt;
&lt;p&gt;During sync, the WpdWudfSampleDriver simulates&amp;nbsp;file and folder creation&amp;nbsp;by allowing content to be created and transferred to the device.&amp;nbsp;&amp;nbsp; The data&amp;nbsp;is not persisted by the driver, and will exist as long as the sample driver is still loaded.&amp;nbsp;&amp;nbsp;&amp;nbsp;Once the driver is disconnected (e.g. disable in Device Manager), the data goes away.&amp;nbsp;&amp;nbsp; Typically, your WPD driver&amp;nbsp;would be sending this data to your physical device and persisting it there, so this should not be an issue for real devices.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Modifications to the WpdWudfSampleDriver to Enumerate and Sync in WMP11&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;Some of the changes below involve updating the fake contents on the device for illustration.&amp;nbsp;&amp;nbsp;&amp;nbsp;The same property requirements will apply for&amp;nbsp;your&amp;nbsp;own&amp;nbsp;driver or device objects.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p mce_keep="true"&gt;1.&amp;nbsp; Add WPD_DEVICE_SYNC_PARTNER as a writable property for the "Device" object.&amp;nbsp;&amp;nbsp; This is needed by WMP11 for setting up a sync partnership&amp;nbsp;with the device.&amp;nbsp;&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;In deviceobjectfakecontent.h:&lt;br&gt;&lt;br&gt;class DeviceObjectFakeContent : public FakeContent&lt;br&gt;{&lt;br&gt;  ...&lt;br&gt;&lt;br&gt;    virtual HRESULT GetAllValues(&lt;br&gt;        IPortableDeviceValues*  pValues)&lt;br&gt;    {&lt;br&gt;	...&lt;br&gt;        // Add WPD_DEVICE_SYNC_PARTNER&lt;br&gt;        hrSetValue = pValues-&amp;gt;SetStringValue(WPD_DEVICE_SYNC_PARTNER, SyncPartner);&lt;br&gt;        if (hrSetValue != S_OK)&lt;br&gt;        {&lt;br&gt;            CHECK_HR(hrSetValue, "Failed to set WPD_DEVICE_SYNC_PARTNER");&lt;br&gt;            return hrSetValue;&lt;br&gt;        }&lt;br&gt;        ...&lt;br&gt;    }	&lt;br&gt;&lt;br&gt;    virtual HRESULT WriteValue(&lt;br&gt;        const PROPERTYKEY&amp;amp; key,&lt;br&gt;        const PROPVARIANT&amp;amp; Value)&lt;br&gt;    {&lt;br&gt;        ...&lt;br&gt;        else if(IsEqualPropertyKey(key, WPD_DEVICE_SYNC_PARTNER))&lt;br&gt;        {&lt;br&gt;            if (Value.vt == VT_LPWSTR)&lt;br&gt;            {&lt;br&gt;               SyncPartner = Value.pwszVal;&lt;br&gt;            }&lt;br&gt;            else&lt;br&gt;            {&lt;br&gt;                hr = E_INVALIDARG;&lt;br&gt;                CHECK_HR(hr, "Failed to set WPD_DEVICE_SYNC_PARTNER because type was not VT_LPWSTR");&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;	...&lt;br&gt;    }&lt;br&gt;   ...&lt;br&gt;&lt;br&gt;private:&lt;br&gt;    ...&lt;br&gt;    CAtlStringW SyncPartner;&lt;br&gt;};&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;2. Add WPD_OBJECT_NON_CONSUMABLE as a writable property for all objects.&amp;nbsp;&amp;nbsp; This allows simulating the saving of sync settings into a&amp;nbsp;file on the device called&amp;nbsp;WMPInfo.xml.&amp;nbsp;&amp;nbsp; This file is created by WMP11 on the device and&amp;nbsp;marked as "Non Consumable," with Format = WPD_OBJECT_FORMAT_UNSPECIFIED and Content Type =&amp;nbsp;WPD_CONTENT_TYPE_UNSPECIFIED.&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;In fakecontent.h:&lt;br&gt;&lt;br&gt;class FakeContent&lt;br&gt;{&lt;br&gt;&lt;br&gt;    virtual HRESULT WriteValue(&lt;br&gt;        const PROPERTYKEY&amp;amp; key,&lt;br&gt;        const PROPVARIANT&amp;amp; Value)&lt;br&gt;    {&lt;br&gt;        ...&lt;br&gt;        else if (IsEqualPropertyKey(key, WPD_OBJECT_NON_CONSUMABLE))&lt;br&gt;        {&lt;br&gt;            if(Value.vt == VT_BOOL)&lt;br&gt;            {&lt;br&gt;                NonConsumable = Value.boolVal;&lt;br&gt;            }&lt;br&gt;            else&lt;br&gt;            {&lt;br&gt;                hr = E_INVALIDARG;&lt;br&gt;                CHECK_HR(hr, "Failed to set WPD_OBJECT_NON_CONSUMABLE because type was not VT_BOOL");&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;        ...&lt;br&gt;    }&lt;br&gt;   ...&lt;br&gt;};&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;3. Add&amp;nbsp;support for WPD_OBJECT_ORIGINAL_FILE_NAME in for all objects.&amp;nbsp; This involves updating the support properties and fixed attributes tables, and overriding FakeGenericFileContent::GetAllValues() to return this property in addition to the standard properties.&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;In helpers.cpp:&lt;br&gt;&lt;br&gt;const PROPERTYKEY* g_SupportedPropertiesForFakeContentFormat[] =&lt;br&gt;{&lt;br&gt;    ...&lt;br&gt;    &amp;amp;WPD_OBJECT_ORIGINAL_FILE_NAME,&lt;br&gt;    ...&lt;br&gt;};&lt;br&gt;&lt;br&gt;KeyAndAttributesEntry g_FixedAttributesTable [] =&lt;br&gt;{     &lt;br&gt;    ...&lt;br&gt;    {&amp;amp;FakeContent_Format, &amp;amp;WPD_OBJECT_ORIGINAL_FILE_NAME, &lt;br&gt;         UnspecifiedForm_CanRead_CannotWrite_CannotDelete_Fast},&lt;br&gt;    // Properties for the device object&lt;br&gt;    ...&lt;br&gt;}&lt;br&gt;&lt;br&gt;In fakecontent.h:&lt;br&gt;&lt;br&gt;class FakeGenericFileContent : public FakeContent&lt;br&gt;{&lt;br&gt;public:&lt;br&gt;&lt;br&gt;    virtual HRESULT GetAllValues(&lt;br&gt;        IPortableDeviceValues*  pStore)&lt;br&gt;    {&lt;br&gt;        HRESULT             hr          = S_OK;&lt;br&gt;        PropVariantWrapper  pvValue;&lt;br&gt;&lt;br&gt;        // Call the base class to fill in the standard properties&lt;br&gt;        hr = FakeContent::GetAllValues(pStore);&lt;br&gt;        if (FAILED(hr))&lt;br&gt;        {&lt;br&gt;            CHECK_HR(hr, "Failed to get basic property set");&lt;br&gt;            return hr;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        // Add WPD_OBJECT_ORIGINAL_FILE_NAME&lt;br&gt;        pvValue = FileName;&lt;br&gt;        hr = pStore-&amp;gt;SetValue(WPD_OBJECT_ORIGINAL_FILE_NAME, &amp;amp;pvValue);&lt;br&gt;        if (hr != S_OK)&lt;br&gt;        {&lt;br&gt;            CHECK_HR(hr, ("Failed to set WPD_OBJECT_ORIGINAL_FILE_NAME"));&lt;br&gt;            return hr;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        return hr;&lt;br&gt;    }&lt;br&gt;    ...&lt;br&gt;};&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;4. Add support for creation of folders.&amp;nbsp;&amp;nbsp; These folders need to support WPD_OBJECT_ORIGINAL_FILE_NAME.&amp;nbsp;&amp;nbsp;&amp;nbsp; This allows WMP11 to create the "Album", "Artist" folders on the device during the sync operation.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;One way to do this is to&amp;nbsp;define a new &lt;b&gt;FakeFolderContent &lt;/b&gt;class that inherits from &lt;b&gt;FakeContent&lt;/b&gt;, and return WPD_OBJECT_ORIGINAL_FILE_NAME in &lt;b&gt;FakeFolderContent::GetAllValues()&lt;/b&gt;.&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;Added new header file: fakefoldercontent.h&lt;br&gt;&lt;br&gt;class FakeFolderContent : public FakeContent&lt;br&gt;{&lt;br&gt;public:&lt;br&gt;    ...&lt;br&gt;&lt;br&gt;    virtual HRESULT GetAllValues(&lt;br&gt;        IPortableDeviceValues*  pStore)&lt;br&gt;    {&lt;br&gt;        HRESULT             hr          = S_OK;&lt;br&gt;        PropVariantWrapper  pvValue;&lt;br&gt;&lt;br&gt;        // Call the base class to fill in the standard properties&lt;br&gt;        hr = FakeContent::GetAllValues(pStore);&lt;br&gt;        if (FAILED(hr))&lt;br&gt;        {&lt;br&gt;            CHECK_HR(hr, "Failed to get basic property set");&lt;br&gt;            return hr;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        // Add WPD_OBJECT_ORIGINAL_FILE_NAME&lt;br&gt;        pvValue = FileName;&lt;br&gt;        hr = pStore-&amp;gt;SetValue(WPD_OBJECT_ORIGINAL_FILE_NAME, &amp;amp;pvValue);&lt;br&gt;        if (hr != S_OK)&lt;br&gt;        {&lt;br&gt;            CHECK_HR(hr, ("Failed to set WPD_OBJECT_ORIGINAL_FILE_NAME"));&lt;br&gt;            return hr;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        return hr;&lt;br&gt;    }&lt;br&gt;};&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;All top level folders (e.g. Video Folder, Music Folder) in the sample driver can then initialize a &lt;b&gt;FakeFolderContent &lt;/b&gt;instead of a &lt;b&gt;FakeContent&lt;/b&gt;.&amp;nbsp;&amp;nbsp;&amp;nbsp; The value of WPD_OBJECT_ORIGINAL_FILE_NAME is usually the same as WPD_OBJECT_NAME.&amp;nbsp; Assign&amp;nbsp;the value of FileName in &lt;b&gt;FakeDevice::CreateContentObject() &lt;/b&gt;whenever an object is created, so that it will be returned during subsequent "Get Property" queries.&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;In fakedevice.h:&lt;br&gt;&lt;br&gt;class FakeDevice&lt;br&gt;{&lt;br&gt;    ...   &lt;br&gt;    HRESULT InitializeContent(&lt;br&gt;        IPortableDeviceClassExtension *pPortableDeviceClassExtension)&lt;br&gt;    {&lt;br&gt;        ...&lt;br&gt;        &lt;br&gt;        // Add Media folder: Music folder&lt;br&gt;        pContent = new FakeFolderContent();&lt;br&gt;        if (pContent)&lt;br&gt;        {&lt;br&gt;            ...&lt;br&gt;            pContent-&amp;gt;FileName  = pContent-&amp;gt;Name;  // Set Original File Name property&lt;br&gt;            ...&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        // Repeat for other types of folders declared here&lt;br&gt;        ...&lt;br&gt;&lt;br&gt;        // Add generic file content objects to storage 1&lt;br&gt;        for(DWORD dwIndex = 0; dwIndex &amp;lt; NUM_VERTICAL_OBJECTS; dwIndex++)&lt;br&gt;        {&lt;br&gt;            m_dwLastObjectID++;&lt;br&gt;&lt;br&gt;            pContent = new FakeGenericFileContent();&lt;br&gt;            if (pContent)&lt;br&gt;            {&lt;br&gt;                ...&lt;br&gt;                pContent-&amp;gt;FileName = pContent-&amp;gt;Name;&lt;br&gt;                ...&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;        ...&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    HRESULT CreateContentObject(&lt;br&gt;        LPCWSTR                 pszObjectName,&lt;br&gt;        LPCWSTR                 pszParentID,&lt;br&gt;        REFGUID                 guidContentType,&lt;br&gt;        IPortableDeviceValues*  pObjectProperties,&lt;br&gt;        FakeContent**           ppContent)&lt;br&gt;    {&lt;br&gt;        ...&lt;br&gt;        if(guidContentType == WPD_CONTENT_TYPE_FOLDER)&lt;br&gt;        {&lt;br&gt;            FakeContent* pContent = NULL;&lt;br&gt;&lt;br&gt;            pContent = new FakeContent();&lt;br&gt;            if (pContent)&lt;br&gt;            {&lt;br&gt;                ...&lt;br&gt;                pContent-&amp;gt;FileName = pszObjectName;&lt;br&gt;                ...&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;   }&lt;br&gt;   ...&lt;br&gt;}; &lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;5.&amp;nbsp; Modify WpdWudfSampleDriver.INF to set &lt;b&gt;EnableLegacySupport &lt;/b&gt;to&lt;b&gt; 3 &lt;/b&gt;so that the WMDM compatibility&amp;nbsp;component is registered and enabled&amp;nbsp;for this device when it installs.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;; Enable support for legacy WIA and WMDM applications&lt;br&gt;HKR,,"EnableLegacySupport",0x10001,3&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;6. When returning the list of rendering information profiles in &lt;b&gt;SetRenderingProfiles()&lt;/b&gt;, return an additional profile for WPD_OBJECT_FORMAT_WMV.&amp;nbsp; This profile contains a single WPD_PROPERTY_ATTRIBUTE_FORM_ENUMERATION entry with an IPortableDevicePropVariantCollection containing the list of valid FourCC Codec VT_UI4 values.&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p mce_keep="true"&gt;This step is needed&amp;nbsp;because the sample driver reports support for WMV.&amp;nbsp;&amp;nbsp; &amp;nbsp;In your real driver implementation, you don't need this step unless your device needs to support WPD_OBJECT_FORMAT_WMV.&amp;nbsp;&amp;nbsp; WMP11 has additional requirements on the attributes of FourCC Codec property, and would not enumerate any content on the device otherwise [Symptom: you will see the device in the Sync Pane, but no content under the device].&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;In helpers.cpp:&lt;br&gt;&lt;br&gt;HRESULT GetVideoProfile(&lt;br&gt;    IPortableDeviceValues** ppProfile)&lt;br&gt;{&lt;br&gt;    HRESULT hr = S_OK;&lt;br&gt;    CComPtr&amp;lt;IPortableDeviceValues&amp;gt; pProfile;&lt;br&gt;    CComPtr&amp;lt;IPortableDeviceValues&amp;gt; pFourCCCode;&lt;br&gt;&lt;br&gt;    hr = CoCreateInstance(CLSID_PortableDeviceValues,&lt;br&gt;                          NULL,&lt;br&gt;                          CLSCTX_INPROC_SERVER,&lt;br&gt;                          IID_IPortableDeviceValues,&lt;br&gt;                          (VOID**) &amp;amp;pProfile);&lt;br&gt;    CHECK_HR(hr, "Failed to CoCreateInstance CLSID_PortableDeviceValues");&lt;br&gt;&lt;br&gt;    if (hr == S_OK)&lt;br&gt;    {&lt;br&gt;        hr = CoCreateInstance(CLSID_PortableDeviceValues,&lt;br&gt;                              NULL,&lt;br&gt;                              CLSCTX_INPROC_SERVER,&lt;br&gt;                              IID_IPortableDeviceValues,&lt;br&gt;                              (VOID**) &amp;amp;pFourCCCode);&lt;br&gt;        CHECK_HR(hr, "Failed to CoCreateInstance CLSID_PortableDeviceValues");&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    // Set the value for WPD_OBJECT_FORMAT to indicate this profile applies to WMV objects&lt;br&gt;    if (hr == S_OK)&lt;br&gt;    {&lt;br&gt;        hr = pProfile-&amp;gt;SetGuidValue(WPD_OBJECT_FORMAT, WPD_OBJECT_FORMAT_WMV);&lt;br&gt;        CHECK_HR(hr, "Failed to set WPD_OBJECT_FORMAT");&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    // Set the value for WPD_VIDEO_FOURCC_CODE&lt;br&gt;    if (hr == S_OK)&lt;br&gt;    {&lt;br&gt;        CComPtr&amp;lt;IPortableDevicePropVariantCollection&amp;gt; pFourCCCodeEnumElements;&lt;br&gt;&lt;br&gt;        if (hr == S_OK)&lt;br&gt;        {&lt;br&gt;            hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection,&lt;br&gt;                                  NULL,&lt;br&gt;                                  CLSCTX_INPROC_SERVER,&lt;br&gt;                                  IID_IPortableDevicePropVariantCollection,&lt;br&gt;                                  (VOID**) &amp;amp;pFourCCCodeEnumElements);&lt;br&gt;            CHECK_HR(hr, "Failed to CoCreateInstance &lt;br&gt;                     CLSID_PortableDevicePropVariantCollection");&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        if (hr == S_OK)&lt;br&gt;        {&lt;br&gt;            hr = pFourCCCode-&amp;gt;SetUnsignedIntegerValue(&lt;br&gt;                                 WPD_PROPERTY_ATTRIBUTE_FORM, &lt;br&gt;                                 WPD_PROPERTY_ATTRIBUTE_FORM_ENUMERATION);&lt;br&gt;            CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_FORM &lt;br&gt;                          for WPD_VIDEO_FOURCC_CODE");&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        if (hr == S_OK)&lt;br&gt;        {&lt;br&gt;            // Only 1 sample value is set here, add more as appropriate for your device&lt;br&gt;            PROPVARIANT pvValue;&lt;br&gt;            PropVariantInit(&amp;amp;pvValue);&lt;br&gt;            pvValue.vt = VT_UI4;&lt;br&gt;            pvValue.ulVal = MAKEFOURCC('W', 'M', 'V', '3');&lt;br&gt;            hr = pFourCCCodeEnumElements-&amp;gt;Add(&amp;amp;pvValue);&lt;br&gt;            CHECK_HR(hr, "Failed to populate the FourCC Code Enumeration Elements");&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        if (hr == S_OK)&lt;br&gt;        {&lt;br&gt;            hr = pFourCCCode-&amp;gt;SetIPortableDevicePropVariantCollectionValue(&lt;br&gt;                                 WPD_PROPERTY_ATTRIBUTE_ENUMERATION_ELEMENTS, &lt;br&gt;                                 pFourCCCodeEnumElements);&lt;br&gt;            CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_ENUMERATION_ELEMENTS &lt;br&gt;                          for WPD_VIDEO_FOURCC_CODE");&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        // Now set the Video FourCC Code property to be pFourCCCode&lt;br&gt;        if (hr == S_OK)&lt;br&gt;        {&lt;br&gt;            hr = pProfile-&amp;gt;SetIPortableDeviceValuesValue(&lt;br&gt;                              WPD_VIDEO_FOURCC_CODE, &lt;br&gt;                              pFourCCCode);&lt;br&gt;            CHECK_HR(hr, "Failed to add the WPD_VIDEO_FOURCC_CODE attributes &lt;br&gt;                          to the WPD_OBJECT_FORMAT_WMV rendering profile");&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    // Set the output result&lt;br&gt;    if (hr == S_OK)&lt;br&gt;    {&lt;br&gt;        hr = pProfile-&amp;gt;QueryInterface(IID_PPV_ARGS(ppProfile));&lt;br&gt;        CHECK_HR(hr, "Failed to QI for IPortableDeviceValues");&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    return hr;&lt;br&gt;}&lt;br&gt;&lt;br&gt;HRESULT SetRenderingProfiles(&lt;br&gt;    IPortableDeviceValues*          pValues)&lt;br&gt;{&lt;br&gt;    ...&lt;br&gt;    CComPtr&amp;lt;IPortableDeviceValues&amp;gt;  pVideoProfile;&lt;br&gt;    ...&lt;br&gt;&lt;br&gt;    // Get the video profile&lt;br&gt;    if (hr == S_OK)&lt;br&gt;    {&lt;br&gt;        hr = GetVideoProfile(&amp;amp;pVideoProfile);&lt;br&gt;        CHECK_HR(hr, "Failed to get video profile properties");&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    // Add the profile to the collection&lt;br&gt;    if (hr == S_OK)&lt;br&gt;    {&lt;br&gt;        hr = pProfiles-&amp;gt;Add(pVideoProfile);&lt;br&gt;        CHECK_HR(hr, "Failed to add video profile to profile collection");&lt;br&gt;    }&lt;br&gt;    ...&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;

&lt;p&gt;&lt;b&gt;Known Issue with Multiple Storages&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;When a device that contains multiple storages&amp;nbsp;is disconnected, one of the storages will still remain in the treeview.&amp;nbsp;&amp;nbsp; This is a known bug in WMP11.&amp;nbsp;&amp;nbsp; Since the WpdWudfSampleDriver emulates multiple storages, you'll see this bug when you disable the driver from Device Manager while WMP11 is running.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p mce_keep="true"&gt;&lt;b&gt;Update [August 7, 2009]:&amp;nbsp;&lt;/b&gt; The WDK 7.0.0 now contains 
an updated &lt;b&gt;WpdWudfSampleDriver&lt;/b&gt; sample that supports enumeration in 
Windows Media Player. You can get the latest WDK &lt;a href="http://www.microsoft.com/whdc/DevTools/WDK/WDKpkg.mspx" mce_href="http://www.microsoft.com/whdc/DevTools/WDK/WDKpkg.mspx"&gt;here&lt;/a&gt;. See &lt;a href="http://www.microsoft.com/whdc/devtools/wdk/RelNotesW7.mspx#EHJAE" mce_href="http://www.microsoft.com/whdc/devtools/wdk/RelNotesW7.mspx#EHJAE"&gt;this 
WDK 7.0.0 RTM release note&lt;/a&gt; for the complete list of build environments and 
target operating systems applicable to the WPD driver samples. &lt;br&gt;&lt;/p&gt;

&lt;p mce_keep="true"&gt;&amp;nbsp; &lt;br&gt;&lt;/p&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2485116" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WMDM/default.aspx">WMDM</category></item><item><title>New Driver and Application Whitepapers Are Here</title><link>http://blogs.msdn.com/wpdblog/archive/2007/05/07/wpd-whitepapers.aspx</link><pubDate>Mon, 07 May 2007 21:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2466855</guid><dc:creator>wpdblog</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/2466855.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=2466855</wfw:commentRss><description>&lt;P&gt;We've published two new WPD developer-centric&amp;nbsp;whitepapers at the Microsoft WHDC website for WinHEC.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The first&amp;nbsp;covers how to do WMDRM metering and license synchronization from a WPD application; the second&amp;nbsp;describes how to port the existing WPD "Hello World" sample driver to communicate with a Parallax Basic Stamp II microcontroller to&amp;nbsp;read temperature sensor data.&amp;nbsp;&amp;nbsp; Both contain sample code.&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;I. Accessing WMDRM APIs from a WPD Application:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.microsoft.com/whdc/device/media/WMDRM_API.mspx" mce_href="http://www.microsoft.com/whdc/device/media/WMDRM_API.mspx"&gt;http://www.microsoft.com/whdc/device/media/WMDRM_API.mspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;This whitepaper describes how to associate a WPD device instance with a WMDM device instance for MTP devices; the WMDM device instance is then&amp;nbsp;used&amp;nbsp;for calling Windows Media Digital Rights Management (WMDRM) application interfaces. To&amp;nbsp;build the sample WPD application, you need the Windows Media Format SDK v11 and the Windows SDK (v6000).&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;II. Creating a WPD Driver for a Microcontroller-Based Sensor:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.microsoft.com/whdc/device/media/WPD_drv.mspx" mce_href="http://www.microsoft.com/whdc/device/media/WPD_drv.mspx"&gt;http://www.microsoft.com/whdc/device/media/WPD_drv.mspx&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;This sample is based on the Parallax Basic Stamp II microcontroller to provide an example of a simple hardware device that&amp;nbsp;can have a WPD driver for it.&amp;nbsp;&amp;nbsp; Parallax provides an &lt;A class="" title="Basic Stamp Activity Kit for Windows Portable Devices" href="http://www.parallax.com/detail.asp?product_id=910-90005" mce_href="http://www.parallax.com/detail.asp?product_id=910-90005"&gt;activity kit&lt;/A&gt; that contains the hardware components for this sample&amp;nbsp;driver.&amp;nbsp; To&amp;nbsp;build the driver,&amp;nbsp;you need the&amp;nbsp;Windows Driver Kit&amp;nbsp;(v6000).&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;References&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;All WPD-related whitepapers are posted &lt;A class="" title="Windows Portable Devices Whitepapers" href="http://www.microsoft.com/whdc/device/netAttach/default.mspx" mce_href="http://www.microsoft.com/whdc/device/netAttach/default.mspx"&gt;here&lt;/A&gt;.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;A class="" title="Downloading WPD for Development" href="http://blogs.msdn.com/controlpanel/blogs/To%20download%20the%20pre-requisities,%20see%20http://blogs.msdn.com/wpdblog/pages/downloading-wpd-for-development.aspx" mce_href="To download the pre-requisities, see http://blogs.msdn.com/wpdblog/pages/downloading-wpd-for-development.aspx"&gt;More information&lt;/A&gt; on downloading the various SDKs.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/EM&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2466855" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/SDK/default.aspx">SDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WMDM/default.aspx">WMDM</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/DRM/default.aspx">DRM</category></item><item><title>Driver Dev Guide:  Supporting WPD_CLIENT_EVENT_COOKIE</title><link>http://blogs.msdn.com/wpdblog/archive/2007/05/04/driver-dev-guide-sending-wpd-client-event-cookie-with-events.aspx</link><pubDate>Fri, 04 May 2007 03:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2402905</guid><dc:creator>wpdblog</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/2402905.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=2402905</wfw:commentRss><description>&lt;p mce_keep="true"&gt;WPD Applications&amp;nbsp;can specify&amp;nbsp;a unique&amp;nbsp;string "cookie"&amp;nbsp;in the client information when calling &lt;a href="http://msdn.microsoft.com/en-us/library/dd375690%28VS.85%29.aspx" title="IPortableDevice::Open" mce_href="http://msdn.microsoft.com/en-us/library/dd375690(VS.85).aspx"&gt;IPortableDevice::Open&lt;/a&gt;:&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;table rules="rows" border="0" cols="3" frame="below"&gt;
&lt;tbody&gt;
&lt;tr valign="top"&gt;
&lt;td width="28%"&gt;&lt;b&gt;WPD_CLIENT_EVENT_COOKIE&lt;/b&gt;&lt;/td&gt;
&lt;td width="29%"&gt;VT_LPWSTR&lt;/td&gt;
&lt;td width="43%"&gt;Client supplied cookie returned by the driver in events posted as a direct result of operations issued by this client.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&amp;nbsp; 
&lt;p mce_keep="true"&gt;This is in addition&lt;b&gt; &lt;/b&gt;to the&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/dd419935.aspx" title="WPD Client Information Properties" mce_href="http://msdn.microsoft.com/en-us/library/dd419935.aspx"&gt;client information&amp;nbsp;properties&lt;/a&gt; described&amp;nbsp;on MSDN, and declared in &lt;b&gt;PortableDevice.h&lt;/b&gt;.&lt;/p&gt;
&lt;p mce_keep="true"&gt;Depending on the application, this&amp;nbsp;value&amp;nbsp;will typically contain&amp;nbsp;the application's&amp;nbsp;DLL name or CLSID, or a&amp;nbsp;unique application-generated identifier&amp;nbsp;if the application supports multiple instances of itself running simultaneously.&amp;nbsp;&amp;nbsp;&amp;nbsp; The actual string&amp;nbsp;contents does not matter to the driver, it is passed back to the application when events are sent.&lt;/p&gt;
&lt;p mce_keep="true"&gt;When your driver sends an event and sets the cookie in the event parameters, the application can retrieve the cookie to determine if the event is a result of actions that originated from itself or another program.&amp;nbsp;&amp;nbsp;&amp;nbsp;For example,&amp;nbsp;Application&amp;nbsp;A creates an object on the device,&amp;nbsp;and receives an ObjectAdded event&amp;nbsp;containing&amp;nbsp;its client event cookie, it can&amp;nbsp;choose not to refresh its view of the device contents&amp;nbsp;because&amp;nbsp;the view has been updated at the time the object was created.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If Application B&amp;nbsp;creates another object on the device,&amp;nbsp;Application A will receive an ObjectAdded event with a&amp;nbsp;different cookie (or no cookie), and knows that&amp;nbsp;it needs to refresh the&amp;nbsp;device&amp;nbsp;contents view, because the object was added by some other client application.&lt;/p&gt;
&lt;p mce_keep="true"&gt;In an environment where there can be two or more client applications&amp;nbsp;communicating with your driver (Explorer&amp;nbsp;is virtually guaranteed to be one client through the WPD Shell Namespace Extension), supporting the event cookie mechanism is a good WPD programming practice that may help reduce the client traffic to your device in response to events, and to&amp;nbsp;streamline application-side event handling.&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;How to support WPD_CLIENT_EVENT_COOKIE in your WPD driver:&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;1. Add a handler for the WPD_COMMAND_COMMON_SAVE_CLIENT_INFORMATION command.&amp;nbsp; The &lt;b&gt;WpdWudfSampleDriver&lt;/b&gt; from the WDK contains an example of this in &lt;b&gt;WpdBaseDriver::OnSaveClientInfo()&lt;/b&gt;.&lt;/p&gt;
&lt;p mce_keep="true"&gt;2. In &lt;b&gt;OnSaveClientInfo()&lt;/b&gt;, if the application sets WPD_CLIENT_EVENT_COOKIE in the client information parameters, save the cookie with your context info. Some applications may choose not to send this cookie, in which case your driver does not have to do anything here.&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;LPWSTR pszEventCookie&amp;nbsp;= NULL;&amp;nbsp;&lt;br&gt;&lt;br&gt;hr = pClientInfo-&amp;gt;GetStringValue(WPD_CLIENT_EVENT_COOKIE, &amp;amp;pszEventCookie);&lt;br&gt;&lt;br&gt;if (hr == S_OK &amp;amp;&amp;amp; pszEventCookie != NULL)&lt;br&gt;{&lt;br&gt;    // Store the cookie value with the client context&lt;br&gt;    pContext-&amp;gt;EventCookie = pszEventCookie;&lt;br&gt;}&lt;br&gt;&lt;br&gt;CoTaskMemFree(pszEventCookie);&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;3. When posting events, if the client event cookie is available, send it along with the event parameters.&amp;nbsp;&amp;nbsp; In the sample driver, this code will be added to the &lt;b&gt;PostWpdEvent()&lt;/b&gt; function.&lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;HRESULT hrEventCookie = GetClientEventCookie(pCommandParams, &amp;amp;pszEventCookie);&lt;br&gt;&lt;br&gt;if (hrEventCookie == S_OK &amp;amp;&amp;amp; pszEventCookie != NULL)&lt;br&gt;{&lt;br&gt;    // Add it to the event parameters&lt;br&gt;    // The application's OnEvent callback will match this with its cookie&lt;br&gt;    hrEventCookie = pEventParams-&amp;gt;SetStringValue(WPD_CLIENT_EVENT_COOKIE, pszEventCookie);&lt;br&gt;}&lt;br&gt;&lt;br&gt;CoTaskMemFree(pszEventCookie);&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;And here's an outline of the &lt;b&gt;GetClientEventCookie()&lt;/b&gt; helper function.&amp;nbsp;&amp;nbsp; It uses the client information context&amp;nbsp;supplied in the command parameters&amp;nbsp;to look up the saved client cookie in the context map. &lt;/p&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;ClientContext* pClientContext = NULL;&amp;nbsp;&amp;nbsp; // This is a context helper object defined by the sample driver&lt;br&gt;&lt;br&gt;hr = pCommandParams-&amp;gt;GetStringValue(WPD_PROPERTY_COMMON_CLIENT_INFORMATION_CONTEXT, &amp;amp;pszClientContext);&lt;br&gt;&lt;br&gt;if (hr == S_OK)&lt;br&gt;{&lt;br&gt;    hr = GetClientContext(pCommandParams, pszClientContext, (IUnknown**)&amp;amp;pClientContext);&lt;br&gt;&lt;br&gt;    if (hr == S_OK &amp;amp;&amp;amp; pClientContext != NULL &amp;amp;&amp;amp; pClientContext-&amp;gt;EventCookie.GetLength() &amp;gt; 0)&lt;br&gt;    {&lt;br&gt;       // Allocate the cookie string to return &lt;br&gt;       *ppszEventCookie = AtlAllocTaskWideString(pClientContext-&amp;gt;EventCookie);&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    if (pClientContext != NULL)&amp;nbsp;&lt;br&gt;     &amp;nbsp;&amp;nbsp;&amp;nbsp; pClientContext-&amp;gt;Release();&lt;br&gt;&lt;br&gt;    CoTaskMemFree(pszClientContext);&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;&lt;i&gt;&lt;/i&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;For an overview on posting events,&amp;nbsp;refer to this&amp;nbsp;&lt;a href="http://blogs.msdn.com/wpdblog/archive/2007/03/16/how-to-post-events-from-your-wpd-driver.aspx" class="" title="How to Post Events From Your WPD Driver" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/03/16/how-to-post-events-from-your-wpd-driver.aspx"&gt;post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;/i&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2402905" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category></item><item><title>Installing the Sample Drivers on XP and Vista</title><link>http://blogs.msdn.com/wpdblog/archive/2007/04/03/installing-the-sample-drivers-on-xp-and-vista.aspx</link><pubDate>Tue, 03 Apr 2007 03:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2015189</guid><dc:creator>wpdblog</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/2015189.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=2015189</wfw:commentRss><description>&lt;p&gt;A question was raised today on how to run the WPD sample drivers on Windows XP.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WPD drivers and applications&amp;nbsp;can run downlevel on Windows XP as long as the WPD and UMDF runtimes are both installed.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Compiling a WPD Driver&amp;nbsp;for&amp;nbsp;your&amp;nbsp;OS&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;For the driver to run on Windows XP, it has to be built using a Windows XP x86 build environment provided by the Windows Driver Kit (v6000 or later).&amp;nbsp;&amp;nbsp; Similarly, for running on&amp;nbsp;Windows Vista,&amp;nbsp;use&amp;nbsp;one of the&amp;nbsp;Windows Vista build environments.&lt;/p&gt;
&lt;p mce_keep="true"&gt;If the runtime OS does not match the build environment, you may get a "Code 10 -&amp;nbsp;This Device Cannot Start" in error message in Device Manager after installing the driver.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Installing WPD on the XP machine&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;Either one of these supply the WPD runtime components&amp;nbsp;for Windows XP:&lt;/p&gt;
&lt;p mce_keep="true"&gt;1. Install Windows Media Player 11, or&lt;/p&gt;
&lt;p mce_keep="true"&gt;2. Install the Windows Media Format SDK 11 redistributable: WMFDist11-WindowsXP-X86-ENU.exe package, typically under c:\WMSDK\WMFSDK11\Redist folder&amp;nbsp;from a Windows Media Format 11 SDK install.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Obtaining the WUDF Co-Installer&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;The UMDF runtime is distributed and installed by referencing its co-installer in the driver INF.&amp;nbsp;&amp;nbsp; For Windows Vista and XP, the recommended co-installer to use is the version that is distributed&amp;nbsp;in&amp;nbsp;the&lt;b&gt; Windows Driver Kits&lt;/b&gt;: under the &lt;b&gt;\WinDDK\6001.xxxxx\redist\wdf\&lt;/b&gt; folder.&amp;nbsp;&amp;nbsp; Copy this to the same location as your updated driver INF&amp;nbsp;before installing your driver.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Modifying the Sample Driver INF&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;The following example shows the&amp;nbsp;INF changes to enable the WpdHelloWorldDriver to install in Windows XP using the v1.7 UMDF co-installer.&amp;nbsp;&amp;nbsp; The actual version number would depend on what was provided in the WDK.&amp;nbsp; The modified/added entries are highlighted in &lt;font color="red"&gt;red&lt;/font&gt;, and the same updates would apply to both WPD driver samples. &lt;br&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;The changes involve&amp;nbsp;adding a CopyFiles directive that references WUDFUpdate_01007.dll, and updating the AddReg entries to use UMDF&amp;nbsp;v1.7.&lt;/p&gt;
&lt;p&gt;[SourceDisksFiles]&lt;br&gt;WpdHelloWorldDriver.dll=1&lt;br&gt;&lt;font color="red"&gt;WUDFUpdate_01007.dll=1&lt;/font&gt;&lt;br&gt;...&lt;br&gt;&lt;br&gt;[Basic_Install.CoInstallers]&lt;br&gt;AddReg=Basic_Install.CoInstallers_AddReg&lt;br&gt;&lt;font color="red"&gt;CopyFiles=CoInstallers_CopyFiles&lt;/font&gt;&lt;br&gt;...&lt;br&gt;&lt;/p&gt;
&lt;p&gt;; Add the co-installer&amp;nbsp;DLL to the CopyFiles list&lt;br&gt;&lt;font color="red"&gt;[CoInstallers_CopyFiles]&lt;br&gt;WUDFUpdate_01007.dll&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;&lt;br&gt;; Update the registration to use the&amp;nbsp;correct binary&lt;br&gt;[Basic_Install.CoInstallers_AddReg] &lt;br&gt;HKR,,CoInstallers32,0x00010000,&lt;font color="red"&gt;"WUDFUpdate_01007.dll"&lt;/font&gt;&lt;br&gt;&lt;br&gt;...&lt;/p&gt;
&lt;p&gt;&lt;br&gt;; Update the UMDF version to 1.7.0&lt;br&gt;[WpdHelloWorldDriver_Install]&lt;br&gt;UmdfLibraryVersion=&lt;font color="red"&gt;1.7.0&lt;/font&gt;&lt;br&gt;&lt;br&gt;...&lt;/p&gt;
&lt;p&gt;&lt;br&gt;; Set the Co-Installer CopyFiles destination to system32&lt;br&gt;[DestinationDirs]&lt;br&gt;System32Copy=12,UMDF ; copy to system32\drivers\umdf&lt;br&gt;&lt;font color="red"&gt;Basic_Install.CoInstallers_CopyFiles=11&lt;/font&gt;&lt;br&gt;...&lt;br&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The same updated INF&amp;nbsp;will also work&amp;nbsp;on Windows Vista, as long as the UMDF co-installer DLL is&amp;nbsp;provided&amp;nbsp;with&amp;nbsp;your driver files during install AND you've compiled the driver DLL with the correct WDK build environment (see the first section of this post).&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;On Windows Vista, installing the WPD runtime components is not required&amp;nbsp;because WPD is available inbox for most SKUs.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2015189" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Issues/default.aspx">Issues</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WUDF+Coinstaller/default.aspx">WUDF Coinstaller</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Driver+INF/default.aspx">Driver INF</category></item><item><title>Driver Dev Guide: WPP Tracing in your WPD Driver</title><link>http://blogs.msdn.com/wpdblog/archive/2007/04/01/driver-dev-guide-using-wpp-tracing-in-your-wpd-driver.aspx</link><pubDate>Sun, 01 Apr 2007 21:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2007130</guid><dc:creator>wpdblog</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/2007130.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=2007130</wfw:commentRss><description>&lt;P&gt;&lt;A class="" title="WPP Software Tracing" href="http://msdn2.microsoft.com/en-us/library/ms793164.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms793164.aspx"&gt;WPP Software Tracing&lt;/A&gt; is the recommended way to log trace and error&amp;nbsp;messages in your WPD driver.&amp;nbsp; WPP, short for &lt;B&gt;W&lt;/B&gt;indows Software Trace &lt;B&gt;P&lt;/B&gt;re&lt;B&gt;P&lt;/B&gt;rocessor, provides&amp;nbsp;an efficient real-time event logging mechanism.&amp;nbsp;&amp;nbsp;&amp;nbsp; In addition, WPP traces include the system timestamp and can be used as a way to measure performance,&amp;nbsp;for example&amp;nbsp;by calculating the elapsed time between function calls.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;B&gt;From OutputDebugString to WPP&lt;/B&gt;&lt;/P&gt;
&lt;P&gt;The WPD&amp;nbsp;sample drivers in the Windows Driver Kit (WDK)&amp;nbsp;log&amp;nbsp;error&amp;nbsp;messages using a&amp;nbsp;CHECK_HR function that wraps around OutputDebugString.&amp;nbsp;&amp;nbsp; While OutputDebugString is simple to use during development,&amp;nbsp;it necessitates&amp;nbsp;an active debugger connection in order to view the traces, and should be used minimally in shipping code.&amp;nbsp;&amp;nbsp; WPP tracing&amp;nbsp;is much more lightweight, flexible,&amp;nbsp;and&amp;nbsp;preferable for a range of tracing applications: logging errors for diagnosing failures, tracing code execution during development, to name a few.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;How to switch your WPD driver's tracing from OutputDebugString to WPP transparently:&lt;/P&gt;
&lt;P&gt;Step 1. &lt;B&gt;Remove&lt;/B&gt; the original CHECK_HR() function&amp;nbsp;definition (it can be found in WpdHelloWorldDriver.cpp&amp;nbsp;or WpdWudfSampleDriver.cpp for the WPD samples) and&amp;nbsp;its declaration in stdafx.h.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Step 2. &lt;B&gt;Add&lt;/B&gt; the following code (&lt;B&gt;include&lt;/B&gt; the WPP config comment blocks)&amp;nbsp;to stdafx.h:&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'courier-new'"&gt;&lt;PRE&gt;// TODO: Choose a different trace ID for your WPD driver&lt;BR&gt;#define MYDRIVER_TRACING_ID      L"Microsoft\\WPD\\MyWpdDriver"&lt;BR&gt;&lt;BR&gt;// TODO: Choose a different trace control GUID for your WPD driver&lt;BR&gt;// TODO: Define trace flag bits for your WPD driver&lt;BR&gt;&lt;BR&gt;#define WPP_CONTROL_GUIDS                                                   \&lt;BR&gt;    WPP_DEFINE_CONTROL_GUID(                                                \&lt;BR&gt;        MyWpdDriverCtrlGuid, (da5fbdfd,1eae,4ecf,b426,a3818f325ddb),        \&lt;BR&gt;                                                                            \&lt;BR&gt;        WPP_DEFINE_BIT(TRACE_FLAG_ALL)                                      \&lt;BR&gt;        WPP_DEFINE_BIT(TRACE_FLAG_DRIVER)                                   \&lt;BR&gt;        WPP_DEFINE_BIT(TRACE_FLAG_DEVICE)                                   \&lt;BR&gt;        )                             &lt;BR&gt;&lt;BR&gt;//&lt;BR&gt;// Prefer trace statement that is based on&lt;BR&gt;//     - the standard trace LEVEL (evntrace.h), and&lt;BR&gt;//     - specific flag bit.&lt;BR&gt;//&lt;BR&gt;#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \&lt;BR&gt;           WPP_LEVEL_LOGGER(flags)&lt;BR&gt;               &lt;BR&gt;#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \&lt;BR&gt;           (WPP_LEVEL_ENABLED(flags) &amp;amp;&amp;amp; WPP_CONTROL(WPP_BIT_ ## flags).Level &amp;gt;= lvl)&lt;BR&gt;&lt;BR&gt;//&lt;BR&gt;// This comment block is scanned by the trace preprocessor to define our&lt;BR&gt;// Trace and TraceEvents function.&lt;BR&gt;//&lt;BR&gt;// begin_wpp config&lt;BR&gt;// FUNC Trace{FLAG=TRACE_FLAG_ALL}(LEVEL, MSG, ...);&lt;BR&gt;// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);&lt;BR&gt;// end_wpp&lt;BR&gt;//&lt;BR&gt;&lt;BR&gt;// MACRO: CHECK_HR&lt;BR&gt;// Configuration block that defines trace macro. It uses the PRE/POST macros to include&lt;BR&gt;// code as part of the trace macro expansion. CHECK_HR is equivalent to the code below:&lt;BR&gt;//&lt;BR&gt;// {if (hrCheck != S_OK){  // This is the code in the PRE macro&lt;BR&gt;//     DoTraceMessage(TRACE_FLAG_ALL,  "%!STDPREFIX!" MSG " hr= %!HRESULT!", ..., hrCheck)&lt;BR&gt;// ;}}                              // This is the code in the POST macro&lt;BR&gt;//                                 &lt;BR&gt;&lt;BR&gt;// begin_wpp config&lt;BR&gt;// USEPREFIX (CHECK_HR,"%!STDPREFIX!");&lt;BR&gt;// FUNC CHECK_HR{FLAG=TRACE_FLAG_ALL}(hrCheck, MSG, ...);&lt;BR&gt;// USESUFFIX (CHECK_HR, " hr= %!HRESULT!", hrCheck);&lt;BR&gt;// end_wpp&lt;BR&gt;&lt;BR&gt;#define WPP_FLAG_hrCheck_PRE(FLAGS, hrCheck) {if(hrCheck != S_OK) {&lt;BR&gt;#define WPP_FLAG_hrCheck_POST(FLAGS, hrCheck) ; } }&lt;BR&gt;#define WPP_FLAG_hrCheck_ENABLED(FLAGS, hrCheck) WPP_FLAG_ENABLED(FLAGS)&lt;BR&gt;#define WPP_FLAG_hrCheck_LOGGER(FLAGS, hrCheck) WPP_FLAG_LOGGER(FLAGS)&lt;BR&gt;&lt;/PRE&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Step 3. &lt;B&gt;Add&lt;/B&gt;&amp;nbsp;a RUN_WPP directive to your sources file:&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'courier-new'"&gt;&lt;PRE&gt;RUN_WPP= $(SOURCES) -scan:stdafx.h&lt;BR&gt;&lt;/PRE&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Step 4. &lt;B&gt;Add&lt;/B&gt;&amp;nbsp;the WPP initialization and cleanup routines to DllMain:&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'courier-new'"&gt;&lt;PRE&gt;// DLL Entry Point&lt;BR&gt;extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)&lt;BR&gt;{&lt;BR&gt;    if(DLL_PROCESS_ATTACH == dwReason)&lt;BR&gt;    {&lt;BR&gt;        g_hInstance = hInstance;&lt;BR&gt;      &lt;BR&gt;&lt;B&gt;        //&lt;BR&gt;        // Initialize tracing.&lt;BR&gt;        //&lt;BR&gt;        WPP_INIT_TRACING(MYDRIVER_TRACING_ID);&lt;/B&gt;&lt;BR&gt;    }&lt;BR&gt;    else if (DLL_PROCESS_DETACH == dwReason)&lt;BR&gt;    {&lt;BR&gt;&lt;B&gt;        //&lt;BR&gt;        // Cleanup tracing.&lt;BR&gt;        //&lt;BR&gt;        WPP_CLEANUP();&lt;/B&gt;&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    return _AtlModule.DllMain(dwReason, lpReserved);&lt;BR&gt;}&lt;BR&gt;&lt;/PRE&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Step 5. For&amp;nbsp;each .cpp file, &lt;B&gt;add &lt;/B&gt;a&amp;nbsp;#include &lt;I&gt;&amp;lt;filename&amp;gt;.tmh&lt;/I&gt; &lt;B&gt;after&lt;/B&gt;&amp;nbsp;the regular includes:&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'courier-new'"&gt;&lt;PRE&gt;//&lt;BR&gt;// WpdBaseDriver.cpp&lt;BR&gt;//&lt;BR&gt;&lt;BR&gt;#include "stdafx.h"&lt;BR&gt;#include "WpdBaseDriver.h"&lt;BR&gt;&lt;BR&gt;&lt;B&gt;// Include the WPP generated Trace Message Header (tmh) file for this .cpp&lt;BR&gt;#include "WpdBaseDriver.tmh"&lt;/B&gt;&lt;BR&gt;&lt;BR&gt;...&lt;BR&gt;&lt;BR&gt;&lt;/PRE&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;&lt;B&gt;Repeat Step 5&lt;/B&gt; for all other .CPP files.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Step 6. &lt;B&gt;Rebuild&lt;/B&gt; your driver.&amp;nbsp;&amp;nbsp;Since we&amp;nbsp;replaced the CHECK_HR&amp;nbsp;function with an equivalent WPP&amp;nbsp;macro that has the same&amp;nbsp;signature (our WPP changes&amp;nbsp;were "under the hood"),&amp;nbsp;&lt;B&gt;no&amp;nbsp;changes &lt;/B&gt;are needed for&amp;nbsp;any code&amp;nbsp;that uses&amp;nbsp;CHECK_HR. &amp;nbsp; You can continue to use CHECK_HR the same way as before :).&lt;/P&gt;
&lt;P mce_keep="true"&gt;The WPP preprocessor&amp;nbsp;will process stdafx.h for tracing macros,&amp;nbsp;and generate a &lt;A class="" title="Trace Message Header File" href="http://msdn2.microsoft.com/en-us/library/ms797965.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms797965.aspx"&gt;Trace Message Header &lt;/A&gt;(tmh) file for each cpp file in the obj folders.&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;Inspecting the preprocessor output for&amp;nbsp;each&amp;nbsp;.CPP file&amp;nbsp;that calls CHECK_HR&amp;nbsp;(generated using&amp;nbsp;&lt;I&gt;make WpdBaseDriver.pp&lt;/I&gt;), you will notice that all CHECK_HR trace statements&amp;nbsp;have been&amp;nbsp;wrapped by WPP function calls, while the tracing&amp;nbsp;text and&amp;nbsp;WPP functions are defined in &lt;I&gt;WpdBaseDriver.tmh&lt;/I&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The most common WPP-related&amp;nbsp;compilation errors you&amp;nbsp;may encounter&amp;nbsp;are due to mismatched format identifiers and&amp;nbsp;parameters &amp;nbsp;(e.g. if your format string contains an extra %d that does not match an argument) or&amp;nbsp;missing entries in the &lt;A class="" title=WPP_CONTROL_GUIDS href="http://msdn2.microsoft.com/en-us/library/ms793151.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms793151.aspx"&gt;WPP_CONTROL_GUIDS&lt;/A&gt;&amp;nbsp;macro.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;B&gt;&lt;/B&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;B&gt;More WPP Tracing Macros&lt;/B&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We've also defined TraceEvents and Trace functions in&amp;nbsp;stdafx.h&amp;nbsp;that are general purpose WPP trace&amp;nbsp;macros wrapping &lt;A class="" title=DoTraceMessage href="http://msdn2.microsoft.com/en-us/library/ms793193.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms793193.aspx"&gt;DoTraceMessage&lt;/A&gt;.&amp;nbsp;&amp;nbsp; These can be used for both error and non-error trace logging using a combination of levels and flags.&amp;nbsp;&amp;nbsp;&amp;nbsp;For examples on how to use them in your driver, refer to the UMDF sample drivers in the WDK.&lt;/P&gt;
&lt;P mce_keep="true"&gt;To understand the WPP declarations used in stdafx.h,&amp;nbsp;customize the CHECK_HR macro, or to define&amp;nbsp;your own&amp;nbsp;tracing macros, visit the&amp;nbsp;&lt;A class="" title="WPP Macros in the tracedrv sample" href="http://msdn2.microsoft.com/en-us/library/ms793169.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms793169.aspx"&gt;WPP macros guide&lt;/A&gt;&amp;nbsp;which describes the WDK tracedrv sample in detail.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;B&gt;Generating and Viewing Traces&lt;/B&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;To generate traces, you can use &lt;A class="" title=TraceView href="http://msdn2.microsoft.com/en-us/library/ms797981.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms797981.aspx"&gt;Traceview&lt;/A&gt;&amp;nbsp; (UI) or Tracelog (command line).&amp;nbsp;&amp;nbsp; TraceView also allows you to view traces in real-time as they are logged.&amp;nbsp;These are available in the WDK.&amp;nbsp;&amp;nbsp; A quick way to get started is to create a new log session from Traceview &lt;A class="" title="Creating a WPP Trace Session" href="http://msdn2.microsoft.com/en-us/library/ms797996.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms797996.aspx"&gt;using the PDB file&lt;/A&gt; that contains the private symbols for your driver.&amp;nbsp;&amp;nbsp; Alternatively, you use a .CTL file that specifies your driver as a trace provider (replace own values below):&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'courier-new'"&gt;&lt;PRE&gt;da5fbdfd-1eae-4ecf-b426-a3818f325ddb    MyWpdDriverCtlGuid&lt;BR&gt;&lt;/PRE&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;&lt;B&gt;&lt;/B&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;B&gt;Converting Binary Traces to A Human-Readable Form&lt;/B&gt;&lt;/P&gt;WPP traces log to a binary ETL format.&amp;nbsp; To convert them to text, supply Trace Format (TMF and TMC) files that can be generated from&amp;nbsp;the .PDB file using TracePDB.&amp;nbsp; For more details, refer to the &lt;A class="" title="WPP Tracing Tools" href="http://msdn2.microsoft.com/en-us/library/ms797960.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms797960.aspx"&gt;tracing tools&lt;/A&gt; section in the MSDN docs. 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;I&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/I&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2007130" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Tools/default.aspx">Tools</category></item><item><title>Driver Dev Guide: How to Post Events from your WPD Driver</title><link>http://blogs.msdn.com/wpdblog/archive/2007/03/16/how-to-post-events-from-your-wpd-driver.aspx</link><pubDate>Sat, 17 Mar 2007 01:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1896911</guid><dc:creator>wpdblog</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/1896911.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=1896911</wfw:commentRss><description>&lt;p&gt;&lt;a href="https://blogs.msdn.com/dimeby8/default.aspx" class="" title="DimeBy8's Blog" mce_href="https://blogs.msdn.com/dimeby8/default.aspx"&gt;DimeBy8&lt;/a&gt;&amp;nbsp;wrote a great &lt;a href="https://blogs.msdn.com/dimeby8/archive/2006/10/06/Listening-to-WPD-Events.aspx" class="" title="Listening to WPD Events" mce_href="https://blogs.msdn.com/dimeby8/archive/2006/10/06/Listening-to-WPD-Events.aspx"&gt;post&lt;/a&gt; on how a WPD application can receive driver-initiated WPD PnP events;&amp;nbsp;this post&amp;nbsp;will describe &lt;b&gt;the driver's side of our eventing story&lt;/b&gt;.&amp;nbsp;&amp;nbsp; While this mechanism&amp;nbsp;is&amp;nbsp;"under the covers" for&amp;nbsp;most WPD application developers, it helps to get an end-to-end picture of how&amp;nbsp;stuff works in WPD land,&amp;nbsp;especially if you are thinking about writing a WPD driver and application for vertical scenarios that involve&amp;nbsp;posting and receiving custom events.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Standard WPD Events and Parameters&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Here is the &lt;a href="http://msdn.microsoft.com/en-us/library/dd318066%28VS.85%29.aspx" title="WPD Event Constants" mce_href="http://msdn.microsoft.com/en-us/library/dd318066(VS.85).aspx"&gt;list of standard&amp;nbsp;WPD events&lt;/a&gt;.&amp;nbsp;&amp;nbsp; These GUIDs are defined in PortableDevice.h.&amp;nbsp;&amp;nbsp; When you begin accessing these events as a WPD application or driver), you may&amp;nbsp;soon realize a missing piece of information:&amp;nbsp;&lt;b&gt;what/where are the&amp;nbsp;parameters for these events?&lt;/b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The Event parameters are described in more detail in the &lt;a href="http://www.microsoft.com/whdc/device/media/WPDguide.mspx" class="" title="Basic WPD Device Driver Requirements" mce_href="http://www.microsoft.com/whdc/device/media/WPDguide.mspx"&gt;Basic WPD Device Driver Requirements&lt;/a&gt;&amp;nbsp;WHDC whitepaper,&amp;nbsp;under &lt;i&gt;Requirements for Event Parameters.&amp;nbsp;&amp;nbsp; &lt;/i&gt;&lt;/p&gt;
&lt;p&gt;A&amp;nbsp;&lt;i&gt;snippet&lt;/i&gt; from the whitepaper that describes&amp;nbsp;the required&amp;nbsp;parameters for WPD_EVENT_OBJECT_UPDATED:&lt;/p&gt;
&lt;h4 style="margin: 12pt 0in 0pt;"&gt;&lt;font size="2"&gt;&amp;nbsp; WPD_EVENT_OBJECT_UPDATED&lt;/font&gt;&lt;/h4&gt;
&lt;p class="BodyTextLink" style="margin: 0in 0in 4pt;"&gt;&amp;nbsp; This event is sent after an object has been updated so that any connected client should refresh its view of that object.&lt;/p&gt;
&lt;p class="TableHead" style="margin: 8pt 0in 1pt;"&gt;&lt;b&gt;&amp;nbsp; Parameters &lt;/b&gt;&lt;/p&gt;
&lt;p class="DT" style="margin: 0in 0in 0pt 9pt;"&gt;&lt;span class="MsoHyperlink"&gt;&lt;span style="font-weight: normal;"&gt;&amp;nbsp; &lt;font color="#0000ff"&gt;WPD_EVENT_PARAMETER_PNP_DEVICE_ID&lt;/font&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="DL" style="margin: 0in 0in 4pt 0.25in;"&gt;&amp;nbsp; Required.&lt;/p&gt;
&lt;p class="DT" style="margin: 0in 0in 0pt 9pt;"&gt;&lt;span class="MsoHyperlink"&gt;&lt;span style="font-weight: normal;"&gt;&amp;nbsp; &lt;font color="#0000ff"&gt;WPD_EVENT_PARAMETER_EVENT_ID&lt;/font&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="DL" style="margin: 0in 0in 4pt 0.25in;"&gt;&amp;nbsp; Required.&lt;/p&gt;
&lt;p class="DT" style="margin: 0in 0in 0pt 9pt;"&gt;&lt;span class="MsoHyperlink"&gt;&lt;span style="font-weight: normal;"&gt;&amp;nbsp; &lt;font color="#0000ff"&gt;WPD_OBJECT_PERSISTENT_UNIQUE_ID&lt;/font&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="DL" style="margin: 0in 0in 4pt 0.25in;"&gt;&amp;nbsp; Required.&lt;/p&gt;
&lt;p class="DT" style="margin: 0in 0in 0pt 9pt;"&gt;&lt;span class="MsoHyperlink"&gt;&lt;span style="font-weight: normal;"&gt;&amp;nbsp; &lt;font color="#0000ff"&gt;WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID&lt;/font&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="DL" style="margin: 0in 0in 4pt 0.25in;"&gt;&amp;nbsp; Required.&lt;/p&gt;
&lt;p class="DT" style="margin: 0in 0in 0pt 9pt;"&gt;&lt;span class="MsoHyperlink"&gt;&lt;span style="font-weight: normal;"&gt;&amp;nbsp; &lt;font color="#0000ff"&gt;WPD_EVENT_PARAMETER_CHILD_HIERARCHY_CHANGED&lt;/font&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="DL" style="margin: 0in 0in 4pt 0.25in;"&gt;&amp;nbsp; Required if the object hierarchy at any level under this object has changed.&lt;/p&gt;
&lt;p mce_keep="true"&gt;Event parameters matter when you're sending a standard WPD event from your driver.&amp;nbsp;&amp;nbsp;&amp;nbsp;For example, when receiving WPD_EVENT_OBJECT_UPDATED, applications may utilize information such as WPD_OBJECT_PERSISTENT_UNIQUE_ID to determine which object's properties would need to be refreshed in their properties view.&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p mce_keep="true"&gt;*Aside: One consequence of supporting any WPD event that requires the&amp;nbsp;Persistent Unique ID of objects&amp;nbsp;is that your driver needs to support this property (but this is a required property anyway for most content objects).&amp;nbsp;&amp;nbsp;&amp;nbsp;The list of required properties is also covered in &lt;a href="http://www.microsoft.com/whdc/device/media/WPDguide.mspx" class="" title="Basic WPD Device Driver Requirements" mce_href="http://www.microsoft.com/whdc/device/media/WPDguide.mspx"&gt;Basic WPD Device Driver Requirements&lt;/a&gt;.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Posting a WPD Event from&amp;nbsp;Your Driver&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;Now that you know what parameters to send with&amp;nbsp;a WPD&amp;nbsp;event, posting the event is a&amp;nbsp;three step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div mce_keep="true"&gt;Initialize an&amp;nbsp;IPortableDeviceValues to hold the event parameters.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div mce_keep="true"&gt;Serialize the IPortableDeviceValues to a BYTE buffer.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div mce_keep="true"&gt;Call &lt;a href="http://msdn2.microsoft.com/en-us/library/aa511339.aspx" class="" title="IWDFDevice::PostEvent" mce_href="http://msdn2.microsoft.com/en-us/library/aa511339.aspx"&gt;IWDFDevice::PostEvent&lt;/a&gt;&amp;nbsp;with the EventGuid = WPD_EVENT_NOTIFICATION and the serialized buffer.&amp;nbsp; Only &lt;i&gt;WdfEventBroadcast&lt;/i&gt; events are supported, which means all WPD applications that call IPortableDevice::Advise can receive the event your driver posts.&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: 9pt; font-family: 'courier-new';"&gt;&lt;pre&gt;BYTE* pBuffer  = NULL;&lt;br&gt;DWORD cbBuffer = 0;&lt;br&gt;&lt;br&gt;// Populate the event parameters&lt;br&gt;hr = pIPortableDeviceValues-&amp;gt;SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, WPD_EVENT_OBJECT_UPDATED);&lt;br&gt;&lt;br&gt;// Set other required event parameters here ....&lt;br&gt;&lt;br&gt;if (hr == S_OK)&lt;br&gt;{&lt;br&gt;    // Serialize the event parameters to a buffer &lt;br&gt;    hr = pWpdSerializer-&amp;gt;GetBufferFromIPortableDeviceValues(pIPortableDeviceValues, &amp;amp;pBuffer, &amp;amp;cbBuffer);&lt;br&gt;}&lt;br&gt;&lt;br&gt;// Send the event.&lt;br&gt;if (hr == S_OK)&lt;br&gt;{&lt;br&gt;    hr = pIWDFDevice-&amp;gt;PostEvent(WPD_EVENT_NOTIFICATION, WdfEventBroadcast, pBuffer, cbBuffer);&lt;br&gt;}&lt;br&gt;&lt;br&gt;// Cleanup ...&lt;br&gt;CoTaskMemFree(pBuffer);&lt;br&gt;pBuffer = NULL;&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Defining a Custom WPD Event (and&amp;nbsp;adding it to WpdInfo/WpdMon's Vocab!)&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;WPD's extensibility mechanism allows for custom events to be defined very easily.&amp;nbsp;&amp;nbsp; You define a new GUID for your custom event, and define&amp;nbsp;PROPERTYKEYs for your event parameters (or reuse existing PROPERTYKEYs).&amp;nbsp;&amp;nbsp; On the application side, check for this custom event GUID the same way as you handle a WPD event, and&amp;nbsp;process the event.&amp;nbsp;&amp;nbsp; Your driver should also report these new event(s) when&amp;nbsp;responding to WPD_COMMAND_CAPABILITIES_GET_SUPPORTED_EVENTS and WPD_COMMAND_CAPABILITIES_GET_EVENT_OPTIONS.&lt;/p&gt;
&lt;p mce_keep="true"&gt;Both the WPDInfo and WPDMon WDK tools&amp;nbsp;can receive and display custom WPD events in the raw GUID form, which means you already have a handy way to validate your driver's event posting functionality without needing to write a WPD application.&amp;nbsp; &lt;/p&gt;
&lt;p mce_keep="true"&gt;You can even "teach" our tools to translate the custom event GUID to&amp;nbsp;its symbolic name.&amp;nbsp;&amp;nbsp;&amp;nbsp;This can be done by adding an entry&amp;nbsp;to&amp;nbsp;the&amp;nbsp;&lt;i&gt;WpdInfo.GUIDs&lt;/i&gt; file (this is a text file usually located in the same folder path as the tool exes), and&amp;nbsp;restarting the tools to reload this file.&amp;nbsp;&amp;nbsp; In a similar way, symbolic names for your custom&amp;nbsp;PROPERTYKEYs&amp;nbsp;can go into&amp;nbsp;&lt;i&gt;WpdInfo.Properties &lt;/i&gt;file, custom commands&amp;nbsp;in &lt;i&gt;WpdInfo.Commands&lt;/i&gt;, etc.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p mce_keep="true"&gt;It's important to note that updating these WpdInfo.* dictionary files only enables the WPD tools&amp;nbsp;in your PC&amp;nbsp;to translate custom GUIDs and PROPERTYKEYs to symbolic string like names,&amp;nbsp;other WPD applications and drivers know nothing on these custom values that are &lt;b&gt;specific &lt;/b&gt;to your driver and&amp;nbsp;application.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1896911" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Tools/default.aspx">Tools</category></item><item><title>WPDMon Gotchas</title><link>http://blogs.msdn.com/wpdblog/archive/2007/02/05/wpdmon-gotchas.aspx</link><pubDate>Tue, 06 Feb 2007 02:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1607554</guid><dc:creator>wpdblog</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/1607554.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=1607554</wfw:commentRss><description>&lt;p&gt;If you're developing a WPD driver or a WPD application, you may have come across the &lt;a href="http://msdn.microsoft.com/en-us/library/dd419923.aspx" title="Introduction to WPDMon" mce_href="http://msdn.microsoft.com/en-us/library/dd419923.aspx"&gt;WPD Monitor tool&lt;/a&gt; (a.k.a. WpdMon).&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;This is a tool that displays WPD&amp;nbsp;traffic between applications and&amp;nbsp;a&amp;nbsp;WPD driver for diagnostic purposes.&amp;nbsp;&amp;nbsp; Plug and Play (PnP) messages&amp;nbsp;and Raw&amp;nbsp;(DeviceIoControl) traffic are also viewable.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WpdMon is available in the Windows Driver Kits, e.g. c:\WinDDK\6000\tools\wpd\x86.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;u&gt;Known issues in WpdMon&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Issue #1 WPDMon.exe is not showing any traces&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Make sure that you have installed WpdMon according to the instructions in WpdMon.htm (also found under e.g.&amp;nbsp;c:\WinDDK\6000\tools\wpd\x86).&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1. Ensure that all WPD devices are unplugged &lt;br&gt;2. For 32-bit systems, copy the Shim DLL to the AppPatch directory (“copy WpdMonShim.dll %windir%\AppPatch”) from an&amp;nbsp;Administrator Command Prompt.&amp;nbsp; On 64-bit systems, copy the Shim DLL to the AppPatch64 directory (“copy WpdMonShim.dll %windir%\AppPatch\AppPatch64”)&lt;br&gt;3. Register the shim (“Regsvr32 %windir%\AppPatch\WpdMonShim.dll” for 32-bit, or “Regsvr32 %windir%\AppPatch\AppPatch&lt;b&gt;64&lt;/b&gt;\WpdMonShim.dll” for 64-bit) from an&amp;nbsp;Administrator Command Prompt.&amp;nbsp;&lt;br&gt;4. Plug WPD devices back in &lt;br&gt;5. The WPD Monitor Application (WpdMon.exe) is now ready to capture WPD API/DDI traffic, and can be copied and run directly from any directory.&amp;nbsp; It requires administrator privileges, so you need to right click on WpdMon.exe from Explorer and select "Run Elevated", or launch WpdMon from an Administrator Command Prompt.&lt;br&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Issue #2&amp;nbsp; I've installed WpdMon according to the instructions in WpdMon.htm, but I still can't see any traces&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;Ensure that you've launched WpdMon with Administrator privileges.&amp;nbsp;&amp;nbsp;&amp;nbsp; Either right click on the WpdMon.exe from Explorer and select "Run Elevated", or launch WpdMon from an Administrator Command Prompt.&lt;/p&gt;
&lt;p mce_keep="true"&gt;Ensure that you have &lt;i&gt;Monitor -&amp;gt;&amp;nbsp;API Traffic&lt;/i&gt; checked to enable WPD API tracing.&lt;/p&gt;
&lt;p mce_keep="true"&gt;If you have a Root Enumerated WPD device (such as one of the WPD driver samples from the WDK) running before WpdMon was installed, the Windows User Mode Driver Framework (WUDF) driver process (WUDFHost.exe) is still running,&amp;nbsp;&amp;nbsp;&amp;nbsp; You'll need to force WUDFHost.exe process&amp;nbsp;to restart so that the WpdMonShim dll can load:&lt;/p&gt;
&lt;p mce_keep="true"&gt;1. Launch WpdMon.exe with Administrator privileges&lt;br&gt;2. From Device Manager, select the WPD device (under Portable Devices)&lt;br&gt;3. Right click "Disable" to disable the WPD device&lt;br&gt;4. Right click "Enable" to re-enable the WPD device&lt;br&gt;5. WpdMon.exe should now show traces&lt;br&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Issue #3&amp;nbsp; I see a lot of traces in WpdMon and would like to save them to a file, but the "File -&amp;gt;&amp;nbsp;Save Viewer Output As" dialog keeps getting out of scope&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;WpdMon logs to both the window and a &lt;i&gt;Wpdmon.htm&lt;/i&gt; file, both in the same directory&amp;nbsp;as WpdMon.exe.&amp;nbsp;&amp;nbsp; Sometimes when there is a lot of WPD API traffic going on, the WpdMon window would update rapidly and grab the window focus from the File-&amp;gt;Save As dialog.&lt;/p&gt;
&lt;p mce_keep="true"&gt;There are two ways to get around this:&lt;/p&gt;
&lt;p mce_keep="true"&gt;1. Uncheck "Log to Viewer" from the Options menu to disable logging to Window, or&lt;/p&gt;
&lt;p mce_keep="true"&gt;2. If you need the Viewer output, uncheck "Auto Scroll Viewer Output" from the Options menu to disable the scrolling.&amp;nbsp;&amp;nbsp;You will have to scroll down manually to view the latest traces.&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Setting up WpdMon.ini&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;You can configure default WpdMon settings by modifying the WpdMon.ini file.&amp;nbsp;&amp;nbsp;&amp;nbsp;This is useful in situations where you want WpdMon to log to&amp;nbsp;HTML&amp;nbsp;silently, for example.&lt;/p&gt;
&lt;p mce_keep="true"&gt;1. Close WpdMon&lt;br&gt;2. Open WpdMon.ini in a text editor (e.g. Notepad)&lt;br&gt;3. Under the [General] section, set the following options (0=disable, 1=enable).&lt;/p&gt;
&lt;p mce_keep="true"&gt;LogToViewer=0&lt;br&gt;LogToHTMLFile=1&lt;/p&gt;
&lt;p mce_keep="true"&gt;4. Reopen WpdMon&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;WpdMon.ini also contains settings to disable/enable API, Raw and PnP tracing by default.&amp;nbsp; You can set &lt;i&gt;Enabled=1&lt;/i&gt; under each parser section (e.g. [APIParser]) to enable the WPD API traces.&amp;nbsp;&amp;nbsp; &lt;i&gt;Enabled=0&lt;/i&gt; will disable the API tracing.&amp;nbsp;&amp;nbsp; You can turn this on/off dynamically while WpdMon is running, to start and stop the tracing.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Issue #4&amp;nbsp; I lost the instructions since WpdMon.exe overwrote the tool readme:&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;WpdMon automatically saves traces to WpdMon.htm.&amp;nbsp; Unfortunately, this file bears the same name as the tool readme and will overwrite the readme when WpdMon.exe is launched.&amp;nbsp; You may want to save a copy of the original WpdMon.htm as backup &lt;i&gt;before &lt;/i&gt;running WpdMon, or refer to an identical copy from a different OS architecture that was not overwritten, e.g. in c:\WinDDK\6000\tools\wpd\&lt;i&gt;amd64\&lt;/i&gt;wpdmon.htm).&amp;nbsp;&amp;nbsp; &lt;br&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Issue #5&amp;nbsp; WpdMon keeps logging even after I've closed my WPD application&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;Sometimes when WpdMon captures and processes a lot of realtime&amp;nbsp;WPD traffic, there can be a delay between the actual WPD operation and tracing display.&amp;nbsp;&amp;nbsp;&amp;nbsp; This is normal as the window may take some time to display all the traces.&amp;nbsp;&amp;nbsp; You can speed things up by minimizing the WpdMon window, and then clicking on something else in Explorer so that the WpdMon is not in focus.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;Once the&amp;nbsp;minimized WpdMon window stops flickering,&amp;nbsp;restore the window, and&amp;nbsp;scroll down to refresh it.&lt;/p&gt;
&lt;p mce_keep="true"&gt;If you still see&amp;nbsp;intermittent traffic, it is possibly because other WPD applications (e.g. Explorer via the WPD Shell Namespace Extension or Windows Media Player) are communciating with your driver/device.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Still can't get WpdMon to show API traces for debugging your driver?&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;If you are developing a WPD driver and need tracing information, a good alternative is to convert your driver traces to WPP tracing.&amp;nbsp;&amp;nbsp; &lt;a href="http://blogs.msdn.com/wpdblog/archive/2007/04/01/driver-dev-guide-using-wpp-tracing-in-your-wpd-driver.aspx" class="" title="Adding WPP Tracing in your WPD Driver" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/04/01/driver-dev-guide-using-wpp-tracing-in-your-wpd-driver.aspx"&gt;This post&lt;/a&gt; describes how to migrate the CHECK_HR macro used in our sample drivers to use WPP traces "under the covers", and should provide you with a good start for adopting WPP for your driver logging needs.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;
&lt;p minmax_bound="true"&gt;&lt;i minmax_bound="true"&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1607554" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Tools/default.aspx">Tools</category></item><item><title>Debugging Your WPD Driver with Visual Studio 8</title><link>http://blogs.msdn.com/wpdblog/archive/2007/02/01/debugging-your-wpd-driver-with-visual-studio-8.aspx</link><pubDate>Fri, 02 Feb 2007 00:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1576725</guid><dc:creator>wpdblog</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/1576725.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=1576725</wfw:commentRss><description>&lt;p&gt;WPD drivers are based on the Windows Driver Foundation (WDF) – User-Mode Driver Framework (UMDF) platform. UMDF drivers provide greater stability and security than kernel-mode drivers while providing comparable performance. And, UMDF drivers allow the use of user-mode debuggers such as Visual Studio 8. (Debugging a driver in user-mode tends to be faster than debugging in kernel-mode because an error only affects the current process rather than the entire computer.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;General Visual Studio 8 Debugging Tips&lt;br&gt;&lt;/b&gt;Once your driver is installed, you can create a debugging project in Visual Studio 8 by following these steps:&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Open Visual Studio 8 and select “File/New/Project from Existing Code…” menu.&lt;/p&gt;
&lt;p&gt;2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Follow the steps in the “Welcome to the Create Project form Existing Code Files Wizard” (specifying the language, the location of your driver source files, a project name, and so on).&lt;/p&gt;
&lt;p&gt;3.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Open your newly created project.&lt;/p&gt;
&lt;p&gt;4.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Select the “Debug/Attach to Process…” menu and then choose WudfHost.exe in the list of Available Processes that appears in the “Attach to Process” dialog.&lt;/p&gt;
&lt;p&gt;Once you complete the above steps, you can begin setting breakpoints in your driver’s source code and debug your driver.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Tips for Debugging WPD Driver Initialization Code&lt;br&gt;&lt;/b&gt;A WPD driver’s initialization code (for example, the code found in WpdBaseDriver::Initialize() in the two WPD sample drivers that ship with the Windows Driver Kit), executes during the installation of your driver. In order to debug this initialization code, you’ll need to accomplish the following tasks:&lt;/p&gt;
&lt;p&gt;1.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Create a debugging project in Visual Studio 8 (as described in the previous section).&lt;/p&gt;
&lt;p&gt;2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Open an instance of regedit.exe and specify a delay period (in seconds) for the WudfHost.exe process. This delay is specified using the following key: \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WUDF\Services\{193a…}\HostProcessDbgBreakOnStart&lt;/p&gt;
&lt;p&gt;3.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Force the WUDFHost.exe process to reload.&amp;nbsp; This can be done in a couple of ways, depending on what your device configuration is:&lt;/p&gt;
&lt;p&gt;a)&amp;nbsp;&amp;nbsp; From Device Manager, Disable and then Enable your device's WPD devnode&lt;/p&gt;
&lt;p&gt;b)&amp;nbsp;&amp;nbsp; If your device has a physical connection to the PC, unplug and then re-reconnect your device.&lt;/p&gt;
&lt;p&gt;4.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Upon driver reload, start Visual Studio 8, open your debug project, and attach to the WudfHost.exe process.&amp;nbsp;&amp;nbsp; As a side effect, you may see Device Manager hanging when you reload the driver,&amp;nbsp;while WudfHost.exe is waiting for a debugger to connect.&lt;/p&gt;
&lt;p&gt;The delay which you set for the …\HostProcessDbgBreakOnStart value provides the necessary time to start the debugger prior to the installation of your driver. (For example, a value of 0x00000040 would delay the installation for 64 seconds.) This delay allows you time to attach to the process, set a breakpoint in your initialization code, and begin debugging.&lt;/p&gt;
&lt;p&gt;For more information about the &lt;b&gt;HostProcessDbgBreakOnStart&lt;/b&gt; value, refer to &lt;a href="http://msdn.microsoft.com/en-us/library/aa510985.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa510985.aspx"&gt;this MSDN topic&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;b&gt;Update [August 7, 2009]:&lt;/b&gt;&amp;nbsp; The WDF team has provided an excellent tool that makes debugging both kernel mode and user mode WDF drivers much easier. The WDFVerifier is available in the &lt;a href="http://www.microsoft.com/whdc/devtools/WDK/default.mspx" mce_href="http://www.microsoft.com/whdc/devtools/WDK/default.mspx"&gt;Windows Driver Kit&lt;/a&gt; (WDK). For details, refer to the &lt;a href="http://msdn.microsoft.com/en-us/library/cc264238.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc264238.aspx"&gt;WDFVerifier&lt;/a&gt; MSDN page. In addition, we recommend these in-depth posts by &lt;a href="http://blogs.msdn.com/bobkjelgaard/default.aspx" mce_href="http://blogs.msdn.com/bobkjelgaard/default.aspx"&gt;Bob Kjelgaard&lt;/a&gt;, an SDET from the WDF team, covering basic and advanced usages of WdfVerifier:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2007/10/08/wdfverifier-basics-assistance-in-debugging-umdf-drivers.aspx" mce_href="http://blogs.msdn.com/bobkjelgaard/archive/2007/10/08/wdfverifier-basics-assistance-in-debugging-umdf-drivers.aspx"&gt;WdfVerifier Basics&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2007/10/26/remote-usage-of-wdfverifier-benefits-pitfalls-and-common-problems.aspx" mce_href="http://blogs.msdn.com/bobkjelgaard/archive/2007/10/26/remote-usage-of-wdfverifier-benefits-pitfalls-and-common-problems.aspx"&gt;Remote usage of WdfVerifier - Benefits, Pitfalls and Common Problems&lt;/a&gt;&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p mce_keep="true"&gt;&amp;nbsp; &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;br&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1576725" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Tools/default.aspx">Tools</category></item><item><title>Building Driver Samples from the WDK</title><link>http://blogs.msdn.com/wpdblog/archive/2007/01/31/building-driver-samples-from-the-wdk.aspx</link><pubDate>Wed, 31 Jan 2007 10:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1563058</guid><dc:creator>wpdblog</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/1563058.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=1563058</wfw:commentRss><description>&lt;p&gt;&lt;b&gt;Help!&amp;nbsp;The WPD&amp;nbsp;driver sample doesn't build!&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Seeing this error while building the WPD driver samples&amp;nbsp;using the Windows Driver Kit&amp;nbsp;(WDK)&amp;nbsp;build environment?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p mce_keep="true"&gt;errors in directory c:\winddk\6000\src\umdf\wpd\wpdhelloworlddriver&lt;br&gt;NMAKE : fatal error U1073: don't know how to make 'C:\WinDDK\6000\lib\mfc\i386\atls.lib'&lt;br&gt;nmake.exe /nologo BUILDMSG=Stop. -i BUILD_PASS=PASS2 LINKONLY=1 NOPASS0=1 MAKEDLL=1 MAKEDIR_RELATIVE_TO_BASEDIR=src\umdf\wpd\wpdhelloworlddriver MAKEDIR_LOWERCASE=c:\winddk\6000\src\umdf\wpd\wpdhelloworlddriver failed - rc = 2&lt;/p&gt;&lt;/blockquote&gt;
&lt;p mce_keep="true"&gt;No worries, this is expected.&amp;nbsp; The is because the WDK build environment provides an older&amp;nbsp;version of the ATL libraries than what WPD needs.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p mce_keep="true"&gt;To build the WPD driver samples provided with the WDK, follow these&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/aa973571.aspx" title="Build Instructions" mce_href="http://msdn.microsoft.com/en-us/library/aa973571.aspx"&gt;step-by-step instructions&lt;/a&gt;&amp;nbsp;(MSDN library section: &lt;i&gt;"Win32 and COM Development\Windows Driver Kit\Device and Driver Technology\Portable Devices\Windows Portable Devices\WPD Programming Guide\Familiarizing Yourself with the Sample Driver"&lt;/i&gt; ).&lt;/p&gt;
&lt;p mce_keep="true"&gt;In a nutshell, you will&amp;nbsp;need to&amp;nbsp;install Visual Studio 2005, and&amp;nbsp;reference the ATL libraries&amp;nbsp;from there.&amp;nbsp;&amp;nbsp;This build environment configuration only needs to be done the first time, and you'll be good to go&amp;nbsp;for building our sample drivers.&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Update [August 7, 2009]: &lt;/b&gt;The ATL-related build issues in the first section have finally been
addressed in the WDK for Windows 7 (a.k.a WDK 7.0.0).&amp;nbsp; You can get the
latest WDK &lt;a href="http://www.microsoft.com/whdc/DevTools/WDK/WDKpkg.mspx" mce_href="http://www.microsoft.com/whdc/DevTools/WDK/WDKpkg.mspx"&gt;here&lt;/a&gt;. To build the drivers, simply type "build -cZ" or "bcz" from the WDK command window for the target OS of your choice. See &lt;a href="http://www.microsoft.com/whdc/devtools/wdk/RelNotesW7.mspx#EHJAE" mce_href="http://www.microsoft.com/whdc/devtools/wdk/RelNotesW7.mspx#EHJAE"&gt;this WDK 7.0.0 RTM release note&lt;/a&gt; for the complete list of build environments and target operating systems applicable to the WPD driver samples. &lt;br&gt;&lt;/p&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p mce_keep="true"&gt;&lt;b&gt;Which sample should I use?&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;To&amp;nbsp;get a running start on writing a WPD driver, we recommend using the &lt;b&gt;WpdHelloWorldDriver&lt;/b&gt; as a template, it covers some basic driver functionality such as retrieving properties,&amp;nbsp;enumeration, and reporting device capabilities.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;More advanced driver functionality is demonstrated by&amp;nbsp;the &lt;b&gt;WpdWudfSampleDriver&lt;/b&gt; (a.k.a. the&amp;nbsp;WPD Comprehensive Sample Driver),&amp;nbsp;such as driver-initiated events,&amp;nbsp;object management, and content&amp;nbsp;transfer.&amp;nbsp; On Windows Vista, this sample driver is also visible from Windows Image Acquisition (WIA) camera applications (using the WPD-WIA compatibility layer).&amp;nbsp; More on&amp;nbsp;WIA in future posts....&lt;/p&gt;&lt;p mce_keep="true"&gt;To develop a WPD driver that enumerates in Windows Media Player 11, you can start with the &lt;b&gt;WpdWudfSampleDriver &lt;/b&gt;with &lt;a href="http://blogs.msdn.com/wpdblog/archive/2007/05/08/getting-a-wpd-sample-driver-working-with-windows-media-player-11.aspx" title="Getting the WpdWudfSampleDriver enumerating in WMP11" mce_href="http://blogs.msdn.com/wpdblog/archive/2007/05/08/getting-a-wpd-sample-driver-working-with-windows-media-player-11.aspx"&gt;a few extra modifications&lt;/a&gt;.&lt;br&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Update [August 7, 2009]:&amp;nbsp;&lt;/b&gt; The WDK 7.0.0 now contains an updated &lt;b&gt;WpdWudfSampleDriver&lt;/b&gt; sample that supports enumeration in Windows Media Player.&lt;/p&gt;&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p mce_keep="true"&gt;&lt;b&gt;Known issues in the sample drivers&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;Both sample drivers do&amp;nbsp;not enumerate&amp;nbsp;in Windows Media Device Manager (WMDM) applications (such as Windows Media Player) by default. &amp;nbsp; See the previous section for an example of enabling that with the comprehensive sample driver.&lt;/p&gt;
&lt;p mce_keep="true"&gt;Both sample drivers install as "root enumerated" devices, i.e. they install using the Add Legacy Hardware option.&amp;nbsp; Hence, they are shown as always connected in Device Manager.&amp;nbsp;&amp;nbsp; While this provides an&amp;nbsp;easy way to install&amp;nbsp;and test a&amp;nbsp;device driver,&amp;nbsp;this means that certain Plug-and-Play functionality may&amp;nbsp;not be available&amp;nbsp;(such as Autoplay in Windows Vista).&amp;nbsp;&amp;nbsp;&amp;nbsp;To&amp;nbsp;enable Autoplay, one way is to install and configure&amp;nbsp;a bus driver for your device (for a sample, refer to the Toaster Bus Driver in the WDK).&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;p mce_keep="true"&gt;&lt;b&gt;What tools can I use? &lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;During development, we highly recommend&amp;nbsp;using the &lt;a href="http://msdn.microsoft.com/en-us/library/aa973613.aspx" title="Wpd Information Tool" mce_href="http://msdn.microsoft.com/en-us/library/aa973613.aspx"&gt;WpdInfo&lt;/a&gt;&amp;nbsp;GUI tool, which uses the WPD API&amp;nbsp;to access your driver.&amp;nbsp;&amp;nbsp;You can&amp;nbsp;query driver&amp;nbsp;capabilities, browse the object tree, send raw WPD commands, update properties, etc.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p mce_keep="true"&gt;Other useful WPD tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div mce_keep="true"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa973612.aspx" title="WPDDeviceInspector" mce_href="http://msdn.microsoft.com/en-us/library/aa973612.aspx"&gt;WPD Device Inspector&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div mce_keep="true"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa973614.aspx" title="WPDMon" mce_href="http://msdn.microsoft.com/en-us/library/aa973614.aspx"&gt;WPD Monitor&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p mce_keep="true"&gt;All these tools are developed in-house, and used extensively by us for development and troubleshooting. :)&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;b&gt;Basic driver requirements&lt;/b&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;This &lt;a href="http://www.microsoft.com/whdc/device/media/WPDguide.mspx" class="" title="WPD Basic Driver Requirements" mce_href="http://www.microsoft.com/whdc/device/media/WPDguide.mspx"&gt;whitepaper&lt;/a&gt; lists basic requirements that your driver should satisfy to work well with most WPD applications,&amp;nbsp;such as the required properties that a particular&amp;nbsp;object content&amp;nbsp;type should support.&amp;nbsp;&amp;nbsp; These requirements are also implemented as logo tests for the Windows Vista Cellular Handset Basic Logo for Windows Logo Program v3, but are generic enough to apply to any WPD driver.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;br&gt;&lt;/p&gt;&lt;p mce_keep="true"&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1563058" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Tools/default.aspx">Tools</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/Issues/default.aspx">Issues</category></item><item><title>Getting Your Feet Wet .... with WPD Development</title><link>http://blogs.msdn.com/wpdblog/archive/2007/01/23/getting-your-feet-wet-with-wpd-development.aspx</link><pubDate>Tue, 23 Jan 2007 21:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1516199</guid><dc:creator>wpdblog</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/wpdblog/comments/1516199.aspx</comments><wfw:commentRss>http://blogs.msdn.com/wpdblog/commentrss.aspx?PostID=1516199</wfw:commentRss><description>&lt;p&gt;Here’s a common question we get from developers:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I read about WPD from the &lt;a href="http://msdn.microsoft.com/en-us/library/dd388998%28VS.85%29.aspx" title="WPD on MSDN" mce_href="http://msdn.microsoft.com/en-us/library/dd388998(VS.85).aspx"&gt;MSDN library&lt;/a&gt;, but where do I download the samples, tools and build environment that are mentioned in the docs?“&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;b&gt;Writing a WPD Application&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To get started on developing a WPD application, download the &lt;a href="http://msdn.microsoft.com/en-us/windows/bb980924.aspx" title="Windows SDK" mce_href="http://msdn.microsoft.com/en-us/windows/bb980924.aspx"&gt;Windows SDK&lt;/a&gt;.&amp;nbsp; This contains the header and library files, build environment, and code for a sample WPD application. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Writing a WPD Driver &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;To get started on developing a WPD driver, download the &lt;a href="http://www.microsoft.com/whdc/devtools/WDK/default.mspx" class="" title="Windows Driver Kit" mce_href="http://www.microsoft.com/whdc/devtools/WDK/default.mspx"&gt;Windows Driver Kit&lt;/a&gt;.&amp;nbsp;&amp;nbsp; This contains sample drivers, tools, build environment, and documentation for WPD and User Mode Driver Framework.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;We recommend using WPDInfo and WPDMon as debugging and testing tools for driver development.&amp;nbsp;&amp;nbsp; These are bundled into the Windows Driver Kits.&amp;nbsp; For more details on these tools, refer to the &lt;a href="http://download.microsoft.com/download/5/D/6/5D6EAF2B-7DDF-476B-93DC-7CF0072878E6/WPD_tips.doc" class="" title="WPD Tips" mce_href="http://download.microsoft.com/download/5/D/6/5D6EAF2B-7DDF-476B-93DC-7CF0072878E6/WPD_tips.doc"&gt;"WPD Tips" Whitepaper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Need more tips and tricks?&amp;nbsp; One of our WPD enthusiasts has written a &lt;a href="http://blogs.msdn.com/dimeby8" class="" title="DimeBy8" mce_href="http://blogs.msdn.com/dimeby8"&gt;blog&lt;/a&gt; with tons of WPD and Media Transfer Protocol (MTP) how-tos.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&lt;i&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/i&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1516199" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/wpdblog/archive/tags/SDK/default.aspx">SDK</category><category domain="http://blogs.msdn.com/wpdblog/archive/tags/WDK/default.aspx">WDK</category></item></channel></rss>