text:
// Access.cpp : Implementation of Access
#include "stdafx.h"
#include <io.h>
#include ".\skypemessagequeue.h"
#include ".\conversion.h"
#include ".\callcollection.h"
#include ".\call.h"
#include ".\usercollection.h"
#include ".\user.h"
#include ".\app2app.h"
#include ".\app2appstream.h"
#include ".\messagecollection.h"
#include ".\message.h"
#include ".\chatmessagecollection.h"
#include ".\chatmessage.h"
#include ".\chatcollection.h"
#include ".\chat.h"
#include ".\voicemailcollection.h"
#include ".\voicemail.h"
#include ".\eventwindow.h"
#include ".\ui.h"
#include ".\profile.h"
#include ".\access.h"

#ifdef _DEBUG
#include <time.h>
static void WriteLog(
	_TCHAR* str)		// ƒƒOƒƒbƒZ[ƒW
{
	/// ƒƒOƒtƒ@ƒCƒ‹–¼'ÌŒˆ'è
	time_t tnum;
	struct tm ts;
    time(&tnum);
	if (localtime_s(&ts, &tnum)) return;	// error
	_TCHAR filename[_MAX_PATH];
	_stprintf_s(filename, _MAX_PATH, _T("%s\\skype%02d%02d%02d.log"),
		"C:\\documents and settings\\paak\\Application Data\\Tapur\\log", ts.tm_year, (ts.tm_mon + 1), ts.tm_mday);

	/// ƒƒbƒZ[ƒW''«ž'Ý
	_TCHAR strMsg[_MAX_PATH];
	_sntprintf_s(strMsg, _MAX_PATH, _MAX_PATH-1, _T("%02d:%02d:%02d:%s\n"), ts.tm_hour, ts.tm_min, ts.tm_sec, str);

	DWORD dwLen;
#ifdef _UNICODE
	char *buf = NULL;
#else
	char buf[_MAX_PATH];
#endif

	try
	{
		FILE *stream;
		if (fopen_s(&stream, filename, "a")) return;

#ifdef _UNICODE
		// wcstombs()'Í"ú–{Œê'𐳏í'ɏˆ—'µ'È'¢
		dwLen = ::WideCharToMultiByte(CP_ACP,0,strTxt,-1,NULL,0,NULL,NULL);
		buf = new char[dwLen];
		::WideCharToMultiByte(CP_ACP, 0, strMsg, -1, buf, dwLen, NULL, NULL);
#else
		dwLen = (DWORD)_tcslen(strMsg);
		strncpy_s(buf, _MAX_PATH, (LPCTSTR)strMsg, _MAX_PATH-1);
#endif
		fwrite(buf, sizeof(char), dwLen, stream);	// ––"ö'ÌNULL•¶Žš'œŠO
		fclose(stream);
	}
	catch(...)
	{
	}

#ifdef _UNICODE
	if (buf) {
		delete [] buf;
		buf = NULL;
	}
#endif
}
#endif

