diff options
| author | Rozhuk Ivan <rozhuk.im@gmail.com> | 2014-11-29 20:25:42 +0000 | 
|---|---|---|
| committer | Rozhuk Ivan <rozhuk.im@gmail.com> | 2014-11-29 20:25:42 +0000 | 
| commit | f73897a8ca83abe24a15016808790e01d061cb36 (patch) | |
| tree | 3e62a5d4cabf5b5e573109a6df3cba61cb9ff11a | |
| parent | 9da683d81d193e7885fae9b804e633b05d863389 (diff) | |
SkypeClassic: code cleanup
git-svn-id: http://svn.miranda-ng.org/main/trunk@11161 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
| -rw-r--r-- | protocols/SkypeClassic/src/gchat.cpp | 1713 | 
1 files changed, 858 insertions, 855 deletions
| diff --git a/protocols/SkypeClassic/src/gchat.cpp b/protocols/SkypeClassic/src/gchat.cpp index 37e075544e..82a66c8fcb 100644 --- a/protocols/SkypeClassic/src/gchat.cpp +++ b/protocols/SkypeClassic/src/gchat.cpp @@ -1,855 +1,858 @@ -#include "skype.h"
 -#include "skypeapi.h"
 -#include "gchat.h"
 -#include "contacts.h"
 -#include "debug.h"
 -#include "utf8.h"
 -#include "pthread.h"
 -
 -#include <m_langpack.h>
 -#include <m_userinfo.h>
 -#include <m_history.h>
 -#include <m_contacts.h>
 -
 -#ifndef DWLP_USER
 -#define DWLP_USER DWL_USER
 -#endif
 -
 -#ifdef _UNICODE
 -#define STR "%S"
 -#else
 -#define STR "%s"
 -#endif
 -
 -#pragma warning (disable: 4706) // assignment within conditional expression
 -
 -extern HANDLE hInitChat;
 -extern HINSTANCE hInst;
 -extern char protocol, g_szProtoName[];
 -extern DWORD mirandaVersion;
 -
 -static gchat_contacts *chats=NULL;
 -static int chatcount=0;
 -static CRITICAL_SECTION m_GCMutex;
 -
 -// TODO: Disable groupchat for Protocol verisons <5
 -
 -/****************************************************************************/
 -/*                  Chat management helper functions                        */
 -/****************************************************************************/
 -
 -/* Get the gchat_contacts entry for the chat with the id szChatId
 -   If the chat doesn't already exist in the list, it is added.
 -
 -   Parameters: szChatId - String with the chat ID of the chat to be found
 -   Returns:    Pointer to the gchat_contacts entry for the given id.
 -			   NULL on failure (not enough memory)
 -*/
 -gchat_contacts *GetChat(const TCHAR *szChatId) {
 -	int i;
 -
 -	for (i=0;i<chatcount;i++)
 -		if (!_tcscmp(chats[i].szChatName, szChatId)) return &chats[i];
 -	if (chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*(++chatcount))) {
 -		memset(&chats[chatcount-1], 0, sizeof(gchat_contacts));
 -		chats[chatcount-1].szChatName=_tcsdup(szChatId);
 -		return &chats[chatcount-1];
 -	}
 -	return NULL;
 -}
 -
 -/* Removes the gchat_contacts entry for the chat with the id szChatId,
 -   if it exists.
 -  
 -   Parameters: szChatId - String with the chat ID to be removed from list
 - */
 -void RemChat(TCHAR *szChatId) {
 -	int i;
 -
 -	for (i=0;i<chatcount;i++)
 -		if (!_tcscmp(chats[i].szChatName, szChatId)) {
 -			if (chats[i].szChatName) free(chats[i].szChatName);
 -			if (chats[i].mJoinedContacts) free(chats[i].mJoinedContacts);
 -			if (i<--chatcount) memmove(&chats[i], &chats[i+1], (chatcount-i)*sizeof(gchat_contacts));
 -			chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*chatcount);
 -			return;
 -		}
 -}
 -
 -/* Checks, if the contact with the handle hContact exists in the groupchat
 -   given in gc
 -
 -  Parameters: gc       - gchat_contacts entry for the chat session to be searched
 -			  who      - Name of member
 -  Returns:    -1  = Not found
 -              >=0 = Number of found item
 - */
 -static int ExistsChatContact(gchat_contacts *gc, const TCHAR *who) {
 -	int i;
 -
 -	for (i=0;i<gc->mJoinedCount;i++)
 -		if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) return i;
 -	return -1;
 -}
 -
 -gchat_contact *GetChatContact(gchat_contacts *gc, const TCHAR *who) {
 -	int i = ExistsChatContact (gc, who);
 -
 -	if (i==-1) return NULL;
 -	return &gc->mJoinedContacts[i];
 -}
 -
 -/* Adds contact with the name who to the groupchat given in gc
 -
 -  Parameters: gc   -
 -  Returns:    -1  = Contact not found
 -			  -2  = On failure
 -			  >=0 = Number of added item
 - */
 -static int AddChatContact(gchat_contacts *gc, char *who, TCHAR *pszRole)
 -{
 -	LOG (("AddChatContact %s", who));
 -	TCHAR *twho = make_nonutf_tchar_string((const unsigned char*)who);
 -	if (!twho)
 -		return -2;
 -
 -	int i = ExistsChatContact(gc, twho);
 -	if (i >= 0)
 -		return i;
 -
 -	MCONTACT hContact = find_contact(who);
 -
 -	GCDEST gcd = { SKYPE_PROTONAME, gc->szChatName, GC_EVENT_JOIN };
 -	GCEVENT gce = { sizeof(gce), &gcd };
 -	gce.time = (DWORD)time(NULL);
 -	gce.dwFlags = GCEF_ADDTOLOG;
 -	gce.ptszStatus = pszRole ? pszRole : _T("USER");
 -
 -	CONTACTINFO ci = {0};
 -	ci.cbSize = sizeof(ci);
 -	ci.szProto = SKYPE_PROTONAME;
 -	ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
 -	ci.hContact = hContact;
 -
 -	if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci))
 -		gce.ptszNick=ci.pszVal; 
 -	else
 -		gce.ptszNick=twho;
 -        
 -	gce.ptszUID=twho;
 -	if (!CallService(MS_GC_EVENT, 0, (LPARAM)&gce)) {
 -		if ((gc->mJoinedContacts=(gchat_contact*)realloc(gc->mJoinedContacts, (gc->mJoinedCount+1)*sizeof(gchat_contact))))
 -		{
 -			gc->mJoinedContacts[i=gc->mJoinedCount].hContact=hContact;
 -			_tcscpy (gc->mJoinedContacts[i].szRole, gce.ptszStatus);
 -			_tcscpy (gc->mJoinedContacts[i].who, twho);
 -			gc->mJoinedCount++;
 -		}
 -	}
 -    if (ci.pszVal) mir_free (ci.pszVal);
 -	free_nonutf_tchar_string (twho);
 -	return i;
 -}
 -
 -void RemChatContact(gchat_contacts *gc, const TCHAR *who) {
 -	int i;
 -
 -	if (!gc) return;
 -	for (i=0;i<gc->mJoinedCount;i++)
 -		if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) {
 -			if (i<--gc->mJoinedCount) 
 -				memmove(&gc->mJoinedContacts[i], &gc->mJoinedContacts[i+1], (gc->mJoinedCount-i)*sizeof(gchat_contact));
 -			if (gc->mJoinedCount) gc->mJoinedContacts = (gchat_contact*)realloc(gc->mJoinedContacts, sizeof(gchat_contact)*gc->mJoinedCount);
 -			else {free (gc->mJoinedContacts); gc->mJoinedContacts = NULL; }
 -			return;
 -		}
 -}
 -
 -MCONTACT find_chat(LPCTSTR chatname) {
 -	for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) {
 -		if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1)
 -		{
 -			DBVARIANT dbv;
 -			if (!db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) {
 -				int tCompareResult = _tcscmp(dbv.ptszVal, chatname);
 -				db_free(&dbv);
 -				if (!tCompareResult)
 -					return hContact; // already there, return handle
 -			}
 -		}
 -	}
 -	return NULL;
 -}
 -
 -#ifdef _UNICODE
 -MCONTACT find_chatA(char *chatname) {
 -	for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) {
 -		if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1)
 -		{
 -			DBVARIANT dbv;
 -			if (!db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) {
 -				int tCompareResult = strcmp(dbv.pszVal, chatname);
 -				db_free(&dbv);
 -				if (!tCompareResult)
 -					return hContact; // already there, return handle
 -			}
 -		}
 -	}
 -	return NULL;
 -}
 -#endif
 -
 -
 -
 -int  __cdecl AddMembers(char *szSkypeMsg) {
 -	BYTE *contactmask=NULL;
 -	DBVARIANT dbv2;
 -	CONTACTINFO ci={0};
 -	char *who, *nextoken;
 -	int i, iRet = 0;
 -	gchat_contacts *gc;
 -
 -	LOG(("AddMembers STARTED"));
 -	char *ptr=strstr(szSkypeMsg, " MEMBERS");
 -	if (!ptr)
 -		return -1;
 -	EnterCriticalSection(&m_GCMutex);
 -	ptr[0]=0;
 -	TCHAR *szChatId = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5);
 -	ptr+=9;
 -	if (find_chat(szChatId) && (gc=GetChat(szChatId)) && 
 -		!db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2))
 -	{
 -		char *pszMemObjs, *token;
 -
 -		if (protocol>=7 && (pszMemObjs = SkypeGet ("CHAT", szSkypeMsg+5, "MEMBEROBJECTS"))) {
 -			// Add new contacts (protocol 7+ with memberobjects, supports roles)
 -			for (token=strtok_r(pszMemObjs, ", ", &nextoken); token; token=strtok_r(NULL, ", ", &nextoken)) {
 -				if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) {
 -					iRet = -1;
 -					break;
 -				}
 -				if (!(who = SkypeGet ("CHATMEMBER", token, "IDENTITY"))) continue;
 -				if (strcmp(who, dbv2.pszVal)) {
 -					TCHAR *ptszRole = NULL;
 -
 -					char *pszRole = SkypeGet("CHATMEMBER", token, "ROLE");
 -					if (pszRole)
 -						ptszRole = make_nonutf_tchar_string((const unsigned char*)pszRole);
 -
 -					i=AddChatContact(gc, who, ptszRole);
 -					free_nonutf_tchar_string (ptszRole);
 -					if (pszRole) free (pszRole);
 -					if (!(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) {
 -						iRet = -1;
 -						free (who);
 -						break;
 -					}
 -					contactmask[i]=TRUE;
 -				}
 -				free (who);
 -			}
 -			free (pszMemObjs);
 -		}
 -		else
 -		{
 -			// Add new contacts (normal)
 -			for (who=strtok_r(ptr, " ", &nextoken); who; who=strtok_r(NULL, " ", &nextoken)) {
 -				if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) {
 -					iRet = -1;
 -					break;
 -				}
 -				if (strcmp(who, dbv2.pszVal)) {
 -					i=AddChatContact(gc, who, NULL);
 -					if (i<0 || !(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) {
 -						iRet = -1;
 -						break;
 -					}
 -					contactmask[i]=TRUE;
 -				}
 -			}
 -		}
 -		// Quit contacts which are no longer there
 -		if (iRet == 0 && contactmask) {
 -			GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_QUIT };
 -			GCEVENT gce = { sizeof(gce), &gcd };
 -			gce.time = (DWORD)time(NULL);
 -			gce.dwFlags = GCEF_ADDTOLOG;
 -        
 -			ci.cbSize = sizeof(ci);
 -			ci.szProto = SKYPE_PROTONAME;
 -			ci.dwFlag = CNF_DISPLAY;
 -
 -			for (i=0;i<gc->mJoinedCount;i++)
 -			if (!contactmask[i]) 
 -			{
 -				ci.hContact = gc->mJoinedContacts[i].hContact;
 -				ci.dwFlag = CNF_TCHAR;
 -				if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; 
 -				else gce.ptszNick=gc->mJoinedContacts[i].who;
 -				gce.ptszUID = gc->mJoinedContacts[i].who;
 -				CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -				if (ci.pszVal) {
 -					mir_free (ci.pszVal);
 -					ci.pszVal=NULL;
 -				}
 -				RemChatContact(gc, gc->mJoinedContacts[i].who);
 -			}
 -	// We don't do this, because the dialog group-chat may have been started intentionally
 -	/*
 -			if (gc->mJoinedCount == 1) {
 -				// switch back to normal session
 -				KillChatSession(&gcd);
 -			}
 -	*/
 -		}
 -		if (contactmask) free(contactmask);
 -		db_free(&dbv2);
 -	} else iRet = -1;
 -	free_nonutf_tchar_string (szChatId);
 -	LeaveCriticalSection(&m_GCMutex);
 -	LOG(("AddMembers DONE"));
 -	return iRet;
 -}
 -
 -void AddMembersThread(char *szSkypeMsg)
 -{
 -	AddMembers(szSkypeMsg);
 -	free(szSkypeMsg);
 -}
 -
 -/****************************************************************************/
 -/*                           Window procedures                              */
 -/****************************************************************************/
 -INT_PTR CALLBACK InputBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 -{
 -	switch (msg) {
 -	case WM_INITDIALOG:
 -	{
 -		TranslateDialogDefault(hwndDlg);
 -		SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
 -		SetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)lParam);
 -		return TRUE;
 -	}
 -
 -	case WM_COMMAND:
 -		switch ( LOWORD( wParam )) {
 -		case IDOK:
 -		{	
 -			GetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER), (MAX_BUF-1)*sizeof(TCHAR));
 -			EndDialog(hwndDlg, 1);
 -			break;
 -		}
 -		case IDCANCEL:
 -			EndDialog(hwndDlg, 0);
 -			break;
 -	}	}
 -	return FALSE;
 -}
 -
 -/****************************************************************************/
 -/*                      Core Chat management functions                      */
 -/****************************************************************************/
 -
 -/* We have a new Groupchat
 -
 -   This hook is called when a new chat is initialised.
 -   Parameters:  wParam = (char *)Name of new chat session [Has to be ASCIIZ/UTF8]
 -				lParam = 1 - Create groupchat, but don't open it
 -				         0 - Default - open groupchat after init
 -*/
 -
 -int __cdecl  ChatInit(WPARAM wParam, LPARAM lParam)
 -{
 -	if (!wParam) return -1;
 -
 -	DBVARIANT dbv, dbv2;
 -	int iRet = -1;
 -
 -	GCSESSION gcw = { sizeof(gcw) };
 -	gcw.iType = GCW_CHATROOM;
 -	gcw.pszModule = SKYPE_PROTONAME;
 -
 -	char *szChatName = SkypeGet ("CHAT", (char *)wParam, "FRIENDLYNAME");
 -	if (!szChatName || !*szChatName)
 -		gcw.ptszName=TranslateT("Unknown"); else {
 -#ifdef _UNICODE
 -		gcw.ptszName=make_unicode_string((const unsigned char*)szChatName);
 -		free (szChatName);
 -		szChatName = (char*)gcw.ptszName;
 -#else
 -		gcw.ptszName=szChatName;
 -#endif
 -	}
 -	gcw.ptszID = make_nonutf_tchar_string((const unsigned char*)wParam);
 -	gcw.ptszStatusbarText = NULL;
 -	EnterCriticalSection(&m_GCMutex);
 -	if (!CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw)) {
 -		char *szChatRole;
 -
 -		GCDEST gcd = { SKYPE_PROTONAME, gcw.ptszID, GC_EVENT_ADDGROUP };
 -		GCEVENT gce = { sizeof(gce), &gcd };
 -		gce.ptszStatus = _T("CREATOR");
 -		// BUG: Groupchat returns nonzero on success here in earlier versions, so we don't check
 -		// it here
 -		CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -		gce.ptszStatus = _T("MASTER");
 -		CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -		gce.ptszStatus = _T("HELPER");
 -		CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -		gce.ptszStatus = _T("USER");
 -		CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -		gce.ptszStatus = _T("LISTENER");
 -		CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -		gce.ptszStatus = _T("APPLICANT");
 -		CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -
 -		gcd.iType = GC_EVENT_JOIN;
 -		gce.ptszStatus = NULL;
 -		if (protocol >=7 && (szChatRole = SkypeGet ("CHAT", (char *)wParam, "MYROLE"))) {
 -			if (strncmp(szChatRole, "ERROR", 5))
 -			{
 -#ifdef _UNICODE
 -				gce.ptszStatus = make_unicode_string((const unsigned char*)szChatRole);
 -				free (szChatRole);
 -#else
 -				gce.ptszStatus = szChatRole;
 -#endif
 -			}
 -		}
 -		if (!gce.ptszStatus) gce.ptszStatus=_tcsdup(_T("CREATOR"));
 -
 -		if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) {
 -			if (!db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) {
 -				gce.ptszNick = dbv.ptszVal;
 -				gce.ptszUID = dbv2.ptszVal;
 -				gce.time = 0;
 -				gce.bIsMe = TRUE;
 -				gce.dwFlags |= GCEF_ADDTOLOG;
 -				if (!CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce)) {
 -					gcd.iType = GC_EVENT_CONTROL;
 -					if (!lParam)
 -						CallService(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
 -					CallService(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
 -					CallService(MS_GC_EVENT, lParam ? WINDOW_HIDDEN : WINDOW_VISIBLE, (LPARAM)&gce);
 -					SkypeSend ("GET CHAT %s MEMBERS", (char *)wParam);
 -					iRet = 0;
 -				}
 -				else {LOG (("ChatInit: Joining 'me' failed."));}
 -			}
 -			db_free(&dbv2);
 -		}
 -		free ((void*)gce.ptszStatus);
 -		db_free(&dbv);
 -	}
 -	free (szChatName);
 -	free_nonutf_tchar_string ((void*)gcw.ptszID);
 -	LeaveCriticalSection(&m_GCMutex);
 -	return iRet;
 -}
 -
 -/* Open new Groupchat
 -
 -   Parameters:  szChatId = (char *)Name of new chat session
 -*/
 -int  __cdecl ChatStart(char *szChatId, BOOL bJustCreate) {
 -	LOG(("ChatStart: New groupchat started"));
 -	if (!szChatId || NotifyEventHooks(hInitChat, (WPARAM)szChatId, bJustCreate)) return -1;
 -	return 0;
 -}
 -
 -
 -void KillChatSession(GCDEST *gcd)
 -{
 -	GCEVENT gce = { sizeof(gce), gcd };
 -	EnterCriticalSection(&m_GCMutex);
 -	LOG(("KillChatSession: Groupchatsession terminated."));
 -	gcd->iType = GC_EVENT_CONTROL;
 -	if (SkypeSend ("ALTER CHAT "STR" LEAVE", gcd->ptszID) == 0)
 -	{
 -		CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce);
 -		CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
 -	}
 -	LeaveCriticalSection(&m_GCMutex);
 -}
 -
 -void InviteUser(const TCHAR *szChatId)
 -{
 -	if (!szChatId)
 -		return;
 -
 -	gchat_contacts *gc=GetChat(szChatId);
 -	if (!gc)
 -		return;
 -
 -	// add the heading
 -	HMENU tMenu = CreatePopupMenu();
 -	AppendMenu(tMenu, MF_STRING|MF_GRAYED|MF_DISABLED, 0, TranslateT("&Invite user..."));
 -	AppendMenu(tMenu, MF_SEPARATOR, 1, NULL);
 -    
 -	DBVARIANT dbv;
 -	POINT pt;
 -	int j;
 -
 -	// generate a list of contact
 -	for (MCONTACT hContact = db_find_first(SKYPE_PROTONAME);hContact;hContact = db_find_next(hContact,SKYPE_PROTONAME)) {
 -		if (!db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) &&
 -			 db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE) 
 -		{
 -			BOOL alreadyInSession = FALSE;
 -			for (j=0; j<gc->mJoinedCount; j++) {
 -				if (gc->mJoinedContacts[j].hContact==hContact) {
 -					alreadyInSession = TRUE;
 -					break;
 -				}
 -			}
 -            if (!alreadyInSession)
 -				AppendMenu(tMenu, MF_STRING, (UINT_PTR)hContact, 
 -					(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR));
 -        }
 -		
 -	}
 -
 -	HWND tWindow = CreateWindow(_T("EDIT"),_T(""),0,1,1,1,1,NULL,NULL,hInst,NULL);
 -
 -	GetCursorPos (&pt);
 -	MCONTACT hInvitedUser = (MCONTACT)TrackPopupMenu(tMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, tWindow, NULL);
 -	DestroyMenu(tMenu);
 -	DestroyWindow(tWindow);
 -
 -	if (!hInvitedUser || db_get_s(hInvitedUser, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) 
 -		return;
 -	SkypeSend ("ALTER CHAT "STR" ADDMEMBERS %s", szChatId, dbv.pszVal);
 -	db_free(&dbv);
 -
 -}
 -
 -static void KickUser (MCONTACT hContact, GCHOOK *gch)
 -{
 -	EnterCriticalSection(&m_GCMutex);
 -	if (SkypeSend ("ALTER CHAT "STR" KICK "STR, gch->pDest->ptszID, gch->ptszUID)!=-1) {
 -		char *ptr = SkypeRcv("ALTER CHAT KICK", 2000);
 -		if (ptr) {
 -			if (strncmp(ptr, "ERROR", 5)) {
 -				GCDEST gcd = { SKYPE_PROTONAME, gch->pDest->ptszID, GC_EVENT_KICK };
 -				GCEVENT gce = { sizeof(gce), &gcd };
 -				gce.time = (DWORD)time(NULL);
 -				gce.dwFlags = GCEF_ADDTOLOG;
 -				gce.ptszUID = gch->ptszUID;
 -
 -				CONTACTINFO ci = {0};
 -				ci.cbSize = sizeof(ci);
 -				ci.szProto = SKYPE_PROTONAME;
 -				ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
 -				ci.hContact = hContact;
 -				if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; 
 -				else gce.ptszNick=gce.ptszUID;
 -        
 -				DBVARIANT dbv;
 -				if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) {
 -					gce.ptszStatus = dbv.ptszVal;		
 -					CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
 -					RemChatContact (GetChat(gcd.ptszID), gch->ptszUID);
 -					db_free(&dbv);
 -				}
 -				if (ci.pszVal) mir_free (ci.pszVal);
 -			}
 -			free (ptr);
 -		}
 -	}
 -	LeaveCriticalSection(&m_GCMutex);
 -}
 -
 -void SetChatTopic(const TCHAR *szChatId, TCHAR *szTopic, BOOL bSet)
 -{
 -	MCONTACT hContact = find_chat (szChatId);
 -	char *szUTFTopic;
 -
 -	GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_TOPIC };
 -	GCEVENT gce = { sizeof(gce), &gcd };
 -	gce.ptszText = szTopic;
 -	gce.dwFlags = GCEF_ADDTOLOG;
 -	gce.time = (DWORD)time (NULL);
 -	CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -
 -	gcd.iType = GC_EVENT_SETSBTEXT;
 -	CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -
 -	if (bSet) {
 -#ifdef _UNICODE
 -		szUTFTopic=(char*)make_utf8_string(szTopic);
 -#else
 -		if (utf8_encode(szTopic, &szUTFTopic)==-1) szUTFTopic = NULL;
 -#endif
 -		if (szUTFTopic) {
 -			SkypeSend ("ALTER CHAT "STR" SETTOPIC %s", szChatId, szUTFTopic);
 -			free (szUTFTopic);
 -		}
 -		testfor ("ALTER CHAT SETTOPIC", INFINITE);
 -	}
 -
 -	if (hContact)
 -		db_set_ts(hContact, SKYPE_PROTONAME, "Nick", szTopic);
 -}
 -
 -
 -int GCEventHook(WPARAM,LPARAM lParam) {
 -	GCHOOK *gch = (GCHOOK*) lParam;
 -	if(gch) {
 -		gchat_contacts *gc = GetChat(gch->pDest->ptszID);
 -		if (!_stricmp(gch->pDest->pszModule, SKYPE_PROTONAME)) {
 -
 -			switch (gch->pDest->iType) {
 -			case GC_SESSION_TERMINATE: {
 -				MCONTACT hContact;
 -
 -				if (gc->mJoinedCount == 1) {
 -					// switch back to normal session
 -                    // I don't know if this behaviour isn't a bit annoying, therefore, we
 -					// don't do this now, until a user requests this feature :)
 -                    
 -					// open up srmm dialog when quit while 1 person left
 -//					CallService(MS_MSG_SENDMESSAGE, (WPARAM)gc->mJoinedContacts[0].hContact, 0);
 -
 -					RemChatContact(gc, gc->mJoinedContacts[0].who);
 -				}
 -				// Delete Chatroom from Contact list, as we don't need it anymore...?
 -				if (hContact = find_chat(gc->szChatName))
 -					CallService(MS_DB_CONTACT_DELETE, hContact, 0); 
 -				RemChat(gc->szChatName);
 -
 -				break;
 -			}
 -			case GC_USER_MESSAGE:
 -				if(gch && gch->ptszText && _tcslen(gch->ptszText) > 0) {
 -					DBVARIANT dbv, dbv2;
 -					CCSDATA ccs = {0};
 -					TCHAR *pEnd;
 -
 -					// remove the ending linebreak
 -					for (pEnd = &gch->ptszText[_tcslen(gch->ptszText) - 1];
 -						 *pEnd==_T('\r') || *pEnd==_T('\n'); pEnd--) *pEnd=0;
 -                    // Send message to the chat-contact    
 -					if (ccs.hContact = find_chat(gch->pDest->ptszID)) {
 -#ifdef _UNICODE
 -						// If PREF_UTF is supported, just convert it to UTF8 and pass the buffer to PSS_MESSAGE
 -						if (mirandaVersion >= 0x070000) {
 -							ccs.lParam = (LPARAM)make_utf8_string(gch->ptszText);
 -							ccs.wParam = PREF_UTF;
 -							CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
 -							free ((void*)ccs.lParam);
 -						} else {
 -						// Otherwise create this strange dual miranda-format
 -							ccs.lParam = (LPARAM)calloc(3, _tcslen(gch->ptszText)+1);
 -							wcstombs ((char*)ccs.lParam, gch->ptszText, _tcslen(gch->ptszText)+1);
 -							_tcscpy ((TCHAR*)((char*)ccs.lParam+strlen((char*)ccs.lParam)+1), gch->ptszText);
 -							ccs.wParam = PREF_UNICODE;
 -							CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
 -							free ((void*)ccs.lParam);
 -						}
 -#else
 -						ccs.lParam = (LPARAM)gch->ptszText;
 -						ccs.wParam = PREF_TCHAR;
 -						CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs);
 -#endif
 -					}
 -
 -					// Add our line to the chatlog	
 -					GCDEST gcd = { gch->pDest->pszModule, gch->pDest->ptszID, 0 };
 -					GCEVENT gce = { sizeof(gce), &gcd };
 -					if ( _tcsncmp(gch->ptszText, _T("/me "), 4)==0 && _tcslen(gch->ptszText)>4) {
 -						gce.ptszText = gch->ptszText+4;
 -						gcd.iType = GC_EVENT_ACTION;
 -					}
 -					else {
 -						gce.ptszText = gch->ptszText;
 -						gcd.iType = GC_EVENT_MESSAGE;
 -					}
 -
 -					if (db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv))
 -						gce.ptszNick = TranslateT("Me");
 -					else
 -						gce.ptszNick = dbv.ptszVal;
 -					db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2);
 -					gce.ptszUID = dbv2.ptszVal;
 -					gce.time = (DWORD)time(NULL);
 -					gce.dwFlags = GCEF_ADDTOLOG;
 -					gce.bIsMe = TRUE;
 -					CallService(MS_GC_EVENT, 0, (LPARAM)&gce);
 -					if (dbv.pszVal) db_free(&dbv);
 -					if (dbv2.pszVal) db_free(&dbv2);
 -				}
 -				break;
 -			case GC_USER_CHANMGR:
 -				InviteUser(gch->pDest->ptszID);
 -				break;
 -			case GC_USER_PRIVMESS: {
 -				MCONTACT hContact = find_contactT(gch->ptszUID);
 -				if (hContact) CallService(MS_MSG_SENDMESSAGE, hContact, 0);
 -				break;
 -
 -			}
 -			case GC_USER_LOGMENU:
 -				switch(gch->dwData) {
 -				case 10: InviteUser(gch->pDest->ptszID); break;
 -				case 20: KillChatSession(gch->pDest); break;
 -                case 30: 
 -					{
 -						TCHAR *ptr, buf[MAX_BUF];
 -
 -						ptr = SkypeGetT ("CHAT", (TCHAR*)gch->pDest->ptszID, "TOPIC");
 -						_tcscpy(buf, ptr);
 -						free(ptr);
 -						if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INPUTBOX), NULL, InputBoxDlgProc, (LPARAM)&buf))
 -							SetChatTopic(gch->pDest->ptszID, buf, TRUE);
 -						break;
 -					}
 -				}
 -				break;
 -			case GC_USER_NICKLISTMENU: {
 -				MCONTACT hContact = find_contactT(gch->ptszUID);
 -
 -				switch(gch->dwData) {
 -				case 10:CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); break;
 -				case 20:CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); break;
 -				case 30: KickUser(hContact, gch); break;
 -				case 110: KillChatSession(gch->pDest); break;
 -				}
 -				break;
 -			}			
 -			default:
 -				break;
 -			}
 -		}
 -
 -	}
 -	return 0;
 -}
 -
 -int __cdecl  GCMenuHook(WPARAM,LPARAM lParam) {
 -	GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
 -	DBVARIANT dbv;
 -	TCHAR* szInvite  = TranslateT("&Invite user...");
 -	TCHAR* szLeave   = TranslateT("&Leave chat session");
 -	TCHAR* szTopic   = TranslateT("Set &Topic...");
 -	TCHAR* szDetails = TranslateT("User &details");
 -	TCHAR* szHistory = TranslateT("User &history");
 -	TCHAR* szKick    = TranslateT("&Kick user");
 -
 -	static struct gc_item Item_log[] = {
 -		{NULL, 10, MENU_ITEM, FALSE},
 -		{NULL, 30, MENU_ITEM, FALSE},
 -		{NULL, 20, MENU_ITEM, FALSE}
 -	};
 -	static struct gc_item Item_nicklist_me[] = {
 -		{NULL, 20, MENU_ITEM, FALSE},
 -		{_T(""), 100, MENU_SEPARATOR, FALSE},
 -		{NULL, 110, MENU_ITEM, FALSE}
 -	};
 -	static struct gc_item Item_nicklist[] = {
 -		{NULL, 10, MENU_ITEM, FALSE},
 -		{NULL, 20, MENU_ITEM, FALSE},
 -		{NULL, 30, MENU_ITEM, FALSE}
 -	};
 -
 -	Item_log[0].pszDesc  = szInvite;
 -	Item_log[1].pszDesc  = szTopic;
 -	Item_log[2].pszDesc  = szLeave;
 -	Item_nicklist_me[0].pszDesc  = szHistory;
 -	Item_nicklist_me[2].pszDesc  = szLeave;
 -	Item_nicklist[0].pszDesc  = szDetails;
 -	Item_nicklist[1].pszDesc  = szHistory;
 -	Item_nicklist[2].pszDesc  = szKick;
 -
 -	LOG (("GCMenuHook started."));
 -	if(gcmi) {
 -		if (!_stricmp(gcmi->pszModule, SKYPE_PROTONAME)) {
 -			switch (gcmi->Type)
 -			{
 -			case MENU_ON_LOG:
 -				gcmi->nItems = sizeof(Item_log)/sizeof(Item_log[0]);
 -				gcmi->Item = &Item_log[0];
 -                LOG (("GCMenuHook: Items in log window: %d", gcmi->nItems));
 -				break;
 -			case MENU_ON_NICKLIST:
 -				if (db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1;
 -				if (!lstrcmp(dbv.ptszVal, gcmi->pszUID)) {
 -					gcmi->nItems = sizeof(Item_nicklist_me)/sizeof(Item_nicklist_me[0]);
 -					gcmi->Item = &Item_nicklist_me[0];
 -				} else {
 -					gchat_contacts *gcs = GetChat(gcmi->pszID);
 -					gchat_contact *gc = gcs?GetChatContact(gcs, gcmi->pszUID):NULL;
 -					gcmi->nItems = sizeof(Item_nicklist)/sizeof(Item_nicklist[0]);
 -
 -					Item_nicklist[2].bDisabled = FALSE;
 -					if (gc && !gc->hContact)
 -					{
 -						gcmi->nItems -= 2;
 -						gcmi->Item = &Item_nicklist[2];
 -					}
 -					else
 -						gcmi->Item = &Item_nicklist[0];
 -					/*
 -					if (protocol<7) Item_nicklist[2].bDisabled = TRUE;
 -					else {
 -						TCHAR *szChatRole;
 -						if (szChatRole = SkypeGetT ("CHAT", gcmi->pszID, "MYROLE")) {
 -							if (_tcscmp(szChatRole, _T("MASTER")) && _tcscmp(szChatRole, _T("CREATOR")))
 -								Item_nicklist[2].bDisabled = TRUE;
 -							free (szChatRole);
 -						}
 -					}*/
 -					
 -				}
 -				db_free(&dbv);
 -				break;
 -			}
 -        } else {LOG (("GCMenuHook: ERROR: Not our protocol."));}
 -	} else {LOG (("GCMenuHook: ERROR: No gcmi"));}
 -	LOG (("GCMenuHook: terminated."));
 -	return 0;
 -}
 -
 -INT_PTR GCOnLeaveChat(WPARAM wParam,LPARAM)
 -{
 -	MCONTACT hContact = (MCONTACT)wParam;
 -	DBVARIANT dbv;
 -
 -	if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0)
 -	{
 -		GCDEST gcd = { SKYPE_PROTONAME, dbv.ptszVal, GC_EVENT_CONTROL };
 -		KillChatSession(&gcd);
 -		db_free(&dbv);
 -	}
 -	return 0;
 -}
 - 
 -INT_PTR GCOnJoinChat(WPARAM wParam,LPARAM)
 -{
 -	MCONTACT hContact = (MCONTACT)wParam;
 -	DBVARIANT dbv;
 -
 -	if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0)
 -	{
 -		ChatStart (dbv.pszVal, FALSE);
 -		db_free(&dbv);
 -	}
 -	return 0;
 -}
 -
 -void GCInit(void)
 -{
 -	InitializeCriticalSection (&m_GCMutex);
 -}
 -
 -void GCExit(void)
 -{
 -	DeleteCriticalSection (&m_GCMutex);
 -
 -	for (int i=0; i < chatcount; i++) {
 -		free(chats[i].szChatName);
 -		free(chats[i].mJoinedContacts);
 -	}
 -	free(chats); chats = NULL;
 -	chatcount = 0;
 -}
 +#include "skype.h" +#include "skypeapi.h" +#include "gchat.h" +#include "contacts.h" +#include "debug.h" +#include "utf8.h" +#include "pthread.h" + +#include <m_langpack.h> +#include <m_userinfo.h> +#include <m_history.h> +#include <m_contacts.h> + +#ifndef DWLP_USER +#define DWLP_USER DWL_USER +#endif + +#ifdef _UNICODE +#define STR "%S" +#else +#define STR "%s" +#endif + +#pragma warning (disable: 4706) // assignment within conditional expression + +extern HANDLE hInitChat; +extern HINSTANCE hInst; +extern char protocol, g_szProtoName[]; +extern DWORD mirandaVersion; + +static gchat_contacts *chats=NULL; +static int chatcount=0; +static CRITICAL_SECTION m_GCMutex; + +// TODO: Disable groupchat for Protocol verisons <5 + +/****************************************************************************/ +/*                  Chat management helper functions                        */ +/****************************************************************************/ + +/* Get the gchat_contacts entry for the chat with the id szChatId +   If the chat doesn't already exist in the list, it is added. + +   Parameters: szChatId - String with the chat ID of the chat to be found +   Returns:    Pointer to the gchat_contacts entry for the given id. +			   NULL on failure (not enough memory) +*/ +gchat_contacts *GetChat(const TCHAR *szChatId) { +	int i; + +	for (i=0;i<chatcount;i++) +		if (!_tcscmp(chats[i].szChatName, szChatId)) return &chats[i]; +	if (chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*(++chatcount))) { +		memset(&chats[chatcount-1], 0, sizeof(gchat_contacts)); +		chats[chatcount-1].szChatName=_tcsdup(szChatId); +		return &chats[chatcount-1]; +	} +	return NULL; +} + +/* Removes the gchat_contacts entry for the chat with the id szChatId, +   if it exists. +   +   Parameters: szChatId - String with the chat ID to be removed from list + */ +void RemChat(TCHAR *szChatId) { +	int i; + +	for (i=0;i<chatcount;i++) +		if (!_tcscmp(chats[i].szChatName, szChatId)) { +			if (chats[i].szChatName) free(chats[i].szChatName); +			if (chats[i].mJoinedContacts) free(chats[i].mJoinedContacts); +			if (i<--chatcount) memmove(&chats[i], &chats[i+1], (chatcount-i)*sizeof(gchat_contacts)); +			chats = (gchat_contacts *)realloc(chats, sizeof(gchat_contacts)*chatcount); +			return; +		} +} + +/* Checks, if the contact with the handle hContact exists in the groupchat +   given in gc + +  Parameters: gc       - gchat_contacts entry for the chat session to be searched +			  who      - Name of member +  Returns:    -1  = Not found +              >=0 = Number of found item + */ +static int ExistsChatContact(gchat_contacts *gc, const TCHAR *who) { +	int i; + +	for (i=0;i<gc->mJoinedCount;i++) +		if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) return i; +	return -1; +} + +gchat_contact *GetChatContact(gchat_contacts *gc, const TCHAR *who) { +	int i = ExistsChatContact (gc, who); + +	if (i==-1) return NULL; +	return &gc->mJoinedContacts[i]; +} + +/* Adds contact with the name who to the groupchat given in gc + +  Parameters: gc   - +  Returns:    -1  = Contact not found +			  -2  = On failure +			  >=0 = Number of added item + */ +static int AddChatContact(gchat_contacts *gc, char *who, TCHAR *pszRole) +{ +	LOG (("AddChatContact %s", who)); +	TCHAR *twho = make_nonutf_tchar_string((const unsigned char*)who); +	if (!twho) +		return -2; + +	int i = ExistsChatContact(gc, twho); +	if (i >= 0) +		return i; + +	MCONTACT hContact = find_contact(who); + +	GCDEST gcd = { SKYPE_PROTONAME, gc->szChatName, GC_EVENT_JOIN }; +	GCEVENT gce = { sizeof(gce), &gcd }; +	gce.time = (DWORD)time(NULL); +	gce.dwFlags = GCEF_ADDTOLOG; +	gce.ptszStatus = pszRole ? pszRole : _T("USER"); + +	CONTACTINFO ci = {0}; +	ci.cbSize = sizeof(ci); +	ci.szProto = SKYPE_PROTONAME; +	ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; +	ci.hContact = hContact; + +	if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) +		gce.ptszNick=ci.pszVal;  +	else +		gce.ptszNick=twho; +         +	gce.ptszUID=twho; +	if (!CallService(MS_GC_EVENT, 0, (LPARAM)&gce)) { +		if ((gc->mJoinedContacts=(gchat_contact*)realloc(gc->mJoinedContacts, (gc->mJoinedCount+1)*sizeof(gchat_contact)))) +		{ +			gc->mJoinedContacts[i=gc->mJoinedCount].hContact=hContact; +			_tcscpy (gc->mJoinedContacts[i].szRole, gce.ptszStatus); +			_tcscpy (gc->mJoinedContacts[i].who, twho); +			gc->mJoinedCount++; +		} +	} +    if (ci.pszVal) mir_free (ci.pszVal); +	free_nonutf_tchar_string (twho); +	return i; +} + +void RemChatContact(gchat_contacts *gc, const TCHAR *who) { +	int i; + +	if (!gc) return; +	for (i=0;i<gc->mJoinedCount;i++) +		if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) { +			if (i<--gc->mJoinedCount)  +				memmove(&gc->mJoinedContacts[i], &gc->mJoinedContacts[i+1], (gc->mJoinedCount-i)*sizeof(gchat_contact)); +			if (gc->mJoinedCount) gc->mJoinedContacts = (gchat_contact*)realloc(gc->mJoinedContacts, sizeof(gchat_contact)*gc->mJoinedCount); +			else {free (gc->mJoinedContacts); gc->mJoinedContacts = NULL; } +			return; +		} +} + +MCONTACT find_chat(LPCTSTR chatname) { +	for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) { +		if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1) +		{ +			DBVARIANT dbv; +			if (!db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) { +				int tCompareResult = _tcscmp(dbv.ptszVal, chatname); +				db_free(&dbv); +				if (!tCompareResult) +					return hContact; // already there, return handle +			} +		} +	} +	return NULL; +} + +#ifdef _UNICODE +MCONTACT find_chatA(char *chatname) { +	for (MCONTACT hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact,SKYPE_PROTONAME)) { +		if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1) +		{ +			DBVARIANT dbv; +			if (!db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) { +				int tCompareResult = strcmp(dbv.pszVal, chatname); +				db_free(&dbv); +				if (!tCompareResult) +					return hContact; // already there, return handle +			} +		} +	} +	return NULL; +} +#endif + + + +int  __cdecl AddMembers(char *szSkypeMsg) { +	BYTE *contactmask=NULL; +	DBVARIANT dbv2; +	CONTACTINFO ci={0}; +	char *who, *nextoken; +	int i, iRet = 0; +	gchat_contacts *gc; + +	LOG(("AddMembers STARTED")); +	char *ptr=strstr(szSkypeMsg, " MEMBERS"); +	if (!ptr) +		return -1; +	EnterCriticalSection(&m_GCMutex); +	ptr[0]=0; +	TCHAR *szChatId = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5); +	ptr+=9; +	if (find_chat(szChatId) && (gc=GetChat(szChatId)) &&  +		!db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) +	{ +		char *pszMemObjs, *token; + +		if (protocol>=7 && (pszMemObjs = SkypeGet ("CHAT", szSkypeMsg+5, "MEMBEROBJECTS"))) { +			// Add new contacts (protocol 7+ with memberobjects, supports roles) +			for (token=strtok_r(pszMemObjs, ", ", &nextoken); token; token=strtok_r(NULL, ", ", &nextoken)) { +				if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) { +					iRet = -1; +					break; +				} +				if (!(who = SkypeGet ("CHATMEMBER", token, "IDENTITY"))) continue; +				if (strcmp(who, dbv2.pszVal)) { +					TCHAR *ptszRole = NULL; + +					char *pszRole = SkypeGet("CHATMEMBER", token, "ROLE"); +					if (pszRole) +						ptszRole = make_nonutf_tchar_string((const unsigned char*)pszRole); + +					i=AddChatContact(gc, who, ptszRole); +					free_nonutf_tchar_string (ptszRole); +					if (pszRole) free (pszRole); +					if (!(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) { +						iRet = -1; +						free (who); +						break; +					} +					contactmask[i]=TRUE; +				} +				free (who); +			} +			free (pszMemObjs); +		} +		else +		{ +			// Add new contacts (normal) +			for (who=strtok_r(ptr, " ", &nextoken); who; who=strtok_r(NULL, " ", &nextoken)) { +				if (!contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) { +					iRet = -1; +					break; +				} +				if (strcmp(who, dbv2.pszVal)) { +					i=AddChatContact(gc, who, NULL); +					if (i<0 || !(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) { +						iRet = -1; +						break; +					} +					contactmask[i]=TRUE; +				} +			} +		} +		// Quit contacts which are no longer there +		if (iRet == 0 && contactmask) { +			GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_QUIT }; +			GCEVENT gce = { sizeof(gce), &gcd }; +			gce.time = (DWORD)time(NULL); +			gce.dwFlags = GCEF_ADDTOLOG; +         +			ci.cbSize = sizeof(ci); +			ci.szProto = SKYPE_PROTONAME; +			ci.dwFlag = CNF_DISPLAY; + +			for (i=0;i<gc->mJoinedCount;i++) +			if (!contactmask[i])  +			{ +				ci.hContact = gc->mJoinedContacts[i].hContact; +				ci.dwFlag = CNF_TCHAR; +				if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal;  +				else gce.ptszNick=gc->mJoinedContacts[i].who; +				gce.ptszUID = gc->mJoinedContacts[i].who; +				CallService(MS_GC_EVENT, 0, (LPARAM)&gce); +				if (ci.pszVal) { +					mir_free (ci.pszVal); +					ci.pszVal=NULL; +				} +				RemChatContact(gc, gc->mJoinedContacts[i].who); +			} +	// We don't do this, because the dialog group-chat may have been started intentionally +	/* +			if (gc->mJoinedCount == 1) { +				// switch back to normal session +				KillChatSession(&gcd); +			} +	*/ +		} +		if (contactmask) free(contactmask); +		db_free(&dbv2); +	} else iRet = -1; +	free_nonutf_tchar_string (szChatId); +	LeaveCriticalSection(&m_GCMutex); +	LOG(("AddMembers DONE")); +	return iRet; +} + +void AddMembersThread(char *szSkypeMsg) +{ +	AddMembers(szSkypeMsg); +	free(szSkypeMsg); +} + +/****************************************************************************/ +/*                           Window procedures                              */ +/****************************************************************************/ +INT_PTR CALLBACK InputBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ +	switch (msg) { +	case WM_INITDIALOG: +	{ +		TranslateDialogDefault(hwndDlg); +		SetWindowLongPtr(hwndDlg, DWLP_USER, lParam); +		SetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)lParam); +		return TRUE; +	} + +	case WM_COMMAND: +		switch ( LOWORD( wParam )) { +		case IDOK: +		{	 +			GetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER), (MAX_BUF-1)*sizeof(TCHAR)); +			EndDialog(hwndDlg, 1); +			break; +		} +		case IDCANCEL: +			EndDialog(hwndDlg, 0); +			break; +	}	} +	return FALSE; +} + +/****************************************************************************/ +/*                      Core Chat management functions                      */ +/****************************************************************************/ + +/* We have a new Groupchat + +   This hook is called when a new chat is initialised. +   Parameters:  wParam = (char *)Name of new chat session [Has to be ASCIIZ/UTF8] +				lParam = 1 - Create groupchat, but don't open it +				         0 - Default - open groupchat after init +*/ + +int __cdecl  ChatInit(WPARAM wParam, LPARAM lParam) +{ +	if (!wParam) return -1; + +	DBVARIANT dbv, dbv2; +	int iRet = -1; + +	GCSESSION gcw = { sizeof(gcw) }; +	gcw.iType = GCW_CHATROOM; +	gcw.pszModule = SKYPE_PROTONAME; + +	char *szChatName = SkypeGet ("CHAT", (char *)wParam, "FRIENDLYNAME"); +	if (!szChatName || !*szChatName) +		gcw.ptszName=TranslateT("Unknown"); else { +#ifdef _UNICODE +		gcw.ptszName=make_unicode_string((const unsigned char*)szChatName); +		free (szChatName); +		szChatName = (char*)gcw.ptszName; +#else +		gcw.ptszName=szChatName; +#endif +	} +	gcw.ptszID = make_nonutf_tchar_string((const unsigned char*)wParam); +	gcw.ptszStatusbarText = NULL; +	EnterCriticalSection(&m_GCMutex); +	if (!CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw)) { +		char *szChatRole; + +		GCDEST gcd = { SKYPE_PROTONAME, gcw.ptszID, GC_EVENT_ADDGROUP }; +		GCEVENT gce = { sizeof(gce), &gcd }; +		gce.ptszStatus = _T("CREATOR"); +		// BUG: Groupchat returns nonzero on success here in earlier versions, so we don't check +		// it here +		CallService(MS_GC_EVENT, 0, (LPARAM)&gce); +		gce.ptszStatus = _T("MASTER"); +		CallService(MS_GC_EVENT, 0, (LPARAM)&gce); +		gce.ptszStatus = _T("HELPER"); +		CallService(MS_GC_EVENT, 0, (LPARAM)&gce); +		gce.ptszStatus = _T("USER"); +		CallService(MS_GC_EVENT, 0, (LPARAM)&gce); +		gce.ptszStatus = _T("LISTENER"); +		CallService(MS_GC_EVENT, 0, (LPARAM)&gce); +		gce.ptszStatus = _T("APPLICANT"); +		CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + +		gcd.iType = GC_EVENT_JOIN; +		gce.ptszStatus = NULL; +		if (protocol >=7 && (szChatRole = SkypeGet ("CHAT", (char *)wParam, "MYROLE"))) { +			if (strncmp(szChatRole, "ERROR", 5)) +			{ +#ifdef _UNICODE +				gce.ptszStatus = make_unicode_string((const unsigned char*)szChatRole); +				free (szChatRole); +#else +				gce.ptszStatus = szChatRole; +#endif +			} +		} +		if (!gce.ptszStatus) gce.ptszStatus=_tcsdup(_T("CREATOR")); + +		if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) { +			if (!db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) { +				gce.ptszNick = dbv.ptszVal; +				gce.ptszUID = dbv2.ptszVal; +				gce.time = 0; +				gce.bIsMe = TRUE; +				gce.dwFlags |= GCEF_ADDTOLOG; +				if (!CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce)) { +					gcd.iType = GC_EVENT_CONTROL; +					if (!lParam) +						CallService(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce); +					CallService(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce); +					CallService(MS_GC_EVENT, lParam ? WINDOW_HIDDEN : WINDOW_VISIBLE, (LPARAM)&gce); +					SkypeSend ("GET CHAT %s MEMBERS", (char *)wParam); +					iRet = 0; +				} +				else {LOG (("ChatInit: Joining 'me' failed."));} +			} +			db_free(&dbv2); +		} +		free ((void*)gce.ptszStatus); +		db_free(&dbv); +	} +	free (szChatName); +	free_nonutf_tchar_string ((void*)gcw.ptszID); +	LeaveCriticalSection(&m_GCMutex); +	return iRet; +} + +/* Open new Groupchat + +   Parameters:  szChatId = (char *)Name of new chat session +*/ +int  __cdecl ChatStart(char *szChatId, BOOL bJustCreate) { +	LOG(("ChatStart: New groupchat started")); +	if (!szChatId || NotifyEventHooks(hInitChat, (WPARAM)szChatId, bJustCreate)) return -1; +	return 0; +} + + +void KillChatSession(GCDEST *gcd) +{ +	GCEVENT gce = { sizeof(gce), gcd }; +	EnterCriticalSection(&m_GCMutex); +	LOG(("KillChatSession: Groupchatsession terminated.")); +	gcd->iType = GC_EVENT_CONTROL; +	if (SkypeSend ("ALTER CHAT "STR" LEAVE", gcd->ptszID) == 0) +	{ +		CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); +		CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce); +	} +	LeaveCriticalSection(&m_GCMutex); +} + +void InviteUser(const TCHAR *szChatId) +{ +	if (!szChatId) +		return; + +	gchat_contacts *gc=GetChat(szChatId); +	if (!gc) +		return; + +	// add the heading +	HMENU tMenu = CreatePopupMenu(); +	AppendMenu(tMenu, MF_STRING|MF_GRAYED|MF_DISABLED, 0, TranslateT("&Invite user...")); +	AppendMenu(tMenu, MF_SEPARATOR, 1, NULL); +     +	DBVARIANT dbv; +	POINT pt; +	int j; + +	// generate a list of contact +	for (MCONTACT hContact = db_find_first(SKYPE_PROTONAME);hContact;hContact = db_find_next(hContact,SKYPE_PROTONAME)) { +		if (!db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) && +			 db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE)  +		{ +			BOOL alreadyInSession = FALSE; +			for (j=0; j<gc->mJoinedCount; j++) { +				if (gc->mJoinedContacts[j].hContact==hContact) { +					alreadyInSession = TRUE; +					break; +				} +			} +            if (!alreadyInSession) +				AppendMenu(tMenu, MF_STRING, (UINT_PTR)hContact,  +					(TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR)); +        } +		 +	} + +	HWND tWindow = CreateWindow(_T("EDIT"),_T(""),0,1,1,1,1,NULL,NULL,hInst,NULL); + +	GetCursorPos (&pt); +	MCONTACT hInvitedUser = (MCONTACT)TrackPopupMenu(tMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, tWindow, NULL); +	DestroyMenu(tMenu); +	DestroyWindow(tWindow); + +	if (!hInvitedUser || db_get_s(hInvitedUser, SKYPE_PROTONAME, SKYPE_NAME, &dbv))  +		return; +	SkypeSend ("ALTER CHAT "STR" ADDMEMBERS %s", szChatId, dbv.pszVal); +	db_free(&dbv); + +} + +static void KickUser (MCONTACT hContact, GCHOOK *gch) +{ +	EnterCriticalSection(&m_GCMutex); +	if (SkypeSend ("ALTER CHAT "STR" KICK "STR, gch->pDest->ptszID, gch->ptszUID)!=-1) { +		char *ptr = SkypeRcv("ALTER CHAT KICK", 2000); +		if (ptr) { +			if (strncmp(ptr, "ERROR", 5)) { +				GCDEST gcd = { SKYPE_PROTONAME, gch->pDest->ptszID, GC_EVENT_KICK }; +				GCEVENT gce = { sizeof(gce), &gcd }; +				gce.time = (DWORD)time(NULL); +				gce.dwFlags = GCEF_ADDTOLOG; +				gce.ptszUID = gch->ptszUID; + +				CONTACTINFO ci = {0}; +				ci.cbSize = sizeof(ci); +				ci.szProto = SKYPE_PROTONAME; +				ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; +				ci.hContact = hContact; +				if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal;  +				else gce.ptszNick=gce.ptszUID; +         +				DBVARIANT dbv; +				if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) { +					gce.ptszStatus = dbv.ptszVal;		 +					CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); +					RemChatContact (GetChat(gcd.ptszID), gch->ptszUID); +					db_free(&dbv); +				} +				if (ci.pszVal) mir_free (ci.pszVal); +			} +			free (ptr); +		} +	} +	LeaveCriticalSection(&m_GCMutex); +} + +void SetChatTopic(const TCHAR *szChatId, TCHAR *szTopic, BOOL bSet) +{ +	MCONTACT hContact = find_chat (szChatId); +	char *szUTFTopic; + +	GCDEST gcd = { SKYPE_PROTONAME, szChatId, GC_EVENT_TOPIC }; +	GCEVENT gce = { sizeof(gce), &gcd }; +	gce.ptszText = szTopic; +	gce.dwFlags = GCEF_ADDTOLOG; +	gce.time = (DWORD)time (NULL); +	CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + +	gcd.iType = GC_EVENT_SETSBTEXT; +	CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + +	if (bSet) { +#ifdef _UNICODE +		szUTFTopic=(char*)make_utf8_string(szTopic); +#else +		if (utf8_encode(szTopic, &szUTFTopic)==-1) szUTFTopic = NULL; +#endif +		if (szUTFTopic) { +			SkypeSend ("ALTER CHAT "STR" SETTOPIC %s", szChatId, szUTFTopic); +			free (szUTFTopic); +		} +		testfor ("ALTER CHAT SETTOPIC", INFINITE); +	} + +	if (hContact) +		db_set_ts(hContact, SKYPE_PROTONAME, "Nick", szTopic); +} + + +int GCEventHook(WPARAM,LPARAM lParam) { +	GCHOOK *gch = (GCHOOK*)lParam; +	gchat_contacts *gc; + +	if (gch == NULL || gch->pDest == NULL) +		return 0; +	if (_stricmp(gch->pDest->pszModule, SKYPE_PROTONAME)) +		return 0; +	gc = GetChat(gch->pDest->ptszID); + +	switch (gch->pDest->iType) { +	case GC_SESSION_TERMINATE: { +		MCONTACT hContact; + +		if (gc->mJoinedCount == 1) { +			// switch back to normal session +			// I don't know if this behaviour isn't a bit annoying, therefore, we +			// don't do this now, until a user requests this feature :) +     +			// open up srmm dialog when quit while 1 person left +			// CallService(MS_MSG_SENDMESSAGE, (WPARAM)gc->mJoinedContacts[0].hContact, 0); + +			RemChatContact(gc, gc->mJoinedContacts[0].who); +		} +		// Delete Chatroom from Contact list, as we don't need it anymore...? +		if (hContact = find_chat(gc->szChatName)) +			CallService(MS_DB_CONTACT_DELETE, hContact, 0);  +		RemChat(gc->szChatName); + +		break; +	} +	case GC_USER_MESSAGE: +		if(gch->ptszText && _tcslen(gch->ptszText) > 0) { +			DBVARIANT dbv, dbv2; +			CCSDATA ccs = {0}; +			TCHAR *pEnd; + +			// remove the ending linebreak +			for (pEnd = &gch->ptszText[_tcslen(gch->ptszText) - 1]; +				 *pEnd==_T('\r') || *pEnd==_T('\n'); pEnd--) *pEnd=0; +    // Send message to the chat-contact     +			if (ccs.hContact = find_chat(gch->pDest->ptszID)) { +#ifdef _UNICODE +				// If PREF_UTF is supported, just convert it to UTF8 and pass the buffer to PSS_MESSAGE +				if (mirandaVersion >= 0x070000) { +					ccs.lParam = (LPARAM)make_utf8_string(gch->ptszText); +					ccs.wParam = PREF_UTF; +					CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); +					free ((void*)ccs.lParam); +				} else { +				// Otherwise create this strange dual miranda-format +					ccs.lParam = (LPARAM)calloc(3, _tcslen(gch->ptszText)+1); +					wcstombs ((char*)ccs.lParam, gch->ptszText, _tcslen(gch->ptszText)+1); +					_tcscpy ((TCHAR*)((char*)ccs.lParam+strlen((char*)ccs.lParam)+1), gch->ptszText); +					ccs.wParam = PREF_UNICODE; +					CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); +					free ((void*)ccs.lParam); +				} +#else +				ccs.lParam = (LPARAM)gch->ptszText; +				ccs.wParam = PREF_TCHAR; +				CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); +#endif +			} + +			// Add our line to the chatlog	 +			GCDEST gcd = { gch->pDest->pszModule, gch->pDest->ptszID, 0 }; +			GCEVENT gce = { sizeof(gce), &gcd }; +			if ( _tcsncmp(gch->ptszText, _T("/me "), 4)==0 && _tcslen(gch->ptszText)>4) { +				gce.ptszText = gch->ptszText+4; +				gcd.iType = GC_EVENT_ACTION; +			} +			else { +				gce.ptszText = gch->ptszText; +				gcd.iType = GC_EVENT_MESSAGE; +			} + +			if (db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) +				gce.ptszNick = TranslateT("Me"); +			else +				gce.ptszNick = dbv.ptszVal; +			db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2); +			gce.ptszUID = dbv2.ptszVal; +			gce.time = (DWORD)time(NULL); +			gce.dwFlags = GCEF_ADDTOLOG; +			gce.bIsMe = TRUE; +			CallService(MS_GC_EVENT, 0, (LPARAM)&gce); +			if (dbv.pszVal) db_free(&dbv); +			if (dbv2.pszVal) db_free(&dbv2); +		} +		break; +	case GC_USER_CHANMGR: +		InviteUser(gch->pDest->ptszID); +		break; +	case GC_USER_PRIVMESS: { +		MCONTACT hContact = find_contactT(gch->ptszUID); +		if (hContact) CallService(MS_MSG_SENDMESSAGE, hContact, 0); +		break; + +	} +	case GC_USER_LOGMENU: +		switch(gch->dwData) { +		case 10: InviteUser(gch->pDest->ptszID); break; +		case 20: KillChatSession(gch->pDest); break; +		case 30:  +			{ +				TCHAR *ptr, buf[MAX_BUF]; + +				ptr = SkypeGetT ("CHAT", (TCHAR*)gch->pDest->ptszID, "TOPIC"); +				_tcscpy(buf, ptr); +				free(ptr); +				if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INPUTBOX), NULL, InputBoxDlgProc, (LPARAM)&buf)) +					SetChatTopic(gch->pDest->ptszID, buf, TRUE); +				break; +			} +		} +		break; +	case GC_USER_NICKLISTMENU: { +		MCONTACT hContact = find_contactT(gch->ptszUID); + +		switch(gch->dwData) { +		case 10:CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); break; +		case 20:CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); break; +		case 30: KickUser(hContact, gch); break; +		case 110: KillChatSession(gch->pDest); break; +		} +		break; +	}			 +	default: +		break; +	} + +	return 0; +} + +int __cdecl  GCMenuHook(WPARAM,LPARAM lParam) { +	GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; +	DBVARIANT dbv; +	TCHAR* szInvite  = TranslateT("&Invite user..."); +	TCHAR* szLeave   = TranslateT("&Leave chat session"); +	TCHAR* szTopic   = TranslateT("Set &Topic..."); +	TCHAR* szDetails = TranslateT("User &details"); +	TCHAR* szHistory = TranslateT("User &history"); +	TCHAR* szKick    = TranslateT("&Kick user"); + +	static struct gc_item Item_log[] = { +		{NULL, 10, MENU_ITEM, FALSE}, +		{NULL, 30, MENU_ITEM, FALSE}, +		{NULL, 20, MENU_ITEM, FALSE} +	}; +	static struct gc_item Item_nicklist_me[] = { +		{NULL, 20, MENU_ITEM, FALSE}, +		{_T(""), 100, MENU_SEPARATOR, FALSE}, +		{NULL, 110, MENU_ITEM, FALSE} +	}; +	static struct gc_item Item_nicklist[] = { +		{NULL, 10, MENU_ITEM, FALSE}, +		{NULL, 20, MENU_ITEM, FALSE}, +		{NULL, 30, MENU_ITEM, FALSE} +	}; + +	Item_log[0].pszDesc  = szInvite; +	Item_log[1].pszDesc  = szTopic; +	Item_log[2].pszDesc  = szLeave; +	Item_nicklist_me[0].pszDesc  = szHistory; +	Item_nicklist_me[2].pszDesc  = szLeave; +	Item_nicklist[0].pszDesc  = szDetails; +	Item_nicklist[1].pszDesc  = szHistory; +	Item_nicklist[2].pszDesc  = szKick; + +	LOG (("GCMenuHook started.")); +	if(gcmi) { +		if (!_stricmp(gcmi->pszModule, SKYPE_PROTONAME)) { +			switch (gcmi->Type) +			{ +			case MENU_ON_LOG: +				gcmi->nItems = sizeof(Item_log)/sizeof(Item_log[0]); +				gcmi->Item = &Item_log[0]; +                LOG (("GCMenuHook: Items in log window: %d", gcmi->nItems)); +				break; +			case MENU_ON_NICKLIST: +				if (db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; +				if (!lstrcmp(dbv.ptszVal, gcmi->pszUID)) { +					gcmi->nItems = sizeof(Item_nicklist_me)/sizeof(Item_nicklist_me[0]); +					gcmi->Item = &Item_nicklist_me[0]; +				} else { +					gchat_contacts *gcs = GetChat(gcmi->pszID); +					gchat_contact *gc = gcs?GetChatContact(gcs, gcmi->pszUID):NULL; +					gcmi->nItems = sizeof(Item_nicklist)/sizeof(Item_nicklist[0]); + +					Item_nicklist[2].bDisabled = FALSE; +					if (gc && !gc->hContact) +					{ +						gcmi->nItems -= 2; +						gcmi->Item = &Item_nicklist[2]; +					} +					else +						gcmi->Item = &Item_nicklist[0]; +					/* +					if (protocol<7) Item_nicklist[2].bDisabled = TRUE; +					else { +						TCHAR *szChatRole; +						if (szChatRole = SkypeGetT ("CHAT", gcmi->pszID, "MYROLE")) { +							if (_tcscmp(szChatRole, _T("MASTER")) && _tcscmp(szChatRole, _T("CREATOR"))) +								Item_nicklist[2].bDisabled = TRUE; +							free (szChatRole); +						} +					}*/ +					 +				} +				db_free(&dbv); +				break; +			} +        } else {LOG (("GCMenuHook: ERROR: Not our protocol."));} +	} else {LOG (("GCMenuHook: ERROR: No gcmi"));} +	LOG (("GCMenuHook: terminated.")); +	return 0; +} + +INT_PTR GCOnLeaveChat(WPARAM wParam,LPARAM) +{ +	MCONTACT hContact = (MCONTACT)wParam; +	DBVARIANT dbv; + +	if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0) +	{ +		GCDEST gcd = { SKYPE_PROTONAME, dbv.ptszVal, GC_EVENT_CONTROL }; +		KillChatSession(&gcd); +		db_free(&dbv); +	} +	return 0; +} +  +INT_PTR GCOnJoinChat(WPARAM wParam,LPARAM) +{ +	MCONTACT hContact = (MCONTACT)wParam; +	DBVARIANT dbv; + +	if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0) +	{ +		ChatStart (dbv.pszVal, FALSE); +		db_free(&dbv); +	} +	return 0; +} + +void GCInit(void) +{ +	InitializeCriticalSection (&m_GCMutex); +} + +void GCExit(void) +{ +	DeleteCriticalSection (&m_GCMutex); + +	for (int i=0; i < chatcount; i++) { +		free(chats[i].szChatName); +		free(chats[i].mJoinedContacts); +	} +	free(chats); +	chats = NULL; +	chatcount = 0; +} | 
