~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/handler/win_delay_loader.cc

Tags: innodb-plugin-1.0.2
InnoDB Plugin 1.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***********************************************************************
 
2
This file contains functions that implement the delay loader on Windows.
 
3
 
 
4
This is a customized version of delay loader with limited functionalities.
 
5
It does not support:
 
6
 
 
7
* (manual) unloading
 
8
* multiple delay loaded DLLs
 
9
* multiple loading of the same DLL
 
10
 
 
11
This delay loader is used only by the InnoDB plugin. Other components (DLLs)
 
12
can still use the default delay loader, provided by MSVC.
 
13
 
 
14
Several acronyms used by Microsoft:
 
15
 * IAT: import address table
 
16
 * INT: import name table
 
17
 * RVA: Relative Virtual Address
 
18
 
 
19
See http://msdn.microsoft.com/en-us/magazine/bb985992.aspx for details of
 
20
PE format.
 
21
 
 
22
(c) 2008 Innobase Oy
 
23
***********************************************************************/
 
24
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
 
25
# define WIN32_LEAN_AND_MEAN
 
26
# include <windows.h>
 
27
# include <delayimp.h>
 
28
# include <mysql_priv.h>
 
29
 
 
30
extern "C" {
 
31
# include "univ.i"
 
32
# include "hash0hash.h"
 
33
}
 
34
 
 
35
/***********************************************************************
 
36
This following contains a list of externals that can not be resolved by
 
37
delay loading. They have to be resolved indirectly via their addresses
 
38
in the .map file. All of them are external variables. */
 
39
CHARSET_INFO*           wdl_my_charset_bin;
 
40
CHARSET_INFO*           wdl_my_charset_latin1;
 
41
CHARSET_INFO*           wdl_my_charset_filename;
 
42
CHARSET_INFO**          wdl_system_charset_info;
 
43
CHARSET_INFO**          wdl_default_charset_info;
 
44
CHARSET_INFO**          wdl_all_charsets;
 
45
system_variables*       wdl_global_system_variables;
 
46
char*                   wdl_mysql_real_data_home;
 
47
char**                  wdl_mysql_data_home;
 
48
char**                  wdl_tx_isolation_names;
 
49
char**                  wdl_binlog_format_names;
 
50
char*                   wdl_reg_ext;
 
51
pthread_mutex_t*        wdl_LOCK_thread_count;
 
52
key_map*                wdl_key_map_full;
 
53
MY_TMPDIR*              wdl_mysql_tmpdir_list;
 
54
bool*                   wdl_mysqld_embedded;
 
55
uint*                   wdl_lower_case_table_names;
 
56
ulong*                  wdl_specialflag;
 
57
int*                    wdl_my_umask;
 
58
 
 
59
/***********************************************************************
 
60
The following is defined in ha_innodb.cc. It is used for copying the
 
61
system variables from the builtin innodb plugin to the dynamic plugin.
 
62
*/
 
63
extern struct st_mysql_plugin*  builtin_innobase_plugin_ptr;
 
64
 
 
65
/***********************************************************************
 
66
The preffered load-address defined in PE (portable executable format).*/
 
67
#if defined(_M_IA64)
 
68
#pragma section(".base", long, read)
 
69
extern "C"
 
70
__declspec(allocate(".base"))
 
71
const IMAGE_DOS_HEADER __ImageBase;
 
72
#else
 
73
extern "C"
 
74
const IMAGE_DOS_HEADER __ImageBase;
 
75
#endif
 
76
 
 
77
/***********************************************************************
 
78
A template function for converting a relative address (RVA) to an
 
79
absolute address (VA). This is due to the pointers in the delay
 
80
descriptor (ImgDelayDescr in delayimp.h) have been changed from
 
81
VAs to RVAs to work on both 32- and 64-bit platforms. */
 
82
template <class X>
 
83
X PFromRva(RVA rva) {
 
84
        return X(PBYTE(&__ImageBase) + rva);
 
85
}
 
86
 
 
87
/***********************************************************************
 
88
Convert to the old format for convenience. The structure as well as its
 
89
element names follow the definition of ImgDelayDescr in delayimp.h. */
 
90
struct InternalImgDelayDescr {
 
91
        DWORD           grAttrs;        /* attributes */
 
92
        LPCSTR          szName;         /* pointer to dll name */
 
93
        HMODULE*        phmod;          /* address of module handle */
 
94
        PImgThunkData   pIAT;           /* address of the IAT */
 
95
        PCImgThunkData  pINT;           /* address of the INT */
 
96
        PCImgThunkData  pBoundIAT;      /* address of the optional bound IAT */
 
97
        PCImgThunkData  pUnloadIAT;     /* address of optional copy of
 
98
                                           original IAT */
 
99
        DWORD           dwTimeStamp;    /* 0 if not bound,
 
100
                                           otherwise date/time stamp of DLL
 
101
                                           bound to (Old BIND) */
 
102
};
 
103
 
 
104
typedef struct map_hash_chain_struct    map_hash_chain_t;
 
105
 
 
106
struct map_hash_chain_struct {
 
107
        char*                   symbol; /* pointer to a symbol */
 
108
        ulint                   value;  /* address of the symbol */
 
109
        map_hash_chain_t*       next;   /* pointer to the next cell
 
110
                                        in the same folder. */
 
111
        map_hash_chain_t*       chain;  /* a linear chain used for
 
112
                                        cleanup. */
 
113
};
 
114
 
 
115
static HMODULE                          my_hmod = 0;
 
116
static struct hash_table_struct*        m_htbl = NULL ;
 
117
static map_hash_chain_t*                chain_header = NULL;
 
118
static ibool                            wdl_init = FALSE;
 
119
const ulint                             MAP_HASH_CELLS_NUM = 10000;
 
120
 
 
121
#ifndef DBUG_OFF
 
122
/***********************************************************************
 
123
In the dynamic plugin, it is required to call the following dbug functions
 
124
in the server:
 
125
        _db_pargs_
 
126
        _db_doprnt_
 
127
        _db_enter_
 
128
        _db_return_
 
129
        _db_dump_
 
130
 
 
131
The plugin will get those function pointers during the initialization.
 
132
*/
 
133
typedef void (__cdecl* pfn_db_enter_)(
 
134
        const char*     _func_,
 
135
        const char*     _file_,
 
136
        uint            _line_,
 
137
        const char**    _sfunc_,
 
138
        const char**    _sfile_,
 
139
        uint*           _slevel_,
 
140
        char***);
 
141
 
 
142
typedef void (__cdecl* pfn_db_return_)(
 
143
        uint            _line_,
 
144
        const char**    _sfunc_,
 
145
        const char**    _sfile_,
 
146
        uint*           _slevel_);
 
147
 
 
148
typedef void (__cdecl* pfn_db_pargs_)(
 
149
        uint            _line_,
 
150
        const char*     keyword);
 
151
 
 
152
typedef void (__cdecl* pfn_db_doprnt_)(
 
153
        const char*     format,
 
154
        ...);
 
155
 
 
156
typedef void (__cdecl* pfn_db_dump_)(
 
157
        uint                    _line_,
 
158
        const char*             keyword,
 
159
        const unsigned char*    memory,
 
160
        size_t                  length);
 
161
 
 
162
static pfn_db_enter_    wdl_db_enter_;
 
163
static pfn_db_return_   wdl_db_return_;
 
164
static pfn_db_pargs_    wdl_db_pargs_;
 
165
static pfn_db_doprnt_   wdl_db_doprnt_;
 
166
static pfn_db_dump_     wdl_db_dump_;
 
167
#endif /* !DBUG_OFF */
 
168
 
 
169
/*****************************************************************
 
170
Creates a hash table with >= n array cells. The actual number of cells is
 
171
chosen to be a prime number slightly bigger than n.
 
172
 
 
173
This is the same function as hash_create in hash0hash.c, except the
 
174
memory allocation. This function is invoked before the engine is
 
175
initialized, and buffer pools are not ready yet. */
 
176
static
 
177
hash_table_t*
 
178
wdl_hash_create(
 
179
/*============*/
 
180
                        /* out, own: created hash table */
 
181
        ulint   n)      /* in: number of array cells */
 
182
{
 
183
        hash_cell_t*    array;
 
184
        ulint           prime;
 
185
        hash_table_t*   table;
 
186
 
 
187
        prime = ut_find_prime(n);
 
188
 
 
189
        table = (hash_table_t*) malloc(sizeof(hash_table_t));
 
190
        if (table == NULL) {
 
191
                return(NULL);
 
192
        }
 
193
 
 
194
        array = (hash_cell_t*) malloc(sizeof(hash_cell_t) * prime);
 
195
        if (array == NULL) {
 
196
                free(table);
 
197
                return(NULL);
 
198
        }
 
199
 
 
200
        table->array = array;
 
201
        table->n_cells = prime;
 
202
        table->n_mutexes = 0;
 
203
        table->mutexes = NULL;
 
204
        table->heaps = NULL;
 
205
        table->heap = NULL;
 
206
        table->magic_n = HASH_TABLE_MAGIC_N;
 
207
 
 
208
        /* Initialize the cell array */
 
209
        hash_table_clear(table);
 
210
 
 
211
        return(table);
 
212
}
 
213
 
 
214
/*****************************************************************
 
215
Frees a hash table. */
 
216
static
 
217
void
 
218
wdl_hash_table_free(
 
219
/*================*/
 
220
        hash_table_t*   table)  /* in, own: hash table */
 
221
{
 
222
        ut_a(table != NULL);
 
223
        ut_a(table->mutexes == NULL);
 
224
 
 
225
        free(table->array);
 
226
        free(table);
 
227
}
 
228
 
 
229
/***********************************************************************
 
230
Function for calculating the count of imports given the base of the IAT. */
 
231
static
 
232
ulint
 
233
wdl_import_count(
 
234
/*=============*/
 
235
                                        /* out: number of imports */
 
236
        PCImgThunkData  pitd_base)      /* in: base of the IAT */
 
237
{
 
238
        ulint           ret = 0;
 
239
        PCImgThunkData  pitd = pitd_base;
 
240
 
 
241
        while (pitd->u1.Function) {
 
242
                pitd++;
 
243
                ret++;
 
244
        }
 
245
 
 
246
        return(ret);
 
247
}
 
