|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||
| Visual Basic Network Services NetFileEnum: Get Open File Info from a Specified Machine |
||
| Posted: | Saturday April 05, 2003 | |
| Updated: | Monday December 26, 2011 | |
| Applies to: | VB4-32, VB5, VB6 | |
| Developed with: | VB6, Windows NT4 | |
| OS restrictions: | Windows NT4 / Windows 2000 / Windows XP - see comments | |
| Author: | VBnet - Randy Birch | |
|
Related: |
NetUserGetInfo: Enumerate the User List and Obtain User Info GetSecurityDescriptorOwner: Local or Remote File or Folder Owner |
|
| Prerequisites |
| Windows NT4, Windows 2000, Windows XP, Windows .Net Server 2003 or later. The parameters for Windows 95/98/Me are different from those for Windows NT/2000/XP or later. For more information and syntax, see the Comments section below. |
|
|
NetFileEnum
returns information about some (or all) open files on a machine or
server, depending on the parameters specified in making the call.
The formatting of a call to NetFileEnum, and the handling of the buffer containing the returned data should appear familiar to anyone who has used the other Net* api calls covered on this site. When NetFileEnum is passed a remote workstation or server, a buffer containing a varying number of FILE_INFO_2 or FILE_INFO_3 structures is returned, where each identifies a specific file and file owner opened on the referenced machine. To create the output for this demo I connected (using XP Pro) as two different users via fast user switching in order to open a series of documents and applications on my laptop. Connected via my home networking LAN, the files identified as BIRCHR were opened from my "main" (normal usage) XP session, while those identified as VBNET_TEST were started under a second Windows session using that logon name. Since my code queried the laptop for open files, the opened files on that machine for all users were returned. (Passing vbNullString as the server parameter returns open files on the local machine.) Note that the listing does not contain any files opened or owned by the laptop session itself - only those opened via the network connection are returned. (If you lack a second machine with which to test this code, share a couple of your local drives or folders, map a couple of new drives to those folders, and open documents or apps through those mapped drives. Even though everything is actually on the local machine, the files opened via the mapped drives are identified as network connections). One unexplained anomaly I noticed is that some files return share attributes outside the three available read, write and create constant values. The C header files only lists those three possible permissions, so I have no idea what the other values returned represent. For example the permissions for the C:\Program Files entry is 1 (read access), while the \PIPE\srvsvc entry returns 35. Windows 9x only supports the more limited FILE_INFO_50 structure, where several of the available structure members are declared but unsupported under 9x. In addition, the API declaration for NT-based systems is different that the declare for a 9x machine; please see the Comments section below for more information regarding 9x. |
| BAS Module Code |
| None. |
|
|
| Form Code |
|
|
| To a form, add a command button (Command1), a label (Label1) and a list box (List1), along with the following code: |
|
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const LB_SETTABSTOPS As Long = &H192
Private Const MAX_PREFERRED_LENGTH As Long = -1
Private Type FILE_INFO_3
fi3_id As Long
fi3_permissions As Long
fi3_num_locks As Long
fi3_pathname As Long
fi3_username As Long
End Type
Private Const PERM_FILE_READ = &H1 'user has read access
Private Const PERM_FILE_WRITE = &H2 'user has write access
Private Const PERM_FILE_CREATE = &H4 'user has create access
Private Declare Function NetFileEnum Lib "Netapi32" _
(ByVal servername As Long, _
ByVal basepath 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
Private Declare Function NetApiBufferFree Lib "netapi32.dll" _
(ByVal Buffer As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" _
(pTo As Any, uFrom As Any, _
ByVal lSize As Long)
Private Declare Function lstrlenW Lib "kernel32" _
(ByVal lpString As Long) As Long
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Sub Form_Load()
ReDim TabArray(0 To 1) As Long
TabArray(0) = 68
TabArray(1) = 149
'Clear existing tabs and set tabstops
Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 0&, ByVal 0&)
Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 2&, TabArray(0))
Command1.Caption = "NetFileEnum"
End Sub
Private Sub Command1_Click()
Dim numconnections As Long
Dim sServer As String
'change to your remote machine name,
'or leave blank for the local machine
sServer = "lpxp"
numconnections = GetFileConnections(sServer)
Label1.Caption = numconnections & " connections on machine " & sServer
End Sub
Private Function GetFileConnections(sServer As String) As Long
Dim bufptr As Long
Dim dwServer As Long
Dim dwEntriesread As Long
Dim dwTotalentries As Long
Dim dwResumehandle As Long
Dim dwDomain As Long
Dim fi3 As FILE_INFO_3
Dim success As Long
Dim nStructSize As Long
Dim cnt As Long
Dim tmp As String
Const NERR_SUCCESS As Long = 0&
Const ERROR_MORE_DATA As Long = 234&
If Len(sServer) = 0 Then
sServer = vbNullString
Else
sServer = "\\" & sServer & vbNullString
End If
dwServer = StrPtr(sServer)
nStructSize = LenB(fi3)
success = NetFileEnum(dwServer, _
0&, _
0&, _
3, _
bufptr, _
MAX_PREFERRED_LENGTH, _
dwEntriesread, _
dwTotalentries, _
dwResumehandle)
If success = NERR_SUCCESS And _
success <> ERROR_MORE_DATA Then
For cnt = 0 To dwEntriesread - 1
CopyMemory fi3, ByVal bufptr + (nStructSize * cnt), nStructSize
List1.AddItem GetPointerToByteStringW(fi3.fi3_username) & vbTab & _
GetPermissionType(fi3.fi3_permissions) & vbTab & _
GetPointerToByteStringW(fi3.fi3_pathname)
Next
GetFileConnections = dwEntriesread
End If
Call NetApiBufferFree(bufptr)
End Function
Public Function GetPointerToByteStringW(ByVal dwData As Long) As String
Dim tmp() As Byte
Dim tmplen As Long
If dwData <> 0 Then
tmplen = lstrlenW(dwData) * 2
If tmplen <> 0 Then
ReDim tmp(0 To (tmplen - 1)) As Byte
CopyMemory tmp(0), ByVal dwData, tmplen
GetPointerToByteStringW = tmp
End If
End If
End Function
Private Function GetPermissionType(ByVal dwPermissions As Long) As String
Dim tmp As String
If dwPermissions And PERM_FILE_READ Then tmp = "read "
If dwPermissions And PERM_FILE_WRITE Then tmp = tmp & "write "
If dwPermissions And PERM_FILE_CREATE Then tmp = tmp & "create "
GetPermissionType = tmp & "access"
End Function |
| Comments |
|
The MSDN has the following information concerning using this API on 9x
machines: Windows 95/98/Me:
The calling application must use the cbBuffer
parameter to specify the size, in bytes, of the information buffer
pointed to by the pbBuffer parameter. (The cbBuffer parameter replaces
the prefmaxlen parameter.) Neither a user name parameter nor a resume
handle parameter is available on this platform. Therefore, the
parameter list is as follows.
The Windows 9x C demo code shows this calling convention: NetFileEnum Sample (Windows 95/98/Me) Windows 95/98/Me: The following code sample demonstrates how to list the open files on a server with a call to the NetFileEnum function. The sample allocates the memory required to receive 20 file_info_50 structures. If this size is inadequate, the sample warns the caller that there are more entries to enumerate. Finally, the sample frees the allocated memory. #include <stdio.h>
#include <assert.h>
#include <windows.h>
#include <svrapi.h>
const short MAX_ENTRIES = 20;
int main(int argc, char FAR * argv[])
{
char FAR * pszServerName = NULL;
short nLevel = 50;
struct file_info_50* pBuf = NULL;
struct file_info_50* pTmpBuf = NULL;
short cbBuffer;
short nEntriesRead = 0;
short nTotalEntries = 0;
short nTotalCount = 0;
int i;
NET_API_STATUS nStatus;
//
// ServerName can be NULL to indicate the local computer.
//
if (argc > 2)
{
printf("Usage: %s [\\\\ServerName]\n", argv[0]);
exit(1);
}
if (argc == 2)
pszServerName = argv[1];
//
// Allocate the memory required to receive a maximum of
// 20 file_info_50 structures.
//
cbBuffer = MAX_ENTRIES * sizeof(struct file_info_50);
pBuf = malloc(cbBuffer);
if (pBuf == NULL)
printf("No memory\n");
// Call the NetFileEnum function to list the
// open files, specifying information level 50.
//
nStatus = NetFileEnum(pszServerName,
NULL,
nLevel,
(char FAR *)pBuf,
cbBuffer,
&nEntriesRead,
&nTotalEntries);
//
// Loop through the entries; process errors.
//
if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
{
if ((pTmpBuf = pBuf) != NULL)
{
for (i = 0; (i < nEntriesRead); i++)
{
assert(pTmpBuf != NULL);
if (pTmpBuf == NULL)
{
fprintf(stderr, "An access violation has occurred\n");
break;
}
//
// Display the information for each entry retrieved.
//
printf("\tShare: %s\n", pTmpBuf->fi50_sharename);
printf("\n\tPath: %s\n", pTmpBuf->fi50_pathname);
printf("\tUser: %s\n", pTmpBuf->fi50_username);
printf("\tID: %d\n", pTmpBuf->fi50_id);
pTmpBuf++;
nTotalCount++;
}
}
}
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
//
// Display a warning if the buffer was not large enough
// to contain all available entries.
//
if ((nEntriesRead < nTotalEntries) || (nStatus == ERROR_MORE_DATA))
fprintf(stderr, "Not all entries have been enumerated\n");
//
// Free the allocated memory.
//
if (pBuf != NULL)
free(pBuf);
fprintf(stderr, "\nTotal of %d entries enumerated\n", nTotalCount);
return 0;
}
The FILE_INFO_50 structure used by 9x machines is defined as:
typedef struct _file_info_50 { |
|
|
|
|
|
|||||
|
|||||
|
|
|||||
|
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |
![]() |