Announcement

Collapse
No announcement yet.

She compiles fine but refuses to work like her VB mother!

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

  • She compiles fine but refuses to work like her VB mother!

    I just ported some VB source over to PB, its compiling and executing ok, but failing when it starts its main call, and Ive got no idea why, its got me buggered. Basically the code just uses NetSessionEnum to report who is connected to your computer over NetBIOS (eg. through Explorer, etc)
    Can anybody spot the bug that Ive seemingly introduced?
    Original VB source: http://www.mvps.org/vbnet/code/netwo...essionenum.htm

    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
    %SESS_GUEST = &H1         'session logged on as a guest
    %SESS_NOENCRYPTION = &H2  'session not using encryption
    %NERR_SUCCESS = 0&
    %MAX_PREFERRED_LENGTH = -1
    %ERROR_MORE_DATA = 234&
    %LB_SETTABSTOPS = &H192
     
    Type SESSION_INFO_502
      sesi502_cname As Long
      sesi502_username As Long
      sesi502_num_open As Long
      sesi502_time As Long
      sesi502_idle_time As Long
      sesi502_user_flags As Long
      sesi502_cltype_name As Long
      sesi502_transport As Long
    End Type
     
    Declare Function NetSessionEnum Lib "Netapi32.dll" Alias "NetSessionEnum" _
      (ByVal servername As Long, _
       ByVal UncClientName As Long, _
       ByVal username As Long, _
       ByVal level As Long, _
       bufptr As Long, _
       ByVal prefmaxlen As Long, _
       entriesread As Long, _
       totalentries As Long, _
       resume_handle As Long) As Long
     
    Declare Function NetApiBufferFree Lib "netapi32.dll" ALIAS "NetApiBufferFree" _
       (ByVal Buffer As Long) As Long
     
    Type SESSION_INFO_50
      sesi50_cname As Long
      sesi50_username As Long
      sesi50_key As Long
      sesi50_num_conns As Long
      sesi50_num_opens As Long
      sesi50_time As Long
      sesi50_idle_time As Long
      sesi50_protocol As Long
      pad1 As Long
    End Type
     
    Declare Function NetSessionEnum9x Lib "Netapi32.dll" _
       Alias "NetSessionEnum9x" _
      (ByVal pszServer As Long, _
       ByVal level As Long, _
       bufptr As Long, _
       cbBuffer As Long, _
       entriesread As Long, _
       totalentries As Long) As Long
     
    Function GetSessionUserType(ByVal dwSessionType As Long) As String
       Select Case dwSessionType
          Case %SESS_GUEST:        GetSessionUserType = "Guest"
          Case %SESS_NOENCRYPTION: GetSessionUserType = "No encryption"
          Case Else:               GetSessionUserType = ""
       End Select
    End Function
                          
    FUNCTION PBMAIN() AS LONG
       Dim bufptr          As Long  'output
       Dim dwServer        As Long  'pointer to the server
       Dim dwEntriesread   As Long  'out
       Dim dwTotalentries  As Long  'out
       Dim dwResumehandle  As Long  'out
       Dim success         As Long
       Dim nStructSize     As Long
       Dim cnt             As Long
       Dim usrname         As String
       Dim bServer         As String
       Dim si502           As SESSION_INFO_502
       bServer = "\\" & Environ$("COMPUTERNAME") & CHR$(0)
       dwServer = StrPtr(bServer)
       success = NetSessionEnum(dwServer, _
                                0&, _
                                0&, _
                                502, _
                                bufptr, _
                                -1, _
                                dwEntriesread, _
                                dwTotalentries, _
                                dwResumehandle)
       Msgbox "Success=" & STR$(success) & $CRLF & "TotalEntries=" & STR$(dwTotalEntries) & $CRLF & "EntriesRead=" & STR$(dwEntriesRead)
       If success = %NERR_SUCCESS And _
          success <> %ERROR_MORE_DATA Then
          nStructSize = sizeof(si502)
          For cnt = 0 To dwEntriesread - 1
           Msgbox "dwEntries=" & STR$(dwEntriesRead)
           MoveMemory _
             varptr(si502), _
             byval bufptr + (nStructSize * cnt), _
             nStructSize
            usrname = str$(si502.sesi502_username)
            If Len(usrname) > 0 Then
                Msgbox usrname & ", " & _
                              str$(si502.sesi502_cname) & ", " & _
                              str$(si502.sesi502_time \ 60) & ", " & _
                              str$(si502.sesi502_idle_time \ 60) & ", " & _
                              str$(si502.sesi502_num_open) & ", " & _
                              str$(si502.sesi502_cltype_name)
    
    
             End If
          Next
       End If
       Call NetApiBufferFree(bufptr)
    End Function

    [This message has been edited by Wayne Diamond (edited August 09, 2001).]
    -

  • #2
    It's subtle... VB uses UNICODE internally, and NetSessioEnum needs Unicode for the server name.

    I've modified your code so that the first call should return 'success'. I'll leave the rest to you to deal with!

    Also note that I revamped your DECLARE to make it easier to use with ASCIIZ strings, although it is difficult to deal with Unicode strings stored in ASCIIZ with native Basic statements because of the embedded NUL's. However, the API deals with them fine, so no problemo!

    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
    %NERR_SUCCESS = 0&
    
    TYPE SESSION_INFO_502
      sesi502_cname AS LONG
      sesi502_username AS LONG
      sesi502_num_open AS LONG
      sesi502_time AS LONG
      sesi502_idle_time AS LONG
      sesi502_user_flags AS LONG
      sesi502_cltype_name AS LONG
      sesi502_transport AS LONG
    END TYPE
    
    DECLARE FUNCTION NetSessionEnum LIB "Netapi32.dll" ALIAS "NetSessionEnum" _
      (servername AS ASCIIZ, _
       UncClientName AS ASCIIZ, _
       username AS ASCIIZ, _
       BYVAL level AS LONG, _
       bufptr AS LONG, _
       BYVAL prefmaxlen AS LONG, _
       entriesread AS LONG, _
       totalentries AS LONG, _
       resume_handle AS LONG) AS LONG
    
    DECLARE FUNCTION NetApiBufferFree LIB "netapi32.dll" ALIAS "NetApiBufferFree" _
       (BYVAL Buffer AS LONG) AS LONG
    
    TYPE SESSION_INFO_50
      sesi50_cname AS LONG
      sesi50_username AS LONG
      sesi50_key AS LONG
      sesi50_num_conns AS LONG
      sesi50_num_opens AS LONG
      sesi50_time AS LONG
      sesi50_idle_time AS LONG
      sesi50_protocol AS LONG
      pad1 AS LONG
    END TYPE
    
    FUNCTION PBMAIN() AS LONG
       DIM szServer1       AS ASCIIZ * 1024 ' server name
       DIM szServer2       AS ASCIIZ * 1024 ' server name
       DIM dwEntriesread   AS LONG  'out
       DIM dwTotalentries  AS LONG  'out
       DIM dwResumehandle  AS LONG  'out
       DIM success         AS LONG
       DIM si502           AS SESSION_INFO_502
    
       szServer1 = "\\" & ENVIRON$("COMPUTERNAME") & CHR$(0)
       MultiByteToWideChar %CP_ACP, _              ' code page
                          %NULL, _                 ' performance and mapping flags
                          szServer1, _             ' ANSI string to convert
                          LEN(szServer1), _        ' len of ANSI string
                          szServer2, _            ' buffer for Unicode string
                          LEN(szServer2)           ' len of Unicode buffer
    
       success = NetSessionEnum(szServer2, _
                                BYVAL 0&, _
                                BYVAL 0&, _
                                502&, _
                                BYVAL VARPTR(si502), _
                                -1&, _
                                dwEntriesread, _
                                dwTotalentries, _
                                dwResumehandle)
       MSGBOX "Success=" & STR$(success) & $CRLF & "TotalEntries=" & STR$(dwTotalEntries) & $CRLF & "EntriesRead=" & STR$(dwEntriesRead)
    END FUNCTION

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      UNICODE... I never would've thought of that!
      Thankyou for clearing that hurdle, I should be able to hammer the rest out, Ill post finished result to Source code forum soon


      ------------------
      -

      Comment


      • #4
        Done! Except for one thing - its only returning the first letter of the machine name ("W" instead of "WAYNE"), and im assuming thats because of Unicode... how can I get around that? Ive tried various string ptrs, asciiz ptrs etc, but none of the combinations I tried worked

        Code:
        #COMPILE EXE
        #INCLUDE "win32api.inc"
        %NERR_SUCCESS = 0&
        TYPE SESSION_INFO_502
          sesi502_cname AS LONG
          sesi502_username AS LONG
          sesi502_num_open AS LONG
          sesi502_time AS LONG
          sesi502_idle_time AS LONG
          sesi502_user_flags AS LONG
          sesi502_cltype_name AS LONG
          sesi502_transport AS LONG
        END TYPE
        DECLARE FUNCTION NetSessionEnum LIB "Netapi32.dll" ALIAS "NetSessionEnum" _
          (servername AS ASCIIZ, _
           UncClientName AS ASCIIZ, _
           username AS ASCIIZ, _
           BYVAL level AS LONG, _
           bufptr AS LONG, _
           BYVAL prefmaxlen AS LONG, _
           entriesread AS LONG, _
           totalentries AS LONG, _
           resume_handle AS LONG) AS LONG
        DECLARE FUNCTION NetApiBufferFree LIB "netapi32.dll" ALIAS "NetApiBufferFree" _
           (BYVAL Buffer AS LONG) AS LONG
        TYPE SESSION_INFO_50
          sesi50_cname AS LONG
          sesi50_username AS LONG
          sesi50_key AS LONG
          sesi50_num_conns AS LONG
          sesi50_num_opens AS LONG
          sesi50_time AS LONG
          sesi50_idle_time AS LONG
          sesi50_protocol AS LONG
          pad1 AS LONG
        END TYPE
        FUNCTION PBMAIN() AS LONG
           DIM szServer1       AS ASCIIZ * 1024 ' server name
           DIM szServer2       AS ASCIIZ * 1024 ' server name
           DIM dwEntriesread   AS LONG  'out
           DIM dwTotalentries  AS LONG  'out
           DIM dwResumehandle  AS LONG  'out
           DIM success         AS LONG
           Dim bufptr          As Long
           Dim nStructSize     As Long
           Dim cnt             As Long
           Dim usrname         As String
           Dim bServer         As String
           DIM si502           AS SESSION_INFO_502
           szServer1 = "\\" & ENVIRON$("COMPUTERNAME") & CHR$(0)
           MultiByteToWideChar %CP_ACP, _              ' code page
                              %NULL, _                 ' performance and mapping flags
                              szServer1, _             ' ANSI string to convert
                              LEN(szServer1), _        ' len of ANSI string
                              szServer2, _            ' buffer for Unicode string
                              LEN(szServer2)           ' len of Unicode buffer
           success = NetSessionEnum(szServer2, _
                                    BYVAL 0&, _
                                    BYVAL 0&, _
                                    502&, _
                                    bufptr, _
                                    -1&, _
                                    dwEntriesread, _
                                    dwTotalentries, _
                                    dwResumehandle)
           If success = %NERR_SUCCESS And _
              success <> %ERROR_MORE_DATA Then
              nStructSize = sizeof(si502)
              For cnt = 0 To dwEntriesread - 1
               MoveMemory varptr(si502), bufptr + (nStructSize * cnt), nStructSize
                 usrname = PEEK$(si502.sesi502_username, 128)
                 MSGBOX "usrname=" & usrname  'Only getting the first character for some reason
              Next
           End If
        END FUNCTION

        ------------------
        -

        Comment


        • #5
          My guess is that the API is returning Unicode, and you need to convert the string (from the PEEK$) into an ANSI string using WideCharToMultiByte.

          Every other character of a Unicode string is (usually) a CHR$(0), so the MSGBOX is seeing the second character of the string as an end-of-string marker. The whole string is really there...

          -- Eric


          ------------------
          Perfect Sync Development Tools
          Perfect Sync Web Site
          Contact Us: mailto:[email protected][email protected]</A>
          "Not my circus, not my monkeys."

          Comment


          • #6

            Picked this one up here sometime, think it came from Dave N

            Code:
            FUNCTION uniStrToAnsi(BYVAL u AS LONG) AS STRING
            
              DIM Buffer AS STRING
              DIM x      AS STRING
              DIM l      AS LONG
            
              l = lstrlenW(BYVAL u)
              x = PEEK$(u, l * 2)
            
              Buffer = SPACE$(LEN(x) \ 2)
            
              WideCharToMultiByte %CP_ACP, _               ' code page
                                  %NULL, _                 ' performance and mapping flags
                                  BYVAL STRPTR(x), _       ' Unicode string to convert
                                  LEN(x), _                ' len of Unicode string
                                  BYVAL STRPTR(Buffer), _  ' buffer for ANSI string
                                  LEN(Buffer), _           ' len of ANSI buffer
                                  BYVAL %NULL, _           ' default for unmappable chars
                                  BYVAL %NULL              ' default flag
            
            
              FUNCTION = RTRIM$(Buffer)
            
            END FUNCTION
            so, if You include this and do a "MsgBox uniStrToAnsi(si502.sesi502_username)" you should get the whole name...

            -p



            ------------------

            Comment


            • #7
              Eric, right you are, and Per, that function did the trick perfectly!
              Thankyou all very much, I'm sure this won't be the last time I'll have to do this so it should come in handy
              Ill post finished demo to the source code forum as soon as I jazz it up and make it PBCC and PBDLL compatible
              Cheers again


              ------------------
              -

              Comment


              • #8
                So I did some tinkering, and added two functions, one for the machine name, the other or unicode...
                That st uff is a lot easier than I imagined! (The unicode stuff that is)

                Code:
                #Compile Exe
                #Include "win32api.inc"
                %NERR_SUCCESS = 0&
                Type SESSION_INFO_502
                  sesi502_cname As Long
                  sesi502_username As Long
                  sesi502_num_open As Long
                  sesi502_time As Long
                  sesi502_idle_time As Long
                  sesi502_user_flags As Long
                  sesi502_cltype_name As Long
                  sesi502_transport As Long
                End Type
                Declare Function NetSessionEnum Lib "Netapi32.dll" Alias "NetSessionEnum" _
                  (servername As Asciiz, _
                   UncClientName As Asciiz, _
                   username As Asciiz, _
                   ByVal level As Long, _
                   bufptr As Long, _
                   ByVal prefmaxlen As Long, _
                   entriesread As Long, _
                   totalentries As Long, _
                   resume_handle As Long) As Long
                Declare Function NetApiBufferFree Lib "netapi32.dll" Alias "NetApiBufferFree" _
                   (ByVal Buffer As Long) As Long
                Type SESSION_INFO_50
                  sesi50_cname As Long
                  sesi50_username As Long
                  sesi50_key As Long
                  sesi50_num_conns As Long
                  sesi50_num_opens As Long
                  sesi50_time As Long
                  sesi50_idle_time As Long
                  sesi50_protocol As Long
                  pad1 As Long
                End Type
                
                Declare Function CCSGetComputerName()As String
                Declare Function AnsiToUnicode(St As String) As String
                Declare Function UniCodeToAnsi(ByVal u As Long) As String
                
                Function PbMain() As Long
                   Dim szServer1       As String ' server name
                   Dim szServer2       As Asciiz * 128 ' server name
                   Dim dwEntriesread   As Long  'out
                   Dim dwTotalentries  As Long  'out
                   Dim dwResumehandle  As Long  'out
                   Dim success         As Long
                   Dim bufptr          As Long
                   Dim nStructSize     As Long
                   Dim cnt             As Long
                   Dim usrname         As String
                   Dim bServer         As String
                   Dim si502           As SESSION_INFO_502
                   Dim lResult         As Long
                
                   szServer1 = "\\" & CCSGetComputerName
                   szServer2 = AnsiToUnicode(szServer1)
                   success = NetSessionEnum(szServer2, _
                                            ByVal 0&, _
                                            ByVal 0&, _
                                            502&, _
                                            bufptr, _
                                            -1&, _
                                            dwEntriesread, _
                                            dwTotalentries, _
                                            dwResumehandle)
                   If success = %NERR_SUCCESS And _
                      success <> %ERROR_MORE_DATA Then
                      nStructSize = SizeOf(si502)
                      For cnt = 0 To dwEntriesread - 1
                         MoveMemory VarPtr(si502), bufptr + (nStructSize * cnt), nStructSize
                         usrname = Peek$(si502.sesi502_username, 128)
                         MsgBox UniCodeToAnsi(si502.sesi502_username)
                      Next
                   End If
                End Function
                
                '--------------------------------------------------------------------------------
                Function CCSGetComputerName()As String
                Local lResult As Long
                Local buff    As Asciiz * 17
                lResult = GetComputerName(buff, SizeOf(buff))
                Function = buff
                End Function
                
                '--------------------------------------------------------------------------------
                Function AnsiToUnicode(St As String) As String
                Local OutBuff As String
                Local lResult As Long
                lResult = MultiByteToWideChar(%CP_ACP, _                ' code page
                                              %NULL, _                  ' performance and mapping flags
                                              ByVal StrPtr(St), _       ' ANSI string to convert
                                              Len(St), _                ' len of ANSI string
                                              ByVal StrPtr(OutBuff), _  ' buffer for Unicode string
                                              SizeOf(OutBuff))             ' len of Unicode buffer
                Function = OutBuff
                End Function
                '--------------------------------------------------------------------------------
                Function UniCodeToAnsi(ByVal u As Long) As String
                  Dim Buffer As String
                  Dim x      As String
                  Dim l      As Long
                
                  l = lstrlenW(ByVal u)
                  x = Peek$(u, l * 2)
                  Buffer = Space$(Len(x) \ 2)
                  WideCharToMultiByte %CP_ACP, _               ' code page
                                      %NULL, _                 ' performance and mapping flags
                                      ByVal StrPtr(x), _       ' Unicode string to convert
                                      Len(x), _                ' len of Unicode string
                                      ByVal StrPtr(Buffer), _  ' buffer for ANSI string
                                      Len(Buffer), _           ' len of ANSI buffer
                                      ByVal %NULL, _           ' default for unmappable chars
                                      ByVal %NULL              ' default flag
                  Function = Rtrim$(Buffer)
                End Function
                '--------------------------------------------------------------------------------
                ------------------
                Scott

                [This message has been edited by Scott Turchin (edited August 09, 2001).]
                Scott Turchin
                MCSE, MCP+I
                http://www.tngbbs.com
                ----------------------
                True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                Comment


                • #9
                  Scott, just use Dave's uniStrToAnsi function that Per posted above, it grabs the whole name rather than just the first char


                  ------------------
                  -

                  Comment


                  • #10
                    See message again, I updated it..
                    I just found out someone is listening to MP3's on my comptuer because of this code hehe...
                    (I have a huge library)...

                    Anyway, VERY interesting stuff!

                    Also, I will be free this weekend to write code!
                    I have 3 projects going but will also take a look at that protocol stuff if you still want me too

                    Scott

                    ------------------
                    Scott
                    Scott Turchin
                    MCSE, MCP+I
                    http://www.tngbbs.com
                    ----------------------
                    True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                    Comment


                    • #11
                      scott, time to invest in a personal firewall , tiny personal firewall and zonealarm both handle netbios/tcp139 connections easily enough (or are you intentionally leaving that port open for internet file sharing?)

                      final code for this thread (from me anyway) has been posted to http://www.powerbasic.com/support/pb...ad.php?t=23098



                      [this message has been edited by wayne diamond (edited august 09, 2001).]
                      -

                      Comment


                      • #12
                        i just posted a demo for netusergetinfo to get information about the users returned in the netsessionenum example, its at http://www.powerbasic.com/support/pb...ad.php?t=23099
                        it works fine for users on the local machine, but can anybody figure out how to call it to retrieve info from remote machines in the lan? it should already be capable of doing that in its current form, i just dont think im calling it correctly
                        anyone?




                        ------------------
                        -

                        Comment

                        Working...
                        X