Cluebat-man to the rescue

A weblog dedicated to Visual C++, interoperability and other stuff.

Tech-ed Berlin 2009: Afterthoughts

All in all, tech-ed was worth it this year.

If you’re an an IT professional, then visiting tech-ed is a valuable learning experience. Even though most of my job involves off-the-shelf process control software, this software is still running on the Windows platform, and uses Windows and Microsoft technologies to work.

So for the purpose of administering and troubleshooting software on the windows platform, it is important to know how the software works, what it’s capabilities and configuration options are, and how it fits into the larger ‘Microsoft’ eco system.

By attending tech-ed and choosing the appropriate tracks, it is possible to keep a broad perspective. By knowing the important basic aspects of Windows 2008 and SQL server, Active Directory and other related things, I can get a better understanding, which will always come in handy eventually. Sooner or later we’ll run Windows 2008 and Vista, or ‘7’, or SQL server 2008, or something else.

And some things are downright practical already: The capabilities of powershell are astounding, and can definitely make life much easier in cases where now batch files are used that are not always easy to understand, or unable to provide much feedback when run as a scheduled task.

From that perspective, tech-ed was definitely a success.

Technorati Tags: ,,

Posted: Nov 16 2009, 02:47 PM by vanDooren | with no comments
Filed under: , ,
Installing Windows 7: Defeating the black screen

After tech-ed I am excited about developing for Windows 7, and playing with the parallel computing toolset that is going to be part of Visual Studio 2010. Since my existing partitions were already quite cramped, I thought I’d install 7 on a new disk so that I can put it on a 200 GB partition.

I bought a new 640GB Western Digital disk and set out to install Windows 7. all went fine until after the first reboot, when I got a black screen and my monitor fell in power save. I tried rebooting in safe mode but that didn’t work.

For some reason, Windows 7 can sometimes do something funky to the display settings, causing the video card to turn into a problematic mode.

After some fiddling around, I found out (thanks google) that I can press F8 to start Windows 7, and choose an option to force the video resolution to 640*480 and bot succesfully. I was then able to download the proper nvidia drivers, install them, and configure the proper display settings.

Technorati Tags: ,
Tech-ed Berlin 2009: Day 5

Check-out was a painless experience. I’d already packed my stuff yesterday so I was at the reception early enough to avoid the rush. The cloakroom in the Messe was organized properly so luggage drop-off was painless as well.

Time for a coffee and a quick e-mail check, and it was time for the first session of the day.

DEV307: Parallel computing for managed developers

This talk is hosted by Steve Teixeira.

It is a repeat of the talk that was held earlier this week. Despite that, the room is filling up nicely. When the session starts, the room is not completely packed, but just well attended.

From interviews with customers in large ISVs and game companies, there is still only a minority of programmers who program in parallel. Usually, the parallellimization (my spell checker claims this is not a real word J) is done by one or 2 programmers at most who do the infrastructure, and the rest of the team just makes their code so that it can hook into that. The number mentioned was that only a handful of percent of programmers program in parallel. This really surprised me, since I have been doing that for over 10 years, as I thought many people did.

One of the big reasons for this disconnect with the parallel world is that up until recently, thinking about parallelism meant that you had to think in term of actual execution flow instead of task based. Threads, locks, and the various patterns made it hard to focus on solving the actual problem at hand, because the concurrency plumbing around a parallel problem was so complex.

To ease the transition to parallel programming, Microsoft is working on a parallel programming toolkit that has all the basic plumbing in place so that programmers can start thinking about task based programming and letting the runtime take care of the gory guts underneath. This way, you, the programmer, are not forced to hammer your solution in a threading paradigm, and implement the guts to support cancellation, exception handling, and other things that can otherwise turn a seemingly simple threaded solution from simple to stupendously convoluted.

Steve is a natural born speaker, and again his presentation was a handful of powerpoint slides, interspersed with lots of demos and code explanations. This presentation was based mainly on the necessity to change the way we think about parallel execution.

CLI309: Sysinternals tutorials

This talk is hosted by Aaron Margosis.

Now that I see him, I recognize him as ‘the other guy’ whose name I forgot during the virtualization - > app compat talk.

His presentation included 3 powerpoint slides, and these were shown during the first 2 minutes. The rest of the presentation was a non-stop demo of some of the sysinternals tools and how they can be used.

I have been using these tools for over 10 years now, and they are THE tools you need during trouble shooting, debugging, or simply if you want to know what goes on under the hood. Despite the fact that I have been using them for so long, I still saw a couple of interesting features that I hadn’t seen before.

This talk went very smoothly, and Aaron is a great speaker. As with Mark Russinovich’s talk, the room was packed full. They had already changed the room assignment so that it was now in one of the biggest rooms of the convention center, but still it was packed.

There is little point in me trying to cover the contents of this presentation here. Just download the latest release of the sysinternals suite and start playing with it.

Lunch

The food aspect of the lunch was as basic as it gets: packed lunch. The turkey sandwich wasn’t bad though.

The company was great though. Steve and I finally managed to meet up and we spent an hour and a half catching up. That was really great, and one of the nice things about going to tech-ed. Not only is the learning experience extremely valuable, but you also get to meet people from all over the world.

Because of this, I missed the last session of the week. As usual, this wasn’t a real drama. The afternoon session(s) on the last day of tech-ed is/are usually less interesting because they factor in that many people are already leaving because of their flight times.

I had thought to attend Mark Russinovich’s talk about ‘The case of the unexplained…’ windows troubleshooting talk, which is would cover the various troubleshooting scenarios he was involved in, and solved with the sysinternals tools. I followed the blog series in which he wrote about those things so I didn’t miss a whole lot.

Day 5 wrap-up

Today was less intense, due to the fact that everybody is leaving today, and the schedule is set to that expectation. The talks were interesting though.

I am writing this from the starbucks at Tegel airport, and I have to admit that I misjudged the size of the mugs here. I chose the middle size because I thought that it was the size I am used to. The only reason I thought that, was the relation between the different sizes that were shown.

Now that I am actually holding it, I can conclude that they don’t use ‘small’, ‘medium’ and ‘large’, but ‘large’, ‘oversized’ and ‘humongous’.

I still have some time to fill before I can check-in for my home flight, so I can get something to eat and finish my reports. I’ve already checked with my colleague and there were no dramas at work so that is good.

I have to say that Tegel airport is a much nicer place to wait than Barcelona airport. There’s a lot of stores here, a starbucks, places to sit… and so far noone is looking me out of the premises because I am not actually buying additional coffee so that is nice.

My flight doesn’t leave for another couple of hours so I can do some development or begin on my tech-ed wrap-up report. It won’t be as extensive as the day posts, but I always like making a summary of the week.

I am already looking forward to home, and being able to hug my kids. Unfortunately, my wife is in the US at the moment, and it will be another week before I see her back.

I had an interesting experience at the security challenge though. I always carry a swiss pocketknife with me. You know the ones: with a file, screwdriver, can openener, a dozen other things, and of course, a blade. A couple of times I thought ‘I must not forget to put it in my checked luggage’. And of course I arrived at the security gate with that knife in my pockets.

I quickly put it in my carry on bag and put everything in those plastic X ray boxes. I was told not to take off my rings, and I triggered the metal detector. I was wanded down by a friendly security guard. For some reason, their detectors were set so sensitive that the wand beeped because of the individual rivets in my jeans, the zipper of my jeans, my rings, and even the roll of peppermints in my pockets.

No kidding, the wand beeped at the foil wrapper of my peppermints. Still, I was allowed to go through but there was no fooling the X ray machine. The lady kindly asked if I had a knife in my bag after which I dutifully handed it over. She looked at it for a minute, tried to open it (she failed), said ‘Hm, ok no problem’ and then gave it back to me with a smile.

She must have decided that I was unlikely to attempt a hijack with a little swiss army knife. It probably helped that it was clearly recognizable as a swiss knife, and that I used it as a keychain with keys attached. I don’t think I’d have gotten the same treatment had it been my spyderco. Interestingly, she made more of a fuss about the fact that my drinking bottle was still half filled with water. So I opened it and started drinking, and after a couple of gulps she told me it was ok.

It was nice to see that the German security guards were both paying attention AND showing common sense.

Posted: Nov 15 2009, 04:01 AM by vanDooren | with no comments
Filed under:
Tech-ed Berlin 2009: Day 4

Today I will go shopping for presents for my wife and kids. The last session ends at 18:15 and the store I want to go to is open till 21:00. There is a train station right next to the ‘spielmax’, and I feel confident that I will be able to get there in 1 go.

CLI312: Group Policy changes for Windows 7 and 2008R2

This session is hosted by Michael Kleef.

There are 2 reasons for me to attend this session. First of all, this is the only remotely interesting session at this hour of the day, and Group policy is something interesting which I actually use.

Secondly, this session is in the same room as CLI401, which it THE talk by Mark Russinovich. This means I don’t have to travel half a mile to get there in time.

The most important thing I took away from this talk was that in ‘7’, group policy is no longer just a logon action, but a hardened service to apply policy in the background. That sure is nice and would have solved a lot of my problems, if we actually ran something other than XP on my network. Still it is good to know for future reference.

This new service is network aware, so it will try to haul in group policy when it detects a domain controller, and not blindly wait until it is triggered by its default schedule. This is a boon for mobile users, or rather, the admins in charge of the machines of mobile users.

Then there was a word on group policy replication and how FRS (the file replication) sucks really bad. DFRs is supposed to be much , much better and solve a lot of issues. In particular, if FRS breaks (and it does), it doesn’t tell you. DFRs logs things in the windows event log for you.

Preferences were also mentioned, and how they can be used to help you configure computers with much more options, like printers, drive mappings, and other things. These are not real policies though.

Some part of the talk also covered the difference between adm files and admx files (the new file format for policies) and how they make your life easier.

I was impressed by the group policy abilities, though sadly I won’t be able to use them for a while, since we are still running 2003/XP.

CLI401: Windows 7 and 2008R2 kernel changes

This talk is hosted by Mark Russinovich.

This is amazing. I left the previous talk 5 minutes early to go to the bathroom and then returned immediately to make sure I got a good seat. For me, this is the most anticipated talk at tech-ed. The amazing thing is that the previous talk has ended slightly early, and yet the room is filling up already! There is another half hour to go, and most of the front half of the room is already occupied. And this is the largest room of the event!

2 years ago I was talking with a new programmer. You know the type: wearing a suit, having a slick haircut, carrying books about ‘patterns’… We ended up talking about programming, and I mentioned I was a C++ MVP and that I was currently reading Windows System Internals 4th edition because I really wanted to know how things work under the hood. He said he didn’t care about that level of understanding. He cared about managed languages, patterns, and ‘agile’ programming. No offense to the agile people, but it just fit with the rest of the picture.

At that point we had a bit of a disconnect. I am of the opinion that if you want to be a –real– programmer, then it is your duty to understand what you are doing, and not just doing things to get results.

At this point we are still 5 minutes away from the start of the talk, and the back of the room is getting packed as well. There are still some seats available, but pretty soon they’ll have to start turning people away.

As the talk is beginning, there is one moron in front of me using his cell phone. Personally, I would not presume to think that what I am saying is more interesting than what Mark is saying. And this is where Marks status among the audience shone through, because the guy with the phone was prodded from several sides and told bluntly to shut his yap. He stubbornly kept talking on, and I was glad he quit half a minute later, because there is a good chance that bad things would have happened.

Mark’s talk was very good. He has an easy way of talking to an audience, and he connected immediately. The talk started with an explanation of the various ways in which the memory footprint of Windows 7 and 2008R2 (they’re based off the same kernel version) has been decreased, so that it’s the first OS release ever to use significantly less resources than its predecessor. And not only has the memory footprint been reduced, but there have been other changes that prevent runaway processes to stomp over the working set of other components or applications.

In the realm of power efficiency, Mark talked mostly about core parking, triggered services and timer coalescence. One of the major investments in ‘7’ development  was to make sure that the kernel was doing ‘nothing’ as much as possible. J Incidentally, the kernel version for ‘7’ is 6.1, for no better reason than app compatibility and the morons who implement OS version checking the wrong way.

After that he briefly touched on the new virtual service accounts and managed service accounts, which are almost identical to normal service accounts, except that they managed their passwords like computer accounts.

The final part of the talk was about scalability, the number of CPUs Windows can use properly, and what was done to decrease the amount of lock contention in the kernel. It was pretty impressive. The biggest single improvement in scalability was the removal of the Dispatcher lock, which was apparently a very surgical process to do, and quite an achievement.

The talk zoomed past and was very interesting.

Afterwards I managed to ask Mark about his recent Newsid blog post, because I manage a complex software infrastructure in which the machine SID is used by the application, and I wanted to ask him about it. Mark asked if that software also runs on our DCs, and when I said yes, he then told me that it is not using the machine SID to communicate.

After first I was a bit skeptical, but then I remembered that in the past, we had 2 machines in our system which were both active in the software system AND fulfilling a domain controller role. So Mark was probably right. The reason I thougth it did use the SIDs, was that they are displayed, and sometimes referred to in documents or procedures.

Mark’s talk was top notch.

Lunch

Mashed potatos with onion, Brussels sprouts, and pommes gratin with carrot and corn. It was good.

You may notice the absence of meat here. Quite unusual for me, and I haven’t turned vegetarian overnight. The meat was a good looking beef stew, but the description included mushrooms. I can eat regular plain mushrooms just fine. I like them. But if they used forest mushrooms (the weird looking ones) even in small amount, then that would be the end of tech-ed for me.

On the same note, I skipped desert, since all the cakes and muffins had red blotches, and I religiously stay away from red fruit, on the assumption that it may contain strawberry. The chances may be small, but strawberry could indeed cause a religious experience for me, or at least allow me to find out whether there is an afterlife or not.

For the same reason I skipped the sandwiches during the event party on Tuesday. I nearly picked up a cheese sandwich when I noticed they had slices of strawberry in between. I’ll never understand why on earth someone would put strawberry in a cheese sandwich, but it sure kept me on my toes.

DEV313: Architecture discovery and Validation with VS2010

This talk is hosted by Peter Provost.

The talk centered around the new architect tools in VS, and how they can be used by developers and architects to get an overview of large and complex applications, by creating hierarchies of namespaces and assemblies, and perform analysis on those various diagrams.

Related to this was the layering of code and classes, and how it could be used.

He also showed the UML modeling that can be done of existing code, to get a better understanding of what actual code is doing, and whether it is looking good (understandable) or not. The flip side of this was the ability to generate code from UML diagrams. What was also very interesting was being able to define validation diagrams which are checked against the code during compilation. This allows architects to detect violations of the various layer interfaces that were defined. The violations messages would take you to the violations themselves, so that you could easily see what the issue was, and you could fix it there and then.

This is something that is generally only useful for large projects, like for example the last project I did for a satellite test bench. With over 20 projects, a handful of developers and 50000 lines of code, it would have been very useful. Especially since we had to document everything with UML in detailed design documents. This would have saved me many months of work, both in documentation and design.

The first question of course was: does this support unmanaged C++. And the answer was no, it did not… yet.

This is apparently the number 1 asked question. Even people within Microsoft would really like to use this for the unmanaged codebases of the various projects which are unmanaged, and can be classified as ‘complex’, like Windows, Office, …

It will not happen in the VS2010 timeframe, but they are actively working on that feature. Judging by the effort required to make Intellisense run decently (not super, just ok) doing this for unmanaged C++ is a task of herculean proportions.

DEV410: Building high performance parallel software

This session is hosted by Steve Teixeira, who is generally a good guy despite having left the C++ team. The contender for this session slot was SIA313 about how attackers target the Windows stack, and how to protect against that. That seemed interesting too, but this is probably more practically useful to me.

Btw, as much as I would like, I am not going to hang around after his talk, because I will have to RUN (not walk) to hall 7-2C if I want to be in time to have a good seat for Mark Russinovich’s next talk CLI402 about the limits of Windows 7: another talk any self respecting geek just has to see if he or she is here this week.

I told Steve I’d drop by tomorrow morning at his other talk so that we could chat for a bit longer. He was glad he didn’t have to compete with Mark in the same session slot though J

Steve’s talk was basically a rollercoaster ride of demos with only a handful of slides, where he showed off the capabilities of the new concurrency analyzer tool (I forgot the actual name) for analyzing concurrency scenarios. I have to say it was pretty impressive.

After that part of the talk he also showed lock contention scenarios and how you recognize them. Btw, locks do not contend with Chuck Norris. For the rest of us it can be a real pain to deal with. The new analyzer even has runtime deadlock detection, which was sweet to see.

I didn’t write down much of the details, since these were demos and I was paying attention to those. This was a very nice talk and the new concurrency / parallelism features in VS2010 are definitely worth checking out.

CLI402: Pushing the limits of Windows

As I already mentioned, this is another talk by Mark Russinovich. The limits of windows are like the price of clothes in the ‘better’ boutiques: If you have to ask, you can’t afford it. But despite that fact it is really interesting to know the limits and know where they come from.

Steve’s talk ran slightly over time, so I hurried to get here. I didn’t quite run though. It was more like the speedwalk where you don’t trot and don’t quite shove people out of the way to get through. There is still 25 minutes to go and I have one of the last ‘really good’ seats where one has an un-obstructed view of the screen at about the right distance. There is a ton of people milling around and the front half of the room is packed; the back half is filling up as well. Really. They should have used the keynote hall for Mark’s talk.

10 minutes to go and the room is almost packed.

5 minutes and there is an announcement asking people to put up their hand if they are next to an empty seat. People are still queueing up, but too bad for them.

Mark held a captivating talk about the different types of memory (virtual, physical, …) the paged and non paged pool, processes, threads, object and handles. It was really an interesting talk. But the very best thing was when the talk ended, and I was able to walk out, been able to say to myself: I already knew –ALL– of that. That was a proud geek moment. J

I am not going to go into detail here because that would take too much time, and it would be incomplete as well. If you care about that, buy Windows System Internals, 5th edition.

The 6th edition is coming out somewhere in spring next year, and will cover ‘7’ and 2008R2. Still, 5th edition is definitely not a waste of time to read, because Vista/2008 is what we will be running next year if all goes well, and it is always good to know the gory details, even if I’ll never use it as anything else but a reference for understanding what the system is doing or for troubleshooting.

Wrap-up day 4

Whew, day 4 is at an end. I have to admit that I feel the strain of having to pay attention all week. Despite that, it is sooo worth it.

I learned a lot of great stuff today, and this is really the only place in Europe where you can get it. It was the first time I saw Mark Russinovich speak, and it was definitely something worth repeating.

After his talk I went went shopping for some toys for my kids. I can proudly announce that I took the correct train, and found it at the first try (after asking for help). Next I’ll be finishing this report, catch up with my mail, and then pack my stuff so that I can check out early tomorrow. I’m already looking forward to tomorrow evening when I can finally sleep in my own bed again.

Posted: Nov 12 2009, 01:27 PM by vanDooren | with no comments
Filed under:
Tech-ed Berlin 2009: Day 3

Yesterday evening I started reading in Windows System Internals 5th edition, and then read some fiction and went to bed early.

People sometimes say ‘Oh wow you can go to tech-ed, be sure to go to this place or that and do some sightseeing...’. Tech-ed ends at 19:00, by which time I am tired from having to pay attention all day. Then I have to eat something, go back to the hotel, finish my report, and shower. By then it is past 21:00, and all I want to do is just a bit of reading and then sleep long enough so that I can pay attention all day again, next day. Seriously: if you don't stay for the weekend, the amount of time you can spend being a tourist is limited if you want to make the event itself worthwhile.

Anyway, I had breakfast as usual. I am not going to repeat my breakfast report every day unless something changes ok? By now we all know that if the hotel has bacon, I eat it. It is as simple as that. Never change a winning team. Bacon, coffee, orange juice, and the day begins.

CLI306: How to deploy Windows 7 on a stick.

I had to choose between this and DEV208: Triple boost your application with ‘7’, .NET4.0 and Intel multicore. The reason I didn’t go to that one was that it specifically mentions ‘Intel’ multicore, which leads me to believe that the talk is done by an Intel rep, and thus only a glorified marketing blurb for intel CPUs. After all, for all practical intents and purposes, the CPU type means nothing for the software development. Make no mistake it can have a huge impact on performance, but that is no different between intel and amd.

In hindsight, choosing the deployment session was perhaps the bad decision. This session was mostly about using the deployment workbench. It was basically an hour long demo with narration. The deployment workbench looks like a great tool, and I’ll definitely play around with it at home to see how it works. It has some nice features, like being able to import drivers in your setup, as well as applications.

It has always been possible to import drivers in a windows setup, but it involved a lot of manual work, text file editing, the ritual slaughter of a goat, and about 30 tries before you got the last setting right. Been there, done that, have the goat carcass to prove it.

All in all this was not an uninteresting talk, but the title was misleading. When someone says: Deploying ‘7’ on a stick, I would expect it means that you deply ‘7’ ON the stick and then boot from it. Instead, they deployed ‘7’ FROM the stick. They made a bootable stick that then installed ‘7’ onto the machine that the stick was booted in. Too bad, because that is not nearly as interesting to me.

INT308: Deep Dive in Windows Workflow Foundation

This session is hosted by Nuno Godinho.

I watched it for 5 minutes, and then decided that it was not for me and left, and went to CLI322.

CLI322: Windows 7 Applocker

I’d rather have gone to the 2008R2 failover clustering session, but that was full so I decided to check out the applocker session. It is interesting enough to learn more about, and since my daughter is nearly at the age when she can start using a computer, it may come in handy. J

Basically, Applocker is a technology that allows you (the admin) to create blacklists or whitelists of applications that can be run on a computer. These policies can be configured to have permissions based on user name or user group, meaning that these policies are no longer specific to a machine, but to users as well, and this can be very powerful.

With the policies you can control the execution of exes, scripts, and dlls. Currently there is no good way to work with managed applications yet if they are not exe based (for example web apps running in the Java runtime.)

The rulesets can be created using wizards, manually, or via powershell. It looked pretty impressive. It is also possible to build a reference machine, and then scan that machine for everything that’s installed and generate rules base off of that to give you a configuration head start.

And as with other policies that were mentioned yesterday (for example in the Kerberos talk)  it is possible to deploy these policies in an audit mode, enabling you to monitor the impact of these policies on your environment before you actually enable them, thus allowing for a smoother implementation.

Lunch

Lunch was a winner today as well. I had poached salmon, broccoli, carrots, and pasta. I didn’t go to any of the lunchtime sessions because nothing interesting was running, and you can really only attend them if you run to the lunch hall, shove people out of the way in the buffet line, and then ram the food down your throat while running back to the other side of the conference center where the sessions are held.

Instead I took the time to eat, and then ambled to the community lounge to sit in a sofa, read my email and write the previous part of my report.

OFS218: What’s new in Office2010 for Developers?

This session is hosted by John R. Durant

My alternative would have been ARC306: The architecture of predictive programming, but I have not idea what that would be about, so for all I know it would have been totally useless to me.

Otoh, the title of this topic mentions developers (which I am) and office 2010 (which I don’t know much about) so there is a good chance I’ll learn something useful here.

First of All I should mention John’s presentation style. The man is a born speaker. Have you ever watched one of Chris Rock’s HBO standup comedy specials? You can find them on youtube if you haven’t. John is a bit like that. Despite the fact that I am not really the intended audience for this talk, he manages to make it interesting enough that this hour and 15 minutes zooms past.

As to the topic at hand, it is really a bit out of my league. He basically demoes a lot of the new data interfacing options in office 2010, which implement online – offline presentation capabilities, as well as an underlying sync framework to cope with data changes.

This is all very exciting stuff for people who are involved with enterprise document management / generation. Especially when sharepoint is involved. I really see the benefits for those people, as it enables them to do a lot of nifty things for document generation and presentation that is invisible or at least unobtrusive to end users.

In my job, this is not something I am involved in at all. Still, it was very interesting to see what can be done with tomorrow’s office technology. Once there was a time when I could still keep in touch with the different office interop technologies just by making some simple samples. Nowadays, the world of office automation is a vast landscape of technologies and options that is very hard to navigate for those who are not involved with it on a daily basis.

DEV309: The Windows API Codepack

This session is hosted by Kate Gregory, and I had to attend it for several reasons. I’m a system software developer (cunningly disguised as a system administrator), so the Windows API is something I am interested in. It is about managed code development, which is something I do more and more. And Kate is a superb speaker so I had faith that one of the only ‘real’ developer talks this tech-ed would also be a good one.

There was a long break before this talk, but I decided to turn up early enough to get a good seat. It has been my impression so far that developers really get the short end of the stick this tech-ed, and any real development session is jumped by the developers in the audience like a limping gazelle by a pride of lions. And whaddaya know: it is 20 minutes before the start of the session and the room is already filling up nicely. Go Kate!

<snip>

It is now a minute or 2 before the start of the session, and the room is getting packed. And it is a big room. Take that, tech-ed event organizers! Tech – ed should be about development, NOT boring IT pro stuff.

Anyway, Kate held an interesting talk about developing for Windows 7 features, using managed code.

Instead of showing lots of code, Kate showed a selection of Windows 7 features that make the difference between ‘XP/2003’ era programming and ‘7’/2008R2 era programming (For the sake of not embarrassing ourselves, well just pretend Vista never happened. J) and then showed how easy it is to use those features in your application, through the use of the Windows API Codepack.

The first topic she handled was the taskbar, and how your app can do all sorts of interesting stuff with the application icon. Then she discussed the application thumbnails and restart / recovery behavior. And finally she covered some aspects of making your application powerstate-aware.

All in all it was a very interesting talk, filled with stuff you can use right now, with very little time, and a very big payoff.

I wish I could say more about it, but this session had lot's of cool demos, and it is rather difficult to explain why it was cool, and what she made those features do. Go to the codepack website and play with the codepack samples. You'll be pleasantly surprised.

CLI310: Is Virtualization a silver bullet for compatibility?

This talk is hosted by Jeremy Chapman, and some other guy I didn’t catch the name of.

This is where I have to admit that I attended this pretty interesting talk purely by accident, since in all my naivety I had just looked at the title and thought: Virtual Machines. As it turned out, it was about application compatibility, and What Windows does in order to make sure that older applications work with ‘7’.

Interestingly, one of the speakers mentioned that ‘Virtual’ is now the new ‘.NET’ (anyone remember Microsoft .NET Server?) or ‘Live’ brand that is slapped onto every new technology, because it is a marketing buzzword.

The talk started off very well, with the explanation that in ‘ye olden days’, backwards compatibility was king. This started changing after Bill Gates’s famous TWC memo, but Vista was really the first new OS where backwards compatibility was clubbed in the back of the head, and then beaten up in a back alley by ‘security’ and ‘stability’.

As a result, there was a lot of wailing, and the gnashing of teeth, because now there was a ton of applications who were no longer allowed to do the naughty things they were used to doing. UAC and running as a standard user were the biggest application compatibility hit ever in the history of Windows. Btw remember folks: every time you turn off UAC, Steve Ballmer kills a kitten.

The speakers then gave specific examples of the different ways in which apps would be causing problems.

After that, they proceeded to discuss the various ways in which Windows tries to fix it. The first thing they mentioned were the app compat shims, that can be used to trick an application into thinking everything was ok. One such example is configuring the shim to give a specific Windows version when the application asks for it, because the version check is implemented wrongly by the application. There are a number of shims shipped by default, but you can also create custom ones by yourself if you need to.

And there are things like folders that are now in a different location or have a different name. These are now created as junctions to those new folders.

App-V was briefly discussed as a way to separate applications from each other, but I missed the earlier talk about them so I cannot say much about that.

The most interesting thing I learned was some background on how the new XP mode works. It is basically a fully activated Windows XP virtual machine running in the background, which shows the UI of the applications its running in the ‘7’ desktop. They even mentioned that it has the ability to install USB drivers. I have to try this at home, because it would finally allow me to use that Canon digital camera with the wonky software without having to install and configure a separate VM for it. Of course it’ll still run in a VM, but in a way that it doesn’t bother me so much.

Of course it is still a local XP vm, and you have to make sure it is patched, maintained, etc. For home use that is not an issue, but for enterprise use it is a pain. For that, the have something called Med-V, which is basically the enterprise version of XP mode, which allows admins to centrally manage and maintain those virtual machines.

I ended up in this talk by accident, but it was very useful, and gave me a better understanding about the ways in which Windows deals with compatibility.

Day 3 wrap-up

Another day filled with learning. The food was great, the company was great, and so was the schnitzel I ate for diner this evening. It was so unbelievably good, and again very cheap. Only 12 euros for the diner + 1 pint of warsteiner.

Tomorrow, tech-ed finishes at 18:15, so today I took some time to get directions to the nearest toy store, so that I could buy something for my daughters.

Posted: Nov 11 2009, 02:29 PM by vanDooren | with no comments
Filed under:
Tech-ed Berlin 2009: Day 2

To answer the question that you all have been asking yourself, I can answer with a resounding YES. The hotel serves bacon at breakfast. And as a matter of fact, it is possibly the best bacon I’ve had in years. The correct thickness, and fried just to the point between bending and breaking. It was kept in a bowl, resting on whitebread to absorb the excessive fat so it didn’t slide off my plate either.

They had a variety of bread, cereal, fruit and vegetables, different types of egg, salmon and a couple of terrines, yoghurt, fruit juices, etc. They even had over a dozen types of tea leaves. The only thing that disappointed was the coffee. Overall, the breakfast was superb.

 I also have to say that this is by far the cleanest hotel room I can remember in a long time. The tiling in the bathroom is immaculate, as is the grouting. I could not find a single spot that was less than absolutely clean, so a big kudos to the KuDamm101 hotel.

My trip to the conference center was flawless this time, and I arrived in time to get a cup of coffee and read my email. The coffee is good btw. It is not the black bliss that was poured in Barcelona, but definitely above average.

I forgot to mention yesterday, but during the keynote speech it was proven yet again that computer geeks as a crowd are depressingly easy to please: all you have to do to make the crowd go wild is to throw a box of free t-shirts in the audience. Even bricks of 100 dollar bills would probably not have the same effect.

CLI302: How Windows storage is changing everything

This session is hosted by Mark Minosi. I saw him speak yesterday and so I knew he was a great speaker. I chose this talk because it ties in with VHD, which was mentioned yesterday in his ‘7’ talk and it seems interesting. The contenders for this session slot were VS tips and tricks, and parallel programming for managed developers.

Luckily, Steve’s talk on parallel programming is repeated on Friday. And the VS tips and trick is probably interesting, but not something I can’t easily figure out myself by looking at the slides afterwards.

The talk on VHS was interesting. VHD is technology for Virtual Hard Disks. And since the technology is cool, it is also used by the Windows Backup utilities to backup your files to virtual disk files.

VHDs are like the virtual disks we have all been using for a long time, via VirtualPC, VMWare or whichever virtual technology you happen to use. The difference is that you can mount them in Windows, assign them a drive letter, and use them natively like any other disk.

What you can also do is install Windows in one of these virtual disks, and then configure the boot manager to boot from that virtual disk. This is a cool thing to do.

Now of course, you might wonder what the difference is between this and just using VirtualPC. The answer is: not a lot. For plain yoghurt desktop use, I don’t think this is worth the bother. And annoyingly, you cannot run XP or Vista this way. Only ‘7’ and 2008R2.

The biggest difference would be that the booted OS runs bare metal. It is the sole OS, and gets access to all the hardware and resources, whereas a VM typically only has 1 or 2 CPUs, has to share memory with the host OS, and performs disk IO at a much slower rate. Additionally, direct access to other disks in the machine is not possible with VM clients.

So that might be an interesting option if you need to run different OSes in a multi boot environment without wanting to dedicate individual partitions to each one.

SRV203: Windows Server 2008R2 Overview

This session is hosted by Joey Snow. It is a high level overview of the new features of 2008R2 that make it worthwhile.

The first thing that was mentioned was that the virtualization and hyper-V technology for R2 got improved significantly. Items mentioned were live migration to other hardware (this was impressive to the developer in me), and the usage of new CPU technology to improve performance.

Remote Desktop got overhauled to support cool new things like remote application support and improved performance for media, making it possible to view e.g. an MPEG file on a remote server.

What was also nice was the system management software that includes a best practices analyzer that can scan your network, and then tell you if your DC, DNS, etc infrastructure follows the industry best practices (which are kept as XML config files so they are configurable), what the impact is if you don’t, and how you can resolve that.

The backup tool in R2 is finally becoming usable too. Microsoft finally got to see that we want to back up individual files and folders, and that we want to back them up to a logical volume instead of a dedicated physical disk.

Then there was also Direct Access, which allows for direct VPN connection to the corporate network, using IPv6 and IPSec. At the same time, you can still browse the internet without going through the corporate network.

App locker is a way to control which apps your users can run, via group policy and digital certificates, using blacklists or whitelists. And BranchCache enables people in branch offices to download files from the corporate network and caching them locally in a way that is invisible to the end users, thus relieving the server and network infrastructure.

And one of the things that I personally liked very much is the ability of Powershell to be executed remotely, just by adding 1 line to the top of the script. This allows me to write scripts that can be executed remotely on a server for doing administrative tasks without having to log on to the machine itself. By the way, Joey showed an Integrated Script Editor. It is not quite Visual Studio yet, but it looks very usable, with many nifty features and even features like breakpoints and stepping.

DEV203-demo: MFC stuff.

This was a lunch time session. I quickly ate my lunch and then got to the session. The food was great btw. The pork was perfectly cooked, and soft as butter. The baked potatoes and carrots were very good as well.

I did not attend this MFC session because it was about MFC. I hate MFC. MFC is the spawn of the devil. When God inspired Bjarne Stroustroup to start C++, he had templates in mind. Unfortunately, the devil got wind of this initiative, and caused delays in the formation of the C++ standard. So instead of using templates as God intended it to be, the MFC team decided not to use them and started on the object hierarchy road, paved wit good intentions, that lead to the current mess. ATL and WTL still followed God’s big plan, but it was too little, too late. MFC had a big head start, and is now here to stay, like original sin.

But I digress.

I attended this session because I assumed that because of the dearth of developer sessions, it would be a watering hole for C++ developers. And I was right. Kate Gregory was also there, and I talked to her for an hour or so. Kate has a talk tomorrow which I will attend. It was good talking to her. She is a C++ expert, as well as a nice person.

I did not hear anything from the MFC demo, so my C++ soul is still safe.

SVR315: IPv6 for the reluctant

Another talk by Mark Minosi. I wanted to attend this one because I don’t know too much about IPv6 yet, and since it is part of ‘7’ and 2008, and probably the way of the future, I felt this is an excellent opportunity to learn more about it.

Unfortunately, the session room was full and I was not able to attend this session so I chose the SVR205: introduction to Hyper-V and Windows2008R2

SVR205: introduction to Hyper-V and Windows2008R2

This session was hosted by Edwin Yuen and Jeff Woolsey.

The session was OK. It showed many features of Hyper-V, and I have to say I was impressed. For my environment, the difference between this and VMWare Server is negligible. Currently we run VMWare Server 2.0, but if I ever have the opportunity to switch, I’ll switch to Hyper-V R2. The management utilities are impressive, as is the live migration. What is even more impressive is that you can migrate to servers with a different CPU architecture without downtime.

Hyper-V accomplishes this by normalizing the set of instructions that the VM has access to. This made it possible to migrate a running VM from a P4 to a CoreDuo to a Core2Duo to a Core I7 nehalem without going down. And of course, everything is done via a powershell interface, making it possible to script everything you could want to do with your virtual infrastructure.

There was a lot of infrastructure management provided out of the box, and most of it is 100% FREE. I am not an expert in virtualization by any measure, but I think that this is seriously going to eat into VMWare’s revenue.

SVR302: Windows Crash Dump Analysis

This session is hosted by Daniel Pearson. My alternative choice would have been DAT206: SQL Server 2008 Power Hour. I didn’t really know which one to choose, but since this is in one of the smaller rooms and I was there, I just went ahead and chose this one. It is also more advanced than a SQL Server demo, and possibly I’ll learn some neat tricks here. The room is filling up quickly, and this session room will probably be full to capacity before the talk starts.

Basically, Daniel uses the ‘Not My Fault’ application to load the ‘myfault’ driver in order to cause a specific driver error, such as a buffer overrun, pagefault at dispatch level, or other bug. Then he demonstrates how to figure out the cause of the problem, using windbg.

He also used driver verifier to demonstrate how you can inspect suspect device drivers by performing more stringent checking and analysis at runtime. This has to be enabled explicitly, because it can cause a significant runtime overhead.

All in all it was an interesting session, but not as advanced as I would have expected really.

SIA401: Cracking Open Kerberos

And yet another talk by Mark Minosi.

I’ve always wanted to know more about Kerberos, and this is an excellent time to learn. It is a 400 level session so quite advanced, but I hope I know enough to be able to understand what he is talking about. Mark is a great speaker so that helps too.

Mark explained the process involved in authenticating a user on the domain, by following the Kerberos tickets. The explanation was really good and made sense. After a discussion on what Kerberos does and how it does it, he then explained the difference with NTLM (the old Windows authentication protocol), and why you should take steps to disable it where and when possible. He mentioned that around 5 to 10% of all authentication is still done via NTLM, even in a modern Windows domain.

There are several reasons for this, and they have a severe impact on functionality and security, causing weird problems (like admins not being able to join a computer to a domain) and possible attack vectors due to the weak NTLM encryption.

Mark then proceeded to explain about the new group policies in R2, enabling administrators to audit and block NTLM requests completely.

After that he explained about token bloat, service identity and authentication, and some of the edge problems that may cause Kerberos to stop functioning.

