summaryrefslogtreecommitdiff
path: root/protocols/SkypeClassic/src/alogon.cpp
blob: 3eedadc637445b675050f1415b2a22462d2edb75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "skype.h"
#include "debug.h"

extern char g_szProtoName[];
extern HANDLE SkypeReady;

/**
 * Purpose: Retrieves class name from window
 *
 * Note: This is some sort of hack to return static local variable,
 * but it works :)
 */
static const TCHAR* getClassName(HWND wnd)
{
	static TCHAR className[256];

	*className = 0;
	GetClassName(wnd, &className[0], sizeof(className) / sizeof(className[0]));
	return className;
}

/**
 * Purpose: Finds a window
 *
 * Note: This function relies on Skype window placement.
 * It should work for Skype 3.x
 */
static HWND findWindow(HWND parent, const TCHAR* childClassName)
{
	// Get child window
	// This window is not combo box or edit box
	HWND wnd = GetWindow(parent, GW_CHILD);
	while (wnd != NULL && mir_tstrcmp(getClassName(wnd), childClassName) != 0)
		wnd = GetWindow(wnd, GW_HWNDNEXT);

	return wnd;
}

static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
	DWORD dwPID;
	GetWindowThreadProcessId(hWnd, &dwPID);
	if (lParam != 0 && dwPID != (DWORD)lParam) return TRUE;
	const TCHAR *lpszClassName = getClassName(hWnd);
	if (mir_tstrcmp(lpszClassName, _T("tSkMainForm.UnicodeClass")) == 0 ||
		mir_tstrcmp(lpszClassName, _T("TLoginForm.UnicodeClass")) == 0)
	{
		HWND loginControl = GetWindow(hWnd, GW_CHILD);

		LOG(("setUserNamePasswordThread: Skype window found!"));

		// Sleep for some time, while Skype is loading
		// It loads slowly :(
		//Sleep(5000);
		LOG(("TLoginControl = %S", getClassName(loginControl)));

		// Check for login control
		if (mir_tstrcmp(getClassName(loginControl), _T("TLoginControl")) == 0)
		{
			// Find user name window
			HWND userName = findWindow(loginControl, _T("TNavigableTntComboBox.UnicodeClass"));
			HWND password = findWindow(loginControl, _T("TNavigableTntEdit.UnicodeClass"));

			LOG(("userName=%08X; password=%08X", userName, password));
			if (userName && password)
			{
				// Set user name and password
				DBVARIANT dbv;

				if (!db_get_ws(NULL, SKYPE_PROTONAME, "LoginUserName", &dbv))
				{
					SetWindowTextW(userName, dbv.pwszVal);
					db_free(&dbv);
				}

				if (!db_get_ws(NULL, SKYPE_PROTONAME, "LoginPassword", &dbv))
				{
					SetWindowTextW(password, dbv.pwszVal);
					db_free(&dbv);
					SendMessageW(password, WM_CHAR, 13, 0);
				}


				SendMessageW(hWnd,
					WM_COMMAND,
					0x4a8,  // sign-in button; WARNING: This ID can change during newer Skype versions
					(LPARAM)findWindow(loginControl, _T("TTntButton.UnicodeClass")));
			}
			return FALSE;
		}

	}
	return TRUE;
}

void __cdecl setUserNamePasswordThread(void *lpDummy)
{
	DWORD dwPid = (DWORD)lpDummy;
	HANDLE mutex = CreateMutex(NULL, TRUE, _T("setUserNamePasswordMutex"));

	// Check double entrance
	if (GetLastError() == ERROR_ALREADY_EXISTS)
		return;

	WaitForSingleObject(SkypeReady, 5000);
	EnumWindows(EnumWindowsProc, dwPid);

	ReleaseMutex(mutex);
	CloseHandle(mutex);
}

/**
 * Purpose: Finds Skype window and sets user name and password.
 *
 * Note: This function relies on Skype window placement.
 * It should work for Skype 3.x
 */
void setUserNamePassword(int dwPid)
{
	mir_forkthread(setUserNamePasswordThread, (void*)dwPid);

	// Give time to thread
	Sleep(100);
}