~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
19
/*******************************************************************//**
20
@file handler/win_delay_loader.cc
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
52
/*******************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
75
/*******************************************************************//**
76
The preferred load-address defined in PE (portable executable format). */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
87
/*******************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
91
VAs to RVAs to work on both 32- and 64-bit platforms.
92
@return	absolute virtual address */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
93
template <class X>
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
94
X PFromRva(
95
/*=======*/
96
	RVA	rva)	/*!< in: relative virtual address */
97
{
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
98
	return X(PBYTE(&__ImageBase) + rva);
99
}
100
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
101
/*******************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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. */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
113
					   original IAT */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
114
	DWORD		dwTimeStamp;	/*!< 0 if not bound,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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 {
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
125
					in the same folder. */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
126
	map_hash_chain_t*	chain;	/*!< a linear chain used for
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
137
/*******************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
146
The plugin will get those function pointers during the initialization. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
183
/*************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
189
initialized, and buffer pools are not ready yet.
190
@return	own: created hash table */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
191
static
192
hash_table_t*
193
wdl_hash_create(
194
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
195
	ulint	n)	/*!< in: number of array cells */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
228
/*************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
229
Frees a hash table. */
230
static
231
void
232
wdl_hash_table_free(
233
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
234
	hash_table_t*	table)	/*!< in, own: hash table */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
235
{
236
	ut_a(table != NULL);
237
	ut_a(table->mutexes == NULL);
238
239
	free(table->array);
240
	free(table);
241
}
242
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
243
/*******************************************************************//**
244
Function for calculating the count of imports given the base of the IAT.
245
@return	number of imports */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
246
static
247
ulint
248
wdl_import_count(
249
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
250
	PCImgThunkData	pitd_base)	/*!< in: base of the IAT */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
263
/*******************************************************************//**
264
Read Mapfile to a hashtable for faster access
265
@return	TRUE if the mapfile is loaded successfully. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
266
static
267
ibool
268
wdl_load_mapfile(
269
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
270
	const char*	filename)	/*!< in: name of the mapfile. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
358
			map_cell->value = (ulint) _strtoui64(tmp_buf, NULL, 0)
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
375
/*************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
397
/*******************************************************************//**
398
Load the mapfile mysqld.map.
399
@return	the module handle */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
447
/*******************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
448
Retrieves the address of an exported function. It follows the convention
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
449
of GetProcAddress().
450
@return	address of exported function. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
451
static
452
FARPROC
453
wdl_get_procaddr_from_map(
454
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
455
	HANDLE		m_handle,	/*!< in: module handle */
456
	const char*	import_proc)	/*!< in: procedure name */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
468
		,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
488
			,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
489
			(ut_strcmp(hash_chain->symbol, import_proc) == 0));
490
491
		if (hash_chain == NULL) {
492
#endif
493
			if (wdl_init == TRUE) {
494
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
495
				errmsg_printf(ERRMSG_LVL_ERROR, 
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
510
/*******************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
511
Retrieves the address of an exported variable.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
512
Note: It does not follow the Windows call convention FARPROC.
513
@return	address of exported variable. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
514
static
515
void*
516
wdl_get_varaddr_from_map(
517
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
518
	HANDLE		m_handle,		/*!< in: module handle */
519
	const char*	import_variable)	/*!< in: variable name */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
531
		,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
551
			,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
552
			(ut_strcmp(hash_chain->symbol, import_variable) == 0));
553
554
		if (hash_chain == NULL) {
555
#endif
556
			if (wdl_init == TRUE) {
557
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
558
				errmsg_printf(ERRMSG_LVL_ERROR, 
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
573
/*******************************************************************//**
574
Bind all unresolved external variables from the MySQL executable.
575
@return	TRUE if successful */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
669
/*******************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
680
So, it has to follow Windows call convention.
681
@return	the address of the imported function */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
682
extern "C"
683
FARPROC WINAPI
684
__delayLoadHelper2(
685
/*===============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
686
	PCImgDelayDescr	pidd,		/*!< in: a const pointer to a
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
687
					ImgDelayDescr, see delayimp.h. */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
688
	FARPROC*	iat_entry)	/*!< in/out: A pointer to the slot in
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
726
		errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid parameter for delay loader.");
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
763
		errmsg_printf(ERRMSG_LVL_ERROR, 
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
816
extern "C"
817
BOOL WINAPI
818
__FUnloadDelayLoadedDLL2(
819
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
820
	LPCSTR	module_name)	/*!< in: DLL name */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
821
{
822
	return(TRUE);
823
}
824
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
825
/**************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
829
convention.
830
@return	S_OK if the DLL matches, otherwise ERROR_MOD_NOT_FOUND is returned. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
831
extern "C"
832
HRESULT WINAPI
833
__HrLoadAllImportsForDll(
834
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
835
	LPCSTR	module_name)	/*!< in: DLL name */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
895
/**************************************************************//**
896
The main function of a DLL
897
@return	TRUE if the call succeeds */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
898
BOOL
899
WINAPI
900
DllMain(
901
/*====*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
902
	HINSTANCE	hinstDLL,	/*!< in: handle to the DLL module */
903
	DWORD		fdwReason,	/*!< Reason code that indicates why the
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
904
					DLL entry-point function is being
905
					called.*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
906
	LPVOID		lpvReserved)	/*!< in: additional parameter based on
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
926
/**************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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_(
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
939
{
940
	if (wdl_db_enter_ != NULL) {
941
942
		wdl_db_enter_(_func_, _file_, _line_, _sfunc_, _sfile_,
943
			      _slevel_, _sframep_);
944
	}
945
}
946
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
947
/**************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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_(
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
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 */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
957
{
958
	if (wdl_db_return_ != NULL) {
959
960
		wdl_db_return_(_line_, _sfunc_, _sfile_, _slevel_);
961
	}
962
}
963
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
964
/**************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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_(
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
970
	uint		_line_,		/*!< in: current source line number */
971
	const char*	keyword)	/*!< in: keyword for current macro */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
972
{
973
	if (wdl_db_pargs_ != NULL) {
974
975
		wdl_db_pargs_(_line_, keyword);
976
	}
977
}
978
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
979
/**************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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_(
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
986
	const char*	format,		/*!< in: the format string */
987
	...)				/*!< in: list of arguments */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1002
/**************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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_(
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1007
	uint			_line_,		/*!< in: current source line
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1008
						number */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1009
	const char*		keyword,	/*!< in: keyword list */
1010
	const unsigned char*	memory,		/*!< in: memory to dump */
1011
	size_t			length)		/*!< in: bytes to dump */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
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) */