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


NetUserGetInfo: Enumerate the User List and Obtain User Info
GetSecurityDescriptorOwner: Local or Remote File or Folder Owner
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

 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
      sServer = "\\" & sServer & vbNullString
   End If
   dwServer = StrPtr(sServer)
   nStructSize = LenB(fi3)
   success = NetFileEnum(dwServer, _
                         0&, _
                         0&, _
                         3, _
                         bufptr, _
                         MAX_PREFERRED_LENGTH, _
                         dwEntriesread, _
                         dwTotalentries, _

   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 & _

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

const char FAR * pszServer,
const char FAR * pszBasePath,
short sLevel,
char FAR * pbBuffer,
unsigned short cbBuffer,
unsigned short FAR * pcEntriesRead,
unsigned short FAR * pcTotalAvail );

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]);

   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,
                         (char FAR *)pBuf,
   // 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");
            // 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);

      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)

   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 {
   unsigned long fi50_id;
   unsigned short fi50_permissions;
   unsigned short fi50_num_locks;
   char FAR* fi50_pathname;
   char FAR* fi50_username;
   char FAR* fi50_sharename;
} _file_info_50;


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter