summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/src/modern_sync.cpp
blob: 5f6901fe18841d99609d10b1ccdd6d3bd2345fa3 (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
#include "hdr/modern_commonheaders.h"
#include "hdr/modern_sync.h"

static INT_PTR SyncCaller(WPARAM proc, LPARAM lParam)
{
	typedef int (*P0PARAMFUNC)();
	typedef int (*P1PARAMFUNC)(WPARAM);
	typedef int (*P2PARAMFUNC)(WPARAM, LPARAM);
	typedef int (*P3PARAMFUNC)(WPARAM, LPARAM, LPARAM);
	typedef int (*P4PARAMFUNC)(WPARAM, LPARAM, LPARAM, LPARAM);

	LPARAM * params = (LPARAM *)lParam;
	int count = params[0];
	switch (count) {
	case 0:
		return ((P0PARAMFUNC)proc)();

	case 1:
		return ((P1PARAMFUNC)proc)((WPARAM)params[1]);

	case 2:
		return ((P2PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2]);

	case 3:
		return ((P3PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2], (LPARAM)params[3]);

	case 4:
		return ((P4PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2], (LPARAM)params[3], (LPARAM)params[4]);
	}
	return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////

struct SYNCCALLITEM
{
	WPARAM  wParam;
	LPARAM  lParam;
	int     nResult;
	HANDLE  hDoneEvent;
	PSYNCCALLBACKPROC pfnProc;    
};

static HRESULT SyncCallWinProcProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& nReturn )
{
	nReturn = 0;
	if (pcli->hwndContactList == NULL )
		return E_FAIL;
	
	SYNCCALLITEM item = {0};
	item.wParam = wParam;
	item.lParam = lParam;
	item.pfnProc = pfnProc;
	nReturn = SendMessage(pcli->hwndContactList, UM_SYNCCALL, (WPARAM)&item,0);
	return S_OK;
}

static void CALLBACK _SyncCallerUserAPCProc(void* param)
{
	SYNCCALLITEM* item = (SYNCCALLITEM*)param;
	item->nResult = item->pfnProc(item->wParam, item->lParam);
	SetEvent(item->hDoneEvent);
}

static int SyncCallAPCProxy(PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam)
{
	if (pfnProc == NULL) 
		return 0;

	if (GetCurrentThreadId() == g_dwMainThreadID)
		return pfnProc(wParam, lParam);

	SYNCCALLITEM item;
	item.wParam = wParam;
	item.lParam = lParam;
	item.pfnProc = pfnProc;
	item.nResult = 0;
	item.hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

	CallFunctionAsync(_SyncCallerUserAPCProc, &item);	
		
	WaitForSingleObject(item.hDoneEvent, INFINITE);
	CloseHandle(item.hDoneEvent);
	return item.nResult;
}

/////////////////////////////////////////////////////////////////////////////////////////

LRESULT SyncOnWndProcCall(WPARAM wParam )
{
	SYNCCALLITEM *psci = (SYNCCALLITEM *)wParam;
	if (psci)
		return psci->pfnProc( psci->wParam, psci->lParam);
	return 0;
}

int DoCall( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam)
{
	return SyncCallAPCProxy(pfnProc, 0, lParam);
}

int SyncCall(void * vproc, int count, ... )
{
	LPARAM params[5];
	va_list va;
	int i;
	params[0] = (LPARAM)count;
	va_start(va, count);
	for (i=0; i < count && i < SIZEOF(params)-1; i++)
		params[i+1] = va_arg(va,LPARAM);

	va_end(va);
	return SyncCallAPCProxy(SyncCaller, (WPARAM)vproc, (LPARAM) params);
}