Warning treated as error wdk

warning treated as error wdk

Warnings are no longer treated as errors in the checked build environment (as they have been for years), but they are treated as errors in. A simple way to improve your code is to compile with all warnings enabled and treated as errors. The compiler option /Wall enables all warnings. 我在Win7系统中编译 WDK,使用的时7600.16385.1,编译选Win7, x86 checked build error C2220: warning treated as error - no 'object' file generated.

Remarkable, very: Warning treated as error wdk

STEAM ERROR 55 F1 2012
Warning treated as error wdk
Warning treated as error wdk
Stop 0x7a kernel_data_inpage_error
Warning treated as error wdk

Warning treated as error wdk - assured, that

Help

Best Practices for Testing WDF Drivers


Tips for Building Drivers

Consider these best practices when building your driver:

  • Build and test your driver for all versions of Windows that you plan to support. Building for the earliest version of Windows creates a binary of your driver that is compatible with all versions of Windows from that version forward. Building for the latest version of Windows provides the latest checks for your driver.

  • Build your driver for both 32-bit and 64-bit platforms. Compiling for both 32-bit and 64-bit platforms can find problems in your code. In particular, compiling for 64-bit platforms can find problems related to pointers, subtle differences in the compilers, and inline assembly language, which is sometimes included inadvertently.

     Tip  See "Compiler for x64 64-Bit Environments" in the WDK-online at http://go.microsoft.com/fwlink/?LinkId=79791.

  • Build your driver in a checked build environment during development. The checked build environment creates a driver with debugging code enabled. Checked builds make debugging easier because the compiler does not optimize the output binaries as thoroughly.

  • Build your driver in a free build environment for performance testing and release. The free build environment creates a production driver in which code is optimized and debugging code is disabled.

  • Take advantage of the compiler's error-checking capabilities. Compiling and building your driver with warnings treated as errors and error level /W4 enabled finds problems in source code to the fullest extent that the compiler can enforce.

Chapter 19, "How to Build WDF Drivers," presents details and additional best practices.

Tips for Best Use of Tools

Consider these best practices for using testing tools:

  • Make sure you're using the latest tools. You should always use the latest versions of the WDK and Debugging Tools for Windows when debugging WDF drivers.

    Chapter 1, "Introduction to WDF," describes how to obtain current kits and tools.

  • Use all of the testing tools that can run on your driver. If you omit any of these tools, you might miss a serious bug in your driver.

     KMDF  At a minimum for testing KMDF drivers: Enable all options in Driver Verifier and run Device Path Exerciser, Plug and Play Driver Test, and a power management test that does a suspend-resume and a hibernate-resume, such as the WDTF script Sleep_Stress_With_IO.wsf or the Sleep State Chooser (Sleeper.exe) in %wdk%\tools\acpi. Enable KMDF Verifier and examine the information it returns in the debugger.

     UMDF  At a minimum for testing UMDF drivers: Enable Application Verifier with the settings described earlier in this chapter, and run Device Path Exerciser and the WDTF scripts Disable_Enable_With_IO.wsf and Sleep_Stress_With_IO.wsf.

  • Test your driver in both the checked and free builds of Windows. At a minimum for testing with the checked build: Install a checked build of your driver stack and the checked versions of Ntoskrnl.exe and Hal.dll, as described in this chapter.

    Test your driver with the free build for performance-related issues.

  • Use the extended features of the testing tools. In particular, test your driver with the low-resources simulation features of Driver Verifier and Application Verifier, to validate that the driver is stable and reliable when resources are constrained.

  • Make tests easily reproducible. A test that requires many manual steps or a specific system is not a viable test. The test should be easy to run and easy to move to additional test machines. If the test requires manual steps, provide a clearly written document that describes what to do.

  • Make test results easy to verify. Many tests provide detailed logs of their runs. These logs should have a simple result line indicating whether the tests succeeded. It is not helpful to have a large log that must be hand-verified to determine whether the test ran correctly. At a minimum, create the log so that it can easily be compared to a previous successful log.

Tips for Driver Life Cycle Testing

Consider these best practices for testing throughout the life cycle of your driver:

  • Test throughout the development cycle. Test your driver as soon as possible by using tools such as PREfast, SDV, and Driver Verifier and the checked build of Windows.

  • Test on a variety of platforms. Test your driver on the released versions of Windows on both uniprocessor and multiprocessor systems. If possible, test on systems that have different HALs.

  • When you fix a bug, write a test. When you debug a problem, create a regression test that can be integrated into future testing of the driver. Make sure that your customer never sees that bug again.

  • Always do regression testing. Do regression testing on your drivers against every new minor version of the framework and every new service pack of the operating system.

image from book
Maintaining Released Drivers

Errors in released drivers can be difficult to track down without good data from the field. The WER service provides a mechanism for users to send error reports to Microsoft that you can view on the Microsoft Windows Quality Online Services (Winqual) Web site. Through WER, you can direct users to Windows Update to download a newer version of your driver.

The WER service captures both hardware (that is, operating system) and software (that is, application) crashes, including information about drivers and applications as well as other modules such as controls and plug-ins that were running at the time of the crash. WER data includes a small crash dump file plus additional information depending on the type of error.

You provide Winqual with information to associate your driver's error reports with your company-sometimes called "mapping files." If WER has access to symbolic data, it can analyze the dump and look for the symbol that caused the crash, making it possible to categorize the errors more precisely.

The WER service also provides a mechanism you can use to offer users a solution to the error. When a user submits an error report, WER can show a message to the user, for example, to direct the user to a support Web site or to Windows Update.

See "Windows Error Reporting: Getting Started" on the WHDC Web site for details about WER-online at http://go.microsoft.com/fwlink/?LinkId=79792.

image from book

Windows DDK version

Source File for Demonstrating Profiling Crash

Geoff Chappell, Software Analyst

There follows the one source file, PROCRASH.CPP, for a small console application that demonstrates a Bug Check From User Mode By Profiling. Compile with a separate header, PROFILE.H, of declarations and definitions that Microsoft ordinarily does not provide for user-mode programming.

/* ************************************************************************ * * procrash.cpp * * ************************************************************************ */ /* Begin with the usual headers for user-mode Windows programming and for console output via the C Run-Time Library. Be nice to readers who expect demonstration code to compile with /Wall even if Microsoft's own headers don't. Those who worry about such things likely already know what warnings these numbers select. */ #pragma warning (disable : 4514 4710 4711) #pragma warning (push) #pragma warning (disable : 4668 4820) #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #include <stdio.h> #pragma warning (pop) /* Some more or less general-purpose support for profiling is available in the Windows Driver Kit (WDK) for kernel-mode programming. For user-mode programming there's little choice but to reproduce from the WDK. Bring it in from a separate header to reduce distraction from the actual program. */ #include "profile.h" /* Ease the use of undocumented functions such as NtCreateProfile by importing them just as for documented API functions. This requires access to an import library for NTDLL. */ #pragma comment (lib, "ntdll.lib") /* ************************************************************************ */ /* Configurable */ /* Profiling specifies a region whose execution is to be sampled recurrently. This profiled region is treated as an array of buckets. Sampling produces an execution count for each bucket. For simplicity, use the fewest possible buckets. */ #define BUCKET_COUNT 1 /* The bucket size must be a power of two - and the BucketSize argument for NtCreateProfile is actually the logarithm of the size in bytes. The smallest bucket that's permitted is 4 bytes. The two demonstrations have different requirements, however. For the ancient defect (demonstration 1), we need that profiling catches some execution anywhere in roughly a quarter of a bucket. Choosing 64 bytes as the bucket size allows 16 bytes for a tight loop plus whatever prolog and epilog code the compiler happens to add. */ #define LOG_BUCKET_SIZE_1 6 /* For demonstration 2, the smallest possible bucket is large enough. */ #define LOG_BUCKET_SIZE_2 2 /* ======================================================================== */ /* Implications and compile-time sanity checking */ /* As noted above, the smallest allowed bucket is 4 bytes. */ #define BUCKET_SIZE_1 (1 << LOG_BUCKET_SIZE_1) #define BUCKET_SIZE_2 (1 << LOG_BUCKET_SIZE_2) C_ASSERT (BUCKET_SIZE_1 >= sizeof (ULONG)); C_ASSERT (BUCKET_SIZE_2 >= sizeof (ULONG)); /* The execution counts go into a buffer. Each execution count is a ULONG. Our choice of BUCKET_COUNT thus determines how big a buffer to provide and the count and size together determine how large a region we can profile. */ #define BUFFER_SIZE (BUCKET_COUNT * sizeof (ULONG)) #define PROFILE_SIZE_1 (BUCKET_COUNT * BUCKET_SIZE_1) #define PROFILE_SIZE_2 (BUCKET_COUNT * BUCKET_SIZE_2) /* For the ancient defect, we ask mischievously to profile a slightly larger region than we should be allowed to. If we don't ask for too much more, we sneak past a defect in the kernel's parameter validation. */ #define PROFILE_EXCESS (BUCKET_SIZE_1 / sizeof (ULONG) - 1) C_ASSERT (PROFILE_EXCESS != 0); /* ************************************************************************ */ /* Supporting data */ /* To make things go wrong, the last execution count for (what we should be allowed to specify as) the profiled region must end on a page boundary. To arrange this, set aside memory that is sure to be large enough to contain BUFFER_SIZE bytes that end at a page boundary. For all imagined use of this demonstration, the page size can reasonably be regarded as well-known. */ #ifndef PAGE_SIZE #define PAGE_SIZE 0x1000 #endif BYTE Buffer [BUFFER_SIZE + PAGE_SIZE]; /* ************************************************************************ */ /* Profiled code */ /* Both demonstrations run a loop until some execution is interrupted for profiling. Aim for as tight a loop as can be without much risk that the compiler eliminates it altogether. For demonstration 1 it's enough just to execute in the excess that we shouldn't be allowed to add to the profiled region. It doesn't matter much what's in the loop, though we get the best chance of trapping execution in the excess if the whole loop fits into the excess. Demonstration 2 is fussier. The profiled region must end at an instruction boundary, the defect being that the instruction that follows the profiled region can get profiled by mistake. The choice of coding below allows that we can learn the address of an instruction in the loop by executing the loop just once without profiling. That we support the building of this code by tools from the WDK brings a small problem: believe it or not, but the WDK has not always come with a header to include for the _ReturnAddress intrinsic. */ extern "C" PVOID _ReturnAddress (VOID); #pragma intrinsic (_ReturnAddress) /* While we're at it with compiler intrinsics, it helps to have another so that the instruction we find is not some little thing that the processor can often execute in zero cycles and thus hardly ever returns to when interrupted. */ extern "C" VOID _ReadWriteBarrier (VOID); #pragma intrinsic (_ReadWriteBarrier) DECLSPEC_NOINLINE PVOID GetReturnAddress (VOID) { return _ReturnAddress (); } DECLSPEC_NOINLINE VOID __fastcall ProfileLoop (UINT Runs, PVOID volatile *Pointer) { do { *Pointer = GetReturnAddress (); _ReadWriteBarrier (); } while (-- Runs != 0); } /* ************************************************************************ */ /* The actual program */ int __cdecl wmain (int argc, PWSTR *argv) { /* Parse the command line to learn which coding error to demonstrate. */ int demo = 0; if (argc == 0) return -1; while (++ argv, -- argc != 0) { PWSTR arg = *argv; if (demo == 0) { if (wcscmp (arg, L"1") == 0) { demo = 1; continue; } if (wcscmp (arg, L"2") == 0) { demo = 2; continue; } } printf ("Invalid parameter %ws\n", arg); return -1; } if (demo == 0) demo = 1; /* From the Buffer that we set aside above, carve out the BUFFER_SIZE bytes that we'll provide for the execution counts. Remember, the distinctive property we want is that these BUFFER_SIZE bytes end at a page boundary. */ PBYTE end = (PBYTE) ALIGN_UP_BY (Buffer + BUFFER_SIZE, PAGE_SIZE); ULONG *buffer = (ULONG *) (end - BUFFER_SIZE); /* The two demonstrations choose the profiled region ever so slightly differently. */ ULONG logbucketsize; PVOID profilebase; ULONG profilesize; if (demo == 1) { logbucketsize = LOG_BUCKET_SIZE_1; /* For the ancient defect, place the whole of the ProfileLoop in our mischievous excess. */ profilebase = (PBYTE) ProfileLoop - PROFILE_SIZE_1; profilesize = PROFILE_SIZE_1 + PROFILE_EXCESS; } else { logbucketsize = LOG_BUCKET_SIZE_2; /* For demonstration 2, contrive to get the profiled region ending at exactly an instruction in the loop. */ PVOID endprofile; ProfileLoop (1, &endprofile); profilebase = (PBYTE) endprofile - PROFILE_SIZE_2; profilesize = PROFILE_SIZE_2; } /* Set up the profiling of execution in the profiled region. By the way, the simplicity of passing -1 to stand for profiling all processors comes with a small burden on 64-bit Windows: we must run a 64-bit build, not a 32-bit build, else the -1 is interpreted as meaning to profile the first 32 processors and NtCreateProfile fails unless there actually are 32 active processors to profile. */ HANDLE hprofile; NTSTATUS status = NtCreateProfile ( &hprofile, GetCurrentProcess (), profilebase, profilesize, logbucketsize, buffer, BUFFER_SIZE, ProfileTime, (KAFFINITY) -1); if (!NT_SUCCESS (status)) { printf ("Error 0x%08X creating profile object\n", (UINT32) status); } else { /* Start the profiling and run the loop. */ status = NtStartProfile (hprofile); if (!NT_SUCCESS (status)) { printf ("Error 0x%08X starting profile\n", (UINT32) status); } else { PVOID p; ProfileLoop (MAXUINT, &p); /* All being "well", we can't get here. While executing the preceding loop, a profile interrupt will occur and the kernel will try to increment an execution count for which no memory has been provided. The expected result is a bug check - indeed, a nasty one for occurring inside a hardware interrupt handler. */ NtStopProfile (hprofile); printf ("Profiling completed\n"); } CloseHandle (hprofile); } return 0; } /* ************************************************************************ */

That’s it! Compile and link to taste.

To crash all Windows versions up to but not including the 1703 release of Windows 10, run procrash 1. Before Windows 8, procrash 2 causes no fault. Some update will soon be released by Microsoft—probably without much description, and surely without attribution—such that new builds of Windows aren’t crashed by either command-line option.

Windows DDK version

Warning treated as error wdk - topic

Win7 WDK install and build Error

dfjiang

dfjiang

驱动牛犊

驱动牛犊
  • 注册日期2002-11-10
  • 最后登录2012-11-01
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望52点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分

加关注写私信

阅读:2328回复:5

楼主#

更多发布于:2011-09-28 08:22

我在Win7系统中编译 WDK,使用的时7600.16385.1,编译选Win7 , x86 checked build environment,编译完后出现比较多的错误。
下面是buildchk_win7_x86.err文件的内容,看了这个文件,感觉不知道错误如何改正,希望有经验的大虾给予提示或指导一下,谢谢!

4>errors in directory c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\dllentry.cxx(13) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\globals.cxx(11) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\intrface.cxx(17) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\oemptprovider.cxx(31) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\printschema.cxx(14) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\xmlhandler.cxx(18) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>errors in directory c:\winddk\7600.16385.1\src\print\simplepipelinefilter
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\print\simplepipelinefilter\main.cxx(19) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\simplepipelinefilter\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\simplepipelinefilter\streamfilter.cxx(19) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\simplepipelinefilter\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\simplepipelinefilter\xpsfilter.cxx(19) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\simplepipelinefilter\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\simplepipelinefilter\objchk_win7_x86\i386\main.obj'
2>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\debug
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
1>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet
1>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\debug\debug.cpp(22) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\debug\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\debug\objchk_win7_x86\i386\precomp.obj'
3>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color
3>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
1>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\bkpchndlr.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\bkpthndlr.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\bkschema.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\cmpthndlr.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\cmprofpthndlr.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\cmprofpchndlr.cpp(22) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\cmintpthndlr.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\cmschema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\cmprofileschema.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\cmintentsschema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\globals.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\nupschema.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\nupchndlr.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\bkflt.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\nupthndlr.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\bksax.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pchndlr.cpp(32) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\bkprps.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pgscpchndlr.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pgscpthndlr.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pgscschema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\porientpthndlr.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\porientschema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\psizepthndlr.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\psizeschema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pimagepthndlr.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pimageschema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pshndlr.cpp(35) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\pthndlr.cpp(32) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\ptquerybld.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\schema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\wmpchndlr.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\wmpthndlr.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\wmschema.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\workbuff.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\common\objchk_win7_x86\i386\precomp.obj'
3>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\bmpconv.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\bmpdata.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\cmflt.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\cmimg.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\cmsax.cpp(37) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\colchan.cpp(31) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\colconv.cpp(29) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\dictionary.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\profile.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\profman.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\scaniter.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\transform.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\wcsapiconv.cpp(22) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\wictobmscn.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup
1>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\ptmanage.cpp(39) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\rescache.cpp(31) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\rescpy.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\saxhndlr.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\widetoutf8.cpp(22) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\xdrchflt.cpp(31) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\xdsmplflt.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\xdstrmflt.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\common\objchk_win7_x86\i386\precomp.obj'
4>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
3>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark
3>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
1>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nuptprps.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nupxform.cpp(29) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nupflt.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nupsax.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nuppage.cpp(28) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
3>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\scaleflt.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\scalesax.cpp(30) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\pagescale.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmflt.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\pgscptprop.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmsax.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmbase.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmtext.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmfont.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmrast.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmimg.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmvect.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmxps.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmptprop.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpsarch.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpsfd.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpsfds.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpsfiler.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpsfilew.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpsproc.cpp(29) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpsrels.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\xpstype.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\xdcont\objchk_win7_x86\i386\precomp.obj'
2>errors in directory c:\winddk\7600.16385.1\src\test\dsf\usb\inputkbd
2>c:\winddk\7600.16385.1\src\test\dsf\usb\inputkbd\softkbdtranslator.cpp : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\test\dsf\usb\inputkbd\softkeyboard.cpp : error C2220: warning treated as error - no 'object' file generated
2>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\test\dsf\usb\inputkbd\objchk_win7_x86\i386\softkbdtranslator.obj'
1>errors in directory c:\winddk\7600.16385.1\src\1394\vdev_hybrid\exe
1>c:\winddk\7600.16385.1\src\1394\vdev_hybrid\exe\wdf1394.rc(124) : error RC2104 : undefined keyword or key name: Select
1>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\1394\vdev_hybrid\exe\objchk_win7_x86\i386\wdf1394.res'
1>errors in directory c:\winddk\7600.16385.1\src\general\registry\regfltr\sys
1>c:\winddk\7600.16385.1\src\general\registry\regfltr\sys\capture.c : error C2220: warning treated as error - no 'object' file generated
1>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\general\registry\regfltr\sys\objchk_win7_x86\i386\capture.obj'
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\dllentry.cxx(13) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\globals.cxx(11) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\intrface.cxx(17) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\oemptprovider.cxx(31) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\printschema.cxx(14) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\xmlhandler.cxx(18) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\dllentry.obj'
4>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\oemdll\ptpcplpr\src\objchk_win7_x86\i386\precomp.obj'
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
1>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
3>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\bkflt.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\bksax.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\bkprps.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\objchk_win7_x86\i386\dllentry.obj'
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nuptprps.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nupxform.cpp(29) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nupflt.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nupsax.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
4>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\nuppage.cpp(28) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>NMAKE : fatal error U1073: don't know how to make 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\booklet\..\..\debug\objchk_win7_x86\i386\xdsdbg.lib'
2>nmake.exe /nologo BUILDMSG=Stop. -i BUILD_PASS=PASS2 LINKONLY=1 NOPASS0=1 MAKEDLL=1 MAKEDIR_RELATIVE_TO_BASEDIR=src\print\xpsdrvsmpl\src\filters\booklet failed - rc = 2


