www.pudn.com > warsrc.rar > NTSecurityExt.cpp


// NTSecurityExt.cpp : Defines the initialization routines for the DLL. 
// 
 
#include "stdafx.h" 
#include  
#include  // Unicode API 
#include  // Lan manager API 
#include "FTPDaemonCore.h" 
#include "NTSecurityExt.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
 
static AFX_EXTENSION_MODULE NTSecurityExtDLL = { NULL, NULL }; 
 
int CallOnPreFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnPostFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnGetSecurityDescriptor(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnConnect(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnReceive(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnSend(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnCommand(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnClose(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnSendCmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnSITECmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnIdle(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnVerifyIPAddress(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnVerifyUploadedFile(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnVerifyTransferRequest(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
int CallOnSocketIsDestroyed(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam); 
 
//////////////////////////////////////// 
// ADDED: This is required for plugin's 
static CNTSecExt *pMe; 
 
extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) 
{ 
	if (dwReason == DLL_PROCESS_ATTACH) 
	{ 
		TRACE0("NTSECURITYEXT.DLL Initializing!\n"); 
		 
		// Extension DLL one-time initialization 
		AfxInitExtensionModule(NTSecurityExtDLL, hInstance); 
 
		// Insert this DLL into the resource chain 
		new CDynLinkLibrary(NTSecurityExtDLL); 
 
		//////////////////////////////////////// 
		// ADDED: This is required for plugin's 
		// Create, Register and set up the dll 
		if (!IsNT()) 
		{ 
			CLog *pLog = CLog::GetLog(); 
			if (pLog) 
				pLog->LogMsg(LOGF_ERROR,"CNTSecExt.dll can only run on NT systems."); 
			return 0; // This module can only run on NT systems 
		} 
 
		pMe = new CNTSecExt; 
		if (pMe->Register("NTSecurityExt") != 0) 
			return 0; // Failure 
	} 
	else if (dwReason == DLL_PROCESS_DETACH) 
	{ 
		//////////////////////////////////////// 
		// ADDED: This is required for plugin's 
		if (pMe) 
			delete pMe; 
 
		TRACE0("NTSECURITYEXT.DLL Terminating!\n"); 
	} 
	return 1;   // ok 
} 
 
// Initialize the extended COptions variables 
void CNTSecExt::InitializeCOptions() 
{ 
	DeclOpt("NT User database", m_SystemName, "", 1, DATATYPE_CSTRING); 
	DeclOpt("Default FTP Access", m_DefaultFTPAccess, TRUE, 2, DATATYPE_BOOL); 
	DeclOpt("Give NT Admins Admin", m_GiveAdminsAdmin, TRUE, 3, DATATYPE_BOOL); 
} 
 
CNTSecExt::CNTSecExt() 
{ 
} 
 
CNTSecExt::~CNTSecExt() 
{ 
} 
 
// Called when a user tries to log on. 
// What we do here is to check if the user exist in the 
// NT user database, and is member of the NT user group we have  
// reserved for War server users.  
// If the user exist and has login permissions in NT, we 
// create the user in the war user database (provided that it don't  
// already exist), and leave's the processessing to the default 
// implementation. We allow other plugins to process the login 
// reqest 
int CNTSecExt::OnLogin(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	int Rval = CFuncList::OkContinue; 
 
	LogMsg(LOGF_DEBUG, "CNTSecExt::OnLogin(): Called."); 
 
	USER *pUser = (USER *)wParam; 
	LOGINPRMS *pLP = (LOGINPRMS *)lParam; 
 
	ASSERT(AfxIsValidAddress(pUser, sizeof(USER))); 
	ASSERT(AfxIsValidAddress(pLP, sizeof(LOGINPRMS))); 
	ASSERT(AfxIsValidString(pLP->UserID)); 
 
	*pUser = CUsr::FindUser(UT_USER, pLP->UserID); 
	*pUser = CUsr::MapUser(*pUser); 
 
	LPWSTR NTSystemName = NULL; 
	LPWSTR UserName; 
	NET_API_STATUS rCode; 
	USER_INFO_1 *pUserInfo1 = NULL; 
 
	// We use the old Lan Manager API to get extended information. We could 
	// use the new NT 3.51 security interafce, but I don't know how to extract 
	// the home directory from that... 
	// The good news is that we get most of the infromation we need. The bad  
	// news is that we have to rewrite this code when NT 5 arrives... 
 
	// Convert to unicode 
	WORD wSNbuf[64]; 
	WORD wUNbuf[64]; 
 
	if (m_SystemName != "") 
		MultiByteToWideChar( CP_ACP, 0,m_SystemName,-1, NTSystemName = (LPWSTR)wSNbuf, sizeof(wSNbuf) / sizeof(WORD)); 
 
	MultiByteToWideChar( CP_ACP, 0,pLP->UserID,-1, UserName = (LPWSTR)wUNbuf, sizeof(wUNbuf) / sizeof(WORD)); 
 
	rCode = NetUserGetInfo( 
		NTSystemName, 
		UserName, 
		1, 
		(LPBYTE *) &pUserInfo1); 
 
	if (!rCode) 
	{ 
		char HomeDir[MAX_PATH]; 
		WideCharToMultiByte(CP_ACP, 0, pUserInfo1->usri1_home_dir, -1, HomeDir, MAX_PATH, NULL, NULL); 
		 
		// Check login permissions 
		if (pUserInfo1->usri1_flags & (UF_ACCOUNTDISABLE | UF_LOCKOUT)) 
		{ 
			// User has no access 
			LogMsg(LOGF_SECURITY, "OnLogin(%s) - The user's NT account is disabled. Access is denied.",  
				pLP->UserID); 
			Rval = CFuncList::AbortError; 
			goto done; 
		} 
 
		// Get the NT class 
		USER Class = CUsr::FindUser(UT_CLASS,"(NT_Users)"); 
		if (Class == INVALID_USER_VALUE) 
		{ 
			// Create the NT user class! 
			if ((Class = CUsr::AddUser(UT_CLASS,"(NT_Users)", TRUE)) == INVALID_USER_VALUE) 
			{ 
				LogMsg(LOGF_SECURITY, "OnLogin(%s) - Failed to create class (NT_Users).",  
				pLP->UserID); 
				Rval = CFuncList::AbortError; 
				goto done; 
			} 
			CUsr::SetParam(Class,"FTP Access", m_DefaultFTPAccess); 
		} 
 
		if (*pUser == INVALID_USER_VALUE) 
		{ 
			// Create the user. We need a daemon user to store extra info 
			if ((*pUser = CUsr::AddUser(UT_USER, pLP->UserID)) != INVALID_USER_VALUE) 
			{ 
				LogMsg(LOGF_SYSTEM,"OnLogin(%s) - Created NT user entry in daemon user database.", pLP->UserID); 
			} 
			else 
			{ 
				LogMsg(LOGF_WARNINGS, "OnLogin(%s) - The users NT account is OK. Failed to create server user.",  
					pLP->UserID); 
				Rval = CFuncList::AbortError; 
				goto done; 
			} 
 
			CUsr::SetParam(*pUser,"FTP Access", m_DefaultFTPAccess); 
		} 
 
		LogMsg(LOGF_DEBUG,"OnLogin(%s) - Converting account to NT user style.", pLP->UserID); 
 
		CUsr::SetParam(*pUser, "PWmode", PW_NORMAL); 
		if (*HomeDir) 
			CUsr::SetParam(*pUser, "Home", HomeDir); 
		CUsr::SetParam(*pUser,"Class", Class); 
		if (pUserInfo1->usri1_priv == USER_PRIV_ADMIN) 
		{ 
			if (m_GiveAdminsAdmin) 
				CUsr::SetParam(*pUser,"Administrator", TRUE); 
		} 
		else if (CUsr::IsAdmin(*pUser)) 
			CUsr::SetParam(*pUser,"Administrator", FALSE); 
	} 
	else 
	{ 
		switch(rCode) 
		{ 
			case ERROR_ACCESS_DENIED: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned: ERROR_ACCESS_DENIED.", pLP->UserID); break; 
			case NERR_InvalidComputer: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned: NERR_InvalidComputer.", pLP->UserID); break; 
			case NERR_UserNotFound: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned: NERR_UserNotFound.", pLP->UserID); break; 
			default: LogMsg(LOGF_DEBUG,"OnLogin(%s) - NetUserGetInfo() returned unexpected error code: %d. (%s)", pLP->UserID, rCode, GetLastErrorText(rCode)); break; 
		} 
	} 
 
done: 
	if (*pUser != INVALID_USER_VALUE) 
		CUsr::SetParam(*pUser, "NT User", (rCode == 0) && (Rval == CFuncList::OkContinue)); 
 
	// Clean up 
	if (pUserInfo1) 
		NetApiBufferFree(pUserInfo1); 
	return Rval; 
} 
 
int CNTSecExt::OnLogout(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	int Rval = CFuncList::OkContinue; 
 
	LogMsg(LOGF_DEBUG, "CNTSecExt::OnLogout(): Called."); 
	CTextSock *pSock = (CTextSock *)lParam; 
 
	DeleteNTProp(pSock); 
 
	return Rval; 
} 
 
int CNTSecExt::OnPassword(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	int Rval = CFuncList::OkContinue; 
 
	LogMsg(LOGF_DEBUG, "CNTSecExt::OnPassword(): Called."); 
 
	USER *pUser = (USER *)wParam; 
	LOGINPRMS *pLP = (LOGINPRMS *)lParam; 
 
	ASSERT(AfxIsValidAddress(pUser, sizeof(USER))); 
	ASSERT(AfxIsValidAddress(pLP, sizeof(LOGINPRMS))); 
	ASSERT(AfxIsValidString(pLP->UserID)); 
 
	*pUser = CUsr::FindUser(UT_USER, pLP->UserID); 
	*pUser = CUsr::MapUser(*pUser); 
	HANDLE lh; 
 
	// Delete any previous logon handle for this connection 
	DeleteNTProp(pLP->Sock); 
 
	if (CUsr::GetParam(*pUser, "NT User", FALSE)) 
	{ 
		// Try to log the user on in NT 
		char SysName[64]; 
		DWORD len = sizeof(SysName); 
		GetComputerName(SysName, &len); 
		LPTSTR System = (LPTSTR) ((m_SystemName == "") ? SysName : (LPCSTR)m_SystemName); 
 
		if (LogonUser( 
			(LPTSTR)pLP->UserID, 
			System, 
			(LPTSTR)pLP->Password, 
			LOGON32_LOGON_BATCH, 
			LOGON32_PROVIDER_DEFAULT, 
			&lh)) 
		{ 
			// Store the logon handle for later use 
			CNTProperties *pNT = new CNTProperties; 
			pNT->hLogon = lh; 
			pNT->pSock = pLP->Sock; 
			m_NTprp.AddFirst((LPVOID)pNT); 
			Rval = CFuncList::OkAllDone; 
			LogMsg(LOGF_INOUT,"User %s logged on with NT password.", pLP->UserID); 
		} 
		else 
		{ 
			int err = GetLastError(); 
			if (err == ERROR_PRIVILEGE_NOT_HELD) 
			{ 
				char AccessName[128] = SE_TCB_NAME; 
				DWORD dw1, dw2; 
 
				LookupPrivilegeDisplayName(NULL, SE_TCB_NAME, AccessName, &dw1, &dw2); 
 
				LogMsg(LOGF_ERROR,"The user that run the FTP server must have '%s' access.", 
					AccessName); 
			} 
			 
			LogMsg(LOGF_DEBUG,"OnPassword(%s) - NT logon failed. Error: %s",  
				pLP->UserID, GetLastErrorText(err)); 
 
			Rval = CFuncList::AbortError; 
		} 
	} 
 
	return Rval; 
} 
 
// Helper. Delete a NT property based on the connection socket 
void CNTSecExt::DeleteNTProp(CTextSock *pSock) 
{ 
	for(CLinkedListItem *Item = m_NTprp.First(); Item;) 
	{ 
		CLinkedListItem *NextItem = m_NTprp.Next(Item); 
 
		CNTProperties *pNT = (CNTProperties *)m_NTprp.Ptr(Item); 
		if (pNT->pSock == pSock) 
		{ 
			delete pNT; 
			m_NTprp.DeleteItem(Item); 
		} 
 
		Item = NextItem; 
	} 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CNTFTPConn callbacks 
 
int CNTFTPConn::OnPreFSYSAccess(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnPostFSYSAccess(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnGetSecurityDescriptor(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnConnect(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnReceive(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnSend(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnCommand(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnClose(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnSendCmd(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnSITECmd(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnIdle(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnVerifyIPAddress(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnVerifyUploadedFile(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
int CNTFTPConn::OnVerifyTransferRequest(int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
 
// Raw callback support 
 
// Reqired function if sockets extentions are used 
// Creates a new socket derived  
int CallOnSocketIsDestroyed(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	delete (CNTFTPConn *)Origin; // CSocketAPI destructor will delete references 
	return 0; 
} 
 
int CallOnPreFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnPreFSYSAccess(Event, wParam, lParam); 
} 
 
int CallOnPostFSYSAccess(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnPostFSYSAccess(Event, wParam, lParam); 
} 
 
int CallOnGetSecurityDescriptor(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnGetSecurityDescriptor(Event, wParam, lParam); 
} 
 
int CallOnConnect(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnConnect(Event, wParam, lParam); 
} 
 
int CallOnReceive(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnReceive(Event, wParam, lParam); 
} 
 
int CallOnSend(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnSend(Event, wParam, lParam); 
} 
 
int CallOnCommand(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnCommand(Event, wParam, lParam); 
} 
 
int CallOnClose(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnClose(Event, wParam, lParam); 
} 
 
int CallOnSendCmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnSendCmd(Event, wParam, lParam); 
} 
 
int CallOnSITECmd(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnSITECmd(Event, wParam, lParam); 
} 
 
int CallOnIdle(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnIdle(Event, wParam, lParam); 
} 
 
int CallOnVerifyIPAddress(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnVerifyIPAddress(Event, wParam, lParam); 
} 
 
int CallOnVerifyUploadedFile(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnVerifyUploadedFile(Event, wParam, lParam); 
} 
 
int CallOnVerifyTransferRequest(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTFTPConn *)Origin)->OnVerifyTransferRequest(Event, wParam, lParam); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Helper (entry point functions) 
// This is the fuction's the server looks for and calls. These must call our own 
// functions that do the actual work. 
 
int CallOnLogin(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTSecExt *)Origin)->OnLogin(Event, wParam, lParam); 
} 
 
int CallOnLogout(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTSecExt *)Origin)->OnLogout(Event, wParam, lParam); 
} 
 
int CallOnPassword(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTSecExt *)Origin)->OnPassword(Event, wParam, lParam); 
} 
 
// Required function 
int CallApiInitInstance(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTSecExt *)Origin)->ApiInitInstance(Event, wParam, lParam); 
} 
 
// Required function 
int CallApiExitInstance(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return ((CNTSecExt *)Origin)->ApiExitInstance(Event, wParam, lParam); 
} 
 
 
int CallApiNewSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	return 0; 
} 
 
 
int CallOnPreFTPDAccept(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	CFTPDCoreCtrlSock *pSock = (CFTPDCoreCtrlSock *)wParam; 
	CFTPDCoreListenSock *pListenSock = (CFTPDCoreListenSock *)lParam; 
	return 0; 
} 
 
int CallOnPostFTPDAccept(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	CFTPDCoreCtrlSock *pSock = (CFTPDCoreCtrlSock *)wParam; 
	CFTPDCoreListenSock *pListenSock = (CFTPDCoreListenSock *)lParam; 
	return 0; 
} 
 
 
 
void CNTSecExt::LogMsg(int flag, LPCSTR Format, ...) 
{ 
	ASSERT(AfxIsValidAddress(this,sizeof(CNTSecExt))); 
	ASSERT(m_pLog != NULL); 
	ASSERT(AfxIsValidAddress(m_pLog, sizeof(CLog))); 
 
 
	if (!ShouldLog(m_pLog, flag)) 
		return; 
 
	{ 
		CString cBuf; 
		ASSERT(AfxIsValidString(Format, FALSE)); 
 
		cBuf.Format("(CNTSecExt) %s", Format); 
 
		va_list argList; 
		va_start(argList, Format); 
		m_pLog->LogMsgV(flag, cBuf, argList); 
		va_end(argList); 
	} 
} 
 
 
 
CNTProperties::CNTProperties() 
{ 
	hLogon = NULL; 
	pSock = NULL; 
} 
 
CNTProperties::~CNTProperties() 
{ 
	if (hLogon) 
		CloseHandle(hLogon); 
} 
 
 
////////////////////////////////////////////////////////////////////////////////// 
// Socket connector subsystem. These functions will create a CSockAPI derived  
// object (of our choise) for Sockey level notifications. 
// Delete the calls you don't need, or add the On*Socket handler to create 
// the object. 
 
 
// Called from the CSock constructor 
// 
int CallOnNewSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	CSock *pSock = (CSock *)lParam; 
	return 0; 
} 
 
int CallOnNewTextSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	CTextSock *pSock = (CTextSock *)lParam; 
 
	// Create a new CNTFTPConn object and link it to the calls we will use. 
	CDllInfo *pDLL = pMe->GetDLLInfo(); 
	ASSERT(pDLL != NULL); 
	if (pDLL == NULL) 
		return 0; 
 
	CNTFTPConn *pConn = new CNTFTPConn; 
	pConn->pSock = pSock; // Required 
	 
	pSock->m_Funcs[CSock::iOnSocketIsDestroyed].AddLast(pDLL, CSock::iOnSocketIsDestroyed, pConn, CallOnSocketIsDestroyed); 
	pSock->m_Funcs[CSock::OnPreFSYSAccess].AddLast(pDLL, CSock::OnPreFSYSAccess, pConn, CallOnPreFSYSAccess); 
	pSock->m_Funcs[CSock::OnPostFSYSAccess].AddLast(pDLL, CSock::OnPostFSYSAccess, pConn, CallOnPostFSYSAccess); 
	pSock->m_Funcs[CSock::OnGetSecurityDescriptor].AddLast(pDLL, CSock::OnGetSecurityDescriptor, pConn, CallOnGetSecurityDescriptor); 
	pSock->m_Funcs[CSock::iOnConnect].AddLast(pDLL, CSock::iOnConnect, pConn, CallOnConnect); 
	pSock->m_Funcs[CSock::iOnReceive].AddLast(pDLL, CSock::iOnReceive, pConn, CallOnReceive); 
	pSock->m_Funcs[CSock::iOnSend].AddLast(pDLL, CSock::iOnSend, pConn, CallOnSend); 
	pSock->m_Funcs[CSock::iOnCommand].AddLast(pDLL, CSock::iOnCommand, pConn, CallOnCommand); 
	pSock->m_Funcs[CSock::iOnClose].AddLast(pDLL, CSock::iOnClose, pConn, CallOnClose); 
	pSock->m_Funcs[CSock::iSendCtrlMsg].AddLast(pDLL, CSock::iSendCtrlMsg, pConn, CallOnSendCmd); 
	pSock->m_Funcs[CSock::iOnSITECmd].AddLast(pDLL, CSock::iOnSITECmd, pConn, CallOnSITECmd); 
	pSock->m_Funcs[CSock::iOnIdle].AddLast(pDLL, CSock::iOnIdle, pConn, CallOnIdle); 
	pSock->m_Funcs[CSock::iOnVerifyIPAddress].AddLast(pDLL, CSock::iOnVerifyIPAddress, pConn, CallOnVerifyIPAddress); 
	pSock->m_Funcs[CSock::iOnVerifyUploadedFile].AddLast(pDLL, CSock::iOnVerifyUploadedFile, pConn, CallOnVerifyUploadedFile); 
	pSock->m_Funcs[CSock::iOnVerifyTransferRequest].AddLast(pDLL, CSock::iOnVerifyTransferRequest, pConn, CallOnVerifyTransferRequest); 
 
	return 0; 
} 
 
int CallOnNewFTPDataSocket(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	CFTPDataSock *pSock = (CFTPDataSock *)lParam; 
	return 0; 
} 
 
int CallOnFTPDCoreCtrlSock(LPVOID Origin, int Event, WPARAM wParam, LPARAM lParam) 
{ 
	CFTPDCoreCtrlSock *pSock = (CFTPDCoreCtrlSock *)lParam; 
	return 0; 
}