forum-msg-id-125633-edit

Original date:2014-12-05 14:11:41 Edited by: ghaberek Subject: Re: Detecting shares using walk_dir()

jimcbrown said...

So imvho this functionality is better off living in the enumerate_shares() function that ghaberek will hopefully get around to writing soon.

And here it is! smile

You can use scan_network() to scan the network for available shares and/or call enumerate_shares() against a specific host (e.g. \\some-server).

-- file: shares.e 
 
include std/dll.e 
include std/machine.e 
include mpr.e -- WNet* functions and constants 
 
constant KB = 1024 -- one kilobyte 
 
public constant 
    -- possible results codes 
    NO_ERROR                    =    0, 
    ERROR_INVALID_HANDLE        =    6, 
    ERROR_INVALID_PARAMETER     =   87, 
    ERROR_MORE_DATA             =  234, 
    ERROR_NO_MORE_ITEMS         =  259, 
    ERROR_INVALID_ADDRESS       =  487, 
    ERROR_NO_NET_OR_BAD_PATH    = 1203, 
    ERROR_NOT_CONTAINER         = 1207, 
    ERROR_EXTENDED_ERROR        = 1208, 
    ERROR_NO_NETWORK            = 1222, 
$ 
 
public enum 
    -- values returned by get_NETRESOURCE() 
    NETRESOURCE_SCOPE, 
    NETRESOURCE_TYPE, 
    NETRESOURCE_DISPLAY_TYPE, 
    NETRESOURCE_USAGE, 
    NETRESOURCE_LOCAL_NAME, 
    NETRESOURCE_REMOTE_NAME, 
    NETRESOURCE_COMMENT, 
    NETRESOURCE_PROVIDER, 
$ 
 
--** 
-- Allocate a NETRESOURCE structure. 
-- 
function new_NETRESOURCE( atom dwScope, atom dwType, atom dwDisplayType, atom dwUsage, sequence szLocalName = "", 
        sequence szRemoteName = "", sequence szComment = "", sequence szProvider = "" ) 
     
    integer nBufferSize, nOffset 
    atom lpNetResource, lpLocalName, lpRemoteName, lpComment, lpProvider 
     
    -- calculate the total buffer size 
    nBufferSize = SIZEOF_NETRESOURCE + 4 -- four NULL terminators 
                    + length( szLocalName ) 
                    + length( szRemoteName ) 
                    + length( szComment ) 
                    + length( szProvider ) 
     
    -- allocate the entire buffer 
    lpNetResource = allocate_data( nBufferSize ) 
    mem_set( lpNetResource, NULL, nBufferSize ) 
     
    nOffset = SIZEOF_NETRESOURCE 
    if length( szLocalName ) = 0 then 
        lpLocalName = NULL 
    else 
        lpLocalName = lpNetResource + nOffset 
        poke( lpLocalName, szLocalName & NULL ) 
    end if 
     
    nOffset += length( szLocalName ) + 1 
    if length( szRemoteName ) = 0 then 
        lpRemoteName = NULL 
    else 
        lpRemoteName = lpNetResource + nOffset 
        poke( lpRemoteName, szRemoteName & NULL ) 
    end if 
     
    nOffset += length( szRemoteName ) + 1 
    if length( szComment ) = 0 then 
        lpComment = NULL 
    else 
        lpComment = lpNetResource + nOffset 
        poke( lpComment, szComment & NULL ) 
    end if 
     
    nOffset += length( lpComment ) + 1 
    if length( szProvider ) = 0 then 
        lpProvider = NULL 
    else 
        lpProvider = lpNetResource + nOffset 
        poke( lpProvider, szProvider & NULL ) 
    end if 
     
    poke4( lpNetResource + NETRESOURCE__dwScope,        dwScope ) 
    poke4( lpNetResource + NETRESOURCE__dwType,         dwType ) 
    poke4( lpNetResource + NETRESOURCE__dwDisplayType,  dwDisplayType ) 
    poke4( lpNetResource + NETRESOURCE__dwUsage,        dwUsage ) 
    poke4( lpNetResource + NETRESOURCE__lpLocalName,    lpLocalName ) 
    poke4( lpNetResource + NETRESOURCE__lpRemoteName,   lpRemoteName ) 
    poke4( lpNetResource + NETRESOURCE__lpComment,      lpComment ) 
    poke4( lpNetResource + NETRESOURCE__lpProvider,     lpProvider ) 
     
    return lpNetResource 
end function 
 
--** 
-- Read a NETRESOURCE structure from memory. 
-- 
function get_NETRESOURCE( atom lpNetResource, integer nCount = 1 ) 
     
    sequence data = repeat( {}, nCount ) 
    atom offset = 0 
     
    for i = 1 to nCount do 
         
        -- peek the whole structure (eight 4-byte values) 
        data[i] = peek4u({ lpNetResource + offset, 8 }) 
         
        -- values 5-8 are really strings 
        for j = 5 to 8 do 
             
            if data[i][j] = 0 then 
                -- null (empty) string 
                data[i][j] = "" 
            else 
                -- peek the string value 
                data[i][j] = peek_string( data[i][j] ) 
            end if 
             
        end for 
         
        -- increment the offset 
        offset += SIZEOF_NETRESOURCE 
         
    end for 
     
    return data 
