Sign in to follow this  
Followers 0
mbevan

help required using dllcall with netapi32 function netserverenum

12 posts in this topic

I am trying to use DllCall for the first time and not having much luck

I want to list all the servers in our domain so have written a script based on the information from microsoft at http://support.microsoft.com/kb/q198896

$SV_TYPE_SERVER = 0x00000002

$iLevel = 101

$pBufPtr = DllStructCreate("uint;uint;uint;uint;uint;uint")

$iPrefMaxLen = 0xFFFFFFFF

$iEntriesRead = 0

$iTotalEntries = 0

$iServerType = $SV_TYPE_SERVER

$iResumeHandle = 0

$aDllRet = DllCall("netapi32.dll", "long", "NetServerEnum", _

"wstr", "", _

"long", $iLevel, _

"ptr", DllStructGetPtr($pBufPtr), _

"long", $iPrefMaxLen, _

"long", $iEntriesRead, _

"long", $iTotalEntries, _

"long", $iServerType, _

"wstr", "", _

"long", $iResumeHandle)

For $iElement = 0 To UBound($aDllRet) - 1

ConsoleWrite("Element " & $iElement & "=" & $aDllRet[$iElement] & @CRLF)

Next

I have tried my best to understand how to convert the VB speak for variable types etc to the matching ones for autoit but I guess I have made a bit of a mess of it as whenever I run the script I get $aDllRet[0] set to a value of 87 (I think this means invalid parameter supplied from a quick google of return codes for the function)

I am not sure what I am doing wrong with the code above - can someone help me out ???

Thanks

Mark

Share this post


Link to post
Share on other sites



Hi,

You're not alone in the universe, i'm facing the same problem. Still looking. I have some hope as i made something similar (working :) ) for the NetGetJoinInfo function of netapi32.dll

Please not that you must call NetApiBufferFree after a successful call.

Below the code of a working netapi32 function:

;########################################################

; Fonction: netGetJoinInfo()

; status: prod

; require: win2k

; return: state of secure channel & "|" & domain/wrkgrp

; ------

;########################################################

Func netGetJoinInfo($wkst = @ComputerName,$deb = 0) ; computer, debug mode

Local $err, $uname, $domStruct, $lpNameBuffer, $result, $domStruct, $bufferType, $typStruct

Local Const $NetSetupUnknownStatus = 0

Local Const $NetSetupUnjoined = 1

Local Const $NetSetupWorkgroupName = 2

Local Const $NetSetupDomainName = 3

Local Const $NETSETUP_JOIN_DOMAIN = 0x00000001

Local Const $NETSETUP_ACCT_CREATE = 0x00000002

Local Const $NETSETUP_ACCT_DELETE = 0x00000003

If StringLen($wkst) = 0 Then $wkst = @Computername

$domStruct = DllStructCreate("char[256]")

$lpNameBuffer = DllStructGetPtr($domStruct)

$typStruct = DllStructCreate("int")

$bufferType = DllStructGetPtr($typStruct)

$err =DllCall($netapi32, "int" ,"NetGetJoinInformation", _

"int_ptr" ,strToUnicode($wkst) , _ ; LPCWSTR lpserver [in ] Pointer to a constant string that specifies the DNS or NetBIOS name of the computer on which to call the function. If this parameter is NULL, the local computer is used.

"ptr" ,$lpNameBuffer , _ ; LPDWORD lpNameBuffer [OUT] Pointer to the buffer that receives the NetBIOS name of the domain or workgroup to which the computer is joined.

"ptr" ,$bufferType) ; PNET... BufferType [OUT] Receives the join status of the specified computer

; Error ?

If $err[0] Then

$lasterr = DllCall ($kernel32, "int", "GetLastError")

If $deb Then MsgBox(0,"error NetGetJoinInformation " & FormatMessage($lasterr[0]),FormatMessage($err[0]))

;get rid of the array & cleanup before leaving with error

$entriesstruct = 0

$totalstruct = 0

DllCall($netapi32, "int" ,"NetApiBufferFree", _

"ptr" ,$lpNameBuffer)

Return -1

EndIf ; $err[0] <> 0

$result = DllStructGetData($typStruct,1)

If $deb Then MsgBox(0,"NetGetJoinInformation " & $wkst,$result & " " & $domn)

;get rid of the array & cleanup

$entriesstruct = 0

$totalstruct = 0

DllCall($netapi32, "int" ,"NetApiBufferFree", _

"ptr" ,$lpNameBuffer)