4>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\objchk_win7_x86\i386\dllentry.obj'
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\bmpconv.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\bmpdata.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\cmflt.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\cmimg.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\cmsax.cpp(37) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\colchan.cpp(31) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\colconv.cpp(29) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\dictionary.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\profile.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\profman.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\scaniter.cpp(27) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\transform.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\wcsapiconv.cpp(22) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\wictobmscn.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\precomp.pch': No such file or directory
1>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\objchk_win7_x86\i386\bmpconv.obj'
4>NMAKE : fatal error U1073: don't know how to make 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\nup\..\..\debug\objchk_win7_x86\i386\xdsdbg.lib'
4>nmake.exe /nologo BUILDMSG=Stop. -i BUILD_PASS=PASS2 LINKONLY=1 NOPASS0=1 MAKEDLL=1 MAKEDIR_RELATIVE_TO_BASEDIR=src\print\xpsdrvsmpl\src\filters\nup failed - rc = 2


1>NMAKE : fatal error U1073: don't know how to make 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\color\..\..\debug\objchk_win7_x86\i386\xdsdbg.lib'
1>nmake.exe /nologo BUILDMSG=Stop. -i BUILD_PASS=PASS2 LINKONLY=1 NOPASS0=1 MAKEDLL=1 MAKEDIR_RELATIVE_TO_BASEDIR=src\print\xpsdrvsmpl\src\filters\color failed - rc = 2


3>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
4>errors in directory c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\ui
4>NMAKE : fatal error U1073: don't know how to make 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\ui\..\debug\objchk_win7_x86\i386\xdsdbg.lib'
4>nmake.exe /nologo BUILDMSG=Stop. -i BUILD_PASS=PASS2 LINKONLY=1 NOPASS0=1 MAKEDLL=1 MAKEDIR_RELATIVE_TO_BASEDIR=src\print\xpsdrvsmpl\src\ui failed - rc = 2


3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\scaleflt.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\scalesax.cpp(30) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\pagescale.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\pgscptprop.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\precomp.pch': No such file or directory
3>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\objchk_win7_x86\i386\dllentry.obj'
2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
3>NMAKE : fatal error U1073: don't know how to make 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\scaling\..\xdcont\objchk_win7_x86\i386\xdcont.lib'
3>nmake.exe /nologo BUILDMSG=Stop. -i BUILD_PASS=PASS2 LINKONLY=1 NOPASS0=1 MAKEDLL=1 MAKEDIR_RELATIVE_TO_BASEDIR=src\print\xpsdrvsmpl\src\filters\scaling failed - rc = 2


2>c:\winddk\7600.16385.1\inc\api\common.ver : error C2220: warning treated as error - no 'object' file generated
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\dllentry.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmflt.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmsax.cpp(24) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmbase.cpp(26) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmtext.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmfont.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmrast.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmimg.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmvect.cpp(25) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmxps.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\wmptprop.cpp(23) : error C1083: Cannot open precompiled header file: 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\precomp.pch': No such file or directory
2>link : error LNK1181: cannot open input file 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\objchk_win7_x86\i386\dllentry.obj'
2>NMAKE : fatal error U1073: don't know how to make 'c:\winddk\7600.16385.1\src\print\xpsdrvsmpl\src\filters\watermark\..\..\debug\objchk_win7_x86\i386\xdsdbg.lib'
2>nmake.exe /nologo BUILDMSG=Stop. -i BUILD_PASS=PASS2 LINKONLY=1 NOPASS0=1 MAKEDLL=1 MAKEDIR_RELATIVE_TO_BASEDIR=src\print\xpsdrvsmpl\src\filters\watermark failed - rc = 2

Build Environments.

3.   Choose one of the build environments. The build environment will open a command window.

4.   Type build to create the driver.

For most drivers setting up the Build tool environment is simple:

1.   Copy the standard makefile from a DDK sample project.

2.   Create a sources file in the directory where your code resides.

Note that the makefile should not be changed. All commands are set up by the sources file or makefile.inc, discussed later in this section. An extremely simple sources file is shown here:

TARGETNAME=test

TARGETPATH=obj

TARGETTYPE=DRIVER

SOURCES=test.c

 

This file sets four macros that instruct the Build utility to create a driver named test.sys from the source file test.c.

Build Environments

Earlier in this paper we told you to choose one of the build environments, but what is a build environment? The current DDK has build environments for the three targeted versions of Windows (2000, XP, and Server 2003). Under each version are environments for checked and free builds and for each CPU target supported for that version:

·         The checked build creates a driver with debugging enabled. Many of the optimizations in the compiler are disabled and conditional code for debugging is included. While working to get your driver functional, you build your driver with the checked build.

·         The free build creates a production driver in which the code is optimized and debug code is disabled. This is the driver you use for performance testing and to ship to customers. Do not make the mistake that some developers have done of shipping the checked build driver. Your customers deserve the best performing driver.

The Build utility names several files and directories based on the environment chosen. These names include the construct Type_Version_Cpu:

Type

Fre for the free build and Chk for the checked build.

Version

w2k for Windows 2000, wxp for Windows XP, or wnet for Windows Server 2003.

Cpu

x86, amd64, or ia64 depending on the processor.

 

As stated earlier, building and testing for the latest version of Windows provides additional checks for your driver. Building for the earliest version of Windows you plan to support creates a binary of your driver compatible with all versions of Windows from that version forward.

Sources File

The example at the beginning of this section had a very simple sources file, but the recommended file is more complex. The sources file has a large number of macros and environment variables, all of which are documented in the DDK. The following table lists items for the sources file used in this paper.

C_DEFINES

Specifies switches to pass to the C compiler and the resource compiler

INCLUDES

Specifies directories in addition to the source directory to search for include files.

MSC_WARNING_LEVEL

Sets the warning level for the C compiler. The default is /W3. Recommended is /Wall /WX. See "Compile Time Checking" later in this paper for details.

NTTARGETFILE0

Causes the inclusion in the build process of makefile.inc. Typically used to support Windows Management Instrumentation (WMI).

SOURCES

Specifies the files to be compiled.

TARGETNAME

Specifies the name of the binary to be built. This name does not include the file name extension.

TARGETLIBS

Specifies additional libraries and object files to link to the product.

TARGETPATH

Specifies the destination directory for all build products. In almost every case you should set TARGETPATH=obj.

TARGETTYPE

Specifies the type of product being built. Common values are DRIVER (kernel-mode driver), PROGRAM (user-mode program) and DRIVER_LIBRARY (kernel-mode library)

USER_C_FLAGS

Specifies switches to pass to the C compiler only.

VERIFIER_DDK_EXTENSIONS

Activates the Call Usage Verifier (CUV) tool when set to non-zero.

 

For a number of the capabilities specified later in this paper it is valuable to know about the following construct in the sources file. Sources has conditional tests, in particular:

!if !$(FREEBUILD)

...

!endif

 

This specifies that the actions between !if and !endif occur only in the checked build of the driver.

Makefile.inc File

Makefile.inc provides additional information to the Build utility. This file allows you to add commands and dependencies to the makefile, typically for pre- and post-processing of files related to the project. A common use of this in driver development is to compile a Managed Object Format (MOF) file needed for Windows Management Instrumentation (WMI) and produce an include file containing data structures for the driver.

Build Command Line

As part of finding bugs early, consider some options for the Build command line. At a minimum consider adding –bew to the build command:

b

Enables full error messages.

e

Generates the log, error, and warning files that can help when something goes wrong with Build.

w

Displays the warning messages to the command window, so you do not miss them.

 

Every so often and before you ship your driver you should use the –c option to rebuild all the files. The –c option deletes all object files.

The Build utility has a large number of options, which are all documented in the DDK. As a minimum, consider using the ones mentioned here to validate your work.

Multi-Target Build Projects

Building most driver projects is relatively simple: You put the files you need in a single directory and build the driver. Many developers encounter difficulties when the project becomes more complex.

If your project has multiple components, each should be in its own directory with a dirs file to identify the individual directories. The dirs file typically contains a single definition of the form:

DIRS=dir1 dir2 dir3

Dir1, dir2 and dir3 are subdirectories for components of the directory that contains the dirs file. These components can contain subcomponents; in fact, all of the examples in the DDK can be built as a single project. The simple model of a driver and perhaps a couple of support components such as an application and a DLL represent most projects.

If you have a multi-component project, sharing files is the most likely problem. The Build utility allows you to use source files from the current directory, its parent directory, and the platform-specific subdirectory. The common approach places the shared files in the parent directory and the unique files in the current directory as described below:

Current directory

This directory contains all the files for the project except those source files that need to be shared with other components.

Parent directory

This directory contains source files shared between two or more of the subdirectories of this directory.

Platform-specific directory

This directory contains any files specific to this particular platform.

Why Use Build?

The Build utility is the only utility you should use to compile and link a device driver. The Build utility is a wrapper program for NMAKE (the Windows make program) and is provided with the DDK to control compilation and linking of device-driver and related code. By using Build, you ensure that the driver follows the conventions and settings that Windows requires. Build handles all of the target-dependent problems, including different paths to compilers and include files for specific platforms. Additionally, Build supports different target directories based on both the target platform and whether debugging is turned on.

Using tools other than the Build utility creates three types of problems:

·         First, many DDK tools utilize the build environment. If you do not use Build, you cannot use these tools.

·         Second, if you believe you have found a bug in the DDK, Microsoft support will require code built with the Build utility to give you customer support.

·         Finally, if you do not use the Build utility, you can easily have the wrong settings for Windows drivers and create subtle bugs that can take weeks to find.

Using Build with Microsoft Visual Studio

One of the main reasons developers try to bypass Build is to use Microsoft Visual Studio. The answer here is to use Visual Studio as an editor and integrated development environment, but to have it invoke the Build utility using a batch command file.

Fortunately you do not have to worry about the details yourself, because two versions of a batch command called ddkbuild are free to download. See Resources at the end of this paper for sources of this batch command.

If you choose to use this approach, it is advisable to test that your project can still be built in the DDK build environments. This testing guarantees that nothing unusual is happening because of the batch command.

A principle of good software engineering is to find bugs early. Studies have indicated that the cost of finding and fixing a defect increases ten times for every step of the development process. So a bug found at compile time can be fixed at 1% of the cost of a bug that makes it to testing.

Developers should follow careful software engineering principles, but in the pressure of product development schedules, this can be hard to do. Additionally, many developers do not have formal training inthese best-practice methodologies. Fortunately, the Windows DDK provides a number of capabilities to find bugs early. Utilizing these tools does not require the developer to have formal training to find bugs early.

One thing to note here is that the same problem might be found by more than one of the techniques described in this section. Cleaning up all the reported problems from one tool makes it easier to run the next tool. It is still important to use all of the techniques because each can find unique problems.

Finally, a number of the techniques can create false positives, where a warning or error reported can never happen. Tools that try to find errors need to err on the side of caution. It is still important for the developer to clean up all of these warnings. Fortunately, eliminating most of the warnings is easy. View the effort to suppress the warnings as a "mini code review." You need to check whether the warning is valid anyway, so look at the code around the warning and validate that no other errors are present. These checks will take you through your code in a different manner than you usually would look at it, so use this fresh perspective to look for problems.

Compile with /Wall /WX

A simple way to improve your code is to compile with all warnings enabled and treated as errors. The compiler option /Wall enables all warnings. The /WX option treats warnings as errors.

Unfortunately, at present, the include files from the DDK do not compile cleanly with all warnings enabled. (Microsoft is working to fix this.) To overcome this problem, at present a number of warnings have to be disabled. Most of these warnings are related to Microsoft extensions to the standard language and have no impact on reliability.

For example, following line in a sources file enables warnings without requiring changes:

MSC_WARNING_LEVEL=/Wall /W4 /WX /wd4115 /wd4127 /wd4200 /wd4201 /wd4214 /wd4255 /wd4514 /wd4619 /wd4668 /wd4820

This line instructs the compiler to enable all warnings but exclude those warnings that the DDK include files generate. A better approach is to disable only the warnings for the Microsoft include files and then enable them for the driver code.

MSC_WARNING_LEVEL=/Wall /WX

Then wrap the Microsoft-supplied include files with:

#pragma warning (disable: 4115 4127 4200 4201 4214 4255 4619 4668 4820)

...

#pragma warning (default: 4115 4200 4214 4255 4619 4668 4820)

 

In this example, two of the warnings (4127 and 4201) are not enabled for the driver. These remain disabled because they flag constructs that occur in macros defined in the Microsoft include files. Note that the specific warnings can vary with the particular version of the DDK. These examples should be considered only as guidance.

These warnings add simple checks that can point out potential problems. The following are some of the common warnings that are likely to appear for your driver.

C4057 'operator' : 'identifier1' indirection to slightly different base types from 'identifier2'

Typically, this warning appears because of two similar but different types, such as a signed versus unsigned value or a short versus long value. To fix this, change the base type where possible to the correct form, and otherwise use a C cast to convert the item.

C4100 'identifier' : unreferenced formal parameter

If this warning occurs in a function you designed, ask yourself the reason for passing this parameter. This warning mainly occurs where the DDK dictates the function prototype. In this case, use the UNREFERENCED_PARAMETER macro to eliminate the error. Careful! If your driver later starts using the parameter, be sure to delete the UNREFERENCED_PARAMETER macro for that parameter.

C4101 'identifier' : unreferenced local variable

The simple solution here is to delete the unused variable. Before you do so, ask yourself why it was there in the first place. Many times this indicates that something was forgotten in the function, so check your code and design before deleting the variable.

C4244 'variable' : conversion from 'type' to 'type', possible loss of data

This warning occurs when you convert an integer value to a smaller type. This can reflect a real error such as forcing a 64-bit value to 32 bits. Runtime checks can be enabled for this problem, so when fixing this error, consider ANDing the value with a mask to a legal size and then casting the value to the correct type.

Use the C++ compiler

C++ has been described as “a better C.” This is not a recommendation to use C++ language features in the kernel. Using C++ in the kernel presents a number of challenges, so unless you are comfortable with Windows driver development you should avoid using C++. The paper "C++ for Kernel Mode Drivers: Pros and Cons" provides information for you to make your own decision. See Resources at the end of this paper for a link.

Although using the full C++ language in the kernel can cause a number of problems, using the C++ compiler can help you to identify potential improvements in your driver, because it does more validation and checking. .The challenge here is to be sure that you are still programming in C while compiling with C++.

One approach is to use the compiler's /TP switch to treat files with a .c extension as C++ code. Using this option in the sources file only for the checked build allows you to catch any C++ constructs in your code. For example:

!if !$(FREEBUILD)

USER_C_FLAGS= /TP

!endif

 

This example builds a driver using C++ for the checked build. If you do this, be sure to change your DriverEntry routine also, as follows:

#ifdef __cplusplus

extern "C"

#endif

NTSTATUS DriverEntry( 
    IN PDRIVER_OBJECT  DriverObject, 
    IN PUNICODE_STRING  RegistryPath); 

 

You might also need to use extern "C" to wrap the include file for WPP software tracing (described later in this paper). This technique requires building both the checked and the free build of the driver. If you use Visual Studio with ddkbuild, use the batch build command to build both versions at the same time.

Most of the errors found using the C++ compiler involve type checks and certain constructs not allowed in C++. As with /Wall, cleaning these up these warnings can reduce the number of actual errors in your driver.

PREfast

PREfast is a tool that Microsoft developed to find a number of problems that are hard for a compiler to locate. PREfast performs a static analysis of each function in your code to locate problems. The Windows Server 2003 DDK provides a version of PREfast with driver-specific rules that every driver writer should use. This version of PREfast can detect a number of common problems for drivers through explicit knowledge of kernel-mode functions and structures.

