I dont think it is a bug but it must be by design. Isn't it reasonable that
NT blocks the mesagebox function before existing mesage boxes are examined
by the user? Otherwise an application could easily display 100000 message
boxes and NT would have to store the text to these message boxes in some
queue and that would trouble the OS itself. No I think it is quite
reasonable that there is a finite number of message boxes to be displayed
and also the fact that threads are allowed to run after the user closes the
message boxes prove that this is not a bug but all by design.
Now what I understand from your posting is that your application is not
happy because of this blocking. Here is a way round it.
Create a sep. worker thread for message boxes and create a queue of messages
to be consumed and displayed by this thread so it becomes something like
DWORD TheThreadFunc(DWORD d)
// Consume all messages by displaying them using the message box function
while More Messages
Now instead of calling MessageBox function in your code call the followiing
Add Message to queue
At one point you will realise that your queue will be finite and will
appreciate the NT's implementation:)
Sumner, Jeff <sum...@bassinc.com> wrote in message
> We have a server app that has several clients attached to it. When
> certain conditions happen on a client, the server app spawns a new
> thread that simply calls MessageBox. The thread is created so the main
> server thread can still be processing when the message box is displayed.
> We have found that when 16 of these threads are created, NT pretty much
> hangs until a few of the message boxes are closed.
> I have written a test program to recreate this, and have noticed the
> exact same behavior. The test program is a console app that takes an
> integer parameter for the number of message boxes to pop up. I ran this
> test app while I have the NT performance monitor up. Any number up to
> 15 works fine, but as soon as I specify 16 or higher, the task manager
> stops dead cold until a couple of the message boxes (and subsequent
> threads) are closed. The code for the test program is less than 3K, so
> I've included it here.
> I have figured something out since I posted the message. The
> MB_SERVICE_NOTIFICATION flag given to MessageBox is causing the problem.
> This flag allows an NT service to display a message box, regardless of
> who is logged in. The box will still display even if nobody is logged
> in. However, NT does not like the 16th box at all.
> If I take this flag out, then each message box is created with its own
> window, and each one appears in the task bar, but only if the "Allow
> Service to Interact with Desktop" option is enabled for the service
> under Control Panel | Services. In this case, NT performs fine when
> more than 15 message boxes are specified, but no message boxes will be
> displayed if nobody is logged in.
> So, to make the long story short, I am thinking that there is a bug in
> NT that causes windows messages to not be processed correctly when
> MB_SERVICE_NOTIFICATION is used and the 16th window is popped up.
> Another thing we have tried is scrapping the multithreading and
> MessageBox altogether and just making a system call to execute "net send
> <machinename> <message>", which causes the message to pop up in a window
> on the specified machine (as long as the NT Messenger service is
> running). The drawback to this is that it appears that the messenger
> service only accepts 6 messages at a time. All others get dropped on
> the floor until one or more of the first 6 are closed.
> Does anybody have any insights? They would be greatly appreciated.
> Thanks for your time.
> Jeff Sumner
> BASSpoiNT Development
> BASS, Inc.
It would be if it just blocked the application, or even dropped the
messagebox calls on the floor (ie, return immediately). However, the
problem seems to be that once you pass 16, none of the normal usermode
processes get any CPU cycles any more. Ctrl-Alt-Del will give you the
usual menu, but the Task Manager for example won't pop up if you start
Quite nasty if your nuclear power plant controller freezes completely
after it put up a couple of message boxes about low levels of cooling
fluid... NT Embedded anyone?
Ok, I immediately retract that example already, for any of a dozen
By the way, we had a good laugh about this at the office. My boss
forwarded the original message to NT Bugtraq. Someone there (Oded
Horovitz) replied with info about the following incredibly overloaded
which has a part 'MaxRequestThreads=16' at the end. This indeed has the
effect you'd expect. Reboot. Pretty useless as far as I'm concerned. But
that doesn't matter.
You can tell your boss that.:)
Nanno Langstraat <tw50...@dutiwy.twi.tudelft.nl> wrote in message
1. That doesn't work around the problem:
- Limiting it to 15 is not save. You'd have to parse that
command-line parameter list for csrss.exe in the registry to find
the limit. Yuck yuck yuck... (or is there another way?)
- Other applications (or even other instances of this app) can call
MessageBox() as well, and there's no way to stop them.
2. You can't program it if you don't know about it. This should be
documented in the VC++ help for MessageBox(...). It isn't. One is
often given to wonder what is... Although it's a veritable treasure
trove of accuracy compared to the NT4 DDK of course.
3. Needlessly enlarging and complicating programs to work around
ridiculously simple but lethal bugs in the OS we're using has
extremely limited appeal to us.
> You can tell your boss that.:)
I'm sure to forward him your solution... :-)
But, to sum it up, I'm really glad it's not our problem.
> 3. Needlessly enlarging and complicating programs to work around
> ridiculously simple but lethal bugs in the OS we're using has
> extremely limited appeal to us.
Am I missing something? Are you all blaming NT for making it difficult to
MessageBox() from inside a service? Gosh, if I had my way, *my* NT
*wouldn't* *ever* let you do a single GUI/User call from a service. It's
just plain stupid. What if a user is not there? What if *nobody* ever looks
at the machine's screen for one simple reason it does not have any, working
somewhere in the closet?
There is one simple rule: if you want communicate anything to the user, make
sure the user is here, in the first place. The only clean way to ensure that
is by communicating through an application that the user starts. Good ol'
Please send any replies to this newsgroup.
I'd say that's a fair way to put it.
Especially if you consider that it must be more or less the simplest of
all Win32 calls, that the penaly is semi-death, and that there's no
reliable way to work around it.
> Gosh, if I had my way, *my* NT *wouldn't* *ever* let you do a single
> GUI/User call from a service. It's just plain stupid.
That's certainly a valid approach to take. However, the architects of
Windows NT seem to have disagreed with you. It is my strong opinion that
if you're about to put something in an OS, you have to consider it well.
If you then decide to go ahead, you need to execute, support and
document it well or at the very least adequately. This problem fails on
at least two counts.
After some consideration I think that I'd like to nominate 'NTFS
streams' as an example of failing on all four counts. They're a poor
excuse for a truly abstract, clean 'containers inside containers'
approach, they don't work well (try copying to and from a FAT disk: they
break, and not even a warning), they're virtually unsupported (don't
even show up in the Explorer) and you almost have to know where to look
in the VC++ documentation.
Oh, and they vie with 'CreateFile(..)' for Worst-Named Concept of the
Year. They more or less act as files, not streams, and the term 'stream'
was hardly in danger of disuse anyway. A fifth consideration? :-)
[Someone please nudge me if this is getting too much off-topic for this
> There is one simple rule: if you want communicate anything to the
> user, make sure the user is here, in the first place. The only clean
> way to ensure that is by communicating through an application that the
> user starts. Good ol' client-server.
I'm inclined to agree with you. Since it is so basic however, in a
better world I'd still like my OS to take care of most of the hassle
Unfortunately, it's my problem. I think I'll punt. :P
Seriously, though, it isn't that big of a deal to us right now.
This whole issue was something we ran into accidentally, and I decided
to check it out.
I agree with all of your points, Nanno. The limitation should
be documented, and it is unreasonable to expect an application to see if
any other application is using a MessageBox. But it is possible to try
and minimize the risk, and the best way I can think of is to make sure
that an application has at most 1 thread that displays 1 MessageBox at a
time (when using the MB_SERVICE_NOTIFICATION flag). This is where I
think Huseyin had a very good idea with the internal queue of messages.
Well, anyway, the problem is still there. I tested it on an NT5
box and saw the 16 limit. But, I now know why it happens and have a
good strategy to improve our code. We may not be able to completely
alleviate the problem, but we can sure "play more fairly". I really
appreciate the help, everyone.
> Especially if you consider that it must be more or less the simplest of
> all Win32 calls, that the penaly is semi-death, and that there's no
> reliable way to work around it.
I believe it's an implementor's duty to *understand* the details. Let's
dissect the problem. You want to display a message box from a service.
Service, a Win32 process, is attached to its own window station (or none, if
no GUI calls have been made so far). Now you ask the Win32 GUI subsystem to
display a message - this requires the process to switch its window station
to the interactive window station and set the thread desktop to the default
desktop. However, to attach to the interactive window station, the account
the service is running under must have appropriate ACLs in the window
station DACL - luxury that normally only SYSTEM may afford. On the other
hand, MessageBox() is guaranteed to work even for non-SYSTEM (Platform
SDK/Windows Base Services/DLLs, Processes, and Threads/Services/About
Services/Interactive Services clearly states that).
Apparently, this prevents the system from ever trying to switch window
station, but it still has to do something to display the message box. An
obvious way to do so is to forward the request to some other process that
knowingly sufficient permissions with regard to the winstation/desktop
business. The proxy process may then have one of its threads to do
MessageBox() and, naturally,
block. When you call the process for delivering messages continuously,
eventually all its worker threads will became blocked.
Unfortunately, the proxy process in question is NT's system process that has
duties other than popping messages to the user - and when all its worker
threads block, so does the system in whole (at least the visual (and
visible) part of the iceberg).
While it *is* shame that the vital process is used for such dangerous moot,
and that the point is not documented, one still has think about the stuff
he's doing. Relying on the OS fool-proofing just does not do. There are many
quite natural ways to block/freeze/hang/whatever NT without doing anything
voodoo - for example, running a
in a process with its priority set to realtime class brings the system to
actual (not just visible) death (OK, drivers continue to work, and so the
LanMan server does, but...).
> That's certainly a valid approach to take. However, the architects of
> Windows NT seem to have disagreed with you. It is my strong opinion that
> if you're about to put something in an OS, you have to consider it well.
> If you then decide to go ahead, you need to execute, support and
> document it well or at the very least adequately.
I agree. Given the common lack of proper documentation, though, I wonder why
get crazy about this one?
Also, it is arguable that architects of Windows *NT* were evil enough to
provide such weird MessageBox() functionality. It is more likely that some
other people built CSRSS, and then *yet* someone found that the
enterprise-level server OS lacks a vital capability of popping messages from
system services, and they put together the kluge we now call
MB_SERVICE_NOTIFICATION. Bad design goals, bad implementation - these always
come in pairs.
> I'm inclined to agree with you. Since it is so basic however, in a
> better world I'd still like my OS to take care of most of the hassle
Despite I hate doing GUI from services (OK, it is just me), there are still
ways of doing it cleaner (than MB_SERVICE_NOTIFICATION). The best and
easiest way is when the service is running under the SYSTEM account:
HWINSTA win_station = OpenWindowStation(
HDESK desktop = OpenInputDesktop(
"Greetings from Inferno!",
Four additional API calls ensure your messages won't be routed through the
system process, so if nobody is going to dismiss them, they'll block only
Thank you for that explanation.
> While it *is* shame that the vital process is used for such dangerous
> moot, and that the point is not documented, one still has think about
> the stuff he's doing. Relying on the OS fool-proofing just does not
Mhh. My preference is for an OS to basically distrust applications, and
to make sure that their bad behaviour does not really hurt other parts.
However, it is known that Microsoft is from a background of trusting
apps to behave themselves, and you're right that I shouldn't have
expected NT to always live through stuff like this.
I also realize that my ideal is easier said than done: it's not that
easy to design an OS that really tries to strictly limit each
application to its own area of relevance (with associated access to
resources), while remaining easy to use. I'm planning to do some
research/work on that in the future.
> Given the common lack of proper documentation, though, I
> wonder why get crazy about this one?
I think I must be projecting all my irritations and peeves on this one
This was probably brought on because MessageBox() used to have such an
innocuous feeling to it in my mind.
> > I'm inclined to agree with you. Since it is so basic however, in a
> > better world I'd still like my OS to take care of most of the hassle
> > involved.
> Despite I hate doing GUI from services (OK, it is just me)
No, it's a valid point to make that it doesn't belong there.
Let's talk about reality here. There is a concept called
"flexibility" that is generally a good thing to take into account when
designing/implementing software. I agree with your statement that
somebody should be at a workstation if you are going to throw some GUI
stuff on the screen. However, what if you want to allow the user to
customize where messages are sent? Maybe there are client machines that
messages should display on because the server is locked in a closet.
Great. Good design, I have no problems with it. But, if the customer
wants an architecture where the server is a usable system, then I see no
problem in treating it as such.
We are not blaming NT for making it difficult to MessageBox()
from inside a service. Quite the contrary, NT makes it extremely simple
to do so. All you have to do is add the MB_SERVICE_NOTIFICATION flag to
call to MessageBox(). What we are talking about is that NT puts a
severe, potentially hazardous limitation on the system when this flag is
used. To make it worse, this limitation is not documented anywhere that
I or anybody else who has posted on this subject has found. The flag
itself is documented, and there is absolutely no mention of any
As far as the system we are building here is concerned, we have
good, justifiable reasons to allow a service to display message boxes.
You do not know the design of this system, and I have neither the time
nor the inclination to go into it here. I am sure that you have not
spent the effort to consider every single possible design. Therefore,
it isn't a good idea to say that something should "never" be done. It
is an even WORSE idea to call someone "stupid" when there is no possible
way that you can have enough information on the subject to make such a
call. This newsgroup is a forum for people to share ideas, not insults.
Evidently, the developers at Microsoft also don't agree with
you. Otherwise, they wouldn't have even implemented and documented the
MB_SERVICE_NOTIFICATION flag in the first place.
Now, to close this message in a less "flaming" manner, I will
say that your points are very valid about not displaying messages if
nobody is there to see them. However, I take great exception when
someone who does not have all of the facts says a practice should never
be done and insults anyone who does use it.
> Mhh. My preference is for an OS to basically distrust applications, and
> to make sure that their bad behaviour does not really hurt other parts.
Me too. However, just like you said, it's hard to be bullet-proof and yet
make things simple. This case is so sharp just because they deliberately
sacrificed robustness for simplicity - it is obvious they decided doing
OpenWindowStation(); SetProcessWindowStation(); etc was pure overkill for
just a MessageBox().
Robustness vs simplicity trade-off is, unfortunately, ubiquitous under NT:
say, leaving system directories with everyone allowed to RWXD is of this
> This was probably brought on because MessageBox() used to have such an
> innocuous feeling to it in my mind.
Sure. Perhaps, the guys who made it were also inspired by the simplicity of
the "usual" MessageBox()...
I just love when they try to shield you from the gory details...
I think I'm guilty of jumping to conclusions yesterday. When I read
Slava's original posting on the subject, it came across to me as being
very judgemental and also to some degree insulting. We (my co-workers
and I) are the ones who have a service that displays message boxes,
which is a practice that Slava said is "just plain stupid". The posting
was very short, and in my interpretation did not propose any possible
solutions, only judgements. I tried to be as diplomatic in my reply as
possible while still making it clear that I did not appreciate that kind
In hindsight, I wish I had seen the dialog between Slava and Nanno
before I posted my reply. Now, I do not believe that it was Slava's
intention to be either judgemental or insulting. Slava, if this is
true, then you have my apologies. I only ask that you try to understand
how I could have interpreted your posting the way I did.
It seems that this topic has opened up a big can of worms. I am now
being cc'ed on a couple of email dialogs between other people, with some
of them heating up a little as well.
Well, one thing I definitely want to say is that I have learned a LOT
over the last few days from everyone who's posted on the subject,
especially Huseyin, Nanno, and Slava. I hope it has been informative
for others as well.
> We are not blaming NT for making it difficult to MessageBox()
> from inside a service. Quite the contrary, NT makes it extremely simple
> to do so. All you have to do is add the MB_SERVICE_NOTIFICATION flag to
> call to MessageBox(). What we are talking about is that NT puts a
> severe, potentially hazardous limitation on the system when this flag is
> used. To make it worse, this limitation is not documented anywhere that
> I or anybody else who has posted on this subject has found. The flag
> itself is documented, and there is absolutely no mention of any
I did admit that I was unhappy about that (lack of the documentation). In a
follow-up, however, I tried to figure out why that simple call with
MB_SERVICE_NOTIFICATION was so problematic. I'm not in any way in a position
to teach someone how to program to the SDK MS imposes on us, but I do think
that in order to succeed, one has to think a bit deeper in an attempt to
grasp how the things fit together. At any rate, MessageBox() is really weird
in its guaranteed functioning from whatever security context it's called,
and that's always a warning (to me, at least) that a trade-off is somewhere
around. (I say it again, blame on them for not documenting it, but then
again, they probably could not do it because they were uncertain if that
particular implementation will survive for long.)
> As far as the system we are building here is concerned, we have
> good, justifiable reasons to allow a service to display message boxes.
> You do not know the design of this system, and I have neither the time
> nor the inclination to go into it here. I am sure that you have not
> spent the effort to consider every single possible design. Therefore,
> it isn't a good idea to say that something should "never" be done. It
> is an even WORSE idea to call someone "stupid" when there is no possible
> way that you can have enough information on the subject to make such a
> call. This newsgroup is a forum for people to share ideas, not insults.
I'm sorry for being offensive. All I wanted is to share my idea (not mine,
I'm just a supporter of) that one should separate GUI from service.
I have no problem with MessageBox() and, for that matter, GUI as a concept
in whole (confession: I even do it). Of course, when the service one is
implementing is inherently bound to one single computer and makes no sense
over network, there have to be some means to control it graphically right on
the machine it's running at. But does that mean it has to pop message boxes,
display menus, etc? I don't think so. All it has to do is provide
programmable interface (such as named pipe, RPC, DCOM, or if talk "one
computer", memory-mapped file and events, ... whatever). Then you write a
tiny client that talks to the service and displays all niceties of GUI. If
you make it appear at the taskbar's tray, and put a shortcut to the start-up
folder, the user will be much more pleased.
Think about it. Are sure that displaying that emergency message is
appropriate to anybody who just happens to be logged on? Do you mind the
machine's administrator having control on who is allowed to interact with
the service? Etc... NT is a semi-multiuser system, and I think it is you who
just don't want to consider every possible usage of the machine where the
service is running on, and the service itself.
Separating GUI from actual working code gives users more control, a virtue
that cannot be overestimated and is certainly worth an additional work to
> Evidently, the developers at Microsoft also don't agree with
> you. Otherwise, they wouldn't have even implemented and documented the
> MB_SERVICE_NOTIFICATION flag in the first place.
As it turns out, they didn't document it. Moreover, there is an article in
the platform SDK that discusses how services should interact with the user,
and it only briefly mentions that flag. I see only one good reason the flag
is here: quick and dirty debugging of a service. Then it makes perfect
> Now, to close this message in a less "flaming" manner, I will
> say that your points are very valid about not displaying messages if
> nobody is there to see them. However, I take great exception when
> someone who does not have all of the facts says a practice should never
> be done and insults anyone who does use it.
As you said above, the people here are free to speak up whatever they think.
I think calling MessageBox() from a service is stupid for the following
1. Reduced controllability (this applies generally to doing GUI from
2. The API is buggy (the subject of the thread says it all).
3. How about terminal server? (same note as of #1).
Please, Jeff, don't take it personal. I call it stupid not because I want to
insult people, no. I call it stupid because I think it is. You may
substitute whatever synonym you like, e.g., unwise.
No hard feelings at all. I hope you read my posting yesterday.
> I do think that in order to succeed, one has to think a bit deeper in
an attempt to
> grasp how the things fit together. At any rate, MessageBox() is really
weird in its
> guaranteed functioning from whatever security context it's called, and
> a warning (to me, at least) that a trade-off is somewhere around.
You are absolutely correct. I was not aware of all of the subtleties
and "quirks" associated with this. As it stands right now, we are
heavily considering changing how the whole thing works. In fact...
> All it has to do is provide programmable interface (such as named
pipe, RPC, DCOM,
> or if talk "one computer", memory-mapped file and events, ...
whatever). Then you write
> a tiny client that talks to the service and displays all niceties of
Something like a tiny client is exactly what we're thinking of.
> Think about it. Are sure that displaying that emergency message is
> anybody who just happens to be logged on? Do you mind the machine's
> having control on who is allowed to interact with the service?
As strange as it sounds, and I will be the first person to testify that
it IS strange, this is the way it was designed to work.
> Separating GUI from actual working code gives users more control, a
virtue that cannot
> be overestimated and is certainly worth an additional work to
I agree 110%. That is the whole reason that MFC is designed around the
Document/View architecture, which itself stemmed from the MVC
> As it turns out, they didn't document it.
(Referring to the MB_SERVICE_NOTIFICATION flag). There is documentation
in the help for MessageBox(). One thing that adds to the whole problem
in the first place is that there is no mention of any possible
side-effects or even things that a developer might want to consider
before using it (other than what to do if the service will be run under
NT 3.x instead of NT4, and in this case it tells yout to just use a
different flag for NT 3.x).
> In hindsight, I wish I had seen the dialog between Slava and Nanno
> before I posted my reply. Now, I do not believe that it was Slava's
> intention to be either judgemental or insulting. Slava, if this is
> true, then you have my apologies. I only ask that you try to understand
> how I could have interpreted your posting the way I did.
You don't have to apologize, really. I believe it was my fault that I
sounded so authoritative. Re-reading my original post, I clearly see it was
a bit rude, and especially my not explaining why I considered calling
MessageBox() harmful ( :-) I wonder if Edsger W. Dijkstra ever visits this
newsgroup), and moreover, not mentioning practical alternatives.
When trying to defeat your post ;-) I think I put my perception of the whole
thing straight and in a manner easy to follow by others, so I say "Thanks,
Jeff, for your healthy criticism", and repeat that you should not feel
guilty in any way. Wisdom is the offspring of discussion, and we're here to
discuss. To say more, discussions are rare in this forum (sadly, most posts
are questions sort of "how do I run a standalone executable
programmatically?", and reading them (not to mention answer them!) is such a
bore...), and it's a real pleasure to follow this one. After all, I *do*
want to know, if I am really missing something, denying calling MessageBox()
from services to be a valid practice.
> > As it turns out, they didn't document it.
> (Referring to the MB_SERVICE_NOTIFICATION flag). There is documentation
> in the help for MessageBox().
I meant "they didn't document it the way they should". As Nanno said, if
they did go that way, they should have at least described the gotchas. This
leads me to another topic, whether they ever took a bother to think through
how it would operate if nobody cared to close the message boxes... But
that's totally different a topic...