Click here to Skip to main content
11,584,288 members (62,040 online)
Click here to Skip to main content
Add your own
alternative version

A Complete FTP Server

, 30 May 2005 378.5K 23.4K 161
This article presents a fully functional implementation of a FTP server.
// stdafx.cpp : source file that includes just the standard includes
//	FTPServer.pch will be the pre-compiled header
//	stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"


/********************************************************************/
/*																	*/
/* Function name : BrowseForFolder									*/		
/* Description   : Browse for folder using SHBrowseForFolder.		*/
/*																	*/
/********************************************************************/
CString BrowseForFolder(HWND hWnd, LPCSTR lpszTitle, UINT nFlags)
{
	// We're going to use the shell to display a 
	// "Choose Directory" dialog box for the user.
	CString strResult = "";
  
	LPMALLOC lpMalloc;
	
	if (::SHGetMalloc(&lpMalloc) != NOERROR)
	{
		// failed to get allocator  
		return strResult; 
	}

	char szBuffer[_MAX_PATH];
	char szDisplayName[_MAX_PATH];

	BROWSEINFO browseInfo;
	browseInfo.hwndOwner = hWnd;
	// set root at Desktop
	browseInfo.pidlRoot = NULL; 
	browseInfo.pszDisplayName = szDisplayName;
	browseInfo.lpszTitle = lpszTitle;
	browseInfo.ulFlags = nFlags;
	browseInfo.lpfn = NULL;
	browseInfo.lParam = 0;
	
	LPITEMIDLIST lpItemIDList;

	if ((lpItemIDList = ::SHBrowseForFolder(&browseInfo)) != NULL)
	{
		// Get the path of the selected folder from the item ID list.
		if (::SHGetPathFromIDList(lpItemIDList, szBuffer))
		{
			// At this point, szBuffer contains the path the user chose.
			if (szBuffer[0] == '\0')
			{
				// SHGetPathFromIDList failed, or SHBrowseForFolder failed.
				AfxMessageBox("Failed to get directory", MB_ICONSTOP|MB_OK);
				return strResult;
			}
     
			// We have a path in szBuffer!
			strResult = szBuffer;
			return strResult;
		}
		else
		{
			// The thing referred to by lpItemIDList 
			// might not have been a file system object.
			// For whatever reason, SHGetPathFromIDList didn't work!
			AfxMessageBox("Failed to get directory", MB_ICONSTOP|MB_OK);
			return strResult; // strResult is empty 
		}
		lpMalloc->Free(lpItemIDList);
		lpMalloc->Release();      
	}
	return strResult;
}


void DoEvents()
{
	MSG msg;

	// window message         
	while (PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))         
	{            
		TranslateMessage(&msg);            
		DispatchMessage(&msg);         
	}      
}


/********************************************************************/
/*																	*/
/* Function name : GetAppDir										*/		
/* Description   : Get application directory.						*/
/*																	*/
/********************************************************************/
void GetAppDir(CString& strAppDir)
{
	TCHAR szFullPath[MAX_PATH];
	TCHAR szDir[_MAX_DIR];
	TCHAR szDrive[_MAX_DRIVE];

	// Get application's full path.
	::GetModuleFileName(NULL, szFullPath, MAX_PATH);

	// Break full path into seperate components.
	_splitpath(szFullPath, szDrive, szDir, NULL, NULL);

	// Store application's drive and path
	strAppDir.Format(_T("%s%s"), szDrive, szDir);
}


PFNSHGETFOLDERPATHA GetFuncPtr_SHGetFolderPathA()
{
	static HMODULE hMod = NULL;
	PFNSHGETFOLDERPATHA pSHGetFolderPath = NULL;

	// Load SHFolder.dll only once
	if (!hMod)
		hMod = LoadLibrary("SHFolder.dll");

	// Obtain a pointer to the SHGetFolderPathA function
	if (hMod)
		pSHGetFolderPath = (PFNSHGETFOLDERPATHA)GetProcAddress(hMod, "SHGetFolderPathA");

	return pSHGetFolderPath;
} 


/********************************************************************/
/*																	*/
/* Function name : CreateStartMenuShortcut							*/		
/* Description   : Create a shortcut using the IShellLink interface.*/
/*																	*/
/********************************************************************/
HRESULT CreateStartMenuShortcut(LPSTR lpszShortcutFile, LPSTR lpszDescription, LPTSTR lpszRelativeFolder)
{
	HRESULT hr;
	PFNSHGETFOLDERPATHA pSHGetFolderPath = NULL;
	TCHAR lpszLink[MAX_PATH];
	BOOL bFound = FALSE;

	pSHGetFolderPath = GetFuncPtr_SHGetFolderPathA();

	// Find the current user's Start Menu Programs folder
	if (pSHGetFolderPath)
	{
		if (lpszRelativeFolder)
			bFound = SUCCEEDED(pSHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, 0, lpszLink));
		else
			bFound = SUCCEEDED(pSHGetFolderPath(NULL, CSIDL_STARTUP, NULL, 0, lpszLink));
	}
	if (bFound)
	{
		// Proceed to create the shortcut
		IShellLink *pIShellLink = NULL;
		IPersistFile *ppf = NULL;
		WCHAR pLinkUnicode[MAX_PATH];

		CoInitialize(NULL);

		// Get a pointer to the IShellLink interface.
		hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                            IID_IShellLink, (void **)&pIShellLink);

		if (SUCCEEDED(hr))
		{
			// Get a pointer to IPersistFile interface for saving shortcut
			hr = pIShellLink->QueryInterface(IID_IPersistFile, (void **)&ppf);

			if (SUCCEEDED(hr))
			{   
	            hr = pIShellLink->SetPath(lpszShortcutFile);
		        hr = pIShellLink->SetDescription(lpszDescription);

				if (SUCCEEDED(hr))
				{
					// Add the target folder to the Start Menu Programs path
					lstrcat(lpszLink, "\\");
					if (lpszRelativeFolder)
					{
						lstrcat(lpszLink, lpszRelativeFolder);
						lstrcat(lpszLink, "\\");
					}
	
					// Create the directory if it does not exist
					CreateDirectory(lpszLink,NULL);

					// Add the file name for the shortcut
					lstrcat(lpszLink, lpszDescription);
					lstrcat(lpszLink, ".lnk");

					// Convert string to Unicode, and call IPersistFile::Save()
					MultiByteToWideChar(CP_ACP, 0, lpszLink, -1, pLinkUnicode, MAX_PATH);
					hr = ppf->Save(pLinkUnicode, TRUE);
				}
				ppf->Release();
			}
			pIShellLink->Release();
		}
		CoUninitialize();
	}
	return hr;
} 


/********************************************************************/
/*																	*/
/* Function name : RemoveStartMenuShortcut							*/		
/* Description   : Create a shortcut using the IShellLink interface.*/
/*																	*/
/********************************************************************/
void RemoveStartMenuShortcut(LPSTR lpszDescription, LPTSTR lpszRelativeFolder)
{
	PFNSHGETFOLDERPATHA pSHGetFolderPath = NULL;
	TCHAR lpszLink[MAX_PATH];
	BOOL bFound = FALSE;

	pSHGetFolderPath = GetFuncPtr_SHGetFolderPathA();

	// Find the current user's Start Menu Programs folder
	if (pSHGetFolderPath)
	{
		if (lpszRelativeFolder)
			bFound = SUCCEEDED(pSHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, 0, lpszLink));
		else
			bFound = SUCCEEDED(pSHGetFolderPath(NULL, CSIDL_STARTUP, NULL, 0, lpszLink));
	}
	if (bFound)
	{
		// Add the target folder to the Start Menu Programs path
		lstrcat(lpszLink, "\\");
		if (lpszRelativeFolder)
		{
			lstrcat(lpszLink, lpszRelativeFolder);
			lstrcat(lpszLink, "\\");
		}

		// Add the file name for the shortcut
		lstrcat(lpszLink, lpszDescription);
		lstrcat(lpszLink, ".lnk");

		DeleteFile(lpszLink);
	}
} 


/********************************************************************/
/*																	*/
/* Function name : GetShortcutTarget								*/		
/* Description   : Get target filename from shortcut.				*/
/*																	*/
/********************************************************************/
CString GetShortcutTarget(LPCTSTR lpszFilename)
{
	CoInitialize(0);
	
	CString strResult;
	HRESULT hResult;
	IShellLink *psl;
	char szPath[MAX_PATH];
	WIN32_FIND_DATA findData;

	// Get a pointer to the IShellLink interface.
	hResult = CoCreateInstance (CLSID_ShellLink, NULL,	CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
	if (SUCCEEDED(hResult))
	{
		IPersistFile *ppf;

		// Get a pointer to the IPersistFile interface.
		hResult = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);

		if (SUCCEEDED(hResult))
		{
			WORD wsz [MAX_PATH]; // buffer for Unicode string

			// Ensure that the string consists of Unicode characters.
			MultiByteToWideChar (CP_ACP, 0, lpszFilename, -1, wsz, MAX_PATH);
			
			// Load the shortcut.
			hResult = ppf->Load (wsz, STGM_READ);
			
			if (SUCCEEDED (hResult))
			{
				// Resolve the shortcut.
				hResult = psl->Resolve (0, SLR_ANY_MATCH|SLR_NO_UI);
				if (SUCCEEDED (hResult))
				{
					lstrcpy (szPath, lpszFilename);
					// Get the path to the shortcut target.
					hResult = psl->GetPath(szPath, MAX_PATH, (WIN32_FIND_DATA *)&findData, 0); 
					strResult = szPath;
				}
			}
			// Release the pointer to IPersistFile.
			ppf->Release ();
		}
		// Release the pointer to IShellLink.
		psl->Release ();
	}
	CoUninitialize();
	
	if (SUCCEEDED(hResult))
		return strResult;
	else
		return "";
}


// Pump messages while waiting for event
BOOL WaitWithMessageLoop(HANDLE hEvent, int nTimeout)
{   
	DWORD dwRet;

	while (1)
	{
		// wait for event or message, if it's a message, process it and return to waiting state
		dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, nTimeout, QS_ALLINPUT);
		if (dwRet == WAIT_OBJECT_0)
		{
			TRACE0("WaitWithMessageLoop() event triggered.\n");
			return TRUE;      
		}   
		else
		if (dwRet == WAIT_OBJECT_0 + 1)
		{
			// process window messages
			AfxGetApp()->PumpMessage();
		}  
		else
		if (dwRet == WAIT_TIMEOUT)
		{
			// timed out !
			return FALSE;
		}
		else
		{
			// WAIT_ABANDONED_0 ...
			return TRUE;
		}
	}
}



/********************************************************************/
/*																	*/
/* Function name : AutoSizeColumns									*/
/* Description   : 													*/
/*																	*/
/********************************************************************/
void AutoSizeColumns(CListCtrl *pListCtrl) 
{
	// Call this after your the control is filled
	pListCtrl->SetRedraw(FALSE);
	int mincol = 0;
    int maxcol = pListCtrl->GetHeaderCtrl()->GetItemCount()-1;
    for (int col = mincol; col <= maxcol; col++) 
	{
		pListCtrl->SetColumnWidth(col, LVSCW_AUTOSIZE);
        int wc1 = pListCtrl->GetColumnWidth(col);
        pListCtrl->SetColumnWidth(col, LVSCW_AUTOSIZE_USEHEADER);
        int wc2 = pListCtrl->GetColumnWidth(col);
        // 10 is minumim column width
		int wc = max(10, max(wc1,wc2));
        pListCtrl->SetColumnWidth(col,wc);
     }
     pListCtrl->SetRedraw(TRUE);
}


/********************************************************************/
/*																	*/
/* Function name : MakeSureDirectoryPathExists						*/
/* Description   : This function creates all the directories in		*/
/*				   the specified DirPath, beginning with the root.	*/
/*				   This is a clone a Microsoft function with the	*/
/*			       same name.										*/
/*																	*/
/********************************************************************/
BOOL MakeSureDirectoryPathExists(LPCTSTR lpszDirPath)
{
	CString strDirPath = lpszDirPath;
	
	int nPos = 0;
   
	while((nPos = strDirPath.Find('\\', nPos+1)) != -1) 
	{
		CreateDirectory(strDirPath.Left(nPos), NULL);
	}
	return CreateDirectory(strDirPath, NULL);
}


/********************************************************************/
/*																	*/
/* Function name : FileExists										*/
/* Description   : Check if file or directory exists				*/
/*																	*/
/********************************************************************/
BOOL FileExists(LPCTSTR lpszFileName, BOOL bIsDirCheck)
{
	// A quick'n'easy way to see if a file exists.
	DWORD dwAttributes = GetFileAttributes(lpszFileName);
    if (dwAttributes == 0xFFFFFFFF)
        return FALSE;

	if ((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
	{
		if (bIsDirCheck)
			return TRUE;
		else
			return FALSE;
	}
	else
	{
		if (!bIsDirCheck)
			return TRUE;
		else
			return FALSE;
	}
}


/********************************************************************/
/*																	*/
/* Function name : GetFileDate										*/
/* Description   : return file date in unix style					*/
/*																	*/
/********************************************************************/
CString GetFileDate(CFileFind &find)
{
	CString strResult;

	CTime time = CTime::GetCurrentTime();

	find.GetLastWriteTime(time);

	CTimeSpan timeSpan = CTime::GetCurrentTime() - time;

	if (timeSpan.GetDays() > 356)
	{
		strResult = time.Format(" %b %d %Y ");
	}
	else
	{
		strResult.Format(" %s %02d:%02d ", time.Format("%b %d"), time.GetHour(), time.GetMinute());
	}
	return strResult;
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Pablo van der Meer
Web Developer
Netherlands Netherlands
No Biography provided

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150603.1 | Last Updated 30 May 2005
Article Copyright 2002 by Pablo van der Meer
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid