blob: e157ca953e907701d4c6468e5a514058e2c7582c [file] [log] [blame]
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001/*
2 * Selector manipulation functions
3 *
4 * Copyright 1995 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000019 */
20
Francois Gougete5ddd262001-10-14 16:18:52 +000021#include "config.h"
Alexandre Julliard894b1882002-04-25 21:40:56 +000022#include "wine/port.h"
Francois Gougete5ddd262001-10-14 16:18:52 +000023
Alexandre Julliardfa68b751995-04-03 16:55:37 +000024#include <string.h>
Dimitrie O. Paun0b7a7bb2000-11-25 01:31:17 +000025
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +000026#include "winerror.h"
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000027#include "wine/winbase16.h"
Alexandre Julliard37e95032001-07-19 00:39:09 +000028#include "wine/server.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000029#include "wine/debug.h"
Alexandre Julliarda7ce2ab2003-11-18 00:16:25 +000030#include "kernel_private.h"
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000031#include "toolhelp.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000032
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000033WINE_DEFAULT_DEBUG_CHANNEL(selector);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000034
Alexandre Julliard914406f2000-11-14 01:54:49 +000035#define LDT_SIZE 8192
36
37/* get the number of selectors needed to cover up to the selector limit */
38inline static WORD get_sel_count( WORD sel )
39{
40 return (wine_ldt_copy.limit[sel >> __AHSHIFT] >> 16) + 1;
41}
42
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000043
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000044/***********************************************************************
45 * AllocSelectorArray (KERNEL.206)
46 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000047WORD WINAPI AllocSelectorArray16( WORD count )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000048{
Alexandre Julliardce131532003-02-26 20:34:45 +000049 WORD i, sel = wine_ldt_alloc_entries( count );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000050
Alexandre Julliard914406f2000-11-14 01:54:49 +000051 if (sel)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000052 {
Alexandre Julliard914406f2000-11-14 01:54:49 +000053 LDT_ENTRY entry;
54 wine_ldt_set_base( &entry, 0 );
55 wine_ldt_set_limit( &entry, 1 ); /* avoid 0 base and limit */
56 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_DATA );
57 for (i = 0; i < count; i++) wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000058 }
Alexandre Julliard914406f2000-11-14 01:54:49 +000059 return sel;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000060}
61
62
63/***********************************************************************
64 * AllocSelector (KERNEL.175)
65 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000066WORD WINAPI AllocSelector16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000067{
68 WORD newsel, count, i;
69
Alexandre Julliard914406f2000-11-14 01:54:49 +000070 count = sel ? get_sel_count(sel) : 1;
Alexandre Julliardce131532003-02-26 20:34:45 +000071 newsel = wine_ldt_alloc_entries( count );
Alexandre Julliard914406f2000-11-14 01:54:49 +000072 TRACE("(%04x): returning %04x\n", sel, newsel );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000073 if (!newsel) return 0;
74 if (!sel) return newsel; /* nothing to copy */
75 for (i = 0; i < count; i++)
76 {
Alexandre Julliard914406f2000-11-14 01:54:49 +000077 LDT_ENTRY entry;
78 wine_ldt_get_entry( sel + (i << __AHSHIFT), &entry );
79 wine_ldt_set_entry( newsel + (i << __AHSHIFT), &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000080 }
81 return newsel;
82}
83
84
85/***********************************************************************
86 * FreeSelector (KERNEL.176)
87 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000088WORD WINAPI FreeSelector16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000089{
Alexandre Julliardce131532003-02-26 20:34:45 +000090 LDT_ENTRY entry;
Alexandre Julliard914406f2000-11-14 01:54:49 +000091
Alexandre Julliardce131532003-02-26 20:34:45 +000092 wine_ldt_get_entry( sel, &entry );
93 if (wine_ldt_is_empty( &entry )) return sel; /* error */
Alexandre Julliard914406f2000-11-14 01:54:49 +000094#ifdef __i386__
Alexandre Julliardce131532003-02-26 20:34:45 +000095 /* Check if we are freeing current %fs selector */
Alexandre Julliard4ced7ef2002-08-14 21:10:50 +000096 if (!((wine_get_fs() ^ sel) & ~3))
Alexandre Julliard59008672002-05-16 20:32:16 +000097 WARN("Freeing %%fs selector (%04x), not good.\n", wine_get_fs() );
Alexandre Julliard914406f2000-11-14 01:54:49 +000098#endif /* __i386__ */
Alexandre Julliardce131532003-02-26 20:34:45 +000099 wine_ldt_free_entries( sel, 1 );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000100 return 0;
101}
102
103
104/***********************************************************************
105 * SELECTOR_SetEntries
106 *
107 * Set the LDT entries for an array of selectors.
108 */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000109static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000110{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000111 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000112 WORD i, count;
113
Alexandre Julliard914406f2000-11-14 01:54:49 +0000114 wine_ldt_set_base( &entry, base );
Alexandre Julliard4ced7ef2002-08-14 21:10:50 +0000115 wine_ldt_set_limit( &entry, size - 1 );
Andreas Mohr757e7cb2002-05-08 00:20:40 +0000116 wine_ldt_set_flags( &entry, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000117 count = (size + 0xffff) / 0x10000;
118 for (i = 0; i < count; i++)
119 {
Alexandre Julliard914406f2000-11-14 01:54:49 +0000120 wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
Gregg Mattinson7c4cb512002-07-03 21:10:43 +0000121 wine_ldt_set_base( &entry, (char*)wine_ldt_get_base(&entry) + 0x10000);
Andreas Mohr757e7cb2002-05-08 00:20:40 +0000122 /* yep, Windows sets limit like that, not 64K sel units */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000123 wine_ldt_set_limit( &entry, wine_ldt_get_limit(&entry) - 0x10000 );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000124 }
125}
126
127
128/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000129 * SELECTOR_AllocBlock
130 *
131 * Allocate selectors for a block of linear memory.
132 */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000133WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000134{
135 WORD sel, count;
136
137 if (!size) return 0;
138 count = (size + 0xffff) / 0x10000;
Alexandre Julliardce131532003-02-26 20:34:45 +0000139 sel = wine_ldt_alloc_entries( count );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000140 if (sel) SELECTOR_SetEntries( sel, base, size, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000141 return sel;
142}
143
144
145/***********************************************************************
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000146 * SELECTOR_FreeBlock
147 *
148 * Free a block of selectors.
149 */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000150void SELECTOR_FreeBlock( WORD sel )
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000151{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000152 WORD i, count = get_sel_count( sel );
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000153
Alexandre Julliard15657091999-05-23 10:25:25 +0000154 TRACE("(%04x,%d)\n", sel, count );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000155 for (i = 0; i < count; i++) FreeSelector16( sel + (i << __AHSHIFT) );
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000156}
157
158
159/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000160 * SELECTOR_ReallocBlock
161 *
162 * Change the size of a block of selectors.
163 */
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000164WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000165{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000166 LDT_ENTRY entry;
Alexandre Julliardce131532003-02-26 20:34:45 +0000167 int oldcount, newcount;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000168
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000169 if (!size) size = 1;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000170 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000171 oldcount = (wine_ldt_get_limit(&entry) >> 16) + 1;
172 newcount = (size + 0xffff) >> 16;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000173
Alexandre Julliardce131532003-02-26 20:34:45 +0000174 sel = wine_ldt_realloc_entries( sel, oldcount, newcount );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000175 if (sel) SELECTOR_SetEntries( sel, base, size, wine_ldt_get_flags(&entry) );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000176 return sel;
177}
178
179
180/***********************************************************************
181 * PrestoChangoSelector (KERNEL.177)
182 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000183WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000184{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000185 LDT_ENTRY entry;
186 wine_ldt_get_entry( selSrc, &entry );
187 /* toggle the executable bit */
188 entry.HighWord.Bits.Type ^= (WINE_LDT_FLAGS_CODE ^ WINE_LDT_FLAGS_DATA);
189 wine_ldt_set_entry( selDst, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000190 return selDst;
191}
192
193
194/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000195 * AllocCStoDSAlias (KERNEL.170)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000196 * AllocAlias (KERNEL.172)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000197 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000198WORD WINAPI AllocCStoDSAlias16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000199{
200 WORD newsel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000201 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000202
Alexandre Julliardce131532003-02-26 20:34:45 +0000203 newsel = wine_ldt_alloc_entries( 1 );
Alexandre Julliard15657091999-05-23 10:25:25 +0000204 TRACE("(%04x): returning %04x\n",
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000205 sel, newsel );
206 if (!newsel) return 0;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000207 wine_ldt_get_entry( sel, &entry );
208 entry.HighWord.Bits.Type = WINE_LDT_FLAGS_DATA;
209 wine_ldt_set_entry( newsel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000210 return newsel;
211}
212
213
214/***********************************************************************
215 * AllocDStoCSAlias (KERNEL.171)
216 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000217WORD WINAPI AllocDStoCSAlias16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000218{
219 WORD newsel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000220 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000221
Alexandre Julliardce131532003-02-26 20:34:45 +0000222 newsel = wine_ldt_alloc_entries( 1 );
Alexandre Julliard15657091999-05-23 10:25:25 +0000223 TRACE("(%04x): returning %04x\n",
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000224 sel, newsel );
225 if (!newsel) return 0;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000226 wine_ldt_get_entry( sel, &entry );
227 entry.HighWord.Bits.Type = WINE_LDT_FLAGS_CODE;
228 wine_ldt_set_entry( newsel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000229 return newsel;
230}
231
232
233/***********************************************************************
234 * LongPtrAdd (KERNEL.180)
235 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000236void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000237{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000238 LDT_ENTRY entry;
239 wine_ldt_get_entry( SELECTOROF(ptr), &entry );
240 wine_ldt_set_base( &entry, (char *)wine_ldt_get_base(&entry) + add );
241 wine_ldt_set_entry( SELECTOROF(ptr), &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000242}
243
244
245/***********************************************************************
Jukka Heinonen56dff0d2002-11-20 19:40:12 +0000246 * GetSelectorBase (KERNEL.186)
Patrik Stridvallb5bb32c2002-09-24 18:29:39 +0000247 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000248DWORD WINAPI GetSelectorBase( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000249{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000250 void *base = wine_ldt_copy.base[sel >> __AHSHIFT];
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000251
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000252 /* if base points into DOSMEM, assume we have to
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000253 * return pointer into physical lower 1MB */
254
Alexandre Julliard914406f2000-11-14 01:54:49 +0000255 return DOSMEM_MapLinearToDos( base );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000256}
257
258
259/***********************************************************************
Jukka Heinonen56dff0d2002-11-20 19:40:12 +0000260 * SetSelectorBase (KERNEL.187)
Patrik Stridvallb5bb32c2002-09-24 18:29:39 +0000261 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000262WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000263{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000264 LDT_ENTRY entry;
265 wine_ldt_get_entry( sel, &entry );
266 wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
267 wine_ldt_set_entry( sel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000268 return sel;
269}
270
271
272/***********************************************************************
273 * GetSelectorLimit (KERNEL.188)
274 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000275DWORD WINAPI GetSelectorLimit16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000276{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000277 return wine_ldt_copy.limit[sel >> __AHSHIFT];
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000278}
279
280
281/***********************************************************************
282 * SetSelectorLimit (KERNEL.189)
283 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000284WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000285{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000286 LDT_ENTRY entry;
287 wine_ldt_get_entry( sel, &entry );
288 wine_ldt_set_limit( &entry, limit );
289 wine_ldt_set_entry( sel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000290 return sel;
291}
292
293
294/***********************************************************************
295 * SelectorAccessRights (KERNEL.196)
296 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000297WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000298{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000299 LDT_ENTRY entry;
300 wine_ldt_get_entry( sel, &entry );
301
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000302 if (op == 0) /* get */
303 {
Alexandre Julliard914406f2000-11-14 01:54:49 +0000304 return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 << 8) & 0xf0);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000305 }
306 else /* set */
307 {
Alexandre Julliard914406f2000-11-14 01:54:49 +0000308 entry.HighWord.Bytes.Flags1 = LOBYTE(val) | 0xf0;
309 entry.HighWord.Bytes.Flags2 = (entry.HighWord.Bytes.Flags2 & 0x0f) | (HIBYTE(val) & 0xf0);
310 wine_ldt_set_entry( sel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000311 return 0;
312 }
313}
314
315
316/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000317 * IsBadCodePtr (KERNEL.336)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000318 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000319BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000320{
321 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000322 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000323
324 sel = SELECTOROF(lpfn);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000325 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000326 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000327 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000328 /* check for code segment, ignoring conforming, read-only and accessed bits */
329 if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_CODE) & 0x18) return TRUE;
330 if (OFFSETOF(lpfn) > wine_ldt_get_limit(&entry)) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000331 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000332}
333
334
335/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000336 * IsBadStringPtr (KERNEL.337)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000337 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000338BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000339{
340 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000341 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000342
343 sel = SELECTOROF(ptr);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000344 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000345 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000346 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000347 /* check for data or readable code segment */
348 if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
349 if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
Alexandre Julliard982a2232000-12-13 20:20:09 +0000350 if (strlen(MapSL(ptr)) < size) size = strlen(MapSL(ptr)) + 1;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000351 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit(&entry))) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000352 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000353}
354
355
356/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000357 * IsBadHugeReadPtr (KERNEL.346)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000358 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000359BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000360{
361 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000362 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000363
364 sel = SELECTOROF(ptr);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000365 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000366 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000367 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000368 /* check for data or readable code segment */
369 if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
370 if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
371 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000372 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000373}
374
375
376/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000377 * IsBadHugeWritePtr (KERNEL.347)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000378 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000379BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000380{
381 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000382 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000383
384 sel = SELECTOROF(ptr);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000385 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000386 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000387 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000388 /* check for writeable data segment, ignoring expand-down and accessed flags */
389 if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
390 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000391 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000392}
393
394/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000395 * IsBadReadPtr (KERNEL.334)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000396 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000397BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000398{
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000399 return IsBadHugeReadPtr16( ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000400}
401
402
403/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000404 * IsBadWritePtr (KERNEL.335)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000405 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000406BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000407{
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000408 return IsBadHugeWritePtr16( ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000409}
410
411
412/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000413 * IsBadFlatReadWritePtr (KERNEL.627)
Ulrich Weigand98b5f771999-07-27 17:09:14 +0000414 */
415BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
416{
417 return bWrite? IsBadHugeWritePtr16( ptr, size )
418 : IsBadHugeReadPtr16( ptr, size );
419}
420
421
422/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000423 * MemoryRead (TOOLHELP.78)
424 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000425DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000426{
Alexandre Julliardce131532003-02-26 20:34:45 +0000427 LDT_ENTRY entry;
428 DWORD limit;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000429
Alexandre Julliardce131532003-02-26 20:34:45 +0000430 wine_ldt_get_entry( sel, &entry );
431 if (wine_ldt_is_empty( &entry )) return 0;
432 limit = wine_ldt_get_limit( &entry );
433 if (offset > limit) return 0;
434 if (offset + count > limit + 1) count = limit + 1 - offset;
435 memcpy( buffer, (char *)wine_ldt_get_base(&entry) + offset, count );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000436 return count;
437}
438
439
440/***********************************************************************
441 * MemoryWrite (TOOLHELP.79)
442 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000443DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000444{
Alexandre Julliardce131532003-02-26 20:34:45 +0000445 LDT_ENTRY entry;
446 DWORD limit;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000447
Alexandre Julliardce131532003-02-26 20:34:45 +0000448 wine_ldt_get_entry( sel, &entry );
449 if (wine_ldt_is_empty( &entry )) return 0;
450 limit = wine_ldt_get_limit( &entry );
451 if (offset > limit) return 0;
452 if (offset + count > limit) count = limit + 1 - offset;
453 memcpy( (char *)wine_ldt_get_base(&entry) + offset, buffer, count );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000454 return count;
455}
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000456
457/************************************* Win95 pointer mapping functions *
458 *
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000459 */
460
Alexandre Julliardb0f58612001-12-19 19:16:27 +0000461struct mapls_entry
462{
463 struct mapls_entry *next;
464 void *addr; /* linear address */
465 int count; /* ref count */
466 WORD sel; /* selector */
467};
468
469static struct mapls_entry *first_entry;
470
471
472/***********************************************************************
473 * MapLS (KERNEL32.@)
474 * MapLS (KERNEL.358)
475 *
476 * Maps linear pointer to segmented.
477 */
478SEGPTR WINAPI MapLS( LPCVOID ptr )
479{
480 struct mapls_entry *entry, *free = NULL;
Eric Pouech62a86092004-06-14 17:04:34 +0000481 const void *base;
Alexandre Julliardb0f58612001-12-19 19:16:27 +0000482 SEGPTR ret = 0;
483
Alexandre Julliardba41fe22005-09-12 21:22:32 +0000484 if (!HIWORD(ptr)) return (SEGPTR)LOWORD(ptr);
Alexandre Julliardb0f58612001-12-19 19:16:27 +0000485
Eric Pouech62a86092004-06-14 17:04:34 +0000486 base = (const char *)ptr - ((unsigned int)ptr & 0x7fff);
Alexandre Julliardb0f58612001-12-19 19:16:27 +0000487 HeapLock( GetProcessHeap() );
488 for (entry = first_entry; entry; entry = entry->next)
489 {
490 if (entry->addr == base) break;
491 if (!entry->count) free = entry;
492 }
493
494 if (!entry)
495 {
496 if (!free) /* no free entry found, create a new one */
497 {
498 if (!(free = HeapAlloc( GetProcessHeap(), 0, sizeof(*free) ))) goto done;
499 if (!(free->sel = SELECTOR_AllocBlock( base, 0x10000, WINE_LDT_FLAGS_DATA )))
500 {
501 HeapFree( GetProcessHeap(), 0, free );
502 goto done;
503 }
504 free->count = 0;
505 free->next = first_entry;
506 first_entry = free;
507 }
508 SetSelectorBase( free->sel, (DWORD)base );
Eric Pouech62a86092004-06-14 17:04:34 +0000509 free->addr = (void*)base;
Alexandre Julliardb0f58612001-12-19 19:16:27 +0000510 entry = free;
511 }
512 entry->count++;
Eric Pouech62a86092004-06-14 17:04:34 +0000513 ret = MAKESEGPTR( entry->sel, (const char *)ptr - (char *)entry->addr );
Alexandre Julliardb0f58612001-12-19 19:16:27 +0000514 done:
515 HeapUnlock( GetProcessHeap() );
516 return ret;
517}
518
519/***********************************************************************
520 * UnMapLS (KERNEL32.@)
521 * UnMapLS (KERNEL.359)
522 *
523 * Free mapped selector.
524 */
525void WINAPI UnMapLS( SEGPTR sptr )
526{
527 struct mapls_entry *entry;
528 WORD sel = SELECTOROF(sptr);
529
530 if (sel)
531 {
532 HeapLock( GetProcessHeap() );
533 for (entry = first_entry; entry; entry = entry->next) if (entry->sel == sel) break;
534 if (entry && entry->count > 0) entry->count--;
535 HeapUnlock( GetProcessHeap() );
536 }
537}
538
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000539/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000540 * MapSL (KERNEL32.@)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000541 * MapSL (KERNEL.357)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000542 *
543 * Maps fixed segmented pointer to linear.
544 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000545LPVOID WINAPI MapSL( SEGPTR sptr )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000546{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000547 return (char *)wine_ldt_copy.base[SELECTOROF(sptr) >> __AHSHIFT] + OFFSETOF(sptr);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000548}
549
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000550/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000551 * MapSLFix (KERNEL32.@)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000552 *
553 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
554 * unexpected linear address change when GlobalCompact() shuffles
555 * moveable blocks.
556 */
557
558LPVOID WINAPI MapSLFix( SEGPTR sptr )
559{
Alexandre Julliard982a2232000-12-13 20:20:09 +0000560 return MapSL(sptr);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000561}
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000562
563/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000564 * UnMapSLFixArray (KERNEL32.@)
Alexandre Julliard643463b2006-01-13 14:26:24 +0100565 *
566 * Must not change EAX, hence defined as asm function.
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000567 */
Alexandre Julliard643463b2006-01-13 14:26:24 +0100568#ifdef __i386__
569__ASM_GLOBAL_FUNC( UnMapSLFixArray, "ret $8" );
Alexandre Julliard2c7a2482005-05-07 18:25:51 +0000570#endif
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000571
Alexandre Julliard643463b2006-01-13 14:26:24 +0100572
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000573/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000574 * GetThreadSelectorEntry (KERNEL32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000575 */
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000576BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000577{
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000578#ifdef __i386__
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000579 BOOL ret;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000580
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000581 if (!(sel & 4)) /* GDT selector */
582 {
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000583 sel &= ~3; /* ignore RPL */
584 if (!sel) /* null selector */
585 {
586 memset( ldtent, 0, sizeof(*ldtent) );
587 return TRUE;
588 }
589 ldtent->BaseLow = 0;
590 ldtent->HighWord.Bits.BaseMid = 0;
591 ldtent->HighWord.Bits.BaseHi = 0;
592 ldtent->LimitLow = 0xffff;
593 ldtent->HighWord.Bits.LimitHi = 0xf;
594 ldtent->HighWord.Bits.Dpl = 3;
595 ldtent->HighWord.Bits.Sys = 0;
596 ldtent->HighWord.Bits.Pres = 1;
597 ldtent->HighWord.Bits.Granularity = 1;
598 ldtent->HighWord.Bits.Default_Big = 1;
599 ldtent->HighWord.Bits.Type = 0x12;
600 /* it has to be one of the system GDT selectors */
Alexandre Julliard59008672002-05-16 20:32:16 +0000601 if (sel == (wine_get_ds() & ~3)) return TRUE;
602 if (sel == (wine_get_ss() & ~3)) return TRUE;
603 if (sel == (wine_get_cs() & ~3))
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000604 {
605 ldtent->HighWord.Bits.Type |= 8; /* code segment */
606 return TRUE;
607 }
608 SetLastError( ERROR_NOACCESS );
609 return FALSE;
610 }
611
Alexandre Julliard67a74992001-02-27 02:09:16 +0000612 SERVER_START_REQ( get_selector_entry )
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000613 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000614 req->handle = hthread;
615 req->entry = sel >> __AHSHIFT;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000616 if ((ret = !wine_server_call_err( req )))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000617 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000618 if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000619 {
620 SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */
621 ret = FALSE;
622 }
623 else
624 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000625 wine_ldt_set_base( ldtent, (void *)reply->base );
626 wine_ldt_set_limit( ldtent, reply->limit );
627 wine_ldt_set_flags( ldtent, reply->flags );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000628 }
629 }
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000630 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000631 SERVER_END_REQ;
632 return ret;
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000633#else
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000634 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000635 return FALSE;
636#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000637}
638
639
Alexandre Julliard643463b2006-01-13 14:26:24 +0100640#ifdef __i386__
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000641
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000642/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000643 * SMapLS (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000644 */
Alexandre Julliard643463b2006-01-13 14:26:24 +0100645__ASM_GLOBAL_FUNC( SMapLS,
646 "xor %edx,%edx\n\t"
647 "testl $0xffff0000,%eax\n\t"
648 "jz 1f\n\t"
649 "pushl %eax\n\t"
650 "call " __ASM_NAME("MapLS") "\n\t"
651 "movl %eax,%edx\n"
652 "1:\tret" );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000653
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000654/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000655 * SUnMapLS (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000656 */
Alexandre Julliard643463b2006-01-13 14:26:24 +0100657__ASM_GLOBAL_FUNC( SUnMapLS,
658 "pushl %eax\n\t" /* preserve eax */
659 "pushl %eax\n\t"
660 "call " __ASM_NAME("UnMapLS") "\n\t"
661 "popl %eax\n\t"
662 "ret" );
Alexandre Julliard2c7a2482005-05-07 18:25:51 +0000663
664/***********************************************************************
665 * SMapLS_IP_EBP_8 (KERNEL32.@)
666 * SMapLS_IP_EBP_12 (KERNEL32.@)
667 * SMapLS_IP_EBP_16 (KERNEL32.@)
668 * SMapLS_IP_EBP_20 (KERNEL32.@)
669 * SMapLS_IP_EBP_24 (KERNEL32.@)
670 * SMapLS_IP_EBP_28 (KERNEL32.@)
671 * SMapLS_IP_EBP_32 (KERNEL32.@)
672 * SMapLS_IP_EBP_36 (KERNEL32.@)
673 * SMapLS_IP_EBP_40 (KERNEL32.@)
674 *
675 * These functions map linear pointers at [EBP+xxx] to segmented pointers
676 * and return them.
677 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
678 * unravel them at SUnMapLS. We just store the segmented pointer there.
679 */
680#define DEFINE_SMapLS(n) \
Alexandre Julliard643463b2006-01-13 14:26:24 +0100681 __ASM_GLOBAL_FUNC( SMapLS_IP_EBP_ ## n, \
682 "movl " #n "(%ebp),%eax\n\t" \
683 "call " __ASM_NAME("SMapLS") "\n\t" \
684 "movl %edx," #n "(%ebp)\n\t" \
685 "ret" );
Alexandre Julliard2c7a2482005-05-07 18:25:51 +0000686
687DEFINE_SMapLS(8);
688DEFINE_SMapLS(12);
689DEFINE_SMapLS(16);
690DEFINE_SMapLS(20);
691DEFINE_SMapLS(24);
692DEFINE_SMapLS(28);
693DEFINE_SMapLS(32);
694DEFINE_SMapLS(36);
695DEFINE_SMapLS(40);
696
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000697
698/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000699 * SUnMapLS_IP_EBP_8 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000700 * SUnMapLS_IP_EBP_12 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000701 * SUnMapLS_IP_EBP_16 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000702 * SUnMapLS_IP_EBP_20 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000703 * SUnMapLS_IP_EBP_24 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000704 * SUnMapLS_IP_EBP_28 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000705 * SUnMapLS_IP_EBP_32 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000706 * SUnMapLS_IP_EBP_36 (KERNEL32.@)
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000707 * SUnMapLS_IP_EBP_40 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000708 */
Alexandre Julliard2c7a2482005-05-07 18:25:51 +0000709
710#define DEFINE_SUnMapLS(n) \
Alexandre Julliard643463b2006-01-13 14:26:24 +0100711 __ASM_GLOBAL_FUNC( SUnMapLS_IP_EBP_ ## n, \
712 "pushl %eax\n\t" /* preserve eax */ \
713 "pushl " #n "(%ebp)\n\t" \
714 "call " __ASM_NAME("UnMapLS") "\n\t" \
715 "movl $0," #n "(%ebp)\n\t" \
716 "popl %eax\n\t" \
717 "ret" )
Alexandre Julliard2c7a2482005-05-07 18:25:51 +0000718
719DEFINE_SUnMapLS(8);
720DEFINE_SUnMapLS(12);
721DEFINE_SUnMapLS(16);
722DEFINE_SUnMapLS(20);
723DEFINE_SUnMapLS(24);
724DEFINE_SUnMapLS(28);
725DEFINE_SUnMapLS(32);
726DEFINE_SUnMapLS(36);
727DEFINE_SUnMapLS(40);
728
Alexandre Julliard643463b2006-01-13 14:26:24 +0100729#endif /* __i386__ */