Jump to content

Recommended Posts

Posted

Kafu wrote in 2013: " Next step would be to create nested function calls, first with $iScope = 1, then pass the resulting $tagNETRESOURCE structure to the next _WinNet_OpenEnum() call to enumerate the child resources of that one... "

Has anyone succeeded in doing this? I have been trying but I guess I have to admit that I failed!

The C/C++ code fromm Microsoft is

#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "mpr.lib")

#include <windows.h>
#include <stdio.h>
#include <winnetwk.h>

BOOL WINAPI EnumerateFunc(LPNETRESOURCE lpnr);
void DisplayStruct(int i, LPNETRESOURCE lpnrLocal);

int main()
{

    LPNETRESOURCE lpnr = NULL;

    if (EnumerateFunc(lpnr) == FALSE) {
        printf("Call to EnumerateFunc failed\n");
        return 1;
    } else
        return 0;

}

BOOL WINAPI EnumerateFunc(LPNETRESOURCE lpnr)
{
    DWORD dwResult, dwResultEnum;
    HANDLE hEnum;
    DWORD cbBuffer = 16384;     // 16K is a good size
    DWORD cEntries = -1;        // enumerate all possible entries
    LPNETRESOURCE lpnrLocal;    // pointer to enumerated structures
    DWORD i;
    //
    // Call the WNetOpenEnum function to begin the enumeration.
    //
    dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, // all network resources
                            RESOURCETYPE_ANY,   // all resources
                            0,  // enumerate all resources
                            lpnr,       // NULL first time the function is called
                            &hEnum);    // handle to the resource

    if (dwResult != NO_ERROR) {
        printf("WnetOpenEnum failed with error %d\n", dwResult);
        return FALSE;
    }
    //
    // Call the GlobalAlloc function to allocate resources.
    //
    lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
    if (lpnrLocal == NULL) {
        printf("WnetOpenEnum failed with error %d\n", dwResult);
//      NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetOpenEnum");
        return FALSE;
    }

    do {
        dwResultEnum = WNetEnumResource(hEnum,  // resource handle
                                        &cEntries,      // defined locally as -1
                                        lpnrLocal,      // LPNETRESOURCE
                                        &cbBuffer);     // buffer size
        if (dwResultEnum == NO_ERROR) {
            for (i = 0; i < cEntries; i++) {
                DisplayStruct(i, &lpnrLocal[i]);

                if (RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage
                                                & RESOURCEUSAGE_CONTAINER))
                    if (!EnumerateFunc(&lpnrLocal[i]))
                        printf("EnumerateFunc returned FALSE\n");
            }
        }
         else if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
            printf("WNetEnumResource failed with error %d\n", dwResultEnum);

            break;
        }
    }
    while (dwResultEnum != ERROR_NO_MORE_ITEMS);
    dwResult = WNetCloseEnum(hEnum);

    if (dwResult != NO_ERROR) {
        printf("WNetCloseEnum failed with error %d\n", dwResult);
        return FALSE;
    }

    return TRUE;
}

void DisplayStruct(int i, LPNETRESOURCE lpnrLocal)
{
    printf("NETRESOURCE[%d] Scope: ", i);
    switch (lpnrLocal->dwScope) {
    case (RESOURCE_CONNECTED):
        printf("connected\n");
        break;
    case (RESOURCE_GLOBALNET):
        printf("all resources\n");
        break;
    case (RESOURCE_REMEMBERED):
        printf("remembered\n");
        break;
    default:
        printf("unknown scope %d\n", lpnrLocal->dwScope);
        break;
    }

    printf("NETRESOURCE[%d] Type: ", i);
    switch (lpnrLocal->dwType) {
    case (RESOURCETYPE_ANY):
        printf("any\n");
        break;
    case (RESOURCETYPE_DISK):
        printf("disk\n");
        break;
    case (RESOURCETYPE_PRINT):
        printf("print\n");
        break;
    default:
        printf("unknown type %d\n", lpnrLocal->dwType);
        break;
    }

    printf("NETRESOURCE[%d] DisplayType: ", i);
    switch (lpnrLocal->dwDisplayType) {
    case (RESOURCEDISPLAYTYPE_GENERIC):
        printf("generic\n");
        break;
    case (RESOURCEDISPLAYTYPE_DOMAIN):
        printf("domain\n");
        break;
    case (RESOURCEDISPLAYTYPE_SERVER):
        printf("server\n");
        break;
    case (RESOURCEDISPLAYTYPE_SHARE):
        printf("share\n");
        break;
    case (RESOURCEDISPLAYTYPE_FILE):
        printf("file\n");
        break;
    case (RESOURCEDISPLAYTYPE_GROUP):
        printf("group\n");
        break;
    case (RESOURCEDISPLAYTYPE_NETWORK):
        printf("network\n");
        break;
    default:
        printf("unknown display type %d\n", lpnrLocal->dwDisplayType);
        break;
    }

    printf("NETRESOURCE[%d] Usage: 0x%x = ", i, lpnrLocal->dwUsage);
    if (lpnrLocal->dwUsage & RESOURCEUSAGE_CONNECTABLE)
        printf("connectable ");
    if (lpnrLocal->dwUsage & RESOURCEUSAGE_CONTAINER)
        printf("container ");
    printf("\n");

    printf("NETRESOURCE[%d] Localname: %S\n", i, lpnrLocal->lpLocalName);
    printf("NETRESOURCE[%d] Remotename: %S\n", i, lpnrLocal->lpRemoteName);
    printf("NETRESOURCE[%d] Comment: %S\n", i, lpnrLocal->lpComment);
    printf("NETRESOURCE[%d] Provider: %S\n", i, lpnrLocal->lpProvider);
    printf("\n");
}

