FileUse() *-- For Windows NT Platform (NT 4, NT 2000) * * Modified version of Ramon F. Jaquez * FAQ ID: 7896 * * 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(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' && No servername is specified, local computer used tcServerName = NULL lcServerName = NULL ELSE lcServerName = StrConv(StrConv(tcServerName + Chr(0), 1), 5) ENDIF IF Type('tcBasePath')#'C' && No path is specified, all files tcBasePath = NULL lcBasePath = NULL ELSE lcBasePath = StrConv(StrConv(tcBasePath + Chr(0), 1), 5) ENDIF IF Type('tcUserName')#'C' && No username, all users tcUserName = NULL lcUserName = NULL ELSE lcUserName = StrConv(StrConv(tcUserName + Chr(0), 1), 5) ENDIF LOCAL lnBufferPointer LOCAL lnPreferedMaxLength, lnEntriesRead, lnTotalEntries LOCAL lnResumeHandle, lnError LOCAL loPointersObject LOCAL lnI, lcDll, lnPermissions, lnID LOCAL llContinue, lnpFileInfo, lcFileName LOCAL lnLocks 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. *-- 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))) ENDFUNCnot very well tested