Announcement

Collapse
No announcement yet.

Error Handling Problems

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Error Handling Problems

    I FINALLY had some time to work on some of my ongoing attempt at error handling routines and have run into a few problems that I just cant seem to solve.

    1.) SetError and GetLastError - If I set an error and then the next line in the same function is GetLastError then all is fine, but if that next line is a Macro, or a call to a function then GetLastError returns 0 so from the docs where is says
    You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data. That is because some functions call SetLastError(0) when they succeed, wiping out the error code set by the most recently failed function.
    Is this what is happening when I leave my function where it is set (even momentarily) to call a function or Macro, and internally the value is being re-set????

    2.) This is a bit trickier and some people don't like the concept, but PB suppt says its perfectly fine, so I will run with it. What I am doing is for logging purposes is the ability to log the API function called and the responses without adding extra lines of code to purposely say "I called this with these parameters" but more let macros wrap the whole thing so something like
    Code:
    MacroReturnedValue = CallMacro(CallFunc(GetLastError()))
    can break it all down on its own and write to a file if I want it to.

    Anyways things work great so far, until I hit a function that a parameter is declared "AS ANY" or more specifically if I declare
    Code:
         DECLARE FUNCTION BackupRead ALIAS "BackupRead" (BYVAL hFile AS DWORD, lpBuffer AS BYTE, BYVAL nNumberOfBytesToRead AS LONG, lpNumberOfBytesRead AS LONG, BYVAL bAbort AS LONG, BYVAL bProcessSecurity AS LONG, lpContext AS ANY) AS LONG
    is legal but using it creates a compiler error if I have a wrapper called
    Code:
    FUNCTION BackupRead ALIAS "BackupRead" (BYVAL hFile AS DWORD, lpBuffer AS BYTE, BYVAL nNumberOfBytesToRead AS LONG, lpNumberOfBytesRead AS LONG, BYVAL bAbort AS LONG, BYVAL bProcessSecurity AS LONG, lpContext AS ANY) AS LONG
    
    End Function
    My only choice so far is to rename the wrapping function and change the variable to a variant? like
    Code:
         FUNCTION PbBackupRead ALIAS "BackupRead" (BYVAL hFile AS DWORD, lpBuffer AS BYTE, BYVAL nNumberOfBytesToRead AS LONG, lpNumberOfBytesRead AS LONG, BYVAL bAbort AS LONG, BYVAL bProcessSecurity AS LONG, lpContext AS VARIANT) AS LONG
              DeclareFunctionSubParams
              REDIM FunctionParams(6)
              FunctionParams(0) = hFile
              FunctionParams(1) = lpBuffer
              FunctionParams(2) = nNumberOfBytesToRead
              FunctionParams(3) = lpNumberOfBytesRead
              FunctionParams(4) = bAbort
              FunctionParams(5) = bProcessSecurity
              FunctionParams(6) = lpContext
              LookUpFunctionSubParams
              CALL DWORD RealFunction USING BackupRead (BYVAL hFile, lpBuffer, BYVAL nNumberOfBytesToRead, lpNumberOfBytesRead, BYVAL bAbort, BYVAL bProcessSecurity , lpContext) TO RealFunctionReply                 'Call Function
              FUNCTION = RealFunctionReply                                                         'Return Reply
         END FUNCTION
    I think its because the docs say
    Using ANY disables type checking for a given parameter, and passes the full 32-bit address of the variable passed on the stack. Since the internal format of variables differ greatly by type, you must use caution to be absolutely certain your code knows the data type in each invocation. Normally, a second parameter is used to specify the actual type of the ANY parameter.
    But I found nothing that says I can use "AS ANY" in a declare, but not in the actual function as a parameter?

    If I change the ANY to a Variant in the actual function then I get a error that the declare does not match the actual wrapper. and if I keep the wrapper as ANY then I get another compiler error, so I ask, is the only way around to rename the function and use VARIANT where-ever I see "AS ANY" and then handle it????
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

  • #2
    Some intrinsic functions or statements containing expressions compile into one or more WinAPI calls... so on return GetLastError() may not be what you think it is.

    Most common example we see here is

    Code:
    DECLARE FUNCTION     Foo LIB 'User32.DLL"   ALIAS ...(sz AS ASCII)   <<< any WinAPI function
    
    ....
     CALL         Foo ("Hello World") 
     Z              = GetLastError()
    At least 999,999 times out of 1,000,000, Z will be zero, since the LAST winapi call was the deallocation of the temporary string used to hold "Hello World"

    But I found nothing that says I can use "AS ANY" in a declare, but not in the actual function as a parameter?
    Of course not. It would be impossible to compile it.

    Code:
     
    FUNCTION FOO  (X AS ANY)  As something
    Um, how much space does X take on the stack? If BYREF, the answer is four bytes, but keep reading....

    Great, it's byref. Now when it's time to do something with X, when we find the data at that address, is it to be interpreted as a 32-bit signed integer? an 8-byte IEEE DOUBLE? A 16 bit VARIANT (VARIANTAPI structure in PB-speak) with its own additional pointers in it?

    A procedure with an 'ANY' parameter cannot be compiled. It can be CALLed, but only because in a DECLARE statement "ANY" means "Pass the address of whatever variable appears in this parameter position at the point of call."


    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Not only is not the only way, but passing a pointer to a VARIANT when the function is expecting another kind of variable is plainly wrong.

      If you have problems with the ANY parameter, then add complementary declarations that suit your needs, e.g.

      Code:
      DECLARE FUNCTION BackupRead2 ALIAS "BackupRead" (BYVAL hFile AS DWORD, lpBuffer AS BYTE, BYVAL nNumberOfBytesToRead AS LONG, lpNumberOfBytesRead AS LONG, BYVAL bAbort AS LONG, BYVAL bProcessSecurity AS LONG, lpContext AS DWORD) AS LONG
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        If you have problems with the ANY parameter, then add complementary declarations that suit your needs, e.g.
        Requires at least 8x, maybe 9x, because prior versions did not support shared aliases.
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment

        Working...
        X