Where is RAII when you need it?

A

Alf P. Steinbach

Alf said:
But you do have to make sure your exit value is < INT_MAX, and
0x80004005L isn't!

Addendum: I changed the enum that client code uses, to be based on `int`.


Code:
struct Exit_code
{
enum Enum: int
{
success = EXIT_SUCCESS,
failure = static_cast<int>(
cppx::process::detail::exitcode_failure )
};
};


That moves the formal problem to compile time, where presumably g++'s
-ftrapv option can't reach. g++ can still refuse to compile the code
though, since I intentionally used just a relatively clear static_cast
rather than the more subtle and complicated bitlevel rewrite I showed
earlier. In such cases, is there any advantage in catering to possible
but very unlikely perverse compiler behavior?

It still looks like a pointless exercise. If you are only declaring one
failure value, why use something other than EXIT_FAILURE?

That's the /general failure/ value I use in Windows.

The other failure values, in Windows, are then the ordinary Windows
error codes -- it's no cost feature that is sometimes really handy.

To reiterate, EXIT_FAILURE, as mentioned up-thread, is typically a value
(namely 1) that collides with Windows' ERROR_INVALID_FUNCTION code,
while the above value, used for that platform, does not collide.

As mentioned else-thread (I think it was in this thread), there is also
an error code value that collides with an API-level interpretation of
the process exit code, namely STILL_RUNNING, value 259 IIRC. One way to
avoid that problem is to replace it with the general failure value, and
another way is to translate it to a so called "HRESULT" (the general
failure value is an example of such). When the process exit code is
produced by a general, common "main" implementation, this is easy to do.


Cheers & hth.,

- Alf
 
I

Ian Collins

Alf said:
Alf said:
On 19.11.2013 01:17, Ian Collins wrote:

But you do have to make sure your exit value is < INT_MAX, and
0x80004005L isn't!

Addendum: I changed the enum that client code uses, to be based on `int`.


Code:
struct Exit_code
{
enum Enum: int
{
success = EXIT_SUCCESS,
failure = static_cast<int>(
cppx::process::detail::exitcode_failure )
};
};


That moves the formal problem to compile time, where presumably g++'s
-ftrapv option can't reach. g++ can still refuse to compile the code
though, since I intentionally used just a relatively clear static_cast
rather than the more subtle and complicated bitlevel rewrite I showed
earlier. In such cases, is there any advantage in catering to possible
but very unlikely perverse compiler behavior?

It still looks like a pointless exercise. If you are only declaring one
failure value, why use something other than EXIT_FAILURE?

That's the /general failure/ value I use in Windows.

The other failure values, in Windows, are then the ordinary Windows
error codes -- it's no cost feature that is sometimes really handy.

But are those error codes designed to be used as application return
values? Is it normal practice on windows to use then as such?
To reiterate, EXIT_FAILURE, as mentioned up-thread, is typically a value
(namely 1) that collides with Windows' ERROR_INVALID_FUNCTION code,
while the above value, used for that platform, does not collide.

So? in the Unix world, EXIT_FAILURE "collides" with EPERM. The fact
that the error codes exist in different domains makes the "collision"
irreverent.
 
A

Alf P. Steinbach

Alf said:
Alf P. Steinbach wrote:
On 19.11.2013 01:17, Ian Collins wrote:

But you do have to make sure your exit value is < INT_MAX, and
0x80004005L isn't!

Addendum: I changed the enum that client code uses, to be based on
`int`.


Code:
struct Exit_code
{
enum Enum: int
{
success = EXIT_SUCCESS,
failure = static_cast<int>(
cppx::process::detail::exitcode_failure )
};
};


That moves the formal problem to compile time, where presumably g++'s
-ftrapv option can't reach. g++ can still refuse to compile the code
though, since I intentionally used just a relatively clear static_cast
rather than the more subtle and complicated bitlevel rewrite I showed
earlier. In such cases, is there any advantage in catering to possible
but very unlikely perverse compiler behavior?

It still looks like a pointless exercise. If you are only declaring one
failure value, why use something other than EXIT_FAILURE?

That's the /general failure/ value I use in Windows.

The other failure values, in Windows, are then the ordinary Windows
error codes -- it's no cost feature that is sometimes really handy.

But are those error codes designed to be used as application return
values? Is it normal practice on windows to use then as such?

My guess is at best as good as yours here. Most likely "no" to both,
though. At a guess. :)