It's proably not work me posting my code.

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Posted

That's exactly the thread the OP referred to with his quote ;)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted (edited)

can't you build it and find out? there are free versions of Visual Studio you can download

 

I just built it as a console exe in Visual Studio 2017, latest updates and it works fine.

 

// ConsoleApplication1.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include "pch.h"
#include <iostream>
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "mpr.lib")

#include <windows.h>
#include <stdio.h>
#include <winnetwk.h>

BOOL WINAPI EnumerateFunc(LPNETRESOURCE lpnr);
void DisplayStruct(int i, LPNETRESOURCE lpnrLocal);

int main()
{

    LPNETRESOURCE lpnr = NULL;

    if (EnumerateFunc(lpnr) == FALSE) {
        printf("Call to EnumerateFunc failed\n");
        return 1;
    }
    else
        return 0;

}

BOOL WINAPI EnumerateFunc(LPNETRESOURCE lpnr)
{
    DWORD dwResult, dwResultEnum;
    HANDLE hEnum;
    DWORD cbBuffer = 16384;     // 16K is a good size
    DWORD cEntries = -1;        // enumerate all possible entries
    LPNETRESOURCE lpnrLocal;    // pointer to enumerated structures
    DWORD i;
    //
    // Call the WNetOpenEnum function to begin the enumeration.
    //
    dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, // all network resources
        RESOURCETYPE_ANY,   // all resources
        0,  // enumerate all resources
        lpnr,       // NULL first time the function is called
        &hEnum);    // handle to the resource

    if (dwResult != NO_ERROR) {
        printf("WnetOpenEnum failed with error %d\n", dwResult);
        return FALSE;
    }
    //
    // Call the GlobalAlloc function to allocate resources.
    //
    lpnrLocal = (LPNETRESOURCE)GlobalAlloc(GPTR, cbBuffer);
    if (lpnrLocal == NULL) {
        printf("WnetOpenEnum failed with error %d\n", dwResult);
        //      NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetOpenEnum");
        return FALSE;
    }

    do {
        dwResultEnum = WNetEnumResource(hEnum,  // resource handle
            &cEntries,      // defined locally as -1
            lpnrLocal,      // LPNETRESOURCE
            &cbBuffer);     // buffer size
        if (dwResultEnum == NO_ERROR) {
            for (i = 0; i < cEntries; i++) {
                DisplayStruct(i, &lpnrLocal[i]);

                if (RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage
                    & RESOURCEUSAGE_CONTAINER))
                    if (!EnumerateFunc(&lpnrLocal[i]))
                        printf("EnumerateFunc returned FALSE\n");
            }
        }
        else if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
            printf("WNetEnumResource failed with error %d\n", dwResultEnum);

            break;
        }
    } while (dwResultEnum != ERROR_NO_MORE_ITEMS);
    dwResult = WNetCloseEnum(hEnum);

    if (dwResult != NO_ERROR) {
        printf("WNetCloseEnum failed with error %d\n", dwResult);
        return FALSE;
    }

    return TRUE;
}