248
 
 
249
/***********************************************************************
 
250
Read Mapfile to a hashtable for faster access */
 
251
static
 
252
ibool
 
253
wdl_load_mapfile(
 
254
/*=============*/
 
255
                                        /* out: TRUE if the mapfile is
 
256
                                        loaded successfully. */
 
257
        const char*     filename)       /* in: name of the mapfile. */
 
258
{
 
259
        FILE*           fp;
 
260
        const size_t    nSize = 256;
 
261
        char            tmp_buf[nSize];
 
262
        char*           func_name;
 
263
        char*           func_addr;
 
264
        ulint           load_addr = 0;
 
265
        ibool           valid_load_addr = FALSE;
 
266
#ifdef _WIN64
 
267
        const char*     tmp_string = " Preferred load address is %16llx";
 
268
#else
 
269
        const char*     tmp_string = " Preferred load address is %08x";
 
270
#endif
 
271
 
 
272
        fp = fopen(filename, "r");
 
273
        if (fp == NULL) {
 
274
 
 
275
                return(FALSE);
 
276
        }
 
277
 
 
278
        /* Check whether to create the hashtable */
 
279
        if (m_htbl == NULL) {
 
280
 
 
281
                m_htbl = wdl_hash_create(MAP_HASH_CELLS_NUM);
 
282
 
 
283
                if (m_htbl == NULL) {
 
284
 
 
285
                        fclose(fp);
 
286
                        return(FALSE);
 
287
                }
 
288
        }
 
289
 
 
290
        /* Search start of symbol list and get the preferred load address */
 
291
        while (fgets(tmp_buf, sizeof(tmp_buf), fp)) {
 
292
 
 
293
                if (sscanf(tmp_buf, tmp_string, &load_addr) == 1) {
 
294
 
 
295
                        valid_load_addr = TRUE;
 
296
                }
 
297
 
 
298
                if (strstr(tmp_buf, "Rva+Base") != NULL) {
 
299
 
 
300
                        break;
 
301
                }
 
302
        }
 
303
 
 
304
        if (valid_load_addr == FALSE) {
 
305
 
 
306
                /* No "Preferred load address", the map file is wrong. */
 
307
                fclose(fp);
 
308
                return(FALSE);
 
309
        }
 
310
 
 
311
        /* Read symbol list */
 
312
        while (fgets(tmp_buf, sizeof(tmp_buf), fp))
 
313
        {
 
314
                map_hash_chain_t*       map_cell;
 
315
                ulint                   map_fold;
 
316
 
 
317
                if (*tmp_buf == 0) {
 
318
 
 
319
                        continue;
 
320
                }
 
321
 
 
322
                func_name = strtok(tmp_buf, " ");
 
323
                func_name = strtok(NULL, " ");
 
324
                func_addr = strtok(NULL, " ");
 
325
 
 
326
                if (func_name && func_addr) {
 
327
 
 
328
                        ut_snprintf(tmp_buf, nSize, "0x%s", func_addr);
 
329
                        if (*func_name == '_') {
 
330
 
 
331
                                func_name++;
 
332
                        }
 
333
 
 
334
                        map_cell = (map_hash_chain_t*)
 
335
                                   malloc(sizeof(map_hash_chain_t));
 
336
                        if (map_cell == NULL) {
 
337
                                return(FALSE);
 
338
                        }
 
339
 
 
340
                        /* Chain all cells together */
 
341
                        map_cell->chain = chain_header;
 
342
                        chain_header = map_cell;
 
343
 
 
344
                        map_cell->symbol = strdup(func_name);
 
345
                        map_cell->value = (ulint) strtoull(tmp_buf, NULL, 0)
 
346
                                          - load_addr;
 
347
                        map_fold = ut_fold_string(map_cell->symbol);
 
348
 
 
349
                        HASH_INSERT(map_hash_chain_t,
 
350
                                    next,
 
351
                                    m_htbl,
 
352
                                    map_fold,
 
353
                                    map_cell);
 
354
                }
 
355
        }
 
356
 
 
357
        fclose(fp);
 
358
 
 
359
        return(TRUE);
 
360
}
 
361
 
 
362
/*****************************************************************
 
363
Cleanup.during DLL unload */
 
364
static
 
365
void
 
366
wdl_cleanup(void)
 
367
/*=============*/
 
368
{
 
369
        while (chain_header != NULL) {
 
370
                map_hash_chain_t*       tmp;
 
371
 
 
372
                tmp = chain_header->chain;
 
373
                free(chain_header->symbol);
 
374
                free(chain_header);
 
375
                chain_header = tmp;
 
376
        }
 
377
 
 
378
        if (m_htbl != NULL) {
 
379
 
 
380
                wdl_hash_table_free(m_htbl);
 
381
        }
 
382
}
 
383
 
 
384
/***********************************************************************
 
385
Load the mapfile mysqld.map. */
 
386
static
 
387
HMODULE
 
388
wdl_get_mysqld_mapfile(void)
 
389
/*========================*/
 
390
                        /* out: the module handle */
 