All in all this was a very good talk, and Mark’s gift for connecting with the audience made this session appear much simpler than it actually was. I had a math teach like that once in high school. The difficulty of a topic lies not just with the topic, but also with the ability of the teacher to explain. And Mark certainly has a gift for speaking.

Day 2 wrap-up

I saw a lot of great tech stuff today. On one hand I feel that it is a shame that there are not more developer sessions. I used to be able to choose between 10 developer sessions every hour, and now there are only a handful. The split is probably 60% IT 40 % dev. As Kate said to me: you don’t know you live in a golden age until it is over. The 1 week event type was chosen for economic reasons, so it will probably be so for the next couple of years.

On the other hand I now get to see some interesting sessions that I would normally not have attended, or which would not have been scheduled for the developer week. Since I wear both the developer and sysadmin hat, this 1 week setup has its advantages too.

There was a ‘party’ tonight in the exhibition hall, so I ate some of the food and drank a beer, bought a copy of Windows System Internals, 5th edition and went back to the hotel. I have the 4th edition of this book, and it was written at the time of XP and 2003. The 5th edition covers the Vista kernel and the 2008 kernel. ‘7’ and 2008R2 are not covered (they are too new) but they are based off the same kernel as Vista / 2008, so that doesn’t really matter that much despite the fact that some of the cool new features are not yet covered.

Still, any self respecting geek involved with Windows should read these books, even though they have as much pages as a Robert Jordan novel. Whether it is system administration or software development: if you really want to –know- what you are doing, then you have to have a good understanding of the fundamentals. This book is by far the best such resource that is not covered under NDA.

Posted: Nov 10 2009, 01:26 PM by vanDooren | with 1 comment(s)
Filed under:
Tech-ed Berlin 2009: Day 1

After a boring cab drive to the airport, I had an even more boring flight to Berlin. And that is exactly how I want all my flights to be. I don’t want it to be the thrilling and exciting near-death experience I had once, flying to Nice.

I arrived in Berlin safe and sound, and took a cab to the hotel. Sadly, the hotel is not near the conference center, on account of there not being any hotels nearby. The hotel is 2 short train rides away. It’s really easy to find. And of course, to those that know me it will come as no surprise that it took several tries for me to arrive at he correct location.

What sucks most is that a) my flight got rescheduled sometime ago (leaving 1 hour later than expected), delayed for half an hour, and the event agenda got re-shuffled since I booked. As a result, I missed 2 sessions. Because for some silly reason, someone decided that the keynote should be at the end of the day instead of the beginning.

Had I known this in advance, I’d have left for Berlin yesterday. I didn’t because I wanted an extra day with my wife and kids. Ironic, since they weren’t at home yesterday due to unforeseen circumstances. Next time I’ll just leave on Sunday, taking some extra time to travel.

Whatever. I am typing this while the keynote speech is starting. It’ll probably be an hour and a half filled with mind numbing explanations of why Microsoft technology is the greatest on earth.

I have to say I preferred Barcelona as the venue for tech-ed, for a number of reasons:

1) Walking down the street in November. Berlin: 5 degrees Celsius and rain. Barcelona: 20 degrees Celsius and cloudless skies.

2) Crossing the street from the hotel and being at the event in less than 2 minutes.

3) The venue itself. The messe is a complex of industrial looking buildings, with concrete, asphalt, etc, rather than the aesthetically pleasant looking ICC in Barcelona.

4) additionally, the idea of having 1 big event for developers and IT professionals is less than stellar. Because now, there are only half as much developer sessions as there used to be in Barcelona. Only 1 real C++ session, no large selection of .NET and C# and SQL Server sessions...

Still, I’ve had my first coffee of the day and I am starting to get a feel for the place. Tech-ed is still a good place to be. And if my knowledge of German cuisine is still accurate, the food will be good, plenty, and NOT drowned in olive oil.

CLI324: Windows ‘Lucky’ 7

This session was hosted by Mark Minasi

It was a good session, and basically enumerated the features of 7 that are either new, or changed from Vista or XP.

Mark is a great speaker, and managed to make the time fly while discussing the topics. It was not in depth so I am not going to repeat too much of it here. The things that got me interested most are the ability to image disks into files, like VMWare virtual disks. These disks can be shared, backed up and mounted. Very exiting stuff that would make my life easier, if we ever get to the point where we will actually use 7.

Other cool features are the ability to deploy to USB media, which would presumably allow me to boot from USB disk, as well as the ability to easily perform preconfigured installs.

When talking about Vista and how 7 compares to it, Mark mentioned that one Microsoft developer said ‘We are going to throw Vista under the bus’, comparing it with Windows Miserable Edition. Interestingly, In terms of raw speed, 7 is really not that much better. But when it comes to perceived speed, 7 is the clear winner due to being more responsive, and getting less in the way of what the user wants to do.

The talk was great, and the speaker connected well with the audience.

Sadly, this was the only technical session I will see today. As luck would have it, there is only 1 C++ talk this tech-ed, and I missed it. At least they could have scheduled some boring IT talks in the first 2 sessions but alas.

The actual keynote

The keynote itself so far has the hallmarks or every other keynote I’ve seen so far. A couple of tech delegates got singled out for public humiliation while a couple of IT bigwigs (presumably million dollar customers) sat on stage explaining how good their infrastructure is and how Microsoft helped them to enable it.

Bla bla bla snore.

I don’t want to sound jaded here, or un-appreciative of the fact that my company is letting me attend this event (I am really grateful), but keynote speeches tend to be hype and blubber, void of tech content and generally a waste of time. What was even worse about this keynote is that they didn’t show off anything related to Visual Studio 10. Instead, they demoed Server 2008 Hypervisor and Exchange 2010.

That said, it is interesting to a developer like me that with the newest release of 2008R2 and the System Management Center software, detailed knowledge and understanding of the low level OS guts are no longer absolutely necessary. Between the 2 of them, those applications let admins manage their infrastructure with only a modicum of nitty gritty knowledge. The software goes out of its way to be user friendly.

That is not a bad thing. It just feels weird that you can administer a complex system without having to troll through log files, understand dcom security configuration, and other arcane things.

At least tomorrow I’ll be able to dive deep in technical content, and hopefully start my day with bacon and coffee. At least 2 plates of the former and 2 big cups of the latter.

Wrap-up day 1

The travel was good, the weather not so much.

The windows 7 presentation was good, the keynote not so much.

I had a very good pizza in an Italian restaurant, for only 7 euros. Dirt cheap.

I am now making a schedule of which sessions I want to see, and when to see them. Some of the sessions I’d like to see are scheduled in the same slot, but some of them get repeated throughout the week so I can probably schedule my attendance so that I can see most of the people I want to see.

Posted: Nov 09 2009, 01:39 PM by vanDooren | with no comments
Filed under:
VMWare Server 2 Console WTF

I've been using VMWare Server 2 on a Vista 64 host to simulate a network environment for testing our operating procedures. Everything was working fine before I got on holiday. Now I am back for 2 weeks, and suddenly, VMWare thorws a wobbler.

Using the server console, I can start and stop local virtual machines, but whenever I try to connect to the console, I got the following error: 'Error opening the remote virtual machine machinename:8333\16:
An unexplained error occured.
'

Brilliant. An error message that is as useless as a bookshelf made from mashed potatoes, that turns up without any changes to the system. And of course, googling did turn up many people with the same problem, but noone with a solution. Eventually, I found someone who suggested a solution for generic connection problems:

  1. On the host computer you need to access the network properties for vmnet1.
  2. find Internet protocol tcp/ip (v4) click properties
  3. in the window use following DNS server address enter the static ip address displayed or enter the ip address 127.0.0.1
  4. hit ok
  5. hit ok again
  6. done ! restart the machine to verify working

I have no idea why this is suddenly necessary, because the machine name is the local name and I can ping it without a problem. And VMWare consoles used to work just fine before my holiday, so I am really a bit annoyed with this. Still, the above fix worked like a charm so I am not going to complain too much.

Posted: Aug 19 2009, 04:48 AM by vanDooren | with no comments
Filed under:
Long time no see

It's been a while since I blogged here. Lack of inspiration, lack of time, lack of interest... Over the past couple of months, I've been occupied with other stuff.

The guest bathroom needed finishing, and my wife had a number of creative ideas that looked great but also needed a lot of time. I have started doing martial arts again, and I have been practising 2 times per week, so that is another 2 evenings no available for doing tech stuff. And the little time that I had left, I didn;t feel like programming.

But now I am back. I have started participating in the MSDN forums again, and I hope to write some more articles on ATL in the near future, because ATL is just cool.

My registration for tech-ed in Berlin has also been approved last week, so I will be blogging about that in november. Last year I didn't go, so most of the content should be new to me. Too bad they switched from Barcelona to Berlin. Spain can still be very nice in November. Then again, I won't miss the olive oil.

Oh and in case anyone was wondering: I was re-awarded in July, so I'll be an MVP for another year.

Posted: Aug 17 2009, 01:53 AM by vanDooren | with no comments
Filed under:
Practical ATL: Solving the race condition in CAtlExeModuleT

When I was spelunking through the ATL header for my previous articles (the class object plumbing) I discovered that there is a serious race condition in the server lifetime management.

I contacted the Microsoft C++ folks, and someone from the libraries group told me that this problem has already been fixed in the next release of Visual C++.

But since the issue still exists in all current ATL projects, I decided to write something about it and publish the fix which will circumvent the problem in the recent versions of ATL (7.0 and upwards if I am correct).

The problem

The module lock count of an ATL COM server is managed in the CAtlExeModuleT<T> class. It is this lock count that keeps the server alive as long as it is nonzero.

The CAtlExeModuleT<T> class manages its reference count via the  CComGlobalsThreadModel class increment and decrement methods. CComGlobalsThreadModel is a typedef for CComMultiThreadModel so these methods map to InterlockedIncrement and InterlockedDecrement

The last module lock is released if
- the class object itself has no more external connections (IExternalConnection), and
- there are no more object instances.

As soon as the final module lock is released (module refcount is 0), the shutdown of the server is initiated, which will happen through either a WM_QUIT message or a win32 event object. In both cases there is a time window between the triggering of the shutdown, and the actual call to CoRevokeClassObject. This time window can be several seconds.

This time window causes a race condition between the server (which is already dying at that point) trying to revoke the class object, and a hypothetical client, requesting an interface pointer to the class object. Depending on how the race turns out, the client might end up with an S_OK HRESULT from CoGetClassObject, and an invalid interface pointer. This will cause a critical problem in the client, and may cause an application  crash.

The solution

The proper way to manage the server lifetime is to use CoAddRefServerProcess and CoReleaseRefServerProcess to manage the module lockcount. Those functions will (according to MSDN http://msdn.microsoft.com/en-us/library/aa910552.aspx) suspend all class objects when the reference count drops to 0, in an atomic operation.

In that case, the server starts dying AFTER all class objects are suspended. Any incoming client request for the class object will spawn a new server process after the dying server has finished revoking its class objects.

The fix

The code for fixing this is simple. I simply created a new class that inherits from CAtlExeModuleT<T> and then overrides the Lock and Unlock methods.

template <typename T>

class CAtlExeModuleT_NoRace : public CAtlExeModuleT<T>

{

public:

  typedef CAtlExeModuleT<T> base;

 

#if _ATL_VER < 0x0A00

  LONG Lock(void)

  {

    CoAddRefServerProcess();

    return base::Lock();

  }

 

  LONG Unlock(void)

  {

    CoReleaseServerProcess();

    return base::Unlock();

  }

#else

  //removed compiler messages

#endif

};

I use CoxxxxServerProcess functions to explicitly manage the class object registration, and then I delegate to the base class which maintains its own reference count.

The reason I do that is that the base::Unlock function is the one which triggers the module shutdown, and I don’t want to mess with that. And Unlock works only when paired with Lock, so the only thing I really need to do is to call the CoxxxxServerProcess routines to prevent possible activation requests. The rest is still done by CAtlExeModuleT<T>.

I put a compiler condition around my implementation of the new Lock and Unlock methods, because they are only needed for current versions of ATL. The next version of ATL won’t have this problem, so it would be dangerous to meddle with the reference counting, especially since I cannot predict what side effects this may have.

The conditional compilation allows you to safely upgrade the project to the next version of ATL. The compiler messages which show up in the compiler output inform you that it is no longer needed to inherit from CAtlExeModuleT_NoRace as shown below:

class CStuff_ServerModule : public CAtlExeModuleT_NoRace< CStuff_ServerModule >

{

public :

  DECLARE_LIBID(LIBID_Stuff_ServerLib)

  DECLARE_REGISTRY_APPID_RESOURCEID(IDR_STUFF_SERVER, "{597B5DFF-DACE-42B0-9E49-54A09C10B2BB}")

};

The only thing you have to do to use my new module class is to include the header and change CAtlExeModuleT to CAtlExeModuleT_NoRace.

And if you upgrade the project to VC10, then you can simply change it back as indicated by the compiler output messages that are printed out when the compiler parses my class.

Conclusion

I was surprised that this bug was still in the ATL headers after all these years. When I contacted the VC++ team I was half expecting them to tell me that I had missed something. This issue is what caused CoAddRefServerProcess to be created after all, over a decade ago, so a COM programmer implementing lifetime management should be aware of it.

However, the modular and hierarchical nature of ATL made it easy to fix this problem, so I guess that is a plus for ATL. And mistakes happen. It is always a bit painful if it happens in widely used libraries, but I too have had my share of whoopsies over the years. It is sad but it happens.

The header file with the fix is attached to this blog post under the MIT license.

 

Could not create NTDS settings on domain controller...

Could not create NTDS settings yadayadayada on domain controller CN=yadayadayada. The RPC server is unavailable.

This was the error message greeting me (with some meaningful text instead of the yadayadayada of course :)) when I tried to add a backup domain controller to the domain of our test and development network. It was the first time I encountered an error at the DC promotion stage.

