06 Oct 2013 @ 6:39 AM 

Within my Updating component, Each Element is given a little Progress Bar right within the ListView. It’s drawn using a Gradient background. I’ve given passing thought to the idea of figuring out how to draw the standard Themed Progress bar within the ListView. Today I decided to delve into the seedy underbelly that is the Theme API and sort out how to do exactly that.

The Theme API

The Theme API resides in uxtheme.dll. Using a ‘theme’ component involves three steps:

  1. using the OpenThemeData() function to get a handle to the Theme.
  2. using the DrawThemeBackground() and DrawThemeText() functions to draw applicable parts of that theme element.
  3. closing the theme

At it’s core, Themes are really just groups of images; OpenThemeData() grabs a block of images, and you use the parameters of DrawThemeBackground() and DrawThemeText() to select which portion of the image to use. The Theme API refers to these as “parts” and “States”. The first step to using the Theme API is, of course, to declare the Functions you will be using. Unfortunately while the Functions themselves are well-documented, what is less available is the actual Constants for using the functions; so while I was able to grab some useful declarations from PInvoke.NET I had to use the Windows SDK to recreate the enumerations. Since I am only interested in the Progress Bar portions at this time, I only recreated the appropriate enumerations for them. Here is the class I came up with.

It’s worth noting there is actually a lot in common between some of the Theme Elements, so it might actually make sense for a “full API” sort of implementation that handles all the different cases in a early-bound fashion that let’s you choose the appropriate component. They all use the same functions so it would be a matter of separating each specific type into a different implementation of an abstract class of some sort. But that is for another post for sure. Here we are focused on the progressbar. This code draws the ProgressBar on the given Graphics Object by grabbing it’s DC and using the Theme API functions. Also note the “Default” action which attempts to draw a progressbar the theme API, by simply drawing a plain-style progressbar box. This is to make sure it still works if Themes are disabled on the system it runs on.

So now the question is how do we utilize this for something like a ListView Subitem? The answer is surprisingly… (or perhaps relatively) easily- we simply set the ownerDraw property and override the appropriate functions. I created this sample project which simply advances and shrinks the progressbar values over time by different degrees in a number of List Items. To do this I created a relatively simple Wrapper class around some simple data. This is my preferred pattern when working with the ListView- I typically attach a Data Class to each ListItem through the Tag Property, which allows me to add all sorts of useful data- this can be particularly useful in cases where Delegates or actions are passed ListViewItem’s.

With that out of the way, I could work on the bulk of things. The Sample Program is to eliminate the surrounding faff if I was to simply release the Updater as is, which doesn’t really work well as a simple demonstration of the ProgressBar functionality. Here is the Code behind for the Form itself:

It is reasonably short. In short the Form Creates a thread that iterates over all items and advances their progress (or decrements it) each time, and then forces it to refresh. The Actual drawing logic is in lvwDisplay_DrawSubItem, which basically just draws the item with the given progress within the set bounds for Index 1.

lvwpbar

Behold! The result! Beautiful, really. The ThemePaint Class can also paint the Error and Paused Progressbars. One thing I’ve tried was getting the “marquee” effect properly- there appears to be a way to do so but I’ve yet to work out the best way to get the appropriate effect. Perhaps in a future post I will generic-ize the ThemePaint class to a set of classes for the various Them-able things that can be drawn, though I think such a class may have reasonably dubious value, it might be a good exercise.

Posted By: BC_Programming
Last Edit: 06 Oct 2013 @ 06:39 AM

EmailPermalinkComments (0)
Tags
Tags: , , , ,
Categories: API, C#, Programming
 08 Dec 2010 @ 1:25 AM 

There are a lot of people, forum posters and the like, vouching for any number of “addon” programs that allow you to install DirectX 10 on your Windows XP PC, even though DX10 is a Vista+ feature.

There are torrents that claim to have DX10, but half of them are just a few Vista DirectX DLLs zipped up. Instructions say something like “copy to your windows folder, now u have directx10 and your games run faster”

