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 if(lpwzLocalFile
) HeapFree(GetProcessHeap(), 0, lpwzLocalFile
);
169 if(lpwzNewRemoteFile
) 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(hIC
, &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
&& hIC
->lpfnStatusCB
)
293 INTERNET_ASYNC_RESULT iar
;
295 iar
.dwResult
= (DWORD
)bSuccess
;
296 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
297 SendAsyncCallback(hIC
, &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 if(lpwzDirectory
) 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 hIC
->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
&& hIC
->lpfnStatusCB
)
426 INTERNET_ASYNC_RESULT iar
;
428 iar
.dwResult
= (DWORD
)bSuccess
;
429 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
430 SendAsyncCallback(hIC
, &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 if(lpwzDirectory
) 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
&& hIC
->lpfnStatusCB
)
550 INTERNET_ASYNC_RESULT iar
;
552 iar
.dwResult
= (DWORD
)bSuccess
;
553 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
554 SendAsyncCallback(hIC
, &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 if(lpwzSearchFile
) 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 hIC
->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
&& hIC
->lpfnStatusCB
)
710 INTERNET_ASYNC_RESULT iar
;
714 iar
.dwResult
= (DWORD
)hFindNext
;
715 iar
.dwError
= ERROR_SUCCESS
;
716 SendAsyncCallback(hIC
, &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(hIC
, &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 hIC
->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 strncpyW(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1],
868 len
< *lpdwCurrentDirectory
? len
: *lpdwCurrentDirectory
);
869 HeapFree(GetProcessHeap(), 0, lpszResponseBuffer
);
870 *lpdwCurrentDirectory
= len
;
874 FTP_SetResponseError(nResCode
);
878 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
880 INTERNET_ASYNC_RESULT iar
;
882 iar
.dwResult
= (DWORD
)bSuccess
;
883 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
884 SendAsyncCallback(hIC
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
885 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
888 return (DWORD
) bSuccess
;
891 /***********************************************************************
892 * FtpOpenFileA (WININET.@)
894 * Open a remote file for writing or reading
897 * HINTERNET handle on success
901 HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
902 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
908 lpwzFileName
= lpszFileName
?WININET_strdup_AtoW(lpszFileName
):NULL
;
909 ret
= FtpOpenFileW(hFtpSession
, lpwzFileName
, fdwAccess
, dwFlags
, dwContext
);
910 if(lpwzFileName
) HeapFree(GetProcessHeap(), 0, lpwzFileName
);
915 /***********************************************************************
916 * FtpOpenFileW (WININET.@)
918 * Open a remote file for writing or reading
921 * HINTERNET handle on success
925 HINTERNET WINAPI
FtpOpenFileW(HINTERNET hFtpSession
,
926 LPCWSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
929 LPWININETFTPSESSIONW lpwfs
;
930 LPWININETAPPINFOW hIC
= NULL
;
933 TRACE("(%p,%s,0x%08lx,0x%08lx,0x%08lx)\n", hFtpSession
,
934 debugstr_w(lpszFileName
), fdwAccess
, dwFlags
, dwContext
);
936 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
937 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
939 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
943 if (lpwfs
->download_in_progress
!= NULL
) {
944 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
947 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
948 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
950 WORKREQUEST workRequest
;
951 struct WORKREQ_FTPOPENFILEW
*req
;
953 workRequest
.asyncall
= FTPOPENFILEW
;
954 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
955 req
= &workRequest
.u
.FtpOpenFileW
;
956 req
->lpszFilename
= WININET_strdupW(lpszFileName
);
957 req
->dwAccess
= fdwAccess
;
958 req
->dwFlags
= dwFlags
;
959 req
->dwContext
= dwContext
;
961 INTERNET_AsyncCall(&workRequest
);
966 r
= FTP_FtpOpenFileW(lpwfs
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
971 WININET_Release( &lpwfs
->hdr
);
977 /***********************************************************************
978 * FTP_FtpOpenFileW (Internal)
980 * Open a remote file for writing or reading
983 * HINTERNET handle on success
987 HINTERNET
FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs
,
988 LPCWSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
992 BOOL bSuccess
= FALSE
;
993 LPWININETFILE lpwh
= NULL
;
994 LPWININETAPPINFOW hIC
= NULL
;
995 HINTERNET handle
= NULL
;
999 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1001 /* Clear any error information */
1002 INTERNET_SetLastError(0);
1004 if (GENERIC_READ
== fdwAccess
)
1006 /* Set up socket to retrieve data */
1007 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
1009 else if (GENERIC_WRITE
== fdwAccess
)
1011 /* Set up socket to send data */
1012 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
1015 /* Get data socket to server */
1016 if (bSuccess
&& FTP_GetDataSocket(lpwfs
, &nDataSocket
))
1018 lpwh
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
1019 lpwh
->hdr
.htype
= WH_HFILE
;
1020 lpwh
->hdr
.dwFlags
= dwFlags
;
1021 lpwh
->hdr
.dwContext
= dwContext
;
1022 lpwh
->hdr
.lpwhparent
= WININET_AddRef( &lpwfs
->hdr
);
1023 lpwh
->hdr
.dwRefCount
= 1;
1024 lpwh
->hdr
.destroy
= FTP_CloseFileTransferHandle
;
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
&& hIC
->lpfnStatusCB
)
1042 INTERNET_ASYNC_RESULT iar
;
1046 iar
.dwResult
= (DWORD
)handle
;
1047 iar
.dwError
= ERROR_SUCCESS
;
1048 SendAsyncCallback(hIC
, &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(hIC
, &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 if(lpwzRemoteFile
) HeapFree(GetProcessHeap(), 0, lpwzRemoteFile
);
1089 if(lpwzNewFile
) 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
&& hIC
->lpfnStatusCB
)
1224 INTERNET_ASYNC_RESULT iar
;
1226 iar
.dwResult
= (DWORD
)bSuccess
;
1227 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1228 SendAsyncCallback(hIC
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1229 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1236 /***********************************************************************
1237 * FtpDeleteFileA (WININET.@)
1239 * Delete a file on the ftp server
1246 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
1248 LPWSTR lpwzFileName
;
1251 lpwzFileName
= lpszFileName
?WININET_strdup_AtoW(lpszFileName
):NULL
;
1252 ret
= FtpDeleteFileW(hFtpSession
, lpwzFileName
);
1253 if(lpwzFileName
) HeapFree(GetProcessHeap(), 0, lpwzFileName
);
1257 /***********************************************************************
1258 * FtpDeleteFileW (WININET.@)
1260 * Delete a file on the ftp server
1267 BOOL WINAPI
FtpDeleteFileW(HINTERNET hFtpSession
, LPCWSTR lpszFileName
)
1269 LPWININETFTPSESSIONW lpwfs
;
1270 LPWININETAPPINFOW hIC
= NULL
;
1273 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1274 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1276 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1280 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1281 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1283 WORKREQUEST workRequest
;
1284 struct WORKREQ_FTPDELETEFILEW
*req
;
1286 workRequest
.asyncall
= FTPDELETEFILEW
;
1287 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1288 req
= &workRequest
.u
.FtpDeleteFileW
;
1289 req
->lpszFilename
= WININET_strdupW(lpszFileName
);
1291 r
= INTERNET_AsyncCall(&workRequest
);
1295 r
= FTP_FtpDeleteFileW(hFtpSession
, lpszFileName
);
1300 WININET_Release( &lpwfs
->hdr
);
1305 /***********************************************************************
1306 * FTP_FtpDeleteFileW (Internal)
1308 * Delete a file on the ftp server
1315 BOOL
FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszFileName
)
1318 BOOL bSuccess
= FALSE
;
1319 LPWININETAPPINFOW hIC
= NULL
;
1321 TRACE("%p\n", lpwfs
);
1323 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1325 /* Clear any error information */
1326 INTERNET_SetLastError(0);
1328 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1331 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1334 if (nResCode
== 250)
1337 FTP_SetResponseError(nResCode
);
1340 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1341 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1343 INTERNET_ASYNC_RESULT iar
;
1345 iar
.dwResult
= (DWORD
)bSuccess
;
1346 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1347 SendAsyncCallback(hIC
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1348 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1355 /***********************************************************************
1356 * FtpRemoveDirectoryA (WININET.@)
1358 * Remove a directory on the ftp server
1365 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1367 LPWSTR lpwzDirectory
;
1370 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
1371 ret
= FtpRemoveDirectoryW(hFtpSession
, lpwzDirectory
);
1372 if(lpwzDirectory
) HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
1376 /***********************************************************************
1377 * FtpRemoveDirectoryW (WININET.@)
1379 * Remove a directory on the ftp server
1386 BOOL WINAPI
FtpRemoveDirectoryW(HINTERNET hFtpSession
, LPCWSTR lpszDirectory
)
1388 LPWININETFTPSESSIONW lpwfs
;
1389 LPWININETAPPINFOW hIC
= NULL
;
1392 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1393 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1395 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1399 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1400 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1402 WORKREQUEST workRequest
;
1403 struct WORKREQ_FTPREMOVEDIRECTORYW
*req
;
1405 workRequest
.asyncall
= FTPREMOVEDIRECTORYW
;
1406 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1407 req
= &workRequest
.u
.FtpRemoveDirectoryW
;
1408 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
1410 r
= INTERNET_AsyncCall(&workRequest
);
1414 r
= FTP_FtpRemoveDirectoryW(lpwfs
, lpszDirectory
);
1419 WININET_Release( &lpwfs
->hdr
);
1424 /***********************************************************************
1425 * FTP_FtpRemoveDirectoryW (Internal)
1427 * Remove a directory on the ftp server
1434 BOOL
FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszDirectory
)
1437 BOOL bSuccess
= FALSE
;
1438 LPWININETAPPINFOW hIC
= NULL
;
1442 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1444 /* Clear any error information */
1445 INTERNET_SetLastError(0);
1447 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1450 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1453 if (nResCode
== 250)
1456 FTP_SetResponseError(nResCode
);
1460 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1461 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1463 INTERNET_ASYNC_RESULT iar
;
1465 iar
.dwResult
= (DWORD
)bSuccess
;
1466 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1467 SendAsyncCallback(hIC
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1468 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1475 /***********************************************************************
1476 * FtpRenameFileA (WININET.@)
1478 * Rename a file on the ftp server
1485 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1491 lpwzSrc
= lpszSrc
?WININET_strdup_AtoW(lpszSrc
):NULL
;
1492 lpwzDest
= lpszDest
?WININET_strdup_AtoW(lpszDest
):NULL
;
1493 ret
= FtpRenameFileW(hFtpSession
, lpwzSrc
, lpwzDest
);
1494 if(lpwzSrc
) HeapFree(GetProcessHeap(), 0, lpwzSrc
);
1495 if(lpwzDest
) HeapFree(GetProcessHeap(), 0, lpwzDest
);
1499 /***********************************************************************
1500 * FtpRenameFileW (WININET.@)
1502 * Rename a file on the ftp server
1509 BOOL WINAPI
FtpRenameFileW(HINTERNET hFtpSession
, LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1511 LPWININETFTPSESSIONW lpwfs
;
1512 LPWININETAPPINFOW hIC
= NULL
;
1515 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1516 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1518 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1522 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1523 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1525 WORKREQUEST workRequest
;
1526 struct WORKREQ_FTPRENAMEFILEW
*req
;
1528 workRequest
.asyncall
= FTPRENAMEFILEW
;
1529 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1530 req
= &workRequest
.u
.FtpRenameFileW
;
1531 req
->lpszSrcFile
= WININET_strdupW(lpszSrc
);
1532 req
->lpszDestFile
= WININET_strdupW(lpszDest
);
1534 r
= INTERNET_AsyncCall(&workRequest
);
1538 r
= FTP_FtpRenameFileW(hFtpSession
, lpszSrc
, lpszDest
);
1543 WININET_Release( &lpwfs
->hdr
);
1548 /***********************************************************************
1549 * FTP_FtpRenameFileA (Internal)
1551 * Rename a file on the ftp server
1558 BOOL
FTP_FtpRenameFileW( LPWININETFTPSESSIONW lpwfs
,
1559 LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1562 BOOL bSuccess
= FALSE
;
1563 LPWININETAPPINFOW hIC
= NULL
;
1567 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1569 /* Clear any error information */
1570 INTERNET_SetLastError(0);
1572 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1575 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1576 if (nResCode
== 350)
1578 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1581 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1584 if (nResCode
== 250)
1587 FTP_SetResponseError(nResCode
);
1590 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1591 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1593 INTERNET_ASYNC_RESULT iar
;
1595 iar
.dwResult
= (DWORD
)bSuccess
;
1596 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1597 SendAsyncCallback(hIC
, &lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1598 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1605 /***********************************************************************
1606 * FTP_Connect (internal)
1608 * Connect to a ftp server
1611 * HINTERNET a session handle on success
1616 HINTERNET
FTP_Connect(LPWININETAPPINFOW hIC
, LPCWSTR lpszServerName
,
1617 INTERNET_PORT nServerPort
, LPCWSTR lpszUserName
,
1618 LPCWSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
,
1619 DWORD dwInternalFlags
)
1621 static const WCHAR szDefaultUsername
[] = {'a','n','o','n','y','m','o','u','s','\0'};
1622 static const WCHAR szDefaultPassword
[] = {'u','s','e','r','@','s','e','r','v','e','r','\0'};
1623 struct sockaddr_in socketAddr
;
1624 struct hostent
*phe
= NULL
;
1625 INT nsocket
= -1, sock_namelen
;
1626 BOOL bSuccess
= FALSE
;
1627 LPWININETFTPSESSIONW lpwfs
= NULL
;
1628 HINTERNET handle
= NULL
;
1630 TRACE("%p Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1631 hIC
, debugstr_w(lpszServerName
),
1632 nServerPort
, debugstr_w(lpszUserName
), debugstr_w(lpszPassword
));
1634 assert( hIC
->hdr
.htype
!= WH_HINIT
);
1636 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1638 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
1642 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONW
));
1645 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1649 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1650 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1652 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1653 lpwfs
->hdr
.lpwhparent
= WININET_AddRef( &hIC
->hdr
);
1654 lpwfs
->hdr
.dwFlags
= dwFlags
;
1655 lpwfs
->hdr
.dwContext
= dwContext
;
1656 lpwfs
->hdr
.dwInternalFlags
= dwInternalFlags
;
1657 lpwfs
->hdr
.dwRefCount
= 1;
1658 lpwfs
->hdr
.destroy
= FTP_CloseSessionHandle
;
1659 lpwfs
->download_in_progress
= NULL
;
1661 handle
= WININET_AllocHandle( &lpwfs
->hdr
);
1664 ERR("Failed to alloc handle\n");
1665 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1669 if(hIC
->lpszProxy
&& hIC
->dwAccessType
== INTERNET_OPEN_TYPE_PROXY
) {
1670 if(strchrW(hIC
->lpszProxy
, ' '))
1671 FIXME("Several proxies not implemented.\n");
1672 if(hIC
->lpszProxyBypass
)
1673 FIXME("Proxy bypass is ignored.\n");
1675 if ( !lpszUserName
) {
1676 lpwfs
->lpszUserName
= WININET_strdupW(szDefaultUsername
);
1677 lpwfs
->lpszPassword
= WININET_strdupW(szDefaultPassword
);
1680 lpwfs
->lpszUserName
= WININET_strdupW(lpszUserName
);
1681 lpwfs
->lpszPassword
= WININET_strdupW(lpszPassword
);
1684 /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
1685 if (hIC
->lpfnStatusCB
&& !(lpwfs
->hdr
.dwInternalFlags
& INET_OPENURL
))
1687 INTERNET_ASYNC_RESULT iar
;
1689 iar
.dwResult
= (DWORD
)handle
;
1690 iar
.dwError
= ERROR_SUCCESS
;
1692 SendAsyncCallback(hIC
, &hIC
->hdr
, dwContext
,
1693 INTERNET_STATUS_HANDLE_CREATED
, &iar
,
1694 sizeof(INTERNET_ASYNC_RESULT
));
1697 SendAsyncCallback(hIC
, &hIC
->hdr
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1698 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1700 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1702 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1706 SendAsyncCallback(hIC
, &hIC
->hdr
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1707 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1709 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
1712 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1716 SendAsyncCallback(hIC
, &hIC
->hdr
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1717 &socketAddr
, sizeof(struct sockaddr_in
));
1719 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1721 ERR("Unable to connect (%s)\n", strerror(errno
));
1722 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1726 TRACE("Connected to server\n");
1727 lpwfs
->sndSocket
= nsocket
;
1728 SendAsyncCallback(hIC
, &hIC
->hdr
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1729 &socketAddr
, sizeof(struct sockaddr_in
));
1731 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1732 getsockname(nsocket
, (struct sockaddr
*) &lpwfs
->socketAddress
, &sock_namelen
);
1733 lpwfs
->phostent
= phe
;
1735 if (FTP_ConnectToHost(lpwfs
))
1737 TRACE("Successfully logged into server\n");
1743 if (!bSuccess
&& nsocket
== -1)
1744 closesocket(nsocket
);
1746 if (!bSuccess
&& lpwfs
)
1748 HeapFree(GetProcessHeap(), 0, lpwfs
);
1749 WININET_FreeHandle( handle
);
1753 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1755 INTERNET_ASYNC_RESULT iar
;
1757 iar
.dwResult
= (DWORD
)lpwfs
;
1758 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1759 SendAsyncCallback(hIC
, &hIC
->hdr
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1760 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1767 /***********************************************************************
1768 * FTP_ConnectToHost (internal)
1770 * Connect to a ftp server
1777 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs
)
1780 BOOL bSuccess
= FALSE
;
1783 FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1785 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1788 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1791 /* Login successful... */
1792 if (nResCode
== 230)
1794 /* User name okay, need password... */
1795 else if (nResCode
== 331)
1796 bSuccess
= FTP_SendPassword(lpwfs
);
1797 /* Need account for login... */
1798 else if (nResCode
== 332)
1799 bSuccess
= FTP_SendAccount(lpwfs
);
1801 FTP_SetResponseError(nResCode
);
1804 TRACE("Returning %d\n", bSuccess
);
1810 /***********************************************************************
1811 * FTP_SendCommandA (internal)
1813 * Send command to server
1820 BOOL
FTP_SendCommandA(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1821 INTERNET_STATUS_CALLBACK lpfnStatusCB
, LPWININETHANDLEHEADER hdr
, DWORD dwContext
)
1825 DWORD nBytesSent
= 0;
1829 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1833 HINTERNET hHandle
= WININET_FindHandle( hdr
);
1836 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1837 WININET_Release( hdr
);
1841 dwParamLen
= lpszParam
?strlen(lpszParam
)+1:0;
1842 len
= dwParamLen
+ strlen(szFtpCommands
[ftpCmd
]) + strlen(szCRLF
);
1843 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1845 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1848 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], dwParamLen
? " " : "",
1849 dwParamLen
? lpszParam
: "", szCRLF
);
1851 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1852 while((nBytesSent
< len
) && (nRC
!= -1))
1854 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1858 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1862 HINTERNET hHandle
= WININET_FindHandle( hdr
);
1865 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1866 &nBytesSent
, sizeof(DWORD
));
1867 WININET_Release( hdr
);
1871 TRACE("Sent %ld bytes\n", nBytesSent
);
1875 /***********************************************************************
1876 * FTP_SendCommand (internal)
1878 * Send command to server
1885 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCWSTR lpszParam
,
1886 INTERNET_STATUS_CALLBACK lpfnStatusCB
, LPWININETHANDLEHEADER hdr
, DWORD dwContext
)
1889 LPSTR lpszParamA
= lpszParam
?WININET_strdup_WtoA(lpszParam
):NULL
;
1890 ret
= FTP_SendCommandA(nSocket
, ftpCmd
, lpszParamA
, lpfnStatusCB
, hdr
, dwContext
);
1891 HeapFree(GetProcessHeap(), 0, lpszParamA
);
1895 /***********************************************************************
1896 * FTP_ReceiveResponse (internal)
1898 * Receive response from server
1901 * Reply code on success
1905 INT
FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs
, DWORD dwContext
)
1907 LPSTR lpszResponse
= INTERNET_GetResponseBuffer();
1910 char firstprefix
[5];
1911 BOOL multiline
= FALSE
;
1912 LPWININETAPPINFOW hIC
= NULL
;
1914 TRACE("socket(%d) \n", lpwfs
->sndSocket
);
1916 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1917 SendAsyncCallback(hIC
, &lpwfs
->hdr
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1921 if (!INTERNET_GetNextLine(lpwfs
->sndSocket
, &nRecv
))
1928 if(lpszResponse
[3] != '-')
1931 { /* Start of multiline repsonse. Loop until we get "nnn " */
1933 memcpy(firstprefix
, lpszResponse
, 3);
1934 firstprefix
[3] = ' ';
1935 firstprefix
[4] = '\0';
1940 if(!memcmp(firstprefix
, lpszResponse
, 4))
1948 rc
= atoi(lpszResponse
);
1950 SendAsyncCallback(hIC
, &lpwfs
->hdr
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1951 &nRecv
, sizeof(DWORD
));
1955 TRACE("return %d\n", rc
);
1960 /***********************************************************************
1961 * FTP_SendPassword (internal)
1963 * Send password to ftp server
1970 BOOL
FTP_SendPassword(LPWININETFTPSESSIONW lpwfs
)
1973 BOOL bSuccess
= FALSE
;
1976 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1979 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1982 TRACE("Received reply code %d\n", nResCode
);
1983 /* Login successful... */
1984 if (nResCode
== 230)
1986 /* Command not implemented, superfluous at the server site... */
1987 /* Need account for login... */
1988 else if (nResCode
== 332)
1989 bSuccess
= FTP_SendAccount(lpwfs
);
1991 FTP_SetResponseError(nResCode
);
1995 TRACE("Returning %d\n", bSuccess
);
2000 /***********************************************************************
2001 * FTP_SendAccount (internal)
2010 BOOL
FTP_SendAccount(LPWININETFTPSESSIONW lpwfs
)
2013 BOOL bSuccess
= FALSE
;
2016 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, szNoAccount
, 0, 0, 0))
2019 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2023 FTP_SetResponseError(nResCode
);
2030 /***********************************************************************
2031 * FTP_SendStore (internal)
2033 * Send request to upload file to ftp server
2040 BOOL
FTP_SendStore(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
2043 BOOL bSuccess
= FALSE
;
2046 if (!FTP_InitListenSocket(lpwfs
))
2049 if (!FTP_SendType(lpwfs
, dwType
))
2052 if (!FTP_SendPortOrPasv(lpwfs
))
2055 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
2057 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2060 if (nResCode
== 150)
2063 FTP_SetResponseError(nResCode
);
2067 if (!bSuccess
&& lpwfs
->lstnSocket
!= -1)
2069 closesocket(lpwfs
->lstnSocket
);
2070 lpwfs
->lstnSocket
= -1;
2077 /***********************************************************************
2078 * FTP_InitListenSocket (internal)
2080 * Create a socket to listen for server response
2087 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs
)
2089 BOOL bSuccess
= FALSE
;
2090 size_t namelen
= sizeof(struct sockaddr_in
);
2094 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
2095 if (lpwfs
->lstnSocket
== -1)
2097 TRACE("Unable to create listening socket\n");
2101 /* We obtain our ip addr from the name of the command channel socket */
2102 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
2104 /* and get the system to assign us a port */
2105 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
2107 if (bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)) == -1)
2109 TRACE("Unable to bind socket\n");
2113 if (listen(lpwfs
->lstnSocket
, MAX_BACKLOG
) == -1)
2115 TRACE("listen failed\n");
2119 if (getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
) != -1)
2123 if (!bSuccess
&& lpwfs
->lstnSocket
== -1)
2125 closesocket(lpwfs
->lstnSocket
);
2126 lpwfs
->lstnSocket
= -1;
2133 /***********************************************************************
2134 * FTP_SendType (internal)
2136 * Tell server type of data being transferred
2142 * W98SE doesn't cache the type that's currently set
2143 * (i.e. it sends it always),
2144 * so we probably don't want to do that either.
2146 BOOL
FTP_SendType(LPWININETFTPSESSIONW lpwfs
, DWORD dwType
)
2149 WCHAR type
[] = { 'I','\0' };
2150 BOOL bSuccess
= FALSE
;
2153 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
2156 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
2159 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
)/100;
2165 FTP_SetResponseError(nResCode
);
2172 /***********************************************************************
2173 * FTP_GetFileSize (internal)
2175 * Retrieves from the server the size of the given file
2182 BOOL
FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD
*dwSize
)
2185 BOOL bSuccess
= FALSE
;
2189 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_SIZE
, lpszRemoteFile
, 0, 0, 0))
2192 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2195 if (nResCode
== 213) {
2196 /* Now parses the output to get the actual file size */
2198 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2200 for (i
= 0; (lpszResponseBuffer
[i
] != ' ') && (lpszResponseBuffer
[i
] != '\0'); i
++) ;
2201 if (lpszResponseBuffer
[i
] == '\0') return FALSE
;
2202 *dwSize
= atol(&(lpszResponseBuffer
[i
+ 1]));
2206 FTP_SetResponseError(nResCode
);
2215 /***********************************************************************
2216 * FTP_SendPort (internal)
2218 * Tell server which port to use
2225 BOOL
FTP_SendPort(LPWININETFTPSESSIONW lpwfs
)
2227 static const WCHAR szIPFormat
[] = {'%','d',',','%','d',',','%','d',',','%','d',',','%','d',',','%','d','\0'};
2229 WCHAR szIPAddress
[64];
2230 BOOL bSuccess
= FALSE
;
2233 sprintfW(szIPAddress
, szIPFormat
,
2234 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
2235 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
2236 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
2237 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
2238 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
2239 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
2241 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
2244 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2247 if (nResCode
== 200)
2250 FTP_SetResponseError(nResCode
);
2258 /***********************************************************************
2259 * FTP_DoPassive (internal)
2261 * Tell server that we want to do passive transfers
2262 * and connect data socket
2269 BOOL
FTP_DoPassive(LPWININETFTPSESSIONW lpwfs
)
2272 BOOL bSuccess
= FALSE
;
2275 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASV
, NULL
, 0, 0, 0))
2278 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2281 if (nResCode
== 227)
2283 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2287 char *pAddr
, *pPort
;
2289 struct sockaddr_in dataSocketAddress
;
2291 p
= lpszResponseBuffer
+4; /* skip status code */
2293 /* do a very strict check; we can improve that later. */
2295 if (strncmp(p
, "Entering Passive Mode", 21))
2297 ERR("unknown response '%.*s', aborting\n", 21, p
);
2300 p
+= 21; /* skip string */
2301 if ((*p
++ != ' ') || (*p
++ != '('))
2303 ERR("unknown response format, aborting\n");
2307 if (sscanf(p
, "%d,%d,%d,%d,%d,%d", &f
[0], &f
[1], &f
[2], &f
[3],
2310 ERR("unknown response address format '%s', aborting\n", p
);
2313 for (i
=0; i
< 6; i
++)
2316 dataSocketAddress
= lpwfs
->socketAddress
;
2317 pAddr
= (char *)&(dataSocketAddress
.sin_addr
.s_addr
);
2318 pPort
= (char *)&(dataSocketAddress
.sin_port
);
2326 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
2330 if (connect(nsocket
, (struct sockaddr
*)&dataSocketAddress
, sizeof(dataSocketAddress
)))
2332 ERR("can't connect passive FTP data port.\n");
2335 lpwfs
->pasvSocket
= nsocket
;
2339 FTP_SetResponseError(nResCode
);
2347 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs
)
2349 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2351 if (!FTP_DoPassive(lpwfs
))
2356 if (!FTP_SendPort(lpwfs
))
2363 /***********************************************************************
2364 * FTP_GetDataSocket (internal)
2366 * Either accepts an incoming data socket connection from the server
2367 * or just returns the already opened socket after a PASV command
2368 * in case of passive FTP.
2376 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs
, LPINT nDataSocket
)
2378 struct sockaddr_in saddr
;
2379 size_t addrlen
= sizeof(struct sockaddr
);
2382 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2384 *nDataSocket
= lpwfs
->pasvSocket
;
2388 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
2389 closesocket(lpwfs
->lstnSocket
);
2390 lpwfs
->lstnSocket
= -1;
2392 return *nDataSocket
!= -1;
2396 /***********************************************************************
2397 * FTP_SendData (internal)
2399 * Send data to the server
2406 BOOL
FTP_SendData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, HANDLE hFile
)
2408 BY_HANDLE_FILE_INFORMATION fi
;
2409 DWORD nBytesRead
= 0;
2410 DWORD nBytesSent
= 0;
2411 DWORD nTotalSent
= 0;
2412 DWORD nBytesToSend
, nLen
;
2414 time_t s_long_time
, e_long_time
;
2419 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2420 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2422 /* Get the size of the file. */
2423 GetFileInformationByHandle(hFile
, &fi
);
2428 nBytesToSend
= nBytesRead
- nBytesSent
;
2430 if (nBytesToSend
<= 0)
2432 /* Read data from file. */
2434 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
2435 ERR("Failed reading from file\n");
2438 nBytesToSend
= nBytesRead
;
2443 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
2444 DATA_PACKET_SIZE
: nBytesToSend
;
2445 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
2453 /* Do some computation to display the status. */
2455 nSeconds
= e_long_time
- s_long_time
;
2456 if( nSeconds
/ 60 > 0 )
2458 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
2459 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
2460 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2464 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
2465 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
2466 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2468 } while (nRC
!= -1);
2470 TRACE("file transfer complete!\n");
2472 if(lpszBuffer
!= NULL
)
2473 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2479 /***********************************************************************
2480 * FTP_SendRetrieve (internal)
2482 * Send request to retrieve a file
2485 * Number of bytes to be received on success
2489 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
2495 if (!FTP_InitListenSocket(lpwfs
))
2498 if (!FTP_SendType(lpwfs
, dwType
))
2501 if (!FTP_SendPortOrPasv(lpwfs
))
2504 if (!FTP_GetFileSize(lpwfs
, lpszRemoteFile
, &nResult
))
2507 TRACE("Waiting to receive %ld bytes\n", nResult
);
2509 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
2512 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2513 if ((nResCode
!= 125) && (nResCode
!= 150)) {
2514 /* That means that we got an error getting the file. */
2519 if (0 == nResult
&& lpwfs
->lstnSocket
!= -1)
2521 closesocket(lpwfs
->lstnSocket
);
2522 lpwfs
->lstnSocket
= -1;
2529 /***********************************************************************
2530 * FTP_RetrieveData (internal)
2532 * Retrieve data from server
2539 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
2541 DWORD nBytesWritten
;
2542 DWORD nBytesReceived
= 0;
2548 if (INVALID_HANDLE_VALUE
== hFile
)
2551 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2552 if (NULL
== lpszBuffer
)
2554 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
2558 while (nBytesReceived
< nBytes
&& nRC
!= -1)
2560 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2563 /* other side closed socket. */
2566 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2567 nBytesReceived
+= nRC
;
2570 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2571 nBytesReceived
* 100 / nBytes
);
2574 TRACE("Data transfer complete\n");
2575 if (NULL
!= lpszBuffer
)
2576 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2583 /***********************************************************************
2584 * FTP_CloseSessionHandle (internal)
2586 * Deallocate session handle
2593 static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr
)
2595 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) hdr
;
2599 if (lpwfs
->download_in_progress
!= NULL
)
2600 lpwfs
->download_in_progress
->session_deleted
= TRUE
;
2602 if (lpwfs
->sndSocket
!= -1)
2603 closesocket(lpwfs
->sndSocket
);
2605 if (lpwfs
->lstnSocket
!= -1)
2606 closesocket(lpwfs
->lstnSocket
);
2608 if (lpwfs
->lpszPassword
)
2609 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2611 if (lpwfs
->lpszUserName
)
2612 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2614 HeapFree(GetProcessHeap(), 0, lpwfs
);
2618 /***********************************************************************
2619 * FTP_CloseFindNextHandle (internal)
2621 * Deallocate session handle
2628 static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr
)
2630 LPWININETFINDNEXTW lpwfn
= (LPWININETFINDNEXTW
) hdr
;
2635 for (i
= 0; i
< lpwfn
->size
; i
++)
2637 if (NULL
!= lpwfn
->lpafp
[i
].lpszName
)
2638 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2641 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2642 HeapFree(GetProcessHeap(), 0, lpwfn
);
2645 /***********************************************************************
2646 * FTP_CloseFileTransferHandle (internal)
2648 * Closes the file transfer handle. This also 'cleans' the data queue of
2649 * the 'transfer conplete' message (this is a bit of a hack though :-/ )
2652 static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr
)
2654 LPWININETFILE lpwh
= (LPWININETFILE
) hdr
;
2655 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) lpwh
->hdr
.lpwhparent
;
2660 if (!lpwh
->session_deleted
)
2661 lpwfs
->download_in_progress
= NULL
;
2663 /* This just serves to flush the control socket of any spurrious lines written
2664 to it (like '226 Transfer complete.').
2666 Wonder what to do if the server sends us an error code though...
2668 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2670 if (lpwh
->nDataSocket
!= -1)
2671 closesocket(lpwh
->nDataSocket
);
2673 HeapFree(GetProcessHeap(), 0, lpwh
);
2676 /***********************************************************************
2677 * FTP_ReceiveFileList (internal)
2679 * Read file list from server
2682 * Handle to file list on success
2686 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2687 LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwContext
)
2690 LPFILEPROPERTIESW lpafp
= NULL
;
2691 LPWININETFINDNEXTW lpwfn
= NULL
;
2692 HINTERNET handle
= 0;
2694 TRACE("(%p,%d,%s,%p,%ld)\n", lpwfs
, nSocket
, debugstr_w(lpszSearchFile
), lpFindFileData
, dwContext
);
2696 if (FTP_ParseDirectory(lpwfs
, nSocket
, lpszSearchFile
, &lpafp
, &dwSize
))
2699 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2701 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTW
));
2704 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2705 lpwfn
->hdr
.lpwhparent
= WININET_AddRef( &lpwfs
->hdr
);
2706 lpwfn
->hdr
.dwContext
= dwContext
;
2707 lpwfn
->hdr
.dwRefCount
= 1;
2708 lpwfn
->hdr
.destroy
= FTP_CloseFindNextHandle
;
2709 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2710 lpwfn
->size
= dwSize
;
2711 lpwfn
->lpafp
= lpafp
;
2713 handle
= WININET_AllocHandle( &lpwfn
->hdr
);
2718 WININET_Release( &lpwfn
->hdr
);
2720 TRACE("Matched %ld files\n", dwSize
);
2725 /***********************************************************************
2726 * FTP_ConvertFileProp (internal)
2728 * Converts FILEPROPERTIESW struct to WIN32_FIND_DATAA
2735 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp
, LPWIN32_FIND_DATAW lpFindFileData
)
2737 BOOL bSuccess
= FALSE
;
2739 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAW
));
2743 /* Convert 'Unix' time to Windows time */
2744 RtlSecondsSince1970ToTime(mktime(&lpafp
->tmLastModified
),
2745 (LARGE_INTEGER
*) &(lpFindFileData
->ftLastAccessTime
));
2747 /* Not all fields are filled in */
2748 lpFindFileData
->nFileSizeHigh
= 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */
2749 lpFindFileData
->nFileSizeLow
= lpafp
->nSize
;
2751 if (lpafp
->bIsDirectory
)
2752 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2754 if (lpafp
->lpszName
)
2755 strncpyW(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2763 /***********************************************************************
2764 * FTP_ParseNextFile (internal)
2766 * Parse the next line in file listing
2772 BOOL
FTP_ParseNextFile(INT nSocket
, LPCWSTR lpszSearchFile
, LPFILEPROPERTIESW lpfp
)
2774 static const char szSpace
[] = " \t";
2782 lpfp
->lpszName
= NULL
;
2784 if(!(pszLine
= INTERNET_GetNextLine(nSocket
, &nBufLen
)))
2787 pszToken
= strtok(pszLine
, szSpace
);
2789 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2792 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2794 if(!isdigit(pszToken
[0]) && 10 == strlen(pszToken
)) {
2795 if(!FTP_ParsePermission(pszToken
, lpfp
))
2796 lpfp
->bIsDirectory
= FALSE
;
2797 for(i
=0; i
<=3; i
++) {
2798 if(!(pszToken
= strtok(NULL
, szSpace
)))
2801 if(!pszToken
) continue;
2802 if(lpfp
->bIsDirectory
) {
2803 TRACE("Is directory\n");
2807 TRACE("Size: %s\n", pszToken
);
2808 lpfp
->nSize
= atol(pszToken
);
2811 lpfp
->tmLastModified
.tm_sec
= 0;
2812 lpfp
->tmLastModified
.tm_min
= 0;
2813 lpfp
->tmLastModified
.tm_hour
= 0;
2814 lpfp
->tmLastModified
.tm_mday
= 0;
2815 lpfp
->tmLastModified
.tm_mon
= 0;
2816 lpfp
->tmLastModified
.tm_year
= 0;
2818 /* Determine month */
2819 pszToken
= strtok(NULL
, szSpace
);
2820 if(!pszToken
) continue;
2821 if(strlen(pszToken
) >= 3) {
2823 if((pszTmp
= StrStrIA(szMonths
, pszToken
)))
2824 lpfp
->tmLastModified
.tm_mon
= ((pszTmp
- szMonths
) / 3)+1;
2827 pszToken
= strtok(NULL
, szSpace
);
2828 if(!pszToken
) continue;
2829 lpfp
->tmLastModified
.tm_mday
= atoi(pszToken
);
2830 /* Determine time or year */
2831 pszToken
= strtok(NULL
, szSpace
);
2832 if(!pszToken
) continue;
2833 if((pszTmp
= strchr(pszToken
, ':'))) {
2838 lpfp
->tmLastModified
.tm_min
= atoi(pszTmp
);
2839 lpfp
->tmLastModified
.tm_hour
= atoi(pszToken
);
2841 apTM
= localtime(&aTime
);
2842 lpfp
->tmLastModified
.tm_year
= apTM
->tm_year
;
2845 lpfp
->tmLastModified
.tm_year
= atoi(pszToken
) - 1900;
2846 lpfp
->tmLastModified
.tm_hour
= 12;
2848 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2849 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2850 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2851 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2853 pszToken
= strtok(NULL
, szSpace
);
2854 if(!pszToken
) continue;
2855 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2856 TRACE("File: %s\n", debugstr_w(lpfp
->lpszName
));
2858 /* NT way of parsing ... :
2860 07-13-03 08:55PM <DIR> sakpatch
2861 05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
2863 else if(isdigit(pszToken
[0]) && 8 == strlen(pszToken
)) {
2864 lpfp
->permissions
= 0xFFFF; /* No idea, put full permission :-) */
2866 sscanf(pszToken
, "%d-%d-%d",
2867 &lpfp
->tmLastModified
.tm_mon
,
2868 &lpfp
->tmLastModified
.tm_mday
,
2869 &lpfp
->tmLastModified
.tm_year
);
2871 /* Hacky and bad Y2K protection :-) */
2872 if (lpfp
->tmLastModified
.tm_year
< 70)
2873 lpfp
->tmLastModified
.tm_year
+= 100;
2875 pszToken
= strtok(NULL
, szSpace
);
2876 if(!pszToken
) continue;
2877 sscanf(pszToken
, "%d:%d",
2878 &lpfp
->tmLastModified
.tm_hour
,
2879 &lpfp
->tmLastModified
.tm_min
);
2880 if((pszToken
[5] == 'P') && (pszToken
[6] == 'M')) {
2881 lpfp
->tmLastModified
.tm_hour
+= 12;
2883 lpfp
->tmLastModified
.tm_sec
= 0;
2885 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2886 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2887 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2888 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2890 pszToken
= strtok(NULL
, szSpace
);
2891 if(!pszToken
) continue;
2892 if(!strcasecmp(pszToken
, "<DIR>")) {
2893 lpfp
->bIsDirectory
= TRUE
;
2895 TRACE("Is directory\n");
2898 lpfp
->bIsDirectory
= FALSE
;
2899 lpfp
->nSize
= atol(pszToken
);
2900 TRACE("Size: %ld\n", lpfp
->nSize
);
2903 pszToken
= strtok(NULL
, szSpace
);
2904 if(!pszToken
) continue;
2905 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2906 TRACE("Name: %s\n", debugstr_w(lpfp
->lpszName
));
2908 /* EPLF format - http://cr.yp.to/ftp/list/eplf.html */
2909 else if(pszToken
[0] == '+') {
2910 FIXME("EPLF Format not implemented\n");
2913 if(lpfp
->lpszName
) {
2914 if((lpszSearchFile
== NULL
) ||
2915 (PathMatchSpecW(lpfp
->lpszName
, lpszSearchFile
))) {
2917 TRACE("Matched: %s\n", debugstr_w(lpfp
->lpszName
));
2920 HeapFree(GetProcessHeap(), 0, lpfp
->lpszName
);
2921 lpfp
->lpszName
= NULL
;
2928 /***********************************************************************
2929 * FTP_ParseDirectory (internal)
2931 * Parse string of directory information
2937 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2938 LPFILEPROPERTIESW
*lpafp
, LPDWORD dwfp
)
2940 BOOL bSuccess
= TRUE
;
2941 INT sizeFilePropArray
= 500;/*20; */
2942 INT indexFilePropArray
= -1;
2946 /* Allocate intial file properties array */
2947 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESW
)*(sizeFilePropArray
));
2952 if (indexFilePropArray
+1 >= sizeFilePropArray
)
2954 LPFILEPROPERTIESW tmpafp
;
2956 sizeFilePropArray
*= 2;
2957 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2958 sizeof(FILEPROPERTIESW
)*sizeFilePropArray
);
2967 indexFilePropArray
++;
2968 } while (FTP_ParseNextFile(nSocket
, lpszSearchFile
, &(*lpafp
)[indexFilePropArray
]));
2970 if (bSuccess
&& indexFilePropArray
)
2972 if (indexFilePropArray
< sizeFilePropArray
- 1)
2974 LPFILEPROPERTIESW tmpafp
;
2976 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2977 sizeof(FILEPROPERTIESW
)*indexFilePropArray
);
2981 *dwfp
= indexFilePropArray
;
2985 HeapFree(GetProcessHeap(), 0, *lpafp
);
2986 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2994 /***********************************************************************
2995 * FTP_ParsePermission (internal)
2997 * Parse permission string of directory information
3004 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESW lpfp
)
3006 BOOL bSuccess
= TRUE
;
3007 unsigned short nPermission
= 0;
3012 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
3018 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
3024 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
3027 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
3030 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
3033 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
3036 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
3039 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
3042 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
3045 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
3048 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
3052 }while (nPos
<= nLast
);
3054 lpfp
->permissions
= nPermission
;
3059 /***********************************************************************
3060 * FTP_SetResponseError (internal)
3062 * Set the appropriate error code for a given response from the server
3067 DWORD
FTP_SetResponseError(DWORD dwResponse
)
3073 case 421: /* Service not available - Server may be shutting down. */
3074 dwCode
= ERROR_INTERNET_TIMEOUT
;
3077 case 425: /* Cannot open data connection. */
3078 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
3081 case 426: /* Connection closed, transer aborted. */
3082 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
3085 case 500: /* Syntax error. Command unrecognized. */
3086 case 501: /* Syntax error. Error in parameters or arguments. */
3087 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
3090 case 530: /* Not logged in. Login incorrect. */
3091 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
3094 case 550: /* File action not taken. File not found or no access. */
3095 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
3098 case 450: /* File action not taken. File may be busy. */
3099 case 451: /* Action aborted. Server error. */
3100 case 452: /* Action not taken. Insufficient storage space on server. */
3101 case 502: /* Command not implemented. */
3102 case 503: /* Bad sequence of command. */
3103 case 504: /* Command not implemented for that parameter. */
3104 case 532: /* Need account for storing files */
3105 case 551: /* Requested action aborted. Page type unknown */
3106 case 552: /* Action aborted. Exceeded storage allocation */
3107 case 553: /* Action not taken. File name not allowed. */
3110 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
3114 INTERNET_SetLastError(dwCode
);