I was writing some unit tests today where I wanted to start some process asynchronously, but have it automatically exit after a specified number of seconds. Preferably something that's available on a standard W2K3 box, so that I wouldn't be creating any additional prerequisites for other developer boxes or the build machine.
Usually I just use
ping -t -n count host for this, but I was also thinking that it would be nice to be able to terminate the process before the timeout. Not sure exactly how I came across it, but somehow I found
waitfor.exe lying around in my
WAITFOR uses a mailslot to wait on or send a signal to. The waiting and sending can happen on the same machine, or the signal can be sent across the network.
In one command prompt, you perform the wait:
C:\\> WAITFOR /T 42 SignalName
In another, you send the signal:
C:\\> WAITFOR /SI SignalName
Way nicer than the old-fashioned approach of having process A poll a directory until process B has created a particular file. And, no less important, if the signal is not received within the specified timeout, you get:
C:\\> WAITFOR /T 1 Godot
ERROR: Timed out waiting for 'Godot'.
In my previous post, I wrote about some findings w.r.t. REGEDIT. One of them was about a limitation on the depth of key hierarchies during a registry export.
When I found out about this limitation, I was actually encountering stack overflows in REGEDIT. However, shortly afterwards I wasn't able to reproduce that behaviour, so I considered it to be some fluke and just wrote about the limitation itself.
However, today I managed to overflow REGEDIT's stack again by just having it export a deep hierarchy to
.REG, and this time I captured a crash dump:
0:000> kb 300
ChildEBP RetAddr Args to Child
0004308c 77f60938 000002b8 00000000 000430b8 ADVAPI32!LocalBaseRegEnumKey+0x13
000430c4 0100bb37 000002b8 00000000 00043654 ADVAPI32!RegEnumKeyW+0x8c
00043890 0100bb08 000002b8 000438a0 004b0048 regedit!PutBranch+0x124
0004404c 0100bb08 000002bc 0004405c 004b0048 regedit!PutBranch+0xf5
00044800 0100bb08 000002c0 00044810 004b0048 regedit!PutBranch+0xf5
00044fac 0100bb08 000002c4 00044fbc 004b0048 regedit!PutBranch+0xf5
... Removed 190 lines that all end in regedit!PutBranch+0xf5
0007f1d4 0100bb08 00000578 0007f1e4 004b0048 regedit!PutBranch+0xf5
0007f458 0100bb08 0000057c 0007f468 004b0048 regedit!PutBranch+0xf5
0007f6c8 0100be1b 80000001 0007f6f0 00070e54 regedit!PutBranch+0xf5
0007f944 01006be3 0007f974 01059de0 00070e54 regedit!ExportWinNT50RegFile+0x16d
0007f958 01007272 00070e54 00000000 0007f974 regedit!RegEdit_ExportRegFile+0x2e
0007fb80 010062eb 00070e54 0000110a 7739c2ee regedit!RegEdit_OnCommandExportRegFile+0x65
0007fb98 01009751 00070e54 00000293 00000000 regedit!RegEdit_OnCommand+0x7f
0007fbbc 01009947 00070e54 00000293 000ad310 regedit!RegEdit_OnKeyTreeCommand+0xc4
0007fc24 010045ba 00070e54 00160c39 0007fc50 regedit!RegEdit_OnKeyTreeContextMenu+0x1a1
0007fc34 0100689f 00130dc2 00070e54 000002c4 regedit!RegEdit_OnContextMenu+0x2a
0007fc50 7739b6e3 00130dc2 0000007b 00070e54 regedit!RegEditWndProc+0x128
0007fc7c 7739b874 01006777 00130dc2 0000007b USER32!InternalCallWinProc+0x28
0007fcf4 7739c2d3 00000000 01006777 00130dc2 USER32!UserCallWinProcCheckWow+0x151
0007fd30 7739c337 00615210 00615118 00070e54 USER32!SendMessageWorker+0x4bd
0007fd50 7745b0ee 00130dc2 0000007b 00070e54 USER32!SendMessageW+0x7f
0007fd74 7745bcfc 00070e54 00000062 00000025 COMCTL32!TV_SendRButtonDown+0xad
0007fdc4 7739b6e3 00070e54 00000204 00000002 COMCTL32!TV_WndProc+0x616
0007fdf0 7739b874 7745b6e6 00070e54 00000204 USER32!InternalCallWinProc+0x28
0007fe68 7739ba92 00000000 7745b6e6 00070e54 USER32!UserCallWinProcCheckWow+0x151
0007fed0 7739bad0 0007fef8 00000000 0007ff1c USER32!DispatchMessageWorker+0x327
0007fee0 01009cb9 0007fef8 ffffffff 00000000 USER32!DispatchMessageW+0xf
0007ff1c 01016e04 01000000 00000000 000a24a6 regedit!WinMain+0x154
0007ffc0 77e6f23b 00000000 00000000 7ffdf000 regedit!WinMainCRTStartup+0x182
0007fff0 00000000 01016c82 00000000 78746341 kernel32!BaseProcessStart+0x23
If somebody wants to dive into the crash dump, let me know.
Exporting a deep key hierarchy on W2K8 X64 didn't work either, BTW:
NOTE (2008-08-21): Also see the update to this post.
I've been working on a tool that can export registry information in REGEDIT's
.REG format. Since that format doesn't seem to be fully documented, I spent quite some time experimenting with REGEDIT. Here are some of my more interesting findings (all on W2K3).
No expansion beyond 32 levels
When you expand a key in REGEDIT, it passes the "root"
HKLM) and the full path to
RegOpenKey() instead of the immediate parent and just the name of the key you're trying to expand. This means that it will run into the "up to 32 levels at a time" limitation of the registry API:
No export beyond 200 levels
Although the registry supports 512 levels of keys, REGEDIT will only export upto a depth of about 200, silently ignoring anything beyond that...
Granted, that's not a very common scenario, but I would expect at least a warning message or something.
Importing values of non-existing types
WinNT.h defines 12 value types, ranging from
REG_NONE (0) to
REG_QWORD (11). REGEDIT however, will gladly accept all other 32-bit values as well...
I was just looking at Recipezaar for some culinary inspiration, and found the following "popular recipes" on the home page: