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
173
174
175
176
177
178
179
180
181
182
183
184
185
|
/*
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.
===============================================================================
File name : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/commonheaders.cpp $
Revision : $Revision: 210 $
Last change on : $Date: 2010-10-02 22:27:36 +0400 (Сб, 02 окт 2010) $
Last change by : $Author: ing.u.horn $
===============================================================================
*/
#include "commonheaders.h"
// global:
PLUGINLINK* pluginLink = NULL;
HINSTANCE ghInst = NULL;
MM_INTERFACE mmi; //memory interface
UTF8_INTERFACE utfi; //utf8 interface
LIST_INTERFACE li; //list interface
//XML_API xi; //for late use
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)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;
}
|