#include "Mra.h"
#include "MraOfflineMsg.h"
#include "MraRTFMsg.h"
#include "MraPlaces.h"






void			MraThreadProc					(LPVOID lpParameter);
DWORD			MraGetNLBData					(LPSTR lpszHost,SIZE_T dwHostBuffSize,WORD *pwPort);
DWORD			MraNetworkDispather				();
DWORD			MraCommandDispather				(mrim_packet_header_t *pmaHeader,DWORD *pdwPingPeriod,DWORD *pdwNextPingSendTickTime,BOOL *pbContinue);




//DWORD			GetMraStatusFromMiradaStatus	(DWORD dwMirandaStatus,DWORD dwXStatusMir,DWORD *pdwXStatusMra);
//DWORD			GetMiradaStatusFromMraStatus	(DWORD dwMraStatus,DWORD dwXStatusMra,DWORD *pdwXStatusMir);
//DWORD			GetMraXStatusIDFromMraUriStatus	(LPSTR lpszStatusUri,SIZE_T dwStatusUriSize);

DWORD			GetUL				(LPBYTE *plpData);
DWORDLONG		GetUIDL				(LPBYTE *plpData);
MRA_GUID		GetGUID				(LPBYTE *plpData);
DWORD			GetLPS				(LPBYTE lpbData,DWORD dwDataSize,LPBYTE *plpCurrentData,MRA_LPS *plpsString);






DWORD StartConnect()
{
	DWORD dwRetErrorCode=NO_ERROR;

	if (InterlockedExchangeAdd((volatile LONG*)&masMraSettings.dwGlobalPluginRunning,0))
	{
		if (InterlockedCompareExchange((volatile LONG*)&masMraSettings.dwThreadWorkerRunning,TRUE,FALSE)==FALSE)
		{// ����� ���/��� �� �������, ��������� ������ ��� �������� � ���������
			char szPass[MAX_PATH];
			SIZE_T dwEMailSize=0,dwPasswordSize=0;

			DB_Mra_GetStaticStringA(NULL,"e-mail",NULL,0,&dwEMailSize);

			if (dwEMailSize>5 && GetPassDB(szPass,sizeof(szPass),&dwPasswordSize))
			{// mir_forkthread
				InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());
				masMraSettings.hThreadWorker=mir_forkthread(MraThreadProc,NULL);
				if (masMraSettings.hThreadWorker==NULL)
				{
					dwRetErrorCode=GetLastError();
					InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerRunning,FALSE);
					MraSetStatus(ID_STATUS_OFFLINE,0);
				}
			}else{
				MraThreadClean();
				if (!(dwEMailSize>5))
				{
					MraPopupShowFromAgentW(MRA_POPUP_TYPE_WARNING,0,TranslateW(L"Please, setup e-mail in options"));
				}else{
					MraPopupShowFromAgentW(MRA_POPUP_TYPE_WARNING,0,TranslateW(L"Please, setup password in options"));
				}
			}
			SecureZeroMemory(szPass,sizeof(szPass));
		}else{
			DebugBreak();
		}
	}else{
		dwRetErrorCode=ERROR_OPERATION_ABORTED;
		//DebugBreak();
	}
return(dwRetErrorCode);
}


void MraThreadProc(LPVOID lpParameter)
{
	DWORD dwRetErrorCode=NO_ERROR;

	if (TRUE)
	{
		BOOL bConnected=FALSE;
		char szHost[MAX_PATH];
		DWORD dwConnectReTryCount,dwCurConnectReTryCount;
		NETLIBOPENCONNECTION nloc={0};

		SleepEx(100,FALSE);// to prevent high CPU load by some status plugins like allwaysonline

		dwConnectReTryCount=DB_Mra_GetDword(NULL,"ConnectReTryCountMRIM",MRA_DEFAULT_CONN_RETRY_COUNT_MRIM);
	
		nloc.cbSize=sizeof(nloc);
		nloc.flags=NLOCF_V2;
		nloc.szHost=szHost;
		nloc.timeout=DB_Mra_GetDword(NULL,"TimeOutConnectMRIM",MRA_DEFAULT_TIMEOUT_CONN_MRIM);
		if (nloc.timeout<MRA_TIMEOUT_CONN_MIN) nloc.timeout=MRA_TIMEOUT_CONN_MIN;
		if (nloc.timeout>MRA_TIMEOUT_CONN_���) nloc.timeout=MRA_TIMEOUT_CONN_���;

		InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());
		if (MraGetNLBData((LPSTR)nloc.szHost,MAX_PATH,&nloc.wPort)==NO_ERROR)
		{
			dwCurConnectReTryCount=dwConnectReTryCount;
			do{
				InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());
				masMraSettings.hConnection=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)masMraSettings.hNetlibUser,(LPARAM)&nloc);
			}while(--dwCurConnectReTryCount && masMraSettings.hConnection==NULL);

			if (masMraSettings.hConnection)
			{
				bConnected=TRUE;
			}
		}

		if (bConnected==FALSE)
		if (DB_Mra_GetByte(NULL,"NLBFailDirectConnect",MRA_DEFAULT_NLB_FAIL_DIRECT_CONNECT))
		{
			if (IsHTTPSProxyUsed(masMraSettings.hNetlibUser))
			{// ����� https ������ ������ 443 ����
				nloc.wPort=MRA_SERVER_PORT_HTTPS;
			}else{
				nloc.wPort=DB_Mra_GetWord(NULL,"ServerPort",MRA_DEFAULT_SERVER_PORT);
				if (nloc.wPort==MRA_SERVER_PORT_STANDART_NLB) nloc.wPort=MRA_SERVER_PORT_STANDART;
			}

			for(DWORD i=1;(i<MRA_MAX_MRIM_SERVER && MraGetStatus(0,0)!=ID_STATUS_OFFLINE);i++)
			{
				mir_snprintf(szHost,SIZEOF(szHost),"mrim%lu.mail.ru",i);
				
				dwCurConnectReTryCount=dwConnectReTryCount;
				do{
					InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());
					masMraSettings.hConnection=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)masMraSettings.hNetlibUser,(LPARAM)&nloc);
				}while(--dwCurConnectReTryCount && masMraSettings.hConnection==NULL);

				if (masMraSettings.hConnection)
				{
					bConnected=TRUE;
					break;
				}
			}
		}


		if (bConnected && MraGetStatus(0,0)!=ID_STATUS_OFFLINE)
		{
			/*SOCKET sktSocket;
			struct sockaddr_in saName;
			int iNamelen=sizeof(struct sockaddr_in);

			sktSocket=(SOCKET)CallService(MS_NETLIB_GETSOCKET,(WPARAM)masMraSettings.hConnection,(LPARAM)NULL);
			getsockname(sktSocket,(struct sockaddr*)&saName,&iNamelen);
			memmove(&masMraSettings.dwIP,&saName.sin_addr,4);
			masMraSettings.dwPort=ntohs(saName.sin_port);*/

			dwRetErrorCode=MraNetworkDispather();
		}else{
			if (bConnected==FALSE)
			{
				ShowFormatedErrorMessage(L"Can't connect to MRIM server, error",GetLastError());
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,ACKTYPE_LOGIN,ACKRESULT_FAILED,NULL,LOGINERR_NONETWORK,0);
			}
		}
	}
	MraThreadClean();
}


void MraThreadClean()
{
	MraMPopSessionQueueFlush(masMraSettings.hMPopSessionQueue);
	Netlib_CloseHandle(masMraSettings.hConnection);// called twice, if user set offline, its normal
	masMraSettings.hConnection=NULL;
	masMraSettings.dwCMDNum=0;

	SleepEx(100,FALSE);// to prevent high CPU load by some status plugins like allwaysonline

	masMraSettings.hThreadWorker=NULL;
	InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerRunning,FALSE);
	MraSetStatus(ID_STATUS_OFFLINE,0);
}



DWORD MraGetNLBData(LPSTR lpszHost,SIZE_T dwHostBuffSize,WORD *pwPort)
{
	DWORD dwRetErrorCode;

	BOOL bContinue=TRUE;
	BYTE btBuff[MAX_PATH];
	DWORD dwConnectReTryCount,dwCurConnectReTryCount;
	LPSTR lpszPort;
	SIZE_T dwBytesReceived,dwRcvBuffSizeUsed=0;
	NETLIBSELECT nls={0};
	NETLIBOPENCONNECTION nloc={0};


	dwConnectReTryCount=DB_Mra_GetDword(NULL,"ConnectReTryCountNLB",MRA_DEFAULT_CONN_RETRY_COUNT_NLB);
	
	nloc.cbSize=sizeof(nloc);
	nloc.flags=NLOCF_V2;
	if (DB_Mra_GetStaticStringA(NULL,"Server",(LPSTR)btBuff,SIZEOF(btBuff),NULL))
	{
		nloc.szHost=(LPSTR)btBuff;
	}else{
		nloc.szHost=MRA_DEFAULT_SERVER;
	}

	if (IsHTTPSProxyUsed(masMraSettings.hNetlibUser))
	{// ����� https ������ ������ 443 ����
		nloc.wPort=MRA_SERVER_PORT_HTTPS;
	}else{
		nloc.wPort=DB_Mra_GetWord(NULL,"ServerPort",MRA_DEFAULT_SERVER_PORT);
	}
	nloc.timeout=DB_Mra_GetDword(NULL,"TimeOutConnectNLB",MRA_DEFAULT_TIMEOUT_CONN_NLB);
	if (nloc.timeout<MRA_TIMEOUT_CONN_MIN) nloc.timeout=MRA_TIMEOUT_CONN_MIN;
	if (nloc.timeout>MRA_TIMEOUT_CONN_���) nloc.timeout=MRA_TIMEOUT_CONN_���;


	dwCurConnectReTryCount=dwConnectReTryCount;
	do{
		InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());
		nls.hReadConns[0]=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)masMraSettings.hNetlibUser,(LPARAM)&nloc);
	}while(--dwCurConnectReTryCount && nls.hReadConns[0]==NULL);

	if (nls.hReadConns[0])
	{
		nls.cbSize=sizeof(nls);
		nls.dwTimeout=(1000*DB_Mra_GetDword(NULL,"TimeOutReceiveNLB",MRA_DEFAULT_TIMEOUT_RECV_NLB));
		InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());

		while(MraGetStatus(0,0)!=ID_STATUS_OFFLINE && bContinue)
		{
			switch(CallService(MS_NETLIB_SELECT,0,(LPARAM)&nls)) {
			case SOCKET_ERROR:
			case 0:// Time out
				bContinue=FALSE;
				break;
			case 1:
				dwBytesReceived=Netlib_Recv(nls.hReadConns[0],(LPSTR)(btBuff+dwRcvBuffSizeUsed),(SIZEOF(btBuff)-dwRcvBuffSizeUsed),0);
				if (dwBytesReceived && dwBytesReceived!=SOCKET_ERROR)
				{
					dwRcvBuffSizeUsed+=dwBytesReceived;
				}else{
					bContinue=FALSE;
				}
				break;
			}
			InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());
		}
		Netlib_CloseHandle(nls.hReadConns[0]);

		if (dwRcvBuffSizeUsed)
		{// received, work with data
			lpszPort=(LPSTR)MemoryFindByte(0,btBuff,dwRcvBuffSizeUsed,':');
			if (lpszPort)
			{
				(*lpszPort)=0;
				lpszPort++;

				lstrcpynA(lpszHost,(LPSTR)btBuff,dwHostBuffSize);
				if (pwPort) (*pwPort)=(WORD)StrToUNum32(lpszPort,(dwRcvBuffSizeUsed-(lpszPort-(LPSTR)btBuff)));
				dwRetErrorCode=NO_ERROR;
			}else{
				dwRetErrorCode=ERROR_INVALID_USER_BUFFER;
				ShowFormatedErrorMessage(L"NLB data corrupted",NO_ERROR);
			}
		}else{
			dwRetErrorCode=GetLastError();
			ShowFormatedErrorMessage(L"Can't get data for NLB, error",dwRetErrorCode);
		}
	}else{
		dwRetErrorCode=GetLastError();
		ShowFormatedErrorMessage(L"Can't connect to NLB server, error",dwRetErrorCode);
	}
return(dwRetErrorCode);
}


