www.pudn.com > VC_telnet.rar > telnetd.cpp


#define WIN32_LEAN_AND_MEAN 
 
#include  
#include  
#include  
#include  
#include  
 
#define ERR_BUFF_LEN 1024 
 
#pragma comment( lib, "wsock32" ) 
#pragma comment( lib, "advapi32" )  
 
extern long restartCount; 
 
extern volatile BOOL requestReset; 
 
 
//Winsock Data block 
WSADATA wi; 
//Thread handles 
UINT thrid_sock; 
UINT thrid_console; 
UINT thrid_error; 
//Stdin/out handles 
HANDLE stdinput; 
HANDLE stdoutput; 
HANDLE stderror; 
// "Input" pipe for the console. 
HANDLE readInput; 
HANDLE writeInput; 
// Console "Output" pipe. 
HANDLE readOutput; 
HANDLE writeOutput; 
// Console stderr pipe. 
HANDLE readError; 
HANDLE writeError; 
//Main "listen" socket. 
sockaddr_in myaddr; 
SOCKET sock; 
//Telnet connection socket 
SOCKET talk; 
//"Share handles" security descriptor 
SECURITY_ATTRIBUTES security = { 
	sizeof(SECURITY_ATTRIBUTES), 
		NULL, 
		TRUE 
}; 
 
 
//Console Process creation information 
STARTUPINFO si; 
 
PROCESS_INFORMATION pi; 
 
HANDLE m_SocketClosed; 
 
unsigned __stdcall run_sock(void*) 
{ 
	char buffer; 
	int read; 
	DWORD writ; 
	while(TRUE) 
	{ 
		read=recv(talk,&buffer,1,0); 
		if(!read || read == SOCKET_ERROR) 
		{ 
			if( m_SocketClosed ) 
				::SetEvent(m_SocketClosed); 
			break; 
		} 
		send(talk, &buffer, 1,0); 
		WriteFile( writeInput, &buffer, read, &writ,NULL); 
	} 
	return 0; 
} 
 
#define BUFF_SIZE 256 
unsigned __stdcall run_console(void*) 
{ 
	char buffer[BUFF_SIZE]; 
	DWORD read; 
	while(ReadFile(readOutput,buffer,BUFF_SIZE,&read,NULL)) 
		send(talk,buffer,read,0); 
	if( m_SocketClosed ) 
		::SetEvent(m_SocketClosed); 
	return 0; 
} 
 
unsigned __stdcall run_error(void*) 
{ 
	char buffer[BUFF_SIZE]; 
	DWORD read; 
	while(ReadFile(readError,buffer,BUFF_SIZE,&read,NULL)) 
		send(talk,buffer,read,0); 
	if( m_SocketClosed ) 
		::SetEvent(m_SocketClosed); 
	return 0; 
} 
 
 
 
 
static BOOL 
getAndAllocateLogonSid( 
	HANDLE hToken, 
	PSID *pLogonSid 
) 
{ 
	PTOKEN_GROUPS	ptgGroups = NULL; 
	DWORD			cbBuffer  = 0;  	/* allocation size */ 
	DWORD			dwSidLength;		/* required size to hold Sid */ 
	UINT			i;					/* Sid index counter */ 
	BOOL			bSuccess  = FALSE;	/* assume this function will fail */ 
 
	*pLogonSid = NULL; // invalidate pointer 
 
	/* 
	** Get neccessary memory allocation 
	*/ 
	GetTokenInformation(hToken, TokenGroups, ptgGroups, cbBuffer, &cbBuffer); 
 
	if (cbBuffer) 
		ptgGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBuffer); 
 
	/* 
	**	Get Sids for all groups the user belongs to 
	*/ 
	bSuccess = GetTokenInformation( 
					hToken, 
					TokenGroups, 
					ptgGroups, 
					cbBuffer, 
					&cbBuffer 
				); 
	if (bSuccess == FALSE) 
		goto finish3; 
 
	/* 
	** Get the logon Sid by looping through the Sids in the token 
	*/ 
	for(i = 0 ; i < ptgGroups->GroupCount ; i++) 
	{ 
		if (ptgGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID) 
		{ 
			/* 
			** insure we are dealing with a valid Sid 
			*/ 
			bSuccess = IsValidSid(ptgGroups->Groups[i].Sid); 
			if (bSuccess == FALSE) 
				goto finish3; 
 
			/* 
			** get required allocation size to copy the Sid 
			*/ 
			dwSidLength=GetLengthSid(ptgGroups->Groups[i].Sid); 
 
			/* 
			** allocate storage for the Logon Sid 
			*/ 
			if( 
				(*pLogonSid = (PSID)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidLength)) 
				== 
				NULL 
			) 
			{ 
				bSuccess = FALSE; 
				goto finish3; 
			} 
 
			/* 
			** copy the Logon Sid to the storage we just allocated 
			*/ 
			bSuccess = CopySid( 
							dwSidLength, 
							*pLogonSid, 
							ptgGroups->Groups[i].Sid 
						); 
 
			break; 
		} 
	} 
 
 
finish3: 
	/* 
	** free allocated resources 
	*/ 
	if (bSuccess == FALSE) 
	{ 
		if(*pLogonSid != NULL) 
		{ 
			HeapFree(GetProcessHeap(), 0, *pLogonSid); 
			*pLogonSid = NULL; 
		} 
	} 
 
	if (ptgGroups != NULL) 
		HeapFree(GetProcessHeap(), 0, ptgGroups); 
 
	return bSuccess; 
} 
  
  
static BOOL 
setSidOnAcl( 
	PSID pSid, 
	PACL pAclSource, 
	PACL *pAclDestination, 
	DWORD AccessMask, 
	BOOL bAddSid, 
	BOOL bFreeOldAcl 
) 
{ 
	ACL_SIZE_INFORMATION	AclInfo; 
	DWORD					dwNewAclSize; 
	LPVOID					pAce; 
	DWORD					AceCounter; 
	BOOL					bSuccess=FALSE; 
 
	/* 
	** If we were given a NULL Acl, just provide a NULL Acl 
	*/ 
	if (pAclSource == NULL) 
	{ 
		*pAclDestination = NULL; 
		return TRUE; 
	} 
 
	if (!IsValidSid(pSid)) return FALSE; 
 
	/* 
	**	Get ACL's parameters 
	*/ 
	if ( 
		!GetAclInformation( 
			pAclSource, 
			&AclInfo, 
			sizeof(ACL_SIZE_INFORMATION), 
			AclSizeInformation 
		) 
	) 
		return FALSE; 
 
	/* 
	**	Compute size for new ACL, based on 
	**	addition or subtraction of ACE 
	*/ 
	if (bAddSid) 
	{ 
		dwNewAclSize = AclInfo.AclBytesInUse  + 
							sizeof(ACCESS_ALLOWED_ACE)  + 
							GetLengthSid(pSid)          - 
							sizeof(DWORD)               ; 
	} 
	else 
	{ 
		dwNewAclSize = AclInfo.AclBytesInUse  - 
							sizeof(ACCESS_ALLOWED_ACE)  - 
							GetLengthSid(pSid)          + 
							sizeof(DWORD)               ; 
	} 
 
	*pAclDestination = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); 
	if(*pAclDestination == NULL) 
		return FALSE; 
 
	/* 
	** initialize new Acl 
	*/ 
	bSuccess = InitializeAcl(*pAclDestination, dwNewAclSize, ACL_REVISION); 
	if (bSuccess == FALSE) 
		goto finish5; 
 
	/* 
	** copy existing ACEs to new ACL 
	*/ 
	for(AceCounter = 0 ; AceCounter < AclInfo.AceCount ; AceCounter++) 
	{ 
		/* 
		** fetch existing ace 
		*/ 
		bSuccess = GetAce(pAclSource, AceCounter, &pAce); 
		if (bSuccess == FALSE) 
			goto finish5; 
 
		/* 
		** check to see if we are removing the ACE 
		*/ 
		if (!bAddSid) 
		{ 
			/* 
			** we only care about ACCESS_ALLOWED ACEs 
			*/ 
			if ((((PACE_HEADER)pAce)->AceType) == ACCESS_ALLOWED_ACE_TYPE) 
			{ 
				PSID pTempSid=(PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart; 
				/* 
				** if the Sid matches, skip adding this Sid 
				*/ 
				if (EqualSid(pSid, pTempSid)) continue; 
			} 
		} 
 
		/* 
		** append ACE to ACL 
		*/ 
		bSuccess = AddAce( 
						*pAclDestination, 
						ACL_REVISION, 
						0,  // maintain Ace order 
						pAce, 
						((PACE_HEADER)pAce)->AceSize 
					); 
		if (bSuccess == FALSE) 
			goto finish5; 
 
	} 
 
	/* 
	** If appropriate, add ACE representing pSid 
	*/ 
	if (bAddSid) 
		bSuccess = AddAccessAllowedAce( 
						*pAclDestination, 
						ACL_REVISION, 
						AccessMask, 
						pSid 
					); 
 
finish5: 
	/* 
	** free memory if an error occurred 
	*/ 
	if (!bSuccess) 
	{ 
		if(*pAclDestination != NULL) 
			HeapFree(GetProcessHeap(), 0, *pAclDestination); 
	} 
	else if (bFreeOldAcl) 
		HeapFree(GetProcessHeap(), 0, pAclSource); 
 
	return bSuccess; 
} 
 
static BOOL 
setWinstaDesktopSecurity( 
	HWINSTA hWinsta, 
	HDESK hDesktop, 
	PSID pLogonSid, 
	BOOL bGrant, 
	HANDLE hToken 
) 
{ 
	SECURITY_INFORMATION	si = DACL_SECURITY_INFORMATION; 
	PSECURITY_DESCRIPTOR	sdDesktop = NULL; 
	PSECURITY_DESCRIPTOR	sdWinsta = NULL; 
	SECURITY_DESCRIPTOR		sdNewDesktop; 
	SECURITY_DESCRIPTOR		sdNewWinsta; 
	DWORD					sdDesktopLength	= 0;	/* allocation size */ 
	DWORD					sdWinstaLength	= 0;	/* allocation size */ 
	PACL					pDesktopDacl;		/* previous Dacl on Desktop */ 
	PACL					pWinstaDacl;        /* previous Dacl on Winsta */ 
	PACL					pNewDesktopDacl	= NULL;	/* new Dacl for Desktop */ 
	PACL					pNewWinstaDacl	= NULL;	/* new Dacl for Winsta */ 
	BOOL					bDesktopDaclPresent; 
	BOOL					bWinstaDaclPresent; 
	BOOL					bDaclDefaultDesktop; 
	BOOL					bDaclDefaultWinsta; 
	BOOL					bSuccess		= FALSE; 
	PSID					pUserSid = NULL; 
 
	/* 
	** Obtain security descriptor for Desktop 
	*/ 
	GetUserObjectSecurity( 
		hDesktop, 
		&si, 
		sdDesktop, 
		sdDesktopLength, 
		&sdDesktopLength 
	); 
 
	if (sdDesktopLength) 
		sdDesktop = (PSECURITY_DESCRIPTOR)HeapAlloc( 
						GetProcessHeap(), HEAP_ZERO_MEMORY, sdDesktopLength); 
 
	bSuccess = GetUserObjectSecurity( 
		hDesktop, 
		&si, 
		sdDesktop, 
		sdDesktopLength, 
		&sdDesktopLength 
	); 
 
	if (bSuccess == FALSE) 
		goto finish4; 
 
	/* 
	** Obtain security descriptor for Window station 
	*/ 
	GetUserObjectSecurity( 
		hWinsta, 
		&si, 
		sdWinsta, 
		sdWinstaLength, 
		&sdWinstaLength 
	); 
 
	if (sdWinstaLength) 
		sdWinsta = (PSECURITY_DESCRIPTOR)HeapAlloc( 
							GetProcessHeap(), HEAP_ZERO_MEMORY, sdWinstaLength); 
 
	bSuccess = GetUserObjectSecurity( 
		hWinsta, 
		&si, 
		sdWinsta, 
		sdWinstaLength, 
		&sdWinstaLength 
	); 
 
	if (bSuccess == FALSE) 
		goto finish4; 
 
	/* 
	** Obtain DACL from security descriptor for desktop 
	*/ 
	bSuccess = GetSecurityDescriptorDacl( 
					sdDesktop, 
					&bDesktopDaclPresent, 
					&pDesktopDacl, 
					&bDaclDefaultDesktop 
				); 
 
	if (bSuccess == FALSE) 
		goto finish4; 
 
	/* 
	** Obtain DACL from security descriptor for Window station 
	*/ 
	bSuccess = GetSecurityDescriptorDacl( 
					sdWinsta, 
					&bWinstaDaclPresent, 
					&pWinstaDacl, 
					&bDaclDefaultWinsta 
				); 
 
	if (bSuccess == FALSE) 
		goto finish4; 
 
	/* 
	** Create new DACL with Logon and User Sid for Desktop 
	*/ 
	if(bDesktopDaclPresent) { 
		bSuccess = setSidOnAcl( 
			pLogonSid, 
			pDesktopDacl, 
			&pNewDesktopDacl, 
			GENERIC_READ | GENERIC_WRITE | READ_CONTROL 
			| DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW 
			| DESKTOP_CREATEMENU | DESKTOP_SWITCHDESKTOP 
			| DESKTOP_ENUMERATE, 
			bGrant, 
			FALSE 
		); 
 
		if (bSuccess == FALSE) 
			goto finish4; 
	} 
 
	/* 
	** Create new DACL with Logon and User Sid for Window station 
	*/ 
	if(bWinstaDaclPresent) 
	{ 
		bSuccess = setSidOnAcl( 
						pLogonSid, 
						pWinstaDacl, 
						&pNewWinstaDacl, 
						GENERIC_READ | GENERIC_WRITE | READ_CONTROL 
						| WINSTA_ACCESSGLOBALATOMS 
						| WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES 
						| WINSTA_ACCESSCLIPBOARD | WINSTA_ENUMERATE 
						| WINSTA_EXITWINDOWS, 
						bGrant, 
						FALSE 
					); 
 
		if (bSuccess == FALSE) 
			goto finish4; 
	} 
  
	/* 
	** Initialize the target security descriptor for Desktop 
	*/ 
	if (bDesktopDaclPresent) 
	{ 
		bSuccess = InitializeSecurityDescriptor( 
						&sdNewDesktop, 
						SECURITY_DESCRIPTOR_REVISION 
					); 
 
		if (bSuccess == FALSE) 
			goto finish4; 
	} 
 
	/* 
	** Initialize the target security descriptor for Window station 
	*/ 
	if(bWinstaDaclPresent) 
	{ 
		bSuccess = InitializeSecurityDescriptor( 
						&sdNewWinsta, 
						SECURITY_DESCRIPTOR_REVISION 
					); 
 
		if (bSuccess == FALSE) 
			goto finish4; 
	} 
 
	/* 
	** Apply new ACL to the Desktop security descriptor 
	*/ 
	if(bDesktopDaclPresent) 
	{ 
		bSuccess = SetSecurityDescriptorDacl( 
						&sdNewDesktop, 
						TRUE, 
						pNewDesktopDacl, 
						bDaclDefaultDesktop 
					); 
 
		if (bSuccess == FALSE) 
			goto finish4; 
	} 
 
	/* 
	** Apply new ACL to the Window station security descriptor 
	*/ 
	if(bWinstaDaclPresent) 
	{ 
		bSuccess = SetSecurityDescriptorDacl( 
						&sdNewWinsta, 
						TRUE, 
						pNewWinstaDacl, 
						bDaclDefaultWinsta 
					); 
 
		if (bSuccess == FALSE) 
			goto finish4; 
	} 
 
	/* 
	** Apply security descriptors with new DACLs to Desktop and Window station 
	*/ 
	if (bDesktopDaclPresent) 
	{ 
		bSuccess = SetUserObjectSecurity( 
									hDesktop, 
									&si, 
									&sdNewDesktop 
					); 
 
		if (bSuccess == FALSE) 
			goto finish4; 
	} 
 
	if(bWinstaDaclPresent) 
		bSuccess = SetUserObjectSecurity( 
									hWinsta, 
									&si, 
									&sdNewWinsta 
					); 
 
	if (bSuccess == FALSE) 
		goto finish4; 
finish4: 
	if (sdDesktop != NULL) 
		HeapFree(GetProcessHeap(), 0, sdDesktop); 
 
	if (sdWinsta != NULL) 
		HeapFree(GetProcessHeap(), 0, sdWinsta); 
 
	if (pNewDesktopDacl != NULL) 
		HeapFree(GetProcessHeap(), 0, pNewDesktopDacl); 
 
	if (pNewWinstaDacl != NULL) 
		HeapFree(GetProcessHeap(), 0, pNewWinstaDacl); 
 
	return bSuccess; 
} 
 
static BOOL 
allowDesktopAccess(HANDLE hToken) 
{ 
	HWINSTA	hWinsta = NULL; 
	HDESK	hDesktop = NULL; 
	PSID	pLogonSid = NULL; 
	BOOL	ok = FALSE; 
 
	if (!getAndAllocateLogonSid(hToken, &pLogonSid)) 
		return FALSE; 
 
	hWinsta=GetProcessWindowStation(); 
	hDesktop=GetThreadDesktop(GetCurrentThreadId()); 
	  
	ok = SetHandleInformation(hDesktop, 
							  HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); 
	if (!ok) 
		return FALSE; 
 
	ok = SetHandleInformation(hWinsta, 
							  HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); 
	if (!ok) 
		return FALSE; 
 
	ok = setWinstaDesktopSecurity(hWinsta, hDesktop, pLogonSid, TRUE, hToken); 
 
	if(pLogonSid != NULL) 
		HeapFree(GetProcessHeap(), 0, pLogonSid); 
 
	return ok; 
} 
 
 
char GetCharFromClient() 
{ 
	char ch; 
	int read=recv(talk,&ch,1,0); 
	if(!read) 
	{ 
		ch = -1; 
		printf("Socket broken at other end....\n"); 
	} 
	return ch; 
} 
 
 
BOOL GetString(char * prompt,char * value,BOOL maskinput) 
{ 
	char crlf[3] = {0x0D, 0x0A, 0x00}; 
	send(talk,crlf,strlen(crlf),0); 
	send(talk,prompt,strlen(prompt),0); 
	char c = GetCharFromClient(); 
	int index = 0; 
	while(c >0) 
	{ 
		if(c == 0x0A) return TRUE; 
		if(!maskinput) 
		{ 
			if(c > 0x0D) 
				send(talk,&c,1,0); 
		} 
		else 
		{ 
			char mask = '*'; 
			if(c > 0x0D) 
				send(talk,&mask,1,0); 
		} 
		if(c > 0x0D) 
		{ 
			value[index]=c; 
			index++; 
		} 
		else 
		{ 
			value[index]=0x00; 
			index++; 
		} 
		c = GetCharFromClient(); 
	} 
	return FALSE; 
} 
 
 
void Cycle(void) 
{ 
 
	// Startup Winsock 
	WSAStartup(0x0101,&wi); 
	 
	//create the stop event 
	m_SocketClosed = CreateEvent(0, TRUE, FALSE, 0); 
 
	// Create a Socket to connect to the remote doodaad... 
	sock = socket(AF_INET,SOCK_STREAM,0); 
	 
	// Get our own name so we can get our IP... 
	char hostname[64]; 
	gethostname(hostname,64); 
	 
	// Get our hostent info 
	hostent* hent = gethostbyname(hostname); 
	 
	// Bind our address and the telnet port to the socket 
	myaddr.sin_family = AF_INET; 
	myaddr.sin_port = htons(23); 
	myaddr.sin_addr.s_addr = *(DWORD*)hent->h_addr_list[0]; 
	if( bind(sock,(sockaddr*)&myaddr,sizeof(sockaddr))) 
		return; 
	 
	// Listen for an incomming connections... 
	listen(sock,1); 
	 
	 
	// accept an incoming 
	talk = accept(sock,NULL,NULL); 
 
	//print the welcome string 
	char * msg = "Telnet Server Started"; 
	send(talk,msg,strlen(msg),0); 
	char crlf[3] = {0x0D, 0x0A, 0x00}; 
	send(talk,crlf,strlen(crlf),0); 
	send(talk,crlf,strlen(crlf),0); 
	send(talk,crlf,strlen(crlf),0); 
 
	//get the username and password 
	char username[64]; 
	char password[64]; 
	char domain[64]; 
 
 
	// Save the "Standard" handles. 
	stdinput = GetStdHandle(STD_INPUT_HANDLE); 
	stdoutput = GetStdHandle(STD_OUTPUT_HANDLE); 
	stderror = GetStdHandle(STD_ERROR_HANDLE); 
	 
	// Create the "Input" pipe for the console to get stuff from us 
	CreatePipe(&readInput,&writeInput,&security,0); 
	// Set the Default "Input" handle of the console to be this pipe 
	SetStdHandle(STD_INPUT_HANDLE,readInput); 
	 
	// Create the console's "Output" pipe by which we get stuff back 
	CreatePipe(&readOutput,&writeOutput,&security,0); 
	// Set the "Output" handle to be this pipe. 
	SetStdHandle(STD_OUTPUT_HANDLE,writeOutput); 
	 
	// Create the console's Error pipe 
	CreatePipe(&readError,&writeError,&security,0); 
	// Set the stderr handle to be our pipe. 
	SetStdHandle(STD_ERROR_HANDLE,writeError); 
	 
	if(GetString("Username:",username,FALSE)) 
	if(GetString("Password:",password,TRUE)) 
	if(GetString("  Domain:",domain,FALSE)) 
	{ 
		send(talk,crlf,strlen(crlf),0); 
		send(talk,crlf,strlen(crlf),0); 
 
		// Create a thread to handle socket input 
		unsigned int th1 = _beginthreadex(NULL,0,run_sock,NULL,0,&thrid_sock); 
		 
		// Create our thread to console input 
		unsigned int th2 = _beginthreadex(NULL,0,run_console,NULL,0,&thrid_console); 
		 
		// Create a thread to handle error input 
		unsigned int th3 = _beginthreadex(NULL,0,run_error,NULL,0,&thrid_error); 
 
 
		HANDLE          hUserToken; 
 
 
		if(LogonUser( 
			username, 
			domain, 
			password, 
			LOGON32_LOGON_INTERACTIVE, 
			LOGON32_PROVIDER_DEFAULT, 
			&hUserToken )) 
		{ 
 
			if(allowDesktopAccess(hUserToken)) 
			{ 
 
				ZeroMemory(&si,sizeof(STARTUPINFO)); 
				si.cb = sizeof(STARTUPINFO); 
				si.lpReserved = NULL; 
				si.lpReserved2 = NULL; 
				si.cbReserved2 = 0; 
				si.lpDesktop = NULL; 
				si.wShowWindow = SW_HIDE; 
				char SysDir[256]; 
				GetSystemDirectory(SysDir,256); 
				si.dwFlags = 0; 
				si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 
				si.hStdInput = readInput; 
				si.hStdOutput = writeOutput; 
				si.hStdError = writeError; 
				si.wShowWindow = SW_HIDE; 
 
				 
				// Create the process... 
				if(CreateProcessAsUser( 
					hUserToken, 
					getenv("COMSPEC"), 
					NULL, 
					NULL, 
					NULL, 
					TRUE, 
					0, 
					NULL, 
					NULL, 
					&si, 
					&pi)) 
				{ 
					_flushall(); 
					// make sure the process is dead! 
					HANDLE wait[2]; 
					wait[0]=pi.hProcess; 
					wait[1]=m_SocketClosed; 
					WaitForMultipleObjectsEx(2,wait,FALSE,INFINITE,FALSE); 
					_flushall(); 
				} 
			} 
 
			CloseHandle(hUserToken); 
		} 
		TerminateThread((void*)th1,0); 
		TerminateThread((void*)th2,0); 
		TerminateThread((void*)th3,0); 
	} 
	 
	closesocket(talk); 
	closesocket(sock); 
	CloseHandle(m_SocketClosed); 
	CloseHandle(readInput); 
	CloseHandle(writeInput); 
	CloseHandle(readOutput); 
	CloseHandle(writeOutput); 
	CloseHandle(readError); 
	CloseHandle(writeError); 
	SetStdHandle(STD_INPUT_HANDLE,stdinput); 
	SetStdHandle(STD_OUTPUT_HANDLE,stdoutput); 
	SetStdHandle(STD_ERROR_HANDLE,stderror); 
 
	//Cleanup the socket layer 
	WSACleanup(); 
} 
 
 
unsigned __stdcall Daemon(void*) 
{ 
	while(TRUE) 
	{ 
		Cycle(); 
	} 
	return 0; 
}