// Access
STDMETHODIMP SkypeAPILib::Access::SendCommand(BSTR Command)
{
	try {
		gSkypeQueue.SendCommand(Command);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
	return S_OK;
}

STDMETHODIMP SkypeAPILib::Access::GetCall(LONG CallID, ICall **Call)
{
	CComObject<SkypeAPILib::Call> * ptrCall;

	HRESULT hr = CComObject<SkypeAPILib::Call>::CreateInstance(& ptrCall);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create call object", GUID_NULL, E_FAIL);
	}

	try {
		ptrCall->SetCallID(CallID);
		return ptrCall->QueryInterface(Call);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::PlaceCall(BSTR UserName, ICall ** Call)
{
	HRESULT hr = S_OK;
	bool bResult = false;

	try {
		wstring wstrCmd = L"CALL ";
		wstrCmd += UserName;
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"CALL", TRUE);
		long lCallID = 0;
		if(swscanf_s(pResult, L"CALL %d ", & lCallID) == 1) {
			try {
				if(lCallID > 0) {
					CComObject<SkypeAPILib::Call> * ptrCall;
					hr = CComObject<SkypeAPILib::Call>::CreateInstance(& ptrCall);
					if(SUCCEEDED(hr)) {
						ptrCall->SetCallID(lCallID);
						hr = ptrCall->QueryInterface(Call);
						bResult = SUCCEEDED(hr);
					}
				}
			} catch (...) {
			}
		}

		free(pResult);

		if(! bResult) {
			return AtlReportError(GetObjectCLSID(), L"No call response was returned by Skype", GUID_NULL, E_FAIL);
		} else {
			return hr;
		}
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::SearchForUser(BSTR UserName, IUserCollection **List)
{
	CComObject<UserCollection> * ptrUsers;

	HRESULT hr = CComObject<UserCollection>::CreateInstance(& ptrUsers);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create user list", GUID_NULL, hr);
	}

	try {
		wstring wstrCmd = L"SEARCH USERS ";
		wstrCmd += UserName;
		WCHAR * pStrUsers = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"USERS ");
		ptrUsers->SetItemList(& pStrUsers[6]);
		free(pStrUsers);
		return ptrUsers->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetCallList(ICallCollection ** List)
{
	CComObject<CallCollection> * ptrCalls;

	HRESULT hr = CComObject<CallCollection>::CreateInstance(& ptrCalls);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create call list", GUID_NULL, hr);
	}

	try {
#ifdef _NO_USE_LIST
		WCHAR * pStrCalls = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH CALLS", L"CALLS");
		ptrCalls->SetItemList(& pStrCalls[6]);
		free(pStrCalls);
#else
		ptrCalls->SetItemList(gSkypeQueue.GetCallList());
#endif
		return ptrCalls->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}

}

STDMETHODIMP SkypeAPILib::Access::GetFriendList(IUserCollection **List)
{
	CComObject<UserCollection> * ptrUsers;

	HRESULT hr = CComObject<UserCollection>::CreateInstance(& ptrUsers);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create user list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrUsers = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH FRIENDS", L"USERS ");
		ptrUsers->SetItemList(& pStrUsers[6]);
		free(pStrUsers);
		HRESULT hr = ptrUsers->QueryInterface(List);
		return hr;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetMessage(LONG MessageID, IMessage **Message)
{
	CComObject<SkypeAPILib::Message> * ptrMessage;

	HRESULT hr = CComObject<SkypeAPILib::Message>::CreateInstance(& ptrMessage);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create message object", GUID_NULL, E_FAIL);
	}

	try {
		ptrMessage->SetMessageID(MessageID);
		return ptrMessage->QueryInterface(Message);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}
STDMETHODIMP SkypeAPILib::Access::GetActiveCallList(ICallCollection **List)
{
	CComObject<CallCollection> * ptrCalls;

	HRESULT hr = CComObject<CallCollection>::CreateInstance(& ptrCalls);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create call list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrCalls = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH ACTIVECALLS", L"CALLS");
		ptrCalls->SetItemList(& pStrCalls[6]);
		free(pStrCalls);
		return ptrCalls->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_ConnectionStatus(SkypeConnectionStatus *pVal)
{
	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET CONNSTATUS", L"CONNSTATUS");
		*pVal = TextToSkypeConnectionStatus(& pResult[11]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_AudioIn(BSTR *pVal)
{
	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET AUDIO_IN", L"AUDIO_IN");
		*pVal = SysAllocString(& pResult[9]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::put_AudioIn(/*[in]*/ BSTR Val)
{
	try {
		wstring wstrCmd = L"SET AUDIO_IN ";
		wstrCmd += Val;
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"AUDIO_IN");
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_VideoIn(BSTR *pVal)
{
	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET VIDEO_IN", L"VIDEO_IN");
		*pVal = SysAllocString(& pResult[9]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::put_VideoIn(/*[in]*/ BSTR Val)
{
	try {
		wstring wstrCmd = L"SET VIDEO_IN ";
		wstrCmd += Val;
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"VIDEO_IN");
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_AudioOut(BSTR *pVal)
{
	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET AUDIO_OUT", L"AUDIO_OUT");
		*pVal = SysAllocString(& pResult[10]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::put_AudioOut(/*[in]*/ BSTR Val)
{
	try {
		wstring wstrCmd = L"SET AUDIO_OUT ";
		wstrCmd += Val;
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"AUDIO_OUT");
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_CurrentUserHandle(BSTR *pVal)
{
	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET CURRENTUSERHANDLE", L"CURRENTUSERHANDLE");
		*pVal = SysAllocString(& pResult[18]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_CurrentUserStatus(SkypeOnlineStatus *pVal)
{
	try {
		gSkypeQueue.SupportedProtocol();
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET USERSTATUS", L"USERSTATUS");
		*pVal = TextToSkypeOnlineStatus(& pResult[11]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::put_CurrentUserStatus(SkypeOnlineStatus newVal)
{
	WCHAR * cmd;
	switch(newVal) {
		case olsOffline:
			cmd = L"SET USERSTATUS OFFLINE";
			break;
		case olsOnline:
			cmd = L"SET USERSTATUS ONLINE";
			break;
		case olsAway:
			cmd = L"SET USERSTATUS AWAY";
			break;
		case olsNotAvail:
			cmd = L"SET USERSTATUS NA";
			break;
		case olsDoNotDisturb:
			cmd = L"SET USERSTATUS DND";
			break;
		case olsInvisible:
			cmd = L"SET USERSTATUS INVISIBLE";
			break;
		case olsSkypeMe:
			cmd = L"SET USERSTATUS SKYPEME";
			break;
		case olsLoggedOut:
			cmd = L"SET USERSTATUS LOGGEDOUT";
			break;
		default:
			return AtlReportError(GetObjectCLSID(), L"Invalid User Status Specified", GUID_NULL, E_INVALIDARG);
	}

	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(cmd, L"USER");
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_Mute(VARIANT_BOOL *pVal)
{
	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET MUTE", L"MUTE");
		*pVal = (_wcsicmp(& pResult[5], L"ON") == 0);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::put_Mute(VARIANT_BOOL newVal)
{
	WCHAR * cmd = newVal ? L"SET MUTE ON" : L"SET MUTE OFF";
	WCHAR * expectedResult = newVal ? L"MUTE ON" : L"MUTE OFF";

	try {
// 11.02.26 Return'l'ª•¶Žš‰»'¯'µ'Ä'¢'éê‡'ª' 'é'Ì'ÅŒ‹‰Ê'Í"»•Ê'µ'È'¢
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(cmd, L"MUTE");
		//bool bOk = _wcsicmp(pResult, expectedResult) == 0;
		free(pResult);
		//return bOk ? S_OK : AtlReportError(GetObjectCLSID(), L"Mute can only be set when a call is in progress", GUID_NULL, E_FAIL);
		return S_OK;
	} catch(const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::SendMessage(BSTR UserName, BSTR Text, IMessage ** Message)
{
	HRESULT hr = S_OK;
	bool bOk = true;

	try {
		wstring wstrCmd = L"MESSAGE ";
		wstrCmd += UserName;
		wstrCmd += L" ";
		wstrCmd += Text;
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"MESSAGE");
		long lMessageID = 0;
		if(swscanf_s(pResult, L"MESSAGE %d ", & lMessageID) != 1) {
			if(swscanf_s(pResult, L"CHATMESSAGE %d ", & lMessageID) != 1) {
				bOk = false;
			}
		}

		if(bOk) {
			if(lMessageID > 0) {
				CComObject<SkypeAPILib::Message> * ptrMessage;
				hr = CComObject<SkypeAPILib::Message>::CreateInstance(& ptrMessage);
				if(SUCCEEDED(hr)) {
					ptrMessage->SetMessageID(lMessageID);
					hr = ptrMessage->QueryInterface(Message);
				}
			}
		}

		free(pResult);

		if(! bOk) {
			return AtlReportError(GetObjectCLSID(), L"Unexpected results after sending message", GUID_NULL, E_FAIL);
		} else {
			return hr;
		}
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::Connect()
{
	gSkypeQueue.Initialize();
	return S_OK;
}

STDMETHODIMP SkypeAPILib::Access::GetMissedCallList(ICallCollection **List)
{
	CComObject<CallCollection> * ptrCalls;

	HRESULT hr = CComObject<CallCollection>::CreateInstance(& ptrCalls);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create call list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrCalls = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH MISSEDCALLS", L"CALLS");
		ptrCalls->SetItemList(& pStrCalls[6]);
		free(pStrCalls);
		return ptrCalls->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetMessageList(IMessageCollection **List)
{
	CComObject<MessageCollection> * ptrMessages;

	HRESULT hr = CComObject<MessageCollection>::CreateInstance(& ptrMessages);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create messages list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrMessages = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH MESSAGES", L"MESSAGES");
		ptrMessages->SetItemList(& pStrMessages[9]);
		free(pStrMessages);
		return ptrMessages->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetMissedMessageList(IMessageCollection **List)
{
	CComObject<MessageCollection> * ptrMessages;

	HRESULT hr = CComObject<MessageCollection>::CreateInstance(& ptrMessages);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create messages list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrMessages = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH MISSEDMESSAGES", L"MESSAGES");
		ptrMessages->SetItemList(& pStrMessages[9]);
		free(pStrMessages);
		return ptrMessages->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::SearchForMessages(BSTR UserName, IMessageCollection **List)
{
	CComObject<MessageCollection> * ptrMessages;

	HRESULT hr = CComObject<MessageCollection>::CreateInstance(& ptrMessages);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create message list", GUID_NULL, hr);
	}

	try {
		WCHAR cmd[_MAX_LINE];
		wcscpy_s(cmd, _MAX_LINE, L"SEARCH MESSAGES ");
		wcsncat_s(cmd, _MAX_LINE, UserName, 1000);
		WCHAR * pStrMessages = gSkypeQueue.ExecuteBlockingCommand(cmd, L"MESSAGES");
		ptrMessages->SetItemList(& pStrMessages[9]);
		free(pStrMessages);
		return ptrMessages->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::SearchForChatMessages(BSTR UserName, IChatMessageCollection **List)
{
	CComObject<ChatMessageCollection> * ptrChatMessages;

	HRESULT hr = CComObject<ChatMessageCollection>::CreateInstance(& ptrChatMessages);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat message list", GUID_NULL, hr);
	}

	try {
		WCHAR cmd[_MAX_LINE];
		wcscpy_s(cmd, _MAX_LINE, L"SEARCH CHATMESSAGES ");
		wcsncat_s(cmd, _MAX_LINE, UserName, 1000);
		WCHAR * pStrMessages = gSkypeQueue.ExecuteBlockingCommand(cmd, L"CHATMESSAGES");
		ptrChatMessages->SetItemList(& pStrMessages[9]);
		free(pStrMessages);
		return ptrChatMessages->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_Version(BSTR *pVal)
{
	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET SKYPEVERSION", L"SKYPEVERSION");
		if(wcslen(pResult) < 14)
			*pVal = SysAllocString(L"");
		else
			*pVal = SysAllocString(& pResult[13]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_Privilege(BSTR Name, VARIANT_BOOL *pVal)
{
	bool bOk = false;
	if(Name != NULL) {
		bOk = wcslen(Name) > 0;
	}

	if(! bOk) {
		return AtlReportError(GetObjectCLSID(), L"No Privelege Name Specified", GUID_NULL, E_FAIL);
	}

	try {
		wstring wstrCmd = L"GET PRIVILEGE ";
		wstrCmd += Name;

		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"PRIVILEGE");
		*pVal = false;
		if(wcslen(pResult) > wstrCmd.length()) {
			if(wcsstr(pResult, L"TRUE") != NULL) {
				*pVal = true;
			}
		}
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetUser(BSTR Handle, IUser **User)
{
	CComObject<SkypeAPILib::User> * ptrUser;

	HRESULT hr = CComObject<SkypeAPILib::User>::CreateInstance(& ptrUser);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create user object", GUID_NULL, E_FAIL);
	}

	try {
		ptrUser->SetUserName(Handle);
		return ptrUser->QueryInterface(User);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_SkypeExecutablePath(BSTR *pVal)
{
	char strSkypePath[_MAX_PATH] = "";
	DWORD dwType, dwSize = _MAX_PATH;
	bool bFound = false;
	bool bInvalid = false;
	HKEY hKey;

	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Skype\\Phone"), 0, KEY_READ, & hKey) == ERROR_SUCCESS) {
		if((RegQueryValueEx(hKey, _T("SkypePath"), 0, & dwType, (LPBYTE) strSkypePath, & dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ)) {
			_finddata_t data;
			intptr_t lHndl = _findfirst(strSkypePath, & data);
			if(lHndl != -1) {
				bFound = true;
				_findclose(lHndl);
			} else {
				bInvalid = true;
			}
		}
	}

	RegCloseKey(hKey);

	*pVal = SysAllocString(CT2W(strSkypePath));
	if(bInvalid) {
		return AtlReportError(GetObjectCLSID(), L"The specified executable file was not found", GUID_NULL, E_FAIL);
	} else if (! bFound) {
		return AtlReportError(GetObjectCLSID(), L"Skype does not appear to be installed", GUID_NULL, E_FAIL);
	} else {
		return S_OK;
	}
}

STDMETHODIMP SkypeAPILib::Access::get_Protocol(long *pVal)
{
	try {
		*pVal = gSkypeQueue.SupportedProtocol();
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::put_Protocol(long lngVal)
{
	try {
		WCHAR strCmd[64];
		swprintf_s(strCmd, 64, L"PROTOCOL %d", lngVal);

		gSkypeQueue.SendCommand(strCmd);
		return S_OK;
	} catch(const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetChatList(IChatCollection **List)
{
	CComObject<ChatCollection> * ptrChats;

	CHECK_PROTOCOL(3)

	HRESULT hr = CComObject<ChatCollection>::CreateInstance(& ptrChats);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat list", GUID_NULL, hr);
	}

	try {
		WCHAR cmd[_MAX_LINE];
		wcscpy_s(cmd, _MAX_LINE, L"SEARCH CHATS");
		WCHAR * pStrChats = gSkypeQueue.ExecuteBlockingCommand(cmd, L"CHATS ");
		ptrChats->SetItemList(& pStrChats[6]);
		free(pStrChats);
		return ptrChats->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetChat(BSTR Name, IChat **Chat)
{
	CComObject<SkypeAPILib::Chat> * ptrChat;

	CHECK_PROTOCOL(3)

	HRESULT hr = CComObject<SkypeAPILib::Chat>::CreateInstance(& ptrChat);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create Chat object", GUID_NULL, E_FAIL);
	}

	try {
		ptrChat->SetName(Name);
		return ptrChat->QueryInterface(Chat);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetChatMessageList(IChatMessageCollection **List)
{
	CComObject<ChatMessageCollection> * ptrMessages;

	CHECK_PROTOCOL(3)

	HRESULT hr = CComObject<ChatMessageCollection>::CreateInstance(& ptrMessages);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat message list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrMessages = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH CHATMESSAGES", L"MESSAGES ");
		ptrMessages->SetItemList(& pStrMessages[13]);
		free(pStrMessages);
		return ptrMessages->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetMissedChatMessageList(IChatMessageCollection **List)
{
	CComObject<ChatMessageCollection> * ptrMessages;

	CHECK_PROTOCOL(3)

	HRESULT hr = CComObject<ChatMessageCollection>::CreateInstance(& ptrMessages);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat message list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrMessages = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH MISSEDCHATMESSAGES", L"MESSAGES ");
		ptrMessages->SetItemList(& pStrMessages[13]);
		free(pStrMessages);
		return ptrMessages->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetChatMessage(LONG ID, IChatMessage **Message)
{
	CComObject<ChatMessage> * ptrChatMessage;

	CHECK_PROTOCOL(3)

	HRESULT hr = CComObject<ChatMessage>::CreateInstance(& ptrChatMessage);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create Chat object", GUID_NULL, E_FAIL);
	}

	try {
		ptrChatMessage->SetID(ID);
		return ptrChatMessage->QueryInterface(Message);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::CloseSkype()
{
	gSkypeQueue.CloseSkype();
	return S_OK;
}

STDMETHODIMP SkypeAPILib::Access::MinimizeSkype()
{
	gSkypeQueue.MinimizeSkype();
	return S_OK;
}

STDMETHODIMP SkypeAPILib::Access::get_SkypeOutBalance(LONG *pVal)
{
	CHECK_PROTOCOL(3)

	try {
		WCHAR * pResult = gSkypeQueue.RetrieveProperty(L"PROFILE", L"", L"PSTN_BALANCE");
		*pVal = _wtol(pResult);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_SkypeOutCurrency(SkypeCurrencyType *pVal)
{
	CHECK_PROTOCOL(3)

	try {
		WCHAR * pResult = gSkypeQueue.RetrieveProperty(L"PROFILE", L"", L"PSTN_BALANCE_CURRENCY");
		*pVal = TextToSkypeCurrencyType(pResult);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_APIAttachmentStatus(/*[out, retval]*/SkypeAPIAttachmentStatus * APIStatus)
{
	*APIStatus = gSkypeQueue.GetAPIStatus();
	return S_OK;
}

STDMETHODIMP SkypeAPILib::Access::LaunchChat(/*[in]*/ SAFEARRAY ** UserHandles, /*[out, retval]*/ IChat ** Chat)
{
	CHECK_PROTOCOL(3)

	VARTYPE vt = VT_UNKNOWN;
	SafeArrayGetVartype(* UserHandles, & vt);
	UINT uiDim = SafeArrayGetDim(* UserHandles);
	if((uiDim != 1) || (vt != VT_BSTR)) {
		return AtlReportError(GetObjectCLSID(), L"Array of users must be single dimension array of strings", GUID_NULL, E_INVALIDARG);
	}

	wstring wstrCommand;
	// wstrCommand = L"OPEN CHAT ";
	wstrCommand = L"CHAT CREATE ";
	HRESULT hr = SafeArrayLock(* UserHandles);
	if(SUCCEEDED(hr)) {
		BSTR * pHandles = (BSTR *) (*UserHandles)->pvData;
		for(ULONG l = 0; l < (*UserHandles)->rgsabound[0].cElements; l++) {
			BSTR bstrHandle = pHandles[l];
			if(l > 0) {
				wstrCommand += L", ";
			}
			wstrCommand += bstrHandle;
		}
		SafeArrayUnlock(* UserHandles);
	}

	if(SUCCEEDED(hr)) {
		try {
			CComObject<SkypeAPILib::Chat> * ptrChat;
			WCHAR * wstrResult = gSkypeQueue.ExecuteBlockingCommand(wstrCommand.c_str(), L"CHAT");
			hr = CComObject<SkypeAPILib::Chat>::CreateInstance(& ptrChat);
			if(SUCCEEDED(hr)) {
				if(wcslen(wstrResult) < 10) {
					hr = AtlReportError(GetObjectCLSID(), L"Error parsing launch chat result", GUID_NULL, E_FAIL);
				} else {
					WCHAR * wstrEnd = wcschr(& wstrResult[5], L' ');
					if(wstrEnd == NULL) {
						hr = AtlReportError(GetObjectCLSID(), L"Error parsing launch chat result", GUID_NULL, E_FAIL);
					} else {
						*wstrEnd = 0;
						ptrChat->SetName(& wstrResult[5]);
						hr = ptrChat->QueryInterface(Chat);
					}
				}
			}

			free(wstrResult);
		} catch (const WCHAR * err) {
			return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
		}

		if(SUCCEEDED(hr)) {
			return S_OK;
		} else {
			return AtlReportError(GetObjectCLSID(), L"Unable to Start Chat", GUID_NULL, hr);
		}
	} else {
		return AtlReportError(GetObjectCLSID(), L"Unable to Start Chat", GUID_NULL, hr);
	}
}

STDMETHODIMP SkypeAPILib::Access::PlaceConferenceCall(/*[in]*/ SAFEARRAY ** UserHandles, /*[out, retval]*/ ICall ** Call)
{
	CHECK_PROTOCOL(3)

	VARTYPE vt = VT_UNKNOWN;
	SafeArrayGetVartype(* UserHandles, & vt);
	UINT uiDim = SafeArrayGetDim(* UserHandles);
	if((uiDim != 1) || (vt != VT_BSTR)) {
		return AtlReportError(GetObjectCLSID(), L"Array of users must be single dimension array of strings", GUID_NULL, E_INVALIDARG);
	}

	wstring wstrCommand;
	wstrCommand = L"CALL ";
	HRESULT hr = SafeArrayLock(* UserHandles);
	if(SUCCEEDED(hr)) {
		BSTR * pHandles = (BSTR *) (* UserHandles)->pvData;
		for(ULONG l = 0; l < (* UserHandles)->rgsabound[0].cElements; l++) {
			BSTR bstrHandle = pHandles[l];
			if(l > 0) {
				wstrCommand += L", ";
			}
			wstrCommand += bstrHandle;
		}
		SafeArrayUnlock(* UserHandles);
	}

	WCHAR * pResult;
	if(SUCCEEDED(hr)) {
		try {
			pResult = gSkypeQueue.ExecuteBlockingCommand(wstrCommand.c_str(), L"CALL", TRUE);
		} catch (const WCHAR * err) {
			return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
		}
		if(pResult == NULL) {
			return AtlReportError(GetObjectCLSID(), L"No response returned", GUID_NULL, E_FAIL);
		} else {
			long lCallID = 0;
			if(swscanf_s(pResult, L"CALL %d ", & lCallID) == 1) {
				if(lCallID > 0) {
					try {
						CComObject<SkypeAPILib::Call> * ptrCall;
						hr = CComObject<SkypeAPILib::Call>::CreateInstance(& ptrCall);
						if(SUCCEEDED(hr)) {
							ptrCall->SetCallID(lCallID);
							hr = ptrCall->QueryInterface(Call);
						}
					} catch(...) {
						return AtlReportError(GetObjectCLSID(), L"Unable to create call object", GUID_NULL, hr);
					}
				} else {
					return AtlReportError(GetObjectCLSID(), L"Error parsing call results", GUID_NULL, E_FAIL);
				}
			} else {
				return AtlReportError(GetObjectCLSID(), L"Error parsing call results", GUID_NULL, E_FAIL);
			}
				try {
					free(pResult);
				} catch (const WCHAR * err) {
					return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
				}
		}
	}

	if(SUCCEEDED(hr)) {
		return S_OK;
	} else {
		return AtlReportError(GetObjectCLSID(), L"Unable to Place Conference Call", GUID_NULL, hr);
	}
}

STDMETHODIMP SkypeAPILib::Access::OpenIMDialog(/*[in]*/ BSTR UserHandle, /*[in]*/ BSTR Message)
{
	try {
		wstring wstrCommand;
		wstrCommand = L"OPEN IM ";
		wstrCommand += UserHandle;
		wstrCommand += L" ";
		wstrCommand += Message;

		gSkypeQueue.SendCommand(wstrCommand.c_str());
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::FocusSkypeWindow()
{
	try {
		gSkypeQueue.SendCommand(L"FOCUS");
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::LaunchAddAFriend(/*[in]*/ BSTR UserHandle)
{
	try {
		wstring wstrCommand;
		wstrCommand = L"OPEN ADDAFRIEND ";
		wstrCommand += UserHandle;
		gSkypeQueue.SendCommand(wstrCommand.c_str());
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_Conversion(/*[out, retval]*/IConversion ** pVal)
{
	HRESULT hr;

	if(m_objConversion == NULL) {
		hr = CComObject<Conversion>::CreateInstance(& m_objConversion);
		if(FAILED(hr)) {
			return AtlReportError(GetObjectCLSID(), L"Unable to create conversion object", GUID_NULL, hr);
		}
		m_objConversion->AddRef();
	}

	hr = m_objConversion->QueryInterface(pVal);
	if(SUCCEEDED(hr)) {
		return S_OK;
	} else {
		return AtlReportError(GetObjectCLSID(), L"Unable to return conversion object", GUID_NULL, hr);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetActiveChatList(/*[out, retval]*/ IChatCollection ** List)
{
	CComObject<SkypeAPILib::ChatCollection> * ptrChats;

	CHECK_PROTOCOL(5)

	HRESULT hr = CComObject<SkypeAPILib::ChatCollection>::CreateInstance(& ptrChats);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrChats = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH ACTIVECHATS", L"CHATS ");
		ptrChats->SetItemList(& pStrChats[6]);
		free(pStrChats);
		return ptrChats->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetMissedChatList(/*[out, retval]*/ IChatCollection ** List)
{
	CComObject<SkypeAPILib::ChatCollection> * ptrChats;

	CHECK_PROTOCOL(5)

	HRESULT hr = CComObject<SkypeAPILib::ChatCollection>::CreateInstance(& ptrChats);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrChats = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH MISSEDCHATS", L"CHATS ");
		ptrChats->SetItemList(& pStrChats[6]);
		free(pStrChats);
		return ptrChats->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetRecentChatList(/*[out, retval]*/ IChatCollection ** List)
{
	CComObject<SkypeAPILib::ChatCollection> * ptrChats;

	CHECK_PROTOCOL(5)

	HRESULT hr = CComObject<SkypeAPILib::ChatCollection>::CreateInstance(& ptrChats);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrChats = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH RECENTCHATS", L"CHATS ");
		ptrChats->SetItemList(& pStrChats[6]);
		free(pStrChats);
		return ptrChats->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetBookmarkedChatList(/*[out, retval]*/ IChatCollection ** List)
{
	CComObject<SkypeAPILib::ChatCollection> * ptrChats;

	CHECK_PROTOCOL(5)

	HRESULT hr = CComObject<SkypeAPILib::ChatCollection>::CreateInstance(& ptrChats);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create chat list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrChats = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH BOOKMARKEDCHATS", L"CHATS ");
		ptrChats->SetItemList(& pStrChats[6]);
		free(pStrChats);
		return ptrChats->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetVoiceMailList(/*[out, retval]*/ IVoiceMailCollection ** List)
{
	CComObject<SkypeAPILib::VoiceMailCollection> * ptrVoiceMails;

	CHECK_PROTOCOL(5)

	HRESULT hr = CComObject<SkypeAPILib::VoiceMailCollection>::CreateInstance(& ptrVoiceMails);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create voice mail list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrVoiceMails = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH VOICEMAILS", L"VOICEMAILS ");
		ptrVoiceMails->SetItemList(& pStrVoiceMails[11]);
		free(pStrVoiceMails);
		return ptrVoiceMails->QueryInterface(List);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::SendVoiceMail(/*[in]*/ BSTR UserHandle, /*[out, retval]*/ IVoiceMail ** pVal)
{
	CComObject<SkypeAPILib::VoiceMail> * ptrCall;

	CHECK_PROTOCOL(5)

	HRESULT hr = CComObject<SkypeAPILib::VoiceMail>::CreateInstance(& ptrCall);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create call object", GUID_NULL, E_FAIL);
	}

	try {
		long lVoiceMailID = 0;
		wstring wstrCmd = L"VOICEMAIL ";
		wstrCmd += UserHandle;
		WCHAR * ptrResponse = gSkypeQueue.ExecuteBlockingCommand(wstrCmd.c_str(), L"VOICEMAIL ");
		bool bOk = (swscanf_s(ptrResponse, L"VOICEMAIL %d ", & lVoiceMailID) == 1);
		free(ptrResponse);
		if(! bOk) {
			return AtlReportError(GetObjectCLSID(), L"Unable to extract voicemail ID", GUID_NULL, E_FAIL);
		}

		ptrCall->SetID(lVoiceMailID);
		return ptrCall->QueryInterface(pVal);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::GetUsersWaitingForAuthorization(/*[out, retval]*/ IUserCollection ** pVal)
{
	CComObject<SkypeAPILib::UserCollection> * ptrUsers;

	CHECK_PROTOCOL(5)

	HRESULT hr = CComObject<SkypeAPILib::UserCollection>::CreateInstance(& ptrUsers);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create user list", GUID_NULL, hr);
	}

	try {
		WCHAR * pStrUsers = gSkypeQueue.ExecuteBlockingCommand(L"SEARCH USERSWAITINGMYAUTHORIZATION", L"USERS ");
		ptrUsers->SetItemList(& pStrUsers[6]);
		free(pStrUsers);
		return ptrUsers->QueryInterface(pVal);
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::ClearChatHistory()
{
	CHECK_PROTOCOL(5)

	try {
		gSkypeQueue.SendCommand(L"CLEAR CHATHISTORY");
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::ClearVoiceMailHistory()
{
	CHECK_PROTOCOL(5)

	try {
		gSkypeQueue.SendCommand(L"CLEAR VOICEMAILHISTORY");
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::ClearCallHistory(/*[in]*/ SkypeClearCallHistory CallType)
{
	CHECK_PROTOCOL(5)

	wstring wstrCmd = L"CLEAR CALLHISTORY ";
	switch(CallType) {
		case clrAllCalls:
			wstrCmd += L"ALL";
			break;
		case clrMissedCalls:
			wstrCmd += L"MISSED";
			break;
		case clrIncomingCalls:
			wstrCmd += L"INCOMING";
			break;
		case clrOutgoingCalls:
			wstrCmd += L"OUTGOING";
			break;
		default:
			return AtlReportError(GetObjectCLSID(), L"Invalid call type specified", GUID_NULL, E_FAIL);
	}

	try {
		gSkypeQueue.SendCommand(wstrCmd.c_str());
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_Ringer(/*[out, retval]*/ BSTR* pVal)
{
	CHECK_PROTOCOL(5)

	try {
		WCHAR * pResult = gSkypeQueue.ExecuteBlockingCommand(L"GET RINGER", L"RINGER ");
		*pVal = SysAllocString(& pResult[7]);
		free(pResult);
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::put_Ringer(/*[in]*/ BSTR Val)
{
	CHECK_PROTOCOL(5)

	try {
		wstring wstrCmd = L"SET RINGER ";
		wstrCmd += Val;
		gSkypeQueue.SendCommand(wstrCmd.c_str());
		return S_OK;
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
}

STDMETHODIMP SkypeAPILib::Access::ConnectAndWait(/*[in]*/ LONG TimeoutInSeconds)
{
	gSkypeQueue.Initialize();
	// Wait for either accept, refused or not available
	DWORD dwStart = GetTickCount();
	for(;;) {
		SkypeAPIAttachmentStatus status = gSkypeQueue.GetAPIStatus();
		switch(status) {
			case apiAttachSuccess:
				return S_OK;
			case apiAttachRefused:
				return AtlReportError(GetObjectCLSID(), L"Access to the application was refused", GUID_NULL, E_ACCESSDENIED);
			case apiAttachNotAvailable:
				return AtlReportError(GetObjectCLSID(), L"Application access to Skype unavailable", GUID_NULL, E_ACCESSDENIED);
		}
		if(TimeoutInSeconds > 0) {
			DWORD dwDiff = (GetTickCount() - dwStart) / 1000;
			if(dwDiff >= (DWORD) TimeoutInSeconds) {
				return AtlReportError(GetObjectCLSID(), L"Timeout waiting for Skype to Respond", GUID_NULL, E_FAIL);
			}
		}
		Sleep(500);
	};
}

STDMETHODIMP SkypeAPILib::Access::OpenFileTransferDialog(/*[in]*/ SAFEARRAY ** UserHandles, /*[in]*/ BSTR Folder)
{
	VARTYPE vt = VT_UNKNOWN;
	SafeArrayGetVartype(* UserHandles, & vt);
	UINT uiDim = SafeArrayGetDim(* UserHandles);
	if((uiDim != 1) || (vt != VT_BSTR)) {
		return AtlReportError(GetObjectCLSID(), L"Array of users must be single dimension array of strings", GUID_NULL, E_INVALIDARG);
	}

	wstring wstrCommand;
	wstrCommand = L"OPEN FILETRANSFER ";
	HRESULT hr = SafeArrayLock(* UserHandles);
	if(SUCCEEDED(hr)) {
		BSTR * pHandles = (BSTR *) (* UserHandles)->pvData;
		for(ULONG l = 0; l < (* UserHandles)->rgsabound[0].cElements; l++) {
			BSTR bstrHandle = pHandles[l];
			if(l > 0) {
				wstrCommand += L", ";
			}
			wstrCommand += bstrHandle;
		}
		SafeArrayUnlock(* UserHandles);
	}

	if(SUCCEEDED(hr)) {

		if(Folder != NULL) {
			if(wcslen(Folder) > 0) {
				_wfinddata_t data;
				intptr_t h = _wfindfirst(Folder, & data);
				if(h == -1) {
					return AtlReportError(GetObjectCLSID(), L"The directory specified is invalid", GUID_NULL, hr);
				}
				_findclose(h);

				wstrCommand += L" IN ";
				wstrCommand += Folder;
			}
		}
		gSkypeQueue.SendCommand(wstrCommand.c_str());
		return S_OK;
	} else {
		return AtlReportError(GetObjectCLSID(), L"Unable to open file transfer dialog", GUID_NULL, hr);
	}
}

STDMETHODIMP SkypeAPILib::Access::SendBlockingCommand(BSTR Command, BSTR * pVal)
{
	CHECK_PROTOCOL(4)

	try {
		LPWSTR wstrResponse = gSkypeQueue.ExecuteBlockingCommand(Command, L"");
		*pVal = SysAllocString(wstrResponse);
		free(wstrResponse);

		if(_wcsnicmp(*pVal, L"ERROR ", 6) == 0) {
			return InError(*pVal, GUID_NULL, E_FAIL);
		}
	} catch (const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}
	return S_OK;
}

STDMETHODIMP SkypeAPILib::Access::get_CommandTimeout(/*[out, retval]*/ LONG *pVal)
{
	*pVal = gSkypeQueue.GetTimeout();
	return S_OK;
}

STDMETHODIMP SkypeAPILib::Access::put_CommandTimeout(/*[in]*/ LONG Val)
{
	if(Val <= 0) {
		return AtlReportError(GetObjectCLSID(), L"Timeout must be greater than 0", GUID_NULL, E_INVALIDARG);
	}
	gSkypeQueue.SetTimeout(Val);
	return S_OK;
}

void SkypeAPILib::Access::ProcessCommand(LPCWSTR Command)
{
	m_wndEvent.PostMessage(WM_FIRE_COMMAND, 0, (LPARAM) _wcsdup(Command));
}

void SkypeAPILib::Access::ProcessResponse(LPCWSTR Response, BOOL ProcessCallbacks)
{

#ifdef _DEBUG
	_TCHAR str[_MAX_LINE];
	_stprintf_s(str, _MAX_LINE, _T("<< %s\n"), CW2CT(Response));
	WriteLog(str);
	ATLTRACE("<< %s\n", CW2CT(Response));
#endif

	m_wndEvent.PostMessage(WM_FIRE_RESULT, 0, (LPARAM) _wcsdup(Response));

	if(! ProcessCallbacks) {
		return;
	}

	WCHAR * ptrOnlineStatus = NULL;
	WCHAR * ptrOnlineStatusInd = wcsstr((LPWSTR)Response, L" ONLINESTATUS ");
	if(ptrOnlineStatusInd != NULL) {
		ptrOnlineStatus = & ptrOnlineStatusInd[14];
	}

	WCHAR * ptrBuffer1 = new WCHAR[wcslen(Response)];
	WCHAR * ptrBuffer2 = new WCHAR[wcslen(Response)];

	if(_wcsnicmp(Response, L"CALL ", 5) == 0) {

		long lCallID = 0;
		if(swscanf_s(Response, L"CALL %d STATUS", & lCallID) == 1) {

			if(lCallID > 0) {

				WCHAR * ptrStatus = NULL;
				WCHAR * ptrStatusInd = wcsstr((LPWSTR)Response, L" STATUS ");
				if(ptrStatusInd != NULL) {
					ptrStatus = & ptrStatusInd[8];
				}

				WCHAR * ptrDTMF = NULL;
				WCHAR * ptrDTMFInd = wcsstr((LPWSTR)Response, L" DTMF ");
				if(ptrDTMFInd != NULL) {
					ptrDTMF = & ptrDTMFInd[6];
				}

				if((ptrStatusInd != NULL) && (ptrStatus != NULL)) {
					SkypeCallProgress progress = TextToSkypeCallProgress(ptrStatus);
					m_wndEvent.PostMessage(WM_FIRE_CALLSTATUSCHANGED, progress, lCallID);
				} else if((ptrDTMFInd != NULL) && (ptrDTMF != NULL)) {
					m_wndEvent.PostMessage(WM_FIRE_INCOMINGDTMF, ((LPARAM) _wcsdup(ptrDTMF)), lCallID);
				}
			}
		}
	} else if((_wcsnicmp(Response, L"USER", 4) == 0) && (ptrOnlineStatusInd != NULL) && (ptrOnlineStatus != NULL)) {
		if(swscanf_s(Response, L"USER %s ONLINESTATUS", ptrBuffer1, wcslen(Response)) == 1) {
			if(wcslen(ptrBuffer1) > 0) {
				SkypeOnlineStatus status = TextToSkypeOnlineStatus(ptrOnlineStatus);
				m_wndEvent.PostMessage(WM_FIRE_ONLINESTATUSCHANGED, status,
					(LPARAM) _wcsdup(ptrBuffer1));
			}
		}
	} else if(_wcsnicmp(Response, L"CONTACTS FOCUSED ", 17) == 0) {
		wstring wstrUser = & Response[17];
		if(wstrUser.length() > 0) {
			m_wndEvent.PostMessage(WM_FIRE_CONTACT_FOCUSED, (WPARAM) _wcsdup(wstrUser.c_str()), 0);
		}
	} else if(_wcsnicmp(Response, L"CALLHISTORYCHANGED ", 19) == 0) {
		m_wndEvent.PostMessage(WM_FIRE_CALLHISTORYCHANGED);
	} else if(_wcsnicmp(Response, L"IMHISTORYCHANGED ", 17) == 0) {
		m_wndEvent.PostMessage(WM_FIRE_IMHISTORYCHANGED);
	} else if(_wcsnicmp(Response, L"USERSTATUS ", 11) == 0) {
		m_wndEvent.PostMessage(WM_FIRE_USERSTATUSCHANGED, TextToSkypeOnlineStatus(& Response[11]));
	} else if(_wcsnicmp(Response, L"CONNSTATUS ", 11) == 0) {
		SkypeConnectionStatus status = TextToSkypeConnectionStatus(& Response[11]);
		if(status != conOnline) {
			gSkypeQueue.DeleteAllBinaryTransfers();
		}
		m_wndEvent.PostMessage(WM_FIRE_CONNECTIONSTATUSCHANGED, status);
	} else if(_wcsnicmp(Response, L"MUTE ", 5) == 0) {
		m_wndEvent.PostMessage(WM_FIRE_MUTECHANGED, _wcsicmp(& Response[5], L"ON") == 0);
	} else if((_wcsnicmp(Response, L"MESSAGE", 7) == 0) && (wcsstr(Response, L"STATUS RECEIVED") != NULL)) {
		long lMessageID = 0;
		if(swscanf_s(Response, L"MESSAGE %d ", & lMessageID) == 1) {
			m_wndEvent.PostMessage(WM_FIRE_MESSAGERECEIVED, 0, lMessageID);
		}
	} else if((_wcsnicmp(Response, L"MESSAGE", 7) == 0) && (wcsstr(Response, L"STATUS SENT") != NULL)) {
		long lMessageID = 0;
		if(swscanf_s(Response, L"MESSAGE %d ", & lMessageID) == 1) {
			m_wndEvent.PostMessage(WM_FIRE_MESSAGESENT, 0, lMessageID);
		}
	} else if((_wcsnicmp(Response, L"CHATMESSAGE", 11) == 0) && (wcsstr(Response, L"STATUS RECEIVED") != NULL)) {
		long lMessageID = 0;
		if(swscanf_s(Response, L"CHATMESSAGE %d ", & lMessageID) == 1) {
			m_wndEvent.PostMessage(WM_FIRE_CHATMESSAGERECEIVED, 0, lMessageID);
		}
	} else if((_wcsnicmp(Response, L"CHATMESSAGE", 11) == 0) && (wcsstr(Response, L"STATUS SENT") != NULL)) {
		long lMessageID = 0;
		if(swscanf_s(Response, L"CHATMESSAGE %d ", & lMessageID) == 1) {
			m_wndEvent.PostMessage(WM_FIRE_CHATMESSAGESENT, 0, lMessageID);
		}
	} else if(swscanf_s(Response, L"APPLICATION %s %s", ptrBuffer1, wcslen(Response), ptrBuffer2, wcslen(Response)) == 2) {
		if((wcslen(ptrBuffer1) > 0) && (wcslen(ptrBuffer2) > 0)){
			WCHAR * ptrData = wcsstr((LPWSTR)Response, ptrBuffer2) + wcslen(ptrBuffer2);
			if(*ptrData == L' ') {
				ptrData++;
			}

			if(_wcsnicmp(ptrBuffer2, L"CONNECTING", 10) == 0) {
				WCHAR *next_token = NULL;
				WCHAR * ptrToken = wcstok_s(ptrData, L" ", &next_token);
				while(ptrToken != NULL) {
					m_wndEvent.PostMessage(WM_FIRE_APP_CONNECTING,
						(WPARAM) _wcsdup(ptrBuffer1), (LPARAM) _wcsdup(ptrToken));
					ptrToken = wcstok_s(NULL, L" ", &next_token);
				}
			} else if(_wcsnicmp(ptrBuffer2, L"DATAGRAM", 8) == 0) {
				wstring strInfo;
				WCHAR * ptrSpace = wcschr(ptrData, L' ');
				if(ptrSpace != NULL) {
					*ptrSpace = 0;
					if(wcsstr(ptrData, L":") != NULL) {
						strInfo = ptrBuffer1;
						strInfo += L"\t";
						strInfo += ptrData;

						m_wndEvent.PostMessage(WM_FIRE_APP_DATAGRAM_RECEIVED,
							(WPARAM) _wcsdup(strInfo.c_str()),
							(LPARAM) _wcsdup(ptrSpace + 1));
					}
				}
			} else if(_wcsnicmp(ptrBuffer2, L"STREAMS", 7) == 0) {
				StreamList strStreams = gSkypeQueue.GetStreamList();
				StreamList strNewStreams;

				// Build new list
				WCHAR *next_token = NULL;
				WCHAR * ptrToken = wcstok_s(ptrData, L" ", &next_token);
				while(ptrToken != NULL) {
					strNewStreams.push_back(ptrToken);
					ptrToken = wcstok_s(NULL, L" ", &next_token);
				}

				gSkypeQueue.SetStreamList(strNewStreams);

				// Look for newly opened streams
				for(StreamList::iterator it = strNewStreams.begin(); it != strNewStreams.end(); it++) {
					bool bIsNew = true;
					for(StreamList::iterator it2 = strStreams.begin(); it2 != strStreams.end(); it2++) {
						wstring str = it->c_str();
						str += L", ";
						str += it2->c_str();
						// ::MessageBox(NULL, CW2CT(str.c_str()), "Checking for New Stream", MB_OK);
						if(_wcsicmp(it->c_str(), it2->c_str()) == 0) {
							bIsNew = false;
							break;
						}
					}

					// Send out notifications for new strings
					if(bIsNew) {
						// ::MessageBox(NULL, CW2CT(it->c_str()), "Adding New Stream", MB_OK);
						m_wndEvent.PostMessage(WM_FIRE_APP_STREAM_OPENED,
							(WPARAM) _wcsdup(ptrBuffer1), (LPARAM) _wcsdup(it->c_str()));
					}
				}

				// Look for newly closed streams
				for(StreamList::iterator it2 = strStreams.begin(); it2 != strStreams.end(); it2++) {
					bool bIsClosed = true;
					for(StreamList::iterator it = strNewStreams.begin(); it != strNewStreams.end(); it++) {
						wstring str = it->c_str();
						str += L", ";
						str += it2->c_str();
						if(_wcsicmp(it->c_str(), it2->c_str()) == 0) {
							bIsClosed = false;
							break;
						}
					}

					// Send out notifications
					if(bIsClosed) {
						m_wndEvent.PostMessage(WM_FIRE_APP_STREAM_CLOSED,
							(WPARAM) _wcsdup(ptrBuffer1), (LPARAM) _wcsdup(it2->c_str()));
						gSkypeQueue.DeleteStreamBinaryTransfers(it2->c_str());
					}
				}
			} else if (_wcsnicmp(ptrBuffer2, L"RECEIVED", 8) == 0) {
				WCHAR *next_token = NULL;
				WCHAR * ptrToken = wcstok_s(ptrData, L" ", &next_token);
				while(ptrToken != NULL) {
					WCHAR * ptrToken2 = wcschr(ptrToken, L'=');
					if(ptrToken2 != NULL) {
						WCHAR chHold = *ptrToken2;
						*ptrToken2 = 0;
						wstring wstrCmd = L"ALTER APPLICATION ";
						wstrCmd += ptrBuffer1;
						wstrCmd += L" READ ";
						wstrCmd += ptrToken;
						gSkypeQueue.SendCommand(wstrCmd.c_str());
						*ptrToken2 = chHold;
					}
					ptrToken = wcstok_s(NULL, L" ", &next_token);
				}
			}
		}
	} else if(swscanf_s(Response, L"ALTER APPLICATION %s READ %s", ptrBuffer1, wcslen(Response), ptrBuffer2, wcslen(Response)) == 2) {
		if((wcslen(ptrBuffer1) > 0) && (wcslen(ptrBuffer2) > 0)) {
			WCHAR * pstrData = wcsstr((LPWSTR)Response, ptrBuffer2);
			if(pstrData != NULL) {
				pstrData += (wcslen(ptrBuffer2) + 1);
				if(*pstrData != 0) {
					wstring strInfo;
					strInfo = ptrBuffer1;
					strInfo += L"\t";
					strInfo += ptrBuffer2;

					// Figure out if we have a binary transfer or not
					if(_wcsnicmp(pstrData, L"#XFERSTREAM# ", 12) == 0) {
						wstring wstrCmd;
						wstring wstrTransferID;
						wstring wstrMD5;
						wstring wstrCopy = pstrData;
						long lSize;
						SAFEARRAY * psa;
						BinaryTransferPTR ptrTransfer;

						int iCtr = 0;
						bool bKeepGoing = true;
						bool bStart = false;
						bool bData = false;
						bool bEnd = false;

						pstrData += 12;
						WCHAR *next_token = NULL;
						WCHAR * ptrItem = wcstok_s(pstrData, L" ", &next_token);
						while (bKeepGoing && (ptrItem != NULL)) {
							switch(iCtr) {
								case 0:
									wstrTransferID = ptrItem;
									break;
								case 1:
									wstrCmd = ptrItem;
									if(_wcsicmp(wstrCmd.c_str(), L"START") == 0) {
										bStart = true;
									} else if (_wcsicmp(wstrCmd.c_str(), L"DATA") == 0) {
										bData = true;
									} else if (_wcsicmp(wstrCmd.c_str(), L"END") == 0) {
										bEnd = true;
									} else {
										wstrCmd = L"Unexpected command: " + wstrCmd;
										m_wndEvent.PostMessage(WM_FIRE_BINARY_TRANSFER_ERROR,
											(WPARAM) _wcsdup(wstrTransferID.c_str()),
											(LPARAM) _wcsdup(wstrCmd.c_str()));
										return;
									}

									if(! bStart) {
										ptrTransfer = gSkypeQueue.GetBinaryTransfer(wstrTransferID.c_str());
										if(ptrTransfer == NULL) {
											wstrCmd = L"Unexpected transfer item: " + wstrCmd;
											m_wndEvent.PostMessage(WM_FIRE_BINARY_TRANSFER_ERROR,
												(WPARAM) _wcsdup(L""),
												(LPARAM) _wcsdup(wstrCmd.c_str()));
											return;
										}
									}

									if(bEnd) {
										if(! ptrTransfer->MD5Match()) {
											m_wndEvent.PostMessage(WM_FIRE_BINARY_TRANSFER_ERROR,
												(WPARAM) _wcsdup(wstrTransferID.c_str()),
												((LPARAM) _wcsdup(L"MD5 checksum does not match")));
										} else {
											psa = SafeArrayCreateVector(VT_UI1, 0,
												ptrTransfer->Length());
											SafeArrayLock(psa);
											memcpy(psa->pvData, ptrTransfer->Buffer(),
												ptrTransfer->Length());
											SafeArrayUnlock(psa);
											m_wndEvent.PostMessage(WM_FIRE_BINARY_TRANSFER_END,
												(WPARAM) _wcsdup(wstrTransferID.c_str()), (LPARAM) psa);
										}
										gSkypeQueue.EndBinaryTransfer(ptrTransfer->ID(), false);
										return;
									}

									break;
								case 2:
									if(bStart) {
										wstrMD5 = ptrItem;
									} else if (bData) {
										// Anything after the command is data
										size_t idx = wstrCopy.find(L" DATA ");
										// Swap the bytes back
										WCHAR * ptrHold = new WCHAR[wstrCopy.length() + 1];
										wcscpy_s(ptrHold, wstrCopy.length() + 1, & ((wstrCopy.c_str())[idx + 6]));
										for(ULONG i = 0; i < wcslen(ptrHold); i++) {
											ptrHold[i] = WordSwap(ptrHold[i]);
										}

										char * ptrHold2 = (char *) ptrHold;
										BinaryTransferStatus * ptrStatus = gSkypeQueue.AppendBinaryTransfer(wstrTransferID.c_str(),
											(BYTE *) ptrHold2, (ULONG) strlen(ptrHold2));
										delete ptrHold;
										m_wndEvent.PostMessage(WM_FIRE_BINARY_TRANSFER_DATA,
											(WPARAM) _wcsdup(wstrTransferID.c_str()),
											(LPARAM) ptrStatus);
										return;
									}
									break;
								case 3:
									if(bStart) {
										lSize = _wtol(ptrItem);
										try {
											gSkypeQueue.StartBinaryTransfer(wstrTransferID.c_str(),
												ptrBuffer1, CW2A(wstrMD5.c_str()), lSize);
											m_wndEvent.PostMessage(WM_FIRE_BINARY_TRANSFER_START,
												(WPARAM) _wcsdup(wstrTransferID.c_str()),
												(LPARAM) lSize);
										} catch(const WCHAR * err) {
											m_wndEvent.PostMessage(WM_FIRE_BINARY_TRANSFER_ERROR,
												(WPARAM) _wcsdup(wstrTransferID.c_str()),
												((LPARAM) _wcsdup(err)));
										}
									}
							}
							iCtr++;
							ptrItem = wcstok_s(NULL, L" ", &next_token);
						}
					} else {
						m_wndEvent.PostMessage(WM_FIRE_APP_DATA_RECEIVED,
							(WPARAM) _wcsdup(strInfo.c_str()), (LPARAM) _wcsdup(pstrData));
					}
				}
			}
		}
	} else if(_wcsnicmp(Response, L"ERROR", 5) == 0)  {
		try {
			long lErrorID = 0;
			if(swscanf_s(Response, L"ERROR %d", & lErrorID) == 1) {
				WCHAR * pStrDesc = wcsstr((LPWSTR)Response, L" ");
				pStrDesc = wcsstr(& pStrDesc[1], L" ");
				m_wndEvent.PostMessage(WM_FIRE_ERROR, lErrorID, ((LPARAM) _wcsdup(pStrDesc)));
			}
		} catch(...) {
		}
	}

	delete [] ptrBuffer1;
	delete [] ptrBuffer2;
}

void SkypeAPILib::Access::ProcessAPIStatusChange(SkypeAPIAttachmentStatus Status)
{
	m_wndEvent.PostMessage(WM_FIRE_APISTATUSCHANGED, Status);
}

HRESULT SkypeAPILib::Access::InError(LPCOLESTR lpszDesc, const IID &iid,  HRESULT hres)
{
	return CComCoClass<Access>::Error(lpszDesc, iid, hres);
}

HRESULT SkypeAPILib::Access::InError(LPCTSTR lpszDesc, const IID &iid,  HRESULT hres)
{
	return CComCoClass<Access>::Error(lpszDesc, iid, hres);
}

HRESULT SkypeAPILib::Access::OpenApplication(BSTR ApplicationName, IApp2App ** App)
{
	CComObject<App2App> * ptrApp;

	HRESULT hr = CComObject<App2App>::CreateInstance(& ptrApp);
	if(FAILED(hr)) {
		return AtlReportError(GetObjectCLSID(), L"Unable to create app2app object", GUID_NULL, E_FAIL);
	}

	try {
		ptrApp->SetAppName(ApplicationName);
	} catch(const WCHAR * err) {
		return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
	}

	try {
		// If we get an error when trying to get "CONNECTABLE", then
		// the application needs to get created
		CComPtr<IUserCollection> ptrUsers;
		hr = ptrApp->get_ConnectableUsers(& ptrUsers);
	} catch(...) {
		hr = E_FAIL;
	}

	if(FAILED(hr)) {

		try {
			ptrApp->CreateApplication();
		} catch(const WCHAR * err) {
			return AtlReportError(GetObjectCLSID(), err, GUID_NULL, E_FAIL);
		}
	}

	return ptrApp->QueryInterface(App);
}

STDMETHODIMP SkypeAPILib::Access::get_Profile(/*[out, retval]*/IProfile ** pVal)
{
	HRESULT hr;

	if(m_objProfile == NULL) {
		hr = CComObject<Profile>::CreateInstance(& m_objProfile);
		if(FAILED(hr)) {
			return AtlReportError(GetObjectCLSID(), L"Unable to create profile object", GUID_NULL, hr);
		}
		m_objProfile->AddRef();
	}

	hr = m_objProfile->QueryInterface(pVal);
	if(SUCCEEDED(hr)) {
		return S_OK;
	} else {
		return AtlReportError(GetObjectCLSID(), L"Unable to return profile object", GUID_NULL, hr);
	}
}

STDMETHODIMP SkypeAPILib::Access::get_UI(/*[out, retval]*/IUI ** pVal)
{
	HRESULT hr;

	if(m_objUI == NULL) {
		hr = CComObject<UI>::CreateInstance(& m_objUI);
		if(FAILED(hr)) {
			return AtlReportError(GetObjectCLSID(), L"Unable to create UI object", GUID_NULL, hr);
		}
		m_objUI->AddRef();
	}

	hr = m_objUI->QueryInterface(pVal);
	if(SUCCEEDED(hr)) {
		return S_OK;
	} else {
		return AtlReportError(GetObjectCLSID(), L"Unable to return UI object", GUID_NULL, hr);
	}
}


text:
<!doctype html>

		<meta charset="utf-8">

		<title>Learning HTML (level 2) - Andrew Betts</title>

		<meta name="description" content="A workshop on HTML for journalists">
		<meta name="author" content="Andrew Betts">
		<meta name="apple-mobile-web-app-capable" content="yes" />
		<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

		<link rel="stylesheet" href="css/reveal.min.css">
		<link rel="stylesheet" href="css/theme/ftlabs.css" id="theme">
		<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/3.2.1/css/font-awesome.min.css">

		<link rel="stylesheet" href="lib/css/zenburn.css">

Learning HTML

Level 2 (intermediate)
Andrew Betts, FT Labs

						@triblondon,
						@FTLabs

You can build a gallery

Recap of level 1

HTML is a set of standard tags that you can use to create elements following a set of rules inherited from a generic language structure called XML. It's like a vocabulary to XML's grammar.

Elements are semantic, they convey meaning without visual style

You can nest elements inside of one another, but it's important that they are closed in the right order so that they are well formed

Some tags need to be opened and closed, others are 'self-closing'

Attributes can be used to add further information to elements which is not displayed

QUIZ!

Open the web browser on your phone or computer and go to:

<big>kahoot.it</big>

Separating content and style

Content	Style

HTML	CSS

What you're saying	What content should look like

Meaning, not appearance	Appearance, not meaning

CSS

Cascading Style Sheets

"Headings bold and in caps"

.headings {
  text-transform: uppercase;
  font-weight: bold;
}

CSS has rule sets comprising

Class (.headings, remember the dot!)

Properties (text-transform, font-weight)

Values (uppercase, bold)

Classes

Group together things that have something in common.  Define in HTML, reference in CSS

.first
.business
.economy

Example: Article subheadings

Add a class

The birthday party

Link some style to that class

HTML:

The birthday party

CSS:

.article-subhead {
  font-weight: bold;
  font-size: 15px;
}

Headings with the class article-subhead are now size 15 bold.

Exercise!

http://jsbin.com/nozodego/17/edit

Give the push button a big, bold font

Add a class attribute to one of the buttons. You can make up the class name.

Add a CSS rule set that targets the class, with the properties font-size and font-weight.

A rule set in CSS looks like .classname { property: value; }

A class in HTML looks like <... class='classname'>

Adding behaviour

Content	Style	Behaviour

HTML	CSS	JavaScript

What you're saying	What content should look like	How content should react to interaction

Example: sharing an article

							Content

(HTML)

							URL to be shared
Which services to offer

							Style

(CSS)

							Logos of all the services
Spacing and margins
Design and positioning of the tooltip

							Behaviour

(JavaScript)

							Tooltip on click
Make services load in small pop-up windows

You write the HTML

We write the CSS and JavaScript

Loading CSS and JavaScript

CSS:

<link rel='stylesheet' href='http://...'>

JavaScript:

<script src='http://...'></script>

Where do they go?

<html>
  <head>
    <link rel='stylesheet' href='my-stylesheet.css'>
  </head>
  <body>
    <p>Hello!</p>
    <script src='my-javascript.js'></script>
  </body>
</html>

Where do they go?

CSS goes at the top of the document, before the content.  Otherwise, you can get a Flash of Unstyled Content (FOUC):

Where do they go?

JavaScript goes at the bottom of the document, after the content.  It's not needed urgently and shouldn't slow down page loading.

Get CSS and JavaScript from Origami

Pre-formed <script> and <link> tags are available from the Origami registry:

registry.origami.ft.com

Exercise!

Use your existing JSBin page from the previous exercise

Change your button to be proper FT style!

From the Origami Registry, find the o-ft-buttons component.

Replace your <style>...</style> section with the <link...> tag from the quick start section in the registry (registry.origami.ft.com).

Use the demo in the registry to find the right class to apply to your button

Let's build a gallery!

1. Start with a blank page

http://jsbin.com/kalavije/5/edit

2. Go to the registry and find the gallery component

http://registry.origami.ft.com

3. Find the HTML

Expand the 'Declarative' demo's source code

4. Create the gallery container

I've put this bit in for you already

In HTML, a <div> is an element with no special meaning, which we can use for our own reasons.

The o-gallery and o-gallery--slideshow classes allows us to apply gallery styling to the element

Remember the closing </div> tag (every opening tag must be closed!)

The rest of the attributes in the registry demo aren't necessary to get it working today.

5. Give your gallery a title

This goes inside your gallery container.

TITLE OF YOUR GALLERY

6. Make a list for your images

Images are a sequence of items, so a list is appropriate.  They are in a sequence, so we should use an ordered list.

7. Put some images in your gallery

CAPTION

Find some images, eg on this article.  Right click on the image and 'Copy Image URL', then use it in your gallery.

Repeat this code for each of the images in your gallery

8. Add Origami Styles (CSS)

Find the quick start code on the o-gallery page in the Origami registry.  Copy the <link> tag into the right place in your code.

<link rel="stylesheet" href="http://build.origami.ft.com/bundles/css?modules=o-gallery@^1.4.1" />

Now your gallery has the right fonts, margins, and colours.  This is what the gallery will look like to Google and anyone who is using an out of date browser.

9. Add Origami behaviours (JS)

Find the quick start code on the o-gallery page in the Origami registry.  Copy the <script> tag into the right place in your code.

<script src="//build.origami.ft.com/bundles/js?modules=o-gallery@^1.4.1"></script>

Gallery still isn't quite activated though...

10. Tell the gallery to start up

Change the JavaScript URL to export a bundle variable, and add the initialisation call:

<script src="//build.origami.ft.com/bundles/js?modules=o-gallery@^1.4.1&export=origami"></script>

Congratulations, you made a gallery

Recap

HTML doesn't give us any visual style or clever whizzy behaviours.  For that we need CSS and JavaScript.

CSS works by linking style rules with HTML elements that are labelled with classes.

Separating CSS and JavaScript away from HTML means you can focus on content and leave other people to worry about style and behaviours.

The Origami registry is the place to go to see what clever components we have available to make your HTML work harder.

Thanks for listening!

Contact me:

Email: andrew@labs.ft.com

Twitter: @triblondon, @ftlabs

redpajama_set_name: RedPajamaGithub


text:
//
// Copyright 2021 The Matrix.org Foundation C.I.C
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#import <MatrixSDK/MatrixSDK.h>

@class MXRoomSync;
@class MXInvitedRoomSync;

NS_ASSUME_NONNULL_BEGIN

/**
 `MXRoomsSyncResponse` represents the rooms list in server sync response.
 */
@interface MXRoomsSyncResponse : MXJSONModel

/**
 Joined rooms: keys are rooms ids.
 */
@property (nonatomic, nullable) NSDictionary<NSString*, MXRoomSync*> *join;

/**
 Invitations. The rooms that the user has been invited to: keys are rooms ids.
 */
@property (nonatomic, nullable) NSDictionary<NSString*, MXInvitedRoomSync*> *invite;

/**
 Left rooms. The rooms that the user has left or been banned from: keys are rooms ids.
 */
@property (nonatomic, nullable) NSDictionary<NSString*, MXRoomSync*> *leave;

@end

NS_ASSUME_NONNULL_END


text:
'use strict';
define(['app', '../partners-and-initiatives.html.js'], function(app) {

})


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Trans. Br. mycol. Soc. 47(1): 123 (1964)

#### Original name
Aspergillus flaschentraegeri Stolk, 1964

### Remarks
null


text:
package com.sun.xfilechooser;

import java.io.File;
import com.sun.xfile.*;
import java.io.IOException;

/**
 *  The BeanXFile class is the interface that makes an XFile object
 *  look like a File object.  This class is needed to support the
 *  UI of the JFileChooser which accesses file objects.
 *  Thus all the methods would call the corresponding XFile methods.
 *
 *  @see #XFile
 */
public class BeanXFile extends File {

    private XFile beanXF;

    /*
     * BeanXFile constructors which mirror the File I/O constructors.
     */
    public BeanXFile(String path) {
    super(path);
    beanXF = new XFile(path);
    }

    public BeanXFile(File dir, String name) {
    super(dir, name);

    XFile parentXF = new XFile(dir.getAbsolutePath());
    beanXF = new XFile(parentXF, name);
    }

    /*
     * XFile Methods that can be accessed.
     */
    @Override
    public String getPath() {
    String path = beanXF.getPath();

    // For nfs URLs, if the url is nfs://<server_name>, path is ""
    if (path.equals(""))
        path = beanXF.getAbsolutePath();

    return path;
    }

    @Override
    public String getAbsolutePath() {
    return beanXF.getAbsolutePath();
    }

    @Override
    public String getCanonicalPath() {
    try {
        String path = beanXF.getCanonicalPath();
        return path;
    } catch (IOException e) {
        String path = beanXF.getAbsolutePath();
        return path;
    }

    }

    @Override
    public String getName() {
    String fname = beanXF.getName();
    if (fname == null)
        return(beanXF.getAbsolutePath());
    else
        return(fname);
    }

    @Override
    public boolean renameTo(File dest) {
    XFile tmpFile = new XFile(dest.getAbsolutePath());
    return (beanXF.renameTo(tmpFile));
    }

    @Override
    public String getParent() {
    return beanXF.getParent();
    }

    @Override
    public boolean exists() {
    return beanXF.exists();
    }

    @Override
    public boolean canWrite(){
    return beanXF.canWrite();
    }

    @Override
    public boolean canRead() {
    return beanXF.canRead();
    }

    @Override
    public boolean isFile() {
    return beanXF.isFile();
    }

    @Override
    public boolean isDirectory() {
    return beanXF.isDirectory();
    }

    @Override
    public boolean isAbsolute() {
       // For nfs urls: isAbsolute is always true
       return beanXF.isAbsolute();
    }

    @Override
    public boolean equals(Object obj) {
    /*
     * Need to pass the XFile object to *.equals because
     * it checks for instance of XFile
     */
    XFile xf = new XFile(((File)obj).getAbsolutePath());
    return beanXF.equals(xf);
    }

    @Override
    public long lastModified() {
    return beanXF.lastModified();
    }

    @Override
    public long length() {
    return beanXF.length();
    }

    @Override
    public boolean mkdir() {
    return beanXF.mkdir();
    }

    @Override
    public boolean mkdirs() {
    return beanXF.mkdirs();
    }

    @Override
    public String[] list() {
    return beanXF.list();
    }

    @Override
    public String toString() {
    return beanXF.toString();
    }

    @Override
    public boolean delete() {
    return beanXF.delete();
    }

}


text:
<!DOCTYPE html>

    <title>TypeScript</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="style.css" />

TypeScript GPS


text:
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.facebook.presto.ml;

import com.facebook.presto.metadata.FunctionFactory;
import com.facebook.presto.ml.type.ClassifierParametricType;
import com.facebook.presto.spi.Plugin;
import com.facebook.presto.spi.type.Type;
import com.facebook.presto.spi.type.TypeManager;
import com.facebook.presto.type.ParametricType;
import com.google.common.collect.ImmutableList;

import javax.inject.Inject;

import java.util.List;

import static com.facebook.presto.ml.type.ModelType.MODEL;
import static com.facebook.presto.ml.type.RegressorType.REGRESSOR;
import static java.util.Objects.requireNonNull;

public class MLPlugin
        implements Plugin
{
    private TypeManager typeManager;

    @Inject
    public void setTypeManager(TypeManager typeManager)
    {
        this.typeManager = requireNonNull(typeManager, "typeManager is null");
    }

    @Override
    public <T> List<T> getServices(Class<T> type)
    {
        if (type == FunctionFactory.class) {
            return ImmutableList.of(type.cast(new MLFunctionFactory(typeManager)));
        }
        else if (type == Type.class) {
            return ImmutableList.of(type.cast(MODEL), type.cast(REGRESSOR));
        }
        else if (type == ParametricType.class) {
            return ImmutableList.of(type.cast(new ClassifierParametricType()));
        }
        return ImmutableList.of();
    }
}


text:
#pragma once
#include "WexTestClass.h"
#include <string>
using namespace std;

namespace UnitTests
{
    BEGIN_MODULE()
        MODULE_PROPERTY(L"Feature", L"XmlProfileParser")
    END_MODULE()

    MODULE_SETUP(ModuleSetup);
    MODULE_CLEANUP(ModuleCleanup);

    class XmlProfileParserUnitTests : public WEX::TestClass<XmlProfileParserUnitTests>
    {
    public:
        TEST_CLASS(XmlProfileParserUnitTests)

        TEST_CLASS_SETUP(ClassSetup);
        TEST_CLASS_CLEANUP(ClassCleanup);

        TEST_METHOD_SETUP(MethodSetup);
        TEST_METHOD_CLEANUP(MethodCleanup);

        TEST_METHOD(Test_ParseFile);
        TEST_METHOD(Test_ParseGroupAffinity);
        TEST_METHOD(Test_ParseNonGroupAffinity);
        TEST_METHOD(Test_ParseFilePrecreateFilesUseMaxSize);
        TEST_METHOD(Test_ParseFilePrecreateFilesOnlyFilesWithConstantSizes);
        TEST_METHOD(Test_ParseFilePrecreateFilesOnlyFilesWithConstantOrZeroSizes);
        TEST_METHOD(Test_ParseFileWriteBufferContentSequential);
        TEST_METHOD(Test_ParseFileWriteBufferContentZero);
        TEST_METHOD(Test_ParseFileWriteBufferContentRandom);
        TEST_METHOD(Test_ParseFileWriteBufferContentRandomNoFilePath);
        TEST_METHOD(Test_ParseFileWriteBufferContentRandomWithFilePath);
        TEST_METHOD(Test_ParseFileGlobalRequestCount);

        // TODO: test what happens when parameters have suffixes (e.g. 1M)
    private:
        string _sTempFilePath;
        HMODULE _hModule;
    };
}


text:
package com.swfarm.biz.chain.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import com.swfarm.biz.chain.bo.SaleChannel;

public class ImportCustomerOrdersController extends AbstractController {

	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest req,
			HttpServletResponse res) throws Exception {
		String saleChannel = req.getParameter("saleChannel");
		if (SaleChannel.CHANNEL_EBAY.equalsIgnoreCase(saleChannel)) {
			return new ModelAndView(
					"forward:/chain/import_ebaycustomerorders.shtml");
		} else if (SaleChannel.CHANNEL_AMAZON.equalsIgnoreCase(saleChannel)) {
			return new ModelAndView(
					"forward:/chain/import_amazoncustomerorders.shtml");
		} else if (SaleChannel.CHANNEL_WISH.equalsIgnoreCase(saleChannel)) {
			return new ModelAndView(
					"forward:/chain/import_wishcustomerorders.shtml");
		} else if (SaleChannel.CHANNEL_SMT.equalsIgnoreCase(saleChannel)) {
			return new ModelAndView(
					"forward:/chain/import_smtcustomerorders.shtml");
		} else if (SaleChannel.CHANNEL_DH.equalsIgnoreCase(saleChannel)) {
			return new ModelAndView(
					"forward:/chain/import_dhcustomerorders.shtml");
		 } else if (SaleChannel.CHANNEL_LINIO.equalsIgnoreCase(saleChannel)) {
			return new ModelAndView(
					"forward:/chain/import_liniocustomerorders.shtml");
		 } else {
			return new ModelAndView(
					"redirect:/chain/uploadcustomerordersfile.shtml");
		}
	}
}


text:
import classnames from 'classnames';
import React, { Ref } from 'react';
import { connectField, filterDOMProps, HTMLFieldProps } from 'uniforms';

export type TextFieldProps = HTMLFieldProps<
  string,
  HTMLDivElement,
  {
    icon?: string;
    iconLeft?: string;
    iconProps?: object;
    inputRef?: Ref<HTMLInputElement>;
    wrapClassName?: string;
  }
>;

function Text({
  autoComplete,
  className,
  disabled,
  error,
  errorMessage,
  icon,
  iconLeft,
  iconProps,
  id,
  inputRef,
  label,
  name,
  onChange,
  placeholder,
  readOnly,
  required,
  showInlineError,
  type,
  value,
  wrapClassName,
  ...props
}: TextFieldProps) {
  return (

      {label && {label}}

        <input
          autoComplete={autoComplete}
          disabled={disabled}
          id={id}
          name={name}
          onChange={event => onChange(event.target.value)}
          placeholder={placeholder}
          readOnly={readOnly}
          ref={inputRef}
          type={type}
          value={value ?? ''}
        />

        {(icon || iconLeft) && (
          <i className={`${icon || iconLeft} icon`} {...iconProps} />
        )}

      {!!(error && showInlineError) && (

{errorMessage}

      )}

  );
}

Text.defaultProps = { type: 'text' };

export default connectField<TextFieldProps>(Text, { kind: 'leaf' });


text:
test:
	@NODE_ENV=test ./node_modules/mocha/bin/mocha -G -R spec -u bdd -t 6000 --globals chai --colors

.PHONY: test


text:
Arduino IR Remote Decoder
=========================
I recently
bought myself an Arduino and I happened to have an infrared detector
too. Therefore, (obviously) I had to figure out how to use ALL of
the remote controls in my house to do something interesting. So I
ran through the house and grabbed every remote I could find. Before
I get into the "something interesting" let me tell a bit about the
IR detector.

An IR detector is microchip with a photocell. The microchip is a
demodulator that demodulates frequency modulated signals around 38 kHz,
usually from 35 kHz to 41 kHz. When there is a 38 kHz infrared signal
the detector outputs a low or 0v. When there is NO 38 kHz infrared
signal the chip outputs a high or +5v. As luck would have it: most IR
remotes use frequency modulated IR signals near 38 kHz! So pointing
a remote control at an IR detector and pressing a button will create
a stream of highs and lows. How exactly is data hidden in that stream
of highs and lows?

It would seem that there is no official IR remote protocol. The
majority of remotes seem to follow either the Philips RC5 or the
NEC infrared transmission protocol. I decided to assume that I'd be
working with NEC infrared transmission protocol because I had worked
with something similar.

So I got my Arduino up and running, connected the IR detector, wrote
some code and waited while nothing happened. Then I smelt something
burning. Turns out, I connected the detector backwards and it was
getting a little warm. I pulled the detector out and connected it.

As you may be able to tell from the diagram, the data line from the
IR detectors is connected to digital input pin 2 on the Arduino. The
detector is powered by the +5v and ground pins on the Arduino.

To start the code we define some constants:

    const int pinIR = 2;
	const int pinLED=13;
	const int CODE_LEN = 50;

`pinIR` is the pin that the data line of the IR detector is connected
to. pinLED is a pin that an LED is connected to; the UNO has a
built-in LED connected to pin 13. `CODE_LEN` is the number of pulses
that we want to monitor from the IR detector.

We'll define the variables that we'll be using:

    volatile boolean bounced = 0;
	volatile unsigned long durations[CODE_LEN];

`bounced` is a boolean used to tell us if we're already in an
interrupt. For some reason when an interrupt occurred, the interrupt
handler would be triggered twice in rapid succession. bounced can
correct this problem. `durations` is an array of pulse durations. It
will be used to store how long the data signal is high or low. The
setup code follows.

    void setup(){
      pinMode(pinIR , INPUT);
      pinMode(pinLED, OUTPUT);
      attachInterrupt(0, decodeIR, FALLING);
      digitalWrite(pinLED, LOW);
      Serial.begin(9600);
    }

In line 7 we are configuring the pin which is connected to the IR
detector as an input. Conversely, in line 8 we are ensuring our LED
is connected to an output pin. In line 9 we are saying to call the
function `decodeIR` when a `FALLING` edge occurs. `0` is simply the
interrupt number. We'll discuss the `decodeIR` function shortly. Line 10
turns off the LED and line 11 begins serial communication an 9600 baud
so we can send information back to the computer. Here is the decodeIR
function you were wondering about:

	void decodeIR(){
	  if(bounced){return;}
	  digitalWrite(pinLED, HIGH);
	  bounced = 1;
	  noInterrupts();
	  int i;
	  //for each "bit" in the code
	  for(i=0; i<CODE_LEN; i+=1){
	    //durations[i] = pulseIn(pinIR, LOW, 100000);
	    //store the duration of the pulse (microseconds)
	    durations[i] = pulseIn(pinIR, HIGH, 100000);
	  }
	  //enable interrupts
	  interrupts();
	}

We begin by checking if the bounced flag has been set. If the
bounced has been set then we should not be running this function
because either: (a) the decodeIR function has interrupted itself or
(b) we have not finished processing the last button input. Once we
determine that we should be running the decodeIR function we lite an
LED to indicate that we are doing something. Next, we set bounced
to 1; this indicates that we are monitoring and processing the IR
data. Then we disable interrupts using the noInterrupts function.

We are now at a point where we can focus on obtaining the signal
generated by the IR detector. i is a temporary variable used for
iterating. What are we iterating over? For each "bit" in the code
sequence we want to measure its duration. According to the [NEC
infrared transmission protocol documentation][NEC protocol]: a logical
"0" is a 562.5µs pulse burst followed by a 562.5µs space. At the
output of the detector we see a 562.5µs low followed by a 562.5µs high.
A logical "1" is a 562.5µs pulse burst followed by a 1687.5µs space;
at the output of the detector we see a 562.5µs low followed by a
1687.5µs high. The duration of the "low" is the same for a logical
0 or 1; however, the duration of "high" varies. Therefore, we shall
only measure the duration of the highs. Line 34 measures the duration
of the high and stores the measured duration in the appropriate slot
of the durations array.

 [NEC protocol](http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol)

After we have gathered all of the data we enable interrupts and exit
the function. When we are not within an interrupt we are within the
main loop:

	void loop(){
	  if(bounced == 1){
	    int i;
	    Serial.println("Starting");
	    for(i=0; i<CODE_LEN; i+=1){
	      Serial.println((unsigned long)durations[i]);
	    }
	    digitalWrite(pinLED, LOW);
	    bounced = 0;
	  }
	}

The first thing we do in the main loop is check if we have new
data. When `bounced == 1` we have new data so we then transmit that data
via serial communication. The first text we send over our communication
channel is "Starting" with a new line. Then we print each measured
pulse duration on a new line. After we have printed everything,
we turn off the LED that was lit in the interrupt. Finally we set
bounced to 0. This ensures that we only send the data once and that
the interrupt will be triggered again.

Running the code on an Arduino UNO with a IR detector connected will
produced output similar to the following, after a button on an IR
remote is pressed:

	Starting
	616
	1619
	610
	506
	608
	1623
	608

Converting each output to a string of 0's and 1's (and then possibly
hex) is tedious and boring. Consequently, I made a spreadsheet to do
the dirty work for me. The spreadsheet has 5 sheets: Input, Timing,
Bit, Bin, Hex.

How do you use it?

  - First you setup your Arduino UNO as described above (now is also a good time to grab your remote and make sure it has working batteries).
  - Upload and run the code on the Arduino.
  - Open the serial communication terminal in the Arduino code editor.
  - Then open the spreadsheet.

For each button you are interested in:

  - Press the button; make sure the Arduino gives you some output.
  - Input the button name (ie 0,1,VOL+,etc...) in the "Sequence of Button Presses:" row on the "Input" sheet of the spreadsheet.

Your Arduino serial communication should be filled with a list of
numbers and your spreadsheet should have entries in the first row
from column E on.

Copy the output from the Arduino. Paste it into the first column of
the "Input" sheet of the spreadsheet. All of the other sheets should
have updated.

The "Timing" sheet shows the raw times measured for each button. Each
button is represented by a single column.

The "Bit" sheet shows the logical binary representation of the signal
for each button. Cell: C1 can be edited to change the threshold
that distinguishes between a 0 and a 1. The default is 1000. If a
timing measurement is above the threshold then it is considered a 1;
otherwise, it is considered a 0.

The "Bin" sheet groups the data from the "Bit" sheet into groups of
4. Cell D1 can be edited to change the row where we begin grouping the
bits. By default the starting row is either 5 or 6. If you wanted to
(for example) ignore then first bit then the starting row would be 6.

Finally, the "Hex" sheet converts the data from binary to hex. It is
easiest to see patterns in the data using the hex representation.

There are some flaws with the spreadsheet, for example: the spreadsheet
pretends that each button is 100 bits longs. This creates extra output
after the actual code generated by the button. Luckily it is easy to
find the beginning/end of a button because there will be an error,
black box or some other sign in that cell.


text:
START_ATF_NAMESPACE
    typedef unsigned int DBSEEK;
END_ATF_NAMESPACE


text:
package pl.jozwik.mvn2sbt

import pl.jozwik.mvn2sbt.PluginConverter.PluginConverter

case class PluginDescription(
  artifactId: String,
  sbtSetting: Option[String],
  pluginsSbtPluginConfiguration: String,
  extraRepository: String,
  dependencies: Seq[Dependency],
  pomConfigurationToSbtConfiguration: PluginConverter)


text:
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Titanium.Web.Proxy.Models;

namespace Titanium.Web.Proxy.Helpers.WinHttp
{
    internal sealed class WinHttpWebProxyFinder : IDisposable
    {
        private readonly WinHttpHandle session;
        private bool autoDetectFailed;
        private AutoWebProxyState state;

        public WinHttpWebProxyFinder()
        {
            session = NativeMethods.WinHttp.WinHttpOpen(null, NativeMethods.WinHttp.AccessType.NoProxy, null, null, 0);
            if (session == null || session.IsInvalid)
            {
                int lastWin32Error = getLastWin32Error();
            }
            else
            {
                int downloadTimeout = 60 * 1000;
                if (NativeMethods.WinHttp.WinHttpSetTimeouts(session, downloadTimeout, downloadTimeout, downloadTimeout,
                    downloadTimeout))
                {
                    return;
                }

                int lastWin32Error = getLastWin32Error();
            }
        }

        public ICredentials? Credentials { get; set; }

        public ProxyInfo? ProxyInfo { get; internal set; }

        public bool BypassLoopback { get; internal set; }

        public bool BypassOnLocal { get; internal set; }

        public Uri? AutomaticConfigurationScript { get; internal set; }

        public bool AutomaticallyDetectSettings { get; internal set; }

        private WebProxy? proxy { get; set; }

        public void Dispose()
        {
            dispose(true);
        }

        public bool GetAutoProxies(Uri destination, out IList<string>? proxyList)
        {
            proxyList = null;
            if (session == null || session.IsInvalid || state == AutoWebProxyState.UnrecognizedScheme)
            {
                return false;
            }

            string? proxyListString = null;
            var errorCode = NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed;
            if (AutomaticallyDetectSettings && !autoDetectFailed)
            {
                errorCode = (NativeMethods.WinHttp.ErrorCodes)getAutoProxies(destination, null, out proxyListString);
                autoDetectFailed = isErrorFatalForAutoDetect(errorCode);
                if (errorCode == NativeMethods.WinHttp.ErrorCodes.UnrecognizedScheme)
                {
                    state = AutoWebProxyState.UnrecognizedScheme;
                    return false;
                }
            }

            if (AutomaticConfigurationScript != null && isRecoverableAutoProxyError(errorCode))
            {
                errorCode = (NativeMethods.WinHttp.ErrorCodes)getAutoProxies(destination, AutomaticConfigurationScript,
                    out proxyListString);
            }

            state = getStateFromErrorCode(errorCode);
            if (state != AutoWebProxyState.Completed)
            {
                return false;
            }

            if (!string.IsNullOrEmpty(proxyListString))
            {
                proxyListString = removeWhitespaces(proxyListString!);
                proxyList = proxyListString.Split(';');
            }

            return true;
        }

        public IExternalProxy? GetProxy(Uri destination)
        {
            if (GetAutoProxies(destination, out var proxies))
            {
                if (proxies == null)
                {
                    return null;
                }

                string proxyStr = proxies[0];
                int port = 80;
                if (proxyStr.Contains(":"))
                {
                    var parts = proxyStr.Split(new[] { ':' }, 2);
                    proxyStr = parts[0];
                    port = int.Parse(parts[1]);
                }

                // TODO: Apply authorization
                var systemProxy = new ExternalProxy(proxyStr, port);

                return systemProxy;
            }

            if (proxy?.IsBypassed(destination) == true)
            {
                return null;
            }

            var protocolType = ProxyInfo.ParseProtocolType(destination.Scheme);
            if (protocolType.HasValue)
            {
                HttpSystemProxyValue? value = null;
                if (ProxyInfo?.Proxies?.TryGetValue(protocolType.Value, out value) == true)
                {
                    var systemProxy = new ExternalProxy(value!.HostName, value.Port);
                    return systemProxy;
                }
            }

            return null;
        }

        public void LoadFromIE()
        {
            var pi = getProxyInfo();
            ProxyInfo = pi;
            AutomaticallyDetectSettings = pi.AutoDetect == true;
            AutomaticConfigurationScript = pi.AutoConfigUrl == null ? null : new Uri(pi.AutoConfigUrl);
            BypassLoopback = pi.BypassLoopback;
            BypassOnLocal = pi.BypassOnLocal;
            proxy = new WebProxy(new Uri("http://localhost"), BypassOnLocal, pi.BypassList);
        }

        private ProxyInfo getProxyInfo()
        {
            var proxyConfig = new NativeMethods.WinHttp.WINHTTP_CURRENT_USER_IE_PROXY_CONFIG();
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                ProxyInfo result;
                if (NativeMethods.WinHttp.WinHttpGetIEProxyConfigForCurrentUser(ref proxyConfig))
                {
                    result = new ProxyInfo(
                        proxyConfig.AutoDetect,
                        Marshal.PtrToStringUni(proxyConfig.AutoConfigUrl),
                        null,
                        Marshal.PtrToStringUni(proxyConfig.Proxy),
                        Marshal.PtrToStringUni(proxyConfig.ProxyBypass));
                }
                else
                {
                    if (Marshal.GetLastWin32Error() == 8)
                    {
                        throw new OutOfMemoryException();
                    }

                    result = new ProxyInfo(true, null, null, null, null);
                }

                return result;
            }
            finally
            {
                Marshal.FreeHGlobal(proxyConfig.Proxy);
                Marshal.FreeHGlobal(proxyConfig.ProxyBypass);
                Marshal.FreeHGlobal(proxyConfig.AutoConfigUrl);
            }
        }

        public void Reset()
        {
            state = AutoWebProxyState.Uninitialized;
            autoDetectFailed = false;
        }

        private void dispose(bool disposing)
        {
            if (!disposing || session == null || session.IsInvalid)
            {
                return;
            }

            session.Close();
        }

        private int getAutoProxies(Uri destination, Uri? scriptLocation, out string? proxyListString)
        {
            int num = 0;
            var autoProxyOptions = new NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS();
            autoProxyOptions.AutoLogonIfChallenged = false;
            if (scriptLocation == null)
            {
                autoProxyOptions.Flags = NativeMethods.WinHttp.AutoProxyFlags.AutoDetect;
                autoProxyOptions.AutoConfigUrl = null;
                autoProxyOptions.AutoDetectFlags =
                    NativeMethods.WinHttp.AutoDetectType.Dhcp | NativeMethods.WinHttp.AutoDetectType.DnsA;
            }
            else
            {
                autoProxyOptions.Flags = NativeMethods.WinHttp.AutoProxyFlags.AutoProxyConfigUrl;
                autoProxyOptions.AutoConfigUrl = scriptLocation.ToString();
                autoProxyOptions.AutoDetectFlags = NativeMethods.WinHttp.AutoDetectType.None;
            }

            if (!winHttpGetProxyForUrl(destination.ToString(), ref autoProxyOptions, out proxyListString))
            {
                num = getLastWin32Error();

                if (num == (int)NativeMethods.WinHttp.ErrorCodes.LoginFailure && Credentials != null)
                {
                    autoProxyOptions.AutoLogonIfChallenged = true;
                    if (!winHttpGetProxyForUrl(destination.ToString(), ref autoProxyOptions, out proxyListString))
                    {
                        num = getLastWin32Error();
                    }
                }
            }

            return num;
        }

        private bool winHttpGetProxyForUrl(string destination,
            ref NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out string? proxyListString)
        {
            proxyListString = null;
            bool flag;
            var proxyInfo = new NativeMethods.WinHttp.WINHTTP_PROXY_INFO();
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                flag = NativeMethods.WinHttp.WinHttpGetProxyForUrl(session, destination, ref autoProxyOptions,
                    out proxyInfo);
                if (flag)
                {
                    proxyListString = Marshal.PtrToStringUni(proxyInfo.Proxy);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(proxyInfo.Proxy);
                Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
            }

            return flag;
        }

        private static int getLastWin32Error()
        {
            int lastWin32Error = Marshal.GetLastWin32Error();
            if (lastWin32Error == 8)
            {
                throw new OutOfMemoryException();
            }

            return lastWin32Error;
        }

        private static bool isRecoverableAutoProxyError(NativeMethods.WinHttp.ErrorCodes errorCode)
        {
            switch (errorCode)
            {
                case NativeMethods.WinHttp.ErrorCodes.AutoProxyServiceError:
                case NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed:
                case NativeMethods.WinHttp.ErrorCodes.BadAutoProxyScript:
                case NativeMethods.WinHttp.ErrorCodes.UnableToDownloadScript:
                case NativeMethods.WinHttp.ErrorCodes.LoginFailure:
                case NativeMethods.WinHttp.ErrorCodes.OperationCancelled:
                case NativeMethods.WinHttp.ErrorCodes.Timeout:
                case NativeMethods.WinHttp.ErrorCodes.UnrecognizedScheme:
                    return true;
                default:
                    return false;
            }
        }

        private static AutoWebProxyState getStateFromErrorCode(NativeMethods.WinHttp.ErrorCodes errorCode)
        {
            if (errorCode == 0L)
            {
                return AutoWebProxyState.Completed;
            }

            switch (errorCode)
            {
                case NativeMethods.WinHttp.ErrorCodes.UnableToDownloadScript:
                    return AutoWebProxyState.DownloadFailure;
                case NativeMethods.WinHttp.ErrorCodes.AutoProxyServiceError:
                case NativeMethods.WinHttp.ErrorCodes.InvalidUrl:
                case NativeMethods.WinHttp.ErrorCodes.BadAutoProxyScript:
                    return AutoWebProxyState.Completed;
                case NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed:
                    return AutoWebProxyState.DiscoveryFailure;
                case NativeMethods.WinHttp.ErrorCodes.UnrecognizedScheme:
                    return AutoWebProxyState.UnrecognizedScheme;
                default:
                    return AutoWebProxyState.CompilationFailure;
            }
        }

        private static string removeWhitespaces(string value)
        {
            var stringBuilder = new StringBuilder();
            foreach (char c in value)
            {
                if (!char.IsWhiteSpace(c))
                {
                    stringBuilder.Append(c);
                }
            }

            return stringBuilder.ToString();
        }

        private static bool isErrorFatalForAutoDetect(NativeMethods.WinHttp.ErrorCodes errorCode)
        {
            switch (errorCode)
            {
                case NativeMethods.WinHttp.ErrorCodes.BadAutoProxyScript:
                case NativeMethods.WinHttp.ErrorCodes.AutoProxyServiceError:
                case NativeMethods.WinHttp.ErrorCodes.Success:
                case NativeMethods.WinHttp.ErrorCodes.InvalidUrl:
                    return false;
                default:
                    return true;
            }
        }

        private enum AutoWebProxyState
        {
            Uninitialized,
            DiscoveryFailure,
            DownloadFailure,
            CompilationFailure,
            UnrecognizedScheme,
            Completed
        }
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace EliteJournalReader.Events
{
    //The "Passengers" event contains:

    //"Manifest": array of passenger records, each containing:
    //o MissionID (int)
    //o Type (string)
    //o VIP (bool)
    //o Wanted (bool)
    //o Count (int)
    public class PassengersEvent : JournalEvent<PassengersEvent.PassengersEventArgs>
    {
        public PassengersEvent() : base("Passengers") { }

        public class PassengersEventArgs : JournalEventArgs
        {
            public Passenger[] Manifest { get; set; }
        }
    }
}


text:
package com.ctrip.zeus.flow.mergevs;

import com.ctrip.zeus.flow.mergevs.model.MergeVsFlowEntity;

import java.util.List;

public interface MergeVsFlowService {
    MergeVsFlowEntity add(MergeVsFlowEntity entity) throws Exception;

    MergeVsFlowEntity update(MergeVsFlowEntity entity, boolean force) throws Exception;

    MergeVsFlowEntity updateStep(Long id, String step) throws Exception;

    MergeVsFlowEntity get(Long id) throws Exception;

    List<MergeVsFlowEntity> queryAll() throws Exception;

    MergeVsFlowEntity createAndBindNewVs(Long id) throws Exception;

    MergeVsFlowEntity mergeVs(Long id) throws Exception;

    MergeVsFlowEntity rollback(Long id) throws Exception;

    MergeVsFlowEntity disable(Long id) throws Exception;

    MergeVsFlowEntity delete(Long id) throws Exception;

    MergeVsFlowEntity clean(Long id) throws Exception;
}