At least two others have raised similar concerns about what some unknown
error code designer (who may not even have existed) once maybe had in
mind. Your question here about normal/usual practice appears to be
somewhat in the same category. That is, it appears to be associated with
general blind conformance, with adherence to rules laid down by others
or already used by peers, at any cost, and that seen as inherently
positive, with the opposite seen as inherently negative.

Regardless, it makes no sense to me.

If you're talking about size compatibility, yes all the error code
values and the process exit code are 32-bit, very compatible, no
problem. I've discussed in detail the limitations on values for the case
where one desires perfection. Namely, avoid 259 STILL_RUNNING.

If you're talking about relevant general practice and/or the Holy
Standard, std::system_error exception class, introduced in C++11,
carries an error code up the call chain, and that's its main purpose.

At the top of the call chain the code can be logged, discarded, and/or
reported. Using the process exit code is one cost-free way to report it,
not excluding other ways. That's what I do.

Does that help?

So? in the Unix world, EXIT_FAILURE "collides" with EPERM. The fact
that the error codes exist in different domains makes the "collision"
irreverent.

Sorry, again I fail to see what that's about, how it can matter for
anything?


Cheers,

- Alf (baffled)
 
I

Ian Collins

Alf said:
Alf said:
On 19.11.2013 19:07, Ian Collins wrote:
Alf P. Steinbach wrote:
On 19.11.2013 01:17, Ian Collins wrote:

But you do have to make sure your exit value is < INT_MAX, and
0x80004005L isn't!

Addendum: I changed the enum that client code uses, to be based on
`int`.


Code:
struct Exit_code
{
enum Enum: int
{
success = EXIT_SUCCESS,
failure = static_cast<int>(
cppx::process::detail::exitcode_failure )
};
};


That moves the formal problem to compile time, where presumably g++'s
-ftrapv option can't reach. g++ can still refuse to compile the code
though, since I intentionally used just a relatively clear static_cast
rather than the more subtle and complicated bitlevel rewrite I showed
earlier. In such cases, is there any advantage in catering to possible
but very unlikely perverse compiler behavior?

It still looks like a pointless exercise. If you are only declaring one
failure value, why use something other than EXIT_FAILURE?

That's the /general failure/ value I use in Windows.

The other failure values, in Windows, are then the ordinary Windows
error codes -- it's no cost feature that is sometimes really handy.

But are those error codes designed to be used as application return
values? Is it normal practice on windows to use then as such?

My guess is at best as good as yours here. Most likely "no" to both,
though. At a guess. :)

At least two others have raised similar concerns about what some unknown
error code designer (who may not even have existed) once maybe had in
mind. Your question here about normal/usual practice appears to be
somewhat in the same category. That is, it appears to be associated with
general blind conformance, with adherence to rules laid down by others
or already used by peers, at any cost, and that seen as inherently
positive, with the opposite seen as inherently negative.

Conventions exist for good reasons.
Regardless, it makes no sense to me.

Just as returning values the calling environment won't understand makes
no sense to me (and the majority of other programmers I'd wager).
If you're talking about size compatibility, yes all the error code
values and the process exit code are 32-bit, very compatible, no
problem. I've discussed in detail the limitations on values for the case
where one desires perfection. Namely, avoid 259 STILL_RUNNING.

If you're talking about relevant general practice and/or the Holy
Standard, std::system_error exception class, introduced in C++11,
carries an error code up the call chain, and that's its main purpose.

At the top of the call chain the code can be logged, discarded, and/or
reported. Using the process exit code is one cost-free way to report it,
not excluding other ways. That's what I do.

Does that help?

Not really, but I'm not a windows programmer or user. How would such an
error return help a customer or general users diagnose a crash? In the
Unix world, abnormal termination would usually be reported by one or
more of a message on stderr, a syslog entry or a core file.
Sorry, again I fail to see what that's about, how it can matter for
anything?

Well ERROR_INVALID_FUNCTION and EPERM are both API error codes that
happen to be 1. You say you don't use EXIT_FAILURE because it clashes
with ERROR_INVALID_FUNCTION, I'm saying there are many sets of error
codes that use the value 1. I'm also saying ERROR_INVALID_FUNCTION is
more an application return code than EPERM (or TRUE or any of the many
other common macros that happen to be 1).
 
I

Ian Collins

Scott said:
Ian's point is that they are two different domains. The values from the
set of errno values (API return values) are distinct from the values used
to return application status. Only two of the latter are defined, 0 for
success and 1 for failure (codified by POSIX as EXIT_SUCCESS and EXIT_FAILURE)
the remainder of the 8-bit space is application defined).

The exit(2) api (which is invoked implicitly by a return from main()) on unix
and unix-like systems isn't designed to take an API error code, just an
application status code. Conflating the two is a programmer error.

Thank you for Scott summing up my points better than I did :)
 
A

Alf P. Steinbach

Just as returning values the calling environment won't understand makes
no sense to me (and the majority of other programmers I'd wager).

The general convention for process exit codes in Windows is as in *nix,
namely that 0 means success and anything else means failure.

Using system error codes as process exit codes is entirely consistent
with that, and is consistent with the common variation of failure codes.

So, I'm sorry but your statement about "won't understand" is nonsense.

Not really, but I'm not a windows programmer or user. How would such an
error return help a customer or general users diagnose a crash?

One can use any Windows error code checking tool, such as Microsoft's
errlook, to get a descriptive message, if such exists. At the API level
such tools work by calling the FormatMessage function, and there are a
variety of wrappers for that. And so it's not much work to code up an
errlook program, on the spot, if one doesn't already have one.

Some APIs have separate error message table DLLs, e.g. that was the case
for the telephony API in the 90's (I'm not sure how it is today), and
then one has to specify the DLL -- or "module" -- to errlook.

However, the majority of the most likely error codes have messages
available via the default tables, and these messages also appear as
comments in the headers, such as in <winerror.h> (the headers are
generated by the "message compiler" tool, which also generates the
message tables).

In the
Unix world, abnormal termination would usually be reported by one or
more of a message on stderr, a syslog entry or a core file.

Well there's a huge difference but I think it's mostly irrelevant to
this discussion.

For, (the cost-free) reporting via process exit codes come in addition
to the more detailed reporting and debugging mechanisms.

Sometimes very handy, but not at all most of the time. ;-)

Well ERROR_INVALID_FUNCTION and EPERM are both API error codes that
happen to be 1. You say you don't use EXIT_FAILURE because it clashes
with ERROR_INVALID_FUNCTION, I'm saying there are many sets of error
codes that use the value 1. I'm also saying ERROR_INVALID_FUNCTION is
more an application return code than EPERM (or TRUE or any of the many
other common macros that happen to be 1).

So? Since I'm returning Windows error codes, that's what I have to
support. I fail to see the imagined problem -- things do work OK. :)


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

Thank you for Scott summing up my points better than I did :)

I have Lurndal killfiled so, happily, I do not see postings.

He conflates the C++ standard with Posix regarding EXIT_FAILURE, and he
conflates Posix with Windows regarding the Windows exit() function.

One could of course get the opposite impression from reading Lurndal, or
for that matter from your response (!), but summing up all this
conflation of his: it's nonsense -- emotionally evocative nonsense.


Cheers & hth.,

- Alf
 
I

Ian Collins

Alf said:
I have Lurndal killfiled so, happily, I do not see postings.

Am I the only person you haven't kill-filed?
He conflates the C++ standard with Posix regarding EXIT_FAILURE, and he
conflates Posix with Windows regarding the Windows exit() function.

One could of course get the opposite impression from reading Lurndal, or
for that matter from your response (!), but summing up all this
conflation of his: it's nonsense -- emotionally evocative nonsense.

I'm sorry Alf, but the nonsense was your earlier statement:

Anyway, when the value 1 signifies an error, then in Windows it is
ERROR_INVALID_FUNCTION, and so with the common Windows convention that
EXIT_FAILURE = 1 one simply does not want to use EXIT_FAILURE: one could
not then distinguish general failure from ERROR_INVALID_FUNCTION.
 
A

Alf P. Steinbach

Am I the only person you haven't kill-filed?


I'm sorry Alf, but the nonsense was your earlier statement:

Anyway, when the value 1 signifies an error, then in Windows it is
ERROR_INVALID_FUNCTION, and so with the common Windows convention that
EXIT_FAILURE = 1 one simply does not want to use EXIT_FAILURE: one could
not then distinguish general failure from ERROR_INVALID_FUNCTION.

I can't see what you don't understand about it, sorry.

It's at the level of facts like 2+2 = 4.

Denial of that is very difficult to argue against, and please do note
that IT WORKS -- not by magic but by design. It works. No problem.

Anyway, regarding the possibility of doing this also in *nix, which
maybe is the hidden issue?, note that Lurndal wrote "the remainder of
the 8-bit space [of *nix process exit codes] is application defined".

If that's correct then nothing prevents doing the same in *nix -- I
mean, regardless of Lurndal's irrational self-contradicting assertion
that it would be a conflation and an error to use the available space.


Cheers & hth.,

- Alf
 
G

Geoff

But are those error codes designed to be used as application return
values? Is it normal practice on windows to use then as such?

The Windows error codes are designed to identify the cause and
severity of the error and it's documented in winerror.h:

//
// Note: There is a slightly modified layout for HRESULT values
below,
// after the heading "COM Error Codes".
//
// Values are 32 bit values laid 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
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
//
// where
//
// Sev - is the severity code
//
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
//
// C - is the Customer code flag
//
// R - is a reserved bit
//
// Facility - is the facility code
//
// Code - is the facility's status code
//

They then go on to enumerate the facility codes and all of those
facilities are internal to Windows.

Each of the error codes returned from Win32 are enumerated in that
header and the text of the message associated with that error code is
also listed in the comments about that error code.

The COM error codes have an altered bitmap format and it's these codes
that are interpreted by the HRESULT 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
//


In Windows, a dialog box appears with the message text and the error
code from the Win32 system so there is really no reason to return it
from the application. I suppose a lazy C++ program could pass it up
the call chain and let it all unroll but then you run into the hazards
Alf is concerned about with collision of the error code with some
constant that doesn't have the same meaning at a higher level.

Windows itself returns error 259L, that Alf is so paranoid about, and
it's defined thus:

//
// MessageId: ERROR_NO_MORE_ITEMS
//
// MessageText:
//
// No more data is available.
//
#define ERROR_NO_MORE_ITEMS 259L

The actual Windows error codes returned from Win32 facilities are
logged by the system in the Event Log (the Windows equivalent of the
*nix syslog) and can be analyzed post-mortem if need be.

The point of the multiplicity of Win32 error codes, IMHO, is for a
user program to interpret the error at the point of use and deal with
it appropriately, terminating the operation and returning its own
error codes as necessary and they were never intended to returned from
main.

Alf commits a grevious error when he cites STILL_RUNNING as value 259.
The actual macro name is STILL_ACTIVE and can be returned from the
Win32 GetExitCodeThread function and must be avoided when terminating
a thread or process since the return value from a thread lingers.
Microsoft warns about this in their documentation:

"Important The GetExitCodeThread function returns a valid error code
defined by the application only after the thread terminates.
Therefore, an application should not use STILL_ACTIVE (259) as an
error code. If a thread returns STILL_ACTIVE (259) as an error code,
applications that test for this value could interpret it to mean that
the thread is still running and continue to test for the completion of
the thread after the thread has terminated, which could put the
application into an infinite loop."

Alf's policy of returning Windows internal error codes from his
application creates complication and hazard where none would exist by
simply returning EXIT_SUCCESS or EXIT_FAILURE.

But then, I don't know anything and I am plinked.
 
I

Ian Collins

Alf said:
I can't see what you don't understand about it, sorry.

It's not a matter of comprehension. The issue is your justification.

Asserting "one simply does not want to use EXIT_FAILURE: one could not
then distinguish general failure from ERROR_INVALID_FUNCTION" is
nonsense and no different form claiming "one simply does not want to use
ERROR_INVALID_FUNCTION": one could not then distinguish specific failure
from S_FALSE".

The macros exist in different domains.
Anyway, regarding the possibility of doing this also in *nix, which
maybe is the hidden issue?, note that Lurndal wrote "the remainder of
the 8-bit space [of *nix process exit codes] is application defined".

If that's correct then nothing prevents doing the same in *nix

It doesn't, but I doubt anyone would. Application failures seldom map
to specific API errors.
 
I

Ian Collins

Geoff said:
The Windows error codes are designed to identify the cause and
severity of the error and it's documented in winerror.h:

//
// Note: There is a slightly modified layout for HRESULT values
below,
// after the heading "COM Error Codes".
//
// Values are 32 bit values laid 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
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
//
// where
//
// Sev - is the severity code
//
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
//
// C - is the Customer code flag
//
// R - is a reserved bit
//
// Facility - is the facility code
//
// Code - is the facility's status code
//

They then go on to enumerate the facility codes and all of those
facilities are internal to Windows.

Each of the error codes returned from Win32 are enumerated in that
header and the text of the message associated with that error code is
also listed in the comments about that error code.

The COM error codes have an altered bitmap format and it's these codes
that are interpreted by the HRESULT 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
//


In Windows, a dialog box appears with the message text and the error
code from the Win32 system so there is really no reason to return it
from the application. I suppose a lazy C++ program could pass it up
the call chain and let it all unroll but then you run into the hazards
Alf is concerned about with collision of the error code with some
constant that doesn't have the same meaning at a higher level.

Windows itself returns error 259L, that Alf is so paranoid about, and
it's defined thus:

//
// MessageId: ERROR_NO_MORE_ITEMS
//
// MessageText:
//
// No more data is available.
//
#define ERROR_NO_MORE_ITEMS 259L

The actual Windows error codes returned from Win32 facilities are
logged by the system in the Event Log (the Windows equivalent of the
*nix syslog) and can be analyzed post-mortem if need be.

The point of the multiplicity of Win32 error codes, IMHO, is for a
user program to interpret the error at the point of use and deal with
it appropriately, terminating the operation and returning its own
error codes as necessary and they were never intended to returned from
main.

Alf commits a grevious error when he cites STILL_RUNNING as value 259.
The actual macro name is STILL_ACTIVE and can be returned from the
Win32 GetExitCodeThread function and must be avoided when terminating
a thread or process since the return value from a thread lingers.
Microsoft warns about this in their documentation:

"Important The GetExitCodeThread function returns a valid error code
defined by the application only after the thread terminates.
Therefore, an application should not use STILL_ACTIVE (259) as an
error code. If a thread returns STILL_ACTIVE (259) as an error code,
applications that test for this value could interpret it to mean that
the thread is still running and continue to test for the completion of
the thread after the thread has terminated, which could put the
application into an infinite loop."

Alf's policy of returning Windows internal error codes from his
application creates complication and hazard where none would exist by
simply returning EXIT_SUCCESS or EXIT_FAILURE.

But then, I don't know anything and I am plinked.

Or plonked...

Thank you for the detailed explanation Geoff, the internals of the Win32
API is somewhere I have never ventured!

I'll re-quote this snippet for emphasis:
 
A

Alf P. Steinbach

It's not a matter of comprehension. The issue is your justification.

Asserting "one simply does not want to use EXIT_FAILURE: one could not
then distinguish general failure from ERROR_INVALID_FUNCTION" is
nonsense and no different form claiming "one simply does not want to use
ERROR_INVALID_FUNCTION": one could not then distinguish specific failure
from S_FALSE".

The macros exist in different domains.

Oh my.

First, let me just again note that the error code scheme WORKS, is
cost-free, and is sometimes very handy.

No known problem, sometimes advantage.

It's just silly, absolute nonsense, to give that up for some
hypothetical quite blurry ideal, if that's what you're arguing.

So to reiterate, the arguments, which do not seem to make sense in
themselves, are in the direction of a purpose that also is nonsense.

* * *

Now, when one's goal is to report error codes via the process exit code,
then a conflict with the C++ implementation's choices for the
standard's values does matter.

Conflicts with other values, from *nix-land as you mentioned, values
that are used perhaps in some irrelevant imagined impractical scheme
that hasn't been mentioned, do not matter for what we discuss.

I.e. that's nonsense.

* * *

Since you now mention S_FALSE, that's a real problem, a conflict (and
yes the values are in one shared domain). The FormatMessage API function
resolves this conflict in favor of ERROR_INVALID_FUNCTION. The working
assumption is simply that any value except 0 denotes an error/failure,
and then this selects the ERROR_INVALID_FUNCTION interpretation.

Anyway, regarding the possibility of doing this also in *nix, which
maybe is the hidden issue?, note that Lurndal wrote "the remainder of
the 8-bit space [of *nix process exit codes] is application defined".

If that's correct then nothing prevents doing the same in *nix

It doesn't, but I doubt anyone would. Application failures seldom map
to specific API errors.

Not always, but often enough to make the error code of practical value.

If one then has the error code information at hand, good, pretty handy.

If not, more work.


Cheers & hth.,

- Alf ;-)
 
A

Alf P. Steinbach

Geoff wrote:
[snip quoting of lots of Windows headers stuff]
That's incorrect, and very silly.

The reader can imagine how impractical it would be with such boxes
popping up all the time, every time a program failed. ">dir x". Bang, box!

I gather that Geoff is irrationally generalizing from some particular
experience.


[snip]
Oh -- sorry 'bout that.


[snip]
Geoff fails to point out any of the "complication" and "hazard" that he
envisions, but based on some 20 years of Windows API level programming I
am pretty sure that there is no such, that it's just his fantasy.

Or plonked...

No, not plonked: Geoff is decidedly among the very-light-weight trolls,
as evidenced above.

Thank you for the detailed explanation Geoff, the internals of the Win32
API is somewhere I have never ventured!

I'll re-quote this snippet for emphasis:

Not sure what you find interesting here, but it's incorrect and I just
can't resist correcting incorrect technical statements; namely, there is
a facility for user-defined codes, used by some COM libraries.


Cheers & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top