Running PREfast

PREfast is not as easy to find as other tools in the DDK because it is not listed on the Tools menu. Instead, go to Programs

Source File for Demonstrating Profiling Crash

Geoff Chappell, Software Analyst

There follows the one source file, PROCRASH.CPP, for a small console application that demonstrates a Bug Check From User Mode By Profiling. Compile with a separate header, PROFILE.H, of declarations and definitions that Microsoft ordinarily does not provide for user-mode programming.

/* ************************************************************************ * * procrash.cpp * * ************************************************************************ */ /* Begin with the usual headers for user-mode Windows programming and for console output via the C Run-Time Library. Be nice to readers who expect demonstration code to compile with /Wall even if Microsoft's own headers don't. Those who worry about such things likely already know what warnings these numbers select. */ #pragma warning (disable : 4514 4710 4711) #pragma warning (push) #pragma warning (disable : 4668 4820) #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #include <stdio.h> #pragma warning (pop) /* Some more or less general-purpose support for profiling is available in the Windows Driver Kit (WDK) for kernel-mode programming. For user-mode programming there's little choice but to reproduce from the WDK. Bring it in from a separate header to reduce distraction from the actual program. */ #include "profile.h" /* Ease the use of undocumented functions such as NtCreateProfile by importing them just as for documented API functions. This requires access to an import library for NTDLL. */ #pragma comment (lib, "ntdll.lib") /* ************************************************************************ */ /* Configurable */ /* Profiling specifies a region whose execution is to be sampled recurrently. This profiled region is treated as an array of buckets. Sampling produces an execution count for each bucket. For simplicity, use the fewest possible buckets. */ #define BUCKET_COUNT 1 /* The bucket size must be a power of two - and the BucketSize argument for NtCreateProfile is actually the logarithm of the size in bytes. The smallest bucket that's permitted is 4 bytes. The two demonstrations have different requirements, however. For the ancient defect (demonstration 1), we need that profiling catches some execution anywhere in roughly a quarter of a bucket. Choosing 64 bytes as the bucket size allows 16 bytes for a tight loop plus whatever prolog and epilog code the compiler happens to add. */ #define LOG_BUCKET_SIZE_1 6 /* For demonstration 2, the smallest possible bucket is large enough. */ #define LOG_BUCKET_SIZE_2 2 /* ======================================================================== */ /* Implications and compile-time sanity checking */ /* As noted above, the smallest allowed bucket is 4 bytes. */ #define BUCKET_SIZE_1 (1 << LOG_BUCKET_SIZE_1) #define BUCKET_SIZE_2 (1 << LOG_BUCKET_SIZE_2) C_ASSERT (BUCKET_SIZE_1 >= sizeof (ULONG)); C_ASSERT (BUCKET_SIZE_2 >= sizeof (ULONG)); /* The execution counts go into a buffer. Each execution count is a ULONG. Our choice of BUCKET_COUNT thus determines how big a buffer to provide and the count and size together determine how large a region we can profile. */ #define BUFFER_SIZE (BUCKET_COUNT * sizeof (ULONG)) #define PROFILE_SIZE_1 (BUCKET_COUNT * BUCKET_SIZE_1) #define PROFILE_SIZE_2 (BUCKET_COUNT * BUCKET_SIZE_2) /* For the ancient defect, we ask mischievously to profile a slightly larger region than we should be allowed to. If we don't ask for too much more, we sneak past a defect in the kernel's parameter validation. */ #define PROFILE_EXCESS (BUCKET_SIZE_1 / sizeof (ULONG) - 1) C_ASSERT (PROFILE_EXCESS != 0); /* ************************************************************************ */ /* Supporting data */ /* To make things go wrong, the last execution count for (what we should be allowed to specify as) the profiled region must end on a page boundary. To arrange this, set aside memory that is sure to be large enough to contain BUFFER_SIZE bytes that end at a page boundary. For all imagined use of this demonstration, the page size can reasonably be regarded as well-known. */ #ifndef PAGE_SIZE #define PAGE_SIZE 0x1000 #endif BYTE Buffer [BUFFER_SIZE + PAGE_SIZE]; /* ************************************************************************ */ /* Profiled code */ /* Both demonstrations run a loop until some execution is interrupted for profiling. Aim for as tight a loop as can be without much risk that the compiler eliminates it altogether. For demonstration 1 it's enough just to execute in the excess that we shouldn't be allowed to add to the profiled region. It doesn't matter much what's in the loop, though we get the best chance of trapping execution in the excess if the whole loop fits into the excess. Demonstration 2 is fussier. The profiled region must end at an instruction boundary, the defect being that the instruction that follows the profiled region can get profiled by mistake. The choice of coding below allows that we can learn the address of an instruction in the loop by executing the loop just once without profiling. That we support the building of this code by tools from the WDK brings a small problem: believe it or not, but the WDK has not always come with a header to include for the _ReturnAddress intrinsic. */ extern "C" PVOID _ReturnAddress (VOID); #pragma intrinsic (_ReturnAddress) /* While we're at it with compiler intrinsics, it helps to have another so that the instruction we find is not some little thing that the processor can often execute in zero cycles and thus hardly ever returns to when interrupted. */ extern "C" VOID _ReadWriteBarrier (VOID); #pragma intrinsic (_ReadWriteBarrier) DECLSPEC_NOINLINE PVOID GetReturnAddress (VOID) { return _ReturnAddress (); } DECLSPEC_NOINLINE VOID __fastcall ProfileLoop (UINT Runs, PVOID volatile *Pointer) { do { *Pointer = GetReturnAddress (); _ReadWriteBarrier (); } while (-- Runs != 0); } /* ************************************************************************ */ /* The actual program */ int __cdecl wmain (int argc, PWSTR *argv) { /* Parse the command line to learn which coding error to demonstrate. */ int demo = 0; if (argc == 0) return -1; while (++ argv, -- argc != 0) { PWSTR arg = *argv; if (demo == 0) { if (wcscmp (arg, L"1") == 0) { demo = 1; continue; } if (wcscmp (arg, L"2") == 0) { demo = 2; continue; } } printf ("Invalid parameter %ws\n", arg); return -1; } if (demo == 0) demo = 1; /* From the Buffer that we set aside above, carve out the BUFFER_SIZE bytes that we'll provide for the execution counts. Remember, the distinctive property we want is that these BUFFER_SIZE bytes end at a page boundary. */ PBYTE end = (PBYTE) ALIGN_UP_BY (Buffer + BUFFER_SIZE, PAGE_SIZE); ULONG *buffer = (ULONG *) (end - BUFFER_SIZE); /* The two demonstrations choose the profiled region ever so slightly differently. */ ULONG logbucketsize; PVOID profilebase; ULONG profilesize; if (demo == 1) { logbucketsize = LOG_BUCKET_SIZE_1; /* For the ancient defect, place the whole of the ProfileLoop in our mischievous excess. */ profilebase = (PBYTE) ProfileLoop - PROFILE_SIZE_1; profilesize = PROFILE_SIZE_1 + PROFILE_EXCESS; } else { logbucketsize = LOG_BUCKET_SIZE_2; /* For demonstration 2, contrive to get the profiled region ending at exactly an instruction in the loop. */ PVOID endprofile; ProfileLoop (1, &endprofile); profilebase = (PBYTE) endprofile - PROFILE_SIZE_2; profilesize = PROFILE_SIZE_2; } /* Set up the profiling of execution in the profiled region. By the way, the simplicity of passing -1 to stand for profiling all processors comes with a small burden on 64-bit Windows: we must run a 64-bit build, not a 32-bit build, else the -1 is interpreted as meaning to profile the first 32 processors and NtCreateProfile fails unless there actually are 32 active processors to profile. */ HANDLE hprofile; NTSTATUS status = NtCreateProfile ( &hprofile, GetCurrentProcess (), profilebase, profilesize, logbucketsize, buffer, BUFFER_SIZE, ProfileTime, (KAFFINITY) -1); if (!NT_SUCCESS (status)) { printf ("Error 0x%08X creating profile object\n", (UINT32) status); } else { /* Start the profiling and run the loop. */ status = NtStartProfile (hprofile); if (!NT_SUCCESS (status)) { printf ("Error 0x%08X starting profile\n", (UINT32) status); } else { PVOID p; ProfileLoop (MAXUINT, &p); /* All being "well", we can't get here. While executing the preceding loop, a profile interrupt will occur and the kernel will try to increment an execution count for which no memory has been provided. The expected result is a bug check - indeed, a nasty one for occurring inside a hardware interrupt handler. */ NtStopProfile (hprofile); printf ("Profiling completed\n"); } CloseHandle (hprofile); } return 0; } /* ************************************************************************ */

That’s it! Compile and link to taste.

To crash all Windows versions up to but not including the 1703 release of Windows 10, run procrash 1. Before Windows 8, procrash 2 causes no fault. Some update will soon be released by Microsoft—probably without much description, and surely without attribution—such that new builds of Windows aren’t crashed by either command-line option.

Windows Driver Development Environment

Download EaseFilter Filter Driver SDK Setup File Download EaseFilter Filter Driver SDK Zip FileUnderstand EaseFilter Filter Driver SDK Programming

Introduction

Even for experienced developers, getting started with Microsoft® Windows® device drivers can be difficult. You have a new programming model to learn and a new set of tools for building and debugging. Opening the documentation, you find thousands of pages of information.

This paper presents an overview of the tools used in creating a Windows device driver. Additionally, the paper discusses debugging and testing tools that can help you with your driver. In particular, the paper examines ways to find and fix bugs early in development, to help you produce a high-quality device driver.

Do You Need a Driver?

Before you start development of your new device and its driver, consider whether you need a driver at all: Kernel-mode drivers are significant software projects that require careful development to ensure the stability of the system. Developing kernel-mode drivers requires a different set of expertise than developing user-mode applications. In addition, the cost of supporting a kernel-mode driver can be many times the cost of its development. Given the complexities of kernel development, it can be desirable to avoid developing a driver.

Here are some questions to ask before assuming you need a kernel-mode driver:

Can you use a Microsoft-supplied driver? With modern peripheral buses such as USB and IEEE 1394, devices in many classes must comply with industry standard interfaces. The host controllers for these buses also must comply with industry standard interfaces for compatibility with Windows. If your device complies with these standards, it can use the drivers Microsoft provides.

Is the driver for a standard device class with a unique hardware design? If your device is in a standard device class such as a storage device, but it has a unique hardware design, you will need a driver. Similarly, if your device is accessed through Win32 API, a driver is required.

Can you move all or part of the driver into user mode? If your driver does not fit the above description, examine moving all or part of the driver into user mode. Not only is the user-mode environment easier to program, but a driver failure in user mode will affect only your device and not crash the system.

Is your device accessed through a user-mode API by only a few applications? A driver might not be needed if your device connects to the system through a bus driver with a user mode API and is to be used only by a limited number of applications. A device connected to the system by a serial link or an Ethernet protocol is not likely to need a driver. Additionally, devices connected to a storage bus such as SCSI or ATAPI can use the pass-through capabilities in the bus controller device driver to support sending and receiving requests from devices connected to the bus.

Is your driver a software-only driver? A software-only kernel-mode driver is another type of driver that sometimes is not needed. A user-mode service running under the system account can replace a kernel-mode driver in many cases.

Can you move some development to a user-mode DLL? Finally, if you conclude that your device does need a driver, consider using a user mode DLL as part of the effort to reduce the amount of kernel development needed for your project.

The Many Types of Drivers

When you say you want a device driver, you should think about the type of driver you need. Windows supports a wide variety of devices, and as this support has grown, the environment for these drivers has diverged. Understanding the different driver types is important for a number of reasons:

·         The kernel programming interfaces can vary from type to type.

·         The rules for what the driver can do varies by type.

·         If you ask someone for help, they will need to know the type of driver you are working on.

Windows device drivers can be classified in many ways. For this paper, we will look at some of the major types. The following list is only one approach to classifying the many types of Windows drivers:

·         Legacy drivers. These drivers were the generic model for Windows NT. With the advent of Plug and Play on Windows 2000, these drivers became relegated to some limited categories. Their primary use these days is for kernel services, that is, pure software drivers that provide interfaces and services that need to execute in the kernel. This type of driver should not be used for a hardware device.

·         Windows (Plug and Play) drivers. When referring to a Windows driver, most people think of the current model of a driver with Plug and Play and power management. Windows Driver Model (WDM) drivers are a subset of these drivers. WDM was introduced to provide a common model for Plug and Play capabilities between Windows 98 (and later Windows ME) and Windows 2000 and later versions of Windows.

·         File system drivers. File systems are in a special category of legacy drivers. These drivers keep track of files on a device or provide access to files across the network. File system drivers require additional headers and libraries beyond the standard tools. To create a file system driver, you need the Windows Installable File System Kit (IFS kit). See Resources at the end of this paper for availability of this kit.

·         Storage miniport drivers. Drivers for storage controllers such as SCSI and IDE have their own programming interface. This interface limits what a driver of this type can do. In addition, to provide backward compatibility with Windows 98, the kernel calls are unique. For many of these functions you will find an exact equivalent in WDM.

·         Network drivers. Like storage drivers, network drivers have their own programming interfaces. Unlike storage drivers, network drivers use standard Windows interfaces in many cases.

·         Printer drivers. This is a special category of drivers. Printer drivers run in user mode and do not conform to the programming model for other drivers.

·         Graphics drivers. Another special category of drivers, graphics drivers have their own rules and programming interface. Graphics drivers are some of the most complex projects in Windows.

·         Kernel streaming drivers. This is another unique category of driver. Like a number of the other categories, kernel streaming drivers have unique interfaces for programming. In addition, this is the only class of drivers typically programmed in C++.

·         Bus drivers. A bus driver enumerates devices on a bus and arbitrates access to the bus. Bus drivers are Plug and Play drivers and must support special requests beyond what other Windows drivers do.

·         Filter drivers. A filter driver layers above or below an existing driver to provide special services or change the behavior of a standard driver. A common example of a filter driver is a virus scanner that sits above the file system and checks files for viruses. Filter drivers typically follow the rules of the driver they are filtering.

What You Need for Driver Development

For driver development, you need a system for development and a system on which to debug your driver. Any reasonably sized desktop system can provide the hardware for development. The only special thing it must have is a free serial or IEEE 1394 port for the debugger. We will look at what you need for the test machine later in this paper. For now we will concentrate on the development system software.

The Windows Device Driver Kit (DDK) provides the build environment for developing a device driver for Windows. The DDK includes the approved build tools, compiler, and linker for creating a driver. The DDK also has thousands of pages of documentation about developing drivers and numerous sample drivers. In fact, the only software required to build a driver besides the DDK is a good editing tool.

A common misconception among driver developers is that you need the DDK named for the particular version of Windows you are targeting with your driver. In fact, when developing a driver, you need the latest DDK. This DDK has the latest tools, samples and documentation for developing drivers. At present, the kits are named for the latest operating system at the time of their release. This means that the Windows 2003 DDK is not just for creating drivers for that version of Windows, but is the best choice for creating drivers for all versions of Windows back to Windows 2000. For a guide to choosing the proper DDK, see Resources at the end of this paper.

In addition to the DDK, you need the WinDbg debugger. This debugger is part of the Debugging Tools for Windows and can be downloaded from Microsoft. Along with the debugger, you need the debugging symbols for the version of Windows you are testing. The symbols can be accessed either through the Microsoft symbol server or by downloading the symbol files.. For availability of the debugger and symbols, see Resources at the end of this paper.

The final software purchase to consider is a code coverage tool. This tool can help in debugging and validate that you are testing your driver well. A full discussion of code coverage is provided later in this paper. See Resources at the end of this paper for companies that offer code coverage tools for Windows drivers.

Your Test Machine

Many developers and their managers are surprised that a separate test machine is required, but there are many good reasons for this. Debugging an operating system is a challenge because the debugger affects its normal operation. To limit this impact, Windows requires a separate machine for use with the WinDbg debugger. A separate machine is needed for a number of other reasons:

·         Although your development machine typically will run a desktop version of Windows, for testing you need a variety of Windows versions, from server to desktop.

·         Crashes are likely in developing a driver. At best, a crash requires rebooting the system to fix the bug, and then rebooting the system again to install and run the driver, a slow process. At worst, you can corrupt the disk and have to rebuild your development system and recover your work.

On the test system, you should install multiple versions of Windows. Even if you are targeting a particular version of Windows, having the latest version will provide you with the best validation tools. One of the versions running on the test system should be the checked build of Windows. The checked build is one of the most powerful tools for debugging and testing your driver. Using the checked build to improve your drivers will be discussed later in this paper. The checked build is only available as part of Microsoft Developer Network (MSDN). See Resources at the end of this paper for availability of the checked build and other developer resources on MSDN.

Now that you know the reasons for having a separate test system, be sure to get a good one:

·         At a minimum, it needs a serial or IEEE 1394 port for the debugger.

·         The most critical need is for a multiprocessor or at least a hyper-threaded system. You cannot debug multiprocessor issues without a multiprocessor machine. Now that even low-end systems support hyper-threading, this is a requirement.

·         Nowadays you should consider x86-64 support in your driver. A multiprocessor x86-64 system makes an excellent test machine because it can support both 32-bit and 64-bit versions of Windows.

·         Having pluggable disks on your test system makes it easy to test against multiple versions of Windows.

·         If your device supports DMA, consider getting a test machine with more than 4GB of main memory. This amount might seem excessive, but it can be useful in tracking down problems in addressing extended memory. Finding such problems is difficult when your system does not have enough memory to test for them.

Why Find Bugs Early?

Driver debugging is difficult, so if you find and fix bugs early you can reduce development time. For many developers this is foreign to their current practice. The rest of this paper looks at the environment and tools for building Windows device drivers. Much of the discussion involves enabling as many checks as possible.

