15f12c8d7Swinesync #ifdef __REACTOS__
25f12c8d7Swinesync #include "precomp.h"
35f12c8d7Swinesync #else
4c2c66affSColin Finck /*
5c2c66affSColin Finck * WININET - Ftp implementation
6c2c66affSColin Finck *
7c2c66affSColin Finck * Copyright 1999 Corel Corporation
8c2c66affSColin Finck * Copyright 2004 Mike McCormack for CodeWeavers
9c2c66affSColin Finck * Copyright 2004 Kevin Koltzau
10c2c66affSColin Finck * Copyright 2007 Hans Leidekker
11c2c66affSColin Finck *
12c2c66affSColin Finck * Ulrich Czekalla
13c2c66affSColin Finck * Noureddine Jemmali
14c2c66affSColin Finck *
15c2c66affSColin Finck * Copyright 2000 Andreas Mohr
16c2c66affSColin Finck * Copyright 2002 Jaco Greeff
17c2c66affSColin Finck *
18c2c66affSColin Finck * This library is free software; you can redistribute it and/or
19c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
20c2c66affSColin Finck * License as published by the Free Software Foundation; either
21c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
22c2c66affSColin Finck *
23c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
24c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
25c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26c2c66affSColin Finck * Lesser General Public License for more details.
27c2c66affSColin Finck *
28c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
29c2c66affSColin Finck * License along with this library; if not, write to the Free Software
30c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31c2c66affSColin Finck */
32c2c66affSColin Finck
33bc01cef0SAmine Khaldi #include "ws2tcpip.h"
34bc01cef0SAmine Khaldi
35bc01cef0SAmine Khaldi #include <stdarg.h>
36bc01cef0SAmine Khaldi #include <stdio.h>
37bc01cef0SAmine Khaldi #include <stdlib.h>
38bc01cef0SAmine Khaldi #include <string.h>
39bc01cef0SAmine Khaldi #include <time.h>
40bc01cef0SAmine Khaldi #include <assert.h>
41bc01cef0SAmine Khaldi
42bc01cef0SAmine Khaldi #include "windef.h"
43bc01cef0SAmine Khaldi #include "winbase.h"
44bc01cef0SAmine Khaldi #include "wingdi.h"
45bc01cef0SAmine Khaldi #include "winuser.h"
46bc01cef0SAmine Khaldi #include "wininet.h"
47bc01cef0SAmine Khaldi #include "winnls.h"
48bc01cef0SAmine Khaldi #include "winerror.h"
49bc01cef0SAmine Khaldi #include "winreg.h"
50bc01cef0SAmine Khaldi #include "winternl.h"
51bc01cef0SAmine Khaldi #include "shlwapi.h"
52bc01cef0SAmine Khaldi
53bc01cef0SAmine Khaldi #include "wine/debug.h"
54c2c66affSColin Finck #include "internet.h"
555f12c8d7Swinesync #endif /* defined(__REACTOS__) */
56c2c66affSColin Finck
57bc01cef0SAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(wininet);
58bc01cef0SAmine Khaldi
59c2c66affSColin Finck #define RESPONSE_TIMEOUT 30
60c2c66affSColin Finck
61c2c66affSColin Finck typedef struct _ftp_session_t ftp_session_t;
62c2c66affSColin Finck
63c2c66affSColin Finck typedef struct
64c2c66affSColin Finck {
65c2c66affSColin Finck object_header_t hdr;
66c2c66affSColin Finck ftp_session_t *lpFtpSession;
67c2c66affSColin Finck BOOL session_deleted;
68c2c66affSColin Finck int nDataSocket;
69c2c66affSColin Finck WCHAR *cache_file;
70c2c66affSColin Finck HANDLE cache_file_handle;
71c2c66affSColin Finck } ftp_file_t;
72c2c66affSColin Finck
73c2c66affSColin Finck struct _ftp_session_t
74c2c66affSColin Finck {
75c2c66affSColin Finck object_header_t hdr;
76c2c66affSColin Finck appinfo_t *lpAppInfo;
77c2c66affSColin Finck int sndSocket;
78c2c66affSColin Finck int lstnSocket;
79c2c66affSColin Finck int pasvSocket; /* data socket connected by us in case of passive FTP */
80c2c66affSColin Finck ftp_file_t *download_in_progress;
81c2c66affSColin Finck struct sockaddr_in socketAddress;
82c2c66affSColin Finck struct sockaddr_in lstnSocketAddress;
83c2c66affSColin Finck LPWSTR servername;
84c2c66affSColin Finck INTERNET_PORT serverport;
85c2c66affSColin Finck LPWSTR lpszPassword;
86c2c66affSColin Finck LPWSTR lpszUserName;
87c2c66affSColin Finck };
88c2c66affSColin Finck
89c2c66affSColin Finck typedef struct
90c2c66affSColin Finck {
91c2c66affSColin Finck BOOL bIsDirectory;
92c2c66affSColin Finck LPWSTR lpszName;
93c2c66affSColin Finck DWORD nSize;
94c2c66affSColin Finck SYSTEMTIME tmLastModified;
95c2c66affSColin Finck unsigned short permissions;
96c2c66affSColin Finck } FILEPROPERTIESW, *LPFILEPROPERTIESW;
97c2c66affSColin Finck
98c2c66affSColin Finck typedef struct
99c2c66affSColin Finck {
100c2c66affSColin Finck object_header_t hdr;
101c2c66affSColin Finck ftp_session_t *lpFtpSession;
102c2c66affSColin Finck DWORD index;
103c2c66affSColin Finck DWORD size;
104c2c66affSColin Finck LPFILEPROPERTIESW lpafp;
105c2c66affSColin Finck } WININETFTPFINDNEXTW, *LPWININETFTPFINDNEXTW;
106c2c66affSColin Finck
107c2c66affSColin Finck #define DATA_PACKET_SIZE 0x2000
108c2c66affSColin Finck #define szCRLF "\r\n"
109c2c66affSColin Finck #define MAX_BACKLOG 5
110c2c66affSColin Finck
111c2c66affSColin Finck /* Testing shows that Windows only accepts dwFlags where the last
112c2c66affSColin Finck * 3 (yes 3) bits define FTP_TRANSFER_TYPE_UNKNOWN, FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY.
113c2c66affSColin Finck */
114c2c66affSColin Finck #define FTP_CONDITION_MASK 0x0007
115c2c66affSColin Finck
116c2c66affSColin Finck typedef enum {
117c2c66affSColin Finck /* FTP commands with arguments. */
118c2c66affSColin Finck FTP_CMD_ACCT,
119c2c66affSColin Finck FTP_CMD_CWD,
120c2c66affSColin Finck FTP_CMD_DELE,
121c2c66affSColin Finck FTP_CMD_MKD,
122c2c66affSColin Finck FTP_CMD_PASS,
123c2c66affSColin Finck FTP_CMD_PORT,
124c2c66affSColin Finck FTP_CMD_RETR,
125c2c66affSColin Finck FTP_CMD_RMD,
126c2c66affSColin Finck FTP_CMD_RNFR,
127c2c66affSColin Finck FTP_CMD_RNTO,
128c2c66affSColin Finck FTP_CMD_STOR,
129c2c66affSColin Finck FTP_CMD_TYPE,
130c2c66affSColin Finck FTP_CMD_USER,
131c2c66affSColin Finck FTP_CMD_SIZE,
132c2c66affSColin Finck
133c2c66affSColin Finck /* FTP commands without arguments. */
134c2c66affSColin Finck FTP_CMD_ABOR,
135c2c66affSColin Finck FTP_CMD_LIST,
136c2c66affSColin Finck FTP_CMD_NLST,
137c2c66affSColin Finck FTP_CMD_PASV,
138c2c66affSColin Finck FTP_CMD_PWD,
139c2c66affSColin Finck FTP_CMD_QUIT,
140c2c66affSColin Finck } FTP_COMMAND;
141c2c66affSColin Finck
142c2c66affSColin Finck static const CHAR *const szFtpCommands[] = {
143c2c66affSColin Finck "ACCT",
144c2c66affSColin Finck "CWD",
145c2c66affSColin Finck "DELE",
146c2c66affSColin Finck "MKD",
147c2c66affSColin Finck "PASS",
148c2c66affSColin Finck "PORT",
149c2c66affSColin Finck "RETR",
150c2c66affSColin Finck "RMD",
151c2c66affSColin Finck "RNFR",
152c2c66affSColin Finck "RNTO",
153c2c66affSColin Finck "STOR",
154c2c66affSColin Finck "TYPE",
155c2c66affSColin Finck "USER",
156c2c66affSColin Finck "SIZE",
157c2c66affSColin Finck "ABOR",
158c2c66affSColin Finck "LIST",
159c2c66affSColin Finck "NLST",
160c2c66affSColin Finck "PASV",
161c2c66affSColin Finck "PWD",
162c2c66affSColin Finck "QUIT",
163c2c66affSColin Finck };
164c2c66affSColin Finck
165c2c66affSColin Finck static const CHAR szMonths[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
166c2c66affSColin Finck
167c2c66affSColin Finck static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
168c2c66affSColin Finck INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext);
169c2c66affSColin Finck static BOOL FTP_SendStore(ftp_session_t*, LPCWSTR lpszRemoteFile, DWORD dwType);
170c2c66affSColin Finck static BOOL FTP_GetDataSocket(ftp_session_t*, LPINT nDataSocket);
171c2c66affSColin Finck static BOOL FTP_SendData(ftp_session_t*, INT nDataSocket, HANDLE hFile);
172c2c66affSColin Finck static INT FTP_ReceiveResponse(ftp_session_t*, DWORD_PTR dwContext);
173c2c66affSColin Finck static BOOL FTP_SendRetrieve(ftp_session_t*, LPCWSTR lpszRemoteFile, DWORD dwType);
174c2c66affSColin Finck static BOOL FTP_RetrieveFileData(ftp_session_t*, INT nDataSocket, HANDLE hFile);
175c2c66affSColin Finck static BOOL FTP_InitListenSocket(ftp_session_t*);
176c2c66affSColin Finck static BOOL FTP_ConnectToHost(ftp_session_t*);
177c2c66affSColin Finck static BOOL FTP_SendPassword(ftp_session_t*);
178c2c66affSColin Finck static BOOL FTP_SendAccount(ftp_session_t*);
179c2c66affSColin Finck static BOOL FTP_SendType(ftp_session_t*, DWORD dwType);
180c2c66affSColin Finck static BOOL FTP_SendPort(ftp_session_t*);
181c2c66affSColin Finck static BOOL FTP_DoPassive(ftp_session_t*);
182c2c66affSColin Finck static BOOL FTP_SendPortOrPasv(ftp_session_t*);
183c2c66affSColin Finck static BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESW lpfp);
184c2c66affSColin Finck static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERTIESW fileprop);
185c2c66affSColin Finck static BOOL FTP_ParseDirectory(ftp_session_t*, INT nSocket, LPCWSTR lpszSearchFile,
186c2c66affSColin Finck LPFILEPROPERTIESW *lpafp, LPDWORD dwfp);
187c2c66affSColin Finck static HINTERNET FTP_ReceiveFileList(ftp_session_t*, INT nSocket, LPCWSTR lpszSearchFile,
188c2c66affSColin Finck LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext);
189c2c66affSColin Finck static DWORD FTP_SetResponseError(DWORD dwResponse);
190c2c66affSColin Finck static BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData);
191c2c66affSColin Finck static BOOL FTP_FtpPutFileW(ftp_session_t*, LPCWSTR lpszLocalFile,
192c2c66affSColin Finck LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext);
193c2c66affSColin Finck static BOOL FTP_FtpSetCurrentDirectoryW(ftp_session_t*, LPCWSTR lpszDirectory);
194c2c66affSColin Finck static BOOL FTP_FtpCreateDirectoryW(ftp_session_t*, LPCWSTR lpszDirectory);
195c2c66affSColin Finck static HINTERNET FTP_FtpFindFirstFileW(ftp_session_t*,
196c2c66affSColin Finck LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext);
197c2c66affSColin Finck static BOOL FTP_FtpGetCurrentDirectoryW(ftp_session_t*, LPWSTR lpszCurrentDirectory,
198c2c66affSColin Finck LPDWORD lpdwCurrentDirectory);
199c2c66affSColin Finck static BOOL FTP_FtpRenameFileW(ftp_session_t*, LPCWSTR lpszSrc, LPCWSTR lpszDest);
200c2c66affSColin Finck static BOOL FTP_FtpRemoveDirectoryW(ftp_session_t*, LPCWSTR lpszDirectory);
201c2c66affSColin Finck static BOOL FTP_FtpDeleteFileW(ftp_session_t*, LPCWSTR lpszFileName);
202c2c66affSColin Finck static BOOL FTP_FtpGetFileW(ftp_session_t*, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
203c2c66affSColin Finck BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
204c2c66affSColin Finck DWORD_PTR dwContext);
205c2c66affSColin Finck
206c2c66affSColin Finck /* A temporary helper until we get rid of INTERNET_GetLastError calls */
res_to_le(DWORD res)207c2c66affSColin Finck static BOOL res_to_le(DWORD res)
208c2c66affSColin Finck {
209c2c66affSColin Finck if(res != ERROR_SUCCESS)
210c2c66affSColin Finck INTERNET_SetLastError(res);
211c2c66affSColin Finck return res == ERROR_SUCCESS;
212c2c66affSColin Finck }
213c2c66affSColin Finck
214c2c66affSColin Finck /***********************************************************************
215c2c66affSColin Finck * FtpPutFileA (WININET.@)
216c2c66affSColin Finck *
217c2c66affSColin Finck * Uploads a file to the FTP server
218c2c66affSColin Finck *
219c2c66affSColin Finck * RETURNS
220c2c66affSColin Finck * TRUE on success
221c2c66affSColin Finck * FALSE on failure
222c2c66affSColin Finck *
223c2c66affSColin Finck */
FtpPutFileA(HINTERNET hConnect,LPCSTR lpszLocalFile,LPCSTR lpszNewRemoteFile,DWORD dwFlags,DWORD_PTR dwContext)224c2c66affSColin Finck BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
225c2c66affSColin Finck LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext)
226c2c66affSColin Finck {
227c2c66affSColin Finck LPWSTR lpwzLocalFile;
228c2c66affSColin Finck LPWSTR lpwzNewRemoteFile;
229c2c66affSColin Finck BOOL ret;
230c2c66affSColin Finck
231c2c66affSColin Finck lpwzLocalFile = heap_strdupAtoW(lpszLocalFile);
232c2c66affSColin Finck lpwzNewRemoteFile = heap_strdupAtoW(lpszNewRemoteFile);
233c2c66affSColin Finck ret = FtpPutFileW(hConnect, lpwzLocalFile, lpwzNewRemoteFile,
234c2c66affSColin Finck dwFlags, dwContext);
235c2c66affSColin Finck heap_free(lpwzLocalFile);
236c2c66affSColin Finck heap_free(lpwzNewRemoteFile);
237c2c66affSColin Finck return ret;
238c2c66affSColin Finck }
239c2c66affSColin Finck
240c2c66affSColin Finck typedef struct {
241c2c66affSColin Finck task_header_t hdr;
242c2c66affSColin Finck WCHAR *local_file;
243c2c66affSColin Finck WCHAR *remote_file;
244c2c66affSColin Finck DWORD flags;
245c2c66affSColin Finck DWORD_PTR context;
246c2c66affSColin Finck } put_file_task_t;
247c2c66affSColin Finck
AsyncFtpPutFileProc(task_header_t * hdr)248c2c66affSColin Finck static void AsyncFtpPutFileProc(task_header_t *hdr)
249c2c66affSColin Finck {
250c2c66affSColin Finck put_file_task_t *task = (put_file_task_t*)hdr;
251c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
252c2c66affSColin Finck
253c2c66affSColin Finck TRACE("%p\n", session);
254c2c66affSColin Finck
255c2c66affSColin Finck FTP_FtpPutFileW(session, task->local_file, task->remote_file,
256c2c66affSColin Finck task->flags, task->context);
257c2c66affSColin Finck
258c2c66affSColin Finck heap_free(task->local_file);
259c2c66affSColin Finck heap_free(task->remote_file);
260c2c66affSColin Finck }
261c2c66affSColin Finck
262c2c66affSColin Finck /***********************************************************************
263c2c66affSColin Finck * FtpPutFileW (WININET.@)
264c2c66affSColin Finck *
265c2c66affSColin Finck * Uploads a file to the FTP server
266c2c66affSColin Finck *
267c2c66affSColin Finck * RETURNS
268c2c66affSColin Finck * TRUE on success
269c2c66affSColin Finck * FALSE on failure
270c2c66affSColin Finck *
271c2c66affSColin Finck */
FtpPutFileW(HINTERNET hConnect,LPCWSTR lpszLocalFile,LPCWSTR lpszNewRemoteFile,DWORD dwFlags,DWORD_PTR dwContext)272c2c66affSColin Finck BOOL WINAPI FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile,
273c2c66affSColin Finck LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext)
274c2c66affSColin Finck {
275c2c66affSColin Finck ftp_session_t *lpwfs;
276c2c66affSColin Finck appinfo_t *hIC = NULL;
277c2c66affSColin Finck BOOL r = FALSE;
278c2c66affSColin Finck
279c2c66affSColin Finck if (!lpszLocalFile || !lpszNewRemoteFile)
280c2c66affSColin Finck {
281c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
282c2c66affSColin Finck return FALSE;
283c2c66affSColin Finck }
284c2c66affSColin Finck
285c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hConnect );
286c2c66affSColin Finck if (!lpwfs)
287c2c66affSColin Finck {
288c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
289c2c66affSColin Finck return FALSE;
290c2c66affSColin Finck }
291c2c66affSColin Finck
292c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
293c2c66affSColin Finck {
294c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
295c2c66affSColin Finck goto lend;
296c2c66affSColin Finck }
297c2c66affSColin Finck
298c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
299c2c66affSColin Finck {
300c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
301c2c66affSColin Finck goto lend;
302c2c66affSColin Finck }
303c2c66affSColin Finck
304c2c66affSColin Finck if ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY)
305c2c66affSColin Finck {
306c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
307c2c66affSColin Finck goto lend;
308c2c66affSColin Finck }
309c2c66affSColin Finck
310c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
311c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
312c2c66affSColin Finck {
313c2c66affSColin Finck put_file_task_t *task = alloc_async_task(&lpwfs->hdr, AsyncFtpPutFileProc, sizeof(*task));
314c2c66affSColin Finck
315c2c66affSColin Finck task->local_file = heap_strdupW(lpszLocalFile);
316c2c66affSColin Finck task->remote_file = heap_strdupW(lpszNewRemoteFile);
317c2c66affSColin Finck task->flags = dwFlags;
318c2c66affSColin Finck task->context = dwContext;
319c2c66affSColin Finck
320c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
321c2c66affSColin Finck }
322c2c66affSColin Finck else
323c2c66affSColin Finck {
324c2c66affSColin Finck r = FTP_FtpPutFileW(lpwfs, lpszLocalFile,
325c2c66affSColin Finck lpszNewRemoteFile, dwFlags, dwContext);
326c2c66affSColin Finck }
327c2c66affSColin Finck
328c2c66affSColin Finck lend:
329c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
330c2c66affSColin Finck
331c2c66affSColin Finck return r;
332c2c66affSColin Finck }
333c2c66affSColin Finck
334c2c66affSColin Finck /***********************************************************************
335c2c66affSColin Finck * FTP_FtpPutFileW (Internal)
336c2c66affSColin Finck *
337c2c66affSColin Finck * Uploads a file to the FTP server
338c2c66affSColin Finck *
339c2c66affSColin Finck * RETURNS
340c2c66affSColin Finck * TRUE on success
341c2c66affSColin Finck * FALSE on failure
342c2c66affSColin Finck *
343c2c66affSColin Finck */
FTP_FtpPutFileW(ftp_session_t * lpwfs,LPCWSTR lpszLocalFile,LPCWSTR lpszNewRemoteFile,DWORD dwFlags,DWORD_PTR dwContext)344c2c66affSColin Finck static BOOL FTP_FtpPutFileW(ftp_session_t *lpwfs, LPCWSTR lpszLocalFile,
345c2c66affSColin Finck LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext)
346c2c66affSColin Finck {
347c2c66affSColin Finck HANDLE hFile;
348c2c66affSColin Finck BOOL bSuccess = FALSE;
349c2c66affSColin Finck appinfo_t *hIC = NULL;
350c2c66affSColin Finck INT nResCode;
351c2c66affSColin Finck
352c2c66affSColin Finck TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", debugstr_w(lpszLocalFile), debugstr_w(lpszNewRemoteFile));
353c2c66affSColin Finck
354c2c66affSColin Finck /* Clear any error information */
355c2c66affSColin Finck INTERNET_SetLastError(0);
356c2c66affSColin Finck
357c2c66affSColin Finck /* Open file to be uploaded */
358c2c66affSColin Finck if (INVALID_HANDLE_VALUE ==
359c2c66affSColin Finck (hFile = CreateFileW(lpszLocalFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)))
360c2c66affSColin Finck /* Let CreateFile set the appropriate error */
361c2c66affSColin Finck return FALSE;
362c2c66affSColin Finck
363c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
364c2c66affSColin Finck
365c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
366c2c66affSColin Finck
367c2c66affSColin Finck if (FTP_SendStore(lpwfs, lpszNewRemoteFile, dwFlags))
368c2c66affSColin Finck {
369c2c66affSColin Finck INT nDataSocket;
370c2c66affSColin Finck
371c2c66affSColin Finck /* Get data socket to server */
372c2c66affSColin Finck if (FTP_GetDataSocket(lpwfs, &nDataSocket))
373c2c66affSColin Finck {
374c2c66affSColin Finck FTP_SendData(lpwfs, nDataSocket, hFile);
375c2c66affSColin Finck closesocket(nDataSocket);
376c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, dwContext);
377c2c66affSColin Finck if (nResCode)
378c2c66affSColin Finck {
379c2c66affSColin Finck if (nResCode == 226)
380c2c66affSColin Finck bSuccess = TRUE;
381c2c66affSColin Finck else
382c2c66affSColin Finck FTP_SetResponseError(nResCode);
383c2c66affSColin Finck }
384c2c66affSColin Finck }
385c2c66affSColin Finck }
386c2c66affSColin Finck
387c2c66affSColin Finck if (lpwfs->lstnSocket != -1)
388c2c66affSColin Finck {
389c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
390c2c66affSColin Finck lpwfs->lstnSocket = -1;
391c2c66affSColin Finck }
392c2c66affSColin Finck
393c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
394c2c66affSColin Finck {
395c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
396c2c66affSColin Finck
397c2c66affSColin Finck iar.dwResult = (DWORD)bSuccess;
398c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
399c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
400c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
401c2c66affSColin Finck }
402c2c66affSColin Finck
403c2c66affSColin Finck CloseHandle(hFile);
404c2c66affSColin Finck
405c2c66affSColin Finck return bSuccess;
406c2c66affSColin Finck }
407c2c66affSColin Finck
408c2c66affSColin Finck
409c2c66affSColin Finck /***********************************************************************
410c2c66affSColin Finck * FtpSetCurrentDirectoryA (WININET.@)
411c2c66affSColin Finck *
412c2c66affSColin Finck * Change the working directory on the FTP server
413c2c66affSColin Finck *
414c2c66affSColin Finck * RETURNS
415c2c66affSColin Finck * TRUE on success
416c2c66affSColin Finck * FALSE on failure
417c2c66affSColin Finck *
418c2c66affSColin Finck */
FtpSetCurrentDirectoryA(HINTERNET hConnect,LPCSTR lpszDirectory)419c2c66affSColin Finck BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
420c2c66affSColin Finck {
421c2c66affSColin Finck LPWSTR lpwzDirectory;
422c2c66affSColin Finck BOOL ret;
423c2c66affSColin Finck
424c2c66affSColin Finck lpwzDirectory = heap_strdupAtoW(lpszDirectory);
425c2c66affSColin Finck ret = FtpSetCurrentDirectoryW(hConnect, lpwzDirectory);
426c2c66affSColin Finck heap_free(lpwzDirectory);
427c2c66affSColin Finck return ret;
428c2c66affSColin Finck }
429c2c66affSColin Finck
430c2c66affSColin Finck typedef struct {
431c2c66affSColin Finck task_header_t hdr;
432c2c66affSColin Finck WCHAR *directory;
433c2c66affSColin Finck } directory_task_t;
434c2c66affSColin Finck
AsyncFtpSetCurrentDirectoryProc(task_header_t * hdr)435c2c66affSColin Finck static void AsyncFtpSetCurrentDirectoryProc(task_header_t *hdr)
436c2c66affSColin Finck {
437c2c66affSColin Finck directory_task_t *task = (directory_task_t*)hdr;
438c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
439c2c66affSColin Finck
440c2c66affSColin Finck TRACE("%p\n", session);
441c2c66affSColin Finck
442c2c66affSColin Finck FTP_FtpSetCurrentDirectoryW(session, task->directory);
443c2c66affSColin Finck heap_free(task->directory);
444c2c66affSColin Finck }
445c2c66affSColin Finck
446c2c66affSColin Finck /***********************************************************************
447c2c66affSColin Finck * FtpSetCurrentDirectoryW (WININET.@)
448c2c66affSColin Finck *
449c2c66affSColin Finck * Change the working directory on the FTP server
450c2c66affSColin Finck *
451c2c66affSColin Finck * RETURNS
452c2c66affSColin Finck * TRUE on success
453c2c66affSColin Finck * FALSE on failure
454c2c66affSColin Finck *
455c2c66affSColin Finck */
FtpSetCurrentDirectoryW(HINTERNET hConnect,LPCWSTR lpszDirectory)456c2c66affSColin Finck BOOL WINAPI FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
457c2c66affSColin Finck {
458c2c66affSColin Finck ftp_session_t *lpwfs = NULL;
459c2c66affSColin Finck appinfo_t *hIC = NULL;
460c2c66affSColin Finck BOOL r = FALSE;
461c2c66affSColin Finck
462c2c66affSColin Finck if (!lpszDirectory)
463c2c66affSColin Finck {
464c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
465c2c66affSColin Finck goto lend;
466c2c66affSColin Finck }
467c2c66affSColin Finck
468c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hConnect );
469c2c66affSColin Finck if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
470c2c66affSColin Finck {
471c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
472c2c66affSColin Finck goto lend;
473c2c66affSColin Finck }
474c2c66affSColin Finck
475c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
476c2c66affSColin Finck {
477c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
478c2c66affSColin Finck goto lend;
479c2c66affSColin Finck }
480c2c66affSColin Finck
481c2c66affSColin Finck TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
482c2c66affSColin Finck
483c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
484c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
485c2c66affSColin Finck {
486c2c66affSColin Finck directory_task_t *task;
487c2c66affSColin Finck
488c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpSetCurrentDirectoryProc, sizeof(*task));
489c2c66affSColin Finck task->directory = heap_strdupW(lpszDirectory);
490c2c66affSColin Finck
491c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
492c2c66affSColin Finck }
493c2c66affSColin Finck else
494c2c66affSColin Finck {
495c2c66affSColin Finck r = FTP_FtpSetCurrentDirectoryW(lpwfs, lpszDirectory);
496c2c66affSColin Finck }
497c2c66affSColin Finck
498c2c66affSColin Finck lend:
499c2c66affSColin Finck if( lpwfs )
500c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
501c2c66affSColin Finck
502c2c66affSColin Finck return r;
503c2c66affSColin Finck }
504c2c66affSColin Finck
505c2c66affSColin Finck
506c2c66affSColin Finck /***********************************************************************
507c2c66affSColin Finck * FTP_FtpSetCurrentDirectoryW (Internal)
508c2c66affSColin Finck *
509c2c66affSColin Finck * Change the working directory on the FTP server
510c2c66affSColin Finck *
511c2c66affSColin Finck * RETURNS
512c2c66affSColin Finck * TRUE on success
513c2c66affSColin Finck * FALSE on failure
514c2c66affSColin Finck *
515c2c66affSColin Finck */
FTP_FtpSetCurrentDirectoryW(ftp_session_t * lpwfs,LPCWSTR lpszDirectory)516c2c66affSColin Finck static BOOL FTP_FtpSetCurrentDirectoryW(ftp_session_t *lpwfs, LPCWSTR lpszDirectory)
517c2c66affSColin Finck {
518c2c66affSColin Finck INT nResCode;
519c2c66affSColin Finck appinfo_t *hIC = NULL;
520c2c66affSColin Finck BOOL bSuccess = FALSE;
521c2c66affSColin Finck
522c2c66affSColin Finck TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
523c2c66affSColin Finck
524c2c66affSColin Finck /* Clear any error information */
525c2c66affSColin Finck INTERNET_SetLastError(0);
526c2c66affSColin Finck
527c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
528c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_CWD, lpszDirectory,
529c2c66affSColin Finck lpwfs->hdr.lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext))
530c2c66affSColin Finck goto lend;
531c2c66affSColin Finck
532c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
533c2c66affSColin Finck
534c2c66affSColin Finck if (nResCode)
535c2c66affSColin Finck {
536c2c66affSColin Finck if (nResCode == 250)
537c2c66affSColin Finck bSuccess = TRUE;
538c2c66affSColin Finck else
539c2c66affSColin Finck FTP_SetResponseError(nResCode);
540c2c66affSColin Finck }
541c2c66affSColin Finck
542c2c66affSColin Finck lend:
543c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
544c2c66affSColin Finck {
545c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
546c2c66affSColin Finck
547c2c66affSColin Finck iar.dwResult = bSuccess;
548c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
549c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
550c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
551c2c66affSColin Finck }
552c2c66affSColin Finck return bSuccess;
553c2c66affSColin Finck }
554c2c66affSColin Finck
555c2c66affSColin Finck
556c2c66affSColin Finck /***********************************************************************
557c2c66affSColin Finck * FtpCreateDirectoryA (WININET.@)
558c2c66affSColin Finck *
559c2c66affSColin Finck * Create new directory on the FTP server
560c2c66affSColin Finck *
561c2c66affSColin Finck * RETURNS
562c2c66affSColin Finck * TRUE on success
563c2c66affSColin Finck * FALSE on failure
564c2c66affSColin Finck *
565c2c66affSColin Finck */
FtpCreateDirectoryA(HINTERNET hConnect,LPCSTR lpszDirectory)566c2c66affSColin Finck BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
567c2c66affSColin Finck {
568c2c66affSColin Finck LPWSTR lpwzDirectory;
569c2c66affSColin Finck BOOL ret;
570c2c66affSColin Finck
571c2c66affSColin Finck lpwzDirectory = heap_strdupAtoW(lpszDirectory);
572c2c66affSColin Finck ret = FtpCreateDirectoryW(hConnect, lpwzDirectory);
573c2c66affSColin Finck heap_free(lpwzDirectory);
574c2c66affSColin Finck return ret;
575c2c66affSColin Finck }
576c2c66affSColin Finck
577c2c66affSColin Finck
AsyncFtpCreateDirectoryProc(task_header_t * hdr)578c2c66affSColin Finck static void AsyncFtpCreateDirectoryProc(task_header_t *hdr)
579c2c66affSColin Finck {
580c2c66affSColin Finck directory_task_t *task = (directory_task_t*)hdr;
581c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
582c2c66affSColin Finck
583c2c66affSColin Finck TRACE(" %p\n", session);
584c2c66affSColin Finck
585c2c66affSColin Finck FTP_FtpCreateDirectoryW(session, task->directory);
586c2c66affSColin Finck heap_free(task->directory);
587c2c66affSColin Finck }
588c2c66affSColin Finck
589c2c66affSColin Finck /***********************************************************************
590c2c66affSColin Finck * FtpCreateDirectoryW (WININET.@)
591c2c66affSColin Finck *
592c2c66affSColin Finck * Create new directory on the FTP server
593c2c66affSColin Finck *
594c2c66affSColin Finck * RETURNS
595c2c66affSColin Finck * TRUE on success
596c2c66affSColin Finck * FALSE on failure
597c2c66affSColin Finck *
598c2c66affSColin Finck */
FtpCreateDirectoryW(HINTERNET hConnect,LPCWSTR lpszDirectory)599c2c66affSColin Finck BOOL WINAPI FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
600c2c66affSColin Finck {
601c2c66affSColin Finck ftp_session_t *lpwfs;
602c2c66affSColin Finck appinfo_t *hIC = NULL;
603c2c66affSColin Finck BOOL r = FALSE;
604c2c66affSColin Finck
605c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hConnect );
606c2c66affSColin Finck if (!lpwfs)
607c2c66affSColin Finck {
608c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
609c2c66affSColin Finck return FALSE;
610c2c66affSColin Finck }
611c2c66affSColin Finck
612c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
613c2c66affSColin Finck {
614c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
615c2c66affSColin Finck goto lend;
616c2c66affSColin Finck }
617c2c66affSColin Finck
618c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
619c2c66affSColin Finck {
620c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
621c2c66affSColin Finck goto lend;
622c2c66affSColin Finck }
623c2c66affSColin Finck
624c2c66affSColin Finck if (!lpszDirectory)
625c2c66affSColin Finck {
626c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
627c2c66affSColin Finck goto lend;
628c2c66affSColin Finck }
629c2c66affSColin Finck
630c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
631c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
632c2c66affSColin Finck {
633c2c66affSColin Finck directory_task_t *task;
634c2c66affSColin Finck
635c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpCreateDirectoryProc, sizeof(*task));
636c2c66affSColin Finck task->directory = heap_strdupW(lpszDirectory);
637c2c66affSColin Finck
638c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
639c2c66affSColin Finck }
640c2c66affSColin Finck else
641c2c66affSColin Finck {
642c2c66affSColin Finck r = FTP_FtpCreateDirectoryW(lpwfs, lpszDirectory);
643c2c66affSColin Finck }
644c2c66affSColin Finck lend:
645c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
646c2c66affSColin Finck
647c2c66affSColin Finck return r;
648c2c66affSColin Finck }
649c2c66affSColin Finck
650c2c66affSColin Finck
651c2c66affSColin Finck /***********************************************************************
652c2c66affSColin Finck * FTP_FtpCreateDirectoryW (Internal)
653c2c66affSColin Finck *
654c2c66affSColin Finck * Create new directory on the FTP server
655c2c66affSColin Finck *
656c2c66affSColin Finck * RETURNS
657c2c66affSColin Finck * TRUE on success
658c2c66affSColin Finck * FALSE on failure
659c2c66affSColin Finck *
660c2c66affSColin Finck */
FTP_FtpCreateDirectoryW(ftp_session_t * lpwfs,LPCWSTR lpszDirectory)661c2c66affSColin Finck static BOOL FTP_FtpCreateDirectoryW(ftp_session_t *lpwfs, LPCWSTR lpszDirectory)
662c2c66affSColin Finck {
663c2c66affSColin Finck INT nResCode;
664c2c66affSColin Finck BOOL bSuccess = FALSE;
665c2c66affSColin Finck appinfo_t *hIC = NULL;
666c2c66affSColin Finck
667c2c66affSColin Finck TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
668c2c66affSColin Finck
669c2c66affSColin Finck /* Clear any error information */
670c2c66affSColin Finck INTERNET_SetLastError(0);
671c2c66affSColin Finck
672c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_MKD, lpszDirectory, 0, 0, 0))
673c2c66affSColin Finck goto lend;
674c2c66affSColin Finck
675c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
676c2c66affSColin Finck if (nResCode)
677c2c66affSColin Finck {
678c2c66affSColin Finck if (nResCode == 257)
679c2c66affSColin Finck bSuccess = TRUE;
680c2c66affSColin Finck else
681c2c66affSColin Finck FTP_SetResponseError(nResCode);
682c2c66affSColin Finck }
683c2c66affSColin Finck
684c2c66affSColin Finck lend:
685c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
686c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
687c2c66affSColin Finck {
688c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
689c2c66affSColin Finck
690c2c66affSColin Finck iar.dwResult = (DWORD)bSuccess;
691c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
692c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
693c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
694c2c66affSColin Finck }
695c2c66affSColin Finck
696c2c66affSColin Finck return bSuccess;
697c2c66affSColin Finck }
698c2c66affSColin Finck
699c2c66affSColin Finck /***********************************************************************
700c2c66affSColin Finck * FtpFindFirstFileA (WININET.@)
701c2c66affSColin Finck *
702c2c66affSColin Finck * Search the specified directory
703c2c66affSColin Finck *
704c2c66affSColin Finck * RETURNS
705c2c66affSColin Finck * HINTERNET on success
706c2c66affSColin Finck * NULL on failure
707c2c66affSColin Finck *
708c2c66affSColin Finck */
FtpFindFirstFileA(HINTERNET hConnect,LPCSTR lpszSearchFile,LPWIN32_FIND_DATAA lpFindFileData,DWORD dwFlags,DWORD_PTR dwContext)709c2c66affSColin Finck HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect,
710c2c66affSColin Finck LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext)
711c2c66affSColin Finck {
712c2c66affSColin Finck LPWSTR lpwzSearchFile;
713c2c66affSColin Finck WIN32_FIND_DATAW wfd;
714c2c66affSColin Finck LPWIN32_FIND_DATAW lpFindFileDataW;
715c2c66affSColin Finck HINTERNET ret;
716c2c66affSColin Finck
717c2c66affSColin Finck lpwzSearchFile = heap_strdupAtoW(lpszSearchFile);
718c2c66affSColin Finck lpFindFileDataW = lpFindFileData?&wfd:NULL;
719c2c66affSColin Finck ret = FtpFindFirstFileW(hConnect, lpwzSearchFile, lpFindFileDataW, dwFlags, dwContext);
720c2c66affSColin Finck heap_free(lpwzSearchFile);
721c2c66affSColin Finck
722c2c66affSColin Finck if (ret && lpFindFileData)
723c2c66affSColin Finck WININET_find_data_WtoA(lpFindFileDataW, lpFindFileData);
724c2c66affSColin Finck
725c2c66affSColin Finck return ret;
726c2c66affSColin Finck }
727c2c66affSColin Finck
728c2c66affSColin Finck typedef struct {
729c2c66affSColin Finck task_header_t hdr;
730c2c66affSColin Finck WCHAR *search_file;
731c2c66affSColin Finck WIN32_FIND_DATAW *find_file_data;
732c2c66affSColin Finck DWORD flags;
733c2c66affSColin Finck DWORD_PTR context;
734c2c66affSColin Finck } find_first_file_task_t;
735c2c66affSColin Finck
AsyncFtpFindFirstFileProc(task_header_t * hdr)736c2c66affSColin Finck static void AsyncFtpFindFirstFileProc(task_header_t *hdr)
737c2c66affSColin Finck {
738c2c66affSColin Finck find_first_file_task_t *task = (find_first_file_task_t*)hdr;
739c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
740c2c66affSColin Finck
741c2c66affSColin Finck TRACE("%p\n", session);
742c2c66affSColin Finck
743c2c66affSColin Finck FTP_FtpFindFirstFileW(session, task->search_file, task->find_file_data, task->flags, task->context);
744c2c66affSColin Finck heap_free(task->search_file);
745c2c66affSColin Finck }
746c2c66affSColin Finck
747c2c66affSColin Finck /***********************************************************************
748c2c66affSColin Finck * FtpFindFirstFileW (WININET.@)
749c2c66affSColin Finck *
750c2c66affSColin Finck * Search the specified directory
751c2c66affSColin Finck *
752c2c66affSColin Finck * RETURNS
753c2c66affSColin Finck * HINTERNET on success
754c2c66affSColin Finck * NULL on failure
755c2c66affSColin Finck *
756c2c66affSColin Finck */
FtpFindFirstFileW(HINTERNET hConnect,LPCWSTR lpszSearchFile,LPWIN32_FIND_DATAW lpFindFileData,DWORD dwFlags,DWORD_PTR dwContext)757c2c66affSColin Finck HINTERNET WINAPI FtpFindFirstFileW(HINTERNET hConnect,
758c2c66affSColin Finck LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext)
759c2c66affSColin Finck {
760c2c66affSColin Finck ftp_session_t *lpwfs;
761c2c66affSColin Finck appinfo_t *hIC = NULL;
762c2c66affSColin Finck HINTERNET r = NULL;
763c2c66affSColin Finck
764c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hConnect );
765c2c66affSColin Finck if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
766c2c66affSColin Finck {
767c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
768c2c66affSColin Finck goto lend;
769c2c66affSColin Finck }
770c2c66affSColin Finck
771c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
772c2c66affSColin Finck {
773c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
774c2c66affSColin Finck goto lend;
775c2c66affSColin Finck }
776c2c66affSColin Finck
777c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
778c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
779c2c66affSColin Finck {
780c2c66affSColin Finck find_first_file_task_t *task;
781c2c66affSColin Finck
782c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpFindFirstFileProc, sizeof(*task));
783c2c66affSColin Finck task->search_file = heap_strdupW(lpszSearchFile);
784c2c66affSColin Finck task->find_file_data = lpFindFileData;
785c2c66affSColin Finck task->flags = dwFlags;
786c2c66affSColin Finck task->context = dwContext;
787c2c66affSColin Finck
788c2c66affSColin Finck INTERNET_AsyncCall(&task->hdr);
789c2c66affSColin Finck r = NULL;
790c2c66affSColin Finck }
791c2c66affSColin Finck else
792c2c66affSColin Finck {
793c2c66affSColin Finck r = FTP_FtpFindFirstFileW(lpwfs, lpszSearchFile, lpFindFileData,
794c2c66affSColin Finck dwFlags, dwContext);
795c2c66affSColin Finck }
796c2c66affSColin Finck lend:
797c2c66affSColin Finck if( lpwfs )
798c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
799c2c66affSColin Finck
800c2c66affSColin Finck return r;
801c2c66affSColin Finck }
802c2c66affSColin Finck
803c2c66affSColin Finck
804c2c66affSColin Finck /***********************************************************************
805c2c66affSColin Finck * FTP_FtpFindFirstFileW (Internal)
806c2c66affSColin Finck *
807c2c66affSColin Finck * Search the specified directory
808c2c66affSColin Finck *
809c2c66affSColin Finck * RETURNS
810c2c66affSColin Finck * HINTERNET on success
811c2c66affSColin Finck * NULL on failure
812c2c66affSColin Finck *
813c2c66affSColin Finck */
FTP_FtpFindFirstFileW(ftp_session_t * lpwfs,LPCWSTR lpszSearchFile,LPWIN32_FIND_DATAW lpFindFileData,DWORD dwFlags,DWORD_PTR dwContext)814c2c66affSColin Finck static HINTERNET FTP_FtpFindFirstFileW(ftp_session_t *lpwfs,
815c2c66affSColin Finck LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext)
816c2c66affSColin Finck {
817c2c66affSColin Finck INT nResCode;
818c2c66affSColin Finck appinfo_t *hIC = NULL;
819c2c66affSColin Finck HINTERNET hFindNext = NULL;
820c2c66affSColin Finck LPWSTR lpszSearchPath = NULL;
821c2c66affSColin Finck
822c2c66affSColin Finck TRACE("\n");
823c2c66affSColin Finck
824c2c66affSColin Finck /* Clear any error information */
825c2c66affSColin Finck INTERNET_SetLastError(0);
826c2c66affSColin Finck
827c2c66affSColin Finck if (!FTP_InitListenSocket(lpwfs))
828c2c66affSColin Finck goto lend;
829c2c66affSColin Finck
830c2c66affSColin Finck if (!FTP_SendType(lpwfs, INTERNET_FLAG_TRANSFER_ASCII))
831c2c66affSColin Finck goto lend;
832c2c66affSColin Finck
833c2c66affSColin Finck if (!FTP_SendPortOrPasv(lpwfs))
834c2c66affSColin Finck goto lend;
835c2c66affSColin Finck
836c2c66affSColin Finck /* split search path into file and path */
837c2c66affSColin Finck if (lpszSearchFile)
838c2c66affSColin Finck {
839c2c66affSColin Finck LPCWSTR name = lpszSearchFile, p;
8405f12c8d7Swinesync if ((p = wcsrchr( name, '\\' ))) name = p + 1;
8415f12c8d7Swinesync if ((p = wcsrchr( name, '/' ))) name = p + 1;
842c2c66affSColin Finck if (name != lpszSearchFile)
843c2c66affSColin Finck {
844c2c66affSColin Finck lpszSearchPath = heap_strndupW(lpszSearchFile, name - lpszSearchFile);
845c2c66affSColin Finck lpszSearchFile = name;
846c2c66affSColin Finck }
847c2c66affSColin Finck }
848c2c66affSColin Finck
849c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_LIST, lpszSearchPath,
850c2c66affSColin Finck lpwfs->hdr.lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext))
851c2c66affSColin Finck goto lend;
852c2c66affSColin Finck
853c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
854c2c66affSColin Finck if (nResCode)
855c2c66affSColin Finck {
856c2c66affSColin Finck if (nResCode == 125 || nResCode == 150)
857c2c66affSColin Finck {
858c2c66affSColin Finck INT nDataSocket;
859c2c66affSColin Finck
860c2c66affSColin Finck /* Get data socket to server */
861c2c66affSColin Finck if (FTP_GetDataSocket(lpwfs, &nDataSocket))
862c2c66affSColin Finck {
863c2c66affSColin Finck hFindNext = FTP_ReceiveFileList(lpwfs, nDataSocket, lpszSearchFile, lpFindFileData, dwContext);
864c2c66affSColin Finck closesocket(nDataSocket);
865c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
866c2c66affSColin Finck if (nResCode != 226 && nResCode != 250)
867c2c66affSColin Finck INTERNET_SetLastError(ERROR_NO_MORE_FILES);
868c2c66affSColin Finck }
869c2c66affSColin Finck }
870c2c66affSColin Finck else
871c2c66affSColin Finck FTP_SetResponseError(nResCode);
872c2c66affSColin Finck }
873c2c66affSColin Finck
874c2c66affSColin Finck lend:
875c2c66affSColin Finck heap_free(lpszSearchPath);
876c2c66affSColin Finck
877c2c66affSColin Finck if (lpwfs->lstnSocket != -1)
878c2c66affSColin Finck {
879c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
880c2c66affSColin Finck lpwfs->lstnSocket = -1;
881c2c66affSColin Finck }
882c2c66affSColin Finck
883c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
884c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
885c2c66affSColin Finck {
886c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
887c2c66affSColin Finck
888c2c66affSColin Finck if (hFindNext)
889c2c66affSColin Finck {
890c2c66affSColin Finck iar.dwResult = (DWORD_PTR)hFindNext;
891c2c66affSColin Finck iar.dwError = ERROR_SUCCESS;
892c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
893c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
894c2c66affSColin Finck }
895c2c66affSColin Finck
896c2c66affSColin Finck iar.dwResult = (DWORD_PTR)hFindNext;
897c2c66affSColin Finck iar.dwError = hFindNext ? ERROR_SUCCESS : INTERNET_GetLastError();
898c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
899c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
900c2c66affSColin Finck }
901c2c66affSColin Finck
902c2c66affSColin Finck return hFindNext;
903c2c66affSColin Finck }
904c2c66affSColin Finck
905c2c66affSColin Finck
906c2c66affSColin Finck /***********************************************************************
907c2c66affSColin Finck * FtpGetCurrentDirectoryA (WININET.@)
908c2c66affSColin Finck *
909c2c66affSColin Finck * Retrieves the current directory
910c2c66affSColin Finck *
911c2c66affSColin Finck * RETURNS
912c2c66affSColin Finck * TRUE on success
913c2c66affSColin Finck * FALSE on failure
914c2c66affSColin Finck *
915c2c66affSColin Finck */
FtpGetCurrentDirectoryA(HINTERNET hFtpSession,LPSTR lpszCurrentDirectory,LPDWORD lpdwCurrentDirectory)916c2c66affSColin Finck BOOL WINAPI FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory,
917c2c66affSColin Finck LPDWORD lpdwCurrentDirectory)
918c2c66affSColin Finck {
919c2c66affSColin Finck WCHAR *dir = NULL;
920c2c66affSColin Finck DWORD len;
921c2c66affSColin Finck BOOL ret;
922c2c66affSColin Finck
923c2c66affSColin Finck if(lpdwCurrentDirectory) {
924c2c66affSColin Finck len = *lpdwCurrentDirectory;
925c2c66affSColin Finck if(lpszCurrentDirectory)
926c2c66affSColin Finck {
927c2c66affSColin Finck dir = heap_alloc(len * sizeof(WCHAR));
928c2c66affSColin Finck if (NULL == dir)
929c2c66affSColin Finck {
930c2c66affSColin Finck INTERNET_SetLastError(ERROR_OUTOFMEMORY);
931c2c66affSColin Finck return FALSE;
932c2c66affSColin Finck }
933c2c66affSColin Finck }
934c2c66affSColin Finck }
935c2c66affSColin Finck ret = FtpGetCurrentDirectoryW(hFtpSession, lpszCurrentDirectory?dir:NULL, lpdwCurrentDirectory?&len:NULL);
936c2c66affSColin Finck
937c2c66affSColin Finck if (ret && lpszCurrentDirectory)
938c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, dir, -1, lpszCurrentDirectory, len, NULL, NULL);
939c2c66affSColin Finck
940c2c66affSColin Finck if (lpdwCurrentDirectory) *lpdwCurrentDirectory = len;
941c2c66affSColin Finck heap_free(dir);
942c2c66affSColin Finck return ret;
943c2c66affSColin Finck }
944c2c66affSColin Finck
945c2c66affSColin Finck typedef struct {
946c2c66affSColin Finck task_header_t hdr;
947c2c66affSColin Finck WCHAR *directory;
948c2c66affSColin Finck DWORD *directory_len;
949c2c66affSColin Finck } get_current_dir_task_t;
950c2c66affSColin Finck
AsyncFtpGetCurrentDirectoryProc(task_header_t * hdr)951c2c66affSColin Finck static void AsyncFtpGetCurrentDirectoryProc(task_header_t *hdr)
952c2c66affSColin Finck {
953c2c66affSColin Finck get_current_dir_task_t *task = (get_current_dir_task_t*)hdr;
954c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
955c2c66affSColin Finck
956c2c66affSColin Finck TRACE("%p\n", session);
957c2c66affSColin Finck
958c2c66affSColin Finck FTP_FtpGetCurrentDirectoryW(session, task->directory, task->directory_len);
959c2c66affSColin Finck }
960c2c66affSColin Finck
961c2c66affSColin Finck /***********************************************************************
962c2c66affSColin Finck * FtpGetCurrentDirectoryW (WININET.@)
963c2c66affSColin Finck *
964c2c66affSColin Finck * Retrieves the current directory
965c2c66affSColin Finck *
966c2c66affSColin Finck * RETURNS
967c2c66affSColin Finck * TRUE on success
968c2c66affSColin Finck * FALSE on failure
969c2c66affSColin Finck *
970c2c66affSColin Finck */
FtpGetCurrentDirectoryW(HINTERNET hFtpSession,LPWSTR lpszCurrentDirectory,LPDWORD lpdwCurrentDirectory)971c2c66affSColin Finck BOOL WINAPI FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDirectory,
972c2c66affSColin Finck LPDWORD lpdwCurrentDirectory)
973c2c66affSColin Finck {
974c2c66affSColin Finck ftp_session_t *lpwfs;
975c2c66affSColin Finck appinfo_t *hIC = NULL;
976c2c66affSColin Finck BOOL r = FALSE;
977c2c66affSColin Finck
978c2c66affSColin Finck TRACE("%p %p %p\n", hFtpSession, lpszCurrentDirectory, lpdwCurrentDirectory);
979c2c66affSColin Finck
980c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hFtpSession );
981c2c66affSColin Finck if (NULL == lpwfs)
982c2c66affSColin Finck {
983c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
984c2c66affSColin Finck goto lend;
985c2c66affSColin Finck }
986c2c66affSColin Finck
987c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
988c2c66affSColin Finck {
989c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
990c2c66affSColin Finck goto lend;
991c2c66affSColin Finck }
992c2c66affSColin Finck
993c2c66affSColin Finck if (!lpdwCurrentDirectory)
994c2c66affSColin Finck {
995c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
996c2c66affSColin Finck goto lend;
997c2c66affSColin Finck }
998c2c66affSColin Finck
999c2c66affSColin Finck if (lpszCurrentDirectory == NULL)
1000c2c66affSColin Finck {
1001c2c66affSColin Finck INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1002c2c66affSColin Finck goto lend;
1003c2c66affSColin Finck }
1004c2c66affSColin Finck
1005c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
1006c2c66affSColin Finck {
1007c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1008c2c66affSColin Finck goto lend;
1009c2c66affSColin Finck }
1010c2c66affSColin Finck
1011c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1012c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1013c2c66affSColin Finck {
1014c2c66affSColin Finck get_current_dir_task_t *task;
1015c2c66affSColin Finck
1016c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpGetCurrentDirectoryProc, sizeof(*task));
1017c2c66affSColin Finck task->directory = lpszCurrentDirectory;
1018c2c66affSColin Finck task->directory_len = lpdwCurrentDirectory;
1019c2c66affSColin Finck
1020c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
1021c2c66affSColin Finck }
1022c2c66affSColin Finck else
1023c2c66affSColin Finck {
1024c2c66affSColin Finck r = FTP_FtpGetCurrentDirectoryW(lpwfs, lpszCurrentDirectory,
1025c2c66affSColin Finck lpdwCurrentDirectory);
1026c2c66affSColin Finck }
1027c2c66affSColin Finck
1028c2c66affSColin Finck lend:
1029c2c66affSColin Finck if( lpwfs )
1030c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
1031c2c66affSColin Finck
1032c2c66affSColin Finck return r;
1033c2c66affSColin Finck }
1034c2c66affSColin Finck
1035c2c66affSColin Finck
1036c2c66affSColin Finck /***********************************************************************
1037c2c66affSColin Finck * FTP_FtpGetCurrentDirectoryW (Internal)
1038c2c66affSColin Finck *
1039c2c66affSColin Finck * Retrieves the current directory
1040c2c66affSColin Finck *
1041c2c66affSColin Finck * RETURNS
1042c2c66affSColin Finck * TRUE on success
1043c2c66affSColin Finck * FALSE on failure
1044c2c66affSColin Finck *
1045c2c66affSColin Finck */
FTP_FtpGetCurrentDirectoryW(ftp_session_t * lpwfs,LPWSTR lpszCurrentDirectory,LPDWORD lpdwCurrentDirectory)1046c2c66affSColin Finck static BOOL FTP_FtpGetCurrentDirectoryW(ftp_session_t *lpwfs, LPWSTR lpszCurrentDirectory,
1047c2c66affSColin Finck LPDWORD lpdwCurrentDirectory)
1048c2c66affSColin Finck {
1049c2c66affSColin Finck INT nResCode;
1050c2c66affSColin Finck appinfo_t *hIC = NULL;
1051c2c66affSColin Finck BOOL bSuccess = FALSE;
1052c2c66affSColin Finck
1053c2c66affSColin Finck /* Clear any error information */
1054c2c66affSColin Finck INTERNET_SetLastError(0);
1055c2c66affSColin Finck
1056c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1057c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PWD, NULL,
1058c2c66affSColin Finck lpwfs->hdr.lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext))
1059c2c66affSColin Finck goto lend;
1060c2c66affSColin Finck
1061c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
1062c2c66affSColin Finck if (nResCode)
1063c2c66affSColin Finck {
1064c2c66affSColin Finck if (nResCode == 257) /* Extract directory name */
1065c2c66affSColin Finck {
1066c2c66affSColin Finck DWORD firstpos, lastpos, len;
1067c2c66affSColin Finck LPWSTR lpszResponseBuffer = heap_strdupAtoW(INTERNET_GetResponseBuffer());
1068c2c66affSColin Finck
1069c2c66affSColin Finck for (firstpos = 0, lastpos = 0; lpszResponseBuffer[lastpos]; lastpos++)
1070c2c66affSColin Finck {
1071c2c66affSColin Finck if ('"' == lpszResponseBuffer[lastpos])
1072c2c66affSColin Finck {
1073c2c66affSColin Finck if (!firstpos)
1074c2c66affSColin Finck firstpos = lastpos;
1075c2c66affSColin Finck else
1076c2c66affSColin Finck break;
1077c2c66affSColin Finck }
1078c2c66affSColin Finck }
1079c2c66affSColin Finck len = lastpos - firstpos;
1080c2c66affSColin Finck if (*lpdwCurrentDirectory >= len)
1081c2c66affSColin Finck {
1082c2c66affSColin Finck memcpy(lpszCurrentDirectory, &lpszResponseBuffer[firstpos + 1], len * sizeof(WCHAR));
1083c2c66affSColin Finck lpszCurrentDirectory[len - 1] = 0;
1084c2c66affSColin Finck *lpdwCurrentDirectory = len;
1085c2c66affSColin Finck bSuccess = TRUE;
1086c2c66affSColin Finck }
1087c2c66affSColin Finck else INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1088c2c66affSColin Finck
1089c2c66affSColin Finck heap_free(lpszResponseBuffer);
1090c2c66affSColin Finck }
1091c2c66affSColin Finck else
1092c2c66affSColin Finck FTP_SetResponseError(nResCode);
1093c2c66affSColin Finck }
1094c2c66affSColin Finck
1095c2c66affSColin Finck lend:
1096c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1097c2c66affSColin Finck {
1098c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
1099c2c66affSColin Finck
1100c2c66affSColin Finck iar.dwResult = bSuccess;
1101c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
1102c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1103c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
1104c2c66affSColin Finck }
1105c2c66affSColin Finck
1106c2c66affSColin Finck return bSuccess;
1107c2c66affSColin Finck }
1108c2c66affSColin Finck
1109c2c66affSColin Finck
1110c2c66affSColin Finck /***********************************************************************
1111c2c66affSColin Finck * FTPFILE_Destroy(internal)
1112c2c66affSColin Finck *
1113c2c66affSColin Finck * Closes the file transfer handle. This also 'cleans' the data queue of
1114c2c66affSColin Finck * the 'transfer complete' message (this is a bit of a hack though :-/ )
1115c2c66affSColin Finck *
1116c2c66affSColin Finck */
FTPFILE_Destroy(object_header_t * hdr)1117c2c66affSColin Finck static void FTPFILE_Destroy(object_header_t *hdr)
1118c2c66affSColin Finck {
1119c2c66affSColin Finck ftp_file_t *lpwh = (ftp_file_t*) hdr;
1120c2c66affSColin Finck ftp_session_t *lpwfs = lpwh->lpFtpSession;
1121c2c66affSColin Finck INT nResCode;
1122c2c66affSColin Finck
1123c2c66affSColin Finck TRACE("\n");
1124c2c66affSColin Finck
1125c2c66affSColin Finck if (lpwh->cache_file_handle != INVALID_HANDLE_VALUE)
1126c2c66affSColin Finck CloseHandle(lpwh->cache_file_handle);
1127c2c66affSColin Finck
1128c2c66affSColin Finck heap_free(lpwh->cache_file);
1129c2c66affSColin Finck
1130c2c66affSColin Finck if (!lpwh->session_deleted)
1131c2c66affSColin Finck lpwfs->download_in_progress = NULL;
1132c2c66affSColin Finck
1133c2c66affSColin Finck if (lpwh->nDataSocket != -1)
1134c2c66affSColin Finck closesocket(lpwh->nDataSocket);
1135c2c66affSColin Finck
1136c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
1137c2c66affSColin Finck if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n");
1138c2c66affSColin Finck
1139c2c66affSColin Finck WININET_Release(&lpwh->lpFtpSession->hdr);
1140c2c66affSColin Finck }
1141c2c66affSColin Finck
FTPFILE_QueryOption(object_header_t * hdr,DWORD option,void * buffer,DWORD * size,BOOL unicode)1142c2c66affSColin Finck static DWORD FTPFILE_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
1143c2c66affSColin Finck {
1144c2c66affSColin Finck switch(option) {
1145c2c66affSColin Finck case INTERNET_OPTION_HANDLE_TYPE:
1146c2c66affSColin Finck TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
1147c2c66affSColin Finck
1148c2c66affSColin Finck if (*size < sizeof(ULONG))
1149c2c66affSColin Finck return ERROR_INSUFFICIENT_BUFFER;
1150c2c66affSColin Finck
1151c2c66affSColin Finck *size = sizeof(DWORD);
1152c2c66affSColin Finck *(DWORD*)buffer = INTERNET_HANDLE_TYPE_FTP_FILE;
1153c2c66affSColin Finck return ERROR_SUCCESS;
1154c2c66affSColin Finck case INTERNET_OPTION_DATAFILE_NAME:
1155c2c66affSColin Finck {
1156c2c66affSColin Finck DWORD required;
1157c2c66affSColin Finck ftp_file_t *file = (ftp_file_t *)hdr;
1158c2c66affSColin Finck
1159c2c66affSColin Finck TRACE("INTERNET_OPTION_DATAFILE_NAME\n");
1160c2c66affSColin Finck
1161c2c66affSColin Finck if (!file->cache_file)
1162c2c66affSColin Finck {
1163c2c66affSColin Finck *size = 0;
1164c2c66affSColin Finck return ERROR_INTERNET_ITEM_NOT_FOUND;
1165c2c66affSColin Finck }
1166c2c66affSColin Finck if (unicode)
1167c2c66affSColin Finck {
1168c2c66affSColin Finck required = (lstrlenW(file->cache_file) + 1) * sizeof(WCHAR);
1169c2c66affSColin Finck if (*size < required)
1170c2c66affSColin Finck return ERROR_INSUFFICIENT_BUFFER;
1171c2c66affSColin Finck
1172c2c66affSColin Finck *size = required;
1173c2c66affSColin Finck memcpy(buffer, file->cache_file, *size);
1174c2c66affSColin Finck return ERROR_SUCCESS;
1175c2c66affSColin Finck }
1176c2c66affSColin Finck else
1177c2c66affSColin Finck {
1178c2c66affSColin Finck required = WideCharToMultiByte(CP_ACP, 0, file->cache_file, -1, NULL, 0, NULL, NULL);
1179c2c66affSColin Finck if (required > *size)
1180c2c66affSColin Finck return ERROR_INSUFFICIENT_BUFFER;
1181c2c66affSColin Finck
1182c2c66affSColin Finck *size = WideCharToMultiByte(CP_ACP, 0, file->cache_file, -1, buffer, *size, NULL, NULL);
1183c2c66affSColin Finck return ERROR_SUCCESS;
1184c2c66affSColin Finck }
1185c2c66affSColin Finck }
1186c2c66affSColin Finck }
1187c2c66affSColin Finck return INET_QueryOption(hdr, option, buffer, size, unicode);
1188c2c66affSColin Finck }
1189c2c66affSColin Finck
FTPFILE_ReadFile(object_header_t * hdr,void * buffer,DWORD size,DWORD * read,DWORD flags,DWORD_PTR context)1190c2c66affSColin Finck static DWORD FTPFILE_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read,
1191c2c66affSColin Finck DWORD flags, DWORD_PTR context)
1192c2c66affSColin Finck {
1193c2c66affSColin Finck ftp_file_t *file = (ftp_file_t*)hdr;
1194c2c66affSColin Finck int res;
1195c2c66affSColin Finck DWORD error;
1196c2c66affSColin Finck
1197c2c66affSColin Finck if (file->nDataSocket == -1)
1198c2c66affSColin Finck return ERROR_INTERNET_DISCONNECTED;
1199c2c66affSColin Finck
1200c2c66affSColin Finck /* FIXME: FTP should use NETCON_ stuff */
1201c2c66affSColin Finck res = sock_recv(file->nDataSocket, buffer, size, MSG_WAITALL);
1202c2c66affSColin Finck *read = res>0 ? res : 0;
1203c2c66affSColin Finck
1204c2c66affSColin Finck error = res >= 0 ? ERROR_SUCCESS : INTERNET_ERROR_BASE; /* FIXME */
1205c2c66affSColin Finck if (error == ERROR_SUCCESS && file->cache_file)
1206c2c66affSColin Finck {
1207c2c66affSColin Finck DWORD bytes_written;
1208c2c66affSColin Finck
1209c2c66affSColin Finck if (!WriteFile(file->cache_file_handle, buffer, *read, &bytes_written, NULL))
1210c2c66affSColin Finck WARN("WriteFile failed: %u\n", GetLastError());
1211c2c66affSColin Finck }
1212c2c66affSColin Finck return error;
1213c2c66affSColin Finck }
1214c2c66affSColin Finck
FTPFILE_WriteFile(object_header_t * hdr,const void * buffer,DWORD size,DWORD * written)1215c2c66affSColin Finck static DWORD FTPFILE_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
1216c2c66affSColin Finck {
1217c2c66affSColin Finck ftp_file_t *lpwh = (ftp_file_t*) hdr;
1218c2c66affSColin Finck int res;
1219c2c66affSColin Finck
1220c2c66affSColin Finck res = sock_send(lpwh->nDataSocket, buffer, size, 0);
1221c2c66affSColin Finck
1222c2c66affSColin Finck *written = res>0 ? res : 0;
1223c2c66affSColin Finck return res >= 0 ? ERROR_SUCCESS : WSAGetLastError();
1224c2c66affSColin Finck }
1225c2c66affSColin Finck
FTP_ReceiveRequestData(ftp_file_t * file,BOOL first_notif)1226c2c66affSColin Finck static void FTP_ReceiveRequestData(ftp_file_t *file, BOOL first_notif)
1227c2c66affSColin Finck {
1228c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
1229c2c66affSColin Finck BYTE buffer[4096];
1230c2c66affSColin Finck int available;
1231c2c66affSColin Finck
1232c2c66affSColin Finck TRACE("%p\n", file);
1233c2c66affSColin Finck
1234c2c66affSColin Finck available = sock_recv(file->nDataSocket, buffer, sizeof(buffer), MSG_PEEK);
1235c2c66affSColin Finck
1236c2c66affSColin Finck if(available != -1) {
1237c2c66affSColin Finck iar.dwResult = (DWORD_PTR)file->hdr.hInternet;
1238c2c66affSColin Finck iar.dwError = first_notif ? 0 : available;
1239c2c66affSColin Finck }else {
1240c2c66affSColin Finck iar.dwResult = 0;
1241c2c66affSColin Finck iar.dwError = INTERNET_GetLastError();
1242c2c66affSColin Finck }
1243c2c66affSColin Finck
1244c2c66affSColin Finck INTERNET_SendCallback(&file->hdr, file->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar,
1245c2c66affSColin Finck sizeof(INTERNET_ASYNC_RESULT));
1246c2c66affSColin Finck }
1247c2c66affSColin Finck
FTPFILE_AsyncQueryDataAvailableProc(task_header_t * task)1248c2c66affSColin Finck static void FTPFILE_AsyncQueryDataAvailableProc(task_header_t *task)
1249c2c66affSColin Finck {
1250c2c66affSColin Finck ftp_file_t *file = (ftp_file_t*)task->hdr;
1251c2c66affSColin Finck
1252c2c66affSColin Finck FTP_ReceiveRequestData(file, FALSE);
1253c2c66affSColin Finck }
1254c2c66affSColin Finck
FTPFILE_QueryDataAvailable(object_header_t * hdr,DWORD * available,DWORD flags,DWORD_PTR ctx)1255c2c66affSColin Finck static DWORD FTPFILE_QueryDataAvailable(object_header_t *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx)
1256c2c66affSColin Finck {
1257c2c66affSColin Finck ftp_file_t *file = (ftp_file_t*) hdr;
1258c2c66affSColin Finck ULONG unread = 0;
1259c2c66affSColin Finck int retval;
1260c2c66affSColin Finck
1261c2c66affSColin Finck TRACE("(%p %p %x %lx)\n", file, available, flags, ctx);
1262c2c66affSColin Finck
1263c2c66affSColin Finck retval = ioctlsocket(file->nDataSocket, FIONREAD, &unread);
1264c2c66affSColin Finck if (!retval)
1265c2c66affSColin Finck TRACE("%d bytes of queued, but unread data\n", unread);
1266c2c66affSColin Finck
1267c2c66affSColin Finck *available = unread;
1268c2c66affSColin Finck
1269c2c66affSColin Finck if(!unread) {
1270c2c66affSColin Finck BYTE byte;
1271c2c66affSColin Finck
1272c2c66affSColin Finck *available = 0;
1273c2c66affSColin Finck
1274c2c66affSColin Finck retval = sock_recv(file->nDataSocket, &byte, 1, MSG_PEEK);
1275c2c66affSColin Finck if(retval > 0) {
1276c2c66affSColin Finck task_header_t *task;
1277c2c66affSColin Finck
1278c2c66affSColin Finck task = alloc_async_task(&file->hdr, FTPFILE_AsyncQueryDataAvailableProc, sizeof(*task));
1279c2c66affSColin Finck INTERNET_AsyncCall(task);
1280c2c66affSColin Finck
1281c2c66affSColin Finck return ERROR_IO_PENDING;
1282c2c66affSColin Finck }
1283c2c66affSColin Finck }
1284c2c66affSColin Finck
1285c2c66affSColin Finck return ERROR_SUCCESS;
1286c2c66affSColin Finck }
1287c2c66affSColin Finck
FTPFILE_LockRequestFile(object_header_t * hdr,req_file_t ** ret)1288c2c66affSColin Finck static DWORD FTPFILE_LockRequestFile(object_header_t *hdr, req_file_t **ret)
1289c2c66affSColin Finck {
1290c2c66affSColin Finck ftp_file_t *file = (ftp_file_t*)hdr;
1291c2c66affSColin Finck FIXME("%p\n", file);
1292c2c66affSColin Finck return ERROR_NOT_SUPPORTED;
1293c2c66affSColin Finck }
1294c2c66affSColin Finck
1295c2c66affSColin Finck static const object_vtbl_t FTPFILEVtbl = {
1296c2c66affSColin Finck FTPFILE_Destroy,
1297c2c66affSColin Finck NULL,
1298c2c66affSColin Finck FTPFILE_QueryOption,
1299c2c66affSColin Finck INET_SetOption,
1300c2c66affSColin Finck FTPFILE_ReadFile,
1301c2c66affSColin Finck FTPFILE_WriteFile,
1302c2c66affSColin Finck FTPFILE_QueryDataAvailable,
1303c2c66affSColin Finck NULL,
1304c2c66affSColin Finck FTPFILE_LockRequestFile
1305c2c66affSColin Finck };
1306c2c66affSColin Finck
1307c2c66affSColin Finck /***********************************************************************
1308c2c66affSColin Finck * FTP_FtpOpenFileW (Internal)
1309c2c66affSColin Finck *
1310c2c66affSColin Finck * Open a remote file for writing or reading
1311c2c66affSColin Finck *
1312c2c66affSColin Finck * RETURNS
1313c2c66affSColin Finck * HINTERNET handle on success
1314c2c66affSColin Finck * NULL on failure
1315c2c66affSColin Finck *
1316c2c66affSColin Finck */
FTP_FtpOpenFileW(ftp_session_t * lpwfs,LPCWSTR lpszFileName,DWORD fdwAccess,DWORD dwFlags,DWORD_PTR dwContext)1317c2c66affSColin Finck static HINTERNET FTP_FtpOpenFileW(ftp_session_t *lpwfs,
1318c2c66affSColin Finck LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
1319c2c66affSColin Finck DWORD_PTR dwContext)
1320c2c66affSColin Finck {
1321c2c66affSColin Finck INT nDataSocket;
1322c2c66affSColin Finck BOOL bSuccess = FALSE;
1323c2c66affSColin Finck ftp_file_t *lpwh = NULL;
1324c2c66affSColin Finck appinfo_t *hIC = NULL;
1325c2c66affSColin Finck
1326c2c66affSColin Finck TRACE("\n");
1327c2c66affSColin Finck
1328c2c66affSColin Finck /* Clear any error information */
1329c2c66affSColin Finck INTERNET_SetLastError(0);
1330c2c66affSColin Finck
1331c2c66affSColin Finck if (GENERIC_READ == fdwAccess)
1332c2c66affSColin Finck {
1333c2c66affSColin Finck /* Set up socket to retrieve data */
1334c2c66affSColin Finck bSuccess = FTP_SendRetrieve(lpwfs, lpszFileName, dwFlags);
1335c2c66affSColin Finck }
1336c2c66affSColin Finck else if (GENERIC_WRITE == fdwAccess)
1337c2c66affSColin Finck {
1338c2c66affSColin Finck /* Set up socket to send data */
1339c2c66affSColin Finck bSuccess = FTP_SendStore(lpwfs, lpszFileName, dwFlags);
1340c2c66affSColin Finck }
1341c2c66affSColin Finck
1342c2c66affSColin Finck /* Get data socket to server */
1343c2c66affSColin Finck if (bSuccess && FTP_GetDataSocket(lpwfs, &nDataSocket))
1344c2c66affSColin Finck {
1345c2c66affSColin Finck lpwh = alloc_object(&lpwfs->hdr, &FTPFILEVtbl, sizeof(ftp_file_t));
1346c2c66affSColin Finck lpwh->hdr.htype = WH_HFILE;
1347c2c66affSColin Finck lpwh->hdr.dwFlags = dwFlags;
1348c2c66affSColin Finck lpwh->hdr.dwContext = dwContext;
1349c2c66affSColin Finck lpwh->nDataSocket = nDataSocket;
1350c2c66affSColin Finck lpwh->cache_file = NULL;
1351c2c66affSColin Finck lpwh->cache_file_handle = INVALID_HANDLE_VALUE;
1352c2c66affSColin Finck lpwh->session_deleted = FALSE;
1353c2c66affSColin Finck
1354c2c66affSColin Finck WININET_AddRef( &lpwfs->hdr );
1355c2c66affSColin Finck lpwh->lpFtpSession = lpwfs;
1356c2c66affSColin Finck list_add_head( &lpwfs->hdr.children, &lpwh->hdr.entry );
1357c2c66affSColin Finck
1358c2c66affSColin Finck /* Indicate that a download is currently in progress */
1359c2c66affSColin Finck lpwfs->download_in_progress = lpwh;
1360c2c66affSColin Finck }
1361c2c66affSColin Finck
1362c2c66affSColin Finck if (lpwfs->lstnSocket != -1)
1363c2c66affSColin Finck {
1364c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
1365c2c66affSColin Finck lpwfs->lstnSocket = -1;
1366c2c66affSColin Finck }
1367c2c66affSColin Finck
1368c2c66affSColin Finck if (bSuccess && fdwAccess == GENERIC_READ)
1369c2c66affSColin Finck {
1370c2c66affSColin Finck WCHAR filename[MAX_PATH + 1];
1371c2c66affSColin Finck URL_COMPONENTSW uc;
1372c2c66affSColin Finck DWORD len;
1373c2c66affSColin Finck
1374c2c66affSColin Finck memset(&uc, 0, sizeof(uc));
1375c2c66affSColin Finck uc.dwStructSize = sizeof(uc);
1376c2c66affSColin Finck uc.nScheme = INTERNET_SCHEME_FTP;
1377c2c66affSColin Finck uc.lpszHostName = lpwfs->servername;
1378c2c66affSColin Finck uc.nPort = lpwfs->serverport;
1379c2c66affSColin Finck uc.lpszUserName = lpwfs->lpszUserName;
1380c2c66affSColin Finck uc.lpszUrlPath = heap_strdupW(lpszFileName);
1381c2c66affSColin Finck
1382c2c66affSColin Finck if (!InternetCreateUrlW(&uc, 0, NULL, &len) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1383c2c66affSColin Finck {
1384c2c66affSColin Finck WCHAR *url = heap_alloc(len * sizeof(WCHAR));
1385c2c66affSColin Finck
1386c2c66affSColin Finck if (url && InternetCreateUrlW(&uc, 0, url, &len) && CreateUrlCacheEntryW(url, 0, NULL, filename, 0))
1387c2c66affSColin Finck {
1388c2c66affSColin Finck lpwh->cache_file = heap_strdupW(filename);
1389c2c66affSColin Finck lpwh->cache_file_handle = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ,
1390c2c66affSColin Finck NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1391c2c66affSColin Finck if (lpwh->cache_file_handle == INVALID_HANDLE_VALUE)
1392c2c66affSColin Finck {
1393c2c66affSColin Finck WARN("Could not create cache file: %u\n", GetLastError());
1394c2c66affSColin Finck heap_free(lpwh->cache_file);
1395c2c66affSColin Finck lpwh->cache_file = NULL;
1396c2c66affSColin Finck }
1397c2c66affSColin Finck }
1398c2c66affSColin Finck heap_free(url);
1399c2c66affSColin Finck }
1400c2c66affSColin Finck heap_free(uc.lpszUrlPath);
1401c2c66affSColin Finck }
1402c2c66affSColin Finck
1403c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1404c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1405c2c66affSColin Finck {
1406c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
1407c2c66affSColin Finck
1408c2c66affSColin Finck if (lpwh)
1409c2c66affSColin Finck {
1410c2c66affSColin Finck iar.dwResult = (DWORD_PTR)lpwh->hdr.hInternet;
1411c2c66affSColin Finck iar.dwError = ERROR_SUCCESS;
1412c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
1413c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
1414c2c66affSColin Finck }
1415c2c66affSColin Finck
1416c2c66affSColin Finck if(bSuccess) {
1417c2c66affSColin Finck FTP_ReceiveRequestData(lpwh, TRUE);
1418c2c66affSColin Finck }else {
1419c2c66affSColin Finck iar.dwResult = 0;
1420c2c66affSColin Finck iar.dwError = INTERNET_GetLastError();
1421c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1422c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
1423c2c66affSColin Finck }
1424c2c66affSColin Finck }
1425c2c66affSColin Finck
1426c2c66affSColin Finck if(!bSuccess)
1427c2c66affSColin Finck return FALSE;
1428c2c66affSColin Finck
1429c2c66affSColin Finck return lpwh->hdr.hInternet;
1430c2c66affSColin Finck }
1431c2c66affSColin Finck
1432c2c66affSColin Finck
1433c2c66affSColin Finck /***********************************************************************
1434c2c66affSColin Finck * FtpOpenFileA (WININET.@)
1435c2c66affSColin Finck *
1436c2c66affSColin Finck * Open a remote file for writing or reading
1437c2c66affSColin Finck *
1438c2c66affSColin Finck * RETURNS
1439c2c66affSColin Finck * HINTERNET handle on success
1440c2c66affSColin Finck * NULL on failure
1441c2c66affSColin Finck *
1442c2c66affSColin Finck */
FtpOpenFileA(HINTERNET hFtpSession,LPCSTR lpszFileName,DWORD fdwAccess,DWORD dwFlags,DWORD_PTR dwContext)1443c2c66affSColin Finck HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
1444c2c66affSColin Finck LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
1445c2c66affSColin Finck DWORD_PTR dwContext)
1446c2c66affSColin Finck {
1447c2c66affSColin Finck LPWSTR lpwzFileName;
1448c2c66affSColin Finck HINTERNET ret;
1449c2c66affSColin Finck
1450c2c66affSColin Finck lpwzFileName = heap_strdupAtoW(lpszFileName);
1451c2c66affSColin Finck ret = FtpOpenFileW(hFtpSession, lpwzFileName, fdwAccess, dwFlags, dwContext);
1452c2c66affSColin Finck heap_free(lpwzFileName);
1453c2c66affSColin Finck return ret;
1454c2c66affSColin Finck }
1455c2c66affSColin Finck
1456c2c66affSColin Finck typedef struct {
1457c2c66affSColin Finck task_header_t hdr;
1458c2c66affSColin Finck WCHAR *file_name;
1459c2c66affSColin Finck DWORD access;
1460c2c66affSColin Finck DWORD flags;
1461c2c66affSColin Finck DWORD_PTR context;
1462c2c66affSColin Finck } open_file_task_t;
1463c2c66affSColin Finck
AsyncFtpOpenFileProc(task_header_t * hdr)1464c2c66affSColin Finck static void AsyncFtpOpenFileProc(task_header_t *hdr)
1465c2c66affSColin Finck {
1466c2c66affSColin Finck open_file_task_t *task = (open_file_task_t*)hdr;
1467c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
1468c2c66affSColin Finck
1469c2c66affSColin Finck TRACE("%p\n", session);
1470c2c66affSColin Finck
1471c2c66affSColin Finck FTP_FtpOpenFileW(session, task->file_name, task->access, task->flags, task->context);
1472c2c66affSColin Finck heap_free(task->file_name);
1473c2c66affSColin Finck }
1474c2c66affSColin Finck
1475c2c66affSColin Finck /***********************************************************************
1476c2c66affSColin Finck * FtpOpenFileW (WININET.@)
1477c2c66affSColin Finck *
1478c2c66affSColin Finck * Open a remote file for writing or reading
1479c2c66affSColin Finck *
1480c2c66affSColin Finck * RETURNS
1481c2c66affSColin Finck * HINTERNET handle on success
1482c2c66affSColin Finck * NULL on failure
1483c2c66affSColin Finck *
1484c2c66affSColin Finck */
FtpOpenFileW(HINTERNET hFtpSession,LPCWSTR lpszFileName,DWORD fdwAccess,DWORD dwFlags,DWORD_PTR dwContext)1485c2c66affSColin Finck HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession,
1486c2c66affSColin Finck LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
1487c2c66affSColin Finck DWORD_PTR dwContext)
1488c2c66affSColin Finck {
1489c2c66affSColin Finck ftp_session_t *lpwfs;
1490c2c66affSColin Finck appinfo_t *hIC = NULL;
1491c2c66affSColin Finck HINTERNET r = NULL;
1492c2c66affSColin Finck
1493c2c66affSColin Finck TRACE("(%p,%s,0x%08x,0x%08x,0x%08lx)\n", hFtpSession,
1494c2c66affSColin Finck debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext);
1495c2c66affSColin Finck
1496c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hFtpSession );
1497c2c66affSColin Finck if (!lpwfs)
1498c2c66affSColin Finck {
1499c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
1500c2c66affSColin Finck return FALSE;
1501c2c66affSColin Finck }
1502c2c66affSColin Finck
1503c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
1504c2c66affSColin Finck {
1505c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1506c2c66affSColin Finck goto lend;
1507c2c66affSColin Finck }
1508c2c66affSColin Finck
1509c2c66affSColin Finck if ((!lpszFileName) ||
1510c2c66affSColin Finck ((fdwAccess != GENERIC_READ) && (fdwAccess != GENERIC_WRITE)) ||
1511c2c66affSColin Finck ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY))
1512c2c66affSColin Finck {
1513c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1514c2c66affSColin Finck goto lend;
1515c2c66affSColin Finck }
1516c2c66affSColin Finck
1517c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
1518c2c66affSColin Finck {
1519c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1520c2c66affSColin Finck goto lend;
1521c2c66affSColin Finck }
1522c2c66affSColin Finck
1523c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1524c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1525c2c66affSColin Finck {
1526c2c66affSColin Finck open_file_task_t *task;
1527c2c66affSColin Finck
1528c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpOpenFileProc, sizeof(*task));
1529c2c66affSColin Finck task->file_name = heap_strdupW(lpszFileName);
1530c2c66affSColin Finck task->access = fdwAccess;
1531c2c66affSColin Finck task->flags = dwFlags;
1532c2c66affSColin Finck task->context = dwContext;
1533c2c66affSColin Finck
1534c2c66affSColin Finck INTERNET_AsyncCall(&task->hdr);
1535c2c66affSColin Finck r = NULL;
1536c2c66affSColin Finck }
1537c2c66affSColin Finck else
1538c2c66affSColin Finck {
1539c2c66affSColin Finck r = FTP_FtpOpenFileW(lpwfs, lpszFileName, fdwAccess, dwFlags, dwContext);
1540c2c66affSColin Finck }
1541c2c66affSColin Finck
1542c2c66affSColin Finck lend:
1543c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
1544c2c66affSColin Finck
1545c2c66affSColin Finck return r;
1546c2c66affSColin Finck }
1547c2c66affSColin Finck
1548c2c66affSColin Finck
1549c2c66affSColin Finck /***********************************************************************
1550c2c66affSColin Finck * FtpGetFileA (WININET.@)
1551c2c66affSColin Finck *
1552c2c66affSColin Finck * Retrieve file from the FTP server
1553c2c66affSColin Finck *
1554c2c66affSColin Finck * RETURNS
1555c2c66affSColin Finck * TRUE on success
1556c2c66affSColin Finck * FALSE on failure
1557c2c66affSColin Finck *
1558c2c66affSColin Finck */
FtpGetFileA(HINTERNET hInternet,LPCSTR lpszRemoteFile,LPCSTR lpszNewFile,BOOL fFailIfExists,DWORD dwLocalFlagsAttribute,DWORD dwInternetFlags,DWORD_PTR dwContext)1559c2c66affSColin Finck BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile,
1560c2c66affSColin Finck BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
1561c2c66affSColin Finck DWORD_PTR dwContext)
1562c2c66affSColin Finck {
1563c2c66affSColin Finck LPWSTR lpwzRemoteFile;
1564c2c66affSColin Finck LPWSTR lpwzNewFile;
1565c2c66affSColin Finck BOOL ret;
1566c2c66affSColin Finck
1567c2c66affSColin Finck lpwzRemoteFile = heap_strdupAtoW(lpszRemoteFile);
1568c2c66affSColin Finck lpwzNewFile = heap_strdupAtoW(lpszNewFile);
1569c2c66affSColin Finck ret = FtpGetFileW(hInternet, lpwzRemoteFile, lpwzNewFile, fFailIfExists,
1570c2c66affSColin Finck dwLocalFlagsAttribute, dwInternetFlags, dwContext);
1571c2c66affSColin Finck heap_free(lpwzRemoteFile);
1572c2c66affSColin Finck heap_free(lpwzNewFile);
1573c2c66affSColin Finck return ret;
1574c2c66affSColin Finck }
1575c2c66affSColin Finck
1576c2c66affSColin Finck typedef struct {
1577c2c66affSColin Finck task_header_t hdr;
1578c2c66affSColin Finck WCHAR *remote_file;
1579c2c66affSColin Finck WCHAR *new_file;
1580c2c66affSColin Finck BOOL fail_if_exists;
1581c2c66affSColin Finck DWORD local_attr;
1582c2c66affSColin Finck DWORD flags;
1583c2c66affSColin Finck DWORD_PTR context;
1584c2c66affSColin Finck } get_file_task_t;
1585c2c66affSColin Finck
AsyncFtpGetFileProc(task_header_t * hdr)1586c2c66affSColin Finck static void AsyncFtpGetFileProc(task_header_t *hdr)
1587c2c66affSColin Finck {
1588c2c66affSColin Finck get_file_task_t *task = (get_file_task_t*)hdr;
1589c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
1590c2c66affSColin Finck
1591c2c66affSColin Finck TRACE("%p\n", session);
1592c2c66affSColin Finck
1593c2c66affSColin Finck FTP_FtpGetFileW(session, task->remote_file, task->new_file, task->fail_if_exists,
1594c2c66affSColin Finck task->local_attr, task->flags, task->context);
1595c2c66affSColin Finck heap_free(task->remote_file);
1596c2c66affSColin Finck heap_free(task->new_file);
1597c2c66affSColin Finck }
1598c2c66affSColin Finck
1599c2c66affSColin Finck
1600c2c66affSColin Finck /***********************************************************************
1601c2c66affSColin Finck * FtpGetFileW (WININET.@)
1602c2c66affSColin Finck *
1603c2c66affSColin Finck * Retrieve file from the FTP server
1604c2c66affSColin Finck *
1605c2c66affSColin Finck * RETURNS
1606c2c66affSColin Finck * TRUE on success
1607c2c66affSColin Finck * FALSE on failure
1608c2c66affSColin Finck *
1609c2c66affSColin Finck */
FtpGetFileW(HINTERNET hInternet,LPCWSTR lpszRemoteFile,LPCWSTR lpszNewFile,BOOL fFailIfExists,DWORD dwLocalFlagsAttribute,DWORD dwInternetFlags,DWORD_PTR dwContext)1610c2c66affSColin Finck BOOL WINAPI FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
1611c2c66affSColin Finck BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
1612c2c66affSColin Finck DWORD_PTR dwContext)
1613c2c66affSColin Finck {
1614c2c66affSColin Finck ftp_session_t *lpwfs;
1615c2c66affSColin Finck appinfo_t *hIC = NULL;
1616c2c66affSColin Finck BOOL r = FALSE;
1617c2c66affSColin Finck
1618c2c66affSColin Finck if (!lpszRemoteFile || !lpszNewFile)
1619c2c66affSColin Finck {
1620c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1621c2c66affSColin Finck return FALSE;
1622c2c66affSColin Finck }
1623c2c66affSColin Finck
1624c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hInternet );
1625c2c66affSColin Finck if (!lpwfs)
1626c2c66affSColin Finck {
1627c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
1628c2c66affSColin Finck return FALSE;
1629c2c66affSColin Finck }
1630c2c66affSColin Finck
1631c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
1632c2c66affSColin Finck {
1633c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1634c2c66affSColin Finck goto lend;
1635c2c66affSColin Finck }
1636c2c66affSColin Finck
1637c2c66affSColin Finck if ((dwInternetFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY)
1638c2c66affSColin Finck {
1639c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1640c2c66affSColin Finck goto lend;
1641c2c66affSColin Finck }
1642c2c66affSColin Finck
1643c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
1644c2c66affSColin Finck {
1645c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1646c2c66affSColin Finck goto lend;
1647c2c66affSColin Finck }
1648c2c66affSColin Finck
1649c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1650c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1651c2c66affSColin Finck {
1652c2c66affSColin Finck get_file_task_t *task;
1653c2c66affSColin Finck
1654c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpGetFileProc, sizeof(*task));
1655c2c66affSColin Finck task->remote_file = heap_strdupW(lpszRemoteFile);
1656c2c66affSColin Finck task->new_file = heap_strdupW(lpszNewFile);
1657c2c66affSColin Finck task->local_attr = dwLocalFlagsAttribute;
1658c2c66affSColin Finck task->fail_if_exists = fFailIfExists;
1659c2c66affSColin Finck task->flags = dwInternetFlags;
1660c2c66affSColin Finck task->context = dwContext;
1661c2c66affSColin Finck
1662c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
1663c2c66affSColin Finck }
1664c2c66affSColin Finck else
1665c2c66affSColin Finck {
1666c2c66affSColin Finck r = FTP_FtpGetFileW(lpwfs, lpszRemoteFile, lpszNewFile,
1667c2c66affSColin Finck fFailIfExists, dwLocalFlagsAttribute, dwInternetFlags, dwContext);
1668c2c66affSColin Finck }
1669c2c66affSColin Finck
1670c2c66affSColin Finck lend:
1671c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
1672c2c66affSColin Finck
1673c2c66affSColin Finck return r;
1674c2c66affSColin Finck }
1675c2c66affSColin Finck
1676c2c66affSColin Finck
1677c2c66affSColin Finck /***********************************************************************
1678c2c66affSColin Finck * FTP_FtpGetFileW (Internal)
1679c2c66affSColin Finck *
1680c2c66affSColin Finck * Retrieve file from the FTP server
1681c2c66affSColin Finck *
1682c2c66affSColin Finck * RETURNS
1683c2c66affSColin Finck * TRUE on success
1684c2c66affSColin Finck * FALSE on failure
1685c2c66affSColin Finck *
1686c2c66affSColin Finck */
FTP_FtpGetFileW(ftp_session_t * lpwfs,LPCWSTR lpszRemoteFile,LPCWSTR lpszNewFile,BOOL fFailIfExists,DWORD dwLocalFlagsAttribute,DWORD dwInternetFlags,DWORD_PTR dwContext)1687c2c66affSColin Finck static BOOL FTP_FtpGetFileW(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
1688c2c66affSColin Finck BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
1689c2c66affSColin Finck DWORD_PTR dwContext)
1690c2c66affSColin Finck {
1691c2c66affSColin Finck BOOL bSuccess = FALSE;
1692c2c66affSColin Finck HANDLE hFile;
1693c2c66affSColin Finck appinfo_t *hIC = NULL;
1694c2c66affSColin Finck
1695c2c66affSColin Finck TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", debugstr_w(lpszRemoteFile), debugstr_w(lpszNewFile));
1696c2c66affSColin Finck
1697c2c66affSColin Finck /* Clear any error information */
1698c2c66affSColin Finck INTERNET_SetLastError(0);
1699c2c66affSColin Finck
1700c2c66affSColin Finck /* Ensure we can write to lpszNewfile by opening it */
1701c2c66affSColin Finck hFile = CreateFileW(lpszNewFile, GENERIC_WRITE, 0, 0, fFailIfExists ?
1702c2c66affSColin Finck CREATE_NEW : CREATE_ALWAYS, dwLocalFlagsAttribute, 0);
1703c2c66affSColin Finck if (INVALID_HANDLE_VALUE == hFile)
1704c2c66affSColin Finck return FALSE;
1705c2c66affSColin Finck
1706c2c66affSColin Finck /* Set up socket to retrieve data */
1707c2c66affSColin Finck if (FTP_SendRetrieve(lpwfs, lpszRemoteFile, dwInternetFlags))
1708c2c66affSColin Finck {
1709c2c66affSColin Finck INT nDataSocket;
1710c2c66affSColin Finck
1711c2c66affSColin Finck /* Get data socket to server */
1712c2c66affSColin Finck if (FTP_GetDataSocket(lpwfs, &nDataSocket))
1713c2c66affSColin Finck {
1714c2c66affSColin Finck INT nResCode;
1715c2c66affSColin Finck
1716c2c66affSColin Finck /* Receive data */
1717c2c66affSColin Finck FTP_RetrieveFileData(lpwfs, nDataSocket, hFile);
1718c2c66affSColin Finck closesocket(nDataSocket);
1719c2c66affSColin Finck
1720c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, dwContext);
1721c2c66affSColin Finck if (nResCode)
1722c2c66affSColin Finck {
1723c2c66affSColin Finck if (nResCode == 226)
1724c2c66affSColin Finck bSuccess = TRUE;
1725c2c66affSColin Finck else
1726c2c66affSColin Finck FTP_SetResponseError(nResCode);
1727c2c66affSColin Finck }
1728c2c66affSColin Finck }
1729c2c66affSColin Finck }
1730c2c66affSColin Finck
1731c2c66affSColin Finck if (lpwfs->lstnSocket != -1)
1732c2c66affSColin Finck {
1733c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
1734c2c66affSColin Finck lpwfs->lstnSocket = -1;
1735c2c66affSColin Finck }
1736c2c66affSColin Finck
1737c2c66affSColin Finck CloseHandle(hFile);
1738c2c66affSColin Finck
1739c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1740c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1741c2c66affSColin Finck {
1742c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
1743c2c66affSColin Finck
1744c2c66affSColin Finck iar.dwResult = (DWORD)bSuccess;
1745c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1746c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1747c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
1748c2c66affSColin Finck }
1749c2c66affSColin Finck
1750c2c66affSColin Finck if (!bSuccess) DeleteFileW(lpszNewFile);
1751c2c66affSColin Finck return bSuccess;
1752c2c66affSColin Finck }
1753c2c66affSColin Finck
1754c2c66affSColin Finck /***********************************************************************
1755c2c66affSColin Finck * FtpGetFileSize (WININET.@)
1756c2c66affSColin Finck */
FtpGetFileSize(HINTERNET hFile,LPDWORD lpdwFileSizeHigh)1757c2c66affSColin Finck DWORD WINAPI FtpGetFileSize( HINTERNET hFile, LPDWORD lpdwFileSizeHigh )
1758c2c66affSColin Finck {
1759c2c66affSColin Finck FIXME("(%p, %p)\n", hFile, lpdwFileSizeHigh);
1760c2c66affSColin Finck
1761c2c66affSColin Finck if (lpdwFileSizeHigh)
1762c2c66affSColin Finck *lpdwFileSizeHigh = 0;
1763c2c66affSColin Finck
1764c2c66affSColin Finck return 0;
1765c2c66affSColin Finck }
1766c2c66affSColin Finck
1767c2c66affSColin Finck /***********************************************************************
1768c2c66affSColin Finck * FtpDeleteFileA (WININET.@)
1769c2c66affSColin Finck *
1770c2c66affSColin Finck * Delete a file on the ftp server
1771c2c66affSColin Finck *
1772c2c66affSColin Finck * RETURNS
1773c2c66affSColin Finck * TRUE on success
1774c2c66affSColin Finck * FALSE on failure
1775c2c66affSColin Finck *
1776c2c66affSColin Finck */
FtpDeleteFileA(HINTERNET hFtpSession,LPCSTR lpszFileName)1777c2c66affSColin Finck BOOL WINAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
1778c2c66affSColin Finck {
1779c2c66affSColin Finck LPWSTR lpwzFileName;
1780c2c66affSColin Finck BOOL ret;
1781c2c66affSColin Finck
1782c2c66affSColin Finck lpwzFileName = heap_strdupAtoW(lpszFileName);
1783c2c66affSColin Finck ret = FtpDeleteFileW(hFtpSession, lpwzFileName);
1784c2c66affSColin Finck heap_free(lpwzFileName);
1785c2c66affSColin Finck return ret;
1786c2c66affSColin Finck }
1787c2c66affSColin Finck
1788c2c66affSColin Finck typedef struct {
1789c2c66affSColin Finck task_header_t hdr;
1790c2c66affSColin Finck WCHAR *file_name;
1791c2c66affSColin Finck } delete_file_task_t;
1792c2c66affSColin Finck
AsyncFtpDeleteFileProc(task_header_t * hdr)1793c2c66affSColin Finck static void AsyncFtpDeleteFileProc(task_header_t *hdr)
1794c2c66affSColin Finck {
1795c2c66affSColin Finck delete_file_task_t *task = (delete_file_task_t*)hdr;
1796c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
1797c2c66affSColin Finck
1798c2c66affSColin Finck TRACE("%p\n", session);
1799c2c66affSColin Finck
1800c2c66affSColin Finck FTP_FtpDeleteFileW(session, task->file_name);
1801c2c66affSColin Finck heap_free(task->file_name);
1802c2c66affSColin Finck }
1803c2c66affSColin Finck
1804c2c66affSColin Finck /***********************************************************************
1805c2c66affSColin Finck * FtpDeleteFileW (WININET.@)
1806c2c66affSColin Finck *
1807c2c66affSColin Finck * Delete a file on the ftp server
1808c2c66affSColin Finck *
1809c2c66affSColin Finck * RETURNS
1810c2c66affSColin Finck * TRUE on success
1811c2c66affSColin Finck * FALSE on failure
1812c2c66affSColin Finck *
1813c2c66affSColin Finck */
FtpDeleteFileW(HINTERNET hFtpSession,LPCWSTR lpszFileName)1814c2c66affSColin Finck BOOL WINAPI FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName)
1815c2c66affSColin Finck {
1816c2c66affSColin Finck ftp_session_t *lpwfs;
1817c2c66affSColin Finck appinfo_t *hIC = NULL;
1818c2c66affSColin Finck BOOL r = FALSE;
1819c2c66affSColin Finck
1820c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hFtpSession );
1821c2c66affSColin Finck if (!lpwfs)
1822c2c66affSColin Finck {
1823c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
1824c2c66affSColin Finck return FALSE;
1825c2c66affSColin Finck }
1826c2c66affSColin Finck
1827c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
1828c2c66affSColin Finck {
1829c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1830c2c66affSColin Finck goto lend;
1831c2c66affSColin Finck }
1832c2c66affSColin Finck
1833c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
1834c2c66affSColin Finck {
1835c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1836c2c66affSColin Finck goto lend;
1837c2c66affSColin Finck }
1838c2c66affSColin Finck
1839c2c66affSColin Finck if (!lpszFileName)
1840c2c66affSColin Finck {
1841c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1842c2c66affSColin Finck goto lend;
1843c2c66affSColin Finck }
1844c2c66affSColin Finck
1845c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1846c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1847c2c66affSColin Finck {
1848c2c66affSColin Finck delete_file_task_t *task;
1849c2c66affSColin Finck
1850c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpDeleteFileProc, sizeof(*task));
1851c2c66affSColin Finck task->file_name = heap_strdupW(lpszFileName);
1852c2c66affSColin Finck
1853c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
1854c2c66affSColin Finck }
1855c2c66affSColin Finck else
1856c2c66affSColin Finck {
1857c2c66affSColin Finck r = FTP_FtpDeleteFileW(lpwfs, lpszFileName);
1858c2c66affSColin Finck }
1859c2c66affSColin Finck
1860c2c66affSColin Finck lend:
1861c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
1862c2c66affSColin Finck
1863c2c66affSColin Finck return r;
1864c2c66affSColin Finck }
1865c2c66affSColin Finck
1866c2c66affSColin Finck /***********************************************************************
1867c2c66affSColin Finck * FTP_FtpDeleteFileW (Internal)
1868c2c66affSColin Finck *
1869c2c66affSColin Finck * Delete a file on the ftp server
1870c2c66affSColin Finck *
1871c2c66affSColin Finck * RETURNS
1872c2c66affSColin Finck * TRUE on success
1873c2c66affSColin Finck * FALSE on failure
1874c2c66affSColin Finck *
1875c2c66affSColin Finck */
FTP_FtpDeleteFileW(ftp_session_t * lpwfs,LPCWSTR lpszFileName)1876c2c66affSColin Finck BOOL FTP_FtpDeleteFileW(ftp_session_t *lpwfs, LPCWSTR lpszFileName)
1877c2c66affSColin Finck {
1878c2c66affSColin Finck INT nResCode;
1879c2c66affSColin Finck BOOL bSuccess = FALSE;
1880c2c66affSColin Finck appinfo_t *hIC = NULL;
1881c2c66affSColin Finck
1882c2c66affSColin Finck TRACE("%p\n", lpwfs);
1883c2c66affSColin Finck
1884c2c66affSColin Finck /* Clear any error information */
1885c2c66affSColin Finck INTERNET_SetLastError(0);
1886c2c66affSColin Finck
1887c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_DELE, lpszFileName, 0, 0, 0))
1888c2c66affSColin Finck goto lend;
1889c2c66affSColin Finck
1890c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
1891c2c66affSColin Finck if (nResCode)
1892c2c66affSColin Finck {
1893c2c66affSColin Finck if (nResCode == 250)
1894c2c66affSColin Finck bSuccess = TRUE;
1895c2c66affSColin Finck else
1896c2c66affSColin Finck FTP_SetResponseError(nResCode);
1897c2c66affSColin Finck }
1898c2c66affSColin Finck lend:
1899c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1900c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1901c2c66affSColin Finck {
1902c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
1903c2c66affSColin Finck
1904c2c66affSColin Finck iar.dwResult = (DWORD)bSuccess;
1905c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1906c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1907c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
1908c2c66affSColin Finck }
1909c2c66affSColin Finck
1910c2c66affSColin Finck return bSuccess;
1911c2c66affSColin Finck }
1912c2c66affSColin Finck
1913c2c66affSColin Finck
1914c2c66affSColin Finck /***********************************************************************
1915c2c66affSColin Finck * FtpRemoveDirectoryA (WININET.@)
1916c2c66affSColin Finck *
1917c2c66affSColin Finck * Remove a directory on the ftp server
1918c2c66affSColin Finck *
1919c2c66affSColin Finck * RETURNS
1920c2c66affSColin Finck * TRUE on success
1921c2c66affSColin Finck * FALSE on failure
1922c2c66affSColin Finck *
1923c2c66affSColin Finck */
FtpRemoveDirectoryA(HINTERNET hFtpSession,LPCSTR lpszDirectory)1924c2c66affSColin Finck BOOL WINAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
1925c2c66affSColin Finck {
1926c2c66affSColin Finck LPWSTR lpwzDirectory;
1927c2c66affSColin Finck BOOL ret;
1928c2c66affSColin Finck
1929c2c66affSColin Finck lpwzDirectory = heap_strdupAtoW(lpszDirectory);
1930c2c66affSColin Finck ret = FtpRemoveDirectoryW(hFtpSession, lpwzDirectory);
1931c2c66affSColin Finck heap_free(lpwzDirectory);
1932c2c66affSColin Finck return ret;
1933c2c66affSColin Finck }
1934c2c66affSColin Finck
AsyncFtpRemoveDirectoryProc(task_header_t * hdr)1935c2c66affSColin Finck static void AsyncFtpRemoveDirectoryProc(task_header_t *hdr)
1936c2c66affSColin Finck {
1937c2c66affSColin Finck directory_task_t *task = (directory_task_t*)hdr;
1938c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
1939c2c66affSColin Finck
1940c2c66affSColin Finck TRACE("%p\n", session);
1941c2c66affSColin Finck
1942c2c66affSColin Finck FTP_FtpRemoveDirectoryW(session, task->directory);
1943c2c66affSColin Finck heap_free(task->directory);
1944c2c66affSColin Finck }
1945c2c66affSColin Finck
1946c2c66affSColin Finck /***********************************************************************
1947c2c66affSColin Finck * FtpRemoveDirectoryW (WININET.@)
1948c2c66affSColin Finck *
1949c2c66affSColin Finck * Remove a directory on the ftp server
1950c2c66affSColin Finck *
1951c2c66affSColin Finck * RETURNS
1952c2c66affSColin Finck * TRUE on success
1953c2c66affSColin Finck * FALSE on failure
1954c2c66affSColin Finck *
1955c2c66affSColin Finck */
FtpRemoveDirectoryW(HINTERNET hFtpSession,LPCWSTR lpszDirectory)1956c2c66affSColin Finck BOOL WINAPI FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory)
1957c2c66affSColin Finck {
1958c2c66affSColin Finck ftp_session_t *lpwfs;
1959c2c66affSColin Finck appinfo_t *hIC = NULL;
1960c2c66affSColin Finck BOOL r = FALSE;
1961c2c66affSColin Finck
1962c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hFtpSession );
1963c2c66affSColin Finck if (!lpwfs)
1964c2c66affSColin Finck {
1965c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
1966c2c66affSColin Finck return FALSE;
1967c2c66affSColin Finck }
1968c2c66affSColin Finck
1969c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
1970c2c66affSColin Finck {
1971c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1972c2c66affSColin Finck goto lend;
1973c2c66affSColin Finck }
1974c2c66affSColin Finck
1975c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
1976c2c66affSColin Finck {
1977c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1978c2c66affSColin Finck goto lend;
1979c2c66affSColin Finck }
1980c2c66affSColin Finck
1981c2c66affSColin Finck if (!lpszDirectory)
1982c2c66affSColin Finck {
1983c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1984c2c66affSColin Finck goto lend;
1985c2c66affSColin Finck }
1986c2c66affSColin Finck
1987c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
1988c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1989c2c66affSColin Finck {
1990c2c66affSColin Finck directory_task_t *task;
1991c2c66affSColin Finck
1992c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpRemoveDirectoryProc, sizeof(*task));
1993c2c66affSColin Finck task->directory = heap_strdupW(lpszDirectory);
1994c2c66affSColin Finck
1995c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
1996c2c66affSColin Finck }
1997c2c66affSColin Finck else
1998c2c66affSColin Finck {
1999c2c66affSColin Finck r = FTP_FtpRemoveDirectoryW(lpwfs, lpszDirectory);
2000c2c66affSColin Finck }
2001c2c66affSColin Finck
2002c2c66affSColin Finck lend:
2003c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
2004c2c66affSColin Finck
2005c2c66affSColin Finck return r;
2006c2c66affSColin Finck }
2007c2c66affSColin Finck
2008c2c66affSColin Finck /***********************************************************************
2009c2c66affSColin Finck * FTP_FtpRemoveDirectoryW (Internal)
2010c2c66affSColin Finck *
2011c2c66affSColin Finck * Remove a directory on the ftp server
2012c2c66affSColin Finck *
2013c2c66affSColin Finck * RETURNS
2014c2c66affSColin Finck * TRUE on success
2015c2c66affSColin Finck * FALSE on failure
2016c2c66affSColin Finck *
2017c2c66affSColin Finck */
FTP_FtpRemoveDirectoryW(ftp_session_t * lpwfs,LPCWSTR lpszDirectory)2018c2c66affSColin Finck BOOL FTP_FtpRemoveDirectoryW(ftp_session_t *lpwfs, LPCWSTR lpszDirectory)
2019c2c66affSColin Finck {
2020c2c66affSColin Finck INT nResCode;
2021c2c66affSColin Finck BOOL bSuccess = FALSE;
2022c2c66affSColin Finck appinfo_t *hIC = NULL;
2023c2c66affSColin Finck
2024c2c66affSColin Finck TRACE("\n");
2025c2c66affSColin Finck
2026c2c66affSColin Finck /* Clear any error information */
2027c2c66affSColin Finck INTERNET_SetLastError(0);
2028c2c66affSColin Finck
2029c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RMD, lpszDirectory, 0, 0, 0))
2030c2c66affSColin Finck goto lend;
2031c2c66affSColin Finck
2032c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2033c2c66affSColin Finck if (nResCode)
2034c2c66affSColin Finck {
2035c2c66affSColin Finck if (nResCode == 250)
2036c2c66affSColin Finck bSuccess = TRUE;
2037c2c66affSColin Finck else
2038c2c66affSColin Finck FTP_SetResponseError(nResCode);
2039c2c66affSColin Finck }
2040c2c66affSColin Finck
2041c2c66affSColin Finck lend:
2042c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
2043c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
2044c2c66affSColin Finck {
2045c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
2046c2c66affSColin Finck
2047c2c66affSColin Finck iar.dwResult = (DWORD)bSuccess;
2048c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
2049c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
2050c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
2051c2c66affSColin Finck }
2052c2c66affSColin Finck
2053c2c66affSColin Finck return bSuccess;
2054c2c66affSColin Finck }
2055c2c66affSColin Finck
2056c2c66affSColin Finck
2057c2c66affSColin Finck /***********************************************************************
2058c2c66affSColin Finck * FtpRenameFileA (WININET.@)
2059c2c66affSColin Finck *
2060c2c66affSColin Finck * Rename a file on the ftp server
2061c2c66affSColin Finck *
2062c2c66affSColin Finck * RETURNS
2063c2c66affSColin Finck * TRUE on success
2064c2c66affSColin Finck * FALSE on failure
2065c2c66affSColin Finck *
2066c2c66affSColin Finck */
FtpRenameFileA(HINTERNET hFtpSession,LPCSTR lpszSrc,LPCSTR lpszDest)2067c2c66affSColin Finck BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDest)
2068c2c66affSColin Finck {
2069c2c66affSColin Finck LPWSTR lpwzSrc;
2070c2c66affSColin Finck LPWSTR lpwzDest;
2071c2c66affSColin Finck BOOL ret;
2072c2c66affSColin Finck
2073c2c66affSColin Finck lpwzSrc = heap_strdupAtoW(lpszSrc);
2074c2c66affSColin Finck lpwzDest = heap_strdupAtoW(lpszDest);
2075c2c66affSColin Finck ret = FtpRenameFileW(hFtpSession, lpwzSrc, lpwzDest);
2076c2c66affSColin Finck heap_free(lpwzSrc);
2077c2c66affSColin Finck heap_free(lpwzDest);
2078c2c66affSColin Finck return ret;
2079c2c66affSColin Finck }
2080c2c66affSColin Finck
2081c2c66affSColin Finck typedef struct {
2082c2c66affSColin Finck task_header_t hdr;
2083c2c66affSColin Finck WCHAR *src_file;
2084c2c66affSColin Finck WCHAR *dst_file;
2085c2c66affSColin Finck } rename_file_task_t;
2086c2c66affSColin Finck
AsyncFtpRenameFileProc(task_header_t * hdr)2087c2c66affSColin Finck static void AsyncFtpRenameFileProc(task_header_t *hdr)
2088c2c66affSColin Finck {
2089c2c66affSColin Finck rename_file_task_t *task = (rename_file_task_t*)hdr;
2090c2c66affSColin Finck ftp_session_t *session = (ftp_session_t*)task->hdr.hdr;
2091c2c66affSColin Finck
2092c2c66affSColin Finck TRACE("%p\n", session);
2093c2c66affSColin Finck
2094c2c66affSColin Finck FTP_FtpRenameFileW(session, task->src_file, task->dst_file);
2095c2c66affSColin Finck heap_free(task->src_file);
2096c2c66affSColin Finck heap_free(task->dst_file);
2097c2c66affSColin Finck }
2098c2c66affSColin Finck
2099c2c66affSColin Finck /***********************************************************************
2100c2c66affSColin Finck * FtpRenameFileW (WININET.@)
2101c2c66affSColin Finck *
2102c2c66affSColin Finck * Rename a file on the ftp server
2103c2c66affSColin Finck *
2104c2c66affSColin Finck * RETURNS
2105c2c66affSColin Finck * TRUE on success
2106c2c66affSColin Finck * FALSE on failure
2107c2c66affSColin Finck *
2108c2c66affSColin Finck */
FtpRenameFileW(HINTERNET hFtpSession,LPCWSTR lpszSrc,LPCWSTR lpszDest)2109c2c66affSColin Finck BOOL WINAPI FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszDest)
2110c2c66affSColin Finck {
2111c2c66affSColin Finck ftp_session_t *lpwfs;
2112c2c66affSColin Finck appinfo_t *hIC = NULL;
2113c2c66affSColin Finck BOOL r = FALSE;
2114c2c66affSColin Finck
2115c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hFtpSession );
2116c2c66affSColin Finck if (!lpwfs)
2117c2c66affSColin Finck {
2118c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
2119c2c66affSColin Finck return FALSE;
2120c2c66affSColin Finck }
2121c2c66affSColin Finck
2122c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
2123c2c66affSColin Finck {
2124c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
2125c2c66affSColin Finck goto lend;
2126c2c66affSColin Finck }
2127c2c66affSColin Finck
2128c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
2129c2c66affSColin Finck {
2130c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2131c2c66affSColin Finck goto lend;
2132c2c66affSColin Finck }
2133c2c66affSColin Finck
2134c2c66affSColin Finck if (!lpszSrc || !lpszDest)
2135c2c66affSColin Finck {
2136c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2137c2c66affSColin Finck goto lend;
2138c2c66affSColin Finck }
2139c2c66affSColin Finck
2140c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
2141c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
2142c2c66affSColin Finck {
2143c2c66affSColin Finck rename_file_task_t *task;
2144c2c66affSColin Finck
2145c2c66affSColin Finck task = alloc_async_task(&lpwfs->hdr, AsyncFtpRenameFileProc, sizeof(*task));
2146c2c66affSColin Finck task->src_file = heap_strdupW(lpszSrc);
2147c2c66affSColin Finck task->dst_file = heap_strdupW(lpszDest);
2148c2c66affSColin Finck
2149c2c66affSColin Finck r = res_to_le(INTERNET_AsyncCall(&task->hdr));
2150c2c66affSColin Finck }
2151c2c66affSColin Finck else
2152c2c66affSColin Finck {
2153c2c66affSColin Finck r = FTP_FtpRenameFileW(lpwfs, lpszSrc, lpszDest);
2154c2c66affSColin Finck }
2155c2c66affSColin Finck
2156c2c66affSColin Finck lend:
2157c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
2158c2c66affSColin Finck
2159c2c66affSColin Finck return r;
2160c2c66affSColin Finck }
2161c2c66affSColin Finck
2162c2c66affSColin Finck /***********************************************************************
2163c2c66affSColin Finck * FTP_FtpRenameFileW (Internal)
2164c2c66affSColin Finck *
2165c2c66affSColin Finck * Rename a file on the ftp server
2166c2c66affSColin Finck *
2167c2c66affSColin Finck * RETURNS
2168c2c66affSColin Finck * TRUE on success
2169c2c66affSColin Finck * FALSE on failure
2170c2c66affSColin Finck *
2171c2c66affSColin Finck */
FTP_FtpRenameFileW(ftp_session_t * lpwfs,LPCWSTR lpszSrc,LPCWSTR lpszDest)2172c2c66affSColin Finck BOOL FTP_FtpRenameFileW(ftp_session_t *lpwfs, LPCWSTR lpszSrc, LPCWSTR lpszDest)
2173c2c66affSColin Finck {
2174c2c66affSColin Finck INT nResCode;
2175c2c66affSColin Finck BOOL bSuccess = FALSE;
2176c2c66affSColin Finck appinfo_t *hIC = NULL;
2177c2c66affSColin Finck
2178c2c66affSColin Finck TRACE("\n");
2179c2c66affSColin Finck
2180c2c66affSColin Finck /* Clear any error information */
2181c2c66affSColin Finck INTERNET_SetLastError(0);
2182c2c66affSColin Finck
2183c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNFR, lpszSrc, 0, 0, 0))
2184c2c66affSColin Finck goto lend;
2185c2c66affSColin Finck
2186c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2187c2c66affSColin Finck if (nResCode == 350)
2188c2c66affSColin Finck {
2189c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNTO, lpszDest, 0, 0, 0))
2190c2c66affSColin Finck goto lend;
2191c2c66affSColin Finck
2192c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2193c2c66affSColin Finck }
2194c2c66affSColin Finck
2195c2c66affSColin Finck if (nResCode == 250)
2196c2c66affSColin Finck bSuccess = TRUE;
2197c2c66affSColin Finck else
2198c2c66affSColin Finck FTP_SetResponseError(nResCode);
2199c2c66affSColin Finck
2200c2c66affSColin Finck lend:
2201c2c66affSColin Finck hIC = lpwfs->lpAppInfo;
2202c2c66affSColin Finck if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
2203c2c66affSColin Finck {
2204c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
2205c2c66affSColin Finck
2206c2c66affSColin Finck iar.dwResult = (DWORD)bSuccess;
2207c2c66affSColin Finck iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
2208c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
2209c2c66affSColin Finck &iar, sizeof(INTERNET_ASYNC_RESULT));
2210c2c66affSColin Finck }
2211c2c66affSColin Finck
2212c2c66affSColin Finck return bSuccess;
2213c2c66affSColin Finck }
2214c2c66affSColin Finck
2215c2c66affSColin Finck /***********************************************************************
2216c2c66affSColin Finck * FtpCommandA (WININET.@)
2217c2c66affSColin Finck */
FtpCommandA(HINTERNET hConnect,BOOL fExpectResponse,DWORD dwFlags,LPCSTR lpszCommand,DWORD_PTR dwContext,HINTERNET * phFtpCommand)2218c2c66affSColin Finck BOOL WINAPI FtpCommandA( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags,
2219c2c66affSColin Finck LPCSTR lpszCommand, DWORD_PTR dwContext, HINTERNET* phFtpCommand )
2220c2c66affSColin Finck {
2221c2c66affSColin Finck BOOL r;
2222c2c66affSColin Finck WCHAR *cmdW;
2223c2c66affSColin Finck
2224c2c66affSColin Finck TRACE("%p %d 0x%08x %s 0x%08lx %p\n", hConnect, fExpectResponse, dwFlags,
2225c2c66affSColin Finck debugstr_a(lpszCommand), dwContext, phFtpCommand);
2226c2c66affSColin Finck
2227c2c66affSColin Finck if (fExpectResponse)
2228c2c66affSColin Finck {
2229c2c66affSColin Finck FIXME("data connection not supported\n");
2230c2c66affSColin Finck return FALSE;
2231c2c66affSColin Finck }
2232c2c66affSColin Finck
2233c2c66affSColin Finck if (!lpszCommand || !lpszCommand[0])
2234c2c66affSColin Finck {
2235c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2236c2c66affSColin Finck return FALSE;
2237c2c66affSColin Finck }
2238c2c66affSColin Finck
2239c2c66affSColin Finck if (!(cmdW = heap_strdupAtoW(lpszCommand)))
2240c2c66affSColin Finck {
2241c2c66affSColin Finck INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2242c2c66affSColin Finck return FALSE;
2243c2c66affSColin Finck }
2244c2c66affSColin Finck
2245c2c66affSColin Finck r = FtpCommandW(hConnect, fExpectResponse, dwFlags, cmdW, dwContext, phFtpCommand);
2246c2c66affSColin Finck
2247c2c66affSColin Finck heap_free(cmdW);
2248c2c66affSColin Finck return r;
2249c2c66affSColin Finck }
2250c2c66affSColin Finck
2251c2c66affSColin Finck /***********************************************************************
2252c2c66affSColin Finck * FtpCommandW (WININET.@)
2253c2c66affSColin Finck */
FtpCommandW(HINTERNET hConnect,BOOL fExpectResponse,DWORD dwFlags,LPCWSTR lpszCommand,DWORD_PTR dwContext,HINTERNET * phFtpCommand)2254c2c66affSColin Finck BOOL WINAPI FtpCommandW( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags,
2255c2c66affSColin Finck LPCWSTR lpszCommand, DWORD_PTR dwContext, HINTERNET* phFtpCommand )
2256c2c66affSColin Finck {
2257c2c66affSColin Finck BOOL r = FALSE;
2258c2c66affSColin Finck ftp_session_t *lpwfs;
2259c2c66affSColin Finck LPSTR cmd = NULL;
2260c2c66affSColin Finck DWORD len, nBytesSent= 0;
2261c2c66affSColin Finck INT nResCode, nRC = 0;
2262c2c66affSColin Finck
2263c2c66affSColin Finck TRACE("%p %d 0x%08x %s 0x%08lx %p\n", hConnect, fExpectResponse, dwFlags,
2264c2c66affSColin Finck debugstr_w(lpszCommand), dwContext, phFtpCommand);
2265c2c66affSColin Finck
2266c2c66affSColin Finck if (!lpszCommand || !lpszCommand[0])
2267c2c66affSColin Finck {
2268c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2269c2c66affSColin Finck return FALSE;
2270c2c66affSColin Finck }
2271c2c66affSColin Finck
2272c2c66affSColin Finck if (fExpectResponse)
2273c2c66affSColin Finck {
2274c2c66affSColin Finck FIXME("data connection not supported\n");
2275c2c66affSColin Finck return FALSE;
2276c2c66affSColin Finck }
2277c2c66affSColin Finck
2278c2c66affSColin Finck lpwfs = (ftp_session_t*) get_handle_object( hConnect );
2279c2c66affSColin Finck if (!lpwfs)
2280c2c66affSColin Finck {
2281c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_HANDLE);
2282c2c66affSColin Finck return FALSE;
2283c2c66affSColin Finck }
2284c2c66affSColin Finck
2285c2c66affSColin Finck if (WH_HFTPSESSION != lpwfs->hdr.htype)
2286c2c66affSColin Finck {
2287c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
2288c2c66affSColin Finck goto lend;
2289c2c66affSColin Finck }
2290c2c66affSColin Finck
2291c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
2292c2c66affSColin Finck {
2293c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2294c2c66affSColin Finck goto lend;
2295c2c66affSColin Finck }
2296c2c66affSColin Finck
2297c2c66affSColin Finck len = WideCharToMultiByte(CP_ACP, 0, lpszCommand, -1, NULL, 0, NULL, NULL) + strlen(szCRLF);
2298c2c66affSColin Finck if ((cmd = heap_alloc(len)))
2299c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, lpszCommand, -1, cmd, len, NULL, NULL);
2300c2c66affSColin Finck else
2301c2c66affSColin Finck {
2302c2c66affSColin Finck INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2303c2c66affSColin Finck goto lend;
2304c2c66affSColin Finck }
2305c2c66affSColin Finck
2306c2c66affSColin Finck strcat(cmd, szCRLF);
2307c2c66affSColin Finck len--;
2308c2c66affSColin Finck
2309c2c66affSColin Finck TRACE("Sending (%s) len(%d)\n", debugstr_a(cmd), len);
2310c2c66affSColin Finck while ((nBytesSent < len) && (nRC != -1))
2311c2c66affSColin Finck {
2312c2c66affSColin Finck nRC = sock_send(lpwfs->sndSocket, cmd + nBytesSent, len - nBytesSent, 0);
2313c2c66affSColin Finck if (nRC != -1)
2314c2c66affSColin Finck {
2315c2c66affSColin Finck nBytesSent += nRC;
2316c2c66affSColin Finck TRACE("Sent %d bytes\n", nRC);
2317c2c66affSColin Finck }
2318c2c66affSColin Finck }
2319c2c66affSColin Finck
2320c2c66affSColin Finck if (nBytesSent)
2321c2c66affSColin Finck {
2322c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2323c2c66affSColin Finck if (nResCode > 0 && nResCode < 400)
2324c2c66affSColin Finck r = TRUE;
2325c2c66affSColin Finck else
2326c2c66affSColin Finck FTP_SetResponseError(nResCode);
2327c2c66affSColin Finck }
2328c2c66affSColin Finck
2329c2c66affSColin Finck lend:
2330c2c66affSColin Finck WININET_Release( &lpwfs->hdr );
2331c2c66affSColin Finck heap_free( cmd );
2332c2c66affSColin Finck return r;
2333c2c66affSColin Finck }
2334c2c66affSColin Finck
2335c2c66affSColin Finck
2336c2c66affSColin Finck /***********************************************************************
2337c2c66affSColin Finck * FTPSESSION_Destroy (internal)
2338c2c66affSColin Finck *
2339c2c66affSColin Finck * Deallocate session handle
2340c2c66affSColin Finck */
FTPSESSION_Destroy(object_header_t * hdr)2341c2c66affSColin Finck static void FTPSESSION_Destroy(object_header_t *hdr)
2342c2c66affSColin Finck {
2343c2c66affSColin Finck ftp_session_t *lpwfs = (ftp_session_t*) hdr;
2344c2c66affSColin Finck
2345c2c66affSColin Finck TRACE("\n");
2346c2c66affSColin Finck
2347c2c66affSColin Finck WININET_Release(&lpwfs->lpAppInfo->hdr);
2348c2c66affSColin Finck
2349c2c66affSColin Finck heap_free(lpwfs->lpszPassword);
2350c2c66affSColin Finck heap_free(lpwfs->lpszUserName);
2351c2c66affSColin Finck heap_free(lpwfs->servername);
2352c2c66affSColin Finck }
2353c2c66affSColin Finck
FTPSESSION_CloseConnection(object_header_t * hdr)2354c2c66affSColin Finck static void FTPSESSION_CloseConnection(object_header_t *hdr)
2355c2c66affSColin Finck {
2356c2c66affSColin Finck ftp_session_t *lpwfs = (ftp_session_t*) hdr;
2357c2c66affSColin Finck
2358c2c66affSColin Finck TRACE("\n");
2359c2c66affSColin Finck
2360c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext,
2361c2c66affSColin Finck INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
2362c2c66affSColin Finck
2363c2c66affSColin Finck if (lpwfs->download_in_progress != NULL)
2364c2c66affSColin Finck lpwfs->download_in_progress->session_deleted = TRUE;
2365c2c66affSColin Finck
2366c2c66affSColin Finck if (lpwfs->sndSocket != -1)
2367c2c66affSColin Finck closesocket(lpwfs->sndSocket);
2368c2c66affSColin Finck
2369c2c66affSColin Finck if (lpwfs->lstnSocket != -1)
2370c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
2371c2c66affSColin Finck
2372c2c66affSColin Finck if (lpwfs->pasvSocket != -1)
2373c2c66affSColin Finck closesocket(lpwfs->pasvSocket);
2374c2c66affSColin Finck
2375c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, lpwfs->hdr.dwContext,
2376c2c66affSColin Finck INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
2377c2c66affSColin Finck }
2378c2c66affSColin Finck
FTPSESSION_QueryOption(object_header_t * hdr,DWORD option,void * buffer,DWORD * size,BOOL unicode)2379c2c66affSColin Finck static DWORD FTPSESSION_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
2380c2c66affSColin Finck {
2381c2c66affSColin Finck switch(option) {
2382c2c66affSColin Finck case INTERNET_OPTION_HANDLE_TYPE:
2383c2c66affSColin Finck TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
2384c2c66affSColin Finck
2385c2c66affSColin Finck if (*size < sizeof(ULONG))
2386c2c66affSColin Finck return ERROR_INSUFFICIENT_BUFFER;
2387c2c66affSColin Finck
2388c2c66affSColin Finck *size = sizeof(DWORD);
2389c2c66affSColin Finck *(DWORD*)buffer = INTERNET_HANDLE_TYPE_CONNECT_FTP;
2390c2c66affSColin Finck return ERROR_SUCCESS;
2391c2c66affSColin Finck }
2392c2c66affSColin Finck
2393c2c66affSColin Finck return INET_QueryOption(hdr, option, buffer, size, unicode);
2394c2c66affSColin Finck }
2395c2c66affSColin Finck
2396c2c66affSColin Finck static const object_vtbl_t FTPSESSIONVtbl = {
2397c2c66affSColin Finck FTPSESSION_Destroy,
2398c2c66affSColin Finck FTPSESSION_CloseConnection,
2399c2c66affSColin Finck FTPSESSION_QueryOption,
2400c2c66affSColin Finck INET_SetOption,
2401c2c66affSColin Finck NULL,
2402c2c66affSColin Finck NULL,
2403c2c66affSColin Finck NULL,
2404c2c66affSColin Finck NULL
2405c2c66affSColin Finck };
2406c2c66affSColin Finck
2407c2c66affSColin Finck
2408c2c66affSColin Finck /***********************************************************************
2409c2c66affSColin Finck * FTP_Connect (internal)
2410c2c66affSColin Finck *
2411c2c66affSColin Finck * Connect to a ftp server
2412c2c66affSColin Finck *
2413c2c66affSColin Finck * RETURNS
2414c2c66affSColin Finck * HINTERNET a session handle on success
2415c2c66affSColin Finck * NULL on failure
2416c2c66affSColin Finck *
2417c2c66affSColin Finck * NOTES:
2418c2c66affSColin Finck *
2419c2c66affSColin Finck * Windows uses 'anonymous' as the username, when given a NULL username
2420c2c66affSColin Finck * and a NULL password. The password is first looked up in:
2421c2c66affSColin Finck *
2422c2c66affSColin Finck * HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\EmailName
2423c2c66affSColin Finck *
2424c2c66affSColin Finck * If this entry is not present it uses the current username as the password.
2425c2c66affSColin Finck *
2426c2c66affSColin Finck */
2427c2c66affSColin Finck
FTP_Connect(appinfo_t * hIC,LPCWSTR lpszServerName,INTERNET_PORT nServerPort,LPCWSTR lpszUserName,LPCWSTR lpszPassword,DWORD dwFlags,DWORD_PTR dwContext,DWORD dwInternalFlags)2428c2c66affSColin Finck HINTERNET FTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
2429c2c66affSColin Finck INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
2430c2c66affSColin Finck LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext,
2431c2c66affSColin Finck DWORD dwInternalFlags)
2432c2c66affSColin Finck {
2433c2c66affSColin Finck struct sockaddr_in socketAddr;
2434c2c66affSColin Finck INT nsocket = -1;
2435c2c66affSColin Finck socklen_t sock_namelen;
2436c2c66affSColin Finck BOOL bSuccess = FALSE;
2437c2c66affSColin Finck ftp_session_t *lpwfs = NULL;
2438c2c66affSColin Finck char szaddr[INET6_ADDRSTRLEN];
2439c2c66affSColin Finck
2440c2c66affSColin Finck TRACE("%p Server(%s) Port(%d) User(%s) Paswd(%s)\n",
2441c2c66affSColin Finck hIC, debugstr_w(lpszServerName),
2442c2c66affSColin Finck nServerPort, debugstr_w(lpszUserName), debugstr_w(lpszPassword));
2443c2c66affSColin Finck
2444c2c66affSColin Finck assert( hIC->hdr.htype == WH_HINIT );
2445c2c66affSColin Finck
2446c2c66affSColin Finck if ((!lpszUserName || !*lpszUserName) && lpszPassword && *lpszPassword)
2447c2c66affSColin Finck {
2448c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2449c2c66affSColin Finck return NULL;
2450c2c66affSColin Finck }
2451c2c66affSColin Finck
2452c2c66affSColin Finck lpwfs = alloc_object(&hIC->hdr, &FTPSESSIONVtbl, sizeof(ftp_session_t));
2453c2c66affSColin Finck if (NULL == lpwfs)
2454c2c66affSColin Finck {
2455c2c66affSColin Finck INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2456c2c66affSColin Finck return NULL;
2457c2c66affSColin Finck }
2458c2c66affSColin Finck
2459c2c66affSColin Finck if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
2460c2c66affSColin Finck lpwfs->serverport = INTERNET_DEFAULT_FTP_PORT;
2461c2c66affSColin Finck else
2462c2c66affSColin Finck lpwfs->serverport = nServerPort;
2463c2c66affSColin Finck
2464c2c66affSColin Finck lpwfs->hdr.htype = WH_HFTPSESSION;
2465c2c66affSColin Finck lpwfs->hdr.dwFlags = dwFlags;
2466c2c66affSColin Finck lpwfs->hdr.dwContext = dwContext;
2467c2c66affSColin Finck lpwfs->hdr.dwInternalFlags |= dwInternalFlags;
2468c2c66affSColin Finck lpwfs->download_in_progress = NULL;
2469c2c66affSColin Finck lpwfs->sndSocket = -1;
2470c2c66affSColin Finck lpwfs->lstnSocket = -1;
2471c2c66affSColin Finck lpwfs->pasvSocket = -1;
2472c2c66affSColin Finck
2473c2c66affSColin Finck WININET_AddRef( &hIC->hdr );
2474c2c66affSColin Finck lpwfs->lpAppInfo = hIC;
2475c2c66affSColin Finck list_add_head( &hIC->hdr.children, &lpwfs->hdr.entry );
2476c2c66affSColin Finck
2477c2c66affSColin Finck if(hIC->proxy && hIC->accessType == INTERNET_OPEN_TYPE_PROXY) {
24785f12c8d7Swinesync if(wcschr(hIC->proxy, ' '))
2479c2c66affSColin Finck FIXME("Several proxies not implemented.\n");
2480c2c66affSColin Finck if(hIC->proxyBypass)
2481c2c66affSColin Finck FIXME("Proxy bypass is ignored.\n");
2482c2c66affSColin Finck }
2483c2c66affSColin Finck if (!lpszUserName || !lpszUserName[0]) {
2484c2c66affSColin Finck HKEY key;
2485c2c66affSColin Finck WCHAR szPassword[MAX_PATH];
2486c2c66affSColin Finck DWORD len = sizeof(szPassword);
2487c2c66affSColin Finck
2488*e152f78aSwinesync lpwfs->lpszUserName = heap_strdupW(L"anonymous");
2489c2c66affSColin Finck
2490*e152f78aSwinesync RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", &key);
2491*e152f78aSwinesync if (RegQueryValueExW(key, L"EmailName", NULL, NULL, (LPBYTE)szPassword, &len)) {
2492c2c66affSColin Finck /* Nothing in the registry, get the username and use that as the password */
2493c2c66affSColin Finck if (!GetUserNameW(szPassword, &len)) {
2494c2c66affSColin Finck /* Should never get here, but use an empty password as failsafe */
2495*e152f78aSwinesync lstrcpyW(szPassword, L"");
2496c2c66affSColin Finck }
2497c2c66affSColin Finck }
2498c2c66affSColin Finck RegCloseKey(key);
2499c2c66affSColin Finck
2500c2c66affSColin Finck TRACE("Password used for anonymous ftp : (%s)\n", debugstr_w(szPassword));
2501c2c66affSColin Finck lpwfs->lpszPassword = heap_strdupW(szPassword);
2502c2c66affSColin Finck }
2503c2c66affSColin Finck else {
2504c2c66affSColin Finck lpwfs->lpszUserName = heap_strdupW(lpszUserName);
2505*e152f78aSwinesync lpwfs->lpszPassword = heap_strdupW(lpszPassword ? lpszPassword : L"");
2506c2c66affSColin Finck }
2507c2c66affSColin Finck lpwfs->servername = heap_strdupW(lpszServerName);
2508c2c66affSColin Finck
2509c2c66affSColin Finck /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
2510c2c66affSColin Finck if (!(lpwfs->hdr.dwInternalFlags & INET_OPENURL))
2511c2c66affSColin Finck {
2512c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
2513c2c66affSColin Finck
2514c2c66affSColin Finck iar.dwResult = (DWORD_PTR)lpwfs->hdr.hInternet;
2515c2c66affSColin Finck iar.dwError = ERROR_SUCCESS;
2516c2c66affSColin Finck
2517c2c66affSColin Finck INTERNET_SendCallback(&hIC->hdr, dwContext,
2518c2c66affSColin Finck INTERNET_STATUS_HANDLE_CREATED, &iar,
2519c2c66affSColin Finck sizeof(INTERNET_ASYNC_RESULT));
2520c2c66affSColin Finck }
2521c2c66affSColin Finck
2522c2c66affSColin Finck INTERNET_SendCallback(&hIC->hdr, dwContext, INTERNET_STATUS_RESOLVING_NAME,
25235f12c8d7Swinesync (LPWSTR) lpszServerName, (lstrlenW(lpszServerName)+1) * sizeof(WCHAR));
2524c2c66affSColin Finck
2525c2c66affSColin Finck sock_namelen = sizeof(socketAddr);
2526c2c66affSColin Finck if (!GetAddress(lpszServerName, lpwfs->serverport, (struct sockaddr *)&socketAddr, &sock_namelen, szaddr))
2527c2c66affSColin Finck {
2528c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
2529c2c66affSColin Finck goto lerror;
2530c2c66affSColin Finck }
2531c2c66affSColin Finck
2532c2c66affSColin Finck if (socketAddr.sin_family != AF_INET)
2533c2c66affSColin Finck {
2534c2c66affSColin Finck WARN("unsupported address family %d\n", socketAddr.sin_family);
2535c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
2536c2c66affSColin Finck goto lerror;
2537c2c66affSColin Finck }
2538c2c66affSColin Finck
2539c2c66affSColin Finck INTERNET_SendCallback(&hIC->hdr, dwContext, INTERNET_STATUS_NAME_RESOLVED,
2540c2c66affSColin Finck szaddr, strlen(szaddr)+1);
2541c2c66affSColin Finck
2542c2c66affSColin Finck init_winsock();
2543c2c66affSColin Finck nsocket = socket(AF_INET,SOCK_STREAM,0);
2544c2c66affSColin Finck if (nsocket == -1)
2545c2c66affSColin Finck {
2546c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
2547c2c66affSColin Finck goto lerror;
2548c2c66affSColin Finck }
2549c2c66affSColin Finck
2550c2c66affSColin Finck INTERNET_SendCallback(&hIC->hdr, dwContext, INTERNET_STATUS_CONNECTING_TO_SERVER,
2551c2c66affSColin Finck szaddr, strlen(szaddr)+1);
2552c2c66affSColin Finck
2553c2c66affSColin Finck if (connect(nsocket, (struct sockaddr *)&socketAddr, sock_namelen) < 0)
2554c2c66affSColin Finck {
2555c2c66affSColin Finck ERR("Unable to connect (%d)\n", WSAGetLastError());
2556c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
2557c2c66affSColin Finck closesocket(nsocket);
2558c2c66affSColin Finck }
2559c2c66affSColin Finck else
2560c2c66affSColin Finck {
2561c2c66affSColin Finck TRACE("Connected to server\n");
2562c2c66affSColin Finck lpwfs->sndSocket = nsocket;
2563c2c66affSColin Finck INTERNET_SendCallback(&hIC->hdr, dwContext, INTERNET_STATUS_CONNECTED_TO_SERVER,
2564c2c66affSColin Finck szaddr, strlen(szaddr)+1);
2565c2c66affSColin Finck
2566c2c66affSColin Finck sock_namelen = sizeof(lpwfs->socketAddress);
2567c2c66affSColin Finck getsockname(nsocket, (struct sockaddr *) &lpwfs->socketAddress, &sock_namelen);
2568c2c66affSColin Finck
2569c2c66affSColin Finck if (FTP_ConnectToHost(lpwfs))
2570c2c66affSColin Finck {
2571c2c66affSColin Finck TRACE("Successfully logged into server\n");
2572c2c66affSColin Finck bSuccess = TRUE;
2573c2c66affSColin Finck }
2574c2c66affSColin Finck }
2575c2c66affSColin Finck
2576c2c66affSColin Finck lerror:
2577c2c66affSColin Finck if (!bSuccess)
2578c2c66affSColin Finck {
2579c2c66affSColin Finck WININET_Release(&lpwfs->hdr);
2580c2c66affSColin Finck return NULL;
2581c2c66affSColin Finck }
2582c2c66affSColin Finck
2583c2c66affSColin Finck return lpwfs->hdr.hInternet;
2584c2c66affSColin Finck }
2585c2c66affSColin Finck
2586c2c66affSColin Finck
2587c2c66affSColin Finck /***********************************************************************
2588c2c66affSColin Finck * FTP_ConnectToHost (internal)
2589c2c66affSColin Finck *
2590c2c66affSColin Finck * Connect to a ftp server
2591c2c66affSColin Finck *
2592c2c66affSColin Finck * RETURNS
2593c2c66affSColin Finck * TRUE on success
2594c2c66affSColin Finck * NULL on failure
2595c2c66affSColin Finck *
2596c2c66affSColin Finck */
FTP_ConnectToHost(ftp_session_t * lpwfs)2597c2c66affSColin Finck static BOOL FTP_ConnectToHost(ftp_session_t *lpwfs)
2598c2c66affSColin Finck {
2599c2c66affSColin Finck INT nResCode;
2600c2c66affSColin Finck BOOL bSuccess = FALSE;
2601c2c66affSColin Finck
2602c2c66affSColin Finck TRACE("\n");
2603c2c66affSColin Finck FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2604c2c66affSColin Finck
2605c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_USER, lpwfs->lpszUserName, 0, 0, 0))
2606c2c66affSColin Finck goto lend;
2607c2c66affSColin Finck
2608c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2609c2c66affSColin Finck if (nResCode)
2610c2c66affSColin Finck {
2611c2c66affSColin Finck /* Login successful... */
2612c2c66affSColin Finck if (nResCode == 230)
2613c2c66affSColin Finck bSuccess = TRUE;
2614c2c66affSColin Finck /* User name okay, need password... */
2615c2c66affSColin Finck else if (nResCode == 331)
2616c2c66affSColin Finck bSuccess = FTP_SendPassword(lpwfs);
2617c2c66affSColin Finck /* Need account for login... */
2618c2c66affSColin Finck else if (nResCode == 332)
2619c2c66affSColin Finck bSuccess = FTP_SendAccount(lpwfs);
2620c2c66affSColin Finck else
2621c2c66affSColin Finck FTP_SetResponseError(nResCode);
2622c2c66affSColin Finck }
2623c2c66affSColin Finck
2624c2c66affSColin Finck TRACE("Returning %d\n", bSuccess);
2625c2c66affSColin Finck lend:
2626c2c66affSColin Finck return bSuccess;
2627c2c66affSColin Finck }
2628c2c66affSColin Finck
2629c2c66affSColin Finck /***********************************************************************
2630c2c66affSColin Finck * FTP_GetNextLine (internal)
2631c2c66affSColin Finck *
2632c2c66affSColin Finck * Parse next line in directory string listing
2633c2c66affSColin Finck *
2634c2c66affSColin Finck * RETURNS
2635c2c66affSColin Finck * Pointer to beginning of next line
2636c2c66affSColin Finck * NULL on failure
2637c2c66affSColin Finck *
2638c2c66affSColin Finck */
2639c2c66affSColin Finck
FTP_GetNextLine(INT nSocket,LPDWORD dwLen)2640c2c66affSColin Finck static LPSTR FTP_GetNextLine(INT nSocket, LPDWORD dwLen)
2641c2c66affSColin Finck {
2642c2c66affSColin Finck struct timeval tv = {RESPONSE_TIMEOUT,0};
2643c2c66affSColin Finck FD_SET set;
2644c2c66affSColin Finck INT nRecv = 0;
2645c2c66affSColin Finck LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
2646c2c66affSColin Finck
2647c2c66affSColin Finck TRACE("\n");
2648c2c66affSColin Finck
2649c2c66affSColin Finck FD_ZERO(&set);
2650c2c66affSColin Finck FD_SET(nSocket, &set);
2651c2c66affSColin Finck
2652c2c66affSColin Finck while (nRecv < MAX_REPLY_LEN)
2653c2c66affSColin Finck {
2654c2c66affSColin Finck if (select(nSocket+1, &set, NULL, NULL, &tv) > 0)
2655c2c66affSColin Finck {
2656c2c66affSColin Finck if (sock_recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2657c2c66affSColin Finck {
2658c2c66affSColin Finck INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2659c2c66affSColin Finck return NULL;
2660c2c66affSColin Finck }
2661c2c66affSColin Finck
2662c2c66affSColin Finck if (lpszBuffer[nRecv] == '\n')
2663c2c66affSColin Finck {
2664c2c66affSColin Finck lpszBuffer[nRecv] = '\0';
2665c2c66affSColin Finck *dwLen = nRecv - 1;
2666c2c66affSColin Finck TRACE(":%d %s\n", nRecv, lpszBuffer);
2667c2c66affSColin Finck return lpszBuffer;
2668c2c66affSColin Finck }
2669c2c66affSColin Finck if (lpszBuffer[nRecv] != '\r')
2670c2c66affSColin Finck nRecv++;
2671c2c66affSColin Finck }
2672c2c66affSColin Finck else
2673c2c66affSColin Finck {
2674c2c66affSColin Finck INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
2675c2c66affSColin Finck return NULL;
2676c2c66affSColin Finck }
2677c2c66affSColin Finck }
2678c2c66affSColin Finck
2679c2c66affSColin Finck return NULL;
2680c2c66affSColin Finck }
2681c2c66affSColin Finck
2682c2c66affSColin Finck /***********************************************************************
2683c2c66affSColin Finck * FTP_SendCommandA (internal)
2684c2c66affSColin Finck *
2685c2c66affSColin Finck * Send command to server
2686c2c66affSColin Finck *
2687c2c66affSColin Finck * RETURNS
2688c2c66affSColin Finck * TRUE on success
2689c2c66affSColin Finck * NULL on failure
2690c2c66affSColin Finck *
2691c2c66affSColin Finck */
FTP_SendCommandA(INT nSocket,FTP_COMMAND ftpCmd,LPCSTR lpszParam,INTERNET_STATUS_CALLBACK lpfnStatusCB,object_header_t * hdr,DWORD_PTR dwContext)2692c2c66affSColin Finck static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
2693c2c66affSColin Finck INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext)
2694c2c66affSColin Finck {
2695c2c66affSColin Finck DWORD len;
2696c2c66affSColin Finck CHAR *buf;
2697c2c66affSColin Finck DWORD nBytesSent = 0;
2698c2c66affSColin Finck int nRC = 0;
2699c2c66affSColin Finck DWORD dwParamLen;
2700c2c66affSColin Finck
2701c2c66affSColin Finck TRACE("%d: (%s) %d\n", ftpCmd, debugstr_a(lpszParam), nSocket);
2702c2c66affSColin Finck
2703c2c66affSColin Finck if (lpfnStatusCB)
2704c2c66affSColin Finck {
2705c2c66affSColin Finck lpfnStatusCB(hdr->hInternet, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
2706c2c66affSColin Finck }
2707c2c66affSColin Finck
2708c2c66affSColin Finck dwParamLen = lpszParam?strlen(lpszParam)+1:0;
2709c2c66affSColin Finck len = dwParamLen + strlen(szFtpCommands[ftpCmd]) + strlen(szCRLF);
2710c2c66affSColin Finck if (NULL == (buf = heap_alloc(len+1)))
2711c2c66affSColin Finck {
2712c2c66affSColin Finck INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2713c2c66affSColin Finck return FALSE;
2714c2c66affSColin Finck }
2715c2c66affSColin Finck sprintf(buf, "%s%s%s%s", szFtpCommands[ftpCmd], dwParamLen ? " " : "",
2716c2c66affSColin Finck dwParamLen ? lpszParam : "", szCRLF);
2717c2c66affSColin Finck
2718c2c66affSColin Finck TRACE("Sending (%s) len(%d)\n", debugstr_a(buf), len);
2719c2c66affSColin Finck while((nBytesSent < len) && (nRC != -1))
2720c2c66affSColin Finck {
2721c2c66affSColin Finck nRC = sock_send(nSocket, buf+nBytesSent, len - nBytesSent, 0);
2722c2c66affSColin Finck nBytesSent += nRC;
2723c2c66affSColin Finck }
2724c2c66affSColin Finck heap_free(buf);
2725c2c66affSColin Finck
2726c2c66affSColin Finck if (lpfnStatusCB)
2727c2c66affSColin Finck {
2728c2c66affSColin Finck lpfnStatusCB(hdr->hInternet, dwContext, INTERNET_STATUS_REQUEST_SENT,
2729c2c66affSColin Finck &nBytesSent, sizeof(DWORD));
2730c2c66affSColin Finck }
2731c2c66affSColin Finck
2732c2c66affSColin Finck TRACE("Sent %d bytes\n", nBytesSent);
2733c2c66affSColin Finck return (nRC != -1);
2734c2c66affSColin Finck }
2735c2c66affSColin Finck
2736c2c66affSColin Finck /***********************************************************************
2737c2c66affSColin Finck * FTP_SendCommand (internal)
2738c2c66affSColin Finck *
2739c2c66affSColin Finck * Send command to server
2740c2c66affSColin Finck *
2741c2c66affSColin Finck * RETURNS
2742c2c66affSColin Finck * TRUE on success
2743c2c66affSColin Finck * NULL on failure
2744c2c66affSColin Finck *
2745c2c66affSColin Finck */
FTP_SendCommand(INT nSocket,FTP_COMMAND ftpCmd,LPCWSTR lpszParam,INTERNET_STATUS_CALLBACK lpfnStatusCB,object_header_t * hdr,DWORD_PTR dwContext)2746c2c66affSColin Finck static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
2747c2c66affSColin Finck INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext)
2748c2c66affSColin Finck {
2749c2c66affSColin Finck BOOL ret;
2750c2c66affSColin Finck LPSTR lpszParamA = heap_strdupWtoA(lpszParam);
2751c2c66affSColin Finck ret = FTP_SendCommandA(nSocket, ftpCmd, lpszParamA, lpfnStatusCB, hdr, dwContext);
2752c2c66affSColin Finck heap_free(lpszParamA);
2753c2c66affSColin Finck return ret;
2754c2c66affSColin Finck }
2755c2c66affSColin Finck
2756c2c66affSColin Finck /***********************************************************************
2757c2c66affSColin Finck * FTP_ReceiveResponse (internal)
2758c2c66affSColin Finck *
2759c2c66affSColin Finck * Receive response from server
2760c2c66affSColin Finck *
2761c2c66affSColin Finck * RETURNS
2762c2c66affSColin Finck * Reply code on success
2763c2c66affSColin Finck * 0 on failure
2764c2c66affSColin Finck *
2765c2c66affSColin Finck */
FTP_ReceiveResponse(ftp_session_t * lpwfs,DWORD_PTR dwContext)2766c2c66affSColin Finck INT FTP_ReceiveResponse(ftp_session_t *lpwfs, DWORD_PTR dwContext)
2767c2c66affSColin Finck {
2768c2c66affSColin Finck LPSTR lpszResponse = INTERNET_GetResponseBuffer();
2769c2c66affSColin Finck DWORD nRecv;
2770c2c66affSColin Finck INT rc = 0;
2771c2c66affSColin Finck char firstprefix[5];
2772c2c66affSColin Finck BOOL multiline = FALSE;
2773c2c66affSColin Finck
2774c2c66affSColin Finck TRACE("socket(%d)\n", lpwfs->sndSocket);
2775c2c66affSColin Finck
2776c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
2777c2c66affSColin Finck
2778c2c66affSColin Finck while(1)
2779c2c66affSColin Finck {
2780c2c66affSColin Finck if (!FTP_GetNextLine(lpwfs->sndSocket, &nRecv))
2781c2c66affSColin Finck goto lerror;
2782c2c66affSColin Finck
2783c2c66affSColin Finck if (nRecv >= 3)
2784c2c66affSColin Finck {
2785c2c66affSColin Finck if(!multiline)
2786c2c66affSColin Finck {
2787c2c66affSColin Finck if(lpszResponse[3] != '-')
2788c2c66affSColin Finck break;
2789c2c66affSColin Finck else
2790c2c66affSColin Finck { /* Start of multiline response. Loop until we get "nnn " */
2791c2c66affSColin Finck multiline = TRUE;
2792c2c66affSColin Finck memcpy(firstprefix, lpszResponse, 3);
2793c2c66affSColin Finck firstprefix[3] = ' ';
2794c2c66affSColin Finck firstprefix[4] = '\0';
2795c2c66affSColin Finck }
2796c2c66affSColin Finck }
2797c2c66affSColin Finck else
2798c2c66affSColin Finck {
2799c2c66affSColin Finck if(!memcmp(firstprefix, lpszResponse, 4))
2800c2c66affSColin Finck break;
2801c2c66affSColin Finck }
2802c2c66affSColin Finck }
2803c2c66affSColin Finck }
2804c2c66affSColin Finck
2805c2c66affSColin Finck if (nRecv >= 3)
2806c2c66affSColin Finck {
2807c2c66affSColin Finck rc = atoi(lpszResponse);
2808c2c66affSColin Finck
2809c2c66affSColin Finck INTERNET_SendCallback(&lpwfs->hdr, dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
2810c2c66affSColin Finck &nRecv, sizeof(DWORD));
2811c2c66affSColin Finck }
2812c2c66affSColin Finck
2813c2c66affSColin Finck lerror:
2814c2c66affSColin Finck TRACE("return %d\n", rc);
2815c2c66affSColin Finck return rc;
2816c2c66affSColin Finck }
2817c2c66affSColin Finck
2818c2c66affSColin Finck
2819c2c66affSColin Finck /***********************************************************************
2820c2c66affSColin Finck * FTP_SendPassword (internal)
2821c2c66affSColin Finck *
2822c2c66affSColin Finck * Send password to ftp server
2823c2c66affSColin Finck *
2824c2c66affSColin Finck * RETURNS
2825c2c66affSColin Finck * TRUE on success
2826c2c66affSColin Finck * NULL on failure
2827c2c66affSColin Finck *
2828c2c66affSColin Finck */
FTP_SendPassword(ftp_session_t * lpwfs)2829c2c66affSColin Finck static BOOL FTP_SendPassword(ftp_session_t *lpwfs)
2830c2c66affSColin Finck {
2831c2c66affSColin Finck INT nResCode;
2832c2c66affSColin Finck BOOL bSuccess = FALSE;
2833c2c66affSColin Finck
2834c2c66affSColin Finck TRACE("\n");
2835c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASS, lpwfs->lpszPassword, 0, 0, 0))
2836c2c66affSColin Finck goto lend;
2837c2c66affSColin Finck
2838c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2839c2c66affSColin Finck if (nResCode)
2840c2c66affSColin Finck {
2841c2c66affSColin Finck TRACE("Received reply code %d\n", nResCode);
2842c2c66affSColin Finck /* Login successful... */
2843c2c66affSColin Finck if (nResCode == 230)
2844c2c66affSColin Finck bSuccess = TRUE;
2845c2c66affSColin Finck /* Command not implemented, superfluous at the server site... */
2846c2c66affSColin Finck /* Need account for login... */
2847c2c66affSColin Finck else if (nResCode == 332)
2848c2c66affSColin Finck bSuccess = FTP_SendAccount(lpwfs);
2849c2c66affSColin Finck else
2850c2c66affSColin Finck FTP_SetResponseError(nResCode);
2851c2c66affSColin Finck }
2852c2c66affSColin Finck
2853c2c66affSColin Finck lend:
2854c2c66affSColin Finck TRACE("Returning %d\n", bSuccess);
2855c2c66affSColin Finck return bSuccess;
2856c2c66affSColin Finck }
2857c2c66affSColin Finck
2858c2c66affSColin Finck
2859c2c66affSColin Finck /***********************************************************************
2860c2c66affSColin Finck * FTP_SendAccount (internal)
2861c2c66affSColin Finck *
2862c2c66affSColin Finck *
2863c2c66affSColin Finck *
2864c2c66affSColin Finck * RETURNS
2865c2c66affSColin Finck * TRUE on success
2866c2c66affSColin Finck * FALSE on failure
2867c2c66affSColin Finck *
2868c2c66affSColin Finck */
FTP_SendAccount(ftp_session_t * lpwfs)2869c2c66affSColin Finck static BOOL FTP_SendAccount(ftp_session_t *lpwfs)
2870c2c66affSColin Finck {
2871c2c66affSColin Finck INT nResCode;
2872c2c66affSColin Finck BOOL bSuccess = FALSE;
2873c2c66affSColin Finck
2874c2c66affSColin Finck TRACE("\n");
2875*e152f78aSwinesync if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_ACCT, L"noaccount", 0, 0, 0))
2876c2c66affSColin Finck goto lend;
2877c2c66affSColin Finck
2878c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2879c2c66affSColin Finck if (nResCode)
2880c2c66affSColin Finck bSuccess = TRUE;
2881c2c66affSColin Finck else
2882c2c66affSColin Finck FTP_SetResponseError(nResCode);
2883c2c66affSColin Finck
2884c2c66affSColin Finck lend:
2885c2c66affSColin Finck return bSuccess;
2886c2c66affSColin Finck }
2887c2c66affSColin Finck
2888c2c66affSColin Finck
2889c2c66affSColin Finck /***********************************************************************
2890c2c66affSColin Finck * FTP_SendStore (internal)
2891c2c66affSColin Finck *
2892c2c66affSColin Finck * Send request to upload file to ftp server
2893c2c66affSColin Finck *
2894c2c66affSColin Finck * RETURNS
2895c2c66affSColin Finck * TRUE on success
2896c2c66affSColin Finck * FALSE on failure
2897c2c66affSColin Finck *
2898c2c66affSColin Finck */
FTP_SendStore(ftp_session_t * lpwfs,LPCWSTR lpszRemoteFile,DWORD dwType)2899c2c66affSColin Finck static BOOL FTP_SendStore(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
2900c2c66affSColin Finck {
2901c2c66affSColin Finck INT nResCode;
2902c2c66affSColin Finck BOOL bSuccess = FALSE;
2903c2c66affSColin Finck
2904c2c66affSColin Finck TRACE("\n");
2905c2c66affSColin Finck if (!FTP_InitListenSocket(lpwfs))
2906c2c66affSColin Finck goto lend;
2907c2c66affSColin Finck
2908c2c66affSColin Finck if (!FTP_SendType(lpwfs, dwType))
2909c2c66affSColin Finck goto lend;
2910c2c66affSColin Finck
2911c2c66affSColin Finck if (!FTP_SendPortOrPasv(lpwfs))
2912c2c66affSColin Finck goto lend;
2913c2c66affSColin Finck
2914c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_STOR, lpszRemoteFile, 0, 0, 0))
2915c2c66affSColin Finck goto lend;
2916c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2917c2c66affSColin Finck if (nResCode)
2918c2c66affSColin Finck {
2919c2c66affSColin Finck if (nResCode == 150 || nResCode == 125)
2920c2c66affSColin Finck bSuccess = TRUE;
2921c2c66affSColin Finck else
2922c2c66affSColin Finck FTP_SetResponseError(nResCode);
2923c2c66affSColin Finck }
2924c2c66affSColin Finck
2925c2c66affSColin Finck lend:
2926c2c66affSColin Finck if (!bSuccess && lpwfs->lstnSocket != -1)
2927c2c66affSColin Finck {
2928c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
2929c2c66affSColin Finck lpwfs->lstnSocket = -1;
2930c2c66affSColin Finck }
2931c2c66affSColin Finck
2932c2c66affSColin Finck return bSuccess;
2933c2c66affSColin Finck }
2934c2c66affSColin Finck
2935c2c66affSColin Finck
2936c2c66affSColin Finck /***********************************************************************
2937c2c66affSColin Finck * FTP_InitListenSocket (internal)
2938c2c66affSColin Finck *
2939c2c66affSColin Finck * Create a socket to listen for server response
2940c2c66affSColin Finck *
2941c2c66affSColin Finck * RETURNS
2942c2c66affSColin Finck * TRUE on success
2943c2c66affSColin Finck * FALSE on failure
2944c2c66affSColin Finck *
2945c2c66affSColin Finck */
FTP_InitListenSocket(ftp_session_t * lpwfs)2946c2c66affSColin Finck static BOOL FTP_InitListenSocket(ftp_session_t *lpwfs)
2947c2c66affSColin Finck {
2948c2c66affSColin Finck BOOL bSuccess = FALSE;
2949c2c66affSColin Finck socklen_t namelen = sizeof(lpwfs->lstnSocketAddress);
2950c2c66affSColin Finck
2951c2c66affSColin Finck TRACE("\n");
2952c2c66affSColin Finck
2953c2c66affSColin Finck init_winsock();
2954c2c66affSColin Finck lpwfs->lstnSocket = socket(AF_INET, SOCK_STREAM, 0);
2955c2c66affSColin Finck if (lpwfs->lstnSocket == -1)
2956c2c66affSColin Finck {
2957c2c66affSColin Finck TRACE("Unable to create listening socket\n");
2958c2c66affSColin Finck goto lend;
2959c2c66affSColin Finck }
2960c2c66affSColin Finck
2961c2c66affSColin Finck /* We obtain our ip addr from the name of the command channel socket */
2962c2c66affSColin Finck lpwfs->lstnSocketAddress = lpwfs->socketAddress;
2963c2c66affSColin Finck
2964c2c66affSColin Finck /* and get the system to assign us a port */
2965c2c66affSColin Finck lpwfs->lstnSocketAddress.sin_port = htons(0);
2966c2c66affSColin Finck
2967c2c66affSColin Finck if (bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(lpwfs->lstnSocketAddress)) == -1)
2968c2c66affSColin Finck {
2969c2c66affSColin Finck TRACE("Unable to bind socket\n");
2970c2c66affSColin Finck goto lend;
2971c2c66affSColin Finck }
2972c2c66affSColin Finck
2973c2c66affSColin Finck if (listen(lpwfs->lstnSocket, MAX_BACKLOG) == -1)
2974c2c66affSColin Finck {
2975c2c66affSColin Finck TRACE("listen failed\n");
2976c2c66affSColin Finck goto lend;
2977c2c66affSColin Finck }
2978c2c66affSColin Finck
2979c2c66affSColin Finck if (getsockname(lpwfs->lstnSocket, (struct sockaddr *) &lpwfs->lstnSocketAddress, &namelen) != -1)
2980c2c66affSColin Finck bSuccess = TRUE;
2981c2c66affSColin Finck
2982c2c66affSColin Finck lend:
2983c2c66affSColin Finck if (!bSuccess && lpwfs->lstnSocket != -1)
2984c2c66affSColin Finck {
2985c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
2986c2c66affSColin Finck lpwfs->lstnSocket = -1;
2987c2c66affSColin Finck }
2988c2c66affSColin Finck
2989c2c66affSColin Finck return bSuccess;
2990c2c66affSColin Finck }
2991c2c66affSColin Finck
2992c2c66affSColin Finck
2993c2c66affSColin Finck /***********************************************************************
2994c2c66affSColin Finck * FTP_SendType (internal)
2995c2c66affSColin Finck *
2996c2c66affSColin Finck * Tell server type of data being transferred
2997c2c66affSColin Finck *
2998c2c66affSColin Finck * RETURNS
2999c2c66affSColin Finck * TRUE on success
3000c2c66affSColin Finck * FALSE on failure
3001c2c66affSColin Finck *
3002c2c66affSColin Finck * W98SE doesn't cache the type that's currently set
3003c2c66affSColin Finck * (i.e. it sends it always),
3004c2c66affSColin Finck * so we probably don't want to do that either.
3005c2c66affSColin Finck */
FTP_SendType(ftp_session_t * lpwfs,DWORD dwType)3006c2c66affSColin Finck static BOOL FTP_SendType(ftp_session_t *lpwfs, DWORD dwType)
3007c2c66affSColin Finck {
3008c2c66affSColin Finck INT nResCode;
3009*e152f78aSwinesync WCHAR type[] = L"I";
3010c2c66affSColin Finck BOOL bSuccess = FALSE;
3011c2c66affSColin Finck
3012c2c66affSColin Finck TRACE("\n");
3013c2c66affSColin Finck if (dwType & INTERNET_FLAG_TRANSFER_ASCII)
3014c2c66affSColin Finck type[0] = 'A';
3015c2c66affSColin Finck
3016c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_TYPE, type, 0, 0, 0))
3017c2c66affSColin Finck goto lend;
3018c2c66affSColin Finck
3019c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext)/100;
3020c2c66affSColin Finck if (nResCode)
3021c2c66affSColin Finck {
3022c2c66affSColin Finck if (nResCode == 2)
3023c2c66affSColin Finck bSuccess = TRUE;
3024c2c66affSColin Finck else
3025c2c66affSColin Finck FTP_SetResponseError(nResCode);
3026c2c66affSColin Finck }
3027c2c66affSColin Finck
3028c2c66affSColin Finck lend:
3029c2c66affSColin Finck return bSuccess;
3030c2c66affSColin Finck }
3031c2c66affSColin Finck
3032c2c66affSColin Finck
3033c2c66affSColin Finck #if 0 /* FIXME: should probably be used for FtpGetFileSize */
3034c2c66affSColin Finck /***********************************************************************
3035c2c66affSColin Finck * FTP_GetFileSize (internal)
3036c2c66affSColin Finck *
3037c2c66affSColin Finck * Retrieves from the server the size of the given file
3038c2c66affSColin Finck *
3039c2c66affSColin Finck * RETURNS
3040c2c66affSColin Finck * TRUE on success
3041c2c66affSColin Finck * FALSE on failure
3042c2c66affSColin Finck *
3043c2c66affSColin Finck */
3044c2c66affSColin Finck static BOOL FTP_GetFileSize(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD *dwSize)
3045c2c66affSColin Finck {
3046c2c66affSColin Finck INT nResCode;
3047c2c66affSColin Finck BOOL bSuccess = FALSE;
3048c2c66affSColin Finck
3049c2c66affSColin Finck TRACE("\n");
3050c2c66affSColin Finck
3051c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_SIZE, lpszRemoteFile, 0, 0, 0))
3052c2c66affSColin Finck goto lend;
3053c2c66affSColin Finck
3054c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3055c2c66affSColin Finck if (nResCode)
3056c2c66affSColin Finck {
3057c2c66affSColin Finck if (nResCode == 213) {
3058c2c66affSColin Finck /* Now parses the output to get the actual file size */
3059c2c66affSColin Finck int i;
3060c2c66affSColin Finck LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
3061c2c66affSColin Finck
3062c2c66affSColin Finck for (i = 0; (lpszResponseBuffer[i] != ' ') && (lpszResponseBuffer[i] != '\0'); i++) ;
3063c2c66affSColin Finck if (lpszResponseBuffer[i] == '\0') return FALSE;
3064c2c66affSColin Finck *dwSize = atol(&(lpszResponseBuffer[i + 1]));
3065c2c66affSColin Finck
3066c2c66affSColin Finck bSuccess = TRUE;
3067c2c66affSColin Finck } else {
3068c2c66affSColin Finck FTP_SetResponseError(nResCode);
3069c2c66affSColin Finck }
3070c2c66affSColin Finck }
3071c2c66affSColin Finck
3072c2c66affSColin Finck lend:
3073c2c66affSColin Finck return bSuccess;
3074c2c66affSColin Finck }
3075c2c66affSColin Finck #endif
3076c2c66affSColin Finck
3077c2c66affSColin Finck
3078c2c66affSColin Finck /***********************************************************************
3079c2c66affSColin Finck * FTP_SendPort (internal)
3080c2c66affSColin Finck *
3081c2c66affSColin Finck * Tell server which port to use
3082c2c66affSColin Finck *
3083c2c66affSColin Finck * RETURNS
3084c2c66affSColin Finck * TRUE on success
3085c2c66affSColin Finck * FALSE on failure
3086c2c66affSColin Finck *
3087c2c66affSColin Finck */
FTP_SendPort(ftp_session_t * lpwfs)3088c2c66affSColin Finck static BOOL FTP_SendPort(ftp_session_t *lpwfs)
3089c2c66affSColin Finck {
3090c2c66affSColin Finck INT nResCode;
3091c2c66affSColin Finck WCHAR szIPAddress[64];
3092c2c66affSColin Finck BOOL bSuccess = FALSE;
3093c2c66affSColin Finck TRACE("\n");
3094c2c66affSColin Finck
3095*e152f78aSwinesync swprintf(szIPAddress, ARRAY_SIZE(szIPAddress), L"%d,%d,%d,%d,%d,%d",
3096c2c66affSColin Finck lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0x000000FF,
3097c2c66affSColin Finck (lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0x0000FF00)>>8,
3098c2c66affSColin Finck (lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0x00FF0000)>>16,
3099c2c66affSColin Finck (lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0xFF000000)>>24,
3100c2c66affSColin Finck lpwfs->lstnSocketAddress.sin_port & 0xFF,
3101c2c66affSColin Finck (lpwfs->lstnSocketAddress.sin_port & 0xFF00)>>8);
3102c2c66affSColin Finck
3103c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PORT, szIPAddress, 0, 0, 0))
3104c2c66affSColin Finck goto lend;
3105c2c66affSColin Finck
3106c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3107c2c66affSColin Finck if (nResCode)
3108c2c66affSColin Finck {
3109c2c66affSColin Finck if (nResCode == 200)
3110c2c66affSColin Finck bSuccess = TRUE;
3111c2c66affSColin Finck else
3112c2c66affSColin Finck FTP_SetResponseError(nResCode);
3113c2c66affSColin Finck }
3114c2c66affSColin Finck
3115c2c66affSColin Finck lend:
3116c2c66affSColin Finck return bSuccess;
3117c2c66affSColin Finck }
3118c2c66affSColin Finck
3119c2c66affSColin Finck
3120c2c66affSColin Finck /***********************************************************************
3121c2c66affSColin Finck * FTP_DoPassive (internal)
3122c2c66affSColin Finck *
3123c2c66affSColin Finck * Tell server that we want to do passive transfers
3124c2c66affSColin Finck * and connect data socket
3125c2c66affSColin Finck *
3126c2c66affSColin Finck * RETURNS
3127c2c66affSColin Finck * TRUE on success
3128c2c66affSColin Finck * FALSE on failure
3129c2c66affSColin Finck *
3130c2c66affSColin Finck */
FTP_DoPassive(ftp_session_t * lpwfs)3131c2c66affSColin Finck static BOOL FTP_DoPassive(ftp_session_t *lpwfs)
3132c2c66affSColin Finck {
3133c2c66affSColin Finck INT nResCode;
3134c2c66affSColin Finck BOOL bSuccess = FALSE;
3135c2c66affSColin Finck
3136c2c66affSColin Finck TRACE("\n");
3137c2c66affSColin Finck if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASV, NULL, 0, 0, 0))
3138c2c66affSColin Finck goto lend;
3139c2c66affSColin Finck
3140c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3141c2c66affSColin Finck if (nResCode)
3142c2c66affSColin Finck {
3143c2c66affSColin Finck if (nResCode == 227)
3144c2c66affSColin Finck {
3145c2c66affSColin Finck LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
3146c2c66affSColin Finck LPSTR p;
3147c2c66affSColin Finck int f[6];
3148c2c66affSColin Finck int i;
3149c2c66affSColin Finck char *pAddr, *pPort;
3150c2c66affSColin Finck INT nsocket = -1;
3151c2c66affSColin Finck struct sockaddr_in dataSocketAddress;
3152c2c66affSColin Finck
3153c2c66affSColin Finck p = lpszResponseBuffer+4; /* skip status code */
3154c2c66affSColin Finck while (*p != '\0' && (*p < '0' || *p > '9')) p++;
3155c2c66affSColin Finck
3156c2c66affSColin Finck if (*p == '\0')
3157c2c66affSColin Finck {
3158c2c66affSColin Finck ERR("no address found in response, aborting\n");
3159c2c66affSColin Finck goto lend;
3160c2c66affSColin Finck }
3161c2c66affSColin Finck
3162c2c66affSColin Finck if (sscanf(p, "%d,%d,%d,%d,%d,%d", &f[0], &f[1], &f[2], &f[3],
3163c2c66affSColin Finck &f[4], &f[5]) != 6)
3164c2c66affSColin Finck {
3165c2c66affSColin Finck ERR("unknown response address format '%s', aborting\n", p);
3166c2c66affSColin Finck goto lend;
3167c2c66affSColin Finck }
3168c2c66affSColin Finck for (i=0; i < 6; i++)
3169c2c66affSColin Finck f[i] = f[i] & 0xff;
3170c2c66affSColin Finck
3171c2c66affSColin Finck dataSocketAddress = lpwfs->socketAddress;
3172c2c66affSColin Finck pAddr = (char *)&(dataSocketAddress.sin_addr.S_un.S_addr);
3173c2c66affSColin Finck pPort = (char *)&(dataSocketAddress.sin_port);
3174c2c66affSColin Finck pAddr[0] = f[0];
3175c2c66affSColin Finck pAddr[1] = f[1];
3176c2c66affSColin Finck pAddr[2] = f[2];
3177c2c66affSColin Finck pAddr[3] = f[3];
3178c2c66affSColin Finck pPort[0] = f[4];
3179c2c66affSColin Finck pPort[1] = f[5];
3180c2c66affSColin Finck
3181c2c66affSColin Finck nsocket = socket(AF_INET,SOCK_STREAM,0);
3182c2c66affSColin Finck if (nsocket == -1)
3183c2c66affSColin Finck goto lend;
3184c2c66affSColin Finck
3185c2c66affSColin Finck if (connect(nsocket, (struct sockaddr *)&dataSocketAddress, sizeof(dataSocketAddress)))
3186c2c66affSColin Finck {
3187c2c66affSColin Finck ERR("can't connect passive FTP data port.\n");
3188c2c66affSColin Finck closesocket(nsocket);
3189c2c66affSColin Finck goto lend;
3190c2c66affSColin Finck }
3191c2c66affSColin Finck lpwfs->pasvSocket = nsocket;
3192c2c66affSColin Finck bSuccess = TRUE;
3193c2c66affSColin Finck }
3194c2c66affSColin Finck else
3195c2c66affSColin Finck FTP_SetResponseError(nResCode);
3196c2c66affSColin Finck }
3197c2c66affSColin Finck
3198c2c66affSColin Finck lend:
3199c2c66affSColin Finck return bSuccess;
3200c2c66affSColin Finck }
3201c2c66affSColin Finck
3202c2c66affSColin Finck
FTP_SendPortOrPasv(ftp_session_t * lpwfs)3203c2c66affSColin Finck static BOOL FTP_SendPortOrPasv(ftp_session_t *lpwfs)
3204c2c66affSColin Finck {
3205c2c66affSColin Finck if (lpwfs->hdr.dwFlags & INTERNET_FLAG_PASSIVE)
3206c2c66affSColin Finck {
3207c2c66affSColin Finck if (!FTP_DoPassive(lpwfs))
3208c2c66affSColin Finck return FALSE;
3209c2c66affSColin Finck }
3210c2c66affSColin Finck else
3211c2c66affSColin Finck {
3212c2c66affSColin Finck if (!FTP_SendPort(lpwfs))
3213c2c66affSColin Finck return FALSE;
3214c2c66affSColin Finck }
3215c2c66affSColin Finck return TRUE;
3216c2c66affSColin Finck }
3217c2c66affSColin Finck
3218c2c66affSColin Finck
3219c2c66affSColin Finck /***********************************************************************
3220c2c66affSColin Finck * FTP_GetDataSocket (internal)
3221c2c66affSColin Finck *
3222c2c66affSColin Finck * Either accepts an incoming data socket connection from the server
3223c2c66affSColin Finck * or just returns the already opened socket after a PASV command
3224c2c66affSColin Finck * in case of passive FTP.
3225c2c66affSColin Finck *
3226c2c66affSColin Finck *
3227c2c66affSColin Finck * RETURNS
3228c2c66affSColin Finck * TRUE on success
3229c2c66affSColin Finck * FALSE on failure
3230c2c66affSColin Finck *
3231c2c66affSColin Finck */
FTP_GetDataSocket(ftp_session_t * lpwfs,LPINT nDataSocket)3232c2c66affSColin Finck static BOOL FTP_GetDataSocket(ftp_session_t *lpwfs, LPINT nDataSocket)
3233c2c66affSColin Finck {
3234c2c66affSColin Finck struct sockaddr_in saddr;
3235c2c66affSColin Finck socklen_t addrlen = sizeof(saddr);
3236c2c66affSColin Finck
3237c2c66affSColin Finck TRACE("\n");
3238c2c66affSColin Finck if (lpwfs->hdr.dwFlags & INTERNET_FLAG_PASSIVE)
3239c2c66affSColin Finck {
3240c2c66affSColin Finck *nDataSocket = lpwfs->pasvSocket;
3241c2c66affSColin Finck lpwfs->pasvSocket = -1;
3242c2c66affSColin Finck }
3243c2c66affSColin Finck else
3244c2c66affSColin Finck {
3245c2c66affSColin Finck *nDataSocket = accept(lpwfs->lstnSocket, (struct sockaddr *) &saddr, &addrlen);
3246c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
3247c2c66affSColin Finck lpwfs->lstnSocket = -1;
3248c2c66affSColin Finck }
3249c2c66affSColin Finck return *nDataSocket != -1;
3250c2c66affSColin Finck }
3251c2c66affSColin Finck
3252c2c66affSColin Finck
3253c2c66affSColin Finck /***********************************************************************
3254c2c66affSColin Finck * FTP_SendData (internal)
3255c2c66affSColin Finck *
3256c2c66affSColin Finck * Send data to the server
3257c2c66affSColin Finck *
3258c2c66affSColin Finck * RETURNS
3259c2c66affSColin Finck * TRUE on success
3260c2c66affSColin Finck * FALSE on failure
3261c2c66affSColin Finck *
3262c2c66affSColin Finck */
FTP_SendData(ftp_session_t * lpwfs,INT nDataSocket,HANDLE hFile)3263c2c66affSColin Finck static BOOL FTP_SendData(ftp_session_t *lpwfs, INT nDataSocket, HANDLE hFile)
3264c2c66affSColin Finck {
3265c2c66affSColin Finck BY_HANDLE_FILE_INFORMATION fi;
3266c2c66affSColin Finck DWORD nBytesRead = 0;
3267c2c66affSColin Finck DWORD nBytesSent = 0;
3268c2c66affSColin Finck DWORD nTotalSent = 0;
3269c2c66affSColin Finck DWORD nBytesToSend, nLen;
3270c2c66affSColin Finck int nRC = 1;
3271c2c66affSColin Finck time_t s_long_time, e_long_time;
3272c2c66affSColin Finck LONG nSeconds;
3273c2c66affSColin Finck CHAR *lpszBuffer;
3274c2c66affSColin Finck
3275c2c66affSColin Finck TRACE("\n");
3276c2c66affSColin Finck lpszBuffer = heap_alloc_zero(sizeof(CHAR)*DATA_PACKET_SIZE);
3277c2c66affSColin Finck
3278c2c66affSColin Finck /* Get the size of the file. */
3279c2c66affSColin Finck GetFileInformationByHandle(hFile, &fi);
3280c2c66affSColin Finck time(&s_long_time);
3281c2c66affSColin Finck
3282c2c66affSColin Finck do
3283c2c66affSColin Finck {
3284c2c66affSColin Finck nBytesToSend = nBytesRead - nBytesSent;
3285c2c66affSColin Finck
3286c2c66affSColin Finck if (nBytesToSend <= 0)
3287c2c66affSColin Finck {
3288c2c66affSColin Finck /* Read data from file. */
3289c2c66affSColin Finck nBytesSent = 0;
3290c2c66affSColin Finck if (!ReadFile(hFile, lpszBuffer, DATA_PACKET_SIZE, &nBytesRead, 0))
3291c2c66affSColin Finck ERR("Failed reading from file\n");
3292c2c66affSColin Finck
3293c2c66affSColin Finck if (nBytesRead > 0)
3294c2c66affSColin Finck nBytesToSend = nBytesRead;
3295c2c66affSColin Finck else
3296c2c66affSColin Finck break;
3297c2c66affSColin Finck }
3298c2c66affSColin Finck
3299c2c66affSColin Finck nLen = DATA_PACKET_SIZE < nBytesToSend ?
3300c2c66affSColin Finck DATA_PACKET_SIZE : nBytesToSend;
3301c2c66affSColin Finck nRC = sock_send(nDataSocket, lpszBuffer, nLen, 0);
3302c2c66affSColin Finck
3303c2c66affSColin Finck if (nRC != -1)
3304c2c66affSColin Finck {
3305c2c66affSColin Finck nBytesSent += nRC;
3306c2c66affSColin Finck nTotalSent += nRC;
3307c2c66affSColin Finck }
3308c2c66affSColin Finck
3309c2c66affSColin Finck /* Do some computation to display the status. */
3310c2c66affSColin Finck time(&e_long_time);
3311c2c66affSColin Finck nSeconds = e_long_time - s_long_time;
3312c2c66affSColin Finck if( nSeconds / 60 > 0 )
3313c2c66affSColin Finck {
3314c2c66affSColin Finck TRACE( "%d bytes of %d bytes (%d%%) in %d min %d sec estimated remaining time %d sec\n",
3315c2c66affSColin Finck nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds / 60,
3316c2c66affSColin Finck nSeconds % 60, (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent );
3317c2c66affSColin Finck }
3318c2c66affSColin Finck else
3319c2c66affSColin Finck {
3320c2c66affSColin Finck TRACE( "%d bytes of %d bytes (%d%%) in %d sec estimated remaining time %d sec\n",
3321c2c66affSColin Finck nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds,
3322c2c66affSColin Finck (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent);
3323c2c66affSColin Finck }
3324c2c66affSColin Finck } while (nRC != -1);
3325c2c66affSColin Finck
3326c2c66affSColin Finck TRACE("file transfer complete!\n");
3327c2c66affSColin Finck
3328c2c66affSColin Finck heap_free(lpszBuffer);
3329c2c66affSColin Finck return nTotalSent;
3330c2c66affSColin Finck }
3331c2c66affSColin Finck
3332c2c66affSColin Finck
3333c2c66affSColin Finck /***********************************************************************
3334c2c66affSColin Finck * FTP_SendRetrieve (internal)
3335c2c66affSColin Finck *
3336c2c66affSColin Finck * Send request to retrieve a file
3337c2c66affSColin Finck *
3338c2c66affSColin Finck * RETURNS
3339c2c66affSColin Finck * Number of bytes to be received on success
3340c2c66affSColin Finck * 0 on failure
3341c2c66affSColin Finck *
3342c2c66affSColin Finck */
FTP_SendRetrieve(ftp_session_t * lpwfs,LPCWSTR lpszRemoteFile,DWORD dwType)3343c2c66affSColin Finck static BOOL FTP_SendRetrieve(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
3344c2c66affSColin Finck {
3345c2c66affSColin Finck INT nResCode;
3346c2c66affSColin Finck BOOL ret;
3347c2c66affSColin Finck
3348c2c66affSColin Finck TRACE("\n");
3349c2c66affSColin Finck if (!(ret = FTP_InitListenSocket(lpwfs)))
3350c2c66affSColin Finck goto lend;
3351c2c66affSColin Finck
3352c2c66affSColin Finck if (!(ret = FTP_SendType(lpwfs, dwType)))
3353c2c66affSColin Finck goto lend;
3354c2c66affSColin Finck
3355c2c66affSColin Finck if (!(ret = FTP_SendPortOrPasv(lpwfs)))
3356c2c66affSColin Finck goto lend;
3357c2c66affSColin Finck
3358c2c66affSColin Finck if (!(ret = FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0)))
3359c2c66affSColin Finck goto lend;
3360c2c66affSColin Finck
3361c2c66affSColin Finck nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3362c2c66affSColin Finck if ((nResCode != 125) && (nResCode != 150)) {
3363c2c66affSColin Finck /* That means that we got an error getting the file. */
3364c2c66affSColin Finck FTP_SetResponseError(nResCode);
3365c2c66affSColin Finck ret = FALSE;
3366c2c66affSColin Finck }
3367c2c66affSColin Finck
3368c2c66affSColin Finck lend:
3369c2c66affSColin Finck if (!ret && lpwfs->lstnSocket != -1)
3370c2c66affSColin Finck {
3371c2c66affSColin Finck closesocket(lpwfs->lstnSocket);
3372c2c66affSColin Finck lpwfs->lstnSocket = -1;
3373c2c66affSColin Finck }
3374c2c66affSColin Finck
3375c2c66affSColin Finck return ret;
3376c2c66affSColin Finck }
3377c2c66affSColin Finck
3378c2c66affSColin Finck
3379c2c66affSColin Finck /***********************************************************************
3380c2c66affSColin Finck * FTP_RetrieveData (internal)
3381c2c66affSColin Finck *
3382c2c66affSColin Finck * Retrieve data from server
3383c2c66affSColin Finck *
3384c2c66affSColin Finck * RETURNS
3385c2c66affSColin Finck * TRUE on success
3386c2c66affSColin Finck * FALSE on failure
3387c2c66affSColin Finck *
3388c2c66affSColin Finck */
FTP_RetrieveFileData(ftp_session_t * lpwfs,INT nDataSocket,HANDLE hFile)3389c2c66affSColin Finck static BOOL FTP_RetrieveFileData(ftp_session_t *lpwfs, INT nDataSocket, HANDLE hFile)
3390c2c66affSColin Finck {
3391c2c66affSColin Finck DWORD nBytesWritten;
3392c2c66affSColin Finck INT nRC = 0;
3393c2c66affSColin Finck CHAR *lpszBuffer;
3394c2c66affSColin Finck
3395c2c66affSColin Finck TRACE("\n");
3396c2c66affSColin Finck
3397c2c66affSColin Finck lpszBuffer = heap_alloc_zero(sizeof(CHAR)*DATA_PACKET_SIZE);
3398c2c66affSColin Finck if (NULL == lpszBuffer)
3399c2c66affSColin Finck {
3400c2c66affSColin Finck INTERNET_SetLastError(ERROR_OUTOFMEMORY);
3401c2c66affSColin Finck return FALSE;
3402c2c66affSColin Finck }
3403c2c66affSColin Finck
3404c2c66affSColin Finck while (nRC != -1)
3405c2c66affSColin Finck {
3406c2c66affSColin Finck nRC = sock_recv(nDataSocket, lpszBuffer, DATA_PACKET_SIZE, 0);
3407c2c66affSColin Finck if (nRC != -1)
3408c2c66affSColin Finck {
3409c2c66affSColin Finck /* other side closed socket. */
3410c2c66affSColin Finck if (nRC == 0)
3411c2c66affSColin Finck goto recv_end;
3412c2c66affSColin Finck WriteFile(hFile, lpszBuffer, nRC, &nBytesWritten, NULL);
3413c2c66affSColin Finck }
3414c2c66affSColin Finck }
3415c2c66affSColin Finck
3416c2c66affSColin Finck TRACE("Data transfer complete\n");
3417c2c66affSColin Finck
3418c2c66affSColin Finck recv_end:
3419c2c66affSColin Finck heap_free(lpszBuffer);
3420c2c66affSColin Finck return (nRC != -1);
3421c2c66affSColin Finck }
3422c2c66affSColin Finck
3423c2c66affSColin Finck /***********************************************************************
3424c2c66affSColin Finck * FTPFINDNEXT_Destroy (internal)
3425c2c66affSColin Finck *
3426c2c66affSColin Finck * Deallocate session handle
3427c2c66affSColin Finck */
FTPFINDNEXT_Destroy(object_header_t * hdr)3428c2c66affSColin Finck static void FTPFINDNEXT_Destroy(object_header_t *hdr)
3429c2c66affSColin Finck {
3430c2c66affSColin Finck LPWININETFTPFINDNEXTW lpwfn = (LPWININETFTPFINDNEXTW) hdr;
3431c2c66affSColin Finck DWORD i;
3432c2c66affSColin Finck
3433c2c66affSColin Finck TRACE("\n");
3434c2c66affSColin Finck
3435c2c66affSColin Finck WININET_Release(&lpwfn->lpFtpSession->hdr);
3436c2c66affSColin Finck
3437c2c66affSColin Finck for (i = 0; i < lpwfn->size; i++)
3438c2c66affSColin Finck {
3439c2c66affSColin Finck heap_free(lpwfn->lpafp[i].lpszName);
3440c2c66affSColin Finck }
3441c2c66affSColin Finck heap_free(lpwfn->lpafp);
3442c2c66affSColin Finck }
3443c2c66affSColin Finck
FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW * find,LPVOID data)3444c2c66affSColin Finck static DWORD FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data)
3445c2c66affSColin Finck {
3446c2c66affSColin Finck WIN32_FIND_DATAW *find_data = data;
3447c2c66affSColin Finck DWORD res = ERROR_SUCCESS;
3448c2c66affSColin Finck
3449c2c66affSColin Finck TRACE("index(%d) size(%d)\n", find->index, find->size);
3450c2c66affSColin Finck
3451c2c66affSColin Finck ZeroMemory(find_data, sizeof(WIN32_FIND_DATAW));
3452c2c66affSColin Finck
3453c2c66affSColin Finck if (find->index < find->size) {
3454c2c66affSColin Finck FTP_ConvertFileProp(&find->lpafp[find->index], find_data);
3455c2c66affSColin Finck find->index++;
3456c2c66affSColin Finck
3457c2c66affSColin Finck TRACE("Name: %s\nSize: %d\n", debugstr_w(find_data->cFileName), find_data->nFileSizeLow);
3458c2c66affSColin Finck }else {
3459c2c66affSColin Finck res = ERROR_NO_MORE_FILES;
3460c2c66affSColin Finck }
3461c2c66affSColin Finck
3462c2c66affSColin Finck if (find->hdr.dwFlags & INTERNET_FLAG_ASYNC)
3463c2c66affSColin Finck {
3464c2c66affSColin Finck INTERNET_ASYNC_RESULT iar;
3465c2c66affSColin Finck
3466c2c66affSColin Finck iar.dwResult = (res == ERROR_SUCCESS);
3467c2c66affSColin Finck iar.dwError = res;
3468c2c66affSColin Finck
3469c2c66affSColin Finck INTERNET_SendCallback(&find->hdr, find->hdr.dwContext,
3470c2c66affSColin Finck INTERNET_STATUS_REQUEST_COMPLETE, &iar,
3471c2c66affSColin Finck sizeof(INTERNET_ASYNC_RESULT));
3472c2c66affSColin Finck }
3473c2c66affSColin Finck
3474c2c66affSColin Finck return res;
3475c2c66affSColin Finck }
3476c2c66affSColin Finck
3477c2c66affSColin Finck typedef struct {
3478c2c66affSColin Finck task_header_t hdr;
3479c2c66affSColin Finck WIN32_FIND_DATAW *find_data;
3480c2c66affSColin Finck } find_next_task_t;
3481c2c66affSColin Finck
FTPFINDNEXT_AsyncFindNextFileProc(task_header_t * hdr)3482c2c66affSColin Finck static void FTPFINDNEXT_AsyncFindNextFileProc(task_header_t *hdr)
3483c2c66affSColin Finck {
3484c2c66affSColin Finck find_next_task_t *task = (find_next_task_t*)hdr;
3485c2c66affSColin Finck
3486c2c66affSColin Finck FTPFINDNEXT_FindNextFileProc((WININETFTPFINDNEXTW*)task->hdr.hdr, task->find_data);
3487c2c66affSColin Finck }
3488c2c66affSColin Finck
FTPFINDNEXT_QueryOption(object_header_t * hdr,DWORD option,void * buffer,DWORD * size,BOOL unicode)3489c2c66affSColin Finck static DWORD FTPFINDNEXT_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
3490c2c66affSColin Finck {
3491c2c66affSColin Finck switch(option) {
3492c2c66affSColin Finck case INTERNET_OPTION_HANDLE_TYPE:
3493c2c66affSColin Finck TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
3494c2c66affSColin Finck
3495c2c66affSColin Finck if (*size < sizeof(ULONG))
3496c2c66affSColin Finck return ERROR_INSUFFICIENT_BUFFER;
3497c2c66affSColin Finck
3498c2c66affSColin Finck *size = sizeof(DWORD);
3499c2c66affSColin Finck *(DWORD*)buffer = INTERNET_HANDLE_TYPE_FTP_FIND;
3500c2c66affSColin Finck return ERROR_SUCCESS;
3501c2c66affSColin Finck }
3502c2c66affSColin Finck
3503c2c66affSColin Finck return INET_QueryOption(hdr, option, buffer, size, unicode);
3504c2c66affSColin Finck }
3505c2c66affSColin Finck
FTPFINDNEXT_FindNextFileW(object_header_t * hdr,void * data)3506c2c66affSColin Finck static DWORD FTPFINDNEXT_FindNextFileW(object_header_t *hdr, void *data)
3507c2c66affSColin Finck {
3508c2c66affSColin Finck WININETFTPFINDNEXTW *find = (WININETFTPFINDNEXTW*)hdr;
3509c2c66affSColin Finck
3510c2c66affSColin Finck if (find->lpFtpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
3511c2c66affSColin Finck {
3512c2c66affSColin Finck find_next_task_t *task;
3513c2c66affSColin Finck
3514c2c66affSColin Finck task = alloc_async_task(&find->hdr, FTPFINDNEXT_AsyncFindNextFileProc, sizeof(*task));
3515c2c66affSColin Finck task->find_data = data;
3516c2c66affSColin Finck
3517c2c66affSColin Finck INTERNET_AsyncCall(&task->hdr);
3518c2c66affSColin Finck return ERROR_SUCCESS;
3519c2c66affSColin Finck }
3520c2c66affSColin Finck
3521c2c66affSColin Finck return FTPFINDNEXT_FindNextFileProc(find, data);
3522c2c66affSColin Finck }
3523c2c66affSColin Finck
3524c2c66affSColin Finck static const object_vtbl_t FTPFINDNEXTVtbl = {
3525c2c66affSColin Finck FTPFINDNEXT_Destroy,
3526c2c66affSColin Finck NULL,
3527c2c66affSColin Finck FTPFINDNEXT_QueryOption,
3528c2c66affSColin Finck INET_SetOption,
3529c2c66affSColin Finck NULL,
3530c2c66affSColin Finck NULL,
3531c2c66affSColin Finck NULL,
3532c2c66affSColin Finck FTPFINDNEXT_FindNextFileW
3533c2c66affSColin Finck };
3534c2c66affSColin Finck
3535c2c66affSColin Finck /***********************************************************************
3536c2c66affSColin Finck * FTP_ReceiveFileList (internal)
3537c2c66affSColin Finck *
3538c2c66affSColin Finck * Read file list from server
3539c2c66affSColin Finck *
3540c2c66affSColin Finck * RETURNS
3541c2c66affSColin Finck * Handle to file list on success
3542c2c66affSColin Finck * NULL on failure
3543c2c66affSColin Finck *
3544c2c66affSColin Finck */
FTP_ReceiveFileList(ftp_session_t * lpwfs,INT nSocket,LPCWSTR lpszSearchFile,LPWIN32_FIND_DATAW lpFindFileData,DWORD_PTR dwContext)3545c2c66affSColin Finck static HINTERNET FTP_ReceiveFileList(ftp_session_t *lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
3546c2c66affSColin Finck LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext)
3547c2c66affSColin Finck {
3548c2c66affSColin Finck DWORD dwSize = 0;
3549c2c66affSColin Finck LPFILEPROPERTIESW lpafp = NULL;
3550c2c66affSColin Finck LPWININETFTPFINDNEXTW lpwfn = NULL;
3551c2c66affSColin Finck
3552c2c66affSColin Finck TRACE("(%p,%d,%s,%p,%08lx)\n", lpwfs, nSocket, debugstr_w(lpszSearchFile), lpFindFileData, dwContext);
3553c2c66affSColin Finck
3554c2c66affSColin Finck if (FTP_ParseDirectory(lpwfs, nSocket, lpszSearchFile, &lpafp, &dwSize))
3555c2c66affSColin Finck {
3556c2c66affSColin Finck if(lpFindFileData)
3557c2c66affSColin Finck FTP_ConvertFileProp(lpafp, lpFindFileData);
3558c2c66affSColin Finck
3559c2c66affSColin Finck lpwfn = alloc_object(&lpwfs->hdr, &FTPFINDNEXTVtbl, sizeof(WININETFTPFINDNEXTW));
3560c2c66affSColin Finck if (lpwfn)
3561c2c66affSColin Finck {
3562c2c66affSColin Finck lpwfn->hdr.htype = WH_HFTPFINDNEXT;
3563c2c66affSColin Finck lpwfn->hdr.dwContext = dwContext;
3564c2c66affSColin Finck lpwfn->index = 1; /* Next index is 1 since we return index 0 */
3565c2c66affSColin Finck lpwfn->size = dwSize;
3566c2c66affSColin Finck lpwfn->lpafp = lpafp;
3567c2c66affSColin Finck
3568c2c66affSColin Finck WININET_AddRef( &lpwfs->hdr );
3569c2c66affSColin Finck lpwfn->lpFtpSession = lpwfs;
3570c2c66affSColin Finck list_add_head( &lpwfs->hdr.children, &lpwfn->hdr.entry );
3571c2c66affSColin Finck }
3572c2c66affSColin Finck }
3573c2c66affSColin Finck
3574c2c66affSColin Finck TRACE("Matched %d files\n", dwSize);
3575c2c66affSColin Finck return lpwfn ? lpwfn->hdr.hInternet : NULL;
3576c2c66affSColin Finck }
3577c2c66affSColin Finck
3578c2c66affSColin Finck
3579c2c66affSColin Finck /***********************************************************************
3580c2c66affSColin Finck * FTP_ConvertFileProp (internal)
3581c2c66affSColin Finck *
3582c2c66affSColin Finck * Converts FILEPROPERTIESW struct to WIN32_FIND_DATAA
3583c2c66affSColin Finck *
3584c2c66affSColin Finck * RETURNS
3585c2c66affSColin Finck * TRUE on success
3586c2c66affSColin Finck * FALSE on failure
3587c2c66affSColin Finck *
3588c2c66affSColin Finck */
FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp,LPWIN32_FIND_DATAW lpFindFileData)3589c2c66affSColin Finck static BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData)
3590c2c66affSColin Finck {
3591c2c66affSColin Finck BOOL bSuccess = FALSE;
3592c2c66affSColin Finck
3593c2c66affSColin Finck ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAW));
3594c2c66affSColin Finck
3595c2c66affSColin Finck if (lpafp)
3596c2c66affSColin Finck {
3597c2c66affSColin Finck SystemTimeToFileTime( &lpafp->tmLastModified, &lpFindFileData->ftLastAccessTime );
3598c2c66affSColin Finck lpFindFileData->ftLastWriteTime = lpFindFileData->ftLastAccessTime;
3599c2c66affSColin Finck lpFindFileData->ftCreationTime = lpFindFileData->ftLastAccessTime;
3600c2c66affSColin Finck
3601c2c66affSColin Finck /* Not all fields are filled in */
3602c2c66affSColin Finck lpFindFileData->nFileSizeHigh = 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */
3603c2c66affSColin Finck lpFindFileData->nFileSizeLow = lpafp->nSize;
3604c2c66affSColin Finck
3605c2c66affSColin Finck if (lpafp->bIsDirectory)
3606c2c66affSColin Finck lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
3607c2c66affSColin Finck
3608c2c66affSColin Finck if (lpafp->lpszName)
3609c2c66affSColin Finck lstrcpynW(lpFindFileData->cFileName, lpafp->lpszName, MAX_PATH);
3610c2c66affSColin Finck
3611c2c66affSColin Finck bSuccess = TRUE;
3612c2c66affSColin Finck }
3613c2c66affSColin Finck
3614c2c66affSColin Finck return bSuccess;
3615c2c66affSColin Finck }
3616c2c66affSColin Finck
3617c2c66affSColin Finck /***********************************************************************
3618c2c66affSColin Finck * FTP_ParseNextFile (internal)
3619c2c66affSColin Finck *
3620c2c66affSColin Finck * Parse the next line in file listing
3621c2c66affSColin Finck *
3622c2c66affSColin Finck * RETURNS
3623c2c66affSColin Finck * TRUE on success
3624c2c66affSColin Finck * FALSE on failure
3625c2c66affSColin Finck */
FTP_ParseNextFile(INT nSocket,LPCWSTR lpszSearchFile,LPFILEPROPERTIESW lpfp)3626c2c66affSColin Finck static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERTIESW lpfp)
3627c2c66affSColin Finck {
3628c2c66affSColin Finck static const char szSpace[] = " \t";
3629c2c66affSColin Finck DWORD nBufLen;
3630c2c66affSColin Finck char *pszLine;
3631c2c66affSColin Finck char *pszToken;
3632c2c66affSColin Finck char *pszTmp;
3633c2c66affSColin Finck BOOL found = FALSE;
3634c2c66affSColin Finck int i;
3635c2c66affSColin Finck
3636c2c66affSColin Finck lpfp->lpszName = NULL;
3637c2c66affSColin Finck do {
3638c2c66affSColin Finck if(!(pszLine = FTP_GetNextLine(nSocket, &nBufLen)))
3639c2c66affSColin Finck return FALSE;
3640c2c66affSColin Finck
3641c2c66affSColin Finck pszToken = strtok(pszLine, szSpace);
3642c2c66affSColin Finck /* ls format
3643c2c66affSColin Finck * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
3644c2c66affSColin Finck *
3645c2c66affSColin Finck * For instance:
3646c2c66affSColin Finck * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
3647c2c66affSColin Finck */
3648c2c66affSColin Finck if(!isdigit(pszToken[0]) && 10 == strlen(pszToken)) {
3649c2c66affSColin Finck if(!FTP_ParsePermission(pszToken, lpfp))
3650c2c66affSColin Finck lpfp->bIsDirectory = FALSE;
3651c2c66affSColin Finck for(i=0; i<=3; i++) {
3652c2c66affSColin Finck if(!(pszToken = strtok(NULL, szSpace)))
3653c2c66affSColin Finck break;
3654c2c66affSColin Finck }
3655c2c66affSColin Finck if(!pszToken) continue;
3656c2c66affSColin Finck if(lpfp->bIsDirectory) {
3657c2c66affSColin Finck TRACE("Is directory\n");
3658c2c66affSColin Finck lpfp->nSize = 0;
3659c2c66affSColin Finck }
3660c2c66affSColin Finck else {
3661c2c66affSColin Finck TRACE("Size: %s\n", pszToken);
3662c2c66affSColin Finck lpfp->nSize = atol(pszToken);
3663c2c66affSColin Finck }
3664c2c66affSColin Finck
3665c2c66affSColin Finck lpfp->tmLastModified.wSecond = 0;
3666c2c66affSColin Finck lpfp->tmLastModified.wMinute = 0;
3667c2c66affSColin Finck lpfp->tmLastModified.wHour = 0;
3668c2c66affSColin Finck lpfp->tmLastModified.wDay = 0;
3669c2c66affSColin Finck lpfp->tmLastModified.wMonth = 0;
3670c2c66affSColin Finck lpfp->tmLastModified.wYear = 0;
3671c2c66affSColin Finck
3672c2c66affSColin Finck /* Determine month */
3673c2c66affSColin Finck pszToken = strtok(NULL, szSpace);
3674c2c66affSColin Finck if(!pszToken) continue;
3675c2c66affSColin Finck if(strlen(pszToken) >= 3) {
3676c2c66affSColin Finck pszToken[3] = 0;
3677c2c66affSColin Finck if((pszTmp = StrStrIA(szMonths, pszToken)))
3678c2c66affSColin Finck lpfp->tmLastModified.wMonth = ((pszTmp - szMonths) / 3)+1;
3679c2c66affSColin Finck }
3680c2c66affSColin Finck /* Determine day */
3681c2c66affSColin Finck pszToken = strtok(NULL, szSpace);
3682c2c66affSColin Finck if(!pszToken) continue;
3683c2c66affSColin Finck lpfp->tmLastModified.wDay = atoi(pszToken);
3684c2c66affSColin Finck /* Determine time or year */
3685c2c66affSColin Finck pszToken = strtok(NULL, szSpace);
3686c2c66affSColin Finck if(!pszToken) continue;
3687c2c66affSColin Finck if((pszTmp = strchr(pszToken, ':'))) {
3688c2c66affSColin Finck SYSTEMTIME curr_time;
3689c2c66affSColin Finck *pszTmp = 0;
3690c2c66affSColin Finck pszTmp++;
3691c2c66affSColin Finck lpfp->tmLastModified.wMinute = atoi(pszTmp);
3692c2c66affSColin Finck lpfp->tmLastModified.wHour = atoi(pszToken);
3693c2c66affSColin Finck GetLocalTime( &curr_time );
3694c2c66affSColin Finck lpfp->tmLastModified.wYear = curr_time.wYear;
3695c2c66affSColin Finck }
3696c2c66affSColin Finck else {
3697c2c66affSColin Finck lpfp->tmLastModified.wYear = atoi(pszToken);
3698c2c66affSColin Finck lpfp->tmLastModified.wHour = 12;
3699c2c66affSColin Finck }
3700c2c66affSColin Finck TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n",
3701c2c66affSColin Finck lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond,
3702c2c66affSColin Finck lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay);
3703c2c66affSColin Finck
3704c2c66affSColin Finck pszToken = strtok(NULL, szSpace);
3705c2c66affSColin Finck if(!pszToken) continue;
3706c2c66affSColin Finck lpfp->lpszName = heap_strdupAtoW(pszToken);
3707c2c66affSColin Finck TRACE("File: %s\n", debugstr_w(lpfp->lpszName));
3708c2c66affSColin Finck }
3709c2c66affSColin Finck /* NT way of parsing ... :
3710c2c66affSColin Finck
3711c2c66affSColin Finck 07-13-03 08:55PM <DIR> sakpatch
3712c2c66affSColin Finck 05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
3713c2c66affSColin Finck */
3714c2c66affSColin Finck else if(isdigit(pszToken[0]) && 8 == strlen(pszToken)) {
3715c2c66affSColin Finck int mon, mday, year, hour, min;
3716c2c66affSColin Finck lpfp->permissions = 0xFFFF; /* No idea, put full permission :-) */
3717c2c66affSColin Finck
3718c2c66affSColin Finck sscanf(pszToken, "%d-%d-%d", &mon, &mday, &year);
3719c2c66affSColin Finck lpfp->tmLastModified.wDay = mday;
3720c2c66affSColin Finck lpfp->tmLastModified.wMonth = mon;
3721c2c66affSColin Finck lpfp->tmLastModified.wYear = year;
3722c2c66affSColin Finck
3723c2c66affSColin Finck /* Hacky and bad Y2K protection :-) */
3724c2c66affSColin Finck if (lpfp->tmLastModified.wYear < 70) lpfp->tmLastModified.wYear += 2000;
3725c2c66affSColin Finck
3726c2c66affSColin Finck pszToken = strtok(NULL, szSpace);
3727c2c66affSColin Finck if(!pszToken) continue;
3728c2c66affSColin Finck sscanf(pszToken, "%d:%d", &hour, &min);
3729c2c66affSColin Finck lpfp->tmLastModified.wHour = hour;
3730c2c66affSColin Finck lpfp->tmLastModified.wMinute = min;
3731c2c66affSColin Finck if((pszToken[5] == 'P') && (pszToken[6] == 'M')) {
3732c2c66affSColin Finck lpfp->tmLastModified.wHour += 12;
3733c2c66affSColin Finck }
3734c2c66affSColin Finck lpfp->tmLastModified.wSecond = 0;
3735c2c66affSColin Finck
3736c2c66affSColin Finck TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n",
3737c2c66affSColin Finck lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond,
3738c2c66affSColin Finck lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay);
3739c2c66affSColin Finck
3740c2c66affSColin Finck pszToken = strtok(NULL, szSpace);
3741c2c66affSColin Finck if(!pszToken) continue;
374294937754Swinesync if(!stricmp(pszToken, "<DIR>")) {
3743c2c66affSColin Finck lpfp->bIsDirectory = TRUE;
3744c2c66affSColin Finck lpfp->nSize = 0;
3745c2c66affSColin Finck TRACE("Is directory\n");
3746c2c66affSColin Finck }
3747c2c66affSColin Finck else {
3748c2c66affSColin Finck lpfp->bIsDirectory = FALSE;
3749c2c66affSColin Finck lpfp->nSize = atol(pszToken);
3750c2c66affSColin Finck TRACE("Size: %d\n", lpfp->nSize);
3751c2c66affSColin Finck }
3752c2c66affSColin Finck
3753c2c66affSColin Finck pszToken = strtok(NULL, szSpace);
3754c2c66affSColin Finck if(!pszToken) continue;
3755c2c66affSColin Finck lpfp->lpszName = heap_strdupAtoW(pszToken);
3756c2c66affSColin Finck TRACE("Name: %s\n", debugstr_w(lpfp->lpszName));
3757c2c66affSColin Finck }
3758c2c66affSColin Finck /* EPLF format - http://cr.yp.to/ftp/list/eplf.html */
3759c2c66affSColin Finck else if(pszToken[0] == '+') {
3760c2c66affSColin Finck FIXME("EPLF Format not implemented\n");
3761c2c66affSColin Finck }
3762c2c66affSColin Finck
3763c2c66affSColin Finck if(lpfp->lpszName) {
3764c2c66affSColin Finck if((lpszSearchFile == NULL) ||
3765c2c66affSColin Finck (PathMatchSpecW(lpfp->lpszName, lpszSearchFile))) {
3766c2c66affSColin Finck found = TRUE;
3767c2c66affSColin Finck TRACE("Matched: %s\n", debugstr_w(lpfp->lpszName));
3768c2c66affSColin Finck }
3769c2c66affSColin Finck else {
3770c2c66affSColin Finck heap_free(lpfp->lpszName);
3771c2c66affSColin Finck lpfp->lpszName = NULL;
3772c2c66affSColin Finck }
3773c2c66affSColin Finck }
3774c2c66affSColin Finck } while(!found);
3775c2c66affSColin Finck return TRUE;
3776c2c66affSColin Finck }
3777c2c66affSColin Finck
3778c2c66affSColin Finck /***********************************************************************
3779c2c66affSColin Finck * FTP_ParseDirectory (internal)
3780c2c66affSColin Finck *
3781c2c66affSColin Finck * Parse string of directory information
3782c2c66affSColin Finck *
3783c2c66affSColin Finck * RETURNS
3784c2c66affSColin Finck * TRUE on success
3785c2c66affSColin Finck * FALSE on failure
3786c2c66affSColin Finck */
FTP_ParseDirectory(ftp_session_t * lpwfs,INT nSocket,LPCWSTR lpszSearchFile,LPFILEPROPERTIESW * lpafp,LPDWORD dwfp)3787c2c66affSColin Finck static BOOL FTP_ParseDirectory(ftp_session_t *lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
3788c2c66affSColin Finck LPFILEPROPERTIESW *lpafp, LPDWORD dwfp)
3789c2c66affSColin Finck {
3790c2c66affSColin Finck BOOL bSuccess = TRUE;
3791c2c66affSColin Finck INT sizeFilePropArray = 500;/*20; */
3792c2c66affSColin Finck INT indexFilePropArray = -1;
3793c2c66affSColin Finck
3794c2c66affSColin Finck TRACE("\n");
3795c2c66affSColin Finck
3796c2c66affSColin Finck /* Allocate initial file properties array */
3797c2c66affSColin Finck *lpafp = heap_alloc_zero(sizeof(FILEPROPERTIESW)*(sizeFilePropArray));
3798c2c66affSColin Finck if (!*lpafp)
3799c2c66affSColin Finck return FALSE;
3800c2c66affSColin Finck
3801c2c66affSColin Finck do {
3802c2c66affSColin Finck if (indexFilePropArray+1 >= sizeFilePropArray)
3803c2c66affSColin Finck {
3804c2c66affSColin Finck LPFILEPROPERTIESW tmpafp;
3805c2c66affSColin Finck
3806c2c66affSColin Finck sizeFilePropArray *= 2;
3807c2c66affSColin Finck tmpafp = heap_realloc_zero(*lpafp, sizeof(FILEPROPERTIESW)*sizeFilePropArray);
3808c2c66affSColin Finck if (NULL == tmpafp)
3809c2c66affSColin Finck {
3810c2c66affSColin Finck bSuccess = FALSE;
3811c2c66affSColin Finck break;
3812c2c66affSColin Finck }
3813c2c66affSColin Finck
3814c2c66affSColin Finck *lpafp = tmpafp;
3815c2c66affSColin Finck }
3816c2c66affSColin Finck indexFilePropArray++;
3817c2c66affSColin Finck } while (FTP_ParseNextFile(nSocket, lpszSearchFile, &(*lpafp)[indexFilePropArray]));
3818c2c66affSColin Finck
3819c2c66affSColin Finck if (bSuccess && indexFilePropArray)
3820c2c66affSColin Finck {
3821c2c66affSColin Finck if (indexFilePropArray < sizeFilePropArray - 1)
3822c2c66affSColin Finck {
3823c2c66affSColin Finck LPFILEPROPERTIESW tmpafp;
3824c2c66affSColin Finck
3825c2c66affSColin Finck tmpafp = heap_realloc(*lpafp, sizeof(FILEPROPERTIESW)*indexFilePropArray);
3826c2c66affSColin Finck if (NULL != tmpafp)
3827c2c66affSColin Finck *lpafp = tmpafp;
3828c2c66affSColin Finck }
3829c2c66affSColin Finck *dwfp = indexFilePropArray;
3830c2c66affSColin Finck }
3831c2c66affSColin Finck else
3832c2c66affSColin Finck {
3833c2c66affSColin Finck heap_free(*lpafp);
3834c2c66affSColin Finck INTERNET_SetLastError(ERROR_NO_MORE_FILES);
3835c2c66affSColin Finck bSuccess = FALSE;
3836c2c66affSColin Finck }
3837c2c66affSColin Finck
3838c2c66affSColin Finck return bSuccess;
3839c2c66affSColin Finck }
3840c2c66affSColin Finck
3841c2c66affSColin Finck
3842c2c66affSColin Finck /***********************************************************************
3843c2c66affSColin Finck * FTP_ParsePermission (internal)
3844c2c66affSColin Finck *
3845c2c66affSColin Finck * Parse permission string of directory information
3846c2c66affSColin Finck *
3847c2c66affSColin Finck * RETURNS
3848c2c66affSColin Finck * TRUE on success
3849c2c66affSColin Finck * FALSE on failure
3850c2c66affSColin Finck *
3851c2c66affSColin Finck */
FTP_ParsePermission(LPCSTR lpszPermission,LPFILEPROPERTIESW lpfp)3852c2c66affSColin Finck static BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESW lpfp)
3853c2c66affSColin Finck {
3854c2c66affSColin Finck BOOL bSuccess = TRUE;
3855c2c66affSColin Finck unsigned short nPermission = 0;
3856c2c66affSColin Finck INT nPos = 1;
3857c2c66affSColin Finck INT nLast = 9;
3858c2c66affSColin Finck
3859c2c66affSColin Finck TRACE("\n");
3860c2c66affSColin Finck if ((*lpszPermission != 'd') && (*lpszPermission != '-') && (*lpszPermission != 'l'))
3861c2c66affSColin Finck {
3862c2c66affSColin Finck bSuccess = FALSE;
3863c2c66affSColin Finck return bSuccess;
3864c2c66affSColin Finck }
3865c2c66affSColin Finck
3866c2c66affSColin Finck lpfp->bIsDirectory = (*lpszPermission == 'd');
3867c2c66affSColin Finck do
3868c2c66affSColin Finck {
3869c2c66affSColin Finck switch (nPos)
3870c2c66affSColin Finck {
3871c2c66affSColin Finck case 1:
3872c2c66affSColin Finck nPermission |= (*(lpszPermission+1) == 'r' ? 1 : 0) << 8;
3873c2c66affSColin Finck break;
3874c2c66affSColin Finck case 2:
3875c2c66affSColin Finck nPermission |= (*(lpszPermission+2) == 'w' ? 1 : 0) << 7;
3876c2c66affSColin Finck break;
3877c2c66affSColin Finck case 3:
3878c2c66affSColin Finck nPermission |= (*(lpszPermission+3) == 'x' ? 1 : 0) << 6;
3879c2c66affSColin Finck break;
3880c2c66affSColin Finck case 4:
3881c2c66affSColin Finck nPermission |= (*(lpszPermission+4) == 'r' ? 1 : 0) << 5;
3882c2c66affSColin Finck break;
3883c2c66affSColin Finck case 5:
3884c2c66affSColin Finck nPermission |= (*(lpszPermission+5) == 'w' ? 1 : 0) << 4;
3885c2c66affSColin Finck break;
3886c2c66affSColin Finck case 6:
3887c2c66affSColin Finck nPermission |= (*(lpszPermission+6) == 'x' ? 1 : 0) << 3;
3888c2c66affSColin Finck break;
3889c2c66affSColin Finck case 7:
3890c2c66affSColin Finck nPermission |= (*(lpszPermission+7) == 'r' ? 1 : 0) << 2;
3891c2c66affSColin Finck break;
3892c2c66affSColin Finck case 8:
3893c2c66affSColin Finck nPermission |= (*(lpszPermission+8) == 'w' ? 1 : 0) << 1;
3894c2c66affSColin Finck break;
3895c2c66affSColin Finck case 9:
3896c2c66affSColin Finck nPermission |= (*(lpszPermission+9) == 'x' ? 1 : 0);
3897c2c66affSColin Finck break;
3898c2c66affSColin Finck }
3899c2c66affSColin Finck nPos++;
3900c2c66affSColin Finck }while (nPos <= nLast);
3901c2c66affSColin Finck
3902c2c66affSColin Finck lpfp->permissions = nPermission;
3903c2c66affSColin Finck return bSuccess;
3904c2c66affSColin Finck }
3905c2c66affSColin Finck
3906c2c66affSColin Finck
3907c2c66affSColin Finck /***********************************************************************
3908c2c66affSColin Finck * FTP_SetResponseError (internal)
3909c2c66affSColin Finck *
3910c2c66affSColin Finck * Set the appropriate error code for a given response from the server
3911c2c66affSColin Finck *
3912c2c66affSColin Finck * RETURNS
3913c2c66affSColin Finck *
3914c2c66affSColin Finck */
FTP_SetResponseError(DWORD dwResponse)3915c2c66affSColin Finck static DWORD FTP_SetResponseError(DWORD dwResponse)
3916c2c66affSColin Finck {
3917c2c66affSColin Finck DWORD dwCode = 0;
3918c2c66affSColin Finck
3919c2c66affSColin Finck switch(dwResponse)
3920c2c66affSColin Finck {
3921c2c66affSColin Finck case 425: /* Cannot open data connection. */
3922c2c66affSColin Finck dwCode = ERROR_INTERNET_CANNOT_CONNECT;
3923c2c66affSColin Finck break;
3924c2c66affSColin Finck
39251e7b4025Swinesync case 426: /* Connection closed, transfer aborted. */
3926c2c66affSColin Finck dwCode = ERROR_INTERNET_CONNECTION_ABORTED;
3927c2c66affSColin Finck break;
3928c2c66affSColin Finck
3929c2c66affSColin Finck case 530: /* Not logged in. Login incorrect. */
3930c2c66affSColin Finck dwCode = ERROR_INTERNET_LOGIN_FAILURE;
3931c2c66affSColin Finck break;
3932c2c66affSColin Finck
3933c2c66affSColin Finck case 421: /* Service not available - Server may be shutting down. */
3934c2c66affSColin Finck case 450: /* File action not taken. File may be busy. */
3935c2c66affSColin Finck case 451: /* Action aborted. Server error. */
3936c2c66affSColin Finck case 452: /* Action not taken. Insufficient storage space on server. */
3937c2c66affSColin Finck case 500: /* Syntax error. Command unrecognized. */
3938c2c66affSColin Finck case 501: /* Syntax error. Error in parameters or arguments. */
3939c2c66affSColin Finck case 502: /* Command not implemented. */
3940c2c66affSColin Finck case 503: /* Bad sequence of commands. */
3941c2c66affSColin Finck case 504: /* Command not implemented for that parameter. */
3942c2c66affSColin Finck case 532: /* Need account for storing files */
3943c2c66affSColin Finck case 550: /* File action not taken. File not found or no access. */
3944c2c66affSColin Finck case 551: /* Requested action aborted. Page type unknown */
3945c2c66affSColin Finck case 552: /* Action aborted. Exceeded storage allocation */
3946c2c66affSColin Finck case 553: /* Action not taken. File name not allowed. */
3947c2c66affSColin Finck
3948c2c66affSColin Finck default:
3949c2c66affSColin Finck dwCode = ERROR_INTERNET_EXTENDED_ERROR;
3950c2c66affSColin Finck break;
3951c2c66affSColin Finck }
3952c2c66affSColin Finck
3953c2c66affSColin Finck INTERNET_SetLastError(dwCode);
3954c2c66affSColin Finck return dwCode;
3955c2c66affSColin Finck }
3956