//************************************************************************ //*** FileSystem - Binary file operations for VDF15+. //************************************************************************ //*** Based on original package: akefs.pkg //*** Version: 4.0 //*** (C) NordTeam Gruppen, NOVAX A/S //*** //*** Author......: Allan Kim Eriksen //*** Created.....: 23/08 2001 //************************************************************************ // cFilesystem class with functions and procedures to access binary files. // Filenumbers are not limited to 10 but only to system resources. // Also windows API calls for file copy, file move ect. // This class is for vdf 15 and up. // This class is not limited to 2 GB but can handle filesizes up $7FFFFFFFFFFFFFFF (9 exabyte) //************************************************************************ // Be aware that argument_size has to be larger // than the requested amount of bytes read in the buffer for // BytesFromBinaryFile. //************************************************************************ //************************************************************************ // Constants used for the external functions. //************************************************************************ // fsCreatefile. #IFNDEF GENERIC_READ Define GENERIC_READ for |CI$80000000 Define GENERIC_WRITE for |CI$40000000 Define GENERIC_RANDOM for (GENERIC_READ + GENERIC_WRITE) Define CREATE_NEW for |CI$00000001 Define CREATE_ALWAYS for |CI$00000002 Define OPEN_EXISTING for |CI$00000003 Define OPEN_ALWAYS for |CI$00000004 Define TRUNCATE_EXISTING for |CI$00000005 #ENDIF #IFNDEF FILE_ATTRIBUTE_NORMAL Define FILE_ATTRIBUTE_NORMAL for |CI$00000080 #ENDIF #IFNDEF FILE_SHARE_READ Define FILE_SHARE_READ for |CI$1 Define FILE_SHARE_WRITE for |CI$2 Define FILE_SHARE_RANDOM for (FILE_SHARE_READ + FILE_SHARE_WRITE) #ENDIF // Generel. Define FNULL for |CI$0 // FormatString. #IFNDEF FORMAT_MESSAGE_ALLOCATE_BUFFER Define FORMAT_MESSAGE_ALLOCATE_BUFFER for |CI$0100 Define FORMAT_MESSAGE_IGNORE_INSERTS for |CI$0200 Define FORMAT_MESSAGE_FROM_STRING for |CI$0400 Define FORMAT_MESSAGE_FROM_HMODULE for |CI$0800 Define FORMAT_MESSAGE_FROM_SYSTEM for |CI$1000 Define FORMAT_MESSAGE_ARGUMENT_ARRAY for |CI$2000 Define FORMAT_MESSAGE_MAX_WIDTH_MASK for |CI$00FF #ENDIF // SetFilePosition. #IFNDEF FILE_BEGIN Define FILE_BEGIN for 0 Define FILE_CURRENT for 1 Define FILE_END for 2 Define INVALID_SET_FILE_POINTER for |CI$FFFFFFFF #ENDIF // FindFile. #IFNDEF INVALID_HANDLE_VALUE Define INVALID_HANDLE_VALUE For |CI-1 Define INVALID_FILE_SIZE for |CI$FFFFFFFF #ENDIF #IFNDEF ERROR_NO_MORE_FILES Define ERROR_NO_MORE_FILES for |CI18 Define ERROR_MOD_NOT_FOUND for |CI126 #ENDIF #IFNDEF MAX_PATH Define MAX_PATH for 260 #ENDIF #IFNDEF FILE_ATTRIBUTE_READONLY Define FILE_ATTRIBUTE_READONLY for |CI$01 Define FILE_ATTRIBUTE_HIDDEN For |CI$02 Define FILE_ATTRIBUTE_SYSTEM For |CI$04 Define FILE_ATTRIBUTE_DIRECTORY for |CI$10 Define FILE_ATTRIBUTE_ARCHIVE For |CI$20 Define FILE_ATTRIBUTE_NORMAL For |CI$80 Define FILE_ATTRIBUTE_TEMPORARY for |CI$100 Define FILE_ATTRIBUTE_SPARSE_FILE for |CI$200 Define FILE_ATTRIBUTE_REPARSE_POINT for |CI$400 Define FILE_ATTRIBUTE_COMPRESSED for |CI$800 Define FILE_ATTRIBUTE_OFFLINE for |CI$1000 Define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED for |CI$2000 Define FILE_ATTRIBUTE_ENCRYPTED for |CI$4000 #ENDIF // Flags for tsVS_FIXEDFILEINFO.dwFileFlags. #IFNDEF VS_FF_DEBUG Define VS_FF_DEBUG for |CI$01 Define VS_FF_INFOINFERRED for |CI$10 Define VS_FF_PATCHED for |CI$04 Define VS_FF_PRERELEASE for |CI$02 Define VS_FF_PRIVATEBUILD for |CI$08 Define VS_FF_SPECIALBUILD for |CI$20 #ENDIF // Flags for tsVS_FIXEDFILEINFO.dwFileOS. #IFNDEF VOS_DOS Define VOS_DOS for |CI$10000 Define VOS_NT for |CI$40000 Define VOS_WINDOWS16 for |CI$00001 Define VOS_WINDOWS32 for |CI$00004 Define VOS_OS216 for |CI$20000 Define VOS_OS232 for |CI$30000 Define VOS_PM16 for |CI$00002 Define VOS_PM32 for |CI$00003 Define VOS_UNKNOWN for |CI$00000 #ENDIF // Flags for tsVS_FIXEDFILEINFO.dwFileType. #IFNDEF VFT_APP Define VFT_APP for |CI$01 Define VFT_DLL for |CI$02 Define VFT_DRV for |CI$03 Define VFT_FONT for |CI$04 Define VFT_STATIC_LIB for |CI$07 Define VFT_UNKNOWN for |CI$00 Define VFT_VXD for |CI$05 #ENDIF // Flags for tsVS_FIXEDFILEINFO.dwFileSubtype if tsVS_FIXEDFILEINFO.dwFileType = VFT_DRV. #IFNDEF VFT2_DRV_COMM Define VFT2_DRV_COMM for |CI$0A Define VFT2_DRV_DISPLAY for |CI$04 Define VFT2_DRV_INSTALLABLE for |CI$08 Define VFT2_DRV_KEYBOARD for |CI$02 Define VFT2_DRV_LANGUAGE for |CI$03 Define VFT2_DRV_MOUSE for |CI$05 Define VFT2_DRV_NETWORK for |CI$06 Define VFT2_DRV_PRINTER for |CI$01 Define VFT2_DRV_SOUND for |CI$09 Define VFT2_DRV_SYSTEM for |CI$07 Define VFT2_DRV_VERSIONED_PRINTER for |CI$0C #ENDIF // Flags for tsVS_FIXEDFILEINFO.dwFileSubtype if tsVS_FIXEDFILEINFO.dwFileType = VFT_FONT. #IFNDEF VFT2_FONT_RASTER Define VFT2_FONT_RASTER for |CI$01 Define VFT2_FONT_TRUETYPE for |CI$03 Define VFT2_FONT_VECTOR for |CI$02 #ENDIF #IFNDEF VFT2_UNKNOWN Define VFT2_UNKNOWN for |CI$00 #ENDIF Define FS_FILEHANDLEMISSING for "The filehandle does not exists for the current filenumber." // Filesearch Enum_List Define DIRMODE_FILES_ONLY For 1 Define DIRMODE_DIRECTORIES_ONLY Define DIRMODE_FILES_AND_DIRECTORIES End_Enum_List //************************************************************************ // Declarations of external functions. // Functions that needs variables for output are made global stings or // integers, and can be found on top of the declaration. //************************************************************************ External_Function fsCreatefile "CreateFileA" kernel32.dll ; Pointer lpFile ; //filename DWord dwDesAccess ; // access mode DWord dwShare ; // share mode Pointer lpSecAtt ; // SD DWord dwCrDisp ; // how to create DWord dwFlags ; // file attributes Handle hTempFile ; // handle to template fil Returns Integer //Returns handle that can be used to access the object External_Function fsGetLastError "GetLastError" kernel32.dll Returns Integer External_Function fsFormatMessage "FormatMessageA" kernel32.dll ; DWord dwFlags ; // source and processing options Pointer lpSrc ; // message source DWord dwMsgId ; // message identifier DWord dwLngId ; // language identifier Pointer lpBuf ; // message buffer DWord nSize ; // maximum size of message buffer Pointer Arg ; // array of message inserts Returns Integer External_Function fsLocalFree "LocalFree" kernel32.dll ; Handle hMem ; // A handle to the local memory object. Returns Integer External_Function fsCloseHandle "CloseHandle" kernel32.dll ; Handle hObject ; // handle to object Returns Integer External_Function fsReadFile "ReadFile" kernel32.dll ; Handle hFile ; // handle to file Pointer lpBuffer ; // data buffer DWord nBytesToRead ; // number of bytes to read Pointer lpBytesRead ; // number of bytes read Pointer lpOverlapped ; // overlapped buffer Returns Integer External_Function fsWriteFile "WriteFile" kernel32.dll ; Handle hFile ; // handle to file Pointer lpBuf ; // data buffer DWord nNumBytesWrt ; // number of bytes to write Pointer lpNumBytesWritten ; // number of bytes written Pointer lpOverlapped ; // overlapped buffer Returns Integer External_Function fsGetFileSizeEx "GetFileSizeEx" kernel32.dll ; Handle hFile ; // handle to file Pointer lpFileSizeHigh ; // A pointer to a LARGE_INTEGER structure that receives the file size, in bytes. Returns Integer External_Function fsSetFilePointer "SetFilePointer" kernel32.dll ; Handle hFile ; // handle to file UInteger lDistanceToMove ; // The low order 32-bits of a signed value that specifies the number of bytes to move the file pointer. Pointer lpDistanceToMoveHigh ; // A pointer to the high order 32-bits of the signed 64-bit distance to move. DWord dwMoveMethod ; // The starting point for the file pointer move. Returns UInteger External_Function fsSetEndOfFile "SetEndOfFile" kernel32.dll ; Handle hFile ; // handle to the file to have its EOF position moved. Returns Integer // nonzero if success External_Function fsDeleteFile "DeleteFileA" Kernel32.Dll ; Pointer lpFileName ; // Pointer to a null-terminated string that specifies the file to be deleted. Returns Integer External_Function fsMoveFile "MoveFileA" Kernel32.Dll ; Pointer lpExistingFileName ; // Pointer to a null-terminated string that names an existing file or directory. Pointer lpNewFileName ; // Pointer to a null-terminated string that specifies the new name of a file or directory. Returns Integer // The new name must Not already exist. A new File may be on A different File system Or drive. A new directory must be on the same drive. External_Function fsCopyFile "CopyFileA" Kernel32.Dll ; Pointer lpExistingFileName ; // Pointer to a null-terminated string that specifies the name of an existing file. Pointer lpNewFileName ; // Pointer to a null-terminated string that specifies the name of the new file. Boolean bFailIfExists ; // If bFailIfExists is TRUE and the new file specified by lpNewFileName already exists, the function fails. Returns Integer // If bFailIfExists is FALSE and the new file already exists, the function overwrites the existing file and succeeds. External_Function fsFindFirstFile "FindFirstFileA" Kernel32.Dll ; Pointer lpFileName ; // Pointer to a null-terminated string that specifies a valid directory or path and file name, which can contain wildcard characters (* and ?). Pointer lpWin32_Find_Data ; // Pointer to the WIN32_FIND_DATA structure that receives information about the found file or subdirectory. Returns Integer External_Function fsFindNextFile "FindNextFileA" Kernel32.Dll ; Handle hFindFile ; // handle returned by a previous call to the FindFirstFile function. Pointer lpWin32_Find_Data ; // Pointer to the WIN32_FIND_DATA structure that receives information about the found file or subdirectory. Returns Integer External_Function fsFindClose "FindClose" Kernel32.dll ; Handle hFindFile ; // File search handle. This handle must have been previously opened by the FindFirstFile function. Returns Integer External_Function fsFileTimeToSystemTime "FileTimeToSystemTime" Kernel32.dll ; Pointer lpFiletime ; // Pointer to a FILETIME structure containing the file time to convert to system date and time format. Pointer lpSystemtime ; // Pointer to a SYSTEMTIME structure to receive the converted file time. Returns Integer External_Function fsSystemTimeToTzSpecificLocalTime "SystemTimeToTzSpecificLocalTime" Kernel32.dll ; Pointer lpTimeZone ; // A pointer to a TIME_ZONE_INFORMATION structure that specifies the time zone of interest. Pointer lpUniversalTime ; // A pointer to a SYSTEMTIME structure that specifies a time, in UTC. Pointer lpLocalTime ; // A pointer to a SYSTEMTIME structure that receives the local time. Returns Integer External_Function fsGetTempFileName "GetTempFileNameA" kernel32.dll ; Pointer sPathname ; Pointer sPrefixString ; Integer iUnique ; Pointer sTempFileName ; Returns Integer External_Function fsGetTempPath "GetTempPathA" Kernel32.Dll ; Integer nBufferLength ; Pointer lpBuffer ; Returns Integer External_Function fsCreateDirectory "CreateDirectoryA" Kernel32.dll ; Pointer lpDirName ; // Pointer to a null-terminated string that specifies the path of the directory to be created. Pointer lpSecAttributes ; // Pointer to a SECURITY_ATTRIBUTES structure. Returns Integer External_Function fsRemoveDirectory "RemoveDirectoryA" Kernel32.dll ; Pointer lpDirName ; // Pointer to a null-terminated string that specifies the path of the directory to be removed. Returns Integer External_Function fsExtractAssociatedIcon "ExtractAssociatedIconA" shell32.dll ; Handle hInst ; Pointer lpIconPath ; Integer lpiIcon ; Returns Handle External_Function fsDestroyIcon "DestroyIcon" User32.dll ; Handle hIcon ; Returns Integer External_Function fsGetFileVersionInfoSize "GetFileVersionInfoSizeA" Version.dll ; Pointer lpFilename ; // The name of the file of interest. The function uses the search sequence specified by the LoadLibrary function. Pointer lpHandle ; // A pointer to a variable that the function sets to zero. Returns UInteger External_Function fsGetFileVersionInfo "GetFileVersionInfoA" Version.dll ; Pointer lpFilename ; // The name of the file. If a full path is not specified, the function uses the search sequence specified by the LoadLibrary function. DWord dwHandle ; // This parameter is ignored. DWord dwLen ; // The size, in bytes, of the buffer pointed to by the lpData parameter. Pointer lpData ; // Pointer to a buffer that receives the file-version information. Returns Boolean External_Function fsVerQueryValue "VerQueryValueA" Version.dll ; Pointer lpBlock ; // The version-information resource returned by the GetFileVersionInfo function. Pointer lpSubBlock ; // The version-information value to be retrieved. Pointer lpBuffer ; // When this method returns, contains the address of a pointer to the requested version information in the buffer pointed to by lpBlock. Pointer lpLen ; // When this method returns, contains a pointer to the size of the requested data pointed to by lpBuffer. Returns Boolean //************************************************************************ // Structures //************************************************************************ Struct structWFD // Used by FindFirstFile DWord dwFileAttributes UBigInt ftCreationDateTime UBigInt ftLastAccessDateTime UBigInt ftLastWriteDateTime UInteger nFileSizeHigh UInteger nFileSizeLow DWord dares DWord dbres UChar[MAX_PATH] cFileName UChar[14] cAlternateFileName End_Struct Struct structSystemTime UShort wYear UShort wMonth UShort wDayOfWeek UShort wDay UShort wHour UShort wMinute UShort wSecond UShort wMillieseconds End_Struct Struct structFile Handle hFilehandle String sFilename // Assigned filename in OEM format. Boolean bEndOfFile // True then the end of the binary file had been read. End_Struct Struct structFileBufferPointer Integer iBufferPointer Integer iBufferSize BigInt biFromFilePosition End_Struct Struct tsSearchResult String sFilename String sAlternateFileName // 8.3 format DateTime dtCreationDateTime DateTime dtLastAccessDateTime DateTime dtLastWriteDateTime BigInt biFileSize Integer iFileAttributes End_Struct Struct tsVS_FIXEDFILEINFO DWord dwSignature DWord dwStrucVersion DWord dwFileVersionMS DWord dwFileVersionLS DWord dwProductVersionMS DWord dwProductVersionLS DWord dwFileFlagsMask DWord dwFileFlags DWord dwFileOS DWord dwFileType DWord dwFileSubtype // DWord dwFileDateMS // DWord dwFileDateLS UBigInt ubiFileDate End_Struct Struct tsFileVersionInfo tsVS_FIXEDFILEINFO lsFIXEDFILEINFO Short[] siFileVersion Short[] siProductVersion DateTime dtCreationDateTime String sComments String sCompanyName String sFileDescription String sFileVersion String sInternalName String sLegalCopyright String sLegalTrademarks String sOriginalFilename String sProductName String sProductVersion String sPrivateBuild String sSpecialBuild End_Struct Struct tsLandAndCodePage UShort wLanguage UShort wCodePage End_Struct Register_Function FileErrorText Integer iFilenumber Returns String //************************************************************************ // The filesystem class //************************************************************************ Class cFilesystem is a cObject Procedure Construct_Object Forward Send Construct_Object // True then the end of the binary file had been read - not when $1A (EOF) is met. // Legacy property. Use the BinaryFileEndOfFile function instead. Property Boolean pbEOF False // True if any error has occured during fileoprerations. Property Boolean pbError False // If errormessages should be called with dataflex error command set this to true Property Boolean pbErrorAsVDFError False // Keeps assigned handles and filenames for each filenumber. // private Property structFile[] plsFile // Keeps read cached buffers for each filenumer. Used for BinaryReadChcheu // private Property String[] psaCachedBuffer // Pointers for cached buffers. // private Property structFileBufferPointer[] plsCachedPointer End_Procedure // Returns the next available filenumber for a binary file. Function BinaryFileNextFilenumber Returns Integer structFile[] lsFile Integer iMaxFiles iCurrentFile iNextFileNumber Get plsFile to lsFile Move (SizeOfArray(lsFile)) to iMaxFiles Move -1 to iNextFileNumber Move 0 to iCurrentFile While (iCurrentFile < iMaxFiles and iNextFileNumber = -1) If (lsFile[iCurrentFile].hFilehandle = 0) Move iCurrentFile to iNextFileNumber Else Increment iCurrentFile Loop If (iNextFileNumber = -1) Move iMaxFiles to iNextFileNumber Function_Return iNextFileNumber End_Function // Opens a binary file. // If bShared is false or not pharsed the file is opened in exclusive. // If bShared is True the file is opened with both read and write shared mode // If bCreate is True the file is created if it does not exist already. // If bReadOnly is True the file is opened with only read access (and only read shared mode if bShared is also true). // Returns true if the file was opened or created without error. Function BinaryFileOpen Integer iFilenumber String sFilename Boolean bShared Boolean bCreate Boolean bReadOnly Returns Boolean Pointer lpFilenamePointer Integer iReturnValue iErrornumber DWord dwSharedMode dwCreateMode dwAccessMode structFile[] lsFile String sFilenameANSI Boolean bOk bFilehandleOK Get plsFile to lsFile If (iFilenumber < SizeOfArray(lsFile)) Begin If (lsFile[iFilenumber].hFilehandle = 0) Move True to bFilehandleOK End Else Move True to bFilehandleOK If bFilehandleOK Begin Move sFilename to lsFile[iFilenumber].sFilename Move (ToAnsi(sFilename)) to sFilenameANSI Set pbError to False Move False to bOk Move GENERIC_RANDOM to dwAccessMode Move FNULL to dwSharedMode If (num_arguments > 2) Begin If (bShared = True) Move FILE_SHARE_RANDOM to dwSharedMode End Move OPEN_EXISTING to dwCreateMode If (num_arguments > 3) Begin If (bCreate = True) Move OPEN_ALWAYS to dwCreateMode End If (num_arguments > 4) Begin If (bReadOnly = True) Begin Move GENERIC_READ to dwAccessMode If (bShared = True) Move FILE_SHARE_READ to dwSharedMode End End Append sFilenameANSI (Character(0)) (Character(0)) Move (fsCreatefile(AddressOf(sFilenameANSI), dwAccessMode, dwSharedMode, FNULL, dwCreateMode, FILE_ATTRIBUTE_NORMAL, FNULL)) to iReturnValue If (iReturnValue = INVALID_HANDLE_VALUE) Begin Move (fsGetLastError()) to iErrornumber If iErrornumber Send DoShowError iErrornumber ("File: "+ sFilename) End Else Begin Move iReturnValue to lsFile[iFilenumber].hFilehandle Move False to lsFile[iFilenumber].bEndOfFile Set plsFile to lsFile Set pbEOF to False Move True to bOk End End Else Begin Send warning_box "The filenumber is already used." End Function_Return bOk End_Function // Closing a binary file // Returns true if the file could be closed. Function BinaryFileClose Integer iFilenumber Returns Boolean Integer iRetVal iErrorNumber Handle hHandle structFile[] lsFile structFileBufferPointer[] lsFileBufferPointer String[] saCachedBuffer Boolean bOk Get BinaryFileHandle iFilenumber to hHandle Set pbError to False Move False to bOk If hHandle Begin Move (fsCloseHandle(hHandle)) to iRetVal If (iRetVal = 0) Begin // Could not close Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber (FileErrorText(Self, iFilenumber)) End Else Begin Get plsFile to lsFile Get plsCachedPointer to lsFileBufferPointer Get psaCachedBuffer to saCachedBuffer Move 0 to lsFile[iFilenumber].hFilehandle Move "" to saCachedBuffer[iFilenumber] Move 1 to lsFileBufferPointer[iFilenumber].iBufferPointer Move 0 to lsFileBufferPointer[iFilenumber].iBufferSize Move 0 to lsFileBufferPointer[iFilenumber].biFromFilePosition Set plsFile to lsFile Set plsCachedPointer to lsFileBufferPointer Set psaCachedBuffer to saCachedBuffer Move True to bOk End End Function_Return bOk End_Function // Reading from a binary file. // The data read from the file is placed in sReadBuffer and the function returns the number of bytes read. // Then the function returns 0 the end of file has been reached (pbEOF will then be true) or an error has occured (pbError will then be true). // No errors occures if you try to read past end of file. // To speed up reading process you should read in a block of data at a time (i.e. iNumberOfBytes = 2000) instead of // reading one byte at a time. No errors occures if you try to read past end // of file. Note that iNumberOfBytes must not exceed the argument size. Function BinaryFileRead Integer iFilenumber Integer iNumberOfBytes String ByRef sReadBuffer Returns Integer Handle hFileHandle Integer iBytesRead iMaxBuffer iErrorNumber Boolean bOk structFile[] lsFile Set pbError to False Move 0 to iBytesRead Get_Argument_Size to iMaxBuffer If (iNumberOfBytes > iMaxBuffer) Begin Send warning_box "Blocksize to read exceeds argument size!" Function_Return iBytesRead End If (iNumberOfBytes < 1) Begin Send warning_box "Number of bytes to read can not be less than one." Function_Return iBytesRead End Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin ZeroString iNumberOfBytes to sReadBuffer Move (fsReadFile(hFileHandle, AddressOf(sReadBuffer), iNumberOfBytes, (AddressOf(iBytesRead)), FNULL)) to bOk If (bOk = False) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber (FileErrorText(Self, iFilenumber)) End Else Begin If (iBytesRead = 0 or iBytesRead <> iNumberOfBytes) Begin Get plsFile to lsFile Move True to lsFile[iFilenumber].bEndOfFile Set plsFile to lsFile Set pbEOF to True Move (Left(sReadBuffer, iBytesRead)) to sReadBuffer End End End Else Send warning_box FS_FILEHANDLEMISSING Function_Return iBytesRead End_Function // Reading from a binary file until a string of bytes are matched. // The data read from the file is placed in the sReturnBuffer and the function returns the number of bytes read until the match is read including the match. // Then the function returns 0 the end of file has been reached (pbEOF will then be true) or an error has occured (pbError will then be true). // The return string buffer would also be empty. // No errors occures if you try to read past end of file. // To speed up reading process the buffer will be read in sizes of the current argument_size. Function BinaryFileReadCachedUntilMatch Integer iFilenumber String sMatchString String ByRef sReturnBuffer Boolean ByRef bEndOfFile Returns Integer Handle hFileHandle Integer iBuffersize iMatchPos iLengthMatch String sByte structFile[] lsFile structFileBufferPointer[] lsFileBufferPointer String[] saCachedBuffer Get plsFile to lsFile Move "" to sReturnBuffer Move 1 to iMatchPos If (iFilenumber < SizeOfArray(lsFile)) Begin Move lsFile[iFilenumber].hFilehandle to hFileHandle If (hFileHandle <> 0) Begin Move (Length(sMatchString)) to iLengthMatch Get plsCachedPointer to lsFileBufferPointer Get psaCachedBuffer to saCachedBuffer If (iFilenumber >= SizeOfArray(lsFileBufferPointer)) Begin Move 1 to lsFileBufferPointer[iFilenumber].iBufferPointer Move "" to saCachedBuffer[iFilenumber] End Repeat If (lsFileBufferPointer[iFilenumber].iBufferPointer > lsFileBufferPointer[iFilenumber].iBufferSize) Begin Get_Argument_Size to iBuffersize Get BinaryFilePosition iFilenumber to lsFileBufferPointer[iFilenumber].biFromFilePosition Get BinaryFileRead iFilenumber iBuffersize (&saCachedBuffer[iFilenumber]) to lsFileBufferPointer[iFilenumber].iBufferSize Move 1 to lsFileBufferPointer[iFilenumber].iBufferPointer Set psaCachedBuffer to saCachedBuffer End If (lsFileBufferPointer[iFilenumber].iBufferPointer =< lsFileBufferPointer[iFilenumber].iBufferSize) Begin Move (Mid(saCachedBuffer[iFilenumber], 1, lsFileBufferPointer[iFilenumber].iBufferPointer)) to sByte Increment lsFileBufferPointer[iFilenumber].iBufferPointer Move (sReturnBuffer + sByte) to sReturnBuffer If (sByte = Mid(sMatchString, 1, iMatchPos)) Begin Increment iMatchPos End Else Begin Move 1 to iMatchPos End End Until (iMatchPos > iLengthMatch or lsFileBufferPointer[iFilenumber].iBufferSize = 0) Set plsCachedPointer to lsFileBufferPointer If (lsFileBufferPointer[iFilenumber].iBufferSize = 0) Begin Move lsFile[iFilenumber].bEndOfFile to bEndOfFile End End Else Send warning_box FS_FILEHANDLEMISSING End Function_Return (Length(sReturnBuffer)) End_Function // Reading from a binary file as CSV file for next text field. // The data read from the file is placed in the sReturnBuffer excluding the separator and the function returns true. // Then the function returns false the end of file has been reached (pbEOF will then be true) or an error has occured (pbError will then be true). // When the end of row data has been read the bEndOfRow is set true. // The end of row is indicated with sCharEOL. If that is not applied the charactersequence character(13) + character(10) is used. // The return string buffer would also be empty. // No errors occures if you try to read past end of file. // To speed up reading process the buffer will be read in sizes of the current argument_size. Function BinaryFileReadCachedCSV Integer iFilenumber String sFieldseparator String sTextQualification String ByRef sReturnBuffer Boolean ByRef bEndOfRow Boolean ByRef bEndOfFile String sCharEOL Returns Integer Handle hFileHandle Integer iLengthSeparator iLengthTextQualification iEOLLength iTestLength String sByte sEOL sTestBuffer structFile[] lsFile structFileBufferPointer[] lsFileBufferPointer String[] saCachedBuffer Boolean bInTextFieldMode bTextFieldReady bFieldSeparator bTextQualificator bEscapeTextQualificatorTest bByteOk BigInt biAfterTextQualificator Get plsFile to lsFile If (num_arguments > 6) Begin Move sCharEOL to sEOL End Else Begin Move ((Character(13))+(character(10))) to sEOL End Move (Length(sEOL)) to iEOLLength Move "" to sReturnBuffer Move "" to sByte Move False to bInTextFieldMode Move False to bTextFieldReady Move False to bEndOfRow Move False to bTextQualificator If (iFilenumber < SizeOfArray(lsFile)) Begin Move lsFile[iFilenumber].hFilehandle to hFileHandle If (hFileHandle <> 0) Begin Move (Length(sFieldseparator)) to iLengthSeparator Move (Length(sTextQualification)) to iLengthTextQualification Get plsCachedPointer to lsFileBufferPointer Get psaCachedBuffer to saCachedBuffer If (iFilenumber >= SizeOfArray(lsFileBufferPointer)) Begin Move 1 to lsFileBufferPointer[iFilenumber].iBufferPointer Move "" to saCachedBuffer[iFilenumber] End Repeat Get NextByteCSV (&iFilenumber) (&lsFileBufferPointer[iFilenumber]) (&saCachedBuffer) (&sByte) to bByteOk If bByteOk Begin Move (sReturnBuffer + sByte) to sReturnBuffer Move (Right(sReturnBuffer, iLengthSeparator) = sFieldseparator) to bFieldSeparator If bFieldSeparator Begin Move (Left(sReturnBuffer, (Length(sReturnBuffer) - iLengthSeparator))) to sReturnBuffer Move True to bTextFieldReady Move False to bEscapeTextQualificatorTest End If (not(bTextFieldReady)) Begin Move (Right(sReturnBuffer, iEOLLength) = sEOL) to bEndOfRow If bEndOfRow Begin Move (Left(sReturnBuffer, (Length(sReturnBuffer) - iEOLLength))) to sReturnBuffer Move True to bTextFieldReady End End If (not(bTextFieldReady)) Begin Move (Right(sReturnBuffer, iLengthTextQualification) = sTextQualification) to bTextQualificator If bTextQualificator Begin // Read until end of text field. Place filepointer after text field. Move True to bInTextFieldMode Move (Left(sReturnBuffer, (Length(sReturnBuffer) - iLengthTextQualification))) to sReturnBuffer Repeat Get NextByteCSV (&iFilenumber) (&lsFileBufferPointer[iFilenumber]) (&saCachedBuffer) (&sByte) to bByteOk If bByteOk Begin Move (sReturnBuffer + sByte) to sReturnBuffer Move (Right(sReturnBuffer, iLengthTextQualification) = sTextQualification) to bTextQualificator If bTextQualificator Begin // Either it is the end of the text field or the escape text qualificator has been read. // Read ahead to a new buffer to see if the next bytes are the text qualificator. // If it is, add the new buffer to the return buffer. // If not, restore the filebuffer to this position and mark the text field ended. Move (Left(sReturnBuffer, (Length(sReturnBuffer) - iLengthTextQualification))) to sReturnBuffer Set plsCachedPointer to lsFileBufferPointer Get BinaryFileCachedPosition iFilenumber to biAfterTextQualificator Move "" to sTestBuffer Move 0 to iTestLength Move True to bEscapeTextQualificatorTest Repeat Get NextByteCSV (&iFilenumber) (&lsFileBufferPointer[iFilenumber]) (&saCachedBuffer) (&sByte) to bByteOk If bByteOk Begin Move (sTestBuffer + sByte) to sTestBuffer Increment iTestLength If (Left(sTextQualification, iTestLength) = sTestBuffer) Begin If (iTestLength = iLengthTextQualification) Begin Move (sReturnBuffer + sTestBuffer) to sReturnBuffer Move False to bEscapeTextQualificatorTest End End Else Begin Set BinaryFileChachedPosition iFilenumber to biAfterTextQualificator Get plsCachedPointer to lsFileBufferPointer Move False to bEscapeTextQualificatorTest Move False to bInTextFieldMode End End Until (bEscapeTextQualificatorTest = False or lsFileBufferPointer[iFilenumber].iBufferSize = 0 or bByteOk = False) End End Until (bInTextFieldMode = False or lsFileBufferPointer[iFilenumber].iBufferSize = 0 or bByteOk = False) End End End Until (bTextFieldReady = True or lsFileBufferPointer[iFilenumber].iBufferSize = 0 or bByteOk = False) Set plsCachedPointer to lsFileBufferPointer If (lsFileBufferPointer[iFilenumber].iBufferSize = 0) Begin Move lsFile[iFilenumber].bEndOfFile to bEndOfFile If (bEndOfFile = True) Begin Move True to bTextFieldReady Move True to bEndOfRow End End End Else Send warning_box FS_FILEHANDLEMISSING End Function_Return bTextFieldReady End_Function {Visibility = Private} Function NextByteCSV Integer ByRef iFilenumber structFileBufferPointer ByRef lsFileBufferPointer String[] ByRef saCachedBuffer String ByRef sByte Returns String Integer iBufferSize Boolean bOk If (lsFileBufferPointer.iBufferPointer > lsFileBufferPointer.iBufferSize) Begin Get_Argument_Size to iBufferSize Get BinaryFilePosition iFilenumber to lsFileBufferPointer.biFromFilePosition Get BinaryFileRead iFilenumber iBufferSize (&saCachedBuffer[iFilenumber]) to lsFileBufferPointer.iBufferSize Move 1 to lsFileBufferPointer.iBufferPointer Set psaCachedBuffer to saCachedBuffer End If (lsFileBufferPointer.iBufferPointer <= lsFileBufferPointer.iBufferSize) Begin Move (Mid(saCachedBuffer[iFilenumber], 1, lsFileBufferPointer.iBufferPointer)) to sByte Increment lsFileBufferPointer.iBufferPointer Move True to bOk End Function_Return bOk End_Function // Shortcut to read a binary file as lines from a textfile. // Reads from cached file until sCharEOL are recieved. // Data is returned without the ending sCharEOL // If sCharEOL is not applied the charactersequence character(13) + character(10) is used. // Returns True when the line has been read. Function BinaryFileReadCachedLN Integer iFilenumber String ByRef sLine Boolean ByRef bEndOfFile String sCharEOL Returns Boolean Boolean bEndOfRow Integer iBytesRead iEOLLength String sEOL If (num_arguments > 3) Begin Move sCharEOL to sEOL End Else Begin Move ((Character(13))+(character(10))) to sEOL End Move (Length(sEOL)) to iEOLLength Get BinaryFileReadCachedUntilMatch iFilenumber sEOL (&sLine) (&bEndOfFile) to iBytesRead If (iBytesRead > 0) Begin If (Right(sLine, iEOLLength) = sEOL) Begin Move (Left(sLine, (Length(sLine) - iEOLLength))) to sLine Move True to bEndOfRow End End Function_Return bEndOfRow End_Function // Writing to a binary file. // Returns true if the data was written to the file without error. Function BinaryFileWrite Integer iFilenumber String ByRef sWriteData Returns Boolean Integer iBytesWritten iBytesToWrite iErrorNumber Handle hFileHandle Boolean bOk Set pbError to False Move False to bOk Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin Move 0 to iBytesWritten Move (Length(sWriteData)) to iBytesToWrite Move (fsWriteFile(hFileHandle, AddressOf(sWriteData), iBytesToWrite, AddressOf(iBytesWritten), FNULL)) to bOk If (bOk = False) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber (FileErrorText(Self, iFilenumber)) End If (iBytesToWrite <> iBytesWritten) Begin Send Warning_box "Not all data could be written!" Move False to bOk End End Else Send warning_box FS_FILEHANDLEMISSING Function_Return bOk End_Function // Write HEX values to a binary file as bytes. // HEX values in sWriteHEX are first coverted to bytes and then written // to the binary file. // Returns true if the HEX data was written to the file without error. Function BinaryFileWriteHex Integer iFilenumer String ByRef sWriteHex Returns Boolean String sData Integer iLength iCount iByte Boolean bOk Move (Length(sWritehex)) to iLength Move 1 to iCount While (iCount < iLength) Move ("$"+Mid(sWriteHex, 2, iCount)) to iByte Move (iCount + 2) to iCount Move (sData + Character(iByte)) to sData Loop Get BinaryFileWrite iFilenumer (&sData) to bOk Function_Return bOk End_Function // Retrives the file size from a binary file. Function BinaryFileSize Integer iFilenumber Returns BigInt BigInt biFilesize Handle hFileHandle Boolean bOk Integer iErrorNumber Set pbError to False Move -1 to biFilesize Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin // The LARGE_INTEGER structure has the same structure as a BigInt. Move (fsGetFileSizeEx(hFileHandle, AddressOf(biFilesize))) to bOk If (bOk = -False) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber (FileErrorText(Self, iFilenumber)) End End Else Send warning_box FS_FILEHANDLEMISSING Function_Return biFilesize End_Function // Retrives the file position from a binary file. // Returns -1 if an error occured. Function BinaryFilePosition Integer iFilenumber Returns BigInt BigInt biFilePosition biBigHi Handle hFileHandle Boolean bOk Integer iErrorNumber iLo iHi UInteger iNewPos Set pbError to False Move -1 to biFilePosition Move 0 to iHi Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin Move (2^32) to biBigHi Move (fsSetFilePointer(hFileHandle, ilo, AddressOf(iHi), FILE_CURRENT)) to iNewPos If (iNewPos = (biBigHi - 1)) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber (FileErrorText(Self, iFilenumber)) Else Move True to bOk End Else Move True to bOk If bOk Begin Move ((iHi * biBigHi) + iNewPos) to biFilePosition End End Else Send warning_box FS_FILEHANDLEMISSING Function_Return biFilePosition End_Function // Sets the file position from a binary file to a new position. Procedure Set BinaryFilePosition Integer iFilenumber BigInt biPosition Handle hFileHandle Integer iHi iErrorNumber UInteger iLo iNewPos Boolean bOk BigInt biFileSize biBigHi structFile[] lsFile Set pbError to False Move False to bOk Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin Move (2^32) to biBigHi Move (biPosition / biBigHi) to iHi Move (biPosition - (iHi * biBigHi)) to iLo Move (fsSetFilePointer(hFileHandle, iLo, AddressOf(iHi), FILE_BEGIN)) to iNewPos If (iNewPos = (biBigHi - 1)) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber (FileErrorText(Self, iFilenumber)) Else Move True to bOk End Else Move True to bOk If bOk Begin Get BinaryFileSize iFilenumber to biFileSize Get plsFile to lsFile If (biFileSize > biPosition) Begin Move False to lsFile[iFilenumber].bEndOfFile Set pbEOF to False End Else Begin Move True to lsFile[iFilenumber].bEndOfFile Set pbEOF to True End Set plsFile to lsFile End End Else Send warning_box FS_FILEHANDLEMISSING Set pbError to (not(bOk)) End_Procedure // Returns -1 if an error occured. Function BinaryFileCachedPosition Integer iFileNumber Returns BigInt BigInt biPosition structFileBufferPointer[] lsFileBufferPointer Handle hFileHandle Move -1 to biPosition Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin Get plsCachedPointer to lsFileBufferPointer If (iFilenumber < SizeOfArray(lsFileBufferPointer)) Begin If (lsFileBufferPointer[iFileNumber].iBufferSize > 0) Begin Move (lsFileBufferPointer[iFileNumber].biFromFilePosition + lsFileBufferPointer[iFileNumber].iBufferPointer - 1) to biPosition End Else Begin Get BinaryFilePosition iFileNumber to biPosition End End Else Begin Get BinaryFilePosition iFileNumber to biPosition End End Else Send warning_box FS_FILEHANDLEMISSING Function_Return biPosition End_Function // Sets the pointer for the current file cache. Procedure Set BinaryFileChachedPosition Integer iFileNumber BigInt biNewPosition Handle hFileHandle structFileBufferPointer[] lsFileBufferPointer String[] saCachedBuffer Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin Get plsCachedPointer to lsFileBufferPointer If (lsFileBufferPointer[iFileNumber].biFromFilePosition > biNewPosition) Begin Move 1 to lsFileBufferPointer[iFileNumber].iBufferPointer Move 0 to lsFileBufferPointer[iFileNumber].iBufferSize Set plsCachedPointer to lsFileBufferPointer Set BinaryFilePosition iFileNumber to biNewPosition Get psaCachedBuffer to saCachedBuffer Move "" to saCachedBuffer[iFileNumber] Set psaCachedBuffer to saCachedBuffer End Else If ((lsFileBufferPointer[iFileNumber].biFromFilePosition + lsFileBufferPointer[iFileNumber].iBufferSize) < biNewPosition) Begin Move 1 to lsFileBufferPointer[iFileNumber].iBufferPointer Move 0 to lsFileBufferPointer[iFileNumber].iBufferSize Set plsCachedPointer to lsFileBufferPointer Set BinaryFilePosition iFileNumber to biNewPosition Get psaCachedBuffer to saCachedBuffer Move "" to saCachedBuffer[iFileNumber] Set psaCachedBuffer to saCachedBuffer End Else Begin Move (biNewPosition - lsFileBufferPointer[iFileNumber].biFromFilePosition + 1) to lsFileBufferPointer[iFileNumber].iBufferPointer Set plsCachedPointer to lsFileBufferPointer End End Else Send warning_box FS_FILEHANDLEMISSING End_Procedure // Truncate or extend a binary file to the specified file position // by setting the binary file End Of File position. // If biPosition is -1 the current file position is used as EOF position. Procedure Set BinaryFileEndOfFile Integer iFilenumber BigInt biPosition Handle hFileHandle Boolean bError bOk Integer iErrorNumber structFile[] lsFile Set pbError to False Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin If (biPosition > -1) Set BinaryFilePosition iFilenumber to biPosition Get pbError to bError If (bError = False) Begin Move (fsSetEndOfFile(hFileHandle)) to bOk If (bOk = False) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber (FileErrorText(Self, iFilenumber)) End Else Begin Get plsFile to lsFile Move True to lsFile[iFilenumber].bEndOfFile Set plsFile to lsFile Set pbEOF to True End End End Else Send warning_box FS_FILEHANDLEMISSING Set pbError to (not(bOk)) End_Procedure // Returns true if the last read from the binary file had reached the end. Function BinaryFileEndOfFile Integer iFilenumber Returns Boolean structFile[] lsFile Handle hFileHandle Boolean bEndOfFile Move True to bEndOfFile Set pbError to False Get BinaryFileHandle iFilenumber to hFileHandle If hFileHandle Begin Get plsFile to lsFile Move lsFile[iFilenumber].bEndOfFile to bEndOfFile End Else Send warning_box FS_FILEHANDLEMISSING Function_Return bEndOfFile End_Function // Returns the filehandle from the filenumber. // Returns 0 if the filenumber is not used. Function BinaryFileHandle Integer iFilenumber Returns Handle Handle hFileHandle structFile[] lsFile Get plsFile to lsFile If (iFilenumber < SizeOfArray(lsFile)) Move lsFile[iFilenumber].hFilehandle to hFileHandle Function_Return hFileHandle End_Function // Searches for a file // iMode = DIRMODE_FILES_ONLY (default) // iMode = DIRMODE_DIRECTORIES_ONLY // iMode = DIRMODE_FILES_AND_DIRECTORIES // Returns True if found Function FileExists String sFilePathMask Integer iFileDirMode Returns Boolean Integer iMode Boolean bFound tsSearchResult[] lsResult Move False to bFound Set pbError to False If (num_arguments < 2) Move DIRMODE_FILES_ONLY to iMode Else Move iFileDirMode to iMode Get FileSearch sFilePathMask iMode True to lsResult If (SizeOfArray(lsResult) > 0) Move True to bFound Function_Return bFound End_Function // Deletes a file. // Returns True if succeeds. Function FileDelete String sFilename Integer iRetryAttempts Returns Boolean Boolean bFound bDeleted Integer iErrorNumber iRetryLeft String sFilenameANSI Set pbError to False If (num_arguments > 1) Move iRetryAttempts to iRetryLeft Else Move 0 to iRetryLeft Get FileExists sFilename to bFound If bFound Begin Repeat Move (ToAnsi(sFilename)) to sFilenameANSI Move (sFilenameANSI+(Character(0))) to sFilenameANSI Move (fsDeleteFile(AddressOf(sFilenameANSI))) to bDeleted If (bDeleted = False) Begin Decrement iRetryLeft If (iRetryLeft <= 0) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber ("Tried to delete file: "+sFilename) End Else Begin Sleep 1 End End Until (bDeleted = True or iRetryLeft <= 0) End Function_Return bDeleted End_Function // Moves a file or directory. // Returns True if succeeds. Function FileMove String sExistingFileName String sNewFileName Integer iRetryAttempts Returns Boolean Boolean bMoved Integer iErrorNumber iRetryLeft String sExistingFilenameANSI sNewFileNameANSI Set pbError to False If (num_arguments > 2) Move iRetryAttempts to iRetryLeft Else Move 0 to iRetryLeft Move (ToAnsi(sExistingFileName)) to sExistingFileNameANSI Move (ToAnsi(sNewFileName)) to sNewFileNameANSI Move (sExistingFilenameANSI+(Character(0))) to sExistingFilenameANSI Move (sNewFileNameANSI+(Character(0))) to sNewFileNameANSI Repeat Move (fsMoveFile(AddressOf(sExistingFilenameANSI), AddressOf(sNewFileNameANSI))) to bMoved If (bMoved = False) Begin Decrement iRetryLeft If (iRetryLeft <= 0) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber ("Tried to move/rename file: "+sExistingFileName+" to "+sNewFileName) End Else Begin Sleep 1 End End Until (bMoved = True or iRetryLeft <= 0) Function_Return bMoved End_Function // Copies a file. Overwriting an existing file by default. // Returns True if succeeds. Function FileCopy String sExistingFileName String sNewFileName Boolean bFailIfExists Integer iRetryAttempts Returns Boolean Boolean bCopied String sExistingFileNameANSI sNewFileNameANSI Boolean bDoNotOverwrite Integer iErrorNumber iRetryLeft Set pbError to False Move (ToAnsi(sExistingFileName)) to sExistingFileNameANSI Move (ToAnsi(sNewFileName)) to sNewFileNameANSI Move (sExistingFileNameANSI+(Character(0))) to sExistingFileNameANSI Move (sNewFileNameANSI+(Character(0))) to sNewFileNameANSI If (Num_Arguments > 2) Move bFailIfExists to bDoNotOverwrite Else Move False to bDoNotOverwrite If (num_arguments > 3) Move iRetryAttempts to iRetryLeft Else Move 0 to iRetryLeft Repeat Move (fsCopyFile(AddressOf(sExistingFileNameANSI), AddressOf(sNewFileNameANSI), bDoNotOverwrite)) to bCopied If (bCopied = False) Begin Decrement iRetryLeft If (iRetryLeft <= 0) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber ("Tried to copy file: "+sExistingFileName+" to "+sNewFileName) End Else Begin Sleep 1 End End Until (bCopied = True or iRetryLeft <= 0) Function_Return bCopied End_Function // Renames a file or directory. // Returns True if succeeds. Function FileRename String sExistingFileName String sNewFileName Integer iRetryAttempts Returns Boolean Boolean bRenamed If (num_arguments > 2) Begin Get FileMove sExistingFileName sNewFileName iRetryAttempts to bRenamed End Else Begin Get FileMove sExistingFileName sNewFileName to bRenamed End Function_Return bRenamed End_Function // Returns the file size of a file. // Returns -1 if an error occured. Function FileSize String sFilename Returns BigInt tsSearchResult[] lsSearchResult Get FileSearch sFilename DIRMODE_FILES_ONLY to lsSearchResult If (SizeOfArray(lsSearchResult) > 0) Function_Return lsSearchResult[0].biFileSize Else Function_Return -1 End_Function // Returns the last write date of a file. // Returns 0 if an error occured. Function FileDate String sFilename Returns Date tsSearchResult[] lsSearchResult Get FileSearch sFilename DIRMODE_FILES_ONLY to lsSearchResult If (SizeOfArray(lsSearchResult) > 0) Function_Return lsSearchResult[0].dtLastWriteDateTime Else Function_Return 0 End_Function // Returns the fileversion info. // Returns false if an error occured. Function FileVersion String sFilename tsFileVersionInfo ByRef lsFileVersionInfo Returns Boolean Boolean bOk Integer iErrorNumber iStatus Get _FileVersion sFilename (&lsFileVersionInfo) to iStatus If (iStatus = -1) Begin Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber ("Tried to get fileversion info from file: "+sFilename) End Move (iStatus = 0) to bOk Function_Return bOk End_Function {Visibility = Private} Function _FileVersion String sFilename tsFileVersionInfo ByRef lsFileVersionInfo Returns Integer tsVS_FIXEDFILEINFO lsFIXEDFILEINFO UInteger iBytesNeeded Address aBuffer Boolean bOk String sSubBlock DWord dwBufferLen dwBufferPointer tsLandAndCodePage lsLandAndCodePage Move (ToANSI(sFilename)) to sFilename Move (sFilename + (Character(0))) to sFilename Move 0 to iBytesNeeded Move 0 to aBuffer Move 0 to lsFIXEDFILEINFO.dwStrucVersion // Initialize the variable. Move 0 to lsLandAndCodePage.wCodePage Move (fsGetFileVersionInfoSize(AddressOf(sFilename), 0)) to iBytesNeeded If (iBytesNeeded = 0) Begin Function_Return False End Move False to bOk Move (Alloc(iBytesNeeded)) to aBuffer Move (MemSet(aBuffer, 0, iBytesNeeded)) to bOk Move (fsGetFileVersionInfo(AddressOf(sFilename), 0, iBytesNeeded, aBuffer)) to bOk If (not(bOk)) Begin Move (Free(aBuffer)) to bOk Function_Return -1 End Move "\" to sSubBlock Move (sSubBlock + (Character(0))) to sSubBlock Move 0 to dwBufferLen Move 0 to dwBufferPointer Move (fsVerQueryValue(aBuffer, AddressOf(sSubBlock), AddressOf(dwBufferPointer), AddressOf(dwBufferLen))) to bOk If (not(bOk)) Begin Move (Free(aBuffer)) to bOk Function_Return -1 End If (dwBufferLen <> 52) Begin Send warning_box (SFormat("Length of bufferdata for VS_FIXEDFILEINFO struct are not in the expected size.\nLength is %1 and should have been 52.", dwBufferLen)) Move (Free(aBuffer)) to bOk Function_Return -2 End Move (MemCopy(AddressOf(lsFIXEDFILEINFO), dwBufferPointer, dwBufferLen)) to bOk If (not(bOk)) Begin Move (Free(aBuffer)) to bOk Function_Return -1 End Move lsFIXEDFILEINFO to lsFileVersionInfo.lsFIXEDFILEINFO Get ConvertFileTileToLocalDateTime lsFIXEDFILEINFO.ubiFileDate to lsFileVersionInfo.dtCreationDateTime Move (Hi(lsFIXEDFILEINFO.dwFileVersionMS)) to lsFileVersionInfo.siFileVersion[0] Move (Low(lsFIXEDFILEINFO.dwFileVersionMS)) to lsFileVersionInfo.siFileVersion[1] Move (Hi(lsFIXEDFILEINFO.dwFileVersionLS)) to lsFileVersionInfo.siFileVersion[2] Move (Low(lsFIXEDFILEINFO.dwFileVersionLS)) to lsFileVersionInfo.siFileVersion[3] Move (Hi(lsFIXEDFILEINFO.dwProductVersionMS)) to lsFileVersionInfo.siProductVersion[0] Move (Low(lsFIXEDFILEINFO.dwProductVersionMS)) to lsFileVersionInfo.siProductVersion[1] Move (Hi(lsFIXEDFILEINFO.dwProductVersionLS)) to lsFileVersionInfo.siProductVersion[2] Move (Low(lsFIXEDFILEINFO.dwProductVersionLS)) to lsFileVersionInfo.siProductVersion[3] Move "\VarFileInfo\Translation" to sSubBlock Move (sSubBlock + (Character(0))) to sSubBlock Move 0 to dwBufferLen Move 0 to dwBufferPointer Move (fsVerQueryValue(aBuffer, AddressOf(sSubBlock), AddressOf(dwBufferPointer), AddressOf(dwBufferLen))) to bOk If (not(bOk)) Begin Move (Free(aBuffer)) to bOk Function_Return -1 End If (dwBufferLen <> 4) Begin Send warning_box (SFormat("Length of bufferdata for land and codepage nunbers are not in the expected size.\nLength is %1 and should have been 4.", dwBufferLen)) Move (Free(aBuffer)) to bOk Function_Return -2 End Move (MemCopy(AddressOf(lsLandAndCodePage), dwBufferPointer, dwBufferLen)) to bOk Get VerQueryValueStringFileInfo aBuffer "Comments" lsLandAndCodePage to lsFileVersionInfo.sComments Get VerQueryValueStringFileInfo aBuffer "CompanyName" lsLandAndCodePage to lsFileVersionInfo.sCompanyName Get VerQueryValueStringFileInfo aBuffer "FileDescription" lsLandAndCodePage to lsFileVersionInfo.sFileDescription Get VerQueryValueStringFileInfo aBuffer "FileVersion" lsLandAndCodePage to lsFileVersionInfo.sFileVersion Get VerQueryValueStringFileInfo aBuffer "InternalName" lsLandAndCodePage to lsFileVersionInfo.sInternalName Get VerQueryValueStringFileInfo aBuffer "LegalCopyright" lsLandAndCodePage to lsFileVersionInfo.sLegalCopyright Get VerQueryValueStringFileInfo aBuffer "LegalTrademarks" lsLandAndCodePage to lsFileVersionInfo.sLegalTrademarks Get VerQueryValueStringFileInfo aBuffer "OriginalFilename" lsLandAndCodePage to lsFileVersionInfo.sOriginalFilename Get VerQueryValueStringFileInfo aBuffer "ProductName" lsLandAndCodePage to lsFileVersionInfo.sProductName Get VerQueryValueStringFileInfo aBuffer "ProductVersion" lsLandAndCodePage to lsFileVersionInfo.sProductVersion Get VerQueryValueStringFileInfo aBuffer "PrivateBuild" lsLandAndCodePage to lsFileVersionInfo.sPrivateBuild Get VerQueryValueStringFileInfo aBuffer "SpecialBuild" lsLandAndCodePage to lsFileVersionInfo.sSpecialBuild Move (Free(aBuffer)) to bOk Function_Return 0 End_Function // Convert an short integer to a 4-character hex string. Function ShortToHex Short siValue Returns String String sHex Move "" to sHex Repeat Move (Mid ("0123456789ABCDEF", 1, ((siValue iand |CI$0F) + 1)) + sHex) to sHex Move (siValue / |CI$10) to siValue Until (siValue = 0) Move (Right("0000" + sHex, 4)) to sHex Function_Return sHex End_Function {Visibility = Private} Function VerQueryValueStringFileInfo Address aBuffer String sInfoName tsLandAndCodePage lsLandAndCodePage Returns String String sSubBlock String sValue DWord dwBufferLen dwBufferPointer Boolean bOk Move (SFormat("\StringFileInfo\%1%2\%3", ShortToHex(Self, lsLandAndCodePage.wLanguage), ShortToHex(Self, lsLandAndCodePage.wCodePage), sInfoName)) to sSubBlock Move (sSubBlock + (Character(0))) to sSubBlock Move 0 to dwBufferLen Move 0 to dwBufferPointer Move (fsVerQueryValue(aBuffer, AddressOf(sSubBlock), AddressOf(dwBufferPointer), AddressOf(dwBufferLen))) to bOk If (not(bOk)) Begin Function_Return "" End ZeroString dwBufferLen to sValue Move (MemCopy(AddressOf(sValue), dwBufferPointer, dwBufferLen)) to bOk Function_Return (ToOEM(CString(sValue))) End_Function // Returns the file extention without the leading "." // Example sFile = "x:\text.txt". The function returns "txt". Function FileExtention String sFilename Returns String String sExtention Integer iPos Move (RightPos(".", sFilename)) to iPos If (iPos > 0) Begin Move (Right(sFilename, (Length(sFilename) - iPos))) to sExtention If (sExtention contains "\" or sExtention contains " ") Begin Move "" to sExtention End End Function_Return sExtention End_Function // Gets a handle to an icon stored as a resource in a file or an icon // stored in a file's associated executable file. // When the icon handle is no longer needed, close it by using the DestroyFileIcon procedure. Function FileIcon String sFilename Returns Handle Handle hIcon Integer iIcon String sFilenameANSI Move 0 to iIcon Move (ToANSI(sFilename)) to sFilenameANSI Move (Pad(sFilenameANSI, 128)) to sFilenameANSI Move (fsExtractAssociatedIcon(0, AddressOf(sFilenameANSI), AddressOf(iIcon))) to hIcon Function_Return hIcon End_Function // Destroy hIcon, created from FileIcon. Procedure DestroyFileIcon Handle hIcon Integer iResult If (hIcon <> 0) Begin Move (fsDestroyIcon(hIcon)) to iResult End End_Procedure // Search a directory for the files with normal windows mask-signs // Returns an array of matching files and directories // iMode = DIRMODE_FILES_ONLY // iMode = DIRMODE_DIRECTORIES_ONLY // iMode = DIRMODE_FILES_AND_DIRECTORIES (default) // If bReturnOnlyOne is true only one search result item is returned. // If bReturnOnlyOne is true and no items where found no error is shown. Function FileSearch String sFilePathMask Integer iFileDirMode Boolean bReturnOnlyOne Returns tsSearchResult[] tsSearchResult[] lsSearchResult Integer iSearchResultCount iMode iErrorNumber structWFD lsFindData String sTempFilename sFilePathMaskANSI Handle hFindFile Boolean bError bStop bFound bOk bOnlyOne BigInt biBigHi Address aFileName If (num_arguments < 2) Move DIRMODE_FILES_AND_DIRECTORIES to iMode Else Move iFileDirMode to iMode If (num_arguments < 3) Move False to bOnlyOne Else Move bReturnOnlyOne to bOnlyOne Move (ToAnsi(sFilePathMask)) to sFilePathMaskANSI Move 0 to lsFindData.dwFileAttributes // Initialize lsFindData Move (fsFindFirstFile(AddressOf(sFilePathMaskANSI), AddressOf(lsFindData))) to hFindFile If (hFindFile <> INVALID_HANDLE_VALUE) Begin Move False to bError Move False to bStop Move (2^32) to biBigHi Set pbError to bError While (bError = False and bStop = False) Move False to bFound Case Begin Case (iMode = DIRMODE_FILES_ONLY) If (lsFindData.dwFileAttributes iand FILE_ATTRIBUTE_DIRECTORY = 0) Move True to bFound Case Break Case (iMode = DIRMODE_DIRECTORIES_ONLY) If (lsFindData.dwFileAttributes iand FILE_ATTRIBUTE_DIRECTORY = FILE_ATTRIBUTE_DIRECTORY) Move True to bFound Case Break Case Else Move True to bFound Case Break Case End If bFound Begin Move (AddressOf(lsFindData.cFileName)) to aFilename Move aFilename to lsSearchResult[iSearchResultCount].sFilename Move (ToOEM(lsSearchResult[iSearchResultCount].sFilename)) to lsSearchResult[iSearchResultCount].sFilename Move (AddressOf(lsFindData.cAlternateFileName)) to aFilename Move aFilename to lsSearchResult[iSearchResultCount].sAlternateFileName Move (ToOEM(lsSearchResult[iSearchResultCount].sAlternateFileName)) to lsSearchResult[iSearchResultCount].sAlternateFileName Move lsFindData.dwFileAttributes to lsSearchResult[iSearchResultCount].iFileAttributes Get ConvertFileTileToLocalDateTime lsFindData.ftCreationDateTime to lsSearchResult[iSearchResultCount].dtCreationDateTime Get ConvertFileTileToLocalDateTime lsFindData.ftLastAccessDateTime to lsSearchResult[iSearchResultCount].dtLastAccessDateTime Get ConvertFileTileToLocalDateTime lsFindData.ftLastWriteDateTime to lsSearchResult[iSearchResultCount].dtLastWriteDateTime Move ((lsFindData.nFileSizeHigh * biBigHi) + lsFindData.nFileSizeLow) to lsSearchResult[iSearchResultCount].biFileSize Increment iSearchResultCount If bOnlyOne Move True to bStop End If (bStop = False) Move (fsFindNextFile(hFindFile, AddressOf(lsFindData))) to bOk If (bOk = False) Begin Move True to bStop If (bOnlyOne = False) Begin Move (fsGetLastError()) to iErrorNumber If (iErrorNumber <> ERROR_NO_MORE_FILES and iErrorNumber <> ERROR_MOD_NOT_FOUND and iErrorNumber <> 0) Send DoShowError iErrorNumber ("Search path: "+sFilePathMask) End End Get pbError to bError Loop Move (fsFindClose(hFindFile)) to bOk End Function_Return lsSearchResult End_Function // Search a directory and all subdirectories for the files with normal windows mask-signs. // lsResult[?].sFileName contains full path and filename. // iMode = DIRMODE_FILES_ONLY // iMode = DIRMODE_DIRECTORIES_ONLY // iMode = DIRMODE_FILES_AND_DIRECTORIES (default) Function FileSearchRecursive String sFilePathMask Integer iFileDirMode Boolean bReturnOnlyOne Returns tsSearchResult[] Integer iMode Boolean bOnlyOne tsSearchResult[] lsFinalResult lsSearchResult If (num_arguments < 2) Move DIRMODE_FILES_AND_DIRECTORIES to iMode Else Move iFileDirMode to iMode If (num_arguments < 3) Move False to bOnlyOne Else Move bReturnOnlyOne to bOnlyOne Get FileSearchRecursivePriv sFilePathMask iMode bOnlyOne (&lsFinalResult) to lsSearchResult Function_Return lsFinalResult End_Function // Private {Visibility = Private} Function FileSearchRecursivePriv String sFilePathMask Integer iFileDirMode Boolean bReturnOnlyOne tsSearchResult[] ByRef lsFinalResult Returns tsSearchResult[] tsSearchResult[] lsSearchResultDir lsSearchResult Integer iMax iCnt iLast iFinalMax String sSearchInDir sFileMask Boolean bStop Move (RightPos("\", sFilePathMask)) to iLast If (iLast > 0) Begin Move (Left(sFilePathMask, iLast - 1)) to sSearchInDir Move (Mid(sFilePathMask, Length(sFilePathMask), iLast + 1)) to sFileMask End Get FileSearch (sSearchInDir + "\*.*") DIRMODE_DIRECTORIES_ONLY to lsSearchResultDir Move (SizeOfArray(lsSearchResultDir)) to iMax Move 0 to iCnt While (iCnt < iMax and bStop = False) If (lsSearchResultDir[iCnt].sFilename <> "." and lsSearchResultDir[iCnt].sFilename <> "..") Begin Get FileSearchRecursivePriv (sSearchInDir + "\" + lsSearchResultDir[iCnt].sFilename + "\" + sFileMask) iFileDirMode bReturnOnlyOne (&lsFinalResult) to lsSearchResult End Increment iCnt If (bReturnOnlyOne = True) Begin If (SizeOfArray(lsFinalResult) > 0) Begin Move True to bStop End End Loop If (bStop = False) Begin Get FileSearch sFilePathMask iFileDirMode to lsSearchResult Move (SizeOfArray(lsSearchResult)) to iMax Move (SizeOfArray(lsFinalResult)) to iFinalMax Move 0 to iCnt While (iCnt < iMax and bStop = False) Move lsSearchResult[iCnt] to lsFinalResult[iFinalMax] Move (sSearchInDir + "\" + lsSearchResult[iCnt].sFilename) to lsFinalResult[iFinalMax].sFilename Increment iFinalMax Increment iCnt If (bReturnOnlyOne = True) Begin If (SizeOfArray(lsFinalResult) > 0) Begin Move True to bStop End End End End Function_Return lsSearchResult End_Function // Finds a list of files. // sSearchFiles is a list of files to search for separated by semicolon (;). // sSearchFiles may not contain paths but may contain wildcards. // sSearchPaths may only contain paths. // Returns a string array with the files // Returns only files with full path. // Use: // Get ListOfFiles "path1;path2" "*.txt;*.asc" // This will return all the .txt and .asc files with full path that exists in path1 and path2. Function ListOfFiles String sSearchPaths String sSearchFiles Returns String[] String[] saFileList Integer iFilelistCount iSearchFilesCount iCurSearchFile Integer iSearchPathsCount iCurSearchPath iFilesFound iCurFileFound String sCurSearchFile sCurSearchPath tsSearchResult[] lsSearchResult Get CountOfFields sSearchPaths to iSearchPathsCount Get CountOfFields sSearchFiles to iSearchFilesCount If (iSearchFilesCount > 0 and iSearchPathsCount > 0) Begin For iCurSearchFile from 1 to iSearchFilesCount Get FieldAtIndex sSearchFiles iCurSearchFile to sCurSearchFile Move (Trim(sCurSearchFile)) to sCurSearchFile If (sCurSearchFile <> "") Begin For iCurSearchPath from 1 to iSearchPathsCount Get FieldAtIndex sSearchPaths iCurSearchPath to sCurSearchPath If (Right(sCurSearchPath, 1) <> "\") Move (sCurSearchPath + "\") to sCurSearchPath Get FileSearch (sCurSearchPath + sCurSearchFile) DIRMODE_FILES_ONLY to lsSearchResult Move (SizeOfArray(lsSearchResult)) to iFilesFound Decrement iFilesFound For iCurFileFound from 0 to iFilesFound Move (sCurSearchPath + lsSearchResult[iCurFileFound].sFilename) to saFileList[iFilelistCount] Increment iFilelistCount Loop Loop End Loop End Function_Return saFileList End_Function // Get Windows Temp path Function FileTempPath Returns String String sTempPath Integer iRetVal ZeroString MAX_PATH to sTempPath Move (fsGetTempPath(MAX_PATH, AddressOf(sTempPath))) to iRetVal If (iRetVal > MAX_PATH) Begin ZeroString iRetval to sTempPath Move (fsGetTempPath(iRetVal, AddressOf(sTempPath))) to iRetVal End Move (ToOEM(sTempPath)) to sTempPath Move (CString(sTempPath)) to sTempPath Function_Return sTempPath End_Function // Generates a temporary file. // Returns full path and filename or blank if no file could be created. // sPathName is the place where the temporary file is generated. If it is // not argumented the TEMP enviroment variable is used. If that is also not // available the current directory is used. // You can prefix the first 3 letters of the filename with sPrefix. Function FileTempFileName String sPathName String sPrefix Returns String String sPathNameTmp sPrefixTmp sTempFileName Boolean bOk Set pbError to False If (num_arguments > 0) Move sPathName to sPathNameTmp Else Move "" to sPathNameTmp If (num_arguments > 1) Move sPrefix to sPrefixTmp Else Move "" to sPrefixTmp Move (Trim(sPathNameTmp)) to sPathNameTmp If (sPathNameTmp = "") Begin Get FileTempPath to sPathNameTmp If (sPathNameTmp = "") Move "." to sPathNameTmp End ZeroString MAX_PATH to sTempFilename Move (ToANSI(sPathNameTmp)) to sPathNameTmp Move (ToANSI(sPrefixTmp)) to sPrefixTmp Move (fsGetTempFileName(AddressOf(sPathNameTmp), AddressOf(sPrefixTmp), 0, AddressOf(sTempFileName))) to bOk If bOk Begin Move (ToOEM(sTempFileName)) to sTempFileName Move (CString(sTempFileName)) to sTempFileName End Function_Return sTempFileName End_Function // Creates a new directory. // Returns True if succeeds. Function DirectoryCreate String sDirectoryName Returns Boolean String sDirectorynameANSI Boolean bFound bOk Integer iErrorNumber Move False to bOk Set pbError to False Get FileExists sDirectoryName DIRMODE_DIRECTORIES_ONLY to bFound If (not(bFound)) Begin Move (toAnsi(sDirectoryName)) to sDirectorynameANSI Move (sDirectorynameANSI+(Character(0))) to sDirectorynameANSI Move (fsCreateDirectory(AddressOf(sDirectorynameANSI), FNULL)) to bOk If (bOk = False) Begin // Could not create Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber ("Tried to create directory: "+sDirectoryname) End End Function_Return bOk End_Function // Removes an existing empty directory. // Returns True if succeeds. Function DirectoryRemove String sDirectoryName Returns Boolean String sDirectorynameANSI Boolean bFound bOk Integer iErrorNumber Move False to bOk Set pbError to False Get FileExists sDirectoryName DIRMODE_DIRECTORIES_ONLY to bFound If bFound Begin Move (toAnsi(sDirectoryName)) to sDirectorynameANSI Move (sDirectorynameANSI+(Character(0))) to sDirectorynameANSI Move (fsRemoveDirectory(AddressOf(sDirectorynameANSI))) to bOk If (bOk = False) Begin // Could not delete Move (fsGetLastError()) to iErrorNumber If iErrorNumber Send DoShowError iErrorNumber ("Tried to remove directory: "+sDirectoryName) End End Function_Return bOk End_Function // Removes a directory and all its contents. // Returns true on succes. Function DirectoryRemoveRecursive String sDirectoryName Returns Boolean tsSearchResult[] alsSearchResults Integer iIndex Boolean bOk bExists If (Right(sDirectoryName, 1) = "\") Begin Move (Left(sDirectoryName, Length(sDirectoryName) - 1)) to sDirectoryName End Get FileSearch (sDirectoryName + "\*") DIRMODE_DIRECTORIES_ONLY to alsSearchResults For iIndex from 2 to (SizeOfArray(alsSearchResults) - 1) Get DirectoryRemoveRecursive (sDirectoryName + "\" + alsSearchResults[iIndex].sFilename) to bOk If (not(bOk)) Begin Function_Return False End Loop Get FileSearch (sDirectoryName + "\*") DIRMODE_FILES_ONLY to alsSearchResults For iIndex from 0 to (SizeOfArray(alsSearchResults) - 1) Get FileDelete (sDirectoryName + "\" + alsSearchResults[iIndex].sFilename) to bOk If (not(bOk)) Begin Function_Return False End Loop Get DirectoryRemove sDirectoryName to bOk Function_Return bOk End_Function // Converts the filetime in UTC and returns a datetime in local time. // private Function ConvertFileTileToLocalDateTime UBigInt ubiFileTime Returns DateTime Boolean bOk UBigInt ubiZero structSystemTime lsSystemTime lsLocalTime DateTime dtLocalTime Move 0 to lsSystemTime.wDay Move 0 to lsLocalTime.wDay Move 0 to ubiZero If (ubiFileTime <> ubiZero) Begin Move (fsFileTimeToSystemTime(AddressOf(ubiFileTime), AddressOf(lsSystemTime))) to bOk If bOk Begin Move (fsSystemTimeToTzSpecificLocalTime(FNULL, AddressOf(lsSystemTime), AddressOf(lsLocalTime))) to bOk If bOk Begin Move (DateSetYear(dtLocalTime, lsLocalTime.wYear)) to dtLocalTime Move (DateSetMonth(dtLocalTime, lsLocalTime.wMonth)) to dtLocalTime Move (DateSetDay(dtLocalTime, lsLocalTime.wDay)) to dtLocalTime Move (DateSetHour(dtLocalTime, lsLocalTime.wHour)) to dtLocalTime Move (DateSetMinute(dtLocalTime, lsLocalTime.wMinute)) to dtLocalTime Move (DateSetSecond(dtLocalTime, lsLocalTime.wSecond)) to dtLocalTime Move (DateSetMillisecond(dtLocalTime, lsLocalTime.wMillieseconds)) to dtLocalTime End End End Function_Return dtLocalTime End_Function // Returns the filename with full path where the casing is preserved from windows. Function FilePreservedFilename String sFilename Returns String Integer iNumOfDirectories iCurrentDirectory iSearchMode String sPreservedFilename sCurDir sSearchName tsSearchResult[] lsSearchResult Get CountOfFields sFilename "\" to iNumOfDirectories For iCurrentDirectory from 1 to (iNumOfDirectories - 1) Get FieldAtIndex sFilename iCurrentDirectory "\" to sCurDir If (sCurDir <> "") Begin If (Right(sCurDir, 1) <> ":") Begin Move (sPreservedFilename + sCurDir) to sSearchName Get FileSearch sSearchName DIRMODE_DIRECTORIES_ONLY to lsSearchResult If (SizeOfArray(lsSearchResult) > 0) Begin Move (sPreservedFilename + lsSearchResult[0].sFilename + "\") to sPreservedFilename End Else Begin Move (sPreservedFilename + sCurDir + "\") to sPreservedFilename End End Else Begin Move (sPreservedFilename + sCurDir + "\") to sPreservedFilename End End Else Begin Move (sPreservedFilename + "\") to sPreservedFilename End Loop Get FileSearch sFilename DIRMODE_FILES_AND_DIRECTORIES to lsSearchResult If (SizeOfArray(lsSearchResult) > 0) Begin Move (sPreservedFilename + lsSearchResult[0].sFilename) to sPreservedFilename End Else Begin Function_Return "" End Function_Return sPreservedFilename End_Function // Returns the number of fields present in a string of fields seperated by a delimiter. // If sDelimiter is not applied the ";" will be used. Function CountOfFields String sFields String sDelimiter Returns Integer Integer iChar icChar iField String sDlm If (sFields ="") Function_Return 0 If (num_arguments > 1) Move sDelimiter to sDlm Else Move ";" to sDlm Move (Length(sFields) -1) to icChar For iChar from 1 to icChar If (Mid(sFields, 1, iChar) = sDlm) Increment iField Loop Function_Return (iField +1) End_Function // Returns a field from a string containing multiple delimited fields. // Index is 1-based. Function FieldAtIndex String sFields Integer iIndex String sDelimiter Returns String Integer iChar iField iPos String sField sDlm If (num_arguments > 2) Move sDelimiter to sDlm Else Move ";" to sDlm Move (sFields + sDlm) to sFields For iField from 1 to iIndex Move (Pos(sDlm, sFields)) to iPos If iPos Begin Move (Left(sFields, iPos -1)) to sField Move (Right(sFields, Length(sFields) -iPos)) to sFields End Else Function_Return "" Loop Function_Return sField End_Function // Removes the file extention from the sFile string and returns the extention including "." // Example sFile = "x:\text.txt". The function returns ".txt" and sFile = "x:\text". Function RemoveExtention String ByRef sFilename Returns String String sExtention Integer iLengthExtention Get FileExtention sFilename to sExtention Move (Length(sExtention)) to iLengthExtention If (iLengthExtention > 0) Begin Move (Left(sFilename, (Length(sFilename) - iLengthExtention - 1))) to sFilename End Function_Return sExtention End_Function // Add a directory separator if it is not present. // Example sFoldername = "x:\FolderA". The function returns "x:\FolderA\" Function AddFolderSeperator String sFolderName Returns String String sDirSep Move (SysConf(SYSCONF_DIR_SEPARATOR)) to sDirSep Move (Trim(sFolderName)) to sFolderName If (Right(sFolderName, 1) <> sDirSep) Begin Move (sFolderName + sDirSep) to sFolderName End Function_Return sFolderName End_Function // Removes a directory separator if it is present. // Example sFoldername = "x:\FolderA\". The function returns "x:\FolderA" Function RemoveFolderSeperator String sFolderName Returns String String sDirSep Move (SysConf(SYSCONF_DIR_SEPARATOR)) to sDirSep Move (Trim(sFolderName)) to sFolderName If (Right(sFolderName, 1) = sDirSep) Begin Move (Left(sFolderName, Length(sFolderName) - 1)) to sFolderName End Function_Return sFolderName End_Function // Fetch the error message from the system message table using the default language. Procedure DoShowError Integer iErrorNumber String sAppendErrorText Pointer lpOut lpOutText Integer iRetChars iRetVal iMaxFiles String sMsg sFilename Boolean bOk Move 0 to lpOut Move (fsFormatMessage((FORMAT_MESSAGE_FROM_SYSTEM+FORMAT_MESSAGE_IGNORE_INSERTS+FORMAT_MESSAGE_ALLOCATE_BUFFER), FNULL, iErrorNumber, FNULL, AddressOf(lpOut), 0, FNULL)) to iRetChars If (iRetChars > 0) Begin ZeroString iRetChars to sMsg Move (MemCopy(AddressOf(sMsg), lpOut, iRetChars)) to bOk Move (fsLocalFree(lpOut)) to iRetVal Move (ToOEM(sMsg)) to sMsg If (num_arguments > 0) Begin Move (Trim(sAppendErrorText)) to sAppendErrorText If (sAppendErrorText <> "") Begin Append sMsg "\n" sAppendErrorText End End Send warning_box sMsg End End_Procedure // Shows a warning message to user with OK button and a exclamation icon. // private Procedure warning_box String sWngMsg Integer iVoid Boolean bSendVdfError Set pbError to True Get pbErrorAsVDFError to bSendVdfError If (bSendVdfError = False) Get Message_Box sWngMsg "Filesystem Error" MB_OK MB_ICONEXCLAMATION to iVoid Else Error DFERR_PROGRAM sWngMsg End_Procedure // Fetch the filename from the list of filenames associated with a filenumber. // This function is used for reporting filenames during an error. // private Function FileErrorText Integer iFilenumber Returns String String sErrorText structFile[] lsFile Get plsFile to lsFile If (iFilenumber < SizeOfArray(lsFile)) Move ("File: "+lsFile[iFilenumber].sFilename) to sErrorText Function_Return sErrorText End_Function End_Class