2 * WININET - Ftp implementation
4 * Copyright 1999 Corel Corporation
19 #include <sys/types.h>
20 #ifdef HAVE_SYS_SOCKET_H
21 # include <sys/socket.h>
25 #ifdef HAVE_NETINET_IN_SYSTM_H
26 # include <netinet/in_systm.h>
28 #ifdef HAVE_NETINET_IN_H
29 # include <netinet/in.h>
31 #ifdef HAVE_NETINET_IP_H
32 # include <netinet/ip.h>
43 #include "debugtools.h"
46 DEFAULT_DEBUG_CHANNEL(wininet);
48 #define NOACCOUNT "noaccount"
49 #define DATA_PACKET_SIZE 0x2000
54 /* FTP commands with arguments. */
69 /* FTP commands without arguments. */
77 static const CHAR *szFtpCommands[] = {
98 static const CHAR szMonths[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
100 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
101 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext);
102 BOOL FTP_SendStore(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType);
103 BOOL FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs, LPINT nDataSocket);
104 BOOL FTP_SendData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, HANDLE hFile);
105 INT FTP_ReceiveResponse(INT nSocket, LPSTR lpszResponse, DWORD dwResponse,
106 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext);
107 DWORD FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType);
108 BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile);
109 BOOL FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs);
110 BOOL FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs);
111 BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs);
112 BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs);
113 BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType);
114 BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs);
115 BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESA lpfp);
116 BOOL FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs, INT nSocket, LPFILEPROPERTIESA *lpafp, LPDWORD dwfp);
117 HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs, INT nSocket,
118 LPWIN32_FIND_DATAA lpFindFileData, DWORD dwContext);
119 DWORD FTP_SetResponseError(DWORD dwResponse);
121 inline static LPSTR FTP_strdup( LPCSTR str )
123 LPSTR ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
124 if (ret) strcpy( ret, str );
128 /***********************************************************************
129 * FtpPutFileA (WININET.43)
131 * Uploads a file to the FTP server
138 BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
139 LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext)
141 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
142 LPWININETAPPINFOA hIC = NULL;
144 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
146 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
150 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
151 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
153 WORKREQUEST workRequest;
155 workRequest.asyncall = FTPPUTFILEA;
156 workRequest.HFTPSESSION = (DWORD)hConnect;
157 workRequest.LPSZLOCALFILE = (DWORD)FTP_strdup(lpszLocalFile);
158 workRequest.LPSZNEWREMOTEFILE = (DWORD)FTP_strdup(lpszNewRemoteFile);
159 workRequest.DWFLAGS = dwFlags;
160 workRequest.DWCONTEXT = dwContext;
162 return INTERNET_AsyncCall(&workRequest);
166 return FTP_FtpPutFileA(hConnect, lpszLocalFile,
167 lpszNewRemoteFile, dwFlags, dwContext);
171 /***********************************************************************
172 * FTP_FtpPutFileA (Internal)
174 * Uploads a file to the FTP server
181 BOOL WINAPI FTP_FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
182 LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext)
184 HANDLE hFile = (HANDLE)NULL;
185 BOOL bSuccess = FALSE;
186 LPWININETAPPINFOA hIC = NULL;
187 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
190 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile, lpszNewRemoteFile);
191 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
193 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
197 /* Clear any error information */
198 INTERNET_SetLastError(0);
200 /* Open file to be uploaded */
201 if (INVALID_HANDLE_VALUE ==
202 (hFile = CreateFileA(lpszLocalFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)))
204 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND);
208 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
209 if (hIC->lpfnStatusCB)
210 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
212 if (FTP_SendStore(lpwfs, lpszNewRemoteFile, dwFlags))
216 /* Accept connection from ftp server */
217 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
219 FTP_SendData(lpwfs, nDataSocket, hFile);
221 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
222 MAX_REPLY_LEN,0, 0, 0);
228 FTP_SetResponseError(nResCode);
234 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
236 INTERNET_ASYNC_RESULT iar;
238 iar.dwResult = (DWORD)bSuccess;
239 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
240 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
241 &iar, sizeof(INTERNET_ASYNC_RESULT));
251 /***********************************************************************
252 * FtpSetCurrentDirectoryA (WININET.49)
254 * Change the working directory on the FTP server
261 BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
263 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
264 LPWININETAPPINFOA hIC = NULL;
266 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
268 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
272 TRACE("lpszDirectory(%s)\n", lpszDirectory);
274 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
275 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
277 WORKREQUEST workRequest;
279 workRequest.asyncall = FTPSETCURRENTDIRECTORYA;
280 workRequest.HFTPSESSION = (DWORD)hConnect;
281 workRequest.LPSZDIRECTORY = (DWORD)FTP_strdup(lpszDirectory);
283 return INTERNET_AsyncCall(&workRequest);
287 return FTP_FtpSetCurrentDirectoryA(hConnect, lpszDirectory);
292 /***********************************************************************
293 * FTP_FtpSetCurrentDirectoryA (Internal)
295 * Change the working directory on the FTP server
302 BOOL WINAPI FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
305 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
306 LPWININETAPPINFOA hIC = NULL;
307 DWORD bSuccess = FALSE;
309 TRACE("lpszDirectory(%s)\n", lpszDirectory);
311 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
313 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
317 /* Clear any error information */
318 INTERNET_SetLastError(0);
320 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
321 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_CWD, lpszDirectory,
322 hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
325 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
326 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
333 FTP_SetResponseError(nResCode);
337 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
339 INTERNET_ASYNC_RESULT iar;
341 iar.dwResult = (DWORD)bSuccess;
342 iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
343 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
344 &iar, sizeof(INTERNET_ASYNC_RESULT));
350 /***********************************************************************
351 * FtpCreateDirectoryA (WININET.31)
353 * Create new directory on the FTP server
360 BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
362 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
363 LPWININETAPPINFOA hIC = NULL;
365 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
367 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
371 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
372 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
374 WORKREQUEST workRequest;
376 workRequest.asyncall = FTPCREATEDIRECTORYA;
377 workRequest.HFTPSESSION = (DWORD)hConnect;
378 workRequest.LPSZDIRECTORY = (DWORD)FTP_strdup(lpszDirectory);
380 return INTERNET_AsyncCall(&workRequest);
384 return FTP_FtpCreateDirectoryA(hConnect, lpszDirectory);
389 /***********************************************************************
390 * FTP_FtpCreateDirectoryA (Internal)
392 * Create new directory on the FTP server
399 BOOL WINAPI FTP_FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
402 BOOL bSuccess = FALSE;
403 LPWININETAPPINFOA hIC = NULL;
404 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
407 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
409 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
413 /* Clear any error information */
414 INTERNET_SetLastError(0);
416 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_MKD, lpszDirectory, 0, 0, 0))
419 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
420 MAX_REPLY_LEN, 0, 0, 0);
426 FTP_SetResponseError(nResCode);
430 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
431 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
433 INTERNET_ASYNC_RESULT iar;
435 iar.dwResult = (DWORD)bSuccess;
436 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
437 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
438 &iar, sizeof(INTERNET_ASYNC_RESULT));
445 /***********************************************************************
446 * FtpFindFirstFileA (WININET.35)
448 * Search the specified directory
451 * HINTERNET on success
455 INTERNETAPI HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect,
456 LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD dwContext)
458 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
459 LPWININETAPPINFOA hIC = NULL;
461 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
463 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
467 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
468 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
470 WORKREQUEST workRequest;
472 workRequest.asyncall = FTPFINDFIRSTFILEA;
473 workRequest.HFTPSESSION = (DWORD)hConnect;
474 workRequest.LPSZSEARCHFILE = (DWORD)FTP_strdup(lpszSearchFile);
475 workRequest.LPFINDFILEDATA = (DWORD)lpFindFileData;
476 workRequest.DWFLAGS = dwFlags;
477 workRequest.DWCONTEXT= dwContext;
479 INTERNET_AsyncCall(&workRequest);
484 return FTP_FtpFindFirstFileA(hConnect, lpszSearchFile, lpFindFileData,
490 /***********************************************************************
491 * FTP_FtpFindFirstFileA (Internal)
493 * Search the specified directory
496 * HINTERNET on success
500 INTERNETAPI HINTERNET WINAPI FTP_FtpFindFirstFileA(HINTERNET hConnect,
501 LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD dwContext)
504 LPWININETAPPINFOA hIC = NULL;
505 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
506 LPWININETFINDNEXTA hFindNext = NULL;
510 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
512 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
516 /* Clear any error information */
517 INTERNET_SetLastError(0);
519 if (!FTP_InitListenSocket(lpwfs))
522 if (!FTP_SendType(lpwfs, INTERNET_FLAG_TRANSFER_ASCII))
525 if (!FTP_SendPort(lpwfs))
528 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
529 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_LIST, lpszSearchFile,
530 hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
533 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
534 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
537 if (nResCode == 125 || nResCode == 150)
541 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
543 hFindNext = FTP_ReceiveFileList(lpwfs, nDataSocket, lpFindFileData, dwContext);
545 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
546 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
547 if (nResCode != 226 && nResCode != 250)
548 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
554 FTP_SetResponseError(nResCode);
558 if (lpwfs->lstnSocket != INVALID_SOCKET)
559 close(lpwfs->lstnSocket);
561 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
563 INTERNET_ASYNC_RESULT iar;
567 iar.dwResult = (DWORD)hFindNext;
568 iar.dwError = ERROR_SUCCESS;
569 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
570 &iar, sizeof(INTERNET_ASYNC_RESULT));
573 iar.dwResult = (DWORD)hFindNext;
574 iar.dwError = hFindNext ? ERROR_SUCCESS : INTERNET_GetLastError();
575 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
576 &iar, sizeof(INTERNET_ASYNC_RESULT));
579 return (HINTERNET)hFindNext;
583 /***********************************************************************
584 * FtpGetCurrentDirectoryA (WININET.37)
586 * Retrieves the current directory
593 BOOL WINAPI FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory,
594 LPDWORD lpdwCurrentDirectory)
596 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
597 LPWININETAPPINFOA hIC = NULL;
599 TRACE("len(%ld)\n", *lpdwCurrentDirectory);
601 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
603 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
607 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
608 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
610 WORKREQUEST workRequest;
612 workRequest.asyncall = FTPGETCURRENTDIRECTORYA;
613 workRequest.HFTPSESSION = (DWORD)hFtpSession;
614 workRequest.LPSZDIRECTORY = (DWORD)lpszCurrentDirectory;
615 workRequest.LPDWDIRECTORY = (DWORD)lpdwCurrentDirectory;
617 return INTERNET_AsyncCall(&workRequest);
621 return FTP_FtpGetCurrentDirectoryA(hFtpSession, lpszCurrentDirectory,
622 lpdwCurrentDirectory);
627 /***********************************************************************
628 * FTP_FtpGetCurrentDirectoryA (Internal)
630 * Retrieves the current directory
637 BOOL WINAPI FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory,
638 LPDWORD lpdwCurrentDirectory)
641 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
642 LPWININETAPPINFOA hIC = NULL;
643 DWORD bSuccess = FALSE;
645 TRACE("len(%ld)\n", *lpdwCurrentDirectory);
647 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
649 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
653 /* Clear any error information */
654 INTERNET_SetLastError(0);
656 ZeroMemory(lpszCurrentDirectory, *lpdwCurrentDirectory);
658 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
659 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PWD, NULL,
660 hIC->lpfnStatusCB, hFtpSession, lpwfs->hdr.dwContext))
663 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
664 MAX_REPLY_LEN, hIC->lpfnStatusCB, hFtpSession, lpwfs->hdr.dwContext);
667 if (nResCode == 257) /* Extract directory name */
669 INT firstpos, lastpos, len;
670 LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
672 for (firstpos = 0, lastpos = 0; lpszResponseBuffer[lastpos]; lastpos++)
674 if ('"' == lpszResponseBuffer[lastpos])
683 len = lastpos - firstpos - 1;
684 strncpy(lpszCurrentDirectory, &lpszResponseBuffer[firstpos+1],
685 len < *lpdwCurrentDirectory ? len : *lpdwCurrentDirectory);
686 *lpdwCurrentDirectory = len;
690 FTP_SetResponseError(nResCode);
694 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
696 INTERNET_ASYNC_RESULT iar;
698 iar.dwResult = (DWORD)bSuccess;
699 iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
700 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
701 &iar, sizeof(INTERNET_ASYNC_RESULT));
704 return (DWORD) bSuccess;
707 /***********************************************************************
708 * FtpOpenFileA (WININET.41)
710 * Open a remote file for writing or reading
713 * HINTERNET handle on success
717 INTERNETAPI HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
718 LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
721 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
722 LPWININETAPPINFOA hIC = NULL;
724 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
726 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
730 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
731 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
733 WORKREQUEST workRequest;
735 workRequest.asyncall = FTPOPENFILEA;
736 workRequest.HFTPSESSION = (DWORD)hFtpSession;
737 workRequest.LPSZFILENAME = (DWORD)FTP_strdup(lpszFileName);
738 workRequest.FDWACCESS = fdwAccess;
739 workRequest.DWFLAGS = dwFlags;
740 workRequest.DWCONTEXT = dwContext;
742 INTERNET_AsyncCall(&workRequest);
747 return FTP_FtpOpenFileA(hFtpSession, lpszFileName, fdwAccess, dwFlags, dwContext);
752 /***********************************************************************
753 * FTP_FtpOpenFileA (Internal)
755 * Open a remote file for writing or reading
758 * HINTERNET handle on success
762 HINTERNET FTP_FtpOpenFileA(HINTERNET hFtpSession,
763 LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
767 BOOL bSuccess = FALSE;
768 LPWININETFILE hFile = NULL;
769 LPWININETAPPINFOA hIC = NULL;
770 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
774 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
776 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
780 /* Clear any error information */
781 INTERNET_SetLastError(0);
783 if (GENERIC_READ == fdwAccess)
785 /* Set up socket to retrieve data */
786 bSuccess = FTP_SendRetrieve(lpwfs, lpszFileName, dwFlags);
788 else if (GENERIC_WRITE == fdwAccess)
790 /* Set up socket to send data */
791 bSuccess = FTP_SendStore(lpwfs, lpszFileName, dwFlags);
794 /* Accept connection from server */
795 if (bSuccess && FTP_InitDataSocket(lpwfs, &nDataSocket))
797 hFile = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE));
798 hFile->hdr.htype = WH_HFILE;
799 hFile->hdr.dwFlags = dwFlags;
800 hFile->hdr.dwContext = dwContext;
801 hFile->hdr.lpwhparent = hFtpSession;
802 hFile->nDataSocket = nDataSocket;
805 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
806 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
808 INTERNET_ASYNC_RESULT iar;
812 iar.dwResult = (DWORD)hFile;
813 iar.dwError = ERROR_SUCCESS;
814 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
815 &iar, sizeof(INTERNET_ASYNC_RESULT));
818 iar.dwResult = (DWORD)bSuccess;
819 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
820 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
821 &iar, sizeof(INTERNET_ASYNC_RESULT));
824 return (HINTERNET)hFile;
828 /***********************************************************************
829 * FtpGetFileA (WININET.39)
831 * Retrieve file from the FTP server
838 BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile,
839 BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
842 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hInternet;
843 LPWININETAPPINFOA hIC = NULL;
845 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
847 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
851 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
852 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
854 WORKREQUEST workRequest;
856 workRequest.asyncall = FTPGETFILEA;
857 workRequest.HFTPSESSION = (DWORD)hInternet;
858 workRequest.LPSZREMOTEFILE = (DWORD)FTP_strdup(lpszRemoteFile);
859 workRequest.LPSZNEWFILE = (DWORD)FTP_strdup(lpszNewFile);
860 workRequest.DWLOCALFLAGSATTRIBUTE = dwLocalFlagsAttribute;
861 workRequest.FFAILIFEXISTS = (DWORD)fFailIfExists;
862 workRequest.DWFLAGS = dwInternetFlags;
863 workRequest.DWCONTEXT = dwContext;
865 return INTERNET_AsyncCall(&workRequest);
869 return FTP_FtpGetFileA(hInternet, lpszRemoteFile, lpszNewFile,
870 fFailIfExists, dwLocalFlagsAttribute, dwInternetFlags, dwContext);
875 /***********************************************************************
876 * FTP_FtpGetFileA (Internal)
878 * Retrieve file from the FTP server
885 BOOL WINAPI FTP_FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile,
886 BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
890 BOOL bSuccess = FALSE;
892 LPWININETAPPINFOA hIC = NULL;
893 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hInternet;
895 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile, lpszNewFile);
896 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
898 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
902 /* Clear any error information */
903 INTERNET_SetLastError(0);
905 /* Ensure we can write to lpszNewfile by opening it */
906 hFile = CreateFileA(lpszNewFile, GENERIC_WRITE, 0, 0, fFailIfExists ?
907 CREATE_NEW : CREATE_ALWAYS, dwLocalFlagsAttribute, 0);
908 if (INVALID_HANDLE_VALUE == hFile)
911 /* Set up socket to retrieve data */
912 nBytes = FTP_SendRetrieve(lpwfs, lpszRemoteFile, dwInternetFlags);
918 /* Accept connection from ftp server */
919 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
924 FTP_RetrieveFileData(lpwfs, nDataSocket, nBytes, hFile);
925 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
926 MAX_REPLY_LEN, 0, 0, 0);
932 FTP_SetResponseError(nResCode);
942 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
943 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
945 INTERNET_ASYNC_RESULT iar;
947 iar.dwResult = (DWORD)bSuccess;
948 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
949 hIC->lpfnStatusCB(hInternet, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
950 &iar, sizeof(INTERNET_ASYNC_RESULT));
957 /***********************************************************************
958 * FtpDeleteFileA (WININET.33)
960 * Delete a file on the ftp server
967 BOOL WINAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
969 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
970 LPWININETAPPINFOA hIC = NULL;
972 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
974 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
978 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
979 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
981 WORKREQUEST workRequest;
983 workRequest.asyncall = FTPRENAMEFILEA;
984 workRequest.HFTPSESSION = (DWORD)hFtpSession;
985 workRequest.LPSZFILENAME = (DWORD)FTP_strdup(lpszFileName);
987 return INTERNET_AsyncCall(&workRequest);
991 return FTP_FtpDeleteFileA(hFtpSession, lpszFileName);
996 /***********************************************************************
997 * FTP_FtpDeleteFileA (Internal)
999 * Delete a file on the ftp server
1006 BOOL FTP_FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
1009 BOOL bSuccess = FALSE;
1010 LPWININETAPPINFOA hIC = NULL;
1011 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1013 TRACE("0x%08lx\n", (ULONG) hFtpSession);
1014 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1016 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1020 /* Clear any error information */
1021 INTERNET_SetLastError(0);
1023 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_DELE, lpszFileName, 0, 0, 0))
1026 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1027 MAX_REPLY_LEN, 0, 0, 0);
1030 if (nResCode == 250)
1033 FTP_SetResponseError(nResCode);
1036 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1037 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1039 INTERNET_ASYNC_RESULT iar;
1041 iar.dwResult = (DWORD)bSuccess;
1042 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1043 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1044 &iar, sizeof(INTERNET_ASYNC_RESULT));
1051 /***********************************************************************
1052 * FtpRemoveDirectoryA (WININET.45)
1054 * Remove a directory on the ftp server
1061 BOOL WINAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
1063 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1064 LPWININETAPPINFOA hIC = NULL;
1066 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1068 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1072 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1073 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1075 WORKREQUEST workRequest;
1077 workRequest.asyncall = FTPREMOVEDIRECTORYA;
1078 workRequest.HFTPSESSION = (DWORD)hFtpSession;
1079 workRequest.LPSZDIRECTORY = (DWORD)FTP_strdup(lpszDirectory);
1081 return INTERNET_AsyncCall(&workRequest);
1085 return FTP_FtpRemoveDirectoryA(hFtpSession, lpszDirectory);
1090 /***********************************************************************
1091 * FTP_FtpRemoveDirectoryA (Internal)
1093 * Remove a directory on the ftp server
1100 BOOL FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
1103 BOOL bSuccess = FALSE;
1104 LPWININETAPPINFOA hIC = NULL;
1105 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1108 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1110 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1114 /* Clear any error information */
1115 INTERNET_SetLastError(0);
1117 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RMD, lpszDirectory, 0, 0, 0))
1120 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1121 MAX_REPLY_LEN, 0, 0, 0);
1124 if (nResCode == 250)
1127 FTP_SetResponseError(nResCode);
1131 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1132 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1134 INTERNET_ASYNC_RESULT iar;
1136 iar.dwResult = (DWORD)bSuccess;
1137 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1138 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1139 &iar, sizeof(INTERNET_ASYNC_RESULT));
1146 /***********************************************************************
1147 * FtpRenameFileA (WININET.47)
1149 * Rename a file on the ftp server
1156 BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDest)
1158 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1159 LPWININETAPPINFOA hIC = NULL;
1161 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1163 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1167 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1168 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1170 WORKREQUEST workRequest;
1172 workRequest.asyncall = FTPRENAMEFILEA;
1173 workRequest.HFTPSESSION = (DWORD)hFtpSession;
1174 workRequest.LPSZSRCFILE = (DWORD)FTP_strdup(lpszSrc);
1175 workRequest.LPSZDESTFILE = (DWORD)FTP_strdup(lpszDest);
1177 return INTERNET_AsyncCall(&workRequest);
1181 return FTP_FtpRenameFileA(hFtpSession, lpszSrc, lpszDest);
1185 /***********************************************************************
1186 * FTP_FtpRenameFileA (Internal)
1188 * Rename a file on the ftp server
1195 BOOL FTP_FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDest)
1198 BOOL bSuccess = FALSE;
1199 LPWININETAPPINFOA hIC = NULL;
1200 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1203 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1205 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1209 /* Clear any error information */
1210 INTERNET_SetLastError(0);
1212 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNFR, lpszSrc, 0, 0, 0))
1215 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket,
1216 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1217 if (nResCode == 350)
1219 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNTO, lpszDest, 0, 0, 0))
1222 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket,
1223 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1226 if (nResCode == 250)
1229 FTP_SetResponseError(nResCode);
1232 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1233 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1235 INTERNET_ASYNC_RESULT iar;
1237 iar.dwResult = (DWORD)bSuccess;
1238 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1239 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1240 &iar, sizeof(INTERNET_ASYNC_RESULT));
1247 /***********************************************************************
1248 * FTP_Connect (internal)
1250 * Connect to a ftp server
1253 * HINTERNET a session handle on success
1258 HINTERNET FTP_Connect(HINTERNET hInternet, LPCSTR lpszServerName,
1259 INTERNET_PORT nServerPort, LPCSTR lpszUserName,
1260 LPCSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
1262 struct sockaddr_in socketAddr;
1263 struct hostent *phe = NULL;
1264 INT nsocket = INVALID_SOCKET, sock_namelen;
1265 LPWININETAPPINFOA hIC = NULL;
1266 BOOL bSuccess = FALSE;
1267 LPWININETFTPSESSIONA lpwfs = NULL;
1269 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1270 (ULONG) hInternet, lpszServerName,
1271 nServerPort, lpszUserName, lpszPassword);
1273 if (((LPWININETHANDLEHEADER)hInternet)->htype != WH_HINIT)
1276 hIC = (LPWININETAPPINFOA) hInternet;
1278 if (NULL == lpszUserName && NULL != lpszPassword)
1280 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME);
1284 if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
1285 nServerPort = INTERNET_DEFAULT_FTP_PORT;
1287 if (hIC->lpfnStatusCB)
1288 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_RESOLVING_NAME,
1289 (LPSTR) lpszServerName, strlen(lpszServerName));
1291 if (!GetAddress(lpszServerName, nServerPort, &phe, &socketAddr))
1293 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
1297 if (hIC->lpfnStatusCB)
1298 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_NAME_RESOLVED,
1299 (LPSTR) lpszServerName, strlen(lpszServerName));
1301 if (INVALID_SOCKET == (nsocket = socket(AF_INET,SOCK_STREAM,0)))
1303 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
1307 if (hIC->lpfnStatusCB)
1308 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_CONNECTING_TO_SERVER,
1309 &socketAddr, sizeof(struct sockaddr_in));
1311 if (connect(nsocket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0)
1313 ERR("Unable to connect (%s)\n", strerror(errno));
1314 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
1318 TRACE("Connected to server\n");
1319 if (hIC->lpfnStatusCB)
1320 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_CONNECTED_TO_SERVER,
1321 &socketAddr, sizeof(struct sockaddr_in));
1323 lpwfs = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA));
1326 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1330 lpwfs->hdr.htype = WH_HFTPSESSION;
1331 lpwfs->hdr.dwFlags = dwFlags;
1332 lpwfs->hdr.dwContext = dwContext;
1333 lpwfs->hdr.lpwhparent = (LPWININETHANDLEHEADER)hInternet;
1334 lpwfs->sndSocket = nsocket;
1335 sock_namelen = sizeof(lpwfs->socketAddress);
1336 getsockname(nsocket, (struct sockaddr *) &lpwfs->socketAddress, &sock_namelen);
1337 lpwfs->phostent = phe;
1339 if (NULL == lpszUserName)
1341 lpwfs->lpszUserName = FTP_strdup("anonymous");
1342 lpwfs->lpszPassword = FTP_strdup("user@server");
1346 lpwfs->lpszUserName = FTP_strdup(lpszUserName);
1347 lpwfs->lpszPassword = FTP_strdup(lpszPassword);
1350 if (FTP_ConnectToHost(lpwfs))
1352 if (hIC->lpfnStatusCB)
1354 INTERNET_ASYNC_RESULT iar;
1356 iar.dwResult = (DWORD)lpwfs;
1357 iar.dwError = ERROR_SUCCESS;
1359 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_HANDLE_CREATED,
1360 &iar, sizeof(INTERNET_ASYNC_RESULT));
1362 TRACE("Successfully logged into server\n");
1368 if (!bSuccess && INVALID_SOCKET != nsocket)
1371 if (!bSuccess && lpwfs)
1373 HeapFree(GetProcessHeap(), 0, lpwfs);
1377 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1379 INTERNET_ASYNC_RESULT iar;
1381 iar.dwResult = (DWORD)lpwfs;
1382 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1383 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1384 &iar, sizeof(INTERNET_ASYNC_RESULT));
1387 return (HINTERNET) lpwfs;
1391 /***********************************************************************
1392 * FTP_ConnectHost (internal)
1394 * Connect to a ftp server
1401 BOOL FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs)
1404 BOOL bSuccess = FALSE;
1407 FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1409 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_USER, lpwfs->lpszUserName, 0, 0, 0))
1412 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1413 MAX_REPLY_LEN, 0, 0, 0);
1416 /* Login successful... */
1417 if (nResCode == 230)
1419 /* User name okay, need password... */
1420 else if (nResCode == 331)
1421 bSuccess = FTP_SendPassword(lpwfs);
1422 /* Need account for login... */
1423 else if (nResCode == 332)
1424 bSuccess = FTP_SendAccount(lpwfs);
1426 FTP_SetResponseError(nResCode);
1429 TRACE("Returning %d\n", bSuccess);
1435 /***********************************************************************
1436 * FTP_SendCommand (internal)
1438 * Send command to server
1445 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
1446 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
1450 DWORD nBytesSent = 0;
1454 TRACE("%d: (%s) %d\n", ftpCmd, lpszParam, nSocket);
1457 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
1459 bParamHasLen = lpszParam && strlen(lpszParam) > 0;
1460 len = (bParamHasLen ? strlen(lpszParam) : -1) + strlen(szFtpCommands[ftpCmd]) +
1462 if (NULL == (buf = HeapAlloc(GetProcessHeap(), 0, len+1)))
1464 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1467 sprintf(buf, "%s%s%s%s", szFtpCommands[ftpCmd], bParamHasLen ? " " : "",
1468 bParamHasLen ? lpszParam : "", szCRLF);
1470 TRACE("Sending (%s) len(%ld)\n", buf, len);
1471 while((nBytesSent < len) && (nRC != SOCKET_ERROR))
1473 nRC = send(nSocket, buf+nBytesSent, len - nBytesSent, 0);
1477 HeapFree(GetProcessHeap(), 0, (LPVOID)buf);
1480 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_REQUEST_SENT,
1481 &nBytesSent, sizeof(DWORD));
1483 TRACE("Sent %ld bytes\n", nBytesSent);
1484 return (nRC != SOCKET_ERROR);
1488 /***********************************************************************
1489 * FTP_ReceiveResponse (internal)
1491 * Receive response from server
1494 * Reply code on success
1499 INT FTP_ReceiveResponse(INT nSocket, LPSTR lpszResponse, DWORD dwResponse,
1500 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
1504 char firstprefix[5];
1505 BOOL multiline = FALSE;
1508 TRACE("socket(%d) \n", nSocket);
1511 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
1516 if (!INTERNET_GetNextLine(nSocket, lpszResponse, &nRecv))
1523 if(lpszResponse[3] != '-')
1526 { /* Start of multiline repsonse. Loop until we get "nnn " */
1528 memcpy(firstprefix, lpszResponse, 3);
1529 firstprefix[3] = ' ';
1530 firstprefix[4] = '\0';
1535 if(!memcmp(firstprefix, lpszResponse, 4))
1543 lpszResponse[nRecv] = '\0';
1544 rc = atoi(lpszResponse);
1547 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
1548 &nRecv, sizeof(DWORD));
1552 TRACE("return %d\n", rc);
1557 /***********************************************************************
1558 * FTP_SendPassword (internal)
1560 * Send password to ftp server
1567 BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs)
1570 BOOL bSuccess = FALSE;
1573 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASS, lpwfs->lpszPassword, 0, 0, 0))
1576 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1577 MAX_REPLY_LEN, 0, 0, 0);
1580 TRACE("Received reply code %d\n", nResCode);
1581 /* Login successful... */
1582 if (nResCode == 230)
1584 /* Command not implemented, superfluous at the server site... */
1585 /* Need account for login... */
1586 else if (nResCode == 332)
1587 bSuccess = FTP_SendAccount(lpwfs);
1589 FTP_SetResponseError(nResCode);
1593 TRACE("Returning %d\n", bSuccess);
1598 /***********************************************************************
1599 * FTP_SendAccount (internal)
1608 BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs)
1611 BOOL bSuccess = FALSE;
1614 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_ACCT, NOACCOUNT, 0, 0, 0))
1617 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1618 MAX_REPLY_LEN, 0, 0, 0);
1622 FTP_SetResponseError(nResCode);
1629 /***********************************************************************
1630 * FTP_SendStore (internal)
1632 * Send request to upload file to ftp server
1639 BOOL FTP_SendStore(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType)
1642 BOOL bSuccess = FALSE;
1645 if (!FTP_InitListenSocket(lpwfs))
1648 if (!FTP_SendType(lpwfs, dwType))
1651 if (!FTP_SendPort(lpwfs))
1654 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_STOR, lpszRemoteFile, 0, 0, 0))
1656 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1657 MAX_REPLY_LEN, 0, 0, 0);
1660 if (nResCode == 150)
1663 FTP_SetResponseError(nResCode);
1667 if (!bSuccess && INVALID_SOCKET != lpwfs->lstnSocket)
1669 close(lpwfs->lstnSocket);
1670 lpwfs->lstnSocket = INVALID_SOCKET;
1677 /***********************************************************************
1678 * FTP_InitListenSocket (internal)
1680 * Create a socket to listen for server response
1687 BOOL FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs)
1689 BOOL bSuccess = FALSE;
1690 size_t namelen = sizeof(struct sockaddr_in);
1694 lpwfs->lstnSocket = socket(PF_INET, SOCK_STREAM, 0);
1695 if (INVALID_SOCKET == lpwfs->lstnSocket)
1697 TRACE("Unable to create listening socket\n");
1701 /* We obtain our ip addr from the name of the command channel socket */
1702 lpwfs->lstnSocketAddress = lpwfs->socketAddress;
1704 /* and get the system to assign us a port */
1705 lpwfs->lstnSocketAddress.sin_port = htons((u_short) 0);
1707 if (SOCKET_ERROR == bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(struct sockaddr_in)))
1709 TRACE("Unable to bind socket\n");
1713 if (SOCKET_ERROR == listen(lpwfs->lstnSocket, MAX_BACKLOG))
1715 TRACE("listen failed\n");
1719 if (SOCKET_ERROR != getsockname(lpwfs->lstnSocket, (struct sockaddr *) &lpwfs->lstnSocketAddress, &namelen))
1723 if (!bSuccess && INVALID_SOCKET == lpwfs->lstnSocket)
1725 close(lpwfs->lstnSocket);
1726 lpwfs->lstnSocket = INVALID_SOCKET;
1733 /***********************************************************************
1734 * FTP_SendType (internal)
1736 * Tell server type of data being transfered
1743 BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType)
1746 CHAR type[2] = { "I\0" };
1747 BOOL bSuccess = FALSE;
1750 if (dwType & INTERNET_FLAG_TRANSFER_ASCII)
1753 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_TYPE, type, 0, 0, 0))
1756 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1757 MAX_REPLY_LEN, 0, 0, 0)/100;
1763 FTP_SetResponseError(nResCode);
1771 /***********************************************************************
1772 * FTP_SendPort (internal)
1774 * Tell server which port to use
1781 BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs)
1784 CHAR szIPAddress[64];
1785 BOOL bSuccess = FALSE;
1788 sprintf(szIPAddress, "%d,%d,%d,%d,%d,%d",
1789 lpwfs->lstnSocketAddress.sin_addr.s_addr&0x000000FF,
1790 (lpwfs->lstnSocketAddress.sin_addr.s_addr&0x0000FF00)>>8,
1791 (lpwfs->lstnSocketAddress.sin_addr.s_addr&0x00FF0000)>>16,
1792 (lpwfs->lstnSocketAddress.sin_addr.s_addr&0xFF000000)>>24,
1793 lpwfs->lstnSocketAddress.sin_port & 0xFF,
1794 (lpwfs->lstnSocketAddress.sin_port & 0xFF00)>>8);
1796 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PORT, szIPAddress, 0, 0, 0))
1799 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1800 MAX_REPLY_LEN,0, 0, 0);
1803 if (nResCode == 200)
1806 FTP_SetResponseError(nResCode);
1814 /***********************************************************************
1815 * FTP_InitDataSocket (internal)
1824 BOOL FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs, LPINT nDataSocket)
1826 struct sockaddr_in saddr;
1827 size_t addrlen = sizeof(struct sockaddr);
1830 *nDataSocket = accept(lpwfs->lstnSocket, (struct sockaddr *) &saddr, &addrlen);
1831 close(lpwfs->lstnSocket);
1832 lpwfs->lstnSocket = INVALID_SOCKET;
1834 return *nDataSocket != INVALID_SOCKET;
1838 /***********************************************************************
1839 * FTP_SendData (internal)
1841 * Send data to the server
1848 BOOL FTP_SendData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, HANDLE hFile)
1850 BY_HANDLE_FILE_INFORMATION fi;
1851 DWORD nBytesRead = 0;
1852 DWORD nBytesSent = 0;
1853 DWORD nTotalSent = 0;
1854 DWORD nBytesToSend, nLen, nRC = 1;
1855 time_t s_long_time, e_long_time;
1860 lpszBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR)*DATA_PACKET_SIZE);
1861 memset(lpszBuffer, 0, sizeof(CHAR)*DATA_PACKET_SIZE);
1863 /* Get the size of the file. */
1864 GetFileInformationByHandle(hFile, &fi);
1869 nBytesToSend = nBytesRead - nBytesSent;
1871 if (nBytesToSend <= 0)
1873 /* Read data from file. */
1875 if (!ReadFile(hFile, lpszBuffer, DATA_PACKET_SIZE, &nBytesRead, 0))
1876 ERR("Failed reading from file\n");
1879 nBytesToSend = nBytesRead;
1884 nLen = DATA_PACKET_SIZE < nBytesToSend ?
1885 DATA_PACKET_SIZE : nBytesToSend;
1886 nRC = send(nDataSocket, lpszBuffer, nLen, 0);
1888 if (nRC != SOCKET_ERROR)
1894 /* Do some computation to display the status. */
1896 nSeconds = e_long_time - s_long_time;
1897 if( nSeconds / 60 > 0 )
1899 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\n",
1900 nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds / 60,
1901 nSeconds % 60, (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent );
1905 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld sec estimated remainig time %ld sec\n",
1906 nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds,
1907 (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent);
1909 } while (nRC != SOCKET_ERROR);
1911 TRACE("file transfer complete!\n");
1913 if(lpszBuffer != NULL)
1914 HeapFree(GetProcessHeap(), 0, lpszBuffer);
1920 /***********************************************************************
1921 * FTP_SendRetrieve (internal)
1923 * Send request to retrieve a file
1926 * Number of bytes to be received on success
1930 DWORD FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType)
1936 if (!FTP_InitListenSocket(lpwfs))
1939 if (!FTP_SendType(lpwfs, dwType))
1942 if (!FTP_SendPort(lpwfs))
1945 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0))
1948 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1949 MAX_REPLY_LEN, 0, 0, 0);
1952 if (nResCode == 125 || nResCode == 150)
1954 /* Parse size of data to be retrieved */
1955 INT i, sizepos = -1;
1956 LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
1957 for (i = strlen(lpszResponseBuffer) - 1; i >= 0; i--)
1959 if ('(' == lpszResponseBuffer[i])
1968 nResult = atol(&lpszResponseBuffer[sizepos+1]);
1969 TRACE("Waiting to receive %ld bytes\n", nResult);
1975 if (0 == nResult && INVALID_SOCKET != lpwfs->lstnSocket)
1977 close(lpwfs->lstnSocket);
1978 lpwfs->lstnSocket = INVALID_SOCKET;
1985 /***********************************************************************
1986 * FTP_RetrieveData (internal)
1988 * Retrieve data from server
1995 BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile)
1997 DWORD nBytesWritten;
1998 DWORD nBytesReceived = 0;
2004 if (INVALID_HANDLE_VALUE == hFile)
2007 lpszBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CHAR)*DATA_PACKET_SIZE);
2008 if (NULL == lpszBuffer)
2010 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
2014 while (nBytesReceived < nBytes && nRC != SOCKET_ERROR)
2016 nRC = recv(nDataSocket, lpszBuffer, DATA_PACKET_SIZE, 0);
2017 if (nRC != SOCKET_ERROR)
2019 /* other side closed socket. */
2022 WriteFile(hFile, lpszBuffer, nRC, &nBytesWritten, NULL);
2023 nBytesReceived += nRC;
2026 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived, nBytes,
2027 nBytesReceived * 100 / nBytes);
2030 TRACE("Data transfer complete\n");
2031 if (NULL != lpszBuffer)
2032 HeapFree(GetProcessHeap(), 0, lpszBuffer);
2035 return (nRC != SOCKET_ERROR);
2039 /***********************************************************************
2040 * FTP_CloseSessionHandle (internal)
2042 * Deallocate session handle
2049 BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs)
2051 if (INVALID_SOCKET != lpwfs->sndSocket)
2052 close(lpwfs->sndSocket);
2054 if (INVALID_SOCKET != lpwfs->lstnSocket)
2055 close(lpwfs->lstnSocket);
2057 if (lpwfs->lpszPassword)
2058 HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword);
2060 if (lpwfs->lpszUserName)
2061 HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName);
2063 HeapFree(GetProcessHeap(), 0, lpwfs);
2069 /***********************************************************************
2070 * FTP_CloseSessionHandle (internal)
2072 * Deallocate session handle
2079 BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn)
2085 for (i = 0; i < lpwfn->size; i++)
2087 if (NULL != lpwfn->lpafp[i].lpszName)
2088 HeapFree(GetProcessHeap(), 0, lpwfn->lpafp[i].lpszName);
2091 HeapFree(GetProcessHeap(), 0, lpwfn->lpafp);
2092 HeapFree(GetProcessHeap(), 0, lpwfn);
2098 /***********************************************************************
2099 * FTP_ReceiveFileList (internal)
2101 * Read file list from server
2104 * Handle to file list on success
2108 HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs, INT nSocket,
2109 LPWIN32_FIND_DATAA lpFindFileData, DWORD dwContext)
2112 LPFILEPROPERTIESA lpafp = NULL;
2113 LPWININETFINDNEXTA lpwfn = NULL;
2117 if (FTP_ParseDirectory(lpwfs, nSocket, &lpafp, &dwSize))
2119 FTP_ConvertFileProp(lpafp, lpFindFileData);
2121 lpwfn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETFINDNEXTA));
2124 lpwfn->hdr.htype = WH_HFINDNEXT;
2125 lpwfn->hdr.lpwhparent = (LPWININETHANDLEHEADER)lpwfs;
2126 lpwfn->hdr.dwContext = dwContext;
2127 lpwfn->index = 1; /* Next index is 1 since we return index 0 */
2128 lpwfn->size = dwSize;
2129 lpwfn->lpafp = lpafp;
2133 TRACE("Matched %ld files\n", dwSize);
2134 return (HINTERNET)lpwfn;
2138 /***********************************************************************
2139 * FTP_ConvertFileProp (internal)
2141 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2148 BOOL FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp, LPWIN32_FIND_DATAA lpFindFileData)
2150 BOOL bSuccess = FALSE;
2152 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
2156 DWORD access = mktime(&lpafp->tmLastModified);
2158 /* Not all fields are filled in */
2159 lpFindFileData->ftLastAccessTime.dwHighDateTime = HIWORD(access);
2160 lpFindFileData->ftLastAccessTime.dwLowDateTime = LOWORD(access);
2161 lpFindFileData->nFileSizeHigh = HIWORD(lpafp->nSize);
2162 lpFindFileData->nFileSizeLow = LOWORD(lpafp->nSize);
2164 if (lpafp->bIsDirectory)
2165 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
2167 if (lpafp->lpszName)
2168 strncpy(lpFindFileData->cFileName, lpafp->lpszName, MAX_PATH);
2177 /***********************************************************************
2178 * FTP_ParseDirectory (internal)
2180 * Parse string of directory information
2186 * FIXME: - This function needs serious clea-up
2187 * - We should consider both UNIX and NT list formats
2189 #define MAX_MONTH_LEN 10
2190 #define MIN_LEN_DIR_ENTRY 15
2192 BOOL FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs, INT nSocket, LPFILEPROPERTIESA *lpafp, LPDWORD dwfp)
2195 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2198 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2204 CHAR pszMonth[MAX_MONTH_LEN];
2206 BOOL bSuccess = TRUE;
2207 DWORD nBufLen = MAX_REPLY_LEN;
2208 LPFILEPROPERTIESA curFileProp = NULL;
2209 CHAR* pszLine = NULL;
2210 CHAR* pszToken = NULL;
2211 INT nTokenToSkip = 3;
2219 INT sizeFilePropArray = 20;
2220 INT indexFilePropArray = 0;
2224 /* Allocate intial file properties array */
2225 *lpafp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FILEPROPERTIESA)*(sizeFilePropArray));
2232 while ((pszLine = INTERNET_GetNextLine(nSocket, INTERNET_GetResponseBuffer(), &nBufLen)) != NULL)
2234 if (sizeFilePropArray <= indexFilePropArray)
2236 LPFILEPROPERTIESA tmpafp;
2238 sizeFilePropArray *= 2;
2239 tmpafp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *lpafp,
2240 sizeof(FILEPROPERTIESA)*sizeFilePropArray);
2250 curFileProp = &((*lpafp)[indexFilePropArray]);
2252 /* First Parse the permissions. */
2253 pszToken = strtok(pszLine, " \t" );
2255 /* HACK! If this is not a file listing skip the line */
2256 if (!pszToken || 10 != strlen(pszToken) || nBufLen <= MIN_LEN_DIR_ENTRY)
2258 nBufLen = MAX_REPLY_LEN;
2262 FTP_ParsePermission(pszToken, curFileProp);
2268 pszToken = strtok( NULL, " \t" );
2270 } while( nCount <= nTokenToSkip );
2272 /* Store the size of the file in the param list. */
2273 TRACE("nSize-> %s\n", pszToken);
2274 if (pszToken != NULL)
2275 curFileProp->nSize = atol(pszToken);
2277 /* Parse last modified time. */
2285 pszToken = strtok( NULL, " \t" );
2286 strncpy(pszMonth, pszToken, MAX_MONTH_LEN);
2287 CharUpperA(pszMonth);
2288 pszMatch = strstr(szMonths, pszMonth);
2289 if( pszMatch != NULL )
2290 nMonth = (pszMatch - szMonths) / 3;
2292 pszToken = strtok(NULL, " \t");
2293 TRACE("nDay -> %s\n", pszToken);
2294 if (pszToken != NULL)
2295 nDay = atoi(pszToken);
2297 pszToken = strtok(NULL, " \t");
2298 pszMinutes = strchr(pszToken, ':');
2299 if( pszMinutes != NULL )
2302 nMinutes = atoi(pszMinutes);
2303 pszHour = pszMinutes - 3;
2304 if (pszHour != NULL)
2305 nHour = atoi(pszHour);
2307 apTM = localtime( &aTime );
2308 nYear = apTM->tm_year;
2312 nYear = atoi(pszToken);
2317 curFileProp->tmLastModified.tm_sec = nSeconds;
2318 curFileProp->tmLastModified.tm_min = nMinutes;
2319 curFileProp->tmLastModified.tm_hour = nHour;
2320 curFileProp->tmLastModified.tm_mday = nDay;
2321 curFileProp->tmLastModified.tm_mon = nMonth;
2322 curFileProp->tmLastModified.tm_year = nYear;
2324 pszToken = strtok(NULL, " \t");
2325 if(pszToken != NULL)
2327 curFileProp->lpszName = FTP_strdup(pszToken);
2328 TRACE(": %s\n", curFileProp->lpszName);
2331 nBufLen = MAX_REPLY_LEN;
2332 indexFilePropArray++;
2335 if (bSuccess && indexFilePropArray)
2337 if (indexFilePropArray < sizeFilePropArray - 1)
2339 LPFILEPROPERTIESA tmpafp;
2341 tmpafp = HeapReAlloc(GetProcessHeap(), 0, *lpafp,
2342 sizeof(FILEPROPERTIESA)*indexFilePropArray);
2346 *dwfp = indexFilePropArray;
2350 HeapFree(GetProcessHeap(), 0, *lpafp);
2351 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
2360 /***********************************************************************
2361 * FTP_ParsePermission (internal)
2363 * Parse permission string of directory information
2370 BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESA lpfp)
2372 BOOL bSuccess = TRUE;
2373 unsigned short nPermission = 0;
2378 if ((*lpszPermission != 'd') && (*lpszPermission != '-') && (*lpszPermission != 'l'))
2384 lpfp->bIsDirectory = (*lpszPermission == 'd');
2390 nPermission |= (*(lpszPermission+1) == 'r' ? 1 : 0) << 8;
2393 nPermission |= (*(lpszPermission+2) == 'w' ? 1 : 0) << 7;
2396 nPermission |= (*(lpszPermission+3) == 'x' ? 1 : 0) << 6;
2399 nPermission |= (*(lpszPermission+4) == 'r' ? 1 : 0) << 5;
2402 nPermission |= (*(lpszPermission+5) == 'w' ? 1 : 0) << 4;
2405 nPermission |= (*(lpszPermission+6) == 'x' ? 1 : 0) << 3;
2408 nPermission |= (*(lpszPermission+7) == 'r' ? 1 : 0) << 2;
2411 nPermission |= (*(lpszPermission+8) == 'w' ? 1 : 0) << 1;
2414 nPermission |= (*(lpszPermission+9) == 'x' ? 1 : 0);
2418 }while (nPos <= nLast);
2420 lpfp->permissions = nPermission;
2425 /***********************************************************************
2426 * FTP_SetResponseError (internal)
2428 * Set the appropriate error code for a given response from the server
2433 DWORD FTP_SetResponseError(DWORD dwResponse)
2439 case 421: /* Service not available - Server may be shutting down. */
2440 dwCode = ERROR_INTERNET_TIMEOUT;
2443 case 425: /* Cannot open data connection. */
2444 dwCode = ERROR_INTERNET_CANNOT_CONNECT;
2447 case 426: /* Connection closed, transer aborted. */
2448 dwCode = ERROR_INTERNET_CONNECTION_ABORTED;
2451 case 500: /* Syntax error. Command unrecognized. */
2452 case 501: /* Syntax error. Error in parameters or arguments. */
2453 dwCode = ERROR_INTERNET_INCORRECT_FORMAT;
2456 case 530: /* Not logged in. Login incorrect. */
2457 dwCode = ERROR_INTERNET_LOGIN_FAILURE;
2460 case 550: /* File action not taken. File not found or no access. */
2461 dwCode = ERROR_INTERNET_ITEM_NOT_FOUND;
2464 case 450: /* File action not taken. File may be busy. */
2465 case 451: /* Action aborted. Server error. */
2466 case 452: /* Action not taken. Insufficient storage space on server. */
2467 case 502: /* Command not implemented. */
2468 case 503: /* Bad sequence of command. */
2469 case 504: /* Command not implemented for that parameter. */
2470 case 532: /* Need account for storing files */
2471 case 551: /* Requested action aborted. Page type unknown */
2472 case 552: /* Action aborted. Exceeded storage allocation */
2473 case 553: /* Action not taken. File name not allowed. */
2476 dwCode = ERROR_INTERNET_INTERNAL_ERROR;
2480 INTERNET_SetLastError(dwCode);