Archive for the ‘DDK’ Category

A documented way to get loaded modules

Tuesday, June 5th, 2007

This is a new one on me. I just saw this mentioned on NTDEV for the first time yesterday. AuxKlibQueryModuleInformation is a documented way to get the loaded modules, replacing some of the functionality of ZwQuerySystemInformation.

In fact, the entire Auxiliary Kernel-Mode Library Routines section is interesting. I had no idea it existed until now. Other exports include AuxKlibGetImageExportDirectory and AuxKlibGetBugCheckData.

Doron Holan says that it’s backward-compatible all the way to Windows 2000 via a static library, in a similar manner to cancel-safe queues and the safe string library.

Neato.

Why can’t you un-pend an IRP?

Thursday, November 30th, 2006

I was playing around with SDV and the pending bit the other day, and tried setting and clearing it in back-to-back lines in a dispatch routine. Having CSQ mark the IRP pending (which is automatic, if it succeeds at queuing the IRP) caused SDV to blow up with a very confusing error.

According to a PowerPoint slide by Adrian Oney, here’s the reason:

There is no IoUnmarkIrpPending because a driver above you can legally mark your stack location pending and return STATUS_PENDING

He goes on to say that PoCallDriver does this. News to me! I had always wondered why it was illegal (as opposed to simply immoral) to mark and un-mark an IRP as pending; it’s because in so doing, you would destroy the state of the driver above you who was depending on this.

More on Passthru

Monday, November 20th, 2006

Speaking of recent Passthru changes, there’s a not-so-recent set of changes to the Passthru INFs in the XP+ DDKs. If you originally did your IM INFs before that time, it’s time to re-check them. In particular, there were changes around the CopyInf directive.

Speaking of which, I mailed Johan Marien at Microsoft today to let him know that I think the Passthru sample should be made redistributiable, since so many IM drivers are based on it directly. If you agree, you might want to drop him a note in support. Or, leave a comment here and I’ll forward everything on to him.

UPDATE: Thomas Divine points out in the comments that there are known bugs in 3790 Passthru, and also that there is a redistributable version available at wd-3.com. See his comment for details.

Site maintenance: new WDK tag

Sunday, November 19th, 2006

I’m changing over my DDK tag to WDK going forward, with a little bit of a transition period until I get tired of clicking the extra checkbox. I know I have a lot of subscribers to the DDK tag as its own feed, so this is official notice that DDK is now going to be used for downlevel-only posts.

Also, while I’m at it, and since the US holiday of Thanksgiving is approaching, I’d like to send out a thank-you to all of my readers. This blog’s traffic has multiplied again over the past year, and I really enjoy knowing that there are people out there that find this stuff as interesting as I do.

Now back to regularly scheduled programming. :-)

Alex Ionescu is blogging

Sunday, November 19th, 2006

I’ve been meaning to post this for days but I keep forgetting. Alex Ionescu, who is another one of those guys that just seems to know way more than one person should be allowed to know about Windows internals, has started blogging (again).

He’s got a good user-mode debugging series posted, and if I know Alex, there’s plenty more good stuff still to come.

Welcome to the blogosphere, Alex.

More on object lifetimes

Saturday, November 18th, 2006

In an earlier post, I described a subtle race condition resulting from the differing lifetimes of miniport adapters and control device objects. Last week, Gianluca Varenni, the maintainer of WinPcap and one of the brains at CACE technology, pointed out that Microsoft had recently changed the Passthru sample to add reference counting in some instances to adapter objects. I went back and looked, and sure enough, the current DDK WDK sample has additional reference counting built into the driver.

Microsoft didn’t add any comments to the sample describing the reference counting addition, but I found this bug myself a while ago and implemented essentially the same solution. The basic problem is that there is a race between the two different adapter tear-down paths – the one that is initiated from halting the virtual miniport itself and the other that is triggered by the halting of the underlying miniport.

Gianluca also pointed out that nobody in their right mind would write an IM driver from scratch, other than as an educational experience, because it’s entirely too difficult to get the various NDIS synchronization issues right unless you’re an absolute expert at it. Obviously, even Microsoft is still finding bugs.