If you find a bug at compilation time, it takes seconds to fix the code and resubmit the module for compilation. If the bug goes undetected until found by the runtime verification tools, it can take at least five minutes just to rebuild and install the driver to fix the bug. If the bug is not found by the runtime checks, the five minutes stretches to hours or days to find the problem.

Once quality assurance (QA) gets involved, the costs escalate. QA has to find the bug, try to reproduce it, and put it in a bug report. Then management looks at the bug report and discusses it with the developer. Finally, the developer tries to reproduce the problem, and then debug it. Overall, this process can take person-days. The process takes even longer if a customer reports the bug, and although the effort may not increase as rapidly, the time until the customer has the bug fix still grows enormously.

Therefore, the little extra time it takes to enable the warning messages and fix the problems they report is inconsequential compared to the time it can save by finding even a single bug up front.

Installing the Software

Before you install the DDK and the debugger, you need to know several things:

·         Not all of the tools in the DDK work if the directory path for the DDK contains a space. So do not install the DDK at some location like “C:\Program Files\DDK”. If the path contains a space, you will not get a clean error message. Instead, the build of your driver may fail in mysterious ways.

·         The DDK has tools for building drivers for a number of versions of Windows. Before you think you need only the tools for a particular version, consider the following guideline:

Build your driver for the earliest version of Windows you wish to support, but be sure to have the tools to build for the latest version for testing.

You should load the support files for the earliest version of Windows you support and for the latest version of Windows you plan to test. In many cases, the simplest approach is to load the support files for all versions of Windows.

Additionally, you should load the compiler and build tools for a 64-bit target as well as for the 32-bit systems most people need. Even if you do not support 64-bit systems now, using the 64-bit build tools can find bugs in your code.

Finally, you should load most of the samples. Even if you are specializing in a particular type of driver, the rest of the samples can be valuable in showing approaches to coding in the Windows kernel.

·         For the WinDbg debugger, you need either the 32-bit or the 64-bit version of the package, depending on your development system. This confuses some people. It is not the system you are testing but the system the debugger will be running on that determines which version you need.

·         Another choice to make is whether to use the Beta version or the released version of the debugger. The Beta versions have been so stable that most developers use the Beta to get the latest commands.

·         Finally, when you are actually installing the debugger, choose to install the debugger SDK. The SDK allows you to add your own useful tools to WinDbg.

This section explores the development environment needed to compile and link Windows device drivers. The actual process of compiling and linking the driver is controlled by the Build utility. The rest of this section provides an overview of the Build utility and the input file for the tool. At the end of the section we will look at an approach to running Build from the Visual Studio Integrated Development Environment.

Build Utility

To create a driver in the Windows DDK you use the Build utility. This utility invokes the correct tools with the appropriate options to build your driver. The Build utility is a wrapper around the Microsoft NMAKE utility, so it handles issues like checking dependencies to ensure that the correct files are rebuilt after a change.

If you have not worked with Build before, you might want to try building one of the samples from the DDK:

1.   Copy the files under src\general\<sample>\sys (where <sample> is the particular sample’s name) to a test directory.

2.   From the Start menu of your computer, go to Programs Help Published: 14-Feb-06

Source File for Demonstrating Profiling Crash

Geoff Chappell, Software Analyst

There follows the one source file, PROCRASH.CPP, for a small console application that demonstrates a Bug Check From User Mode By Profiling. Compile with a separate header, PROFILE.H, of declarations and definitions that Microsoft ordinarily does not provide for user-mode programming.

/* ************************************************************************ * * procrash.cpp * * ************************************************************************ */ /* Begin with the usual headers for user-mode Windows programming and for console output via the C Run-Time Library. Be nice to readers who expect demonstration code to compile with /Wall even if Microsoft's own headers don't. Those who worry about such things likely already know what warnings these numbers select. */ #pragma warning (disable : 4514 4710 4711) #pragma warning (push) #pragma warning (disable : 4668 4820) #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #include <stdio.h> #pragma warning (pop) /* Some more or less general-purpose support for profiling is available in the Windows Driver Kit (WDK) for kernel-mode programming. For user-mode programming there's little choice but to reproduce from the WDK. Bring it in from a separate header to reduce distraction from the actual program. */ #include "profile.h" /* Ease the use of undocumented functions such as NtCreateProfile by importing them just as for documented API warning treated as error wdk. This requires access to an import library for NTDLL. */ #pragma comment (lib, "ntdll.lib") /* ************************************************************************ */ /* Configurable */ /* Profiling specifies a region whose execution is to be sampled recurrently. This profiled region is treated as an array of buckets. Sampling produces an execution count for each bucket. For simplicity, use the fewest possible buckets. */ #define BUCKET_COUNT 1 /* The bucket size must be a power of two - and the BucketSize argument for NtCreateProfile is actually the logarithm of the size in bytes. The smallest bucket that's permitted is 4 bytes. The two demonstrations have different requirements, warning treated as error wdk, however. For the ancient defect (demonstration 1), we need that profiling catches some execution anywhere in roughly a quarter of a bucket. Choosing 64 bytes as the bucket size allows 16 bytes for a tight loop plus whatever prolog and epilog code the compiler happens to add. */ #define LOG_BUCKET_SIZE_1 essbase error 1012704 /* For demonstration 2, the smallest possible bucket is large enough. */ #define LOG_BUCKET_SIZE_2 warning treated as error wdk /* ======================================================================== */ /* Implications and compile-time sanity checking */ /* As noted above, the smallest allowed bucket is 4 bytes. */ #define BUCKET_SIZE_1 (1 << LOG_BUCKET_SIZE_1) #define BUCKET_SIZE_2 (1 << LOG_BUCKET_SIZE_2) C_ASSERT (BUCKET_SIZE_1 >= sizeof (ULONG)); C_ASSERT (BUCKET_SIZE_2 >= sizeof (ULONG)); /* The execution counts go into a buffer. Each execution count is a ULONG. Our choice of BUCKET_COUNT thus determines how big a buffer to provide and the count and size together determine how large a region we can profile. */ #define BUFFER_SIZE warning treated as error wdk (BUCKET_COUNT * sizeof (ULONG)) #define PROFILE_SIZE_1 (BUCKET_COUNT * BUCKET_SIZE_1) #define PROFILE_SIZE_2 (BUCKET_COUNT * BUCKET_SIZE_2) /* For the ancient defect, we ask mischievously to profile a slightly larger region than we should be allowed to. If we don't ask for too much more, we sneak past a defect in the kernel's parameter validation. */ #define PROFILE_EXCESS (BUCKET_SIZE_1 / sizeof (ULONG) - 1) C_ASSERT (PROFILE_EXCESS != 0); /* ************************************************************************ */ /* Supporting data */ /* To make things go wrong, the last execution count for (what we should be allowed to specify as) the profiled region must end on a page boundary. To arrange this, set aside memory that is sure to be large enough to contain BUFFER_SIZE bytes that end at a page boundary. For all imagined use of this demonstration, the page size can reasonably be regarded as well-known. */ #ifndef PAGE_SIZE #define PAGE_SIZE 0x1000 #endif BYTE Buffer [BUFFER_SIZE + PAGE_SIZE]; /* ************************************************************************ */ /* Profiled code */ /* Both demonstrations run a loop until some execution is interrupted for profiling. Aim for as tight a loop as can be without much risk that the compiler eliminates it altogether. For demonstration 1 it's enough just to execute in the excess that we shouldn't be allowed to add to the profiled region. It doesn't matter much what's in the loop, though we get the best chance of trapping execution in the excess if the whole loop fits into the excess. Demonstration 2 is fussier. The profiled region must end at an instruction boundary, the defect being that the instruction that follows the profiled region can get profiled by mistake. The warning treated as error wdk of coding below allows that we can learn the address of an instruction in the loop by executing the loop just once without profiling, warning treated as error wdk. That we support the building of this code by tools from the WDK brings warning treated as error wdk small problem: believe it or not, but the WDK has not always come with a header to include for the _ReturnAddress intrinsic. */ extern "C" PVOID _ReturnAddress (VOID); #pragma intrinsic (_ReturnAddress) /* While we're at it with compiler intrinsics, it helps to have another so that the instruction we repomd.xml [errno 5] oserror [errno 2] is not some little thing that the processor can often execute in zero cycles and thus hardly ever returns to when interrupted. */ extern "C" VOID _ReadWriteBarrier (VOID); #pragma intrinsic (_ReadWriteBarrier) DECLSPEC_NOINLINE PVOID GetReturnAddress (VOID) { return _ReturnAddress (); } DECLSPEC_NOINLINE VOID __fastcall ProfileLoop (UINT Runs, PVOID volatile *Pointer) { do { *Pointer = GetReturnAddress (); _ReadWriteBarrier (); } while (-- Runs != 0); } /* ************************************************************************ */ /* The actual program */ int __cdecl wmain (int argc, PWSTR *argv) { /* Parse the command line to learn which coding error to demonstrate, warning treated as error wdk. */ int demo = 0; if (argc == 0) return -1; while (++ argv, -- argc != 0) { PWSTR arg = *argv; if (demo == 0) { if (wcscmp (arg, L"1") == 0) { demo = 1; continue; } if (wcscmp (arg, L"2") == 0) { demo = 2; continue; } } printf ("Invalid parameter %ws\n", arg); return -1; } if (demo == 0) demo = 1; /* From the Buffer that we set aside above, carve out the BUFFER_SIZE bytes that we'll provide for the execution counts. Remember, the distinctive property we want is that these BUFFER_SIZE bytes end at a page boundary. */ PBYTE end = (PBYTE) ALIGN_UP_BY (Buffer + BUFFER_SIZE, PAGE_SIZE); ULONG *buffer = (ULONG *) (end - BUFFER_SIZE); /* The two demonstrations choose the profiled region ever so slightly differently. */ ULONG logbucketsize; PVOID profilebase; ULONG profilesize; if (demo == 1) { warning treated as error wdk logbucketsize = LOG_BUCKET_SIZE_1; /* For the ancient defect, place the whole of the ProfileLoop in our mischievous excess. */ profilebase = (PBYTE) ProfileLoop - PROFILE_SIZE_1; profilesize = PROFILE_SIZE_1 + PROFILE_EXCESS; } else { logbucketsize = LOG_BUCKET_SIZE_2; /* For demonstration 2, contrive to get the profiled region ending at exactly an instruction in the loop. */ PVOID endprofile; ProfileLoop (1, &endprofile); profilebase = (PBYTE) endprofile - PROFILE_SIZE_2; profilesize = PROFILE_SIZE_2; } /* Set up the profiling of execution in the profiled region. By the way, the simplicity of passing -1 to stand for profiling all processors comes with a small burden on 64-bit Windows: we must run a 64-bit build, not a 32-bit build, else the -1 is interpreted as meaning to profile the first 32 processors and NtCreateProfile fails unless there actually are 32 active processors to profile. */ HANDLE hprofile; NTSTATUS status = NtCreateProfile ( &hprofile, GetCurrentProcess (), profilebase, profilesize, logbucketsize, buffer, BUFFER_SIZE, ProfileTime, (KAFFINITY) -1); if (!NT_SUCCESS (status)) { printf ("Error 0x%08X creating profile object\n", warning treated as error wdk status); } else { /* Start the profiling and run the loop. */ status = NtStartProfile (hprofile); if (!NT_SUCCESS (status)) { printf ("Error 0x%08X starting profile\n", (UINT32) status); } else { PVOID p; ProfileLoop (MAXUINT, &p); /* All being "well", we can't get here. While executing the preceding loop, a profile interrupt will occur and the kernel will try to increment an execution count for which no warning treated as error wdk has been provided. The expected result is a bug check - indeed, a nasty one for occurring inside a hardware interrupt handler. */ NtStopProfile (hprofile); printf ("Profiling completed\n"); } CloseHandle (hprofile); } return 0; } /* ************************************************************************ */

That’s it! Compile and link to taste.

To crash all Windows versions up to but not including the 1703 release of Windows 10, run procrash 1. Before Windows 8, procrash 2 causes no fault. Some update will soon be released by Microsoft—probably without much description, and surely without attribution—such that new builds of Windows aren’t crashed by either command-line option.

The WDK Build Environment -- Not Getting Better
Hector J. Rodriguez

Windows Driver Development Environment

Download EaseFilter Filter Driver SDK Setup File Download EaseFilter Filter Driver SDK Zip FileUnderstand EaseFilter Filter Driver SDK Programming

Introduction

Even for experienced developers, getting started with Microsoft® Windows® device drivers can be difficult. You have a new programming model to learn and a new set of warning treated as error wdk for building and debugging. Opening the documentation, you find thousands of pages of information.

This paper presents an overview of the tools used in creating a Windows device driver. Additionally, the paper discusses debugging and testing tools that can help you with your driver. In particular, the paper examines ways to find and fix bugs early in development, warning treated as error wdk, to help you produce a high-quality warning treated as error wdk driver.

Do You Need a Driver?

Before you start development of your new device and its driver, consider whether you need a driver at all: Kernel-mode drivers are significant software projects that require careful development to ensure the stability of the system. Developing kernel-mode drivers requires a different set of begin error report 7fe0271 minecraft expertise than developing user-mode applications. In addition, the critical error 8040 of supporting a kernel-mode driver can be many times the cost of its development. Given the complexities of kernel development, warning treated as error wdk, it can be desirable to avoid developing a driver.

Here are some questions to ask before assuming you need a kernel-mode driver:

Can you use a Microsoft-supplied driver? With modern peripheral buses such as USB and IEEE 1394, devices in many classes must comply with industry standard interfaces. The host controllers for these buses also must comply with industry standard interfaces for compatibility with Windows. If warning treated as error wdk device complies with these standards, it can use the drivers Microsoft provides.

Is the driver for a standard device class with a unique hardware design? If your device is in a standard device class such as a storage device, but it has a unique hardware design, you will need a driver. Similarly, if your device is accessed through Win32 API, a driver is required.

Can you move all or part of the driver warning treated as error wdk into user mode? If your driver does not fit the above description, ssl_error_syscall bad file descriptor examine moving all or part of the driver into user mode. Not only is the user-mode environment easier to program, but a driver failure in user mode will affect only your device and not crash the system.

Is your device accessed through a user-mode API by only a few applications? A driver might not be needed if your device connects to the system through a bus driver with a user mode API and is to be used only by a limited number of applications. A device connected to the system by a serial link or an Ethernet protocol is not likely to hd tune c8 write error rate a driver. Additionally, devices connected to a storage bus such as SCSI or ATAPI can use the pass-through capabilities in the bus controller device driver to support sending and receiving requests from devices connected to the bus.

Is your driver a software-only driver? A software-only kernel-mode driver is another type of driver that sometimes is not needed. A user-mode service running under the system account can replace a kernel-mode driver in many cases.

Can you move some development to a user-mode Warning treated as error wdk Finally, if you conclude that your device does need a e19 canon mp160 error driver, consider using a user mode DLL as part of the effort to reduce the amount of kernel development needed for your project, warning treated as error wdk.

The Many Types of Drivers

When you say you want a device driver, you should think about the type of driver you need. Windows supports a wide variety of devices, and as this support has grown, the environment for these drivers has diverged. Understanding warning treated as error wdk different driver types is important for a number of reasons:

·         The kernel programming interfaces can vary from type to type.

·         The rules for what the driver can do varies by type.

·         If you ask someone for help, they will need to know the type of driver you are working on.

Windows device drivers can be classified in many ways. For this paper, we will look at some of the major types. The 14001 error aion list is only one approach to classifying the many types of Windows drivers:

·         Legacy drivers. These drivers were the generic model for Windows NT. With the advent of Plug and Play on Windows 2000, these drivers became relegated to some limited categories. Their primary use these days is for kernel services, that is, pure software drivers that provide interfaces and services that need to execute in the kernel. This type of driver should not be used for a hardware device.

·         Windows (Plug and Play) drivers. When referring to a Windows driver, most people think of the current model of a driver with Plug and Play and power management. Windows Driver Model (WDM) drivers are a subset of these drivers. WDM was introduced to provide a common model for Plug and Play capabilities between Windows 98 (and later Windows ME) ati severe zero display service error and Windows 2000 and later versions of Windows.

·         File system drivers, warning treated as error wdk. File systems are in a special category of legacy drivers. These drivers keep track of files on a device or provide access to files across the network. File system drivers require additional headers and libraries beyond the standard tools, warning treated as error wdk. To create a file system driver, you need the Windows Installable File System Kit (IFS kit). See Resources at the end of this paper for availability of this kit.

·         Storage miniport drivers. Drivers for storage controllers such as SCSI and IDE have their own programming interface. This interface limits what a driver of this type can do. In addition, to provide backward compatibility with Windows 98, the kernel calls are unique. For many of these functions you will find an exact equivalent in WDM.

·         Network drivers. Like storage drivers, network drivers have their own programming interfaces. Unlike storage drivers, network drivers use standard Windows interfaces in many cases.

·         Printer drivers. This is a special category of drivers. Printer drivers run in user mode and do not conform to the programming model for other drivers.

·         Graphics drivers. Another special category of drivers, graphics drivers have their own rules and programming interface. Graphics drivers are some of the most complex projects in Windows.

·         Kernel streaming drivers. This is another unique category of driver. Like a number of the other categories, kernel streaming drivers have unique interfaces for programming. In addition, this is the only class of drivers typically programmed in C++.

·         Bus drivers. A bus driver enumerates devices on a bus and arbitrates access to the bus. Bus drivers are Plug and Play drivers and must support special requests beyond what other Windows drivers do.

·         Filter drivers. A filter driver layers above or below an existing driver to provide special services or change the behavior of a standard driver. A common example of a filter driver is a virus scanner that sits above the file system and checks files for viruses. Filter drivers typically follow the rules of the driver they are filtering.

What You Need for Driver Development

For driver development, you need a system for development and a system on which to debug your driver. Any reasonably sized desktop system can provide the hardware for development, warning treated as error wdk. The only special thing it must have is a free serial or IEEE 1394 port for the debugger. We will look at what you need for the test machine later in this paper. For now we will concentrate on the development system software.

The Windows Device Driver Kit (DDK) provides the build environment for developing a device driver for Windows. The DDK includes the approved build tools, compiler, and linker for creating a driver. The DDK also has thousands of pages of documentation about developing drivers and numerous sample drivers. In fact, the only software required to build a driver besides the DDK is a good editing tool.

A common misconception among driver developers is that you need the DDK named for the particular version of Windows you are targeting with your driver. In fact, when developing a driver, you need the latest DDK. This DDK has the latest tools, samples and documentation for developing drivers. At present, the kits are named for the latest operating system at the time of their release. This means that the Windows 2003 DDK is not just for creating drivers for that version of Windows, but is the best choice for creating drivers for all versions of Windows back to Windows 2000. For a guide to choosing the proper DDK, see Resources at the end of this paper.

In addition to the DDK, you need the WinDbg debugger. This debugger is part of the Debugging Tools for Windows and can be downloaded from Microsoft. Along with the debugger, you need the debugging symbols for the version of Windows you are testing. The warning treated as error wdk can warning treated as error wdk accessed either through the Microsoft symbol server or by downloading the symbol files. For availability of the debugger and symbols, see Resources warning treated as error wdk the end of this paper.

The final software purchase to consider is a code coverage tool. This tool can help in debugging and validate that you are testing your driver well. A full discussion of code coverage is provided later in this paper. See Resources at the end of this paper for companies that offer code coverage tools for Windows drivers.

Your Test Machine

Many developers and their managers are surprised that a separate test warning treated as error wdk is required, but there are many good reasons for this. Debugging an operating system is a challenge because the debugger affects its normal operation. To limit this impact, Windows requires a separate machine for use with the WinDbg debugger. A separate machine is needed for a number of other reasons:

·         Although your development machine typically will run a desktop version warning treated as error wdk Windows, for testing you need a variety of Windows versions, from server to desktop.

·         Crashes are likely in developing a driver. At best, a crash requires rebooting the system to fix the bug, and then rebooting the system again to install and run the driver, a slow process. At worst, you can corrupt the disk and have to rebuild your development system and recover your work.

On the test system, you should install multiple versions of Windows. Even if you are targeting a particular version of Windows, having the latest version will provide you with the best validation tools. One of the versions running on the test system should be the checked build of Windows. The checked build is one of the most powerful tools for debugging and testing your driver, warning treated as error wdk. Using the checked build to improve your drivers will be discussed later in this paper. The checked build is only available as part of Microsoft Developer Network (MSDN). Warning treated as error wdk Resources at the end of this paper for availability of the checked build and other developer resources on MSDN.

Now that you know the reasons for having a separate test system, be sure to get a good one:

·         At a minimum, it needs a serial or IEEE 1394 port for the debugger.

·         The most critical need is for a multiprocessor or at least a hyper-threaded system. You warning treated as error wdk debug multiprocessor issues without a multiprocessor machine. Now that even low-end systems support hyper-threading, this is a requirement.

·         Nowadays you should consider x86-64 support in your driver. Warning treated as error wdk multiprocessor x86-64 system makes an excellent test machine because it can support both 32-bit and 64-bit versions of Windows.

·         Having pluggable disks on your test system makes it easy to test against multiple versions of Windows, warning treated as error wdk.

·         If your device supports DMA, consider getting a test machine with more than 4GB of main memory. This amount might seem excessive, but it can be useful in tracking down problems in addressing extended memory. Finding such problems is difficult when your system does not have enough memory to test for them.

Why Find Bugs Early?

Driver debugging is difficult, so if you find and fix bugs early you can reduce development time. For many developers this is foreign to their current practice. The rest of this paper looks at the environment and tools for building Windows device drivers. Much of the discussion involves enabling as many checks as possible.

If you find a bug at compilation time, it takes seconds to fix the code and resubmit the module for compilation. If the bug goes undetected until found by the runtime verification tools, it can take at least five minutes just to rebuild and install the driver to fix the bug. If the bug is not found by the runtime checks, the five minutes stretches to hours or days to find the problem.

Once quality assurance (QA) gets involved, the costs escalate. QA has to find the bug, try to reproduce it, and put it in a bug report. Then management looks at the bug report and discusses it with the developer. Finally, the developer tries to reproduce the problem, and then debug it. Overall, this process can take person-days. The process takes even longer if a customer reports the bug, and error loading midas.dll delphi the effort may not increase as rapidly, the time until the customer has the bug fix still grows enormously.

Therefore, the little extra time it takes to enable the warning messages and fix the problems they report is inconsequential compared to the time it can save by finding even a single bug up front.

Installing the Software

Before you install the DDK and the debugger, you need to know several things:

·         Not all of the tools in the DDK work if the directory path for the DDK contains a space, warning treated as error wdk. So do not install the DDK at some location like “C:\Program Files\DDK”. If the path contains a space, you will not get a clean error message. Runtime error programm this application has requested, the build of your driver may fail in mysterious ways.

·         The DDK has tools for building drivers for a number of versions of Windows. Before you think you need only the tools for warning treated as error wdk particular version, consider the following guideline:

Build your driver for the earliest version of Windows you wish to support, but be sure to have the tools to build for the latest version for testing.

You should load the support files for the earliest version of Windows you support and for the latest version of Windows you plan to test. In many cases, the simplest approach is to load the support files for all versions of Windows.

Additionally, warning treated as error wdk, you should load the compiler and build tools for a 64-bit target as well as for the 32-bit systems most people need. Even if you do not support 64-bit systems now, using the 64-bit build tools can find bugs in your code.

Finally, you should load most of the samples. Even if you are specializing in a particular type of driver, the rest of the samples can be valuable in showing approaches to coding in the Windows kernel.

·         For the WinDbg debugger, you need either the 32-bit or the 64-bit version of the package, depending on your development system. This confuses some people. It is not the system you are testing but the system the debugger will be running on that determines which version you need.

·         Another choice to make is whether to use the Beta version or the released version of the debugger. The Beta versions have been so stable that most developers use the Beta to get the latest commands.

·         Finally, when you are actually installing the debugger, choose to install the debugger SDK. The SDK allows you to add your own useful tools to WinDbg.

This section explores the development environment needed to compile and link Windows device drivers. The actual process of compiling and linking the driver is controlled by the Build utility. The rest of this section provides an overview of the Build utility and the input file for the tool. At the end of document error codes section we will look at an approach to running Build from the Visual Studio Integrated Development Environment.

Build Utility

To create a driver in the Windows DDK you use the Build utility. This utility invokes the correct tools with the appropriate options to build your driver. The Build utility is a wrapper around the Microsoft NMAKE utility, so it handles issues like checking dependencies to ensure that the correct files are rebuilt after a change.

If you have not worked with Build before, you might want to try building one of the samples from the DDK:

1.   Copy the files under src\general\<sample>\sys (where <sample> is the particular sample’s name) to a test directory.

2.   From the Start menu of your computer, go to Programs PREfast to find out about PREfast.

You invoke PREfast as part of your Build utility command line, for example:

prefast /list build –cefbw

This line builds the driver, runs PREfast on the sources, and displays the defect log on the console. See the PREfast help file for a description of all of the command options.

Common PREfast Reports

PREfast has too many checks to describe in this document; the PREfast documentation warning treated as error wdk in the DDK describes all of the warnings. Some of the common warnings for driver writers are listed below along with notes about how to eliminate them.

1 - Using uninitialized memory <variable>.

This warning could be noise or it could indicate a real problem. In many cases, initializing the variable to a safe value at the beginning of the routine is the best solution. Just be sure not to mask a real problem with the initialization.

11 - Dereferencing NULL pointer <pointer>.

A 162 oki fatal error reason for this warning is that your driver has not tested to see whether a memory allocation returned NULL.

14 - Leaking memory <pointer>.

Typically, this warning is caused by not freeing memory allocated in a function, warning treated as error wdk. Note that if you have a function that allocates memory for your driver, PREfast may generate this error as noise.

8120–8124: Various reports about IRQL

PREfast can catch many cases where the Interrupt Request Level (IRQL) is incorrect for a function that is being called.

8128: An access to <field name> has been made directly; it should be made by <API name>

The DDK contains a number of structures with fields that should not be accessed directly. This is a error 23 pioneer/ bug for developers, and PREfast will catch many of these.

8134: The type of a pool tag should be integral, not a string or string pointer

The DDK allows you to tag memory, typically with a 4-character tag. A common mistake is to use a string for the tag.

8143: A dispatch routine that calls IoMarkIrpPending must also return STATUS_PENDING

This is a common mistake in drivers, which PREfast can catch for you.

Define DEPRECATE_DDK_FUNCTIONS

The DDK has evolved over the years. With the changes, warning treated as error wdk, a number warning treated as error wdk of functions are no longer recommended and supported. The WHQL Test Specifications define a set of functions that should no longer be used. The DDK provides a way to check for functions that should not be used by defining DEPRECATE_DDK_FUNCTIONS in sources as part of a C_DEFINES line. When DEPRECATE_DDK_FUNCTIONS is defined, using these functions generates errors at compile time.

However, DEPRECATE_DDK_FUNCTIONS does not flag every function in the DDK that should not be used. In some cases, these functions are correct for an older version of Windows but have been supplemented by a new routine. For this reason, you should check the DDK documentation when using warning treated as error wdk function for the first time or when a newer DDK becomes available, to see if you are using the best routine.

If you encounter a situation where a function is obsolete in later versions, you have two choices:

·         Typically, the function will be supported even after it is obsolete. One approach is to use the function for all versions of Windows, even though it is obsolete in some of them. The problem is that at some point the function might be removed and your driver would stop working.

·         A better approach is to use MmGetSystemRoutineAddress to check for the presence of the functions. Be sure to check for both the old and the new function, and fail with an error if neither is present. Your driver might last a long time, and both functions could be obsolete someday.

Using Preprocessor Tests and C_ASSERT

Many developers know about runtime assertions, but how many think about assertions at compile time? Many conditions are testable at compile time. As pointed out earlier in this paper, finding bugs early saves time.

You can approach runtime error 216 at 00002e58 time assertions in two ways. Either approach works; the important thing is to test at compile time.

C_ASSERT. One of the most overlooked capabilities in the DDK is the C_ASSERT macro. C_ASSERT checks assertions at compile-time. The expression in C_ASSERT must be determinable at compile time. The checks can include testing use of the sizeof operator on type declarations and use of compile-time constants. An assertion failure results in error C2118: negative subscript. A couple of common examples of C_ASSERT follow:

typedef union {

// Warning: Size of elements must be the same

    TYPE_1     element1;

    TYPE_2     element2; 

} UNION_1;

C_ASSERT ( sizeof(TYPE_1) == sizeof(TYPE_2) );

 

// Warning: Tables need the same number of entries

PCHAR table1[] = {“a”. . };

PCHAR table2[] = {“AA”. . };

C_ASSERT ( RTL_NUMBER_OF(table1) == RTL_NUMBER_OF(table2) );

 

Typically, drivers will have a comment noting that TYPE_1 and TYPE_2 must be the same size or that two arrays must have the same number of elements. These comments should not be easy for a developer to miss. Fail the compilation if the requirements are not met!

Conditional tests. One problem with compile-time asserts is that you get the negative subscript error but you get no useful data until you look at the code. So you might want to consider changing your C_ASSERTs that use only preprocessor data to do conditional tests. The compiler provides a #error statement that will generate an error. The error is reported as a message on the line following the #error, warning treated as error wdk. A couple of common examples are:

#define BLK_SHIFT    9

#define BLK_SIZE           512   // Must be 1 warning treated as error wdk BLK_SHIFT

#if !(BLK_SIZE = (1 << BLK_SHIFT))

#error !(BLK_SIZE == (1 << BLK_SHIFT))

#endif

 

// Need version 5 or module should be changed

#include “driver_include.h” 

#if !(DRIVER_INCLUDE_VERSION == DRIVER_INCLUDE_V5)

#error !(DDRIVER_INCLUDE_VERSION == DRIVER_INCLUDE_V5)

#endif

 

The advantage to this approach is that the error message you see matches the assertion so that you can avoid checking the code.

Build for 32-bit and 64-bit

All of the above approaches help you find bugs at compile time, but only for the targets your driver is compiled for. Compiling for both x86 and x64 can find problems in your code. In particular, compiling for 64-bit can find problems in three major areas:

·         Pointer issues. The most common problems migrating to 64-bit are pointer problems. These include everything from errors in pointer arithmetic to trying to store a pointer in a 32-bit value, or having a structure change in size because of the pointers it contains.

·         Inline assembly language. You should not warning treated as error wdk use inline assembly language (or assembly language at all) in your driver, but sometimes it happens. You might not even realize it; you might be using an include file or a piece of code from another developer who used assembly language. This is the time to catch and fix this code.

·         Compiler differences. A number of subtle differences in the compiler are described in the DDK under “Code Compatibility for x64”. Although it is not likely you will encounter these differences, it is possible.

Be aware that you cannot find all the compatibility problems for the driver without testing on both platforms. Compiling cleanly for both just means you have taken a good first step.

Run ChkINF Before You Install

ChkINF is a phone code sign error overlooked tool. Some developers view it as a WHQL test rather than a development tool. ChkINF is one of the best ways to get your driver installation to work the first time. No INF file is ready to use until ChkINF has validated it and all of the possible errors and warnings have been eliminated.

ChkINF resides in the \tools directory of the DDK. ChkINF is a PERL script, so you warning treated as error wdk need one of the Perl interpreters identified in the DDK documentation for the tool. The DDK also documents all of the command line arguments for the tool. The following is a common approach to running ChkINF.

ChkINF test.inf /B

 

The above validates test.inf warning treated as error wdk invokes the browser to display an HTML file with the results. The report consists of a warning treated as error wdk section with errors and warnings, and then an annotated copy of the INF file showing the problems. Fix all of the problems that the tool reports. Many of the warning messages point to problems that in some cases stop the driver from loading properly.

As with compile-time checking, taking advantage of the multitude of runtime checks can speed your driver development and make your driver more reliable. Runtime checking catches many problems that appear in drivers. Conversely, because runtime checking affects the performance of the system, these checks can hide some problems related to timing in drivers. So be sure to test your driver with runtime checks both on and off.

The tools listed here all should be used. The errors detected by the following techniques have much less overlap, unlike the some of the compile-time checking techniques discussed earlier. Additionally, very few of these tools show false positives. If the problem is reported, it is a real bug.

Some of these techniques cause the code of the driver to change. It is recommended that you follow these steps in debugging and checking your driver:

1.   Activate all of the checks described below for your driver, and work on warning treated as error wdk driver until it runs cleanly in this environment.

2.   Disable the various compile-time modifications and run the driver in your debugging environment again.

3.   Run your driver on the target system (that is, with no debugging enabled) to verify that it works and to use performance profiling against your driver.

Kernel Debuggers

Microsoft provides two debuggers for working with the Windows kernel:

·         KD is a command-line only debugger.

·         WinDbg provides the same command line as KD, but includes a graphical user interface.

The rest of this section discusses WinDbg. Most of the techniques are also applicable to KD.

Setting up the debugger

The debuggers can use two possible interconnects: serial p5ld2-se cmos checksum error bios or IEEE 1394, warning treated as error wdk. Both interconnects have special considerations.

Serial. Debugging over a serial link requires a null-modem cable to connect your test machine to your development system. On the test system, the serial port must be a legacy port, since the debugger directly manages the port. A non-legacy serial port that requires a device driver does not work for the system under test. These restrictions do not apply for the development system. To set up the link:

1.   Connect the null-modem cable to the desired serial ports on the two systems.

2.   Test the link with Hyperterminal:

Open a Hyperterminal session to the port on each system with the same baud rate.

Use a high baud rate to improve response time for the debugger.

Type in each Hyperterminal session and verify that coherent output appears on the other machine.

3.   Edit the boot.ini file on the test machine (described later) to add /debugport=comX /baudrate=y, where comX is the port you tested on the system, warning treated as error wdk, and y is the baud rate of your Hyperterminal test.

4.   Start WinDbg and choose Kernel Debug from the Warning treated as error wdk menu.

5.   Choose the Serial tab and set the baud rate and the port to the values used in the Hyperterminal test.

 

IEEE 1394. For debugging over IEEE 1394, you need a standard IEEE 1394 interface on each system and warning treated as error wdk cable to connect the ports. You cannot use the IEEE 1394 controller for anything but debugging on the test machine. Your systems must be running Windows XP or later to use IEEE 1394. To set up the link:

1.   Connect the IEEE 1394 cable to the ports on the two systems.

2.   Right click My Computer, choose Manage, and open the Device Manager on the test system.

3.   In the Device Manager, disable the IEEE 1394 controller completely by right-clicking the controller and choosing Properties. Set the controller to disabled.

4.   Edit the boot.ini file on the test machine (described later) to add /debugport=1394 /channel=y, where y is the channel you have chosen for the link.

5.   On the development system, repeat steps 2 and 3, warning treated as error wdk, but instead of disabling the IEEE 1394 controller, disable the IEEE 1394 network adapter.

6.   Start WinDbg and choose Kernel Debug from the File menu.

7.   Choose the IEEE 1394 tab and set the channel to the same value you used on the test system.

 

