*-- For Windows NT Platform (NT 4, NT 2000) * * Modified version of Paul Vlad Tatavu file: * Who opened what files on the network? * * This one doesn't use the Pointers.OCX or Pointers.VCX * It's only Visual Foxpro Code. * *-- * The following program displays the open files, the users that * opened these files and other related information. * * This code detects only the files opened using a net shared * path. It does not return the files opened by a user on the * local computer using a local path (i.e. the computer where * the user is logged on). This is normal, because, otherwise, * the number of returned files would be huge. * * The user running this program must be a member of the * Administrators or Account Operators local group. * * In order to keep the code simple, the error handling only * displays the error code. You should integrate it in your * error handling mechanism. * *-- This function returns information about open files. * It returns the open files only if they were * opened using a share on that computer. * *-- It uses: * - The NetFileEnum Win32 API function * to retrieve the wanted information from the OS. * *-- Parameters: * 1. The server name. It can also be a domain name. * Use an empty string for the current computer. * Ex: MyServer * 2. The base path. Only the files in this directory * (and all subdirectories) will be returned. * This path must be specified as the local path * on the computer where the files were opened, and * not as the UNC path. * 3. The user name. * Use an empty string for all users. *-- #DEFINE VER_PLATFORM_WIN32S 0 #DEFINE VER_PLATFORM_WIN32_WINDOWS 1 #DEFINE VER_PLATFORM_WIN32_NT 2 PROCEDURE FileUse LPARAMETERS tcServerName, tcBasePath, tcUserName LOCAL lnmajor, lnminor, lnplatform, lnbuild GetOSVersion(@lnmajor, @lnminor, @lnplatform, @lnbuild) IF lnplatform # VER_PLATFORM_WIN32_NT ? 'Requires Windows NT...' RETURN ENDIF IF Type('tcServerName')#'C' .or. Type('tcBasePath')#'C' .or. Type('tcUserName')#'C' ? 'Invalid Parameters...' RETURN ENDIF LOCAL lcServerName, lcBasePath, lcUserName, lnBufferPointer LOCAL lnPreferedMaxLength, lnEntriesRead, lnTotalEntries LOCAL lnResumeHandle, lnError LOCAL loPointersObject LOCAL lnI, lcDll, lnPermissions, lnID LOCAL llContinue, lnpFileInfo, lcFileName LOCAL lnLocks, lcUserName DECLARE INTEGER NetFileEnum IN NETAPI32 ; STRING @ServerName, STRING @BasePath, ; STRING @UserName, INTEGER nLevel, ; INTEGER @BufferPointer, INTEGER PreferedMaxLength, ; INTEGER @EntriesRead, INTEGER @TotalEntries, ; INTEGER @ResumeHandle DECLARE INTEGER NetApiBufferFree IN NETAPI32 ; INTEGER Pointer *-- This is the structure used by NetFileEnum * to retrieve the information. *typedef struct _FILE_INFO_3 { * DWORD fi3_id; * DWORD fi3_permissions; * DWORD fi3_num_locks; * LPWSTR fi3_pathname; * LPWSTR fi3_username;} FILE_INFO_3 *-- The server name, the base path and the user name * must be in Unicode format. lcServerName = StrConv(StrConv(tcServerName + Chr(0), 1), 5) lcBasePath = StrConv(StrConv(tcBasePath + Chr(0), 1), 5) lcUserName = StrConv(StrConv(tcUserName + Chr(0), 1), 5) *-- Allow for a very large buffer. * If this length is not enough, the info * will be retrieved in more than one step. lnPreferedMaxLength = 100000000 lnResumeHandle = 0 lnEntriesRead = 0 lnTotalEntries = 0 lnBufferPointer = 0 llContinue = .t. DO WHILE llContinue lnError = NetFileEnum( lcServerName, lcBasePath, lcUserName, 3, ; @lnBufferPointer, lnPreferedMaxLength, @lnEntriesRead, ; @lnTotalEntries, @lnResumeHandle) IF lnEntriesRead = 0 *-- There are no (more) open files. llContinue = .f. ENDIF IF lnError = 0 FOR lnI = 1 TO lnEntriesRead ? lnpFileInfo = lnBufferPointer + (lnI - 1) * 20 *-- Extract the file name lcFileName = GetMemoryLPString(lnpFileInfo + 12) ? "File name:", lcFileName *-- Extract the number of locks on this file lnLocks = GetMemoryDWORD(lnpFileInfo + 8) ? "Locks:", lnLocks *-- Extract the user name that opened the file lcUserName = GetMemoryLPString(lnpFileInfo + 16) ? "User:", lcUserName *-- Extract the permissions on this file lnPermissions = GetMemoryDWORD( lnpFileInfo + 4) ? "Permissions:" IF BitTest(lnPermissions, 0) ?? "Read " ENDIF IF BitTest(lnPermissions, 1) ?? "Write " ENDIF IF BitTest(lnPermissions, 2) ?? "Create " ENDIF IF BitTest(lnPermissions, 3) ?? "Execute " ENDIF IF BitTest(lnPermissions, 4) ?? "Delete " ENDIF IF BitTest(lnPermissions, 5) ?? "ChangeAttributes " ENDIF IF BitTest(lnPermissions, 6) ?? "ChangeACL " ENDIF *-- Extract the ID for this file. * This ID is generated when the file is opened and * can be used as parameter for the NetFileGetInfo * Win32 API function. lnID = GetMemoryDWORD(lnpFileInfo) ? "ID for NetFileGetInfo():", lnID ENDFOR *-- Free the memory allocated by NetFileEnum IF lnBufferPointer <> 0 NetApiBufferFree(lnBufferPointer) ENDIF ELSE ? "Error", lnError llContinue = .f. ENDIF ENDDO ENDPROC *-- * Get the OS Version and platform *-- PROCEDURE GetOSVersion LParameter m.major, m.minor, m.platform, m.build Local m.osversion Declare GetVersionEx IN win32api String @OSVERSIONINFO * The OSVERSIONINFO structure is 148 bytes long. m.osversion = long2str(148) + Replicate(Chr(0), 144) =GetVersionEx(@m.osversion) m.major = str2long(Substr(m.osversion, 5, 4)) m.minor = str2long(Substr(m.osversion, 9, 4)) m.build = str2long(Substr(m.osversion, 13, 4)) m.platform = str2long(Substr(m.osversion, 17, 4)) m.build = BitAnd(m.build, 0xFFFF) ENDPROC *-- * Return a Unicode from a pointer to LPWString *-- FUNCTION GetMemoryLPString LParameter m.nPointer, m.nPlatform Local m.cResult, m.nLPStr, m.nslen m.nLPStr = GetMemoryDWORD(m.nPointer) DECLARE RtlMoveMemory IN Kernel32 String@ dest, Integer src, Integer nsize DECLARE Integer lstrlenW IN Kernel32 Integer src m.nslen = lstrlenW(m.nLPStr) * 2 m.cResult = Replicate(chr(0), m.nslen) RtlMoveMemory(@m.cResult, m.nLPStr, m.nslen) m.cResult = StrConv(StrConv(m.cResult, 6), 2) RETURN m.cResult ENDFUNC *-- * Return Number from a pointer to DWORD *-- FUNCTION GetMemoryDWORD LParameter m.nPointer Local m.cstrDWORD DECLARE RtlMoveMemory IN Kernel32 String@ dest, Integer src, Integer nsize m.cstrDWORD = Replicate(chr(0), 4) RtlMoveMemory(@m.cstrDWORD, m.nPointer, 4) RETURN str2long(m.cstrDWORD) ENDFUNC *-- * Convert a Number intto a binary Long Integer *-- FUNCTION long2str LParameter m.nLong m.nLong = Int(m.nLong) RETURN (chr(bitand(m.nLong,255)) + ; chr(bitand(bitrshift(m.nLong, 8), 255)) + ; chr(bitand(bitrshift(m.nLong, 16), 255)) + ; chr(bitand(bitrshift(m.nLong, 24), 255))) ENDFUNC *-- * Convert a binary Long Integer into a Number *-- FUNCTION str2long LParameter m.cpLong Return (Bitlshift(Asc(Substr(m.cpLong, 4, 1)), 24) + ; Bitlshift(Asc(Substr(m.cpLong, 3, 1)), 16) + ; Bitlshift(Asc(Substr(m.cpLong, 2, 1)), 8) + ; Asc(Substr(m.cpLong, 1, 1))) ENDFUNC