end function 
 
--** 
-- Translate an error code into a descriptive string. 
-- 
public function get_net_error( integer error ) 
     
    sequence string 
     
    switch error do 
         
        case NO_ERROR then 
            string = "success" 
             
        case ERROR_INVALID_HANDLE then 
            string = "invalid handle" 
             
        case ERROR_INVALID_PARAMETER then 
            string = "invalid parameter" 
             
        case ERROR_MORE_DATA then 
            string = "more data available" 
             
        case ERROR_NO_MORE_ITEMS then 
            string = "no more items" 
             
        case ERROR_INVALID_ADDRESS then 
            string = "invalid address" 
             
        case ERROR_NO_NET_OR_BAD_PATH then 
            string = "no network or bad path" 
             
        case ERROR_NOT_CONTAINER then 
            string = "not a container" 
             
        case ERROR_EXTENDED_ERROR then 
            string = "extended error" 
             
        case ERROR_NO_NETWORK then 
            string = "no network available" 
             
        case else 
            string = "unknown error" 
             
         
    end switch 
     
    return "Error: " & string 
end function 
 
--** 
-- Scan the network for available resources. 
-- 
-- dwScope can be one of the following: 
-- 
--   RESOURCE_CONNECTED     Enumerate all currently connected resources. The function ignores the dwUsage parameter. 
-- 
--   RESOURCE_CONTEXT       Enumerate only resources in the network context of the caller. Specify this 
--                          value for a Network Neighborhood view. The function ignores the dwUsage parameter. 
-- 
--   RESOURCE_GLOBALNET     Enumerate all resources on the network. 
-- 
--   RESOURCE_REMEMBERED    Enumerate all remembered (persistent) connections. The function ignores the dwUsage parameter. 
-- 
-- dwType can be one of the following: 
-- 
--   RESOURCETYPE_ANY       All resources. This value cannot be combined with RESOURCETYPE_DISK or RESOURCETYPE_PRINT. 
-- 
--   RESOURCETYPE_DISK      All disk resources. 
-- 
--   RESOURCETYPE_PRINT     All print resources. 
-- 
-- dwUsage can be one of the following: 
-- 
--   0                          All resources. 
-- 
--   RESOURCEUSAGE_CONNECTABLE  All connectable resources. 
-- 
--   RESOURCEUSAGE_CONTAINER    All container resources. 
-- 
--   RESOURCEUSAGE_ATTACHED     Setting this value forces WNetOpenEnum to fail if the user is not authenticated. 
--                              The function fails even if the network allows enumeration without authentication. 
-- 
--   RESOURCEUSAGE_ALL          Setting this value is equivalent to setting RESOURCEUSAGE_CONNECTABLE,  
--                              RESOURCEUSAGE_CONTAINER, and RESOURCEUSAGE_ATTACHED. 
-- 
public function scan_network( atom dwScope = RESOURCE_CONTEXT, atom dwType = RESOURCETYPE_ANY, atom dwUsage = 0 ) 
     
    atom lpNetResource = NULL         -- Scan the entire network. 
    atom lphEnum = allocate_data( 4 ) -- Pointer to an enumeration handle. 
    object hResult = NO_ERROR 
     
    hResult = WNetOpenEnum( dwScope, dwType, dwUsage, lpNetResource, lphEnum ) 
    if hResult != NO_ERROR then 
        -- WNetOpenEnum() failed. 
        return hResult 
    end if 
     
    atom hEnum = peek4u( lphEnum ) -- Get the enumeration handle. 
    free( lphEnum ) 
     
    integer nBufferSize = 16 * KB -- N.B. MS docs recommend 16KB here. 
     
    atom lpcCount = allocate_data( 4 ) 
    poke4( lpcCount, -1 ) -- Get as many entries as possible. 
     
    atom lpBuffer = allocate_data( nBufferSize ) 
    atom lpBufferSize = allocate_data( 4 ) 
    poke4( lpBufferSize, nBufferSize ) 
     
    hResult = WNetEnumResource( hEnum, lpcCount, lpBuffer, lpBufferSize ) 
    while hResult = ERROR_MORE_DATA do 
        -- We need to allocate more memory. 
         
        nBufferSize += 16 * KB 
        poke4( lpBufferSize, nBufferSize ) 
         
        free( lpBuffer ) 
        lpBuffer = allocate_data( nBufferSize ) 
         
        hResult = WNetEnumResource( hEnum, lpcCount, lpBuffer, lpBufferSize ) 
    end while 
     
    if hResult = NO_ERROR then 
         
        -- Get the NETRESOURCE items. 
        integer nCount = peek4u( lpcCount ) 
        hResult = get_NETRESOURCE( lpBuffer, nCount ) 
         
    elsif hResult = ERROR_NO_MORE_ITEMS then 
         
        -- Return an empty set. 
        hResult = {} 
         
    end if 
     
    free( lpBufferSize ) 
    free( lpBuffer ) 
    free( lpcCount ) 
     
    WNetCloseEnum( hEnum ) 
     
    return hResult 