void DisplayStruct(int i, LPNETRESOURCE lpnrLocal)
{
    printf("NETRESOURCE[%d] Scope: ", i);
    switch (lpnrLocal->dwScope) {
    case (RESOURCE_CONNECTED):
        printf("connected\n");
        break;
    case (RESOURCE_GLOBALNET):
        printf("all resources\n");
        break;
    case (RESOURCE_REMEMBERED):
        printf("remembered\n");
        break;
    default:
        printf("unknown scope %d\n", lpnrLocal->dwScope);
        break;
    }

    printf("NETRESOURCE[%d] Type: ", i);
    switch (lpnrLocal->dwType) {
    case (RESOURCETYPE_ANY):
        printf("any\n");
        break;
    case (RESOURCETYPE_DISK):
        printf("disk\n");
        break;
    case (RESOURCETYPE_PRINT):
        printf("print\n");
        break;
    default:
        printf("unknown type %d\n", lpnrLocal->dwType);
        break;
    }

    printf("NETRESOURCE[%d] DisplayType: ", i);
    switch (lpnrLocal->dwDisplayType) {
    case (RESOURCEDISPLAYTYPE_GENERIC):
        printf("generic\n");
        break;
    case (RESOURCEDISPLAYTYPE_DOMAIN):
        printf("domain\n");
        break;
    case (RESOURCEDISPLAYTYPE_SERVER):
        printf("server\n");
        break;
    case (RESOURCEDISPLAYTYPE_SHARE):
        printf("share\n");
        break;
    case (RESOURCEDISPLAYTYPE_FILE):
        printf("file\n");
        break;
    case (RESOURCEDISPLAYTYPE_GROUP):
        printf("group\n");
        break;
    case (RESOURCEDISPLAYTYPE_NETWORK):
        printf("network\n");
        break;
    default:
        printf("unknown display type %d\n", lpnrLocal->dwDisplayType);
        break;
    }

    printf("NETRESOURCE[%d] Usage: 0x%x = ", i, lpnrLocal->dwUsage);
    if (lpnrLocal->dwUsage & RESOURCEUSAGE_CONNECTABLE)
        printf("connectable ");
    if (lpnrLocal->dwUsage & RESOURCEUSAGE_CONTAINER)
        printf("container ");
    printf("\n");

    printf("NETRESOURCE[%d] Localname: %S\n", i, lpnrLocal->lpLocalName);
    printf("NETRESOURCE[%d] Remotename: %S\n", i, lpnrLocal->lpRemoteName);
    printf("NETRESOURCE[%d] Comment: %S\n", i, lpnrLocal->lpComment);
    printf("NETRESOURCE[%d] Provider: %S\n", i, lpnrLocal->lpProvider);
    printf("\n");
}

 

pch.cpp

pch.h

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Posted

Thank you for trying Microsoft's code. Good to hear that it works. It appears that I have something wrong in my AutoIt code.

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Posted

Here is my translation to AutoIt:

#include <APIErrorsConstants.au3>
#include <Memory.au3>
#include <WinAPIMisc.au3>
#include <WinNet.au3>

 ; DisplayType
Global Const $RESOURCEDISPLAYTYPE_GENERIC = 0x00000000
Global Const $RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001
Global Const $RESOURCEDISPLAYTYPE_SERVER = 0x00000002
Global Const $RESOURCEDISPLAYTYPE_SHARE = 0x00000003
Global Const $RESOURCEDISPLAYTYPE_FILE = 0x00000004
Global Const $RESOURCEDISPLAYTYPE_GROUP = 0x00000005
Global Const $RESOURCEDISPLAYTYPE_NETWORK = 0x00000006
Global Const $RESOURCEDISPLAYTYPE_ROOT = 0x00000007
Global Const $RESOURCEDISPLAYTYPE_SHAREADMIN = 0x00000008
Global Const $RESOURCEDISPLAYTYPE_DIRECTORY = 0x00000009

Local Const $tagNETRESOURCE_New = "dword Scope;dword Type;dword DisplayType;dword Usage;ptr LocalName;ptr RemoteName;ptr Comment;ptr Provider"
; $tagNETRESOURCE contains "int" instead of "dword" says Kafu


If Not Enumerate(0) Then
    ConsoleWrite('Call to Enumerate failed'&@CRLF)
EndIf

