ReactOS  0.4.14-dev-604-gcfdd483
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 {
249 
250  TRACE("%p\n", session);
251 
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 {
436 
437  TRACE("%p\n", session);
438 
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 {
579 
580  TRACE(" %p\n", session);
581 
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 {
737 
738  TRACE("%p\n", session);
739 
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 {
952 
953  TRACE("%p\n", session);
954 
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 {
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 {
1587 
1588  TRACE("%p\n", session);
1589 
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 {
1794 
1795  TRACE("%p\n", session);
1796 
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 {
1936 
1937  TRACE("%p\n", session);
1938 
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 {
2088 
2089  TRACE("%p\n", session);
2090 
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  WININET_Release(&lpwfs->hdr);
2585  return NULL;
2586  }
2587 
2588  return lpwfs->hdr.hInternet;
2589 }
2590 
2591 
2592 /***********************************************************************
2593  * FTP_ConnectToHost (internal)
2594  *
2595  * Connect to a ftp server
2596  *
2597  * RETURNS
2598  * TRUE on success
2599  * NULL on failure
2600  *
2601  */
2603 {
2604  INT nResCode;
2605  BOOL bSuccess = FALSE;
2606 
2607  TRACE("\n");
2608  FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2609 
2610  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_USER, lpwfs->lpszUserName, 0, 0, 0))
2611  goto lend;
2612 
2613  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2614  if (nResCode)
2615  {
2616  /* Login successful... */
2617  if (nResCode == 230)
2618  bSuccess = TRUE;
2619  /* User name okay, need password... */
2620  else if (nResCode == 331)
2621  bSuccess = FTP_SendPassword(lpwfs);
2622  /* Need account for login... */
2623  else if (nResCode == 332)
2624  bSuccess = FTP_SendAccount(lpwfs);
2625  else
2626  FTP_SetResponseError(nResCode);
2627  }
2628 
2629  TRACE("Returning %d\n", bSuccess);
2630 lend:
2631  return bSuccess;
2632 }
2633 
2634 /***********************************************************************
2635  * FTP_GetNextLine (internal)
2636  *
2637  * Parse next line in directory string listing
2638  *
2639  * RETURNS
2640  * Pointer to beginning of next line
2641  * NULL on failure
2642  *
2643  */
2644 
2645 static LPSTR FTP_GetNextLine(INT nSocket, LPDWORD dwLen)
2646 {
2647  struct timeval tv = {RESPONSE_TIMEOUT,0};
2648  FD_SET set;
2649  INT nRecv = 0;
2650  LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
2651 
2652  TRACE("\n");
2653 
2654  FD_ZERO(&set);
2655  FD_SET(nSocket, &set);
2656 
2657  while (nRecv < MAX_REPLY_LEN)
2658  {
2659  if (select(nSocket+1, &set, NULL, NULL, &tv) > 0)
2660  {
2661  if (sock_recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2662  {
2664  return NULL;
2665  }
2666 
2667  if (lpszBuffer[nRecv] == '\n')
2668  {
2669  lpszBuffer[nRecv] = '\0';
2670  *dwLen = nRecv - 1;
2671  TRACE(":%d %s\n", nRecv, lpszBuffer);
2672  return lpszBuffer;
2673  }
2674  if (lpszBuffer[nRecv] != '\r')
2675  nRecv++;
2676  }
2677  else
2678  {
2680  return NULL;
2681  }
2682  }
2683 
2684  return NULL;
2685 }
2686 
2687 /***********************************************************************
2688  * FTP_SendCommandA (internal)
2689  *
2690  * Send command to server
2691  *
2692  * RETURNS
2693  * TRUE on success
2694  * NULL on failure
2695  *
2696  */
2697 static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
2698  INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext)
2699 {
2700  DWORD len;
2701  CHAR *buf;
2702  DWORD nBytesSent = 0;
2703  int nRC = 0;
2704  DWORD dwParamLen;
2705 
2706  TRACE("%d: (%s) %d\n", ftpCmd, debugstr_a(lpszParam), nSocket);
2707 
2708  if (lpfnStatusCB)
2709  {
2710  lpfnStatusCB(hdr->hInternet, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
2711  }
2712 
2713  dwParamLen = lpszParam?strlen(lpszParam)+1:0;
2714  len = dwParamLen + strlen(szFtpCommands[ftpCmd]) + strlen(szCRLF);
2715  if (NULL == (buf = heap_alloc(len+1)))
2716  {
2718  return FALSE;
2719  }
2720  sprintf(buf, "%s%s%s%s", szFtpCommands[ftpCmd], dwParamLen ? " " : "",
2721  dwParamLen ? lpszParam : "", szCRLF);
2722 
2723  TRACE("Sending (%s) len(%d)\n", debugstr_a(buf), len);
2724  while((nBytesSent < len) && (nRC != -1))
2725  {
2726  nRC = sock_send(nSocket, buf+nBytesSent, len - nBytesSent, 0);
2727  nBytesSent += nRC;
2728  }
2729  heap_free(buf);
2730 
2731  if (lpfnStatusCB)
2732  {
2733  lpfnStatusCB(hdr->hInternet, dwContext, INTERNET_STATUS_REQUEST_SENT,
2734  &nBytesSent, sizeof(DWORD));
2735  }
2736 
2737  TRACE("Sent %d bytes\n", nBytesSent);
2738  return (nRC != -1);
2739 }
2740 
2741 /***********************************************************************
2742  * FTP_SendCommand (internal)
2743  *
2744  * Send command to server
2745  *
2746  * RETURNS
2747  * TRUE on success
2748  * NULL on failure
2749  *
2750  */
2751 static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
2752  INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext)
2753 {
2754  BOOL ret;
2755  LPSTR lpszParamA = heap_strdupWtoA(lpszParam);
2756  ret = FTP_SendCommandA(nSocket, ftpCmd, lpszParamA, lpfnStatusCB, hdr, dwContext);
2757  heap_free(lpszParamA);
2758  return ret;
2759 }
2760 
2761 /***********************************************************************
2762  * FTP_ReceiveResponse (internal)
2763  *
2764  * Receive response from server
2765  *
2766  * RETURNS
2767  * Reply code on success
2768  * 0 on failure
2769  *
2770  */
2772 {
2773  LPSTR lpszResponse = INTERNET_GetResponseBuffer();
2774  DWORD nRecv;
2775  INT rc = 0;
2776  char firstprefix[5];
2777  BOOL multiline = FALSE;
2778 
2779  TRACE("socket(%d)\n", lpwfs->sndSocket);
2780 
2782 
2783  while(1)
2784  {
2785  if (!FTP_GetNextLine(lpwfs->sndSocket, &nRecv))
2786  goto lerror;
2787 
2788  if (nRecv >= 3)
2789  {
2790  if(!multiline)
2791  {
2792  if(lpszResponse[3] != '-')
2793  break;
2794  else
2795  { /* Start of multiline response. Loop until we get "nnn " */
2796  multiline = TRUE;
2797  memcpy(firstprefix, lpszResponse, 3);
2798  firstprefix[3] = ' ';
2799  firstprefix[4] = '\0';
2800  }
2801  }
2802  else
2803  {
2804  if(!memcmp(firstprefix, lpszResponse, 4))
2805  break;
2806  }
2807  }
2808  }
2809 
2810  if (nRecv >= 3)
2811  {
2812  rc = atoi(lpszResponse);
2813 
2815  &nRecv, sizeof(DWORD));
2816  }
2817 
2818 lerror:
2819  TRACE("return %d\n", rc);
2820  return rc;
2821 }
2822 
2823 
2824 /***********************************************************************
2825  * FTP_SendPassword (internal)
2826  *
2827  * Send password to ftp server
2828  *
2829  * RETURNS
2830  * TRUE on success
2831  * NULL on failure
2832  *
2833  */
2835 {
2836  INT nResCode;
2837  BOOL bSuccess = FALSE;
2838 
2839  TRACE("\n");
2840  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASS, lpwfs->lpszPassword, 0, 0, 0))
2841  goto lend;
2842 
2843  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2844  if (nResCode)
2845  {
2846  TRACE("Received reply code %d\n", nResCode);
2847  /* Login successful... */
2848  if (nResCode == 230)
2849  bSuccess = TRUE;
2850  /* Command not implemented, superfluous at the server site... */
2851  /* Need account for login... */
2852  else if (nResCode == 332)
2853  bSuccess = FTP_SendAccount(lpwfs);
2854  else
2855  FTP_SetResponseError(nResCode);
2856  }
2857 
2858 lend:
2859  TRACE("Returning %d\n", bSuccess);
2860  return bSuccess;
2861 }
2862 
2863 
2864 /***********************************************************************
2865  * FTP_SendAccount (internal)
2866  *
2867  *
2868  *
2869  * RETURNS
2870  * TRUE on success
2871  * FALSE on failure
2872  *
2873  */
2875 {
2876  INT nResCode;
2877  BOOL bSuccess = FALSE;
2878 
2879  TRACE("\n");
2880  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_ACCT, szNoAccount, 0, 0, 0))
2881  goto lend;
2882 
2883  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2884  if (nResCode)
2885  bSuccess = TRUE;
2886  else
2887  FTP_SetResponseError(nResCode);
2888 
2889 lend:
2890  return bSuccess;
2891 }
2892 
2893 
2894 /***********************************************************************
2895  * FTP_SendStore (internal)
2896  *
2897  * Send request to upload file to ftp server
2898  *
2899  * RETURNS
2900  * TRUE on success
2901  * FALSE on failure
2902  *
2903  */
2904 static BOOL FTP_SendStore(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
2905 {
2906  INT nResCode;
2907  BOOL bSuccess = FALSE;
2908 
2909  TRACE("\n");
2910  if (!FTP_InitListenSocket(lpwfs))
2911  goto lend;
2912 
2913  if (!FTP_SendType(lpwfs, dwType))
2914  goto lend;
2915 
2916  if (!FTP_SendPortOrPasv(lpwfs))
2917  goto lend;
2918 
2919  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_STOR, lpszRemoteFile, 0, 0, 0))
2920  goto lend;
2921  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
2922  if (nResCode)
2923  {
2924  if (nResCode == 150 || nResCode == 125)
2925  bSuccess = TRUE;
2926  else
2927  FTP_SetResponseError(nResCode);
2928  }
2929 
2930 lend:
2931  if (!bSuccess && lpwfs->lstnSocket != -1)
2932  {
2933  closesocket(lpwfs->lstnSocket);
2934  lpwfs->lstnSocket = -1;
2935  }
2936 
2937  return bSuccess;
2938 }
2939 
2940 
2941 /***********************************************************************
2942  * FTP_InitListenSocket (internal)
2943  *
2944  * Create a socket to listen for server response
2945  *
2946  * RETURNS
2947  * TRUE on success
2948  * FALSE on failure
2949  *
2950  */
2952 {
2953  BOOL bSuccess = FALSE;
2954  socklen_t namelen = sizeof(lpwfs->lstnSocketAddress);
2955 
2956  TRACE("\n");
2957 
2958  init_winsock();
2959  lpwfs->lstnSocket = socket(AF_INET, SOCK_STREAM, 0);
2960  if (lpwfs->lstnSocket == -1)
2961  {
2962  TRACE("Unable to create listening socket\n");
2963  goto lend;
2964  }
2965 
2966  /* We obtain our ip addr from the name of the command channel socket */
2967  lpwfs->lstnSocketAddress = lpwfs->socketAddress;
2968 
2969  /* and get the system to assign us a port */
2970  lpwfs->lstnSocketAddress.sin_port = htons(0);
2971 
2972  if (bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(lpwfs->lstnSocketAddress)) == -1)
2973  {
2974  TRACE("Unable to bind socket\n");
2975  goto lend;
2976  }
2977 
2978  if (listen(lpwfs->lstnSocket, MAX_BACKLOG) == -1)
2979  {
2980  TRACE("listen failed\n");
2981  goto lend;
2982  }
2983 
2984  if (getsockname(lpwfs->lstnSocket, (struct sockaddr *) &lpwfs->lstnSocketAddress, &namelen) != -1)
2985  bSuccess = TRUE;
2986 
2987 lend:
2988  if (!bSuccess && lpwfs->lstnSocket != -1)
2989  {
2990  closesocket(lpwfs->lstnSocket);
2991  lpwfs->lstnSocket = -1;
2992  }
2993 
2994  return bSuccess;
2995 }
2996 
2997 
2998 /***********************************************************************
2999  * FTP_SendType (internal)
3000  *
3001  * Tell server type of data being transferred
3002  *
3003  * RETURNS
3004  * TRUE on success
3005  * FALSE on failure
3006  *
3007  * W98SE doesn't cache the type that's currently set
3008  * (i.e. it sends it always),
3009  * so we probably don't want to do that either.
3010  */
3011 static BOOL FTP_SendType(ftp_session_t *lpwfs, DWORD dwType)
3012 {
3013  INT nResCode;
3014  WCHAR type[] = { 'I','\0' };
3015  BOOL bSuccess = FALSE;
3016 
3017  TRACE("\n");
3018  if (dwType & INTERNET_FLAG_TRANSFER_ASCII)
3019  type[0] = 'A';
3020 
3021  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_TYPE, type, 0, 0, 0))
3022  goto lend;
3023 
3024  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext)/100;
3025  if (nResCode)
3026  {
3027  if (nResCode == 2)
3028  bSuccess = TRUE;
3029  else
3030  FTP_SetResponseError(nResCode);
3031  }
3032 
3033 lend:
3034  return bSuccess;
3035 }
3036 
3037 
3038 #if 0 /* FIXME: should probably be used for FtpGetFileSize */
3039 /***********************************************************************
3040  * FTP_GetFileSize (internal)
3041  *
3042  * Retrieves from the server the size of the given file
3043  *
3044  * RETURNS
3045  * TRUE on success
3046  * FALSE on failure
3047  *
3048  */
3049 static BOOL FTP_GetFileSize(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD *dwSize)
3050 {
3051  INT nResCode;
3052  BOOL bSuccess = FALSE;
3053 
3054  TRACE("\n");
3055 
3056  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_SIZE, lpszRemoteFile, 0, 0, 0))
3057  goto lend;
3058 
3059  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3060  if (nResCode)
3061  {
3062  if (nResCode == 213) {
3063  /* Now parses the output to get the actual file size */
3064  int i;
3065  LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
3066 
3067  for (i = 0; (lpszResponseBuffer[i] != ' ') && (lpszResponseBuffer[i] != '\0'); i++) ;
3068  if (lpszResponseBuffer[i] == '\0') return FALSE;
3069  *dwSize = atol(&(lpszResponseBuffer[i + 1]));
3070 
3071  bSuccess = TRUE;
3072  } else {
3073  FTP_SetResponseError(nResCode);
3074  }
3075  }
3076 
3077 lend:
3078  return bSuccess;
3079 }
3080 #endif
3081 
3082 
3083 /***********************************************************************
3084  * FTP_SendPort (internal)
3085  *
3086  * Tell server which port to use
3087  *
3088  * RETURNS
3089  * TRUE on success
3090  * FALSE on failure
3091  *
3092  */
3094 {
3095  static const WCHAR szIPFormat[] = {'%','d',',','%','d',',','%','d',',','%','d',',','%','d',',','%','d','\0'};
3096  INT nResCode;
3097  WCHAR szIPAddress[64];
3098  BOOL bSuccess = FALSE;
3099  TRACE("\n");
3100 
3101  sprintfW(szIPAddress, szIPFormat,
3102  lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0x000000FF,
3103  (lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0x0000FF00)>>8,
3104  (lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0x00FF0000)>>16,
3105  (lpwfs->lstnSocketAddress.sin_addr.S_un.S_addr&0xFF000000)>>24,
3106  lpwfs->lstnSocketAddress.sin_port & 0xFF,
3107  (lpwfs->lstnSocketAddress.sin_port & 0xFF00)>>8);
3108 
3109  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PORT, szIPAddress, 0, 0, 0))
3110  goto lend;
3111 
3112  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3113  if (nResCode)
3114  {
3115  if (nResCode == 200)
3116  bSuccess = TRUE;
3117  else
3118  FTP_SetResponseError(nResCode);
3119  }
3120 
3121 lend:
3122  return bSuccess;
3123 }
3124 
3125 
3126 /***********************************************************************
3127  * FTP_DoPassive (internal)
3128  *
3129  * Tell server that we want to do passive transfers
3130  * and connect data socket
3131  *
3132  * RETURNS
3133  * TRUE on success
3134  * FALSE on failure
3135  *
3136  */
3138 {
3139  INT nResCode;
3140  BOOL bSuccess = FALSE;
3141 
3142  TRACE("\n");
3143  if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASV, NULL, 0, 0, 0))
3144  goto lend;
3145 
3146  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3147  if (nResCode)
3148  {
3149  if (nResCode == 227)
3150  {
3151  LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
3152  LPSTR p;
3153  int f[6];
3154  int i;
3155  char *pAddr, *pPort;
3156  INT nsocket = -1;
3157  struct sockaddr_in dataSocketAddress;
3158 
3159  p = lpszResponseBuffer+4; /* skip status code */
3160  while (*p != '\0' && (*p < '0' || *p > '9')) p++;
3161 
3162  if (*p == '\0')
3163  {
3164  ERR("no address found in response, aborting\n");
3165  goto lend;
3166  }
3167 
3168  if (sscanf(p, "%d,%d,%d,%d,%d,%d", &f[0], &f[1], &f[2], &f[3],
3169  &f[4], &f[5]) != 6)
3170  {
3171  ERR("unknown response address format '%s', aborting\n", p);
3172  goto lend;
3173  }
3174  for (i=0; i < 6; i++)
3175  f[i] = f[i] & 0xff;
3176 
3177  dataSocketAddress = lpwfs->socketAddress;
3178  pAddr = (char *)&(dataSocketAddress.sin_addr.S_un.S_addr);
3179  pPort = (char *)&(dataSocketAddress.sin_port);
3180  pAddr[0] = f[0];
3181  pAddr[1] = f[1];
3182  pAddr[2] = f[2];
3183  pAddr[3] = f[3];
3184  pPort[0] = f[4];
3185  pPort[1] = f[5];
3186 
3187  nsocket = socket(AF_INET,SOCK_STREAM,0);
3188  if (nsocket == -1)
3189  goto lend;
3190 
3191  if (connect(nsocket, (struct sockaddr *)&dataSocketAddress, sizeof(dataSocketAddress)))
3192  {
3193  ERR("can't connect passive FTP data port.\n");
3194  closesocket(nsocket);
3195  goto lend;
3196  }
3197  lpwfs->pasvSocket = nsocket;
3198  bSuccess = TRUE;
3199  }
3200  else
3201  FTP_SetResponseError(nResCode);
3202  }
3203 
3204 lend:
3205  return bSuccess;
3206 }
3207 
3208 
3210 {
3211  if (lpwfs->hdr.dwFlags & INTERNET_FLAG_PASSIVE)
3212  {
3213  if (!FTP_DoPassive(lpwfs))
3214  return FALSE;
3215  }
3216  else
3217  {
3218  if (!FTP_SendPort(lpwfs))
3219  return FALSE;
3220  }
3221  return TRUE;
3222 }
3223 
3224 
3225 /***********************************************************************
3226  * FTP_GetDataSocket (internal)
3227  *
3228  * Either accepts an incoming data socket connection from the server
3229  * or just returns the already opened socket after a PASV command
3230  * in case of passive FTP.
3231  *
3232  *
3233  * RETURNS
3234  * TRUE on success
3235  * FALSE on failure
3236  *
3237  */
3238 static BOOL FTP_GetDataSocket(ftp_session_t *lpwfs, LPINT nDataSocket)
3239 {
3240  struct sockaddr_in saddr;
3241  socklen_t addrlen = sizeof(saddr);
3242 
3243  TRACE("\n");
3244  if (lpwfs->hdr.dwFlags & INTERNET_FLAG_PASSIVE)
3245  {
3246  *nDataSocket = lpwfs->pasvSocket;
3247  lpwfs->pasvSocket = -1;
3248  }
3249  else
3250  {
3251  *nDataSocket = accept(lpwfs->lstnSocket, (struct sockaddr *) &saddr, &addrlen);
3252  closesocket(lpwfs->lstnSocket);
3253  lpwfs->lstnSocket = -1;
3254  }
3255  return *nDataSocket != -1;
3256 }
3257 
3258 
3259 /***********************************************************************
3260  * FTP_SendData (internal)
3261  *
3262  * Send data to the server
3263  *
3264  * RETURNS
3265  * TRUE on success
3266  * FALSE on failure
3267  *
3268  */
3269 static BOOL FTP_SendData(ftp_session_t *lpwfs, INT nDataSocket, HANDLE hFile)
3270 {
3272  DWORD nBytesRead = 0;
3273  DWORD nBytesSent = 0;
3274  DWORD nTotalSent = 0;
3275  DWORD nBytesToSend, nLen;
3276  int nRC = 1;
3277  time_t s_long_time, e_long_time;
3278  LONG nSeconds;
3279  CHAR *lpszBuffer;
3280 
3281  TRACE("\n");
3282  lpszBuffer = heap_alloc_zero(sizeof(CHAR)*DATA_PACKET_SIZE);
3283 
3284  /* Get the size of the file. */
3286  time(&s_long_time);
3287 
3288  do
3289  {
3290  nBytesToSend = nBytesRead - nBytesSent;
3291 
3292  if (nBytesToSend <= 0)
3293  {
3294  /* Read data from file. */
3295  nBytesSent = 0;
3296  if (!ReadFile(hFile, lpszBuffer, DATA_PACKET_SIZE, &nBytesRead, 0))
3297  ERR("Failed reading from file\n");
3298 
3299  if (nBytesRead > 0)
3300  nBytesToSend = nBytesRead;
3301  else
3302  break;
3303  }
3304 
3305  nLen = DATA_PACKET_SIZE < nBytesToSend ?
3306  DATA_PACKET_SIZE : nBytesToSend;
3307  nRC = sock_send(nDataSocket, lpszBuffer, nLen, 0);
3308 
3309  if (nRC != -1)
3310  {
3311  nBytesSent += nRC;
3312  nTotalSent += nRC;
3313  }
3314 
3315  /* Do some computation to display the status. */
3316  time(&e_long_time);
3317  nSeconds = e_long_time - s_long_time;
3318  if( nSeconds / 60 > 0 )
3319  {
3320  TRACE( "%d bytes of %d bytes (%d%%) in %d min %d sec estimated remaining time %d sec\n",
3321  nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds / 60,
3322  nSeconds % 60, (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent );
3323  }
3324  else
3325  {
3326  TRACE( "%d bytes of %d bytes (%d%%) in %d sec estimated remaining time %d sec\n",
3327  nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds,
3328  (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent);
3329  }
3330  } while (nRC != -1);
3331 
3332  TRACE("file transfer complete!\n");
3333 
3334  heap_free(lpszBuffer);
3335  return nTotalSent;
3336 }
3337 
3338 
3339 /***********************************************************************
3340  * FTP_SendRetrieve (internal)
3341  *
3342  * Send request to retrieve a file
3343  *
3344  * RETURNS
3345  * Number of bytes to be received on success
3346  * 0 on failure
3347  *
3348  */
3349 static BOOL FTP_SendRetrieve(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
3350 {
3351  INT nResCode;
3352  BOOL ret;
3353 
3354  TRACE("\n");
3355  if (!(ret = FTP_InitListenSocket(lpwfs)))
3356  goto lend;
3357 
3358  if (!(ret = FTP_SendType(lpwfs, dwType)))
3359  goto lend;
3360 
3361  if (!(ret = FTP_SendPortOrPasv(lpwfs)))
3362  goto lend;
3363 
3364  if (!(ret = FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0)))
3365  goto lend;
3366 
3367  nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
3368  if ((nResCode != 125) && (nResCode != 150)) {
3369  /* That means that we got an error getting the file. */
3370  FTP_SetResponseError(nResCode);
3371  ret = FALSE;
3372  }
3373 
3374 lend:
3375  if (!ret && lpwfs->lstnSocket != -1)
3376  {
3377  closesocket(lpwfs->lstnSocket);
3378  lpwfs->lstnSocket = -1;
3379  }
3380 
3381  return ret;
3382 }
3383 
3384 
3385 /***********************************************************************
3386  * FTP_RetrieveData (internal)
3387  *
3388  * Retrieve data from server
3389  *
3390  * RETURNS
3391  * TRUE on success
3392  * FALSE on failure
3393  *
3394  */
3396 {
3397  DWORD nBytesWritten;
3398  INT nRC = 0;
3399  CHAR *lpszBuffer;
3400 
3401  TRACE("\n");
3402 
3403  lpszBuffer = heap_alloc_zero(sizeof(CHAR)*DATA_PACKET_SIZE);
3404  if (NULL == lpszBuffer)
3405  {
3407  return FALSE;
3408  }
3409 
3410  while (nRC != -1)
3411  {
3412  nRC = sock_recv(nDataSocket, lpszBuffer, DATA_PACKET_SIZE, 0);
3413  if (nRC != -1)
3414  {
3415  /* other side closed socket. */
3416  if (nRC == 0)
3417  goto recv_end;
3418  WriteFile(hFile, lpszBuffer, nRC, &nBytesWritten, NULL);
3419  }
3420  }
3421 
3422  TRACE("Data transfer complete\n");
3423 
3424 recv_end:
3425  heap_free(lpszBuffer);
3426  return (nRC != -1);
3427 }
3428 
3429 /***********************************************************************
3430  * FTPFINDNEXT_Destroy (internal)
3431  *
3432  * Deallocate session handle
3433  */
3435 {
3437  DWORD i;
3438 
3439  TRACE("\n");
3440 
3441  WININET_Release(&lpwfn->lpFtpSession->hdr);
3442 
3443  for (i = 0; i < lpwfn->size; i++)
3444  {
3445  heap_free(lpwfn->lpafp[i].lpszName);
3446  }
3447  heap_free(lpwfn->lpafp);
3448 }
3449 
3451 {
3454 
3455  TRACE("index(%d) size(%d)\n", find->index, find->size);
3456 
3458 
3459  if (find->index < find->size) {
3460  FTP_ConvertFileProp(&find->lpafp[find->index], find_data);
3461  find->index++;
3462 
3463  TRACE("Name: %s\nSize: %d\n", debugstr_w(find_data->cFileName), find_data->nFileSizeLow);
3464  }else {
3466  }
3467 
3468  if (find->hdr.dwFlags & INTERNET_FLAG_ASYNC)
3469  {
3471 
3472  iar.dwResult = (res == ERROR_SUCCESS);
3473  iar.dwError = res;
3474 
3475  INTERNET_SendCallback(&find->hdr, find->hdr.dwContext,
3477  sizeof(INTERNET_ASYNC_RESULT));
3478  }
3479 
3480  return res;
3481 }
3482 
3483 typedef struct {
3487 
3489 {
3491 
3493 }
3494 
3496 {
3497  switch(option) {
3499  TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
3500 
3501  if (*size < sizeof(ULONG))
3503 
3504  *size = sizeof(DWORD);
3506  return ERROR_SUCCESS;
3507  }
3508 
3509  return INET_QueryOption(hdr, option, buffer, size, unicode);
3510 }
3511 
3513 {
3515 
3516  if (find->lpFtpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
3517  {
3518  find_next_task_t *task;
3519 
3520  task = alloc_async_task(&find->hdr, FTPFINDNEXT_AsyncFindNextFileProc, sizeof(*task));
3521  task->find_data = data;
3522 
3523  INTERNET_AsyncCall(&task->hdr);
3524  return ERROR_SUCCESS;
3525  }
3526 
3528 }
3529 
3532  NULL,
3535  NULL,
3536  NULL,
3537  NULL,
3539 };
3540 
3541 /***********************************************************************
3542  * FTP_ReceiveFileList (internal)
3543  *
3544  * Read file list from server
3545  *
3546  * RETURNS
3547  * Handle to file list on success
3548  * NULL on failure
3549  *
3550  */
3551 static HINTERNET FTP_ReceiveFileList(ftp_session_t *lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
3552  LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext)
3553 {
3554  DWORD dwSize = 0;
3555  LPFILEPROPERTIESW lpafp = NULL;
3556  LPWININETFTPFINDNEXTW lpwfn = NULL;
3557 
3558  TRACE("(%p,%d,%s,%p,%08lx)\n", lpwfs, nSocket, debugstr_w(lpszSearchFile), lpFindFileData, dwContext);
3559 
3560  if (FTP_ParseDirectory(lpwfs, nSocket, lpszSearchFile, &lpafp, &dwSize))
3561  {
3562  if(lpFindFileData)
3563  FTP_ConvertFileProp(lpafp, lpFindFileData);
3564 
3565  lpwfn = alloc_object(&lpwfs->hdr, &FTPFINDNEXTVtbl, sizeof(WININETFTPFINDNEXTW));
3566  if (lpwfn)
3567  {
3568  lpwfn->hdr.htype = WH_HFTPFINDNEXT;
3569  lpwfn->hdr.dwContext = dwContext;
3570  lpwfn->index = 1; /* Next index is 1 since we return index 0 */
3571  lpwfn->size = dwSize;
3572  lpwfn->lpafp = lpafp;
3573 
3574  WININET_AddRef( &lpwfs->hdr );
3575  lpwfn->lpFtpSession = lpwfs;
3576  list_add_head( &lpwfs->hdr.children, &lpwfn->hdr.entry );
3577  }
3578  }
3579 
3580  TRACE("Matched %d files\n", dwSize);
3581  return lpwfn ? lpwfn->hdr.hInternet : NULL;
3582 }
3583 
3584 
3585 /***********************************************************************
3586  * FTP_ConvertFileProp (internal)
3587  *
3588  * Converts FILEPROPERTIESW struct to WIN32_FIND_DATAA
3589  *
3590  * RETURNS
3591  * TRUE on success
3592  * FALSE on failure
3593  *
3594  */
3596 {
3597  BOOL bSuccess = FALSE;
3598 
3599  ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAW));
3600 
3601  if (lpafp)
3602  {
3603  SystemTimeToFileTime( &lpafp->tmLastModified, &lpFindFileData->ftLastAccessTime );
3604  lpFindFileData->ftLastWriteTime = lpFindFileData->ftLastAccessTime;
3605  lpFindFileData->ftCreationTime = lpFindFileData->ftLastAccessTime;
3606 
3607  /* Not all fields are filled in */
3608  lpFindFileData->nFileSizeHigh = 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */
3609  lpFindFileData->nFileSizeLow = lpafp->nSize;
3610 
3611  if (lpafp->bIsDirectory)
3612  lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
3613 
3614  if (lpafp->lpszName)
3615  lstrcpynW(lpFindFileData->cFileName, lpafp->lpszName, MAX_PATH);
3616 
3617  bSuccess = TRUE;
3618  }
3619 
3620  return bSuccess;
3621 }
3622 
3623 /***********************************************************************
3624  * FTP_ParseNextFile (internal)
3625  *
3626  * Parse the next line in file listing
3627  *
3628  * RETURNS
3629  * TRUE on success
3630  * FALSE on failure
3631  */
3632 static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERTIESW lpfp)
3633 {
3634  static const char szSpace[] = " \t";
3635  DWORD nBufLen;
3636  char *pszLine;
3637  char *pszToken;
3638  char *pszTmp;
3639  BOOL found = FALSE;
3640  int i;
3641 
3642  lpfp->lpszName = NULL;
3643  do {
3644  if(!(pszLine = FTP_GetNextLine(nSocket, &nBufLen)))
3645  return FALSE;
3646 
3647  pszToken = strtok(pszLine, szSpace);
3648  /* ls format
3649  * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
3650  *
3651  * For instance:
3652  * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
3653  */
3654  if(!isdigit(pszToken[0]) && 10 == strlen(pszToken)) {
3655  if(!FTP_ParsePermission(pszToken, lpfp))
3656  lpfp->bIsDirectory = FALSE;
3657  for(i=0; i<=3; i++) {
3658  if(!(pszToken = strtok(NULL, szSpace)))
3659  break;
3660  }
3661  if(!pszToken) continue;
3662  if(lpfp->bIsDirectory) {
3663  TRACE("Is directory\n");
3664  lpfp->nSize = 0;
3665  }
3666  else {
3667  TRACE("Size: %s\n", pszToken);
3668  lpfp->nSize = atol(pszToken);
3669  }
3670 
3671  lpfp->tmLastModified.wSecond = 0;
3672  lpfp->tmLastModified.wMinute = 0;
3673  lpfp->tmLastModified.wHour = 0;
3674  lpfp->tmLastModified.wDay = 0;
3675  lpfp->tmLastModified.wMonth = 0;
3676  lpfp->tmLastModified.wYear = 0;
3677 
3678  /* Determine month */
3679  pszToken = strtok(NULL, szSpace);
3680  if(!pszToken) continue;
3681  if(strlen(pszToken) >= 3) {
3682  pszToken[3] = 0;
3683  if((pszTmp = StrStrIA(szMonths, pszToken)))
3684  lpfp->tmLastModified.wMonth = ((pszTmp - szMonths) / 3)+1;
3685  }
3686  /* Determine day */
3687  pszToken = strtok(NULL, szSpace);
3688  if(!pszToken) continue;
3689  lpfp->tmLastModified.wDay = atoi(pszToken);
3690  /* Determine time or year */
3691  pszToken = strtok(NULL, szSpace);
3692  if(!pszToken) continue;
3693  if((pszTmp = strchr(pszToken, ':'))) {
3694  SYSTEMTIME curr_time;
3695  *pszTmp = 0;
3696  pszTmp++;
3697  lpfp->tmLastModified.wMinute = atoi(pszTmp);
3698  lpfp->tmLastModified.wHour = atoi(pszToken);
3699  GetLocalTime( &curr_time );
3700  lpfp->tmLastModified.wYear = curr_time.wYear;
3701  }
3702  else {
3703  lpfp->tmLastModified.wYear = atoi(pszToken);
3704  lpfp->tmLastModified.wHour = 12;
3705  }
3706  TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n",
3709 
3710  pszToken = strtok(NULL, szSpace);
3711  if(!pszToken) continue;
3712  lpfp->lpszName = heap_strdupAtoW(pszToken);
3713  TRACE("File: %s\n", debugstr_w(lpfp->lpszName));
3714  }
3715  /* NT way of parsing ... :
3716 
3717  07-13-03 08:55PM <DIR> sakpatch
3718  05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
3719  */
3720  else if(isdigit(pszToken[0]) && 8 == strlen(pszToken)) {
3721  int mon, mday, year, hour, min;
3722  lpfp->permissions = 0xFFFF; /* No idea, put full permission :-) */
3723 
3724  sscanf(pszToken, "%d-%d-%d", &mon, &mday, &year);
3725  lpfp->tmLastModified.wDay = mday;
3726  lpfp->tmLastModified.wMonth = mon;
3727  lpfp->tmLastModified.wYear = year;
3728 
3729  /* Hacky and bad Y2K protection :-) */
3730  if (lpfp->tmLastModified.wYear < 70) lpfp->tmLastModified.wYear += 2000;
3731 
3732  pszToken = strtok(NULL, szSpace);
3733  if(!pszToken) continue;
3734  sscanf(pszToken, "%d:%d", &hour, &min);
3735  lpfp->tmLastModified.wHour = hour;
3736  lpfp->tmLastModified.wMinute = min;
3737  if((pszToken[5] == 'P') && (pszToken[6] == 'M')) {
3738  lpfp->tmLastModified.wHour += 12;
3739  }
3740  lpfp->tmLastModified.wSecond = 0;
3741 
3742  TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n",
3745 
3746  pszToken = strtok(NULL, szSpace);
3747  if(!pszToken) continue;
3748  if(!_strnicmp(pszToken, "<DIR>", -1)) {
3749  lpfp->bIsDirectory = TRUE;
3750  lpfp->nSize = 0;
3751  TRACE("Is directory\n");
3752  }
3753  else {
3754  lpfp->bIsDirectory = FALSE;
3755  lpfp->nSize = atol(pszToken);
3756  TRACE("Size: %d\n", lpfp->nSize);
3757  }
3758 
3759  pszToken = strtok(NULL, szSpace);
3760  if(!pszToken) continue;
3761  lpfp->lpszName = heap_strdupAtoW(pszToken);
3762  TRACE("Name: %s\n", debugstr_w(lpfp->lpszName));
3763  }
3764  /* EPLF format - http://cr.yp.to/ftp/list/eplf.html */
3765  else if(pszToken[0] == '+') {
3766  FIXME("EPLF Format not implemented\n");
3767  }
3768 
3769  if(lpfp->lpszName) {
3770  if((lpszSearchFile == NULL) ||
3771  (PathMatchSpecW(lpfp->lpszName, lpszSearchFile))) {
3772  found = TRUE;
3773  TRACE("Matched: %s\n", debugstr_w(lpfp->lpszName));
3774  }
3775  else {
3776  heap_free(lpfp->lpszName);
3777  lpfp->lpszName = NULL;
3778  }
3779  }
3780  } while(!found);
3781  return TRUE;
3782 }
3783 
3784 /***********************************************************************
3785  * FTP_ParseDirectory (internal)
3786  *
3787  * Parse string of directory information
3788  *
3789  * RETURNS
3790  * TRUE on success
3791  * FALSE on failure
3792  */
3793 static BOOL FTP_ParseDirectory(ftp_session_t *lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
3794  LPFILEPROPERTIESW *lpafp, LPDWORD dwfp)
3795 {
3796  BOOL bSuccess = TRUE;
3797  INT sizeFilePropArray = 500;/*20; */
3798  INT indexFilePropArray = -1;
3799 
3800  TRACE("\n");
3801 
3802  /* Allocate initial file properties array */
3803  *lpafp = heap_alloc_zero(sizeof(FILEPROPERTIESW)*(sizeFilePropArray));
3804  if (!*lpafp)
3805  return FALSE;
3806 
3807  do {
3808  if (indexFilePropArray+1 >= sizeFilePropArray)
3809  {
3810  LPFILEPROPERTIESW tmpafp;
3811 
3812  sizeFilePropArray *= 2;
3813  tmpafp = heap_realloc_zero(*lpafp, sizeof(FILEPROPERTIESW)*sizeFilePropArray);
3814  if (NULL == tmpafp)
3815  {
3816  bSuccess = FALSE;
3817  break;
3818  }
3819 
3820  *lpafp = tmpafp;
3821  }
3822  indexFilePropArray++;
3823  } while (FTP_ParseNextFile(nSocket, lpszSearchFile, &(*lpafp)[indexFilePropArray]));
3824 
3825  if (bSuccess && indexFilePropArray)
3826  {
3827  if (indexFilePropArray < sizeFilePropArray - 1)
3828  {
3829  LPFILEPROPERTIESW tmpafp;
3830 
3831  tmpafp = heap_realloc(*lpafp, sizeof(FILEPROPERTIESW)*indexFilePropArray);
3832  if (NULL != tmpafp)
3833  *lpafp = tmpafp;
3834  }
3835  *dwfp = indexFilePropArray;
3836  }
3837  else
3838  {
3839  heap_free(*lpafp);
3841  bSuccess = FALSE;
3842  }
3843 
3844  return bSuccess;
3845 }
3846 
3847 
3848 /***********************************************************************
3849  * FTP_ParsePermission (internal)
3850  *
3851  * Parse permission string of directory information
3852  *
3853  * RETURNS
3854  * TRUE on success
3855  * FALSE on failure
3856  *
3857  */
3858 static BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESW lpfp)
3859 {
3860  BOOL bSuccess = TRUE;
3861  unsigned short nPermission = 0;
3862  INT nPos = 1;
3863  INT nLast = 9;
3864 
3865  TRACE("\n");
3866  if ((*lpszPermission != 'd') && (*lpszPermission != '-') && (*lpszPermission != 'l'))
3867  {
3868  bSuccess = FALSE;
3869  return bSuccess;
3870  }
3871 
3872  lpfp->bIsDirectory = (*lpszPermission == 'd');
3873  do
3874  {
3875  switch (nPos)
3876  {
3877  case 1:
3878  nPermission |= (*(lpszPermission+1) == 'r' ? 1 : 0) << 8;
3879  break;
3880  case 2:
3881  nPermission |= (*(lpszPermission+2) == 'w' ? 1 : 0) << 7;
3882  break;
3883  case 3:
3884  nPermission |= (*(lpszPermission+3) == 'x' ? 1 : 0) << 6;
3885  break;
3886  case 4:
3887  nPermission |= (*(lpszPermission+4) == 'r' ? 1 : 0) << 5;
3888  break;
3889  case 5:
3890  nPermission |= (*(lpszPermission+5) == 'w' ? 1 : 0) << 4;
3891  break;
3892  case 6:
3893  nPermission |= (*(lpszPermission+6) == 'x' ? 1 : 0) << 3;
3894  break;
3895  case 7:
3896  nPermission |= (*(lpszPermission+7) == 'r' ? 1 : 0) << 2;
3897  break;
3898  case 8:
3899  nPermission |= (*(lpszPermission+8) == 'w' ? 1 : 0) << 1;
3900  break;
3901  case 9:
3902  nPermission |= (*(lpszPermission+9) == 'x' ? 1 : 0);
3903  break;
3904  }
3905  nPos++;
3906  }while (nPos <= nLast);
3907 
3908  lpfp->permissions = nPermission;
3909  return bSuccess;
3910 }
3911 
3912 
3913 /***********************************************************************
3914  * FTP_SetResponseError (internal)
3915  *
3916  * Set the appropriate error code for a given response from the server
3917  *
3918  * RETURNS
3919  *
3920  */
3922 {
3923  DWORD dwCode = 0;
3924 
3925  switch(dwResponse)
3926  {
3927  case 425: /* Cannot open data connection. */
3929  break;
3930 
3931  case 426: /* Connection closed, transer aborted. */
3933  break;
3934 
3935  case 530: /* Not logged in. Login incorrect. */
3937  break;
3938 
3939  case 421: /* Service not available - Server may be shutting down. */
3940  case 450: /* File action not taken. File may be busy. */
3941  case 451: /* Action aborted. Server error. */
3942  case 452: /* Action not taken. Insufficient storage space on server. */
3943  case 500: /* Syntax error. Command unrecognized. */
3944  case 501: /* Syntax error. Error in parameters or arguments. */
3945  case 502: /* Command not implemented. */
3946  case 503: /* Bad sequence of commands. */
3947  case 504: /* Command not implemented for that parameter. */
3948  case 532: /* Need account for storing files */
3949  case 550: /* File action not taken. File not found or no access. */
3950  case 551: /* Requested action aborted. Page type unknown */
3951  case 552: /* Action aborted. Exceeded storage allocation */
3952  case 553: /* Action not taken. File name not allowed. */
3953 
3954  default:
3956  break;
3957  }
3958 
3959  INTERNET_SetLastError(dwCode);
3960  return dwCode;
3961 }
#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:2827
Definition: winsock.h:66
static BOOL FTP_SendPort(ftp_session_t *)
Definition: ftp.c:3093
static BOOL FTP_DoPassive(ftp_session_t *)
Definition: ftp.c:3137
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static LPSTR FTP_GetNextLine(INT nSocket, LPDWORD dwLen)
Definition: ftp.c:2645
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:915
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
static BOOL FTP_SendType(ftp_session_t *, DWORD dwType)
Definition: ftp.c:3011
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:2602
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:3720
#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
static DWORD FTP_SetResponseError(DWORD dwResponse)
Definition: ftp.c:3921
#define ERROR_INTERNET_EXTENDED_ERROR
Definition: wininet.h:1992
DWORD dwStructSize
Definition: wininet.h:211
#define ERROR_INTERNET_DISCONNECTED
Definition: wininet.h:2072
WORD wMonth
Definition: winbase.h:878
Definition: http.c:7098
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:2697
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:2951
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:3820
#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:2630
#define closesocket
Definition: precomp.h:57
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
Definition: internet.h:287
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:399
#define assert(x)
Definition: debug.h:53
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1642
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:2668
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:3485
static void AsyncFtpFindFirstFileProc(task_header_t *hdr)
Definition: ftp.c:733
static void FTPFINDNEXT_Destroy(object_header_t *hdr)
Definition: ftp.c:3434
__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:3484
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:415
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:419
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:405
#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:3269
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:3595
#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:2771
WORD wYear
Definition: winbase.h:877
DWORD nFileSizeLow
Definition: winbase.h:916
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:2904
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
#define MAX_REPLY_LEN
Definition: request.c:2568
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:3741
DWORD accessType
Definition: internet.h:298
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
#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:2834
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:882
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:177
WCHAR lpszDest[260]
SYSTEMTIME tmLastModified
Definition: ftp.c:90
static BOOL FTP_SendPortOrPasv(ftp_session_t *)
Definition: ftp.c:3209
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
_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:434
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:3395
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
static void FTPFINDNEXT_AsyncFindNextFileProc(task_header_t *hdr)
Definition: ftp.c:3488
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:50
DWORD index
Definition: ftp.c:98
DWORD INET_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
Definition: internet.c:2531
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:3632
struct list entry
Definition: internet.h:286
INTERNET_SCHEME nScheme
Definition: wininet.h:214
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
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:919
#define ERROR_FTP_TRANSFER_IN_PROGRESS
Definition: wininet.h:2046
#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:883
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:914
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:3238
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:111
static BOOL FTP_ParseDirectory(ftp_session_t *, INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERTIESW *lpafp, LPDWORD dwfp)
Definition: ftp.c:3793
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:913
#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:3777
#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:2874
#define ERROR_INTERNET_TIMEOUT
Definition: wininet.h:1991
HINTERNET hInternet
Definition: internet.h:276
static const object_vtbl_t FTPFINDNEXTVtbl
Definition: ftp.c:3530
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:3858
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:219
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:880
#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:158
static int sock_send(int fd, const void *msg, size_t len, int flags)
Definition: net.c:38
BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags, LPWSTR lpszUrl, LPDWORD lpdwUrlLength)
Definition: internet.c:4307
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
#define ioctlsocket
Definition: precomp.h:58
__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:881
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:911
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:3495
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:408
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:2751
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:3512
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:38
#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:3798
#define INET6_ADDRSTRLEN
Definition: ws2ipdef.h:132
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:3349
#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:912
static HINTERNET FTP_ReceiveFileList(ftp_session_t *, INT nSocket, LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext)
Definition: ftp.c:3551
#define htons(x)
Definition: module.h:213