WinGetLastError() - OS2

This is a discussion on WinGetLastError() - OS2 ; Hello, I have a function to load a container in details view that wraps the CM_INSERTRECORDARRAY message. If WinSendMsg() returns 0, it indicates the request failed for some reason and WinGetLastError() has the reason. WinGetLastError() uses an anchor block to ...

+ Reply to Thread
Results 1 to 18 of 18

Thread: WinGetLastError()

  1. WinGetLastError()

    Hello,
    I have a function to load a container in details view that wraps the
    CM_INSERTRECORDARRAY message. If WinSendMsg() returns 0, it indicates the
    request failed for some reason and WinGetLastError() has the reason.
    WinGetLastError() uses an anchor block to decide where the error code
    exists.
    My problem is how to *get* the appropriate anchor block. As it turns out
    it is not the anchor block of the window where the request failed but the
    thread that initiated the request. A window's anchor block is retrieved
    with WinQueryAnchorBlock(HWND) but that is no use in the multi-threaded
    application.
    How do I get the current thread's anchor block?

    --
    jmm (hyphen) list (at) sohnen-moe (dot) com
    (Remove .AXSPAMGN for email)

  2. Re: WinGetLastError()

    In , on 07/13/2008
    at 12:41 PM, Jim Moe said:

    Hi,

    > My problem is how to *get* the appropriate anchor block. As it turns
    >out it is not the anchor block of the window where the request failed but
    >the thread that initiated the request. A window's anchor block is
    >retrieved with WinQueryAnchorBlock(HWND) but that is no use in the
    >multi-threaded application.


    Why do you say this? Is WinGetLastError() or WinGetErrorInfo() not
    returning data you can use? FWIW, my experience is that this that these
    report appropriate results for CM_INSERTRECORD failures.

    > How do I get the current thread's anchor block?


    Well, you could either save it in a static or issue WinQueryAnchorBlock()
    for a window you know was created by the current thread. However, I
    suspect your problem is elesewhere.

    Steven

    --
    --------------------------------------------------------------------------------------------
    Steven Levine MR2/ICE 3.00 beta 11pre14 #10183
    eCS/Warp/DIY/14.103a_W4 www.scoug.com irc.ca.webbnet.info #scoug (Wed 7pm PST)
    --------------------------------------------------------------------------------------------


  3. Re: WinGetLastError()

    On Sun, 13 Jul 2008 13:36:32 -0700, Steven Levine
    wrote:

    >> How do I get the current thread's anchor block?

    >
    > Well, you could either save it in a static or issue WinQueryAnchorBlock()
    > for a window you know was created by the current thread. However, I
    > suspect your problem is elesewhere.


    Or you can fabricate it from the PID and TID. One is in the low word and
    the other is in the high word. I forget which way round it is, but it's
    easy enough to work it out.
    Somehow I doubt it is used anyway, as PM knows the context of what thread is
    calling it.

  4. Re: WinGetLastError()

    Hi,

    Jim Moe schrieb:
    > I have a function to load a container in details view that wraps the
    > CM_INSERTRECORDARRAY message. If WinSendMsg() returns 0, it indicates the
    > request failed for some reason and WinGetLastError() has the reason.
    > WinGetLastError() uses an anchor block to decide where the error code
    > exists.
    > My problem is how to *get* the appropriate anchor block.


    as far as I know. WinGetLastError does not use the hab at all. Simply
    call WinGetLastError(NULL). Of course, this is unspecified behavior. But
    it is very likely that no one is going to rewrite the PM.


    Marcel

  5. Re: WinGetLastError()

    On 07/13/08 01:36 pm, Steven Levine wrote:
    >
    >> My problem is how to *get* the appropriate anchor block. As it turns
    >>out it is not the anchor block of the window where the request failed but
    >>the thread that initiated the request. A window's anchor block is
    >>retrieved with WinQueryAnchorBlock(HWND) but that is no use in the
    >>multi-threaded application.

    >
    > Why do you say this? Is WinGetLastError() or WinGetErrorInfo() not
    > returning data you can use? FWIW, my experience is that this that these
    > report appropriate results for CM_INSERTRECORD failures.
    >

    No, WinGetLastError(anchor) does not because I do not have the correct
    anchor block. It always returns 0, no error, since the error occurs in a
    thread the did not create the window.

    >> How do I get the current thread's anchor block?

    >
    > Well, you could either save it in a static or issue WinQueryAnchorBlock()
    > for a window you know was created by the current thread. However, I
    > suspect your problem is elesewhere.
    >

    Multiple threads would write to the static variable.
    WinQueryAnchorBlock(window) returns the anchor block of the thread that
    created the window, not the thread in which an error occurred.

    --
    jmm (hyphen) list (at) sohnen-moe (dot) com
    (Remove .AXSPAMGN for email)

  6. Re: WinGetLastError()

    On 07/13/08 05:00 pm, Marcel Müller wrote:
    >> My problem is how to *get* the appropriate anchor block.

    >
    > As far as I know, WinGetLastError does not use the hab at all. Simply
    > call WinGetLastError(NULL). Of course, this is unspecified behavior. But
    > it is very likely that no one is going to rewrite the PM.
    >

    Should that be WinGetLastError(NULLHANDLE)?
    This would imply I have no hope of ever getting the error value that
    occurred in a thread.

    --
    jmm (hyphen) list (at) sohnen-moe (dot) com
    (Remove .AXSPAMGN for email)

  7. Re: WinGetLastError()

    In , on 07/13/2008
    at 05:35 PM, Jim Moe said:

    Hi,

    > Multiple threads would write to the static variable.


    So? Use a static array or use Paul's suggestion and try to fabricate the
    HAB.

    > WinQueryAnchorBlock(window) returns the anchor block of the thread that
    >created the window, not the thread in which an error occurred.


    I would also note that the docs do not say that a 0 return always
    indicates an error. Is it possible that 0 is the correct number of
    inserted records?

    Steven

    --
    --------------------------------------------------------------------------------------------
    Steven Levine MR2/ICE 3.00 beta 11pre14 #10183
    eCS/Warp/DIY/14.103a_W4 www.scoug.com irc.ca.webbnet.info #scoug (Wed 7pm PST)
    --------------------------------------------------------------------------------------------


  8. Re: WinGetLastError()

    On 07/13/08 09:35 pm, Steven Levine wrote:
    >
    >> Multiple threads would write to the static variable.

    >
    > So? Use a static array [...]
    >

    So I would have to manage an array (boundary checks, stale entry
    markers, next-empty-slot index, ...) and then step through all of the
    entries to discover if there was an error.
    >
    > I would also note that the docs do not say that a 0 return always
    > indicates an error. Is it possible that 0 is the correct number of
    > inserted records?
    >

    This is true. However, the purpose of CM_INSERTRECORDARRAY is to add
    records and the return value is the number of records in the container
    after insertion, including any records that are already there.

    --
    jmm (hyphen) list (at) sohnen-moe (dot) com
    (Remove .AXSPAMGN for email)

  9. Re: WinGetLastError()

    On 07/13/08 04:32 pm, Paul Ratcliffe wrote:
    >
    >>> How do I get the current thread's anchor block?

    >>

    > Or you can fabricate it from the PID and TID. One is in the low word and
    > the other is in the high word. I forget which way round it is, but it's
    > easy enough to work it out.
    >

    What's the easiest way to get both the current PID and TID?

    > Somehow I doubt it is used anyway, as PM knows the context of what thread is
    > calling it.


    Since WinGetLastError() requires a valid anchor block, getting the
    anchor block value for the current thread should be easy. Not so far.

    --
    jmm (hyphen) list (at) sohnen-moe (dot) com
    (Remove .AXSPAMGN for email)

  10. Re: WinGetLastError()

    On Mon, 14 Jul 2008 00:42:14 UTC, Jim Moe
    wrote:

    > >> My problem is how to *get* the appropriate anchor block.

    > >
    > > As far as I know, WinGetLastError does not use the hab at all. Simply
    > > call WinGetLastError(NULL). Of course, this is unspecified behavior. But
    > > it is very likely that no one is going to rewrite the PM.
    > >

    > Should that be WinGetLastError(NULLHANDLE)?
    > This would imply I have no hope of ever getting the error value that
    > occurred in a thread.


    When I need to pass a HAB and I don't happen to have it in scope, I just
    specify 1. I'm pretty certain it's not used anyway.

    See this thread:
    http://groups.google.com/group/comp...._frm/thread/5f
    c78425003ab8c8/d726f9352d7fec94?lnk=st&q=#d726f9352d7fec94

    In particular, since Marc was part of the OS/2 team at IBM, I'd assume he
    knows what he's talking about...

    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  11. Re: WinGetLastError()

    Jim Moe wrote:
    > On 07/13/08 04:32 pm, Paul Ratcliffe wrote:
    >
    >>>> How do I get the current thread's anchor block?
    >>>

    >>Or you can fabricate it from the PID and TID. One is in the low word and
    >>the other is in the high word. I forget which way round it is, but it's
    >>easy enough to work it out.
    >>

    >
    > What's the easiest way to get both the current PID and TID?
    >


    DosGetInfoBlocks.

    >
    >>Somehow I doubt it is used anyway, as PM knows the context of what thread is
    >>calling it.

    >
    >
    > Since WinGetLastError() requires a valid anchor block, getting the
    > anchor block value for the current thread should be easy. Not so far.
    >


    --
    prf

    ** Posted from http://www.teranews.com **

  12. Re: WinGetLastError()

    On Mon, 14 Jul 2008 00:35:50 UTC, Jim Moe wrote:
    > On 07/13/08 01:36 pm, Steven Levine wrote:
    > >
    > >> My problem is how to *get* the appropriate anchor block. As it turns
    > >>out it is not the anchor block of the window where the request failed but
    > >>the thread that initiated the request. A window's anchor block is
    > >>retrieved with WinQueryAnchorBlock(HWND) but that is no use in the
    > >>multi-threaded application.

    > >
    > > Why do you say this? Is WinGetLastError() or WinGetErrorInfo() not
    > > returning data you can use? FWIW, my experience is that this that these
    > > report appropriate results for CM_INSERTRECORD failures.
    > >

    > No, WinGetLastError(anchor) does not because I do not have the correct
    > anchor block. It always returns 0, no error, since the error occurs in a
    > thread the did not create the window.


    This discussion seems to be going all over the place without actually
    getting anywhere. Steve's earlier comment that the problem may be
    elsewhere seems very likely.

    First, you should be aware that when you *send* a message to a window
    created by another thread, the system performs a context switch to that
    thread. The msg is then handled on the window's thread, not the sender's.
    Therefore, any error that occurs while inserting records _should_ be noted
    in the anchor block associated with the target window. If you're getting
    no error using that HAB, then no error occurred on its thread.

    One reason could be that the operation never even happened. In order to
    send a message, the sending thread must have a message queue. Did you
    call WinInitialize() & WinCreateMsgQueue() on that secondary thread?
    If not, that could be why you get a 0 return when you call WinSendMsg(),
    i.e. the call itself is failing.



    --
    == == almost usable email address: Rich AT E-vertise.Com == ==
    __________________________________________________ _________________
    |
    | DragText v3.9 with NLS support
    Rich Walsh | A Distinctly Different Desktop Enhancement
    Ft Myers, FL | http://e-vertise.com/dragtext/
    __________________________________________________ _________________


  13. Re: WinGetLastError()

    On Sun, 13 Jul 2008 23:30:19 -0700, Jim Moe
    wrote:

    > Since WinGetLastError() requires a valid anchor block, getting the
    > anchor block value for the current thread should be easy. Not so far.


    It's not difficult. You save the return from from WinInitialize()... in thread
    local storage, or otherwise... or fabricate it as described previously.

  14. Re: WinGetLastError()

    On 07/14/08 10:28 am, Rich Walsh wrote:
    >
    > First, you should be aware that when you *send* a message to a window
    > created by another thread, the system performs a context switch to that
    > thread. The msg is then handled on the window's thread, not the sender's.
    > Therefore, any error that occurs while inserting records _should_ be noted
    > in the anchor block associated with the target window. If you're getting
    > no error using that HAB, then no error occurred on its thread.
    >
    > One reason could be that the operation never even happened. In order to
    > send a message, the sending thread must have a message queue. Did you
    > call WinInitialize() & WinCreateMsgQueue() on that secondary thread?
    > If not, that could be why you get a 0 return when you call WinSendMsg(),
    > i.e. the call itself is failing.
    >

    Yes, all threads start by creating an anchor block and a message queue.
    From the other responses it would seem WinGetLastError() ignores its
    argument and returns whatever error last occurred in the current thread.
    If what you say is true about switching threads to update the container
    (I have no reason to doubt it), there is no way to determine what error
    occurred since it happened in another thread.
    Does WinGetErrorInfo() use its argument? Or does it also ignore it?

    --
    jmm (hyphen) list (at) sohnen-moe (dot) com
    (Remove .AXSPAMGN for email)

  15. Re: WinGetLastError()

    In , on 07/14/2008
    at 11:18 AM, Jim Moe said:

    Hi,

    > From the other responses it would seem WinGetLastError() ignores its
    >argument and returns whatever error last occurred in the current thread.
    > If what you say is true about switching threads to update the container
    >(I have no reason to doubt it), there is no way to determine what error
    >occurred since it happened in another thread.


    I would not be so quick to say this. While the PM docs are not perfect,
    they do say


    In multiple thread applications where there are multiple anchor blocks,
    errors are stored in the anchor block created by the WinInitialize
    function of the thread invoking a call. The last error for the process and
    thread on which this function call is made will be returned.


    I read this as saying PM is smart enough to reflect the error to the
    calling thread's anchor block regardless of context switches. This
    matches my experience with cross thread calls.

    > Does WinGetErrorInfo() use its argument? Or does it also ignore it?


    You will have to experiment to know for sure.

    Based on what other's say, it appears that is does not need to use the
    parameter.

    Perhaps, it's time for you to post your failing code so others can
    comment.

    Steven

    --
    --------------------------------------------------------------------------------------------
    Steven Levine MR2/ICE 3.00 beta 11pre14 #10183
    eCS/Warp/DIY/14.103a_W4 www.scoug.com irc.ca.webbnet.info #scoug (Wed 7pm PST)
    --------------------------------------------------------------------------------------------


  16. Re: WinGetLastError()

    On 07/13/08 12:41 pm, Jim Moe wrote:
    >
    > I have a function to load a container in details view that wraps the
    > CM_INSERTRECORDARRAY message. If WinSendMsg() returns 0, it indicates the
    > request failed for some reason and WinGetLastError() has the reason.
    >

    It would seem that Steven's take on the documentation is correct. A
    return value of zero (0) for CM_INSERTRECORDARRAY does not necessarily
    indicate an error.
    The PM documentation for CM_INSERTRECORDARRAY is very ambiguous,
    misleading even. The return value is the

    "Number of RECORDCORE structures in the root level of the container:
    "0 - No RECORDCORE structures were inserted. The WinGetLastError()
    function may return the following errors: ...
    "Other - The number of RECORDCORE structures in the container."

    I interpreted this to mean that the function would return the number of
    records extant in the container. If there were 5, the return value is 5
    plus any new records added. Hah!
    Apparently it is the number of records actually inserted. If 5 records
    are presented for insertion and all 5 are already there, 0 is returned.

    Nevertheless, I still have no certainty that a return value of 0 from
    WinGetLastError() is correct.
    I tried adding CCS_VERIFYPOINTERS to the container style when creating
    the control. This should have resulted in a
    PMERR_RECORD_CURRENTLY_INSERTED value from WinGetLastError() when
    duplicate values were requested for insertion. It still returned 0, no error.
    At this point my option is to simply ignore the return value since it is
    useless. All that matters is that the records show in the container.

    --
    jmm (hyphen) list (at) sohnen-moe (dot) com
    (Remove .AXSPAMGN for email)

  17. Re: WinGetLastError()

    In , on 07/17/2008
    at 08:47 AM, Jim Moe said:

    Hi,

    > The PM documentation for CM_INSERTRECORDARRAY is very ambiguous,
    >misleading even.


    That's why this list exists. :-)

    > Apparently it is the number of records actually inserted.


    I suspected this, but did not what to say anything specific without
    testing.

    >If 5 records
    >are presented for insertion and all 5 are already there, 0 is returned.


    I didn't know this. Since records can be shared across containers, I've
    always gone under the assumption that the same record could exist multiple
    times in a single container, although I've never had a reason to verify
    this. I do see where the docs describe the behavior you are expecting.

    > I tried adding CCS_VERIFYPOINTERS to the container style when creating
    >the control. This should have resulted in a
    >PMERR_RECORD_CURRENTLY_INSERTED value from WinGetLastError() when
    >duplicate values were requested for insertion.


    My expectation was that PMERR_RECORD_CURRENTLY_INSERTED occurred if you
    attempted to free a record that was still in use based on a reference
    count maintained by PM.

    >It still returned 0


    Well, the returned count does allow you to do useful santity checks the
    results.

    Steven

    --
    --------------------------------------------------------------------------------------------
    Steven Levine MR2/ICE 3.00 beta 11pre14 #10183
    eCS/Warp/DIY/14.103a_W4 www.scoug.com irc.ca.webbnet.info #scoug (Wed 7pm PST)
    --------------------------------------------------------------------------------------------


  18. Re: WinGetLastError()

    Alex Taylor wrote:
    > On Mon, 14 Jul 2008 00:42:14 UTC, Jim Moe
    > wrote:
    >
    >>>> My problem is how to *get* the appropriate anchor block.
    >>> As far as I know, WinGetLastError does not use the hab at all. Simply
    >>> call WinGetLastError(NULL). Of course, this is unspecified behavior. But
    >>> it is very likely that no one is going to rewrite the PM.
    >>>

    >> Should that be WinGetLastError(NULLHANDLE)?
    >> This would imply I have no hope of ever getting the error value that
    >> occurred in a thread.

    >
    > When I need to pass a HAB and I don't happen to have it in scope, I just
    > specify 1. I'm pretty certain it's not used anyway.


    IBM too. See PM reference to WinInitialize:


    "The operating system does not generally use the information supplied by
    the hab parameter to its calls; instead, it deduces it from the identity
    of the thread that is making the call. Thus an OS/2 application is not
    required to supply any particular value as the hab parameter. However,
    in order to be portable to other environments, an application must
    provide the hab, that is returned by the WinInitialize function of the
    thread, to any OS/2 function that requires it."


    Marcel

+ Reply to Thread