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 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
)
880 INTERNET_ASYNC_RESULT iar
;
882 iar
.dwResult
= (DWORD
)bSuccess
;
883 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
884 SendAsyncCallback(&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 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
->hdr
.lpfnStatusCB
= lpwfs
->hdr
.lpfnStatusCB
;
1026 lpwh
->nDataSocket
= nDataSocket
;
1027 lpwh
->session_deleted
= FALSE
;
1029 handle
= WININET_AllocHandle( &lpwh
->hdr
);
1033 /* Indicate that a download is currently in progress */
1034 lpwfs
->download_in_progress
= lpwh
;
1037 if (lpwfs
->lstnSocket
!= -1)
1038 closesocket(lpwfs
->lstnSocket
);
1040 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1041 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1043 INTERNET_ASYNC_RESULT iar
;
1047 iar
.dwResult
= (DWORD
)handle
;
1048 iar
.dwError
= ERROR_SUCCESS
;
1049 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1050 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1053 iar
.dwResult
= (DWORD
)bSuccess
;
1054 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1055 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1056 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1061 WININET_Release( &lpwh
->hdr
);
1067 /***********************************************************************
1068 * FtpGetFileA (WININET.@)
1070 * Retrieve file from the FTP server
1077 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
1078 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1081 LPWSTR lpwzRemoteFile
;
1085 lpwzRemoteFile
= lpszRemoteFile
?WININET_strdup_AtoW(lpszRemoteFile
):NULL
;
1086 lpwzNewFile
= lpszNewFile
?WININET_strdup_AtoW(lpszNewFile
):NULL
;
1087 ret
= FtpGetFileW(hInternet
, lpwzRemoteFile
, lpwzNewFile
, fFailIfExists
,
1088 dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
1089 HeapFree(GetProcessHeap(), 0, lpwzRemoteFile
);
1090 HeapFree(GetProcessHeap(), 0, lpwzNewFile
);
1095 /***********************************************************************
1096 * FtpGetFileW (WININET.@)
1098 * Retrieve file from the FTP server
1105 BOOL WINAPI
FtpGetFileW(HINTERNET hInternet
, LPCWSTR lpszRemoteFile
, LPCWSTR lpszNewFile
,
1106 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1109 LPWININETFTPSESSIONW lpwfs
;
1110 LPWININETAPPINFOW hIC
= NULL
;
1113 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hInternet
);
1114 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1116 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1120 if (lpwfs
->download_in_progress
!= NULL
) {
1121 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
1125 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1126 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1128 WORKREQUEST workRequest
;
1129 struct WORKREQ_FTPGETFILEW
*req
;
1131 workRequest
.asyncall
= FTPGETFILEW
;
1132 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1133 req
= &workRequest
.u
.FtpGetFileW
;
1134 req
->lpszRemoteFile
= WININET_strdupW(lpszRemoteFile
);
1135 req
->lpszNewFile
= WININET_strdupW(lpszNewFile
);
1136 req
->dwLocalFlagsAttribute
= dwLocalFlagsAttribute
;
1137 req
->fFailIfExists
= fFailIfExists
;
1138 req
->dwFlags
= dwInternetFlags
;
1139 req
->dwContext
= dwContext
;
1141 r
= INTERNET_AsyncCall(&workRequest
);
1145 r
= FTP_FtpGetFileW(lpwfs
, lpszRemoteFile
, lpszNewFile
,
1146 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
1151 WININET_Release( &lpwfs
->hdr
);
1157 /***********************************************************************
1158 * FTP_FtpGetFileW (Internal)
1160 * Retrieve file from the FTP server
1167 BOOL WINAPI
FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, LPCWSTR lpszNewFile
,
1168 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1172 BOOL bSuccess
= FALSE
;
1174 LPWININETAPPINFOW hIC
= NULL
;
1176 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", debugstr_w(lpszRemoteFile
), debugstr_w(lpszNewFile
));
1178 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1180 /* Clear any error information */
1181 INTERNET_SetLastError(0);
1183 /* Ensure we can write to lpszNewfile by opening it */
1184 hFile
= CreateFileW(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
1185 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
1186 if (INVALID_HANDLE_VALUE
== hFile
)
1189 /* Set up socket to retrieve data */
1190 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
1196 /* Get data socket to server */
1197 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
1202 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
1203 nResCode
= FTP_ReceiveResponse(lpwfs
, dwContext
);
1206 if (nResCode
== 226)
1209 FTP_SetResponseError(nResCode
);
1211 closesocket(nDataSocket
);
1216 if (lpwfs
->lstnSocket
!= -1)
1217 closesocket(lpwfs
->lstnSocket
);
1222 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1223 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1225 INTERNET_ASYNC_RESULT iar
;
1227 iar
.dwResult
= (DWORD
)bSuccess
;
1228 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1229 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1230 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1237 /***********************************************************************
1238 * FtpDeleteFileA (WININET.@)
1240 * Delete a file on the ftp server
1247 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
1249 LPWSTR lpwzFileName
;
1252 lpwzFileName
= lpszFileName
?WININET_strdup_AtoW(lpszFileName
):NULL
;
1253 ret
= FtpDeleteFileW(hFtpSession
, lpwzFileName
);
1254 HeapFree(GetProcessHeap(), 0, lpwzFileName
);
1258 /***********************************************************************
1259 * FtpDeleteFileW (WININET.@)
1261 * Delete a file on the ftp server
1268 BOOL WINAPI
FtpDeleteFileW(HINTERNET hFtpSession
, LPCWSTR lpszFileName
)
1270 LPWININETFTPSESSIONW lpwfs
;
1271 LPWININETAPPINFOW hIC
= NULL
;
1274 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1275 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1277 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1281 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1282 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1284 WORKREQUEST workRequest
;
1285 struct WORKREQ_FTPDELETEFILEW
*req
;
1287 workRequest
.asyncall
= FTPDELETEFILEW
;
1288 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1289 req
= &workRequest
.u
.FtpDeleteFileW
;
1290 req
->lpszFilename
= WININET_strdupW(lpszFileName
);
1292 r
= INTERNET_AsyncCall(&workRequest
);
1296 r
= FTP_FtpDeleteFileW(hFtpSession
, lpszFileName
);
1301 WININET_Release( &lpwfs
->hdr
);
1306 /***********************************************************************
1307 * FTP_FtpDeleteFileW (Internal)
1309 * Delete a file on the ftp server
1316 BOOL
FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszFileName
)
1319 BOOL bSuccess
= FALSE
;
1320 LPWININETAPPINFOW hIC
= NULL
;
1322 TRACE("%p\n", lpwfs
);
1324 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1326 /* Clear any error information */
1327 INTERNET_SetLastError(0);
1329 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1332 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1335 if (nResCode
== 250)
1338 FTP_SetResponseError(nResCode
);
1341 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1342 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1344 INTERNET_ASYNC_RESULT iar
;
1346 iar
.dwResult
= (DWORD
)bSuccess
;
1347 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1348 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1349 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1356 /***********************************************************************
1357 * FtpRemoveDirectoryA (WININET.@)
1359 * Remove a directory on the ftp server
1366 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1368 LPWSTR lpwzDirectory
;
1371 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
1372 ret
= FtpRemoveDirectoryW(hFtpSession
, lpwzDirectory
);
1373 HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
1377 /***********************************************************************
1378 * FtpRemoveDirectoryW (WININET.@)
1380 * Remove a directory on the ftp server
1387 BOOL WINAPI
FtpRemoveDirectoryW(HINTERNET hFtpSession
, LPCWSTR lpszDirectory
)
1389 LPWININETFTPSESSIONW lpwfs
;
1390 LPWININETAPPINFOW hIC
= NULL
;
1393 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1394 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1396 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1400 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1401 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1403 WORKREQUEST workRequest
;
1404 struct WORKREQ_FTPREMOVEDIRECTORYW
*req
;
1406 workRequest
.asyncall
= FTPREMOVEDIRECTORYW
;
1407 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1408 req
= &workRequest
.u
.FtpRemoveDirectoryW
;
1409 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
1411 r
= INTERNET_AsyncCall(&workRequest
);
1415 r
= FTP_FtpRemoveDirectoryW(lpwfs
, lpszDirectory
);
1420 WININET_Release( &lpwfs
->hdr
);
1425 /***********************************************************************
1426 * FTP_FtpRemoveDirectoryW (Internal)
1428 * Remove a directory on the ftp server
1435 BOOL
FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszDirectory
)
1438 BOOL bSuccess
= FALSE
;
1439 LPWININETAPPINFOW hIC
= NULL
;
1443 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1445 /* Clear any error information */
1446 INTERNET_SetLastError(0);
1448 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1451 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1454 if (nResCode
== 250)
1457 FTP_SetResponseError(nResCode
);
1461 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1462 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1464 INTERNET_ASYNC_RESULT iar
;
1466 iar
.dwResult
= (DWORD
)bSuccess
;
1467 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1468 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1469 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1476 /***********************************************************************
1477 * FtpRenameFileA (WININET.@)
1479 * Rename a file on the ftp server
1486 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1492 lpwzSrc
= lpszSrc
?WININET_strdup_AtoW(lpszSrc
):NULL
;
1493 lpwzDest
= lpszDest
?WININET_strdup_AtoW(lpszDest
):NULL
;
1494 ret
= FtpRenameFileW(hFtpSession
, lpwzSrc
, lpwzDest
);
1495 HeapFree(GetProcessHeap(), 0, lpwzSrc
);
1496 HeapFree(GetProcessHeap(), 0, lpwzDest
);
1500 /***********************************************************************
1501 * FtpRenameFileW (WININET.@)
1503 * Rename a file on the ftp server
1510 BOOL WINAPI
FtpRenameFileW(HINTERNET hFtpSession
, LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1512 LPWININETFTPSESSIONW lpwfs
;
1513 LPWININETAPPINFOW hIC
= NULL
;
1516 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1517 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1519 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1523 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1524 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1526 WORKREQUEST workRequest
;
1527 struct WORKREQ_FTPRENAMEFILEW
*req
;
1529 workRequest
.asyncall
= FTPRENAMEFILEW
;
1530 workRequest
.hdr
= WININET_AddRef( &lpwfs
->hdr
);
1531 req
= &workRequest
.u
.FtpRenameFileW
;
1532 req
->lpszSrcFile
= WININET_strdupW(lpszSrc
);
1533 req
->lpszDestFile
= WININET_strdupW(lpszDest
);
1535 r
= INTERNET_AsyncCall(&workRequest
);
1539 r
= FTP_FtpRenameFileW(hFtpSession
, lpszSrc
, lpszDest
);
1544 WININET_Release( &lpwfs
->hdr
);
1549 /***********************************************************************
1550 * FTP_FtpRenameFileA (Internal)
1552 * Rename a file on the ftp server
1559 BOOL
FTP_FtpRenameFileW( LPWININETFTPSESSIONW lpwfs
,
1560 LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1563 BOOL bSuccess
= FALSE
;
1564 LPWININETAPPINFOW hIC
= NULL
;
1568 assert (WH_HFTPSESSION
== lpwfs
->hdr
.htype
);
1570 /* Clear any error information */
1571 INTERNET_SetLastError(0);
1573 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1576 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1577 if (nResCode
== 350)
1579 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1582 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1585 if (nResCode
== 250)
1588 FTP_SetResponseError(nResCode
);
1591 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1592 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1594 INTERNET_ASYNC_RESULT iar
;
1596 iar
.dwResult
= (DWORD
)bSuccess
;
1597 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1598 SendAsyncCallback(&lpwfs
->hdr
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1599 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1606 /***********************************************************************
1607 * FTP_Connect (internal)
1609 * Connect to a ftp server
1612 * HINTERNET a session handle on success
1617 HINTERNET
FTP_Connect(LPWININETAPPINFOW hIC
, LPCWSTR lpszServerName
,
1618 INTERNET_PORT nServerPort
, LPCWSTR lpszUserName
,
1619 LPCWSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
,
1620 DWORD dwInternalFlags
)
1622 static const WCHAR szDefaultUsername
[] = {'a','n','o','n','y','m','o','u','s','\0'};
1623 static const WCHAR szDefaultPassword
[] = {'u','s','e','r','@','s','e','r','v','e','r','\0'};
1624 struct sockaddr_in socketAddr
;
1625 struct hostent
*phe
= NULL
;
1626 INT nsocket
= -1, sock_namelen
;
1627 BOOL bSuccess
= FALSE
;
1628 LPWININETFTPSESSIONW lpwfs
= NULL
;
1629 HINTERNET handle
= NULL
;
1631 TRACE("%p Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1632 hIC
, debugstr_w(lpszServerName
),
1633 nServerPort
, debugstr_w(lpszUserName
), debugstr_w(lpszPassword
));
1635 assert( hIC
->hdr
.htype
== WH_HINIT
);
1637 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1639 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
1643 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONW
));
1646 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1650 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1651 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1653 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1654 lpwfs
->hdr
.lpwhparent
= WININET_AddRef( &hIC
->hdr
);
1655 lpwfs
->hdr
.dwFlags
= dwFlags
;
1656 lpwfs
->hdr
.dwContext
= dwContext
;
1657 lpwfs
->hdr
.dwInternalFlags
= dwInternalFlags
;
1658 lpwfs
->hdr
.dwRefCount
= 1;
1659 lpwfs
->hdr
.destroy
= FTP_CloseSessionHandle
;
1660 lpwfs
->hdr
.lpfnStatusCB
= hIC
->hdr
.lpfnStatusCB
;
1661 lpwfs
->download_in_progress
= NULL
;
1663 handle
= WININET_AllocHandle( &lpwfs
->hdr
);
1666 ERR("Failed to alloc handle\n");
1667 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1671 if(hIC
->lpszProxy
&& hIC
->dwAccessType
== INTERNET_OPEN_TYPE_PROXY
) {
1672 if(strchrW(hIC
->lpszProxy
, ' '))
1673 FIXME("Several proxies not implemented.\n");
1674 if(hIC
->lpszProxyBypass
)
1675 FIXME("Proxy bypass is ignored.\n");
1677 if ( !lpszUserName
) {
1678 lpwfs
->lpszUserName
= WININET_strdupW(szDefaultUsername
);
1679 lpwfs
->lpszPassword
= WININET_strdupW(szDefaultPassword
);
1682 lpwfs
->lpszUserName
= WININET_strdupW(lpszUserName
);
1683 lpwfs
->lpszPassword
= WININET_strdupW(lpszPassword
);
1686 /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
1687 if (!(lpwfs
->hdr
.dwInternalFlags
& INET_OPENURL
))
1689 INTERNET_ASYNC_RESULT iar
;
1691 iar
.dwResult
= (DWORD
)handle
;
1692 iar
.dwError
= ERROR_SUCCESS
;
1694 SendAsyncCallback(&hIC
->hdr
, dwContext
,
1695 INTERNET_STATUS_HANDLE_CREATED
, &iar
,
1696 sizeof(INTERNET_ASYNC_RESULT
));
1699 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1700 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1702 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1704 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1708 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1709 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1711 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
1714 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1718 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1719 &socketAddr
, sizeof(struct sockaddr_in
));
1721 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1723 ERR("Unable to connect (%s)\n", strerror(errno
));
1724 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1728 TRACE("Connected to server\n");
1729 lpwfs
->sndSocket
= nsocket
;
1730 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1731 &socketAddr
, sizeof(struct sockaddr_in
));
1733 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1734 getsockname(nsocket
, (struct sockaddr
*) &lpwfs
->socketAddress
, &sock_namelen
);
1735 lpwfs
->phostent
= phe
;
1737 if (FTP_ConnectToHost(lpwfs
))
1739 TRACE("Successfully logged into server\n");
1745 if (!bSuccess
&& nsocket
== -1)
1746 closesocket(nsocket
);
1748 if (!bSuccess
&& lpwfs
)
1750 HeapFree(GetProcessHeap(), 0, lpwfs
);
1751 WININET_FreeHandle( handle
);
1755 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1757 INTERNET_ASYNC_RESULT iar
;
1759 iar
.dwResult
= (DWORD
)lpwfs
;
1760 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1761 SendAsyncCallback(&hIC
->hdr
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1762 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1769 /***********************************************************************
1770 * FTP_ConnectToHost (internal)
1772 * Connect to a ftp server
1779 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs
)
1782 BOOL bSuccess
= FALSE
;
1785 FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1787 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1790 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1793 /* Login successful... */
1794 if (nResCode
== 230)
1796 /* User name okay, need password... */
1797 else if (nResCode
== 331)
1798 bSuccess
= FTP_SendPassword(lpwfs
);
1799 /* Need account for login... */
1800 else if (nResCode
== 332)
1801 bSuccess
= FTP_SendAccount(lpwfs
);
1803 FTP_SetResponseError(nResCode
);
1806 TRACE("Returning %d\n", bSuccess
);
1812 /***********************************************************************
1813 * FTP_SendCommandA (internal)
1815 * Send command to server
1822 BOOL
FTP_SendCommandA(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1823 INTERNET_STATUS_CALLBACK lpfnStatusCB
, LPWININETHANDLEHEADER hdr
, DWORD dwContext
)
1827 DWORD nBytesSent
= 0;
1831 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1835 HINTERNET hHandle
= WININET_FindHandle( hdr
);
1838 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1839 WININET_Release( hdr
);
1843 dwParamLen
= lpszParam
?strlen(lpszParam
)+1:0;
1844 len
= dwParamLen
+ strlen(szFtpCommands
[ftpCmd
]) + strlen(szCRLF
);
1845 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1847 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1850 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], dwParamLen
? " " : "",
1851 dwParamLen
? lpszParam
: "", szCRLF
);
1853 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1854 while((nBytesSent
< len
) && (nRC
!= -1))
1856 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1860 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1864 HINTERNET hHandle
= WININET_FindHandle( hdr
);
1867 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1868 &nBytesSent
, sizeof(DWORD
));
1869 WININET_Release( hdr
);
1873 TRACE("Sent %ld bytes\n", nBytesSent
);
1877 /***********************************************************************
1878 * FTP_SendCommand (internal)
1880 * Send command to server
1887 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCWSTR lpszParam
,
1888 INTERNET_STATUS_CALLBACK lpfnStatusCB
, LPWININETHANDLEHEADER hdr
, DWORD dwContext
)
1891 LPSTR lpszParamA
= lpszParam
?WININET_strdup_WtoA(lpszParam
):NULL
;
1892 ret
= FTP_SendCommandA(nSocket
, ftpCmd
, lpszParamA
, lpfnStatusCB
, hdr
, dwContext
);
1893 HeapFree(GetProcessHeap(), 0, lpszParamA
);
1897 /***********************************************************************
1898 * FTP_ReceiveResponse (internal)
1900 * Receive response from server
1903 * Reply code on success
1907 INT
FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs
, DWORD dwContext
)
1909 LPSTR lpszResponse
= INTERNET_GetResponseBuffer();
1912 char firstprefix
[5];
1913 BOOL multiline
= FALSE
;
1914 LPWININETAPPINFOW hIC
= NULL
;
1916 TRACE("socket(%d) \n", lpwfs
->sndSocket
);
1918 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1919 SendAsyncCallback(&lpwfs
->hdr
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1923 if (!INTERNET_GetNextLine(lpwfs
->sndSocket
, &nRecv
))
1930 if(lpszResponse
[3] != '-')
1933 { /* Start of multiline repsonse. Loop until we get "nnn " */
1935 memcpy(firstprefix
, lpszResponse
, 3);
1936 firstprefix
[3] = ' ';
1937 firstprefix
[4] = '\0';
1942 if(!memcmp(firstprefix
, lpszResponse
, 4))
1950 rc
= atoi(lpszResponse
);
1952 SendAsyncCallback(&lpwfs
->hdr
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1953 &nRecv
, sizeof(DWORD
));
1957 TRACE("return %d\n", rc
);
1962 /***********************************************************************
1963 * FTP_SendPassword (internal)
1965 * Send password to ftp server
1972 BOOL
FTP_SendPassword(LPWININETFTPSESSIONW lpwfs
)
1975 BOOL bSuccess
= FALSE
;
1978 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1981 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1984 TRACE("Received reply code %d\n", nResCode
);
1985 /* Login successful... */
1986 if (nResCode
== 230)
1988 /* Command not implemented, superfluous at the server site... */
1989 /* Need account for login... */
1990 else if (nResCode
== 332)
1991 bSuccess
= FTP_SendAccount(lpwfs
);
1993 FTP_SetResponseError(nResCode
);
1997 TRACE("Returning %d\n", bSuccess
);
2002 /***********************************************************************
2003 * FTP_SendAccount (internal)
2012 BOOL
FTP_SendAccount(LPWININETFTPSESSIONW lpwfs
)
2015 BOOL bSuccess
= FALSE
;
2018 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, szNoAccount
, 0, 0, 0))
2021 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2025 FTP_SetResponseError(nResCode
);
2032 /***********************************************************************
2033 * FTP_SendStore (internal)
2035 * Send request to upload file to ftp server
2042 BOOL
FTP_SendStore(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
2045 BOOL bSuccess
= FALSE
;
2048 if (!FTP_InitListenSocket(lpwfs
))
2051 if (!FTP_SendType(lpwfs
, dwType
))
2054 if (!FTP_SendPortOrPasv(lpwfs
))
2057 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
2059 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2062 if (nResCode
== 150)
2065 FTP_SetResponseError(nResCode
);
2069 if (!bSuccess
&& lpwfs
->lstnSocket
!= -1)
2071 closesocket(lpwfs
->lstnSocket
);
2072 lpwfs
->lstnSocket
= -1;
2079 /***********************************************************************
2080 * FTP_InitListenSocket (internal)
2082 * Create a socket to listen for server response
2089 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs
)
2091 BOOL bSuccess
= FALSE
;
2092 size_t namelen
= sizeof(struct sockaddr_in
);
2096 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
2097 if (lpwfs
->lstnSocket
== -1)
2099 TRACE("Unable to create listening socket\n");
2103 /* We obtain our ip addr from the name of the command channel socket */
2104 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
2106 /* and get the system to assign us a port */
2107 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
2109 if (bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)) == -1)
2111 TRACE("Unable to bind socket\n");
2115 if (listen(lpwfs
->lstnSocket
, MAX_BACKLOG
) == -1)
2117 TRACE("listen failed\n");
2121 if (getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
) != -1)
2125 if (!bSuccess
&& lpwfs
->lstnSocket
== -1)
2127 closesocket(lpwfs
->lstnSocket
);
2128 lpwfs
->lstnSocket
= -1;
2135 /***********************************************************************
2136 * FTP_SendType (internal)
2138 * Tell server type of data being transferred
2144 * W98SE doesn't cache the type that's currently set
2145 * (i.e. it sends it always),
2146 * so we probably don't want to do that either.
2148 BOOL
FTP_SendType(LPWININETFTPSESSIONW lpwfs
, DWORD dwType
)
2151 WCHAR type
[] = { 'I','\0' };
2152 BOOL bSuccess
= FALSE
;
2155 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
2158 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
2161 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
)/100;
2167 FTP_SetResponseError(nResCode
);
2174 /***********************************************************************
2175 * FTP_GetFileSize (internal)
2177 * Retrieves from the server the size of the given file
2184 BOOL
FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD
*dwSize
)
2187 BOOL bSuccess
= FALSE
;
2191 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_SIZE
, lpszRemoteFile
, 0, 0, 0))
2194 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2197 if (nResCode
== 213) {
2198 /* Now parses the output to get the actual file size */
2200 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2202 for (i
= 0; (lpszResponseBuffer
[i
] != ' ') && (lpszResponseBuffer
[i
] != '\0'); i
++) ;
2203 if (lpszResponseBuffer
[i
] == '\0') return FALSE
;
2204 *dwSize
= atol(&(lpszResponseBuffer
[i
+ 1]));
2208 FTP_SetResponseError(nResCode
);
2217 /***********************************************************************
2218 * FTP_SendPort (internal)
2220 * Tell server which port to use
2227 BOOL
FTP_SendPort(LPWININETFTPSESSIONW lpwfs
)
2229 static const WCHAR szIPFormat
[] = {'%','d',',','%','d',',','%','d',',','%','d',',','%','d',',','%','d','\0'};
2231 WCHAR szIPAddress
[64];
2232 BOOL bSuccess
= FALSE
;
2235 sprintfW(szIPAddress
, szIPFormat
,
2236 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
2237 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
2238 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
2239 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
2240 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
2241 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
2243 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
2246 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2249 if (nResCode
== 200)
2252 FTP_SetResponseError(nResCode
);
2260 /***********************************************************************
2261 * FTP_DoPassive (internal)
2263 * Tell server that we want to do passive transfers
2264 * and connect data socket
2271 BOOL
FTP_DoPassive(LPWININETFTPSESSIONW lpwfs
)
2274 BOOL bSuccess
= FALSE
;
2277 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASV
, NULL
, 0, 0, 0))
2280 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2283 if (nResCode
== 227)
2285 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2289 char *pAddr
, *pPort
;
2291 struct sockaddr_in dataSocketAddress
;
2293 p
= lpszResponseBuffer
+4; /* skip status code */
2295 /* do a very strict check; we can improve that later. */
2297 if (strncmp(p
, "Entering Passive Mode", 21))
2299 ERR("unknown response '%.*s', aborting\n", 21, p
);
2302 p
+= 21; /* skip string */
2303 if ((*p
++ != ' ') || (*p
++ != '('))
2305 ERR("unknown response format, aborting\n");
2309 if (sscanf(p
, "%d,%d,%d,%d,%d,%d", &f
[0], &f
[1], &f
[2], &f
[3],
2312 ERR("unknown response address format '%s', aborting\n", p
);
2315 for (i
=0; i
< 6; i
++)
2318 dataSocketAddress
= lpwfs
->socketAddress
;
2319 pAddr
= (char *)&(dataSocketAddress
.sin_addr
.s_addr
);
2320 pPort
= (char *)&(dataSocketAddress
.sin_port
);
2328 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
2332 if (connect(nsocket
, (struct sockaddr
*)&dataSocketAddress
, sizeof(dataSocketAddress
)))
2334 ERR("can't connect passive FTP data port.\n");
2337 lpwfs
->pasvSocket
= nsocket
;
2341 FTP_SetResponseError(nResCode
);
2349 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs
)
2351 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2353 if (!FTP_DoPassive(lpwfs
))
2358 if (!FTP_SendPort(lpwfs
))
2365 /***********************************************************************
2366 * FTP_GetDataSocket (internal)
2368 * Either accepts an incoming data socket connection from the server
2369 * or just returns the already opened socket after a PASV command
2370 * in case of passive FTP.
2378 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs
, LPINT nDataSocket
)
2380 struct sockaddr_in saddr
;
2381 size_t addrlen
= sizeof(struct sockaddr
);
2384 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2386 *nDataSocket
= lpwfs
->pasvSocket
;
2390 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
2391 closesocket(lpwfs
->lstnSocket
);
2392 lpwfs
->lstnSocket
= -1;
2394 return *nDataSocket
!= -1;
2398 /***********************************************************************
2399 * FTP_SendData (internal)
2401 * Send data to the server
2408 BOOL
FTP_SendData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, HANDLE hFile
)
2410 BY_HANDLE_FILE_INFORMATION fi
;
2411 DWORD nBytesRead
= 0;
2412 DWORD nBytesSent
= 0;
2413 DWORD nTotalSent
= 0;
2414 DWORD nBytesToSend
, nLen
;
2416 time_t s_long_time
, e_long_time
;
2421 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2422 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2424 /* Get the size of the file. */
2425 GetFileInformationByHandle(hFile
, &fi
);
2430 nBytesToSend
= nBytesRead
- nBytesSent
;
2432 if (nBytesToSend
<= 0)
2434 /* Read data from file. */
2436 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
2437 ERR("Failed reading from file\n");
2440 nBytesToSend
= nBytesRead
;
2445 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
2446 DATA_PACKET_SIZE
: nBytesToSend
;
2447 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
2455 /* Do some computation to display the status. */
2457 nSeconds
= e_long_time
- s_long_time
;
2458 if( nSeconds
/ 60 > 0 )
2460 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
2461 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
2462 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2466 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
2467 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
2468 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2470 } while (nRC
!= -1);
2472 TRACE("file transfer complete!\n");
2474 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2480 /***********************************************************************
2481 * FTP_SendRetrieve (internal)
2483 * Send request to retrieve a file
2486 * Number of bytes to be received on success
2490 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
2496 if (!FTP_InitListenSocket(lpwfs
))
2499 if (!FTP_SendType(lpwfs
, dwType
))
2502 if (!FTP_SendPortOrPasv(lpwfs
))
2505 if (!FTP_GetFileSize(lpwfs
, lpszRemoteFile
, &nResult
))
2508 TRACE("Waiting to receive %ld bytes\n", nResult
);
2510 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
2513 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2514 if ((nResCode
!= 125) && (nResCode
!= 150)) {
2515 /* That means that we got an error getting the file. */
2520 if (0 == nResult
&& lpwfs
->lstnSocket
!= -1)
2522 closesocket(lpwfs
->lstnSocket
);
2523 lpwfs
->lstnSocket
= -1;
2530 /***********************************************************************
2531 * FTP_RetrieveData (internal)
2533 * Retrieve data from server
2540 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
2542 DWORD nBytesWritten
;
2543 DWORD nBytesReceived
= 0;
2549 if (INVALID_HANDLE_VALUE
== hFile
)
2552 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2553 if (NULL
== lpszBuffer
)
2555 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
2559 while (nBytesReceived
< nBytes
&& nRC
!= -1)
2561 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2564 /* other side closed socket. */
2567 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2568 nBytesReceived
+= nRC
;
2571 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2572 nBytesReceived
* 100 / nBytes
);
2575 TRACE("Data transfer complete\n");
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 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2609 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2610 HeapFree(GetProcessHeap(), 0, lpwfs
);
2614 /***********************************************************************
2615 * FTP_CloseFindNextHandle (internal)
2617 * Deallocate session handle
2624 static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr
)
2626 LPWININETFINDNEXTW lpwfn
= (LPWININETFINDNEXTW
) hdr
;
2631 for (i
= 0; i
< lpwfn
->size
; i
++)
2633 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2636 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2637 HeapFree(GetProcessHeap(), 0, lpwfn
);
2640 /***********************************************************************
2641 * FTP_CloseFileTransferHandle (internal)
2643 * Closes the file transfer handle. This also 'cleans' the data queue of
2644 * the 'transfer conplete' message (this is a bit of a hack though :-/ )
2647 static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr
)
2649 LPWININETFILE lpwh
= (LPWININETFILE
) hdr
;
2650 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) lpwh
->hdr
.lpwhparent
;
2655 if (!lpwh
->session_deleted
)
2656 lpwfs
->download_in_progress
= NULL
;
2658 /* This just serves to flush the control socket of any spurrious lines written
2659 to it (like '226 Transfer complete.').
2661 Wonder what to do if the server sends us an error code though...
2663 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2665 if (lpwh
->nDataSocket
!= -1)
2666 closesocket(lpwh
->nDataSocket
);
2668 HeapFree(GetProcessHeap(), 0, lpwh
);
2671 /***********************************************************************
2672 * FTP_ReceiveFileList (internal)
2674 * Read file list from server
2677 * Handle to file list on success
2681 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2682 LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwContext
)
2685 LPFILEPROPERTIESW lpafp
= NULL
;
2686 LPWININETFINDNEXTW lpwfn
= NULL
;
2687 HINTERNET handle
= 0;
2689 TRACE("(%p,%d,%s,%p,%ld)\n", lpwfs
, nSocket
, debugstr_w(lpszSearchFile
), lpFindFileData
, dwContext
);
2691 if (FTP_ParseDirectory(lpwfs
, nSocket
, lpszSearchFile
, &lpafp
, &dwSize
))
2694 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2696 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTW
));
2699 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2700 lpwfn
->hdr
.lpwhparent
= WININET_AddRef( &lpwfs
->hdr
);
2701 lpwfn
->hdr
.dwContext
= dwContext
;
2702 lpwfn
->hdr
.dwRefCount
= 1;
2703 lpwfn
->hdr
.destroy
= FTP_CloseFindNextHandle
;
2704 lpwfn
->hdr
.lpfnStatusCB
= lpwfs
->hdr
.lpfnStatusCB
;
2705 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2706 lpwfn
->size
= dwSize
;
2707 lpwfn
->lpafp
= lpafp
;
2709 handle
= WININET_AllocHandle( &lpwfn
->hdr
);
2714 WININET_Release( &lpwfn
->hdr
);
2716 TRACE("Matched %ld files\n", dwSize
);
2721 /***********************************************************************
2722 * FTP_ConvertFileProp (internal)
2724 * Converts FILEPROPERTIESW struct to WIN32_FIND_DATAA
2731 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp
, LPWIN32_FIND_DATAW lpFindFileData
)
2733 BOOL bSuccess
= FALSE
;
2735 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAW
));
2739 /* Convert 'Unix' time to Windows time */
2740 RtlSecondsSince1970ToTime(mktime(&lpafp
->tmLastModified
),
2741 (LARGE_INTEGER
*) &(lpFindFileData
->ftLastAccessTime
));
2742 lpFindFileData
->ftLastWriteTime
= lpFindFileData
->ftLastAccessTime
;
2743 lpFindFileData
->ftCreationTime
= lpFindFileData
->ftLastAccessTime
;
2745 /* Not all fields are filled in */
2746 lpFindFileData
->nFileSizeHigh
= 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */
2747 lpFindFileData
->nFileSizeLow
= lpafp
->nSize
;
2749 if (lpafp
->bIsDirectory
)
2750 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2752 if (lpafp
->lpszName
)
2753 strncpyW(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2761 /***********************************************************************
2762 * FTP_ParseNextFile (internal)
2764 * Parse the next line in file listing
2770 BOOL
FTP_ParseNextFile(INT nSocket
, LPCWSTR lpszSearchFile
, LPFILEPROPERTIESW lpfp
)
2772 static const char szSpace
[] = " \t";
2780 lpfp
->lpszName
= NULL
;
2782 if(!(pszLine
= INTERNET_GetNextLine(nSocket
, &nBufLen
)))
2785 pszToken
= strtok(pszLine
, szSpace
);
2787 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2790 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2792 if(!isdigit(pszToken
[0]) && 10 == strlen(pszToken
)) {
2793 if(!FTP_ParsePermission(pszToken
, lpfp
))
2794 lpfp
->bIsDirectory
= FALSE
;
2795 for(i
=0; i
<=3; i
++) {
2796 if(!(pszToken
= strtok(NULL
, szSpace
)))
2799 if(!pszToken
) continue;
2800 if(lpfp
->bIsDirectory
) {
2801 TRACE("Is directory\n");
2805 TRACE("Size: %s\n", pszToken
);
2806 lpfp
->nSize
= atol(pszToken
);
2809 lpfp
->tmLastModified
.tm_sec
= 0;
2810 lpfp
->tmLastModified
.tm_min
= 0;
2811 lpfp
->tmLastModified
.tm_hour
= 0;
2812 lpfp
->tmLastModified
.tm_mday
= 0;
2813 lpfp
->tmLastModified
.tm_mon
= 0;
2814 lpfp
->tmLastModified
.tm_year
= 0;
2816 /* Determine month */
2817 pszToken
= strtok(NULL
, szSpace
);
2818 if(!pszToken
) continue;
2819 if(strlen(pszToken
) >= 3) {
2821 if((pszTmp
= StrStrIA(szMonths
, pszToken
)))
2822 lpfp
->tmLastModified
.tm_mon
= ((pszTmp
- szMonths
) / 3)+1;
2825 pszToken
= strtok(NULL
, szSpace
);
2826 if(!pszToken
) continue;
2827 lpfp
->tmLastModified
.tm_mday
= atoi(pszToken
);
2828 /* Determine time or year */
2829 pszToken
= strtok(NULL
, szSpace
);
2830 if(!pszToken
) continue;
2831 if((pszTmp
= strchr(pszToken
, ':'))) {
2836 lpfp
->tmLastModified
.tm_min
= atoi(pszTmp
);
2837 lpfp
->tmLastModified
.tm_hour
= atoi(pszToken
);
2839 apTM
= localtime(&aTime
);
2840 lpfp
->tmLastModified
.tm_year
= apTM
->tm_year
;
2843 lpfp
->tmLastModified
.tm_year
= atoi(pszToken
) - 1900;
2844 lpfp
->tmLastModified
.tm_hour
= 12;
2846 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2847 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2848 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2849 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2851 pszToken
= strtok(NULL
, szSpace
);
2852 if(!pszToken
) continue;
2853 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2854 TRACE("File: %s\n", debugstr_w(lpfp
->lpszName
));
2856 /* NT way of parsing ... :
2858 07-13-03 08:55PM <DIR> sakpatch
2859 05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
2861 else if(isdigit(pszToken
[0]) && 8 == strlen(pszToken
)) {
2862 lpfp
->permissions
= 0xFFFF; /* No idea, put full permission :-) */
2864 sscanf(pszToken
, "%d-%d-%d",
2865 &lpfp
->tmLastModified
.tm_mon
,
2866 &lpfp
->tmLastModified
.tm_mday
,
2867 &lpfp
->tmLastModified
.tm_year
);
2869 /* Hacky and bad Y2K protection :-) */
2870 if (lpfp
->tmLastModified
.tm_year
< 70)
2871 lpfp
->tmLastModified
.tm_year
+= 100;
2873 pszToken
= strtok(NULL
, szSpace
);
2874 if(!pszToken
) continue;
2875 sscanf(pszToken
, "%d:%d",
2876 &lpfp
->tmLastModified
.tm_hour
,
2877 &lpfp
->tmLastModified
.tm_min
);
2878 if((pszToken
[5] == 'P') && (pszToken
[6] == 'M')) {
2879 lpfp
->tmLastModified
.tm_hour
+= 12;
2881 lpfp
->tmLastModified
.tm_sec
= 0;
2883 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2884 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2885 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2886 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2888 pszToken
= strtok(NULL
, szSpace
);
2889 if(!pszToken
) continue;
2890 if(!strcasecmp(pszToken
, "<DIR>")) {
2891 lpfp
->bIsDirectory
= TRUE
;
2893 TRACE("Is directory\n");
2896 lpfp
->bIsDirectory
= FALSE
;
2897 lpfp
->nSize
= atol(pszToken
);
2898 TRACE("Size: %ld\n", lpfp
->nSize
);
2901 pszToken
= strtok(NULL
, szSpace
);
2902 if(!pszToken
) continue;
2903 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2904 TRACE("Name: %s\n", debugstr_w(lpfp
->lpszName
));
2906 /* EPLF format - http://cr.yp.to/ftp/list/eplf.html */
2907 else if(pszToken
[0] == '+') {
2908 FIXME("EPLF Format not implemented\n");
2911 if(lpfp
->lpszName
) {
2912 if((lpszSearchFile
== NULL
) ||
2913 (PathMatchSpecW(lpfp
->lpszName
, lpszSearchFile
))) {
2915 TRACE("Matched: %s\n", debugstr_w(lpfp
->lpszName
));
2918 HeapFree(GetProcessHeap(), 0, lpfp
->lpszName
);
2919 lpfp
->lpszName
= NULL
;
2926 /***********************************************************************
2927 * FTP_ParseDirectory (internal)
2929 * Parse string of directory information
2935 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2936 LPFILEPROPERTIESW
*lpafp
, LPDWORD dwfp
)
2938 BOOL bSuccess
= TRUE
;
2939 INT sizeFilePropArray
= 500;/*20; */
2940 INT indexFilePropArray
= -1;
2944 /* Allocate intial file properties array */
2945 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESW
)*(sizeFilePropArray
));
2950 if (indexFilePropArray
+1 >= sizeFilePropArray
)
2952 LPFILEPROPERTIESW tmpafp
;
2954 sizeFilePropArray
*= 2;
2955 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2956 sizeof(FILEPROPERTIESW
)*sizeFilePropArray
);
2965 indexFilePropArray
++;
2966 } while (FTP_ParseNextFile(nSocket
, lpszSearchFile
, &(*lpafp
)[indexFilePropArray
]));
2968 if (bSuccess
&& indexFilePropArray
)
2970 if (indexFilePropArray
< sizeFilePropArray
- 1)
2972 LPFILEPROPERTIESW tmpafp
;
2974 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2975 sizeof(FILEPROPERTIESW
)*indexFilePropArray
);
2979 *dwfp
= indexFilePropArray
;
2983 HeapFree(GetProcessHeap(), 0, *lpafp
);
2984 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2992 /***********************************************************************
2993 * FTP_ParsePermission (internal)
2995 * Parse permission string of directory information
3002 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESW lpfp
)
3004 BOOL bSuccess
= TRUE
;
3005 unsigned short nPermission
= 0;
3010 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
3016 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
3022 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
3025 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
3028 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
3031 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
3034 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
3037 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
3040 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
3043 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
3046 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
3050 }while (nPos
<= nLast
);
3052 lpfp
->permissions
= nPermission
;
3057 /***********************************************************************
3058 * FTP_SetResponseError (internal)
3060 * Set the appropriate error code for a given response from the server
3065 DWORD
FTP_SetResponseError(DWORD dwResponse
)
3071 case 421: /* Service not available - Server may be shutting down. */
3072 dwCode
= ERROR_INTERNET_TIMEOUT
;
3075 case 425: /* Cannot open data connection. */
3076 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
3079 case 426: /* Connection closed, transer aborted. */
3080 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
3083 case 500: /* Syntax error. Command unrecognized. */
3084 case 501: /* Syntax error. Error in parameters or arguments. */
3085 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
3088 case 530: /* Not logged in. Login incorrect. */
3089 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
3092 case 550: /* File action not taken. File not found or no access. */
3093 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
3096 case 450: /* File action not taken. File may be busy. */
3097 case 451: /* Action aborted. Server error. */
3098 case 452: /* Action not taken. Insufficient storage space on server. */
3099 case 502: /* Command not implemented. */
3100 case 503: /* Bad sequence of command. */
3101 case 504: /* Command not implemented for that parameter. */
3102 case 532: /* Need account for storing files */
3103 case 551: /* Requested action aborted. Page type unknown */
3104 case 552: /* Action aborted. Exceeded storage allocation */
3105 case 553: /* Action not taken. File name not allowed. */
3108 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
3112 INTERNET_SetLastError(dwCode
);