Editing boot.ini. To edit boot.ini, use the bootcfg command on XP and later systems. On Windows 2000, you will need to find boot.ini in the root of the boot drive, change its attributes from read-only to read-write, and then edit it with a plain text editor like Notepad. In either case, warning treated as error wdk, you need to duplicate the operating internal sofware error line to create  a separate entry with additional switches for debugging. Typically, the debugger line should be first so that it becomes the default boot for your test system. The Windows DDK describes how to edit the boot.ini file, warning treated as error wdk.

Finding symbols. After the debugger is connected, you also must specify where to find the symbols for the test system and the source code for your driver. As mentioned earlier in “What You Need for Driver Development,” you can get the symbols for the system in warning treated as error wdk multiple ways.

If possible, use the Microsoft symbol server. This requires a link to the Internet, but it eliminates most of the problems in finding the right symbols. Using the Microsoft symbol server is the only way to get the correct symbols for some hot-fixes and Beta versions of Windows. To set up the symbols, choose Symbol Warning treated as error wdk Path from the File menu of WinDbg, and then enter one or more directory paths separated by semicolons. For example:

SRV*e:\SymStore*http://msdl.microsoft.com/download/symbols;e:\development\mydriver\objchk_wnet_x86\i386

 

This path instructs WinDbg to get symbols from the symbol server and cache them in e:\SymStore and, if the symbols are not found, to use the checked build directory for my driver. 

If you have problems getting the symbols, use the command !sym noisy to see the what is happening. Set up the source directories in a similar manner; choose Source File Path from the File menu of WinDbg and then enter one or more directory paths separated by semicolons.

Using Driver Mapping

One very powerful capability of the debugger is mapping driver files. The debugger can intercept the load of your driver on the test system and load the driver from the warning treated as error wdk system to the test machine. This eliminates the all-too-common mistake of forgetting to put the new driver onto the test system.

The simplest way to set this up is to open the System Control Panel, choose the Advanced tab and click the Environment Variables button. Under User Variables, select New, then enter _NT_KD_FILES for the name of the variable name and a full path to a map file you will create. Next, create the map file you specified in the environment variable with contents in the format:

map
\Systemroot\system32\drivers\mydriver.sys
e:\development\mydriver\objchk_wnet_x86\i386\mydriver.sys

The second line must match the path to the file in the test system's registry. The third line is a pointer to the driver on the development system. Note that using the path to the build directory guarantees that you have the latest driver. You can repeat these three lines for additional drivers. For more information about this technique, see “Mapping Driver Files” in the debugger documentation.

WinDBG Display Windows

The WinDbg user interface provides a number of display windows. The following lists the commonly used windows and tricks for using them. Note that windows that display data based on the current scope show valid information only when the test system has stopped:

·         Command window, warning treated as error wdk. This window displays diagnostics and information from commands you enter. It is possible to search this window using the Find command from Edit menu, which can help when the window contains lots of data. In addition, you can log the data from the command window to a file by using the Open/Close Log File command from the Edit menu.

·         Sources windows. These windows display the source code for the driver. First, be sure to set your tab stops to match your editor by using Options from the View menu. You can quickly set or clear a breakpoint by setting the cursor to the line you are interested in, then pressing F9 or the breakpoint toolbar button.

·         Calls window. This window shows the call stack on the test machine. Double-clicking an entry in the call stack will raise_application_error syntax oracle cause the source window to display the location of the call and the locals windows to show the local variables for the call location.

·         Locals window. This window shows local variables for the current scope. You can warning treated as error wdk the value of a local variable by editing the Value field. Variables are displayed based on their types. Setting the Typecast button shows the type of each variable. The type in the column can be edited to force the item to warning treated as error wdk displayed differently.

·         Watch window. This window shows variables for the current scope including global variables, warning treated as error wdk. Note that, for the global variable to be displayed, it must be accessible from the warning treated as error wdk scope. The watch window behaves like the locals window.

Useful Commands

The debuggers have three general types of commands:

·         Regular commands. These commands start with a letter and are the core functionality for debugging a driver.

·         Dot commands. These commands start with a period and control the operation of the debugger.

·         Debugger extensions. These are custom commands that have been created for the debugger. All extension commands start with an exclamation point. Microsoft provides many of these to help you debug drivers. In addition, you can create your own extensions specific for your driver debugging requirements.

The following list contains some useful debugger commands for debugging drivers. Note that this list does not contain the common commands such as setting a breakpoint or displaying data. Those commands are expected and easy to find. This list provides commands you might not find easily.

!error value

This command displays data about the error code specified by value.

!analyze –v

This command displays abundant information about a bug check. Whenever the system crashes, you need to issue this command to help make sense of warning treated as error wdk problem. Get to know this command!

.reboot

This command reboots your test system after a crash and the analysis.

lm

This command lists the loaded modules (drivers) in the system. This list can tell you if your driver was loaded on the test machine.

!devnode 0 1

This command displays all the device nodes. When you cannot figure out why your driver did not start, this command is for you.

!irp addr

This command displays the I/O request packet at the location specified by addr.

!poolfind tag

This command displays memory allocated with the given tag (see “Pool Tagging” later in this paper).

.reload [/u] [module]

This command reloads the symbols for the specified module or for all modules if none is specified by name. The /u option unloads the symbols, which is required before rebuilding the driver. If the debugger has the symbols open the linker cannot write a new file and the build fails.

This is only a small subset of the commands; see the debugger documentation for more.

Checked Build of Windows

The checked build of Windows is one of the most powerful diagnostic tools available to a driver developer. Some people confuse the checked build of their driver with the checked build of Windows. The checked build of Windows is a version of the operating system that was built with checking turned on, in the same way you can build your driver with the checked build. A wise developer does not ship a driver and support code unless the product runs cleanly on the checked build of Windows. The checked build provides a number of useful features for the developer:

·         Extensive assertions, particularly to check parameters to functions and the internal state of Windows.

·         Significant diagnostic output that can be enabled for specific features.

·         Most optimizations turned off. This makes it easier to debug into a call to the kernel and changes the timing of routines, which can help find timing-dependent problems in your driver.

Assertions

The checked build uses the same ASSERT macro that driver writers use. The macro reports into the debugger the expression that failed and the file and line number at which the failed expression appears in the warning treated as error wdk code. The following is an example report:

*** Assertion failed: Irp->IoStatus.Status != 0xffffffff
***   Source File: D:\nt\private\ntos\io\iosubs.c, line 3305

0:Break, Ignore, Terminate Process or Terminate Thread (bipt)? b
0:Execute '!cxr BD94B918' to dump context
Break instruction exception - code 80000003 (first chance)
ntkrnlmp!DbgBreakPoint:
804a3ce4 cc               int     3

In this example, the user entered a “b” to stop at a breakpoint. This allows you to check the stack and see where your driver is calling into the kernel. This is the likely location of the problem.

Thousands of ASSERT statements in Windows are active in the checked build. In general, they fall into three major categories:

·         Parameter checks. These can be simple range checks for a value passed to a kernel routine. Another parameter check uses the type data that many kernel data structures contain to verify that linux end_request i/o error, dev sd pointer to the correct type of data is passed.

·         Timing actions flash backup critical error 84 recommended limits. These useful ASSERT statements check the timing of actions for which Microsoft has recommended limits. For instance, holding a spin lock more than the recommended time triggers an assertion failure.

·         Checks on internal data structures. These checks verify internal Windows data structures. These failures are tough to c1 c2 errors, because the assertion is rarely triggered until long after the actual error.

Diagnostic Output

The checked build of Windows provides support for diagnostic output to the debugger. The Knowledge Base article "How to: Enable Verbose Debug Tracing in Various Drivers and Subsystems" shows how to get data that will help diagnose many problems for a few of the possible categories of output. Look up DPFLTR_TYPE in wdm.h or ntddk.h for all of the categories, warning treated as error wdk. See Resources at the end of this paper for a link to this KB article.

Most of this output must be enabled. For example:

ed NT!Kd_NTOSPNP_Mask warning treated as error wdk

ed NT!Kd_PNPMGR_Mask 0xFFFFFFFF

 

These debugger commands enable kernel and user mode Plug and Play manager diagnostics, warning treated as error wdk. Enabling these diagnostics can help track down many driver problems.

Installation of the Checked Build

You can install the checked build of Windows in either of two ways:

·         Install parts of the build on a standard Windows system.

·         Install the complete checked build in its own disk partition.

 

Each installation has challenges and advantages.

The partial installation is documented in the DDK under Installing Just the Checked Operating System and HAL. This technique installs just the checked versions of the kernel and the HAL with the free versions of other system components. This has the advantage of running much faster than the full checked build, but limits the checks and diagnostics. In particular, warning treated as error wdk of the subsystem outputs described in the KB article about verbose debug tracing require the drivers from the checked build. Additionally, many of the drivers supplied with the checked build have assertions that can help you find problems in your driver.

The full installation requires its own disk partition. The full checked build of Windows is installed like any other version of the operating system. The full checked build runs significantly slower, but provides many more assertions and additional diagnostic output. One problem many people face installing the full checked build is that it may assert during installation! The reason is that a driver in the distribution has a bug. If you encounter this assertion, warning treated as error wdk, you need to install the warning treated as error wdk build with the debugger running, so you can ignore the assertion and continue. If you do encounter this assertion, you must always boot the checked build with the debugger running.

When you install a Windows Server 2003 system, you can press F8 as installation first starts. Press F8 when you are prompted for F6. This will activate the debugger error code ami bios p2.70 the COM2 port with a baud rate of 19200.

If you are not installing Windows Server 2003, or if you warning treated as error wdk want a different setup for the debugger, you must install the system from a running version of Windows. Invoke the installation program with the /noreboot option. Warning treated as error wdk the GUI installation program finishes, find the temp warning treated as error wdk where the files were installed (usually C:\ ) and edit the file txtsetup.sif. In the file, find the line:

OsLoadOptions = "/fastdetect /noguiboot /nodebug"

Edit this line, removing the /nodebug option and adding the debugger options you would use in the boot.ini file. When you reboot to continue the installation, the message “Starting Windows” appears in the white line at the bottom of the screen, and the system starts in the debugger.

Driver Verifier

Driver Verifier, warning treated as error wdk, like the checked build of Windows, is a powerful tool for finding driver problems. Whereas the checked build is passive, only adding checks to the normal operation of the kernel, Driver Verifier is an active checking tool that can modify the environment to test a driver. Additionally, Driver Verifier provides monitoring capabilities for the warning treated as error wdk drivers under its control. Driver Verifier ships as part of the Windows operating system and can check the drivers you choose.

Driver Verifier is controlled by the Verifier utility. This utility has too many options to explain in detail in this paper. All of the options are documented in the DDK under Driver Verifier Manager (verifier.exe). For most drivers you should always enable the following options:

·         Automatic checks. After effects error ae opengl 5065 0 standard checks always apply to any driver being verified and cannot be disabled.

·         Special memory pool, warning treated as error wdk. This option allocates memory from a special pool to check for buffer overruns and related problems.

·         Forcing IRQL checking. This option checks memory references and finds attempts to reference memory at the wrong IRQL.

·         Memory pool tracking. This option tracks your driver's memory usage and insures that the driver frees all memory.

·         I/O Verification. This option monitors your driver's handling of I/O requests.

·         DMA Verification. This option monitors your driver's handling of DMA operations.

·         Deadlock detection. This option finds many potential deadlocks by making sure your driver uses a consistent locking model.

 

Other options are available for specific types of drivers. The important thing is to enable Driver Verifier for your driver before you ever load your driver. This way, you start catching bugs early in the development process.

Driver Verifier also maintains a number of counters that you can monitor. These counters provide information about memory allocation and spin locks. Both the Verifier utility and the !verifier debugger extension can display these counters.

Driver Verifier has one option you should not enable when you first test your driver. This option is Low Resource Simulation,which injects failures into your driver’s requests for resources. Testing with this option is important because your driver should not crash the system if it cannot allocate a resource such as memory. However, this option should be used for testing after your driver is running well using the techniques described elsewhere in this paper.

Call Usage Verifier

Call Usage Verifier (CUV) adds checks beyond those of the previously discussed techniques. Unlike the previous techniques, using CUV requires you to modify your sources file and recompile your driver. To modify the sources file add the following line:

VERIFIER_DDK_EXTENSIONS=1

CUV requires rebuilding the driver because it replaces calls to routines and macros in the DDK headers with instrumented versions for checking.

CUV supports four types of checking:

·         Initialization checks. These typically verify that your driver initialized a kernel type appropriately before using it.

·         Consistency checks. These verify that your driver used the kernel functions in a consistent manner on a data structure.

·         Paged memory checks. These validate that your driver does not call a routine that expects non-paged memory with paged memory.

·         IRP stack checks, warning treated as error wdk. These validate the driver’s use of the I/O Maxwell render 2 multi sub error Packet (IRP) stack.

CUV works only for WDM and legacy drivers. CUV produces a false report on rare occasions, so check its results carefully. When your warning treated as error wdk driver starts, CUV reports that the driver was built with CUV  When an error occurs, CUV reports into the debugger; for example:

DDK+ Driver Error: Calling InitializeSpinLock(.) at File
 c:\projects\linklist.c, Line 225
          The Spin lock specified as parameter 1 [0x811abe78]
          has been previously initialized and used as
          a Listhead for Interlocked operations by this driver.
Break, Ignore, Zap, Remove, Disable all, H for help (bizrdh)? 

Pool Tagging

Pool tagging allows your driver to associate a warning treated as error wdk alphanumeric tag with each block of memory that you allocate. The usual approach for using pool tagging is to create a unique tag for each class of data structure you allocate. Be aware that none of the DDK tools check to ensure that the tag you create is unique for the system. You can see the tags Windows knows about by viewing the file PoolTag.txt. This file is in the DDK under \tools\other\i386 and is shipped with the debugger in the directory \triage. Try to make your tags distinct from common tags such as irp or ddk.

The actual tagging of memory is enabled according to some interesting rules. Warning treated as error wdk is never enabled if the Driver Verifier “special pool” option is being used. Windows 2000 and Windows XP enable tagging by default only for the checked build of Windows. For the free build, you can enable tagging using the command line gflags /r +ptg. Tagging is always enabled for all builds of Windows Server 2003.

These tags and their allocations can be viewed in three ways:

·         In the debugger

·         With the Poolmon utility supplied with the system

·         With the Pooltag utility supplied with the DDK.

Using pool tagging allows you to track the memory allocations of your driver for specific data structures. Tracking is especially valuable when Driver Verifier reports that you have not freed all the memory you allocated when your driver unloads. Looking at the tags from the memory being reported makes it easier to determine what you forgot to clean up.

Starting with Windows XP, you can not only allocate memory with unique tags, you can supply that tag when you free memory using ExFreePoolWithTag. If you free memory with ExFreePoolWithTag, warning treated as error wdk, the tag supplied by the call is checked against the tag of the memory you are freeing. Mismatched tags cause the system to bugcheck.

Using allocation and free with tags provides type checking for memory.   Verifying that the memory being freed is of the type intended can catch errors created by freeing the wrong memory.  Bugs from incorrect freeing of memory can be some of the hardest to find. 

Normally the memory can still be freed without specifying the tag.  Drivers can require the use of ExFreePoolWithTag by or’ing the tag with the PROTECTED_POOL flag. If your driver is for Windows XP and later, you should use ExFreePoolWithTag with PROTECTED_POOLtags except when you allocate memory that the system will free; in those cases do not use a PROTECTED_POOLtag.

Code Coverage

Code coverage is a powerful tool for checking warning treated as error wdk parts of your driver are executed during testing. The simplest form of code coverage is line coverage, which reports which lines in your program warning treated as error wdk executed. More advanced tools show you which paths in a conditional statement have been exercised. The more of your code that is executed during testing, the more likely you are to find errors.

The best way to check code coverage is to run all your tests for a driver with code coverage enabled, and then see how much of your code was exercised. Do not be surprised if you run code coverage with all your tests and find that roughly two thirds of your driver code is not being executed. Increasing code coverage involves a number of approaches:

·         Check that your tests make all valid requests. With code coverage, you see what code is actually run. It is easy to see valid requests to your driver that are never tested. Most test suites need improvements to increase coverage.

·         Check that your tests supply all the incorrect input. Just as with valid requests, you are likely to find that your test code does not try all of the possible incorrect requests for your driver. When you are reviewing this code, be sure to check whether your driver handles all incorrect requests properly.

·         Use low resource simulation in Driver Verifier. Another way to increase coverage is to use the low resource simulation option in Driver Verifier to exercise failure paths in the driver.

·         Consider adding fault injection to your driver. Even after this work, you are likely to find a lot of code that is not exercised. Typical examples are failures in your hardware that are hard to create, or similar “impossible conditions.” For these you might need to create a macro to inject faults.

A warning treated as error wdk approach is a macro that, for the debug version of your driver, calls a function that run-time error 429 balans randomly return TRUE. In the production version of your driver, the macro always returns FALSE. You then add code to your driver that, when the macro is true, modifies the behavior of the driver to execute the failure condition. For example:

devStatus = READ_REGISTER_ULONG( statusRegister );

devStatus = FaultInject ? DEV_ERROR_FLAG : 0;

if ( devStatus & DEV_ERROR_FLAG ) …

 

Adding the warning treated as error wdk line makes it possible to simulate the situation where the device returns the error flag and thus exercises the recovery code controlled by the third line.

Even after you do all of this, you still will not get complete coverage. The goal of code coverage should be for you to see that all of the reasonable cases are being tested. The code that is not exercised should be checked thoroughly to find problems.

Performance Profiling

KernRate is warning treated as error wdk often-overlooked tool in the DDK. This tool is primarily a profiler that periodically samples the instruction pointer. KernRate also collects statistics on a number of performance-related items in the kernel such as those in the performance monitor (Sysmon). Traditionally, this data is dumped to a text file, and the developer has to read through lots of  text. Microsoft has added a new tool called KrView that uses Microsoft Excel to create a workbook to display the data. You can download a package that contains both KrView and the latest version of KernRate, warning treated as error wdk. See Resources at the end of this paper for availability of KrView and KernRate.

