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>
57 #include "wine/debug.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(wininet
);
62 #define DATA_PACKET_SIZE 0x2000
67 /* FTP commands with arguments. */
83 /* FTP commands without arguments. */
92 static const CHAR
*szFtpCommands
[] = {
115 static const CHAR szMonths
[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
116 static const WCHAR szNoAccount
[] = {'n','o','a','c','c','o','u','n','t','\0'};
118 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCWSTR lpszParam
,
119 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
);
120 BOOL
FTP_SendStore(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
);
121 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs
, LPINT nDataSocket
);
122 BOOL
FTP_SendData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, HANDLE hFile
);
123 INT
FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs
, DWORD dwContext
);
124 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
);
125 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
);
126 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs
);
127 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs
);
128 BOOL
FTP_SendPassword(LPWININETFTPSESSIONW lpwfs
);
129 BOOL
FTP_SendAccount(LPWININETFTPSESSIONW lpwfs
);
130 BOOL
FTP_SendType(LPWININETFTPSESSIONW lpwfs
, DWORD dwType
);
131 BOOL
FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD
*dwSize
);
132 BOOL
FTP_SendPort(LPWININETFTPSESSIONW lpwfs
);
133 BOOL
FTP_DoPassive(LPWININETFTPSESSIONW lpwfs
);
134 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs
);
135 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESW lpfp
);
136 BOOL
FTP_ParseNextFile(INT nSocket
, LPCWSTR lpszSearchFile
, LPFILEPROPERTIESW fileprop
);
137 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
138 LPFILEPROPERTIESW
*lpafp
, LPDWORD dwfp
);
139 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
140 LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwContext
);
141 DWORD
FTP_SetResponseError(DWORD dwResponse
);
143 /***********************************************************************
144 * FtpPutFileA (WININET.@)
146 * Uploads a file to the FTP server
153 BOOL WINAPI
FtpPutFileA(HINTERNET hConnect
, LPCSTR lpszLocalFile
,
154 LPCSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
156 LPWSTR lpwzLocalFile
;
157 LPWSTR lpwzNewRemoteFile
;
160 lpwzLocalFile
= lpszLocalFile
?WININET_strdup_AtoW(lpszLocalFile
):NULL
;
161 lpwzNewRemoteFile
= lpszNewRemoteFile
?WININET_strdup_AtoW(lpszNewRemoteFile
):NULL
;
162 ret
= FtpPutFileW(hConnect
, lpwzLocalFile
, lpwzNewRemoteFile
,
164 if(lpwzLocalFile
) HeapFree(GetProcessHeap(), 0, lpwzLocalFile
);
165 if(lpwzNewRemoteFile
) HeapFree(GetProcessHeap(), 0, lpwzNewRemoteFile
);
169 /***********************************************************************
170 * FtpPutFileW (WININET.@)
172 * Uploads a file to the FTP server
179 BOOL WINAPI
FtpPutFileW(HINTERNET hConnect
, LPCWSTR lpszLocalFile
,
180 LPCWSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
182 LPWININETFTPSESSIONW lpwfs
;
183 LPWININETAPPINFOW hIC
= NULL
;
185 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
186 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
188 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
192 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
193 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
195 WORKREQUEST workRequest
;
196 struct WORKREQ_FTPPUTFILEW
*req
= &workRequest
.u
.FtpPutFileW
;
198 workRequest
.asyncall
= FTPPUTFILEW
;
199 workRequest
.handle
= hConnect
;
200 req
->lpszLocalFile
= WININET_strdupW(lpszLocalFile
);
201 req
->lpszNewRemoteFile
= WININET_strdupW(lpszNewRemoteFile
);
202 req
->dwFlags
= dwFlags
;
203 req
->dwContext
= dwContext
;
205 return INTERNET_AsyncCall(&workRequest
);
209 return FTP_FtpPutFileW(hConnect
, lpszLocalFile
,
210 lpszNewRemoteFile
, dwFlags
, dwContext
);
214 /***********************************************************************
215 * FTP_FtpPutFileW (Internal)
217 * Uploads a file to the FTP server
224 BOOL WINAPI
FTP_FtpPutFileW(HINTERNET hConnect
, LPCWSTR lpszLocalFile
,
225 LPCWSTR lpszNewRemoteFile
, DWORD dwFlags
, DWORD dwContext
)
228 BOOL bSuccess
= FALSE
;
229 LPWININETAPPINFOW hIC
= NULL
;
230 LPWININETFTPSESSIONW lpwfs
;
233 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", debugstr_w(lpszLocalFile
), debugstr_w(lpszNewRemoteFile
));
235 if (!lpszLocalFile
|| !lpszNewRemoteFile
)
237 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
241 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
242 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
244 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
248 /* Clear any error information */
249 INTERNET_SetLastError(0);
251 /* Open file to be uploaded */
252 if (INVALID_HANDLE_VALUE
==
253 (hFile
= CreateFileW(lpszLocalFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0)))
255 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND
);
259 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
260 SendAsyncCallback(hIC
, hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
262 if (FTP_SendStore(lpwfs
, lpszNewRemoteFile
, dwFlags
))
266 /* Get data socket to server */
267 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
269 FTP_SendData(lpwfs
, nDataSocket
, hFile
);
271 nResCode
= FTP_ReceiveResponse(lpwfs
, dwContext
);
277 FTP_SetResponseError(nResCode
);
283 if (lpwfs
->lstnSocket
!= -1)
284 close(lpwfs
->lstnSocket
);
286 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
288 INTERNET_ASYNC_RESULT iar
;
290 iar
.dwResult
= (DWORD
)bSuccess
;
291 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
292 SendAsyncCallback(hIC
, hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
293 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
303 /***********************************************************************
304 * FtpSetCurrentDirectoryA (WININET.@)
306 * Change the working directory on the FTP server
313 BOOL WINAPI
FtpSetCurrentDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
315 LPWSTR lpwzDirectory
;
318 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
319 ret
= FtpSetCurrentDirectoryW(hConnect
, lpwzDirectory
);
320 if(lpwzDirectory
) HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
325 /***********************************************************************
326 * FtpSetCurrentDirectoryW (WININET.@)
328 * Change the working directory on the FTP server
335 BOOL WINAPI
FtpSetCurrentDirectoryW(HINTERNET hConnect
, LPCWSTR lpszDirectory
)
337 LPWININETFTPSESSIONW lpwfs
;
338 LPWININETAPPINFOW hIC
= NULL
;
340 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
341 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
343 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
347 TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory
));
349 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
350 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
352 WORKREQUEST workRequest
;
353 struct WORKREQ_FTPSETCURRENTDIRECTORYW
*req
;
355 workRequest
.asyncall
= FTPSETCURRENTDIRECTORYW
;
356 workRequest
.handle
= hConnect
;
357 req
= &workRequest
.u
.FtpSetCurrentDirectoryW
;
358 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
360 return INTERNET_AsyncCall(&workRequest
);
364 return FTP_FtpSetCurrentDirectoryW(hConnect
, lpszDirectory
);
369 /***********************************************************************
370 * FTP_FtpSetCurrentDirectoryW (Internal)
372 * Change the working directory on the FTP server
379 BOOL WINAPI
FTP_FtpSetCurrentDirectoryW(HINTERNET hConnect
, LPCWSTR lpszDirectory
)
382 LPWININETFTPSESSIONW lpwfs
;
383 LPWININETAPPINFOW hIC
= NULL
;
384 DWORD bSuccess
= FALSE
;
386 TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory
));
388 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
389 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
391 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
395 /* Clear any error information */
396 INTERNET_SetLastError(0);
398 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
399 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_CWD
, lpszDirectory
,
400 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
403 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
410 FTP_SetResponseError(nResCode
);
414 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
416 INTERNET_ASYNC_RESULT iar
;
418 iar
.dwResult
= (DWORD
)bSuccess
;
419 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
420 SendAsyncCallback(hIC
, hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
421 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
427 /***********************************************************************
428 * FtpCreateDirectoryA (WININET.@)
430 * Create new directory on the FTP server
437 BOOL WINAPI
FtpCreateDirectoryA(HINTERNET hConnect
, LPCSTR lpszDirectory
)
439 LPWSTR lpwzDirectory
;
442 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
443 ret
= FtpCreateDirectoryW(hConnect
, lpwzDirectory
);
444 if(lpwzDirectory
) HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
449 /***********************************************************************
450 * FtpCreateDirectoryW (WININET.@)
452 * Create new directory on the FTP server
459 BOOL WINAPI
FtpCreateDirectoryW(HINTERNET hConnect
, LPCWSTR lpszDirectory
)
461 LPWININETFTPSESSIONW lpwfs
;
462 LPWININETAPPINFOW hIC
= NULL
;
464 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
465 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
467 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
471 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
472 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
474 WORKREQUEST workRequest
;
475 struct WORKREQ_FTPCREATEDIRECTORYW
*req
;
477 workRequest
.asyncall
= FTPCREATEDIRECTORYW
;
478 workRequest
.handle
= hConnect
;
479 req
= &workRequest
.u
.FtpCreateDirectoryW
;
480 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
482 return INTERNET_AsyncCall(&workRequest
);
486 return FTP_FtpCreateDirectoryW(hConnect
, lpszDirectory
);
491 /***********************************************************************
492 * FTP_FtpCreateDirectoryW (Internal)
494 * Create new directory on the FTP server
501 BOOL WINAPI
FTP_FtpCreateDirectoryW(HINTERNET hConnect
, LPCWSTR lpszDirectory
)
504 BOOL bSuccess
= FALSE
;
505 LPWININETAPPINFOW hIC
= NULL
;
506 LPWININETFTPSESSIONW lpwfs
;
508 TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory
));
510 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
511 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
513 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
517 /* Clear any error information */
518 INTERNET_SetLastError(0);
520 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_MKD
, lpszDirectory
, 0, 0, 0))
523 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
529 FTP_SetResponseError(nResCode
);
533 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
534 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
536 INTERNET_ASYNC_RESULT iar
;
538 iar
.dwResult
= (DWORD
)bSuccess
;
539 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
540 SendAsyncCallback(hIC
, hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
541 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
547 /***********************************************************************
548 * FtpFindFirstFileA (WININET.@)
550 * Search the specified directory
553 * HINTERNET on success
557 HINTERNET WINAPI
FtpFindFirstFileA(HINTERNET hConnect
,
558 LPCSTR lpszSearchFile
, LPWIN32_FIND_DATAA lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
560 LPWSTR lpwzSearchFile
;
561 WIN32_FIND_DATAW wfd
;
562 LPWIN32_FIND_DATAW lpFindFileDataW
;
565 lpwzSearchFile
= lpszSearchFile
?WININET_strdup_AtoW(lpszSearchFile
):NULL
;
566 lpFindFileDataW
= lpFindFileData
?&wfd
:NULL
;
567 ret
= FtpFindFirstFileW(hConnect
, lpwzSearchFile
, lpFindFileDataW
, dwFlags
, dwContext
);
568 if(lpwzSearchFile
) HeapFree(GetProcessHeap(), 0, lpwzSearchFile
);
571 WININET_find_data_WtoA(lpFindFileDataW
, lpFindFileData
);
577 /***********************************************************************
578 * FtpFindFirstFileW (WININET.@)
580 * Search the specified directory
583 * HINTERNET on success
587 HINTERNET WINAPI
FtpFindFirstFileW(HINTERNET hConnect
,
588 LPCWSTR lpszSearchFile
, LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
590 LPWININETFTPSESSIONW lpwfs
;
591 LPWININETAPPINFOW hIC
= NULL
;
593 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
594 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
596 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
600 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
601 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
603 WORKREQUEST workRequest
;
604 struct WORKREQ_FTPFINDFIRSTFILEW
*req
;
606 workRequest
.asyncall
= FTPFINDFIRSTFILEW
;
607 workRequest
.handle
= hConnect
;
608 req
= &workRequest
.u
.FtpFindFirstFileW
;
609 req
->lpszSearchFile
= (lpszSearchFile
== NULL
) ? NULL
: WININET_strdupW(lpszSearchFile
);
610 req
->lpFindFileData
= lpFindFileData
;
611 req
->dwFlags
= dwFlags
;
612 req
->dwContext
= dwContext
;
614 INTERNET_AsyncCall(&workRequest
);
619 return FTP_FtpFindFirstFileW(hConnect
, lpszSearchFile
, lpFindFileData
,
625 /***********************************************************************
626 * FTP_FtpFindFirstFileW (Internal)
628 * Search the specified directory
631 * HINTERNET on success
635 HINTERNET WINAPI
FTP_FtpFindFirstFileW(HINTERNET hConnect
,
636 LPCWSTR lpszSearchFile
, LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwFlags
, DWORD dwContext
)
639 LPWININETAPPINFOW hIC
= NULL
;
640 LPWININETFTPSESSIONW lpwfs
;
641 HINTERNET hFindNext
= NULL
;
645 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hConnect
);
646 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
648 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
652 /* Clear any error information */
653 INTERNET_SetLastError(0);
655 if (!FTP_InitListenSocket(lpwfs
))
658 if (!FTP_SendType(lpwfs
, INTERNET_FLAG_TRANSFER_ASCII
))
661 if (!FTP_SendPortOrPasv(lpwfs
))
664 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
665 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_LIST
, NULL
,
666 hIC
->lpfnStatusCB
, hConnect
, lpwfs
->hdr
.dwContext
))
669 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
672 if (nResCode
== 125 || nResCode
== 150)
676 /* Get data socket to server */
677 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
679 hFindNext
= FTP_ReceiveFileList(lpwfs
, nDataSocket
, lpszSearchFile
, lpFindFileData
, dwContext
);
681 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
682 if (nResCode
!= 226 && nResCode
!= 250)
683 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
687 FTP_SetResponseError(nResCode
);
691 if (lpwfs
->lstnSocket
!= -1)
692 close(lpwfs
->lstnSocket
);
694 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
696 INTERNET_ASYNC_RESULT iar
;
700 iar
.dwResult
= (DWORD
)hFindNext
;
701 iar
.dwError
= ERROR_SUCCESS
;
702 SendAsyncCallback(hIC
, hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
703 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
706 iar
.dwResult
= (DWORD
)hFindNext
;
707 iar
.dwError
= hFindNext
? ERROR_SUCCESS
: INTERNET_GetLastError();
708 SendAsyncCallback(hIC
, hConnect
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
709 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
716 /***********************************************************************
717 * FtpGetCurrentDirectoryA (WININET.@)
719 * Retrieves the current directory
726 BOOL WINAPI
FtpGetCurrentDirectoryA(HINTERNET hFtpSession
, LPSTR lpszCurrentDirectory
,
727 LPDWORD lpdwCurrentDirectory
)
733 if(lpdwCurrentDirectory
) len
= *lpdwCurrentDirectory
;
734 ret
= FtpGetCurrentDirectoryW(hFtpSession
, lpszCurrentDirectory
?dir
:NULL
, lpdwCurrentDirectory
?&len
:NULL
);
735 if(lpdwCurrentDirectory
) {
736 *lpdwCurrentDirectory
= len
;
737 if(lpszCurrentDirectory
)
738 WideCharToMultiByte(CP_ACP
, 0, dir
, len
, lpszCurrentDirectory
, *lpdwCurrentDirectory
, NULL
, NULL
);
744 /***********************************************************************
745 * FtpGetCurrentDirectoryW (WININET.@)
747 * Retrieves the current directory
754 BOOL WINAPI
FtpGetCurrentDirectoryW(HINTERNET hFtpSession
, LPWSTR lpszCurrentDirectory
,
755 LPDWORD lpdwCurrentDirectory
)
757 LPWININETFTPSESSIONW lpwfs
;
758 LPWININETAPPINFOW hIC
= NULL
;
760 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
762 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
763 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
765 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
769 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
770 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
772 WORKREQUEST workRequest
;
773 struct WORKREQ_FTPGETCURRENTDIRECTORYW
*req
;
775 workRequest
.asyncall
= FTPGETCURRENTDIRECTORYW
;
776 workRequest
.handle
= hFtpSession
;
777 req
= &workRequest
.u
.FtpGetCurrentDirectoryW
;
778 req
->lpszDirectory
= lpszCurrentDirectory
;
779 req
->lpdwDirectory
= lpdwCurrentDirectory
;
781 return INTERNET_AsyncCall(&workRequest
);
785 return FTP_FtpGetCurrentDirectoryW(hFtpSession
, lpszCurrentDirectory
,
786 lpdwCurrentDirectory
);
791 /***********************************************************************
792 * FTP_FtpGetCurrentDirectoryA (Internal)
794 * Retrieves the current directory
801 BOOL WINAPI
FTP_FtpGetCurrentDirectoryW(HINTERNET hFtpSession
, LPWSTR lpszCurrentDirectory
,
802 LPDWORD lpdwCurrentDirectory
)
805 LPWININETFTPSESSIONW lpwfs
;
806 LPWININETAPPINFOW hIC
= NULL
;
807 DWORD bSuccess
= FALSE
;
809 TRACE("len(%ld)\n", *lpdwCurrentDirectory
);
811 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
812 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
814 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
818 /* Clear any error information */
819 INTERNET_SetLastError(0);
821 ZeroMemory(lpszCurrentDirectory
, *lpdwCurrentDirectory
);
823 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
824 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PWD
, NULL
,
825 hIC
->lpfnStatusCB
, hFtpSession
, lpwfs
->hdr
.dwContext
))
828 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
831 if (nResCode
== 257) /* Extract directory name */
833 INT firstpos
, lastpos
, len
;
834 LPWSTR lpszResponseBuffer
= WININET_strdup_AtoW(INTERNET_GetResponseBuffer());
836 for (firstpos
= 0, lastpos
= 0; lpszResponseBuffer
[lastpos
]; lastpos
++)
838 if ('"' == lpszResponseBuffer
[lastpos
])
847 len
= lastpos
- firstpos
- 1;
848 strncpyW(lpszCurrentDirectory
, &lpszResponseBuffer
[firstpos
+1],
849 len
< *lpdwCurrentDirectory
? len
: *lpdwCurrentDirectory
);
850 HeapFree(GetProcessHeap(), 0, lpszResponseBuffer
);
851 *lpdwCurrentDirectory
= len
;
855 FTP_SetResponseError(nResCode
);
859 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
861 INTERNET_ASYNC_RESULT iar
;
863 iar
.dwResult
= (DWORD
)bSuccess
;
864 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: ERROR_INTERNET_EXTENDED_ERROR
;
865 SendAsyncCallback(hIC
, hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
866 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
869 return (DWORD
) bSuccess
;
872 /***********************************************************************
873 * FtpOpenFileA (WININET.@)
875 * Open a remote file for writing or reading
878 * HINTERNET handle on success
882 HINTERNET WINAPI
FtpOpenFileA(HINTERNET hFtpSession
,
883 LPCSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
889 lpwzFileName
= lpszFileName
?WININET_strdup_AtoW(lpszFileName
):NULL
;
890 ret
= FtpOpenFileW(hFtpSession
, lpwzFileName
, fdwAccess
, dwFlags
, dwContext
);
891 if(lpwzFileName
) HeapFree(GetProcessHeap(), 0, lpwzFileName
);
896 /***********************************************************************
897 * FtpOpenFileW (WININET.@)
899 * Open a remote file for writing or reading
902 * HINTERNET handle on success
906 HINTERNET WINAPI
FtpOpenFileW(HINTERNET hFtpSession
,
907 LPCWSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
910 LPWININETFTPSESSIONW lpwfs
;
911 LPWININETAPPINFOW hIC
= NULL
;
913 TRACE("(%p,%s,0x%08lx,0x%08lx,0x%08lx)\n", hFtpSession
,
914 debugstr_w(lpszFileName
), fdwAccess
, dwFlags
, dwContext
);
916 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
917 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
919 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
923 if (lpwfs
->download_in_progress
!= NULL
) {
924 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
927 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
928 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
930 WORKREQUEST workRequest
;
931 struct WORKREQ_FTPOPENFILEW
*req
;
933 workRequest
.asyncall
= FTPOPENFILEW
;
934 workRequest
.handle
= hFtpSession
;
935 req
= &workRequest
.u
.FtpOpenFileW
;
936 req
->lpszFilename
= WININET_strdupW(lpszFileName
);
937 req
->dwAccess
= fdwAccess
;
938 req
->dwFlags
= dwFlags
;
939 req
->dwContext
= dwContext
;
941 INTERNET_AsyncCall(&workRequest
);
946 return FTP_FtpOpenFileW(hFtpSession
, lpszFileName
, fdwAccess
, dwFlags
, dwContext
);
951 /***********************************************************************
952 * FTP_FtpOpenFileW (Internal)
954 * Open a remote file for writing or reading
957 * HINTERNET handle on success
961 HINTERNET
FTP_FtpOpenFileW(HINTERNET hFtpSession
,
962 LPCWSTR lpszFileName
, DWORD fdwAccess
, DWORD dwFlags
,
966 BOOL bSuccess
= FALSE
;
967 LPWININETFILE lpwh
= NULL
;
968 LPWININETAPPINFOW hIC
= NULL
;
969 LPWININETFTPSESSIONW lpwfs
;
970 HINTERNET handle
= NULL
;
974 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
975 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
977 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
981 /* Clear any error information */
982 INTERNET_SetLastError(0);
984 if (GENERIC_READ
== fdwAccess
)
986 /* Set up socket to retrieve data */
987 bSuccess
= FTP_SendRetrieve(lpwfs
, lpszFileName
, dwFlags
);
989 else if (GENERIC_WRITE
== fdwAccess
)
991 /* Set up socket to send data */
992 bSuccess
= FTP_SendStore(lpwfs
, lpszFileName
, dwFlags
);
995 /* Get data socket to server */
996 if (bSuccess
&& FTP_GetDataSocket(lpwfs
, &nDataSocket
))
998 lpwh
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE
));
999 handle
= WININET_AllocHandle( &lpwh
->hdr
);
1000 lpwh
->hdr
.htype
= WH_HFILE
;
1001 lpwh
->hdr
.dwFlags
= dwFlags
;
1002 lpwh
->hdr
.dwContext
= dwContext
;
1003 lpwh
->hdr
.lpwhparent
= &lpwfs
->hdr
;
1004 lpwh
->nDataSocket
= nDataSocket
;
1005 lpwh
->session_deleted
= FALSE
;
1007 /* Indicate that a download is currently in progress */
1008 lpwfs
->download_in_progress
= lpwh
;
1011 if (lpwfs
->lstnSocket
!= -1)
1012 close(lpwfs
->lstnSocket
);
1014 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1015 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1017 INTERNET_ASYNC_RESULT iar
;
1021 iar
.dwResult
= (DWORD
)handle
;
1022 iar
.dwError
= ERROR_SUCCESS
;
1023 SendAsyncCallback(hIC
, hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_HANDLE_CREATED
,
1024 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1027 iar
.dwResult
= (DWORD
)bSuccess
;
1028 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1029 SendAsyncCallback(hIC
, hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1030 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1037 /***********************************************************************
1038 * FtpGetFileA (WININET.@)
1040 * Retrieve file from the FTP server
1047 BOOL WINAPI
FtpGetFileA(HINTERNET hInternet
, LPCSTR lpszRemoteFile
, LPCSTR lpszNewFile
,
1048 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1051 LPWSTR lpwzRemoteFile
;
1055 lpwzRemoteFile
= lpszRemoteFile
?WININET_strdup_AtoW(lpszRemoteFile
):NULL
;
1056 lpwzNewFile
= lpszNewFile
?WININET_strdup_AtoW(lpszNewFile
):NULL
;
1057 ret
= FtpGetFileW(hInternet
, lpwzRemoteFile
, lpwzNewFile
, fFailIfExists
,
1058 dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
1059 if(lpwzRemoteFile
) HeapFree(GetProcessHeap(), 0, lpwzRemoteFile
);
1060 if(lpwzNewFile
) HeapFree(GetProcessHeap(), 0, lpwzNewFile
);
1065 /***********************************************************************
1066 * FtpGetFileW (WININET.@)
1068 * Retrieve file from the FTP server
1075 BOOL WINAPI
FtpGetFileW(HINTERNET hInternet
, LPCWSTR lpszRemoteFile
, LPCWSTR lpszNewFile
,
1076 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1079 LPWININETFTPSESSIONW lpwfs
;
1080 LPWININETAPPINFOW hIC
= NULL
;
1082 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hInternet
);
1083 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1085 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1089 if (lpwfs
->download_in_progress
!= NULL
) {
1090 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
1094 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1095 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1097 WORKREQUEST workRequest
;
1098 struct WORKREQ_FTPGETFILEW
*req
;
1100 workRequest
.asyncall
= FTPGETFILEW
;
1101 workRequest
.handle
= hInternet
;
1102 req
= &workRequest
.u
.FtpGetFileW
;
1103 req
->lpszRemoteFile
= WININET_strdupW(lpszRemoteFile
);
1104 req
->lpszNewFile
= WININET_strdupW(lpszNewFile
);
1105 req
->dwLocalFlagsAttribute
= dwLocalFlagsAttribute
;
1106 req
->fFailIfExists
= fFailIfExists
;
1107 req
->dwFlags
= dwInternetFlags
;
1108 req
->dwContext
= dwContext
;
1110 return INTERNET_AsyncCall(&workRequest
);
1114 return FTP_FtpGetFileW(hInternet
, lpszRemoteFile
, lpszNewFile
,
1115 fFailIfExists
, dwLocalFlagsAttribute
, dwInternetFlags
, dwContext
);
1120 /***********************************************************************
1121 * FTP_FtpGetFileW (Internal)
1123 * Retrieve file from the FTP server
1130 BOOL WINAPI
FTP_FtpGetFileW(HINTERNET hInternet
, LPCWSTR lpszRemoteFile
, LPCWSTR lpszNewFile
,
1131 BOOL fFailIfExists
, DWORD dwLocalFlagsAttribute
, DWORD dwInternetFlags
,
1135 BOOL bSuccess
= FALSE
;
1137 LPWININETAPPINFOW hIC
= NULL
;
1138 LPWININETFTPSESSIONW lpwfs
;
1140 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", debugstr_w(lpszRemoteFile
), debugstr_w(lpszNewFile
));
1142 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hInternet
);
1143 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1145 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1149 /* Clear any error information */
1150 INTERNET_SetLastError(0);
1152 /* Ensure we can write to lpszNewfile by opening it */
1153 hFile
= CreateFileW(lpszNewFile
, GENERIC_WRITE
, 0, 0, fFailIfExists
?
1154 CREATE_NEW
: CREATE_ALWAYS
, dwLocalFlagsAttribute
, 0);
1155 if (INVALID_HANDLE_VALUE
== hFile
)
1158 /* Set up socket to retrieve data */
1159 nBytes
= FTP_SendRetrieve(lpwfs
, lpszRemoteFile
, dwInternetFlags
);
1165 /* Get data socket to server */
1166 if (FTP_GetDataSocket(lpwfs
, &nDataSocket
))
1171 FTP_RetrieveFileData(lpwfs
, nDataSocket
, nBytes
, hFile
);
1172 nResCode
= FTP_ReceiveResponse(lpwfs
, dwContext
);
1175 if (nResCode
== 226)
1178 FTP_SetResponseError(nResCode
);
1185 if (lpwfs
->lstnSocket
!= -1)
1186 close(lpwfs
->lstnSocket
);
1191 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1192 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1194 INTERNET_ASYNC_RESULT iar
;
1196 iar
.dwResult
= (DWORD
)bSuccess
;
1197 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1198 SendAsyncCallback(hIC
, hInternet
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1199 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1206 /***********************************************************************
1207 * FtpDeleteFileA (WININET.@)
1209 * Delete a file on the ftp server
1216 BOOL WINAPI
FtpDeleteFileA(HINTERNET hFtpSession
, LPCSTR lpszFileName
)
1218 LPWSTR lpwzFileName
;
1221 lpwzFileName
= lpszFileName
?WININET_strdup_AtoW(lpszFileName
):NULL
;
1222 ret
= FtpDeleteFileW(hFtpSession
, lpwzFileName
);
1223 if(lpwzFileName
) HeapFree(GetProcessHeap(), 0, lpwzFileName
);
1227 /***********************************************************************
1228 * FtpDeleteFileW (WININET.@)
1230 * Delete a file on the ftp server
1237 BOOL WINAPI
FtpDeleteFileW(HINTERNET hFtpSession
, LPCWSTR lpszFileName
)
1239 LPWININETFTPSESSIONW lpwfs
;
1240 LPWININETAPPINFOW hIC
= NULL
;
1242 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1243 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1245 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1249 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1250 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1252 WORKREQUEST workRequest
;
1253 struct WORKREQ_FTPDELETEFILEW
*req
;
1255 workRequest
.asyncall
= FTPDELETEFILEW
;
1256 workRequest
.handle
= hFtpSession
;
1257 req
= &workRequest
.u
.FtpDeleteFileW
;
1258 req
->lpszFilename
= WININET_strdupW(lpszFileName
);
1260 return INTERNET_AsyncCall(&workRequest
);
1264 return FTP_FtpDeleteFileW(hFtpSession
, lpszFileName
);
1268 /***********************************************************************
1269 * FTP_FtpDeleteFileW (Internal)
1271 * Delete a file on the ftp server
1278 BOOL
FTP_FtpDeleteFileW(HINTERNET hFtpSession
, LPCWSTR lpszFileName
)
1281 BOOL bSuccess
= FALSE
;
1282 LPWININETAPPINFOW hIC
= NULL
;
1283 LPWININETFTPSESSIONW lpwfs
;
1285 TRACE("0x%08lx\n", (ULONG
) hFtpSession
);
1287 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1288 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1290 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1294 /* Clear any error information */
1295 INTERNET_SetLastError(0);
1297 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_DELE
, lpszFileName
, 0, 0, 0))
1300 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1303 if (nResCode
== 250)
1306 FTP_SetResponseError(nResCode
);
1309 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1310 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1312 INTERNET_ASYNC_RESULT iar
;
1314 iar
.dwResult
= (DWORD
)bSuccess
;
1315 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1316 SendAsyncCallback(hIC
, hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1317 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1324 /***********************************************************************
1325 * FtpRemoveDirectoryA (WININET.@)
1327 * Remove a directory on the ftp server
1334 BOOL WINAPI
FtpRemoveDirectoryA(HINTERNET hFtpSession
, LPCSTR lpszDirectory
)
1336 LPWSTR lpwzDirectory
;
1339 lpwzDirectory
= lpszDirectory
?WININET_strdup_AtoW(lpszDirectory
):NULL
;
1340 ret
= FtpRemoveDirectoryW(hFtpSession
, lpwzDirectory
);
1341 if(lpwzDirectory
) HeapFree(GetProcessHeap(), 0, lpwzDirectory
);
1345 /***********************************************************************
1346 * FtpRemoveDirectoryW (WININET.@)
1348 * Remove a directory on the ftp server
1355 BOOL WINAPI
FtpRemoveDirectoryW(HINTERNET hFtpSession
, LPCWSTR lpszDirectory
)
1357 LPWININETFTPSESSIONW lpwfs
;
1358 LPWININETAPPINFOW hIC
= NULL
;
1360 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1361 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1363 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1367 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1368 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1370 WORKREQUEST workRequest
;
1371 struct WORKREQ_FTPREMOVEDIRECTORYW
*req
;
1373 workRequest
.asyncall
= FTPREMOVEDIRECTORYW
;
1374 workRequest
.handle
= hFtpSession
;
1375 req
= &workRequest
.u
.FtpRemoveDirectoryW
;
1376 req
->lpszDirectory
= WININET_strdupW(lpszDirectory
);
1378 return INTERNET_AsyncCall(&workRequest
);
1382 return FTP_FtpRemoveDirectoryW(hFtpSession
, lpszDirectory
);
1386 /***********************************************************************
1387 * FTP_FtpRemoveDirectoryW (Internal)
1389 * Remove a directory on the ftp server
1396 BOOL
FTP_FtpRemoveDirectoryW(HINTERNET hFtpSession
, LPCWSTR lpszDirectory
)
1399 BOOL bSuccess
= FALSE
;
1400 LPWININETAPPINFOW hIC
= NULL
;
1401 LPWININETFTPSESSIONW lpwfs
;
1405 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1406 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1408 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1412 /* Clear any error information */
1413 INTERNET_SetLastError(0);
1415 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RMD
, lpszDirectory
, 0, 0, 0))
1418 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1421 if (nResCode
== 250)
1424 FTP_SetResponseError(nResCode
);
1428 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1429 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1431 INTERNET_ASYNC_RESULT iar
;
1433 iar
.dwResult
= (DWORD
)bSuccess
;
1434 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1435 SendAsyncCallback(hIC
, hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1436 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1443 /***********************************************************************
1444 * FtpRenameFileA (WININET.@)
1446 * Rename a file on the ftp server
1453 BOOL WINAPI
FtpRenameFileA(HINTERNET hFtpSession
, LPCSTR lpszSrc
, LPCSTR lpszDest
)
1459 lpwzSrc
= lpszSrc
?WININET_strdup_AtoW(lpszSrc
):NULL
;
1460 lpwzDest
= lpszDest
?WININET_strdup_AtoW(lpszDest
):NULL
;
1461 ret
= FtpRenameFileW(hFtpSession
, lpwzSrc
, lpwzDest
);
1462 if(lpwzSrc
) HeapFree(GetProcessHeap(), 0, lpwzSrc
);
1463 if(lpwzDest
) HeapFree(GetProcessHeap(), 0, lpwzDest
);
1467 /***********************************************************************
1468 * FtpRenameFileW (WININET.@)
1470 * Rename a file on the ftp server
1477 BOOL WINAPI
FtpRenameFileW(HINTERNET hFtpSession
, LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1479 LPWININETFTPSESSIONW lpwfs
;
1480 LPWININETAPPINFOW hIC
= NULL
;
1482 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1483 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1485 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1489 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1490 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
1492 WORKREQUEST workRequest
;
1493 struct WORKREQ_FTPRENAMEFILEW
*req
;
1495 workRequest
.asyncall
= FTPRENAMEFILEW
;
1496 workRequest
.handle
= hFtpSession
;
1497 req
= &workRequest
.u
.FtpRenameFileW
;
1498 req
->lpszSrcFile
= WININET_strdupW(lpszSrc
);
1499 req
->lpszDestFile
= WININET_strdupW(lpszDest
);
1501 return INTERNET_AsyncCall(&workRequest
);
1505 return FTP_FtpRenameFileW(hFtpSession
, lpszSrc
, lpszDest
);
1509 /***********************************************************************
1510 * FTP_FtpRenameFileA (Internal)
1512 * Rename a file on the ftp server
1519 BOOL
FTP_FtpRenameFileW(HINTERNET hFtpSession
, LPCWSTR lpszSrc
, LPCWSTR lpszDest
)
1522 BOOL bSuccess
= FALSE
;
1523 LPWININETAPPINFOW hIC
= NULL
;
1524 LPWININETFTPSESSIONW lpwfs
;
1528 lpwfs
= (LPWININETFTPSESSIONW
) WININET_GetObject( hFtpSession
);
1529 if (NULL
== lpwfs
|| WH_HFTPSESSION
!= lpwfs
->hdr
.htype
)
1531 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
1535 /* Clear any error information */
1536 INTERNET_SetLastError(0);
1538 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNFR
, lpszSrc
, 0, 0, 0))
1541 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1542 if (nResCode
== 350)
1544 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RNTO
, lpszDest
, 0, 0, 0))
1547 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1550 if (nResCode
== 250)
1553 FTP_SetResponseError(nResCode
);
1556 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1557 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1559 INTERNET_ASYNC_RESULT iar
;
1561 iar
.dwResult
= (DWORD
)bSuccess
;
1562 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1563 SendAsyncCallback(hIC
, hFtpSession
, lpwfs
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1564 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1571 /***********************************************************************
1572 * FTP_Connect (internal)
1574 * Connect to a ftp server
1577 * HINTERNET a session handle on success
1582 HINTERNET
FTP_Connect(HINTERNET hInternet
, LPCWSTR lpszServerName
,
1583 INTERNET_PORT nServerPort
, LPCWSTR lpszUserName
,
1584 LPCWSTR lpszPassword
, DWORD dwFlags
, DWORD dwContext
,
1585 DWORD dwInternalFlags
)
1587 static const WCHAR szDefaultUsername
[] = {'a','n','o','n','y','m','o','u','s','\0'};
1588 static const WCHAR szDefaultPassword
[] = {'u','s','e','r','@','s','e','r','v','e','r','\0'};
1589 struct sockaddr_in socketAddr
;
1590 struct hostent
*phe
= NULL
;
1591 INT nsocket
= -1, sock_namelen
;
1592 LPWININETAPPINFOW hIC
= NULL
;
1593 BOOL bSuccess
= FALSE
;
1594 LPWININETFTPSESSIONW lpwfs
= NULL
;
1595 HINTERNET handle
= NULL
;
1597 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1598 (ULONG
) hInternet
, debugstr_w(lpszServerName
),
1599 nServerPort
, debugstr_w(lpszUserName
), debugstr_w(lpszPassword
));
1601 hIC
= (LPWININETAPPINFOW
) WININET_GetObject( hInternet
);
1602 if ( (hIC
== NULL
) || (hIC
->hdr
.htype
!= WH_HINIT
) )
1605 if (NULL
== lpszUserName
&& NULL
!= lpszPassword
)
1607 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
1611 lpwfs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONW
));
1614 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1618 handle
= WININET_AllocHandle( &lpwfs
->hdr
);
1621 ERR("Failed to alloc handle\n");
1622 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1626 if (nServerPort
== INTERNET_INVALID_PORT_NUMBER
)
1627 nServerPort
= INTERNET_DEFAULT_FTP_PORT
;
1629 lpwfs
->hdr
.htype
= WH_HFTPSESSION
;
1630 lpwfs
->hdr
.lpwhparent
= &hIC
->hdr
;
1631 lpwfs
->hdr
.dwFlags
= dwFlags
;
1632 lpwfs
->hdr
.dwContext
= dwContext
;
1633 lpwfs
->hdr
.dwInternalFlags
= dwInternalFlags
;
1634 lpwfs
->download_in_progress
= NULL
;
1635 if(hIC
->lpszProxy
&& hIC
->dwAccessType
== INTERNET_OPEN_TYPE_PROXY
) {
1636 if(strchrW(hIC
->lpszProxy
, ' '))
1637 FIXME("Several proxies not implemented.\n");
1638 if(hIC
->lpszProxyBypass
)
1639 FIXME("Proxy bypass is ignored.\n");
1641 if ( !lpszUserName
) {
1642 lpwfs
->lpszUserName
= WININET_strdupW(szDefaultUsername
);
1643 lpwfs
->lpszPassword
= WININET_strdupW(szDefaultPassword
);
1646 lpwfs
->lpszUserName
= WININET_strdupW(lpszUserName
);
1647 lpwfs
->lpszPassword
= WININET_strdupW(lpszPassword
);
1650 /* Don't send a handle created callback if this handle was created with InternetOpenUrl */
1651 if (hIC
->lpfnStatusCB
&& !(lpwfs
->hdr
.dwInternalFlags
& INET_OPENURL
))
1653 INTERNET_ASYNC_RESULT iar
;
1655 iar
.dwResult
= (DWORD
)handle
;
1656 iar
.dwError
= ERROR_SUCCESS
;
1658 SendAsyncCallback(hIC
, hInternet
, dwContext
,
1659 INTERNET_STATUS_HANDLE_CREATED
, &iar
,
1660 sizeof(INTERNET_ASYNC_RESULT
));
1663 SendAsyncCallback(hIC
, hInternet
, dwContext
, INTERNET_STATUS_RESOLVING_NAME
,
1664 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1666 if (!GetAddress(lpszServerName
, nServerPort
, &phe
, &socketAddr
))
1668 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED
);
1672 SendAsyncCallback(hIC
, hInternet
, dwContext
, INTERNET_STATUS_NAME_RESOLVED
,
1673 (LPWSTR
) lpszServerName
, strlenW(lpszServerName
));
1675 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
1678 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1682 SendAsyncCallback(hIC
, hInternet
, dwContext
, INTERNET_STATUS_CONNECTING_TO_SERVER
,
1683 &socketAddr
, sizeof(struct sockaddr_in
));
1685 if (connect(nsocket
, (struct sockaddr
*)&socketAddr
, sizeof(socketAddr
)) < 0)
1687 ERR("Unable to connect (%s)\n", strerror(errno
));
1688 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT
);
1692 TRACE("Connected to server\n");
1693 lpwfs
->sndSocket
= nsocket
;
1694 SendAsyncCallback(hIC
, hInternet
, dwContext
, INTERNET_STATUS_CONNECTED_TO_SERVER
,
1695 &socketAddr
, sizeof(struct sockaddr_in
));
1697 sock_namelen
= sizeof(lpwfs
->socketAddress
);
1698 getsockname(nsocket
, (struct sockaddr
*) &lpwfs
->socketAddress
, &sock_namelen
);
1699 lpwfs
->phostent
= phe
;
1701 if (FTP_ConnectToHost(lpwfs
))
1703 TRACE("Successfully logged into server\n");
1709 if (!bSuccess
&& nsocket
== -1)
1712 if (!bSuccess
&& lpwfs
)
1714 HeapFree(GetProcessHeap(), 0, lpwfs
);
1715 WININET_FreeHandle( handle
);
1719 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
1721 INTERNET_ASYNC_RESULT iar
;
1723 iar
.dwResult
= (DWORD
)lpwfs
;
1724 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
1725 SendAsyncCallback(hIC
, hInternet
, dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
1726 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
1733 /***********************************************************************
1734 * FTP_ConnectToHost (internal)
1736 * Connect to a ftp server
1743 BOOL
FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs
)
1746 BOOL bSuccess
= FALSE
;
1749 FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1751 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_USER
, lpwfs
->lpszUserName
, 0, 0, 0))
1754 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1757 /* Login successful... */
1758 if (nResCode
== 230)
1760 /* User name okay, need password... */
1761 else if (nResCode
== 331)
1762 bSuccess
= FTP_SendPassword(lpwfs
);
1763 /* Need account for login... */
1764 else if (nResCode
== 332)
1765 bSuccess
= FTP_SendAccount(lpwfs
);
1767 FTP_SetResponseError(nResCode
);
1770 TRACE("Returning %d\n", bSuccess
);
1776 /***********************************************************************
1777 * FTP_SendCommandA (internal)
1779 * Send command to server
1786 BOOL
FTP_SendCommandA(INT nSocket
, FTP_COMMAND ftpCmd
, LPCSTR lpszParam
,
1787 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1791 DWORD nBytesSent
= 0;
1795 TRACE("%d: (%s) %d\n", ftpCmd
, lpszParam
, nSocket
);
1798 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_SENDING_REQUEST
, NULL
, 0);
1800 dwParamLen
= lpszParam
?strlen(lpszParam
)+1:0;
1801 len
= dwParamLen
+ strlen(szFtpCommands
[ftpCmd
]) + strlen(szCRLF
);
1802 if (NULL
== (buf
= HeapAlloc(GetProcessHeap(), 0, len
+1)))
1804 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
1807 sprintf(buf
, "%s%s%s%s", szFtpCommands
[ftpCmd
], dwParamLen
? " " : "",
1808 dwParamLen
? lpszParam
: "", szCRLF
);
1810 TRACE("Sending (%s) len(%ld)\n", buf
, len
);
1811 while((nBytesSent
< len
) && (nRC
!= -1))
1813 nRC
= send(nSocket
, buf
+nBytesSent
, len
- nBytesSent
, 0);
1817 HeapFree(GetProcessHeap(), 0, (LPVOID
)buf
);
1820 lpfnStatusCB(hHandle
, dwContext
, INTERNET_STATUS_REQUEST_SENT
,
1821 &nBytesSent
, sizeof(DWORD
));
1823 TRACE("Sent %ld bytes\n", nBytesSent
);
1827 /***********************************************************************
1828 * FTP_SendCommand (internal)
1830 * Send command to server
1837 BOOL
FTP_SendCommand(INT nSocket
, FTP_COMMAND ftpCmd
, LPCWSTR lpszParam
,
1838 INTERNET_STATUS_CALLBACK lpfnStatusCB
, HINTERNET hHandle
, DWORD dwContext
)
1841 LPSTR lpszParamA
= lpszParam
?WININET_strdup_WtoA(lpszParam
):NULL
;
1842 ret
= FTP_SendCommandA(nSocket
, ftpCmd
, lpszParamA
, lpfnStatusCB
, hHandle
, dwContext
);
1843 HeapFree(GetProcessHeap(), 0, lpszParamA
);
1847 /***********************************************************************
1848 * FTP_ReceiveResponse (internal)
1850 * Receive response from server
1853 * Reply code on success
1857 INT
FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs
, DWORD dwContext
)
1859 LPSTR lpszResponse
= INTERNET_GetResponseBuffer();
1862 char firstprefix
[5];
1863 BOOL multiline
= FALSE
;
1864 LPWININETAPPINFOW hIC
= NULL
;
1867 TRACE("socket(%d) \n", lpwfs
->sndSocket
);
1869 hHandle
= WININET_FindHandle(&lpwfs
->hdr
);
1870 hIC
= (LPWININETAPPINFOW
) lpwfs
->hdr
.lpwhparent
;
1871 SendAsyncCallback(hIC
, hHandle
, dwContext
, INTERNET_STATUS_RECEIVING_RESPONSE
, NULL
, 0);
1875 if (!INTERNET_GetNextLine(lpwfs
->sndSocket
, &nRecv
))
1882 if(lpszResponse
[3] != '-')
1885 { /* Start of multiline repsonse. Loop until we get "nnn " */
1887 memcpy(firstprefix
, lpszResponse
, 3);
1888 firstprefix
[3] = ' ';
1889 firstprefix
[4] = '\0';
1894 if(!memcmp(firstprefix
, lpszResponse
, 4))
1902 rc
= atoi(lpszResponse
);
1904 SendAsyncCallback(hIC
, hHandle
, dwContext
, INTERNET_STATUS_RESPONSE_RECEIVED
,
1905 &nRecv
, sizeof(DWORD
));
1909 TRACE("return %d\n", rc
);
1914 /***********************************************************************
1915 * FTP_SendPassword (internal)
1917 * Send password to ftp server
1924 BOOL
FTP_SendPassword(LPWININETFTPSESSIONW lpwfs
)
1927 BOOL bSuccess
= FALSE
;
1930 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASS
, lpwfs
->lpszPassword
, 0, 0, 0))
1933 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1936 TRACE("Received reply code %d\n", nResCode
);
1937 /* Login successful... */
1938 if (nResCode
== 230)
1940 /* Command not implemented, superfluous at the server site... */
1941 /* Need account for login... */
1942 else if (nResCode
== 332)
1943 bSuccess
= FTP_SendAccount(lpwfs
);
1945 FTP_SetResponseError(nResCode
);
1949 TRACE("Returning %d\n", bSuccess
);
1954 /***********************************************************************
1955 * FTP_SendAccount (internal)
1964 BOOL
FTP_SendAccount(LPWININETFTPSESSIONW lpwfs
)
1967 BOOL bSuccess
= FALSE
;
1970 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_ACCT
, szNoAccount
, 0, 0, 0))
1973 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
1977 FTP_SetResponseError(nResCode
);
1984 /***********************************************************************
1985 * FTP_SendStore (internal)
1987 * Send request to upload file to ftp server
1994 BOOL
FTP_SendStore(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
1997 BOOL bSuccess
= FALSE
;
2000 if (!FTP_InitListenSocket(lpwfs
))
2003 if (!FTP_SendType(lpwfs
, dwType
))
2006 if (!FTP_SendPortOrPasv(lpwfs
))
2009 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_STOR
, lpszRemoteFile
, 0, 0, 0))
2011 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2014 if (nResCode
== 150)
2017 FTP_SetResponseError(nResCode
);
2021 if (!bSuccess
&& lpwfs
->lstnSocket
!= -1)
2023 close(lpwfs
->lstnSocket
);
2024 lpwfs
->lstnSocket
= -1;
2031 /***********************************************************************
2032 * FTP_InitListenSocket (internal)
2034 * Create a socket to listen for server response
2041 BOOL
FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs
)
2043 BOOL bSuccess
= FALSE
;
2044 size_t namelen
= sizeof(struct sockaddr_in
);
2048 lpwfs
->lstnSocket
= socket(PF_INET
, SOCK_STREAM
, 0);
2049 if (lpwfs
->lstnSocket
== -1)
2051 TRACE("Unable to create listening socket\n");
2055 /* We obtain our ip addr from the name of the command channel socket */
2056 lpwfs
->lstnSocketAddress
= lpwfs
->socketAddress
;
2058 /* and get the system to assign us a port */
2059 lpwfs
->lstnSocketAddress
.sin_port
= htons((u_short
) 0);
2061 if (bind(lpwfs
->lstnSocket
,(struct sockaddr
*) &lpwfs
->lstnSocketAddress
, sizeof(struct sockaddr_in
)) == -1)
2063 TRACE("Unable to bind socket\n");
2067 if (listen(lpwfs
->lstnSocket
, MAX_BACKLOG
) == -1)
2069 TRACE("listen failed\n");
2073 if (getsockname(lpwfs
->lstnSocket
, (struct sockaddr
*) &lpwfs
->lstnSocketAddress
, &namelen
) != -1)
2077 if (!bSuccess
&& lpwfs
->lstnSocket
== -1)
2079 close(lpwfs
->lstnSocket
);
2080 lpwfs
->lstnSocket
= -1;
2087 /***********************************************************************
2088 * FTP_SendType (internal)
2090 * Tell server type of data being transferred
2096 * W98SE doesn't cache the type that's currently set
2097 * (i.e. it sends it always),
2098 * so we probably don't want to do that either.
2100 BOOL
FTP_SendType(LPWININETFTPSESSIONW lpwfs
, DWORD dwType
)
2103 WCHAR type
[] = { 'I','\0' };
2104 BOOL bSuccess
= FALSE
;
2107 if (dwType
& INTERNET_FLAG_TRANSFER_ASCII
)
2110 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_TYPE
, type
, 0, 0, 0))
2113 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
)/100;
2119 FTP_SetResponseError(nResCode
);
2126 /***********************************************************************
2127 * FTP_GetFileSize (internal)
2129 * Retrieves from the server the size of the given file
2136 BOOL
FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD
*dwSize
)
2139 BOOL bSuccess
= FALSE
;
2143 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_SIZE
, lpszRemoteFile
, 0, 0, 0))
2146 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2149 if (nResCode
== 213) {
2150 /* Now parses the output to get the actual file size */
2152 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2154 for (i
= 0; (lpszResponseBuffer
[i
] != ' ') && (lpszResponseBuffer
[i
] != '\0'); i
++) ;
2155 if (lpszResponseBuffer
[i
] == '\0') return FALSE
;
2156 *dwSize
= atol(&(lpszResponseBuffer
[i
+ 1]));
2160 FTP_SetResponseError(nResCode
);
2169 /***********************************************************************
2170 * FTP_SendPort (internal)
2172 * Tell server which port to use
2179 BOOL
FTP_SendPort(LPWININETFTPSESSIONW lpwfs
)
2181 static const WCHAR szIPFormat
[] = {'%','d',',','%','d',',','%','d',',','%','d',',','%','d',',','%','d','\0'};
2183 WCHAR szIPAddress
[64];
2184 BOOL bSuccess
= FALSE
;
2187 sprintfW(szIPAddress
, szIPFormat
,
2188 lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x000000FF,
2189 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x0000FF00)>>8,
2190 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0x00FF0000)>>16,
2191 (lpwfs
->lstnSocketAddress
.sin_addr
.s_addr
&0xFF000000)>>24,
2192 lpwfs
->lstnSocketAddress
.sin_port
& 0xFF,
2193 (lpwfs
->lstnSocketAddress
.sin_port
& 0xFF00)>>8);
2195 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PORT
, szIPAddress
, 0, 0, 0))
2198 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2201 if (nResCode
== 200)
2204 FTP_SetResponseError(nResCode
);
2212 /***********************************************************************
2213 * FTP_DoPassive (internal)
2215 * Tell server that we want to do passive transfers
2216 * and connect data socket
2223 BOOL
FTP_DoPassive(LPWININETFTPSESSIONW lpwfs
)
2226 BOOL bSuccess
= FALSE
;
2229 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_PASV
, NULL
, 0, 0, 0))
2232 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2235 if (nResCode
== 227)
2237 LPSTR lpszResponseBuffer
= INTERNET_GetResponseBuffer();
2241 char *pAddr
, *pPort
;
2243 struct sockaddr_in dataSocketAddress
;
2245 p
= lpszResponseBuffer
+4; /* skip status code */
2247 /* do a very strict check; we can improve that later. */
2249 if (strncmp(p
, "Entering Passive Mode", 21))
2251 ERR("unknown response '%.*s', aborting\n", 21, p
);
2254 p
+= 21; /* skip string */
2255 if ((*p
++ != ' ') || (*p
++ != '('))
2257 ERR("unknown response format, aborting\n");
2261 if (sscanf(p
, "%d,%d,%d,%d,%d,%d", &f
[0], &f
[1], &f
[2], &f
[3],
2264 ERR("unknown response address format '%s', aborting\n", p
);
2267 for (i
=0; i
< 6; i
++)
2270 dataSocketAddress
= lpwfs
->socketAddress
;
2271 pAddr
= (char *)&(dataSocketAddress
.sin_addr
.s_addr
);
2272 pPort
= (char *)&(dataSocketAddress
.sin_port
);
2280 nsocket
= socket(AF_INET
,SOCK_STREAM
,0);
2284 if (connect(nsocket
, (struct sockaddr
*)&dataSocketAddress
, sizeof(dataSocketAddress
)))
2286 ERR("can't connect passive FTP data port.\n");
2289 lpwfs
->pasvSocket
= nsocket
;
2293 FTP_SetResponseError(nResCode
);
2301 BOOL
FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs
)
2303 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2305 if (!FTP_DoPassive(lpwfs
))
2310 if (!FTP_SendPort(lpwfs
))
2317 /***********************************************************************
2318 * FTP_GetDataSocket (internal)
2320 * Either accepts an incoming data socket connection from the server
2321 * or just returns the already opened socket after a PASV command
2322 * in case of passive FTP.
2330 BOOL
FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs
, LPINT nDataSocket
)
2332 struct sockaddr_in saddr
;
2333 size_t addrlen
= sizeof(struct sockaddr
);
2336 if (lpwfs
->hdr
.dwFlags
& INTERNET_FLAG_PASSIVE
)
2338 *nDataSocket
= lpwfs
->pasvSocket
;
2342 *nDataSocket
= accept(lpwfs
->lstnSocket
, (struct sockaddr
*) &saddr
, &addrlen
);
2343 close(lpwfs
->lstnSocket
);
2344 lpwfs
->lstnSocket
= -1;
2346 return *nDataSocket
!= -1;
2350 /***********************************************************************
2351 * FTP_SendData (internal)
2353 * Send data to the server
2360 BOOL
FTP_SendData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, HANDLE hFile
)
2362 BY_HANDLE_FILE_INFORMATION fi
;
2363 DWORD nBytesRead
= 0;
2364 DWORD nBytesSent
= 0;
2365 DWORD nTotalSent
= 0;
2366 DWORD nBytesToSend
, nLen
, nRC
= 1;
2367 time_t s_long_time
, e_long_time
;
2372 lpszBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2373 memset(lpszBuffer
, 0, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2375 /* Get the size of the file. */
2376 GetFileInformationByHandle(hFile
, &fi
);
2381 nBytesToSend
= nBytesRead
- nBytesSent
;
2383 if (nBytesToSend
<= 0)
2385 /* Read data from file. */
2387 if (!ReadFile(hFile
, lpszBuffer
, DATA_PACKET_SIZE
, &nBytesRead
, 0))
2388 ERR("Failed reading from file\n");
2391 nBytesToSend
= nBytesRead
;
2396 nLen
= DATA_PACKET_SIZE
< nBytesToSend
?
2397 DATA_PACKET_SIZE
: nBytesToSend
;
2398 nRC
= send(nDataSocket
, lpszBuffer
, nLen
, 0);
2406 /* Do some computation to display the status. */
2408 nSeconds
= e_long_time
- s_long_time
;
2409 if( nSeconds
/ 60 > 0 )
2411 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
2412 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
/ 60,
2413 nSeconds
% 60, (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2417 TRACE( "%ld bytes of %ld bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
2418 nTotalSent
, fi
.nFileSizeLow
, nTotalSent
*100/fi
.nFileSizeLow
, nSeconds
,
2419 (fi
.nFileSizeLow
- nTotalSent
) * nSeconds
/ nTotalSent
);
2421 } while (nRC
!= -1);
2423 TRACE("file transfer complete!\n");
2425 if(lpszBuffer
!= NULL
)
2426 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2432 /***********************************************************************
2433 * FTP_SendRetrieve (internal)
2435 * Send request to retrieve a file
2438 * Number of bytes to be received on success
2442 DWORD
FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs
, LPCWSTR lpszRemoteFile
, DWORD dwType
)
2448 if (!FTP_InitListenSocket(lpwfs
))
2451 if (!FTP_SendType(lpwfs
, dwType
))
2454 if (!FTP_SendPortOrPasv(lpwfs
))
2457 if (!FTP_GetFileSize(lpwfs
, lpszRemoteFile
, &nResult
))
2460 TRACE("Waiting to receive %ld bytes\n", nResult
);
2462 if (!FTP_SendCommand(lpwfs
->sndSocket
, FTP_CMD_RETR
, lpszRemoteFile
, 0, 0, 0))
2465 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2466 if ((nResCode
!= 125) && (nResCode
!= 150)) {
2467 /* That means that we got an error getting the file. */
2472 if (0 == nResult
&& lpwfs
->lstnSocket
!= -1)
2474 close(lpwfs
->lstnSocket
);
2475 lpwfs
->lstnSocket
= -1;
2482 /***********************************************************************
2483 * FTP_RetrieveData (internal)
2485 * Retrieve data from server
2492 BOOL
FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs
, INT nDataSocket
, DWORD nBytes
, HANDLE hFile
)
2494 DWORD nBytesWritten
;
2495 DWORD nBytesReceived
= 0;
2501 if (INVALID_HANDLE_VALUE
== hFile
)
2504 lpszBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CHAR
)*DATA_PACKET_SIZE
);
2505 if (NULL
== lpszBuffer
)
2507 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
2511 while (nBytesReceived
< nBytes
&& nRC
!= -1)
2513 nRC
= recv(nDataSocket
, lpszBuffer
, DATA_PACKET_SIZE
, 0);
2516 /* other side closed socket. */
2519 WriteFile(hFile
, lpszBuffer
, nRC
, &nBytesWritten
, NULL
);
2520 nBytesReceived
+= nRC
;
2523 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived
, nBytes
,
2524 nBytesReceived
* 100 / nBytes
);
2527 TRACE("Data transfer complete\n");
2528 if (NULL
!= lpszBuffer
)
2529 HeapFree(GetProcessHeap(), 0, lpszBuffer
);
2536 /***********************************************************************
2537 * FTP_CloseSessionHandle (internal)
2539 * Deallocate session handle
2546 BOOL
FTP_CloseSessionHandle(LPWININETFTPSESSIONW lpwfs
)
2550 if (lpwfs
->download_in_progress
!= NULL
)
2551 lpwfs
->download_in_progress
->session_deleted
= TRUE
;
2553 if (lpwfs
->sndSocket
!= -1)
2554 close(lpwfs
->sndSocket
);
2556 if (lpwfs
->lstnSocket
!= -1)
2557 close(lpwfs
->lstnSocket
);
2559 if (lpwfs
->lpszPassword
)
2560 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszPassword
);
2562 if (lpwfs
->lpszUserName
)
2563 HeapFree(GetProcessHeap(), 0, lpwfs
->lpszUserName
);
2565 HeapFree(GetProcessHeap(), 0, lpwfs
);
2571 /***********************************************************************
2572 * FTP_CloseFindNextHandle (internal)
2574 * Deallocate session handle
2581 BOOL
FTP_CloseFindNextHandle(LPWININETFINDNEXTW lpwfn
)
2587 for (i
= 0; i
< lpwfn
->size
; i
++)
2589 if (NULL
!= lpwfn
->lpafp
[i
].lpszName
)
2590 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
[i
].lpszName
);
2593 HeapFree(GetProcessHeap(), 0, lpwfn
->lpafp
);
2594 HeapFree(GetProcessHeap(), 0, lpwfn
);
2599 /***********************************************************************
2600 * FTP_CloseFileTransferHandle (internal)
2602 * Closes the file transfer handle. This also 'cleans' the data queue of
2603 * the 'transfer conplete' message (this is a bit of a hack though :-/ )
2610 BOOL
FTP_CloseFileTransferHandle(LPWININETFILE lpwh
)
2612 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) lpwh
->hdr
.lpwhparent
;
2618 if (!lpwh
->session_deleted
)
2619 lpwfs
->download_in_progress
= NULL
;
2621 /* This just serves to flush the control socket of any spurrious lines written
2622 to it (like '226 Transfer complete.').
2624 Wonder what to do if the server sends us an error code though...
2626 nResCode
= FTP_ReceiveResponse(lpwfs
, lpwfs
->hdr
.dwContext
);
2628 if (lpwh
->nDataSocket
!= -1)
2629 close(lpwh
->nDataSocket
);
2631 HeapFree(GetProcessHeap(), 0, lpwh
);
2633 /* If this handle was opened with InternetOpenUrl, we need to close the parent to prevent
2636 if(lpwfs
->hdr
.dwInternalFlags
& INET_OPENURL
)
2638 handle
= WININET_FindHandle( &lpwfs
->hdr
);
2639 InternetCloseHandle(handle
);
2644 /***********************************************************************
2645 * FTP_ReceiveFileList (internal)
2647 * Read file list from server
2650 * Handle to file list on success
2654 HINTERNET
FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2655 LPWIN32_FIND_DATAW lpFindFileData
, DWORD dwContext
)
2658 LPFILEPROPERTIESW lpafp
= NULL
;
2659 LPWININETFINDNEXTW lpwfn
= NULL
;
2660 HINTERNET handle
= 0;
2662 TRACE("(%p,%d,%s,%p,%ld)\n", lpwfs
, nSocket
, debugstr_w(lpszSearchFile
), lpFindFileData
, dwContext
);
2664 if (FTP_ParseDirectory(lpwfs
, nSocket
, lpszSearchFile
, &lpafp
, &dwSize
))
2667 FTP_ConvertFileProp(lpafp
, lpFindFileData
);
2669 lpwfn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WININETFINDNEXTW
));
2672 handle
= WININET_AllocHandle( &lpwfn
->hdr
);
2675 lpwfn
->hdr
.htype
= WH_HFINDNEXT
;
2676 lpwfn
->hdr
.lpwhparent
= (LPWININETHANDLEHEADER
)lpwfs
;
2677 lpwfn
->hdr
.dwContext
= dwContext
;
2678 lpwfn
->index
= 1; /* Next index is 1 since we return index 0 */
2679 lpwfn
->size
= dwSize
;
2680 lpwfn
->lpafp
= lpafp
;
2683 HeapFree( GetProcessHeap(), 0, lpwfn
);
2687 TRACE("Matched %ld files\n", dwSize
);
2692 /***********************************************************************
2693 * FTP_ConvertFileProp (internal)
2695 * Converts FILEPROPERTIESW struct to WIN32_FIND_DATAA
2702 BOOL
FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp
, LPWIN32_FIND_DATAW lpFindFileData
)
2704 BOOL bSuccess
= FALSE
;
2706 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAW
));
2710 /* Convert 'Unix' time to Windows time */
2711 RtlSecondsSince1970ToTime(mktime(&lpafp
->tmLastModified
),
2712 (LARGE_INTEGER
*) &(lpFindFileData
->ftLastAccessTime
));
2714 /* Not all fields are filled in */
2715 lpFindFileData
->nFileSizeHigh
= 0; /* We do not handle files bigger than 0xFFFFFFFF bytes yet :-) */
2716 lpFindFileData
->nFileSizeLow
= lpafp
->nSize
;
2718 if (lpafp
->bIsDirectory
)
2719 lpFindFileData
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
2721 if (lpafp
->lpszName
)
2722 strncpyW(lpFindFileData
->cFileName
, lpafp
->lpszName
, MAX_PATH
);
2730 /***********************************************************************
2731 * FTP_ParseNextFile (internal)
2733 * Parse the next line in file listing
2739 BOOL
FTP_ParseNextFile(INT nSocket
, LPCWSTR lpszSearchFile
, LPFILEPROPERTIESW lpfp
)
2741 static const char szSpace
[] = " \t";
2749 lpfp
->lpszName
= NULL
;
2751 if(!(pszLine
= INTERNET_GetNextLine(nSocket
, &nBufLen
)))
2754 pszToken
= strtok(pszLine
, szSpace
);
2756 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2759 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2761 if(!isdigit(pszToken
[0]) && 10 == strlen(pszToken
)) {
2762 if(!FTP_ParsePermission(pszToken
, lpfp
))
2763 lpfp
->bIsDirectory
= FALSE
;
2764 for(i
=0; i
<=3; i
++) {
2765 if(!(pszToken
= strtok(NULL
, szSpace
)))
2768 if(!pszToken
) continue;
2769 if(lpfp
->bIsDirectory
) {
2770 TRACE("Is directory\n");
2774 TRACE("Size: %s\n", pszToken
);
2775 lpfp
->nSize
= atol(pszToken
);
2778 lpfp
->tmLastModified
.tm_sec
= 0;
2779 lpfp
->tmLastModified
.tm_min
= 0;
2780 lpfp
->tmLastModified
.tm_hour
= 0;
2781 lpfp
->tmLastModified
.tm_mday
= 0;
2782 lpfp
->tmLastModified
.tm_mon
= 0;
2783 lpfp
->tmLastModified
.tm_year
= 0;
2785 /* Determine month */
2786 pszToken
= strtok(NULL
, szSpace
);
2787 if(!pszToken
) continue;
2788 if(strlen(pszToken
) >= 3) {
2790 if((pszTmp
= StrStrIA(szMonths
, pszToken
)))
2791 lpfp
->tmLastModified
.tm_mon
= ((pszTmp
- szMonths
) / 3)+1;
2794 pszToken
= strtok(NULL
, szSpace
);
2795 if(!pszToken
) continue;
2796 lpfp
->tmLastModified
.tm_mday
= atoi(pszToken
);
2797 /* Determine time or year */
2798 pszToken
= strtok(NULL
, szSpace
);
2799 if(!pszToken
) continue;
2800 if((pszTmp
= strchr(pszToken
, ':'))) {
2805 lpfp
->tmLastModified
.tm_min
= atoi(pszTmp
);
2806 lpfp
->tmLastModified
.tm_hour
= atoi(pszToken
);
2808 apTM
= localtime(&aTime
);
2809 lpfp
->tmLastModified
.tm_year
= apTM
->tm_year
;
2812 lpfp
->tmLastModified
.tm_year
= atoi(pszToken
) - 1900;
2813 lpfp
->tmLastModified
.tm_hour
= 12;
2815 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2816 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2817 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2818 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2820 pszToken
= strtok(NULL
, szSpace
);
2821 if(!pszToken
) continue;
2822 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2823 TRACE("File: %s\n", debugstr_w(lpfp
->lpszName
));
2825 /* NT way of parsing ... :
2827 07-13-03 08:55PM <DIR> sakpatch
2828 05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
2830 else if(isdigit(pszToken
[0]) && 8 == strlen(pszToken
)) {
2831 lpfp
->permissions
= 0xFFFF; /* No idea, put full permission :-) */
2833 sscanf(pszToken
, "%d-%d-%d",
2834 &lpfp
->tmLastModified
.tm_mon
,
2835 &lpfp
->tmLastModified
.tm_mday
,
2836 &lpfp
->tmLastModified
.tm_year
);
2838 /* Hacky and bad Y2K protection :-) */
2839 if (lpfp
->tmLastModified
.tm_year
< 70)
2840 lpfp
->tmLastModified
.tm_year
+= 100;
2842 pszToken
= strtok(NULL
, szSpace
);
2843 if(!pszToken
) continue;
2844 sscanf(pszToken
, "%d:%d",
2845 &lpfp
->tmLastModified
.tm_hour
,
2846 &lpfp
->tmLastModified
.tm_min
);
2847 if((pszToken
[5] == 'P') && (pszToken
[6] == 'M')) {
2848 lpfp
->tmLastModified
.tm_hour
+= 12;
2850 lpfp
->tmLastModified
.tm_sec
= 0;
2852 TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
2853 lpfp
->tmLastModified
.tm_hour
, lpfp
->tmLastModified
.tm_min
, lpfp
->tmLastModified
.tm_sec
,
2854 (lpfp
->tmLastModified
.tm_year
>= 100) ? lpfp
->tmLastModified
.tm_year
- 100 : lpfp
->tmLastModified
.tm_year
,
2855 lpfp
->tmLastModified
.tm_mon
, lpfp
->tmLastModified
.tm_mday
);
2857 pszToken
= strtok(NULL
, szSpace
);
2858 if(!pszToken
) continue;
2859 if(!strcasecmp(pszToken
, "<DIR>")) {
2860 lpfp
->bIsDirectory
= TRUE
;
2862 TRACE("Is directory\n");
2865 lpfp
->bIsDirectory
= FALSE
;
2866 lpfp
->nSize
= atol(pszToken
);
2867 TRACE("Size: %ld\n", lpfp
->nSize
);
2870 pszToken
= strtok(NULL
, szSpace
);
2871 if(!pszToken
) continue;
2872 lpfp
->lpszName
= WININET_strdup_AtoW(pszToken
);
2873 TRACE("Name: %s\n", debugstr_w(lpfp
->lpszName
));
2875 /* EPLF format - http://cr.yp.to/ftp/list/eplf.html */
2876 else if(pszToken
[0] == '+') {
2877 FIXME("EPLF Format not implemented\n");
2880 if(lpfp
->lpszName
) {
2881 if((lpszSearchFile
== NULL
) ||
2882 (PathMatchSpecW(lpfp
->lpszName
, lpszSearchFile
))) {
2884 TRACE("Matched: %s\n", debugstr_w(lpfp
->lpszName
));
2887 HeapFree(GetProcessHeap(), 0, lpfp
->lpszName
);
2888 lpfp
->lpszName
= NULL
;
2895 /***********************************************************************
2896 * FTP_ParseDirectory (internal)
2898 * Parse string of directory information
2904 BOOL
FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs
, INT nSocket
, LPCWSTR lpszSearchFile
,
2905 LPFILEPROPERTIESW
*lpafp
, LPDWORD dwfp
)
2907 BOOL bSuccess
= TRUE
;
2908 INT sizeFilePropArray
= 500;/*20; */
2909 INT indexFilePropArray
= -1;
2913 /* Allocate intial file properties array */
2914 *lpafp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FILEPROPERTIESW
)*(sizeFilePropArray
));
2919 if (indexFilePropArray
+1 >= sizeFilePropArray
)
2921 LPFILEPROPERTIESW tmpafp
;
2923 sizeFilePropArray
*= 2;
2924 tmpafp
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *lpafp
,
2925 sizeof(FILEPROPERTIESW
)*sizeFilePropArray
);
2934 indexFilePropArray
++;
2935 } while (FTP_ParseNextFile(nSocket
, lpszSearchFile
, &(*lpafp
)[indexFilePropArray
]));
2937 if (bSuccess
&& indexFilePropArray
)
2939 if (indexFilePropArray
< sizeFilePropArray
- 1)
2941 LPFILEPROPERTIESW tmpafp
;
2943 tmpafp
= HeapReAlloc(GetProcessHeap(), 0, *lpafp
,
2944 sizeof(FILEPROPERTIESW
)*indexFilePropArray
);
2948 *dwfp
= indexFilePropArray
;
2952 HeapFree(GetProcessHeap(), 0, *lpafp
);
2953 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
2961 /***********************************************************************
2962 * FTP_ParsePermission (internal)
2964 * Parse permission string of directory information
2971 BOOL
FTP_ParsePermission(LPCSTR lpszPermission
, LPFILEPROPERTIESW lpfp
)
2973 BOOL bSuccess
= TRUE
;
2974 unsigned short nPermission
= 0;
2979 if ((*lpszPermission
!= 'd') && (*lpszPermission
!= '-') && (*lpszPermission
!= 'l'))
2985 lpfp
->bIsDirectory
= (*lpszPermission
== 'd');
2991 nPermission
|= (*(lpszPermission
+1) == 'r' ? 1 : 0) << 8;
2994 nPermission
|= (*(lpszPermission
+2) == 'w' ? 1 : 0) << 7;
2997 nPermission
|= (*(lpszPermission
+3) == 'x' ? 1 : 0) << 6;
3000 nPermission
|= (*(lpszPermission
+4) == 'r' ? 1 : 0) << 5;
3003 nPermission
|= (*(lpszPermission
+5) == 'w' ? 1 : 0) << 4;
3006 nPermission
|= (*(lpszPermission
+6) == 'x' ? 1 : 0) << 3;
3009 nPermission
|= (*(lpszPermission
+7) == 'r' ? 1 : 0) << 2;
3012 nPermission
|= (*(lpszPermission
+8) == 'w' ? 1 : 0) << 1;
3015 nPermission
|= (*(lpszPermission
+9) == 'x' ? 1 : 0);
3019 }while (nPos
<= nLast
);
3021 lpfp
->permissions
= nPermission
;
3026 /***********************************************************************
3027 * FTP_SetResponseError (internal)
3029 * Set the appropriate error code for a given response from the server
3034 DWORD
FTP_SetResponseError(DWORD dwResponse
)
3040 case 421: /* Service not available - Server may be shutting down. */
3041 dwCode
= ERROR_INTERNET_TIMEOUT
;
3044 case 425: /* Cannot open data connection. */
3045 dwCode
= ERROR_INTERNET_CANNOT_CONNECT
;
3048 case 426: /* Connection closed, transer aborted. */
3049 dwCode
= ERROR_INTERNET_CONNECTION_ABORTED
;
3052 case 500: /* Syntax error. Command unrecognized. */
3053 case 501: /* Syntax error. Error in parameters or arguments. */
3054 dwCode
= ERROR_INTERNET_INCORRECT_FORMAT
;
3057 case 530: /* Not logged in. Login incorrect. */
3058 dwCode
= ERROR_INTERNET_LOGIN_FAILURE
;
3061 case 550: /* File action not taken. File not found or no access. */
3062 dwCode
= ERROR_INTERNET_ITEM_NOT_FOUND
;
3065 case 450: /* File action not taken. File may be busy. */
3066 case 451: /* Action aborted. Server error. */
3067 case 452: /* Action not taken. Insufficient storage space on server. */
3068 case 502: /* Command not implemented. */
3069 case 503: /* Bad sequence of command. */
3070 case 504: /* Command not implemented for that parameter. */
3071 case 532: /* Need account for storing files */
3072 case 551: /* Requested action aborted. Page type unknown */
3073 case 552: /* Action aborted. Exceeded storage allocation */
3074 case 553: /* Action not taken. File name not allowed. */
3077 dwCode
= ERROR_INTERNET_INTERNAL_ERROR
;
3081 INTERNET_SetLastError(dwCode
);