I even found one that claimed to allow you to play, say, Crysis and Ultra High (which usually required DX10) and, when you ran DXdiag after installation, it said DirectX 10.1, so there is NO way its fake!

I say it’s time to truly examine this: normally I would dismiss it off-hand for being stupid, but what the heck, I have a few minutes to spare, may as well give it a proper debunking.

The first step, was, of course to find it. Google is not hard to use, of course. It led me to this page:

http://www.techmixer.com/download-directx-10-for-windows-xp/

yet another blog, it would appear.

In any case, after a bit of running around (the things I do for a blog post) I finally got the ZIP file for this nonsense. I of course don’t have XP installed on a machine so I used a trusty VMWare install, and a XP install that I had sitting about.

I ran the installer, but, while I was running it, I was running Process Monitor to see exactly what it was fiddling with. Once the install was done, I had a logfile from that that I opened on this machine (outside the VM) for inspection. Some interesting entries. First, it explicitly set the version number like so:
RegSetValue HKLM\SOFTWARE\Microsoft\DirectX\Version 4.10.0.5515

This is notable because even my Win7 install identifies my version as 4.09.00.0904; amazingly, this tiny installer was not only able to install a version of DX10 that had a later version then DX11, but it was also able to do so using a tiny 20 MB installer. the technical sycophant might be impressed, but I’m not. Of course the real reason is that it had to explicitly change the version, otherwise, the new version of DXDiag it installed (which is one of the few things it really does copy over) won’t translate that new version number into DirectX10. I also used the results to gather exactly what files it was installing; this is what I found being installed:

C:\WINDOWS\system32\d3d10.dll
C:\WINDOWS\system32\d3d10core.dll
C:\WINDOWS\system32\kernel32new.dll
C:\WINDOWS\system32\msvcrtnew.dll
C:\WINDOWS\system32\ntdllnew.dll
C:\WINDOWS\system32\d3dx10.dll
C:\WINDOWS\system32\d3dx10_33.dll
C:\WINDOWS\system32\d3dx10_34.dll
C:\WINDOWS\system32\d3dx10_35.dll
C:\WINDOWS\system32\d3dx10_36.dll
C:\WINDOWS\system32\d3dx10_37.dll
C:\WINDOWS\system32\d3dx9_33.dll
C:\WINDOWS\system32\d3dx9_34.dll
C:\WINDOWS\system32\d3dx9_35.dll
C:\WINDOWS\system32\d3dx9_36.dll
C:\WINDOWS\system32\d3dx9_37.dll
C:\WINDOWS\system32\dwmapi.dll
C:\WINDOWS\system32\dxgi.dll
C:\Program Files\Common Files\dx.reg
C:\Documents and Settings\Administrator\My Documents\crysis.rtf
C:\Documents and Settings\Administrator\My Documents\msvcrt(DEBUG).dll
C:\WINDOWS\system32\dxcpl.exe
C:\WINDOWS\system32\DXErr.exe

After the install it prompted me to start DXdiag. presumably so it could show off that yes indeed the version number is different. Any idiot can change the version number, though. It’s a simple registry value.

So, anyway, playing the part of such a naive user, I started DXdiag, which of course complained about any number of errors (probably related to the lack of hardware acceleration for most of DX in the VM though) In any case, once started, I was of course greeted to the new version number:

DX10 on XP. yeah right.

Amazing a quick install, and I’m now running DX10! and it was only like a 40 meg file, unlike DX9, so not only did I upgrade from DX 8.1 (included with XP) to DX 10, but I did so without downloading hundreds of megabytes. How very wonderful this all was, so happy and whimsical. So I tried a few small DX programs. they had to run with the software renderer because of VMWare but oh well.

They all crashed, with various DLL entry point not found errors.

So, I installed DX 9.0c. the errors went away. Curious. why would a DX10 demo application need DX9 installed?