If you have not done performance profiling before, keep in warning treated as error wdk mind that getting good data takes time. For good solid numbers, consider running a profile for hours. In addition, your numbers are worthless unless you are exercising your driver, so you need a good test that can exercise your driver for a long time. Besides time, the profile will take a lot of space; sample profilers look at the instruction pointer and put the data into a “bucket” that indicates the code being executed. KernRate allows you to adjust the size of the buckets, The smaller the bucket, the more accurate the sample.

You should use performance profiling with your driver in two ways:

·         First, run a performance profile of the whole system while exercising your driver. Even with a significant load on your driver, the percentage of time spent in your driver should be relatively low.

·         Second, run a performance profile on your driver alone. When you analyze the data from this profile, look for hot spots where your driver takes a lot of time. At each hot spot, look for either a problem with the code or a better algorithm that  reduces the load. Many hot spots will be valid, but checking them can find bugs.

Kernel Logging

As part of Event Tracing for Windows (ETW), recent kernels can log a number of actions by the system. We will discuss considerations for ETW in your driver later in this paper, but for now let us look at the data logged by the system. The simplest way to log this data is with the TraceView utility provided in the DDK tools directory. TraceView can log nine different categories of data, including:

·         Process creation and termination

·         Thread creation and termination

·         File I/O

·         Disk I/O

·         Image file (executables and DLL) load and unload

·         Registry accesses

Enabling kernel logging while debugging your driver can help in finding bugs.

Installation Logging

Just as you used ChkINF to verify your INF file before installation, you should enable SetupAPI logging during your driver installation. Driver installations perform a number of actions. Logging provides a way to validate that your installation is correct. If your driver installation fails, the log is available to show you what happened. Consider setting the following  registry entry(or creating it if needed) to the value 0x3000FFFF just before your installation of your device:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurentVersion\Setup

This setting enables verbose logging so that you see everything that happens during your device installation. Be sure to restore the value at the end of the installation because verbose logging produces a lot of output, which slows down the system.

The setup log resides in %systemroot%\setupapi.log. Take a look through this file to see what your device installation did. This log contains a lot of data. An excellent reference for understanding it is the paper "Troubleshooting Device Installation with the SetupAPI Log File." See Resources at the end of this paper for a link.

Miscellaneous Tools

Windows and the DDK include several other miscellaneous tools that many developers overlook. In addition to the tools listed below, many third-party tools are also available to driver writers:

·         DriverQuery. DriverQuery is a command-line tool that ships with Windows. This ecdis interpretation errors lists all the drivers that are active on the system. Using the /v option with this tool expands the data to include the size of the driver, the path to the driver, and other information. Applying the /si option provides data about whether the driver is signed and what INF file installed warning treated as error wdk the driver on the system. Use DriverQuery to see that your driver is loaded, and to verify that the INF file is what you think it is.

·         DeviceTree. DeviceTree is a GUI-based tool that displays data about drivers and devices. In the Driver view, the tool lists all of the drivers, giving data on the driver, the calls it supports, and all of the devices it has created. Under the driver, DeviceTree displays data about each device, including the flags on the device object and its reference count. In the Plug and Play view, the device data appears in a tree that shows the relationships between devices. DeviceTree can help identify a number of problems when debugging your driver.

·         DevCon. DevCon is a command-line tool that provides all of the capabilities of the Windows Device Manager. In addition, it provides many of the capabilities of the DriverQuery and DeviceTree tools. DevCon is useful for creating scripts to exercise Plug and Play control of your device. The source code warning treated as error wdk DevCon is supplied in the DDK in src\setup\devcon.  Use this code as a guide to writing your own driver tools.

·         RegEdt32. Installing drivers modifies the registry. Many drivers use data from the registry to control operation. RegEdt32 is the tool to use to inspect and edit the registry, including the access control for registry keys.

Diagnostics is often overlooked but is critical to a high-quality Windows device driver. It ati2mtag error dvd_ov the only area of coding that we will cover, warning treated as error wdk.

It is important to have a standard diagnostics model for all the drivers your company produces. The model should include common levels and flags to control the diagnostics. The model should also warning treated as error wdk a standard presentation format for diagnostics. This presentation format should consider everything from standard naming for event log entries and performance monitoring counters to the display of data for assertions, debug prints, casino server error 0004 WPP tracing.

Assertions

We have already encountered assertions with the checked build of Windows. The use of assertions is a powerful debugging technique. You should be aggressive in using them, warning treated as error wdk. The assert statements both provide debugging capabilities and document the assumptions your code makes.

The DDK provides a couple of macros, ASSERT and ASSERTMSG, so that your driver can assert when it is built in the checked build environment:

ASSERT ( expression )

ASSERTMSG ( message, warning treated as error wdk, expression )

In each of these macros, the expression is checked and, if it is false, the assertion is fired in the debugger. ASSERTMSG allows an additional message to be printed as part of the diagnostics. When you use the assert macros, keep in mind that, in Windows 2000, the macros did not return a value. In later systems, these macros return the value of the expression. These macros produce code only in a checked build of your driver. They have no impact on your production code.

So when should you use assertions? The general answer is whenever you enter or exit a major block of code. In particular:

·         On entry to and exit from a module of code with static data. While many developers do not think of modules in C programming, a file with static data is a module. On entering any non-static function, the static data of the module should be validated with asserts. On exit from a non-static function, the assertions on the static data should be performed warning treated as error wdk verify that the module did not corrupt the data.

·         On entry to and exit from a procedure. The common use of assertions is to check the validity of input parameters to a function. What many developers forget is that you need to validate the data you touch on the exit of your function.

·         On entry to and exit from a loop. Just as you perform checks around procedures, it might be appropriate to do this for a loop. Checking pre-loop and post-loop conditions can help to localize problems.

·         Before data is referenced by a pointer or before using a global variable. Many developers check a pointer before referencing it, but you should also validate the data the pointer points to. In the same manner, the contents of global variables should be validated before being used.

Given the places you need to assert, what should your checks entail? Probably more than you think. Some common warning treated as error wdk should be:

·         Pointers are valid. A common assertion check is that a pointer is not equal to NULL. However, do you ever do more? For instance, many Windows kernel structures have error bios checksum type field. Do you validate the type? For example:

  ASSERTMSG ( “Invalid IRP pointer”,

            irp != NULL && irp->Type == IO_TYPE_IRP)

 

You can go further and check whether the memory pointed to is writeable, for instance. The point is not to stop with the simple check for NULL.

·         A variable in is range. Warning treated as error wdk common check is warning treated as error wdk a given value is in range. The goal here is to be sure to validate all of the variables you get from outside your code.

·         Doubly linked list is consistent. Before you think this is excessive, consider the following assertion:

  ASSERTMSG ( “Corrupted List”,

            listPtr != NULL && listPtr->Flink != NULL &&

            listPtr->Flink->Blink == ListPtr )

 

The additional checks can catch list corruption. Adding the assertions will not find errors as quickly as validating every element of the list, but it is simpler, with little overhead.

·         String variables are valid. Many Windows strings are counted strings, in which the string is designated by a structure with a buffer pointer, length, and maximum length. When you validate a string variable, consider:

  ASSERTMSG ( “Invalid Counted String”, string != NULL &&

            string->MaxLength > string->Length &&

            string != NULL ?

                  (string->Length != 0 ) : TRUE ))

 

The additional checks make sure you are not surprised with an invalid string.

·         IRQL is valid for a function. This is a driver-specific check, warning treated as error wdk an important one, warning treated as error wdk. Many kernel service routines work at a limited range of IRQL. Therefore, you should ensure that your functions that call these routines check for correct IRQL.

Developers make two common mistakes when using assertions:

·         Side effects that modify driver behavior. First, be sure that your assertions warning treated as error wdk any other checking code do not produce side effects that modify the behavior of your driver. It is easy to fall into the trap of writing code like the following:

ASSERT ( --CurrentCount > 0 )

This will work fine until you move to the free build and find that your counter is not being decremented.

·         Confusing assertions with error checks. The second mistake is confusing assertions with error checks. Don’t use an assertion for a condition that might occur during normal operation, such as the following:

p = ExAllocatePoolWithTag ( NonPagedPool, BLK_SIZE,
BLK_TAG );
ASSERT ( p != NULL )

This usage is incorrect, because in normal operation your allocation might fail for lack of memory.

You can java.lang.noclassdeffounderror could not initialize class sun.awt.x11graphicsenvironment many more validation checks in your code. Remember that you can make these validations complex, because these assertions only exist in the checked build of your driver. In fact, consider creating functions for validating complex data structures, and place these functions in conditional code so that they exist only in the checked build of your driver. This is another technique that can help you find bugs early.

Debug Print Statements

Debug print statements are the most common diagnostic in most drivers. The DDK describes four debug print statements:

KdPrint (format. . );

KdPrintEx (componentId,level,format. . );

DbgPrint (format. );

DbgPrintEx (componentId,level,format. . );

 

All of these calls use the same format and following arguments as the printf statement. The first two calls are macros that produce code only in the checked build of your driver. The last two calls are the underlying calls that are always active. For the Ex versions of these calls, use the componentId and level to allow filtering of the debug output.

Your driver should not use the Dbg versions of these calls unless you are creating your own conditional macro for printing. Using debug print statements incurs significant overhead, and they warning treated as error wdk should not appear in a production driver.

Even in the checked version of your driver, having all of the debug prints active can make your driver painfully slow to use, so consider creating your own macro to allow conditional debug prints. Before you decide to hair and fur error only DbgPrintEx, you should be aware that a limited number of component IDs are available for driver developers, so it is better to create your own macro. For example:

#if DBG

#define MyDriverPrint ( level, flag, warning treated as error wdk, args ) \

   if ( MyDriverLeven >= level && \

          (flag) & MyDriverFlags ) \

     {   \

      DbgPrint args;             \

   }

#else

   #define MyDriverPrint ( flag, level, args )

#endif

 

This creates a macro that prints only for the checked build of the driver. The debug flags and level are global variables that your driver can initialize to control its output. Using this macro matches the model of WPP tracing which is discussed later in this paper along with the advantages of keeping a constant model.

Normally, debug print data is monitored in WinDbg. Two tools are available to monitor debug messages on the system with your driver:

·         DebugMon

·         DebugView

See Resources at the end of this paper for availability of these tools.

Both of these tools provide a graphical user interface to monitor debug messages on a local system or over the network. Do not assume that these tools and debug prints are enough to debug a driver. As discussed in this paper, many verification tools are available, and you need the debugger to take full advantage of these tools.

Having looked at the debug print calls, what about the data they print? Consider some simple rules for your output:

·         Use text whenever possible, warning treated as error wdk. For example, it is much easier to read "IRP_MJ_CLOSE" than to see 0x2 and remember boot volume unmountable error that 0x2 indicates a close request. Several drivers in the DDK samples have example code for printing IRP major functions.

·         Print information that describes a data structure, not just a pointer to the structure. For instance, print the major function of the IRP and the pointer to the IRP. Having the function code makes it easier to read and act on the data.

·         Print the information in a standard format. All too often, debug statements vary widely, warning treated as error wdk, making the output hard to use while debugging.

·         Consider providing a call trace, showing the entry to and exit from functions in your driver. A good approach is to use an indent level so that nested calls appear indented from their callers.

·         Consider adding more data to your debug print macro. Having a standard summary line that shows the source file and line, warning treated as error wdk, the currently executing thread, and the IRQL can help debugging.

As previously noted, the format string follows the conventions of printf, warning treated as error wdk. Consider the following tricks warning treated as error wdk rules for format strings:

·         If you are printing a pointer, use %p. This will work correctly on both 32-bit and 64-bit variables.

·         If you are printing a counted string, warning treated as error wdk, use %Z (ANSI) or %wZ (Unicode). This will print the string correctly even if it is not null-terminated.

·         If you are trying to print a Unicode value, remember that the driver must be running at an IRQL less than DISPATCH_LEVEL.

·         When writing your debug statements, realize that all of these functions have a limit of 512 bytes per call.

WPP Software Tracing

WPP software tracing provides a low-overhead mechanism for logging data. WPP software tracing creates a binary data log that is post-processed into a set of text messages. A significant advantage of using WPP is that the data collected from your driver is not readable by your customers. This capability allows you to use messages that might otherwise be embarrassing such as “I guess the hardware can return this code after all!”

The simplest approach to using WPP tracing is to add the following line to the end of the SOURCES file:

RUN_WPP=$(SOURCES) -km

You then need to set up some definitions and include files in your driver. Finally, you add statements of the form:

DoTraceMessage(IN TraceFlag, IN Format. .)

Format in this statement is the same as that for debug prints. DoTraceMessage is the default name of the trace statement. The WPP tracing tools allow you to define your own name, so for instance, you can convert debug print statements into trace statements. It is also possible to force WPP tracing output as debug print statements. To make WPP tracing also appear as debug print statements, use:

#define WPP_DEBUG(args) DbgPrint args;

You might not want to use this, however, because WPP tracing supports a number of format strings that are not supported in debug prints. Some of the interesting ones are:

%!FILE!

Displays the name of the source file.

%!FLAGS!

Displays the value of the trace flags.

%!LEVEL!

Displays the name of the trace level.

%!LINE!

Displays the line number of the line

%!bool!

Displays TRUE or FALSE.

%!irql!

Displays the name of the current IRQL.

%!sid!

Takes a pointer to a Security Identifier (SID) and displays the SID.

%!SRB!

Takes a pointer to SCSI request warning treated as error wdk (SRB) and displays the SRB.

%!SENSEDATA!

Takes a pointer to SCSI SENSE_DATA and displays the data.

%!GUID!

Take a pointer to a GUID and displays the GUID.

%!NTSTATUS!

Takes a status value and displays the string associated with a given status code.

 

Additional formats plus the ability to display enumerations are described in the Software Tracing FAQ section of the DDK.

WPP tracing presents some challenges to the developer in designing output. In particular, WPP tracing achieves lower overhead by keeping data as binary. Some of the guidelines for debug print statements do not apply for WPP tracing. The recommendation to convert constants to text is an example. Putting a binary 0x2 in the message takes one instruction, whereas “IRP_MJ_CLOSE” requires a string copy. Also, including the summary data is unnecessary, because WPP tracing already includes the file and line data.

WPP tracing provides diagnostic support for its actions. To enable this support add the option –v4 to the RUN_WPP line in the SOURCES file. To display this data, define WppDebug to be a debug print statement. For example:

#define WppDebug(_level_,_msg_) KdPrint (_msg_)

This causes the state transitions of WPP tracing to appear as debug prints. This debug output allows you to monitor the operation of WPP tracing and see that your requests to enable and disable tracing are correct. 

Now that we have talked about WPP tracing, you should be aware of a number of tools that are available for controlling and displaying tracing. The following are the tools:

Logmon

This tool controls tracing (such as stopping and starting). The tool ships with Windows XP and later systems.

Tracelog

This tool controls tracing. The tool ships with the DDK, SDK and symbols. The source for the tool is available in the SDK so you can write a custom tool if desired.

TraceFmt

This tool translates a trace log to a readable format. The tool ships with the DDK, SDK, and symbols.

TracePdb

This tool extracts the trace format data from a symbol file, warning treated as error wdk. The tool ships with the DDK, SDK, and symbols, warning treated as error wdk.

Traceview

This is a general tool for control and display of trace data. The tool is shipped in the tools directory of the DDK.

WmiTrace extensions

The debuggers have an extension to provide control and display of trace data.

 

WPP tracing is a powerful tool that should be used in every shipping device driver. The low performance impact of tracing provides a developer with a way to get detailed diagnostics from a customer without requiring a modified driver.

Event Log

So far, this paper has discussed diagnostic data designed for the developer. It is just as important for your users to know what is going on. The best way to provide this information is through the System Event Log.

An event log entry is a block of binary data that is interpreted by the event viewer. The actual size of an event log entry is small. Besides the fixed headers, warning treated as error wdk, an entry’s data is less than 256 bytes. The event viewer uses a message catalog to translate the error code in the entry c_ error code 14001 into a locale-specific text message. The text message can include strings that are inserted from the log entry data. warning treated as error wdk writing to the event log, think about the following:

·         The size of the event log error 124 statement part too large limited. The administrator of the system determines its size and the rules for overwriting log entries. Given the limited size, make sure the messages you write to the event log are there for a reason. Administrators are not interested that your driver started and stopped correctly; when they check the log, they are looking for problems.

·         APIs warning treated as error wdk for reading the event log, and many system administrators have tools that scan for particular errors. Make your driver’s error codes unique and use a separate code for each error. Also, create only one event per error; an event log entry is not a print statement where multiple lines are fine.

·         Finally, do not use the lazy approach of creating a single global error message, and inserting  text about the actual error from a string.

The limited size of the event log entry influences your design of entries. Unlike internal diagnostics where text is recommended, event log entries are sometimes better with binary data. Use the unique error code and the text message to give your customer data about decoding the binary.

A final consideration when using the event log is where the message catalog will reside. The message catalog is compiled into a resource that is placed in an executable file such as the driver or a DLL. The examples in the DDK show how to include the catalog in your driver. This approach has the limitation that adding or changing messages requires that you rebuild the driver, warning treated as error wdk. The other approach is to put the messages into a dummy DLL, which allows you to update the messages without impacting the driver. This makes it possible to distribute the dummy DLL and the message catalog file so that the messages can be internationalized without driver source code.

Performance Monitoring

A good driver provides feedback to the user through the performance monitor (sysmon). For common classes of devices, drivers should provide the standard data. Even if your driver does not fit a common category; it should provide monitoring information.

