2 * WININET - Ftp implementation
4 * Copyright 1999 Corel Corporation
15 #include <sys/socket.h>
17 #include <sys/types.h>
25 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(wininet);
30 #define NOACCOUNT "noaccount"
31 #define DATA_PACKET_SIZE 0x2000
34 #define RESPONSE_TIMEOUT 30
37 /* FTP commands with arguments. */
52 /* FTP commands without arguments. */
60 static const CHAR *szFtpCommands[] = {
81 static const CHAR szMonths[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
83 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
84 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext);
85 BOOL FTP_SendStore(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType);
86 BOOL FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs, LPINT nDataSocket);
87 BOOL FTP_SendData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, HANDLE hFile);
88 INT FTP_ReceiveResponse(INT nSocket, LPSTR lpszResponse, DWORD dwResponse,
89 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext);
90 DWORD FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType);
91 BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile);
92 BOOL FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs);
93 BOOL FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs);
94 BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs);
95 BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs);
96 BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType);
97 BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs);
98 BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESA lpfp);
99 BOOL FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs, INT nSocket, LPFILEPROPERTIESA *lpafp, LPDWORD dwfp);
100 HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs, INT nSocket,
101 LPWIN32_FIND_DATAA lpFindFileData, DWORD dwContext);
102 LPSTR FTP_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer);
103 DWORD FTP_SetResponseError(DWORD dwResponse);
105 /***********************************************************************
106 * FtpPutFileA (WININET.43)
108 * Uploads a file to the FTP server
115 BOOLAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
116 LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext)
118 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
119 LPWININETAPPINFOA hIC = NULL;
121 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
123 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
127 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
128 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
130 WORKREQUEST workRequest;
132 workRequest.asyncall = FTPPUTFILEA;
133 workRequest.HFTPSESSION = (DWORD)hConnect;
134 workRequest.LPSZLOCALFILE = (DWORD)strdup(lpszLocalFile);
135 workRequest.LPSZNEWREMOTEFILE = (DWORD)strdup(lpszNewRemoteFile);
136 workRequest.DWFLAGS = dwFlags;
137 workRequest.DWCONTEXT = dwContext;
139 return INTERNET_AsyncCall(&workRequest);
143 return FTP_FtpPutFileA(hConnect, lpszLocalFile,
144 lpszNewRemoteFile, dwFlags, dwContext);
148 /***********************************************************************
149 * FTP_FtpPutFileA (Internal)
151 * Uploads a file to the FTP server
158 BOOLAPI FTP_FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
159 LPCSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext)
161 HANDLE hFile = (HANDLE)NULL;
162 BOOL bSuccess = FALSE;
163 LPWININETAPPINFOA hIC = NULL;
164 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
166 TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", lpszLocalFile, lpszNewRemoteFile);
167 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
169 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
173 /* Clear any error information */
174 INTERNET_SetLastError(0);
176 /* Open file to be uploaded */
177 if (INVALID_HANDLE_VALUE ==
178 (hFile = CreateFileA(lpszLocalFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)))
180 INTERNET_SetLastError(ERROR_FILE_NOT_FOUND);
184 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
185 if (hIC->lpfnStatusCB)
186 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
188 if (FTP_SendStore(lpwfs, lpszNewRemoteFile, dwFlags))
192 /* Accept connection from ftp server */
193 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
195 FTP_SendData(lpwfs, nDataSocket, hFile);
202 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
204 INTERNET_ASYNC_RESULT iar;
206 iar.dwResult = (DWORD)bSuccess;
207 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
208 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
209 &iar, sizeof(INTERNET_ASYNC_RESULT));
219 /***********************************************************************
220 * FtpSetCurrentDirectoryA (WININET.49)
222 * Change the working directory on the FTP server
229 BOOLAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
231 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
232 LPWININETAPPINFOA hIC = NULL;
234 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
236 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
240 TRACE("lpszDirectory(%s)\n", lpszDirectory);
242 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
243 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
245 WORKREQUEST workRequest;
247 workRequest.asyncall = FTPSETCURRENTDIRECTORYA;
248 workRequest.HFTPSESSION = (DWORD)hConnect;
249 workRequest.LPSZDIRECTORY = (DWORD)strdup(lpszDirectory);
251 return INTERNET_AsyncCall(&workRequest);
255 return FTP_FtpSetCurrentDirectoryA(hConnect, lpszDirectory);
260 /***********************************************************************
261 * FTP_FtpSetCurrentDirectoryA (Internal)
263 * Change the working directory on the FTP server
270 BOOLAPI FTP_FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
273 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
274 LPWININETAPPINFOA hIC = NULL;
275 DWORD bSuccess = FALSE;
277 TRACE("lpszDirectory(%s)\n", lpszDirectory);
279 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
281 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
285 /* Clear any error information */
286 INTERNET_SetLastError(0);
288 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
289 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_CWD, lpszDirectory,
290 hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
293 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
294 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
301 FTP_SetResponseError(nResCode);
305 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
307 INTERNET_ASYNC_RESULT iar;
309 iar.dwResult = (DWORD)bSuccess;
310 iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
311 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
312 &iar, sizeof(INTERNET_ASYNC_RESULT));
318 /***********************************************************************
319 * FtpCreateDirectoryA (WININET.31)
321 * Create new directory on the FTP server
328 BOOLAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
330 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
331 LPWININETAPPINFOA hIC = NULL;
333 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
335 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
339 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
340 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
342 WORKREQUEST workRequest;
344 workRequest.asyncall = FTPCREATEDIRECTORYA;
345 workRequest.HFTPSESSION = (DWORD)hConnect;
346 workRequest.LPSZDIRECTORY = (DWORD)strdup(lpszDirectory);
348 return INTERNET_AsyncCall(&workRequest);
352 return FTP_FtpCreateDirectoryA(hConnect, lpszDirectory);
357 /***********************************************************************
358 * FTP_FtpCreateDirectoryA (Internal)
360 * Create new directory on the FTP server
367 BOOLAPI FTP_FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
370 BOOL bSuccess = FALSE;
371 LPWININETAPPINFOA hIC = NULL;
372 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
375 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
377 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
381 /* Clear any error information */
382 INTERNET_SetLastError(0);
384 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_MKD, lpszDirectory, 0, 0, 0))
387 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
388 MAX_REPLY_LEN, 0, 0, 0);
394 FTP_SetResponseError(nResCode);
398 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
399 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
401 INTERNET_ASYNC_RESULT iar;
403 iar.dwResult = (DWORD)bSuccess;
404 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
405 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
406 &iar, sizeof(INTERNET_ASYNC_RESULT));
413 /***********************************************************************
414 * FtpFindFirstFileA (WININET.35)
416 * Search the specified directory
419 * HINTERNET on success
423 INTERNETAPI HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect,
424 LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD dwContext)
426 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
427 LPWININETAPPINFOA hIC = NULL;
429 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
431 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
435 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
436 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
438 WORKREQUEST workRequest;
440 workRequest.asyncall = FTPFINDFIRSTFILEA;
441 workRequest.HFTPSESSION = (DWORD)hConnect;
442 workRequest.LPSZSEARCHFILE = (DWORD)strdup(lpszSearchFile);
443 workRequest.LPFINDFILEDATA = (DWORD)lpFindFileData;
444 workRequest.DWFLAGS = dwFlags;
445 workRequest.DWCONTEXT= dwContext;
447 INTERNET_AsyncCall(&workRequest);
452 return FTP_FtpFindFirstFileA(hConnect, lpszSearchFile, lpFindFileData,
458 /***********************************************************************
459 * FTP_FtpFindFirstFileA (Internal)
461 * Search the specified directory
464 * HINTERNET on success
468 INTERNETAPI HINTERNET WINAPI FTP_FtpFindFirstFileA(HINTERNET hConnect,
469 LPCSTR lpszSearchFile, LPWIN32_FIND_DATAA lpFindFileData, DWORD dwFlags, DWORD dwContext)
472 LPWININETAPPINFOA hIC = NULL;
473 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hConnect;
474 LPWININETFINDNEXTA hFindNext = NULL;
478 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
480 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
484 /* Clear any error information */
485 INTERNET_SetLastError(0);
487 if (!FTP_InitListenSocket(lpwfs))
490 if (!FTP_SendType(lpwfs, INTERNET_FLAG_TRANSFER_ASCII))
493 if (!FTP_SendPort(lpwfs))
496 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
497 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_LIST, lpszSearchFile,
498 hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
501 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
502 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
505 if (nResCode == 125 || nResCode == 150)
509 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
511 hFindNext = FTP_ReceiveFileList(lpwfs, nDataSocket, lpFindFileData, dwContext);
513 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
514 MAX_REPLY_LEN, hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext);
515 if (nResCode != 226 && nResCode != 250)
516 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
522 FTP_SetResponseError(nResCode);
526 if (lpwfs->lstnSocket != INVALID_SOCKET)
527 close(lpwfs->lstnSocket);
529 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
531 INTERNET_ASYNC_RESULT iar;
535 iar.dwResult = (DWORD)hFindNext;
536 iar.dwError = ERROR_SUCCESS;
537 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
538 &iar, sizeof(INTERNET_ASYNC_RESULT));
541 iar.dwResult = (DWORD)hFindNext;
542 iar.dwError = hFindNext ? ERROR_SUCCESS : INTERNET_GetLastError();
543 hIC->lpfnStatusCB(hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
544 &iar, sizeof(INTERNET_ASYNC_RESULT));
547 return (HINTERNET)hFindNext;
551 /***********************************************************************
552 * FtpGetCurrentDirectoryA (WININET.37)
554 * Retrieves the current directory
561 BOOLAPI FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory,
562 LPDWORD lpdwCurrentDirectory)
564 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
565 LPWININETAPPINFOA hIC = NULL;
567 TRACE("len(%ld)\n", *lpdwCurrentDirectory);
569 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
571 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
575 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
576 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
578 WORKREQUEST workRequest;
580 workRequest.asyncall = FTPGETCURRENTDIRECTORYA;
581 workRequest.HFTPSESSION = (DWORD)hFtpSession;
582 workRequest.LPSZDIRECTORY = (DWORD)lpszCurrentDirectory;
583 workRequest.LPDWDIRECTORY = (DWORD)lpdwCurrentDirectory;
585 return INTERNET_AsyncCall(&workRequest);
589 return FTP_FtpGetCurrentDirectoryA(hFtpSession, lpszCurrentDirectory,
590 lpdwCurrentDirectory);
595 /***********************************************************************
596 * FTP_FtpGetCurrentDirectoryA (Internal)
598 * Retrieves the current directory
605 BOOLAPI FTP_FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDirectory,
606 LPDWORD lpdwCurrentDirectory)
609 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
610 LPWININETAPPINFOA hIC = NULL;
611 DWORD bSuccess = FALSE;
613 TRACE("len(%ld)\n", *lpdwCurrentDirectory);
615 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
617 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
621 /* Clear any error information */
622 INTERNET_SetLastError(0);
624 ZeroMemory(lpszCurrentDirectory, *lpdwCurrentDirectory);
626 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
627 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PWD, NULL,
628 hIC->lpfnStatusCB, hFtpSession, lpwfs->hdr.dwContext))
631 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
632 MAX_REPLY_LEN, hIC->lpfnStatusCB, hFtpSession, lpwfs->hdr.dwContext);
635 if (nResCode == 257) /* Extract directory name */
637 INT firstpos, lastpos, len;
638 LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
640 for (firstpos = 0, lastpos = 0; lpszResponseBuffer[lastpos]; lastpos++)
642 if ('"' == lpszResponseBuffer[lastpos])
651 len = lastpos - firstpos - 1;
652 strncpy(lpszCurrentDirectory, &lpszResponseBuffer[firstpos+1],
653 len < *lpdwCurrentDirectory ? len : *lpdwCurrentDirectory);
654 *lpdwCurrentDirectory = len;
658 FTP_SetResponseError(nResCode);
662 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
664 INTERNET_ASYNC_RESULT iar;
666 iar.dwResult = (DWORD)bSuccess;
667 iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
668 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
669 &iar, sizeof(INTERNET_ASYNC_RESULT));
672 return (DWORD) bSuccess;
675 /***********************************************************************
676 * FtpOpenFileA (WININET.41)
678 * Open a remote file for writing or reading
681 * HINTERNET handle on success
685 INTERNETAPI HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
686 LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
689 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
690 LPWININETAPPINFOA hIC = NULL;
692 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
694 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
698 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
699 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
701 WORKREQUEST workRequest;
703 workRequest.asyncall = FTPOPENFILEA;
704 workRequest.HFTPSESSION = (DWORD)hFtpSession;
705 workRequest.LPSZFILENAME = (DWORD)strdup(lpszFileName);
706 workRequest.FDWACCESS = fdwAccess;
707 workRequest.DWFLAGS = dwFlags;
708 workRequest.DWCONTEXT = dwContext;
710 INTERNET_AsyncCall(&workRequest);
715 return FTP_FtpOpenFileA(hFtpSession, lpszFileName, fdwAccess, dwFlags, dwContext);
720 /***********************************************************************
721 * FTP_FtpOpenFileA (Internal)
723 * Open a remote file for writing or reading
726 * HINTERNET handle on success
730 HINTERNET FTP_FtpOpenFileA(HINTERNET hFtpSession,
731 LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
735 BOOL bSuccess = FALSE;
736 LPWININETFILE hFile = NULL;
737 LPWININETAPPINFOA hIC = NULL;
738 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
742 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
744 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
748 /* Clear any error information */
749 INTERNET_SetLastError(0);
751 if (GENERIC_READ == fdwAccess)
753 /* Set up socket to retrieve data */
754 bSuccess = FTP_SendRetrieve(lpwfs, lpszFileName, dwFlags);
756 else if (GENERIC_WRITE == fdwAccess)
758 /* Set up socket to send data */
759 bSuccess = FTP_SendStore(lpwfs, lpszFileName, dwFlags);
762 /* Accept connection from server */
763 if (bSuccess && FTP_InitDataSocket(lpwfs, &nDataSocket))
765 hFile = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE));
766 hFile->hdr.htype = WH_HFILE;
767 hFile->hdr.dwFlags = dwFlags;
768 hFile->hdr.dwContext = dwContext;
769 hFile->hdr.lpwhparent = hFtpSession;
770 hFile->nDataSocket = nDataSocket;
773 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
774 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
776 INTERNET_ASYNC_RESULT iar;
780 iar.dwResult = (DWORD)hFile;
781 iar.dwError = ERROR_SUCCESS;
782 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
783 &iar, sizeof(INTERNET_ASYNC_RESULT));
786 iar.dwResult = (DWORD)bSuccess;
787 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
788 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
789 &iar, sizeof(INTERNET_ASYNC_RESULT));
792 return (HINTERNET)hFile;
796 /***********************************************************************
797 * FtpGetFileA (WININET.39)
799 * Retrieve file from the FTP server
806 BOOLAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile,
807 BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
810 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hInternet;
811 LPWININETAPPINFOA hIC = NULL;
813 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
815 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
819 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
820 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
822 WORKREQUEST workRequest;
824 workRequest.asyncall = FTPGETFILEA;
825 workRequest.HFTPSESSION = (DWORD)hInternet;
826 workRequest.LPSZREMOTEFILE = (DWORD)strdup(lpszRemoteFile);
827 workRequest.LPSZNEWFILE = (DWORD)strdup(lpszNewFile);
828 workRequest.DWLOCALFLAGSATTRIBUTE = dwLocalFlagsAttribute;
829 workRequest.FFAILIFEXISTS = (DWORD)fFailIfExists;
830 workRequest.DWFLAGS = dwInternetFlags;
831 workRequest.DWCONTEXT = dwContext;
833 return INTERNET_AsyncCall(&workRequest);
837 return FTP_FtpGetFileA(hInternet, lpszRemoteFile, lpszNewFile,
838 fFailIfExists, dwLocalFlagsAttribute, dwInternetFlags, dwContext);
843 /***********************************************************************
844 * FTP_FtpGetFileA (Internal)
846 * Retrieve file from the FTP server
853 BOOLAPI FTP_FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszNewFile,
854 BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
858 BOOL bSuccess = FALSE;
860 LPWININETAPPINFOA hIC = NULL;
861 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hInternet;
863 TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", lpszRemoteFile, lpszNewFile);
864 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
866 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
870 /* Clear any error information */
871 INTERNET_SetLastError(0);
873 /* Ensure we can write to lpszNewfile by opening it */
874 hFile = CreateFileA(lpszNewFile, GENERIC_WRITE, 0, 0, fFailIfExists ?
875 CREATE_NEW : CREATE_ALWAYS, dwLocalFlagsAttribute, 0);
876 if (INVALID_HANDLE_VALUE == hFile)
879 /* Set up socket to retrieve data */
880 nBytes = FTP_SendRetrieve(lpwfs, lpszRemoteFile, dwInternetFlags);
886 /* Accept connection from ftp server */
887 if (FTP_InitDataSocket(lpwfs, &nDataSocket))
892 FTP_RetrieveFileData(lpwfs, nDataSocket, nBytes, hFile);
893 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
894 MAX_REPLY_LEN, 0, 0, 0);
900 FTP_SetResponseError(nResCode);
910 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
911 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
913 INTERNET_ASYNC_RESULT iar;
915 iar.dwResult = (DWORD)bSuccess;
916 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
917 hIC->lpfnStatusCB(hInternet, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
918 &iar, sizeof(INTERNET_ASYNC_RESULT));
925 /***********************************************************************
926 * FtpDeleteFileA (WININET.33)
928 * Delete a file on the ftp server
935 BOOLAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
937 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
938 LPWININETAPPINFOA hIC = NULL;
940 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
942 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
946 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
947 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
949 WORKREQUEST workRequest;
951 workRequest.asyncall = FTPRENAMEFILEA;
952 workRequest.HFTPSESSION = (DWORD)hFtpSession;
953 workRequest.LPSZFILENAME = (DWORD)strdup(lpszFileName);
955 return INTERNET_AsyncCall(&workRequest);
959 return FTP_FtpDeleteFileA(hFtpSession, lpszFileName);
964 /***********************************************************************
965 * FTP_FtpDeleteFileA (Internal)
967 * Delete a file on the ftp server
974 BOOL FTP_FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
977 BOOL bSuccess = FALSE;
978 LPWININETAPPINFOA hIC = NULL;
979 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
981 TRACE("0x%08lx\n", (ULONG) hFtpSession);
982 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
984 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
988 /* Clear any error information */
989 INTERNET_SetLastError(0);
991 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_DELE, lpszFileName, 0, 0, 0))
994 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
995 MAX_REPLY_LEN, 0, 0, 0);
1001 FTP_SetResponseError(nResCode);
1004 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1005 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1007 INTERNET_ASYNC_RESULT iar;
1009 iar.dwResult = (DWORD)bSuccess;
1010 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1011 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1012 &iar, sizeof(INTERNET_ASYNC_RESULT));
1019 /***********************************************************************
1020 * FtpRemoveDirectoryA (WININET.45)
1022 * Remove a directory on the ftp server
1029 BOOLAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
1031 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1032 LPWININETAPPINFOA hIC = NULL;
1034 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1036 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1040 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1041 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1043 WORKREQUEST workRequest;
1045 workRequest.asyncall = FTPREMOVEDIRECTORYA;
1046 workRequest.HFTPSESSION = (DWORD)hFtpSession;
1047 workRequest.LPSZDIRECTORY = (DWORD)strdup(lpszDirectory);
1049 return INTERNET_AsyncCall(&workRequest);
1053 return FTP_FtpRemoveDirectoryA(hFtpSession, lpszDirectory);
1058 /***********************************************************************
1059 * FTP_FtpRemoveDirectoryA (Internal)
1061 * Remove a directory on the ftp server
1068 BOOL FTP_FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
1071 BOOL bSuccess = FALSE;
1072 LPWININETAPPINFOA hIC = NULL;
1073 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1076 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1078 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1082 /* Clear any error information */
1083 INTERNET_SetLastError(0);
1085 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RMD, lpszDirectory, 0, 0, 0))
1088 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1089 MAX_REPLY_LEN, 0, 0, 0);
1092 if (nResCode == 250)
1095 FTP_SetResponseError(nResCode);
1099 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1100 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1102 INTERNET_ASYNC_RESULT iar;
1104 iar.dwResult = (DWORD)bSuccess;
1105 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1106 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1107 &iar, sizeof(INTERNET_ASYNC_RESULT));
1114 /***********************************************************************
1115 * FtpRenameFileA (WININET.47)
1117 * Rename a file on the ftp server
1124 BOOLAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDest)
1126 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1127 LPWININETAPPINFOA hIC = NULL;
1129 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1131 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1135 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1136 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
1138 WORKREQUEST workRequest;
1140 workRequest.asyncall = FTPRENAMEFILEA;
1141 workRequest.HFTPSESSION = (DWORD)hFtpSession;
1142 workRequest.LPSZSRCFILE = (DWORD)strdup(lpszSrc);
1143 workRequest.LPSZDESTFILE = (DWORD)strdup(lpszDest);
1145 return INTERNET_AsyncCall(&workRequest);
1149 return FTP_FtpRenameFileA(hFtpSession, lpszSrc, lpszDest);
1153 /***********************************************************************
1154 * FTP_FtpRenameFileA (Internal)
1156 * Rename a file on the ftp server
1163 BOOL FTP_FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDest)
1166 BOOL bSuccess = FALSE;
1167 LPWININETAPPINFOA hIC = NULL;
1168 LPWININETFTPSESSIONA lpwfs = (LPWININETFTPSESSIONA) hFtpSession;
1171 if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
1173 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1177 /* Clear any error information */
1178 INTERNET_SetLastError(0);
1180 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNFR, lpszSrc, 0, 0, 0))
1183 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket,
1184 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1185 if (nResCode == 350)
1187 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RNTO, lpszDest, 0, 0, 0))
1190 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket,
1191 INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1194 if (nResCode == 250)
1197 FTP_SetResponseError(nResCode);
1200 hIC = (LPWININETAPPINFOA) lpwfs->hdr.lpwhparent;
1201 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1203 INTERNET_ASYNC_RESULT iar;
1205 iar.dwResult = (DWORD)bSuccess;
1206 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1207 hIC->lpfnStatusCB(hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1208 &iar, sizeof(INTERNET_ASYNC_RESULT));
1215 /***********************************************************************
1216 * FTP_Connect (internal)
1218 * Connect to a ftp server
1221 * HINTERNET a session handle on success
1226 HINTERNET FTP_Connect(HINTERNET hInternet, LPCSTR lpszServerName,
1227 INTERNET_PORT nServerPort, LPCSTR lpszUserName,
1228 LPCSTR lpszPassword, DWORD dwFlags, DWORD dwContext)
1230 struct sockaddr_in socketAddr;
1231 struct hostent *phe = NULL;
1232 INT nsocket = INVALID_SOCKET;
1233 LPWININETAPPINFOA hIC = NULL;
1234 BOOL bSuccess = FALSE;
1235 LPWININETFTPSESSIONA lpwfs = NULL;
1237 TRACE("0x%08lx Server(%s) Port(%d) User(%s) Paswd(%s)\n",
1238 (ULONG) hInternet, lpszServerName,
1239 nServerPort, lpszUserName, lpszPassword);
1241 if (((LPWININETHANDLEHEADER)hInternet)->htype != WH_HINIT)
1244 hIC = (LPWININETAPPINFOA) hInternet;
1246 if (NULL == lpszUserName && NULL != lpszPassword)
1248 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_USER_NAME);
1252 if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
1253 nServerPort = INTERNET_DEFAULT_FTP_PORT;
1255 if (hIC->lpfnStatusCB)
1256 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_RESOLVING_NAME,
1257 lpszServerName, strlen(lpszServerName));
1259 if (!GetAddress(lpszServerName, nServerPort, &phe, &socketAddr))
1261 INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
1265 if (hIC->lpfnStatusCB)
1266 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_NAME_RESOLVED,
1267 lpszServerName, strlen(lpszServerName));
1269 if (INVALID_SOCKET == (nsocket = socket(AF_INET,SOCK_STREAM,0)))
1271 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
1275 if (hIC->lpfnStatusCB)
1276 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_CONNECTING_TO_SERVER,
1277 &socketAddr, sizeof(struct sockaddr_in));
1279 if (connect(nsocket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0)
1281 ERR("Unable to connect: errno(%d)\n", errno);
1282 INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
1286 TRACE("Connected to server\n");
1287 if (hIC->lpfnStatusCB)
1288 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_CONNECTED_TO_SERVER,
1289 &socketAddr, sizeof(struct sockaddr_in));
1291 lpwfs = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONA));
1294 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1298 lpwfs->hdr.htype = WH_HFTPSESSION;
1299 lpwfs->hdr.dwFlags = dwFlags;
1300 lpwfs->hdr.dwContext = dwContext;
1301 lpwfs->hdr.lpwhparent = (LPWININETHANDLEHEADER)hInternet;
1302 lpwfs->sndSocket = nsocket;
1303 memcpy(&lpwfs->socketAddress, &socketAddr, sizeof(socketAddr));
1304 lpwfs->phostent = phe;
1306 if (NULL == lpszUserName)
1308 lpwfs->lpszUserName = strdup("anonymous");
1309 lpwfs->lpszPassword = strdup("user@server");
1313 lpwfs->lpszUserName = strdup(lpszUserName);
1314 lpwfs->lpszPassword = strdup(lpszPassword);
1317 if (FTP_ConnectToHost(lpwfs))
1319 if (hIC->lpfnStatusCB)
1321 INTERNET_ASYNC_RESULT iar;
1323 iar.dwResult = (DWORD)lpwfs;
1324 iar.dwError = ERROR_SUCCESS;
1326 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_HANDLE_CREATED,
1327 &iar, sizeof(INTERNET_ASYNC_RESULT));
1329 TRACE("Successfully logged into server\n");
1335 if (!bSuccess && INVALID_SOCKET != nsocket)
1338 if (!bSuccess && lpwfs)
1340 HeapFree(GetProcessHeap(), 0, lpwfs);
1344 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
1346 INTERNET_ASYNC_RESULT iar;
1348 iar.dwResult = (DWORD)lpwfs;
1349 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
1350 hIC->lpfnStatusCB(hInternet, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
1351 &iar, sizeof(INTERNET_ASYNC_RESULT));
1354 return (HINTERNET) lpwfs;
1358 /***********************************************************************
1359 * FTP_ConnectHost (internal)
1361 * Connect to a ftp server
1368 BOOL FTP_ConnectToHost(LPWININETFTPSESSIONA lpwfs)
1371 BOOL bSuccess = FALSE;
1374 FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(), MAX_REPLY_LEN, 0, 0, 0);
1376 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_USER, lpwfs->lpszUserName, 0, 0, 0))
1379 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1380 MAX_REPLY_LEN, 0, 0, 0);
1383 /* Login successful... */
1384 if (nResCode == 230)
1386 /* User name okay, need password... */
1387 else if (nResCode == 331)
1388 bSuccess = FTP_SendPassword(lpwfs);
1389 /* Need account for login... */
1390 else if (nResCode == 332)
1391 bSuccess = FTP_SendAccount(lpwfs);
1393 FTP_SetResponseError(nResCode);
1396 TRACE("Returning %d\n", bSuccess);
1402 /***********************************************************************
1403 * FTP_SendCommand (internal)
1405 * Send command to server
1412 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
1413 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
1417 DWORD nBytesSent = 0;
1421 TRACE("%d: (%s) %d\n", ftpCmd, lpszParam, nSocket);
1424 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
1426 bParamHasLen = lpszParam && strlen(lpszParam) > 0;
1427 len = (bParamHasLen ? strlen(lpszParam) : -1) + strlen(szFtpCommands[ftpCmd]) +
1429 if (NULL == (buf = HeapAlloc(GetProcessHeap(), 0, len+1)))
1431 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1434 sprintf(buf, "%s%s%s%s", szFtpCommands[ftpCmd], bParamHasLen ? " " : "",
1435 bParamHasLen ? lpszParam : "", szCRLF);
1437 TRACE("Sending (%s) len(%ld)\n", buf, len);
1438 while((nBytesSent < len) && (nRC != SOCKET_ERROR))
1440 nRC = send(nSocket, buf+nBytesSent, len - nBytesSent, 0);
1444 HeapFree(GetProcessHeap(), 0, (LPVOID)buf);
1447 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_REQUEST_SENT,
1448 &nBytesSent, sizeof(DWORD));
1450 TRACE("Sent %ld bytes\n", nBytesSent);
1451 return (nRC != SOCKET_ERROR);
1455 /***********************************************************************
1456 * FTP_ReceiveResponse (internal)
1458 * Receive response from server
1461 * Reply code on success
1466 INT FTP_ReceiveResponse(INT nSocket, LPSTR lpszResponse, DWORD dwResponse,
1467 INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
1472 TRACE("socket(%d) \n", nSocket);
1475 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
1480 if (!FTP_GetNextLine(nSocket, lpszResponse, &nRecv))
1483 if (nRecv >= 3 && lpszResponse[3] != '-')
1489 lpszResponse[nRecv] = '\0';
1490 rc = atoi(lpszResponse);
1493 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
1494 &nRecv, sizeof(DWORD));
1498 TRACE("return %d\n", rc);
1503 /***********************************************************************
1504 * FTP_SendPassword (internal)
1506 * Send password to ftp server
1513 BOOL FTP_SendPassword(LPWININETFTPSESSIONA lpwfs)
1516 BOOL bSuccess = FALSE;
1519 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PASS, lpwfs->lpszPassword, 0, 0, 0))
1522 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1523 MAX_REPLY_LEN, 0, 0, 0);
1526 TRACE("Received reply code %d\n", nResCode);
1527 /* Login successful... */
1528 if (nResCode == 230)
1530 /* Command not implemented, superfluous at the server site... */
1531 /* Need account for login... */
1532 else if (nResCode == 332)
1533 bSuccess = FTP_SendAccount(lpwfs);
1535 FTP_SetResponseError(nResCode);
1539 TRACE("Returning %d\n", bSuccess);
1544 /***********************************************************************
1545 * FTP_SendAccount (internal)
1554 BOOL FTP_SendAccount(LPWININETFTPSESSIONA lpwfs)
1557 BOOL bSuccess = FALSE;
1560 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_ACCT, NOACCOUNT, 0, 0, 0))
1563 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1564 MAX_REPLY_LEN, 0, 0, 0);
1568 FTP_SetResponseError(nResCode);
1575 /***********************************************************************
1576 * FTP_SendStore (internal)
1578 * Send request to upload file to ftp server
1585 BOOL FTP_SendStore(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType)
1588 BOOL bSuccess = FALSE;
1591 if (!FTP_InitListenSocket(lpwfs))
1594 if (!FTP_SendType(lpwfs, dwType))
1597 if (!FTP_SendPort(lpwfs))
1600 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_STOR, lpszRemoteFile, 0, 0, 0))
1602 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1603 MAX_REPLY_LEN, 0, 0, 0);
1606 if (nResCode == 150)
1609 FTP_SetResponseError(nResCode);
1613 if (!bSuccess && INVALID_SOCKET != lpwfs->lstnSocket)
1615 close(lpwfs->lstnSocket);
1616 lpwfs->lstnSocket = INVALID_SOCKET;
1623 /***********************************************************************
1624 * FTP_InitListenSocket (internal)
1626 * Create a socket to listen for server response
1633 BOOL FTP_InitListenSocket(LPWININETFTPSESSIONA lpwfs)
1635 BOOL bSuccess = FALSE;
1636 socklen_t namelen = sizeof(struct sockaddr_in);
1640 lpwfs->lstnSocket = socket(PF_INET, SOCK_STREAM, 0);
1641 if (INVALID_SOCKET == lpwfs->lstnSocket)
1643 TRACE("Unable to create listening socket\n");
1647 lpwfs->lstnSocketAddress.sin_family = AF_INET;
1648 lpwfs->lstnSocketAddress.sin_port = htons((u_short) 0);
1649 lpwfs->lstnSocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
1650 if (SOCKET_ERROR == bind(lpwfs->lstnSocket,&lpwfs->lstnSocketAddress, sizeof(struct sockaddr_in)))
1652 TRACE("Unable to bind socket\n");
1656 if (SOCKET_ERROR == listen(lpwfs->lstnSocket, MAX_BACKLOG))
1658 TRACE("listen failed\n");
1662 if (SOCKET_ERROR != getsockname(lpwfs->lstnSocket, &lpwfs->lstnSocketAddress, &namelen))
1666 if (!bSuccess && INVALID_SOCKET == lpwfs->lstnSocket)
1668 close(lpwfs->lstnSocket);
1669 lpwfs->lstnSocket = INVALID_SOCKET;
1676 /***********************************************************************
1677 * FTP_SendType (internal)
1679 * Tell server type of data being transfered
1686 BOOL FTP_SendType(LPWININETFTPSESSIONA lpwfs, DWORD dwType)
1689 CHAR type[2] = { "I\0" };
1690 BOOL bSuccess = FALSE;
1693 if (dwType & INTERNET_FLAG_TRANSFER_ASCII)
1696 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_TYPE, type, 0, 0, 0))
1699 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1700 MAX_REPLY_LEN, 0, 0, 0)/100;
1706 FTP_SetResponseError(nResCode);
1714 /***********************************************************************
1715 * FTP_SendPort (internal)
1717 * Tell server which port to use
1724 BOOL FTP_SendPort(LPWININETFTPSESSIONA lpwfs)
1727 CHAR szIPAddress[64];
1728 BOOL bSuccess = FALSE;
1732 sprintf(szIPAddress, "%d,%d,%d,%d,%d,%d",
1733 lpwfs->socketAddress.sin_addr.s_addr&0x000000FF,
1734 (lpwfs->socketAddress.sin_addr.s_addr&0x0000FF00)>>8,
1735 (lpwfs->socketAddress.sin_addr.s_addr&0x00FF0000)>>16,
1736 (lpwfs->socketAddress.sin_addr.s_addr&0xFF000000)>>24,
1737 lpwfs->lstnSocketAddress.sin_port & 0xFF,
1738 (lpwfs->lstnSocketAddress.sin_port & 0xFF00)>>8);
1740 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PORT, szIPAddress, 0, 0, 0))
1743 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1744 MAX_REPLY_LEN,0, 0, 0);
1747 if (nResCode == 200)
1750 FTP_SetResponseError(nResCode);
1758 /***********************************************************************
1759 * FTP_InitDataSocket (internal)
1768 BOOL FTP_InitDataSocket(LPWININETFTPSESSIONA lpwfs, LPINT nDataSocket)
1770 struct sockaddr_in saddr;
1771 socklen_t addrlen = sizeof(struct sockaddr);
1774 *nDataSocket = accept(lpwfs->lstnSocket, &saddr, &addrlen);
1775 close(lpwfs->lstnSocket);
1776 lpwfs->lstnSocket = INVALID_SOCKET;
1778 return *nDataSocket != INVALID_SOCKET;
1782 /***********************************************************************
1783 * FTP_SendData (internal)
1785 * Send data to the server
1792 BOOL FTP_SendData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, HANDLE hFile)
1794 BY_HANDLE_FILE_INFORMATION fi;
1795 DWORD nBytesRead = 0;
1796 DWORD nBytesSent = 0;
1797 DWORD nTotalSent = 0;
1798 DWORD nBytesToSend, nLen, nRC = 1;
1799 time_t s_long_time, e_long_time;
1804 lpszBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR)*DATA_PACKET_SIZE);
1805 memset(lpszBuffer, 0, sizeof(CHAR)*DATA_PACKET_SIZE);
1807 /* Get the size of the file. */
1808 GetFileInformationByHandle(hFile, &fi);
1813 nBytesToSend = nBytesRead - nBytesSent;
1815 if (nBytesToSend <= 0)
1817 /* Read data from file. */
1819 if (!ReadFile(hFile, lpszBuffer, DATA_PACKET_SIZE, &nBytesRead, 0))
1820 ERR("Failed reading from file\n");
1823 nBytesToSend = nBytesRead;
1828 nLen = DATA_PACKET_SIZE < nBytesToSend ?
1829 DATA_PACKET_SIZE : nBytesToSend;
1830 nRC = send(nDataSocket, lpszBuffer, nLen, 0);
1832 if (nRC != SOCKET_ERROR)
1838 /* Do some computation to display the status. */
1840 nSeconds = e_long_time - s_long_time;
1841 if( nSeconds / 60 > 0 )
1843 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld min %ld sec estimated remainig time %ld sec\t\t\r",
1844 nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds / 60,
1845 nSeconds % 60, (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent );
1849 TRACE( "%ld bytes of %d bytes (%ld%%) in %ld sec estimated remainig time %ld sec\t\t\r",
1850 nTotalSent, fi.nFileSizeLow, nTotalSent*100/fi.nFileSizeLow, nSeconds,
1851 (fi.nFileSizeLow - nTotalSent) * nSeconds / nTotalSent);
1853 } while (nRC != SOCKET_ERROR);
1855 TRACE("file transfer complete!\n");
1857 if(lpszBuffer != NULL)
1858 HeapFree(GetProcessHeap(), 0, lpszBuffer);
1864 /***********************************************************************
1865 * FTP_SendRetrieve (internal)
1867 * Send request to retrieve a file
1870 * Number of bytes to be received on success
1874 DWORD FTP_SendRetrieve(LPWININETFTPSESSIONA lpwfs, LPCSTR lpszRemoteFile, DWORD dwType)
1880 if (!FTP_InitListenSocket(lpwfs))
1883 if (!FTP_SendType(lpwfs, dwType))
1886 if (!FTP_SendPort(lpwfs))
1889 if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_RETR, lpszRemoteFile, 0, 0, 0))
1892 nResCode = FTP_ReceiveResponse(lpwfs->sndSocket, INTERNET_GetResponseBuffer(),
1893 MAX_REPLY_LEN, 0, 0, 0);
1896 if (nResCode == 125 || nResCode == 150)
1898 /* Parse size of data to be retrieved */
1899 INT i, sizepos = -1;
1900 LPSTR lpszResponseBuffer = INTERNET_GetResponseBuffer();
1901 for (i = strlen(lpszResponseBuffer) - 1; i >= 0; i--)
1903 if ('(' == lpszResponseBuffer[i])
1912 nResult = atol(&lpszResponseBuffer[sizepos+1]);
1913 TRACE("Waiting to receive %ld bytes\n", nResult);
1919 if (0 == nResult && INVALID_SOCKET != lpwfs->lstnSocket)
1921 close(lpwfs->lstnSocket);
1922 lpwfs->lstnSocket = INVALID_SOCKET;
1929 /***********************************************************************
1930 * FTP_RetrieveData (internal)
1932 * Retrieve data from server
1939 BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONA lpwfs, INT nDataSocket, DWORD nBytes, HANDLE hFile)
1941 DWORD nBytesWritten;
1942 DWORD nBytesReceived = 0;
1948 if (INVALID_HANDLE_VALUE == hFile)
1951 lpszBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CHAR)*DATA_PACKET_SIZE);
1952 if (NULL == lpszBuffer)
1954 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
1958 while (nBytesReceived < nBytes && nRC != SOCKET_ERROR)
1960 nRC = recv(nDataSocket, lpszBuffer, DATA_PACKET_SIZE, 0);
1961 if (nRC != SOCKET_ERROR)
1963 /* other side closed socket. */
1966 WriteFile(hFile, lpszBuffer, nRC, &nBytesWritten, NULL);
1967 nBytesReceived += nRC;
1970 TRACE("%ld bytes of %ld (%ld%%)\r", nBytesReceived, nBytes,
1971 nBytesReceived * 100 / nBytes);
1974 TRACE("Data transfer complete\n");
1975 if (NULL != lpszBuffer)
1976 HeapFree(GetProcessHeap(), 0, lpszBuffer);
1979 return (nRC != SOCKET_ERROR);
1983 /***********************************************************************
1984 * FTP_CloseSessionHandle (internal)
1986 * Deallocate session handle
1993 BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONA lpwfs)
1995 if (INVALID_SOCKET != lpwfs->sndSocket)
1996 close(lpwfs->sndSocket);
1998 if (INVALID_SOCKET != lpwfs->lstnSocket)
1999 close(lpwfs->lstnSocket);
2001 if (lpwfs->lpszPassword)
2002 HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword);
2004 if (lpwfs->lpszUserName)
2005 HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName);
2007 HeapFree(GetProcessHeap(), 0, lpwfs);
2013 /***********************************************************************
2014 * FTP_CloseSessionHandle (internal)
2016 * Deallocate session handle
2023 BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTA lpwfn)
2029 for (i = 0; i < lpwfn->size; i++)
2031 if (NULL != lpwfn->lpafp[i].lpszName)
2032 HeapFree(GetProcessHeap(), 0, lpwfn->lpafp[i].lpszName);
2035 HeapFree(GetProcessHeap(), 0, lpwfn->lpafp);
2036 HeapFree(GetProcessHeap(), 0, lpwfn);
2042 /***********************************************************************
2043 * FTP_ReceiveFileList (internal)
2045 * Read file list from server
2048 * Handle to file list on success
2052 HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONA lpwfs, INT nSocket,
2053 LPWIN32_FIND_DATAA lpFindFileData, DWORD dwContext)
2056 LPFILEPROPERTIESA lpafp = NULL;
2057 LPWININETFINDNEXTA lpwfn = NULL;
2061 if (FTP_ParseDirectory(lpwfs, nSocket, &lpafp, &dwSize))
2063 FTP_ConvertFileProp(lpafp, lpFindFileData);
2065 lpwfn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETFINDNEXTA));
2068 lpwfn->hdr.htype = WH_HFINDNEXT;
2069 lpwfn->hdr.lpwhparent = (LPWININETHANDLEHEADER)lpwfs;
2070 lpwfn->hdr.dwContext = dwContext;
2071 lpwfn->index = 1; /* Next index is 1 since we return index 0 */
2072 lpwfn->size = dwSize;
2073 lpwfn->lpafp = lpafp;
2077 TRACE("Matched %ld files\n", dwSize);
2078 return (HINTERNET)lpwfn;
2082 /***********************************************************************
2083 * FTP_ConvertFileProp (internal)
2085 * Converts FILEPROPERTIESA struct to WIN32_FIND_DATAA
2092 BOOL FTP_ConvertFileProp(LPFILEPROPERTIESA lpafp, LPWIN32_FIND_DATAA lpFindFileData)
2094 BOOL bSuccess = FALSE;
2096 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
2100 DWORD access = mktime(&lpafp->tmLastModified);
2102 /* Not all fields are filled in */
2103 lpFindFileData->ftLastAccessTime.dwHighDateTime = HIWORD(access);
2104 lpFindFileData->ftLastAccessTime.dwLowDateTime = LOWORD(access);
2105 lpFindFileData->nFileSizeHigh = HIWORD(lpafp->nSize);
2106 lpFindFileData->nFileSizeLow = LOWORD(lpafp->nSize);
2108 if (lpafp->bIsDirectory)
2109 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
2111 if (lpafp->lpszName)
2112 strncpy(lpFindFileData->cFileName, lpafp->lpszName, MAX_PATH);
2121 /***********************************************************************
2122 * FTP_ParseDirectory (internal)
2124 * Parse string of directory information
2130 * FIXME: - This function needs serious clea-up
2131 * - We should consider both UNIX and NT list formats
2133 #define MAX_MONTH_LEN 10
2134 #define MIN_LEN_DIR_ENTRY 15
2136 BOOL FTP_ParseDirectory(LPWININETFTPSESSIONA lpwfs, INT nSocket, LPFILEPROPERTIESA *lpafp, LPDWORD dwfp)
2139 * <Permissions> <NoLinks> <owner> <group> <size> <date> <time or year> <filename>
2142 * drwx--s--- 2 pcarrier ens 512 Sep 28 1995 pcarrier
2148 CHAR pszMonth[MAX_MONTH_LEN];
2150 BOOL bSuccess = TRUE;
2151 DWORD nBufLen = MAX_REPLY_LEN;
2152 LPFILEPROPERTIESA curFileProp = NULL;
2153 CHAR* pszLine = NULL;
2154 CHAR* pszToken = NULL;
2155 INT nTokenToSkip = 3;
2163 INT sizeFilePropArray = 20;
2164 INT indexFilePropArray = 0;
2168 /* Allocate intial file properties array */
2169 *lpafp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FILEPROPERTIESA)*(sizeFilePropArray));
2176 while ((pszLine = FTP_GetNextLine(nSocket, INTERNET_GetResponseBuffer(), &nBufLen)) != NULL)
2178 if (sizeFilePropArray <= indexFilePropArray)
2180 LPFILEPROPERTIESA tmpafp;
2182 sizeFilePropArray *= 2;
2183 tmpafp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *lpafp,
2184 sizeof(FILEPROPERTIESA)*sizeFilePropArray);
2194 curFileProp = &((*lpafp)[indexFilePropArray]);
2196 /* First Parse the permissions. */
2197 pszToken = strtok(pszLine, " \t" );
2199 /* HACK! If this is not a file listing skip the line */
2200 if (!pszToken || 10 != strlen(pszToken) || nBufLen <= MIN_LEN_DIR_ENTRY)
2202 nBufLen = MAX_REPLY_LEN;
2206 FTP_ParsePermission(pszToken, curFileProp);
2212 pszToken = strtok( NULL, " \t" );
2214 } while( nCount <= nTokenToSkip );
2216 /* Store the size of the file in the param list. */
2217 TRACE("nSize-> %s\n", pszToken);
2218 if (pszToken != NULL)
2219 curFileProp->nSize = atol(pszToken);
2221 /* Parse last modified time. */
2229 pszToken = strtok( NULL, " \t" );
2230 strncpy(pszMonth, pszToken, MAX_MONTH_LEN);
2231 CharUpperA(pszMonth);
2232 pszMatch = strstr(szMonths, pszMonth);
2233 if( pszMatch != NULL )
2234 nMonth = (pszMatch - szMonths) / 3;
2236 pszToken = strtok(NULL, " \t");
2237 TRACE("nDay -> %s\n", pszToken);
2238 if (pszToken != NULL)
2239 nDay = atoi(pszToken);
2241 pszToken = strtok(NULL, " \t");
2242 pszMinutes = strchr(pszToken, ':');
2243 if( pszMinutes != NULL )
2246 nMinutes = atoi(pszMinutes);
2247 pszHour = pszMinutes - 3;
2248 if (pszHour != NULL)
2249 nHour = atoi(pszHour);
2251 apTM = localtime( &aTime );
2252 nYear = apTM->tm_year;
2256 nYear = atoi(pszToken);
2261 curFileProp->tmLastModified.tm_sec = nSeconds;
2262 curFileProp->tmLastModified.tm_min = nMinutes;
2263 curFileProp->tmLastModified.tm_hour = nHour;
2264 curFileProp->tmLastModified.tm_mday = nDay;
2265 curFileProp->tmLastModified.tm_mon = nMonth;
2266 curFileProp->tmLastModified.tm_year = nYear;
2268 pszToken = strtok(NULL, " \t");
2269 if(pszToken != NULL)
2271 curFileProp->lpszName = strdup(pszToken);
2272 TRACE(": %s\n", curFileProp->lpszName);
2275 nBufLen = MAX_REPLY_LEN;
2276 indexFilePropArray++;
2279 if (bSuccess && indexFilePropArray)
2281 if (indexFilePropArray < sizeFilePropArray - 1)
2283 LPFILEPROPERTIESA tmpafp;
2285 tmpafp = HeapReAlloc(GetProcessHeap(), 0, *lpafp,
2286 sizeof(FILEPROPERTIESA)*indexFilePropArray);
2290 *dwfp = indexFilePropArray;
2294 HeapFree(GetProcessHeap(), 0, *lpafp);
2295 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
2304 /***********************************************************************
2305 * FTP_ParsePermission (internal)
2307 * Parse permission string of directory information
2314 BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESA lpfp)
2316 BOOL bSuccess = TRUE;
2317 unsigned short nPermission = 0;
2322 if ((*lpszPermission != 'd') && (*lpszPermission != '-') && (*lpszPermission != 'l'))
2328 lpfp->bIsDirectory = (*lpszPermission == 'd');
2334 nPermission |= (*(lpszPermission+1) == 'r' ? 1 : 0) << 8;
2337 nPermission |= (*(lpszPermission+2) == 'w' ? 1 : 0) << 7;
2340 nPermission |= (*(lpszPermission+3) == 'x' ? 1 : 0) << 6;
2343 nPermission |= (*(lpszPermission+4) == 'r' ? 1 : 0) << 5;
2346 nPermission |= (*(lpszPermission+5) == 'w' ? 1 : 0) << 4;
2349 nPermission |= (*(lpszPermission+6) == 'x' ? 1 : 0) << 3;
2352 nPermission |= (*(lpszPermission+7) == 'r' ? 1 : 0) << 2;
2355 nPermission |= (*(lpszPermission+8) == 'w' ? 1 : 0) << 1;
2358 nPermission |= (*(lpszPermission+9) == 'x' ? 1 : 0);
2362 }while (nPos <= nLast);
2364 lpfp->permissions = nPermission;
2369 /***********************************************************************
2370 * FTP_GetNextLine (internal)
2372 * Parse next line in directory string listing
2375 * Pointer to begining of next line
2380 LPSTR FTP_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
2384 BOOL bSuccess = FALSE;
2389 while (nRecv < *dwBuffer)
2392 FD_SET(nSocket, &infd);
2393 tv.tv_sec=RESPONSE_TIMEOUT;
2396 if (select(nSocket+1,&infd,NULL,NULL,&tv))
2398 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2400 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2404 if (lpszBuffer[nRecv] == '\n')
2409 if (lpszBuffer[nRecv] != '\r')
2414 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
2422 lpszBuffer[nRecv] = '\0';
2423 *dwBuffer = nRecv - 1;
2424 TRACE(":%d %s\n", nRecv, lpszBuffer);
2434 /***********************************************************************
2435 * FTP_SetResponseError (internal)
2437 * Set the appropriate error code for a given response from the server
2442 DWORD FTP_SetResponseError(DWORD dwResponse)
2448 case 421: /* Service not available - Server may be shutting down. */
2449 dwCode = ERROR_INTERNET_TIMEOUT;
2452 case 425: /* Cannot open data connection. */
2453 dwCode = ERROR_INTERNET_CANNOT_CONNECT;
2456 case 426: /* Connection closed, transer aborted. */
2457 dwCode = ERROR_INTERNET_CONNECTION_ABORTED;
2460 case 500: /* Syntax error. Command unrecognized. */
2461 case 501: /* Syntax error. Error in parameters or arguments. */
2462 dwCode = ERROR_INTERNET_INCORRECT_FORMAT;
2465 case 530: /* Not logged in. Login incorrect. */
2466 dwCode = ERROR_INTERNET_LOGIN_FAILURE;
2469 case 550: /* File action not taken. File not found or no access. */
2470 dwCode = ERROR_INTERNET_ITEM_NOT_FOUND;
2473 case 450: /* File action not taken. File may be busy. */
2474 case 451: /* Action aborted. Server error. */
2475 case 452: /* Action not taken. Insufficient storage space on server. */
2476 case 502: /* Command not implemented. */
2477 case 503: /* Bad sequence of command. */
2478 case 504: /* Command not implemented for that parameter. */
2479 case 532: /* Need account for storing files */
2480 case 551: /* Requested action aborted. Page type unknown */
2481 case 552: /* Action aborted. Exceeded storage allocation */
2482 case 553: /* Action not taken. File name not allowed. */
2485 dwCode = ERROR_INTERNET_INTERNAL_ERROR;
2489 INTERNET_SetLastError(dwCode);