Either way, I decided the various D3d10 files, specifically those with “new” on the end, bore very close examination, namely with dumpbin. I copied them out of the VM to a temporary folder for examination with the trusty dumpbin utility. I started with d3d10.dll, despite my curiousity with regards to the “new” files. So I ran a good ol /EXPORTS on the file with dumpbin, something which has never failed on me before. (at least with a valid windows image). Needless to say, there is a first time for everything:

Mysterious. So, I decided to try an /IMPORTS, see what this dll is importing from:

there’s d3d10core.dll as well as msvcrtnew.dll; I used a few other features of dumpbin to try to examine the d3d10.dll file. It was clear that the file was corrupted on purpose; various fields in the header were screwed around so that it was difficult to dump the headers properly. Essentially, the file was for all intents and purposes corrupted. In any case, after examining it with sysinternals “strings” utility, it became clear that it had an embedded shader processor, and a lot of other string data inside, as well as a list of the exports (the ones that dumpbin refused to list because the export table pointer was invalid); they seemed to simply be DX10 function names.

At this point, I turned to the import table to further examine how exactly calls to this D3d10 dll made it to the graphics pipeline. d3d10core seemed like a good start.

Yet again, I hit a stumbling block as I tried to view the exports. Why they did this on purpose, I do not know, but clearly there is something they don’t want people like me to know about this dll, and I’m going to find out what it is. Checking the import table, it was empty. Which, at least for something like this, is impossible. So I once again turned to the strings utility to try to make some sense out of the files contents. through some effort, I was able to find all the dll names referenced in the file; KERNEL32.DLL,USER32.DLL, and dxgi.dll, as well as that msvcrtnew.dll that was referenced also by the other file. dxgi, being that it was one of the files “distributed” with this set, seemed like the next place to go looking.

I was, to my surprise, able to run dumpbin /exports on the file without a error about the pointer to the export table being out of range:

clearly, yet again, several DX10 oriented function names are being exported. I also noticed that I have a dxgi.dll in my windows folder; presumably because I actually have DX10/11. So I did a quick compare. for the most part, it seemed that the dxgi from the XP DX10 set was exporting a subset of the functions from the Win7 install, but since win7 is DX11 there wasn’t really a way to know. Aside from, of course, taking the dxgi from Vista and seeing what it said. Which is, of course, what I did; and I ran a dumpbin /exports on it as well:

I’m seeing double! I exclaimed. Now curious, I ran a quick fc…

the dxgi.dll they provide in their “DX10 for XP” pack, is, in fact, the DXGI from a base install of Vista. This is the RTM version of Vista, by the way, not SP1 or SP2. This explained why the file was dumpbin /exports-able, since it was MS produced and not created by whomever was responsible for the others. So far, we have the following; programs link to d3d10.dll, which in turn links to d3d10core, which links to dxgi, which links to a number of Vista/7 only functions. Examining the assembly, however, it becomes clear that when dxgi.dll is being loaded by d3d10core.dll, it forcibly changes the import table of dxgi.dll to use the various “new” dlls; for example, while dxgi.dll imports functions from ntdll, the import table is updated on the fly so that the calls to ntdll don’t go to the XP ntdll.dll (where the functions required aren’t present) but rather to “ntdllnew.dll” which was in fact, ntdll.dll from Windows Vista RTM; additionally, so was dwmapi.dll. So, I dug a little deeper. ntdll, do my understanding, was responsible for almost any User-mode to kernel mode context switch; additionally, ntdll.dll is mapped into the process address space when the application starts; so the game trying to use this special D3d10.dll (most likely by accident) would in fact be mapping not only the XP ntdll.dll into it’s process (at startup) but also a second ntdll (the windows Vista ntdll) implicitly when it loads the d3d10 dll. Normally, you cannot map two files with the same name into the same process. thus, the creator of this little sideshow renamed the Vista ntdll.dll to ntdllnew.dll; this is also the reason for the fixups to the import table of dxgi when it’s loaded. (so that instead of importing functions and calling functions in ntdll (on the system) it is instead calling ntdllnew.dll which d3d10core.dll loads on it’s own)

