2 * WININET - Ftp implementation
4 * Copyright 1999 Corel Corporation
5 * Copyright 2004 Mike McCormack for CodeWeavers
6 * Copyright 2004 Kevin Koltzau
11 * Copyright 2000 Andreas Mohr
12 * Copyright 2002 Jaco Greeff
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/port.h"
37 #include <sys/types.h>
38 #ifdef HAVE_SYS_SOCKET_H
39 # include <sys/socket.h>
58 #include "wine/debug.h"
61 WINE_DEFAULT_DEBUG_CHANNEL(wininet
);
63 #define DATA_PACKET_SIZE 0x2000
68 /* FTP commands with arguments. */
84 /* FTP commands without arguments. */
93 static const CHAR
*szFtpCommands
[] = {
116 static const CHAR szMonths
[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
117 static const WCHAR szNoAccount
[] = {'n','o','a','c','c','o','u','n','t','\0'};
119 static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr
);
120 static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr
);
121 static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr
);
122 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCWSTR lpszParam
,
123 INTERNET_STATUS_CALLBACK lpfnStatusCB
, LPWININETHANDLEHEADER hdr
, DWORD dwContext
);
124 BOOL
FTP_SendStore(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
);
125 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs
, LPINT nDataSocket
);
126 BOOL
FTP_SendData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, HANDLE hFile
);
127 INT
FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs
, DWORD dwContext
);
128 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
);
129 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
);
130 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs
);
131 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs
);
132 BOOL
FTP_SendPassword(LPWININETFTPSESSIONW lpwfs
);
133 BOOL
FTP_SendAccount(LPWININETFTPSESSIONW lpwfs
);
134 BOOL
FTP_SendType(LPWININETFTPSESSIONW lpwfs
, DWORD dwType
);
135 BOOL
FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD
*dwSize
);
136 BOOL
FTP_SendPort(LPWININETFTPSESSIONW lpwfs
);
137 BOOL
FTP_DoPassive(LPWININETFTPSESSIONW lpwfs
);
138 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs
);
139 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESW lpfp
);
140 BOOL
FTP_ParseNextFile(INT nSocket
, LPCWSTR lpszSearchFile
, LPFILEPROPERTIESW fileprop
);
141 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
142 LPFILEPROPERTIESW
*lpafp
, LPDWORD dwfp
);
143 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
144 LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwContext
);
145 DWORD
FTP_SetResponseError(DWORD dwResponse
);
147 /***********************************************************************
148 * FtpPutFileA (WININET.@)
150 * Uploads a file to the FTP server
157 BOOL WINAPI
FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
158 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
160 LPWSTR lpwzLocalFile
;
161 LPWSTR lpwzNewRemoteFile
;
164 lpwzLocalFile
= lpszLocalFile
?WININET_strdup_AtoW(lpszLocalFile
):NULL
;
165 lpwzNewRemoteFile
= lpszNewRemoteFile
?WININET_strdup_AtoW(lpszNewRemoteFile
):NULL
;
166 ret
= FtpPutFileW(hConnect
, lpwzLocalFile
, lpwzNewRemoteFile
,
168 HeapFree(GetProcessHeap(), 0, lpwzLocalFile
);
169 HeapFree(GetProcessHeap(), 0, lpwzNewRemoteFile
);
173 /***********************************************************************
174 * FtpPutFileW (WININET.@)
176 * Uploads a file to the FTP server
183 BOOL WINAPI
FtpPutFileW(HINTERNET hConnect
, LPCWSTR lpszLocalFile
,
184 LPCWSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
186 LPWININETFTPSESSIONW lpwfs
;
187 LPWININETAPPINFOW hIC
= NULL
;
190 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
191 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
193 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
197 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
198 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
200 WORKREQUEST workRequest
;
201 struct WORKREQ_FTPPUTFILEW
*req
= &workRequest
.u
.FtpPutFileW
;
203 workRequest
.asyncall
= FTPPUTFILEW
;
204 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
205 req
->lpszLocalFile
= WININET_strdupW(lpszLocalFile
);
206 req
->lpszNewRemoteFile
= WININET_strdupW(lpszNewRemoteFile
);
207 req
->dwFlags
= dwFlags
;
208 req
->dwContext
= dwContext
;
210 r
= INTERNET_AsyncCall(&workRequest
);
214 r
= FTP_FtpPutFileW(lpwfs
, lpszLocalFile
,
215 lpszNewRemoteFile
, dwFlags
, dwContext
);
220 WININET_Release( &lpwfs
->hdr
);
225 /***********************************************************************
226 * FTP_FtpPutFileW (Internal)
228 * Uploads a file to the FTP server
235 BOOL WINAPI
FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszLocalFile
,
236 LPCWSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
239 BOOL bSuccess
= FALSE
;
240 LPWININETAPPINFOW hIC
= NULL
;
243 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", debugstr_w(lpszLocalFile
), debugstr_w(lpszNewRemoteFile
));
245 if (!lpszLocalFile
|| !lpszNewRemoteFile
)
247 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
251 assert( WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
253 /* Clear any error information */
254 INTERNET_SetLastError(0);
256 /* Open file to be uploaded */
257 if (INVALID_HANDLE_VALUE
==
258 (hFile
= CreateFileW(lpszLocalFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0)))
260 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND
);
264 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
265 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
267 if (FTP_SendStore(lpwfs
, lpszNewRemoteFile
, dwFlags
))
271 /* Get data socket to server */
272 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
274 FTP_SendData(lpwfs
, nDataSocket
, hFile
);
275 closesocket(nDataSocket
);
276 nResCode
= FTP_ReceiveResponse(lpwfs
, dwContext
);
282 FTP_SetResponseError(nResCode
);
288 if (lpwfs
->lstnSocket
!= -1)
289 closesocket(lpwfs
->lstnSocket
);
291 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
293 INTERNET_ASYNC_RESULT iar
;
295 iar
.dwResult
= (DWORD
)bSuccess
;
296 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
297 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
298 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
308 /***********************************************************************
309 * FtpSetCurrentDirectoryA (WININET.@)
311 * Change the working directory on the FTP server
318 BOOL WINAPI
FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
320 LPWSTR lpwzDirectory
;
323 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
324 ret
= FtpSetCurrentDirectoryW(hConnect
, lpwzDirectory
);
325 HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
330 /***********************************************************************
331 * FtpSetCurrentDirectoryW (WININET.@)
333 * Change the working directory on the FTP server
340 BOOL WINAPI
FtpSetCurrentDirectoryW(HINTERNET hConnect
, LPCWSTR lpszDirectory
)
342 LPWININETFTPSESSIONW lpwfs
;
343 LPWININETAPPINFOW hIC
= NULL
;
346 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
347 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
349 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
353 TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory
));
355 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
356 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
358 WORKREQUEST workRequest
;
359 struct WORKREQ_FTPSETCURRENTDIRECTORYW
*req
;
361 workRequest
.asyncall
= FTPSETCURRENTDIRECTORYW
;
362 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
363 req
= &workRequest
.u
.FtpSetCurrentDirectoryW
;
364 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
366 r
= INTERNET_AsyncCall(&workRequest
);
370 r
= FTP_FtpSetCurrentDirectoryW(lpwfs
, lpszDirectory
);
375 WININET_Release( &lpwfs
->hdr
);
381 /***********************************************************************
382 * FTP_FtpSetCurrentDirectoryW (Internal)
384 * Change the working directory on the FTP server
391 BOOL WINAPI
FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszDirectory
)
394 LPWININETAPPINFOW hIC
= NULL
;
395 DWORD bSuccess
= FALSE
;
397 TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory
));
399 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
401 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
405 /* Clear any error information */
406 INTERNET_SetLastError(0);
408 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
409 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_CWD
, lpszDirectory
,
410 lpwfs
->hdr
.lpfnStatusCB
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
))
413 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
420 FTP_SetResponseError(nResCode
);
424 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
426 INTERNET_ASYNC_RESULT iar
;
428 iar
.dwResult
= (DWORD
)bSuccess
;
429 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
430 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
431 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
437 /***********************************************************************
438 * FtpCreateDirectoryA (WININET.@)
440 * Create new directory on the FTP server
447 BOOL WINAPI
FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
449 LPWSTR lpwzDirectory
;
452 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
453 ret
= FtpCreateDirectoryW(hConnect
, lpwzDirectory
);
454 HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
459 /***********************************************************************
460 * FtpCreateDirectoryW (WININET.@)
462 * Create new directory on the FTP server
469 BOOL WINAPI
FtpCreateDirectoryW(HINTERNET hConnect
, LPCWSTR lpszDirectory
)
471 LPWININETFTPSESSIONW lpwfs
;
472 LPWININETAPPINFOW hIC
= NULL
;
475 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
476 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
478 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
482 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
483 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
485 WORKREQUEST workRequest
;
486 struct WORKREQ_FTPCREATEDIRECTORYW
*req
;
488 workRequest
.asyncall
= FTPCREATEDIRECTORYW
;
489 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
490 req
= &workRequest
.u
.FtpCreateDirectoryW
;
491 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
493 r
= INTERNET_AsyncCall(&workRequest
);
497 r
= FTP_FtpCreateDirectoryW(lpwfs
, lpszDirectory
);
501 WININET_Release( &lpwfs
->hdr
);
507 /***********************************************************************
508 * FTP_FtpCreateDirectoryW (Internal)
510 * Create new directory on the FTP server
517 BOOL WINAPI
FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszDirectory
)
520 BOOL bSuccess
= FALSE
;
521 LPWININETAPPINFOW hIC
= NULL
;
523 TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory
));
525 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
527 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
531 /* Clear any error information */
532 INTERNET_SetLastError(0);
534 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_MKD
, lpszDirectory
, 0, 0, 0))
537 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
543 FTP_SetResponseError(nResCode
);
547 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
548 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
550 INTERNET_ASYNC_RESULT iar
;
552 iar
.dwResult
= (DWORD
)bSuccess
;
553 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
554 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
555 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
561 /***********************************************************************
562 * FtpFindFirstFileA (WININET.@)
564 * Search the specified directory
567 * HINTERNET on success
571 HINTERNET WINAPI
FtpFindFirstFileA(HINTERNET hConnect
,
572 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
574 LPWSTR lpwzSearchFile
;
575 WIN32_FIND_DATAW wfd
;
576 LPWIN32_FIND_DATAW lpFindFileDataW
;
579 lpwzSearchFile
= lpszSearchFile
?WININET_strdup_AtoW(lpszSearchFile
):NULL
;
580 lpFindFileDataW
= lpFindFileData
?&wfd
:NULL
;
581 ret
= FtpFindFirstFileW(hConnect
, lpwzSearchFile
, lpFindFileDataW
, dwFlags
, dwContext
);
582 HeapFree(GetProcessHeap(), 0, lpwzSearchFile
);
585 WININET_find_data_WtoA(lpFindFileDataW
, lpFindFileData
);
591 /***********************************************************************
592 * FtpFindFirstFileW (WININET.@)
594 * Search the specified directory
597 * HINTERNET on success
601 HINTERNET WINAPI
FtpFindFirstFileW(HINTERNET hConnect
,
602 LPCWSTR lpszSearchFile
, LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
604 LPWININETFTPSESSIONW lpwfs
;
605 LPWININETAPPINFOW hIC
= NULL
;
608 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
609 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
611 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
615 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
616 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
618 WORKREQUEST workRequest
;
619 struct WORKREQ_FTPFINDFIRSTFILEW
*req
;
621 workRequest
.asyncall
= FTPFINDFIRSTFILEW
;
622 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
623 req
= &workRequest
.u
.FtpFindFirstFileW
;
624 req
->lpszSearchFile
= (lpszSearchFile
== NULL
) ? NULL
: WININET_strdupW(lpszSearchFile
);
625 req
->lpFindFileData
= lpFindFileData
;
626 req
->dwFlags
= dwFlags
;
627 req
->dwContext
= dwContext
;
629 INTERNET_AsyncCall(&workRequest
);
634 r
= FTP_FtpFindFirstFileW(lpwfs
, lpszSearchFile
, lpFindFileData
,
639 WININET_Release( &lpwfs
->hdr
);
645 /***********************************************************************
646 * FTP_FtpFindFirstFileW (Internal)
648 * Search the specified directory
651 * HINTERNET on success
655 HINTERNET WINAPI
FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs
,
656 LPCWSTR lpszSearchFile
, LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
659 LPWININETAPPINFOW hIC
= NULL
;
660 HINTERNET hFindNext
= NULL
;
664 assert(WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
666 /* Clear any error information */
667 INTERNET_SetLastError(0);
669 if (!FTP_InitListenSocket(lpwfs
))
672 if (!FTP_SendType(lpwfs
, INTERNET_FLAG_TRANSFER_ASCII
))
675 if (!FTP_SendPortOrPasv(lpwfs
))
678 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
679 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_LIST
, NULL
,
680 lpwfs
->hdr
.lpfnStatusCB
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
))
683 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
686 if (nResCode
== 125 || nResCode
== 150)
690 /* Get data socket to server */
691 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
693 hFindNext
= FTP_ReceiveFileList(lpwfs
, nDataSocket
, lpszSearchFile
, lpFindFileData
, dwContext
);
694 closesocket(nDataSocket
);
695 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
696 if (nResCode
!= 226 && nResCode
!= 250)
697 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
701 FTP_SetResponseError(nResCode
);
705 if (lpwfs
->lstnSocket
!= -1)
706 closesocket(lpwfs
->lstnSocket
);
708 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
710 INTERNET_ASYNC_RESULT iar
;
714 iar
.dwResult
= (DWORD
)hFindNext
;
715 iar
.dwError
= ERROR_SUCCESS
;
716 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
717 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
720 iar
.dwResult
= (DWORD
)hFindNext
;
721 iar
.dwError
= hFindNext
? ERROR_SUCCESS
: INTERNET_GetLastError();
722 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
723 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
730 /***********************************************************************
731 * FtpGetCurrentDirectoryA (WININET.@)
733 * Retrieves the current directory
740 BOOL WINAPI
FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
741 LPDWORD lpdwCurrentDirectory
)
747 if(lpdwCurrentDirectory
) len
= *lpdwCurrentDirectory
;
748 ret
= FtpGetCurrentDirectoryW(hFtpSession
, lpszCurrentDirectory
?dir
:NULL
, lpdwCurrentDirectory
?&len
:NULL
);
749 if(lpdwCurrentDirectory
) {
750 *lpdwCurrentDirectory
= len
;
751 if(lpszCurrentDirectory
)
752 WideCharToMultiByte(CP_ACP
, 0, dir
, len
, lpszCurrentDirectory
, *lpdwCurrentDirectory
, NULL
, NULL
);
758 /***********************************************************************
759 * FtpGetCurrentDirectoryW (WININET.@)
761 * Retrieves the current directory
768 BOOL WINAPI
FtpGetCurrentDirectoryW(HINTERNET hFtpSession
, LPWSTR lpszCurrentDirectory
,
769 LPDWORD lpdwCurrentDirectory
)
771 LPWININETFTPSESSIONW lpwfs
;
772 LPWININETAPPINFOW hIC
= NULL
;
775 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
777 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
778 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
780 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
784 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
785 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
787 WORKREQUEST workRequest
;
788 struct WORKREQ_FTPGETCURRENTDIRECTORYW
*req
;
790 workRequest
.asyncall
= FTPGETCURRENTDIRECTORYW
;
791 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
792 req
= &workRequest
.u
.FtpGetCurrentDirectoryW
;
793 req
->lpszDirectory
= lpszCurrentDirectory
;
794 req
->lpdwDirectory
= lpdwCurrentDirectory
;
796 r
= INTERNET_AsyncCall(&workRequest
);
800 r
= FTP_FtpGetCurrentDirectoryW(lpwfs
, lpszCurrentDirectory
,
801 lpdwCurrentDirectory
);
806 WININET_Release( &lpwfs
->hdr
);
812 /***********************************************************************
813 * FTP_FtpGetCurrentDirectoryA (Internal)
815 * Retrieves the current directory
822 BOOL WINAPI
FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs
, LPWSTR lpszCurrentDirectory
,
823 LPDWORD lpdwCurrentDirectory
)
826 LPWININETAPPINFOW hIC
= NULL
;
827 DWORD bSuccess
= FALSE
;
829 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
831 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
833 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
837 /* Clear any error information */
838 INTERNET_SetLastError(0);
840 ZeroMemory(lpszCurrentDirectory
, *lpdwCurrentDirectory
);
842 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
843 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PWD
, NULL
,
844 lpwfs
->hdr
.lpfnStatusCB
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
))
847 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
850 if (nResCode
== 257) /* Extract directory name */
852 DWORD firstpos
, lastpos
, len
;
853 LPWSTR lpszResponseBuffer
= WININET_strdup_AtoW(INTERNET_GetResponseBuffer());
855 for (firstpos
= 0, lastpos
= 0; lpszResponseBuffer
[lastpos
]; lastpos
++)
857 if ('"' == lpszResponseBuffer
[lastpos
])
866 len
= lastpos
- firstpos
- 1;
867 lstrcpynW(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1], *lpdwCurrentDirectory
);
868 HeapFree(GetProcessHeap(), 0, lpszResponseBuffer
);
869 *lpdwCurrentDirectory
= len
;
873 FTP_SetResponseError(nResCode
);
877 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
879 INTERNET_ASYNC_RESULT iar
;
881 iar
.dwResult
= (DWORD
)bSuccess
;
882 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
883 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
884 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
887 return (DWORD
) bSuccess
;
890 /***********************************************************************
891 * FtpOpenFileA (WININET.@)
893 * Open a remote file for writing or reading
896 * HINTERNET handle on success
900 HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
901 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
907 lpwzFileName
= lpszFileName
?WININET_strdup_AtoW(lpszFileName
):NULL
;
908 ret
= FtpOpenFileW(hFtpSession
, lpwzFileName
, fdwAccess
, dwFlags
, dwContext
);
909 HeapFree(GetProcessHeap(), 0, lpwzFileName
);
914 /***********************************************************************
915 * FtpOpenFileW (WININET.@)
917 * Open a remote file for writing or reading
920 * HINTERNET handle on success
924 HINTERNET WINAPI
FtpOpenFileW(HINTERNET hFtpSession
,
925 LPCWSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
928 LPWININETFTPSESSIONW lpwfs
;
929 LPWININETAPPINFOW hIC
= NULL
;
932 TRACE("(%p,%s,0x%08lx,0x%08lx,0x%08lx)\n", hFtpSession
,
933 debugstr_w(lpszFileName
), fdwAccess
, dwFlags
, dwContext
);
935 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
936 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
938 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
942 if (lpwfs
->download_in_progress
!= NULL
) {
943 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
946 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
947 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
949 WORKREQUEST workRequest
;
950 struct WORKREQ_FTPOPENFILEW
*req
;
952 workRequest
.asyncall
= FTPOPENFILEW
;
953 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
954 req
= &workRequest
.u
.FtpOpenFileW
;
955 req
->lpszFilename
= WININET_strdupW(lpszFileName
);
956 req
->dwAccess
= fdwAccess
;
957 req
->dwFlags
= dwFlags
;
958 req
->dwContext
= dwContext
;
960 INTERNET_AsyncCall(&workRequest
);
965 r
= FTP_FtpOpenFileW(lpwfs
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
970 WININET_Release( &lpwfs
->hdr
);
976 /***********************************************************************
977 * FTP_FtpOpenFileW (Internal)
979 * Open a remote file for writing or reading
982 * HINTERNET handle on success
986 HINTERNET
FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs
,
987 LPCWSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
991 BOOL bSuccess
= FALSE
;
992 LPWININETFILE lpwh
= NULL
;
993 LPWININETAPPINFOW hIC
= NULL
;
994 HINTERNET handle
= NULL
;
998 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1000 /* Clear any error information */
1001 INTERNET_SetLastError(0);
1003 if (GENERIC_READ
== fdwAccess
)
1005 /* Set up socket to retrieve data */
1006 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
1008 else if (GENERIC_WRITE
== fdwAccess
)
1010 /* Set up socket to send data */
1011 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
1014 /* Get data socket to server */
1015 if (bSuccess
&& FTP_GetDataSocket(lpwfs
, &nDataSocket
))
1017 lpwh
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
1018 lpwh
->hdr
.htype
= WH_HFILE
;
1019 lpwh
->hdr
.dwFlags
= dwFlags
;
1020 lpwh
->hdr
.dwContext
= dwContext
;
1021 lpwh
->hdr
.lpwhparent
= WININET_AddRef( &lpwfs
->hdr
);
1022 lpwh
->hdr
.dwRefCount
= 1;
1023 lpwh
->hdr
.destroy
= FTP_CloseFileTransferHandle
;
1024 lpwh
->hdr
.lpfnStatusCB
= lpwfs
->hdr
.lpfnStatusCB
;
1025 lpwh
->nDataSocket
= nDataSocket
;
1026 lpwh
->session_deleted
= FALSE
;
1028 handle
= WININET_AllocHandle( &lpwh
->hdr
);
1032 /* Indicate that a download is currently in progress */
1033 lpwfs
->download_in_progress
= lpwh
;
1036 if (lpwfs
->lstnSocket
!= -1)
1037 closesocket(lpwfs
->lstnSocket
);
1039 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1040 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1042 INTERNET_ASYNC_RESULT iar
;
1046 iar
.dwResult
= (DWORD
)handle
;
1047 iar
.dwError
= ERROR_SUCCESS
;
1048 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1049 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1052 iar
.dwResult
= (DWORD
)bSuccess
;
1053 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1054 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1055 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1060 WININET_Release( &lpwh
->hdr
);
1066 /***********************************************************************
1067 * FtpGetFileA (WININET.@)
1069 * Retrieve file from the FTP server
1076 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
1077 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1080 LPWSTR lpwzRemoteFile
;
1084 lpwzRemoteFile
= lpszRemoteFile
?WININET_strdup_AtoW(lpszRemoteFile
):NULL
;
1085 lpwzNewFile
= lpszNewFile
?WININET_strdup_AtoW(lpszNewFile
):NULL
;
1086 ret
= FtpGetFileW(hInternet
, lpwzRemoteFile
, lpwzNewFile
, fFailIfExists
,
1087 dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
1088 HeapFree(GetProcessHeap(), 0, lpwzRemoteFile
);
1089 HeapFree(GetProcessHeap(), 0, lpwzNewFile
);
1094 /***********************************************************************
1095 * FtpGetFileW (WININET.@)
1097 * Retrieve file from the FTP server
1104 BOOL WINAPI
FtpGetFileW(HINTERNET hInternet
, LPCWSTR lpszRemoteFile
, LPCWSTR lpszNewFile
,
1105 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1108 LPWININETFTPSESSIONW lpwfs
;
1109 LPWININETAPPINFOW hIC
= NULL
;
1112 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hInternet
);
1113 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1115 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1119 if (lpwfs
->download_in_progress
!= NULL
) {
1120 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
1124 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1125 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1127 WORKREQUEST workRequest
;
1128 struct WORKREQ_FTPGETFILEW
*req
;
1130 workRequest
.asyncall
= FTPGETFILEW
;
1131 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1132 req
= &workRequest
.u
.FtpGetFileW
;
1133 req
->lpszRemoteFile
= WININET_strdupW(lpszRemoteFile
);
1134 req
->lpszNewFile
= WININET_strdupW(lpszNewFile
);
1135 req
->dwLocalFlagsAttribute
= dwLocalFlagsAttribute
;
1136 req
->fFailIfExists
= fFailIfExists
;
1137 req
->dwFlags
= dwInternetFlags
;
1138 req
->dwContext
= dwContext
;
1140 r
= INTERNET_AsyncCall(&workRequest
);
1144 r
= FTP_FtpGetFileW(lpwfs
, lpszRemoteFile
, lpszNewFile
,
1145 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
1150 WININET_Release( &lpwfs
->hdr
);
1156 /***********************************************************************
1157 * FTP_FtpGetFileW (Internal)
1159 * Retrieve file from the FTP server
1166 BOOL WINAPI
FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, LPCWSTR lpszNewFile
,
1167 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1171 BOOL bSuccess
= FALSE
;
1173 LPWININETAPPINFOW hIC
= NULL
;
1175 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", debugstr_w(lpszRemoteFile
), debugstr_w(lpszNewFile
));
1177 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1179 /* Clear any error information */
1180 INTERNET_SetLastError(0);
1182 /* Ensure we can write to lpszNewfile by opening it */
1183 hFile
= CreateFileW(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
1184 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
1185 if (INVALID_HANDLE_VALUE
== hFile
)
1188 /* Set up socket to retrieve data */
1189 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
1195 /* Get data socket to server */
1196 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
1201 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
1202 nResCode
= FTP_ReceiveResponse(lpwfs
, dwContext
);
1205 if (nResCode
== 226)
1208 FTP_SetResponseError(nResCode
);
1210 closesocket(nDataSocket
);
1215 if (lpwfs
->lstnSocket
!= -1)
1216 closesocket(lpwfs
->lstnSocket
);
1221 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1222 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1224 INTERNET_ASYNC_RESULT iar
;
1226 iar
.dwResult
= (DWORD
)bSuccess
;
1227 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1228 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1229 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1235 /***********************************************************************
1236 * FtpGetFileSize (WININET.@)
1238 DWORD WINAPI
FtpGetFileSize( HINTERNET hFile
, LPDWORD lpdwFileSizeHigh
)
1240 FIXME("(%p, %p)\n", hFile
, lpdwFileSizeHigh
);
1242 if (lpdwFileSizeHigh
)
1243 *lpdwFileSizeHigh
= 0;
1248 /***********************************************************************
1249 * FtpDeleteFileA (WININET.@)
1251 * Delete a file on the ftp server
1258 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
1260 LPWSTR lpwzFileName
;
1263 lpwzFileName
= lpszFileName
?WININET_strdup_AtoW(lpszFileName
):NULL
;
1264 ret
= FtpDeleteFileW(hFtpSession
, lpwzFileName
);
1265 HeapFree(GetProcessHeap(), 0, lpwzFileName
);
1269 /***********************************************************************
1270 * FtpDeleteFileW (WININET.@)
1272 * Delete a file on the ftp server
1279 BOOL WINAPI
FtpDeleteFileW(HINTERNET hFtpSession
, LPCWSTR lpszFileName
)
1281 LPWININETFTPSESSIONW lpwfs
;
1282 LPWININETAPPINFOW hIC
= NULL
;
1285 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1286 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1288 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1292 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1293 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1295 WORKREQUEST workRequest
;
1296 struct WORKREQ_FTPDELETEFILEW
*req
;
1298 workRequest
.asyncall
= FTPDELETEFILEW
;
1299 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1300 req
= &workRequest
.u
.FtpDeleteFileW
;
1301 req
->lpszFilename
= WININET_strdupW(lpszFileName
);
1303 r
= INTERNET_AsyncCall(&workRequest
);
1307 r
= FTP_FtpDeleteFileW(hFtpSession
, lpszFileName
);
1312 WININET_Release( &lpwfs
->hdr
);
1317 /***********************************************************************
1318 * FTP_FtpDeleteFileW (Internal)
1320 * Delete a file on the ftp server
1327 BOOL
FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszFileName
)
1330 BOOL bSuccess
= FALSE
;
1331 LPWININETAPPINFOW hIC
= NULL
;
1333 TRACE("%p\n", lpwfs
);
1335 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1337 /* Clear any error information */
1338 INTERNET_SetLastError(0);
1340 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1343 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1346 if (nResCode
== 250)
1349 FTP_SetResponseError(nResCode
);
1352 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1353 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1355 INTERNET_ASYNC_RESULT iar
;
1357 iar
.dwResult
= (DWORD
)bSuccess
;
1358 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1359 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1360 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1367 /***********************************************************************
1368 * FtpRemoveDirectoryA (WININET.@)
1370 * Remove a directory on the ftp server
1377 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1379 LPWSTR lpwzDirectory
;
1382 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
1383 ret
= FtpRemoveDirectoryW(hFtpSession
, lpwzDirectory
);
1384 HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
1388 /***********************************************************************
1389 * FtpRemoveDirectoryW (WININET.@)
1391 * Remove a directory on the ftp server
1398 BOOL WINAPI
FtpRemoveDirectoryW(HINTERNET hFtpSession
, LPCWSTR lpszDirectory
)
1400 LPWININETFTPSESSIONW lpwfs
;
1401 LPWININETAPPINFOW hIC
= NULL
;
1404 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1405 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1407 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1411 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1412 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1414 WORKREQUEST workRequest
;
1415 struct WORKREQ_FTPREMOVEDIRECTORYW
*req
;
1417 workRequest
.asyncall
= FTPREMOVEDIRECTORYW
;
1418 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1419 req
= &workRequest
.u
.FtpRemoveDirectoryW
;
1420 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
1422 r
= INTERNET_AsyncCall(&workRequest
);
1426 r
= FTP_FtpRemoveDirectoryW(lpwfs
, lpszDirectory
);
1431 WININET_Release( &lpwfs
->hdr
);
1436 /***********************************************************************
1437 * FTP_FtpRemoveDirectoryW (Internal)
1439 * Remove a directory on the ftp server
1446 BOOL
FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszDirectory
)
1449 BOOL bSuccess
= FALSE
;
1450 LPWININETAPPINFOW hIC
= NULL
;
1454 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1456 /* Clear any error information */
1457 INTERNET_SetLastError(0);
1459 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1462 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1465 if (nResCode
== 250)
1468 FTP_SetResponseError(nResCode
);
1472 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1473 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1475 INTERNET_ASYNC_RESULT iar
;
1477 iar
.dwResult
= (DWORD
)bSuccess
;
1478 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1479 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1480 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1487 /***********************************************************************
1488 * FtpRenameFileA (WININET.@)
1490 * Rename a file on the ftp server
1497 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1503 lpwzSrc
= lpszSrc
?WININET_strdup_AtoW(lpszSrc
):NULL
;
1504 lpwzDest
= lpszDest
?WININET_strdup_AtoW(lpszDest
):NULL
;
1505 ret
= FtpRenameFileW(hFtpSession
, lpwzSrc
, lpwzDest
);
1506 HeapFree(GetProcessHeap(), 0, lpwzSrc
);
1507 HeapFree(GetProcessHeap(), 0, lpwzDest
);
1511 /***********************************************************************
1512 * FtpRenameFileW (WININET.@)
1514 * Rename a file on the ftp server
1521 BOOL WINAPI
FtpRenameFileW(HINTERNET hFtpSession
, LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1523 LPWININETFTPSESSIONW lpwfs
;
1524 LPWININETAPPINFOW hIC
= NULL
;
1527 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1528 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1530 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1534 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1535 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1537 WORKREQUEST workRequest
;
1538 struct WORKREQ_FTPRENAMEFILEW
*req
;
1540 workRequest
.asyncall
= FTPRENAMEFILEW
;
1541 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1542 req
= &workRequest
.u
.FtpRenameFileW
;
1543 req
->lpszSrcFile
= WININET_strdupW(lpszSrc
);
1544 req
->lpszDestFile
= WININET_strdupW(lpszDest
);
1546 r
= INTERNET_AsyncCall(&workRequest
);
1550 r
= FTP_FtpRenameFileW(hFtpSession
, lpszSrc
, lpszDest
);
1555 WININET_Release( &lpwfs
->hdr
);
1560 /***********************************************************************
1561 * FTP_FtpRenameFileA (Internal)
1563 * Rename a file on the ftp server
1570 BOOL
FTP_FtpRenameFileW( LPWININETFTPSESSIONW lpwfs
,
1571 LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1574 BOOL bSuccess
= FALSE
;
1575 LPWININETAPPINFOW hIC
= NULL
;
1579 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1581 /* Clear any error information */
1582 INTERNET_SetLastError(0);
1584 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1587 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1588 if (nResCode
== 350)
1590 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1593 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1596 if (nResCode
== 250)
1599 FTP_SetResponseError(nResCode
);
1602 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1603 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1605 INTERNET_ASYNC_RESULT iar
;
1607 iar
.dwResult
= (DWORD
)bSuccess
;
1608 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1609 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1610 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1616 /***********************************************************************
1617 * FtpCommandA (WININET.@)
1619 BOOL WINAPI
FtpCommandA( HINTERNET hConnect
, BOOL fExpectResponse
, DWORD dwFlags
,
1620 LPCSTR lpszCommand
, DWORD_PTR dwContext
, HINTERNET
* phFtpCommand
)
1622 FIXME("%p %d 0x%08lx %s 0x%08lx %p\n", hConnect
, fExpectResponse
, dwFlags
,
1623 debugstr_a(lpszCommand
), dwContext
, phFtpCommand
);
1628 /***********************************************************************
1629 * FtpCommandW (WININET.@)
1631 BOOL WINAPI
FtpCommandW( HINTERNET hConnect
, BOOL fExpectResponse
, DWORD dwFlags
,
1632 LPCWSTR lpszCommand
, DWORD_PTR dwContext
, HINTERNET
* phFtpCommand
)
1634 FIXME("%p %d 0x%08lx %s 0x%08lx %p\n", hConnect
, fExpectResponse
, dwFlags
,
1635 debugstr_w(lpszCommand
), dwContext
, phFtpCommand
);
1640 /***********************************************************************
1641 * FTP_Connect (internal)
1643 * Connect to a ftp server
1646 * HINTERNET a session handle on success
1651 HINTERNET
FTP_Connect(LPWININETAPPINFOW hIC
, LPCWSTR lpszServerName
,
1652 INTERNET_PORT nServerPort
, LPCWSTR lpszUserName
,
1653 LPCWSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
,
1654 DWORD dwInternalFlags
)
1656 static const WCHAR szDefaultUsername
[] = {'a','n','o','n','y','m','o','u','s','\0'};
1657 static const WCHAR szDefaultPassword
[] = {'u','s','e','r','@','s','e','r','v','e','r','\0'};
1658 struct sockaddr_in socketAddr
;
1659 struct hostent
*phe
= NULL
;
1662 BOOL bSuccess
= FALSE
;
1663 LPWININETFTPSESSIONW lpwfs
= NULL
;
1664 HINTERNET handle
= NULL
;
1666 TRACE("%p Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1667 hIC
, debugstr_w(lpszServerName
),
1668 nServerPort
, debugstr_w(lpszUserName
), debugstr_w(lpszPassword
));
1670 assert( hIC
->hdr
.htype
== WH_HINIT
);
1672 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1674 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
1678 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONW
));
1681 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1685 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1686 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1688 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1689 lpwfs
->hdr
.lpwhparent
= WININET_AddRef( &hIC
->hdr
);
1690 lpwfs
->hdr
.dwFlags
= dwFlags
;
1691 lpwfs
->hdr
.dwContext
= dwContext
;
1692 lpwfs
->hdr
.dwInternalFlags
= dwInternalFlags
;
1693 lpwfs
->hdr
.dwRefCount
= 1;
1694 lpwfs
->hdr
.destroy
= FTP_CloseSessionHandle
;
1695 lpwfs
->hdr
.lpfnStatusCB
= hIC
->hdr
.lpfnStatusCB
;
1696 lpwfs
->download_in_progress
= NULL
;
1698 handle
= WININET_AllocHandle( &lpwfs
->hdr
);
1701 ERR("Failed to alloc handle\n");
1702 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1706 if(hIC
->lpszProxy
&& hIC
->dwAccessType
== INTERNET_OPEN_TYPE_PROXY
) {
1707 if(strchrW(hIC
->lpszProxy
, ' '))
1708 FIXME("Several proxies not implemented.\n");
1709 if(hIC
->lpszProxyBypass
)
1710 FIXME("Proxy bypass is ignored.\n");
1712 if ( !lpszUserName
) {
1713 lpwfs
->lpszUserName
= WININET_strdupW(szDefaultUsername
);
1714 lpwfs
->lpszPassword
= WININET_strdupW(szDefaultPassword
);
1717 lpwfs
->lpszUserName
= WININET_strdupW(lpszUserName
);
1718 lpwfs
->lpszPassword
= WININET_strdupW(lpszPassword
);
1721 /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
1722 if (!(lpwfs
->hdr
.dwInternalFlags
& INET_OPENURL
))
1724 INTERNET_ASYNC_RESULT iar
;
1726 iar
.dwResult
= (DWORD
)handle
;
1727 iar
.dwError
= ERROR_SUCCESS
;
1729 SendAsyncCallback(&hIC
->hdr
, dwContext
,
1730 INTERNET_STATUS_HANDLE_CREATED
, &iar
,
1731 sizeof(INTERNET_ASYNC_RESULT
));
1734 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1735 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1737 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1739 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1743 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1744 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1746 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
1749 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1753 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1754 &socketAddr
, sizeof(struct sockaddr_in
));
1756 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1758 ERR("Unable to connect (%s)\n", strerror(errno
));
1759 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1763 TRACE("Connected to server\n");
1764 lpwfs
->sndSocket
= nsocket
;
1765 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1766 &socketAddr
, sizeof(struct sockaddr_in
));
1768 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1769 getsockname(nsocket
, (struct sockaddr
*) &lpwfs
->socketAddress
, &sock_namelen
);
1770 lpwfs
->phostent
= phe
;
1772 if (FTP_ConnectToHost(lpwfs
))
1774 TRACE("Successfully logged into server\n");
1780 if (!bSuccess
&& nsocket
== -1)
1781 closesocket(nsocket
);
1783 if (!bSuccess
&& lpwfs
)
1785 HeapFree(GetProcessHeap(), 0, lpwfs
);
1786 WININET_FreeHandle( handle
);
1790 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1792 INTERNET_ASYNC_RESULT iar
;
1794 iar
.dwResult
= (DWORD
)lpwfs
;
1795 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1796 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1797 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1804 /***********************************************************************
1805 * FTP_ConnectToHost (internal)
1807 * Connect to a ftp server
1814 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs
)
1817 BOOL bSuccess
= FALSE
;
1820 FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1822 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1825 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1828 /* Login successful... */
1829 if (nResCode
== 230)
1831 /* User name okay, need password... */
1832 else if (nResCode
== 331)
1833 bSuccess
= FTP_SendPassword(lpwfs
);
1834 /* Need account for login... */
1835 else if (nResCode
== 332)
1836 bSuccess
= FTP_SendAccount(lpwfs
);
1838 FTP_SetResponseError(nResCode
);
1841 TRACE("Returning %d\n", bSuccess
);
1847 /***********************************************************************
1848 * FTP_SendCommandA (internal)
1850 * Send command to server
1857 BOOL
FTP_SendCommandA(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1858 INTERNET_STATUS_CALLBACK lpfnStatusCB
, LPWININETHANDLEHEADER hdr
, DWORD dwContext
)
1862 DWORD nBytesSent
= 0;
1866 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1870 HINTERNET hHandle
= WININET_FindHandle( hdr
);
1873 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1874 WININET_Release( hdr
);
1878 dwParamLen
= lpszParam
?strlen(lpszParam
)+1:0;
1879 len
= dwParamLen
+ strlen(szFtpCommands
[ftpCmd
]) + strlen(szCRLF
);
1880 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1882 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1885 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], dwParamLen
? " " : "",
1886 dwParamLen
? lpszParam
: "", szCRLF
);
1888 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1889 while((nBytesSent
< len
) && (nRC
!= -1))
1891 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1895 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1899 HINTERNET hHandle
= WININET_FindHandle( hdr
);
1902 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1903 &nBytesSent
, sizeof(DWORD
));
1904 WININET_Release( hdr
);
1908 TRACE("Sent %ld bytes\n", nBytesSent
);
1912 /***********************************************************************
1913 * FTP_SendCommand (internal)
1915 * Send command to server
1922 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCWSTR lpszParam
,
1923 INTERNET_STATUS_CALLBACK lpfnStatusCB
, LPWININETHANDLEHEADER hdr
, DWORD dwContext
)
1926 LPSTR lpszParamA
= lpszParam
?WININET_strdup_WtoA(lpszParam
):NULL
;
1927 ret
= FTP_SendCommandA(nSocket
, ftpCmd
, lpszParamA
, lpfnStatusCB
, hdr
, dwContext
);
1928 HeapFree(GetProcessHeap(), 0, lpszParamA
);
1932 /***********************************************************************
1933 * FTP_ReceiveResponse (internal)
1935 * Receive response from server
1938 * Reply code on success
1942 INT
FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs
, DWORD dwContext
)
1944 LPSTR lpszResponse
= INTERNET_GetResponseBuffer();
1947 char firstprefix
[5];
1948 BOOL multiline
= FALSE
;
1949 LPWININETAPPINFOW hIC
= NULL
;
1951 TRACE("socket(%d) \n", lpwfs
->sndSocket
);
1953 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1954 SendAsyncCallback(&lpwfs
->hdr
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1958 if (!INTERNET_GetNextLine(lpwfs
->sndSocket
, &nRecv
))
1965 if(lpszResponse
[3] != '-')
1968 { /* Start of multiline repsonse. Loop until we get "nnn " */
1970 memcpy(firstprefix
, lpszResponse
, 3);
1971 firstprefix
[3] = ' ';
1972 firstprefix
[4] = '\0';
1977 if(!memcmp(firstprefix
, lpszResponse
, 4))
1985 rc
= atoi(lpszResponse
);
1987 SendAsyncCallback(&lpwfs
->hdr
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1988 &nRecv
, sizeof(DWORD
));
1992 TRACE("return %d\n", rc
);
1997 /***********************************************************************
1998 * FTP_SendPassword (internal)
2000 * Send password to ftp server
2007 BOOL
FTP_SendPassword(LPWININETFTPSESSIONW lpwfs
)
2010 BOOL bSuccess
= FALSE
;
2013 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
2016 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2019 TRACE("Received reply code %d\n", nResCode
);
2020 /* Login successful... */
2021 if (nResCode
== 230)
2023 /* Command not implemented, superfluous at the server site... */
2024 /* Need account for login... */
2025 else if (nResCode
== 332)
2026 bSuccess
= FTP_SendAccount(lpwfs
);
2028 FTP_SetResponseError(nResCode
);
2032 TRACE("Returning %d\n", bSuccess
);
2037 /***********************************************************************
2038 * FTP_SendAccount (internal)
2047 BOOL
FTP_SendAccount(LPWININETFTPSESSIONW lpwfs
)
2050 BOOL bSuccess
= FALSE
;
2053 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, szNoAccount
, 0, 0, 0))
2056 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2060 FTP_SetResponseError(nResCode
);
2067 /***********************************************************************
2068 * FTP_SendStore (internal)
2070 * Send request to upload file to ftp server
2077 BOOL
FTP_SendStore(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
2080 BOOL bSuccess
= FALSE
;
2083 if (!FTP_InitListenSocket(lpwfs
))
2086 if (!FTP_SendType(lpwfs
, dwType
))
2089 if (!FTP_SendPortOrPasv(lpwfs
))
2092 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
2094 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2097 if (nResCode
== 150)
2100 FTP_SetResponseError(nResCode
);
2104 if (!bSuccess
&& lpwfs
->lstnSocket
!= -1)
2106 closesocket(lpwfs
->lstnSocket
);
2107 lpwfs
->lstnSocket
= -1;
2114 /***********************************************************************
2115 * FTP_InitListenSocket (internal)
2117 * Create a socket to listen for server response
2124 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs
)
2126 BOOL bSuccess
= FALSE
;
2127 size_t namelen
= sizeof(struct sockaddr_in
);
2131 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
2132 if (lpwfs
->lstnSocket
== -1)
2134 TRACE("Unable to create listening socket\n");
2138 /* We obtain our ip addr from the name of the command channel socket */
2139 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
2141 /* and get the system to assign us a port */
2142 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
2144 if (bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)) == -1)
2146 TRACE("Unable to bind socket\n");
2150 if (listen(lpwfs
->lstnSocket
, MAX_BACKLOG
) == -1)
2152 TRACE("listen failed\n");
2156 if (getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
) != -1)
2160 if (!bSuccess
&& lpwfs
->lstnSocket
== -1)
2162 closesocket(lpwfs
->lstnSocket
);
2163 lpwfs
->lstnSocket
= -1;
2170 /***********************************************************************
2171 * FTP_SendType (internal)
2173 * Tell server type of data being transferred
2179 * W98SE doesn't cache the type that's currently set
2180 * (i.e. it sends it always),
2181 * so we probably don't want to do that either.
2183 BOOL
FTP_SendType(LPWININETFTPSESSIONW lpwfs
, DWORD dwType
)
2186 WCHAR type
[] = { 'I','\0' };
2187 BOOL bSuccess
= FALSE
;
2190 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
2193 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
2196 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
)/100;
2202 FTP_SetResponseError(nResCode
);
2209 /***********************************************************************
2210 * FTP_GetFileSize (internal)
2212 * Retrieves from the server the size of the given file
2219 BOOL
FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD
*dwSize
)
2222 BOOL bSuccess
= FALSE
;
2226 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_SIZE
, lpszRemoteFile
, 0, 0, 0))
2229 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2232 if (nResCode
== 213) {
2233 /* Now parses the output to get the actual file size */
2235 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2237 for (i
= 0; (lpszResponseBuffer
[i
] != ' ') && (lpszResponseBuffer
[i
] != '\0'); i
++) ;
2238 if (lpszResponseBuffer
[i
] == '\0') return FALSE
;
2239 *dwSize
= atol(&(lpszResponseBuffer
[i
+ 1]));
2243 FTP_SetResponseError(nResCode
);
2252 /***********************************************************************
2253 * FTP_SendPort (internal)
2255 * Tell server which port to use
2262 BOOL
FTP_SendPort(LPWININETFTPSESSIONW lpwfs
)
2264 static const WCHAR szIPFormat
[] = {'%','d',',','%','d',',','%','d',',','%','d',',','%','d',',','%','d','\0'};
2266 WCHAR szIPAddress
[64];
2267 BOOL bSuccess
= FALSE
;
2270 sprintfW(szIPAddress
, szIPFormat
,
2271 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
2272 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
2273 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
2274 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
2275 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
2276 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
2278 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
2281 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2284 if (nResCode
== 200)
2287 FTP_SetResponseError(nResCode
);
2295 /***********************************************************************
2296 * FTP_DoPassive (internal)
2298 * Tell server that we want to do passive transfers
2299 * and connect data socket
2306 BOOL
FTP_DoPassive(LPWININETFTPSESSIONW lpwfs
)
2309 BOOL bSuccess
= FALSE
;
2312 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASV
, NULL
, 0, 0, 0))
2315 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2318 if (nResCode
== 227)
2320 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2324 char *pAddr
, *pPort
;
2326 struct sockaddr_in dataSocketAddress
;
2328 p
= lpszResponseBuffer
+4; /* skip status code */
2330 /* do a very strict check; we can improve that later. */
2332 if (strncmp(p
, "Entering Passive Mode", 21))
2334 ERR("unknown response '%.*s', aborting\n", 21, p
);
2337 p
+= 21; /* skip string */
2338 if ((*p
++ != ' ') || (*p
++ != '('))
2340 ERR("unknown response format, aborting\n");
2344 if (sscanf(p
, "%d,%d,%d,%d,%d,%d", &f
[0], &f
[1], &f
[2], &f
[3],
2347 ERR("unknown response address format '%s', aborting\n", p
);
2350 for (i
=0; i
< 6; i
++)
2353 dataSocketAddress
= lpwfs
->socketAddress
;
2354 pAddr
= (char *)&(dataSocketAddress
.sin_addr
.s_addr
);
2355 pPort
= (char *)&(dataSocketAddress
.sin_port
);
2363 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
2367 if (connect(nsocket
, (struct sockaddr
*)&dataSocketAddress
, sizeof(dataSocketAddress
)))
2369 ERR("can't connect passive FTP data port.\n");
2372 lpwfs
->pasvSocket
= nsocket
;
2376 FTP_SetResponseError(nResCode
);
2384 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs
)
2386 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2388 if (!FTP_DoPassive(lpwfs
))
2393 if (!FTP_SendPort(lpwfs
))
2400 /***********************************************************************
2401 * FTP_GetDataSocket (internal)
2403 * Either accepts an incoming data socket connection from the server
2404 * or just returns the already opened socket after a PASV command
2405 * in case of passive FTP.
2413 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs
, LPINT nDataSocket
)
2415 struct sockaddr_in saddr
;
2416 size_t addrlen
= sizeof(struct sockaddr
);
2419 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2421 *nDataSocket
= lpwfs
->pasvSocket
;
2425 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
2426 closesocket(lpwfs
->lstnSocket
);
2427 lpwfs
->lstnSocket
= -1;
2429 return *nDataSocket
!= -1;
2433 /***********************************************************************
2434 * FTP_SendData (internal)
2436 * Send data to the server
2443 BOOL
FTP_SendData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, HANDLE hFile
)
2445 BY_HANDLE_FILE_INFORMATION fi
;
2446 DWORD nBytesRead
= 0;
2447 DWORD nBytesSent
= 0;
2448 DWORD nTotalSent
= 0;
2449 DWORD nBytesToSend
, nLen
;
2451 time_t s_long_time
, e_long_time
;
2456 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2457 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2459 /* Get the size of the file. */
2460 GetFileInformationByHandle(hFile
, &fi
);
2465 nBytesToSend
= nBytesRead
- nBytesSent
;
2467 if (nBytesToSend
<= 0)
2469 /* Read data from file. */
2471 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
2472 ERR("Failed reading from file\n");
2475 nBytesToSend
= nBytesRead
;
2480 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
2481 DATA_PACKET_SIZE
: nBytesToSend
;
2482 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
2490 /* Do some computation to display the status. */
2492 nSeconds
= e_long_time
- s_long_time
;
2493 if( nSeconds
/ 60 > 0 )
2495 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
2496 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
2497 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2501 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
2502 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
2503 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2505 } while (nRC
!= -1);
2507 TRACE("file transfer complete!\n");
2509 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2515 /***********************************************************************
2516 * FTP_SendRetrieve (internal)
2518 * Send request to retrieve a file
2521 * Number of bytes to be received on success
2525 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
2531 if (!FTP_InitListenSocket(lpwfs
))
2534 if (!FTP_SendType(lpwfs
, dwType
))
2537 if (!FTP_SendPortOrPasv(lpwfs
))
2540 if (!FTP_GetFileSize(lpwfs
, lpszRemoteFile
, &nResult
))
2543 TRACE("Waiting to receive %ld bytes\n", nResult
);
2545 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
2548 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2549 if ((nResCode
!= 125) && (nResCode
!= 150)) {
2550 /* That means that we got an error getting the file. */
2555 if (0 == nResult
&& lpwfs
->lstnSocket
!= -1)
2557 closesocket(lpwfs
->lstnSocket
);
2558 lpwfs
->lstnSocket
= -1;
2565 /***********************************************************************
2566 * FTP_RetrieveData (internal)
2568 * Retrieve data from server
2575 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
2577 DWORD nBytesWritten
;
2578 DWORD nBytesReceived
= 0;
2584 if (INVALID_HANDLE_VALUE
== hFile
)
2587 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2588 if (NULL
== lpszBuffer
)
2590 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
2594 while (nBytesReceived
< nBytes
&& nRC
!= -1)
2596 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2599 /* other side closed socket. */
2602 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2603 nBytesReceived
+= nRC
;
2606 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2607 nBytesReceived
* 100 / nBytes
);
2610 TRACE("Data transfer complete\n");
2611 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2618 /***********************************************************************
2619 * FTP_CloseSessionHandle (internal)
2621 * Deallocate session handle
2628 static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr
)
2630 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) hdr
;
2634 if (lpwfs
->download_in_progress
!= NULL
)
2635 lpwfs
->download_in_progress
->session_deleted
= TRUE
;
2637 if (lpwfs
->sndSocket
!= -1)
2638 closesocket(lpwfs
->sndSocket
);
2640 if (lpwfs
->lstnSocket
!= -1)
2641 closesocket(lpwfs
->lstnSocket
);
2643 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2644 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2645 HeapFree(GetProcessHeap(), 0, lpwfs
);
2649 /***********************************************************************
2650 * FTP_CloseFindNextHandle (internal)
2652 * Deallocate session handle
2659 static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr
)
2661 LPWININETFINDNEXTW lpwfn
= (LPWININETFINDNEXTW
) hdr
;
2666 for (i
= 0; i
< lpwfn
->size
; i
++)
2668 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2671 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2672 HeapFree(GetProcessHeap(), 0, lpwfn
);
2675 /***********************************************************************
2676 * FTP_CloseFileTransferHandle (internal)
2678 * Closes the file transfer handle. This also 'cleans' the data queue of
2679 * the 'transfer conplete' message (this is a bit of a hack though :-/ )
2682 static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr
)
2684 LPWININETFILE lpwh
= (LPWININETFILE
) hdr
;
2685 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) lpwh
->hdr
.lpwhparent
;
2690 if (!lpwh
->session_deleted
)
2691 lpwfs
->download_in_progress
= NULL
;
2693 /* This just serves to flush the control socket of any spurrious lines written
2694 to it (like '226 Transfer complete.').
2696 Wonder what to do if the server sends us an error code though...
2698 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2700 if (lpwh
->nDataSocket
!= -1)
2701 closesocket(lpwh
->nDataSocket
);
2703 HeapFree(GetProcessHeap(), 0, lpwh
);
2706 /***********************************************************************
2707 * FTP_ReceiveFileList (internal)
2709 * Read file list from server
2712 * Handle to file list on success
2716 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2717 LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwContext
)
2720 LPFILEPROPERTIESW lpafp
= NULL
;
2721 LPWININETFINDNEXTW lpwfn
= NULL
;
2722 HINTERNET handle
= 0;
2724 TRACE("(%p,%d,%s,%p,%ld)\n", lpwfs
, nSocket
, debugstr_w(lpszSearchFile
), lpFindFileData
, dwContext
);
2726 if (FTP_ParseDirectory(lpwfs
, nSocket
, lpszSearchFile
, &lpafp
, &dwSize
))
2729 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2731 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTW
));
2734 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2735 lpwfn
->hdr
.lpwhparent
= WININET_AddRef( &lpwfs
->hdr
);
2736 lpwfn
->hdr
.dwContext
= dwContext
;
2737 lpwfn
->hdr
.dwRefCount
= 1;
2738 lpwfn
->hdr
.destroy
= FTP_CloseFindNextHandle
;
2739 lpwfn
->hdr
.lpfnStatusCB
= lpwfs
->hdr
.lpfnStatusCB
;
2740 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2741 lpwfn
->size
= dwSize
;
2742 lpwfn
->lpafp
= lpafp
;
2744 handle
= WININET_AllocHandle( &lpwfn
->hdr
);
2749 WININET_Release( &lpwfn
->hdr
);
2751 TRACE("Matched %ld files\n", dwSize
);
2756 /***********************************************************************
2757 * FTP_ConvertFileProp (internal)
2759 * Converts FILEPROPERTIESW struct to WIN32_FIND_DATAA
2766 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp
, LPWIN32_FIND_DATAW lpFindFileData
)
2768 BOOL bSuccess
= FALSE
;
2770 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAW
));
2774 /* Convert 'Unix' time to Windows time */
2775 RtlSecondsSince1970ToTime(mktime(&lpafp
->tmLastModified
),
2776 (LARGE_INTEGER
*) &(lpFindFileData
->ftLastAccessTime
));
2777 lpFindFileData
->ftLastWriteTime
= lpFindFileData
->ftLastAccessTime
;
2778 lpFindFileData
->ftCreationTime
= lpFindFileData
->ftLastAccessTime
;
2780 /* Not all fields are filled in */
2781 lpFindFileData
->nFileSizeHigh
= 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */
2782 lpFindFileData
->nFileSizeLow
= lpafp
->nSize
;
2784 if (lpafp
->bIsDirectory
)
2785 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2787 if (lpafp
->lpszName
)
2788 lstrcpynW(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2796 /***********************************************************************
2797 * FTP_ParseNextFile (internal)
2799 * Parse the next line in file listing
2805 BOOL
FTP_ParseNextFile(INT nSocket
, LPCWSTR lpszSearchFile
, LPFILEPROPERTIESW lpfp
)
2807 static const char szSpace
[] = " \t";
2815 lpfp
->lpszName
= NULL
;
2817 if(!(pszLine
= INTERNET_GetNextLine(nSocket
, &nBufLen
)))
2820 pszToken
= strtok(pszLine
, szSpace
);
2822 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2825 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2827 if(!isdigit(pszToken
[0]) && 10 == strlen(pszToken
)) {
2828 if(!FTP_ParsePermission(pszToken
, lpfp
))
2829 lpfp
->bIsDirectory
= FALSE
;
2830 for(i
=0; i
<=3; i
++) {
2831 if(!(pszToken
= strtok(NULL
, szSpace
)))
2834 if(!pszToken
) continue;
2835 if(lpfp
->bIsDirectory
) {
2836 TRACE("Is directory\n");
2840 TRACE("Size: %s\n", pszToken
);
2841 lpfp
->nSize
= atol(pszToken
);
2844 lpfp
->tmLastModified
.tm_sec
= 0;
2845 lpfp
->tmLastModified
.tm_min
= 0;
2846 lpfp
->tmLastModified
.tm_hour
= 0;
2847 lpfp
->tmLastModified
.tm_mday
= 0;
2848 lpfp
->tmLastModified
.tm_mon
= 0;
2849 lpfp
->tmLastModified
.tm_year
= 0;
2851 /* Determine month */
2852 pszToken
= strtok(NULL
, szSpace
);
2853 if(!pszToken
) continue;
2854 if(strlen(pszToken
) >= 3) {
2856 if((pszTmp
= StrStrIA(szMonths
, pszToken
)))
2857 lpfp
->tmLastModified
.tm_mon
= ((pszTmp
- szMonths
) / 3)+1;
2860 pszToken
= strtok(NULL
, szSpace
);
2861 if(!pszToken
) continue;
2862 lpfp
->tmLastModified
.tm_mday
= atoi(pszToken
);
2863 /* Determine time or year */
2864 pszToken
= strtok(NULL
, szSpace
);
2865 if(!pszToken
) continue;
2866 if((pszTmp
= strchr(pszToken
, ':'))) {
2871 lpfp
->tmLastModified
.tm_min
= atoi(pszTmp
);
2872 lpfp
->tmLastModified
.tm_hour
= atoi(pszToken
);
2874 apTM
= localtime(&aTime
);
2875 lpfp
->tmLastModified
.tm_year
= apTM
->tm_year
;
2878 lpfp
->tmLastModified
.tm_year
= atoi(pszToken
) - 1900;
2879 lpfp
->tmLastModified
.tm_hour
= 12;
2881 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2882 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2883 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2884 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2886 pszToken
= strtok(NULL
, szSpace
);
2887 if(!pszToken
) continue;
2888 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2889 TRACE("File: %s\n", debugstr_w(lpfp
->lpszName
));
2891 /* NT way of parsing ... :
2893 07-13-03 08:55PM <DIR> sakpatch
2894 05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
2896 else if(isdigit(pszToken
[0]) && 8 == strlen(pszToken
)) {
2897 lpfp
->permissions
= 0xFFFF; /* No idea, put full permission :-) */
2899 sscanf(pszToken
, "%d-%d-%d",
2900 &lpfp
->tmLastModified
.tm_mon
,
2901 &lpfp
->tmLastModified
.tm_mday
,
2902 &lpfp
->tmLastModified
.tm_year
);
2904 /* Hacky and bad Y2K protection :-) */
2905 if (lpfp
->tmLastModified
.tm_year
< 70)
2906 lpfp
->tmLastModified
.tm_year
+= 100;
2908 pszToken
= strtok(NULL
, szSpace
);
2909 if(!pszToken
) continue;
2910 sscanf(pszToken
, "%d:%d",
2911 &lpfp
->tmLastModified
.tm_hour
,
2912 &lpfp
->tmLastModified
.tm_min
);
2913 if((pszToken
[5] == 'P') && (pszToken
[6] == 'M')) {
2914 lpfp
->tmLastModified
.tm_hour
+= 12;
2916 lpfp
->tmLastModified
.tm_sec
= 0;
2918 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2919 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2920 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2921 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2923 pszToken
= strtok(NULL
, szSpace
);
2924 if(!pszToken
) continue;
2925 if(!strcasecmp(pszToken
, "<DIR>")) {
2926 lpfp
->bIsDirectory
= TRUE
;
2928 TRACE("Is directory\n");
2931 lpfp
->bIsDirectory
= FALSE
;
2932 lpfp
->nSize
= atol(pszToken
);
2933 TRACE("Size: %ld\n", lpfp
->nSize
);
2936 pszToken
= strtok(NULL
, szSpace
);
2937 if(!pszToken
) continue;
2938 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2939 TRACE("Name: %s\n", debugstr_w(lpfp
->lpszName
));
2941 /* EPLF format - http://cr.yp.to/ftp/list/eplf.html */
2942 else if(pszToken
[0] == '+') {
2943 FIXME("EPLF Format not implemented\n");
2946 if(lpfp
->lpszName
) {
2947 if((lpszSearchFile
== NULL
) ||
2948 (PathMatchSpecW(lpfp
->lpszName
, lpszSearchFile
))) {
2950 TRACE("Matched: %s\n", debugstr_w(lpfp
->lpszName
));
2953 HeapFree(GetProcessHeap(), 0, lpfp
->lpszName
);
2954 lpfp
->lpszName
= NULL
;
2961 /***********************************************************************
2962 * FTP_ParseDirectory (internal)
2964 * Parse string of directory information
2970 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2971 LPFILEPROPERTIESW
*lpafp
, LPDWORD dwfp
)
2973 BOOL bSuccess
= TRUE
;
2974 INT sizeFilePropArray
= 500;/*20; */
2975 INT indexFilePropArray
= -1;
2979 /* Allocate intial file properties array */
2980 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESW
)*(sizeFilePropArray
));
2985 if (indexFilePropArray
+1 >= sizeFilePropArray
)
2987 LPFILEPROPERTIESW tmpafp
;
2989 sizeFilePropArray
*= 2;
2990 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2991 sizeof(FILEPROPERTIESW
)*sizeFilePropArray
);
3000 indexFilePropArray
++;
3001 } while (FTP_ParseNextFile(nSocket
, lpszSearchFile
, &(*lpafp
)[indexFilePropArray
]));
3003 if (bSuccess
&& indexFilePropArray
)
3005 if (indexFilePropArray
< sizeFilePropArray
- 1)
3007 LPFILEPROPERTIESW tmpafp
;
3009 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
3010 sizeof(FILEPROPERTIESW
)*indexFilePropArray
);
3014 *dwfp
= indexFilePropArray
;
3018 HeapFree(GetProcessHeap(), 0, *lpafp
);
3019 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
3027 /***********************************************************************
3028 * FTP_ParsePermission (internal)
3030 * Parse permission string of directory information
3037 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESW lpfp
)
3039 BOOL bSuccess
= TRUE
;
3040 unsigned short nPermission
= 0;
3045 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
3051 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
3057 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
3060 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
3063 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
3066 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
3069 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
3072 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
3075 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
3078 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
3081 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
3085 }while (nPos
<= nLast
);
3087 lpfp
->permissions
= nPermission
;
3092 /***********************************************************************
3093 * FTP_SetResponseError (internal)
3095 * Set the appropriate error code for a given response from the server
3100 DWORD
FTP_SetResponseError(DWORD dwResponse
)
3106 case 421: /* Service not available - Server may be shutting down. */
3107 dwCode
= ERROR_INTERNET_TIMEOUT
;
3110 case 425: /* Cannot open data connection. */
3111 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
3114 case 426: /* Connection closed, transer aborted. */
3115 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
3118 case 500: /* Syntax error. Command unrecognized. */
3119 case 501: /* Syntax error. Error in parameters or arguments. */
3120 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
3123 case 530: /* Not logged in. Login incorrect. */
3124 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
3127 case 550: /* File action not taken. File not found or no access. */
3128 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
3131 case 450: /* File action not taken. File may be busy. */
3132 case 451: /* Action aborted. Server error. */
3133 case 452: /* Action not taken. Insufficient storage space on server. */
3134 case 502: /* Command not implemented. */
3135 case 503: /* Bad sequence of command. */
3136 case 504: /* Command not implemented for that parameter. */
3137 case 532: /* Need account for storing files */
3138 case 551: /* Requested action aborted. Page type unknown */
3139 case 552: /* Action aborted. Exceeded storage allocation */
3140 case 553: /* Action not taken. File name not allowed. */
3143 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
3147 INTERNET_SetLastError(dwCode
);