Func Enumerate($lpnr)
    Local $dwResult
    Local $hEnum
    Local $icBuffer = 16384
    Local $icEntries = -1   ; Updated by _WinNet_EnumResource to actual number of entries
; Call _WNet_OpenEnum to begin enumeration
    $dwResult = _cWinNet_OpenEnum( _
                    $RESOURCE_GLOBALNET, _  ; $iScope       all network resoruces
                    $RESOURCETYPE_ANY, _    ; $iType        all i.e. print and disk
                    0, _                    ; $iUsage       all usages
                    $lpnr, _                ; $tResource    0 first time
                    $hEnum)                 ; BYRef
    If Not $dwResult Then
        ConsoleWrite('_cWinNet_OpenEnum failed with error '&@error&@CRLF)
        Return False
    EndIf

    Local $lpnrLocal = _MemGlobalAlloc($icBuffer, $GMEM_ZEROINIT )

    Local $dwResultEnum
    Do
        ; Call _WinNet_EnumResource to continue enumeration
        $dwResultEnum = _WinNet_EnumResource($hEnum, _  ; resource handle
                        $icEntries, _   ; ByRef: before call -1 so updatued to number of  that fit in buffer
                        $lpnrLocal, _   ; 1 or more $ttagRESOURCEs
                        $icBuffer)  ; ByRef: if buffer too small for 1 resource, updated to needed size
        If $dwResultEnum=0 Then
            $lpnr = $lpnrLocal
            For $i = 1 To $icEntries
                DisplayStruct($i,$lpnr)
                ; If $tNETRESOURCE struct represents a container resource, call Enumerate recursively
                Local $tstruct = DllStructCreate($tagNETRESOURCE_New,$lpnr)
                Local $iN = DllStructGetData($tstruct,'Usage')
                If BitAND($iN,$RESOURCEUSAGE_CONTAINER)=$RESOURCEUSAGE_CONTAINER Then
                    If Not Enumerate($tstruct) Then
                        ConsoleWrite('Enumerate returned False'&@CRLF)
                    EndIf
                EndIf
                $lpnr += 32 ; = DllStructGetSize(DllStructCreate($tagNETRESOURCE))
            Next
        ElseIf $dwResultEnum<>$ERROR_NO_MORE_ITEMS Then
            ConsoleWrite('Enumerate failed with error '&$dwResultEnum)
            ExitLoop
        EndIf
    Until $dwResultEnum=$ERROR_NO_MORE_ITEMS
    ; Call WinNet_CloseEnum to end enumeration
    $dwResult = _cWinNet_CloseEnum($hEnum)
    If Not $dwResult<>0 Then
        ConsoleWrite('_WinNet_CloseEnum failed with error '&@error)
        Return False
    EndIf
    Return True
EndFunc