391
{
 
392
        char    file_name[MAX_PATH];
 
393
        char*   ext;
 
394
        ulint   err;
 
395
 
 
396
        if (my_hmod == 0) {
 
397
 
 
398
                size_t  nSize = MAX_PATH - strlen(".map") -1;
 
399
 
 
400
                /* First find out the name of current executable */
 
401
                my_hmod = GetModuleHandle(NULL);
 
402
                if (my_hmod == 0) {
 
403
 
 
404
                        return(my_hmod);
 
405
                }
 
406
 
 
407
                err = GetModuleFileName(my_hmod, file_name, nSize);
 
408
                if (err == 0) {
 
409
 
 
410
                        my_hmod = 0;
 
411
                        return(my_hmod);
 
412
                }
 
413
 
 
414
                ext = strrchr(file_name, '.');
 
415
                if (ext != NULL) {
 
416
 
 
417
                        *ext = 0;
 
418
                        strcat(file_name, ".map");
 
419
 
 
420
                        err = wdl_load_mapfile(file_name);
 
421
                        if (err == 0) {
 
422
 
 
423
                                my_hmod = 0;
 
424
                        }
 
425
                } else {
 
426
 
 
427
                        my_hmod = 0;
 
428
                }
 
429
        }
 
430
 
 
431
        return(my_hmod);
 
432
}
 
433
 
 
434
/***********************************************************************
 
435
Retrieves the address of an exported function. It follows the convention
 
436
of GetProcAddress(). */
 
437
static
 
438
FARPROC
 
439
wdl_get_procaddr_from_map(
 
440
/*======================*/
 
441
                                        /* out: address of exported
 
442
                                        function. */
 
443
        HANDLE          m_handle,       /* in: module handle */
 
444
        const char*     import_proc)    /* in: procedure name */
 
445
{
 
446
        map_hash_chain_t*       hash_chain;
 
447
        ulint                   map_fold;
 
448
 
 
449
        map_fold = ut_fold_string(import_proc);
 
450
        HASH_SEARCH(
 
451
                next,
 
452
                m_htbl,
 
453
                map_fold,
 
454
                map_hash_chain_t*,
 
455
                hash_chain,
 
456
                (ut_strcmp(hash_chain->symbol, import_proc) == 0));
 
457
 
 
458
        if (hash_chain == NULL) {
 
459
 
 
460
#ifdef _WIN64
 
461
                /* On Win64, the leading '_' may not be taken out. In this
 
462
                case, search again without the leading '_'. */
 
463
                if (*import_proc == '_') {
 
464
 
 
465
                        import_proc++;
 
466
                }
 
467
 
 
468
                map_fold = ut_fold_string(import_proc);
 
469
                HASH_SEARCH(
 
470
                        next,
 
471
                        m_htbl,
 
472
                        map_fold,
 
473
                        map_hash_chain_t*,
 
474
                        hash_chain,
 
475
                        (ut_strcmp(hash_chain->symbol, import_proc) == 0));
 
476
 
 
477
                if (hash_chain == NULL) {
 
478
#endif
 
479
                        if (wdl_init == TRUE) {
 
480
 
 
481
                                sql_print_error(
 
482
                                        "InnoDB: the procedure pointer of %s"
 
483
                                        " is not found.",
 
484
                                        import_proc);
 
485
                        }
 
486
 
 
487
                        return(0);
 
488
#ifdef _WIN64
 
489
                }
 
490
#endif
 
491
        }
 
492
 
 
493
        return((FARPROC) ((ulint) m_handle + hash_chain->value));
 
494
}
 
495
 
 
496
/***********************************************************************
 
497
Retrieves the address of an exported variable.
 
498
Note: It does not follow the Windows call convention FARPROC. */
 
499
static
 
500
void*
 
501
wdl_get_varaddr_from_map(
 
502
/*=====================*/
 
503
                                                /* out: address of exported
 
504
                                                variable. */
 
505
        HANDLE          m_handle,               /* in: module handle */
 
506
        const char*     import_variable)        /* in: variable name */
 
507
{
 
508
        map_hash_chain_t*       hash_chain;
 
509
        ulint                   map_fold;
 
510
 
 
511
        map_fold = ut_fold_string(import_variable);
 
512
        HASH_SEARCH(
 
513
                next,
 
514
                m_htbl,
 
515
                map_fold,
 
516
                map_hash_chain_t*,
 
517
                hash_chain,
 
518
                (ut_strcmp(hash_chain->symbol, import_variable) == 0));
 
519
 
 
520
        if (hash_chain == NULL) {
 
521
 
 
522
#ifdef _WIN64
 
523
                /* On Win64, the leading '_' may not be taken out. In this
 
524
                case, search again without the leading '_'. */
 
525
                if (*import_variable == '_') {
 
526
 
 
527
                        import_variable++;
 
528
                }
 
529
 
 
530
                map_fold = ut_fold_string(import_variable);
 
531
                HASH_SEARCH(
 
532
                        next,
 
533
                        m_htbl,
 
534
                        map_fold,
 
535
                        map_hash_chain_t*,
 
536
                        hash_chain,
 
537
                        (ut_strcmp(hash_chain->symbol, import_variable) == 0));
 
538
 
 
539
                if (hash_chain == NULL) {
 
540
#endif
 
541
                        if (wdl_init == TRUE) {
 
542
 
 
543
                                sql_print_error(
 
544
                                        "InnoDB: the variable address of %s"
 
545
                                        " is not found.",
 
546
                                        import_variable);
 
547
                        }
 
548
 
 
549
                        return(0);
 
550
#ifdef _WIN64
 
551
                }
 
552
#endif
 
553
        }
 
554
 
 
555
        return((void*) ((ulint) m_handle + hash_chain->value));
 
556
}
 
557
 
 
558
/***********************************************************************
 
559
Bind all unresolved external variables from the MySQL executable. */
 
560
static
 
561
bool
 
562
wdl_get_external_variables(void)
 
563
/*============================*/
 
564
                        /* out: TRUE if successful */
 
565
{
 
566
        HMODULE hmod = wdl_get_mysqld_mapfile();
 
567
 
 
568
        if (hmod == 0) {
 
569
 
 
570
                return(FALSE);
 
571
        }
 
572
 
 
573
#define GET_SYM(sym, var, type)                                 \
 
574
        var = (type*) wdl_get_varaddr_from_map(hmod, sym);      \
 
575
        if (var == NULL) return(FALSE)
 
576
#ifdef _WIN64
 
577
#define GET_SYM2(sym1, sym2, var, type)                         \
 
578
        var = (type*) wdl_get_varaddr_from_map(hmod, sym1);     \
 
579
        if (var == NULL) return(FALSE)
 
580
#else
 
581
#define GET_SYM2(sym1, sym2, var, type)                         \
 
582
        var = (type*) wdl_get_varaddr_from_map(hmod, sym2);     \
 
583
        if (var == NULL) return(FALSE)
 
584
#endif // (_WIN64)
 
585
#define GET_C_SYM(sym, type) GET_SYM(#sym, wdl_##sym, type)
 
586
#define GET_PROC_ADDR(sym)                                      \
 
587
        wdl##sym = (pfn##sym) wdl_get_procaddr_from_map(hmod, #sym)
 
588
 
 
589
        GET_C_SYM(my_charset_bin, CHARSET_INFO);
 
590
        GET_C_SYM(my_charset_latin1, CHARSET_INFO);
 
591
        GET_C_SYM(my_charset_filename, CHARSET_INFO);
 
592
        GET_C_SYM(default_charset_info, CHARSET_INFO*);
 
593
        GET_C_SYM(all_charsets, CHARSET_INFO*);
 
594
        GET_C_SYM(my_umask, int);
 
595
 
 
596
        GET_SYM("?global_system_variables@@3Usystem_variables@@A",
 
597
                wdl_global_system_variables, struct system_variables);
 
598
        GET_SYM("?mysql_real_data_home@@3PADA",
 
599
                wdl_mysql_real_data_home, char);
 
600
        GET_SYM("?reg_ext@@3PADA", wdl_reg_ext, char);
 
601
        GET_SYM("?LOCK_thread_count@@3U_RTL_CRITICAL_SECTION@@A",
 
602
                wdl_LOCK_thread_count, pthread_mutex_t);
 
603
        GET_SYM("?key_map_full@@3V?$Bitmap@$0EA@@@A",
 
604
                wdl_key_map_full, key_map);
 
605
        GET_SYM("?mysql_tmpdir_list@@3Ust_my_tmpdir@@A",
 
606
                wdl_mysql_tmpdir_list, MY_TMPDIR);
 
607
        GET_SYM("?mysqld_embedded@@3_NA",
 
608
                wdl_mysqld_embedded, bool);
 
609
        GET_SYM("?lower_case_table_names@@3IA",
 
610
                wdl_lower_case_table_names, uint);
 
611
        GET_SYM("?specialflag@@3KA", wdl_specialflag, ulong);
 
612
 
 
613
        GET_SYM2("?system_charset_info@@3PEAUcharset_info_st@@EA",
 
614
                 "?system_charset_info@@3PAUcharset_info_st@@A",
 
615
                 wdl_system_charset_info, CHARSET_INFO*);
 
616
        GET_SYM2("?mysql_data_home@@3PEADEA",
 
617
                 "?mysql_data_home@@3PADA",
 
618
                 wdl_mysql_data_home, char*);
 
619
        GET_SYM2("?tx_isolation_names@@3PAPEBDA",
 
620
                 "?tx_isolation_names@@3PAPBDA",
 
621
                 wdl_tx_isolation_names, char*);
 
622
        GET_SYM2("?binlog_format_names@@3PAPEBDA",
 
623
                 "?binlog_format_names@@3PAPBDA",
 
624
                 wdl_binlog_format_names, char*);
 
625
 
 
626
        /* It is fine if builtin_innobase_plugin is not available. */
 
627
        builtin_innobase_plugin_ptr = (struct st_mysql_plugin*)
 
628
                wdl_get_varaddr_from_map(
 
629
                        hmod,
 
630
                        "?builtin_innobase_plugin@@3PAUst_mysql_plugin@@A");
 
631
 
 
632
#ifndef DBUG_OFF
 
633
        GET_PROC_ADDR(_db_enter_);
 
634
        GET_PROC_ADDR(_db_return_);
 
635
        GET_PROC_ADDR(_db_pargs_);
 
636
        GET_PROC_ADDR(_db_doprnt_);
 
637
        GET_PROC_ADDR(_db_dump_);
 
638
 
 
639
        /* If any of the dbug functions is not available, just make them
 
640
        all invalid. This is the case when working with a non-debug
 
641
        version of the server. */
 
642
        if (wdl_db_enter_ == NULL || wdl_db_return_ == NULL
 
643
            || wdl_db_pargs_ == NULL || wdl_db_doprnt_ == NULL
 
644
            || wdl_db_dump_ == NULL) {
 
645
 
 
646
                wdl_db_enter_ = NULL;
 
647
                wdl_db_return_ = NULL;
 
648
                wdl_db_pargs_ = NULL;
 
649
                wdl_db_doprnt_ = NULL;
 
650
                wdl_db_dump_ = NULL;
 
651
        }
 
652
#endif /* !DBUG_OFF */
 
653
 
 
654
        wdl_init = TRUE;
 
655
        return(TRUE);
 
656
 
 
657
#undef GET_SYM
 
658
#undef GET_SYM2
 
659
#undef GET_C_SYM
 
660
#undef GET_PROC_ADDR
 
661
}
 
