Announcement

Collapse
No announcement yet.

Longs vs Dword vs %INVALID_HANDLE_VALUE

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

  • Michael Mattias
    replied
    My bad, should be "NFS" not "NSF," as in New Feature Suggestion.

    I must have typed that incorrectly because I was talking with a guy in Louisville earlier today and the subject of "NSF" as in (N)ational (S)tandard (F)ormat came up.

    MCM

    Leave a comment:


  • Cliff Nichols
    replied
    ok calm down MCM.... I wasn't trying to start a holy-war with this one. Just trying to figure things out....and the more I figured out, the more I tried to show by "Worst Case Scenario" and how even if it was "allowed" for me to use invalid values, that Windows did not do some sort of GPF. At least then I would have maybe noticed sooner that code I did in the past and through the future may have been wrong in the 1st place.

    In this case I have to check all my code and calculations and determine if I used a Long when I should have used a Dword, or vice-versa?

    I am sure the reason I never caught this mistake before is, lets face it, how often do you come across a variable meant to be a whole value that did not come up somewhere between 0 and 2,147,483,647


    Not to get confused....what is a NSF? (I know it has to do with requesting an option or a fix, but dunno what NSF stands for?)

    Anyways, I now know what started out as what I thought was 1 problem, was really 2 separate problems that "cropped up" at the same time. I will go back and clean up my mistakes of Long vs Dword problem.

    I know I have another problem (well not problem because I know why it crops up, and maybe a solution) that will remain once the code is cleaned up. But wonder if best to post here? or a new question so as not to add confusion and someone still think its a Long vs Dword debate?

    Leave a comment:


  • Michael Mattias
    replied
    >see how things get worse, if you do not know you are plugging illegal values in

    Duh, that's why I have submitted a NSF for an "#OVERFLOW ON" option!!!!!

    Sheesh.

    Leave a comment:


  • Cliff Nichols
    replied
    MCM it gets even funnier

    Just for you, try running my example in the debugger. Both animated and Run until break will give me "-2147483648" for both the gInvalidHandleLong and the lInvalidHandleLong

    However just "Compile and Run" I get "-2147483648" for gInvalidHandleLong but I get "-1" for the lInvalidHandleLong

    Sheesh, Cliff, don't tell me you didn't recognize you have made the "rookiest" of rookie mistakes: making assignments which overflow the destination variables.
    nope....was just proving a point. I had "ASSUMED" that somehow the compiler was handling things behind the scenes that if I plugged a Negative number into a DWORD (which breaks the rules), or a value larger than a Long could handle (again breaks the rules) because I get no error.

    And on TOP of that, not only do I get answers...I (For lack of a better word) "Almost" get the right answer.

    If you consider "Almost" a working Overflow error.

    Anyways now you see one of my problems that I did not even notice until looking for something in the Win32Api.inc and noticed that note.

    Give the debug a run and you will see how things get worse, if you do not know you are plugging illegal values in.

    Leave a comment:


  • Michael Mattias
    replied
    >MCM....you will LOVE this one then for ammo about Globals vs Locals

    Actually, I will love it for ammo re my request for overflow checking.

    Sheesh, Cliff, don't tell me you didn't recognize you have made the "rookiest" of rookie mistakes: making assignments which overflow the destination variables.

    (You can't fit "minus anything" into a DWORD nor can you fit 4,294,967,295 into a LONG).

    Not to mention not explicitly casting your inline numeric literals. Back to...
    Code:
    10 PRINT "HELLO, WORLD"
    20 END
    30 ^C
    Ready> RUN
    ... for you!

    MCM

    Leave a comment:


  • Cliff Nichols
    replied
    MCM....you will LOVE this one then for ammo about Globals vs Locals

    I get the concept of "Its not the data, its how you are looking at it" but can anyone then explain why a global and a local would come up different values? (see below)

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "WIN32API.INC"
    '***************************************************
    '*** %INVALID_HANDLE_VALUE as Dword = 4294967295 ***
    '*** %INVALID_HANDLE_VALUE as Long = -1          ***
    '***************************************************
    GLOBAL gInvalidHandleDword AS DWORD                         '<--- Correct value returns
    GLOBAL gInvalidHandleLong AS LONG                           '<--- Incorrect value returns
    
    FUNCTION PBMAIN () AS LONG
        LOCAL lInvalidHandleDword AS DWORD                      '<--- Correct value returns
        LOCAL lInvalidHandleLong AS LONG                        '<--- Correct value returns
    '*** Plug in LONG definition of %INVALID_HANDLE_VALUE into DWORD variables
        gInvalidHandleDword = -1
        lInvalidHandleDword = -1
    '*** Plug in DWORD definition of %INVALID_HANDLE_VALUE into LONG variables
        gInvalidHandleLong = 4294967295
        lInvalidHandleLong = 4294967295
    MSGBOX FUNCNAME$ + $CR + $CR _
                        + "Global Invalid Dword with -1 = " + STR$(gInvalidHandleDword) + $CR _
                        + "Local Invalid Dword with -1 = " + STR$(lInvalidHandleDword) + $CR + $CR _
                        + "Global Invalid Long with 4294967295 = " + STR$(gInvalidHandleLong) + $CR _
                        + "Local Invalid Long with 4294967295 = " + STR$(lInvalidHandleLong)
    END FUNCTION
    I get the idea that plugging in the wrong value is returning the lowest possible number for a LONG, but what I do not get is why wouldn't the local variable do the same?
    Last edited by Cliff Nichols; 7 Dec 2007, 01:27 PM.

    Leave a comment:


  • Michael Mattias
    replied
    you will see if I declare my variable as Long, then invalid handle is -1 and if I declare my variable as DWORD then invalid value = 4294967295
    Hell, if you were to declare it as a STRING the value would be REPEAT$(CHR$(255), 4)

    Actually the value never changes at ALL. What you are reporting is how you are currently looking at the same four bytes returned by the WinAPI.

    MCM

    Leave a comment:


  • Cliff Nichols
    replied
    Interesting Test

    Here is an interesting lil test. I was able to determine why sometimes I got -1 for %INVALID_HANDLE_VALUE and why sometimes it was 4294967295. It was because sometimes I had the variable declared as Long, sometimes as DWORD. (As you can test by commenting and uncommenting those lines in the code below)
    1. If I close a thread that purposely has an invalid thread handle, then yes the program will throw up an exception (like the documentation states) but as an exe, I do not see the exception, and when I close the program, it does remove from the list of running processes, but if I recompile and run again I get the "Destination file in use" error. However the process is not seen by "Windows Task Manager" nor by SysInternals "Process Viewer" (yep I am watching both as I run and close)
    2. The only thing that will truly release whatever memory location that is not letting go, is to reboot the computer


    Anyways as for the demo of Long vs Dword (using PB Win 8.03 Win32Api.inc) you will see if I declare my variable as Long, then invalid handle is -1 and if I declare my variable as DWORD then invalid value = 4294967295

    Code:
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    %IDD_DIALOG1 =  101                                                             'Demo Dialog
    %IDC_BUTTON2 = 1002                                                             'Loop with thread
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()                                     'Callback function for Windows Messages
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG                    'Create and show the demo
    
    DECLARE FUNCTION ThreadLoopDemo(BYVAL x AS LONG)AS LONG                         'Create Threaded Demo
    DECLARE FUNCTION LoopDemo()AS LONG                                              'Function called both by Thread and without a thread
    DECLARE FUNCTION CreateThreadLoop()AS LONG                                      'Create Thread
    DECLARE FUNCTION DestroyThreadLoop()AS LONG                                     'Destroy Thread and Wait till Thread is Dead
    '------------------------------------------------------------------------------
    
    
    '------------------------------------------------------------------------------
    '   ** Globals **
    '------------------------------------------------------------------------------
    GLOBAL hDlg  AS DWORD                                                           'Dialog
    GLOBAL EscapeLoop AS LONG                                                       'Flag to escape loop
    GLOBAL ThreadLoop AS LONG                                                       'Thread to be closed if open
    'GLOBAL ThreadLoop AS DWORD                                                       'Thread to be closed if open
    GLOBAL FakeThreadLoop AS LONG                                                   'Bogus number for showing demo
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
         ShowDIALOG1 %HWND_DESKTOP                                                  'Start Callback function to show dialog
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
         SELECT CASE AS LONG CBMSG                                                  'Check what message was sent
              CASE %WM_COMMAND                                                      'Process control notifications
                   SELECT CASE AS LONG CBCTL
                        CASE %IDC_BUTTON2                                           'Loop with thread
                             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN         '<--- Not sure why CBCTLMSG = 1 is used?
                                  DestroyThreadLoop                                 'Destroy Thread if it already exists
                                  EscapeLoop = %FALSE                               'Set Flag to false in case was already set to true
                                  CreateThreadLoop                                  'Create Thread (returns Immediately) which then starts the loop
                             END IF
                   END SELECT
              CASE %WM_CLOSE
                   DestroyThreadLoop                                                'Destroy Thread if it already exists
                   EXIT FUNCTION
         END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
         LOCAL lRslt AS LONG
         DIALOG NEW hParent, "Blocking Thread Test", 70, 70, 200, 79, %WS_POPUP OR _          'PbForms create dialog with common properties
                             %WS_BORDER OR %WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
                             %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
                             %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                             %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
                             %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
         CONTROL ADD BUTTON, hDlg, %IDC_BUTTON2, "Global Threaded Flag", 95, 15, 100, 20
         DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt                                'Show Modal (no message pump needed)
         FUNCTION = lRslt
    END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION ThreadLoopDemo(BYVAL x AS LONG)AS LONG                                           'Thread Wrapper Function
         LoopDemo                                                                             'Call Loop Demo within this thread
    END FUNCTION
    
    FUNCTION LoopDemo()AS LONG                                                                'Demo Function (will not die until flag is seen to escape loop
    ''*************************************************************************************************
    ''*** Left in just for Demo purposes although it does nothing while commented
    ''*************************************************************************************************
    '     DO
    '          IF EscapeLoop = %True THEN EXIT DO                                              'Check if Flag is set to escape?
    '     LOOP
    'MSGBOX FUNCNAME$ + $CR + "Escaped the Loop with EscapeLoop = " + STR$(EscapeLoop)         'For Display purposes of demo
    END FUNCTION
    
    FUNCTION CreateThreadLoop()AS LONG                                                        'Create a thread so rest of program is not stalled waiting for a function to finish
         LOCAL lResult AS LONG
         LOCAL ErrorBuff AS ASCIIZ * %MAX_PATH
         NewThread = FREEFILE
         SELECT CASE ThreadLoop
              CASE %INVALID_HANDLE_VALUE, 4294967295, -1                 '%INVALID_HANDLE_VALUE used to be -1 and re-used as (&HFFFFFFFF??? = 4,294,967,295)
                   THREAD CREATE ThreadLoopDemo(1) TO ThreadLoop         '<--- Thread handle is invalid so its ok to create a new one
              CASE 0
                   THREAD CREATE ThreadLoopDemo(1) TO ThreadLoop         '<--- Thread handle is invalid so its ok to create a new one
              CASE ELSE
                   'Do nothing because a thread handle already exists
         END SELECT
         lResult = GetLastError()           'Check for the error
         FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, lResult, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL  'Format the message
    MSGBOX FUNCNAME$ + $CR + "Thread Value = " + STR$(ThreadLoop) + $CR + ErrorBuff
         FUNCTION = ThreadLoop                                                                '<--- Return the value of the Thread Handle (0 if Thread failed to start)
    END FUNCTION
    
    FUNCTION DestroyThreadLoop()AS LONG                                                       'Destroy thread so not inadvertantly left running when parent process closes
         LOCAL TempThread AS LONG
         LOCAL lResult AS LONG
         LOCAL ErrorBuff AS ASCIIZ * %MAX_PATH
         TempThread = ThreadLoop
         SELECT CASE ThreadLoop
              CASE %INVALID_HANDLE_VALUE, 4294967295, -1                 '%INVALID_HANDLE_VALUE used to be -1 and re-used as (&HFFFFFFFF??? = 4,294,967,295)
                   'Do NOTHING because closing an invalid handle raises an exception
              CASE 0
                   'Do NOTHING because already closed
              CASE ELSE
                   THREAD CLOSE ThreadLoop TO ThreadLoop
                   SELECT CASE ThreadLoop
                        CASE %INVALID_HANDLE_VALUE, 4294967295, -1                 '%INVALID_HANDLE_VALUE used to be -1 and re-used as (&HFFFFFFFF??? = 4,294,967,295)
                             'Do NOTHING because Thread is closed, and handle is invalid
                        CASE 0
                            'Do NOTHING because already closed
                        CASE ELSE
                             WaitForSingleObject ThreadLoop, %INFINITE                        'Thread closed but handle not invalidated, so wait till thread done
                   END SELECT
         END SELECT
         lResult = GetLastError()           'Check for the error
         FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, lResult, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL  'Format the message
    MSGBOX "%INVALID_HANDLE_VALUE DWORD= " + STR$(%INVALID_HANDLE_VALUE) + $CR + $CR _
              + "DWORD should Read as 4,294,967,295" + $TAB + $TAB + "LONG should Read as -1" + $CR + $CR _
              + "ThreadLoop before close = " + STR$(TempThread) + $TAB + $TAB + "ThreadLoop after close = " + STR$(ThreadLoop)
         FUNCTION = ThreadLoop
    END FUNCTION

    Leave a comment:


  • Robert DeBolt
    replied
    Originally posted by Cliff Nichols View Post
    Anyways, somewhere in here I know I have seen a function written that either converts DWORD to Long (or Vice versa), or Signed to Unsigned (or Vice versa) but I can not find it. I have been searching all day for any combination of these key words but found nothing yet.

    Anyone know what these Function(s) are called? or where to find them? or who wrote them? (Gut feeling tells me either MCM or Pierre, but found nothing looking for their posts either)
    From the Help file:
    <H1>CBYT, CCUR, CCUX, CDBL, CDWD, CEXT, CINT, CLNG, CQUD, CSNG, and CWRD functions

    These conversion functions are rarely needed as PowerBASIC automatically performs any necessary conversions when executing an assignment statement or passing parameters.
    </H1>

    Leave a comment:


  • Michael Mattias
    replied
    The change from unsigned to signed comparisons for IF/SELECT CASE in 7x was an undocumented "enhancement." SELECT CASE AS LONG added in 7x does 32-bit comparisons.

    It really was a problem only if you decided NOT to change your Win32 header files when you installed 7x. Like I didn't.

    Or if you read the doc and made everything possible a LONG integer for efficiency, then found that some of the stuff in Win32API.INC was changed to DWORD and the comparisons were now signed. Like I did.

    But anyone who started with 7x and that set of WinAPI headers would never know the difference.. except when trying to use code from Source Code Forum posted pre-7X.

    Heck, I still have problems using code posted SINCE 7x, since some of my WinAPI header files are still originals with the fixes I made. (The WinAPI headers are now stable and error-free. 'Twas not always thus). (Big time).

    Essentially PowerBASIC Inc discriminates against us old farts by making us change our ways or do something extra whilst the newbies just 'plug and play.'

    MCM

    Leave a comment:


  • Cliff Nichols
    replied
    "IF Myvar THEN" works the same regardless if MyVar is a LONG or DWORD. It works as though it were "IF ISTRUE(myvar) THEN..."
    In the "TRUE-est" sense of the word, you are correct. TRUE is defined as non-zero while FALSE is defined as zero. So it is my fault for not accounting for values that are "Non-Zero" but really mean "I can not use it". (Bad habit of being used to "True = 1 and False = 0" and not the true meaning of the values)

    With PB/DLL 6x or earlier... do nothing special, both IF and SELECT CASE do 32 bit comparisons
    Over the years I have code written in PB/DLL 6x and up. And usually have no problem between versions (or if I have a problem, the compiler will not let me compile until I fix the problem).

    This all started from my working on some snippet code to demonstrate an idea, when I found this problem and still not sure how to phrase the question or even supply a test to show what I "THINK" I am seeing. So for a theoretical proof of concept think of it this way.

    Scenario 1:
    1. Older compiler Win32Api.inc declared variables (and some equates) as LONG
    2. My Variables used LONG, so I was good as long as the return value from a function was LONG. If it was DWORD then I was good as long as the value was between 0 and 2,147,483,647 if not then I was in trouble


    Scenario 2:
    1. Newer compiler Win32Api.inc declared variables (and some equates) as DWORD
    2. My Variables used LONG, so I am just asking for it if the returned value is a negative number (DWORD is defined as unsigned integers with a range of 0 to 4,294,967,295)


    Scenario 3:
    1. Either New or Old if I am expecting %INVALID_HANDLE_VALUE (And although not tested, I am sure the compiler will not let me compile the wrong version of "Win32Api.inc")
    2. If My Variable is declared as Long, and the (%INVALID_HANDLE_VALUE = 4294967295 = DWORD) I am in trouble
    3. If My Variable is declared as DWORD, and the (%INVALID_HANDLE_VALUE = -1 = LONG) I am in trouble


    Of course it all makes sense when you think about it...they all break the rules for the intended scenario. Some are more forgiving than others, but rules are rules.

    Kinda like Math, I can add 1cm + 1 mm + 1 inch + 1 yard + 1 kilometer but unless I take into account the "Units" then I get 4...but 4 "WHAT?"

    Anyways the more I think outloud the more I think the snippet I was looking for had something to do with changing Signed values to Unsigned values and back again

    Leave a comment:


  • Michael Mattias
    replied
    "IF Myvar THEN" works the same regardless if MyVar is a LONG or DWORD. It works as though it were "IF ISTRUE(myvar) THEN..."

    As for comparing PB LONGs with PB DWORDs....

    With PB/DLL 6x or earlier... do nothing special, both IF and SELECT CASE do 32 bit comparisons

    But since you probably are running a version later than 6x (version not shown), this is a MACRO I use (created by Tom Hanlin)
    Code:
    Macro  EQ32 (a, b) =  BITS???(a) = BITS???(b)
    
    ...
      hFile = CreateFile (.......
      IF eq32 (hFile, %INVALID_HANDLE_VALUE) THEN
       '   does not care about casting of either hFile or INVALID_HANDLE VALUE
      .....
    MCM

    Leave a comment:


  • Cliff Nichols
    started a topic Longs vs Dword vs %INVALID_HANDLE_VALUE

    Longs vs Dword vs %INVALID_HANDLE_VALUE

    I believe I found a bug in my code either from my own math or my declaring something incorrectly (like declared as long when it should be declared as Dword)

    One example from Win32Api.inc
    Code:
    ' *****************************************************************************
    ' * NOTE that many variables (and some equates) that were previously declared *
    ' * AS LONG are now correctly defined AS DWORD, which may cause compatibility *
    ' * issues with existing programs. In particular, %INVALID_HANDLE_VALUE is    *
    ' * &HFFFFFFFF??? rather than -1& now.                                        *
    ' *****************************************************************************
    And from my initial tests, sometimes I get a -1 and sometimes I get 4294967295 so I need to do some more testing and change my routines of
    Code:
    IF MyVar then .....
    because I was expecting 0 if it did not exist, not either of the values above or better known as %INVALID_HANDLE_VALUE

    Anyways, somewhere in here I know I have seen a function written that either converts DWORD to Long (or Vice versa), or Signed to Unsigned (or Vice versa) but I can not find it. I have been searching all day for any combination of these key words but found nothing yet.

    Anyone know what these Function(s) are called? or where to find them? or who wrote them? (Gut feeling tells me either MCM or Pierre, but found nothing looking for their posts either)
Working...
X