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