Holy cow, I wrote a book!
If you are running Windows Server 2003,
you owe it to yourself to
enable the Volume Shadow Copy service.
What this service does is periodically
(according to a schedule you set)
capture a snapshot of the files you specify
so they can be recovered later.
The copies are lazy: If a file doesn't change
between snapshots, a new copy isn't made.
Up to 64 versions of a file can be recorded in the
Bear this in mind when setting your snapshot schedule.
If you take a snapshot twice a day, you're good for a month,
but if you take a snapshot every minute,
you get only an hour's worth of snapshots.
You are trading off snapshot quality against quantity.
Although I can count on my hand the number of times
the Volume Shadow Copy service has saved my bacon,
each time I needed it, it saved me at least a day's work.
Typically, it's because I wasn't paying attention and deleted
the wrong file.
Once it was because I make some changes to a file and ended up
making a bigger mess of things
and would have been better off just returning to the version I had
the previous day.
I just click on "View previous versions of this folder" in the
Tasks Pane, pick the snapshot from yesterday, and drag yesterday's
version of the file to my desktop.
Then I can take that file and compare it to the version I have now
and reconcile the changes.
In the case of a deleted file,
I just click the "Restore" button and back to life it comes.
(Be careful about using "Restore" for a file that still exists,
however, because that will overwrite the current
version with the snapshot version.)
One tricky bit about viewing snapshots is that it works only on
If you want to restore a file from a local hard drive,
you'll need to either connect to the drive from another computer
or (what I do) create a loopback connection and restore it
via the loopback.
Note that the Volume Shadow Copy service is not a replacement for
The shadow copies are kept on the drive itself, so if you lose the
drive, you lose the shadow copies too.
Given the ability of the Volume Shadow Copy service to go back in time
and recover previous versions of a file,
you're probably not surprised that the code name for the feature
John, a colleague in security, points out that
shadow copies provide a curious backdoor to the quota system.
Although you have access to shadow copies of your file, they
do not count against your quota.
Counting them against your quota would be unfair since it is
the system that created these files, not you.
(Of course, this isn't a very useful way to circumvent quota,
because the system will also delete shadow copies whenever it
feels the urge.)
Commenter Andrej Budja asks
why cmd.exe is not themed in Windows XP.
(This question was
repeated by Serge Wautier,
proving that nobody checks whether their suggestion has already
been submitted before adding their own.
It was also asked by
a commenter who goes by the name "S",
repeated again just a few hours later,
which proves again that nobody reads the comments either.)
Knowledge Base article 306509
explains that this behavior exists
because the command prompt window (like all console windows)
is run under the ClientServer Runtime System (CSRSS),
and CSRSS cannot be themed.
But why can't CSRSS be themed?
CSRSS runs as a system service,
so any code that runs as part of CSRSS creates potential
for mass havoc.
The slightest mis-step could crash CSRSS, and with it the entire system.
The CSRSS team decided that they didn't want to take the risk of
allowing the theme code to run in their process,
so they disabled theming for console windows.
(There's also an architectural reason why CSRSS cannot use the theming
services: CSRSS runs as a subsystem, and the user interface theming services
assume that they're running as part of a Win32 program.)
In Windows Vista,
the window frame is drawn by the desktop window manager,
which means that your console windows on Vista get the glassy frame
just like other windows.
But if you take a closer look, you will see that CSRSS itself
doesn't use themed windows:
Notice that the scroll bars retain the classic look.
The window manager giveth and the window manager taketh away,
for at the same time console windows gained the glassy frame,
they also lost drag and drop.
You used to be able to drag a file out of Explorer and
drop it onto a command prompt, but if you try that in Windows Vista,
This is a consequence of
tighter security around the delivery of messages
from a process running at lower integrity
to one running at a higher integrity level (see UIPI).
Since CSRSS is a system process, it runs at very high security level
and won't let any random program (like Explorer) send it messages,
such as the ones used to mediate OLE drag and drop.
You'll see the same thing if you log on as a restricted administrator
and then kick off an elevated copy of Notepad.
You won't be able to drag a file out of Explorer and drop it onto Notepad,
for the same reason.
Welcome, Slashdot readers.
Remember, this Web site is
for entertainment purposes only.
Sean wants to know what the role of MS-DOS was in Windows 95.
I may regret answering this question since it's
clear Slashdot bait.
(Even if Sean didn't intend it that way,
that's what it's going to turn into.)
Remember, what I write here may not be 100% true, but it is "true enough."
(In other words, it gets the point across without getting bogged down
in nitpicky details.)
MS-DOS served two purposes in Windows 95.
When Windows 95 started up, a customized version of
MS-DOS was loaded, and it's that customized version that
processed your CONFIG.SYS file,
which ran your AUTOEXEC.BAT and which
eventually ran WIN.COM, which began the
process of booting up the VMM, or the 32-bit virtual machine manager.
The customized version of MS-DOS was fully functional as far
as the phrase "fully functional" can be applied to MS-DOS in the
It had to be, since it was all that was running
when you ran Windows 95 in "single MS-DOS application mode."
The WIN.COM program started booting what most people
think of as "Windows" proper.
It used the copy of MS-DOS to load the virtual machine manager,
read the SYSTEM.INI file,
load the virtual device drivers,
and then it turned off any running copy of EMM386
and switched into protected mode.
It's protected mode that is what most people think of as "the real Windows."
Once in protected mode, the virtual device drivers did their magic.
Among other things those drivers did was
"suck the brains out of MS-DOS,"
transfer all that state to the 32-bit file system manager,
and then shut off MS-DOS.
All future file system operations would get routed to the
32-bit file system manager.
If a program issued an int 21h,
the 32-bit file system manager would be responsible for handling it.
And that's where the second role of MS-DOS comes into play.
For you see, MS-DOS programs and device drivers
loved to mess with the operating system itself.
They would replace the int 21h service vector,
they would patch the operating system,
they would patch the low-level disk I/O services
int 25h and int 26h.
They would also do crazy things to the BIOS interrupts such
as int 13h, the low-level disk I/O interrupt.
When a program issued an int 21h call to access MS-DOS,
the call would go first to the 32-bit file system manager,
who would do some preliminary munging and then, if it detected
that somebody had hooked the int 21h vector,
it would jump back into the 16-bit code to let the hook run.
Replacing the int 21h service vector is logically
analogous to subclassing a window.
You get the old vector and set your new vector.
When your replacement handler is called, you do some stuff,
and then call the original vector to do "whatever would normally happen."
After the original vector returned, you might do some more work
before returning to the original caller.
One of the 16-bit drivers loaded by CONFIG.SYS was called
The job of this 16-bit driver was to hook MS-DOS first
before the other drivers and programs got a chance!
This driver was in cahoots with the 32-bit file system manager,
for its job was to jump from 16-bit code back into 32-bit code
to let the 32-bit file system manager continue its work.
In other words, MS-DOS was just an extremely elaborate
Any 16-bit drivers and programs would patch or hook what they thought
was the real MS-DOS, but which was in reality just a decoy.
If the 32-bit file system manager detected that somebody bought the decoy,
it told the decoy to quack.
Let's start with a system that didn't contain any "evil" drivers
or programs that patched or hooked MS-DOS.
This was paradise.
The 32-bit file system manager was able to do all the work
without having to deal with pesky drivers that did bizarro things.
Note the extra step of updating the state variables inside MS-DOS.
Even though we extracted the state variables from MS-DOS during
the boot process, we keep those state variables in sync because
drivers and programs frequently "knew" how those state variables
worked and bypassed the operating system and accessed them directly.
Therefore, the file system manager had to maintain the charade that
MS-DOS was running the show (even though it wasn't) so that those drivers and
programs saw what they wanted.
Note also that those state variables were per-VM.
(I.e., each MS-DOS "box" you opened got its own copy of those state
each MS-DOS box had its idea of what the current directory was,
what was in the file tables, that sort of thing.
This was all an act, however, because the real list of open files was kept in
by the 32-bit file system manager.
It had to be, because disk caches had to be kept coherent,
and file sharing need to be enforced globally.
If one MS-DOS box opened a file for exclusive access,
then an attempt by a program running in another MS-DOS box to open the file
should fail with a sharing violation.
Okay, that was the easy case.
The hard case is if you had a driver that hooked
I don't know what the driver does, let's say that
it's a network driver that intercepts I/O to network drives
and handles them in some special way.
Let's suppose also that there's some TSR running in the MS-DOS box
which has hooked int 21h so it can
print a 1 to the screen when the int 21h is active
and a 2 when the int 21h completes.
Let's follow a call to a local device (not a network device,
so the network driver doesn't do anything):
Notice that all the work is still being done by the 32-bit
file system manager.
It's just that the call gets routed through all the 16-bit
stuff to maintain the charade that 16-bit MS-DOS is still
running the show.
The only 16-bit code that actually ran (in red)
is the stuff that the TSR and network driver installed,
plus a tiny bit of glue in the 16-bit IFSMGR hook.
Notice that no 16-bit MS-DOS code ran.
The 32-bit file manager took over for MS-DOS.
A similar sort of "take over but let the crazy stuff happen
if somebody is doing crazy stuff" dance took place when the
I/O subsystem took over control of your hard drive from
16-bit device drivers.
If it recognized the drivers, it would "suck their brains out"
and take over all the operations, in the same way that
the 32-bit file system manager took over operations from
On the other hand, if the driver wasn't one that the I/O subsystem
it let the driver be the one in charge of the drive.
If this happened, it was said that you were going through the
"real-mode mapper" since "real mode" was name for the CPU mode
when protected mode was not running;
in other words, the mapper was letting the 16-bit drivers do the work.
Now, if you were unlucky enough to be using the real-mode mapper,
you probably noticed that system performance to that drive was
That's because you were using the old clunky single-threaded 16-bit drivers
instead of the faster, multithread-enabled 32-bit drivers.
(When a 16-bit driver was running, no other I/O could happen because
16-bit drivers were not designed for multi-threading.)
This awfulness of the real-mode mapper actually came in handy
in a backwards way,
because it was an early indication that your computer got infected
with an MS-DOS virus.
After all, MS-DOS viruses did what TSRs and drivers did:
They hooked interrupt vectors and took over control of your hard drive.
From the I/O subsystem's point of view,
they looked just like a 16-bit hard disk device driver!
When people complained,
"Windows suddenly started running really slow,"
we asked them to look at the system performance page in the
control panel and see if it says that
"Some drives are using MS-DOS compatiblity."
If so, then it meant that the real-mode mapper was in charge,
and if you didn't change hardware, it probably means a virus.
Now, there are parts of MS-DOS that are unrelated to file I/O.
For example, there are functions for allocating memory,
parsing a string containing potential wildcards into FCB format,
that sort of thing.
Those functions were still handled by MS-DOS since they were
just "helper library" type functions and there was no
benefit to reimplementing them in 32-bit code aside from just
being able to say that you did it.
The old 16-bit code worked just fine, and if you let it do the
work, you preserved compatibility with programs that patched MS-DOS
in order to alter the behavior of those functions.
Sometimes people try too hard.
You can download a
C# program to look for a file on your PATH,
or you can use a 90-character batch file:
@for %%e in (%PATHEXT%) do @for %%i in (%1%%e) do @if NOT "%%~$PATH:i"=="" echo %%~$PATH:i
It depends on whom you ask.
The maximum command line length for the
CreateProcess function is 32767 characters.
This limitation comes from the UNICODE_STRING
CreateProcess is the core function for creating
processes, so if you are talking directly to
Win32, then that's the only limit you have to
worry about. But if you are reaching CreateProcess
by some other means, then the path you travel
through may have other limits.
If you are using the CMD.EXE command processor,
then you are also subject to the 8192 character
command line length limit imposed by CMD.EXE.
If you are using the ShellExecute/Ex function,
then you become subject to the INTERNET_MAX_URL_LENGTH
command line length limit imposed by the
(If you are running on Windows 95, then the limit
is only MAX_PATH.)
While I'm here, I may as well mention another
limit: The maximum size of your environment is
32767 characters. The size of the environment
includes the all the variable names plus all the
Okay, but what if you want to pass more than 32767
characters of information to a process?
You'll have to find something other than the command
We'll discuss some options tomorrow.
I haven't experienced this problem, but I know of people who have.
They'll put their laptop into suspend or standby mode, and after a few
seconds, the laptop will spontaneously wake itself up.
Someone gave me this tip
that might (might) help you figure out what is wrong.
Open a command prompt and run the command
powercfg -devicequery wake_from_any
This lists all the hardware devices that are capable of waking up
the computer from standby.
But the operating system typically ignores most of them.
To see the ones that are not being ignored, run the command
powercfg -devicequery wake_armed
This second list is typically much shorter.
On my computer, it listed just the keyboard, the mouse, and the modem.
(The modem? I never use that thing!)
You can disable each of these devices one by one until you find the
one that is waking up the computer.
powercfg -devicedisablewake "device name"
(How is this different from unchecking
Allow this device to wake the computer
from the device properties in Device Manager?
Once you find the one that is causing problems, you can re-enable
powercfg -deviceenablewake "device name"
I would start by disabling wake-up for the keyboard and mouse.
Maybe the optical mouse is detecting tiny vibrations in your room.
Or the device might simply be "chatty",
generating activity even though you aren't touching it.
This may not solve your problem, but at least's something you can try.
I've never actually tried it myself, so who knows whether it works.
Exercise: Count how many disclaimers there are in this article,
and predict how many people will ignore them.
A customer had a debug trace log and needed some help
The trace log was generated by an operating system component,
but the details aren't important to the story.
I've attached the log file. I think the following may be part
of the problem.
[07/17/2005:18:31:19] Creating process D:\Foo\bar\blaz.exe
[07/17/2005:18:31:19] CreateProcess failed with error 2
Senior Test Engineer
I've attached the log file. I think the following may be part
of the problem.
[07/17/2005:18:31:19] Creating process D:\Foo\bar\blaz.exe
[07/17/2005:18:31:19] CreateProcess failed with error 2
Senior Test Engineer
What struck me is that Bob is proud of the fact that he's
a Senior Test Engineer, perhaps because it makes him think that
we will take him more seriously because he has some awesome title.
But apparently a Senior Test Engineer doesn't know what error 2 is.
There are some error codes that you end up committing to memory because
you run into them over and over.
Error 32 is ERROR_SHARING_VIOLATION,
error 3 is ERROR_PATH_NOT_FOUND,
and in this case,
error 2 is ERROR_FILE_NOT_FOUND.
And even if Bob didn't have error 2 memorized,
he should have known to look it up.
Error 2 is ERROR_FILE_NOT_FOUND.
Does the file D:\Foo\bar\blaz.exe exist?
No, it doesn't.
No, it doesn't.
Bob seems to have shut off his brain and decided to treat
troubleshooting not as a collaborative effort but rather as
a game of Twenty Questions
in which the person with the problem volunteers as little information
as possible in order to make things more challenging.
I had to give Bob a nudge.
Can you think of a reason why the system would be looking at
Where did you expect it to be looking for blaz.exe?
This managed to wake Bob out of his stupor, and the investigation
(And no, I don't remember what the final resolution was.
I didn't realize I would have to remember the fine details of
this support incident three years later.)
There are advanced settings in Windows,
settings which normal users not only shouldn't be messing with,
but which they arguably shouldn't even know about,
because that would give them just enough knowledge to be dangerous.
And no matter where you put that advanced setting,
somebody will tell you that you are an idiot.
Here they are on an approximate scale.
If you dig through the comments on this blog, you can probably find
every single position represented somewhere.
If you implement level N, people will demand that you implement
It doesn't stop until you reach the last step,
which is aggressively user-hostile.
(And then there will also be people who complain that
you went too far.)
From a technical standpoint,
each of the above steps is about ten to a hundred times harder
than the previous one.
If you put it in a configuration file, you have to write code
to load a parser and extract the value.
If you want an Advanced button, now you have to write a dialog box
(which is already a lot of work),
consult with the usability and user assistance to come up with
the correct wording for the setting, write help text,
provide guidance to the translators,
and now since it is exposed in the user interface,
you need to write automated tests and add the setting to the
It's a huge amount of work to add a dialog box,
work that could be spent on something that benefits a much
larger set of customers in a more direct manner.
That's why most advanced settings hang out at level 1
or, in the case of configuring program installation, level 2.
If you're so much of a geek that you want to change these
it probably won't kill you to fire up a text editor and write
a little configuration file.
Joel's count of
"fifteen ways to shut down Windows"
is a bit disingenuous, since he's counting six hardware affordances:
"Four FN+key combinations... an on-off button... you can close the lid."
Okay, fine, Joel, we'll play it your way.
Your proposal to narrow
it down to one "Bye" button, still leaves seven ways to shut down Windows.
And then people will ask how to log off.
A customer reported that they had a problem with a particular function
added in Windows 7.
The tricky bit was that the function was used only on very high-end
not the sort of thing your average developer has lying around.
... code that initializes the GroupAffinity structure ...
if (!SetThreadGroupAffinity(hThread, &GrouAffinity, NULL));
printf("SetThreadGroupAffinity failed: %d\n", GetLastError());
The customer reported that the function always failed
with error 122 (ERROR_INSUFFICIENT_BUFFER)
even though the buffer seems perfectly valid.
Since most of us don't have machines with more than 64 processors,
we couldn't run the code on our own machines to see what happens.
People asked some clarifying questions,
like whether this code is compiled 32-bit or 64-bit
(thinking that maybe there is
an issue with the emulation layer),
until somebody noticed that there was a stray semicolon at the end
of the if statement.
The customer was naturally embarrassed, but was gracious enough to
admit that, yup, removing the semicolon fixed the problem.
This reminds me of an incident many years ago.
I was having a horrible time debugging a simple loop.
It looked like the compiler was on drugs and was simply
ignoring my loop conditions and always dropping out of the loop.
At wit's end, I asked a colleague to come to my office and
serve as a second set of eyes.
I talked him through the code as I single-stepped:
"Okay, so we set up the loop here..."
NODE pn = GetActiveNode();
"And we enter the loop, continuing while the node still needs processing."
"Okay, we entered the loop.
Now we realign the skew rods on the node."
"If the treadle is splayed, we need to calibrate the node against it."
if (IsSplayed()) pn->Recalibrate(this);
"And then we loop back to see if there is more work to be done
on this node."
"But look, even though the node needs processing
«view node members», we don't loop back.
We just drop out of the loop.
What's going on?"
— Um, that's an if statement up there,
not a while statement.
A moment of silence while I process this piece of information.
"All right then, sorry to bother you, hey,
how about that sporting event last night, huh?"
Many years ago, I was asked to help a customer with a
problem they were having.
I don't remember the details, and they aren't important to the story anyway,
but as I was investigating one of their crashes,
I started to wonder why they were even doing it.
I expressed my concerns to the customer liaison.
"Why are they writing this code in the first place?
The performance will be terrible, and
it'll never work exactly the way they want it to."
The customer liaison confided,
"Yeah, I thought the same thing.
But this is a feature they're adding to the next version of their
The product is so far behind schedule,
they've been cutting features like mad
to get back on track.
But they can't cut this feature. It's the last one left!"