summaryrefslogtreecommitdiff
path: root/plugins/UserInfoEx/src/commonheaders.cpp
blob: 3d4942e84f12d989414e24a10031ee75ec1f9d4f (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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
UserinfoEx plugin for Miranda IM

Copyright:
© 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "commonheaders.h"

// global:
HINSTANCE		ghInst		= NULL;
TIME_API		tmi;					//timezone interface
FI_INTERFACE	*FIP		= NULL;		//freeimage interface
CLIST_INTERFACE *pcli		= NULL;

MGLOBAL			myGlobals;
pfnDwmIsCompositionEnabled	dwmIsCompositionEnabled;

/**
 * Calculates an unique DWORD number from a string.
 * It's the same as used in langpack.
 *
 * @param		szStr	- string to calculate the hash value for
 * @return	the unique id for the szStr
 **/

#if __GNUC__
#define NOINLINEASM
#endif

DWORD hashSetting(LPCSTR szStr)
{
#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined NOINLINEASM
	__asm
	{
		xor		edx,edx
		xor		eax,eax
		mov		esi,szStr
		mov		al,[esi]
		dec		esi
		xor		cl,cl
		lph_top:			//only 4 of 9 instructions in here don't use AL, so optimal pipe use is impossible
		xor		edx,eax
		inc		esi
		and		cl,31
		movzx	eax,byte ptr [esi]
		add		cl,5
		test	al,al
		rol		eax,cl		//rol is u-pipe only, but pairable
							//rol doesn't touch z-flag
		jnz		lph_top		//5 clock tick loop. not bad.

		xor		eax,edx
	}
#else
	DWORD hash = 0;
	int i;
	int shift = 0;
	for (i = 0; szStr[i]; i++)
	{
		hash ^= szStr[i] << shift;
		if (shift > 24)
		{
			hash ^= (szStr[i] >> (32 - shift)) & 0x7F;
		}
		shift = (shift + 5) & 0x1F;
	}
	return hash;
#endif
}

// MurmurHash2
#ifdef _DEBUG
#pragma optimize( "gt", on )
#endif
unsigned int __fastcall hash_M2(const void * key, unsigned int len)
{
	// 'm' and 'r' are mixing constants generated offline.
	// They're not really 'magic', they just happen to work well.
	const unsigned int m = 0x5bd1e995;
	const int r = 24;

	// Initialize the hash to a 'random' value
	unsigned int h = len;

	// Mix 4 bytes at a time into the hash
	const unsigned char * data = (const unsigned char *)key;

	while(len >= 4)
	{
		unsigned int k = *(unsigned int *)data;

		k *= m;
		k ^= k >> r;
		k *= m;

		h *= m;
		h ^= k;

		data += 4;
		len -= 4;
	}

	// Handle the last few bytes of the input array
	switch(len)
	{
	case 3: h ^= data[2] << 16;
	case 2: h ^= data[1] << 8;
	case 1: h ^= data[0];
			h *= m;
	};

	// Do a few final mixes of the hash to ensure the last few
	// bytes are well-incorporated.
	h ^= h >> 13;
	h *= m;
	h ^= h >> 15;

	return h;
}

unsigned int hashSettingW_M2(const char * key)
{
	if (key == NULL) return 0;
	const unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
	char* buf = (char*)alloca(len + 1);
	for (unsigned i = 0; i <= len ; ++i)
		buf[i] = key[i << 1];
	return hash_M2(buf, len);
}

unsigned int hashSetting_M2(const char * key)
{
	if (key == NULL) return 0;
	const unsigned int len = (unsigned int)mir_strlen((const char*)key);
	return hash_M2(key, len);
}

unsigned int hashSetting_M2(const wchar_t * key)
{
	if (key == NULL) return 0;
	const unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
	return hash_M2(key, len * sizeof(wchar_t));
}

#ifdef _DEBUG
#pragma optimize( "", on )
#endif

INT_PTR myDestroyServiceFunction(const char * key) {
	//DestroyServiceFunction always return 0 therfore we must call ServiceExists to enshure it is delete
	if (!ServiceExists(key)) return 0;
	DestroyServiceFunction((HANDLE)(INT_PTR)hashSetting(key));		//old hash
	if (!ServiceExists(key)) return 0;
	DestroyServiceFunction((HANDLE)(INT_PTR)hashSetting_M2(key));	//new MurmurHash2
	if (!ServiceExists(key)) return 0;
	return 1;
}