~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2009-03-22 08:04:21 UTC
  • mto: (960.5.2 mordred)
  • mto: This revision was merged to the branch mainline in revision 961.
  • Revision ID: mordred@inaugust.com-20090322080421-xkfmhsstf51vvazm
Moved innodb handler code back to handler/ dir.

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
 
                                errmsg_printf(ERRMSG_LVL_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
 
                                errmsg_printf(ERRMSG_LVL_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
 
                errmsg_printf(ERRMSG_LVL_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
 
                errmsg_printf(ERRMSG_LVL_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) */