Func DisplayStruct($i,$lpnr)
    Local $tstruct = DllStructCreate($tagNETRESOURCE_New,$lpnr)
    ConsoleWrite('NETRESOURCE['&$i&'] Scope: ')
    Local $iN = DllStructGetData($tstruct,'Scope ')
    Switch $iN
        Case $RESOURCE_CONNECTED
            ConsoleWrite('connected'&@CRLF)
        Case $RESOURCE_GLOBALNET
            ConsoleWrite('all resources'&@CRLF)
        Case $RESOURCE_REMEMBERED
            ConsoleWrite('remembered'&@CRLF)
        Case Else
            ConsoleWrite('unknown scope '&$iN&@CRLF)
    EndSwitch

    ConsoleWrite('NETRESOURCE['&$i&'] Type: ')
    $iN = DllStructGetData($tstruct,'Type')
    Switch $iN
        Case $RESOURCETYPE_ANY
            ConsoleWrite('any'&@CRLF)
        Case $RESOURCETYPE_DISK
            ConsoleWrite('disk'&@CRLF)
        Case $RESOURCETYPE_PRINT
            ConsoleWrite('print'&@CRLF)
        Case Else
            ConsoleWrite('unknown type '&$iN&@CRLF)
    EndSwitch

    ConsoleWrite('NETRESOURCE['&$i&'] DisplayType: ')
    $iN = DllStructGetData($tstruct,'DisplayType')
    Switch $iN
        Case $RESOURCEDISPLAYTYPE_GENERIC
            ConsoleWrite('generic'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_SERVER
            ConsoleWrite('server'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_SHARE
            ConsoleWrite('share'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_FILE
            ConsoleWrite('file'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_GROUP
            ConsoleWrite('group'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_NETWORK
            ConsoleWrite('network'&@CRLF)
        Case Else
            ConsoleWrite('unknown display type '&$iN)
    EndSwitch

    $iN = DllStructGetData($tstruct,'Usage')
    ConsoleWrite('NETRESOURCE['&$i&'] Usage: '&Hex($iN)&' = ')
    If BitAND($iN,$RESOURCEUSAGE_CONNECTABLE)<>0 Then
        ConsoleWrite('connectable ')
    EndIf
    If BitAND($iN,$RESOURCEUSAGE_CONTAINER)<>0 Then
        ConsoleWrite('container ')
    EndIf
    ConsoleWrite(@CRLF)

    ConsoleWrite('NETRESOURCE['&$i&'] LocalName: '&_PointerToStringW(DllStructGetData($tstruct,'LocalName'))&@CRLF)
    ConsoleWrite('NETRESOURCE['&$i&'] RemoteName: '&_PointerToStringW(DllStructGetData($tstruct,'RemoteName'))&@CRLF)
    ConsoleWrite('NETRESOURCE['&$i&'] Comment: '&_PointerToStringW(DllStructGetData($tstruct,'Comment'))&@CRLF)
    ConsoleWrite('NETRESOURCE['&$i&'] Provider: '&_PointerToStringW(DllStructGetData($tstruct,'Provider'))&@CRLF)
    ConsoleWrite(@CRLF)
EndFunc

Func _PointerToStringW($ptr)
    Return DllStructGetData(DllStructCreate("wchar[" & _WinAPI_StringLenW($ptr) & "]", $ptr), 1)
EndFunc

; Overcomes limitation(s) in WinNet.au3 version
Func _cWinNet_OpenEnum($iScope, $iType, $iUsage, $tResource, ByRef $hEnum)

    Local $aResult = DllCall("mpr.dll", "dword", "WNetOpenEnum", "dword", $iScope, "dword", $iType, "dword", _
        $iUsage, "struct*", $tResource, "handle*", 0)
    If $aResult[0]=0 Then
        $hEnum = $aResult[5]
        Return True
    Else
        Return SetError($aResult[0], 0,False)
    EndIf
EndFunc   ;==>_WinNet_OpenEnum

Func _cWinNet_CloseEnum($hEnum)
    Local $aResult = DllCall("mpr.dll", "dword", "WNetCloseEnum", "handle", $hEnum)
    If $aResult[0]=0 Then
        Return True
    Else
        Return SetError($aResult[0], 0,False)
    EndIf
EndFunc   ;==>_WinNet_CloseEnum

Its output to the console is:

>"F:\Program Files\AutoIt3\SciTE\..\AutoIt3.exe" "F:\Program Files\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /run /prod /ErrorStdOut /in "F:\AutoIt scripts\cFileSelectFolder\to forum.au3" /UserParams    
+>18:50:02 Starting AutoIt3Wrapper v.17.224.935.0 SciTE v.3.7.3.0   Keyboard:00000409  OS:WIN_7/Service Pack 1  CPU:X64 OS:X86  Environment(Language:0409)  CodePage:0  utf8.auto.check:4
+>         SciTEDir => F:\Program Files\AutoIt3\SciTE   UserDir => C:\Users\Chris\AppData\Local\AutoIt v3\SciTE\AutoIt3Wrapper   SCITE_USERHOME => C:\Users\Chris\AppData\Local\AutoIt v3\SciTE
>Running AU3Check (3.3.14.5)  from:F:\Program Files\AutoIt3  input:F:\AutoIt scripts\cFileSelectFolder\to forum.au3
+>18:50:03 AU3Check ended.rc:0
>Running:(3.3.14.5):F:\Program Files\AutoIt3\autoit3.exe "F:\AutoIt scripts\cFileSelectFolder\to forum.au3"    
--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
NETRESOURCE[1] Scope: unknown scope 0
NETRESOURCE[1] Type: any
NETRESOURCE[1] DisplayType: network
NETRESOURCE[1] Usage: 0000000080000002 = container
NETRESOURCE[1] LocalName: 0
NETRESOURCE[1] RemoteName: Microsoft Terminal Services
NETRESOURCE[1] Comment: 0
NETRESOURCE[1] Provider: Microsoft Terminal Services

_cWinNet_OpenEnum failed with error 1204
Enumerate returned False
NETRESOURCE[2] Scope: unknown scope 0
NETRESOURCE[2] Type: any
NETRESOURCE[2] DisplayType: network
NETRESOURCE[2] Usage: 0000000080000002 = container
NETRESOURCE[2] LocalName: 0
NETRESOURCE[2] RemoteName: Microsoft Windows Network
NETRESOURCE[2] Comment: 0
NETRESOURCE[2] Provider: Microsoft Windows Network

_cWinNet_OpenEnum failed with error 1204
Enumerate returned False
NETRESOURCE[3] Scope: unknown scope 0
NETRESOURCE[3] Type: any
NETRESOURCE[3] DisplayType: network
NETRESOURCE[3] Usage: 0000000080000002 = container
NETRESOURCE[3] LocalName: 0
NETRESOURCE[3] RemoteName: Web Client Network
NETRESOURCE[3] Comment: 0
NETRESOURCE[3] Provider: Web Client Network

_cWinNet_OpenEnum failed with error 1204
Enumerate returned False
+>18:50:05 AutoIt3.exe ended.rc:0
+>18:50:05 AutoIt3Wrapper Finished.
>Exit code: 0    Time: 4.437

and the error is: $ERROR_BAD_PROVIDER = 1204 ; The specified network provider name is invalid.

It is occurring in the recursion.

In the C/C++ code, I don't understand

lpnrLocal[i].dwUsage

because, to me, lpnrLocal is not an array.

Help would be greatly appreciated. My network is 2 computers, one (mine) having mapped drives and one printer. The other printer is on the network.

Microsoft's description of their methodology is at https://docs.microsoft.com/en-us/windows/desktop/WNet/enumerating-network-resources

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Posted (edited)

Hello. You code is almost correct. the issue is that you're using the ANSI version of WNetOpenEnum in your Dllcall(By default, AutoIt tries to use the ANSI version of a function name when you don't specific the A-W termination ) so WNetOpenEnum expects ANSI version of NETRESOURCE structure, But you're using Unicode one. So just call WNetOpenEnumW.

Here is your code fixed.

#include <APIErrorsConstants.au3>
#include <Memory.au3>
#include <WinAPIMisc.au3>
#include <WinNet.au3>

 ; DisplayType
Global Const $RESOURCEDISPLAYTYPE_GENERIC = 0x00000000
Global Const $RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001
Global Const $RESOURCEDISPLAYTYPE_SERVER = 0x00000002
Global Const $RESOURCEDISPLAYTYPE_SHARE = 0x00000003
Global Const $RESOURCEDISPLAYTYPE_FILE = 0x00000004
Global Const $RESOURCEDISPLAYTYPE_GROUP = 0x00000005
Global Const $RESOURCEDISPLAYTYPE_NETWORK = 0x00000006
Global Const $RESOURCEDISPLAYTYPE_ROOT = 0x00000007
Global Const $RESOURCEDISPLAYTYPE_SHAREADMIN = 0x00000008
Global Const $RESOURCEDISPLAYTYPE_DIRECTORY = 0x00000009

Local Const $tagNETRESOURCE_New = "dword Scope;dword Type;dword DisplayType;dword Usage;ptr LocalName;ptr RemoteName;ptr Comment;ptr Provider"
; $tagNETRESOURCE contains "int" instead of "dword" says Kafu


If Not Enumerate(0) Then
    ConsoleWrite('Call to Enumerate failed'&@CRLF)
EndIf

Func Enumerate($lpnr)
    Local $dwResult
    Local $hEnum
    Local $icBuffer = 16384
    Local $icEntries = -1   ; Updated by _WinNet_EnumResource to actual number of entries
; Call _WNet_OpenEnum to begin enumeration
    $dwResult = _cWinNet_OpenEnum( _
                    $RESOURCE_GLOBALNET, _  ; $iScope       all network resoruces
                    $RESOURCETYPE_ANY, _    ; $iType        all i.e. print and disk
                    0, _                    ; $iUsage       all usages
                    $lpnr, _                ; $tResource    0 first time
                    $hEnum)                 ; BYRef
    If Not $dwResult Then
        ConsoleWrite('_cWinNet_OpenEnum failed with error '&@error&@CRLF)
        Return False
    EndIf

    Local $lpnrLocal = _MemGlobalAlloc($icBuffer, $GMEM_ZEROINIT )

    Local $dwResultEnum
    Do
        ; Call _WinNet_EnumResource to continue enumeration
        $dwResultEnum = _WinNet_EnumResource($hEnum, _  ; resource handle
                        $icEntries, _   ; ByRef: before call -1 so updatued to number of  that fit in buffer
                        $lpnrLocal, _   ; 1 or more $ttagRESOURCEs
                        $icBuffer)  ; ByRef: if buffer too small for 1 resource, updated to needed size
        If $dwResultEnum=0 Then
            $lpnr = $lpnrLocal
            For $i = 1 To $icEntries
                DisplayStruct($i,$lpnr)
                ; If $tNETRESOURCE struct represents a container resource, call Enumerate recursively
                Local $tstruct = DllStructCreate($tagNETRESOURCE_New,$lpnr)
                Local $iN = DllStructGetData($tstruct,'Usage')
                If BitAND($iN,$RESOURCEUSAGE_CONTAINER)=$RESOURCEUSAGE_CONTAINER Then
                    If Not Enumerate($tstruct) Then
                        ConsoleWrite('Enumerate returned False'&@CRLF)
                    EndIf
                EndIf
                $lpnr += 32 ; = DllStructGetSize(DllStructCreate($tagNETRESOURCE))
            Next
        ElseIf $dwResultEnum<>$ERROR_NO_MORE_ITEMS Then
            ConsoleWrite('Enumerate failed with error '&$dwResultEnum)
            ExitLoop
        EndIf
    Until $dwResultEnum=$ERROR_NO_MORE_ITEMS
    ; Call WinNet_CloseEnum to end enumeration
    $dwResult = _cWinNet_CloseEnum($hEnum)
    If Not $dwResult<>0 Then
        ConsoleWrite('_WinNet_CloseEnum failed with error '&@error)
        Return False
    EndIf
    Return True
EndFunc

Func DisplayStruct($i,$lpnr)
    Local $tstruct = DllStructCreate($tagNETRESOURCE_New,$lpnr)
    ConsoleWrite('NETRESOURCE['&$i&'] Scope: ')
    Local $iN = DllStructGetData($tstruct,'Scope ')
    Switch $iN
        Case $RESOURCE_CONNECTED
            ConsoleWrite('connected'&@CRLF)
        Case $RESOURCE_GLOBALNET
            ConsoleWrite('all resources'&@CRLF)
        Case $RESOURCE_REMEMBERED
            ConsoleWrite('remembered'&@CRLF)
        Case Else
            ConsoleWrite('unknown scope '&$iN&@CRLF)
    EndSwitch

    ConsoleWrite('NETRESOURCE['&$i&'] Type: ')
    $iN = DllStructGetData($tstruct,'Type')
    Switch $iN
        Case $RESOURCETYPE_ANY
            ConsoleWrite('any'&@CRLF)
        Case $RESOURCETYPE_DISK
            ConsoleWrite('disk'&@CRLF)
        Case $RESOURCETYPE_PRINT
            ConsoleWrite('print'&@CRLF)
        Case Else
            ConsoleWrite('unknown type '&$iN&@CRLF)
    EndSwitch

    ConsoleWrite('NETRESOURCE['&$i&'] DisplayType: ')
    $iN = DllStructGetData($tstruct,'DisplayType')
    Switch $iN
        Case $RESOURCEDISPLAYTYPE_GENERIC
            ConsoleWrite('generic'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_SERVER
            ConsoleWrite('server'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_SHARE
            ConsoleWrite('share'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_FILE
            ConsoleWrite('file'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_GROUP
            ConsoleWrite('group'&@CRLF)
        Case $RESOURCEDISPLAYTYPE_NETWORK
            ConsoleWrite('network'&@CRLF)
        Case Else
            ConsoleWrite('unknown display type '&$iN)
    EndSwitch

    $iN = DllStructGetData($tstruct,'Usage')
    ConsoleWrite('NETRESOURCE['&$i&'] Usage: '&Hex($iN)&' = ')
    If BitAND($iN,$RESOURCEUSAGE_CONNECTABLE)<>0 Then
        ConsoleWrite('connectable ')
    EndIf
    If BitAND($iN,$RESOURCEUSAGE_CONTAINER)<>0 Then
        ConsoleWrite('container ')
    EndIf
    ConsoleWrite(@CRLF)

    ConsoleWrite('NETRESOURCE['&$i&'] LocalName: '&_PointerToStringW(DllStructGetData($tstruct,'LocalName'))&@CRLF)
    ConsoleWrite('NETRESOURCE['&$i&'] RemoteName: '&_PointerToStringW(DllStructGetData($tstruct,'RemoteName'))&@CRLF)
    ConsoleWrite('NETRESOURCE['&$i&'] Comment: '&_PointerToStringW(DllStructGetData($tstruct,'Comment'))&@CRLF)
    ConsoleWrite('NETRESOURCE['&$i&'] Provider: '&_PointerToStringW(DllStructGetData($tstruct,'Provider'))&@CRLF)
    ConsoleWrite(@CRLF)
EndFunc

Func _PointerToStringW($ptr)
    Return DllStructGetData(DllStructCreate("wchar[" & _WinAPI_StringLenW($ptr) & "]", $ptr), 1)
EndFunc

; Overcomes limitation(s) in WinNet.au3 version
Func _cWinNet_OpenEnum($iScope, $iType, $iUsage, $tResource, ByRef $hEnum)

    Local $aResult = DllCall("mpr.dll", "dword", "WNetOpenEnumW", "dword", $iScope, "dword", $iType, "dword", _
        $iUsage, "struct*", $tResource, "handle*", 0)
    If $aResult[0]=0 Then
        $hEnum = $aResult[5]
        Return True
    Else
        Return SetError($aResult[0], 0,False)
    EndIf
EndFunc   ;==>_WinNet_OpenEnum

Func _cWinNet_CloseEnum($hEnum)
    Local $aResult = DllCall("mpr.dll", "dword", "WNetCloseEnum", "handle", $hEnum)
    If $aResult[0]=0 Then
        Return True
    Else
        Return SetError($aResult[0], 0,False)
    EndIf
EndFunc   ;==>_WinNet_CloseEnum

 

PD: Make 32 pointer index step functional for 64 bits too

Saludos

Edited by Danyfirex
Posted

The corrected script runs AOK.

What would the ANSI version of $tagRESOURCE_New look like?

By ' Make 32 pointer index step functional for 64 bits too " I am thinking that you mean change

$lpnr += 32

What would be the change for this script to also work on an X64 computer?

The 32 comes from 4 dwords of 8 bytes each.

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Posted (edited)

Acutally $tagNETRESOURCE works for x64 and x86. Don't touch it.

 

something like this is enough:

local $iStep= DllStructGetSize(DllStructCreate($tagNETRESOURCE))

$lpnr+=iStep

 

Saludos

Edited by Danyfirex
Posted (edited)

tested it against the c++ exe, it doesn't work. update, we have been switching equipment out, network issues. i retested on another machine on different network and it looks like it's working

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Posted (edited)

As you can see, I have already written my own versions of _WinNet_OpenEnum and _WinNet_CloseEnum. My versions return True on success, and False on Failure. If the call fails, @error is set to the system error code. I believe that this is the way AutoIt UDFs usually work. I have my own version of _WinNet_EnumResources (not called in the script I posted and you fixed) which I have not implemented yet.

I do see that another function in WinNet.au3 has the same problem: it returns @error if there is an error in the call to DllCall rather than returning @error if the _WinNet function fails. Perhaps other functions in WinNet.au3 also do this.

In writing my _cWinEnumResources I deviated from Microsoft in one way: M$ considers ERROR_NO_MORE_ITEMS to indicate success. I consider it to be failure, as the best way to go: if there are no more items, no data is returned.

Func _cWinNet_EnumResource($hEnum, ByRef $iCount, $pBuffer, ByRef $iBufSize)
    Local $aResult = DllCall("mpr.dll", "dword", "WNetEnumResourceW", "handle", $hEnum, "dword*", $iCount, "struct*", $pBuffer, "dword*", $iBufSize)
    If $aResult=0 Then
        $iCount = $aResult[2]
        $iBufSize = $aResult[4]
        Return True
    Else
        Return SetError($aResult[0],0,False)
    EndIf
EndFunc

I think that it would be beneficial to all for WinNet.au3 to be changed, but this would be script-breaking changes; however, it may be that no one is using the versions of these functions in WinNet.au3 because they are defective, so perhaps no one's script will be broken.

Thoughts?

Edited by c.haslam
Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Posted (edited)

I take back "defective". The Help says: "Success: True ; Failure: False", which is not so.

Edited by c.haslam
Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...