|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. |