~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-10-02 14:17:48 UTC
  • mfrom: (1.1.1 upstream)
  • mto: (2.1.17 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20101002141748-m6vbfbfjhrw1153e
Tags: 2010.09.1802-1
* New upstream release.
* Removed pid-file argument hack.
* Updated GPL-2 address to be new address.
* Directly copy in drizzledump.1 since debian doesn't have sphinx 1.0 yet.
* Link to jquery from libjs-jquery. Add it as a depend.
* Add drizzled.8 symlink to the install files.

Show diffs side-by-side

added added

removed removed

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