662
 
 
663
/***********************************************************************
 
664
The DLL Delayed Loading Helper Function for resolving externals.
 
665
 
 
666
The function may fail due to one of the three reasons:
 
667
 
 
668
* Invalid parameter, which happens if the attributes in pidd aren't
 
669
  specified correctly.
 
670
* Failed to load the map file mysqld.map.
 
671
* Failed to find an external name in the map file mysqld.map.
 
672
 
 
673
Note: this function is called by run-time as well as __HrLoadAllImportsForDll.
 
674
So, it has to follow Windows call convention. */
 
675
extern "C"
 
676
FARPROC WINAPI
 
677
__delayLoadHelper2(
 
678
/*===============*/
 
679
                                        /* out: the address of the imported
 
680
                                        function*/
 
681
        PCImgDelayDescr pidd,           /* in: a const pointer to a
 
682
                                        ImgDelayDescr, see delayimp.h. */
 
683
        FARPROC*        iat_entry)      /* in/out: A pointer to the slot in
 
684
                                        the delay load import address table
 
685
                                        to be updated with the address of the
 
686
                                        imported function. */
 
687
{
 
688
        ulint           iIAT, iINT;
 
689
        HMODULE         hmod;
 
690
        PCImgThunkData  pitd;
 
691
        FARPROC         fun = NULL;
 
692
 
 
693
        /* Set up data used for the hook procs  */
 
694
        InternalImgDelayDescr   idd = {
 
695
                                pidd->grAttrs,
 
696
                                PFromRva<LPCSTR>(pidd->rvaDLLName),
 
697
                                PFromRva<HMODULE*>(pidd->rvaHmod),
 
698
                                PFromRva<PImgThunkData>(pidd->rvaIAT),
 
699
                                PFromRva<PCImgThunkData>(pidd->rvaINT),
 
700
                                PFromRva<PCImgThunkData>(pidd->rvaBoundIAT),
 
701
                                PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT),
 
702
                                pidd->dwTimeStamp
 
703
        };
 
704
 
 
705
        DelayLoadInfo           dli = {
 
706
                                sizeof(DelayLoadInfo),
 
707
                                pidd,
 
708
                                iat_entry,
 
709
                                idd.szName,
 
710
                                {0},
 
711
                                0,
 
712
                                0,
 
713
                                0
 
714
        };
 
715
 
 
716
        /* Check the Delay Load Attributes, log an error of invalid
 
717
        parameter, which happens if the attributes in pidd are not
 
718
        specified correctly. */
 
719
        if ((idd.grAttrs & dlattrRva) == 0) {
 
720
 
 
721
                sql_print_error("InnoDB: invalid parameter for delay loader.");
 
722
                return(0);
 
723
        }
 
724
 
 
725
        hmod = *idd.phmod;
 
726
 
 
727
        /* Calculate the index for the IAT entry in the import address table.
 
728
        The INT entries are ordered the same as the IAT entries so the
 
729
        calculation can be done on the IAT side. */
 
730
        iIAT = (PCImgThunkData) iat_entry - idd.pIAT;
 
731
        iINT = iIAT;
 
732
 
 
733
        pitd = &(idd.pINT[iINT]);
 
734
 
 
735
        dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal);
 
736
 
 
737
        if (dli.dlp.fImportByName) {
 
738
 
 
739
                dli.dlp.szProcName = (LPCSTR) (PFromRva<PIMAGE_IMPORT_BY_NAME>
 
740
                        ((RVA) ((UINT_PTR) pitd->u1.AddressOfData))->Name);
 
741
        } else {
 
742
 
 
743
                dli.dlp.dwOrdinal = (ulint) IMAGE_ORDINAL(pitd->u1.Ordinal);
 
744
        }
 
745
 
 
746
        /* Now, load the mapfile, if it has not been done yet */
 
747
        if (hmod == 0) {
 
748
 
 
749
                hmod = wdl_get_mysqld_mapfile();
 
750
        }
 
751
 
 
752
        if (hmod == 0) {
 
753
                /* LoadLibrary failed. */
 
754
                PDelayLoadInfo  rgpdli[1] = {&dli};
 
755
 
 
756
                dli.dwLastError = ::GetLastError();
 
757
 
 
758
                sql_print_error(
 
759
                        "InnoDB: failed to load mysqld.map with error %d.",
 
760
                        dli.dwLastError);
 
761
 
 
762
                return(0);
 
763
        }
 
764
 
 
765
        /* Store the library handle. */
 
766
        idd.phmod = &hmod;
 
767
 
 
768
        /* Go for the procedure now. */
 
769
        dli.hmodCur = hmod;
 
770
 
 
771
        if (pidd->rvaBoundIAT && pidd->dwTimeStamp) {
 
772
 
 
773
                /* Bound imports exist, check the timestamp from the target
 
774
                image */
 
775
                PIMAGE_NT_HEADERS       pinh;
 
776
 
 
777
                pinh = (PIMAGE_NT_HEADERS) ((byte*) hmod
 
778
                                + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew);
 
779
 
 
780
                if (pinh->Signature == IMAGE_NT_SIGNATURE
 
781
                    && pinh->FileHeader.TimeDateStamp == idd.dwTimeStamp
 
782
                    && (DWORD) hmod == pinh->OptionalHeader.ImageBase) {
 
783
 
 
784
                        /* We have a decent address in the bound IAT. */
 
785
                        fun = (FARPROC) (UINT_PTR)
 
786
                                        idd.pBoundIAT[iIAT].u1.Function;
 
787
 
 
788
                        if (fun) {
 
789
 
 
790
                                *iat_entry = fun;
 
791
                                return(fun);
 
792
                        }
 
793
                }
 
794
        }
 
795
 
 
796
        fun = wdl_get_procaddr_from_map(hmod, dli.dlp.szProcName);
 
797
 
 
798
        if (fun == 0) {
 
799
 
 
800
                return(0);
 
801
        }
 
802
 
 
803
        *iat_entry = fun;
 
804
        return(fun);
 
805
}
 
806
 
 
807
/***********************************************************************
 
808
Unload a DLL that was delay loaded. This function is called by run-time. */
 
809
extern "C"
 
810
BOOL WINAPI
 
811
__FUnloadDelayLoadedDLL2(
 
812
/*=====================*/
 
813
                                /* out: TRUE is returned if the DLL is found
 
814
                                and the IAT matches the original one. */
 
815
        LPCSTR  module_name)    /* in: DLL name */
 
816
{
 
817
        return(TRUE);
 
818
}
 
819
 
 
820
/******************************************************************
 
821
Load all imports from a DLL that was specified with the /delayload linker
 
822
option.
 
823
Note: this function is called by run-time. So, it has to follow Windows call
 
824
convention. */
 
825
extern "C"
 
826
HRESULT WINAPI
 
827
__HrLoadAllImportsForDll(
 
828
/*=====================*/
 
829
                                /* out: S_OK if the DLL matches, otherwise
 
830
                                ERROR_MOD_NOT_FOUND is returned. */
 
831
        LPCSTR  module_name)    /* in: DLL name */
 
832
{
 
833
        PIMAGE_NT_HEADERS       img;
 
834
        PCImgDelayDescr         pidd;
 
835
        IMAGE_DATA_DIRECTORY*   image_data;
 
836
        LPCSTR                  current_module;
 
837
        HRESULT                 ret = ERROR_MOD_NOT_FOUND;
 
838
        HMODULE                 hmod = (HMODULE) &__ImageBase;
 
839
 
 
840
        img = (PIMAGE_NT_HEADERS) ((byte*) hmod
 
841
                                   + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew);
 
842
        image_data =
 
843
         &img->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
 
844
 
 
845
        /* Scan the delay load IAT/INT for the DLL */
 
846
        if (image_data->Size) {
 
847
 
 
848
                pidd = PFromRva<PCImgDelayDescr>(image_data->VirtualAddress);
 
849
 
 
850
                /* Check all of the listed DLLs we want to load. */
 
851
                while (pidd->rvaDLLName) {
 
852
 
 
853
                        current_module = PFromRva<LPCSTR>(pidd->rvaDLLName);
 
854
 
 
855
                        if (stricmp(module_name, current_module) == 0) {
 
856
 
 
857
                                /* Found it, break out with pidd and
 
858
                                current_module set appropriately */
 
859
                                break;
 
860
                        }
 
861
 
 
862
                        /* To the next delay import descriptor */
 
863
                        pidd++;
 
864
                }
 
865
 
 
866
                if (pidd->rvaDLLName) {
 
867
 
 
868
                        /* Found a matching DLL, now process it. */
 
869
                        FARPROC*        iat_entry;
 
870
                        size_t          count;
 
871
 
 
872
                        iat_entry = PFromRva<FARPROC*>(pidd->rvaIAT);
 
873
                        count = wdl_import_count((PCImgThunkData) iat_entry);
 
874
 
 
875
                        /* now load all the imports from the DLL */
 
876
                        while (count > 0) {
 
877
 
 
878
                                /* No need to check the return value */
 
879
                                __delayLoadHelper2(pidd, iat_entry);
 
880
                                iat_entry++;
 
881
                                count--;
 
882
                        }
 
883
 
 
884
                        ret = S_OK;
 
885
                }
 
886
        }
 
887
 
 
888
        return ret;
 
889
}
 
890
 
 
891
/******************************************************************
 
892
The main function of a DLL */
 
893
BOOL
 
894
WINAPI
 
895
DllMain(
 
896
/*====*/
 
897
                                        /* out: TRUE if the call succeeds */
 
898
        HINSTANCE       hinstDLL,       /* in: handle to the DLL module */
 
899
        DWORD           fdwReason,      /* Reason code that indicates why the
 
900
                                        DLL entry-point function is being
 
901
                                        called.*/
 
902
        LPVOID          lpvReserved)    /* in: additional parameter based on
 
903
                                        fdwReason */
 
904
{
 
905
        BOOL    success = TRUE;
 
906
 
 
907
        switch (fdwReason) {
 
908
 
 
909
        case DLL_PROCESS_ATTACH:
 
910
                success = wdl_get_external_variables();
 
911
                break;
 
912
 
 
913
        case DLL_PROCESS_DETACH:
 
914
                wdl_cleanup();
 
915
                break;
 
916
        }
 
917
 
 
918
        return(success);
 
919
}
 
920
 
 
921
#ifndef DBUG_OFF
 
922
/******************************************************************
 
923
Process entry point to user function. It makes the call to _db_enter_
 
924
in mysqld.exe. The DBUG functions are defined in my_dbug.h. */
 
925
extern "C" UNIV_INTERN
 
926
void
 
927
_db_enter_(
 
928
        const char*     _func_,         /* in: current function name */
 
929
        const char*     _file_,         /* in: current file name */
 
930
        uint            _line_,         /* in: current source line number */
 
931
        const char**    _sfunc_,        /* out: previous _func_ */
 
932
        const char**    _sfile_,        /* out: previous _file_ */
 
933
        uint*           _slevel_,       /* out: previous nesting level */
 
934
        char***         _sframep_)      /* out: previous frame pointer */
 
935
{
 
936
        if (wdl_db_enter_ != NULL) {
 
937
 
 
938
                wdl_db_enter_(_func_, _file_, _line_, _sfunc_, _sfile_,
 
939
                              _slevel_, _sframep_);
 
940
        }
 
941
}
 
942
 
 
943
/******************************************************************
 
944
Process exit from user function. It makes the call to _db_return_()
 
945
in the server. */
 
946
extern "C" UNIV_INTERN
 
947
void
 
948
_db_return_(
 
949
        uint            _line_,         /* in: current source line number */
 
950
        const char**    _sfunc_,        /* out: previous _func_ */
 
951
        const char**    _sfile_,        /* out: previous _file_ */
 
952
        uint*           _slevel_)       /* out: previous level */
 
953
{
 
954
        if (wdl_db_return_ != NULL) {
 
955
 
 
956
                wdl_db_return_(_line_, _sfunc_, _sfile_, _slevel_);
 
957
        }
 
958
}
 
959
 
 
960
/******************************************************************
 
961
Log arguments for subsequent use. It makes the call to _db_pargs_()
 
962
in the server. */
 
963
extern "C" UNIV_INTERN
 
964
void
 
965
_db_pargs_(
 
966
        uint            _line_,         /* in: current source line number */
 
967
        const char*     keyword)        /* in: keyword for current macro */
 
968
{
 
969
        if (wdl_db_pargs_ != NULL) {
 
970
 
 
971
                wdl_db_pargs_(_line_, keyword);
 
972
        }
 
973
}
 
974
 
 
975
/******************************************************************
 
976
Handle print of debug lines. It saves the text into a buffer first,
 
977
then makes the call to _db_doprnt_() in the server. The text is
 
978
truncated to the size of buffer. */
 
979
extern "C" UNIV_INTERN
 
980
void
 
981
_db_doprnt_(
 
982
        const char*     format,         /* in: the format string */
 
983
        ...)                            /* in: list of arguments */
 
984
{
 
985
        va_list         argp;
 
986
        char            buffer[512];
 
987
 
 
988
        if (wdl_db_doprnt_ != NULL) {
 
989
 
 
990
                va_start(argp, format);
 
991
                /* it is ok to ignore the trunction. */
 
992
                _vsnprintf(buffer, sizeof(buffer), format, argp);
 
993
                wdl_db_doprnt_(buffer);
 
994
                va_end(argp);
 
995
        }
 
996
}
 
997
 
 
998
/******************************************************************
 
999
Dump a string in hex. It makes the call to _db_dump_() in the server. */
 
1000
extern "C" UNIV_INTERN
 
1001
void
 
1002
_db_dump_(
 
1003
        uint                    _line_,         /* in: current source line
 
1004
                                                number */
 
1005
        const char*             keyword,        /* in: keyword list */
 
1006
        const unsigned char*    memory,         /* in: memory to dump */
 
1007
        size_t                  length)         /* in: bytes to dump */
 
1008
{
 
1009
        if (wdl_db_dump_ != NULL) {
 
1010
 
 
1011
                wdl_db_dump_(_line_, keyword, memory, length);
 
1012
        }
 
1013
}
 
1014
 
 
1015
#endif /* !DBUG_OFF */
 
1016
#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */