[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: win32api: how to access NetFileEnum results?

Robert Chastain

11/23/2006 3:18:00 AM

Trying to modify the below script to allow me to query remote
machines. The first parameter to NetFileEnum needs to be a char * to
the machine name. Can't seem to work out how to do that in ruby.

Thanks,
RC

Subject: Re: win32api: how to access NetFileEnum results?
From: Jos Backus <jos catnook.com>
Date: Wed, 14 Jul 2004 09:28:13 +0900
References: 106163 106180 106240 106266
In-reply-to: 106266

--YiEDa0DAkWCtVeE4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Jul 14, 2004 at 04:57:21AM +0900, daz wrote:
> Re-reading the API suggests a change of tack.
> I think that memcpy isn't required.
[snip]
> p rbuf
> #----------------------------------
>
> Good or bad ?

This yields 10k worth of zeroes on my screen :) I think I understand what you
are trying to do (have win32api follow the pointer automagically) but I can't
seem to get it to work. bufptr does have the right value in this case too, so
that part works fine, but I opted to use the simpler initialization instead.
So I ended up doing some memcpy's which I need anyway to access the pathname
and username fields in the returned FILE_INFO_3 structs. The attached code
works for me; cleanup suggestions welcomed!

Thanks for your help guys.

Cheers,
--
Jos Backus _/ _/_/_/ Sunnyvale, CA
_/ _/ _/
_/ _/_/_/
_/ _/ _/ _/
jos at catnook.com _/_/ _/_/_/ require 'std/disclaimer'

--YiEDa0DAkWCtVeE4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="openfiles.rb"

#!/usr/bin/env ruby

# LMSTR =
# LPBYTE* = P
# DWORD = L
# LPDWORD = P
# PDWORD_PTR = L

# NET_API_STATUS NetFileEnum(
# LMSTR servername,
# LMSTR basepath,
# LMSTR username,
# DWORD level,
# LPBYTE* bufptr,
# DWORD prefmaxlen,
# LPDWORD entriesread,
# LPDWORD totalentries,
# PDWORD_PTR resume_handle
#);

# typedef struct _FILE_INFO_3 {
# DWORD fi3_id;
# DWORD fi3_permissions;
# DWORD fi3_num_locks;
# LMSTR fi3_pathname;
# LMSTR fi3_username;
# } FILE_INFO_3;

require "Win32API"

NetFileEnum = Win32API.new('netapi32', 'NetFileEnum', 'PPPNPNPPP','I')
Memcpy = Win32API.new('msvcrt', 'memcpy', 'PPL', 'P')
Pmemcpy1 = Win32API.new('msvcrt', 'memcpy', 'PLL', 'L')
Pmemcpy2 = Win32API.new('msvcrt', 'memcpy', 'LPL', 'L')
Wcslen = Win32API.new('msvcrt', 'wcslen', 'P', 'L')

class OpenFile
attr_reader :id, :permissions, :num_locks, :pathname, :username
def initialize(id, permissions, num_locks, p_pathname, p_username)
@id, @permissions, @num_locks = id, permissions, num_locks
pathlen = Wcslen.call(p_pathname) * 2
userlen = Wcslen.call(p_username) * 2
pname = "\0" * pathlen
uname = "\0" * userlen
Pmemcpy1.call(pname, p_pathname, pathlen)
Pmemcpy1.call(uname, p_username, userlen)
@pathname = pname.delete("\0")
@username = uname.delete("\0")
end
def inspect
"File #{@pathname} opened by #{@username} (id #{@id},
#{@num_locks} lock(s))"
end
end

MAX_PREFERRED_LENGTH = -1
FILE_INFO_3_SIZE = 20
LEVEL = 3

bufptr = "\0" * 4
entriesread = "\0" * 4
totalentries = "\0" * 4
resume_handle = "\0" * 4

ret = NetFileEnum.call(nil, nil, nil, LEVEL, bufptr, MAX_PREFERRED_LENGTH,
entriesread, totalentries, resume_handle)

if 0 != ret
puts "Failed: #{ret}"
exit
end

entriesread = entriesread.unpack("S")[0]
totalentries = totalentries.unpack("S")[0]

rbuf = "\0" * entriesread * FILE_INFO_3_SIZE

# bufptr now contains a ptr to a ptr
Pmemcpy1.call(rbuf, bufptr.unpack("L")[0], entriesread * FILE_INFO_3_SIZE)

open_files = []
entriesread.times do |i|
open_files << OpenFile.new(*rbuf[i * FILE_INFO_3_SIZE,
FILE_INFO_3_SIZE].unpack("LLLLL"))
end

open_files.each do |file|
p file
end

exit