DECLARE INTEGER InternetOpen in WinINet.dll ; STRING cAgent, INTEGER nType, STRING cProxy, STRING cBypass, INTEGER nFlags DECLARE INTEGER InternetCloseHandle in WinINet.dll ; INTEGER nInternetHandle DECLARE INTEGER InternetConnect in WinINet.dll ; INTEGER nInternetSession, STRING cServer, INTEGER nPort, ; STRING cUserName, STRING cPassword, INTEGER nService, INTEGER nFlags, INTEGER nContext DECLARE INTEGER FtpSetCurrentDirectory IN WinINet.dll ; INTEGER nFtpSession, STRING cDirectory DECLARE INTEGER FtpFindFirstFile IN WinINet.dll ; INTEGER nFtpSession, STRING cSearchFile, STRING @ FindFileData, ; INTEGER nFlags, INTEGER nContext lnSession = InternetOpen("Wininet",0,.NULL.,.NULL.,0) * set as appropriate lcServer = "localhost" lcUserName = "anonymous" lcPassword = "someone@somewhere.com" lcDir = "/pub" IF lnSession!=0 lnFTPSession = InternetConnect(lnSession,lcServer,21,lcUserName,lcPassword,1,0x08000000,0) IF lnFTPSession!=0 IF FtpSetCurrentDirectory(lnFTPSession,lcDir)!=0 * prepare a struct for the API call loFindFile = CREATEOBJECT("Win32_Find_Data") * set the buffer lcBuffer = loFindFile.SetBuffer() * make the call lnEnumFTP = FtpFindFirstFile(lnFTPSession,.NULL.,@lcBuffer,0,0) IF lnEnumFTP!=0 * we got a valid handle, so we may put the result in our object loFindFile.GetFindData(lcBuffer) * from now on, everything may be handled as an object (ain't that nice?) ? loFindFile.FileName+" ("+LTRIM(STR(loFindFile.FileSize))+" bytes)" InternetCloseHandle(lnEnumFTP) ENDIF ENDIF InternetCloseHandle(lnFTPSession) ENDIF InternetCloseHandle(lnSession) ENDIF * This is a class we'll use to emulate the structure required * by FtpFindFirstFile and InternetFindNextFile functions DEFINE CLASS Win32_Find_Data AS CUSTOM HIDDEN _BufferSize, InternalBuffer * structure members will be class properties FileAttributes = 0 && a lot of holes to be filled in... :) CreationTime = {} LastAccessTime = {} LastWriteTime = {} FileSize = 0 FileName = "" AlternateFileName = "" * this is the buffer where the API function will put the result _BufferSize = 318 && size of WIN32_FIND_DATA, ANSI version InternalBuffer = "" * utility methods to read the buffer * Fetch a DWORD from the buffer HIDDEN FUNCTION _GetDWORD LPARAMETER nOffset RETURN ASC(SUBSTR(THIS.InternalBuffer,nOffset,1))+; ASC(SUBSTR(THIS.InternalBuffer,nOffset+1,1))*0x100+; ASC(SUBSTR(THIS.InternalBuffer,nOffset+2,1))*0x10000+; ASC(SUBSTR(THIS.InternalBuffer,nOffset+3,1))*0x1000000 ENDFUNC * Fetch a \0 terminated string from the buffer HIDDEN FUNCTION _GetCHARZ LPARAMETER nOffset, nMaxLength LOCAL lcAsciiZ, lcChar, lnLoop lcAsciiZ = "" FOR lnLoop = nOffset TO (nOffset+nMaxLength)-1 lcChar = SUBSTR(THIS.InternalBuffer,lnLoop,1) IF EMPTY(ASC(lcChar)) EXIT ELSE lcAsciiZ = lcAsciiZ+lcChar ENDIF ENDFOR RETURN lcAsciiZ ENDFUNC * get the data from the buffer and populate our properties PROCEDURE GetFindData LPARAMETERS cBuffer THIS.InternalBuffer = PADR(cBuffer,THIS._BufferSize,CHR(0)) * as proof of concept, get file name and size THIS.FileSize = THIS._GetDWORD(29)*0x100000000+THIS._GetDWORD(33) THIS.FileName = THIS._GetCHARZ(45,260) ENDPROC * set the buffer for the API PROCEDURE SetBuffer RETURN REPLICATE(CHR(0),THIS._BufferSize) ENDPROC ENDDEFINEHope it helps.