- Loading a Direct3D mesh from a resource
- How badly do you want a MacBook Air?
- Visual Studio 2008 SP1: To beta, or not to beta?
- Pair programming at a distance
- New Rhapsody version interesting for embedded software and systems
- An old Visual Studio problem rears its ugly head
- Leaving Windows 9x behind to move forward
- Writing Secure ActiveX Controls
- When Languages Interfere
- .NET Library source welcome, but not earth-shattering
July 03, 2008 | Comments: (0)
Loading a Direct3D mesh from a resource
Why is it that trivial things become hard so often, especially when you're doing API-level C++ programming? Here's an example:
I needed to convert a Windows Direct3D benchmark from loading its textures and meshes from files to loading them from resources, to simplify the installation of the benchmark as an ActiveX control. This should have been trivial: just change the D3DXCreateTextureFromFile calls to D3DXCreateTextureFromResource calls and the D3DXLoadMeshFromX calls to D3DXLoadMeshFromXResource calls, and Bob's your Uncle.
Not so fast.
The textures loaded fine from resources once I plugged g_HInstance in as the hSrcModule and MAKEINTRESOURCEA(iResourceID) as the pSrcResource in the following prototype:
HRESULT D3DXCreateTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DTEXTURE9 * ppTexture );
So the actual code became something like:
D3DXCreateTextureFromResourceA(eng->getD3DDevice(), g_hInstance, MAKEINTRESOURCEA(texNum), &texture );
This worked without a hitch. On the other hand, loading a mesh gave me fits. The prototype is:
HRESULT D3DXLoadMeshFromXResource( HMODULE Module, LPCSTR Name, LPCSTR Type, DWORD Options, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXBUFFER * ppAdjacency, LPD3DXBUFFER * ppMaterials, LPD3DXBUFFER * ppEffectInstances, DWORD * pNumMaterials, LPD3DXMESH * ppMesh );
I tried "X" for the Type, but the mesh didn't load. What to do?
The documentation for the March 2008 DirectX SDK has the promising explanation of the second through fourth parameters:
See Find Resource to find out more about the Module, Name and Type parameters.
While that link works today, when I was trying to solve the problem it brought up an error page in Japanese. Go figure. If you follow the Resource Types link in the Find Resource page, you'll get to a table of standard resource types (which I also couldn't find when I actually had the problem): the one we want is RT_RCDATA, since meshes aren't covered by any of the other standard resource types. (At the time, it took a Google Code search to find this.)
In fact, using that value didn't work for me: RT_RCDATA is not really the enum value you'd expect, but is actually a macro that resolves to the highly intuitive MAKEINTRESOURCE(10). My ActiveX control was compiled for Unicode, so MAKEINTRESOURCE resolved to MAKEINTRESOURCEW, which returns a pointer to a wide character string. Unfortunately, D3DXLoadMeshFromXResource has a LPCSTR for the Type parameter, not a LPTSTR, so it needs an ANSI string, not a Unicode string. What I really needed there was MAKEINTRESOURCEA(10). The final call looked something like:
D3DXLoadMeshFromXResource(g_hInstance, MAKEINTRESOURCEA(meshNum), MAKEINTRESOURCEA(10),
usageFlag, d3dDevice, NULL, NULL, NULL, &dwNumber, &pMesh );
Posted by Martin Heller on July 3, 2008 12:37 PM
May 14, 2008 | Comments: (0)
How badly do you want a MacBook Air?
At least partially in response to my coverage of TopCoder last week, I have been getting a spate of programming contest and community announcements. ZocDoc is an API for doctor appointments. Appistry Enterprise Application Fabric (EAF) is a grid-based application platform for the development and deployment of scalable applications in Java, Spring, .NET or C++.
Notice what these two have in common:
Tuesday, May 13, 2008
ZocDoc Announces Developer Contest - Win a MacBook Air!
Today, ZocDoc kicked off a contest for software developers to create new applications that help patients book doctor appointments anywhere on the web. ZocDoc users have frequently requested integrations into popular applications and devices such as Facebook and iPhones, among others.
The contest, which runs from now until August 1, 2008, challenges developers to build the application that will most benefit patients looking for a doctor. A new API allows developers to pull data from ZocDoc such as doctor and dentist information, practice locations, pictures, URLs and available appointment times, which can be integrated into custom mashups and applications. The developer of the application that benefits the most users (as measured by appointments made) wins a brand new MacBook Air!
If you are a developer, visit the ZocDoc Developer Center to register for the API.
Join Appistry's Peer2Peer Developer Community and you could win a MacBook Air
Appistry Enterprise Application Fabric (EAF) dramatically simplifies the process of developing, deploying, and managing highly scalable and reliable Java and Spring applications.
Now, with Appistry EAF Community Edition, anyone can experience the benefits of Appistry EAF for FREE. Your Peer2Peer membership allows you to:
- Download Appistry EAF Community Edition at no cost
- Utilize it on up to 5 servers or 10 CPU cores for an unlimited amount of time (no expiration)
- Use it for development, testing, even production deployment of applications
It's easy to get started - join the Peer2Peer Developer Community today to download the free software and access developer resources such as tutorials, on-line documentation and support forums.
You could win a MacBook Air when you join Peer2Peer
Hmm. This is the computer that my high-school classmate Steve Levy (or possibly his wife) accidentally threw out with the newspapers.
Posted by Martin Heller on May 14, 2008 11:11 AM
May 13, 2008 | Comments: (0)
Visual Studio 2008 SP1: To beta, or not to beta?
As I mentioned in An old Visual Studio problem rears its ugly head back in February, I've been looking forward to SP1 for Visual Studio 2008 and NET Framework 3.5. Why? These are supposed to fix most of the problems I've been having with Visual Studio, and restore most of the functionality that was cut from the initial 2008 release.
SP1 is out, but only as a first beta-test version. As is true with most beta-test products, there are risks to running it, ranging from a high likelihood of encountering new bugs to a low likelihood of trashing your system to the point where your most effective option is to reinstall Windows from scratch on a newly formatted partition, also known by the woodworking analogy of scraping your drive down to the bare bits.
The list of improvements in this version is impressive. Both Scott Guthrie and Brad Abrams have discussed these in their blogs. Brad does a great job of covering new features; Scott does too, in a slightly different way, and also highlights the known incompatibilities.
Here are the "gotchas", copied from Scott's blog:
1) If you are running Windows Vista you should make sure you have Vista SP1 installed before trying to install .NET 3.5 SP1 Beta. There are some setup issues with .NET 3.5 SP1 when running on the Vista RTM release. These issues will be fixed for the final .NET 3.5 SP1 release - until then please make sure to have Vista SP1 installed before trying to install .NET 3.5 SP1 beta.
2) If you have installed the VS 2008 Tools for Silverlight 2 Beta1 package on your machine, you must uninstall it - as well as uninstall the KB949325 update for VS 2008 - before installing VS 2008 SP1 Beta (otherwise you will get a setup failure). You can find more details on the exact steps to follow here (note: you must uninstall two separate things). It is fine to have the Silverlight 2 runtime on your machine with .NET 3.5 SP1 - the component that needs to be uninstalled is the VS 2008 Tools for Silverlight 2 package. We will release an updated VS 2008 Tools for Silverlight package in a few weeks that works with the VS 2008 SP1 beta.
3) There is a change in behavior in the .NET 3.5 SP1 beta that causes a problem with the shipping versions of Expression Blend. This behavior change is being reverted for the final .NET 3.5 SP1 release, at which time all versions of Blend will have no problems running. Until then, you need to download this recently updated version of Blend 2.5 to work around this issue.
I wouldn't install this version on my primary development system, but I might install it on a secondary development system after doing a full back-up.
To beta, or not to beta? Maybe both.
Posted by Martin Heller on May 13, 2008 11:37 AM
May 04, 2008 | Comments: (0)
Pair programming at a distance
One of the drawbacks of working by myself is that I can't usually do pair programming. This is usually offset by the increased concentration and "flow" that comes from being by myself and undisturbed for long periods, but sometimes I just need another pair of eyes to look at my code.
Last Tuesday was one of those times. No sooner had I published my little blog entry on "clans" than I started to hear bug reports that traced back to some ActiveX code I'd written for PC Pitstop. It wasn't straightforward: two people reported "IE aborted in an unusual manner" errors, but over 8,000 people had run it successfully. I'd missed a rare case.
After looking at the relevant code until my eyes started to cross, I gave Dave Methvin a call. "Dave, do you have a minute? I think that I'm insufficiently paranoid to fix this bug."
Each in our separate offices in different states, we opened up the same Visual Studio project checked out from our version control repository, and looked at the same code. When either of us saw something we didn't understand, we'd point the other at the line of code. It was almost like pair programming, but without the physical presence. In some ways it was better, because we each had our own mouse, keyboard, and screen.
"Look at line 129. What happens if that pointer is null?"
"How could it be null? It's set in line 128."
"Suppose there were no items in the list. It's unlikely, but it's still possible."
"You're right. I'll add an 'if' test right there. OK, it compiles and I've checked it in: update your copy and have a look."
We went on like that for about an hour, and convinced ourselves we'd found every possible problem in what was, after all, not very much code. Then I rebuilt the control, ran all my regression tests, and promoted the control to production.
The ending was happy: after that, there were no more reported "IE aborted" errors, even from the people who had reported them before.
Do you have your own ways of collaborating at a distance?
Posted by Martin Heller on May 4, 2008 12:01 PM
April 14, 2008 | Comments: (0)
New Rhapsody version interesting for embedded software and systems
Last week I took advantage of the fact that Telelogic has a facility here in Andover to get an in-person preview demonstration of Rhapsody 7.2, the new version of their model-driven development product, which is being announced today. I should actually say "Telelogic, an IBM Company," given the recent acquisition: please take that as read. The signage at the facility still just said "Telelogic."
At the beginning of the demo, I sat there thinking "All this modeling junk gets in the way. Let me at the code." Then we got to the point of doing testing on animated UML diagrams synchronized with the compiled code that had been generated underneath, and I started to be impressed. When I realized that many common system-dependent constructs (a timer, a button, ...) had been abstracted and that the entire project could be switched to a different target operating system (there were over a dozen) with a menu pick, I was really impressed.
Some of what's new in version 7.2 extends the capabilities that Rhapsody already had for C++ to plain C. That makes sense for many embedded systems. Other new features are aimed at systems designers, and provide a SysML virtual prototyping facility.
Here's the full release:
Telelogic Announces Enhancements to Rhapsody Model Driven Development Solution including New Eclipse Plug-in
New capabilities facilitate mid-stream adoption of Model Driven Development, and help systems engineers validate technical, real-time or embedded systems designs earlier
MALMO, Sweden and Irvine, California Telelogic, An IBM Company (NYSE: IBM) today announced enhancements to its market leading Model Driven Development™ (MDD™) solution, Telelogic Rhapsody®. The new features decrease time-to-market through the support of MDD best practices that do not disrupt current project workflow, and provide system engineers a way to leverage advanced visualization and prototyping capabilities to easily validate design correctness and effectively communicate intended design behavior.
Today’s announcements include:
- The introduction of Rhapsody 7.2, a new version of the company’s flagship Model-Driven Development solution that provides breakthroughs in systems engineering, software asset re-use, and automated documentation and testing;
- The new Telelogic Rhapsody Eclipse Plug-in, a version of Rhapsody integrated within the Eclipse open source development environment, scheduled for release this summer; Rhapsody Eclipse Plug-in allows embedded device and real-time system software developers to continue working on existing projects at the code level while gradually adopting MDD within a single familiar development environment.
“Leveraging existing code from previous projects is a significant part of most embedded system development efforts and for teams implementing model driven development approaches the need to efficiently automate the transfer of design intent among system models and software code is of key importance,” said Matt Volckmann, Senior Analyst/Program Manager with Venture Development Corporation’s (VDC) Embedded Software practice. “By offering several new features within Rhapsody 7.2 that allow for more integrated methods of code design and model driven development, Telelogic continues its strong history of product innovation and clearly endeavors to maintain its leadership position within the embedded software and system modeling tools market,” said Volckmann. “VDC’s most recent analysis of the embedded standards-based software and system modeling tools ranked Telelogic as the market share leader on a revenue basis”.
New Features Increase Automation; Open MDD to C Developers and Integrated Eclipse Development
Building on Telelogic’s “Code Respect” initiative, Rhapsody now allows C developers to leverage the benefits of MDD while preserving the code structure, functionality and order. Rhapsody further offers the unique ability to reverse-engineer existing code and then forward-generate identical code. This allows software developers to use the right tools for the job and work at either the code or model level.
With Rhapsody’s Eclipse Plug-in, software developers can streamline their workflow and increase efficiencies by taking advantage of Eclipse’s powerful code editing capabilities and gain the benefits of working with an MDD solution all within the same development environment. Using Rhapsody’s strong reverse engineering and code synchronization capabilities, Rhapsody’s Eclipse Plug-in allows developers to work on the code or model within one complete development environment. Working in this manner, the code and model remain in synch and it is easy to navigate from one to the other. Developers can leverage debugging at the code or model level using the Eclipse debugger and Rhapsody’s animation with the ability to synchronize breakpoints between them.
IDT, a company that specializes in Automated Software Testing (www.idtus.com) recently conducted a one year Software Testing survey which concluded that among other statistics, some 50 - 75 percent of the software development lifecycle is spent on testing related efforts. With recent enhancements to Rhapsody TestConductor™, an integrated model-based testing solution, C developers can now detect and eliminate software defects earlier in the development cycle when they are less costly to fix. Rhapsody TestConductor facilitates unit and integration testing by automating many manual test procedures and decreasing the time needed for testing. It executes tests in single or batch mode, determines the success of the test, and creates a report, enabling developers to collaborate more easily and bring products to market more rapidly. Rhapsody TestConductor is based on the Unified Modeling Language™ (UML®) Testing Profile, enabling tests to be easily linked to design requirements captured in Rhapsody or in Requirements Management products such as market leading Telelogic DOORS®.
“Model Driven Development techniques help engineers become more efficient with the potentially time-consuming tasks of test creation and execution, as well as document creation,” said Greg Sikes, Executive Vice President, Modeling Solutions, Telelogic, An IBM Company. “With Rhapsody, engineers immediately gain a better understanding of their software and systems architecture and functionality, while operating in a more open and flexible environment with improved team communication.”
Systems Engineering Advancements
With the enhancements announced today, Rhapsody is the first Systems Modeling Language™ (SysML™) solution that will provide systems engineers with virtual prototyping capabilities using integrated graphical panels to rapidly visualize and validate a user mock-up early in the development cycle. Additionally, the graphical panels will allow engineers to easily modify, monitor and analyze data during simulation making it easier to ensure the design is correct. Rhapsody 7.2 also offers SysML Requirements Tables, Allocation Tables, and N-2 matrices, enabling large quantities of information to be easily organized, customized, and viewed. Improved model consistency and checking functionality further allows software developers to create their own and domain-specific checks, improving design quality and integrity.
Rhapsody 7.2 will be available in April, 2008. The Rhapsody Eclipse Plug-in and graphical panels will be available in Summer 2008.
For more information, visit http://www-306.ibm.com/software/rational/welcome/telelogic/
© 2008 Telelogic AB. Telelogic Rhapsody and Telelogic DOORS are registered trademarks of Telelogic. Rhapsody TestConductor is a trademark of Telelogic. Other trademarks are the properties of their respective holders.
###
Posted by Martin Heller on April 14, 2008 12:00 AM
February 27, 2008 | Comments: (0)
An old Visual Studio problem rears its ugly head
I encountered a Visual Studio 2008 bug this morning that had me baffled. The short summary is that, in a C++ source file with multiple #ifdef blocks, only the first block was properly displaying in gray for the deliberately undefined symbol. Subsequent blocks were showing up in color, even though they used the same symbol as the first block. In addition, mouse hovers didn't display values after a certain point in the file. The project built fine, however.
It was a weird enough symptom that I emailed someone on the Visual Studio team about it to ask if it was a known problem. He was at the launch event, but he forwarded my email to a few other people, who forwarded it to a few more people, until finally someone responded:
Hi Martin,
The most probable cause is one of two things: you are using this file in a solution where it is included by multiple projects/files with different macro contexts. In VS2008 we can only interpret the file once in one context (something we’ve fixed in the next release). The other reason is that you have not specified the full set of macros but I doubt it since you say it builds. If you can isolate this into a small repro, we’d be happy to look at it.
It wasn't either of those problems. When I went to try to isolate a minimum set of files to reproduce the problem, however, I was surprised by what I found. As I wrote back:
I’ve isolated the problem. I’ve also fixed it for now.
In the original ATL project, the CPP file correctly showed the first block that had been #ifdef’d out in gray, but showed subsequent blocks #ifdef’d out using the same name in color. Also, every symbol below a certain point was treated as undefined, even very common symbols like S_OK.
I created a new ATL project, added the problematic CPP file to it, and brought it up for editing. Once the IDE had processed the file, and before I tried to compile, the #ifdef’d blocks all displayed in gray as I expected, and all expected symbol values displayed properly on a mouse hover.
When I switched back to the original project, I immediately saw a message in the output box on the order of “can’t open source database,” along with some irrelevant suggestion about it being open in another project. (If this message was there before, I didn’t notice it.) I closed devenv, deleted the .NCB file for the solution, and reopened the solution. After a pause, all was well.
I remember corrupted .NCB files being a recurrent, nagging problem in Visual Studio .NET, but I thought that was behind us. Apparently it’s still an issue in VS08.
The response was good news:
Indeed, the frequency of the problem has been greatly reduced but given the difficulty in reproducing those problems, we can never be sure to remove it completely. You’ll be happy to know that our next release has completely overhauled this architecture and we’ll be able to safely say that this type of thing won’t ever occur again.
Needless to say, I'm looking forward to Visual Studio 2008 SP1.
Posted by Martin Heller on February 27, 2008 11:30 AM
February 25, 2008 | Comments: (0)
Leaving Windows 9x behind to move forward
Last August I wrote about maintaining backward compatibility to versions of Windows from 15 years ago while supporting new features of Windows Vista. Several of you had trouble believing I would continue to go to all that trouble.
I have finally given up, although not voluntarily.
As it happens, I had to merge some code from a program into an ActiveX control. The program is compiled with Visual Studio 2005 (VS05), maintained by another developer, and runs on Windows 2000, XP, 2003 and Vista. We haven't yet tested it on Windows Server 2008.
The ActiveX control was compiled with Visual Studio .NET 2003 (VS03) and ran on Windows 95 and up. When I tried adding the new code and compiling in VS03, it was clear that I'd have my work cut out trying to remove all the calls to new library functions to get it to compile without errors. Then I'd have to face updating my branched code every time the developer did a maintenance release. There was too much code for me to go the conditional compilation route and get this working in a reasonable amount of time.
I tried upgrading the project to Visual Studio 2008 (VS08). The new code compiled without warnings, but my old code had bunches of errors and warnings. Fortunately, the errors were all from duplicate definitions, and it was easy enough to remove the inline definitions that were now coming from the default SDK. The warnings were mostly to get me to update to "safe" string functions: that can wait until I have time, since this code has been heavily tested over many years.
I got the new code working and tied into the proper ActiveX interfaces, and started testing it on my array of Windows computers and virtual PC images. When I got to the Windows 98 SE Virtual PC, I discovered that the control wouldn't load.
I explored the DLL with "depends" and discovered that the new code uses five kernel functions that weren't introduced until Windows 2000. Using my standard techniques, I wrote a dynaload class for those five functions and modified the code to use them.
The control still wouldn't load in Windows 98.
To make a long story (think days of failed experiments) short, we discovered that VS08 no longer targets Windows 9x. Apparently VS05 doesn't, either. There are a couple of kernel functions called by the C++ libraries that require later versions of Windows. In order to get this control built in VS08 to work on Windows 9x, I'd have to make custom modifications to the C++ libraries and link to them. I'd also have to reapply my changes every time Microsoft updated the libraries.
That was the last straw for me. I reverted to the version of the control without the last group of dynaloads, and I now plan to leave Windows 9x behind. There's no real business reason to keep supporting it, and now there would substantial costs in attempting to do so.
I might wish that Microsoft had continued to target Windows 9x in VS05 and VS08, but I can't really blame them. They, too, need to leave the past behind in order to move forward.
Posted by Martin Heller on February 25, 2008 01:12 PM
February 06, 2008 | Comments: (0)
Writing Secure ActiveX Controls
This recent news story touches on a long-standing problem:
The fact is, writing secure ActiveX controls is an art, not a science. To succeed, a software developer has to look beyond the intended purposes of the interfaces, to other purposes for which they might be used.
Say, for instance, that I wrote an interface to upload files to a site, intended to be run on a well-known safe site. If I had written it in a broad way so that it could be used to silently upload any file to any site, then a malicious site could detect the control and use it to upload Quicken files to steal peoples' financial information.
One safeguard is to be noisy about what you're doing. My ActiveX controls pop up simple OK/Cancel permission dialogs the first time they are invoked in a browser session; the dialogs say what they are going to do and what sites they were intended to work on. That's simple, and only mildly annoying. Of course, users tend to get jaded and accept such dialogs without thinking, but darkening the screen and sounding the klaxon horn of doom probably won't help in the long term.
Another safeguard is to actually check the site currently in use. That's a little harder, but it's possible. Internet Explorer supports a service called IWebBrowser2, which has an interface called get_LocationURL. This returns the URL of the calling page as a BSTR, and you can then use InternetCrackUrl from the wininet library to extract the domain and see if it's on your white list of safe or licensed domains.
A third safeguard is to restrict the functionality of the interface. Perhaps I want the control to upload images. If that's the case, I could restrict the file types it will upload to .GIF, .JPG, .PNG, and .TIFF. The control could also double check that the files were valid before uploading them: there's a reason that .TIFF files all have the number 42 in a specific place.
And yes, 42 is the answer to "life, the universe, and everything."
Do you write ActiveX controls? If so, how do you protect them from malicious use?
If you write Flash controls, how do you protect them?
Posted by Martin Heller on February 6, 2008 07:10 AM
December 14, 2007 | Comments: (0)
I've learned a lot of languages, both human and computer. When I learned Latin in High School, it mostly helped my English. When I learned German, I had both help and interference from my knowledge of Yiddish; ditto for when I learned Dutch. Similar things happened with Russian (college) and Chinese (grad school), although that wasn't quite the same mechanism: my brain would sometimes serve up a word from a different language than the one I was trying to speak.
As I mentioned Wednesday, there are some common constructions that have different meanings in the different languages that were inspired by C. The new object constructor isn't the only place where subtle errors can occur if you get confused.
On the other hand, learning Pascal back in the day mostly helped my Fortran. Learning many different assembly languages didn't seem to cause any interference: writing assembly language was such a painstaking process that I could usually remember what processor I was writing for at the time.
I hear from people who would rather write Java or C# than mess with JavaScript. They're the kind of people who like tools like GWT and Script# and Volta. I also hear from people who would much rather write JavaScript than Java or C#.
Do you program in more than one language? On balance, does already knowing one programming language help you to learn another, or do the languages interfere with each other and cause you to make errors? Do you find yourself preferring one language over another?
Discuss.
Posted by Martin Heller on December 14, 2007 08:18 AM
October 05, 2007 | Comments: (0)
.NET Library source welcome, but not earth-shattering
With all due respect to the esteemed Senator from MuleSource, I wonder what Dave Rosenberg has been smoking. In this blog posting, Dave says that Microsoft's release of the source code to the .NET Libraries is "a patent trolling dream."
I've dealt with my share of patent trolls (I was an expert witness defending against a big one), but I'm also an experienced developer who is familiar with Microsoft development tools.
Microsoft has shipped the source code to its C/C++ runtime libraries with Visual Studio for many years. The practice of publishing copyrighted source code is hardly new: it goes back at least to DEC and IBM. For example, I used to read Dave Cutler's source code for RSX-11M in the 1980s, and I read IBM VM-370 system routines in the 1970s.
If I look in my C:\Program Files\Microsoft Visual Studio 8\VC\crt\src directory or my C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src directory, I can view the source code for any of the C/C++ runtime library, MFC, and ATL routines. Sure, the source code starts with a Microsoft copyright claim, but frankly I don't care:
/***
*abs.c - find absolute value
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines abs() - find the absolute value of an int.
*
*******************************************************************************/#include <cruntime.h>
#include <stdlib.h>#pragma function(abs, _abs64)
...
What's important to me is that I can debug into the library routines if and when they are implicated in programming problems. abs() is a bad example, because it's not something I'd misuse, but there have been plenty of times when being able to debug down into the library has shown me where I've gone astray.
What about the .NET Framework libraries? Well, for one thing, for the basic libraries I can refer to the .NET Framework Standard Library Annotated Reference (Addison-Wesley, 2004 and 2005), of which I was an editor, and find out not only how whole classes and specific members work, but what the designers were thinking. For another, I can use Lutz Roeder's .NET Reflector and see the source code reconstructed from the compiled code, along with the documentation.
Why does that work? Mostly, because the .NET Framework compiles to an intermediate language (IL), not native code. The IL gets JIT-compiled at runtime (or at installation time for the libraries), but that doesn't interfere with the IL and metacode information in the assembly.
In addition, Microsoft chose not to scramble or obfuscate the .NET library code. They have always wanted developers to understand how the library works.
So what's new? Three things: more libraries are being released as source than are covered by the ECMA/ISO standards; we'll be able to debug directly into the library source; and we'll be able to see the internal comments. If history is any guide, the internal comments will be rife with misspellings:
*Exit:
* returns the aboslute value of number
Brad Abrams has a posting about the source release here. He in turn links to a posting by Scott Guthrie and a podcast by Scott Hanselman and Shawn Burke.
Posted by Martin Heller on October 5, 2007 08:18 AM
September 28, 2007 | Comments: (0)
Static Path Analysis and Embedded Systems
In my posting about embedded systems on the 19th, I asked how companies could guarantee the reliability of complicated embedded systems. One set of generic guidelines for this comes from Barry Boehm of USC: see, for example, the Software Reduction Top 10 List.
I know of three vendors addressing this in the embedded space: Coverity, Klocwork, and Parasoft. One technique that all three of these vendors use is static path analysis.
In response to my question about guaranteeing reliability, I got this email from Gwyn Fisher, CTO of Klocwork:
There are software assurance compliance standards that require mission critical systems (e.g. avionics) to provide validation that they've inspected every code path, normally through a combination of manual and automated techniques. This is about as close to a reliability guarantee that exists today, from a software assurance perspective. This is expensive but can be effective for small systems, however, for large, multi-million LOC embedded systems it becomes a more difficult problem to solve. It will always be hard to guarantee reliability for systems of this size and complexity but organizations are engaging in aggressive risk reduction strategies through the use of advanced code analysis techniques. These complement traditional testing techniques and code review methods and provide feasible and cost-effective means that allow an automated tool to at least investigate all code paths for a wide variety of potentially debilitating errors (including difficult to test areas of a system such as error handling routines). The tool makes decisions on which paths are feasible or not, hence worthy of further inspection, enabling the right balance between scalability and intelligent code and defect coverage. If a system can be made free of programming errors through this type of automation, then further along in the development process is subject to rigorous runtime testing, organizations can go a long way to dramatically reducing the risk of field failure and increasing the reliability of business and mission critical embedded systems.
Most developers spend the majority of their time on the true path. Most designers spend most of their time laying out what should happen on the true path. Peer code reviews focus on reviewing the main paths in a system. Most QA organizations spend most of their time testing that the true path does what it’s supposed to do. What about the rest of the system?
Static analysis brings the potential for agnostic coverage:
- Test the false path just as well as the true path
- Validate that the false path doesn’t lead to failure, even in the most “corner” of edge cases
- Ignore a developer’s / designer’s instinct to rigidly peer review only the most “core” of the available code paths – review all feasible paths at all timesThis should be a strong notion for embedded software, since field failure can be very expensive. With current testing techniques it's very difficult to test "edge cases", so static analysis enhances testing coverage for embedded software.
Posted by Martin Heller on September 28, 2007 07:54 AM
August 16, 2007 | Comments: (0)
Maintaining Backward Compatibility
One of the banes of my existence is maintaining backward compatibility to versions of Windows from 15 years ago while supporting new features of Windows Vista. It's quite a juggling act.
I use three tactics. The first is pre-emptive: every time I write new code that includes Windows APIs, I double-check the requirements of the APIs on MSDN. Often I'll find that I want to use an API that doesn't work on Windows 9X systems, or that only works in Windows Vista and above.
The second tactic is adaptive: I dynamically load the DLLs and entry points that aren't compatible with all the systems my software supports. This is a real pain in the neck, but I have some class libraries that make it less painful than writing all the Windows API calls and C++ type casts that would otherwise be needed.
The third tactic is one of testing. I have five computers in my office that cover a range of Windows versions, and one of them has Virtual PCs that cover most of the other Windows versions, plus a bunch of Linux versions. When I create a new build, I test on all the Windows versions I have covered.
When there's a problem loading the software on one or more systems, I run the Microsoft dependency walker tool depends.exe against the software on those systems. Usually, that's enough to help me locate the problem or problems, although sometimes I have to go back to MSDN and read the API descriptions again, carefully. Sometimes there are obscure notes about #include files or libraries that need to be used for compatibility with older systems; using these workarounds generally fixes the problems. It's still a pain in the neck, however.
Q: How did God create the world in seven days?
A: He didn't have an installed base.
Posted by Martin Heller on August 16, 2007 09:33 AM
July 25, 2007 | Comments: (0)
When I wrote about my Web Service Blues on July 11th, I had no idea that I'd still be singing them two weeks later. But I was. The short summary of the issue is that my unmanaged Microsoft Visual C++ Web service client couldn't parse the response from a Microsoft ASP.NET 2.0 Web service.
Every day or two, I'd think of something that could be wrong, come up with a way to test my hypothesis, do the experiment, and see yet another idea go down in flames. Maybe I was formatting the GUIDs incorrectly? We created another Web service call that took strings: ffft.
Maybe the response was malformed? SoapScope didn't think so. And nothing we did to the Web service output changed a thing.
I combed the MSDN news groups. Were people writing C++ clients for Web services? As far as I could tell, yes. I searched the documentation: was there a known problem with C++ WSDL import or parsing? Not that I could tell. I tried porting the project from Visual Studio .NET 2003 to Visual Studio 2005, the same generation of tool used for the service: surely the situation would improve. Nope.
Finally, a query to the Microsoft C++ team, sent through an old friend, got me an answer. It wasn't what I wanted to hear, but it freed us to pursue a RESTful API rather than an XML Web service API.
What you're encountering is very likely by design. We stopped evolving the native Web services stack shortly after we released VS 2002 and now it is a deprecated part of the product (and removed for the 2008 release). Lots of functionality was added to SOAP, WSDL and the entire range of WS* standards after that time (in fact more than 10x the original feature set counting by pages of specs). However we have moved this code to CodePlex at http://www.codeplex.com/AtlServer.
If you have specific problems, the VC++ team has offered to be as helpful as they can, but they encouraged me to encourage you to try working with the sources of ATL Server first.
So there it is: if you want to write a Web service client using Microsoft technology, do it in managed code. Use the .NET Framework. Better yet, use the Windows Communication Foundation.
C++ programmers who insist on trying to make Web services work in native code, write this in your documentation: Here be Dragons.
Posted by Martin Heller on July 25, 2007 12:35 PM
July 11, 2007 | Comments: (0)
One of my software development clients is licensing a Windows application to another software company, for bundling with that company's own product, and I was tasked with integrating this unmanaged C++ application (compiled with Visual Studio .NET 2003) with the other company's C# 2.0 application and ASP.NET 2.0 Web site for licensing. It seemed simple enough.
At first, my opposite number at the licensee and I agreed on a licensing scheme in which their software would write an encrypted license code and expiration date in the registry for our software to read. Then we realized that a simple clock setback attack could effectively extend someone's subscription indefinitely. So, we decided to create a Web API for license verification.
There were two obvious choices: a RESTful API, and a Web Service API. We both had experience with both kinds of Web APIs, and neither of us had a strong preference. For me, it seemed like implementing the RESTful client would have been a matter of adapting a function that was already in the program. Implementing the Web service client seemed like a matter of importing some WSDL and letting Visual Studio generate a proxy, then instantiating and calling the proxy.
We decided on the Web service, because it looked a little easier to implement at the server. It took them under an hour to put up a stub service; it took me under an hour to import the WSDL, generate the proxy, and write the call. It took me about a day to write the rest of the code needed to process all the necessary parameters and handle all the possible error conditions.
When it came time to test the code, I found that the Web service call never returned. My counterpart supplied a C# client that demonstrated that the service was working and could be called from my machine, so I massaged my code and tried again. This time the Web service call returned, but with an error. Further debugging showed that the C++ proxy code couldn't parse the reply from the Web service.
As we fade out to a commercial, my counterpart is trying to make the C++ equivalent of his C# test client work on his machine. The last I heard, he was having the same trouble that I had.
I wrote Web service code, it seemed like the thing to do,
Yes I wrote Web service code, it seemed like the thing to do,
But the client hates the server, and it makes its Daddy blue.
Posted by Martin Heller on July 11, 2007 07:59 AM
June 18, 2007 | Comments: (0)
I knew there had to be a way for a 32-bit application to access the 64-bit registry on a 64-bit system, and I finally found it. Don't ask me what I think of the way Live Search works on the MSDN site, however: the answer would curl your hair.
What I needed to know is mostly buried in an MSDN article called Accessing an Alternate Registry View, which is in the MSDN tree under MSDN / MSDN Library / Win32 and COM Development / Development Guides /Programming Guide for 64-bit Windows / Running 32-bit Applications.
Normally, a 32-bit application only sees the 32-bit registry, and a 64-bit application sees the whole registry. The 32-bit registry is filed under the Wow6432Node key. Looking under the Wow6432Node key is bad practice, however, since that location may change in the future.
Basically, if an application that wants to scan the whole registry detects that it is running on 64-bit Windows, it needs to scan the registry twice: once to get the 32-bit registry keys, and once to get the 64-bit registry keys. Two flags apply:
| Flag name | Value | Description |
| KEY_WOW64_64KEY | 0x0100 | Access a 64-bit key from either a 32-bit or 64-bit application. |
| KEY_WOW64_32KEY | 0x0200 | Access a 32-bit key from either a 32-bit or 64-bit application. |
These flags can be specified in the samDesired parameter of the following registry functions:
Once you have opened a key with one of these flags, subsequent enumeration of the registry continues from the key you opened. Your application does have to be careful to be consistent: if a 32-bit application decides to delete a key that it found using the KEY_WOW64_64KEY flag, it had better use the same flag on the RegDeleteKeyEx call.
By the way, you can simulate the registry view of a 32-bit application for yourself. On a 64-bit system, there are two copies of Regedit. Running "regedit" launches the 64-bit version. Running "c:\Windows\syswow64\regedit.exe –m" lets you launch the 32-bit version. The "-m" flag allows multiple instances of the Registry Editor to be open.
Posted by Martin Heller on June 18, 2007 06:00 AM
June 08, 2007 | Comments: (0)
I mentioned a couple of weeks ago that applications certified to run on Windows Vista must run on x64 as well as 32-bit Vista. Wow64 makes this easy for most 32-bit Windows applications: they automatically run in a 32-bit compatibility environment and never know the difference unless they check the IsWow64Process API.
I said then that a tester had found that merely running certain applications would screw up the keyboard and mouse on Vista for x64. This report turned out to be irreproducible: as far as we can tell, it was a matter of a bad driver installation for a wireless mouse and keyboard. When I tried the same application on a laptop with Vista for x64 installed, I couldn't make the problem happen. When the tester scrubbed his system and reinstalled everything from scratch, the problem went away.
Testing the application on 64-bit Vista made it clear that Wow64 is not an unalloyed blessing. For a system utility, the sandboxes drastically reduce what the program can do. A 32-bit program scanning the 64-bit registry can only see the registry hives under Wow6432Node. A 32-bit program scanning for running programs can only see itself and any other 32-bit programs running in the Wow64 environment.
Next week I'm probably going to have to build a 64-bit version of this C++ application. Based on what I went through 15 years ago making 16-bit Windows programs work on 32-bit Windows, I'm not looking forward to the exercise.
Posted by Martin Heller on June 8, 2007 06:00 AM
May 25, 2007 | Comments: (0)
On the day before WinHEC, the marketing VP of one of my smaller clients asked me to fix a problem with one of their applications. The CTO was in a plane on his way to WinHEC; the developer who used to own the project had left for another job; and the new developer was in the middle of a major modification to the program that wasn't in a buildable state. "Just take the current sources, drop in this one revised C++ file that the new developer sent me, and build it. The current version won't run at all on Windows 2000, and I've got customers that need it now."
What could be bad? It sounded like a five-minute job. Of course, let's not forget that everything is easy for someone who doesn't have to do it.
I checked the project out of the repository. There were two branches in the tree, marked 1.0 and 1.1, so I checked out the most current sources from 1.1. There were no tagged versions. The CTO was the only one who would know which branch I should use, and he was on a plane. I promptly forgot that I'd guessed at the correct branch.
I dropped in the new file, and tried to build the sources with Visual Studio .NET 2003, which was the IDE the previous developer had used. There was a problem: a source file that had nothing whatsoever to do with the issue being fixed wouldn't compile on my installation of Visual Studio 2003. I tried a bunch of things over the next several hours, and the next day I sent an email off to the marketing VP, the new developer, and the CTO (who was at WinHEC and off email):
I can't build the project in Visual Studio 2003: it looks like it needs the current Platform SDK, which I don't have installed on the machine with Visual Studio 2003 because I think it will break another project. I can't build it in Visual Studio 2005, either: it has 12 errors and 198 warnings.
It was becoming a case of not being able to drain the swamp because of the alligators. Eventually, I fixed that problem, and sent off another email to the same people:
I have managed to build the project in Visual Studio 2003 by removing the reference to wincred.h. It appears to have been unused.
I tested the new build on a Windows 2000 Virtual PC, and it loaded and ran fine, so I checked in the sources, and sent the new setup file to the marketing VP for broader testing. Running on one Virtual PC image isn't much of a test, and I wanted to make sure that fixing one problem hadn't introduced others.
The following week, the testers came back with a bunch of errors. Some of them were errors that had been fixed by the version that broke compatibility with Windows 2000. I suspected that I hadn't built from the most current sources, and that the former developer hadn't checked in his latest changes. Fortunately, by then the CTO was back from WinHEC and had caught up on his email: he contacted the former developer, who claimed that the repository was up to date.
The two of us got on the phone, and looked through the source history together trying to figure out what was wrong. Finally, the CTO remembered that the previous production version had been built from the 1.0 directory of the repository: the 1.1 directory was intended as an experimental development branch. D'oh.
We're going to restructure the repository with trunk, branches, and tags directories so that this doesn't happen again. Meanwhile, don't let this happen to you.
Posted by Martin Heller on May 25, 2007 06:00 AM
April 25, 2007 | Comments: (0)
Not quite 20 years ago, I was consulting for Symbolics, working on a Windows front end for PC Macsyma. I was writing Windows code in C, and working closely with a Symbolics LISP programmer named Frank.
One day the two of us were in my office trying to debug my callback interface between Windows help and the Macsyma engine, which enabled running live demos from help files. After watching me sweat out the semicolons and curly-brace-matching and the pairing of LocalAlloc calls with LocalFree calls and the obsessive care about resource leaks that writing Windows C code required, Frank said "Y'know, Martin, you should switch to LISP. It would be like a little vacation for you."
Of course, it was true: compared to LISP on a Symbolics workstation, I was working with flint knives and bear claws. I think I had an 80386-based PC, and was developing for Windows 3.1 using Microsoft C and the Brief editor.
Fast forward to 2007. I'm still tackling the hard stuff, but it's C++ with ATL, in ActiveX controls. I have much better editing and debugging tools, but I still have to be obsessive about resource leaks. I do get to go on a "little vacation" once in a while, but it's not to write LISP: it's to write C#, or sometimes Python.
I'm just finishing up a little sample site in C# and ASP.NET: my vacation is almost over. Pretty soon, it'll be back to the C++ salt mines for me.
Actually, I'm kind of looking forward to it.
Posted by Martin Heller on April 25, 2007 06:25 AM
April 20, 2007 | Comments: (0)
Detecting Vista Integrity, for Real
On April 6th and 9th I presented some sample C++ code I found on a Microsoft site for detecting whether IE is in protected mode and detecting the integrity of a Windows Vista process. In fact, as I found out when I went to implement it, that code doesn't even compile unless you have the Vista SDK installed.
With a little work, I was able to extract the essential symbols from the version of WinNT.h in the Vista SDK, and make the code compile in a normal environment. I also added some code to detect whether Windows Vista is running, and bail if it is not. I'm not quite sure what would happen if you called GetTokenInformation with a flag of TokenIntegrityLevel on an operating system that doesn't have that value defined, and I'd rather not find out.
//from Vista WinNT.h typedef struct _TOKEN_MANDATORY_LABEL { SID_AND_ATTRIBUTES Label; } TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL; #define SECURITY_MANDATORY_UNTRUSTED_RID (0x00000000L) #define SECURITY_MANDATORY_LOW_RID (0x00001000L) #define SECURITY_MANDATORY_MEDIUM_RID (0x00002000L) #define SECURITY_MANDATORY_HIGH_RID (0x00003000L) #define SECURITY_MANDATORY_SYSTEM_RID (0x00004000L) #define SECURITY_MANDATORY_PROTECTED_PROCESS_RID (0x00005000L) #define TokenIntegrityLevel (TOKEN_INFORMATION_CLASS)25 // 0 if it fails, 1 if low, 2 if medium, 3 if high STDMETHODIMP CIE::get_Integrity(BYTE* pVal) { *pVal=0; //return if not Windows Vista or later OSVERSIONINFO osvi = {0}; osvi.dwOSVersionInfoSize=sizeof(osvi); GetVersionEx (&osvi); if(osvi.dwMajorVersion<6) return S_OK; HANDLE hToken; HANDLE hProcess; DWORD dwLengthNeeded; DWORD dwError = ERROR_SUCCESS; PTOKEN_MANDATORY_LABEL pTIL = NULL; //nb: Vista SDK definition DWORD dwIntegrityLevel; hProcess = GetCurrentProcess(); if (OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_QUERY_SOURCE, &hToken)) //nb: Win NT+ only, not Win9x { // Get the Integrity level. if (!GetTokenInformation(hToken, TokenIntegrityLevel, //nb: Win NT+ only, not Win9x NULL, 0, &dwLengthNeeded)) { dwError = GetLastError(); if (dwError == ERROR_INSUFFICIENT_BUFFER) { pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwLengthNeeded); if (pTIL != NULL) { if (GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwLengthNeeded, &dwLengthNeeded)) { dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, //nb: Win NT+ only, not Win9x (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid)-1)); if (dwIntegrityLevel < SECURITY_MANDATORY_MEDIUM_RID) //nb: Vista SDK definition { // Low Integrity *pVal=1; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { // Medium Integrity *pVal=2; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) { // High Integrity *pVal=3; } } LocalFree(pTIL); } } } CloseHandle(hToken); } return S_OK; }
Posted by Martin Heller on April 20, 2007 06:00 AM
April 13, 2007 | Comments: (0)
Every once in a while, I have the experience of needing to do something that I knew how to do very well 5 or 10 or 20 years ago, but have forgotten. Take getting cross-references in C++ programs.
It used to be that the Microsoft C++ build process would run a separate step to generate cross-reference files, so that when you were editing you could quickly find all the places that you had called the Foo() function, to make sure that the redesign you had in mind for that function would actually work. When some version of Visual C++ added a class browser, there wasn't nearly as much need for the hard-core cross-references, so the step to build the rarely-needed cross-reference files was turned off by default.
The other day, I needed to turn that on again in Visual Studio .NET 2003. It took me forever to find the user interface for it, which was right under my nose, in the Configuration Properties dialog under General/Build Browser Information. I had been looking much lower down in the properties, where there were other things that controlled Browser Information, but none of those mattered a whit until the top-level switch had been thrown.
By the way, the secret keys for finding the next and previous references in VS03 are Ctrl-Shift-1 and Ctrl-Shift-2. They aren't documented anywhere, as far as I know: Dave Methvin found them in an Internet search.
Part of the reason I couldn't find the Build Browser Information is that when I really want to understand someone else's C++ project, I usually either fire up SlickEdit or Source Insight. Both of these editors build their own tags files and use them to help you navigate source files.
My copy of Source Insight 3.5 dated from 2003. It still worked fine on Windows XP. There's a new version available that works on Windows Vista and fixes a bunch of bugs that I never encountered. I downloaded it and upgraded on general principles. The Source Insight folks generate updates every couple of months, but I have never felt the need to upgrade. Source Insight is probably the best editor around for understanding big projects.
My copy of SlickEdit 2007 is fresh, and adds a few nice features, like a new class view, and more Python language support. SlickEdit is still the only editor around that does a creditable job of C++ refactoring. It can also open and build existing Visual Studio projects, so I tend to use it a lot for C++ programming.
So why didn't I use one of these rather than Visual Studio .NET 2003? I did, for myself, but the other two programmers working on the project didn't have them.
Along the way, I found a bunch of other cross-reference tools that might do someone some good:
http://www.codeproject.com/dotnet/GoBackAddin.asp
http://www.codeproject.com/macro/kingstools.asp
http://www.stack.nl/~dimitri/doxygen/
http://www.ph.unimelb.edu.au/~ssk/kde/kdoc/
http://home.att.net/~srschmitt/xref/xref_dos_3.html
Posted by Martin Heller on April 13, 2007 06:00 AM
April 09, 2007 | Comments: (0)
Detecting IE7 Protected Mode, Take 2
On Friday, I posted one method that an ActiveX control or IE toolbar can use to determine whether IE 7 is running in Protected Mode. After thinking about this some more, I realized that there are many other ways to accomplish the same goal.
Much of the primary information on IE7 Protected Mode can be found in an MSDN article, Understanding and Working in Protected Mode Internet Explorer. That article mentions the IEIsProtectedModeProcess function I talked about on Friday, but it also explains some of the other characteristics of Protected Mode and Vista UAC mode. For example, Protected Mode modifies IE's environment, so that the Windows GetTempPath() API will return the value of %Temp%\Low rather than the value of %Temp% when Protected Mode is active.
Later in the article, the authors give a code sample, ShowProcessIntegrityLevel(), shown below, that looks at the current process token and determines its integrity level. The integrity level actually tells us more than just whether Protected Mode is enabled.
If we are in Protected Mode, the process integrity will be Low; if we are running as a normal user or running in UAC mode, the process integrity will be Medium; and if we are running as Administrator, the process integrity will be High. An ActiveX control that wants to expose the integrity level to JavaScript through a COM interface could run a variation on this code and return a short integer that is 0 for Low Integrity (Protected Mode), 1 for Medium Integrity (Normal User/UAC mode), and 2 for High Integrity (Administrator).
I really wish this was already built into IE 7, but it'll do.
void ShowProcessIntegrityLevel() { HANDLE hToken; HANDLE hProcess; DWORD dwLengthNeeded; DWORD dwError = ERROR_SUCCESS; PTOKEN_MANDATORY_LABEL pTIL = NULL; LPWSTR pStringSid; DWORD dwIntegrityLevel; hProcess = GetCurrentProcess(); if (OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_QUERY_SOURCE, &hToken)) { // Get the Integrity level. if (!GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &dwLengthNeeded)) { dwError = GetLastError(); if (dwError == ERROR_INSUFFICIENT_BUFFER) { pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwLengthNeeded); if (pTIL != NULL) { if (GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwLengthNeeded, &dwLengthNeeded)) { dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid)-1)); if (dwIntegrityLevel < SECURITY_MANDATORY_MEDIUM_RID) { // Low Integrity wprintf(L"Low Process"); } else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { // Medium Integrity wprintf(L"Medium Process"); } else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) { // High Integrity wprintf(L"High Integrity Process"); } } LocalFree(pTIL); } } } CloseHandle(hToken); } }
Posted by Martin Heller on April 9, 2007 06:00 AM
April 06, 2007 | Comments: (0)
I have been wondering if there's a way that a Web page can tell if it's running in IE7 Protected Mode on Windows Vista. It turns out that yes, there is, but it's not as simple as I'd like.
My hope was that there would be flags that a page could check from JavaScript: ideally, a flag that says either
- "I'm in Protected Mode"
- "I've got normal privilege", or
- "I'm running as Administrator".
I didn't find anything like that, even though IE 7 displays the Protected Mode status to the user. What I did find is an IE API, the IEIsProtectedModeProcess Function, which can tell a caller whether or not IE is a Protected Mode process by setting a BOOL parameter TRUE or FALSE.
It's in ieframe.dll, but only for IE 7 or later. And it is only supported in Microsoft Windows Vista or later. If you call it from earlier versions of Microsoft Windows, this function returns E_NOTIMPL as its HRESULT.
So, if I have this right, I could call this function from an ActiveX control or an IE toolbar, after first dynamically loading it from ieframe.dll. If I called it from an ActiveX control, then the ActiveX control could in turn expose a COM property to JavaScript. I know how to do that.
This seems like scratching your left ear with your right hand, doesn't it? But it should work.
Now I have to figure out how to safely tell if the IE process is running as Administrator. Somehow, I don't think trying to reformat the system drive would be an ideal test.
Posted by Martin Heller on April 6, 2007 06:00 AM
March 26, 2007 | Comments: (0)
Dave Methvin, Rob Cheng and I founded PC Pitstop in 1999. From the beginning, it was a classic Windows DNA site: we wove together an ActiveX control, quite a bit of client-side JavaScript, ASP server code also written in JavaScript, and a SQL Server database. The idea was to quickly and automatically diagnose most common PC ailments.
If I remember correctly, we started out supporting Windows 95 and Windows 98, then added Windows NT and Windows 2000. Over the years we kept updating the site to do more and to support new systems as they were released. I stopped working on it full time after the dot-com bust and terrorist attacks of 2001, which together ruined the market for banner advertising. I continued to consult for the site on and off, and became more active again last summer.
Because PC Pitstop tests tens of thousands of computers every month, we have a pretty good idea about industry trends. We try to anticipate them a little when we think they'll need new code for proper support, but we also find out rather quickly when there are breaking changes from new hardware or new systems.
Last week I finally bit the bullet and started trying to fix the tests that didn't work properly on Windows Vista. There were 8 problems that we were able to identify when people came to the site with Internet Explorer 7 in the default Protected Mode on Windows Vista:
- The CPU Load was not tested
- Running Programs only listed one: IE
- All outgoing pings were lost
- Disk fragmentation was not tested on C:
- Disk speed was not tested on C:
- No CD or DVD drives were detected
- Could not obtain monitor information
- Got incorrect results for the size of the junk files
I tracked down the C++ code in the ActiveX control that does each of these tests, and realized that some of the failing tests were trying to do things that require Administrator privilege on Windows Vista, but that others were doing things that only require normal privilege. IE didn't even have normal privilege, however, because it was running in Protected Mode, which flags itself as a low integrity process.
The whole point of Protected Mode is that sites can't use it to install malware without your permission: if they try, you'll get an elevation prompt that you'll find it hard to ignore. The whole point of PC Pitstop is that we're the good guys, trying to detect suboptimal system settings, low performance, and malware that is already on your computer.
I did three experiments. I verified that all 8 issues happen in Protected Mode. I determined that three problems go away, two completely and one partially, with IE's Protected Mode off. And finally I determined that all tests run correctly when IE is run with Administrator privilege.
I looked at alternative ways to execute the tests that might work with Protected Mode enabled, because I really wanted the site to work that way. I found a way to detect CD and DVD drives using WMI, but the information returned isn't as complete as we get by using the low-level SCSI and ASPI interfaces, so I think that's just a back-up plan. I found a simple way to fix the disk speed problem that I think will be fine on most systems, which involves putting the test file into the temporary directory if the temp directory is on the drive being tested.
There were so many issues that I couldn't fix, however, that I came to a sad realization: PC Pitstop will only run properly on Windows Vista if the browser has Administrative privilege. Like the janitor in your building, we can't clean up after you unless we have the keys to the office.
Posted by Martin Heller on March 26, 2007 06:00 AM
January 22, 2007 | Comments: (0)
Elliptic Curves, Suite B, and CNG
In discussing the Visual Studio Code Name "Orcas" January 2007 CTP I mentioned its managed classes for Elliptic Curve Diffie-Hellman and Elliptic Curve Digital Signature Algorithm cryptographic functionality. No, I didn't expect you to know what that means, but explaining it right then and there would have been a distraction.
We'll need to start with Suite B. This is a set of cryptographic algorithms provided by the NSA to be used in addition to the Advanced Encryption Standard (AES) for for hashing, digital signatures, and key exchange. (Yes, there is a Suite A. It "contains classified algorithms that will not be released. Suite A will be used for the protection of some categories of especially sensitive information.") But back to Suite B:
"The entire suite of cryptographic algorithms is intended to protect both classified and unclassified national security systems and information. Because Suite B is also a subset of the cryptographic algorithms approved by the National Institute of Standards, Suite B is also suitable for use throughout government. NSA's goal in presenting Suite B is to provide industry with a common set of cryptographic algorithms that they can use to create products that meet the needs of the widest range of US Government (USG) needs."
What do elliptic curves have to do with anything? Elliptic Curve Diffie-Hellman or Elliptic Curve MQV are the two recommended ways of doing key exchange in Suite B, and the Elliptic Curve Digital Signature Algorithm is the recommend way of doing digital signatures in Suite B. See this NIST paper if you're up for the details of how elliptic curve key exchange works, and this one for the digital signature standards, including the Elliptic Curve Digital Signature Algorithm.
This NSA paper explains why elliptic curve cryptography is attractive compared to the older RSA and Diffie-Hellman algorithms for public-key cryptography. The short summary is that RSA and Diffie-Hellman have slowly succumbed to increasingly strong attack algorithms, while elliptic curve cryptography has remained at full strength. From a practical point of view, that means that elliptic curve cryptography can provide greater security and more efficient performance, saving both cycles and bandwidth.
As has been noted elsewhere, Microsoft consulted the NSA and NIST about Windows Vista and got certification for its security, so that it would be able to sell Vista systems to the U.S. Government. To do that, Microsoft of course had to meet the current cryptography standards. The old CryptoAPI didn't support elliptic curve cryptography, so Microsoft came up with a replacement, Cryptography API: Next Generation (CNG).
CNG proper is an API intended to be used from unmanaged C++, and is currently only implemented in Windows Vista and Windows Longhorn Server. You can download the CNG SDK here.
It's not trivial to write managed code wrappers for the CNG API, so Microsoft has provided them. The managed classes for Elliptic Curve Diffie-Hellman and Elliptic Curve Digital Signature Algorithm cryptographic functionality are contained in the January CTP, which I haven't been able to install.Posted by Martin Heller on January 22, 2007 06:00 AM
January 12, 2007 | Comments: (0)
A Programmer's Toolbox, Part 1: Editing and C++ Development
I work on several different kinds of projects, in several different programming languages, on several different platforms. You would think that I would at least standardize on one editor for all of them, but I haven't.
If I were going to standardize on one editor, it would probably be SlickEdit, which works on all the different projects, languages, and platforms that I use. It is not cheap, but I already have a license, and it does lots of nice things. Alternatively, I could use GNU Emacs or XEmacs for almost everything I do. I don't particularly like Vi; if I did, I would probably use Vim. Most Linux distributions include versions of Emacs and Vi, or can add them easily; I often edit with Emacs when I'm working on Linux systems.
When I'm writing unmanaged C++ for Windows, I usually work in Visual Studio, either Visual Studio 2005 or Visual Studio .NET 2003. The versions of Visual Studio that I use are fairly expensive, but the free Express versions are more than adequate for individual developers.
Visual Studio makes it very easy to start projects, add classes, add methods and properties to classes, write correct code without spelling everything out, consult the documentation, and debug. I wouldn't bother with the older version, except that a colleague who works on some projects with me hasn't upgraded to Visual Studio 2005. It's annoying that projects can't easily be downgraded from Visual Studio 2005 to Visual Studio .NET 2003; if there is an easy way to do that, I haven't found it.
When I want to refactor more C++ code than I can be sure of doing correctly by hand, I check all my source files in and out of version control for safety, close Visual Studio, open the Visual Studio project with SlickEdit, and use SlickEdit's automatic refactoring functions. When I'm done, I switch back to Visual Studio, recompile, run whatever unit and regression tests I have, and check everything in again. Then I continue in Visual Studio for the usual editing, building, debugging, and testing cycle.
I wish Visual Studio could refactor C++ automatically, but it can't. I rarely find myself doing massive refactoring, in any case: I have been doing C++ development long enough that my first class design is usually fairly close to the final design. When I'm initially wrong, however, it's really nice to be able to refactor with SlickEdit.
Posted by Martin Heller on January 12, 2007 06:13 AM



