AC_FTP.C
资源名称:FTP总集.rar [点击查看]
上传用户:tjfeida
上传日期:2013-03-10
资源大小:1917k
文件大小:26k
源码类别:
Ftp客户端
开发平台:
Visual C++
- /*---------------------------------------------------------------------
- *
- * Program: AC_FTP.EXE Asynch Ftp Client (TCP)
- *
- * filename: ac_ftp.c
- *
- * copyright by Bob Quinn, 1995
- *
- * Description:
- * Client application that uses "file transfer protocol" (ftp)
- * service as described by RFC 959. This application demonstrates
- * bulk data transfer techniques, and reading variable length records
- * from a byte stream (TCP socket). The user interface is minimized
- * in order to emphasize the network code.
- *
- * This software is not subject to any export provision of
- * the United States Department of Commerce, and may be
- * exported to any country or planet.
- *
- * Permission is granted to anyone to use this software for any
- * purpose on any computer system, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The author is not responsible for the consequences of
- * use of this software, no matter how awful, even if they
- * arise from flaws in it.
- *
- * 2. The origin of this software must not be misrepresented,
- * either by explicit claim or by omission. Since few users
- * ever read sources, credits must appear in the documentation.
- *
- * 3. Altered versions must be plainly marked as such, and
- * must not be misrepresented as being the original software.
- * Since few users ever read sources, credits must appear in
- * the documentation.
- *
- * 4. This notice may not be removed or altered.
- *
- ---------------------------------------------------------------------*/
- #define STRICT
- #include "..wsa_xtra.h"
- #include <windows.h>
- #include <windowsx.h>
- #include <string.h> /* for _fmemcpy() & _fmemset() */
- #include <winsock.h>
- #include "resource.h"
- #include <time.h>
- #include <stdio.h>
- #include <direct.h> /* for getcwd() */
- #include "..winsockx.h"
- #include "ac_ftp.h"
- /* Ftp commmand strings (indexed by our command macro values) */
- LPSTR aszFtpCmd[] = {
- "", "CWD", "DELE", "PASS","PORT","RETR","STOR",
- "TYPE","USER","ABOR","LIST","PWD", "QUIT"
- };
- char szAppName[] = "AC_FTP";
- BOOL nAppState=NOT_CONNECTED; /* Application State */
- BOOL bToNul =FALSE; /* Get to NUL device file */
- BOOL bFromNul=FALSE; /* Put from NUL device file */
- BOOL bIOBeep =FALSE; /* Beep on FD_READ, FD_WRITE */
- BOOL bDebug =FALSE; /* Debug output to WinDebug */
- BOOL bReAsync=TRUE; /* Call WSAAsyncSelect after accept() */
- BOOL bLogFile=TRUE; /* Write Cmds and Replies to logfile */
- SOCKET hCtrlSock=INVALID_SOCKET; /* Ftp control socket */
- SOCKET hLstnSock=INVALID_SOCKET; /* Listening data socket */
- SOCKET hDataSock=INVALID_SOCKET; /* Connected data socket */
- char szHost[MAXHOSTNAME]={0}; /* Remote host name or address */
- char szUser[MAXUSERNAME]={0}; /* User ID */
- char szPWrd[MAXPASSWORD]={0}; /* User password */
- SOCKADDR_IN stCLclName; /* Control socket name (local client) */
- SOCKADDR_IN stCRmtName; /* (remote server) */
- SOCKADDR_IN stDLclName; /* Data socket name (local client)*/
- SOCKADDR_IN stDRmtName; /* (remote server) */
- char achInBuf [INPUT_SIZE]; /* Network input data buffer */
- char achOutBuf [INPUT_SIZE]; /* Network output buffer */
- char szFtpRply [RPLY_SIZE]={0}; /* Ftp reply (input) buffer */
- char szDataFile[MAXFILENAME]={0};/* Filename */
- char szFtpCmd [CMD_SIZE]={0}; /* Ftp command buffer */
- char achRplyBuf[BUF_SIZE]; /* Reply display buffer */
- /* first one (index=0) is awaiting a reply
- * second (index=1) is next to be sent, etcetera */
- FTPCMD astFtpCmd[MAX_CMDS]; /* Ftp command queue */
- int nQLen; /* Number of entries in Ftp cmd queue */
- int nFtpRplyCode; /* Ftp reply code from server */
- int iNextRply; /* Index to next reply string */
- int iLastRply;
- HFILE hDataFile=HFILE_ERROR; /* File handle for open data file */
- LONG lStartTime; /* Start time for data transfer */
- LONG lByteCount;
- char szLogFile[] = "ac_ftp.log"; /* Ftp command and reply log file */
- HFILE hLogFile=HFILE_ERROR;
- /*--------------------------------------------------------------------
- * Function: WinMain()
- *
- * Description:
- * initialize WinSock and open main dialog box
- *
- */
- int WINAPI WinMain
- (HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpszCmdLine,
- int nCmdShow)
- {
- MSG msg;
- int nRet;
- lpszCmdLine = lpszCmdLine; /* avoid warning */
- hPrevInstance = hPrevInstance;
- nCmdShow = nCmdShow;
- hInst = hInstance; /* save instance handle */
- /*-------------initialize WinSock DLL------------*/
- nRet = WSAStartup(WSA_VERSION, &stWSAData);
- /* WSAStartup() returns error value if failed (0 on success) */
- if (nRet != 0) {
- WSAperror(nRet, "WSAStartup()", hInst);
- /* No sense continuing if we can't use WinSock */
- } else {
- DialogBox (hInst, MAKEINTRESOURCE(AC_FTP), NULL, Dlg_Main);
- /*---------------release WinSock DLL--------------*/
- nRet = WSACleanup();
- if (nRet == SOCKET_ERROR)
- WSAperror(WSAGetLastError(), "WSACleanup()", hInst);
- }
- return msg.wParam;
- } /* end WinMain() */
- /*--------------------------------------------------------------------
- * Function: Dlg_Main()
- *
- * Description: Do all the message processing for the main dialog box
- */
- BOOL CALLBACK Dlg_Main
- (HWND hDlg,
- UINT msg,
- UINT wParam,
- LPARAM lParam)
- {
- int nAddrSize = sizeof(SOCKADDR);
- WORD WSAEvent, WSAErr;
- SOCKET hSock;
- BOOL bOk, bRet = FALSE;
- int nRet;
- LONG lRet;
- switch (msg) {
- case WSA_ASYNC+1:
- /*-------------------------------------------------
- * Data socket async notification message handlers
- *-------------------------------------------------*/
- hSock = (SOCKET)wParam; /* socket */
- WSAEvent = WSAGETSELECTEVENT (lParam); /* extract event */
- WSAErr = WSAGETSELECTERROR (lParam); /* extract error */
- /* if error, display to user (listen socket should not have
- * an error, but some WinSocks incorrectly post it) */
- if ((WSAErr) && (hSock == hDataSock)) {
- int i,j;
- for (i=0, j=WSAEvent; j; i++, j>>=1); /* convert bit to index */
- WSAperror(WSAErr,aszWSAEvent[i], hInst);
- /* fall-through to call reenabling function for this event */
- }
- switch (WSAEvent) {
- case FD_READ:
- if (bIOBeep)
- MessageBeep(0xFFFF);
- if (hDataSock != INVALID_SOCKET) {
- /* Receive file data or directory list */
- RecvData(hDataSock, hDataFile, achInBuf, INPUT_SIZE);
- }
- break;
- case FD_ACCEPT:
- if (hLstnSock != INVALID_SOCKET) {
- /* Accept the incoming data connection request */
- hDataSock =
- AcceptDataConn(hLstnSock, &stDRmtName);
- nAppState |= DATACONNECTED;
- /* Close the Listening Socket */
- closesocket(hLstnSock);
- hLstnSock = INVALID_SOCKET;
- lStartTime = GetTickCount();
- /* Data transfer should begin with FD_WRITE or FD_READ. We
- * fall through to jumpstart sends since FD_WRITE is not
- * always implemented correctly */
- }
- case FD_WRITE:
- /* Send file data */
- if (astFtpCmd[0].nFtpCmd == STOR) {
- lRet = SendData(&hDataSock, hDataFile, MTU_SIZE);
- }
- break;
- case FD_CLOSE: /* Data connection closed */
- if (hSock == hDataSock) {
- /* Read any remaining data into buffer and close connection */
- CloseFtpConn(&hDataSock,
- (astFtpCmd[0].nFtpCmd != STOR) ? achInBuf : (LPSTR)0,
- INPUT_SIZE, hDlg);
- EndData ();
- }
- break;
- default:
- break;
- } /* end switch(WSAEvent) */
- break;
- case WSA_ASYNC:
- /*-----------------------------------------------------
- * Control socket async notification message handlers
- *-----------------------------------------------------*/
- WSAEvent = WSAGETSELECTEVENT (lParam); /* extract event */
- WSAErr = WSAGETSELECTERROR (lParam); /* extract error */
- if (WSAErr) { /* if error, display to user */
- int i,j;
- for (i=0, j=WSAEvent; j; i++, j>>=1); /* convert bit to index */
- WSAperror(WSAErr,aszWSAEvent[i], hInst);
- /* fall-through to call reenabling function for this event */
- }
- hSock = (SOCKET)wParam;
- switch (WSAEvent) {
- case FD_READ:
- if (!iNextRply) {
- /* Receive reply from server */
- iLastRply = RecvFtpRply(hCtrlSock, szFtpRply, RPLY_SIZE);
- }
- if (iLastRply && (iLastRply != SOCKET_ERROR)) {
- /* Display the reply Message */
- GetDlgItemText (hWinMain, IDC_REPLY, achRplyBuf,
- RPLY_SIZE-strlen(szFtpRply));
- wsprintf (achTempBuf, "%s%s", szFtpRply, achRplyBuf);
- SetDlgItemText (hWinMain, IDC_REPLY, achTempBuf);
- /* Save index to next reply (if there is one) */
- nRet = strlen(szFtpRply);
- if (iLastRply > nRet+2) {
- iNextRply = nRet+3;
- /* Adjust if reply only had LF (no CR) */
- if (szFtpRply[nRet+2])
- iNextRply = nRet+2;
- }
- }
- /* Figure out what to do with reply based on last command */
- ProcessFtpRply (szFtpRply, RPLY_SIZE);
- break;
- case FD_WRITE:
- /* Send command to server */
- if (astFtpCmd[1].nFtpCmd)
- SendFtpCmd();
- break;
- case FD_CONNECT:
- /* Control connected at TCP level */
- nAppState = CTRLCONNECTED;
- wsprintf(achTempBuf, "Server: %s", szHost);
- SetDlgItemText (hDlg, IDC_SERVER, achTempBuf);
- SetDlgItemText (hDlg, IDC_STATUS, "Status: connected");
- break;
- case FD_CLOSE:
- if (nAppState & CTRLCONNECTED) {
- nAppState = NOT_CONNECTED; /* Reset app state */
- AbortFtpCmd();
- if (hCtrlSock != INVALID_SOCKET) /* Close control socket */
- CloseFtpConn(&hCtrlSock, (PSTR)0, 0, hDlg);
- SetDlgItemText (hDlg, IDC_SERVER, "Server: none");
- SetDlgItemText (hDlg, IDC_STATUS, "Status: not connected");
- }
- break;
- default:
- break;
- } /* end switch(WSAEvent) */
- break;
- case WM_COMMAND:
- switch (wParam) {
- case IDC_CONNECT:
- /* If we already have a socket open, tell user to close it */
- if (nAppState & CTRLCONNECTED) {
- MessageBox (hDlg,"Close the active connection first",
- "Can't Connect", MB_OK | MB_ICONASTERISK);
- } else {
- /* Prompt user for server and login user information */
- bOk = DialogBox (hInst, MAKEINTRESOURCE(IDD_SERVER),
- hDlg, Dlg_Login);
- if (bOk) {
- /* Check the destination address and resolve if necessary */
- stCRmtName.sin_addr.s_addr = GetAddr(szHost);
- if (stCRmtName.sin_addr.s_addr == INADDR_ANY) {
- /* Tell user to enter a host */
- wsprintf(achTempBuf,
- "Sorry, server %s is invalid. Try again", szHost);
- MessageBox (hDlg, achTempBuf,
- "Can't connect!", MB_OK | MB_ICONASTERISK);
- } else {
- /* Initiate connect attempt to server */
- hCtrlSock =
- InitCtrlConn(&stCRmtName, hDlg, WSA_ASYNC);
- }
- }
- }
- break;
- case IDC_CLOSE:
- if (nAppState & CTRLCONNECTED) {
- /* Set application state so nothing else is processed */
- nAppState = NOT_CONNECTED;
- /* If we're listening, stop now */
- if (hLstnSock != INVALID_SOCKET) {
- closesocket(hLstnSock);
- hLstnSock = INVALID_SOCKET;
- }
- /* If there is a data connection, then abort it */
- if (hDataSock != INVALID_SOCKET)
- QueueFtpCmd (ABOR, 0);
- /* Quit the control connection */
- if (hCtrlSock != INVALID_SOCKET)
- QueueFtpCmd (QUIT, 0);
- SetDlgItemText (hDlg, IDC_SERVER, "Server: none");
- SetDlgItemText (hDlg, IDC_STATUS, "Status: not connected");
- }
- break;
- case IDC_RETR:
- /* Prompt for name of remote file to get */
- if (nAppState & CTRLCONNECTED) {
- bOk = DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_FILENAME),
- hDlg, Dlg_File, (LONG)(LPSTR)szDataFile);
- if (bOk && szDataFile[0]) {
- if (!bToNul) {
- /* If user provided a filename open same name here for write.
- * Truncate the filename to 8 chars plus 3, if necessary */
- hDataFile = CreateLclFile (szDataFile);
- }
- if (hDataFile != HFILE_ERROR || bToNul) {
- /* Tell the Server where to connect back to us */
- hLstnSock =
- InitDataConn(&stDLclName, hDlg, WSA_ASYNC+1);
- if (hLstnSock != INVALID_SOCKET) {
- /* Queue PORT, TYPE and RETR cmds */
- if (QueueFtpCmd(PORT, 0)) {
- if (QueueFtpCmd (TYPE, "I"))
- QueueFtpCmd(RETR, szDataFile);
- }
- }
- }
- }
- } else
- not_connected();
- break;
- case IDC_STOR:
- /* Prompt for name of local file to send */
- if (nAppState & CTRLCONNECTED) {
- bOk = DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_FILENAME),
- hDlg, Dlg_File, (LONG)(LPSTR)szDataFile);
- if (bOk && szDataFile[0]) {
- if (!bFromNul) {
- /* If user provided filename, try to open same name locally */
- hDataFile = _lopen(szDataFile, 0);
- if (hDataFile == HFILE_ERROR) {
- wsprintf(achTempBuf, "Unable to open file: %s", szDataFile);
- MessageBox (hWinMain, (LPSTR)achTempBuf,"File Error",
- MB_OK | MB_ICONASTERISK);
- }
- }
- if (hDataFile != HFILE_ERROR || bFromNul) {
- /* Tell the Server where to connect back to us */
- hLstnSock =
- InitDataConn(&stDLclName, hDlg, WSA_ASYNC+1);
- if (hLstnSock != INVALID_SOCKET) {
- /* Queue PORT, TYPE and STOR cmds */
- if (QueueFtpCmd (PORT, 0)) {
- if (QueueFtpCmd (TYPE, "I"))
- QueueFtpCmd (STOR, szDataFile);
- }
- }
- }
- }
- } else
- not_connected();
- break;
- case IDC_ABOR:
- if (hCtrlSock != INVALID_SOCKET)
- /* Abort the pending ftp command */
- QueueFtpCmd (ABOR, 0);
- break;
- case IDC_LCWD:
- /* Prompt for directory name, and move to it on local system. */
- bOk = DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_FILENAME),
- hDlg, Dlg_File, (LONG)(LPSTR)szDataFile);
- if (bOk && szDataFile[0]) {
- if (!(_chdir (szDataFile))) {
- getcwd (szDataFile, MAXFILENAME-1);
- SetDlgItemText (hDlg, IDC_LPWD, szDataFile);
- }
- }
- break;
- case IDC_LDEL:
- /* Prompt for filename, and delete it from local system */
- bOk = DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_FILENAME),
- hDlg, Dlg_File, (LONG)(LPSTR)szDataFile);
- if (bOk && szDataFile[0]) {
- /* If user provided filename, then delete it */
- remove (szDataFile);
- }
- break;
- case IDC_LDIR:
- /* Get local file directory, and display in notepad */
- if (GetLclDir(szTempFile)) {
- wsprintf (achTempBuf, "notepad %s", szTempFile);
- WinExec (achTempBuf, SW_SHOW);
- }
- break;
- case IDC_RCWD:
- /* Prompt for directory name, and move to it on remote system. */
- if (nAppState & CTRLCONNECTED) {
- szDataFile[0] = 0;
- bOk = DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_FILENAME),
- hDlg, Dlg_File, (LONG)(LPSTR)szDataFile);
- if (bOk && szDataFile[0]) {
- QueueFtpCmd (CWD, szDataFile);
- }
- } else
- not_connected();
- break;
- case IDC_RDEL:
- /* Prompt for filename, and delete it from remote system */
- if (nAppState & CTRLCONNECTED) {
- szDataFile[0] = 0;
- bOk = DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_FILENAME),
- hDlg, Dlg_File, (LONG)(LPSTR)szDataFile);
- if (bOk && szDataFile[0]) {
- /* If user provided a filename, send command to delete it */
- QueueFtpCmd (DELE, szDataFile);
- }
- } else
- not_connected();
- break;
- case IDC_RDIR:
- /* Get remote file directory, and display in notepad file */
- if (nAppState & CTRLCONNECTED) {
- hDataFile = CreateLclFile (szTempFile);
- if (hDataFile != HFILE_ERROR) {
- /* Prepare to receive the incoming connection from server */
- hLstnSock =
- InitDataConn(&stDLclName, hDlg, WSA_ASYNC+1);
- if (hLstnSock != INVALID_SOCKET) {
- if (QueueFtpCmd (PORT, 0)) /* Queue PORT, TYPE and LIST cmds */
- if (QueueFtpCmd (TYPE, "A"))
- QueueFtpCmd (LIST, 0);
- }
- }
- } else
- not_connected();
- break;
- case IDC_OPTIONS:
- DialogBox (hInst, MAKEINTRESOURCE(IDD_OPTIONS),
- hDlg, Dlg_Options);
- break;
- case IDABOUT:
- DialogBox (hInst, MAKEINTRESOURCE(IDD_ABOUT), hDlg, Dlg_About);
- break;
- case WM_DESTROY:
- case IDC_EXIT:
- SendMessage (hDlg, WM_COMMAND, IDC_CLOSE, 0L);
- if (hLogFile != HFILE_ERROR)
- _lclose(hLogFile);
- EndDialog(hDlg, msg);
- bRet = TRUE;
- break;
- default:
- break;
- } /* end case WM_COMMAND: */
- break;
- case WM_INITDIALOG:
- hWinMain = hDlg; /* save our main window handle */
- /* Assign an icon to dialog box */
- #ifdef WIN32
- SetClassLong (hDlg, GCL_HICON, (LONG)
- LoadIcon((HINSTANCE) GetWindowLong(hDlg, GWL_HINSTANCE),
- __TEXT("AC_FTP")));
- #else
- SetClassWord(hDlg,GCW_HICON,(WORD)LoadIcon(hInst,MAKEINTRESOURCE(AC_FTP)));
- #endif
- /* Initialize FTP command structure array */
- memset (astFtpCmd, 0, (sizeof(struct stFtpCmd))*MAX_CMDS);
- /* Display current working directory */
- getcwd (szDataFile, MAXFILENAME-1);
- SetDlgItemText (hDlg, IDC_LPWD, szDataFile);
- /* Open logfile, if logging enabled */
- if (bLogFile) {
- hLogFile = _lcreat (szLogFile, 0);
- if (hLogFile == HFILE_ERROR) {
- MessageBox (hWinMain, "Unable to open logfile",
- "File Error", MB_OK | MB_ICONASTERISK);
- bLogFile = FALSE;
- }
- }
- /* Center dialog box */
- CenterWnd (hDlg, NULL, TRUE);
- break;
- default:
- break;
- } /* end switch (msg) */
- return (bRet);
- } /* end Dlg_Main() */
- /*---------------------------------------------------------------------
- * Function: Dlg_Login
- *
- * Description: Prompt for destination host, user name, and password
- */
- BOOL CALLBACK Dlg_Login (
- HWND hDlg,
- UINT msg,
- UINT wParam,
- LPARAM lParam)
- {
- BOOL bRet = FALSE;
- lParam = lParam; /* avoid warning */
- switch (msg) {
- case WM_INITDIALOG:
- SetDlgItemText (hDlg, IDC_SERVER, szHost);
- SetDlgItemText (hDlg, IDC_USERNAME, szUser);
- SetDlgItemText (hDlg, IDC_PASSWORD, szPWrd);
- CenterWnd (hDlg, hWinMain, TRUE);
- break;
- case WM_COMMAND:
- switch (wParam) {
- case IDOK:
- GetDlgItemText (hDlg, IDC_SERVER, szHost, MAXHOSTNAME);
- GetDlgItemText (hDlg, IDC_USERNAME, szUser, MAXUSERNAME);
- GetDlgItemText (hDlg, IDC_PASSWORD, szPWrd, MAXPASSWORD);
- EndDialog (hDlg, TRUE);
- bRet = TRUE;
- break;
- case IDCANCEL:
- EndDialog (hDlg, FALSE);
- bRet = FALSE;
- break;
- default:
- break;
- }
- }
- return(bRet);
- } /* end Dlg_Login */
- /*---------------------------------------------------------------------
- * Function: Dlg_Options()
- *
- * Description: Allow user to change a number of run-time parameters
- * that affect the operation, to allow experimentation and debugging.
- */
- BOOL CALLBACK Dlg_Options (
- HWND hDlg,
- UINT msg,
- UINT wParam,
- LPARAM lParam)
- {
- BOOL bRet = FALSE;
- lParam = lParam; /* avoid warning */
- switch (msg) {
- case WM_INITDIALOG:
- CheckDlgButton (hDlg, IDC_TO_NUL, bToNul);
- CheckDlgButton (hDlg, IDC_FROM_NUL,bFromNul);
- CheckDlgButton (hDlg, IDC_LOGFILE, bLogFile);
- CheckDlgButton (hDlg, IDC_IOBEEP, bIOBeep);
- CheckDlgButton (hDlg, IDC_REASYNC, bReAsync);
- CenterWnd (hDlg, hWinMain, TRUE);
- break;
- case WM_COMMAND:
- switch (wParam) {
- case IDC_TO_NUL:
- bToNul = !bToNul;
- break;
- case IDC_FROM_NUL:
- bFromNul = !bFromNul;
- break;
- case IDC_LOGFILE:
- bLogFile = !bLogFile;
- break;
- case IDC_IOBEEP:
- bIOBeep = !bIOBeep;
- break;
- case IDC_REASYNC:
- bReAsync = !bReAsync;
- break;
- case IDOK:
- if (bLogFile && hLogFile == HFILE_ERROR) {
- bLogFile = FALSE;
- } else if (!bLogFile && hLogFile != HFILE_ERROR) {
- _lclose(hLogFile);
- hLogFile = HFILE_ERROR;
- } else if (bLogFile && hLogFile == HFILE_ERROR) {
- hLogFile = _lcreat (szLogFile, 0);
- if (hLogFile == HFILE_ERROR) {
- MessageBox (hWinMain, "Unable to open logfile",
- "File Error", MB_OK | MB_ICONASTERISK);
- bLogFile = FALSE;
- }
- }
- EndDialog (hDlg, TRUE);
- bRet = TRUE;
- break;
- }
- }
- return(bRet);
- } /* end Dlg_Options() */
- /*---------------------------------------------------------------
- * Function: not_connected()
- *
- * Description: tell the user that the client needs a connection.
- */
- void not_connected(void) {
- MessageBox (hWinMain, "You need to connect to an FTP Server",
- "Not Connected", MB_OK | MB_ICONASTERISK);
- }
- /*--------------------------------------------------------------
- * Function: CloseFtpConn()
- *
- * Description: Close the connection gracefully and robustly,
- * reading all remaining data into buffer before closure.
- */
- int CloseFtpConn(SOCKET *hSock, LPSTR achInBuf, int len, HWND hWnd)
- {
- char achDiscard[BUF_SIZE];
- int nRet=0;
- if (*hSock != INVALID_SOCKET) {
- /* disable asynchronous notification if window handle provided */
- if (hWnd) {
- nRet = WSAAsyncSelect(*hSock, hWnd, 0, 0);
- if (nRet == SOCKET_ERROR)
- WSAperror (WSAGetLastError(), "CloseFtpConn() WSAAsyncSelect()", hInst);
- }
- /* Half-close the connection to close neatly */
- nRet = shutdown (*hSock, 1);
- if (nRet == SOCKET_ERROR) {
- WSAperror (WSAGetLastError(), "shutdown()", hInst);
- } else {
- /* Read and discard remaining data (until EOF or error) */
- nRet = 1;
- while (nRet && (nRet != SOCKET_ERROR)) {
- if (achInBuf)
- nRet = RecvData(*hSock, hDataFile, achInBuf, len);
- else
- nRet = recv (*hSock, (LPSTR)achDiscard, BUF_SIZE, 0);
- }
- /* close the socket, and ignore any error
- * (since we can't do much about them anyway */
- closesocket (*hSock);
- }
- *hSock = INVALID_SOCKET; /* we always invalidate socket */
- }
- return (nRet);
- } /* end CloseFtpConn() */