I see this quite often in a COM module call.
http://en.wikipedia.org/wiki/HRESULT
http://msdn2.microsoft.com/en-us/library/dcy94zz2(VS.80).aspx#vcconattributeprogrammmingfaqanchor1
Tom
"June Lee" <iiu...@yahoo.com> wrote in message
news:4gulu3prunl23jd6f...@4ax.com...
I have only seen it used in COM related method calls. IIRC, it was
introduced at the same time when COM came out.
---
Ajay
On Wed, 26 Mar 2008 17:37:16 -0800, June Lee <iiu...@yahoo.com> wrote:
>is HRESULT only used in COM interface programming?
>
>I see this quite often in a COM module call.
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
To add to what others correctly wrote, I would like to suggest you to use
HRESULT only in COM code or ATL development (e.g. if you are developing a
COM component).
One of COM requirements was that it must support several languages,
including C. And C has no exception mechanism for error handling (instead,
you can use exceptions in C++). So, to be compatible also with C, in COM
every error condition is signaled returning HRESULT.
This may lead to some problems in "quality" of code, for example, in typical
COM code, you may have:
<code>
HRESULT SomeFunction(...)
{
// erorr code
HRESULT hr;
...
hr = pX->DoSomething(...);
if ( FAILED(hr) )
... cleanup
return hr;
hr = pY->DoSomethingElse(...);
if ( FAILED(hr) )
... cleanup
return hr;
...
...
// Everything OK
return S_OK;
}
</code>
The problem is duplicating "cleanup".
To avoid duplicating cleanup code in each "if ( FAILED(hr)) ..." branch,
'goto' statements may be used, e.g.:
<code>
hr = pX->DoSomething(...);
if ( FAILED(hr) )
goto ErrorCleanup;
hr = pY->DoSomethingElse(...);
if ( FAILED(hr) )
goto ErrorCleanup;
...
// All right
return S_OK;
// *** CLEANUP [on error] ***
ErrorCleanup:
// Do cleanup here...
...
// Return error code
return hr;
</code>
The above code could be simplified if some quality tools are used, like
smart pointers (like CComPtr COM smart pointer template; in fact, smart
pointers do proper cleanup, like calling IUnknown::Release, when the smart
pointer goes out of scope; so, in that case, returning an error code could
be fine, without explicit cleanup: the smart pointer will do the cleanup
automatically).
However, if you are not targeting COM interface programming, and e.g. you
are doing "pure" C++ (or even MFC programming), I would suggest you to *not*
use HRESULTs.
At least, I would define custom enum for error codes, these are more
readable than HRESULTs, IMHO.
e.g.
<code>
class Something
{
public:
enum ErrorCode
{
Ok = 0, // All right
MemoryFailure,
CantOpenFile,
...
};
// Better custom error code enum than HRESULT
ErrorCode DoSomething(...);
};
</code>
Or you may also consider using C++ exceptions (and use RAII pattern, to
develop exception-safe code).
Giovanni
Maybe I never learned how to use HRESULT correctly, but I recently ran into
trouble using the SUCCEEDED() macro which returns true if the HRESULT >= 0.
But only ERROR_SUCCESS is 0. Something like ERROR_ACCESS_DENIED is 5. So
if I get an HRESULT of 5, testing it with SUCCEEDED() will return true, when
clearly there was an error. To workaround, I must not use SUDCCEEDED() and
instead compare it explicitly to ERROR_SUCCESS.
Why is this? I really hate COM due to the fact that not even the return
values are defined very intuitively.
Thanks,
David
Cheers
Check Abdoul
---------------------
"David Ching" <d...@remove-this.dcsoft.com> wrote in message
news:evWGj.20475$xq2....@newssvr21.news.prodigy.net...
Hi David,
as others wrote, maybe you were using SUCCEEDED in a context different from
HRESULT.
You may want to read this comment on the OldNewThing blog, about SUCCEEDED
being unrelated to ERROR_SUCCESS:
http://blogs.msdn.com/oldnewthing/archive/2004/08/31/223271.aspx#223806
Giovanni
Thanks so much to you and the others who answered. Yes, I was calling
if (SUCCEEDED(GetLastError()))
...
which is of course wrong.
So it seems you're recommending:
if (SUCCEEDED(HRESULT_FROM_WIN32(GetLastError())))
...
instead.
Kind of verbose for my tastes, but it reads well.
I think I got confused because ERROR_SUCCESS, SUCCEEDED(), and the
GetLastError() codes are all defined in winerror.h, making me think they
worked together. In addition, you can pass GetLastError() directly to
::FormatMessage(), just as you can with a HRESULT, again making me think
GetLastError() was interchangeable.
Thanks again for the clarification.
-- David
This is kind of pointless. HRESULT_FROM_WIN32 transforms error code 0
(NOERROR) into S_OK, and any nonzero code into a failed HRESULT. So this
statement is equivalent simply to
if (GetLastError() == NOERROR)
Moreover, GetLastError cannot be relied on unless the previous API call
sigalled an error. Most APIs set the error code on failure, but don't
touch it on success, so GetLastError after a successful call may return
a stale error code from some previous call (or perhaps from some call
made internally by the function you used, from which it successfully
recovered). So the correct idiom is something like this:
if (!SomeAPI()) {
// API failed: get more information about the error
DWORD err = GetLastError();
} else {
// API succeeded
}
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
> So it seems you're recommending:
>
> if (SUCCEEDED(HRESULT_FROM_WIN32(GetLastError())))
> ...
>
> instead.
>
>
> Kind of verbose for my tastes, but it reads well.
Hi David,
I do agree with you about the verbosity.
In that case, you may define also some helper tool, like:
#define WIN32_SUCCEEDED (SUCCEEDED( HRESULT_FROM_WIN32(
::GetLastError() ) ) )
or use a C++ inline function as well:
inline bool Win32Succeeded()
{
return SUCCEEDED( HRESULT_FROM_WIN32( ::GetLastError() ) ) ? true : false;
}
and do:
if ( WIN32_SUCCEEDED )
...
or
if ( Win32Succeeded() )
...
> I think I got confused because ERROR_SUCCESS, SUCCEEDED(), and the
> GetLastError() codes are all defined in winerror.h, making me think they
> worked together. In addition, you can pass GetLastError() directly to
> ::FormatMessage(), just as you can with a HRESULT,
I agree with you about the confusion.
For example, I don't like identifiers like "ERROR_SUCCESS": I find them like
an "oxymoron"! (I hope that word exists in English...)
However, I'm not sure if you can pass HRESULTs to ::FormatMessage...
Giovanni
You can do it something like this:
LPVOID lpMsgBuf=NULL;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, // module to get message from (NULL == system)
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
-- David
> This is kind of pointless. HRESULT_FROM_WIN32 transforms error code 0
> (NOERROR) into S_OK, and any nonzero code into a failed HRESULT. So this
> statement is equivalent simply to
>
> if (GetLastError() == NOERROR)
>
Quite right, Igor. In fact, I essentially did:
if (GetLastError() == ERROR_SUCCESS)
when I found out SUCCEEDED() did not work. Both ERROR_SUCCESS and NOERROR
define to 0; I guess ERROR_SUCCESS is more correct to use since the rest of
the GetLastError() codes begin with "ERROR_" also. But I like the concept
of using a SUCCEEDED style macro better because it reads easier (at least to
me).
> Moreover, GetLastError cannot be relied on unless the previous API call
> sigalled an error. Most APIs set the error code on failure, but don't
> touch it on success, so GetLastError after a successful call may return a
> stale error code from some previous call (or perhaps from some call made
> internally by the function you used, from which it successfully
> recovered). So the correct idiom is something like this:
>
> if (!SomeAPI()) {
> // API failed: get more information about the error
> DWORD err = GetLastError();
> } else {
> // API succeeded
> }
>
Quite right, I was simplifying for illustration, perhaps too much so.
-- David
You are passing GetLastError result here, aren't you?
Where is the HRESULT?
Thanks,
G
Under what circumstances, then, would you want to check that
GetLastError returned a success code (often enough to warrant a special
macro)?
Apparently you don't need an HRESULT here. This code does work (or at least
it did last some time I checked). This is why I thought GetLastError()
returned an HRESULT compatible value.
-- David
>>> LPVOID lpMsgBuf=NULL;
>>> ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
>>> FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
>>> NULL, // module to get message from (NULL == system)
>>> GetLastError(),
> Apparently you don't need an HRESULT here. This code does work (or at
> least it did last some time I checked). This is why I thought
> GetLastError() returned an HRESULT compatible value.
I tried the following code (simulating a DirectDraw failure with an HRESULT
= DDERR_CANNOTATTACHSURFACE):
<code>
HRESULT hr = DDERR_CANNOTATTACHSURFACE;
LPVOID lpMsgBuf=NULL;
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
::MessageBox( NULL, (LPTSTR)lpMsgBuf, _T("Test"), MB_OK );
</code>
and I got no error description...
Maybe FormatMessage with HRESULT works only for some APIs (like when you
successfully used it) but not for all...
Giovanni
An API that fails sets the GetLastError code
An API that succeeds does not change the GetLastError code
Then there's a list of exceptions; for example, the Registry APIs return the error code
directly and do not modify GetLastError, and CreateSemaphore, CreateMutex, CreateEvent,
CreateWaitableTimer, etc. WILL change the error code on success if there is a named object
used.
The only time you want to check GetLastError is on an error, unless you are working in one
of the noted exceptions. When in doubt, read the documentation.
joe
On Fri, 28 Mar 2008 12:45:44 -0400, "Igor Tandetnik" <itand...@mvps.org> wrote:
>David Ching <d...@remove-this.dcsoft.com> wrote:
>> "Igor Tandetnik" <itand...@mvps.org> wrote in message
>> news:ec88t%23OkIH...@TK2MSFTNGP05.phx.gbl...
>>> Moreover, GetLastError cannot be relied on unless the previous API
>>> call sigalled an error. Most APIs set the error code on failure, but
>>> don't touch it on success, so GetLastError after a successful call
>>> may return a stale error code from some previous call (or perhaps
>>> from some call made internally by the function you used, from which
>>> it successfully recovered). So the correct idiom is something like
>>> this: if (!SomeAPI()) {
>>> // API failed: get more information about the error
>>> DWORD err = GetLastError();
>>> } else {
>>> // API succeeded
>>> }
>>>
>>
>> Quite right, I was simplifying for illustration, perhaps too much so.
>
>Under what circumstances, then, would you want to check that
>GetLastError returned a success code (often enough to warrant a special
>macro)?
//
// HRESULTs are 32 bit values layed out as follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +-+-+-+-+-+---------------------+-------------------------------+
// |S|R|C|N|r| Facility | Code |
// +-+-+-+-+-+---------------------+-------------------------------+
//
// where
//
// S - Severity - indicates success/fail
//
// 0 - Success
// 1 - Fail (COERROR)
//
// R - reserved portion of the facility code, corresponds to NT's
// second severity bit.
//
// C - reserved portion of the facility code, corresponds to NT's
// C field.
//
// N - reserved portion of the facility code. Used to indicate a
// mapped NT status value.
//
// r - reserved portion of the facility code. Reserved for internal
// use. Used to indicate HRESULT values that are not status
// values, but are instead message ids for display strings.
//
// Facility - is the facility code
//
// Code - is the facility's status code
//
//
// Severity values
//
#define SEVERITY_SUCCESS 0
#define SEVERITY_ERROR 1
//
// Generic test for success on any status value (non-negative numbers
// indicate success).
//
#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
//
// and the inverse
//
#define FAILED(Status) ((HRESULT)(Status)<0)
So GetLastError() returns an error code, such as 183, which is NOT an HRESULT
This is why an access fault is 0xC0000005
You cannot exchange error codes and HRESULTS trivially
joe
On Fri, 28 Mar 2008 17:27:23 +0100, "Giovanni Dicanio" <giovanni...@invalid.com>
wrote:
The second parameter is NULL for win32 subsystem, must be something else for
DirectDraw.
-- David
Otherwise, they are specific to the module, and you will have to see if there is a
MESSAGETABLE resource in the particular DLL.
joe
On Fri, 28 Mar 2008 18:23:55 +0100, "Giovanni Dicanio" <giovanni...@invalid.com>
wrote:
>
Something along the lines of:
HRESULT foo()
{
if ( !CreateFile(...) )
return GetLastError(); // <-- should instead say return
HRESULT_FROM_WIN32(GetLastError());
...
return ERROR_SUCCESS;
}
int main()
{
if ( SUCCEEDED(foo()) )
...
}
-- David
Ha, you made the same mistake! ;) As you said prior, GetLastError() does
not return HRESULT! ;)
-- David
I think you should do:
return S_OK;
instead of ERROR_SUCCESS, because you are returning HRESULT
G
> The second parameter is NULL for win32 subsystem, must be something else
> for DirectDraw.
Thanks David, that makes sense.
G
Thanks Joe.
When I had to print some diagnostic messages for DirectDraw, I recall that I
used a custom routine to map DDERR_<....> error codes (they are HRESULTs
because DirectDraw is COM-based) into TCHAR strings.
IIRC, also SDL library does that.
Giovanni
FormatMessage is a general message formatting and retrieval facility, supporting
internationalization, in a crude form, as well as message parameters.
It works with plain error codes, too (choosing error code interpretation
ERROR_SUCCESS for numerical value 0).
It retrieves messages from message modules. When you specify "system" flag it
uses modules that contain the [winerror.h] error messages, plus some. For some
APIs, e.g. like RAS, where the "system" flag isn't sufficient, message module
DLLs are (still undocumented, AFAIK) available (quirk, don't know if it's still
that way in XP and Vista: the documententation used to say you could specify
"system" plus a module, but that didn't use to work, you could use one or other
but not both).
To build your own message modules you use the Message Compiler (MC), which is
under-documented.
E.g., you would do that in order to log messages to the event log.
If all you want is the "system" messages, there's not much point in using
FormatMessage directly, at least with Visual C++.
Instead you can simply use the compiler's intrinsic COM support, which does the
lookup for you.
Cheers, & hth.,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
This is another thing about FormatMessage() I don't understand. The HRESULT
should have the 'facility' embedded into it, right? That should mean
Windows should know which DLL contains the message, from the facility code.
So why do you have to specify which module to look in?
-- David
For example, I suggest you look in winerror.h and look at E_UNEXPECTED (0x8000FFFFL). And
the more-or-less 10,000 lines that follow.
It is perfectly legitimate for a component to call SetLastError with one of these results.
Therefore, it is legitimate for GetLastError to retrieve them.
Where is it written that the only form an HRESULT can be returned by is a return result
from a COM component? Note that some layers of interfacing will simply return TRUE or
FALSE and let the caller obtain the HRESULT via GetLastError.
joe
>* Giovanni Dicanio:
>>
>> Maybe FormatMessage with HRESULT works only for some APIs (like when you
>> successfully used it) but not for all...
>
>FormatMessage is a general message formatting and retrieval facility, supporting
>internationalization, in a crude form, as well as message parameters.
>
>It works with plain error codes, too (choosing error code interpretation
>ERROR_SUCCESS for numerical value 0).
>
>It retrieves messages from message modules. When you specify "system" flag it
>uses modules that contain the [winerror.h] error messages, plus some. For some
>APIs, e.g. like RAS, where the "system" flag isn't sufficient, message module
>DLLs are (still undocumented, AFAIK) available (quirk, don't know if it's still
>that way in XP and Vista: the documententation used to say you could specify
>"system" plus a module, but that didn't use to work, you could use one or other
>but not both).
*****
I have not used a version of Windows in which it did not work. You must have been doing
something wrong.
****&
>
>To build your own message modules you use the Message Compiler (MC), which is
>under-documented.
>
>E.g., you would do that in order to log messages to the event log.
>
>If all you want is the "system" messages, there's not much point in using
>FormatMessage directly, at least with Visual C++.
****
Why? Am I supposed to wire in several thousand strings of my own?
****
>
>Instead you can simply use the compiler's intrinsic COM support, which does the
>lookup for you.
****
The "compiler" has no "intrinsic" COM support. The MFC *libraries* allow you to use it,
but it has nothing to do with the compiler. Except for the .tlb support provided by
#import, the compiler doesn't even know COM exists.
So instead of a trivial API, I have to use all of COM to decode an error message? What
part of "simplicity" did I miss here?
joe
****
>
>
>Cheers, & hth.,
>
>- Alf
The code was correct. And your inference is not logically sound.
>> To build your own message modules you use the Message Compiler (MC), which is
>> under-documented.
>>
>> E.g., you would do that in order to log messages to the event log.
>>
>> If all you want is the "system" messages, there's not much point in using
>> FormatMessage directly, at least with Visual C++.
> ****
> Why? Am I supposed to wire in several thousand strings of my own?
No, that's again an invalid inference. You can ->
> ****
>> Instead you can simply use the compiler's intrinsic COM support, which does the
>> lookup for you.
> ****
> The "compiler" has no "intrinsic" COM support.
Silly me.
Pardon me, but I'm laughing.
> The MFC *libraries* allow you to use it,
> but it has nothing to do with the compiler. Except for the .tlb support provided by
> #import, the compiler doesn't even know COM exists.
That, Mr. Newcomer, is fortunately /also/ incorrect. :-)
The Visual C++ compiler's support for COM is very extensive, involving both
syntactical structures with COM-specific keywords, and library components
documented as "Compiler COM Support Classes".
The intrinsic COM support is essentially the COM support you have when you
subtract MFC and ATL from a basic Visual C++ installation.
> So instead of a trivial API, I have to use all of COM to decode an error message? What
> part of "simplicity" did I miss here?
<code>
#include <iostream>
#include <ostream>
#include <comdef.h> // Intrinsic COM support lib components.
#include <winerror.h>
int main()
{
using namespace std;
long const e = ERROR_CLASS_ALREADY_EXISTS;
cout << _com_error( e ).ErrorMessage() << endl;
}
</code>
<output>
Class already exists.
</output>
Cheers, & hth.,
- Alf
PS: Why post so much rubbish, trying to goad someone into helping you and making
a fool of yourself, when you can simply /ask/? I don't understand. But I
assume "Joseph M. Newcomer" is not your real name.
> Silly me.
>
> Pardon me, but I'm laughing.
...
> PS: Why post so much rubbish, trying to goad someone into helping you and
> making a fool of yourself, when you can simply /ask/? I don't understand.
> But I assume "Joseph M. Newcomer" is not your real name.
That is his real name, indeed: he is Joe, and he gives important and quality
contributions in the MFC newsgroup, and also writes very interesting essays
in his web-site (www.flounder.com).
Everyone can make mistakes, and you can correct him, or disagree with some
of Joe's point.
But I don't like the fact that you are offending him: that is *not* good.
Giovanni
Ideally, no one should offend anyone else. There's an attitude here that
seems to think the "quality contributors" have a free pass to offend anyone
they want, and should be protected from being offended, and that's just as
wrong thinking.
-- David
I don't think /I/ am telepathic enough to say that he's offended by what I wrote.
And I think you should not presume any such thing.
That said, it's generally a good idea to check facts before posting, and not
employ ridicule and sarcasm when you haven't (I'm referring to Joseph's use of
quotation marks to indicate "incorrect" use of terms, and his last question),
especially when it then turns out you're quite wrong on the factual. As I
wrote, it would be a much better idea to just /ask/. Like, for example, "This
is unknown to me, could you elaborate, please?".
Cheers, & hth.,
- Alf (does not suffer fools gladly)
> Where is it written that the only form an HRESULT can be returned by is a
> return result
> from a COM component? Note that some layers of interfacing will simply
> return TRUE or
> FALSE and let the caller obtain the HRESULT via GetLastError.
Well, that's the confusion. What sane system would require the caller (me)
to know whether I have to call HRESULT_FROM_WIN32() to get an 'HRESULT'
that I can pass to the SUCCEEDED() macro, or whether I can use what is
returned from GetLastError() directly? Pure nonsense.
-- David
>"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
>news:dcbsu3h67d45s1rqg...@4ax.com...
>> For example, I suggest you look in winerror.h and look at E_UNEXPECTED
>> (0x8000FFFFL). And
>> the more-or-less 10,000 lines that follow.
>>
>And I suggest you look in winerror.h for ERROR_ACCESS_DENIED (5) and the
>many lines that follow and see this is not a valid HRESULT.
***
Yes, those values are not HRESULT values and cannot be used as such. This is news?
****
>
>
>> Where is it written that the only form an HRESULT can be returned by is a
>> return result
>> from a COM component? Note that some layers of interfacing will simply
>> return TRUE or
>> FALSE and let the caller obtain the HRESULT via GetLastError.
>
>Well, that's the confusion. What sane system would require the caller (me)
>to know whether I have to call HRESULT_FROM_WIN32() to get an 'HRESULT'
>that I can pass to the SUCCEEDED() macro, or whether I can use what is
>returned from GetLastError() directly? Pure nonsense.
****
You shouldn't have to know. The documentation will tell you what kinds of errors are
returned. I think we can rightly argue that the documentation does NOT tell us this is
what is insane...
joe
****
What is bogus is some values in winerror.h are HRESULTs and not others.
Furthermore, the ones that are not can still be used in functions that take
HRESULTs such as FormatMessage().
It is not news this is screwed up. What made you think I was talking about
something new?
>>Well, that's the confusion. What sane system would require the caller
>>(me)
>>to know whether I have to call HRESULT_FROM_WIN32() to get an 'HRESULT'
>>that I can pass to the SUCCEEDED() macro, or whether I can use what is
>>returned from GetLastError() directly? Pure nonsense.
> ****
> You shouldn't have to know. The documentation will tell you what kinds of
> errors are
> returned.
Oh please. We're talking about an error numbering system. If the best they
can do is come up with an obscure system that makes the user responsible for
things that should be automatic (like all the error values listed in a
header should be treated similarly) then the implementation is insane.
> I think we can rightly argue that the documentation does NOT tell us this
> is
> what is insane...
The fact that some things are not not documented is bad. The fact that some
are documented does not justify the fact that they need to be documented
when the system should be more intuitive.
Anyway, I started this sub-thread because I thought I did not understand
HRESULT's, but I see that for the most part they are just as screwed up as I
had previously thought. Thanks to Check Abdoul for the info about the
HRESULT_FROM_WIN32 macro. That's the only signal in the rest of this noise.
-- David
> Ideally, no one should offend anyone else.
[...]
I do agree with you David.
Cheers,
G
Woo-hoo, thanks for the tip on _com_error()! Very cool. But does it handle
different locales?
-- David
:-)
-- David
>* Joseph M. Newcomer:
>> See below...
>> On Fri, 28 Mar 2008 19:31:17 +0100, "Alf P. Steinbach" <al...@start.no> wrote:
>>
>>> * Giovanni Dicanio:
>>>> Maybe FormatMessage with HRESULT works only for some APIs (like when you
>>>> successfully used it) but not for all...
>>> FormatMessage is a general message formatting and retrieval facility, supporting
>>> internationalization, in a crude form, as well as message parameters.
>>>
>>> It works with plain error codes, too (choosing error code interpretation
>>> ERROR_SUCCESS for numerical value 0).
>>>
>>> It retrieves messages from message modules. When you specify "system" flag it
>>> uses modules that contain the [winerror.h] error messages, plus some. For some
>>> APIs, e.g. like RAS, where the "system" flag isn't sufficient, message module
>>> DLLs are (still undocumented, AFAIK) available (quirk, don't know if it's still
>>> that way in XP and Vista: the documententation used to say you could specify
>>> "system" plus a module, but that didn't use to work, you could use one or other
>>> but not both).
>> *****
>> I have not used a version of Windows in which it did not work. You must have been doing
>> something wrong.
>> ****&
>
>The code was correct. And your inference is not logically sound.
****
I have used FormatMessage using a module handle since NT 3.51 without problems; I even
wrote about this in 1996 or so. So I don't know why you say it doesn't work. It even
states that when both flags are specified, it selectively tries the system first
beforetrying the HMODULE. I also wrote an essay on how to use FormatMessage to locate
error codes for WinSock in the winsock DLL, and that has worked for years. So why do you
claim it doesn't work?
****
>
>
>>> To build your own message modules you use the Message Compiler (MC), which is
>>> under-documented.
>>>
>>> E.g., you would do that in order to log messages to the event log.
>>>
>>> If all you want is the "system" messages, there's not much point in using
>>> FormatMessage directly, at least with Visual C++.
>> ****
>> Why? Am I supposed to wire in several thousand strings of my own?
>
>No, that's again an invalid inference. You can ->
>
>
>> ****
>>> Instead you can simply use the compiler's intrinsic COM support, which does the
>>> lookup for you.
>> ****
>> The "compiler" has no "intrinsic" COM support.
>
>Silly me.
>
>Pardon me, but I'm laughing.
>
>
>> The MFC *libraries* allow you to use it,
>> but it has nothing to do with the compiler. Except for the .tlb support provided by
>> #import, the compiler doesn't even know COM exists.
>
>That, Mr. Newcomer, is fortunately /also/ incorrect. :-)
****
OK, what part of the compiler knows about COM? Please identify. Those "COM-specific"
keywords are what, exactly? I have never seen one. _bstr_t is not a keyword, for
example. It is just a data type defined in comutil.h. That does not make it "intrinsic"
to the compiler, no matter what the documentation wants to call it. _com_raise_error is
just a function call. According to its documention, it is found in comsupp.lib, which
means it is no more an compiler intrisic function than cos() or sqrt().
A COM Support Class is just a class, and does not require specific knowledge of the
compiler to make it work.
Perhaps you are confusing marketing hype with language definition.
For example, look at comdef.h, there _com_raise_err and _com_error class are defined. They
don't require compiler enhancements, they're just classes defined like any other class.
Your example, _bstr_t, is just a class, defined in comutil.h, just another header file!
The support is not "intrinsic"; you contradict yourself because you show below you are
clearly including a header file to get it!
Please identify the COM-specific keywords that the compiler defines. These would be
reserved words in the C/C++ language, not something found as a #define, class, or template
in a header file.
****
>
>The Visual C++ compiler's support for COM is very extensive, involving both
>syntactical structures with COM-specific keywords, and library components
>documented as "Compiler COM Support Classes".
****
And is printf part of the C language? I think not. printf is part of the C library
support. It is not intrinsic to the C compiler. As soon as you have to say #include, it
is no longer "intrinsic" to the compiler.
****
>
>The intrinsic COM support is essentially the COM support you have when you
>subtract MFC and ATL from a basic Visual C++ installation.
>
>
>> So instead of a trivial API, I have to use all of COM to decode an error message? What
>> part of "simplicity" did I miss here?
>
><code>
> #include <iostream>
> #include <ostream>
> #include <comdef.h> // Intrinsic COM support lib components.
> #include <winerror.h>
>
> int main()
> {
> using namespace std;
> long const e = ERROR_CLASS_ALREADY_EXISTS;
>
> cout << _com_error( e ).ErrorMessage() << endl;
****
What good is cout() in a WIndows app? There's no cout. And how does this differ in any
significant way from what I would write
DWORD err = ::GetLastError();
CString s;
s = ErrorString(err);
So you are saying YOUR function is Good, but MY function is bad? At least my function has
a specification of how it behaves; _com_error::ErrorMessage is not well-defined. For
example, it says it returns the code for an HRESULT; it states that it will return the
error string "#IDispatch error #<wcode>" for a 16-bit error error code (as might be
returned from ::GetLastError()), but your example shows that it is doing something
different than what it is documented to do. Also, there is no discussion about words like
"error" or phrases like "unknown error" and how they are handled for different locales (at
least my function uses a STRINGTABLE entry and is locale-aware as a consequence, and this
is obvious; the documentation for _com_error::ErrorMessage does not state anything at
all). So why would I trust a function that is specified to use an HRESULT and do one
specified thing to do something with a different kind of value, especially when it does
not do what its documentation claims?
****
> }
></code>
>
><output>
> Class already exists.
></output>
>
>
>Cheers, & hth.,
>
>- Alf
>
>
>PS: Why post so much rubbish, trying to goad someone into helping you and making
>a fool of yourself, when you can simply /ask/? I don't understand. But I
>assume "Joseph M. Newcomer" is not your real name.
****
Not another twit who doesn't believe my name...sorry, it is my real name. I can't help
your lack of belief in it. Unfortunately, several schools have awarded me degrees under
that name, the state of Pennsylvania licenses me to drive under that name, and several
banks handle my finances under that name. I file my tax returns under that name. Your
belief system is not relevant to my existence under that name.
Since I was not asking for help, I have no need to goad anyone into giving it to me. You
made a gross mis-statement of fact, that there was "intrinsic" COM support in the
compiler, and there is no such support. There are a few convenient header files and
libraries, but they are not "intrinsic" to the compiler, they're just classes, no matter
what the documentation claims. I've looked at the documentations and the definitions.
There is no "compiler" support for COM, there are no "keywords" that you allude to. There
are a ton of macro definitions, lots of classes, but I don't see anything that relates to
"intrinsic compiler support". Unless you want to call "printf" or "cout" as being
"intrinsic" (neither is!) then there is no intrinsic support in the compiler. Calling a
group of header files and libraries "Compiler COM Support" only means that the person who
wrote that title does not know what he/she is talking about. You have been misled by a
labeling error into thinking that a set of header files, classes, etc. are part of the
"Compiler". They are not. They are just header files that define classes and calls to
library functions. The support is NOT part of the compiler. I just read the code. No
way can you call a header file "intrinsic" support by the compiler.
joe
****
Every once in a while, someone tells me my name is not real. The first time this happened
was in the old CompuServe newsgroups, when someone from Microsoft advised me to use my
real name instead of a handle. "You might even get work if you use your real name". By
that time, I'd been recruited as an instructor by a company who saw my posts, and was
already getting paychecks from the in the name of "Joseph M. Newcomer'. Which I didn't
hestiate to point out. I was the fifth generation of the Newcomer family born on the
family farm. As I pointed out to the poster, his belief in my existence does not affect
my reality.
It takes a lot to offend me. Very few people have ever managed it. The only organization
who managed to really offend me was days from having a lawsuit filed against them for
non-payment of bills when they apologized and paid the amounts I was owed (their claim was
that I cheated the customer by leaving at noon on Friday, and therefore they would not pay
me for the week's teaching; I pointed out that if they had listened to the phone message
I'd left, it said "There's a company-wide technical meeting all this afternoon starting at
2pm, and they told me there was no point in holding class for an hour after lunch, so we
declared the day to be over" But they couldn't because I'd left it for the instructor
coordinator, whom they'd fired that morning, having already fired nearly everyone else in
the past month. Six months later, after they had managed to offend every one of their
contract instructors, they disappeared from sight. I now work for a reputable company
that treats its instructors properly).
joe
>* Giovanni Dicanio:
>> "Alf P. Steinbach" <al...@start.no> ha scritto nel messaggio
>> news:13ush6u...@corp.supernews.com...
>>
>>> Silly me.
>>>
>>> Pardon me, but I'm laughing.
>> ...
>>> PS: Why post so much rubbish, trying to goad someone into helping you and
>>> making a fool of yourself, when you can simply /ask/? I don't understand.
>>> But I assume "Joseph M. Newcomer" is not your real name.
>>
>> That is his real name, indeed: he is Joe, and he gives important and quality
>> contributions in the MFC newsgroup, and also writes very interesting essays
>> in his web-site (www.flounder.com).
>>
>> Everyone can make mistakes, and you can correct him, or disagree with some
>> of Joe's point.
>> But I don't like the fact that you are offending him: that is *not* good.
>
>I don't think /I/ am telepathic enough to say that he's offended by what I wrote.
>
>And I think you should not presume any such thing.
>
>That said, it's generally a good idea to check facts before posting, and not
>employ ridicule and sarcasm when you haven't (I'm referring to Joseph's use of
>quotation marks to indicate "incorrect" use of terms, and his last question),
>especially when it then turns out you're quite wrong on the factual. As I
>wrote, it would be a much better idea to just /ask/. Like, for example, "This
>is unknown to me, could you elaborate, please?".
****
Hmmm. I think I've established that I was correct: the compiler knows nothing about COM.
Any statement that it has special "reserved words" for COM, with the already-mentioned
exception of #import, is erroneous. I had taught COM courses, and had remembered this,
but AFTER checking the facts in the last few minutes, the facts corresponded to my memory
of what was true. There are no special COM keywords known to the compiler, such as
_bstr_t, which is just a class defined in a header file. Fact-checking works both ways.
Before stating something is a fact, it is a good idea to see if it is. Just because there
is some marketing title about "Compiler COM support" does not mean the compiler has a clue
about COM, only that someone who didn't understand the situation was allowed to write a
confusing and misleading title. Misinterpreting this as "compiler intrinsic knowledge" is
incorrect.
joe
****
>
>
>Cheers, & hth.,
>
>- Alf (does not suffer fools gladly)
I believe that's incorrect: AFAIK using _com_error for simple error message
retrieval does not require COM libraries. However, it's irrelevant what goes on
inside.
And it's far simpler than using FormatMessage directly, as demonstrated.
You do lose some control and flexibility.
> He also insisted that the compiler had
> this support "built in" with lots of keywords.
That is at best a misrepresentation (change of context for "this").
> Since I once taught courses in COM, I knew
> he was wrong, but he just had to keep insisting it was intrinsic, and did so by proving it
> wasn't.
That is incorrect.
Best,
- Alf
> :-)
:-)
G
On Sat, 29 Mar 2008 18:41:04 GMT, "David Ching" <d...@remove-this.dcsoft.com> wrote:
>"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
>news:qv1tu3tft96q1ule4...@4ax.com...
>> Yes, those values are not HRESULT values and cannot be used as such. This
>> is news?
>
>What is bogus is some values in winerror.h are HRESULTs and not others.
>Furthermore, the ones that are not can still be used in functions that take
>HRESULTs such as FormatMessage().
>
>It is not news this is screwed up. What made you think I was talking about
>something new?
***
I agree that it is inconsistent. It is hard to say if the COM people got it right because
they had the advantage of afterthought, or they just wanted to add even more gratuitous
complexity.
***
>
>
>>>Well, that's the confusion. What sane system would require the caller
>>>(me)
>>>to know whether I have to call HRESULT_FROM_WIN32() to get an 'HRESULT'
>>>that I can pass to the SUCCEEDED() macro, or whether I can use what is
>>>returned from GetLastError() directly? Pure nonsense.
>> ****
>> You shouldn't have to know. The documentation will tell you what kinds of
>> errors are
>> returned.
>
>Oh please. We're talking about an error numbering system. If the best they
>can do is come up with an obscure system that makes the user responsible for
>things that should be automatic (like all the error values listed in a
>header should be treated similarly) then the implementation is insane.
>
>
>> I think we can rightly argue that the documentation does NOT tell us this
>> is
>> what is insane...
>
>The fact that some things are not not documented is bad. The fact that some
>are documented does not justify the fact that they need to be documented
>when the system should be more intuitive.
****
The problem is that when you get an error that says "Invalid parameter", there should be a
discussion in the API that indicates what are common causes. For example, if two
parameters interact such that if parameter A with certain values means that parameter B
with other specific values is illegal, this ought to be documented. I've wasted hours
trying to figure out what "Invalid parameter" meant under such conditions.
The excuse I was given was "ANY API can return ANY error code" which is nonsense. Most
APIs can only return a small number of error codes.
****
>
>Anyway, I started this sub-thread because I thought I did not understand
>HRESULT's, but I see that for the most part they are just as screwed up as I
>had previously thought. Thanks to Check Abdoul for the info about the
>HRESULT_FROM_WIN32 macro. That's the only signal in the rest of this noise.
****
If you can't live in a perfect world, it is a lot more bearable if the imperfections are
doucumented. That's one of my major gripes about the MS documentation. I often
characterize it as "all of the facts, and none of the truth", but the more I use it, the
more I realize the basic facts are often missing, or plain wrong. See my essay
http://www.flounder.com/msdn_documentation_errors_and_omissions.htm
Given that parts of the API have been stable for decades, it shouldn't take all this time
to get them documented thoroughly, and correctly.
joe
*****
I just looked at this article and it is really impressive. Many of
omissions that are mentioned there are pretty grave. Did you
consider to contact MSDN staff to make some corrections? I think
your MVP status should draw their attention. Fortunately MSDN
library now features Community Content secton on every page, so
people can submit corrections.
Alex
That is a misrepresententation.
As you can see from the text you quoted, I didn't "claim it doesn't work" as you
write, I related experience that "the documententation used to say you could
specify system" plus a module, but that didn't use to work, you could use one or
other but not both".
Now I've invested some time (I wonder whether it's worth it, because the rest of
your reply here is in the same vein as above, argumentative and rhetoric instead
of seeking clarification on the technical) checking old files, and the problem
then, late 90's, manifested with error codes wrapped as HRESULTs via
HRESULT_FROM_WIN32. For example, error code 0x3F should yield the same result
as 0x8007003F. But with both "system" and a HMODULE specified, FormatMessage
didn't grok the latter, and as it happens, still doesn't under Windows XP (I
think it's SP2).
It is relatively easy to fix.
The fix is as described in what I actually wrote. :-)
>>> The MFC *libraries* allow you to use it,
>>> but it has nothing to do with the compiler. Except for the .tlb support provided by
>>> #import, the compiler doesn't even know COM exists.
>> That, Mr. Newcomer, is fortunately /also/ incorrect. :-)
> ****
> OK, what part of the compiler knows about COM? Please identify. Those "COM-specific"
> keywords are what, exactly?
Well, you have either misleadingly snipped a lot of context here, or are
referring to something discussed later in a different context.
A positive interpretation would be the latter.
Just to be clear on that, since I think anyone reading your statements could
easily be misled, the COM specific or strongly COM-related keywords have to do
with general COM support, not with error message retrieval.
> I have never seen one.
That seems to be inconsistent with you mentioning "import" above. Although it's
open to debate whether a preprocessor directive counts as a keyword. I suppose
that in an adversarial debate, which this seems to be from your point of view,
it technically isn't, and so does not count, narrowly focusing it down to a
formal meaning of "keyword" rather than what COM support there is. :-)
But anyway, I'm happy to help.
Here's one example, from the docs: "The keyword __uuidof can be applied to
retrieve the constant GUID attached to a user-defined type."
"__uuidof" retrieves GUID, while keyword "uuid" (yes, it's listed as a keyword)
defines the GUID.
Just in case you don't know, GUIDs are 128 bit identifiers used to dynamically
identify COM interfaces and other COM things. I'm relatively sure that if I
didn't say it you would mention that they can also be used for other things, not
just COM. The compiler's support for them, however, is in support of COM.
From a pure C++ point of view this COM-support language extension is plain
silly, since the same can easily be achieved via templates, within the standard
language, but that same compiler also compiles C. I wish Microsoft could have
limited that particular extension to just C. On the other hand, it allows C +
C++ programmers to only familiarize themselves with a single mechanism.
Then we have the "__interface" keyword. AFAIK it was introduced to handle COM
interfaces. But was general enough that it served also for .NET.
And we have "__event", "__hook", "__unhook" and "__raise", which are not purely
COM specific but work for COM (and also general C++ classes and managed .NET).
Attribute programming, yet another language extension, introduced a host of
different special words in support of COM, but since they are used within
attribute definitions (lots of square brackets) they're not exactly language
keywords, and I'm not familiar with them. Don't know whether it helps you. But
as you can see, contrary to your claims, the Visual C++ compiler does include
quite a lot of COM support via /language extensions/.
> _bstr_t is not a keyword, for
> example. It is just a data type defined in comutil.h.
Right you are.
> That does not make it "intrinsic"
> to the compiler, no matter what the documentation wants to call it.
But here you're wrong. What's intrinsic in a formal sense is whatever the
documentation says is intrinsic, belonging to the compiler: not necessarily
physically built-in. And what's intrinsic in a practical (non-adversial) sense
is a bit more.
For example, early versions of Visual C++ didn't support wchar_t directly, you
had to include some header file. And as far as I know, you can check this out
rather than me, 7.1 uses the same scheme with respect to standard C++ keywords
such as "and" (synonym for &&), and I suspect it's still so with later versions.
Since "and" is required by the C++ standard as keyword, in the standard without
having to #include anything, the support must be regarded as intrinsic in a
compiler that's meant to implement the standard, in the sense that that support
is part and parcel of the compiler.
> _com_raise_error is
> just a function call. According to its documention, it is found in comsupp.lib, which
> means it is no more an compiler intrisic function than cos() or sqrt().
>
> A COM Support Class is just a class, and does not require specific knowledge of the
> compiler to make it work.
>
> Perhaps you are confusing marketing hype with language definition.
>
> For example, look at comdef.h, there _com_raise_err and _com_error class are defined. They
> don't require compiler enhancements, they're just classes defined like any other class.
> Your example, _bstr_t, is just a class, defined in comutil.h, just another header file!
>
> The support is not "intrinsic"; you contradict yourself because you show below you are
> clearly including a header file to get it!
It seems you're hung up on a word definition, having been shown to be wrong on
the main points.
Sorry, I can't help you with that, other than point you to google with search
string "define: intrinsic".
Or e.g. <url: http://www.thefreedictionary.com/intrinsic>.
> Please identify the COM-specific keywords that the compiler defines.
See above. I can't guarantee that that's a complete list. :-)
> These would be
> reserved words in the C/C++ language, not something found as a #define, class, or template
> in a header file.
No, that's incorrect. Neither the C nor the C++ language defines anything
COM-related. However, Visual C++ does, as language extensions (again, see above).
> ****
>> The Visual C++ compiler's support for COM is very extensive, involving both
>> syntactical structures with COM-specific keywords, and library components
>> documented as "Compiler COM Support Classes".
> ****
> And is printf part of the C language? I think not. printf is part of the C library
> support. It is not intrinsic to the C compiler. As soon as you have to say #include, it
> is no longer "intrinsic" to the compiler.
> ****
I would tend to agree there, regarding the Visual C++ implementation of the C++
language, but for a very different reason (conclusion OK, reasoning invalid).
Namely, that to qualify as a conforming C++ compiler for GUI subsystem programs,
with otherwise default options, Visual C++ must be regarded as a so called "free
standing implementation" instead of a "hosted implementation".
And IIRC a free-standing implementation doesn't need to provide printf, hence
it's not an essential part of the compiler (whether it's provided via a library
or by direct code generation by the compiler is an irrelevant implementation
issue, except in the context of discussing physical packaging of compiler).
>> The intrinsic COM support is essentially the COM support you have when you
>> subtract MFC and ATL from a basic Visual C++ installation.
>>
>>
>>> So instead of a trivial API, I have to use all of COM to decode an error message? What
>>> part of "simplicity" did I miss here?
>> <code>
>> #include <iostream>
>> #include <ostream>
>> #include <comdef.h> // Intrinsic COM support lib components.
>> #include <winerror.h>
>>
>> int main()
>> {
>> using namespace std;
>> long const e = ERROR_CLASS_ALREADY_EXISTS;
>>
>> cout << _com_error( e ).ErrorMessage() << endl;
> ****
> What good is cout() in a WIndows app? There's no cout.
I think you mean a GUI subsystem application, for which that statement is incorrect.
In a GUI subsystem application there is a standard output stream, although not
necessarily connected to anything, which you can access via std::cout in C++.
And if you want that GUI subsystem standard output displayed in a console
window, simply pipe the output to a cat program, or e.g. (ugh) Windows' more:
C:> myGuiApp | more
> And how does this differ in any
> significant way from what I would write
> DWORD err = ::GetLastError();
> CString s;
> s = ErrorString(err);
It's simpler in many contexts. For example, when not using MFC or ATL.
> So you are saying YOUR function is Good, but MY function is bad?
No, (getting repetitive, this) that's incorrect. :-)
> At least my function has
> a specification of how it behaves; _com_error::ErrorMessage is not well-defined.
Yes, that's a general problem with Microsoft's software.
If you have a well-documented error message retrieval function it is probably in
many respects better than any such provided by Microsoft.
But not necessarily available to whomeever, wherever, whenever.
[snip]
> Since I was not asking for help, I have no need to goad anyone into giving it to me. You
> made a gross mis-statement of fact, that there was "intrinsic" COM support in the
> compiler, and there is no such support.
No, that's incorrect -- see above.
Cheers, & hth.,
- Alf
--
WHat about `__declspec(uuid(...))' and `__uuidof' keywords? Though
they're not a part of the standard C++, these keywords are used
heavily with COM programming and were designed with COM in mind as
a primary goal.
Also, there are C++ attributes, which aren't standard either.
However, these attributes are supported by the MS C++ compiler and
"are designed to simplify COM programming and .NET Framework
common language runtime development":
"C++ Attributes Reference"
http://msdn2.microsoft.com/en-us/library/f520z3b3.aspx
Alex
I'm sorry, that's incorrect.
COM code generation for e.g. event handling (using special keywords for that,
language extension) certainly implies quite a bit of knowledge about COM... :-)
See reply to your posting else-thread for details.
Cheers, & hth.,
- Alf
--
>Any statement that it has special "reserved words" for COM, with the already-mentioned
>exception of #import, is erroneous.
There are __declspec(uuid) and __uuidof. The #import directive emits code
which heavily uses these keywords, _bstr_t, _com_error, _com_ptr_t, and
even #includes <comdef.h>. It is an integrated system.
--
Doug Harrison
Visual C++ MVP
There is MS extension for the class declaration:
__declspec(uuid(<GUID>))
which associates the GUID with the typename. Then __uuidof will return the
GUID. This is used, for example, by CComPtr and related classes.
****
I presumed that by 'that', you were referring to that fact that <"system" plus a module>
didn't work; in fact, you could always use both, not just one or [the] other. So your
statement seems very clear, and as such, is wrong.
****
>
>Now I've invested some time (I wonder whether it's worth it, because the rest of
>your reply here is in the same vein as above, argumentative and rhetoric instead
>of seeking clarification on the technical) checking old files, and the problem
>then, late 90's, manifested with error codes wrapped as HRESULTs via
>HRESULT_FROM_WIN32. For example, error code 0x3F should yield the same result
>as 0x8007003F. But with both "system" and a HMODULE specified, FormatMessage
>didn't grok the latter, and as it happens, still doesn't under Windows XP (I
>think it's SP2).
****
This is a different statement from what you said. You said that it would not work if you
specified both system ahd from-a-module. Now you are saying something different, that
0x3F and 0x8007003F should give the same message. These are different codes, clearly, and
I'm not sure why FormatMessage would be expected to resolve a code that was the result of
HRESULT_FROM_WIN32. The FormatMessage description does not suggest that it supports this.
But that is not what you stated originally.
****
>
>It is relatively easy to fix.
>
>The fix is as described in what I actually wrote. :-)
>
>
>>>> The MFC *libraries* allow you to use it,
>>>> but it has nothing to do with the compiler. Except for the .tlb support provided by
>>>> #import, the compiler doesn't even know COM exists.
>>> That, Mr. Newcomer, is fortunately /also/ incorrect. :-)
>> ****
>> OK, what part of the compiler knows about COM? Please identify. Those "COM-specific"
>> keywords are what, exactly?
>
>Well, you have either misleadingly snipped a lot of context here, or are
>referring to something discussed later in a different context.
>
>A positive interpretation would be the latter.
>
>Just to be clear on that, since I think anyone reading your statements could
>easily be misled, the COM specific or strongly COM-related keywords have to do
>with general COM support, not with error message retrieval.
****
What COM-specific or strongly COM-related keywords? The terms I am familiar with are NOT
keywords in the C language, they are merely macro definitions from some header file. As
such, they are not "COM-specific keywords" any more than "printf" is an "I/O-specific
keyword" or ULONG is a "scalar-specific keyword". These are not keywords in the C or C++
languages, they are just #defines, or typedefs, or classes, or whatever, but that does not
elevate them to being an intrinsic part of the compiler, any more than 'cos' is a
"math-specific keyword".
****
>
>
>> I have never seen one.
>
>That seems to be inconsistent with you mentioning "import" above. Although it's
>open to debate whether a preprocessor directive counts as a keyword. I suppose
>that in an adversarial debate, which this seems to be from your point of view,
>it technically isn't, and so does not count, narrowly focusing it down to a
>formal meaning of "keyword" rather than what COM support there is. :-)
****
Remember, I said the ONLY COM-specific support I was aware of in the compiler was #import,
yet you are making the claim that there are tons of COM-specific keywords. The only one I
know of that is supported by the compiler is #import; everything else is outside the
compiler, in header files
****
>
>But anyway, I'm happy to help.
>
>Here's one example, from the docs: "The keyword __uuidof can be applied to
>retrieve the constant GUID attached to a user-defined type."
****
OK, I agree. That's ONE reserved word. So now we have two.
The guid is a keyword for __declspec, which is outside the scope of the language
definition.
>
>"__uuidof" retrieves GUID, while keyword "uuid" (yes, it's listed as a keyword)
>defines the GUID.
>
>Just in case you don't know, GUIDs are 128 bit identifiers used to dynamically
>identify COM interfaces and other COM things. I'm relatively sure that if I
>didn't say it you would mention that they can also be used for other things, not
>just COM. The compiler's support for them, however, is in support of COM.
****
You've obviously been reading my essays on the use of GUIDs
****
>
> From a pure C++ point of view this COM-support language extension is plain
>silly, since the same can easily be achieved via templates, within the standard
>language, but that same compiler also compiles C. I wish Microsoft could have
>limited that particular extension to just C. On the other hand, it allows C +
>C++ programmers to only familiarize themselves with a single mechanism.
>
>Then we have the "__interface" keyword. AFAIK it was introduced to handle COM
>interfaces. But was general enough that it served also for .NET.
>
>And we have "__event", "__hook", "__unhook" and "__raise", which are not purely
>COM specific but work for COM (and also general C++ classes and managed .NET).
****
Yes, it said explicitly that these extensions are to support non-COM communication and to
provide a mechanism for inter-module signaling
*****
>
>Attribute programming, yet another language extension, introduced a host of
>different special words in support of COM, but since they are used within
>attribute definitions (lots of square brackets) they're not exactly language
>keywords, and I'm not familiar with them. Don't know whether it helps you. But
>as you can see, contrary to your claims, the Visual C++ compiler does include
>quite a lot of COM support via /language extensions/.
>
>
>> _bstr_t is not a keyword, for
>> example. It is just a data type defined in comutil.h.
>
>Right you are.
>
>
>> That does not make it "intrinsic"
>> to the compiler, no matter what the documentation wants to call it.
>
>But here you're wrong. What's intrinsic in a formal sense is whatever the
>documentation says is intrinsic, belonging to the compiler: not necessarily
>physically built-in. And what's intrinsic in a practical (non-adversial) sense
>is a bit more.
****
So cos, sin, printf, etc. are "intrinsic" by that definition. I'm not sure anyone else
would agree with this as being "intrinsic" to the compiler. They;re just libraries.
****
>
>For example, early versions of Visual C++ didn't support wchar_t directly, you
>had to include some header file. And as far as I know, you can check this out
>rather than me, 7.1 uses the same scheme with respect to standard C++ keywords
>such as "and" (synonym for &&), and I suspect it's still so with later versions.
****
It was a hack in VS5 or something like that, they used 'short' because the ANSI/ISO
standard did not have a type defined for wide characters. So they took the proposed name,
wchar_t, and made it a typedef of 'short'. But we're talking the C++ compiler now, and it
*is* an intrinsic data type.
****
>
>Since "and" is required by the C++ standard as keyword, in the standard without
>having to #include anything, the support must be regarded as intrinsic in a
>compiler that's meant to implement the standard, in the sense that that support
>is part and parcel of the compiler.
****
'and' and 'or' are required as keywords because in some languages, the symbols & and |
(among others) are considered alpha characters (see, for example, Stroustrup, "The C++
Programming Language, Third Edition" p.829. What does this have to do with the
discussion?
****
>
>
>> _com_raise_error is
>> just a function call. According to its documention, it is found in comsupp.lib, which
>> means it is no more an compiler intrisic function than cos() or sqrt().
>>
>> A COM Support Class is just a class, and does not require specific knowledge of the
>> compiler to make it work.
>>
>> Perhaps you are confusing marketing hype with language definition.
>>
>> For example, look at comdef.h, there _com_raise_err and _com_error class are defined. They
>> don't require compiler enhancements, they're just classes defined like any other class.
>> Your example, _bstr_t, is just a class, defined in comutil.h, just another header file!
>>
>> The support is not "intrinsic"; you contradict yourself because you show below you are
>> clearly including a header file to get it!
>
>It seems you're hung up on a word definition, having been shown to be wrong on
>the main points.
****
The main point was an issue of the C++ compiler having tons of keywords to support COM. So
far, we've identified two (#import and __uuidof) and one which is part of __declspec. The
other keywords are extensions that *happen* to work well for COM, but __event, __hook, and
__raise are clearly COM-independent (the documentation even says so).
You said
>The Visual C++ compiler's support for COM is very extensive, involving both
>syntactical structures with COM-specific keywords, and library components
>documented as "Compiler COM Support Classes".
****
There are really only two syntactic structures, __uuidof and __declspec(uuid, ...). But
the library components are not any more intrinsic to the compiler than 'cos' or 'sin'. You
could state
"The Visual C++ compilers support for math is very extensive, involving both syntactical
structures with math-specific keywords and library components documented as "Mathematical
functions" "
But the only syntactic structures for math are the declarations double and float, and the
way to write double and floating constants. The support for math is actually far more
entensive, because it involves the semantics of code generation for operators like +, -,
*, /, %. But functions such as floor(), ceil(), sin(), cos(), etc. are not part of the
compiler. They are part of the runtime support, and as such have no special consideration
any more than any other function a user might write. but a serious mathemetician would
laugh at this "support", since there is no support for Bessel functions, Jacobeans, matrix
operations, matrix inversion, determinants, etc.
A library which is part of the operating environment doesn't make it an intrinsic part of
the compiler.
****
>
>Sorry, I can't help you with that, other than point you to google with search
>string "define: intrinsic".
>
>Or e.g. <url: http://www.thefreedictionary.com/intrinsic>.
***
By that definition, __uuidof and #import are intrinsic. _bstr_t is not. Which was my
point. I was off by one keyword, __uuidof.
****
>
>
>> Please identify the COM-specific keywords that the compiler defines.
>
>See above. I can't guarantee that that's a complete list. :-)
>
>
>> These would be
>> reserved words in the C/C++ language, not something found as a #define, class, or template
>> in a header file.
>
>No, that's incorrect. Neither the C nor the C++ language defines anything
>COM-related. However, Visual C++ does, as language extensions (again, see above).
****
We're up to two keywords in the language extensions. Or three, counting #import.
****
>
>
>
>> ****
>>> The Visual C++ compiler's support for COM is very extensive, involving both
>>> syntactical structures with COM-specific keywords, and library components
>>> documented as "Compiler COM Support Classes".
>> ****
>> And is printf part of the C language? I think not. printf is part of the C library
>> support. It is not intrinsic to the C compiler. As soon as you have to say #include, it
>> is no longer "intrinsic" to the compiler.
>> ****
>
>I would tend to agree there, regarding the Visual C++ implementation of the C++
>language, but for a very different reason (conclusion OK, reasoning invalid).
>
>Namely, that to qualify as a conforming C++ compiler for GUI subsystem programs,
>with otherwise default options, Visual C++ must be regarded as a so called "free
>standing implementation" instead of a "hosted implementation".
>
>And IIRC a free-standing implementation doesn't need to provide printf, hence
>it's not an essential part of the compiler (whether it's provided via a library
>or by direct code generation by the compiler is an irrelevant implementation
>issue, except in the context of discussing physical packaging of compiler).
****
I agree. printf is just a subroutine library. We never needed it for writing embedded
systems.
*****
>
>
>>> The intrinsic COM support is essentially the COM support you have when you
>>> subtract MFC and ATL from a basic Visual C++ installation.
>>>
>>>
>>>> So instead of a trivial API, I have to use all of COM to decode an error message? What
>>>> part of "simplicity" did I miss here?
>>> <code>
>>> #include <iostream>
>>> #include <ostream>
>>> #include <comdef.h> // Intrinsic COM support lib components.
>>> #include <winerror.h>
>>>
>>> int main()
>>> {
>>> using namespace std;
>>> long const e = ERROR_CLASS_ALREADY_EXISTS;
>>>
>>> cout << _com_error( e ).ErrorMessage() << endl;
>> ****
>> What good is cout() in a WIndows app? There's no cout.
>
>I think you mean a GUI subsystem application, for which that statement is incorrect.
>
****
Yes, I was sloppy in my terminology. Exactly: a GUI subsystem application.
****
>In a GUI subsystem application there is a standard output stream, although not
>necessarily connected to anything, which you can access via std::cout in C++.
****
The bits appear to be thrown away.
****
>
>And if you want that GUI subsystem standard output displayed in a console
>window, simply pipe the output to a cat program, or e.g. (ugh) Windows' more:
>
> C:> myGuiApp | more
>
>
>> And how does this differ in any
>> significant way from what I would write
>> DWORD err = ::GetLastError();
>> CString s;
>> s = ErrorString(err);
>
>It's simpler in many contexts. For example, when not using MFC or ATL.
****
Other than discarding the string, which is handled automatically by the destructor, it
appears to be no different
****
>
>
>> So you are saying YOUR function is Good, but MY function is bad?
>
>No, (getting repetitive, this) that's incorrect. :-)
>
>
>> At least my function has
>> a specification of how it behaves; _com_error::ErrorMessage is not well-defined.
>
>Yes, that's a general problem with Microsoft's software.
****
No disagreement there. I find the documentation to be full of holes
****
>
>If you have a well-documented error message retrieval function it is probably in
>many respects better than any such provided by Microsoft.
>
>But not necessarily available to whomeever, wherever, whenever.
>
>
>[snip]
>> Since I was not asking for help, I have no need to goad anyone into giving it to me. You
>> made a gross mis-statement of fact, that there was "intrinsic" COM support in the
>> compiler, and there is no such support.
>
>No, that's incorrect -- see above.
****
Yes, and I stand corrected. There are two intrinsics: __declspec(uuid, ) and __uuidof. My
error.
joe
****
>
>
>Cheers, & hth.,
>
>- Alf
But my statement is erroneous.
joe
But #import acts like a funny preprocessor. Prior to #import the MIDL compiler generated
this stuff.
Unfortunately, MS isn't very good about their MFC or other documentation; for APIs, we
always get specs about which versions implement what, but we get no such consideration for
the language or runtimes. This causes a lot of problems for people who need to do legacy
maintenance, or would like to know when a feature was introduced.
I just went back to my original OLE programming books and no mention of these keywords is
made, so they are a later addition. The keywords are certainly present in VS6.
joe
I've been taken out three times by scripting attacks. Until I can firewall all forms of
client-side scripting so they cannot act upon any part of my permanent state without my
explicit approval, so I know if I can trust scripting, scripting is stripped from all
incoming Web pages. I do not want to spend another week cleaning machines on my network
(which is typically around 8 machines). (Even though I subscribe to daily updates from my
antivirus supplier, these scripting attacks were all of the "day 0" types of attacks, as
they are now called, getting in ahead of the security updates and the antivirus updates.
So I basically don't trust anything I download as part of a client-side script. I've
worked with people developing edefenses, and what they know and were allowed to tell me
was downright scary. But without security clearance, they couldn't tell me the Really
Good Stuff, which was far worse, or so they assured me.)
One seriously scary document is the study the CERT center did on the safety of ActiveX.
While it says that its purpose is to "dispel unwarranted myths about the safety of using
ActiveX" in fact it is very scary, especially the list of programs that are not safe for
scripting but which are marked as such. Prominent in the 2000 list were major programs by
Microsoft, Adobe, Kodak, and others. So we are supposed to believe that all programmers
have followed the correct guidelines, every existing ActiveX control has been fixed, and
no new ones have vulnerabilities? Believe that, and I have a great deal for you on a
bridge for sale in New York, and/or a really good low-cap stock, being sold by the wife of
a deceased Nigerian general (ticker designation SCWU). If anything, the report says that
to be guaranteed safety, you have to configure EVERYTHING, JUST RIGHT, and for selected
controls, just cross your fingers and hope that nothing goes wrong. Sorry, I tried that
approach and it failed. It is easier to not worry about it because it can't happen at all
than to try to make sure I've done everything right according to the report, and
furthermore, I trust the author of the control to have done everything right according to
the report, and furthermore, I trust that there is no lurking backdoor hack that can do
something bad. Right.
So I give up a few dangerous things. I also don't leap out of airplanes wearing only an
assembly of thin fabric, drive automobiles at high speed on closed tracks, race trains to
crossings, or walk down dark, deserted streets in questionable parts of town. I've
decided I'm risk-averse when it comes to exposing myself to unknown dangers for no
commensurate reward. Have you ever confronted the results of the backup of a sanitary
sewer when it shares the rain sewer, and you've just had 12 inches of rain in 24 hours?
Somehow, the advantages of having a basement just don't add up when this can happen once
every few years (it didn't happen to me, but to close relatives, and I had to help clean
it up. We ended up burning our clothes because we couldn't get the smell out of them, I
threw the boots out, and in later years realized how incredibly we had been at risk by not
having hazmat outfits and micropore face masks--which no one had heard of at the time. The
third time I got that feeling while cleaning up my machine, I filled the basement with
solid concrete, as it were. I want proof that the two plumbing systems are disconnected.
http://www.cert.org/reports/activeX_report.pdf
joe
>
>"David Ching" <d...@remove-this.dcsoft.com> ha scritto nel messaggio
>news:JvaHj.30465$R84....@newssvr25.news.prodigy.net...
>>
>> "Igor Tandetnik" <itand...@mvps.org> wrote in message
>> news:e0GkrMPk...@TK2MSFTNGP02.phx.gbl...
>>> Under what circumstances, then, would you want to check that GetLastError
>>> returned a success code (often enough to warrant a special macro)?
>>
>> Something along the lines of:
>>
>> HRESULT foo()
>> {
>> if ( !CreateFile(...) )
>> return GetLastError(); // <-- should instead say return
>> HRESULT_FROM_WIN32(GetLastError());
>>
>> ...
>>
>> return ERROR_SUCCESS;
>> }
>
>I think you should do:
>
> return S_OK;
>
> instead of ERROR_SUCCESS, because you are returning HRESULT
****
It's a fine point, because both are 0, but S_OK is philosophically consistent with an
HRESULT and its a bad idea to mix styles
joe
****
>
>G
Hm, I don't understand what you mean here, but no matter.
>> Now I've invested some time (I wonder whether it's worth it, because the rest of
>> your reply here is in the same vein as above, argumentative and rhetoric instead
>> of seeking clarification on the technical) checking old files, and the problem
>> then, late 90's, manifested with error codes wrapped as HRESULTs via
>> HRESULT_FROM_WIN32. For example, error code 0x3F should yield the same result
>> as 0x8007003F. But with both "system" and a HMODULE specified, FormatMessage
>> didn't grok the latter, and as it happens, still doesn't under Windows XP (I
>> think it's SP2).
> ****
> This is a different statement from what you said. You said that it would not work if you
> specified both system ahd from-a-module. Now you are saying something different, that
> 0x3F and 0x8007003F should give the same message. These are different codes, clearly, and
> I'm not sure why FormatMessage would be expected to resolve a code that was the result of
> HRESULT_FROM_WIN32.
They're the same code, represented as 16-bit error code and as HRESULT,
respectively. FormatMessage deals successfully with both when only using
"system". Add HMODULE and it fails for the HRESULT (on XP).
> The FormatMessage description does not suggest that it supports this.
> But that is not what you stated originally.
Grumble. I used some time on finding the exact failure mode from old files.
Please don't expect me to remember such details off-hand, for a usenet posting
fifteen years on (so initially I just gave the general description)...
And more below.
> The guid is a keyword for __declspec, which is outside the scope of the language
> definition.
>> "__uuidof" retrieves GUID, while keyword "uuid" (yes, it's listed as a keyword)
>> defines the GUID.
At this point, we have 2+1 = three keywords.
>> Just in case you don't know, GUIDs are 128 bit identifiers used to dynamically
>> identify COM interfaces and other COM things. I'm relatively sure that if I
>> didn't say it you would mention that they can also be used for other things, not
>> just COM. The compiler's support for them, however, is in support of COM.
> ****
> You've obviously been reading my essays on the use of GUIDs
:-) No, sorry. Perhaps I'll do that.
> ****
>> From a pure C++ point of view this COM-support language extension is plain
>> silly, since the same can easily be achieved via templates, within the standard
>> language, but that same compiler also compiles C. I wish Microsoft could have
>> limited that particular extension to just C. On the other hand, it allows C +
>> C++ programmers to only familiarize themselves with a single mechanism.
>>
>> Then we have the "__interface" keyword. AFAIK it was introduced to handle COM
>> interfaces. But was general enough that it served also for .NET.
Well, then, at this point we have 3+1 = four keywords, as I count.
>>
>> And we have "__event", "__hook", "__unhook" and "__raise", which are not purely
>> COM specific but work for COM (and also general C++ classes and managed .NET).
> ****
> Yes, it said explicitly that these extensions are to support non-COM communication and to
> provide a mechanism for inter-module signaling
And at this point we have 4+4 = eight keywords, as I count.
Not very much. It pertains to use of word "intrinsic", which I don't agree is
very important at all. :-)
>>> _com_raise_error is
>>> just a function call. According to its documention, it is found in comsupp.lib, which
>>> means it is no more an compiler intrisic function than cos() or sqrt().
>>>
>>> A COM Support Class is just a class, and does not require specific knowledge of the
>>> compiler to make it work.
>>>
>>> Perhaps you are confusing marketing hype with language definition.
>>>
>>> For example, look at comdef.h, there _com_raise_err and _com_error class are defined. They
>>> don't require compiler enhancements, they're just classes defined like any other class.
>>> Your example, _bstr_t, is just a class, defined in comutil.h, just another header file!
>>>
>>> The support is not "intrinsic"; you contradict yourself because you show below you are
>>> clearly including a header file to get it!
>> It seems you're hung up on a word definition, having been shown to be wrong on
>> the main points.
> ****
> The main point was an issue of the C++ compiler having tons of keywords to support COM. So
> far, we've identified two (#import and __uuidof) and one which is part of __declspec.
Eight -- see above.
> The
> other keywords are extensions that *happen* to work well for COM, but __event, __hook, and
> __raise are clearly COM-independent (the documentation even says so).
Since they can generate COM code there is some connection to COM, don't you
think? :-)
The count seems to be rising. :-) Let's settle on eight, and ignore attribute
programming for discussion of keywords (as opposed to more general COM support).
See the usage example I provided right below.
> ****
>> And if you want that GUI subsystem standard output displayed in a console
>> window, simply pipe the output to a cat program, or e.g. (ugh) Windows' more:
>>
>> C:> myGuiApp | more
Here ^^^^^^^^^^^^^^^.
Well, I also count __interface, as well as the four event handler code
generation keywords, for a total of eight. And there's #import, a preprocessor
directive. Plus, in the area of non-keyword-based COM support, requiring deep
knowledge of COM embedded in the compiler, attribute based programming.
Cheers, & hth.,
- Alf
--
Tom
"Giovanni Dicanio" <giovanni...@invalid.com> wrote in message
news:%23OG87fb...@TK2MSFTNGP03.phx.gbl...
>
> "Alf P. Steinbach" <al...@start.no> ha scritto nel messaggio
> news:13ush6u...@corp.supernews.com...
>
>> Silly me.
>>
>> Pardon me, but I'm laughing.
> ...
>> PS: Why post so much rubbish, trying to goad someone into helping you and
>> making a fool of yourself, when you can simply /ask/? I don't
>> understand. But I assume "Joseph M. Newcomer" is not your real name.
>
> That is his real name, indeed: he is Joe, and he gives important and
> quality contributions in the MFC newsgroup, and also writes very
> interesting essays in his web-site (www.flounder.com).
>
> Everyone can make mistakes, and you can correct him, or disagree with some
> of Joe's point.
> But I don't like the fact that you are offending him: that is *not* good.
>
> Giovanni
>
>
>
Tom
"David Ching" <d...@remove-this.dcsoft.com> wrote in message
news:SguHj.30764$R84....@newssvr25.news.prodigy.net...
> "Giovanni Dicanio" <giovanni...@invalid.com> wrote in message
> news:%23OG87fb...@TK2MSFTNGP03.phx.gbl...
>>
>> That is his real name, indeed: he is Joe, and he gives important and
>> quality contributions in the MFC newsgroup, and also writes very
>> interesting essays in his web-site (www.flounder.com).
>>
>> Everyone can make mistakes, and you can correct him, or disagree with
>> some of Joe's point.
>> But I don't like the fact that you are offending him: that is *not* good.
>>
>
Tom
"Giovanni Dicanio" <giovanni...@invalid.com> wrote in message
news:OBdFD2ck...@TK2MSFTNGP02.phx.gbl...
Yes, but I can intuitively grasp the meaning :)
(and I like this metaphor).
G