DWORD MraNetworkDispather()
{
	DWORD dwRetErrorCode=NO_ERROR;

	BOOL bContinue=TRUE;
	DWORD dwSelectRet,dwBytesReceived,dwDataCurrentBuffSize,dwDataCurrentBuffSizeUsed,dwPingPeriod=MAXDWORD,dwNextPingSendTickTime=MAXDWORD;
	SIZE_T dwRcvBuffSize=BUFF_SIZE_RCV,dwRcvBuffSizeUsed=0,dwDataCurrentBuffOffset=0;
	LPBYTE lpbBufferRcv;
	NETLIBSELECT nls={0};
	mrim_packet_header_t *pmaHeader;

	nls.cbSize=sizeof(nls);
	nls.dwTimeout=NETLIB_SELECT_TIMEOUT;
	nls.hReadConns[0]=masMraSettings.hConnection;

	lpbBufferRcv=(LPBYTE)MEMALLOC(dwRcvBuffSize);

	masMraSettings.dwCMDNum=0;
	MraSendCMD(MRIM_CS_HELLO,NULL,0);
	InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount());
	while(MraGetStatus(0,0)!=ID_STATUS_OFFLINE && bContinue)
	{
		dwSelectRet=CallService(MS_NETLIB_SELECT,0,(LPARAM)&nls);
		switch(dwSelectRet){
		case SOCKET_ERROR:
			if (MraGetStatus(0,0)!=ID_STATUS_OFFLINE)
			{
				dwRetErrorCode=GetLastError();
				ShowFormatedErrorMessage(L"Disconnected, socket error",dwRetErrorCode);
			}
			bContinue=FALSE;
			break;
		case 0:// Time out
		case 1:
			dwBytesReceived=GetTickCount();
			InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,dwBytesReceived);
			if (dwNextPingSendTickTime<=dwBytesReceived)
			{// server ping
				dwNextPingSendTickTime=(dwBytesReceived+(dwPingPeriod*1000));
				MraSendCMD(MRIM_CS_PING,NULL,0);
			}
			{
				DWORD dwCMDNum,dwFlags,dwAckType;
				HANDLE hContact;
				LPBYTE lpbData;
				SIZE_T dwDataSize;
				while (MraSendQueueFindOlderThan(masMraSettings.hSendQueueHandle,SEND_QUEUE_TIMEOUT,&dwCMDNum,&dwFlags,&hContact,&dwAckType,&lpbData,&dwDataSize)==NO_ERROR)
				{
					switch(dwAckType){
					case ACKTYPE_ADDED:
					case ACKTYPE_AUTHREQ:
					case ACKTYPE_CONTACTS:
						//nothink to do
						break;
					case ACKTYPE_MESSAGE:
						ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)dwCMDNum,(LPARAM)"Undefined message deliver error, time out",-1);
						break;
					case ACKTYPE_GETINFO:
						ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)1,(LPARAM)NULL,0);
						break;
					case ACKTYPE_SEARCH:
						ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)dwCMDNum,(LPARAM)NULL,0);
						break;
					case ICQACKTYPE_SMS:
						MEMFREE(lpbData);
						break;
					}
					MraSendQueueFree(masMraSettings.hSendQueueHandle,dwCMDNum);
				}
			}
			if (dwSelectRet==0) break;// Time out


			if ((dwRcvBuffSize-dwRcvBuffSizeUsed)<BUFF_SIZE_RCV_MIN_FREE)
			{// ������������ ���������� ������� �����
				dwRcvBuffSize+=BUFF_SIZE_RCV;
				lpbBufferRcv=(LPBYTE)MEMREALLOC(lpbBufferRcv,dwRcvBuffSize);
			}

			dwBytesReceived=Netlib_Recv(nls.hReadConns[0],(LPSTR)(lpbBufferRcv+dwRcvBuffSizeUsed),(dwRcvBuffSize-dwRcvBuffSizeUsed),0);
			if (dwBytesReceived && dwBytesReceived!=SOCKET_ERROR)
			{// connected
				dwRcvBuffSizeUsed+=dwBytesReceived;

				while(TRUE)
				{// ������ ���������
					dwDataCurrentBuffSize=(dwRcvBuffSize-dwDataCurrentBuffOffset);
					dwDataCurrentBuffSizeUsed=(dwRcvBuffSizeUsed-dwDataCurrentBuffOffset);
					pmaHeader=(mrim_packet_header_t*)(lpbBufferRcv+dwDataCurrentBuffOffset);
					if (dwDataCurrentBuffSizeUsed>=sizeof(mrim_packet_header_t))
					{// packet header received
						if (pmaHeader->magic==CS_MAGIC)
						{// packet OK
							if ((dwDataCurrentBuffSizeUsed-sizeof(mrim_packet_header_t))>=pmaHeader->dlen)
							{// full packet received, may be more than one

								MraCommandDispather(pmaHeader,&dwPingPeriod,&dwNextPingSendTickTime,&bContinue);
								
								if ((dwDataCurrentBuffSizeUsed-sizeof(mrim_packet_header_t))>pmaHeader->dlen)
								{// move pointer to next packet in buffer
									dwDataCurrentBuffOffset+=(sizeof(mrim_packet_header_t)+pmaHeader->dlen);
								}else{// move pointer to begin of buffer
									if (dwRcvBuffSize>BUFF_SIZE_RCV)
									{// ������������ ���������� ������� �����
										dwRcvBuffSize=BUFF_SIZE_RCV;
										lpbBufferRcv=(LPBYTE)MEMREALLOC(lpbBufferRcv,dwRcvBuffSize);
									}
									dwDataCurrentBuffOffset=0;
									dwRcvBuffSizeUsed=0;
									break;
								}
							}else{// not all packet received, continue receiving
								if (dwDataCurrentBuffOffset)
								{
									memmove(lpbBufferRcv,(lpbBufferRcv+dwDataCurrentBuffOffset),dwDataCurrentBuffSizeUsed);
									dwRcvBuffSizeUsed=dwDataCurrentBuffSizeUsed;
									dwDataCurrentBuffOffset=0;
								}
								DebugPrintCRLFW(L"Not all packet received, continue receiving");
								break;
							}
						}else{// bad packet
							DebugPrintCRLFW(L"Bad packet");
							dwDataCurrentBuffOffset=0;
							dwRcvBuffSizeUsed=0;
							break;
						}
					}else{// packet to small, continue receiving
						DebugPrintCRLFW(L"Packet to small, continue receiving");
						memmove(lpbBufferRcv,(lpbBufferRcv+dwDataCurrentBuffOffset),dwDataCurrentBuffSizeUsed);
						dwRcvBuffSizeUsed=dwDataCurrentBuffSizeUsed;
						dwDataCurrentBuffOffset=0;
						break;
					}
				}
			}else{// disconnected
				if (MraGetStatus(0,0)!=ID_STATUS_OFFLINE)
				{
					dwRetErrorCode=GetLastError();
					ShowFormatedErrorMessage(L"Disconnected, socket read error",dwRetErrorCode);
				}
				bContinue=FALSE;
			}
			break;
		}// end switch
	}// end while
	MEMFREE(lpbBufferRcv);

return(dwRetErrorCode);
}


DWORD MraCommandDispather(mrim_packet_header_t *pmaHeader,DWORD *pdwPingPeriod,DWORD *pdwNextPingSendTickTime,BOOL *pbContinue)
{
	WCHAR szBuff[4096]={0};
	DWORD dwDataSize,dwTemp,dwAckType;
	SIZE_T dwStringSize;
	MRA_LPS lpsString={0},lpsEMail={0};
	HANDLE hContact=NULL;
	LPBYTE lpbData,lpbDataCurrent;

	lpbData=((((LPBYTE)pmaHeader))+sizeof(mrim_packet_header_t));
	lpbDataCurrent=lpbData;
	dwDataSize=pmaHeader->dlen;


	switch(pmaHeader->msg){
	case MRIM_CS_HELLO_ACK://������������� ��������� ����������// UL ## ping_period ## ��������� ������� ������������� ���������� (� ��������)
		//CredUIPromptForCredentials
		//CYPTPROTECTMEMORY_BLOCK_SIZE=RTL_ENCRYPT_MEMORY_SIZE=8
		//CryptProtectMemory(szBuff,sizeof(szBuff),CRYPTPROTECTMEMORY_SAME_PROCESS);
		if(GetPassDB((LPSTR)szBuff,SIZEOF(szBuff),&dwStringSize))
		{//bit of a security hole here, since it's easy to extract a password from an edit box
			CHAR szEMail[MAX_EMAIL_LEN],szSelfVersionString[MAX_PATH],szUserAgentFormated[USER_AGENT_MAX+MAX_PATH],szValueName[MAX_PATH];
			WCHAR wszStatusTitle[STATUS_TITLE_MAX+4],wszStatusDesc[STATUS_DESC_MAX+4];
			DWORD dwStatus,dwXStatus,dwXStatusMir,dwFutureFlags;
			LPWSTR lpwszStatusTitle,lpwszStatusDesc;
			SIZE_T dwEMailSize,dwSelfVersionSize,dwStatusTitleSize,dwStatusDescSize,dwUserAgentFormatedSize;

			dwXStatusMir=MraGetXStatusInternal();
			dwStatus=GetMraStatusFromMiradaStatus(masMraSettings.dwDesiredStatusMode,dwXStatusMir,&dwXStatus);
			if (IsXStatusValid(dwXStatusMir))
			{// xstatuses
				mir_snprintf(szValueName,SIZEOF(szValueName),"XStatus%ldName",dwXStatusMir);
				if (DB_Mra_GetStaticStringW(NULL,szValueName,wszStatusTitle,(STATUS_TITLE_MAX+1),&dwStatusTitleSize))
				{// custom xstatus name
					lpwszStatusTitle=wszStatusTitle;
				}else{// default xstatus name
					lpwszStatusTitle=TranslateW(lpcszXStatusNameDef[dwXStatusMir]);
					dwStatusTitleSize=lstrlenW(lpwszStatusTitle);
				}

				mir_snprintf(szValueName,SIZEOF(szValueName),"XStatus%ldMsg",dwXStatusMir);
				if (DB_Mra_GetStaticStringW(NULL,szValueName,wszStatusDesc,(STATUS_DESC_MAX+1),&dwStatusDescSize))
				{// custom xstatus description
					lpwszStatusDesc=wszStatusDesc;
				}else{// default xstatus description
					lpwszStatusDesc=NULL;
					dwStatusDescSize=0;
				}
			}else{// not xstatuses
				lpwszStatusTitle=GetStatusModeDescriptionW(masMraSettings.dwDesiredStatusMode);
				dwStatusTitleSize=lstrlenW(lpwszStatusTitle);
				lpwszStatusDesc=NULL;
				dwStatusDescSize=0;
			}

			MraGetSelfVersionString(szSelfVersionString,SIZEOF(szSelfVersionString),&dwSelfVersionSize);
			if (DB_Mra_GetStaticStringA(NULL,"MirVerCustom",szUserAgentFormated,SIZEOF(szUserAgentFormated),&dwUserAgentFormatedSize)==FALSE)
			{
				dwUserAgentFormatedSize=mir_snprintf(szUserAgentFormated,SIZEOF(szUserAgentFormated),"client=\"magent\" name=\"Miranda IM\" title=\"%s\" version=\"777.%lu.%lu.%lu\" build=\"%lu\" protocol=\"%lu.%lu\"",szSelfVersionString,(((PLUGIN_VERSION_DWORD)>>24)&0xFF),(((PLUGIN_VERSION_DWORD)>>16)&0xFF),(((PLUGIN_VERSION_DWORD)>>8)&0xFF),((PLUGIN_VERSION_DWORD)&0xFF),PROTO_MAJOR(PROTO_VERSION),PROTO_MINOR(PROTO_VERSION));// "client=\"magent\" version=\"9.3\" build=\"777\""
			}

			dwFutureFlags=((DB_Mra_GetByte(NULL,"RTFReceiveEnable",MRA_DEFAULT_RTF_RECEIVE_ENABLE)? FEATURE_FLAG_RTF_MESSAGE:0)|MRA_FEATURE_FLAGS);

			if (DB_Mra_GetStaticStringA(NULL,"e-mail",szEMail,SIZEOF(szEMail),&dwEMailSize))
			{
				MraSendCommand_Login2W(szEMail,dwEMailSize,(LPSTR)szBuff,dwStringSize,dwStatus,lpcszStatusUri[dwXStatus],lstrlenA(lpcszStatusUri[dwXStatus]),lpwszStatusTitle,dwStatusTitleSize,lpwszStatusDesc,dwStatusDescSize,dwFutureFlags,szUserAgentFormated,dwUserAgentFormatedSize,szSelfVersionString,dwSelfVersionSize);
			}else{// no login
				(*pbContinue)=FALSE;
			}
			SecureZeroMemory(szBuff,sizeof(szBuff));
		}else{// no password
			(*pbContinue)=FALSE;
		}
		(*pdwPingPeriod)=GetUL(&lpbDataCurrent);
		break;
	case MRIM_CS_LOGIN_ACK://�������� �����������
		masMraSettings.bLoggedIn=TRUE;
		(*pdwNextPingSendTickTime)=0;// force send ping
		MraSendCMD(MRIM_CS_PING,NULL,0);
		MraSetStatus(masMraSettings.dwDesiredStatusMode,masMraSettings.dwDesiredStatusMode);
		//(*((LPBYTE)NULL))=1;// force exception
		//while(TRUE) Sleep(1); // force infinite loop
		MraAvatarsQueueGetAvatarSimple(masMraSettings.hAvatarsQueueHandle,GAIF_FORCE,NULL,0);
		break;
	case MRIM_CS_LOGIN_REJ://�������� ����������� //LPS ## reason ## ������� ������
		ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,ACKTYPE_LOGIN,ACKRESULT_FAILED,NULL,LOGINERR_WRONGPASSWORD,0);

		GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
		dwStringSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsString.lpszData,lpsString.dwSize,szBuff,SIZEOF(szBuff));
		szBuff[dwStringSize]=0;
		MraPopupShowW(NULL,MRA_POPUP_TYPE_ERROR,0,TranslateW(L"Logon error: invalid login/password"),szBuff);
		(*pbContinue)=FALSE;
		break;
	case MRIM_CS_MESSAGE_ACK:// �������� ���������
		{
			DWORD dwMsgID,dwFlags;
			MRA_LPS lpsText,lpsRTFText,lpsMultiChatData;

			dwMsgID=GetUL(&lpbDataCurrent);
			dwFlags=GetUL(&lpbDataCurrent);
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);//LPS ## from ## ����� �����������
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsText);//LPS ## message ## ��������� ������ ���������
			//if (dwFlags&MESSAGE_FLAG_RTF)
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsRTFText);//LPS ## rtf-message ## ��������������� ������ ���������
			if (dwFlags&MESSAGE_FLAG_MULTICHAT) GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsMultiChatData); // LPS multichat_data

			if (MraRecvCommand_Message((DWORD)_time32(NULL),dwFlags,&lpsEMail,&lpsText,&lpsRTFText,&lpsMultiChatData)==NO_ERROR)
			{// ������������ ���������, ������ ���� ������� ��� ����������
				if ((dwFlags&MESSAGE_FLAG_NORECV)==0)
				{// need send delivery status
					MraSendCommand_MessageRecv(lpsEMail.lpszData,lpsEMail.dwSize,dwMsgID);
				}
			}
		}
		break;
	case MRIM_CS_MESSAGE_STATUS:
		if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR)
		{
			dwTemp=GetUL(&lpbDataCurrent);
			switch(dwTemp){
			case MESSAGE_DELIVERED:// Message delivered directly to user
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)pmaHeader->seq,(LPARAM)NULL,0);
				break;//***deb �������� ���� ��-�� ������������� �� ��� ��������� ���������
			case MESSAGE_REJECTED_NOUSER:// Message rejected - no such user
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Message rejected - no such user",-1);
				break;
			case MESSAGE_REJECTED_INTERR:// Internal server error
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Internal server error",-1);
				break;
			case MESSAGE_REJECTED_LIMIT_EXCEEDED:// Offline messages limit exceeded
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Offline messages limit exceeded",-1);
				break;
			case MESSAGE_REJECTED_TOO_LARGE:// Message is too large
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Message is too large",-1);
				break;
			case MESSAGE_REJECTED_DENY_OFFMSG:// User does not accept offline messages
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"User does not accept offline messages",-1);
				break;
			case MESSAGE_REJECTED_DENY_OFFFLSH:// User does not accept offline flash animation
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"User does not accept offline flash animation",-1);
				break;
			default:
				dwTemp=mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),"Undefined message deliver error, code: %lu",dwTemp);
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)szBuff,dwTemp);
				break;
			}
			MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq);
		}else{// not found in queue
			if (GetUL(&lpbDataCurrent)!=MESSAGE_DELIVERED) MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_CS_MESSAGE_STATUS: not found in queue"));
		}
		break;
	case MRIM_CS_CONNECTION_PARAMS:// ��������� ���������� ���������� 
		(*pdwPingPeriod)=GetUL(&lpbDataCurrent);
		(*pdwNextPingSendTickTime)=0;// force send ping
		MraSendCMD(MRIM_CS_PING,NULL,0);
		break;
	case MRIM_CS_USER_INFO:
		while (lpbDataCurrent<(lpbData+dwDataSize))
		{
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"MESSAGES.TOTAL",14)==CSTR_EQUAL)
			{
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				masMraSettings.dwEmailMessagesTotal=StrToUNum32(lpsString.lpszData,lpsString.dwSize);
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"MESSAGES.UNREAD",15)==CSTR_EQUAL)
			{
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				masMraSettings.dwEmailMessagesUnRead=StrToUNum32(lpsString.lpszData,lpsString.dwSize);
			}else			
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"MRIM.NICKNAME",13)==CSTR_EQUAL)
			{
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				DB_Mra_SetLPSStringW(NULL,"Nick",&lpsString);
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"client.endpoint",15)==CSTR_EQUAL)
			{
				LPSTR lpszDelimiter;

				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				dwStringSize=WideCharToMultiByte(MRA_CODE_PAGE,0,lpsString.lpwszData,lpsString.dwSize,(LPSTR)szBuff,sizeof(szBuff),NULL,NULL);
				lpszDelimiter=(LPSTR)MemoryFind(0,szBuff,dwStringSize,":",1);
				if (lpszDelimiter)
				{
					(*lpszDelimiter)=0;
					lpszDelimiter=(LPSTR)szBuff;
					DB_Mra_SetDword(NULL,"IP",HTONL(inet_addr(lpszDelimiter)));
				}
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"connect.xml",11)==CSTR_EQUAL)
			{
				DebugPrintA(lpsString.lpszData);
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				DebugPrintCRLFW(lpsString.lpwszData);
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.show_title",18)==CSTR_EQUAL)
			{
				DebugPrintA(lpsString.lpszData);
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				DebugPrintCRLFW(lpsString.lpwszData);
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.status.id",17)==CSTR_EQUAL)
			{
				DWORDLONG dwBlogStatusID;

				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				dwBlogStatusID=StrToUNum64(lpsString.lpszData,lpsString.dwSize);
				DB_Mra_WriteContactSettingBlob(NULL,DBSETTING_BLOGSTATUSID,&dwBlogStatusID,sizeof(DWORDLONG));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.status.time",19)==CSTR_EQUAL)
			{
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.status.text",19)==CSTR_EQUAL)
			{
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				DB_Mra_SetLPSStringW(NULL,DBSETTING_BLOGSTATUS,&lpsString);
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"HAS_MYMAIL",10)==CSTR_EQUAL)
			{// ???
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				//DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"mrim.status.open_search",23)==CSTR_EQUAL)
			{// ???
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				//DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"rb.target.cookie",16)==CSTR_EQUAL)
			{// ???
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				//DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"show_web_history_link",21)==CSTR_EQUAL)
			{// ???
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				//DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"friends_suggest",15)==CSTR_EQUAL)
			{// ???
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				//DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"timestamp",9)==CSTR_EQUAL)
			{// ???
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				//DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"trusted_update",14)==CSTR_EQUAL)
			{// ???
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				//DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize));
			}else{
			#ifdef _DEBUG
				LPSTR lpszCurrentPos=(LPSTR)szBuff;
				memmove(lpszCurrentPos,lpsString.lpszData,lpsString.dwSize);
				lpszCurrentPos+=lpsString.dwSize;
				(*((WORD*)lpszCurrentPos))=(*((WORD*)": "));
				lpszCurrentPos+=sizeof(WORD);

				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
				memmove(lpszCurrentPos,lpsString.lpszData,lpsString.dwSize);
				lpszCurrentPos+=lpsString.dwSize;
				(*((WORD*)lpszCurrentPos))=(*((WORD*)szCRLF));
				lpszCurrentPos+=sizeof(WORD);(*((WORD*)lpszCurrentPos))=0;

				DebugPrintCRLFA((LPSTR)szBuff);
				//MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,szBuff);
				DebugBreak();
			#endif
			}	
		}
		MraUpdateEmailStatus(NULL,0,NULL,0,0,0);
		break;
	case MRIM_CS_OFFLINE_MESSAGE_ACK://��������� ������������, ���� ������������ �� ��� ��������� � ���� 
		{
			DWORD dwTime,dwFlags;
			MRA_LPS lpsText,lpsRTFText,lpsMultiChatData;
			LPBYTE lpbBuff=NULL;
			DWORDLONG dwMsgUIDL;

			dwMsgUIDL=GetUIDL(&lpbDataCurrent);
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);

			if (MraOfflineMessageGet(&lpsString,&dwTime,&dwFlags,&lpsEMail,&lpsText,&lpsRTFText,&lpsMultiChatData,&lpbBuff)==NO_ERROR)
			{
				dwTemp=MraRecvCommand_Message(dwTime,dwFlags,&lpsEMail,&lpsText,&lpsRTFText,&lpsMultiChatData);
				if (dwTemp==NO_ERROR || dwTemp==ERROR_ACCESS_DENIED)
				{// ������������ ���������, ������ ���� ������� ��� ����������
					MraSendCommand_OfflineMessageDel(dwMsgUIDL);
				}else{
					ShowFormatedErrorMessage(L"Offline message processing error, message will not deleted from server",NO_ERROR);
				}
			}else{
				ShowFormatedErrorMessage(L"Offline message processing error, message will not deleted from server",NO_ERROR);
			}
			MEMFREE(lpbBuff);
		}
		break;
	case MRIM_CS_AUTHORIZE_ACK://���������� �� ����������� 
		{// ��� �����������, �� ��������� ��� �������� ����������� �� ��������� �������, ������ ���� � ��� � ������
			BOOL bAdded;
			BYTE btBuff[BUFF_SIZE_BLOB];
			DBEVENTINFO dbei={0};

			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);
			hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,&bAdded);
			if (bAdded) MraUpdateContactInfo(hContact);

			if (IsEMailChatAgent(lpsEMail.lpszData,lpsEMail.dwSize)==FALSE)
			{
				dbei.cbSize=sizeof(dbei);
				dbei.szModule=PROTOCOL_NAMEA;
				dbei.timestamp=(DWORD)_time32(NULL);
				dbei.flags=0;
				dbei.eventType=EVENTTYPE_ADDED;
				//dbei.cbBlob=0;
				CreateBlobFromContact(hContact,NULL,0,(LPBYTE)&btBuff,SIZEOF(btBuff),&dwStringSize);
				dbei.cbBlob=dwStringSize;
				dbei.pBlob=btBuff;

				CallService(MS_DB_EVENT_ADD,(WPARAM)NULL,(LPARAM)&dbei);
			}

			GetContactBasicInfoW(hContact,NULL,NULL,NULL,&dwTemp,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL);
			dwTemp&=~CONTACT_INTFLAG_NOT_AUTHORIZED;
			SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,SCBIF_SERVER_FLAG,0,0,0,dwTemp,0,NULL,0,NULL,0,NULL,0);
			DB_Mra_SetDword(hContact,"HooksLocked",TRUE);
			DBDeleteContactSetting(hContact,"CList","NotOnList");
			DB_Mra_SetDword(hContact,"HooksLocked",FALSE);
		}
		break;
	case MRIM_CS_MPOP_SESSION://���� ��� web-����������� //
		if (GetUL(&lpbDataCurrent))
		{
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
			MraMPopSessionQueueSetNewMPopKey(masMraSettings.hMPopSessionQueue,lpsString.lpszData,lpsString.dwSize);
			MraMPopSessionQueueStart(masMraSettings.hMPopSessionQueue);
		}else{//error
			MraPopupShowFromAgentW(MRA_POPUP_TYPE_WARNING,0,TranslateW(L"Server error: cant get MPOP key for web authorize"));
			MraMPopSessionQueueFlush(masMraSettings.hMPopSessionQueue);
		}
		break;
/////////////////////////////////////////////////////////////////////////////////////
	case MRIM_CS_FILE_TRANSFER:
		{
			BOOL bAdded;
			DWORD dwIDRequest,dwFilesTotalSize;
			MRA_LPS lpsFiles={0},lpsFilesW={0},lpsAddreses={0};

			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS TO/FROM ANSI
			dwIDRequest=GetUL(&lpbDataCurrent);// DWORD id_request
			dwFilesTotalSize=GetUL(&lpbDataCurrent);// DWORD FILESIZE
			if (GetUL(&lpbDataCurrent))//LPS:
			{
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsFiles);// LPS Files (FileName;FileSize;FileName;FileSize;) ANSI
				if (GetUL(&lpbDataCurrent))// LPS DESCRIPTION
				{
					dwTemp=GetUL(&lpbDataCurrent);// ???
					DebugBreakIf(dwTemp!=1);
					GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsFilesW);// LPS Files (FileName;FileSize;FileName;FileSize;) UNICODE
				}
				GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsAddreses);// LPS Conn (IP:Port;IP:Port;) ANSI
			}

			hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,&bAdded);
			if (bAdded) MraUpdateContactInfo(hContact);

			bAdded=FALSE;
			if (lpsFilesW.dwSize==0)
			{
				lpsFilesW.lpwszData=(LPWSTR)MEMALLOC((lpsFiles.dwSize+MAX_PATH)*sizeof(WCHAR));
				if (lpsFilesW.lpwszData)
				{
					lpsFilesW.dwSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsFiles.lpszData,lpsFiles.dwSize,lpsFilesW.lpwszData,(lpsFiles.dwSize+MAX_PATH));
					bAdded=TRUE;
				}
			}

			if (lpsFilesW.dwSize) MraFilesQueueAddReceive(masMraSettings.hFilesQueueHandle,0,hContact,dwIDRequest,lpsFilesW.lpwszData,lpsFilesW.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize);
			if (bAdded) MEMFREE(lpsFilesW.lpwszData);
		}
		break;
	case MRIM_CS_FILE_TRANSFER_ACK:
		dwAckType=GetUL(&lpbDataCurrent);// DWORD status 
		GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS TO/FROM 
		dwTemp=GetUL(&lpbDataCurrent);// DWORD id_request
		GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS DESCRIPTION

		switch(dwAckType){
		case FILE_TRANSFER_STATUS_OK:// ����������, �� � ��� ��� ������� ����(���), �� ��� ��� �� ���������� ������ �� ������
			//hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,NULL);
			break;
		case FILE_TRANSFER_STATUS_DECLINE:
			MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwTemp,FALSE);
			break;
		case FILE_TRANSFER_STATUS_ERROR:
			ShowFormatedErrorMessage(L"File transfer: error",NO_ERROR);
			MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwTemp,FALSE);
			break;
		case FILE_TRANSFER_STATUS_INCOMPATIBLE_VERS:
			ShowFormatedErrorMessage(L"File transfer: incompatible versions",NO_ERROR);
			MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwTemp,FALSE);
			break;
		case FILE_TRANSFER_MIRROR:
			MraFilesQueueSendMirror(masMraSettings.hFilesQueueHandle,dwTemp,lpsString.lpszData,lpsString.dwSize);
			break;
		default:// ## unknown error
			mir_sntprintf(szBuff,SIZEOF(szBuff),TranslateW(L"MRIM_CS_FILE_TRANSFER_ACK: unknown error, code: %lu"),dwAckType);
			ShowFormatedErrorMessage(szBuff,NO_ERROR);
			break;
		}
		break;
