2 * WININET - Ftp implementation
4 * Copyright 1999 Corel Corporation
17 #include <sys/types.h>
18 #ifdef HAVE_SYS_SOCKET_H
19 # include <sys/socket.h>
32 #include "debugtools.h"
35 DEFAULT_DEBUG_CHANNEL(wininet);
37 #define NOACCOUNT "noaccount"
38 #define DATA_PACKET_SIZE 0x2000
43 /* FTP commands with arguments. */
58 /* FTP commands without arguments. */
66 static const CHAR *szFtpCommands[] = {
87 static const CHAR szMonths[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
89 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
90 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext);
91 BOOL FTP_SendStore(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType);
92 BOOL FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs, LPINT nDataSocket);
93 BOOL FTP_SendData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, HANDLE hFile);
94 INT FTP_ReceiveResponse(INT nSocket, LPSTR lpszResponse, DWORD dwResponse,
95 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext);
96 DWORD FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType);
97 BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile);
98 BOOL FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs);
99 BOOL FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs);
100 BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs);
101 BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs);
102 BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType);
103 BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs);
104 BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESA lpfp);
105 BOOL FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs, INT nSocket, LPFILEPROPERTIESA *lpafp, LPDWORD dwfp);
106 HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs, INT nSocket,
107 LPWIN32_FIND_DATAA lpFindFileData, DWORD dwContext);
108 DWORD FTP_SetResponseError(DWORD dwResponse);
110 /***********************************************************************
111 * FtpPutFileA (WININET.43)
113 * Uploads a file to the FTP server
120 BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
121 LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext)
123 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
124 LPWININETAPPINFOA hIC = NULL;
126 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
128 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
132 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
133 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
135 WORKREQUEST workRequest;
137 workRequest.asyncall = FTPPUTFILEA;
138 workRequest.HFTPSESSION = (DWORD)hConnect;
139 workRequest.LPSZLOCALFILE = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszLocalFile);
140 workRequest.LPSZNEWREMOTEFILE = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszNewRemoteFile);
141 workRequest.DWFLAGS = dwFlags;
142 workRequest.DWCONTEXT = dwContext;
144 return INTERNET_AsyncCall(&workRequest);
148 return FTP_FtpPutFileA(hConnect, lpszLocalFile,
149 lpszNewRemoteFile, dwFlags, dwContext);
153 /***********************************************************************
154 * FTP_FtpPutFileA (Internal)
156 * Uploads a file to the FTP server
163 BOOL WINAPI FTP_FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
164 LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext)
166 HANDLE hFile = (HANDLE)NULL;
167 BOOL bSuccess = FALSE;
168 LPWININETAPPINFOA hIC = NULL;
169 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
171 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile, lpszNewRemoteFile);
172 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
174 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
178 /* Clear any error information */
179 INTERNET_SetLastError(0);
181 /* Open file to be uploaded */
182 if (INVALID_HANDLE_VALUE ==
183 (hFile = CreateFileA(lpszLocalFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)))
185 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND);
189 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
190 if (hIC->lpfnStatusCB)
191 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
193 if (FTP_SendStore(lpwfs, lpszNewRemoteFile, dwFlags))
197 /* Accept connection from ftp server */
198 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
200 FTP_SendData(lpwfs, nDataSocket, hFile);
207 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
209 INTERNET_ASYNC_RESULT iar;
211 iar.dwResult = (DWORD)bSuccess;
212 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
213 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
214 &iar, sizeof(INTERNET_ASYNC_RESULT));
224 /***********************************************************************
225 * FtpSetCurrentDirectoryA (WININET.49)
227 * Change the working directory on the FTP server
234 BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
236 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
237 LPWININETAPPINFOA hIC = NULL;
239 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
241 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
245 TRACE("lpszDirectory(%s)\n", lpszDirectory);
247 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
248 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
250 WORKREQUEST workRequest;
252 workRequest.asyncall = FTPSETCURRENTDIRECTORYA;
253 workRequest.HFTPSESSION = (DWORD)hConnect;
254 workRequest.LPSZDIRECTORY = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszDirectory);
256 return INTERNET_AsyncCall(&workRequest);
260 return FTP_FtpSetCurrentDirectoryA(hConnect, lpszDirectory);
265 /***********************************************************************
266 * FTP_FtpSetCurrentDirectoryA (Internal)
268 * Change the working directory on the FTP server
275 BOOL WINAPI FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
278 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
279 LPWININETAPPINFOA hIC = NULL;
280 DWORD bSuccess = FALSE;
282 TRACE("lpszDirectory(%s)\n", lpszDirectory);
284 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
286 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
290 /* Clear any error information */
291 INTERNET_SetLastError(0);
293 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
294 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_CWD, lpszDirectory,
295 hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
298 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
299 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
306 FTP_SetResponseError(nResCode);
310 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
312 INTERNET_ASYNC_RESULT iar;
314 iar.dwResult = (DWORD)bSuccess;
315 iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
316 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
317 &iar, sizeof(INTERNET_ASYNC_RESULT));
323 /***********************************************************************
324 * FtpCreateDirectoryA (WININET.31)
326 * Create new directory on the FTP server
333 BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
335 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
336 LPWININETAPPINFOA hIC = NULL;
338 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
340 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
344 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
345 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
347 WORKREQUEST workRequest;
349 workRequest.asyncall = FTPCREATEDIRECTORYA;
350 workRequest.HFTPSESSION = (DWORD)hConnect;
351 workRequest.LPSZDIRECTORY = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszDirectory);
353 return INTERNET_AsyncCall(&workRequest);
357 return FTP_FtpCreateDirectoryA(hConnect, lpszDirectory);
362 /***********************************************************************
363 * FTP_FtpCreateDirectoryA (Internal)
365 * Create new directory on the FTP server
372 BOOL WINAPI FTP_FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
375 BOOL bSuccess = FALSE;
376 LPWININETAPPINFOA hIC = NULL;
377 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
380 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
382 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
386 /* Clear any error information */
387 INTERNET_SetLastError(0);
389 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_MKD, lpszDirectory, 0, 0, 0))
392 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
393 MAX_REPLY_LEN, 0, 0, 0);
399 FTP_SetResponseError(nResCode);
403 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
404 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
406 INTERNET_ASYNC_RESULT iar;
408 iar.dwResult = (DWORD)bSuccess;
409 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
410 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
411 &iar, sizeof(INTERNET_ASYNC_RESULT));
418 /***********************************************************************
419 * FtpFindFirstFileA (WININET.35)
421 * Search the specified directory
424 * HINTERNET on success
428 INTERNETAPI HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect,
429 LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD dwContext)
431 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
432 LPWININETAPPINFOA hIC = NULL;
434 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
436 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
440 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
441 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
443 WORKREQUEST workRequest;
445 workRequest.asyncall = FTPFINDFIRSTFILEA;
446 workRequest.HFTPSESSION = (DWORD)hConnect;
447 workRequest.LPSZSEARCHFILE = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszSearchFile);
448 workRequest.LPFINDFILEDATA = (DWORD)lpFindFileData;
449 workRequest.DWFLAGS = dwFlags;
450 workRequest.DWCONTEXT= dwContext;
452 INTERNET_AsyncCall(&workRequest);
457 return FTP_FtpFindFirstFileA(hConnect, lpszSearchFile, lpFindFileData,
463 /***********************************************************************
464 * FTP_FtpFindFirstFileA (Internal)
466 * Search the specified directory
469 * HINTERNET on success
473 INTERNETAPI HINTERNET WINAPI FTP_FtpFindFirstFileA(HINTERNET hConnect,
474 LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD dwContext)
477 LPWININETAPPINFOA hIC = NULL;
478 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
479 LPWININETFINDNEXTA hFindNext = NULL;
483 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
485 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
489 /* Clear any error information */
490 INTERNET_SetLastError(0);
492 if (!FTP_InitListenSocket(lpwfs))
495 if (!FTP_SendType(lpwfs, INTERNET_FLAG_TRANSFER_ASCII))
498 if (!FTP_SendPort(lpwfs))
501 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
502 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_LIST, lpszSearchFile,
503 hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
506 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
507 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
510 if (nResCode == 125 || nResCode == 150)
514 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
516 hFindNext = FTP_ReceiveFileList(lpwfs, nDataSocket, lpFindFileData, dwContext);
518 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
519 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
520 if (nResCode != 226 && nResCode != 250)
521 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
527 FTP_SetResponseError(nResCode);
531 if (lpwfs->lstnSocket != INVALID_SOCKET)
532 close(lpwfs->lstnSocket);
534 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
536 INTERNET_ASYNC_RESULT iar;
540 iar.dwResult = (DWORD)hFindNext;
541 iar.dwError = ERROR_SUCCESS;
542 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
543 &iar, sizeof(INTERNET_ASYNC_RESULT));
546 iar.dwResult = (DWORD)hFindNext;
547 iar.dwError = hFindNext ? ERROR_SUCCESS : INTERNET_GetLastError();
548 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
549 &iar, sizeof(INTERNET_ASYNC_RESULT));
552 return (HINTERNET)hFindNext;
556 /***********************************************************************
557 * FtpGetCurrentDirectoryA (WININET.37)
559 * Retrieves the current directory
566 BOOL WINAPI FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory,
567 LPDWORD lpdwCurrentDirectory)
569 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
570 LPWININETAPPINFOA hIC = NULL;
572 TRACE("len(%ld)\n", *lpdwCurrentDirectory);
574 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
576 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
580 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
581 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
583 WORKREQUEST workRequest;
585 workRequest.asyncall = FTPGETCURRENTDIRECTORYA;
586 workRequest.HFTPSESSION = (DWORD)hFtpSession;
587 workRequest.LPSZDIRECTORY = (DWORD)lpszCurrentDirectory;
588 workRequest.LPDWDIRECTORY = (DWORD)lpdwCurrentDirectory;
590 return INTERNET_AsyncCall(&workRequest);
594 return FTP_FtpGetCurrentDirectoryA(hFtpSession, lpszCurrentDirectory,
595 lpdwCurrentDirectory);
600 /***********************************************************************
601 * FTP_FtpGetCurrentDirectoryA (Internal)
603 * Retrieves the current directory
610 BOOL WINAPI FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory,
611 LPDWORD lpdwCurrentDirectory)
614 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
615 LPWININETAPPINFOA hIC = NULL;
616 DWORD bSuccess = FALSE;
618 TRACE("len(%ld)\n", *lpdwCurrentDirectory);
620 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
622 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
626 /* Clear any error information */
627 INTERNET_SetLastError(0);
629 ZeroMemory(lpszCurrentDirectory, *lpdwCurrentDirectory);
631 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
632 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PWD, NULL,
633 hIC->lpfnStatusCB, hFtpSession, lpwfs->hdr.dwContext))
636 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
637 MAX_REPLY_LEN, hIC->lpfnStatusCB, hFtpSession, lpwfs->hdr.dwContext);
640 if (nResCode == 257) /* Extract directory name */
642 INT firstpos, lastpos, len;
643 LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
645 for (firstpos = 0, lastpos = 0; lpszResponseBuffer[lastpos]; lastpos++)
647 if ('"' == lpszResponseBuffer[lastpos])
656 len = lastpos - firstpos - 1;
657 strncpy(lpszCurrentDirectory, &lpszResponseBuffer[firstpos+1],
658 len < *lpdwCurrentDirectory ? len : *lpdwCurrentDirectory);
659 *lpdwCurrentDirectory = len;
663 FTP_SetResponseError(nResCode);
667 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
669 INTERNET_ASYNC_RESULT iar;
671 iar.dwResult = (DWORD)bSuccess;
672 iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
673 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
674 &iar, sizeof(INTERNET_ASYNC_RESULT));
677 return (DWORD) bSuccess;
680 /***********************************************************************
681 * FtpOpenFileA (WININET.41)
683 * Open a remote file for writing or reading
686 * HINTERNET handle on success
690 INTERNETAPI HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
691 LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
694 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
695 LPWININETAPPINFOA hIC = NULL;
697 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
699 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
703 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
704 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
706 WORKREQUEST workRequest;
708 workRequest.asyncall = FTPOPENFILEA;
709 workRequest.HFTPSESSION = (DWORD)hFtpSession;
710 workRequest.LPSZFILENAME = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszFileName);
711 workRequest.FDWACCESS = fdwAccess;
712 workRequest.DWFLAGS = dwFlags;
713 workRequest.DWCONTEXT = dwContext;
715 INTERNET_AsyncCall(&workRequest);
720 return FTP_FtpOpenFileA(hFtpSession, lpszFileName, fdwAccess, dwFlags, dwContext);
725 /***********************************************************************
726 * FTP_FtpOpenFileA (Internal)
728 * Open a remote file for writing or reading
731 * HINTERNET handle on success
735 HINTERNET FTP_FtpOpenFileA(HINTERNET hFtpSession,
736 LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
740 BOOL bSuccess = FALSE;
741 LPWININETFILE hFile = NULL;
742 LPWININETAPPINFOA hIC = NULL;
743 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
747 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
749 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
753 /* Clear any error information */
754 INTERNET_SetLastError(0);
756 if (GENERIC_READ == fdwAccess)
758 /* Set up socket to retrieve data */
759 bSuccess = FTP_SendRetrieve(lpwfs, lpszFileName, dwFlags);
761 else if (GENERIC_WRITE == fdwAccess)
763 /* Set up socket to send data */
764 bSuccess = FTP_SendStore(lpwfs, lpszFileName, dwFlags);
767 /* Accept connection from server */
768 if (bSuccess && FTP_InitDataSocket(lpwfs, &nDataSocket))
770 hFile = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE));
771 hFile->hdr.htype = WH_HFILE;
772 hFile->hdr.dwFlags = dwFlags;
773 hFile->hdr.dwContext = dwContext;
774 hFile->hdr.lpwhparent = hFtpSession;
775 hFile->nDataSocket = nDataSocket;
778 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
779 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
781 INTERNET_ASYNC_RESULT iar;
785 iar.dwResult = (DWORD)hFile;
786 iar.dwError = ERROR_SUCCESS;
787 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
788 &iar, sizeof(INTERNET_ASYNC_RESULT));
791 iar.dwResult = (DWORD)bSuccess;
792 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
793 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
794 &iar, sizeof(INTERNET_ASYNC_RESULT));
797 return (HINTERNET)hFile;
801 /***********************************************************************
802 * FtpGetFileA (WININET.39)
804 * Retrieve file from the FTP server
811 BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile,
812 BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
815 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hInternet;
816 LPWININETAPPINFOA hIC = NULL;
818 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
820 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
824 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
825 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
827 WORKREQUEST workRequest;
829 workRequest.asyncall = FTPGETFILEA;
830 workRequest.HFTPSESSION = (DWORD)hInternet;
831 workRequest.LPSZREMOTEFILE = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszRemoteFile);
832 workRequest.LPSZNEWFILE = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszNewFile);
833 workRequest.DWLOCALFLAGSATTRIBUTE = dwLocalFlagsAttribute;
834 workRequest.FFAILIFEXISTS = (DWORD)fFailIfExists;
835 workRequest.DWFLAGS = dwInternetFlags;
836 workRequest.DWCONTEXT = dwContext;
838 return INTERNET_AsyncCall(&workRequest);
842 return FTP_FtpGetFileA(hInternet, lpszRemoteFile, lpszNewFile,
843 fFailIfExists, dwLocalFlagsAttribute, dwInternetFlags, dwContext);
848 /***********************************************************************
849 * FTP_FtpGetFileA (Internal)
851 * Retrieve file from the FTP server
858 BOOL WINAPI FTP_FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile,
859 BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
863 BOOL bSuccess = FALSE;
865 LPWININETAPPINFOA hIC = NULL;
866 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hInternet;
868 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile, lpszNewFile);
869 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
871 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
875 /* Clear any error information */
876 INTERNET_SetLastError(0);
878 /* Ensure we can write to lpszNewfile by opening it */
879 hFile = CreateFileA(lpszNewFile, GENERIC_WRITE, 0, 0, fFailIfExists ?
880 CREATE_NEW : CREATE_ALWAYS, dwLocalFlagsAttribute, 0);
881 if (INVALID_HANDLE_VALUE == hFile)
884 /* Set up socket to retrieve data */
885 nBytes = FTP_SendRetrieve(lpwfs, lpszRemoteFile, dwInternetFlags);
891 /* Accept connection from ftp server */
892 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
897 FTP_RetrieveFileData(lpwfs, nDataSocket, nBytes, hFile);
898 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
899 MAX_REPLY_LEN, 0, 0, 0);
905 FTP_SetResponseError(nResCode);
915 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
916 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
918 INTERNET_ASYNC_RESULT iar;
920 iar.dwResult = (DWORD)bSuccess;
921 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
922 hIC->lpfnStatusCB(hInternet, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
923 &iar, sizeof(INTERNET_ASYNC_RESULT));
930 /***********************************************************************
931 * FtpDeleteFileA (WININET.33)
933 * Delete a file on the ftp server
940 BOOL WINAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
942 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
943 LPWININETAPPINFOA hIC = NULL;
945 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
947 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
951 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
952 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
954 WORKREQUEST workRequest;
956 workRequest.asyncall = FTPRENAMEFILEA;
957 workRequest.HFTPSESSION = (DWORD)hFtpSession;
958 workRequest.LPSZFILENAME = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszFileName);
960 return INTERNET_AsyncCall(&workRequest);
964 return FTP_FtpDeleteFileA(hFtpSession, lpszFileName);
969 /***********************************************************************
970 * FTP_FtpDeleteFileA (Internal)
972 * Delete a file on the ftp server
979 BOOL FTP_FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
982 BOOL bSuccess = FALSE;
983 LPWININETAPPINFOA hIC = NULL;
984 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
986 TRACE("0x%08lx\n", (ULONG) hFtpSession);
987 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
989 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
993 /* Clear any error information */
994 INTERNET_SetLastError(0);
996 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_DELE, lpszFileName, 0, 0, 0))
999 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1000 MAX_REPLY_LEN, 0, 0, 0);
1003 if (nResCode == 250)
1006 FTP_SetResponseError(nResCode);
1009 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1010 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1012 INTERNET_ASYNC_RESULT iar;
1014 iar.dwResult = (DWORD)bSuccess;
1015 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1016 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1017 &iar, sizeof(INTERNET_ASYNC_RESULT));
1024 /***********************************************************************
1025 * FtpRemoveDirectoryA (WININET.45)
1027 * Remove a directory on the ftp server
1034 BOOL WINAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
1036 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1037 LPWININETAPPINFOA hIC = NULL;
1039 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1041 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1045 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1046 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1048 WORKREQUEST workRequest;
1050 workRequest.asyncall = FTPREMOVEDIRECTORYA;
1051 workRequest.HFTPSESSION = (DWORD)hFtpSession;
1052 workRequest.LPSZDIRECTORY = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszDirectory);
1054 return INTERNET_AsyncCall(&workRequest);
1058 return FTP_FtpRemoveDirectoryA(hFtpSession, lpszDirectory);
1063 /***********************************************************************
1064 * FTP_FtpRemoveDirectoryA (Internal)
1066 * Remove a directory on the ftp server
1073 BOOL FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
1076 BOOL bSuccess = FALSE;
1077 LPWININETAPPINFOA hIC = NULL;
1078 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1081 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1083 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1087 /* Clear any error information */
1088 INTERNET_SetLastError(0);
1090 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RMD, lpszDirectory, 0, 0, 0))
1093 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1094 MAX_REPLY_LEN, 0, 0, 0);
1097 if (nResCode == 250)
1100 FTP_SetResponseError(nResCode);
1104 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1105 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1107 INTERNET_ASYNC_RESULT iar;
1109 iar.dwResult = (DWORD)bSuccess;
1110 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1111 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1112 &iar, sizeof(INTERNET_ASYNC_RESULT));
1119 /***********************************************************************
1120 * FtpRenameFileA (WININET.47)
1122 * Rename a file on the ftp server
1129 BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDest)
1131 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1132 LPWININETAPPINFOA hIC = NULL;
1134 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1136 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1140 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1141 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1143 WORKREQUEST workRequest;
1145 workRequest.asyncall = FTPRENAMEFILEA;
1146 workRequest.HFTPSESSION = (DWORD)hFtpSession;
1147 workRequest.LPSZSRCFILE = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszSrc);
1148 workRequest.LPSZDESTFILE = (DWORD)HEAP_strdupA(GetProcessHeap(),0,lpszDest);
1150 return INTERNET_AsyncCall(&workRequest);
1154 return FTP_FtpRenameFileA(hFtpSession, lpszSrc, lpszDest);
1158 /***********************************************************************
1159 * FTP_FtpRenameFileA (Internal)
1161 * Rename a file on the ftp server
1168 BOOL FTP_FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDest)
1171 BOOL bSuccess = FALSE;
1172 LPWININETAPPINFOA hIC = NULL;
1173 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1176 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1178 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1182 /* Clear any error information */
1183 INTERNET_SetLastError(0);
1185 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNFR, lpszSrc, 0, 0, 0))
1188 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket,
1189 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1190 if (nResCode == 350)
1192 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNTO, lpszDest, 0, 0, 0))
1195 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket,
1196 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1199 if (nResCode == 250)
1202 FTP_SetResponseError(nResCode);
1205 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1206 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1208 INTERNET_ASYNC_RESULT iar;
1210 iar.dwResult = (DWORD)bSuccess;
1211 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1212 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1213 &iar, sizeof(INTERNET_ASYNC_RESULT));
1220 /***********************************************************************
1221 * FTP_Connect (internal)
1223 * Connect to a ftp server
1226 * HINTERNET a session handle on success
1231 HINTERNET FTP_Connect(HINTERNET hInternet, LPCSTR lpszServerName,
1232 INTERNET_PORT nServerPort, LPCSTR lpszUserName,
1233 LPCSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
1235 struct sockaddr_in socketAddr;
1236 struct hostent *phe = NULL;
1237 INT nsocket = INVALID_SOCKET;
1238 LPWININETAPPINFOA hIC = NULL;
1239 BOOL bSuccess = FALSE;
1240 LPWININETFTPSESSIONA lpwfs = NULL;
1242 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1243 (ULONG) hInternet, lpszServerName,
1244 nServerPort, lpszUserName, lpszPassword);
1246 if (((LPWININETHANDLEHEADER)hInternet)->htype != WH_HINIT)
1249 hIC = (LPWININETAPPINFOA) hInternet;
1251 if (NULL == lpszUserName && NULL != lpszPassword)
1253 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME);
1257 if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
1258 nServerPort = INTERNET_DEFAULT_FTP_PORT;
1260 if (hIC->lpfnStatusCB)
1261 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_RESOLVING_NAME,
1262 (LPSTR) lpszServerName, strlen(lpszServerName));
1264 if (!GetAddress(lpszServerName, nServerPort, &phe, &socketAddr))
1266 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
1270 if (hIC->lpfnStatusCB)
1271 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_NAME_RESOLVED,
1272 (LPSTR) lpszServerName, strlen(lpszServerName));
1274 if (INVALID_SOCKET == (nsocket = socket(AF_INET,SOCK_STREAM,0)))
1276 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
1280 if (hIC->lpfnStatusCB)
1281 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_CONNECTING_TO_SERVER,
1282 &socketAddr, sizeof(struct sockaddr_in));
1284 if (connect(nsocket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0)
1286 ERR("Unable to connect (%s)\n", strerror(errno));
1287 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
1291 TRACE("Connected to server\n");
1292 if (hIC->lpfnStatusCB)
1293 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_CONNECTED_TO_SERVER,
1294 &socketAddr, sizeof(struct sockaddr_in));
1296 lpwfs = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA));
1299 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1303 lpwfs->hdr.htype = WH_HFTPSESSION;
1304 lpwfs->hdr.dwFlags = dwFlags;
1305 lpwfs->hdr.dwContext = dwContext;
1306 lpwfs->hdr.lpwhparent = (LPWININETHANDLEHEADER)hInternet;
1307 lpwfs->sndSocket = nsocket;
1308 memcpy(&lpwfs->socketAddress, &socketAddr, sizeof(socketAddr));
1309 lpwfs->phostent = phe;
1311 if (NULL == lpszUserName)
1313 lpwfs->lpszUserName = HEAP_strdupA(GetProcessHeap(),0,"anonymous");
1314 lpwfs->lpszPassword = HEAP_strdupA(GetProcessHeap(),0,"user@server");
1318 lpwfs->lpszUserName = HEAP_strdupA(GetProcessHeap(),0,lpszUserName);
1319 lpwfs->lpszPassword = HEAP_strdupA(GetProcessHeap(),0,lpszPassword);
1322 if (FTP_ConnectToHost(lpwfs))
1324 if (hIC->lpfnStatusCB)
1326 INTERNET_ASYNC_RESULT iar;
1328 iar.dwResult = (DWORD)lpwfs;
1329 iar.dwError = ERROR_SUCCESS;
1331 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_HANDLE_CREATED,
1332 &iar, sizeof(INTERNET_ASYNC_RESULT));
1334 TRACE("Successfully logged into server\n");
1340 if (!bSuccess && INVALID_SOCKET != nsocket)
1343 if (!bSuccess && lpwfs)
1345 HeapFree(GetProcessHeap(), 0, lpwfs);
1349 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1351 INTERNET_ASYNC_RESULT iar;
1353 iar.dwResult = (DWORD)lpwfs;
1354 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1355 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1356 &iar, sizeof(INTERNET_ASYNC_RESULT));
1359 return (HINTERNET) lpwfs;
1363 /***********************************************************************
1364 * FTP_ConnectHost (internal)
1366 * Connect to a ftp server
1373 BOOL FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs)
1376 BOOL bSuccess = FALSE;
1379 FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1381 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_USER, lpwfs->lpszUserName, 0, 0, 0))
1384 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1385 MAX_REPLY_LEN, 0, 0, 0);
1388 /* Login successful... */
1389 if (nResCode == 230)
1391 /* User name okay, need password... */
1392 else if (nResCode == 331)
1393 bSuccess = FTP_SendPassword(lpwfs);
1394 /* Need account for login... */
1395 else if (nResCode == 332)
1396 bSuccess = FTP_SendAccount(lpwfs);
1398 FTP_SetResponseError(nResCode);
1401 TRACE("Returning %d\n", bSuccess);
1407 /***********************************************************************
1408 * FTP_SendCommand (internal)
1410 * Send command to server
1417 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
1418 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
1422 DWORD nBytesSent = 0;
1426 TRACE("%d: (%s) %d\n", ftpCmd, lpszParam, nSocket);
1429 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
1431 bParamHasLen = lpszParam && strlen(lpszParam) > 0;
1432 len = (bParamHasLen ? strlen(lpszParam) : -1) + strlen(szFtpCommands[ftpCmd]) +
1434 if (NULL == (buf = HeapAlloc(GetProcessHeap(), 0, len+1)))
1436 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1439 sprintf(buf, "%s%s%s%s", szFtpCommands[ftpCmd], bParamHasLen ? " " : "",
1440 bParamHasLen ? lpszParam : "", szCRLF);
1442 TRACE("Sending (%s) len(%ld)\n", buf, len);
1443 while((nBytesSent < len) && (nRC != SOCKET_ERROR))
1445 nRC = send(nSocket, buf+nBytesSent, len - nBytesSent, 0);
1449 HeapFree(GetProcessHeap(), 0, (LPVOID)buf);
1452 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_REQUEST_SENT,
1453 &nBytesSent, sizeof(DWORD));
1455 TRACE("Sent %ld bytes\n", nBytesSent);
1456 return (nRC != SOCKET_ERROR);
1460 /***********************************************************************
1461 * FTP_ReceiveResponse (internal)
1463 * Receive response from server
1466 * Reply code on success
1471 INT FTP_ReceiveResponse(INT nSocket, LPSTR lpszResponse, DWORD dwResponse,
1472 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
1477 TRACE("socket(%d) \n", nSocket);
1480 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
1485 if (!INTERNET_GetNextLine(nSocket, lpszResponse, &nRecv))
1488 if (nRecv >= 3 && lpszResponse[3] != '-')
1494 lpszResponse[nRecv] = '\0';
1495 rc = atoi(lpszResponse);
1498 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
1499 &nRecv, sizeof(DWORD));
1503 TRACE("return %d\n", rc);
1508 /***********************************************************************
1509 * FTP_SendPassword (internal)
1511 * Send password to ftp server
1518 BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs)
1521 BOOL bSuccess = FALSE;
1524 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASS, lpwfs->lpszPassword, 0, 0, 0))
1527 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1528 MAX_REPLY_LEN, 0, 0, 0);
1531 TRACE("Received reply code %d\n", nResCode);
1532 /* Login successful... */
1533 if (nResCode == 230)
1535 /* Command not implemented, superfluous at the server site... */
1536 /* Need account for login... */
1537 else if (nResCode == 332)
1538 bSuccess = FTP_SendAccount(lpwfs);
1540 FTP_SetResponseError(nResCode);
1544 TRACE("Returning %d\n", bSuccess);
1549 /***********************************************************************
1550 * FTP_SendAccount (internal)
1559 BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs)
1562 BOOL bSuccess = FALSE;
1565 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_ACCT, NOACCOUNT, 0, 0, 0))
1568 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1569 MAX_REPLY_LEN, 0, 0, 0);
1573 FTP_SetResponseError(nResCode);
1580 /***********************************************************************
1581 * FTP_SendStore (internal)
1583 * Send request to upload file to ftp server
1590 BOOL FTP_SendStore(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType)
1593 BOOL bSuccess = FALSE;
1596 if (!FTP_InitListenSocket(lpwfs))
1599 if (!FTP_SendType(lpwfs, dwType))
1602 if (!FTP_SendPort(lpwfs))
1605 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_STOR, lpszRemoteFile, 0, 0, 0))
1607 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1608 MAX_REPLY_LEN, 0, 0, 0);
1611 if (nResCode == 150)
1614 FTP_SetResponseError(nResCode);
1618 if (!bSuccess && INVALID_SOCKET != lpwfs->lstnSocket)
1620 close(lpwfs->lstnSocket);
1621 lpwfs->lstnSocket = INVALID_SOCKET;
1628 /***********************************************************************
1629 * FTP_InitListenSocket (internal)
1631 * Create a socket to listen for server response
1638 BOOL FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs)
1640 BOOL bSuccess = FALSE;
1641 size_t namelen = sizeof(struct sockaddr_in);
1645 lpwfs->lstnSocket = socket(PF_INET, SOCK_STREAM, 0);
1646 if (INVALID_SOCKET == lpwfs->lstnSocket)
1648 TRACE("Unable to create listening socket\n");
1652 lpwfs->lstnSocketAddress.sin_family = AF_INET;
1653 lpwfs->lstnSocketAddress.sin_port = htons((u_short) 0);
1654 lpwfs->lstnSocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
1655 if (SOCKET_ERROR == bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(struct sockaddr_in)))
1657 TRACE("Unable to bind socket\n");
1661 if (SOCKET_ERROR == listen(lpwfs->lstnSocket, MAX_BACKLOG))
1663 TRACE("listen failed\n");
1667 if (SOCKET_ERROR != getsockname(lpwfs->lstnSocket, (struct sockaddr *) &lpwfs->lstnSocketAddress, &namelen))
1671 if (!bSuccess && INVALID_SOCKET == lpwfs->lstnSocket)
1673 close(lpwfs->lstnSocket);
1674 lpwfs->lstnSocket = INVALID_SOCKET;
1681 /***********************************************************************
1682 * FTP_SendType (internal)
1684 * Tell server type of data being transfered
1691 BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType)
1694 CHAR type[2] = { "I\0" };
1695 BOOL bSuccess = FALSE;
1698 if (dwType & INTERNET_FLAG_TRANSFER_ASCII)
1701 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_TYPE, type, 0, 0, 0))
1704 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1705 MAX_REPLY_LEN, 0, 0, 0)/100;
1711 FTP_SetResponseError(nResCode);
1719 /***********************************************************************
1720 * FTP_SendPort (internal)
1722 * Tell server which port to use
1729 BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs)
1732 CHAR szIPAddress[64];
1733 BOOL bSuccess = FALSE;
1737 sprintf(szIPAddress, "%d,%d,%d,%d,%d,%d",
1738 lpwfs->socketAddress.sin_addr.s_addr&0x000000FF,
1739 (lpwfs->socketAddress.sin_addr.s_addr&0x0000FF00)>>8,
1740 (lpwfs->socketAddress.sin_addr.s_addr&0x00FF0000)>>16,
1741 (lpwfs->socketAddress.sin_addr.s_addr&0xFF000000)>>24,
1742 lpwfs->lstnSocketAddress.sin_port & 0xFF,
1743 (lpwfs->lstnSocketAddress.sin_port & 0xFF00)>>8);
1745 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PORT, szIPAddress, 0, 0, 0))
1748 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1749 MAX_REPLY_LEN,0, 0, 0);
1752 if (nResCode == 200)
1755 FTP_SetResponseError(nResCode);
1763 /***********************************************************************
1764 * FTP_InitDataSocket (internal)
1773 BOOL FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs, LPINT nDataSocket)
1775 struct sockaddr_in saddr;
1776 size_t addrlen = sizeof(struct sockaddr);
1779 *nDataSocket = accept(lpwfs->lstnSocket, (struct sockaddr *) &saddr, &addrlen);
1780 close(lpwfs->lstnSocket);
1781 lpwfs->lstnSocket = INVALID_SOCKET;
1783 return *nDataSocket != INVALID_SOCKET;
1787 /***********************************************************************
1788 * FTP_SendData (internal)
1790 * Send data to the server
1797 BOOL FTP_SendData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, HANDLE hFile)
1799 BY_HANDLE_FILE_INFORMATION fi;
1800 DWORD nBytesRead = 0;
1801 DWORD nBytesSent = 0;
1802 DWORD nTotalSent = 0;
1803 DWORD nBytesToSend, nLen, nRC = 1;
1804 time_t s_long_time, e_long_time;
1809 lpszBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR)*DATA_PACKET_SIZE);
1810 memset(lpszBuffer, 0, sizeof(CHAR)*DATA_PACKET_SIZE);
1812 /* Get the size of the file. */
1813 GetFileInformationByHandle(hFile, &fi);
1818 nBytesToSend = nBytesRead - nBytesSent;
1820 if (nBytesToSend <= 0)
1822 /* Read data from file. */
1824 if (!ReadFile(hFile, lpszBuffer, DATA_PACKET_SIZE, &nBytesRead, 0))
1825 ERR("Failed reading from file\n");
1828 nBytesToSend = nBytesRead;
1833 nLen = DATA_PACKET_SIZE < nBytesToSend ?
1834 DATA_PACKET_SIZE : nBytesToSend;
1835 nRC = send(nDataSocket, lpszBuffer, nLen, 0);
1837 if (nRC != SOCKET_ERROR)
1843 /* Do some computation to display the status. */
1845 nSeconds = e_long_time - s_long_time;
1846 if( nSeconds / 60 > 0 )
1848 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\t\t\r",
1849 nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds / 60,
1850 nSeconds % 60, (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent );
1854 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld sec estimated remainig time %ld sec\t\t\r",
1855 nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds,
1856 (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent);
1858 } while (nRC != SOCKET_ERROR);
1860 TRACE("file transfer complete!\n");
1862 if(lpszBuffer != NULL)
1863 HeapFree(GetProcessHeap(), 0, lpszBuffer);
1869 /***********************************************************************
1870 * FTP_SendRetrieve (internal)
1872 * Send request to retrieve a file
1875 * Number of bytes to be received on success
1879 DWORD FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType)
1885 if (!FTP_InitListenSocket(lpwfs))
1888 if (!FTP_SendType(lpwfs, dwType))
1891 if (!FTP_SendPort(lpwfs))
1894 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0))
1897 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1898 MAX_REPLY_LEN, 0, 0, 0);
1901 if (nResCode == 125 || nResCode == 150)
1903 /* Parse size of data to be retrieved */
1904 INT i, sizepos = -1;
1905 LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
1906 for (i = strlen(lpszResponseBuffer) - 1; i >= 0; i--)
1908 if ('(' == lpszResponseBuffer[i])
1917 nResult = atol(&lpszResponseBuffer[sizepos+1]);
1918 TRACE("Waiting to receive %ld bytes\n", nResult);
1924 if (0 == nResult && INVALID_SOCKET != lpwfs->lstnSocket)
1926 close(lpwfs->lstnSocket);
1927 lpwfs->lstnSocket = INVALID_SOCKET;
1934 /***********************************************************************
1935 * FTP_RetrieveData (internal)
1937 * Retrieve data from server
1944 BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile)
1946 DWORD nBytesWritten;
1947 DWORD nBytesReceived = 0;
1953 if (INVALID_HANDLE_VALUE == hFile)
1956 lpszBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CHAR)*DATA_PACKET_SIZE);
1957 if (NULL == lpszBuffer)
1959 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1963 while (nBytesReceived < nBytes && nRC != SOCKET_ERROR)
1965 nRC = recv(nDataSocket, lpszBuffer, DATA_PACKET_SIZE, 0);
1966 if (nRC != SOCKET_ERROR)
1968 /* other side closed socket. */
1971 WriteFile(hFile, lpszBuffer, nRC, &nBytesWritten, NULL);
1972 nBytesReceived += nRC;
1975 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived, nBytes,
1976 nBytesReceived * 100 / nBytes);
1979 TRACE("Data transfer complete\n");
1980 if (NULL != lpszBuffer)
1981 HeapFree(GetProcessHeap(), 0, lpszBuffer);
1984 return (nRC != SOCKET_ERROR);
1988 /***********************************************************************
1989 * FTP_CloseSessionHandle (internal)
1991 * Deallocate session handle
1998 BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs)
2000 if (INVALID_SOCKET != lpwfs->sndSocket)
2001 close(lpwfs->sndSocket);
2003 if (INVALID_SOCKET != lpwfs->lstnSocket)
2004 close(lpwfs->lstnSocket);
2006 if (lpwfs->lpszPassword)
2007 HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword);
2009 if (lpwfs->lpszUserName)
2010 HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName);
2012 HeapFree(GetProcessHeap(), 0, lpwfs);
2018 /***********************************************************************
2019 * FTP_CloseSessionHandle (internal)
2021 * Deallocate session handle
2028 BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn)
2034 for (i = 0; i < lpwfn->size; i++)
2036 if (NULL != lpwfn->lpafp[i].lpszName)
2037 HeapFree(GetProcessHeap(), 0, lpwfn->lpafp[i].lpszName);
2040 HeapFree(GetProcessHeap(), 0, lpwfn->lpafp);
2041 HeapFree(GetProcessHeap(), 0, lpwfn);
2047 /***********************************************************************
2048 * FTP_ReceiveFileList (internal)
2050 * Read file list from server
2053 * Handle to file list on success
2057 HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs, INT nSocket,
2058 LPWIN32_FIND_DATAA lpFindFileData, DWORD dwContext)
2061 LPFILEPROPERTIESA lpafp = NULL;
2062 LPWININETFINDNEXTA lpwfn = NULL;
2066 if (FTP_ParseDirectory(lpwfs, nSocket, &lpafp, &dwSize))
2068 FTP_ConvertFileProp(lpafp, lpFindFileData);
2070 lpwfn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETFINDNEXTA));
2073 lpwfn->hdr.htype = WH_HFINDNEXT;
2074 lpwfn->hdr.lpwhparent = (LPWININETHANDLEHEADER)lpwfs;
2075 lpwfn->hdr.dwContext = dwContext;
2076 lpwfn->index = 1; /* Next index is 1 since we return index 0 */
2077 lpwfn->size = dwSize;
2078 lpwfn->lpafp = lpafp;
2082 TRACE("Matched %ld files\n", dwSize);
2083 return (HINTERNET)lpwfn;
2087 /***********************************************************************
2088 * FTP_ConvertFileProp (internal)
2090 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2097 BOOL FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp, LPWIN32_FIND_DATAA lpFindFileData)
2099 BOOL bSuccess = FALSE;
2101 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
2105 DWORD access = mktime(&lpafp->tmLastModified);
2107 /* Not all fields are filled in */
2108 lpFindFileData->ftLastAccessTime.dwHighDateTime = HIWORD(access);
2109 lpFindFileData->ftLastAccessTime.dwLowDateTime = LOWORD(access);
2110 lpFindFileData->nFileSizeHigh = HIWORD(lpafp->nSize);
2111 lpFindFileData->nFileSizeLow = LOWORD(lpafp->nSize);
2113 if (lpafp->bIsDirectory)
2114 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
2116 if (lpafp->lpszName)
2117 strncpy(lpFindFileData->cFileName, lpafp->lpszName, MAX_PATH);
2126 /***********************************************************************
2127 * FTP_ParseDirectory (internal)
2129 * Parse string of directory information
2135 * FIXME: - This function needs serious clea-up
2136 * - We should consider both UNIX and NT list formats
2138 #define MAX_MONTH_LEN 10
2139 #define MIN_LEN_DIR_ENTRY 15
2141 BOOL FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs, INT nSocket, LPFILEPROPERTIESA *lpafp, LPDWORD dwfp)
2144 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2147 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2153 CHAR pszMonth[MAX_MONTH_LEN];
2155 BOOL bSuccess = TRUE;
2156 DWORD nBufLen = MAX_REPLY_LEN;
2157 LPFILEPROPERTIESA curFileProp = NULL;
2158 CHAR* pszLine = NULL;
2159 CHAR* pszToken = NULL;
2160 INT nTokenToSkip = 3;
2168 INT sizeFilePropArray = 20;
2169 INT indexFilePropArray = 0;
2173 /* Allocate intial file properties array */
2174 *lpafp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FILEPROPERTIESA)*(sizeFilePropArray));
2181 while ((pszLine = INTERNET_GetNextLine(nSocket, INTERNET_GetResponseBuffer(), &nBufLen)) != NULL)
2183 if (sizeFilePropArray <= indexFilePropArray)
2185 LPFILEPROPERTIESA tmpafp;
2187 sizeFilePropArray *= 2;
2188 tmpafp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *lpafp,
2189 sizeof(FILEPROPERTIESA)*sizeFilePropArray);
2199 curFileProp = &((*lpafp)[indexFilePropArray]);
2201 /* First Parse the permissions. */
2202 pszToken = strtok(pszLine, " \t" );
2204 /* HACK! If this is not a file listing skip the line */
2205 if (!pszToken || 10 != strlen(pszToken) || nBufLen <= MIN_LEN_DIR_ENTRY)
2207 nBufLen = MAX_REPLY_LEN;
2211 FTP_ParsePermission(pszToken, curFileProp);
2217 pszToken = strtok( NULL, " \t" );
2219 } while( nCount <= nTokenToSkip );
2221 /* Store the size of the file in the param list. */
2222 TRACE("nSize-> %s\n", pszToken);
2223 if (pszToken != NULL)
2224 curFileProp->nSize = atol(pszToken);
2226 /* Parse last modified time. */
2234 pszToken = strtok( NULL, " \t" );
2235 strncpy(pszMonth, pszToken, MAX_MONTH_LEN);
2236 CharUpperA(pszMonth);
2237 pszMatch = strstr(szMonths, pszMonth);
2238 if( pszMatch != NULL )
2239 nMonth = (pszMatch - szMonths) / 3;
2241 pszToken = strtok(NULL, " \t");
2242 TRACE("nDay -> %s\n", pszToken);
2243 if (pszToken != NULL)
2244 nDay = atoi(pszToken);
2246 pszToken = strtok(NULL, " \t");
2247 pszMinutes = strchr(pszToken, ':');
2248 if( pszMinutes != NULL )
2251 nMinutes = atoi(pszMinutes);
2252 pszHour = pszMinutes - 3;
2253 if (pszHour != NULL)
2254 nHour = atoi(pszHour);
2256 apTM = localtime( &aTime );
2257 nYear = apTM->tm_year;
2261 nYear = atoi(pszToken);
2266 curFileProp->tmLastModified.tm_sec = nSeconds;
2267 curFileProp->tmLastModified.tm_min = nMinutes;
2268 curFileProp->tmLastModified.tm_hour = nHour;
2269 curFileProp->tmLastModified.tm_mday = nDay;
2270 curFileProp->tmLastModified.tm_mon = nMonth;
2271 curFileProp->tmLastModified.tm_year = nYear;
2273 pszToken = strtok(NULL, " \t");
2274 if(pszToken != NULL)
2276 curFileProp->lpszName = HEAP_strdupA(GetProcessHeap(),0,pszToken);
2277 TRACE(": %s\n", curFileProp->lpszName);
2280 nBufLen = MAX_REPLY_LEN;
2281 indexFilePropArray++;
2284 if (bSuccess && indexFilePropArray)
2286 if (indexFilePropArray < sizeFilePropArray - 1)
2288 LPFILEPROPERTIESA tmpafp;
2290 tmpafp = HeapReAlloc(GetProcessHeap(), 0, *lpafp,
2291 sizeof(FILEPROPERTIESA)*indexFilePropArray);
2295 *dwfp = indexFilePropArray;
2299 HeapFree(GetProcessHeap(), 0, *lpafp);
2300 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
2309 /***********************************************************************
2310 * FTP_ParsePermission (internal)
2312 * Parse permission string of directory information
2319 BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESA lpfp)
2321 BOOL bSuccess = TRUE;
2322 unsigned short nPermission = 0;
2327 if ((*lpszPermission != 'd') && (*lpszPermission != '-') && (*lpszPermission != 'l'))
2333 lpfp->bIsDirectory = (*lpszPermission == 'd');
2339 nPermission |= (*(lpszPermission+1) == 'r' ? 1 : 0) << 8;
2342 nPermission |= (*(lpszPermission+2) == 'w' ? 1 : 0) << 7;
2345 nPermission |= (*(lpszPermission+3) == 'x' ? 1 : 0) << 6;
2348 nPermission |= (*(lpszPermission+4) == 'r' ? 1 : 0) << 5;
2351 nPermission |= (*(lpszPermission+5) == 'w' ? 1 : 0) << 4;
2354 nPermission |= (*(lpszPermission+6) == 'x' ? 1 : 0) << 3;
2357 nPermission |= (*(lpszPermission+7) == 'r' ? 1 : 0) << 2;
2360 nPermission |= (*(lpszPermission+8) == 'w' ? 1 : 0) << 1;
2363 nPermission |= (*(lpszPermission+9) == 'x' ? 1 : 0);
2367 }while (nPos <= nLast);
2369 lpfp->permissions = nPermission;
2374 /***********************************************************************
2375 * FTP_SetResponseError (internal)
2377 * Set the appropriate error code for a given response from the server
2382 DWORD FTP_SetResponseError(DWORD dwResponse)
2388 case 421: /* Service not available - Server may be shutting down. */
2389 dwCode = ERROR_INTERNET_TIMEOUT;
2392 case 425: /* Cannot open data connection. */
2393 dwCode = ERROR_INTERNET_CANNOT_CONNECT;
2396 case 426: /* Connection closed, transer aborted. */
2397 dwCode = ERROR_INTERNET_CONNECTION_ABORTED;
2400 case 500: /* Syntax error. Command unrecognized. */
2401 case 501: /* Syntax error. Error in parameters or arguments. */
2402 dwCode = ERROR_INTERNET_INCORRECT_FORMAT;
2405 case 530: /* Not logged in. Login incorrect. */
2406 dwCode = ERROR_INTERNET_LOGIN_FAILURE;
2409 case 550: /* File action not taken. File not found or no access. */
2410 dwCode = ERROR_INTERNET_ITEM_NOT_FOUND;
2413 case 450: /* File action not taken. File may be busy. */
2414 case 451: /* Action aborted. Server error. */
2415 case 452: /* Action not taken. Insufficient storage space on server. */
2416 case 502: /* Command not implemented. */
2417 case 503: /* Bad sequence of command. */
2418 case 504: /* Command not implemented for that parameter. */
2419 case 532: /* Need account for storing files */
2420 case 551: /* Requested action aborted. Page type unknown */
2421 case 552: /* Action aborted. Exceeded storage allocation */
2422 case 553: /* Action not taken. File name not allowed. */
2425 dwCode = ERROR_INTERNET_INTERNAL_ERROR;
2429 INTERNET_SetLastError(dwCode);