I checked the usual things (network connections, privileges, etc) but nothing jumped out at me. Now, if an error dialog mentions RPC, then the usual error is either a DNS error, or a DNS server that has not yet refreshed its zone information.

So I opened the DNS config, and discovered that only 1 NIC of our the new DC was registered in DNS. Our networks are multihomed (3 networks in parallel) and yet only 1 address was registered for the NIC. This was a bit odd. There should be 2 (one network has no DNS on purpose).

A quick ping revealed that one of the NICs had no connectivity. It turned out that the primary DC was a bad network connection, due to some wiggling with the cables. Plugging it all the way and then re-registereing the NICs of the new DC with DNS solved the problem.

I still don't understand why we got that problem, because the disconnected NIC was last in the binding order, so the new DC should have used the available connection anyway. My guess is that it retrieved the address via DNS, and got the address of the NIC that was disconnected. Ah well. Live and learn. 

Posted: Apr 14 2009, 11:24 AM by vanDooren | with no comments
Filed under:
The kerberos client received a KRB_AP_ERR_MODIFIED error

This is what I got in the event logs yesterday afternoon:

Event Type: Error
Event Source: Kerberos
Event Category: None
Event ID: 4
Computer: SE-SMURF01
Description:
The kerberos client received a KRB_AP_ERR_MODIFIED error from the server PC-BLABLA09$.  The target name used was . This indicates that the password used to encrypt the kerberos service ticket is different than that on the target server. Commonly, this is due to identically named  machine accounts in the target realm (FOO.BAR.STRIPE.LOCAL), and the client realm.   Please contact your system administrator.

Event Type: Error
Event Source: Kerberos
Event Category: None
Event ID: 4
Computer: SE-SMURF01
Description:
The kerberos client received a KRB_AP_ERR_MODIFIED error from the server PC-BLA09$.  The target name used was RPCSS/PC-BLA10. This indicates that the password used to encrypt the kerberos service ticket is different than that on the target server. Commonly, this is due to identically named  machine accounts in the target realm (FOO.BAR.STRIPE.LOCAL), and the client realm.   Please contact your system administrator.

I had replaced those machines a week ago, and everything seemed to work fine. So I didn't understand why these errors were suddenly popping up. The applications running on those computers where throwing a wobbler as well. Some googling later I found 2 remarks that were useful.

The first one was that someone fixed it by taking the computer out of the domain, renaming it, changing the SID, and changing the IP address. While this is overkill on the scale of killing a mouse with a thermonuclear weapon, it pointed in the direction of a network level problem.

The second remark was by a Microsoft employee who explained that DNS misconfiguration can be the source of problems like this. If kerberos thinks it is communicating with pcA it encrypts the kerb ticket with the password of pcA. but if the ticket then ends up on pcB because of the DNS mismatch, the above events will be logged.

At that moment I realized that I had changed the IP address of an adapter on PC-BLA10 because it conflicted with PC-BLA09. The reason everything worked fine initially was because that port had been left disconnected until 2 days ago when I configured the correct IP address. The conflict was resolved and the DNS information was updated, but that didn't mean that the DNS caches were up to date. So I cleared the DNS cache of the DNS server, and used ipconfig /flushdns to clear the resolver cache on the domain controller and PC-BLA10, and the problem disappeared.

 

Scheduled task would not run

The scheduled task for running ntbackup on our fileserver would not run anymore. It would stop with a return code of 0x80, and nothing worthwhile in the log file or event log. It ran fine for months, apart from the occasional hickup such as having no more free tapes in the loader, or a tape not being imported correctly.

I tried running the backup batch file manually, and that worked fine. I ran it under the dedicated backup account, and that worked fine too. But it wouldn't run automatically, and starting the task manually when logged in didn't work either. I couldn't find any useful debugging info so I turned to google. I found several people who has similar problems, but most had to do with a bug in the HID service which somehow interfered with ntbackup. I looked around some more and finally I found something that ended up giving me the final clue.

I opened up the task manager and noticed that there were 21 instances of xcopy still running, 23 instances of psexec, and 3 instances of ntbackup. These were probably left over from some tests I had done with the backup script of one of the new servers (a backup domain controller) which uses the 3 aforementioned programs.

After killing these dead processes I tried to run the backup task again, and everything worked fine this time. In my naivety, I had assumed that ending a task would end the processes it had spawned, but that seems to have been a mistake. Ah well, everything is working again, and now that I know the cause, I can prevent this from happening again.

This is why I try to understand a problem, rather than just rebooting the machine. A reboot would have fixed the problem in less time then I needed to figure this out. But then I wouldn't have known what happened (I hate that) and I wouldn't be able to prevent this from happening again. I would have been stuck in a regular but unknown problem -> reboot cycle.

Practial ATL: Implementing a non-standard class object

In my previous article in this series, I explained how class objects are associated with COM objects, and how it all fits together.

Armed with that knowledge, I can now demonstrate how to provide a custom class object that will allow us to support parameterized construction.

If you haven’t already read my previous article on class objects, please do so first because I am going to assume you did J

The non-standard class object interface: IStuffCreator

A class object can have any interface you want, just like the COM object we have created earlier. It is just another COM object after all. My custom interface looks like this:

[
      object,
      uuid(6DD69CDB-3128-432b-B335-773A287E6F06),
      oleautomation,
      helpstring("IStuffCreator Interface"),
      pointer_default(unique)
]
interface IStuffCreator : IUnknown {
  [id(1), helpstring("method MakeMeAStuff")]
    HRESULT MakeMeAStuff(
      [in] BSTR name,
      [in] REFIID riid,
      [out, iid_is(riid)] IUnknown** ppStuff);
};

The bits between the square brackets are the attributes that are applied to this interface. ‘Object’ specifies that it is a COM interface. The uuid specifies the GUID that identifies the interface. ‘oleautomation’ specifies that the arguments being used are all automation compatible. The meaning of  ‘helpstring’ is pretty obvious, and pointer_default specifies the assumptions that the marshaller can make about pointers.

If you want to know the details about it, then have a look in MSDN for MIDL attributes.

The interface itself is very simple. Instead of deriving from IDispatch like the IStuff interface, this interface derives from IUnknown. Deriving from IDispatch would only complicate matters without any benefit.

The interface has only one method, which is responsible for handing out new stuffs.

The parameter that will be used for constructing the CStuff instance itself is the ‘name’ parameter. If the CStuff would need multiple parameters, they would have to be part of the parameter list so that they can be used at the time of construction. The riid and ppStuff parameters have the same meaning as those of CoCreateInstance.

The declaration of CStuffCreator

If we want to implement this interface, we add a new C++ class with the name ‘CStuffCreator’ to our project, and implement our IStuffCreator interface

class CStuffCreator:
  public IStuffCreator,
  public CComObjectRootEx<CComGlobalsThreadModel>
{
public:

  CStuffCreator(void){}
  virtual ~CStuffCreator(void){}

  BEGIN_COM_MAP(CStuffCreator)
    COM_INTERFACE_ENTRY(IStuffCreator)
  END_COM_MAP()

  //IStuffCreator methods
  HRESULT STDMETHODCALLTYPE MakeMeAStuff(
    BSTR name,
    REFIID riid,
    IUnknown **ppStuff);

  // helper method
  void SetVoid(void* pv);
  _ATL_CREATORFUNC* m_pfnCreateInstance;
};

As you can see, it is pretty simple. The CComObjectRootEx base class helps with reference counting, and is the same that is used by the other COM objects in our project.

We add IStuffCreator to the interface map using the ATL macros, and then we simply declare the single MakeMeAStuff method that we need to implement.

The SetVoid method and the function pointer are part of the default C++ interface for class objects in ATL, and are explained in my previous article.

The implementation

The implementation of CStuffCreator is even simpler than the declaration:

HRESULT STDMETHODCALLTYPE CStuffCreator::MakeMeAStuff(

  BSTR name,

  REFIID riid,

  IUnknown **ppStuff)

{

  CComPtr<IUnknown> newStuff;

  HRESULT hr = m_pfnCreateInstance(

                 NULL, __uuidof(IUnknown), (void**)&newStuff);

  if(FAILED(hr))

    return hr;

 

  return newStuff->QueryInterface(riid, (void**)ppStuff);

}

 

void CStuffCreator::SetVoid(void* pv)

{

  m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;

}

Ignore the ‘name’ parameter for now. That will be used when we are going to initialize the new instance. The bare functionality of our class object is to use the function pointer to create a new instance. I could have done this in 1 step instead of 2 (the QueryInterface isn’t necessary at this point) but this way I can slide in some additional functionality later on.

And you can see now that the class object will receive the creator function pointer via the ‘SetVoid’ method. This mechanism was explained in my previous article.

Parameterized construction

The point of using a non-standard class object in this demonstration was to be able to create objects that need some sort of initialization before the client has access to them. Normally, ATL supports only default constructors using, because IClassFactory is a generic interface.

For parameterized constructors, we are going to have to do something special.

There are essentially 2 ways we can do this. The first is to change CStuff to have a parameterized constructor. But ATL can’t handle that, and it would mean we have to abandon the incredible convenience of being able to use the ATL::Creator<T> class, ATL::CComObject class, and other helper classes that take the pain out of COM.

Don Box wrote an article about parameterized construction, many years ago, and this was the approach he took. Of course, ATL was much simpler in those days, and abandoning it was perhaps less of an inconvenience.

The approach I am taking is much simpler: I cheat!

That’s right. I cheat. I am not going to implement parameterized constructors. I am going to fake it. But from the client’s point of view, it’s going to look exactly the same, so he won’t mind. And from the server’s point of view, it will be much simpler to implement, so everybody wins.

The second approach to implementing parameterized construction is to implement an internal interface on CStuff, which will be used for initializing it. The new CStuff instance will not be accessible to anyone until the first interface pointer is handed out by the class object. And we are the ones implementing the class interface, so we can make sure that the new instance is initialized properly before it is released into the wild.

The initialization interface

The interface for initializing a CStuff is pretty simple (I left out the header for clarity):

interface IStuffInit : IUnknown {

  [id(1), helpstring("method InitStuffInstance")]

    HRESULT InitStuffInstance(

      [in] BSTR Name);

};

Our CStuff instances are supposed to have a name, so that’s what needs to be in the init interface. If they would also need an address, a hat, and a pair of pants, we would have to put those in the parameter list of the InitStuffInstance method as well.

Implementing the initialization interface

Implementing the interface in CStuff is easy I highlighted the changes that have to be made to the declaration.

// CStuff

 

class ATL_NO_VTABLE CStuff :

  public CComObjectRootEx<CComMultiThreadModel>,

  public CComCoClass<CStuff, &CLSID_Stuff>,

  public IDispatchImpl<IStuff, &IID_IStuff, &LIBID_Stuff_ServerLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,

  public IStuffInit

{

private:

  CComBSTR m_Name;

public:

DECLARE_CLASSFACTORY_EX(CStuffCreator)

 

// removed irrelevant stuff

 

BEGIN_COM_MAP(CStuff)

  COM_INTERFACE_ENTRY(IStuff)

  COM_INTERFACE_ENTRY(IDispatch)

  COM_INTERFACE_ENTRY(IStuffInit)

END_COM_MAP()

 

// removed irrelevant stuff

  HRESULT STDMETHODCALLTYPE InitStuffInstance(BSTR Name);

};

First we add IStuffInit to the inheritance list, we add it to the COM map, and then we add the declaration for InitStuffInstance.

Of course, the name has to be part of the objects state, so we add a CComBSTR variable to hold it.

And finally, we use the DECLARE_CLASSFACTORY_EX macro to change the class object for CStuff from CComClassFactory to CStuffCreator.

The actual implementation of the interface consists of the simple code

STDMETHODIMP CStuff::InitStuffInstance(BSTR Name)

{

  m_Name = Name;

  return S_OK;

}

Note the ease with which CComBSTR allows us to perform simple string operations.

Initializing the new CStuff object

Now that there is a dedicated function to handle the initialization, the changes to CStuffCreator are trivial:

HRESULT STDMETHODCALLTYPE CStuffCreator::MakeMeAStuff(

  BSTR name,

  REFIID riid,

  IUnknown **ppStuff)

{

  CComPtr<IStuffInit> newStuff;

  HRESULT hr = m_pfnCreateInstance(

                  NULL,__uuidof(IStuffInit), (void**)&newStuff);

  if(FAILED(hr))

    return hr;

 

  hr = newStuff->InitStuffInstance(name);

  if(FAILED(hr))

    return hr;

 

  return newStuff->QueryInterface(riid, (void**)ppStuff);

}

What about double initialization

By now you might be wondering: But what if the client application retrieves this interface and performs another initialization?

However, this will not be possible.

It’s true that I put the interface in our IDL file, and that I implemented it in the CStuff object. But I did not put that interface in the library declaration, nor did I put it in the interface list of the coclass.

So for all practical purposes, this interface is not accessible to the client application. If you are really paranoid, you could argue that an attacker might know the interface GUID, and guess the interface definition, and with some trial and error make it work.

Even then, the fix is quite simple. You can add a boolean to your class that indicates if the object was initialized or not. Set it to false in the constructor, and then the InitStuffInstance can either perform initialization if it is false and set it to true, or return E_FAIL if it is already true.

You don’t even have to care about race conditions, because there aren’t any. Only the class object can perform the real initialization. And since no one else has an interface pointer yet, there can’t be a race.

The client side

Creating a new CStuff has changed a little bit, because now we can’t use CoCreateInstance anymore. So construction is now done in 2 stages:

    CComPtr<IStuffCreator> stuffClass;

    hr = CoGetClassObject(

           __uuidof(Stuff), CLSCTX_ALL, NULL,

           __uuidof(IStuffCreator), (void**)&stuffClass);

    if(FAILED(hr))

      return hr;

 

    //make a new stuff   

    CComBSTR stuffName = L"Kato";

    CComPtr<IStuff> newStuffUnk;

    hr = stuffClass->MakeMeAStuff(

           stuffName.m_str,

           (GUID*)&__uuidof(IStuff),

           (IUnknown**)&newStuffUnk);

    if(FAILED(hr))

      return hr;

It’s still very simple though. First we get the class object, and then we use the IStuffCreator interface to create the new CStuff.

Server lifetime management

Everything works, hip hip hurray… until you destroy the first CStuff instance, and then try to create another one. That is where it all goes pear shaped.

The problem is that we haven’t taken care of managing the lifetime of the server (the exe). The key issue here is the module lock reference count.

Each COM module (exe or dll) has a global reference count to keep track of how many objects are ‘alive’. COM objects exist physically inside a DLL or EXE. So the EXE has to stay alive as long as there are living objects inside. Conversely, as soon as there are no living objects anymore, the EXE should shut down.

What happens in our example is that CStuff raises the module ref count when it is created. And when the CStuff instance destroys itself, it lowers the module ref count. If you remember correctly, the class object itself uses CComObjectNoLock as its COM core. This means that its existence does not influence the module lifetime.

So when the CStuff instance destroys itself and lowers the module ref count, the ref count reaches 0 and the server EXE shuts down.

The client is unaware of this and tries to use the class object again. It still thinks it has a valid interface pointer, but the underlying class object is long gone and there will be a critical error in the client application.

You might say ‘well duh, then don’t use CComObjectNoLock, doofus’ but that has the opposite effect. The COM runtime will always have the interface pointer that was used for registering the class object with CoRegisterClassObject. This means that the class object would not destroy as long as the server lives. And the server would keep living as long as the class object was around. This is clearly not the answer.

IExternalConnection to the rescue

The key to solving this problem is a rarely used standard interface. IExternalConnection is an interface that can be used by an object to track how many external connections there are to itself. This is basically an alternative to the standard object reference count.

There are 2 methods in this interface:

  STDMETHODIMP_(DWORD) AddConnection(

                         DWORD extconn, DWORD dwReserved);

  STDMETHODIMP_(DWORD) ReleaseConnection(

                         DWORD extconn,

                         DWORD dwReserved,

                         BOOL bLastUnlockReleases);

 

If a client requests any class object, the COM runtime will retrieve it. But before the interface pointer is released to the client, it will request some interfaces itself for housekeeping purposes. One of those interfaces is IExternalConnection.

If a client requests an interface pointer to a class object, the marshaller will call AddConnection when it hands out the pointer, and ReleaseConnection when the pointer is destroyed.

So all we have to do is to make sure that a call to AddConnection will increment the module lock count, and a call to ReleaseConnection releases the module lock count.

Implementing IExternalConnection

If you look in MSDN, you won’t find it. It is undocumented, but the ATL headers contain an implementation for IExternalConnection. It’s called IExternalConnectionImpl<T>.

To use it, we only have to change CStuffCreator so that it inherits from it, and add it to the COM interface map.

class CStuffCreator:

  public IStuffCreator,

  public IExternalConnectionImpl<CStuffCreator>,

  public CComObjectRootEx<CComGlobalsThreadModel>

{

public:

 

  //removed irrelevant stuff

  BEGIN_COM_MAP(CStuffCreator)

    COM_INTERFACE_ENTRY(IStuffCreator)

    COM_INTERFACE_ENTRY(IExternalConnection)

  END_COM_MAP()

 

  //IExeternalConnectionImpl<T> extension

  void STDMETHODCALLTYPE OnReleaseConnection(

         bool bThisIsLastUnlock, bool bLastUnlockReleases);

  void STDMETHODCALLTYPE OnAddConnection(

         bool bThisIsFirstLock);

 

  //removed irrelevant stuff

};

That is really all there is to it. The default implementation does not modify the module lock count. But it has 2 extension points that we can override. So that’s what we do to make sure the module lock count is managed properly.

void STDMETHODCALLTYPE CStuffCreator::OnAddConnection(

       bool bThisIsFirstLock)

{

  _pAtlModule->Lock();

}

 

void STDMETHODCALLTYPE CStuffCreator::OnReleaseConnection(

       bool bThisIsLastUnlock, bool bLastUnlockReleases)

{

  _pAtlModule->Unlock();

  IExternalConnectionImpl<CStuffCreator>::OnReleaseConnection(

    bThisIsLastUnlock,  bLastUnlockReleases);

}

The only special thing that still needs mentioning is that OnReleaseConnection delegates back to the default implementation in IExternalConnectionImpl. It does this because there is something that needs to be done when the last external connection is closed.

  void OnReleaseConnection(

       bool bThisIsLastUnlock, bool bLastUnlockReleases)

  {

    if (bThisIsLastUnlock && bLastUnlockReleases)

         CoDisconnectObject(static_cast<T*>(this)->GetUnknown(), 0);

  }

If the last connection closes, the class object needs to call CoDisConnectObject to destroy its marshalling stub. Now I could copy paste this code into my implementation of OnReleaseConnection, but it is simpler to just delegate back to the base class for stuff that needs doing anyway.

The result

Now that we have provided this implementation of IExternalConnection, the server EXE will stay alive until all CStuff instances are gone, and noone is using the class object anymore. Only then will the EXE terminate.

CComClassFactory revisited

If you look at the interface implemented by CComClassFactory, you’ll notice that IExternalConnection is missing. And yet, server lifetime of CComClassFactory is managed correctly.

The reason for this is that the COM runtime treats IClassFactory class objects differently from other class objects. It will check if the class object supports IClassFactory. And if it does, it calls IClassFactory::LockServer to indicate that someone is using the class object. And it unlocks the class object when the class object reference is released again.

In a way, it uses the IClassFactory in almost the same way as it would use IExternalConnection. And in a way it is too bad that this functionality was included in IClassFactory directly, instead of making IClassFactory inherit from IExternalConnection. The reasons for this are lost in the mists of time. But whatever the reasons, this is why IClassFactory doesn’t need IExternalConnection.

Conclusion

As you can see, implementing a non standard class object is not so hard. As long as you have a basic understanding of the underlying COM principles, ATL takes care of all the dirty work.

And by using these techniques, we can implement COM objects that need initialization before they can safely be used by the client. The source code for this article is available under the MIT license as usual.

And again I’d like to add a thank you for Microsoft’s Tim Springfield and Amit Mohindra

 

 

Practical ATL: Understanding the class object

In my previous article in this series, I explained how to create a simple COM server and implement a method that returns an enumerator object.

It was all done very easily, but the ATL wizards hide some of the things that you really ought to know for my next article. For starters: where is the class object?

The class object is the COM object responsible for creating new instances of the CStuff COM object that I demonstrated in a previous article. But we didn’t have to write any code for it, nor is it even visible… so what’s up with that?

Some more on class objects

The class object of a COM server is the object that is actually responsible handing out instances of the COM object. The class object is a COM object itself, but only 1 instance of it normally exists in a module (DLL or EXE) per defined COM object type.

For example, the ‘Stuff’ COM object that I implemented in my previous article uses the standard class factory with IClassFactory as the interface for handing out new CStuff instances.

The most important method in IClassFactory is ‘CreateInstance’ which simply creates a new instance of the COM object and then passes an interface pointer back to the caller.

Normally, this process is invisible to the client application, because ‘CoCreateInstance’ uses IClassFactory behind the scenes so that the client doesn’t have to bother with it.

First it calls ‘CoGetClassObject’ to get the class object for the requested COM object, and then it uses the IClassFactory interface of that class object to create a new instance. That instance is then passed to the caller, as an interface pointer of the type that was requested in the call to ‘CoCreateInstance’.

I think it is safe to say that ‘IClassFactory’ (or one of its relatives) is the interface on the class object of 99.99% of all COM objects that have a class object.

The default class factory

By default, CStuff uses CComClassFactory as its default class object. But looking at the declaration of CStuff, it is not immediately apparent how it does this.

CStuff derives from CCoClass<T>, which has the macro DECLARE_CLASSFACTORY in its implementation.

For EXE servers, this macro expands to DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory), which in turn expands to

typedef ATL::CComCreator< ATL::CComObjectNoLock< ATL::CComClassFactory > > _ClassFactoryCreatorClass;

DLL servers use CComObjectCached instead of CComObjectNoLock, but I don’t cover DLL servers in this article.

As you can remember from the first article that featured CStuff, the C++ COM classes are missing the IUnknown core by default, because the implementation of that core depends on how we want to the object to behave.

This means we have to shove our class into a COM object to make it whole. For class objects, the CComObjectNoLock is most appropriate, because the lifetime of the object should not contribute to the lifetime of the server executable. Otherwise there would be a deadlock.

The server would start, and create the class object. And then the server would continue to live until the class object was destroyed. But since the COM runtime will always have a reference to the class object, the reference count would never reach zero, the class object would never be destroyed, and the server would never be able to shut down.

And finally, this class definition is shoved into a creator object which will help us by creating a properly initialized instance of the class object itself via its static CreateInstance function.

Associating the COM object C++ class with the class factory

So the COM object C++ class has a typedef that identifies the class object type. But how does the executable use this fact?.

This is where things get a little hairy, and possibly start to make ominous squishy sounds J

After the class declaration of CStuff, there is the innocuous line OBJECT_ENTRY_AUTO(__uuidof(Stuff), CStuff)

The OBJECT_ENTRY_AUTO is a macro that expands to this:

#define OBJECT_ENTRY_AUTO(clsid, class) \
      __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }; \
      extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \
      OBJECT_ENTRY_PRAGMA(class)

Don’t worry if the sight of this code makes you nauseous. That’s normal. I highlighted the important parts

What it does is simple. It’s just how it does it that is ugly. It creates a map entry for the ATL innards of our server executable. In this map entry, it associates the static method for creating the class object with the static method for creating an object instance.

Creating the class object

Now that the class object and the COM object are associated with each other, the next bit of code in the ATL headers is where the magic happens:

  _ATL_OBJMAP_ENTRY* pEntry;
  if (m_pObjMap != NULL)
  {
    pEntry = m_pObjMap;
    while (pEntry->pclsid != NULL && hr == S_OK)
    {
      hr = pEntry->RegisterClassObject(dwClsContext, dwFlags);
      pEntry++;
    }
  }

When the ATL module initializes, it will iterate over all elements in the object map and register each one. And this registration process entails the following:

    IUnknown* p = NULL;
    if (pfnGetClassObject == NULL)
      return S_OK;
    HRESULT hRes = pfnGetClassObject(
                         pfnCreateInstance,
                         __uuidof(IUnknown),
                         (LPVOID*) &p);
    if (SUCCEEDED(hRes))
      hRes = CoRegisterClassObject(
               *pclsid, p, dwClsContext, dwFlags, &dwRegister);
    if (p != NULL)
      p->Release();
    return hRes;

If you do a bit of spelunking in the headers, you’ll see that pfnGetClassObject is a function pointer that maps to _ClassFactoryCreatorClass::CreateInstance. So this code simply creates a new class object and registers it.

Again, this is specific to EXE servers. In DLL servers, the class object is created on demand in the DllGetClassObject function, which is called by CoGetClassObject if the COM server is a DLL.

Creating CStuff instances

If you look at the _ClassFactoryCreatorClass::CreateInstance, you’ll see that its first parameter is a void *. And the value that is passed in this parameter by the ATL module is the address of the static method for creating new object instances.

_ClassFactoryCreatorClass::CreateInstance simply creates a new class object ‘p’, and then calls p->SetVoid(pv); to pass the aforementioned function pointer to the class object.

And the SetVoid method is no more complicated then this:

  void SetVoid(void* pv)
  {
    m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
  }
  _ATL_CREATORFUNC* m_pfnCreateInstance;

I guess the original developer hadn’t had his morning coffee yet when he came up with this name. It manages to be 100% factually correct, while being 100% opaque at the same time. But it does the job.

When the class object has to create a new instance, it simply does the following:

  STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
  {
    // snip irrelevant code
        hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
    // snip irrelevant code
    return hRes;
  }

Providing a new class factory

Now that you understand how the class object plumbing is hooked up, it is easy to see how you can implement your own class object.

Remember how DECLARE_CLASSFACTORY_EX maps a class object to the _ClassFactoryCreatorClass typedef?

In C++, a typedef in a derived class can override a typedef in a base class. So even though the CCoClass<T> base class says that the _ClassFactoryCreatorClass maps to ATL::CComCreator< ATL::CComObjectNoLock< ATL::CComClassFactory > >,

We can override this by simply putting DECLARE_CLASSFACTORY_EX(CStuffCreator) In the declaration for CStuff. That’s really all there is to it. The macro magic takes care of the rest.

Conclusion

If changing the class object for a COM server is as trivial as adding a single line to your COM server C++ class, then why did I just write 4 pages of stuff?

I wrote all this because if I tell someone to use a macro to do something non-trivial, I want him or her to understand what is going on. There are already far too many programmers on this planet who do things without understanding what it is they do, or how it works. And I am not going to add some more by glossing over the details.

Of course, judging by the number of visitors on this corner of the internet that I call ‘home’, I stand little risk of doing so no matter how crappy I would write J

This article was originally part of my article on implementing a custom class object. But after I spent more than 3 pages on the previous explanation, I thought it would be best to put it in a separate article.

A big thank-you goes to Jim Springfield of the Architects team within the developers division (I think) of Microsoft for taking the time to review this article for correctness, and to Amit Mohindra for helping my questions and articles reach the right people.

And you can find the demo project attached to this article under the MIT license.

 

 

Practical ATL: recognizing marshalling problems

Before I publish my next article, I should explain something else about the black magic aspect of ATL / COM: Marshalling.

The Stuff server we made in the previous article is an out-of-proc server. This means that the arguments being passed to / from a stuff instance have to be somehow moved back and forth between different process contexts (or different threading apartments).

In the case of IStuff, we don’t really have to bother, because IStuff derives from IDispatch. And in that case, there is a marshaller (aptly named Universal Marshaller) that can be used to do all this for you.

If IStuff wouldn’t derive from IDispatch, then we would need to provide our own proxy – stub interface that knows how to marshal the interface. With ATL, this is not difficult. You’ll notice that the Stuff solution of my previous article had a ‘Stuff_ServerPS’ project that I didn’t mention before.

That solution will build the proxy stub dll that will perform the marshaling. It is disabled by default, so you have to enable it in the build configuration before it is built. Also remember to rebuild the proxy, every time the IDL files of your project change.

So for the remainder of this article I will show what can happen if there is a marshalling problem. Don’t worry if it all seems ugly, gory, and incomprehensible. Normally you won’t have to deal with issues like this. But if you should ever do, you should at least recognize the signs that you have a marshaling problem.

Confused? It’s the marshaller

If you find yourself in a situation where very weird things happen, suspect a marshalling problem.

If you get the error code E_NOINTERFACE when you know for sure that your object implements it properly, suspect a marshalling problem.

If you get a crash while using an interface pointer that was properly created without getting a HRESULT that indicated a problem,… that’s right: you can bet it’s a marshaling problem.

Example

The article I am currently writing discusses implementing a non standard class object, for the purpose of parameterized construction of the Stuff object. Never mind for the moment about what any of that means.

For all practical purposes: it just means that I defined the following interface via copy / paste / edit:

[

      object,
      local,
      uuid(6DD69CDB-3128-432b-B335-773A287E6F06),
      dual,
      helpstring("IStuffCreator Interface"),
      pointer_default(unique)
]
interface IStuffCreator : IUnknown {
  [id(1), helpstring("method MakeMeAStuff")]
    HRESULT MakeMeAStuff(
      [in] BSTR name,
      [in] REFIID riid,
      [out] void ** ppStuff);
};

There were 4 things wrong with this interface (showing just why you shouldn’t define IDL interfaces in a hurry). This has to be some sort of record.

  1. ‘local’ shouldn’t be there.
  2. ‘dual’ shouldn’t be there.
  3. ‘void’ should be ‘IUnknown’
  4. ‘ppStuff’ should be attributed with riid_is(riid).

So let’s have a look at the result of these different issues.

Issue 1: local

‘local’ simply shouldn’t be there. ‘local’ is a MIDL attribute that –when use in an interface header- causes MIDL not to generate stubs for that interface.

The effect on our interface is that the IStuff specific methods are not forwarded to the remote server.

You might wonder: why does it exist. The answer is: in case you want to write custom marshalling code, or in case the calls never have to be remoted. In that case you can have a local interface and a remote interface. And usage and marshalling could be optimized.

IUnknown is such an interface. But it has custom stub code to deal with things like remoting

The result of using ‘local’ on my IStuffCreator interface is that trying to call GetEnum on the returned IStuff interface pointer will result in a debug assertion: Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

And if you have this problem with COM, it is usually indeed an indication that you have a calling convention mismatch. In this case, it is a side effect of the fact that we are trying to execute a method that isn’t remoted.

Issue 2: dual

This one shouldn’t be here either. Dual indicates that the interface implements IDispatch, and this could have an effect on marshalling.

In this case, it worked just fine. Perhaps it is because of the fact that I use my object as a class object, or perhaps because my interface itself uses only arguments that are automation compatible, or perhaps because the stars are aligned in the proper configuration.

I don’t know. And anything you don’t know for certain will hurt you when dealing with DCOM. It has to be correct.

Issue 3: void

This one is interesting.

If I want to pass an interface pointer, it has to be passed as an IUnknown**, instead of a void**. This is because Universal Marshaller has no idea on how to marshal something which has only contextual meaning, nor does the IDL compiler know what you mean with it.

With this I mean that my server knows it will be an interface pointer, and my client will know it is an interface pointer, but the stuff in the middle doesn’t. It sees just a memory address.

I used void** because that is what QueryInterface itself uses. And what’s good enough for QI should be good enough for me. Except QI has custom code for marshalling its arguments across, which I don’t. So QI can use void** because both the proxy and the stub know what is going on.

So what happens when you use void**?

I request the class object like this:

    hr = CoGetClassObject(
           __uuidof(Stuff),

           CLSCTX_ALL,

           NULL,

           __uuidof(IStuffCreator),

           (void**)&stuffClass);

 

And the resulting hr is 0x80020008: Bad variable type. There is absolutely nothing wrong with this line of code. But because there is something in the interface itself that confuses the marshaller, it tells me to sod off when I want that specific interface.

Credit where it is due: I figured this one out thanks to someone whose name I can’t figure out J. But his blog post is here.

Issue 4: iid_is(riid)

This one is also a good one.

The iid_is informs the marshaller that riid points to the identifier which identifies the interface that is being marshaled.

This way, the marshaller knows how to marshal the interface that was specified with riid. Without that part, it would only marshal the IUnknown part of the interface, and not the IStuff specific part.

As a result, you can use the IUnknown part of the interface without a problem, but if you use the IStuff specific part, you will get an access violation, stack corruption or other interesting phenomenon.

Conclusion

A couple of things can be concluded at this point.

First of all: Marshaling problems are hard to debug, because the problems occur outside of your source code.

If you use any interfaces that don’t derive from IDispatch, then you have to enable the ‘xxxPS’ project in your solution so that the ProxyStub dll will be built and registered. And of course, this dll has to be part of your install procedure. Without this stub, you could get access violations, or you get an E_NOINTERFACE error if the marshaler doesn't know one of those interface exist.

As I have shown, you need to be careful and pay attention when you manually define COM interfaces. If you don’t, then you can have all sorts of hard to diagnose problems.

And if you ever find yourself in a situation where nothing makes sense, then suspect marshalling issues and have a long hard look at your IDL files.

 

File a bug report and make Visual Studio a better product

If you find a bug in Visual Studio, report it on http://connect.microsoft.com If the bug affects the version of VS that is in development at that time, there is a significant chance it will get fixed before the next release. Just this week I got confirmation that all 3 bugs that I filed in the last months have been resolved.

The first one is a nasty one. If you add an ATL project to an existing, non-empty solution, the ATL wizards will either hang the IDE or fail to work when adding an ATL object. I found a workaround for it, but it involved hand editing the solution file.

The second one is a small bug in the TR1 regex parser. No workaround, other than to restructure the regex.

And the last one was an error in the MSDN documentation about open modes with the fopen family, which counts as a bug because it triggered runtime errors.

All 3 have been fixed. I especially appreciate the first one. I am working on ATL projects, and I develop my COM server in the same solution as a couple of related non-ATL projects. So every time I work with ATL projects, I can have a warm and fuzzy feeling that because of me, VS is now a better product. :)

Practical ATL: Implementing an enumerator object

This is my first article about practical ATL examples, which I already mentioned here.

In this example I will create an ATL Server which implements 1 custom interface: IStuff. Hardly an inspiring name, but I couldn’t think of anything better before I had my first coffee.

This interface will have 1 method which will return an enumerator to the caller. Specifically, this enumerator will implement IEnumString.

Enumerators are part of the interface of many real-life COM servers, but creating your own is an arduous task. ATL makes this much easier, but an example makes things so much easier still.

Since client code will have to deal with this enumerator (and to have a demo app) I will also create a client application that creates an instance of the server, consumes the IStuff interface and then enumerate the items contained in the returned enumerator.

Before we get started

If you don’t own a copy of ‘ATL Internals, Second Edition’ yet, I strongly advise you to buy it. It is worth the money, and apart from leading you through all the interesting and gory stuff, it also starts by explaining the actual process of creating an ATL server through the IDE, as well as implementing methods, properties and events.

I am only going to cover that aspect very lightly. It should be detailed enough for anyone who has done C++ development using VS:

  1. Create a new ATL Server project with project name ‘Stuff_Server’ and a solution name ‘Stuff’.
  2. Choose the EXE project type and click ‘finish’
  3. Add a new class to the project, and specify ATL Simple Object. Use ‘Stuff’ as the name of the object.
  4. Switch to classview, and add a new method to the IStuff interface with the prototype ‘HRESULT GetEnum(IUnknown ** ppEnum).  ppEnum should be marked as an ‘out’ parameter.

Build the project, and you should be ready for the actual work. The ATL wizards will have implemented all the IDL and DCOM stuff for you, and you only have to implement the functionality.

Finally, I always end by changing the project configuration to use static CRT and ATL runtimes instead of dynamic runtimes. This makes it infinitely more easy to distribute the resulting executables without having to bother with registration and installation of the runtime dlls and their manifests.

Creating the server

Now that the ATL wizards have generated the function skeleton for us, it is time to do something with it:

STDMETHODIMP CStuff::GetEnum(IUnknown** ppEnum)
{
 
}

The enumerator

Before we can do anything else, we have to think about the actual enumerator for a bit. In our case we implement IEnumString. This is an interface for enumerating string (who’d have thought, eh?).

Enum interfaces all look alike, and ATL helpfully has a stock implementation for generic enumerators that allows you to specify the Interface, GUID, datatype and data type copy traits as template parameters. In order to facilitate coding, we make a typedef for this class:

typedef CComEnum<

                 IEnumString,

                 &IID_IEnumString,

                 LPOLESTR,

                 _Copy<LPOLESTR> > CComEnumStringAbstract;

 

This will specialize the enumerator for our purposes. The use of the first 3 parameters is obvious. Don’t worry about the _Copy parameter. I will cover that later.

The enumerator itself is a normal COM object, so it needs lifetime management, interface managements, and all other things you really don’t want to care about for something so simple. At this point, CComEnumStringAbstract will still be an abstract class because it can’t decide how to do these things for you.

In order to make our enumerator a full fledged COM object, we have to shove it into a bare COM object. This is very easy:

typedef CComObject<CComEnumStringAbstract> CComEnumString;

And that is all there is to creating an enumerator! Anyone who has ever implemented one manually will agree that this is infinitely more convenient

Implementing GetEnum

The implementation for GetEnum is also fairly easy (comments removed for clarity)

STDMETHODIMP CStuff::GetEnum(IUnknown** ppEnum)
{
  CComEnumString * thEnumObj  = NULL;
  HRESULT hr = CComEnumString::CreateInstance(&thEnumObj);
  if(FAILED(hr))
    return hr;

  CComPtr<CComEnumString> thEnum(thEnumObj);

  LPOLESTR strings[] = {L"One", L"Two", L"Three", NULL};
  hr = thEnum->Init(&strings[0], &strings[3], NULL, AtlFlagCopy);
  if(FAILED(hr))
    return hr;
 
  hr = thEnum->QueryInterface( __uuidof(IUnknown), (void**)ppEnum);
  return hr;
}

First we create a new CComEnumString object. It is worth noting that the object returned by CreateInstance has a refcount of 0. Before we do anything with it we should AddRef it, but instead of doing that manually, I do it via assignment to the CComPtr. smart pointer. That way the object also gets released automatically at the end.

Then we have to make sure the enumerator has some data to enumerate. We do this by populating an array, and then telling the enumerator to copy the data out of it into its own internal buffer. This is done via the AtlFlagCopy flag.

It might seem weird if you come from a C background, but the ‘End’ pointer has to point to the first position beyond the last element. This is normal with collections in C++. That is also why I populate the array with a NULL pointer at the end; So that there is something in the array after the last ‘real’ element. This way there is no buffer overflow.

Using AtlFlagCopy has the overhead of having to copy the data, but otoh the enumerator does not have to care about the lifetime of the array. We could also use new[] to create a new array and then use the AtlFlagTakeOwnership flag to indicate that it is up to the enumerator to call delete[] and clean up. But in this example we can’t do that (read below).

When the enumerator is initialized, we return an IUnknown interface pointer to the caller. Since this will have increased the enumerator ref count, the enumerator object will keep on living when the CComPtr goes out of scope and releases its own reference to the enumerator.

There. That is all there is to it on the server side. No vast amounts of copy pasted boilerplate code, but just a couple of lines of powerful ATL incantations J

_Copy<LPOLESTR> revisited

If an enumerator has to copy data to a client, or if it has to copy data into its internal buffers in the ‘Init’ function, it has to know how to do this.

It’s all good and well to do a simple memcpy of an ULONG or a double, but for strings (LPOLESTR) and interface pointers (IUnknown) this won’t work. There’s ref counting and memory ownership to deal with.

Of course, the template class, not knowing about this, can’t anticipate what you want, so instead it needs a policy class to delegate to. That is where the _Copy<> template class comes in. It has 3 methods: Init, Destroy, and Copy. Those methods perform the actual operations needed to copy an instance of T to another instance of T, to initialize a new one, and to destroy one.

There are several stock specializations for _Copy<>, one of which works for LPOLESTR. So rather than copying the LPOLESTR pointer itself, it calls CoTaskMemAlloc to create a buffer for the copy of the string, and then copies over the data.

If you look at my example more closely, you will also see why I cannot simply new up an array of string literals and pass those to the Init function with the AtlFlagTakeOwnership flag.

LPOLESTR is superficially identical to wchar_t*. So using a string literal instead of an LPOLESTR (which is what I do in my example) will work without a hitch. But if I’d new up an array and tell the enumerator to manage it, that is when it would all go pear shaped.

Because the enumerator would not only call delete[] on the array, but it would also call _Copy::Destroy for each of the items. And trying to free up a string literal with CoTaskMemFree will result in a hard to diagnose crash.

Installing the server

On a development station this is done automatically by Visual Studio. But if you need to do this on another PC, you just execute the server from the command line with the /RegServer argument.

Creating the Client

Creating the client application is fairly simple, but I wanted to show how to do it anyway, because then I could demonstrate that the COM server works as intended.

I create a simple win32 console application so that I only had to care about the actual functionality.

Importing the server type library

In the olden days or yore, working with COM servers in a C++ project was a bit tedious. You had to include the IDL files in your project and compile them, then include the resulting header files, add the .c files to your project for the GUID definitions… Not rocket science by any means, but still… a bit messy and ugly.

Now, I have very few kind words for Visual Basic, but to give credit where it is due: Visual Basic is (in large part) responsible for the existence of tlb files.

Visual Basic programmers wanted to use COM too, and the people who made Visual Basic wanted to prevent the application programmers to have anything to do with IDL. They wanted Visual Basic to take care of all that mess behind the scenes.

And thus the type library (tlb) was born.

The type library contains the same stuff as the IDL files, but in a machine readable, programming language independent format.

To use a COM server, you need to do nothing more than add the following line to the StdAfx.h header file of the client program:

#import "Stuff_Server.tlb" no_namespace

You also need to make sure that the compiler knows where to find Stuff_Server.tlb. This is easily done by adding the following line to the ‘Additional include directories’ setting:

..\Stuff_Server\$(ConfigurationName)

If you then compile StdAfx.cpp, the compiler will pull in the type library and generate the appropriate headers which are then automatically included.

The no_namespace attribute tells the compiler that it shouldn’t put the declarations in a specific namespace.

Using the COM server

The client application code itself is fairly trivial:

int _tmain(int argc, _TCHAR* argv[])

{

  HRESULT hr = CoInitialize(NULL);

  if(SUCCEEDED(hr))

  {

    CComPtr<IStuff> stuff;

    hr = CoCreateInstance(

           __uuidof(Stuff), NULL, CLSCTX_ALL,

           __uuidof(IStuff), (void**)&stuff );

    if(FAILED(hr))

      return hr;

 

    CComPtr<IUnknown> thEnumUnk;

    hr = stuff->GetEnum((IUnknown **)&thEnumUnk);

    if(FAILED(hr))

      return hr;

 

    CComPtr<IEnumString> thEnum;

    thEnumUnk->QueryInterface(__uuidof(IEnumString), (void**) &thEnum);

 

    do

    {

      LPOLESTR str;

      hr = thEnum->Next(1, &str, NULL);

      if(hr == S_OK )

        wprintf(L"%s\n", str);

      CoTaskMemFree(str);

    }while (hr == S_OK );

  }

 

  CoUninitialize();

  return 0;

}

First I initialize the COM runtime and then create a new instance of the Stuff object. I request IStuff as the initial interface. I also use the __uuidof keyword to get the GUID for an interface / object instead of using the CLSID_ and IID_ parameters. In my opinion, it is more convenient.

The COM smart pointer takes care of the reference counting for me. This is most convenient, because then I am certain that it will get released properly without me having to worry about it.

Btw, this is also the reason that all the code is placed into a separate scope block after the call to CoInitialize. The smart pointers clean up their interface pointers when they go out of scope. If CoUninitialize would have been called before that, it would lead to weird problems / crashes.

Via the IStuff interface I request an enumerator object. This gets returned as an IUnknow interface, so I have to get the IEnumString interface via the IUnknown::QueryInterface method. So that’s 3 interfaces already, and I still don’t have to care about reference counting J

After that I use the ‘Next’ method of the IEnumString interface to retrieve the items contained in the enumerator. This the only place where I have to perform a manual cleanup action.

The IEnumString interface does not work with BSTRs, it works with LPOLESTRs. While these are code compatible because they are the same type of data, their semantics are not. The _Copy<LPOLESTR> mentioned earlier allocates data for the string using CoTaskMemAlloc. It has to be freed by CoTaskMemFree.

CComBSTR would use SysAllocString and SysFreeString. And while the code would compile and execute perfectly, there would be an crash as soon as the CComBSTR would try to free the string it got from the call to ‘Next’.

Conclusion

As you can see, implementing COM servers and clients can be really easy with the proper use of ATL. And you’ve also seen that implementing an enumerator object is made really easy.

The code demo code is up for download with this article under the MIT license. Have fun.

I will probably write some more ATL / COM stuff soon. Stay tuned for more DCOM archaeology from the mists of time ;-)

Getting started with ATL

I am currently working on some projects where I have to program a DCOM server. There are several reasons why it has to be DCOM and C++, instead of e.g. .NET remoting and C#.

The biggest pain (imo) about DCOM is that the technology stems from an era when the internet was no ubiquitous, and there were no huge forums filled with experts, or blogs by programming gurus and sites like codeproject.com There were newsgroups, but those were generally only used for specific problems.

There is a vast amount of concise information about everything you can do with the .NET framework. For DCOM there is … a big dark void.

Granted, there are several resources out there. But if you look on sites like codeproject, you will find that most of the articles about DCOM and ATL are written before 2003. Most of the information out there will not cover the improvements that have been made to ATL (or DCOM) since the last 5 years.

And when looking into the more obscure corners of DCOM, there are some things that noone really likes to talk about because the documented semantics are so vague, and if you look into things like custom IMoniker implementation… well… that is a story for another day.

Understanding DCOM

The most important thing with DCOM is that you understand the basics really well. I guess this is true for most things, but unlike other things like .NET, DCOM does not cut you any slack, and does not provide you with tons of helpful diagnostic information.

When I started with DCOM a couple of years ago, I first read ‘Essential COM’ by Don Box. This is really the most excellent book on COM ever.

Of course, this information becomes vitally important in the real world when you have to debug a problem, because no tool is going to tell you anything useful with DCOM related crashes.

Understanding ATL

In the real world (unless maintaining legacy code) you use ATL to write COM clients or servers. Personally, I don’t like books that just tell me how to use technology XYZ. I like to understand the ‘why’ and ‘how’ too.

This is where I have to give big thanks to ‘ATL Internals, Second Edition’. It is one of the very few books on ATL that were written for VS2005, and it is still valid for VS2008. It is also an extremely well written book.

If you are starting with ATL (or if you want to know how it works) buy this book. This book is very, very good, and will teach you a lot.

What happens next?

Over the next weeks / months I will probably write a couple of articles describing how to do specific things with ATL. One article that is nearly finished is about implementing and using IEnumString using ATL.

Not rocket science by any measure, but ATL is severely lacking in the area of easy-to-find, up-to-date and to-the-point examples. So I figured that there is still value in writing about the ancient art of circles and lollipops, even if many developers probably think COM and ATL are no longer worth bothering with.

Oh and I released some win32 DCOM demo projects some time ago. They were interesting for me because making them taught me a lot about the raw DCOM stuff that you normally don’t see with ATL. But I’ve always found that it is always useful to know what makes the motor hum.

So while they are not terribly useful for practical purposes, they are well documented and they might be useful if you are working your way through ‘Essential COM’

Cold, Coffee, and Developers

We are going through an unusual spell of cold weather at the moment. It was -15C when I left for work this morning. The intense cold also caused some of the outside water pipes on our site to freeze. In particular, the ones running to the temporary trailers where I am located atm. No water -> no coffee....

Except for me, that is. I have been making my own coffee for a long time now (pouring hot water over a filter with hand ground arabica beans). This means not only am I the only one here drinking good coffee, the last 2 days I was the only one drinking coffee :D.

And I know several peopel whose day did not begin well because of it. But I didn't gloat. Poking fun at people going through caffeine withdrawal is just too dangerous ;)

And for something compeltely different; I read this on Raymond's blog:

Generally speaking, programmers don't do the visual design. I mean, these are people who are lucky if they are wearing matching socks when they come to work, if they even remember to wear socks at all. And you want them to design a color scheme?

I usually manage to wear matching socks, but when it comes to choosing interior decoration, paint colors, curtains and other stuff, my wife is firmly in charge. She has a veto on my clothes too :)

Maybe there are people which are both great developers and great graphics designers. But I'm not one of them, for sure. I prefer command line apps, services, COM servers, drivers, and other low level stuff. I am good with code, not with graphical stuff. The rare few times I need to have a GUI, the best I can come up with is the default grey dialog based application, and a menu if I am feeling creative.

Posted: Jan 09 2009, 01:04 AM by vanDooren | with no comments
Filed under:
More Posts Next page »