/////////////////////////////////////////////////////////////////////////////////////
	case MRIM_CS_USER_STATUS://����� ������� ������� ������������
		{
			BOOL bAdded;
			DWORD dwStatus,dwXStatus,dwFutureFlags;
			MRA_LPS lpsSpecStatusUri,lpsStatusTitle,lpsStatusDesc,lpsUserAgentFormated;

			dwStatus=GetUL(&lpbDataCurrent);
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsSpecStatusUri);
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsStatusTitle);
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsStatusDesc);
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);
			dwFutureFlags=GetUL(&lpbDataCurrent);// com_support (>=1.14)
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsUserAgentFormated);


			if ((hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,&bAdded)))
			{
				if (bAdded) MraUpdateContactInfo(hContact);

				dwTemp=GetMiradaStatusFromMraStatus(dwStatus,GetMraXStatusIDFromMraUriStatus(lpsSpecStatusUri.lpszData,lpsSpecStatusUri.dwSize),&dwXStatus);
				
				MraContactCapabilitiesSet(hContact,dwFutureFlags);
				DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)dwXStatus);
				DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSNAME,&lpsStatusTitle);
				DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSMSG,&lpsStatusDesc);
				
				if (dwTemp!=ID_STATUS_OFFLINE)// ����� ������� ������ ���� ���� �� ��������, ����� �� �������� ������
				{
					if (lpsUserAgentFormated.dwSize)
					{// ���� �� ������
						if (DB_Mra_GetByte(NULL,"MirVerRaw",MRA_DEFAULT_MIRVER_RAW)==FALSE)
						{// �������� � ������������� ����, ���� ���������...
							MraGetVersionStringFromFormated(lpsUserAgentFormated.lpszData,lpsUserAgentFormated.dwSize,(LPSTR)szBuff,SIZEOF(szBuff),&dwStringSize);
							lpsUserAgentFormated.lpszData=(LPSTR)szBuff;
							lpsUserAgentFormated.dwSize=dwStringSize;
						}
					}else{// �� �� �� ������
						lpsUserAgentFormated.lpszData=MIRVER_UNKNOWN;
						lpsUserAgentFormated.dwSize=(sizeof(MIRVER_UNKNOWN)-1);
					}
					DB_Mra_SetLPSStringA(hContact,"MirVer",&lpsUserAgentFormated);
				}

				if (dwTemp==MraGetContactStatus(hContact))
				{// ������ ���� �� ����, �������������? ;)
					if (dwTemp==ID_STATUS_OFFLINE)
					{// was/now invisible
						WCHAR szEMail[MAX_EMAIL_LEN];

						DB_Mra_GetStaticStringW(hContact,"e-mail",szEMail,SIZEOF(szEMail),NULL);
						mir_sntprintf(szBuff,SIZEOF(szBuff),L"%s <%s> - %s",GetContactNameW(hContact),szEMail,TranslateW(L"invisible status changed"));
						MraPopupShowFromContactW(hContact,MRA_POPUP_TYPE_INFORMATION,0,szBuff);

						MraSetContactStatus(hContact,ID_STATUS_INVISIBLE);
					}else{// server or miranda bug or status change
						//DebugBreak();
					}
				}
				MraSetContactStatus(hContact,dwTemp);
				SetExtraIcons(hContact);
			}
		}
		break;
	case MRIM_CS_LOGOUT:// ������������ �������� ��-�� ������������� ����� � ��� �������.
		if (GetUL(&lpbDataCurrent)==LOGOUT_NO_RELOGIN_FLAG) ShowFormatedErrorMessage(L"Another user connected with your login",NO_ERROR);
		(*pbContinue)=FALSE;
		break;
	case MRIM_CS_ADD_CONTACT_ACK:
	case MRIM_CS_MODIFY_CONTACT_ACK:
		if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR)
		{
			dwTemp=GetUL(&lpbDataCurrent);
			switch(dwTemp){
			case CONTACT_OPER_SUCCESS:// ## ���������� ����������� �������
				if (pmaHeader->msg==MRIM_CS_ADD_CONTACT_ACK) SetContactBasicInfoW(hContact,0,(SCBIF_ID|SCBIF_SERVER_FLAG),GetUL(&lpbDataCurrent),0,0,CONTACT_INTFLAG_NOT_AUTHORIZED,0,NULL,0,NULL,0,NULL,0);
				break;
			case CONTACT_OPER_ERROR:// ## ���������� ������ ���� �����������
				ShowFormatedErrorMessage(L"Sended data is invalid",NO_ERROR);
				break;
			case CONTACT_OPER_INTERR:// ## ��� ��������� ������� ��������� ���������� ������
				ShowFormatedErrorMessage(L"Internal server error",NO_ERROR);
				break;
			case CONTACT_OPER_NO_SUCH_USER:// ## ������������ ������������ �� ���������� � �������
				SetContactBasicInfoW(hContact,0,SCBIF_SERVER_FLAG,0,0,0,-1,0,NULL,0,NULL,0,NULL,0);
				ShowFormatedErrorMessage(L"User does not registred",NO_ERROR);
				break;
			case CONTACT_OPER_INVALID_INFO:// ## ������������ ��� ������������
				ShowFormatedErrorMessage(L"Invalid user name",NO_ERROR);
				break;
			case CONTACT_OPER_USER_EXISTS:// ## ������������ ��� ���� � �������-�����
				ShowFormatedErrorMessage(L"User allready added",NO_ERROR);
				break;
			case CONTACT_OPER_GROUP_LIMIT:// ## ��������� ����������� ���������� ���������� ����� (20)
				ShowFormatedErrorMessage(L"Group limit is 20",NO_ERROR);
				break;
			default:// ## unknown error
				mir_sntprintf(szBuff,SIZEOF(szBuff),TranslateW(L"MRIM_CS_*_CONTACT_ACK: unknown server error, code: %lu"),dwTemp);
				MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,szBuff);
				break;
			}
			MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq);
		}else{// not found in queue
			MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_CS_*_CONTACT_ACK: not found in queue"));
		}
		break;
	case MRIM_CS_ANKETA_INFO:
		if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR)
		{
			switch(GetUL(&lpbDataCurrent)) {
			case MRIM_ANKETA_INFO_STATUS_OK:// ����� ������� ��������
				{
					DWORD dwFeildsNum,dwMaxRows,dwServerTime,dwStatus;
					SIZE_T i;
					MRA_LPS *pmralpsFeilds,*pmralpsValues;

					dwFeildsNum=GetUL(&lpbDataCurrent);
					dwMaxRows=GetUL(&lpbDataCurrent);
					dwServerTime=GetUL(&lpbDataCurrent);

					pmralpsFeilds=(MRA_LPS*)MEMALLOC(((dwFeildsNum*2)+4)*sizeof(MRA_LPS));
					if (pmralpsFeilds)
					{
						pmralpsValues=(pmralpsFeilds+dwFeildsNum);
						// read headers name
						for (i=0;i<dwFeildsNum;i++)
						{
							GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&pmralpsFeilds[i]);
							DebugPrintCRLFA(pmralpsFeilds[i].lpszData);
						}
						
						while (lpbDataCurrent<(lpbData+dwDataSize))
						{
							// read values
							for (i=0;i<dwFeildsNum;i++) GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&pmralpsValues[i]);

							if (dwAckType==ACKTYPE_GETINFO && hContact)
							{// write to DB and exit loop
								DB_Mra_SetDword(hContact,"InfoTS",(DWORD)_time32(NULL));
								//MRA_LPS mralpsUsernameValue;
								for (i=0;i<dwFeildsNum;i++)
								{
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Username",8)==CSTR_EQUAL)
									{
										//mralpsUsernameValue=pmralpsValues[i];
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Domain",6)==CSTR_EQUAL)
									{
										//memmove(szBuff,mralpsUsernameValue.lpszData,mralpsUsernameValue.dwSize);
										//(*((WORD*)&szBuff[mralpsUsernameValue.dwSize]))=(*((WORD*)"@"));
										//memmove(&szBuff[mralpsUsernameValue.dwSize+1],pmralpsValues[i].lpszData,pmralpsValues[i].dwSize);
										//(*((WORD*)&szBuff[pmralpsValues[i].dwSize+mralpsUsernameValue.dwSize+1]))=0;
										//DB_Mra_SetStringA(hContact,"e-mail",pmralpsValues[i].lpszData);
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Flags",5)==CSTR_EQUAL)
									{
										//***
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Nickname",8)==CSTR_EQUAL)
									{
										DB_Mra_SetLPSStringW(hContact,"Nick",&pmralpsValues[i]);
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"FirstName",9)==CSTR_EQUAL)
									{
										DB_Mra_SetLPSStringW(hContact,"FirstName",&pmralpsValues[i]);
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"LastName",8)==CSTR_EQUAL)
									{
										DB_Mra_SetLPSStringW(hContact,"LastName",&pmralpsValues[i]);
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Sex",3)==CSTR_EQUAL)
									{
										switch(StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize)) {
										case 1:// �������
											DB_Mra_SetByte(hContact,"Gender",'M');
											break;
										case 2:// �������
											DB_Mra_SetByte(hContact,"Gender",'F');
											break;
										default:// � ��� ��� �����
											DB_Mra_DeleteValue(hContact,"Gender");
											break;
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Birthday",8)==CSTR_EQUAL)
									{
										if (pmralpsValues[i].dwSize>9)
										{// calc "Age"
											SYSTEMTIME stTime={0};

											stTime.wYear=(WORD)StrToUNum32(pmralpsValues[i].lpszData,4);
											stTime.wMonth=(WORD)StrToUNum32((pmralpsValues[i].lpszData+5),2);
											stTime.wDay=(WORD)StrToUNum32((pmralpsValues[i].lpszData+8),2);
											DB_Mra_SetWord(hContact,"BirthYear",stTime.wYear);
											DB_Mra_SetByte(hContact,"BirthMonth",(BYTE)stTime.wMonth);
											DB_Mra_SetByte(hContact,"BirthDay",(BYTE)stTime.wDay);

											DB_Mra_SetWord(hContact,"Age",(WORD)GetYears(&stTime));
										}else{
											DB_Mra_DeleteValue(hContact,"BirthYear");
											DB_Mra_DeleteValue(hContact,"BirthMonth");
											DB_Mra_DeleteValue(hContact,"BirthDay");
											DB_Mra_DeleteValue(hContact,"Age");
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"City_id",7)==CSTR_EQUAL)
									{
										dwTemp=StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize);
										if (dwTemp)
										{
											for(SIZE_T j=0;mrapPlaces[j].lpszData;j++)
											{
												if (mrapPlaces[j].dwCityID==dwTemp)
												{
													DB_Mra_SetStringW(hContact,"City",mrapPlaces[j].lpszData);
													break;
												}
											}
										}else{
											DB_Mra_DeleteValue(hContact,"City");
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Location",8)==CSTR_EQUAL)
									{//***
										DB_Mra_SetLPSStringW(hContact,"About",&pmralpsValues[i]);
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Zodiac",6)==CSTR_EQUAL)
									{
										//***
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"BMonth",6)==CSTR_EQUAL)
									{// used Birthday
										//if (pmralpsValues[i].dwSize) DB_Mra_SetByte(hContact,"BirthMonth",(BYTE)StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize));
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"BDay",4)==CSTR_EQUAL)
									{// used Birthday
										//if (pmralpsValues[i].dwSize) DB_Mra_SetByte(hContact,"BirthDay",(BYTE)StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize));
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Country_id",10)==CSTR_EQUAL)
									{
										dwTemp=StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize);
										if (dwTemp)
										{
											for(SIZE_T j=0;mrapPlaces[j].lpszData;j++)
											{
												if (mrapPlaces[j].dwCountryID==dwTemp)
												{
													DB_Mra_SetStringW(hContact,"Country",mrapPlaces[j].lpszData);
													break;
												}
											}
										}else{
											DB_Mra_DeleteValue(hContact,"Country");
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Phone",5)==CSTR_EQUAL)
									{
										DB_Mra_DeleteValue(hContact,"Phone");
										DB_Mra_DeleteValue(hContact,"Cellular");
										DB_Mra_DeleteValue(hContact,"Fax");

										if (pmralpsValues[i].dwSize)
										{
											LPSTR lpszCurPos;

											lpsString.lpszData=pmralpsValues[i].lpszData;
											lpszCurPos=(LPSTR)MemoryFindByte(0,pmralpsValues[i].lpszData,pmralpsValues[i].dwSize,',');
											if (lpszCurPos)
											{
												lpsString.dwSize=(lpszCurPos-lpsString.lpszData);
											}else{
												lpsString.dwSize=((pmralpsValues[i].lpszData+pmralpsValues[i].dwSize)-lpsString.lpszData);
											}
											DB_Mra_SetLPSStringA(hContact,"Phone",&lpsString);

											if (lpszCurPos)
											{
												lpsString.lpszData=(++lpszCurPos);
												lpszCurPos=(LPSTR)MemoryFindByte((lpszCurPos-pmralpsValues[i].lpszData),pmralpsValues[i].lpszData,pmralpsValues[i].dwSize,',');
												if (lpszCurPos)
												{
													lpsString.dwSize=(lpszCurPos-lpsString.lpszData);
												}else{
													lpsString.dwSize=((pmralpsValues[i].lpszData+pmralpsValues[i].dwSize)-lpsString.lpszData);
												}
												DB_Mra_SetLPSStringA(hContact,"Cellular",&lpsString);
											}

											if (lpszCurPos)
											{
												lpsString.lpszData=(++lpszCurPos);
												lpszCurPos=(LPSTR)MemoryFindByte((lpszCurPos-pmralpsValues[i].lpszData),pmralpsValues[i].lpszData,pmralpsValues[i].dwSize,',');
												if (lpszCurPos)
												{
													lpsString.dwSize=(lpszCurPos-lpsString.lpszData);
												}else{
													lpsString.dwSize=((pmralpsValues[i].lpszData+pmralpsValues[i].dwSize)-lpsString.lpszData);
												}
												DB_Mra_SetLPSStringA(hContact,"Fax",&lpsString);
											}
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"mrim_status",11)==CSTR_EQUAL)
									{
										if (pmralpsValues[i].dwSize)
										{
											DWORD dwID,dwContactSeverFlags;

											GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL);
											if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED)
											{// ��� ��������������� ��� � ��� ��������� ���������� ������
												dwStatus=StrHexToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize);
												MraSetContactStatus(hContact,GetMiradaStatusFromMraStatus(dwStatus,MRA_MIR_XSTATUS_NONE,NULL));
												DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)MRA_MIR_XSTATUS_NONE);
											}
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"status_uri",10)==CSTR_EQUAL)
									{
										if (pmralpsValues[i].dwSize)
										{
											DWORD dwID,dwContactSeverFlags,dwXStatus;

											GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL);
											if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED)
											{// ��� ��������������� ��� � ��� ��������� ���������� ������
												MraSetContactStatus(hContact,GetMiradaStatusFromMraStatus(dwStatus,GetMraXStatusIDFromMraUriStatus(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize),&dwXStatus));
												DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)dwXStatus);
											}
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"status_title",12)==CSTR_EQUAL)
									{
										if (pmralpsValues[i].dwSize)
										{
											DWORD dwID,dwContactSeverFlags;

											GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL);
											if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED)
											{// ��� ��������������� ��� � ��� ��������� ���������� ������
												DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSNAME,&pmralpsValues[i]);
											}
										}
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"status_desc",11)==CSTR_EQUAL)
									{
										if (pmralpsValues[i].dwSize)
										{
											DWORD dwID,dwContactSeverFlags;

											GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL);
											if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED)
											{// ��� ��������������� ��� � ��� ��������� ���������� ������
												DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSMSG,&pmralpsValues[i]);
											}
										}
									}else{// for DEBUG ONLY
									#ifdef _DEBUG
										DebugPrintCRLFA(pmralpsFeilds[i].lpszData);
										DebugPrintCRLFA(pmralpsValues[i].lpszData);
										//DebugBreak();
									#endif
									}
								}
							}else
							if (dwAckType==ACKTYPE_SEARCH)
							{
								WCHAR szNick[MAX_EMAIL_LEN]={0},
									szFirstName[MAX_EMAIL_LEN]={0},
									szLastName[MAX_EMAIL_LEN]={0},
									szEMail[MAX_EMAIL_LEN]={0};
								MRA_LPS mralpsUsernameValue={0};
								PROTOSEARCHRESULT psr={0};

								psr.cbSize=sizeof(psr);
								psr.flags=PSR_UNICODE;
								psr.nick=szNick;
								psr.firstName=szFirstName;
								psr.lastName=szLastName;
								psr.email=szEMail;
								psr.id=szEMail;

								for (i=0;i<dwFeildsNum;i++)
								{
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Username",8)==CSTR_EQUAL)
									{
										mralpsUsernameValue=pmralpsValues[i];
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Domain",6)==CSTR_EQUAL)
									{// ��� ���� ��� ������ �����
										dwStringSize=MultiByteToWideChar(MRA_CODE_PAGE,0,mralpsUsernameValue.lpszData,mralpsUsernameValue.dwSize,szEMail,SIZEOF(szEMail));

										szEMail[dwStringSize]=(*((WCHAR*)L"@"));
										dwStringSize++;

										dwStringSize+=MultiByteToWideChar(MRA_CODE_PAGE,0,pmralpsValues[i].lpszData,pmralpsValues[i].dwSize,&szEMail[dwStringSize],(SIZEOF(szEMail)-(dwStringSize+1)));
										szEMail[dwStringSize]=0;
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Nickname",8)==CSTR_EQUAL)
									{
										dwStringSize=min((sizeof(szNick)-sizeof(WCHAR)),pmralpsValues[i].dwSize);
										memmove(szNick,pmralpsValues[i].lpwszData,dwStringSize);
										szNick[dwStringSize]=0;
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"FirstName",9)==CSTR_EQUAL)
									{
										dwStringSize=min((sizeof(szFirstName)-sizeof(WCHAR)),pmralpsValues[i].dwSize);
										memmove(szFirstName,pmralpsValues[i].lpwszData,dwStringSize);
										szFirstName[dwStringSize]=0;
									}else
									if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"LastName",8)==CSTR_EQUAL)
									{
										dwStringSize=min((sizeof(szLastName)-sizeof(WCHAR)),pmralpsValues[i].dwSize);
										memmove(szLastName,pmralpsValues[i].lpwszData,dwStringSize);
										szLastName[dwStringSize]=0;
									}
								}// end for
								ProtoBroadcastAck(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_DATA,(HANDLE)pmaHeader->seq,(LPARAM)&psr);
							}
						}// end while	

						MEMFREE(pmralpsFeilds);
					}
				}

				switch(dwAckType){
				case ACKTYPE_GETINFO:
					ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)1,(LPARAM)NULL,0);
					break;
				case ACKTYPE_SEARCH:
				default:
					ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)pmaHeader->seq,(LPARAM)NULL,0);
					break;
				}
				break;
			case MRIM_ANKETA_INFO_STATUS_NOUSER:// �� ������� �� ����� ���������� ������
				SetContactBasicInfoW(hContact,0,SCBIF_SERVER_FLAG,0,0,0,-1,0,NULL,0,NULL,0,NULL,0);
			case MRIM_ANKETA_INFO_STATUS_DBERR:// ������ ���� ������
			case MRIM_ANKETA_INFO_STATUS_RATELIMERR:// ������� ����� ��������, ����� �������� ��������
				switch(dwAckType){
				case ACKTYPE_GETINFO:
					ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)1,(LPARAM)NULL,0);
					break;
				case ACKTYPE_SEARCH:
					ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)pmaHeader->seq,(LPARAM)NULL,0);
					break;
				default:
					DebugBreak();
					break;
				}
				break;
			default:// unknown
				DebugBreak();
				break;
			}
			MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq);
		}else{// not found in queue
			MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_ANKETA_INFO: not found in queue"));
		}
		break;
	case MRIM_CS_MAILBOX_STATUS:
		dwTemp=GetUL(&lpbDataCurrent);
		if (dwTemp > masMraSettings.dwEmailMessagesTotal) masMraSettings.dwEmailMessagesTotal+=(dwTemp-masMraSettings.dwEmailMessagesUnRead);

		dwAckType=masMraSettings.dwEmailMessagesUnRead;// save old value
		masMraSettings.dwEmailMessagesUnRead=dwTemp;// store new value
		if (DB_Mra_GetByte(NULL,"IncrementalNewMailNotify",MRA_DEFAULT_INC_NEW_MAIL_NOTIFY)==0 || dwAckType<dwTemp || dwTemp==0)
		{
			MraUpdateEmailStatus(NULL,0,NULL,0,0,0);
		}
		break;
	case MRIM_CS_GAME:
		{
			DWORD dwGameSessionID,dwGameMsg,dwGameMsgID;

			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);//LPS to/from
			dwGameSessionID=GetUL(&lpbDataCurrent);//DWORD session unique per game
			dwGameMsg=GetUL(&lpbDataCurrent);//DWORD msg internal game message
			dwGameMsgID=GetUL(&lpbDataCurrent);//DWORD msg_id id for ack
			dwTemp=GetUL(&lpbDataCurrent);//DWORD time_send time of client
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);//LPS data

		#ifdef _DEBUG
			BYTE btBuff[1024]={0};
			memmove(btBuff,lpsString.lpszData,lpsString.dwSize);
		#endif

			switch(dwGameMsg){
			case GAME_CONNECTION_INVITE:
				if (MraGetStatus(0,0)!=ID_STATUS_INVISIBLE) MraSendCommand_Game(lpsEMail.lpszData,lpsEMail.dwSize,dwGameSessionID,GAME_DECLINE,dwGameMsgID,lpsString.lpszData,lpsString.dwSize);
				break;
			case GAME_CONNECTION_ACCEPT:
				break;
			case GAME_DECLINE:
				break;
			case GAME_INC_VERSION:
				break;
			case GAME_NO_SUCH_GAME:// user invisible
				if ((hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,FALSE,TRUE,NULL)))
				if (MraGetContactStatus(hContact)==ID_STATUS_OFFLINE)
				{
					MraSetContactStatus(hContact,ID_STATUS_INVISIBLE);
				}
				break;
			case GAME_JOIN:
				break;
			case GAME_CLOSE:
				break;
			case GAME_SPEED:
				break;
			case GAME_SYNCHRONIZATION:
				break;
			case GAME_USER_NOT_FOUND:
				break;
			case GAME_ACCEPT_ACK:
				break;
			case GAME_PING:
				break;
			case GAME_RESULT:
				break;
			case GAME_MESSAGES_NUMBER:
				break;
			default:
				mir_sntprintf(szBuff,SIZEOF(szBuff),TranslateW(L"MRIM_CS_GAME: unknown internal game message code: %lu"),dwGameMsg);
				MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,szBuff);
				break;
			}
		}
		break;
	case MRIM_CS_CONTACT_LIST2:
		dwTemp=GetUL(&lpbDataCurrent);
		if (dwTemp==GET_CONTACTS_OK)
		{// �������� ������� ����
			BOOL bAdded;
			char szGroupMask[MAX_PATH],szContactMask[MAX_PATH];
			DWORD dwID,dwGroupFlags,dwContactFlag,dwGroupID,dwContactSeverFlags,dwStatus,dwXStatus,dwFutureFlags,dwBlogStatusTime;
			MRA_LPS mralpsGroupName,mralpsNick,mralpsCustomPhones,lpsSpecStatusUri,lpsStatusTitle,lpsStatusDesc,lpsUserAgentFormated,lpsBlogStatus,lpsBlogStatusMusic;
			SIZE_T i,j,dwGroupsCount,dwGroupMaskSize,dwContactMaskSize,dwControlParam;
			ULARGE_INTEGER dwBlogStatusID;

			dwGroupsCount=GetUL(&lpbDataCurrent);
			
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
			dwGroupMaskSize=lpsString.dwSize;
			memmove(szGroupMask,lpsString.lpszData,dwGroupMaskSize);(*(szGroupMask+dwGroupMaskSize))=0;

			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
			dwContactMaskSize=lpsString.dwSize;
			memmove(szContactMask,lpsString.lpszData,dwContactMaskSize);(*(szContactMask+dwContactMaskSize))=0;

			DebugPrintCRLFW(L"Groups:");
			DebugPrintCRLFA(szGroupMask);
			dwID=0;
			for(i=0;i<dwGroupsCount;i++)//groups handle
			{
				dwControlParam=0;
				for(j=0;j<dwGroupMaskSize;j++)//enumerating parameters
				{
					switch(szGroupMask[j]) {
					case 's'://LPS
						GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
						break;
					case 'u'://UL
						dwTemp=GetUL(&lpbDataCurrent);
						break;
					case 'z'://sz
						lpsString.lpszData=(LPSTR)lpbDataCurrent;
						lpsString.dwSize=lstrlenA((LPSTR)lpbDataCurrent);
						lpbDataCurrent+=lpsString.dwSize;
						DebugBreak();
						break;
					}
					
					if (j==0 && szGroupMask[j]=='u')
					{// GroupFlags
						dwGroupFlags=dwTemp;
						dwControlParam++;
					}else
					if (j==1 && szGroupMask[j]=='s')
					{// GroupName
						mralpsGroupName=lpsString;
						dwControlParam++;
					}
				}
				
				// add/modify group
				if (dwControlParam>1)// ��� ��������� ��������� �����������������!
				//if (dwGroupFlags&CONTACT_FLAG_GROUP && (dwGroupFlags&CONTACT_FLAG_REMOVED)==0)
				{
					#ifdef _DEBUG
						memmove(szBuff,mralpsGroupName.lpszData,mralpsGroupName.dwSize);
						szBuff[(mralpsGroupName.dwSize/sizeof(WCHAR))]=0;
						DebugPrintW(szBuff);

						mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),": flags: %lu (",dwGroupFlags);
						DebugPrintA((LPSTR)szBuff);
						if (dwGroupFlags&CONTACT_FLAG_REMOVED)		DebugPrintA("CONTACT_FLAG_REMOVED, ");
						if (dwGroupFlags&CONTACT_FLAG_GROUP)		DebugPrintA("CONTACT_FLAG_GROUP, ");
						if (dwGroupFlags&CONTACT_FLAG_INVISIBLE)	DebugPrintA("CONTACT_FLAG_INVISIBLE, ");
						if (dwGroupFlags&CONTACT_FLAG_VISIBLE)		DebugPrintA("CONTACT_FLAG_VISIBLE, ");
						if (dwGroupFlags&CONTACT_FLAG_IGNORE)		DebugPrintA("CONTACT_FLAG_IGNORE, ");
						if (dwGroupFlags&CONTACT_FLAG_SHADOW)		DebugPrintA("CONTACT_FLAG_SHADOW, ");
						if (dwGroupFlags&CONTACT_FLAG_AUTHORIZED)	DebugPrintA("CONTACT_FLAG_AUTHORIZED, ");
						if (dwGroupFlags&CONTACT_FLAG_MULTICHAT)	DebugPrintA("CONTACT_FLAG_MULTICHAT, ");
						if (dwGroupFlags&CONTACT_FLAG_UNICODE_NAME)	DebugPrintA("CONTACT_FLAG_UNICODE_NAME, ");
						if (dwGroupFlags&CONTACT_FLAG_PHONE)		DebugPrintA("CONTACT_FLAG_PHONE, ");
						DebugPrintCRLFA(")");
					#endif//*/
				}
				dwID++;
			}// end for (processing groups)


			DebugPrintCRLFW(L"Contacts:");
			DebugPrintCRLFA(szContactMask);
			dwID=20;
			while (lpbDataCurrent<(lpbData+dwDataSize))
			{
				dwControlParam=0;
				for(j=0;j<dwContactMaskSize;j++)//enumerating parameters
				{
					switch(szContactMask[j]) {
					case 's'://LPS
						GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);
						break;
					case 'u'://UL
						dwTemp=GetUL(&lpbDataCurrent);
						break;
					case 'z'://sz
						lpsString.lpszData=(LPSTR)lpbDataCurrent;
						lpsString.dwSize=lstrlenA((LPSTR)lpbDataCurrent);
						lpbDataCurrent+=lpsString.dwSize;
						DebugBreak();
						break;
					}
					
					if (j==0 && szContactMask[j]=='u')
					{// Flags
						dwContactFlag=dwTemp;
						dwControlParam++;
					}else
					if (j==1 && szContactMask[j]=='u')
					{// Group id
						dwGroupID=dwTemp;
						dwControlParam++;
					}else
					if (j==2 && szContactMask[j]=='s')
					{// Email
						lpsEMail=lpsString;
						dwControlParam++;
					}else
					if (j==3 && szContactMask[j]=='s')
					{// Nick
						mralpsNick=lpsString;
						dwControlParam++;
					}else
					if (j==4 && szContactMask[j]=='u')
					{// Server flags
						dwContactSeverFlags=dwTemp;
						dwControlParam++;
					}else
					if (j==5 && szContactMask[j]=='u')
					{// Status
						dwStatus=dwTemp;
						dwControlParam++;
					}else
					if (j==6 && szContactMask[j]=='s')
					{// Custom Phone number,
						mralpsCustomPhones=lpsString;
						dwControlParam++;
					}else
					if (j==7 && szContactMask[j]=='s')
					{// spec_status_uri
						lpsSpecStatusUri=lpsString;
						dwControlParam++;
					}else
					if (j==8 && szContactMask[j]=='s')
					{// status_title
						lpsStatusTitle=lpsString;
						dwControlParam++;
					}else
					if (j==9 && szContactMask[j]=='s')
					{// status_desc
						lpsStatusDesc=lpsString;
						dwControlParam++;
					}else
					if (j==10 && szContactMask[j]=='u')
					{// com_support (future flags)
						dwFutureFlags=dwTemp;
						dwControlParam++;
					}else
					if (j==11 && szContactMask[j]=='s')
					{// user_agent (formated string)
						lpsUserAgentFormated=lpsString;
						dwControlParam++;
					}else
					if (j==12 && szContactMask[j]=='u')
					{// BlogStatusID
						dwBlogStatusID.LowPart=dwTemp;
						dwControlParam++;
					}else
					if (j==13 && szContactMask[j]=='u')
					{// BlogStatusID
						dwBlogStatusID.HighPart=dwTemp;
						dwControlParam++;
					}else
					if (j==14 && szContactMask[j]=='u')
					{// BlogStatusTime
						dwBlogStatusTime=dwTemp;
						dwControlParam++;
					}else
					if (j==15 && szContactMask[j]=='s')
					{// BlogStatus
						lpsBlogStatus=lpsString;
						dwControlParam++;
					}else
					if (j==16 && szContactMask[j]=='s')
					{// BlogStatusMusic
						lpsBlogStatusMusic=lpsString;
						dwControlParam++;
					}else
					if (j==17 && szContactMask[j]=='s')
					{// BlogStatusSender // ignory
						lpsString=lpsString;
						dwControlParam++;
					}else
					if (j==18 && szContactMask[j]=='s')
					{// geo data ?
						lpsString=lpsString;
						dwControlParam++;
					}else
					if (j==19 && szContactMask[j]=='s')
					{// ?????? ?
						lpsString=lpsString;
						dwControlParam++;
						DebugBreakIf(lpsString.dwSize);
					}else{
						if (szContactMask[j]=='s')
						{
							if (lpsString.dwSize)
							{
								//DebugPrintCRLFA(lpsString.lpszData);
								DebugPrintCRLFW(lpsString.lpwszData);
							}
						}else
						if (szContactMask[j]=='u')
						{
							mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),"%lu, ",dwTemp);//;
							DebugPrintCRLFA((LPSTR)szBuff);
						}else{
							DebugBreak();
						}
					}
				}


				#ifdef _DEBUG

					mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),"ID: %lu, Group id: %lu, ",dwID,dwGroupID);
					DebugPrintA((LPSTR)szBuff);


					memmove(szBuff,lpsEMail.lpszData,lpsEMail.dwSize);
					szBuff[(lpsEMail.dwSize/sizeof(WCHAR))]=0;
					DebugPrintA((LPSTR)szBuff);

					mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),": flags: %lu (",dwContactFlag);
					DebugPrintA((LPSTR)szBuff);
					if (dwContactFlag&CONTACT_FLAG_REMOVED)		DebugPrintA("CONTACT_FLAG_REMOVED, ");
					if (dwContactFlag&CONTACT_FLAG_GROUP)		DebugPrintA("CONTACT_FLAG_GROUP, ");
					if (dwContactFlag&CONTACT_FLAG_INVISIBLE)	DebugPrintA("CONTACT_FLAG_INVISIBLE, ");
					if (dwContactFlag&CONTACT_FLAG_VISIBLE)		DebugPrintA("CONTACT_FLAG_VISIBLE, ");
					if (dwContactFlag&CONTACT_FLAG_IGNORE)		DebugPrintA("CONTACT_FLAG_IGNORE, ");
					if (dwContactFlag&CONTACT_FLAG_SHADOW)		DebugPrintA("CONTACT_FLAG_SHADOW, ");
					if (dwContactFlag&CONTACT_FLAG_AUTHORIZED)	DebugPrintA("CONTACT_FLAG_AUTHORIZED, ");
					if (dwContactFlag&CONTACT_FLAG_MULTICHAT)	DebugPrintA("CONTACT_FLAG_MULTICHAT, ");
					if (dwContactFlag&CONTACT_FLAG_UNICODE_NAME)DebugPrintA("CONTACT_FLAG_UNICODE_NAME, ");
					if (dwContactFlag&CONTACT_FLAG_PHONE)		DebugPrintA("CONTACT_FLAG_PHONE, ");
					DebugPrintA(")");

					mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),": server flags: %lu (",dwContactSeverFlags);
					DebugPrintA((LPSTR)szBuff);
					if (dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED)		DebugPrintA("CONTACT_INTFLAG_NOT_AUTHORIZED, ");
					DebugPrintCRLFA(")");
				#endif//*/

				
				// add/modify contact
				if (dwGroupID!=103)//***deb filtering phone/sms contats
				if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsEMail.lpszData,lpsEMail.dwSize,"phone",5)!=CSTR_EQUAL)
				if (dwControlParam>5)// ��� ��������� ��������� �����������������!
				if ((dwContactFlag&(CONTACT_FLAG_GROUP|CONTACT_FLAG_REMOVED))==0)
				{
					hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,FALSE,&bAdded);
					if (hContact)
					{
						if (GetContactBasicInfoW(hContact,&dwTemp,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL)==NO_ERROR && dwTemp!=-1)
						{//deb ������� ��� � ������, ����� ���������!!!!
							dwTemp=dwTemp;
							//MraSendCommand_ModifyContactW(hContact,dwID,CONTACT_FLAG_REMOVED,dwGroupID,lpsEMail.lpszData,lpsEMail.dwSize,mralpsNick.lpszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize);
							DebugBreak();
						}else{
							dwTemp=GetMiradaStatusFromMraStatus(dwStatus,GetMraXStatusIDFromMraUriStatus(lpsSpecStatusUri.lpszData,lpsSpecStatusUri.dwSize),&dwXStatus);
							if ((dwContactFlag&CONTACT_FLAG_UNICODE_NAME)) mralpsNick.dwSize/=sizeof(WCHAR);

							if (bAdded)
							{// update user info
								SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,(SCBIF_ID|SCBIF_GROUP_ID|SCBIF_FLAG|SCBIF_SERVER_FLAG|SCBIF_STATUS|SCBIF_NICK|SCBIF_PHONES),dwID,dwGroupID,dwContactFlag,dwContactSeverFlags,dwTemp,NULL,0,mralpsNick.lpwszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize);

								// request user info from server
								MraUpdateContactInfo(hContact);
							}else{//****deb - check group ID param
								SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,(SCBIF_ID|SCBIF_GROUP_ID|SCBIF_SERVER_FLAG|SCBIF_STATUS),dwID,dwGroupID,dwContactFlag,dwContactSeverFlags,dwTemp,NULL,0,mralpsNick.lpwszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize);
								if (mralpsNick.dwSize==0)
								{// ����������� ��� � ����� �� �������
									lstrcpynW(szBuff,GetContactNameW(hContact),SIZEOF(szBuff));
									mralpsNick.lpwszData=szBuff;
									mralpsNick.dwSize=lstrlenW(mralpsNick.lpwszData);

									MraSendCommand_ModifyContactW(hContact,dwID,dwContactFlag,dwGroupID,lpsEMail.lpszData,lpsEMail.dwSize,mralpsNick.lpwszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize);
								}
							}

							MraContactCapabilitiesSet(hContact,dwFutureFlags);
							DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)dwXStatus);
							DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSNAME,&lpsStatusTitle);
							DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSMSG,&lpsStatusDesc);
							DB_Mra_SetDword(hContact,DBSETTING_BLOGSTATUSTIME,dwBlogStatusTime);
							DB_Mra_WriteContactSettingBlob(hContact,DBSETTING_BLOGSTATUSID,&dwBlogStatusID.QuadPart,sizeof(DWORDLONG));
							DB_Mra_SetLPSStringW(hContact,DBSETTING_BLOGSTATUS,&lpsBlogStatus);
							DB_Mra_SetLPSStringW(hContact,DBSETTING_BLOGSTATUSMUSIC,&lpsBlogStatusMusic);
							if (IsXStatusValid(dwXStatus)) SetExtraIcons(hContact);
							
							if (dwTemp!=ID_STATUS_OFFLINE)// ����� ������� ������ ���� ���� �� ��������, ����� �� �������� ������
							{
								if (lpsUserAgentFormated.dwSize)
								{// ���� �� ������
									if (DB_Mra_GetByte(NULL,"MirVerRaw",MRA_DEFAULT_MIRVER_RAW)==FALSE)
									{
										MraGetVersionStringFromFormated(lpsUserAgentFormated.lpszData,lpsUserAgentFormated.dwSize,(LPSTR)szBuff,SIZEOF(szBuff),&dwStringSize);
										lpsUserAgentFormated.lpszData=(LPSTR)szBuff;
										lpsUserAgentFormated.dwSize=dwStringSize;
									}
								}else{// �� �� �� ������
									lpsUserAgentFormated.lpszData=MIRVER_UNKNOWN;
									lpsUserAgentFormated.dwSize=(sizeof(MIRVER_UNKNOWN)-1);
								}
								DB_Mra_SetLPSStringA(hContact,"MirVer",&lpsUserAgentFormated);
							}

							if (dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED)
							if (DB_Mra_GetByte(NULL,"AutoAuthRequestOnLogon",MRA_DEFAULT_AUTO_AUTH_REQ_ON_LOGON)) CallProtoService(PROTOCOL_NAMEA,MRA_REQ_AUTH,(WPARAM)hContact,0);
						}
					}
				}
				dwID++;
			}// end while (processing contacts)

			// post processing contact list
			{
				CHAR szEMail[MAX_EMAIL_LEN],szPhones[MAX_EMAIL_LEN];
				WCHAR wszAuthMessage[MAX_PATH],wszNick[MAX_EMAIL_LEN];
				SIZE_T dwEMailSize,dwNickSize,dwPhonesSize,dwAuthMessageSize;

				if (DB_Mra_GetStaticStringW(NULL,"AuthMessage",wszAuthMessage,SIZEOF(wszAuthMessage),&dwAuthMessageSize)==FALSE)
				{// def auth message
					lstrcpynW(wszAuthMessage,TranslateW(MRA_DEFAULT_AUTH_MESSAGE),SIZEOF(wszAuthMessage));
					dwAuthMessageSize=lstrlenW(wszAuthMessage);
				}

				for(hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);hContact!=NULL;hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
				{
					if (GetContactBasicInfoW(hContact,&dwID,NULL,NULL,NULL,NULL,szEMail,SIZEOF(szEMail),&dwEMailSize,NULL,0,NULL,NULL,0,NULL)==NO_ERROR)
					if (dwID==-1)
					{
						if (IsEMailChatAgent(szEMail,dwEMailSize))
						{// ���: ��� ��� �������� �����������, ������� ��� ������� � ������, ����������
							DBDeleteContactSetting(hContact,"CList","Hidden");
							DBDeleteContactSetting(hContact,"CList","NotOnList");
							SetExtraIcons(hContact);
							MraSetContactStatus(hContact,ID_STATUS_ONLINE);

							lstrcpynW(szBuff,GetContactNameW(hContact),SIZEOF(szBuff));
							MraSendCommand_AddContactW(hContact,(CONTACT_FLAG_VISIBLE|CONTACT_FLAG_MULTICHAT|CONTACT_FLAG_UNICODE_NAME),-1,szEMail,dwEMailSize,szBuff,lstrlenW(szBuff),NULL,0,NULL,0,0);
						}else{
							if (DBGetContactSettingByte(hContact,"CList","NotOnList",0)==0)
							{// set extra icons and upload contact
								SetExtraIcons(hContact);
								if (DB_Mra_GetByte(NULL,"AutoAddContactsToServer",MRA_DEFAULT_AUTO_ADD_CONTACTS_TO_SERVER))
								{//add all contacts to server
									GetContactBasicInfoW(hContact,NULL,&dwGroupID,NULL,NULL,NULL,NULL,0,NULL,wszNick,SIZEOF(wszNick),&dwNickSize,szPhones,SIZEOF(szPhones),&dwPhonesSize);
									MraSendCommand_AddContactW(hContact,(CONTACT_FLAG_VISIBLE|CONTACT_FLAG_UNICODE_NAME),dwGroupID,szEMail,dwEMailSize,wszNick,dwNickSize,szPhones,dwPhonesSize,wszAuthMessage,dwAuthMessageSize,0);
								}
							}
						}
						MraUpdateContactInfo(hContact);
					}
				}
			}
		}else{// ������� ���� �������� �� ��������
			// ���� � offline � id � ����������
			for(HANDLE hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);hContact!=NULL;hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
			{// ������� ���� ��������� �������������� �������� � MRA
				SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,(SCBIF_ID|SCBIF_GROUP_ID|SCBIF_SERVER_FLAG|SCBIF_STATUS),-1,-2,0,0,ID_STATUS_OFFLINE,NULL,0,NULL,0,NULL,0);
				// request user info from server
				MraUpdateContactInfo(hContact);
			}

			if (dwTemp==GET_CONTACTS_ERROR)
			{// ��������� �������-���� �����������
				ShowFormatedErrorMessage(L"MRIM_CS_CONTACT_LIST2: bad contact list",NO_ERROR);
			}else
			if (dwTemp==GET_CONTACTS_INTERR)
			{// ��������� ���������� ������
				ShowFormatedErrorMessage(L"MRIM_CS_CONTACT_LIST2: internal server error",NO_ERROR);
			}else{
				mir_sntprintf(szBuff,SIZEOF(szBuff),TranslateW(L"MRIM_CS_CONTACT_LIST2: unknown server error, code: %lu"),dwTemp);
				MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,szBuff);
			}
		}
		break;
	case MRIM_CS_SMS_ACK:
		dwTemp=GetUL(&lpbDataCurrent);
		if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR)
		{
			char szEMail[MAX_EMAIL_LEN];
			LPSTR lpszPhone;
			LPWSTR lpwszMessage;
			SIZE_T dwEMailSize,dwPhoneSize,dwMessageSize;

			if (DB_Mra_GetStaticStringA(NULL,"e-mail",szEMail,SIZEOF(szEMail),&dwEMailSize))
			{
				dwPhoneSize=(*(DWORD*)lpsString.lpszData);
				dwMessageSize=lpsString.dwSize-(dwPhoneSize+sizeof(DWORD)+2);
				lpszPhone=(lpsString.lpszData+sizeof(DWORD));
				lpwszMessage=(LPWSTR)(lpszPhone+dwPhoneSize+1);

				dwTemp=mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),"<sms_response><source>Mail.ru</source><deliverable>Yes</deliverable><network>Mail.ru, Russia</network><message_id>%s-1-1955988055-%s</message_id><destination>%s</destination><messages_left>0</messages_left></sms_response>\r\n",szEMail,lpszPhone,lpszPhone);
				ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,dwAckType,ACKRESULT_SENTREQUEST,(HANDLE)pmaHeader->seq,(LPARAM)szBuff,dwTemp);
			}

			MEMFREE(lpsString.lpszData);
			MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq);
		}else{// not found in queue
			MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_CS_SMS_ACK: not found in queue"));
		}
		break;
	case MRIM_CS_PROXY:
		{
			DWORD dwIDRequest;
			MRA_LPS lpsAddreses={0};
			MRA_GUID mguidSessionID;
	
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS to
			dwIDRequest=GetUL(&lpbDataCurrent);// DWORD id_request
			dwAckType=GetUL(&lpbDataCurrent);// DWORD data_type
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS user_data
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsAddreses);// LPS lps_ip_port
			mguidSessionID=GetGUID(&lpbDataCurrent);// DWORD session_id[4]

			if (dwAckType==MRIM_PROXY_TYPE_FILES)
			{// �����, on file recv
				if (MraMrimProxySetData(MraFilesQueueItemProxyByID(masMraSettings.hFilesQueueHandle,dwIDRequest),lpsEMail.lpszData,lpsEMail.dwSize,dwIDRequest,dwAckType,lpsString.lpszData,lpsString.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize,&mguidSessionID)==NO_ERROR)
				{// ������ �������� ��� ����/proxy enabled// set proxy info to file transfer context
					MraFilesQueueStartMrimProxy(masMraSettings.hFilesQueueHandle,dwIDRequest);
				}else{// ������ ������/�� ������������
					MraSendCommand_ProxyAck(PROXY_STATUS_ERROR,lpsEMail.lpszData,lpsEMail.dwSize,dwIDRequest,dwAckType,lpsString.lpszData,lpsString.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize,mguidSessionID);
					DebugBreak();
				}
			}
			//DebugBreak();
		}
		break;
	case MRIM_CS_PROXY_ACK:
		{
			DWORD dwIDRequest;
			HANDLE hMraMrimProxyData;
			MRA_LPS lpsAddreses={0};
			MRA_GUID mguidSessionID;
	
			dwTemp=GetUL(&lpbDataCurrent);// DWORD status
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS to
			dwIDRequest=GetUL(&lpbDataCurrent);// DWORD id_request
			dwAckType=GetUL(&lpbDataCurrent);// DWORD data_type
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS user_data
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsAddreses);// LPS lps_ip_port
			mguidSessionID=GetGUID(&lpbDataCurrent);// DWORD session_id[4]

			if (dwAckType==MRIM_PROXY_TYPE_FILES)
			{// �����, on file send
				if ((hMraMrimProxyData=MraFilesQueueItemProxyByID(masMraSettings.hFilesQueueHandle,dwIDRequest)))
				{// ������ �������� ��� ����/proxy enabled
					switch(dwTemp){
					case PROXY_STATUS_DECLINE:
						MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwIDRequest,FALSE);
						break;
					case PROXY_STATUS_OK:
						if (MraMrimProxySetData(hMraMrimProxyData,lpsEMail.lpszData,lpsEMail.dwSize,dwIDRequest,dwAckType,lpsString.lpszData,lpsString.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize,&mguidSessionID)==NO_ERROR)
						{// set proxy info to file transfer context
							MraFilesQueueStartMrimProxy(masMraSettings.hFilesQueueHandle,dwIDRequest);
						}
						break;
					case PROXY_STATUS_ERROR:
						ShowFormatedErrorMessage(L"Proxy File transfer: error",NO_ERROR);
						MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwIDRequest,FALSE);
						break;
					case PROXY_STATUS_INCOMPATIBLE_VERS:
						ShowFormatedErrorMessage(L"Proxy File transfer: incompatible versions",NO_ERROR);
						MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwIDRequest,FALSE);
						break;
					case PROXY_STATUS_NOHARDWARE:
					case PROXY_STATUS_MIRROR:
					case PROXY_STATUS_CLOSED:
					default:
						DebugBreak();
						break;
					}
				}else{// ������ ������/�� ������������
					DebugBreak();
				}
			}

			/*if (dwTemp!=2)
			if ((hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,FALSE,TRUE,NULL)))
			if (MraGetContactStatus(hContact)==ID_STATUS_OFFLINE)
			{
				MraSetContactStatus(hContact,ID_STATUS_INVISIBLE);
			}*/

			//DebugBreak();
		}
		break;
	case MRIM_CS_PROXY_HELLO:
		// DWORD[4] Session_id
		DebugBreak();
		break;
	case MRIM_CS_PROXY_HELLO_ACK:
		DebugBreak();
		break;
	case MRIM_CS_NEW_MAIL:
		{
			DWORD dwDate,dwUIDL;

			dwTemp=GetUL(&lpbDataCurrent);// UL unread count
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS from
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS subject
			dwDate=GetUL(&lpbDataCurrent);// UL date
			dwUIDL=GetUL(&lpbDataCurrent);// UL uidl

			if (dwTemp > masMraSettings.dwEmailMessagesTotal) masMraSettings.dwEmailMessagesTotal+=(dwTemp-masMraSettings.dwEmailMessagesUnRead);

			dwAckType=masMraSettings.dwEmailMessagesUnRead;// save old value
			masMraSettings.dwEmailMessagesUnRead=dwTemp;// store new value
			if (DB_Mra_GetByte(NULL,"IncrementalNewMailNotify",MRA_DEFAULT_INC_NEW_MAIL_NOTIFY)==0 || dwAckType<dwTemp || dwTemp==0)
			{
				MraUpdateEmailStatus(lpsEMail.lpszData,lpsEMail.dwSize,lpsString.lpszData,lpsString.dwSize,dwDate,dwUIDL);
			}
		}
		break;
	case MRIM_CS_USER_BLOG_STATUS:
		{
			DWORD dwTime,dwFlags;
			MRA_LPS lpsText;
			LPBYTE lpbBuff=NULL;
			DWORDLONG dwBlogStatusID;

			dwFlags=GetUL(&lpbDataCurrent);// UL flags
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS user
			dwBlogStatusID=GetUIDL(&lpbDataCurrent);// UINT64 id
			dwTime=GetUL(&lpbDataCurrent);// UL time
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsText);// LPS text (MRIM_BLOG_STATUS_MUSIC: track)
			GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS reply_user_nick

			if ((hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,FALSE,TRUE,NULL)))
			{
				if (dwFlags&MRIM_BLOG_STATUS_MUSIC)
				{
					DB_Mra_SetLPSStringW(hContact,DBSETTING_BLOGSTATUSMUSIC,&lpsText);
				}else{
					DB_Mra_SetDword(hContact,DBSETTING_BLOGSTATUSTIME,dwTime);
					DB_Mra_WriteContactSettingBlob(hContact,DBSETTING_BLOGSTATUSID,&dwBlogStatusID,sizeof(DWORDLONG));
					DB_Mra_SetLPSStringW(hContact,DBSETTING_BLOGSTATUS,&lpsText);
				}
			}
		}
		break;

	case MRIM_CS_UNKNOWN:
		/*{
			BYTE btBuff[8192]={0};
			memmove(btBuff,lpbData,dwDataSize);
			DebugBreak();
		}*/
		break;
	case MRIM_CS_USER_GEO:
		/*{
			BYTE btBuff[8192]={0};
			memmove(btBuff,lpbData,dwDataSize);
			DebugBreak();
		}*/
		break;
	case MRIM_CS_SERVER_SETTINGS:
		/*{
			BYTE btBuff[8192]={0};
			memmove(btBuff,lpbData,dwDataSize);
			DebugBreak();
		}*/
		break;
	default:
#ifdef _DEBUG
		/*{
			HANDLE hFile=CreateFile("C:\\Documents and Settings\\Ivan\\������� ����\\MRIM_CS_CONTACT_LIST2.txt",GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

			if (hFile!=INVALID_HANDLE_VALUE)
			{
				WriteFile(hFile,lpbData,dwDataSize,&dwTemp,NULL);
				CloseHandle(hFile);
			}
		}//*/
		{
			BYTE btBuff[8192]={0};
			memmove(btBuff,lpbData,dwDataSize);
			DebugBreak();
		}
#endif
		break;
	}
return(0);
}


DWORD MraRecvCommand_Message(DWORD dwTime,DWORD dwFlags,MRA_LPS *plpsFrom,MRA_LPS *plpsText,MRA_LPS *plpsRFTText,MRA_LPS *plpsMultiChatData)
{// ���������
	BOOL bAdded;
	DWORD dwRetErrorCode=NO_ERROR,dwBackColour;
	LPSTR lpszMessageExt=NULL;
	LPWSTR lpwszMessage=NULL;
	SIZE_T dwMessageSize=0,dwMessageExtSize=0;
	CCSDATA ccs={0};
	PROTORECVEVENT pre={0};

	//ccs.wParam=0;
	ccs.lParam=(LPARAM)&pre;
	pre.timestamp=dwTime;

	// check flags and datas
	if (dwFlags&MESSAGE_FLAG_RTF)
	{
		if (plpsRFTText)
		{
			if (plpsRFTText->lpszData==NULL || plpsRFTText->dwSize==0) dwFlags&=~MESSAGE_FLAG_RTF;
		}else{
			dwFlags&=~MESSAGE_FLAG_RTF;
		}
	}

	if (dwFlags&MESSAGE_FLAG_MULTICHAT)
	{
		if (plpsMultiChatData)
		{
			if (plpsMultiChatData->lpszData==NULL || plpsMultiChatData->dwSize==0) dwFlags&=~MESSAGE_FLAG_MULTICHAT;
		}else{
			dwFlags&=~MESSAGE_FLAG_MULTICHAT;
		}
	}


	// pre processing - extracting/decoding
	if (dwFlags&MESSAGE_FLAG_AUTHORIZE)
	{// extract auth message �� �������� ������
		SIZE_T dwAuthPartsCount,dwAuthBuffSize=(plpsText->dwSize+32),dwAuthDataSize;
		LPBYTE lpbAuthData,lpbDataCurrent;
		MRA_LPS lpsAuthFrom,lpsAuthMessage;

		lpbAuthData=(LPBYTE)MEMALLOC(dwAuthBuffSize);
		if (lpbAuthData)
		{
			BASE64DecodeFormated(plpsText->lpszData,plpsText->dwSize,lpbAuthData,dwAuthBuffSize,&dwAuthDataSize);

			lpbDataCurrent=lpbAuthData;
			dwAuthPartsCount=GetUL(&lpbDataCurrent);
			if (GetLPS(lpbAuthData,dwAuthDataSize,&lpbDataCurrent,&lpsAuthFrom)==NO_ERROR)
			if (GetLPS(lpbAuthData,dwAuthDataSize,&lpbDataCurrent,&lpsAuthMessage)==NO_ERROR)
			{
				if (dwFlags&MESSAGE_FLAG_v1p16 && (dwFlags&MESSAGE_FLAG_CP1251)==0)
				{// unicode text
					memmove(lpbAuthData,lpsAuthMessage.lpszData,lpsAuthMessage.dwSize);
					lpwszMessage=(LPWSTR)lpbAuthData;
					dwMessageSize=(lpsAuthMessage.dwSize/sizeof(WCHAR));
				}else{// ����������� � ������ ����� ������ ���� �� � ���� � ���� ��� �� ���� ������� � ��������� ���� �� ��������� � ����
					lpwszMessage=(LPWSTR)MEMALLOC(((lpsAuthMessage.dwSize+MAX_PATH)*sizeof(WCHAR)));
					if (lpwszMessage)
					{
						dwMessageSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsAuthMessage.lpszData,lpsAuthMessage.dwSize,lpwszMessage,(lpsAuthMessage.dwSize+MAX_PATH));
						(*(lpwszMessage+dwMessageSize))=0;
					}else{// �� ������� �������� ������
						dwRetErrorCode=GetLastError();
					}
				}
			}
			if (lpwszMessage!=(LPWSTR)lpbAuthData) MEMFREE(lpbAuthData);
		}
	}else{
		/*// ����� �������
		if (dwFlags&MESSAGE_FLAG_v1p16 && dwFlags&MESSAGE_FLAG_CP1251)
		{// � ����� �� ��������� � ������...����...��� ������!
			DebugPrintW(L"Unknown message encoding: ");
			if (MemoryFindByte(0,plpsText->lpszData,(plpsText->dwSize-1),0))
			{//��� ������ ��� ������!
				dwFlags&=~MESSAGE_FLAG_CP1251;
				DebugPrintCRLFW(plpsText->lpwszData);
			}else{// �������� ����
				dwFlags&=~MESSAGE_FLAG_v1p16;
				DebugPrintCRLFA(plpsText->lpszData);
			}
		}*/

		if (dwFlags&(MESSAGE_FLAG_ALARM|MESSAGE_FLAG_FLASH|MESSAGE_FLAG_v1p16) && (dwFlags&MESSAGE_FLAG_CP1251)==0)
		{// unicode text
			lpwszMessage=plpsText->lpwszData;
			dwMessageSize=(plpsText->dwSize/sizeof(WCHAR));
		}else{// ����������� � ������ ����� ������ ���� �� � ���� � ���� ��� �� ���� ������� � ��������� ���� �� ��������� � ����
			lpwszMessage=(LPWSTR)MEMALLOC(((plpsText->dwSize+MAX_PATH)*sizeof(WCHAR)));
			if (lpwszMessage)
			{
				dwMessageSize=MultiByteToWideChar(MRA_CODE_PAGE,0,plpsText->lpszData,plpsText->dwSize,lpwszMessage,(plpsText->dwSize+MAX_PATH));
				(*(lpwszMessage+dwMessageSize))=0;
			}else{// �� ������� �������� ������
				dwRetErrorCode=GetLastError();
			}
		}

		if (dwFlags&(MESSAGE_FLAG_CONTACT|MESSAGE_FLAG_NOTIFY|MESSAGE_FLAG_SMS|MESSAGE_SMS_DELIVERY_REPORT|MESSAGE_FLAG_ALARM))
		{
			// ������ �� ������, ��������� �� �������� ����������� ����� ��� � ���������� ������������
		}else{
			if ((dwFlags&MESSAGE_FLAG_RTF) && plpsRFTText) //MESSAGE_FLAG_FLASH there
			if (masMraSettings.lpfnUncompress)// only if uncompress function exist
			if (plpsRFTText->lpszData && plpsRFTText->dwSize)
			{// decode RTF
				SIZE_T dwRTFPartsCount,dwCompressedSize,dwRFTBuffSize=((plpsRFTText->dwSize*16)+8192),dwRTFDataSize;
				LPBYTE lpbRTFData,lpbCompressed,lpbDataCurrent;
				MRA_LPS lpsRTFString,lpsBackColour,lpsString;

				lpbRTFData=(LPBYTE)MEMALLOC(dwRFTBuffSize);
				lpbCompressed=(LPBYTE)MEMALLOC((plpsRFTText->dwSize+32));
				if (lpbRTFData && lpbCompressed)
				{
					BASE64DecodeFormated(plpsRFTText->lpszData,plpsRFTText->dwSize,lpbCompressed,(plpsRFTText->dwSize+32),&dwCompressedSize);
					dwRTFDataSize=dwRFTBuffSize;
					if ((PUNCOMPRESS(masMraSettings.lpfnUncompress))(lpbRTFData,(DWORD*)&dwRTFDataSize,lpbCompressed,dwCompressedSize)==Z_OK)
					{
						lpbDataCurrent=lpbRTFData;
						dwRTFPartsCount=GetUL(&lpbDataCurrent);// ����������� ������ � ��������� ������� ������ 2, ����� ����� ������������ ������ �����, �� ��� ��������� �� ����������
						if (GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsRTFString)==NO_ERROR)
						if (GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsBackColour)==NO_ERROR)
						{
							dwBackColour=(*(DWORD*)lpsBackColour.lpszData);
							if (dwFlags&MESSAGE_FLAG_FLASH)
							{// ���� ������� � ������� �����// ������� lpwszMessage=plpsText->lpwszData, �� ��� ������� � ������� �� ����������
								if (dwRTFPartsCount==3)
								{// ������ ���� ����� � ���������
									DebugBreak();// �������� ��� ��� �� ������ ���������, �� ����� ��� �� ������ ������ ��������, 2008
									GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString);
									lpwszMessage=(LPWSTR)MEMALLOC(((lpsString.dwSize+MAX_PATH)*sizeof(WCHAR)));
									if (lpwszMessage)
									{
										memmove(lpwszMessage,lpsString.lpszData,lpsString.dwSize);
										dwMessageSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsString.lpszData,lpsString.dwSize,lpwszMessage,(lpsString.dwSize+MAX_PATH));
										(*(lpwszMessage+dwMessageSize))=0;
									}else{// �� ������� �������� ������
										dwRetErrorCode=GetLastError();
									}
								}else
								if (dwRTFPartsCount==4)
								{
									GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString);
									GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString);
									lpwszMessage=(LPWSTR)MEMALLOC(lpsString.dwSize);
									if (lpwszMessage)
									{
										memmove(lpwszMessage,lpsString.lpszData,lpsString.dwSize);
										dwMessageSize=lpsString.dwSize;
									}else{// �� ������� �������� ������
										dwRetErrorCode=GetLastError();
									}
								}else{
									DebugBreak();
								}
							}else{// ��� ����� 
								if (dwRTFPartsCount>2)
								{
									GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString);
									DebugBreak();
								}

								lpszMessageExt=(LPSTR)MEMALLOC(lpsRTFString.dwSize);
								if (lpszMessageExt)
								{
									memmove(lpszMessageExt,lpsRTFString.lpszData,lpsRTFString.dwSize);
									dwMessageExtSize=lpsRTFString.dwSize;
								}else{// �� ������� �������� ������
									//dwRetErrorCode=GetLastError(); // �� ����������!
									DebugBreak();
								}
							}
						}
					}else{
						MEMFREE(lpszMessageExt);
						dwMessageExtSize=0;
						DebugBreak();
					}
				}
				MEMFREE(lpbCompressed);
				MEMFREE(lpbRTFData);
			}
		}
	}


	// processing
	if (dwRetErrorCode==NO_ERROR)
	if (MraAntiSpamReceivedMessageW(plpsFrom->lpszData,plpsFrom->dwSize,dwFlags,lpwszMessage,dwMessageSize)==MESSAGE_NOT_SPAM)
	{
		if (dwFlags&(MESSAGE_FLAG_SMS|MESSAGE_SMS_DELIVERY_REPORT))
		{// SMS //if (IsPhone(plpsFrom->lpszData,plpsFrom->dwSize))
			char szPhone[MAX_EMAIL_LEN],szEMail[MAX_EMAIL_LEN],szTime[MAX_PATH];
			LPSTR lpszMessageUTF,lpszBuff;
			LPWSTR lpwszMessageXMLEncoded;
			SIZE_T dwBuffLen,dwMessageXMLEncodedSize;
			INTERNET_TIME itTime;

			dwBuffLen=((dwMessageSize+MAX_PATH)*6);
			lpszMessageUTF=(LPSTR)MEMALLOC(dwBuffLen);
			lpwszMessageXMLEncoded=(LPWSTR)MEMALLOC((dwBuffLen*sizeof(WCHAR)));
			if (lpszMessageUTF && lpwszMessageXMLEncoded)
			{
				InternetTimeGetCurrentTime(&itTime);
				InternetTimeGetString(&itTime,szTime,SIZEOF(szTime),NULL);
				CopyNumber(szPhone,plpsFrom->lpszData,plpsFrom->dwSize);
				DB_Mra_GetStaticStringA(NULL,"e-mail",szEMail,SIZEOF(szEMail),NULL);

				EncodeXML(lpwszMessage,dwMessageSize,lpwszMessageXMLEncoded,dwBuffLen,&dwMessageXMLEncodedSize);
				WideCharToMultiByte(CP_UTF8,0,lpwszMessageXMLEncoded,dwMessageXMLEncodedSize,lpszMessageUTF,dwBuffLen,NULL,NULL);
				lpszBuff=(LPSTR)lpwszMessageXMLEncoded;

				if (dwFlags&MESSAGE_SMS_DELIVERY_REPORT)
				{// ����� � ������� �������� ���
					dwBuffLen=mir_snprintf(lpszBuff,(dwBuffLen*sizeof(WCHAR)),"<sms_delivery_receipt><message_id>%s-1-1955988055-%s</message_id><destination>%s</destination><delivered>No</delivered><submition_time>%s</submition_time><error_code>0</error_code><error><id>15</id><params><param>%s</param></params></error></sms_delivery_receipt>",szEMail,szPhone,szPhone,szTime,lpszMessageUTF);
					ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,ICQACKTYPE_SMS,ACKRESULT_FAILED,(HANDLE)0,(LPARAM)lpszBuff,dwBuffLen);
				}else{// ����� ���!!!
					dwBuffLen=mir_snprintf(lpszBuff,(dwBuffLen*sizeof(WCHAR)),"<sms_message><source>Mail.ru</source><destination_UIN>%s</destination_UIN><sender>%s</sender><senders_network>Mail.ru</senders_network><text>%s</text><time>%s</time></sms_message>",szEMail,szPhone,lpszMessageUTF,szTime);
					ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,ICQACKTYPE_SMS,ACKRESULT_SUCCESS,(HANDLE)0,(LPARAM)lpszBuff,dwBuffLen);
				}
			}else{// �� ������� �������� ������
				dwRetErrorCode=GetLastError();
			}
			MEMFREE(lpwszMessageXMLEncoded);
			MEMFREE(lpszMessageUTF);
		}else{
			ccs.hContact=MraHContactFromEmail(plpsFrom->lpszData,plpsFrom->dwSize,TRUE,TRUE,&bAdded);
			if (bAdded) MraUpdateContactInfo(ccs.hContact);

			if (dwFlags&MESSAGE_FLAG_NOTIFY)
			{// user typing
				CallService(MS_PROTO_CONTACTISTYPING,(WPARAM)ccs.hContact,MAILRU_CONTACTISTYPING_TIMEOUT);
			}else{// text/contact/auth // typing OFF
				CallService(MS_PROTO_CONTACTISTYPING,(WPARAM)ccs.hContact,PROTOTYPE_CONTACTTYPING_OFF);

				if (dwFlags&MESSAGE_FLAG_MULTICHAT)
				{// MULTICHAT
					LPBYTE lpbMultiChatData,lpbDataCurrent;
					SIZE_T dwMultiChatDataSize;
					DWORD dwMultiChatEventType;
					MRA_LPS lpsEMailInMultiChat,lpsString,lpsMultichatName;

					lpbMultiChatData=(LPBYTE)plpsMultiChatData->lpszData;
					dwMultiChatDataSize=plpsMultiChatData->dwSize;
					lpbDataCurrent=lpbMultiChatData;

					dwMultiChatEventType=GetUL(&lpbDataCurrent);// type
					GetLPS(lpbMultiChatData,dwMultiChatDataSize,&lpbDataCurrent,&lpsMultichatName);// multichat_name
					GetLPS(lpbMultiChatData,dwMultiChatDataSize,&lpbDataCurrent,&lpsEMailInMultiChat);

					switch(dwMultiChatEventType){
					case MULTICHAT_MESSAGE:
						MraChatSessionMessageAdd(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize,lpwszMessage,dwMessageSize,dwTime);// LPS sender
						break;
					case MULTICHAT_ADD_MEMBERS:
						MraChatSessionMembersAdd(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize,dwTime);// LPS sender
						GetLPS(lpbMultiChatData,dwMultiChatDataSize,&lpbDataCurrent,&lpsString);// CLPS members
						MraChatSessionSetIviter(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize);
					case MULTICHAT_MEMBERS:
						{
							LPBYTE lpbMultiChatDataLocal,lpbDataCurrentLocal;
							SIZE_T i,dwMultiChatMembersCount,dwMultiChatDataLocalSize;

							if (dwMultiChatEventType==MULTICHAT_MEMBERS) lpsString=lpsEMailInMultiChat;

							lpbMultiChatDataLocal=(LPBYTE)lpsString.lpszData;
							dwMultiChatDataLocalSize=lpsString.dwSize;
							lpbDataCurrentLocal=lpbMultiChatDataLocal;

							dwMultiChatMembersCount=GetUL(&lpbDataCurrentLocal);// count
							for (i=0;i<dwMultiChatMembersCount;i++)
							{
								if (GetLPS(lpbMultiChatDataLocal,dwMultiChatDataLocalSize,&lpbDataCurrentLocal,&lpsString)==NO_ERROR)
								{// CLPS members
									MraChatSessionJoinUser(ccs.hContact,lpsString.lpszData,lpsString.dwSize,((dwMultiChatEventType==MULTICHAT_MEMBERS)? 0:dwTime));
								}
							}

							if (dwMultiChatEventType==MULTICHAT_MEMBERS)
							{
								GetLPS(lpbMultiChatData,dwMultiChatDataSize,&lpbDataCurrent,&lpsEMailInMultiChat);// [ LPS owner ]
								MraChatSessionSetOwner(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize);
							}
						}
						break;
					case MULTICHAT_ATTACHED:
						MraChatSessionJoinUser(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize,dwTime);// LPS member
						break;
					case MULTICHAT_DETACHED:
						MraChatSessionLeftUser(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize,dwTime);// LPS member
						break;
					case MULTICHAT_INVITE:
						MraChatSessionInvite(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize,dwTime);// LPS sender
						MraSendCommand_AddContactW(ccs.hContact,(CONTACT_FLAG_VISIBLE|CONTACT_FLAG_MULTICHAT|CONTACT_FLAG_UNICODE_NAME),-1,plpsFrom->lpszData,plpsFrom->dwSize,lpsMultichatName.lpwszData,(lpsMultichatName.dwSize/sizeof(WCHAR)),NULL,0,NULL,0,0);
						break;
					default:
						DebugBreak();
						break;
					}
				}else
				if (dwFlags&MESSAGE_FLAG_AUTHORIZE)
				{// auth request
					BYTE btBuff[BUFF_SIZE_BLOB];
					BOOL bAutoGrandAuth=FALSE;

					if (IsEMailChatAgent(plpsFrom->lpszData,plpsFrom->dwSize))
					{
						bAutoGrandAuth=FALSE;
					}else{
						if (DBGetContactSettingByte(ccs.hContact,"CList","NotOnList",0))
						{// ��������� �������
							if (DB_Mra_GetByte(NULL,"AutoAuthGrandNewUsers",MRA_DEFAULT_AUTO_AUTH_GRAND_NEW_USERS)) bAutoGrandAuth=TRUE;
						}else{// ���������� �������
							if (DB_Mra_GetByte(NULL,"AutoAuthGrandUsersInCList",MRA_DEFAULT_AUTO_AUTH_GRAND_IN_CLIST)) bAutoGrandAuth=TRUE;
						}
					}

					if (bAdded) DBWriteContactSettingByte(ccs.hContact,"CList","Hidden",1);
					if (bAutoGrandAuth)
					{// auto grand auth
						DBEVENTINFO dbei={0};

						dbei.cbSize=sizeof(dbei);
						dbei.szModule=PROTOCOL_NAMEA;
						dbei.timestamp=_time32(NULL);
						dbei.flags=DBEF_READ;
						dbei.eventType=EVENTTYPE_AUTHREQUEST;
						dbei.pBlob=(PBYTE)btBuff;

						CreateBlobFromContact(ccs.hContact,lpwszMessage,dwMessageSize,btBuff,SIZEOF(btBuff),(SIZE_T*)&dbei.cbBlob);
						CallService(MS_DB_EVENT_ADD,(WPARAM)NULL,(LPARAM)&dbei);
						MraSendCommand_Authorize(plpsFrom->lpszData,plpsFrom->dwSize);
					}else{
						ccs.szProtoService=PSR_AUTH;
						pre.szMessage=(LPSTR)btBuff;
						CreateBlobFromContact(ccs.hContact,lpwszMessage,dwMessageSize,btBuff,SIZEOF(btBuff),(SIZE_T*)&pre.lParam);
						CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
					}
				}else{
					DBDeleteContactSetting(ccs.hContact,"CList","Hidden");

					if (dwFlags&MESSAGE_FLAG_CONTACT)
					{// contacts received
						LPBYTE lpbBuffer,lpbBufferCurPos;

						lpbBuffer=(LPBYTE)MEMALLOC((dwMessageSize+MAX_PATH));
						if (lpbBuffer)
						{
							ccs.szProtoService=PSR_CONTACTS;
							pre.flags=0;
							pre.szMessage=(LPSTR)lpbBuffer;
							pre.lParam=WideCharToMultiByte(MRA_CODE_PAGE,0,lpwszMessage,dwMessageSize,(LPSTR)lpbBuffer,(dwMessageSize+MAX_PATH),NULL,NULL);
							
							lpbBufferCurPos=lpbBuffer;
							while(TRUE)
							{// ���� ������ ; �� 0
								lpbBufferCurPos=(LPBYTE)MemoryFindByte((lpbBufferCurPos-lpbBuffer),lpbBuffer,pre.lParam,';');
								if (lpbBufferCurPos)
								{// founded
									(*lpbBufferCurPos)=0;
									lpbBufferCurPos++;
								}else{
									break;
								}
							}
							CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
							MEMFREE(lpbBuffer);
						}else{// �� ������� �������� ������
							dwRetErrorCode=GetLastError();
						}
					}else
					if (dwFlags&MESSAGE_FLAG_ALARM)
					{// alarm
						if (masMraSettings.heNudgeReceived)
						{
							NotifyEventHooks(masMraSettings.heNudgeReceived,(WPARAM)ccs.hContact,NULL);
						}else{
							pre.flags=0;
							pre.szMessage=(LPSTR)TranslateTS(MRA_ALARM_MESSAGE);
							//pre.lParam=lstrlenA(pre.szMessage);
							ccs.szProtoService=PSR_MESSAGE;
							CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
						}
					}else{// standart message// flash animation
						if ((dwFlags&MESSAGE_FLAG_RTF) && (dwFlags&MESSAGE_FLAG_FLASH)==0 && lpszMessageExt && dwMessageExtSize && DB_Mra_GetByte(NULL,"RTFReceiveEnable",MRA_DEFAULT_RTF_RECEIVE_ENABLE))
						{// ����� � ANSI, �� ����� RTF
							pre.flags=0;
							pre.szMessage=lpszMessageExt;
							//pre.lParam=dwMessageExtSize;
							ccs.szProtoService=PSR_MESSAGE;
							CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
						}else{
							LPSTR lpszMessageUTF;// some plugins can change pre.szMessage pointer and we failed to free it

							lpszMessageUTF=(LPSTR)MEMALLOC(((dwMessageSize+MAX_PATH)*sizeof(WCHAR)));
							if (lpszMessageUTF)
							{
								pre.szMessage=lpszMessageUTF;
								pre.flags=PREF_UTF;
								//pre.lParam=
								WideCharToMultiByte(CP_UTF8,0,lpwszMessage,dwMessageSize,lpszMessageUTF,((dwMessageSize+MAX_PATH)*sizeof(WCHAR)),NULL,NULL);
								ccs.szProtoService=PSR_MESSAGE;
								CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
								MEMFREE(lpszMessageUTF);
							}else{// �� ������� �������� ������
								dwRetErrorCode=GetLastError();
							}
						}
						if (dwFlags&MESSAGE_FLAG_SYSTEM)
						{
							MraPopupShowW(ccs.hContact,MRA_POPUP_TYPE_INFORMATION,0,TranslateW(L"Mail.ru System notify"),(LPWSTR)pre.szMessage);
						}
					}
				}
			}
		}
	}else{// spam blocked
		if (DB_Mra_GetByte(NULL,"AntiSpamSendSpamReportToSrv",MRA_ANTISPAM_DEFAULT_SEND_SPAM_REPORT_TO_SERVER))
		{// ��������� � �����
			//MraSendCommand_MessageAskW(1,(dwFlags|MESSAGE_FLAG_SPAMF_SPAM),plpsFrom->lpszData,plpsFrom->dwSize,plpsText->lpwszData,plpsText->dwSize,plpsRFTText->lpszData,plpsRFTText->dwSize);
		}
		dwRetErrorCode=ERROR_ACCESS_DENIED;
	}

	if (lpwszMessage!=plpsText->lpwszData && lpwszMessage!=(LPWSTR)lpszMessageExt) MEMFREE(lpwszMessage);
	MEMFREE(lpszMessageExt);

