windowscodecs: Create Image Descriptor metadata block for a GIF frame.
[wine] / dlls / msvcp71 / msvcp71.c
1 /*
2  * msvcp71 specific functions
3  *
4  * Copyright 2010 Piotr Caban for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/unicode.h"
28
29 /* Copied from dlls/msvcrt/cpp.c */
30 #ifdef __i386__  /* thiscall functions are i386-specific */
31
32 #define THISCALL(func) __thiscall_ ## func
33 #define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func)
34 #define __thiscall __stdcall
35 #define DEFINE_THISCALL_WRAPPER(func,args) \
36     extern void THISCALL(func)(void); \
37     __ASM_GLOBAL_FUNC(__thiscall_ ## func, \
38                       "popl %eax\n\t" \
39                       "pushl %ecx\n\t" \
40                       "pushl %eax\n\t" \
41                       "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
42 #else /* __i386__ */
43
44 #define THISCALL(func) func
45 #define THISCALL_NAME(func) __ASM_NAME(#func)
46 #define __thiscall __cdecl
47 #define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
48
49 #endif /* __i386__ */
50
51 /* Copied from dlls/msvcp90/msvcp90.h */
52 typedef SIZE_T MSVCP_size_t;
53 typedef unsigned short MSVCP_wchar_t;
54
55 #define BUF_SIZE_CHAR 16
56 typedef struct
57 {
58     void *allocator;
59     union {
60         char buf[BUF_SIZE_CHAR];
61         char *ptr;
62     } data;
63     MSVCP_size_t size;
64     MSVCP_size_t res;
65 } basic_string_char;
66
67 #define BUF_SIZE_WCHAR 8
68 typedef struct
69 {
70     void *allocator;
71     union {
72         MSVCP_wchar_t buf[BUF_SIZE_WCHAR];
73         MSVCP_wchar_t *ptr;
74     } data;
75     MSVCP_size_t size;
76     MSVCP_size_t res;
77 } basic_string_wchar;
78
79 basic_string_char* (__stdcall *pbasic_string_char_replace)(basic_string_char*,
80         MSVCP_size_t, MSVCP_size_t, const char*, MSVCP_size_t);
81 basic_string_wchar* (__stdcall *pbasic_string_wchar_replace)(basic_string_wchar*,
82         MSVCP_size_t, MSVCP_size_t, const MSVCP_wchar_t*, MSVCP_size_t);
83 void (__cdecl *p_String_base_Xlen)(void);
84 void (__cdecl *p_String_base_Xran)(void);
85
86 typedef struct {
87     const char *pos;
88 } basic_string_char_iterator;
89
90 typedef struct {
91     const MSVCP_wchar_t *pos;
92 } basic_string_wchar_iterator;
93
94 static char* basic_string_char_ptr(basic_string_char *this)
95 {
96     if(this->res == BUF_SIZE_CHAR-1)
97         return this->data.buf;
98     return this->data.ptr;
99 }
100
101 static MSVCP_wchar_t* basic_string_wchar_ptr(basic_string_wchar *this)
102 {
103     if(this->res == BUF_SIZE_WCHAR-1)
104         return this->data.buf;
105     return this->data.ptr;
106 }
107
108 /* ?begin@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE?AViterator@12@XZ */
109 /* ?begin@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBE?AVconst_iterator@12@XZ */
110 /* ?rend@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE?AV?$reverse_iterator@Viterator@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@XZ */
111 /* ?rend@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBE?AV?$reverse_iterator@Vconst_iterator@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@XZ */
112 DEFINE_THISCALL_WRAPPER(basic_string_char_begin, 8)
113 basic_string_char_iterator* __thiscall basic_string_char_begin(
114         basic_string_char *this, basic_string_char_iterator *ret)
115 {
116     ret->pos = basic_string_char_ptr(this);
117     return ret;
118 }
119
120 /* ?end@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE?AViterator@12@XZ */
121 /* ?end@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBE?AVconst_iterator@12@XZ */
122 /* ?rbegin@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE?AV?$reverse_iterator@Viterator@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@XZ */
123 /* ?rbegin@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBE?AV?$reverse_iterator@Vconst_iterator@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@XZ */
124 DEFINE_THISCALL_WRAPPER(basic_string_char_end, 8)
125 basic_string_char_iterator* __thiscall basic_string_char_end(
126         basic_string_char *this, basic_string_char_iterator *ret)
127 {
128     ret->pos = basic_string_char_ptr(this)+this->size;
129     return ret;
130 }
131
132 /* ?replace@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@Viterator@12@0ABV12@@Z */
133 DEFINE_THISCALL_WRAPPER(basic_string_char_replace_iter_bstr, 16)
134 basic_string_char* __thiscall basic_string_char_replace_iter_bstr(basic_string_char *this,
135         basic_string_char_iterator beg, basic_string_char_iterator end, basic_string_char *str)
136 {
137     return pbasic_string_char_replace(this, beg.pos-basic_string_char_ptr(this),
138             end.pos-beg.pos, basic_string_char_ptr(str), str->size);
139 }
140
141 /* ?replace@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@Viterator@12@0ID@Z */
142 DEFINE_THISCALL_WRAPPER(basic_string_char_replace_iter_ch, 20)
143 basic_string_char* __thiscall basic_string_char_replace_iter_ch(basic_string_char *this,
144         basic_string_char_iterator beg, basic_string_char_iterator end, MSVCP_size_t count, char ch)
145 {
146     /* TODO: add more efficient implementation */
147     MSVCP_size_t off = beg.pos-basic_string_char_ptr(this);
148
149     pbasic_string_char_replace(this, off, end.pos-beg.pos, NULL, 0);
150     while(count--)
151         pbasic_string_char_replace(this, off, 0, &ch, 1);
152     return this;
153 }
154
155 /* ?replace@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@Viterator@12@0PBD1@Z */
156 DEFINE_THISCALL_WRAPPER(basic_string_char_replace_iter_beg_end, 20)
157 basic_string_char* __thiscall basic_string_char_replace_iter_beg_end(basic_string_char *this,
158         basic_string_char_iterator beg, basic_string_char_iterator end, const char *rbeg, const char *rend)
159 {
160     return pbasic_string_char_replace(this, beg.pos-basic_string_char_ptr(this),
161             end.pos-beg.pos, rbeg, rend-rbeg);
162 }
163
164 /* ?replace@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@Viterator@12@0PBD@Z */
165 DEFINE_THISCALL_WRAPPER(basic_string_char_replace_iter_cstr, 16)
166 basic_string_char* __thiscall basic_string_char_replace_iter_cstr(basic_string_char *this,
167         basic_string_char_iterator beg, basic_string_char_iterator end, const char *str)
168 {
169     return pbasic_string_char_replace(this, beg.pos-basic_string_char_ptr(this),
170             end.pos-beg.pos, str, strlen(str));
171 }
172
173 /* ?replace@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@Viterator@12@0PBDI@Z */
174 DEFINE_THISCALL_WRAPPER(basic_string_char_replace_iter_cstr_len, 20)
175 basic_string_char* __thiscall basic_string_char_replace_iter_cstr_len(basic_string_char *this,
176         basic_string_char_iterator beg, basic_string_char_iterator end, const char *str, MSVCP_size_t len)
177 {
178     return pbasic_string_char_replace(this, beg.pos-basic_string_char_ptr(this),
179             end.pos-beg.pos, str, len);
180 }
181
182 /* ?replace@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@Viterator@12@0Vconst_iterator@12@1@Z */
183 DEFINE_THISCALL_WRAPPER(basic_string_char_replace_iter_iter, 20)
184 basic_string_char* __thiscall basic_string_char_replace_iter_iter(basic_string_char *this,
185         basic_string_char_iterator beg, basic_string_char_iterator end,
186         basic_string_char_iterator rbeg, basic_string_char_iterator rend)
187 {
188     return pbasic_string_char_replace(this, beg.pos-basic_string_char_ptr(this),
189             end.pos-beg.pos, rbeg.pos, rend.pos-rbeg.pos);
190 }
191
192 /* ?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@Vconst_iterator@12@0@Z */
193 DEFINE_THISCALL_WRAPPER(basic_string_char_append_iter, 12)
194 basic_string_char* __thiscall basic_string_char_append_iter(basic_string_char *this,
195         basic_string_char_iterator beg, basic_string_char_iterator end)
196 {
197     return pbasic_string_char_replace(this, this->size, 0, beg.pos, end.pos-beg.pos);
198 }
199
200 /* ?begin@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAE?AViterator@12@XZ */
201 /* ?begin@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QBE?AVconst_iterator@12@XZ */
202 /* ?begin@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE?AViterator@12@XZ */
203 /* ?begin@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBE?AVconst_iterator@12@XZ */
204 /* ?rend@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAE?AV?$reverse_iterator@Viterator@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@2@XZ */
205 /* ?rend@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QBE?AV?$reverse_iterator@Vconst_iterator@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@2@XZ */
206 /* ?rend@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE?AV?$reverse_iterator@Viterator@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@XZ */
207 /* ?rend@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBE?AV?$reverse_iterator@Vconst_iterator@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@XZ */
208 DEFINE_THISCALL_WRAPPER(basic_string_wchar_begin, 8)
209 basic_string_wchar_iterator* __thiscall basic_string_wchar_begin(
210         basic_string_wchar *this, basic_string_wchar_iterator *ret)
211 {
212     ret->pos = basic_string_wchar_ptr(this);
213     return ret;
214 }
215
216 /* ?end@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAE?AViterator@12@XZ */
217 /* ?end@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QBE?AVconst_iterator@12@XZ */
218 /* ?end@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE?AViterator@12@XZ */
219 /* ?end@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBE?AVconst_iterator@12@XZ */
220 /* ?rbegin@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAE?AV?$reverse_iterator@Viterator@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@2@XZ */
221 /* ?rbegin@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QBE?AV?$reverse_iterator@Vconst_iterator@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@2@XZ */
222 /* ?rbegin@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAE?AV?$reverse_iterator@Viterator@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@XZ */
223 /* ?rbegin@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QBE?AV?$reverse_iterator@Vconst_iterator@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@XZ */
224 DEFINE_THISCALL_WRAPPER(basic_string_wchar_end, 8)
225 basic_string_wchar_iterator* __thiscall basic_string_wchar_end(
226         basic_string_wchar *this, basic_string_wchar_iterator *ret)
227 {
228     ret->pos = basic_string_wchar_ptr(this)+this->size;
229     return ret;
230 }
231
232 /* ?replace@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAEAAV12@Viterator@12@0ABV12@@Z */
233 /* ?replace@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@Viterator@12@0ABV12@@Z */
234 DEFINE_THISCALL_WRAPPER(basic_string_wchar_replace_iter_bstr, 16)
235 basic_string_wchar* __thiscall basic_string_wchar_replace_iter_bstr(basic_string_wchar *this,
236         basic_string_wchar_iterator beg, basic_string_wchar_iterator end, basic_string_wchar *str)
237 {
238     return pbasic_string_wchar_replace(this, beg.pos-basic_string_wchar_ptr(this),
239             end.pos-beg.pos, basic_string_wchar_ptr(str), str->size);
240 }
241
242 /* ?replace@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAEAAV12@Viterator@12@0IG@Z */
243 /* ?replace@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@Viterator@12@0I_W@Z */
244 DEFINE_THISCALL_WRAPPER(basic_string_wchar_replace_iter_ch, 20)
245 basic_string_wchar* __thiscall basic_string_wchar_replace_iter_ch(basic_string_wchar *this,
246         basic_string_wchar_iterator beg, basic_string_wchar_iterator end, MSVCP_size_t count, MSVCP_wchar_t ch)
247 {
248     /* TODO: add more efficient implementation */
249     MSVCP_size_t off = beg.pos-basic_string_wchar_ptr(this);
250
251     pbasic_string_wchar_replace(this, off, end.pos-beg.pos, NULL, 0);
252     while(count--)
253         pbasic_string_wchar_replace(this, off, 0, &ch, 1);
254     return this;
255 }
256
257 /* ?replace@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAEAAV12@Viterator@12@0PBG1@Z */
258 /* ?replace@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@Viterator@12@0PB_W1@Z */
259 DEFINE_THISCALL_WRAPPER(basic_string_wchar_replace_iter_beg_end, 20)
260 basic_string_wchar* __thiscall basic_string_wchar_replace_iter_beg_end(basic_string_wchar *this,
261         basic_string_wchar_iterator beg, basic_string_wchar_iterator end,
262         const MSVCP_wchar_t *rbeg, const MSVCP_wchar_t *rend)
263 {
264     return pbasic_string_wchar_replace(this, beg.pos-basic_string_wchar_ptr(this),
265             end.pos-beg.pos, rbeg, rend-rbeg);
266 }
267
268 /* ?replace@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAEAAV12@Viterator@12@0PBG@Z */
269 /* ?replace@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@Viterator@12@0PB_W@Z */
270 DEFINE_THISCALL_WRAPPER(basic_string_wchar_replace_iter_cstr, 16)
271 basic_string_wchar* __thiscall basic_string_wchar_replace_iter_cstr(basic_string_wchar *this,
272         basic_string_wchar_iterator beg, basic_string_wchar_iterator end, const MSVCP_wchar_t *str)
273 {
274     return pbasic_string_wchar_replace(this, beg.pos-basic_string_wchar_ptr(this),
275             end.pos-beg.pos, str, strlenW(str));
276 }
277
278 /* ?replace@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAEAAV12@Viterator@12@0PBGI@Z */
279 /* ?replace@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@Viterator@12@0PB_WI@Z */
280 DEFINE_THISCALL_WRAPPER(basic_string_wchar_replace_iter_cstr_len, 20)
281 basic_string_wchar* __thiscall basic_string_wchar_replace_iter_cstr_len(basic_string_wchar *this,
282         basic_string_wchar_iterator beg, basic_string_wchar_iterator end,
283         const MSVCP_wchar_t *str, MSVCP_size_t len)
284 {
285     return pbasic_string_wchar_replace(this, beg.pos-basic_string_wchar_ptr(this),
286             end.pos-beg.pos, str, len);
287 }
288
289 /* ?replace@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAEAAV12@Viterator@12@0Vconst_iterator@12@1@Z */
290 /* ?replace@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@Viterator@12@0Vconst_iterator@12@1@Z */
291 DEFINE_THISCALL_WRAPPER(basic_string_wchar_replace_iter_iter, 20)
292 basic_string_wchar* __thiscall basic_string_wchar_replace_iter_iter(basic_string_wchar *this,
293         basic_string_wchar_iterator beg, basic_string_wchar_iterator end,
294         basic_string_wchar_iterator rbeg, basic_string_wchar_iterator rend)
295 {
296     return pbasic_string_wchar_replace(this, beg.pos-basic_string_wchar_ptr(this),
297             end.pos-beg.pos, rbeg.pos, rend.pos-rbeg.pos);
298 }
299
300 /* ?append@?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@QAEAAV12@Vconst_iterator@12@0@Z */
301 /* ?append@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QAEAAV12@Vconst_iterator@12@0@Z */
302 DEFINE_THISCALL_WRAPPER(basic_string_wchar_append_iter, 12)
303 basic_string_wchar* __thiscall basic_string_wchar_append_iter(basic_string_wchar *this,
304         basic_string_wchar_iterator beg, basic_string_wchar_iterator end)
305 {
306     return pbasic_string_wchar_replace(this, this->size, 0, beg.pos, end.pos-beg.pos);
307 }
308
309 /* ?_Xlen@_String_base@std@@QBEXXZ */
310 DEFINE_THISCALL_WRAPPER(_String_base__Xlen, 4)
311 void __thiscall _String_base__Xlen(const void/*_String_base*/ *this)
312 {
313     p_String_base_Xlen();
314 }
315
316 /* ?_Xran@_String_base@std@@QBEXXZ */
317 DEFINE_THISCALL_WRAPPER(_String_base__Xran, 4)
318 void __thiscall _String_base__Xran(const void/*_String_base*/ *this)
319 {
320     p_String_base_Xran();
321 }
322
323 static BOOL init_funcs(void)
324 {
325     HMODULE hmod = GetModuleHandleA("msvcp90.dll");
326     if(!hmod)
327         return FALSE;
328
329     pbasic_string_char_replace = (void*)GetProcAddress(hmod, "basic_string_char_replace_helper");
330     pbasic_string_wchar_replace = (void*)GetProcAddress(hmod, "basic_string_wchar_replace_helper");
331
332     p_String_base_Xlen = (void*)GetProcAddress(hmod, "?_Xlen@_String_base@std@@SAXXZ");
333     p_String_base_Xran = (void*)GetProcAddress(hmod, "?_Xran@_String_base@std@@SAXXZ");
334
335     return pbasic_string_char_replace && pbasic_string_wchar_replace;
336 }
337
338 BOOL WINAPI DllMain(HINSTANCE hdll, DWORD reason, LPVOID reserved)
339 {
340     switch (reason)
341     {
342         case DLL_WINE_PREATTACH:
343             return FALSE;  /* prefer native version */
344
345         case DLL_PROCESS_ATTACH:
346             DisableThreadLibraryCalls(hdll);
347             if(!init_funcs())
348                 return FALSE;
349     }
350     return TRUE;
351 }