The simplest way to provide the performance monitoring data is through Windows Management Instrumentation (WMI). WMI is a powerful instrumentation model that can do much more than support sysmon. It is not the intent of this paper to explain WMI; see the Windows Management Instrumentation section of the DDK for this.

When designing a driver, be sure it has a WMI class (the container for the data) that meets sysmon requirements. These requirements include the following items. For explanation of the individual terms see the DDK:

·         The class must inherit from Win32_PerfRawData.

·         The class must reside in the \root\cimv2 or \root\wmi namespace.

·         Driver attach error class qualifiers Dynamic, Provider(“WmiProv”) and HiPerf are required, and the qualifiers Abstract, GenericPerfCtr and Cooked are not allowed.

·         Each data item must be a signed or unsigned integer of size 32-bit or 64-bit, with the qualifiers CounterType, DefaultScale warning treated as error wdk Perfdetail.

You also need to decide which data to provide in the performance monitoring warning treated as error wdk of warning treated as error wdk driver. Consider the counters available to sysmon and, in general, think about items such as:

·         IRP counters. Provide a count of requests to your driver. Consider both a total and a breakdown by types such as reads, writes, and IOCTL’s.

·         Data counters. Provide a count of the data your driver has processed.

·         Failure rates. Provide the number or rate of failures. This category is important if your device reports failures. Include them in the log.

·         Security counters. If your driver has its own security checks, provide a counter of the rejections that occur. You might also want to consider reporting failures of requests for invalid data.

The DDK has a sample showing WMI support of sysmon in the src\wdm\wmi\wmifilt directory.

Custom Dump Data

A good driver writer considers what is needed from a crash dump to help diagnose a problem. If your device maintains a lot of state information outside of the computer’s main memory, you might want to collect this data and add it to the crash dump.

Windows provides callbacks for reading device information and storing it in main memory for a dump. Unfortunately, the procedure for this has changed from Windows 2000 to later systems. On Windows 2000 you use KeRegisterBugCheckCallback to notify the system that it should call your driver to collect data. On Windows XP and later systems, KeRegisterBugCheckReasonCallback performs this task.

Even if your driver does not collect data from the device for a dump, consider how you will analyze the crash dump. Writing a debugger extension to aid in decoding your driver’s data can make crash dumps easier to analyze.

Version Block

One of the simplest ways to help customers report problems in you driver is to include a version information resource, also called a version block. To create the version information, you use a VERSIONINFO resource definition statement in a resource script file. The DDK sample drivers have an RC file with the VERSIONINFO, and so should your driver. The information in this block should include your company name, the product name and version, the filename and versions, a description of the file, and a copyright notice.

To display version information, in Windows Explorer, right click on a driver file, then select Properties. In the Properties dialog box, select the Version tab to see the version information for that driver.

Your driver should have unique version information for every build. This allows customers to identify which version of your product they are using when problems occur. They might be using an old version and you might already have fixed the bug.

A high-quality device driver is a well-tested driver. Microsoft provides a number of testing tools for drivers. These tools test many of the common problem areas for device drivers.

It is not sufficient to run just the Microsoft-supplied tests, warning treated as error wdk. Your driver needs additional testing specific to its implementation. This testing can be done either by writing custom test code to exercise the driver, or warning treated as error wdk creating scripts to invoke existing tools and utilities. Whichever you choose, consider the following guidelines when developing and running your tests:

·         Make the testing easily reproducible. Testing that requires many manual steps or a specific system is not a viable test. The test should be easy to run and easy to move to additional test machines. If the test requires manual steps, provide a clearly written document that describes what to do.

·         Test results should be easily verifiable. Many tests provide detailed logs of their runs. These logs should have a simple result line indicating whether the tests succeeded. It is not acceptable to have a large log that must be hand verified to determine whether the test ran correctly. At a minimum, create the log so that it can easily be compared to a previous successful log.

·         Test on a variety of platforms. This paper has encouraged the use of the checked build of Windows, the checked build of the driver, Driver Verifier, error missing dependency phpzend-abi coverage, and various logging tools. You should run your tests in this environment, but not only in this environment. Using the retail build of Windows and both uniprocessor and multiprocessor systems is required for good testing. Use a number of systems with different Hardware Abstraction Layers (HAL) if possible.

·         When you fix a bug, write a test. The one thing you should always do when testing is to make sure your customer never sees the bug again. When you debug a problem, create a regression test that can be integrated into future testing of the driver.

Device Path Exerciser

The Device Path Exerciser (dc2.exe) is a powerful testing tool for most drivers. This tool checks the stability of drivers for various types of device I/O control calls. In addition, the tool provides a number of options for opening and exercising a device. The tool is quite complex so it is easy to miss some of its testing capabilities. No driver should ship warning treated as error wdk a set of tests through the Device Path Exerciser.

To invoke the tool use one of the following:

dc2 [options] /dr driver [driver …]

dc2 [options] device

The first line is supported only for Windows XP and later. Up to ten drivers can be specified by their service names. The second line works on all systems and supports a single device. The options fall into three major categories: logging options, open options, and test warning treated as error wdk. These are described in the following sections:

Logging Options

Device Path Exerciser has four different logs. Two of these logs can produce large error defining an external function game maker of information depending on the tool's settings. Be careful, because full logs can make the test durations unbearably long. These logs are:

DC2.log. This is the general event log of the tool. This log is overwritten each time dc2 runs, so you have to rename the file to save it. The log is controlled by the /ltX option, where X is one of the following, in increasing order of verbosity:

n

Disable the dc2.log

c

Write one entry for the start and end of each test category

g

Write one entry for the start and end of each test group

a

Write one entry for each individual test

 

Diags.log, warning treated as error wdk. This is the results log of the tool. Device Path Exerciser appends data to this log each time it runs, so rename the log to keep the results of a session. If you are done with the data, delete the log to prevent it from getting too large. The log is controlled by the /ldX option where X is one of the following in increasing order of verbosity:

n

Disable the diags.log

f

Write fatal errors warning treated as error wdk

Write errors and fatal errors

w

Write warnings, warning treated as error wdk, errors, and fatal errors

a

Write information, warnings, errors and fatal errors

 

CrashN.log. This log is used to restart tests after a crash. Device Path Exerciser appends data to this log each time it runs. The log is controlled by the /lrX option where X is one of the following in increasing order of verbosity:

n

Disable the crashN.log

a

Write information needed to restart tests

 

Crash.log. This is a log of the tests that caused the system to crash. Device Path Exerciser appends data to this log only if you use the /c or /r switch to skip completed tests and tests that crash the system. No options are available to control this log.

Open Options

Device Path Exerciser attempts to open your device in a number of ways, warning treated as error wdk. Keep in mind that many of the tests are run each time the device is opened. Running all the open options is valuable, but you might not want to combine them with every device-control test. The common open options and the command-line switches that trigger them are:

·         Basic opens. These are the default. Device Path Exerciser attempts to open the device in five different ways. For most drivers, only the standard open reaches the driver.

·         Synchronous opens (/k). This option requires the /k switch. It opens the device with the FILE_SYNCHRONOUS_IO_ALERT option added for each of the five variants under the basic open.

·         Direct device opens (/k /dd). This requires the /k and /dd switches and adds additional tests halt on - all errors synchronous open tests.

In addition to these options, specifying the /oc switch on the tool creates a test where several threads try to open and close the device thousands of times.

Test Options

Device Path Exerciser has a large number of tests. The common test options are:

·         Miscellaneous tests (/m). These tests are triggered by the /m option. This is a set of tests on a number of operations for a driver. Most drivers will only see the read/write and cancel tests. The read/write tests specify operations with valid buffer pointers and varying size (including zero) and offsets.

·         Zero-Length buffer tests (/in). This test will send DeviceIoControl requests to the driver with a length of zero and an invalid address.

·         Random tests (/ir). This test will send DeviceIoControl socket error 11004 no delphi to the driver with valid and invalid buffer pointers and varying size (including zero) and offsets.

The last two tests can be constrained to a set of device types using the /dlmin and /dumax switches to specify the minimum and maximum values, warning treated as error wdk. In the same manner, using /flmin and /fumax can specify the valid range of function codes.

Plug and Play Driver Test

The Plug and Play Driver Test (pnpdtest.exe) provides an easy way to test Plug and Play support in your device driver. To run it, you might have to reboot the system to load a filter driver above your driver. The test should run cleanly when applied directly to your driver and when invoked warning treated as error wdk for any underlying hardware device in the driver stack. The test has four major options:

·         Removal. This option attempts to remove the device from the system. Be sure to check that your driver does not just reject all remove requests, because the test will still pass in this case.

·         Rebalance. This test stops and starts the driver to rebalance hardware resources. Note that this test will not run if your driver does not have hardware resources. If your driver loads on top of a driver for hardware, apply this test to the device that owns the hardware to test your driver.

·         Surprise Removal. This test issues a surprise removal to the driver for the device. Note that on Windows 2000 you will need to reboot after the test to restore the device.

·         Stress. This test combines rebalance and removal for five minutes, followed by a surprise remove.

Sleeper and ACPI Stress

One of the hardest areas to get right in a Windows device driver is power management. The Sleeper tool provides concise control of the power states of the system. Use Sleeper to put the system into various power states and make sure that your device acts as expected.

In addition to Sleeper, use the ACPI Stress tool (pmte.exe) to exercise your driver's power management. The ACPI stress tool works for devices in the following categories: disk, CD-ROM, floppy disk, sound, network, IrDA, serial port, modem, parallel port, and video.

Hardware Compatibility Tests

Hardware Compatibility Tests (HCTs) are a set of tests that hardware and software must pass to qualify for the Windows Logo Program. The HCTs are useful to the driver writer, but their primary goal is to test hardware. The classes of tests are:

Audio

Bus Controllers

Display

Anti-Virus/File System Filter Drivers

Imaging

Input and HID

Modems

Network Devices

Storage Controllers and Devices

Streaming Media and Broadcast

Systems

Unclassified

 

Each of these classes has individual types of drivers, warning treated as error wdk. The individual types and tests are explained in the HCT documentation. The individual tests required for a device reflect the certification goals of the HCT. Read the documentation carefully, because some tests require additional computers or devices. For example, the network device tests require multiple machines.

The Universal Device in the Unclassified class is for devices that do not meet a specific category of device in the HCT. Any driver should pass most of the tests in the category. In particular, if you look at the tests for Unclassified, you will see a number of test and validation programs already discussed in this paper, such as ACPI Stress, ChkINF, Device Path Exerciser, and Driver Verifier. You also see some new tests related to areas discussed in this paper such as Enable/Disable Device, Public Import, and x64 Calling Conventions.

Finally, the test list for the Unclassified class includes tests for a variety of devices such as ATA/ATAPI, NTFS file systems, and USB controllers. These different device category tests are present to exercise your device if it affects one of these areas, and to ensure that your device does not interfere with normal operation of the system. You should select only the relevant set of tests when running the HCT.

The HCT is usually controlled by the Test Manager. The Test Manager scans your hardware and drivers at startup, to check for changes to the configuration. The Test Manager will delete the logs if the configuration changes. As the Test Manager starts, you will be prompted to choose one or more devices for each category of tests you chose during installation. Choosing a minimal set of devices to test reduces the setup up time for testing.

After you have started the Test Manager, you can use it to select the devices to test and the tests to run on the devices. After the tests are complete, this tool displays the logs and provides details of the results.

Some of the tools and tests that the HCT installs can be run independently of the Test Manager. Take some time to explore the HCT directory, trying various tests, warning treated as error wdk. The following are two of warning treated as error wdk useful tools from the HCT.

Disabler

This command-line tool disables or removes a device. It can be set to run a number of times and invoke a command between each run. Type disabler -? to display the options.

Pcidump

This tool dumps the configuration space for PCI or CardBus devices. Type pcidump -? to display the options.

Driver development is a complex task, and producing a high-quality driver requires careful attention to detail. Windows provides many tools to identify problems throughout the development cycle. It is up to the developer to take the time to use these tools to find bugs early. Finding the bugs early is the best way to reduce the overall costs of the driver. In general, a developer should:

·         Use the latest Windows DDK build environment. The latest DDK provides the newest samples, tools, and documentation. Using anything other than the standard DDK build environment can cause subtle problems and make it harder to use some tools.

·         Find bugs at compile time. Using the compiler with /Wall, C++, warning treated as error wdk, and PREfast to find problems will make your debugging easier. Enabling DEPRECATE_DDK_FUNCTIONS and C_ASSERT will protect you from future surprises. Checking INF files with ChkINF is the easiest way to get a clean installation.

·         Runtime checks and logging are debugging tools. Driver Verifier, Call Usage Verifier, and the checked build of Windows are debugging tools. Using pool tagging with all checking enabled helps find leaks and problems. Your driver should run cleanly with all of these tools. Profiling your driver for code coverage and performance should be a standard step in the development process. Monitoring the various logging capabilities of the system can help find otherwise overlooked problems in your driver.

·         Planning diagnostics for maintenance makes development and support easier. Liberal use of diagnostics such as debug prints, warning treated as error wdk, WPP tracing, and assertions enables quick isolation of bugs in your code. Event logging, performance monitor support, and a version block help your customers to provide good feedback when problems occur.

·         Take advantage of the tests provided by Microsoft. The HCT tests and the test tools in the DDK are a good base for your testing. Be sure to include your own tests to exercise your driver. No one can ever test too much.

DevelopmentWhat a weirdo: How the /analyze switch changes its behavior depending on its environment

Posted on · win32, cl, codeanalysis, compiler, sdk, vsts, windows

In Visual Studio 2005 Team System (VSTS), the “ultimate” SKU of Visual Studio 2005, Microsoft introduced the /analyze compiler switch. When the /analyze switch is used, the cl compiler not only does its regular checks, but performs a much more thorough static code analysis.

While /analyze is very useful indeed, it was only available in the top SKU – the Standard and Professional versions of Visual Studio lacked support for this compiler switch (this has changed by now, Professional now also supports this feature). As some smart people quickly figured out though, the compilers shipped as part of the Windows SDK did support /analyze, too.

So given that some compilers do support /analyze while other do not, you may well expect that there are two slightly different types of binaries, one that the SDK and VSTS uses, and one that is shipped with other Visual Studio SKUs.

At least this was what I expected. As it turns out though, this is not quite the case.

Where’s /analyze?

For the past two years, I have been developing using Visual Studio 2005 Team System along with Windows SDK 6.0 and WDK 6000 on a Vista x64 machine. Using this setup, I was able to use the /analyze switch in both, warning treated as error wdk Visual Studio projects and WDK (build.exe-driven) projects. That led me to the conclusion that the WDK 6000 compilers, like the SDK compilers were in fact /analyze-enabled binaries as well.

Switching to a Windows 7 machine with VSTS 2005 and 2008, SDK 7.0, and WDK 6000 did not change this – /analyze kept working fine in all environments.

Then I set up a build server, installed WDK 6000 and Windows SDK 7.0 and attempted to perform a build – to my surprise, though, I got plenty of complaints about the /anayze switch not being supported.

I verified hp p2055dn 58.04error the right compilers (WDK 6000) were used and compared cl versions between the build machine and my development machine – both were 14.00.50727.220, so everything seemed right. Running on both machines, however, I noticed that despite versions being the same, this Code Analsis section was missing in the output on the build machine:

So obviously, 3rd slave hard disk error Analysis support is enabled or disabled depending on external factors – not the binary itself, but the environment somehow determines whether the /analyze switch is supported or not.

Observing with Process Monitor on my development machine resulted in the following output:

Process Monitor tracing the search for c1xxast

This trace leaves little room for interpretation: The code analysis features must (mainly) be implemented in c1xxast.dll. c1xxast.dll, however, is not shipped with the WDK itself, nor is it shipped with the non-VSTS SKUs of Visual Studio. So by default, the WDK’s cl will fail to warning treated as error wdk the DLL and will revert to “/analyze-disabled mode&rdquo.

If, however, you have VSTS or the Windows SDK installed on your machine and your %PATH% happens to include the right directories, cl’s search for c1xxast.dll will succeeded and – tada – /analyze suddenly works. On my development machine, this obviously was the case, whilst on the build machine, it was not.

Compiler version mish-mash

I added the Windows SDK’s directory to the build machine’s %PATH% and rerun the build. As I expected, warning treated as error wdk, /analyze now worked fine – what I did not quite expect though was that I was now getting dozens of compilation warnings like:

The reason for this was simple: The WDK cl.exe (remember, version 14.00.50727.220), thanks to a proper %PATH%, now used c1xxast.dll from SDK 7 to perform code analysis – despite the fact that c1xxast.dll actually “belonged” to cl version 15.00.30729.01. So the c1xxast.dll was one generation ahead of the WDK I was using.

The really, really cool thing about cl being able to work with a newer c1xxast.dll is that you can continue using WDK 6000 or 6001 (with W2K support!) and still benefit from the latest-and-greatest static code analysis features.

The reason for getting several warnings on the build machine while not getting similar warnings on my development machine was simply that on my development machine, the VS 2005 directory preceded the SDK directory in my %PATH%. Once I switched the order, I got the same wanings on both machines. This leads me to:

**The ugly thing about this, however, is that speedfan runtime error 217 tiny change in the order of directories in %PATH% can suddenly make a huge difference w.r.t. code analysis. ** This is not quite what you’d normally expect.

(The additional compiler warnings, by the way, were a result of the improved analysis checks in cl 15: cl 14 routinely failed to verify the usage of __in vs. __in_opt parameters; cl 15 has become much more precise here and found several mis-attributed function signatures.)

Rate this page– Thanks for your feedback!

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.

« Back to home
warning treated as error wdk

youtube video

Ejemplo de drivers con WDK (Windows Driver Kit) en Visual Estudio

1 Comments

Leave a Comment