::::: : the wood : davidrobins.net

My name is David Robins: Christian, lead developer (resume), writer, photographer, runner, libertarian (voluntaryist), and student.

This is also my son David Geoffrey Robins' site.

Once more into the interface compiler

News ·Thursday April 19, 2007 @ 20:19 EDT (link)

This got so long that I've given it its own entry, separate from the original.

As I've mentioned, I recently did a major rewrite of Word's object model dispatch, which included some gnarly templated (declspec) naked assembly functions. Unfortunately, those are going away now, because x86 assembly doesn't compile in x64 builds (apparently the x64 compiler doesn't do inline assembly at all). The price was an extra level of indirection for C function dispatch (as opposed to C++ or generic handler dispatch). I'm also thinking of changing our (Word-specific) interface compiler to allow inserting small chunks of code directly, so that people don't need to build hundreds of stub functions that just vary one or two parameters to a real handler (this might also obviate the existing handlers, which are pretty limited). So, currently we have something like:
interface IDBorders
{
...
   properties
   {
      VT_I4 DistanceFromRight
         dispid 22
         undo_auto
         get proc HrOamBordersGetFromTextRight
         put proc HrOamBordersPutFromTextRight
   }
}
and the C++ implementation:
/* H R O A M B O R D E R S G E T F R O M T E X T R I G H T */ /*---------------------------------------------------------------------------- %%Function: HrOamBordersGetFromTextRight %%Owner: NoBody %%Id: 00000000-0000-0000-0000-000000000000

----------------------------------------------------------------------------*/ STDMETHODIMPC HrOamBordersGetFromTextRight(IDBorders* pidBorders, long* plFromText) throw0 { return HrOaFormatBorder(pidBorders, wpropFromTextRight, plFromText, fTrue/*fGet*/); }

/* H R O A M B O R D E R S P U T F R O M T E X T R I G H T */ /*---------------------------------------------------------------------------- %%Function: HrOamBordersPutFromTextRight %%Owner: NoBody %%Id: 00000000-0000-0000-0000-000000000000

----------------------------------------------------------------------------*/ STDMETHODIMPC HrOamBordersPutFromTextRight(IDBorders* pidBorders, long lFromText) throw0 { return HrOaFormatBorder(pidBorders, wpropFromTextRight, &lFromText, fFalse/*fGet*/); }
(names and GUIDs removed) repeated over and over with few minor variations; it's be nicer if it was possible to write:
interface IDBorders
{
...
   properties
   {
      VT_I4 DistanceFromRight
         dispid 22
         undo_auto
         get { return HrOaFormatBorder(pid, wpropFromTextRight, plProp, fTrue/*fGet*/); }
         put { return HrOaFormatBorder(pid, wpropFromTextRight, &lProp, fFalse/*fGet*/); }
   }
}
(where pid and lProp/plProp are filled in by our compiler tool, to be the IDispatch interface pointer and the property value respectively). To help prevent abuse, code blocks with more than three statements will result in an error. This win (11 lines + 2 blank per function x 2 = 26 lines saved, which is code developers don't ever need to read) is made possible by the aforementioned removal of assembly: now that we need to generate thunks for C functions, we might as well be flexible with what we put in them, only defaulting to calling the expected implementing function (in this example HrOamBorders(Get|Put)FromRight). The braces make the block unambiguous to our compiler and are a standard sign of a code block in C and C tools.

There are probably downsides to this idea; I hope AT reads this and helps me think this through (hi Ali!). One is that changes to the interface file require (with the new build rules) 111 files to be build in current debug builds, but we can try to cut down those dependencies: really only a handful of source files should depend on object model generated files.

The advantages are clear: remove formulaic code (it could also be moved to a new file, obthunk.cpp, but why write it at all?), making it easier to read source files, and easier to understand how object model calls are implemented (you can go from the property to the actual implementing method, skipping the middleman, and if you really do want to put a breakpoint on a particular method, put a conditional one on the gatekeeper, HrOaDispatch, or put one on the generated thunk function, which has a predictable name).

Muhahaha... I love to delete code. Although I may hold off on this until Office 15 (if I'm still around) - I'll write in the capability, but not do sweeping refactoring yet.

Looking back, looking forward

News ·Thursday April 19, 2007 @ 19:11 EDT (link)


New window
The first entry (hubris much?) in this system is dated November 11, 2000, and I've been keeping an online journal since 1996, then using a static projects.html page on my University of Waterloo math undergrad account; that's over ten years of being on the web. In 1996 I was 18, and the world my oyster; I wouldn't mind being back in school again, although working with smart people to design new things at Microsoft is comparable.

If I may segue: the features we're designing for Word 14 are so new that I probably shouldn't write about them in detail here, but I do want to commit some thoughts about them. Enter private entries: I can now set a private flag on these entries and only view them myself; after all, the main point of this journal was record-keeping, and if nobody ever looked at it I'd still write in it. There are also topics I want to wrestle with without publicizing them, and since converting an entry to public is easy, it makes a good place to save drafts (against accidental tab closure or Firefox dying). The new entries show up locally only and have a different colored heading, and no, they won't show up even if you fish for them by index.

Get Rich Slowly, a site I've been reading, advises having a long-range financial plan, which sounds like a good idea. Right now they're highlighting a series of videos on investing—what are stocks, what are mutual funds, why diversify—which are interesting albeit basic.

Much progress has been made on the house: at the end of March when I wrote last they were finished structure, roofing, and siding, and mostly done drywalling. Now the drywalling is complete, they've replaced the broken windows (left of the front door, garage, bathroom, and one bedroom), and painting is nearly complete. There are some dents in the (new) siding that need to be resolved, and the new bathroom door seems slightly crooked, but aside from that it all looks good. Also, they painted our spare bedroom the same as the rest of the house, rather than the bright yellow it was before, which is great and I am sure will make Honey very happy.


Packed garage
The mortgage company has been very slow at returning our checks (they come from the insurance, who also won't win any speed awards, in our name and the lienholder, so we need to pass them through the mortgage company first, and slice off bits and pieces and send them to us randomly as thanks for the interest-free loan we're giving them). They're sending another 30% today, and then want an "affidavit of completion" to send the rest.

It's been an interesting time here; it's very quiet: I haven't been yelled or fussed at in ages, and I can go to sleep without anyone needing to make sure the covers are perfectly aligned. It reminds me of when I was single, when my pockets did jingle. Ha ha! Honey's been gone since the 6th and will be returning in just over a week (if I pick her up at the airport. I kill myself, I really do).

I started writing about code here, but it got so long that I moved it to its own entry. Enjoy. Next thing on my plate at work is to write some design documents for the new features I'm working on: collaboration and (to a lesser extent, at least in milestone one) server.

I picked up some implements of mass bamboo destruction at the hardware store, using the $250 Home Depot card our insurance gave us: a shovel and a hatchet, as well as some topsoil and bark to cover bare spots and holes (especially those caused by the windstorm; I have three trees tied up now, all of which need more earth), a rake to remove moss, and some grass seed and weed killer. Now I just need a sunny day and a clean garage.

MDM gives away my address

News ·Wednesday March 28, 2007 @ 19:59 EDT (link)

WA plate UNS 457 (light brown Saturn) wins the twit of the week, for driving down the left lane of 51st to pass everyone and then butting in at the end. It's a heinous practice that I see all too frequently, and I wish people wouldn't let them in.


New drywall
Our Internet access was cut for a few days (since Sunday around 2100, back this afternoon), because MDM gave away our Internet (IP) address.

Most MDM customers have a dynamic address, which means it can change at any time (but usually stays the same for extended periods, sometimes for months), and this address is assigned automatically from a pool of addresses using a protocol called DHCP (Dynamic Host Configuration Protocol), which also provides other information to tell a computer how to connect to the Internet.

Having a dynamic address is unsuitable* for running a server (such as the web server that served up the web page you're reading this on) since it's important that the location of the server be known. Furthermore, many ISPs block people from running servers without a static IP, purely out of meanspiritedness (I used to run a server in Waterloo, Toronto, and Fonthill from a regular consumer account with, technically, a dynamic IP, although it didn't change much). Static IPs are usually only available in a "business class" plan; this is the case with MDM (but not with Speakeasy, which is the greatest ISP ever, although they just got bought by Best Buy; I hope for their customers' sakes that quality doesn't degrade).

However, someone at MDM made a mistake and put my static address into the DHCP pool, and naturally enough a computer on the dynamic network got it when it asked their DHCP server for an address to use. Two computers on the same network can't use the same address; it creates conflicts (who gets their packets?) They fixed that today, removing the address from the DHCP pool, and it's working again. They also were able to set up reverse DNS, which will help immensely with getting removed from various mail server blacklists set up by self-appointed net policeweenies (I've just requested removal from Spamhaus's PBL, which was a fairly painless process, especially compared to some).

* There are workarounds, e.g. sites that provide DNS for dynamic addresses, such as dyndns.com, or it's possible to run a script to update DNS whenever one's assigned address changes, but it's inconvenient (for one thing, DNS values are cached and changes take a while to propagate, even with low TTL values).


New roof
In other news, there's no longer a hole in our house: since I last wrote, the trusses have been replaced (some sistered in beside the old ones), the new roof has been installed (it's a nice medium gray), the framing, exterior siding, and drywall has been completed (including Honey's bathroom skylight, although they had to redo one side when we noticed it had been made too small); yesterday they did taping and mudding; I believe painting is next, and after that probably carpet, or perhaps fixtures. They also have some windows sitting around to replace some that were damaged: the master bedroom, the front door, garage (it's on the side that was hit), and downstairs bathroom. I'll post pictures.

REOIV of Fark, commenting on the article Most illegal immigrants crossing into Texas have to be arrested at least six times before federal authorities will prosecute them (a deplorable state of affairs) did me the kindness of coming up with a truly comprehensive plan for illegal immigration (my comments in italics):
  1. Make it a felony to be an illegal immigrant. (Instead of a civil misdemeanor as it is now.)
  2. Punishment options are deportation or jail time billed to your country in the form of tariffs etc. (We'd soon own Mexico and everything in it.)
  3. Arrest illegals any time they are discovered, be it school, hospitals, traffic violations etc. (No more crap like "sanctuary cities" or not being able to ask about legality during traffic stops.)
  4. Anyone helping hide illegals is charged with aiding a felon. (This means you, Roman Catholic church of Satan.)
  5. Any company found to have funny tax information (i.e. their employees are using stolen SSNs etc) or employing illegal immigrants repeatedly loses their right to do business inside the US until the issue is taken care of along with the people in charge of the company are not allowed to run any other companies or businesses. (Punish the enablers, too.)
  6. Any time your Social security number is found being used with another name or in another town every person listed with that number is sent a letter instead of nothing happening. (It's my identity you're stealing; you haveno privacy rights.
  7. All credit reports pull everything based on your social security number on its own even if the names don't match up.
  8. Make English the official language of the United States. Any and all government documents and paperwork are only in English. If you require a translation it is on your dime.
  9. You are only an American Citizen by birth if your parents are American Citizens or were legally in the United States when you were born. If you cannot prove they were here legally when you were born you are not an American citizen. (I can see relaxing this to require only one parent to be a citizen, and only requiring the other to be a legal resident, and not merely for my own sake; it's just reasonable.)
Do those nine things and the problem will clear up quite a bit.

I'd add:
  1. Also fine business employing illegals, say $10k the first time, $100k for the second and subsequent times; raise it for larger companies.
  2. Build the wall; regularly check for tunnels, let agents use them for explosives exercises.
  3. Mine the border, posting appropriate signage (see the Fark link for examples).
  4. Let anyone patrolling the border shoot invaders on sight.
In a similar vein, the Seattle Times has an article stating that low-paid illegal work force has little impact on prices; we frequently hear that getting rid of illegals will cause prices to skyrocket in pro-illegal propaganda.

I got my trophy copy of Office 2007, and my Ship It! plaque last month, with the Office 2007 sticker; very nice. At work we're still planning for M1 (Milestone 1); this release is to only have two milestones (plus M0/MQ/MI: Milestone 0, Quality?, or Innovation, an initial milestone where there's space to do work like my object model rework); Office 2007 had three, but it was a long cycle. We're getting down to scheduling developers; I'm divided between collaboration and server work, which is what I wanted. It should be an interesting journey.

A radio commercial recently caught my attention, because in it they speak about "Nassau scientists" and later about astronauts; I think they want people to think they're saying "NASA scientists", but they're somehow prohibited from actually claiming that (because we know advertisers are scum enough to claim anything if it'll make them richer).

Last, a couple words about country music. I'm fairly fond of old country music—songs about cowboys and lonesome roads and wide prairies and jukeboxen and so on, but I find new country is generally fairly tacky, focusing more on trailer parks and unwed mothers. I suppose it tries to follow reality, so perhaps I'm more upset at reality than music. I've only been inside one doublewide trailer, and it was pretty nice, on a good piece of land, and probably a tenth of the price it'd cost in a bigger city.

We now return to our original problem

News ·Tuesday March 13, 2007 @ 22:06 EDT (link)

A few weeks back I had some trouble RASing (remotely connecting) into work; when it started, I could connect to the VPN but not login to my machines. When I got to IT support, though (escalated to tier 2, eventually), the problem was worse: I couldn't even connect to the VPN: the client, IT Connection Manager (CM), just kept counting. No logs or diagnoses, or course; it's a Windows program, written by incompetents. Naturally I mess around with tcpdump on the Gentoo Linux NAT server (and windump on the Windows XP client), determine it's using PPTP, read the RFC, but don't see anything wrong to start with. It doesn't help that CM keeps on requiring reboots (not obviously, but it gets wedged so that it stops working even if directly connected to the Internet). Eventually I figure out that the NAT box is translating the incoming CLIENT_ID but not the outgoing one, so I switch off translation (it's really only required for multiple clients inside the firewall) and it now connects again.

My second problem was that OWA kept giving me 500 Internal Server Error whenever I tried to login, but eventually I figured out that I needed to use a different server. Entirely non-obvious from a one-line error; such cases should be caught.

So now we're back to the third problem, that I can't terminal serve to my machines. I suspect it's a certificates issue, but who knows; Windows is severely opaque. I'll tell y'all what the problem was if and when IT manages to fix it.

I was home today since both roads to Redmond (124th Street and Woodinville-Duvall) had flooded, which gave me the time to do the aforementioned diagnosis work.

After the "adds/cuts" meeting Friday/Monday, both Word 14 features that I'm interested in are still alive: server and collaboration. I'm still not sure which I'm most interested in, especially as politics enters into it too (e.g. perhaps one group is friendlier, or has less senior people in it which means a better chance to do interesting work). Ah, yes, politics: when features make the world go around (and the employees move up), it's a barroom brawl behind polite smiles.

Construction is scheduled to begin on the trusses and roof this week, starting Thursday. We've contacted our mortgage company and they've received our paperwork and should be sending back the check in a few days.

We'll be flying in to visit the family in August, thanks to my Uncle Murray (he's paying for us to fly up for his daughter's wedding), probably staying for a couple of weeks, perhaps going on a camping trip with the family for a few days.

That's so gay

News ·Wednesday February 28, 2007 @ 22:44 EST (link)

Silver Mazda MPV, WA 803 MDN, cuts me off driving down 163rd Avenue to 40th Street, honked my horn at him; almost got himself run right off the road, idiot.

A teenager gets harrassed, fires back with "That's so gay." Clearly, this is a matter that must be discussed in court. Rebeka, the teenager in question, is Mormon, and was asked questions such as, "Do you have 10 moms?"; she was sent to the principal and given a warning and a notation in her file (whatever that means). Her parents are suing to get it removed, which they shouldn't have to do; it never should have gone that far, and, what, it's fine to insult Mormons, but homosexuals are special (sort of like it's fine to insult Christians, but Muslims are special)? Equal punishment would have been nice; no punishment, better. Kids are kids, and they're pathological, but let's focus on educating them and save discipline for real personal harassment.

One of the Fark comments about it ended with
Anyhoos... of all those groups, the mormons singled themselves out... I mean seriously, they literally pulled their religion out of a hat! I mean, between them and the Scientologists, it's like some kind of functionally retarded race to see who can come up with the most implausible wacky ideas.
Which I think sums things up nicely.

Talk about recidivism: the Mexican drug smuggler that was given immunity in return for helping jail two Border Patrol agents is back at it; then again, I suppose if I had immunity for a crime that profitable I would be too. Here's hoping the full story about the Border Patrol agents comes out (no, I don't know what it is); there are a lot of murky edges. But if it's as simple as them taking potshots at a suspicious illegal alien that was trying to evade them, I hope they're set free and each given medals.

On the house: we have the big check from the insurance, but it has to go through the mortgage company, but we have all the forms so we'll mail that tomorrow and they'll send back part of it with the rest being contingent on their inspection of the work when it nears completion. The contractor and his crew are set to start removing broken trusses and putting in new ones next Thursday and will work over the weekend.

On Word: I'm finally finished the 11 sp3 OACR fixes, which is celebration-level great; we're still planning 14 (major features to be server and collaboration, I'd like to own a major portion of the server work); I've synced and built from the 14 depot but we won't be able to check in until mid-March (because the test team has screwed up all the tests and now needs to fix them).

I sent my N-400 (U.S. citizenship application) last week; current processing times are 8-9 months, so I expect to hear back then for fingerprinting, a civics exam (What are the branches of government?; How many senators are there? Why does the U.S. flag have 13 stripes? and other questions that Americans usually can't answer), and then if all goes well, to be given an oath ceremony date. I told some guys at work, they say they'll crash the ceremony, that should be fun.

And on the Perl front: I released HTTP::Parser 0.03 and Net::SSH2 0.10, fixing all the bugs for those modules; for the legacy Net::SSH::Perl and Net::SFTP modules, most of the bugs were bogus, but there are a few I plan to fix eventually. Regarding the (Microsoft) Office OpenXML modules, I decided against using the Relax NG schemas, since there are no good parsers for them and they're not easily LR(1) (James Clark's reference parser, written in Java, uses the LL(k) lookahead features of JavaCC), so I went with XSD, which is straight XML and can easily be converted to a tree of nodes which will convert between XML and perl objects.

Looking forward to garage sales

News ·Thursday February 15, 2007 @ 22:51 EST (link)

Yep, I'm looking forward to spring cleaning and garage sales, maybe I'll snag a couch for my new office (I moved into my new office Monday, we're at the far end of the building this time 'round). Maybe I like garage sales because it's one of the few places I can still haggle with sellers (the other place I used to haggle was buying lenses at used camera stores; for example, I recall getting my Nikor 105mm macro AF-D for $150 less than the asking price). One just needs to be willing to walk away; there's usually another sale just down the street. Also it's a fun thing to do on weekend mornings.

Honey wanted to get the Our Daily Bread daily meditation emailed to her, but they weren't offering the service any more, so I whipped up a quick perl script using LWP::UserAgent, naturally, pulled out the relevant bits of the page (with regular expressions; there was no need to parse the page), formatted an email with MIME::Lite, and sent it with Mail::QmailQueue. I added it to cron(1) and it's working just fine. I don't think they'd object (they send the paper version for free, and the page doesn't have ads), they just didn't want to be in the business of sending automated email any more.

Two events coming up, both Tuesdays: SPUG hackathon on the 20th and UW 50th anniversary celebration at the Bellevue Arts Museum on the 27th. The last UW event there was interesting and I won a sweater and a baseball cap, so we may go to this one too. (Excuse me while I break to clean up the SPUG wiki front page. That's much better.) Anyway, no, I haven't made a SPUG meeting yet but I hope to make the next one; a hackathon sounds like fun, and I hope rumors of the group's death are greatly exaggerated.

I taught myself a little about LDAP today and managed to muddle my way through getting the ActiveDirectory server to talk to me. Today was the first weekly Word "brown bag" (lunch meeting), each of which will have two people each cover a topic in Word (for example, today was Layout and Email (Word is the default Outlook viewer and editor)), so I was thinking that when I get to my topics (object model and autoformatter, possibly the idle loop too) I may want to use the wiki. But if I do, I'll want to provide a link to the "slides", and right now it rejects users not in the database out of hand (mod_auth_sspi knows their login names, though). Currently I lookup known users' real names in my login table, but it'd be nice to address guests by real name too, hence my poking at Active Directory. I tried Net::LDAP first, but it doesn't do authenticated logins, which would mean storing my password in the wiki code in plaintext (no thanks) so I looked at the RFC 1823 LDAP API, discovered that Windows supports it, and hacked together a few queries. Now I just need to wrap it in a perl module for easy access.

How can these people call themselves our representatives?

News ·Sunday February 11, 2007 @ 01:08 EST (link)

I recently found my way to Americans for Better Immigration, which provides immigration score cards for members of congress, and things aren't pretty. They also have grades for presidential candidates. News shows frequently show the majority of the people being against free handouts and benefits for illegal aliens (benefits that legal residents and citizens usually can't get), but many of these clods in Washington (D.C.) are voting to give away the farm at every turn. Why would anyone support in-state tuition for illegals, when someone from the next state over can't get it? Why not crack down on people stealing identities? Why shouldn't the loophole in the fourteenth amendment that spawns so-called "anchor babies" be closed? Our state senators, Maria Cantwell (votes) and Patty Murray (votes) both scored D-. Why vote against a border fence that helps keep drugs out (sure it's not perfect, but it's a great start)? Mine the borders, build the fence, require employers and landlords to check eligibility, fine the ones that fail it, and take away the free stuff. When they find themselves out in the cold, they'll get the hint and go home.

(Technically, my government representatives aren't responsible to me yet, neither should they be, since I'm not a United States citizen, although I'm preparing my N-400 package presently and after I get my two passport photos and make some photocopies I can send it all in and hopefully get called for a citizenship interview in about ten months.)

Now, how about China? We need to quit buying from them, post-haste; it's hurting the country in the long run. Export and sell goods, sure, but anything we can make here we shouldn't buy there, and a little protectionism and insularity is good for the country. What does the US need from the rest of the world? Just oil, and only because we don't want to drill in the ANWR. If we don't need goods, we shouldn't be importing them, but placing such restrictions is unfree and makes people cry, so instead, tax the hell out of it. Make people pay for propping up hostile foreign nations. Maximizing exports and minimizing imports is the route to long-term profitability. CEOs only care about the quarterly financial statement, so they don't mind exporting jobs overseas and raking in the savings that come from a lower standard of living; the representatives of our government should be looking further ahead. This nation was not founded to support Mexico, China, and a few plutocrats.

I've talked about property tax before, and how most of it goes to schools and since I don't have anyone in school, I shouldn't have to pay that part of it; I wonder if there are any (non-retirement) communities that have resolved not to have schools, and so have drastically lowered property taxes? Of course (for all intents and purposes) not having children in the community means a lack of low-skilled labor too (think service industry), so I may have to rethink my cunning plan; perhaps it'll help to think of my subsidizing schools as actually facilitating child labor. Don't any of you read too much into this, either; that really annoys me. Just take it as my personal musings and leave me alone.

House update: the bids are in

News ·Saturday February 10, 2007 @ 16:59 EST (link)

We heard from our contractor yesterday that he has all his estimates (the last one he was waiting on was the carpet; the insurance is going to replace the master bedroom, and the other bedroom and the hallway carpet too), except for the permits fees; apparently Duvall City Hall is closed most of the time (my tax dollars at work no doubt). His total was about $44k (before tax, overhead, and the aforementioned permits), the adjuster's total was about $47k (but he was too low for the roof and the painting costs); the contractor is going to fax his bids to the adjuster, so hopefully it won't be long before they can start repairs. In toto, these are: We picked up an electric toothbrush (Oral-B Triumph) at Costco, on the recommendation of my dentist (I just went in for my bi-annual cleaning). I expected bleeding when I first used it, but there was none, so I guess I was doing a pretty good job brushing. We also started replacing some of our claimed items, picking up a door mat and laundry sorter. We still need to keep receipts so the insurance will pay the depreciation that they're holding back.

Microsoft Word COM dispatch rewrite

News ·Wednesday February 7, 2007 @ 20:20 EST (link)

I came up with two major Office 14 M0 (milestone 0) projects: one to remove our use of C's setjmp and longjmp (which were used as a poor man's exception; Word was only converted to C++ early in version 12, aka 2007), and another to clean up the object model dispatch, including allowing direct dispatch to Word object methods. The setjmp cleanup could have been trivially done by changing the jumps to exceptions, but that's not the Word way; they were all laboriously changed to return codes, propagated as far up as needed.

Word's object model begins with the GOD structure, or Generic Object Descriptor, a structure of pointers to useful information: first of all, the vtbl (virtual method table, containing pointers to all of the methods implemented by the interface), various other tables, and then the Generic, a structure that naturally became an object during the C++ conversion. The Generic implements the standard IUnknown COM methods AddRef, Release, and QueryInterface, as well as IDispatch, and various internal bookkeeping (for example, keeping track of "advise lists" so, for example, parents can be notified of child deletion and vice versa). It also stores a void pointer which user data can be hung off of, usually a reference to some internal Word structure. Care is taken so that when the item referenced goes away (for example, a document is closed), the object is notified and can mark itself deleted so that it doesn't try to use invalid pointers and crash.

There are several ways to implement COM interfaces; in fact, I wrote a work report about some of them for school, which received a Microsoft-sponsored award. The most common is probably to simply define the interface an an IDL (Interface Definition Language) file, and generate a C or C++ header with MIDL, the Microsoft IDL compiler. Word does have an IDL-type file, but it's not IDL, probably because it had an object model before IDL existed (I don't know, I wasn't there, but we do use our own tools), and we have our own compiler, OAC (probably Office Automation Compiler). In it, one can specify a handler for each method: either a specific function, or a generic handler, which is called in much the same manner as IDispatch::Invoke, i.e. with an array of parameters and flags, as well as method-specific parameters. Handlers are useful for forwarding interfaces to internal classes implemented elsewhere, or for wrapping commands (e.g. one class of handler saves the old selection, selects the object called on, runs a command specified by a handler parameter, and restores the selection).

However, there's a lot of duplicated code in function handlers; many functions extract the previously mentioned void pointer from the generic and invoke a class method; the compiler should be able to generate this code. So, I added support for a class_handler directive to OAC, which would dispatch COM methods to a similarly-named method in a given class, automatically casting the generic's user pointer to an object of that class:

Old:
interface IDShape
{
...
   properties
   {
      VT_FLOAT Width
      dispid 999
      get proc HrOamShapeGetWidth
   }
}

...

STDMETHODIMPC HrOamShapeGetWidth(IDShape *pidsp, float *pflWidth) { int fIDispatch = vrf.fIDispatch; int fObjModelCall = vfObjModelCall;

Generic *pgen = PgenFromPunk(pidsp); OASO *poaso = (OASO *)LpvFromGenericInstanceData(

HRESULT hr = poaso->HrGetWidth(pflWidth);

vrf.fIDispatch = fIDispatch; vfObjModelCall = fObjModelCall;

return HrRaiseExcepHr(pidsp, hr); }
New:
interface IDShape
class_handler OASO
{
...
   properties
   {
      VT_FLOAT Width
      dispid 999
      read_only
   }
}
And both need:
HRESULT OASO::HrGetWidth(float *pflWidth)
{
   *pflWidth = PtFromEmu(PspInternal()->flWidth());
   return S_OK;
}
(Some code facts and names have been changed, but it's a representative sample.)

You won't believe how many times the save/restore of the object model flag code and call to HrRaiseExcepHr (or variants) are repeated. That's one of the things that this new dispatch solves, by going through a common function, the new HrOaDispatch, rather than dispatching directly to the function in question (which didn't always happen; the old code had wrappers too, to setup undo, for example; it was very crusty). True, it does add the overhead of an extra call, but the common entry point makes it easier to ensure that calls are safe (for example, avoiding reentrancy from event callbacks). But getting direct dispatch to C++ methods was decidedly nontrivial.

Fortunately, I started with a fairly pathological class: the shape class, which has virtual bases (there are four combinations: old or new shapes, and inline or floating shapes, all inheriting from a common virtual base, and, for example, there is a "new shape" mid-hierarchy class that provides functionality for both inline and floating new shapes; a new floating shape inherits from the new shape and the floating shape class, both of which derive from a common base). If I can dispatch to this guy, everything else is easy.

To start with, we have to know what method we're dispatching. The old code did this with #defined stubs, but now with C++ we can use templates. What exactly do we put into the object's vtbl? The functional case is easy: just store the function pointer, although to provide a little more information (such as the COM class and method index, for other lookups), a template function is used that accepts these all as template parameters and passes them on to HrOaDispatch. HrOaDispatch then uses the information to figure out how large the stack parameters are for the final function, copies them to the stack (yes Virginia, in assembly), and calls the function, which, in usual stdcall fashion, cleans up the stack for us before it returns.

However, I didn't know at first how complex object model calls can be, especially with virtual bases involved. My first plan was to store the method address and then set up the stack as for function dispatch, and somehow call the method with assembly. Bad idea; the assembly dispatch code generated by the compiler is varied and complex. Instead I wrote a template to do the call: HrOaCallMethodC, HRESULT (C::*)()(C* pC, void *pStack, size_t cbStack), and stored the address of that templated function to use to dispatch the call to the C++ method (letting the compiler do the work of setting it), using #pragma pointers_to_members to ensure all virtual pointers were the same size as well as turning off runtime stack checking for that code (the compiler gets upset when a method that says it takes no parameters has actually consumed parameters).

This took a lot longer to figure out than it takes to write; one of the snags I faced was having to build a separate version of the precompiled headers (PCH) with the runtime checks disabled (disabling them for all of Word wouldn't be looked on favorably); figuring out a way to dispatch to a general method was tough too; there was a lot of casting and gnashing of teeth. But it's worth it to have cleaned up and improved some very old object model dispatch code.

OACR almost whacked

News ·Tuesday February 6, 2007 @ 23:47 EST (link)

I've mentioned OACR1 before; we're still working on Office 11 sp3 (Office 2003 service pack 3 to the folks at home); OACR analyzes source code and points out vulnerabilities (or possible vulnerabilities), such as buffer overflows, and we fix the problem if there is one (usually not, but catching even one exploitable overrun makes much of the hassle worthwhile), or suppress the warning with a comment (OACR frequently isn't intelligent enough to understand how buffers are being managed), or add an annotation or OACR_ASSUME to help OACR understand. It's a massive pain in the behind; such things are the reason God invented interns, but we don't have any right now so we're all pitching in until the muck is raked and we can leave Office 11 alone forevermore (only to get into Office 12sp1, which won't be as bad). In these cases, it would be great to leave the past in the past; we make all these improvements to the product, including to the architecture and the source code, and then we have to abandon them (or copy them all over). Arggh! (For instance, Word 2003 isn't even in C++; it's straight C, the C++ port was done early in 12.)

There are quite a few people in the world that aren't aware that Washington Initiative 957 is just a ploy by gays and sympathizers in their continuing quest to validate and legalize gay marriage. In a nutshell, the Initiative proposes that marriages that don't produce children within three years be annulled; they're aiming at those that oppose gay marriage because it can't result in procreation. It's silly because that's a stupid reason to oppose gay marriage, but they're hoping that people will see the initiative, oppose it, and "throw the baby out with the bathwater" as someone on ChatMS so elegantly put it. One might hope that people aren't that stupid. Haha.

[1] Generally pronounced "whacker" (which makes the headline make more sense), but at least one person pronounces it "ochre".

<Previous 10 entries>