end function 
 
--** 
-- Enumerate the shares provided by server at szRemoteName 
-- 
-- dwType can be one of the following: 
-- 
--   RESOURCETYPE_ANY       All resources. This value cannot be combined with RESOURCETYPE_DISK or RESOURCETYPE_PRINT. 
-- 
--   RESOURCETYPE_DISK      All disk resources. 
-- 
--   RESOURCETYPE_PRINT     All print resources. 
-- 
-- dwUsage can be one of the following: 
-- 
--   0                          All resources. 
-- 
--   RESOURCEUSAGE_CONNECTABLE  All connectable resources. 
-- 
--   RESOURCEUSAGE_CONTAINER    All container resources. 
-- 
--   RESOURCEUSAGE_ATTACHED     Setting this value forces WNetOpenEnum to fail if the user is not authenticated. 
--                              The function fails even if the network allows enumeration without authentication. 
-- 
--   RESOURCEUSAGE_ALL          Setting this value is equivalent to setting RESOURCEUSAGE_CONNECTABLE,  
--                              RESOURCEUSAGE_CONTAINER, and RESOURCEUSAGE_ATTACHED. 
-- 
public function enumerate_shares( sequence szRemoteName, atom dwType = RESOURCETYPE_ANY, atom dwUsage = 0 ) 
     
    atom dwScope = RESOURCE_GLOBALNET -- Enumerate all resources on the server. 
    atom lpNetResource = new_NETRESOURCE( dwScope, dwType, NULL, dwUsage, "", szRemoteName, "", "" ) 
     
    atom lphEnum = allocate_data( 4 ) -- Pointer to an enumeration handle. 
    object hResult = NO_ERROR 
     
    hResult = WNetOpenEnum( dwScope, dwType, dwUsage, lpNetResource, lphEnum ) 
    if hResult != NO_ERROR then 
        -- WNetOpenEnum() failed. 
        return hResult 
    end if 
     
    atom hEnum = peek4u( lphEnum ) -- Get the enumeration handle. 
    free( lphEnum ) 
     
    integer nBufferSize = 16 * KB -- N.B. MS docs recommend 16KB here. 
     
    atom lpcCount = allocate_data( 4 ) 
    poke4( lpcCount, -1 ) -- Get as many entries as possible. 
     
    atom lpBuffer = allocate_data( nBufferSize ) 
    atom lpBufferSize = allocate_data( 4 ) 
    poke4( lpBufferSize, nBufferSize ) 
     
    hResult = WNetEnumResource( hEnum, lpcCount, lpBuffer, lpBufferSize ) 
    while hResult = ERROR_MORE_DATA do 
        -- We need to allocate more memory. 
         
        nBufferSize += 16 * KB 
        poke4( lpBufferSize, nBufferSize ) 
         
        free( lpBuffer ) 
        lpBuffer = allocate_data( nBufferSize ) 
         
        hResult = WNetEnumResource( hEnum, lpcCount, lpBuffer, lpBufferSize ) 
    end while 
     
    if hResult = NO_ERROR then 
         
        -- Get the NETRESOURCE items. 
        integer nCount = peek4u( lpcCount ) 
        hResult = get_NETRESOURCE( lpBuffer, nCount ) 
         
    elsif hResult = ERROR_NO_MORE_ITEMS then 
         
        -- Return an empty set. 
        hResult = {} 
         
    end if 
     
    free( lpNetResource ) 
    free( lpBufferSize ) 
    free( lpBuffer ) 
    free( lpcCount ) 
     
    WNetCloseEnum( hEnum ) 
     
    return hResult 
end function 

Example:

 
include std/error.e 
include shares.e 
 
object network = scan_network() 
if atom( network ) then 
    crash( get_net_error(network) ) 
end if 
 
for i = 1 to length( network ) do 
     
    sequence remoteName = network[i][NETRESOURCE_REMOTE_NAME] 
    if length( remoteName ) then 
        printf( 1, "%s\n", {remoteName} ) 
    else 
        -- empty remote name is the "Network" container 
        puts( 1, "Network Neighborhood\n" ) 
    end if 
     
    object shares = enumerate_shares( remoteName ) 
    if atom( shares ) then 
        crash( get_net_error(shares) ) 
    end if 
     
    for j = 1 to length( shares ) do 
         
        sequence shareName = shares[j][NETRESOURCE_REMOTE_NAME] 
        printf( 1, "\t%s\n", {shareName} ) 
         
    end for 
     
end for 

-Greg

Not Categorized, Please Help

Search



Quick Links

User menu

Not signed in.

Misc Menu