The good news is that IM’s are dead. Vista has a much-improved lightweight filtering architecture, so the writing is no the wall.

EULA clarifications

Tuesday, November 14th, 2006

A big thanks to Johan Marien from Microsoft for addressing some of the recent licensing questions raised over the WDK samples’ EULA. According to Johan, the license restrictions on redistribution of WDK source were present in the SP1 DDK, and the samples.txt file was added to provide a mechanism for making certain source code redistributable in the future.

His post on NTFSD has all of the details, which I won’t repeat here. He also asks for feedback on which samples you would like to see made available for redistribution, so if you have a business need, it may be worth bringing it up with him. Otherwise, it looks like you shouldn’t distribute source code derived from WDK samples to customers, unless you have a separate agreement with Microsoft.

Check that EULA

Monday, November 13th, 2006

Tony Mason from OSR sent a mail to NTFSD today detailing his concerns about the RTM WDK’s newly improved EULA. I am not a lawyer, and neither is Tony, but it looks like source redistribution has been greatly restricted compared to previous kits. If you depend on samples in the kit, it looks like it would be a good idea to read the RTM EULA carefully (or better yet, send it to your lawyer).

…and the same thing goes for NdisInterlocked*()

Monday, November 6th, 2006

A few days ago I wrote about how to keep ExInterlocked*() operations interlocked. Well, the same thing goes for NDIS drivers.

NDIS documents a set of routines that look a whole lot like the ExInterlocked* routines:

#define NdisInterlockedInsertHeadList(...) \
    ExInterlockedInsertHeadList(...)

Unsurprisingly, the rule is the same: Once you use a given spin lock with any NdisInterlocked* function, it must always be used with an NdisInterlocked* function. If you missed the first article, you may want to re-read it for a more detailed explanation.

Not only is there no documentation of this on MSDN, but what documentation there is is wrong: it says that the functions raise to DISPATCH_LEVEL, but in reality, they raise to the highest IRQL in the system (at least when #define‘d to their ExInterlocked counterparts, which is whenever BINARY_COMPATIBLE is not defined).

The documentation also states that the NdisInterlocked* routines must be called from <= DISPATCH_LEVEL; this is probably wrong but I would encourage following the docs regardless unless/until Microsoft clarifies them.

CONTAINING_RECORD for fun and profit

Saturday, November 4th, 2006

Here I want to cover two great uses for the CONTAINING_RECORD macro. CONTAINING_RECORD has been a part of the DDK since forever, and it has a second cousin in Standard C by the name of offsetof.

For those that don’t use it regularly, it looks about like this:

typedef struct _BUFFER {
	LIST_ENTRY  e;
	UCHAR      *buf;
} BUFFER, *PBUFFER;

...

PLIST_ENTRY entry = RemoveHeadList(&listHead);

PBUFFER a = CONTAINING_RECORD(entry, BUFFER, e);

The macro returns a pointer to a data structure given the address of an element inside that structure, as shown above. Although you can get by without it most of the time, there are a couple of good reasons to use it.

First, it helps prevent bugs by keeping you from hard-coding structure offsets elsewhere in your code. For example, take the BUFFER struct above. You could, of course, simply cast BUFFER to LIST_ENTRY, but that encodes the position of e forever in your code. If you change the position (e.g. by adding a member above e in the definition), you will break all instances of code that rely on this layout.

Using CONTAINING_RECORD, on the other hand, allows you to write offset-independent code to refer to elements within the structure. Obviously this won’t work for code that was compiled against a different version of the structure – this is a compile-time technique. But it can mask otherwise silent errors. (Well, silent until the code path in question is executed…)

The reason that they’re silent is also the second great reason to use CONTAINING_RECORD: casts. I’ve written before about how much I like casts in code, so I’m implicitly for anything that eliminates casts. Since CONTAINING_RECORD returns the right type by definition, you no longer have to cast it. So:

PBUFFER buf = (PBUFFER)RemoveHeadList(&listHead);

becomes:

PBUFFER buf = CONTAINING_RECORD(
    RemoveHeadList(&listHead), BUFFER, e);

This has the added bonus of being able to tell when things change out from under it, so it won’t produce as many silent error of the type described above.