return(dwRetErrorCode);
}





DWORD GetMraXStatusIDFromMraUriStatus(LPSTR lpszStatusUri,SIZE_T dwStatusUriSize)
{
	DWORD dwRet=MRA_XSTATUS_UNKNOWN;

	if (lpszStatusUri)
	{
		for(SIZE_T i=0;lpcszStatusUri[i];i++)
		{
			if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpcszStatusUri[i],-1,lpszStatusUri,dwStatusUriSize)==CSTR_EQUAL)
			{
				dwRet=i;
				break;
			}
		}
	}
return(dwRet);
}


DWORD GetMraStatusFromMiradaStatus(DWORD dwMirandaStatus,DWORD dwXStatusMir,DWORD *pdwXStatusMra)
{
	DWORD dwRet;

	if (IsXStatusValid(dwXStatusMir))
	{
		if (pdwXStatusMra) (*pdwXStatusMra)=(dwXStatusMir+MRA_XSTATUS_INDEX_OFFSET-1);
		dwRet=STATUS_USER_DEFINED;
	}else{
		switch(dwMirandaStatus){
		case ID_STATUS_OFFLINE:
			if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_OFFLINE;
			dwRet=STATUS_OFFLINE;
			break;
		case ID_STATUS_ONLINE:
			if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_ONLINE;
			dwRet=STATUS_ONLINE;
			break;
		case ID_STATUS_AWAY:
		case ID_STATUS_NA:
		case ID_STATUS_ONTHEPHONE:
		case ID_STATUS_OUTTOLUNCH:
			if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_AWAY;
			dwRet=STATUS_AWAY;
			break;
		case ID_STATUS_DND:
		case ID_STATUS_OCCUPIED:
			if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_DND;
			dwRet=STATUS_USER_DEFINED;
			break;
		case ID_STATUS_FREECHAT:
			if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_CHAT;
			dwRet=STATUS_USER_DEFINED;
			break;
		case ID_STATUS_INVISIBLE:
			if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_INVISIBLE;
			dwRet=(STATUS_ONLINE|STATUS_FLAG_INVISIBLE);
			break;
		default:
			if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_OFFLINE;
			dwRet=STATUS_OFFLINE;
			break;
		}
	}
return(dwRet);
}


DWORD GetMiradaStatusFromMraStatus(DWORD dwMraStatus,DWORD dwXStatusMra,DWORD *pdwXStatusMir)
{
	DWORD dwRet;

	if (pdwXStatusMir) (*pdwXStatusMir)=0;

	switch(dwMraStatus){
	case STATUS_OFFLINE:
		dwRet=ID_STATUS_OFFLINE;
		break;
	case STATUS_ONLINE:
		dwRet=ID_STATUS_ONLINE;
		break;
	case STATUS_AWAY:
		dwRet=ID_STATUS_AWAY;
		break;
	case STATUS_UNDETERMINATED:
		dwRet=ID_STATUS_OFFLINE;
		break;
	case STATUS_USER_DEFINED:
		switch(dwXStatusMra){
		//case MRA_XSTATUS_OFFLINE:	dwRet=ID_STATUS_OFFLINE;	break;
		//case MRA_XSTATUS_ONLINE:	dwRet=ID_STATUS_ONLINE;		break;
		//case MRA_XSTATUS_AWAY:		dwRet=ID_STATUS_AWAY;		break;
		//case MRA_XSTATUS_INVISIBLE:	dwRet=ID_STATUS_INVISIBLE;	break;
		case MRA_XSTATUS_DND:		dwRet=ID_STATUS_DND;		break;
		case MRA_XSTATUS_CHAT:		dwRet=ID_STATUS_FREECHAT;	break;
		case MRA_XSTATUS_UNKNOWN:
			if (pdwXStatusMir) (*pdwXStatusMir)=MRA_MIR_XSTATUS_UNKNOWN;
			dwRet=ID_STATUS_ONLINE;
			break;
		default:
			if (pdwXStatusMir) (*pdwXStatusMir)=(dwXStatusMra-MRA_XSTATUS_INDEX_OFFSET+1);
			dwRet=ID_STATUS_ONLINE;
			break;
		}
		break;
	default:// STATUS_FLAG_INVISIBLE
		if (dwMraStatus&STATUS_FLAG_INVISIBLE)
		{
			dwRet=ID_STATUS_INVISIBLE;
		}else{
			dwRet=ID_STATUS_OFFLINE;
			DebugBreak();
		}
		break;
	}
return(dwRet);
}


DWORD GetUL(LPBYTE *plpData)
{
	DWORD dwRet=(*(DWORD*)(*plpData));
	(*plpData)+=sizeof(DWORD);
return(dwRet);
}


DWORDLONG GetUIDL(LPBYTE *plpData)
{
	DWORDLONG dwRet=(*(DWORDLONG*)(*plpData));
	(*plpData)+=sizeof(DWORDLONG);
return(dwRet);
}


MRA_GUID GetGUID(LPBYTE *plpData)
{
	MRA_GUID guidRet=(*(MRA_GUID*)(*plpData));
	(*plpData)+=sizeof(MRA_GUID);
return(guidRet);
}


DWORD GetLPS(LPBYTE lpbData,DWORD dwDataSize,LPBYTE *plpCurrentData,MRA_LPS *plpsString)
{
	DWORD dwRetErrorCode;
	LPBYTE lpbDataEnd=(lpbData+dwDataSize);

	if (lpbDataEnd>=((*plpCurrentData)+sizeof(DWORD)))
	{// ������ ������ ������ ����
		if (lpbDataEnd>=((*plpCurrentData)+sizeof(DWORD)+(*(DWORD*)(*plpCurrentData))))
		{// ��� ������ ������ � ������ ����� ��� ������ ������� ������
			plpsString->dwSize=(*(DWORD*)(*plpCurrentData));
			plpsString->lpszData=(LPSTR)((*plpCurrentData)+sizeof(DWORD));
			(*plpCurrentData)+=(sizeof(DWORD)+plpsString->dwSize);
			dwRetErrorCode=NO_ERROR;
		}else{
			plpsString->dwSize=0;
			plpsString->lpszData=NULL;
			dwRetErrorCode=ERROR_INVALID_USER_BUFFER;
		}
	}else{
		plpsString->dwSize=0;
		plpsString->lpszData=NULL;
		dwRetErrorCode=ERROR_INVALID_USER_BUFFER;
	}
return(dwRetErrorCode);
}