return $result & "|" & $domn

EndFunc


registry victim

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Hi joell,

I posted a help request for a similar DLL call here -> http://www.autoitscript.com/forum/index.ph...c=34321&hl= but my one didn't work! So I was happy when "lod3n" directed me to this post.

I don't dispute that it worked for you, but copying the source locally, I can't get it to work. I guesssed that using $netapi32 requires a $netapi32="netapi32.dll" entry, but I couldn't decide what to do with the next error. Can you tell me where I can get hold of the strToUnicode function.

I know I'm being a bit thick, but how does the code cope with the buffer being created by the netapi32.dll and not AUTOIT.

There are quite a few requests for help in using the Network Management Functions, I hope we are nearly there.

(I edited this 'cos I can't spell!)

Edited by jonesy

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

May be my sample for NetLocalGroupGetMembers help for your (Its really work!):

;===============================================================================
;
; Description:       Return the 1-dimension array with the members of particular
;                    local group in the security database (SAM) of computer
; Syntax:            _NetLocalGroupGetMembers ($s_Group, [$s_Computer, [, $i_ShowDomain [, $i_Filter]]])
; Parameter(s):      $s_Group - the name of the local group whose members are to be listed;
;                    $s_Computer - DNS or NetBIOS name of the remote computer on with the function
;                       is to execute. If $s_Computer is skip or NULL-string, the local computer is used;
;                    $i_ShowDomain - 1 full name include domain name, 0 not include;
;                    $i_Filter - set of flags for filtering specified account types, sum of values:
;                        1 - User Type
;                        2 - Group Type
;                       16 - WellKnown Group Type
;                       32 - Deleted Account Type
;                      128 - Unknown Type
; Return Value(s):   On Success - Return the 1-dimension array with the members and
;                                 first element (index 0) returns count of returned members
;                    On Failure - returns -1 in first element (index 0) and set @error on Errors
; Author(s):         <amel27 at oszone dot net>
;
;===============================================================================

Func _NetLocalGroupGetMembers ($group, $server = "", $showdomain = 1, $filter = 511)
    Local $res [1] = [0], $bufptr= DllStructCreate ("ptr")
    If $showdomain Then
        $showdomain=2
    Else
        $showdomain=1
    EndIf
    Local $ret = DllCall ("netapi32.dll", "int", "NetLocalGroupGetMembers", _
        "wstr", $server, _
        "wstr", $group, _
        "int", $showdomain, _
        "ptr", DllStructGetPtr ($bufptr), _
        "int", -1, _
        "int_ptr", 0, _
        "int_ptr", 0, _
        "int_ptr", 0 )
    If $ret[0] Then
        SetError ($ret [0])
        $res[0] = -1
    Else
        If $ret[6]>0 Then
            Local $i, $string
            Local $buffer = DllStructCreate ("ptr[" & $ret[6]*3 & "]", DllStructGetData ($bufptr,1) )
            For $i=3 To $ret[6]*3 Step 3
                If BitAnd (BitShift (1, 1 - DllStructGetData ($buffer, 1, $i-1) ), $filter) Then
                    $ret = DllCall("kernel32.dll", "int", "WideCharToMultiByte", _
                        "int", 0, _
                        "int", 0, _
                        "ptr", DllStructGetData ($buffer, 1, $i), _
                        "int", -1, _
                        "str", "", _
                        "int", 0, _
                        "int", 0, _
                        "int", 0 )
                    $string = DllStructCreate ("char[" & $ret[0] & "]")
                    $ret = DllCall("kernel32.dll", "int", "WideCharToMultiByte", _
                        "int", 0, _
                        "int", 0, _
                        "ptr", DllStructGetData ($buffer, 1, $i), _
                        "int", $ret[0], _
                        "ptr", DllStructGetPtr ($string), _
                        "int", $ret[0], _
                        "int", 0, _
                        "int", 0 )
                    ReDim $res [$res[0]+2]
                    $res [0] = $res [0]+1
                    $res [$res[0]] = DllStructGetData ($string,1)
                EndIf
            Next
        EndIf
    EndIf
    DllCall ("netapi32.dll", "int" ,"NetApiBufferFree", _
        "ptr" , DllStructGetData ($bufptr,1) )
    Return $res
EndFunc
Edited by amel27

Share this post


Link to post
Share on other sites

Amel27 - thanks BRILLIANT! it works!!!! Now all I've got to do is try and understand the how & the why!

There are loads more Network Management functions defined by Microsoft, and there are other requests on the Forum asking for help in using "netapi32.dll". Have you got any more of the Network functions that you have already created?

I think an include file with (nearly?) all of them in it should be included with a future version of AUTOIT.

When I couldn't get it to work, I tried to do the same as this but using OBJ/COM and ADSI. The code below works, but you have to cobble the name together as ADSI doesn't return it correctly. Your version using the Network Management functions is much faster. Now that I've seen a working version, I'll give up on the COM way of doing it.

Once again thanks!

$Members=_NetLocalGroup(@Computername, "Administrators")

msgbox(0,"", $Members[0])
for $i=1 to UBound($Members)-1
    msgbox(0,"", $Members[$i])
next
exit

Func _NetLocalGroup($HOST, $LocalGroup)
    Global $Members[1]
    $Administrators = ObjGet("WinNT://" & $HOST & "/" & $LocalGroup)
    $MemberList=$Administrators.Members
    for $Account in $MemberList
        $FullName=StringUpper(StringRight($Account.Parent, StringLen($Account.Parent)-8))
        if (StringRight($FullName, StringLen($HOST)+1))=("/" & StringUpper($HOST)) then
            $FullName=$Account.Name
        else
            $FullName=$FullName & "\" & $Account.Name
        EndIf
        ReDim $Members[UBound($Members) + 1]
        $Members[UBound($Members) - 1]=$FullName
    next
    $Members[0]=UBound($Members)-1
    Return $Members
EndFunc

Share this post


Link to post
Share on other sites

Thanks for the advice. I was aware of Scriptomatic and had downloaded it some time ago. I don't know where in Scriptomatic to find the com stuff for what I was trying to do, and it keeps crashing on this PC. I'll have to try again when I get back to work.

Having said that, the com way of getting at this information is much slower than using the Network management functions. As I want to check on who has been added to the Local Administrators group on over 4,000 XP workstations, the faster the better.

Share this post


Link to post
Share on other sites

jonesy

Thanks, but I'm not professional in programming, and my English even worse... but I don't like compromises, my code is result of 3-day meditation on above (yours and others) posts...

Have you got any more of the Network functions that you have already created?

As can be seen above converting any NetAPI functions to AutoIt more simpler than it seems... but if necessary I'm ready to write some code, it may be cause put them to rights... I think it will be alter branch of this forum, is it true?

I think an include file with (nearly?) all of them in it should be included with a future version of AUTOIT.

maybe, maybe... but Object-programming is more progressive than via API-functions

Share this post


Link to post
Share on other sites

jonesy

Thanks, but I'm not professional in programming, and my English even worse... but I don't like compromises, my code is result of 3-day meditation on above (yours and others) posts...

As can be seen above converting any NetAPI functions to AutoIt more simpler than it seems... but if necessary I'm ready to write some code, it may be cause put them to rights... I think it will be alter branch of this forum, is it true?

maybe, maybe... but Object-programming is more progressive than via API-functions

You may not be a professional programmer, but your coding style indicates you could/should be. Your English aint bad either!

I was asking if you had more functions already coded before I started to write them myself, because I'm lazy at heart...

I agree that if more functions were to appear in Support, rather than the Scripts & Scraps someone (everyone?) would point out the error of our ways...

I agree that Object-programming in general is the way forward, but I'm not sure this is always the case. There are 3 problems with the COM approach to this problem:

1. Performance. It is noticeably slower to use COM to get at the list of Administrators on a P IV 2.8, compared to the almost instantaneous results when using the NetAPI.

2. The entries returned when using COM are not in the same form that the NetAPI call returns. I'm assuming (in my COM based script) that the information I cobbled together will work in all situations. Just because it works for me and my Domain setup doesn't mean it always will.

3. I'm not convinced that COM is the way forward. My understanding is that using .NET programming languages involves moving away from COM, although not OOP. Not sure of my ground here. I'm sure someone will put me straight - I just hope it doesn't hurt.

Share this post


Link to post
Share on other sites

You may not be a professional programmer, but your coding style indicates you could/should be. Your English aint bad either!

I am NetAdmin (AutoIt is my tool), and speek in English with dictionary very difficult

I was asking if you had more functions already coded before I started to write them myself, because I'm lazy at heart...

Now it is in my interesting too... and please look my refreshing code for _NetLocalGroupGetMembers . :whistle:

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

May be my sample for NetLocalGroupGetMembers help for your (Its really work!):

Hi, would you like to give a example with this. I do not know why the function can not be used on my machine. Thanks!

Edited by netegg

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0