Somehow, at least, I’m guessing (I haven’t actually seen it in action) this little rube-goldberg device allows games (well, not actually, I’ll get to that in a second) to load and call into d3d10.dll on windows XP.

kernel32new.dll is also a hacked version. One of it’s imports however comes from d3d9.dll; so it seems we have d3d10.dll calling d3d10core.dll which in turn loads dxgi.dll from windows vista, hacks it’s import table to call into the Vista ntdllnew.dll rather then the xp ntdll.dll that it would try to load (and fail to work), additionally, imports to kernel32.dll are fixed up to kernel32new.dll (since the dll is loaded in process this affects the running game/application as well) which in turn will perform it’s own special processing on directX related stuff to call d3d9.dll for some reason, although why the d3d9 functions would be being called from kernel32.dll is beyond me.

The other various dlls are for the most part duplicates of those files from a RTM vista install. Given all of this, we can conclude that the arrangement isn’t to actually add DX10 to your machine but rather to emulate it; rather then actually add dx10 capabilities, it is merely giving programs the ability to access the dx10 dlls as they normally would and then at some point later translating it into a call to the native DX api; it seems that it expected DX9 to be installed as well since the entire thing fell apart when I first tried it with the standard 8.1 that XP comes with.

Conclusion

So the question now is, “who uses it”?

The answer? technical sycophants whose understanding of dll import/export tables is far below what they think, and who consider themselves “extreme gamers” that stick to 7 year old operating systems for reasons they pull out of their ass. MS didn’t “artificially” limit DX10 to Vista and higher in some sort of heavy handed move to get gamers on Vista. They did so because making it backward compatible and testing all the various supported scenarios in that instance would be infeasibly arduous. Additionally, they probably realized you’re a bunch of tards who complain about the smallest thing anyway and that you’re not worth the time to please. But it’s ok, since this other fellow has totally hacked together a solution that let’s you play your games using the DX10 setting that simply calls into these amusingly obfuscated dlls that are trying very hard to hide the fact that they are really a DX9 wrapper for DX10. (The standard DX10 libraries don’t have any DX9 references embedded. I particularly find it interesting that they would [i]purposely[/i] obfuscate the export table of several of the files. Do the DX10 SDK samples run? Yes. Do they use “DX10” no. And they don’t run very well, either. You aren’t going to be using DX10 hardware on windows XP. You might be able to play DX10 games really slow via their cleverly disguised DX10->DX9 interface translator, but it seems rather pointless. It’s like putting the body kit of a porsche on a Chevette. It’s still a bloody chevette.

EDITS:

Found a MSDN blog about why DX10 wasn’t created/released for XP:

http://blogs.msdn.com/b/ptaylor/archive/2007/02/14/why-dx10-wasnt-created-on-xp-and-why-it-isnt-in-xp.aspx

Given the new features in the driver model and hardware ( with GPU task switching, GPU memory management and more ) all of which require kernel support – hoisting a driver layer like that on XP is rewriting it to be Vista. FWIW, the MS hw developer page has the graphics logo requirements and it explicitly mentions these GPU features as being required. They are essentially hidden features that API programmers and end-users never see.

Basically, even creating a Translation layer would be a waste of time, which is sort of proven in a way by the fact that the “Alky” project has been dead for ages and barely supported running even the most basic DX10 SDK samples.

Also:

http://blogs.msdn.com/b/ptaylor/archive/2007/06/28/dx10-on-xp-round-2.aspx

Posted By: BC_Programming
Last Edit: 17 Dec 2010 @ 12:05 AM

EmailPermalinkComments (2)
Tags

 Last 50 Posts
 Back
Change Theme...
  • Users » 43307
  • Posts/Pages » 362
  • Comments » 106
Change Theme...
  • VoidVoid « Default
  • LifeLife
  • EarthEarth
  • WindWind
  • WaterWater
  • FireFire
  • LightLight

PP



    No Child Pages.

Windows optimization tips



    No Child Pages.

Software Picks



    No Child Pages.

BC’s Todo List



    No Child Pages.