blob: 7de71c6bb5e4a0101d6d2bdb7a279f191ceb3fe3 [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 Julliard21979011997-03-05 08:22:35 +000028#include "miscemu.h"
Alexandre Julliardfa68b751995-04-03 16:55:37 +000029#include "selectors.h"
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000030#include "stackframe.h"
Alexandre Julliard37e95032001-07-19 00:39:09 +000031#include "wine/server.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000032#include "wine/debug.h"
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000033#include "toolhelp.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000034
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000035WINE_DEFAULT_DEBUG_CHANNEL(selector);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000036
Alexandre Julliard914406f2000-11-14 01:54:49 +000037#define LDT_SIZE 8192
38
39/* get the number of selectors needed to cover up to the selector limit */
40inline static WORD get_sel_count( WORD sel )
41{
42 return (wine_ldt_copy.limit[sel >> __AHSHIFT] >> 16) + 1;
43}
44
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000045
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000046/***********************************************************************
47 * AllocSelectorArray (KERNEL.206)
48 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000049WORD WINAPI AllocSelectorArray16( WORD count )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000050{
Alexandre Julliardce131532003-02-26 20:34:45 +000051 WORD i, sel = wine_ldt_alloc_entries( count );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000052
Alexandre Julliard914406f2000-11-14 01:54:49 +000053 if (sel)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000054 {
Alexandre Julliard914406f2000-11-14 01:54:49 +000055 LDT_ENTRY entry;
56 wine_ldt_set_base( &entry, 0 );
57 wine_ldt_set_limit( &entry, 1 ); /* avoid 0 base and limit */
58 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_DATA );
59 for (i = 0; i < count; i++) wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000060 }
Alexandre Julliard914406f2000-11-14 01:54:49 +000061 return sel;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000062}
63
64
65/***********************************************************************
66 * AllocSelector (KERNEL.175)
67 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000068WORD WINAPI AllocSelector16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000069{
70 WORD newsel, count, i;
71
Alexandre Julliard914406f2000-11-14 01:54:49 +000072 count = sel ? get_sel_count(sel) : 1;
Alexandre Julliardce131532003-02-26 20:34:45 +000073 newsel = wine_ldt_alloc_entries( count );
Alexandre Julliard914406f2000-11-14 01:54:49 +000074 TRACE("(%04x): returning %04x\n", sel, newsel );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000075 if (!newsel) return 0;
76 if (!sel) return newsel; /* nothing to copy */
77 for (i = 0; i < count; i++)
78 {
Alexandre Julliard914406f2000-11-14 01:54:49 +000079 LDT_ENTRY entry;
80 wine_ldt_get_entry( sel + (i << __AHSHIFT), &entry );
81 wine_ldt_set_entry( newsel + (i << __AHSHIFT), &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000082 }
83 return newsel;
84}
85
86
87/***********************************************************************
88 * FreeSelector (KERNEL.176)
89 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000090WORD WINAPI FreeSelector16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000091{
Alexandre Julliardce131532003-02-26 20:34:45 +000092 LDT_ENTRY entry;
Alexandre Julliard914406f2000-11-14 01:54:49 +000093
Alexandre Julliardce131532003-02-26 20:34:45 +000094 wine_ldt_get_entry( sel, &entry );
95 if (wine_ldt_is_empty( &entry )) return sel; /* error */
Alexandre Julliard914406f2000-11-14 01:54:49 +000096#ifdef __i386__
Alexandre Julliardce131532003-02-26 20:34:45 +000097 /* Check if we are freeing current %fs selector */
Alexandre Julliard4ced7ef2002-08-14 21:10:50 +000098 if (!((wine_get_fs() ^ sel) & ~3))
Alexandre Julliard59008672002-05-16 20:32:16 +000099 WARN("Freeing %%fs selector (%04x), not good.\n", wine_get_fs() );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000100#endif /* __i386__ */
Alexandre Julliardce131532003-02-26 20:34:45 +0000101 wine_ldt_free_entries( sel, 1 );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000102 return 0;
103}
104
105
106/***********************************************************************
107 * SELECTOR_SetEntries
108 *
109 * Set the LDT entries for an array of selectors.
110 */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000111static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000112{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000113 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000114 WORD i, count;
115
Alexandre Julliard914406f2000-11-14 01:54:49 +0000116 wine_ldt_set_base( &entry, base );
Alexandre Julliard4ced7ef2002-08-14 21:10:50 +0000117 wine_ldt_set_limit( &entry, size - 1 );
Andreas Mohr757e7cb2002-05-08 00:20:40 +0000118 wine_ldt_set_flags( &entry, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000119 count = (size + 0xffff) / 0x10000;
120 for (i = 0; i < count; i++)
121 {
Alexandre Julliard914406f2000-11-14 01:54:49 +0000122 wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
Gregg Mattinson7c4cb512002-07-03 21:10:43 +0000123 wine_ldt_set_base( &entry, (char*)wine_ldt_get_base(&entry) + 0x10000);
Andreas Mohr757e7cb2002-05-08 00:20:40 +0000124 /* yep, Windows sets limit like that, not 64K sel units */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000125 wine_ldt_set_limit( &entry, wine_ldt_get_limit(&entry) - 0x10000 );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000126 }
127}
128
129
130/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000131 * SELECTOR_AllocBlock
132 *
133 * Allocate selectors for a block of linear memory.
134 */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000135WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000136{
137 WORD sel, count;
138
139 if (!size) return 0;
140 count = (size + 0xffff) / 0x10000;
Alexandre Julliardce131532003-02-26 20:34:45 +0000141 sel = wine_ldt_alloc_entries( count );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000142 if (sel) SELECTOR_SetEntries( sel, base, size, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000143 return sel;
144}
145
146
147/***********************************************************************
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000148 * SELECTOR_FreeBlock
149 *
150 * Free a block of selectors.
151 */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000152void SELECTOR_FreeBlock( WORD sel )
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000153{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000154 WORD i, count = get_sel_count( sel );
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000155
Alexandre Julliard15657091999-05-23 10:25:25 +0000156 TRACE("(%04x,%d)\n", sel, count );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000157 for (i = 0; i < count; i++) FreeSelector16( sel + (i << __AHSHIFT) );
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000158}
159
160
161/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000162 * SELECTOR_ReallocBlock
163 *
164 * Change the size of a block of selectors.
165 */
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000166WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000167{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000168 LDT_ENTRY entry;
Alexandre Julliardce131532003-02-26 20:34:45 +0000169 int oldcount, newcount;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000170
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000171 if (!size) size = 1;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000172 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000173 oldcount = (wine_ldt_get_limit(&entry) >> 16) + 1;
174 newcount = (size + 0xffff) >> 16;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000175
Alexandre Julliardce131532003-02-26 20:34:45 +0000176 sel = wine_ldt_realloc_entries( sel, oldcount, newcount );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000177 if (sel) SELECTOR_SetEntries( sel, base, size, wine_ldt_get_flags(&entry) );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000178 return sel;
179}
180
181
182/***********************************************************************
183 * PrestoChangoSelector (KERNEL.177)
184 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000185WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000186{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000187 LDT_ENTRY entry;
188 wine_ldt_get_entry( selSrc, &entry );
189 /* toggle the executable bit */
190 entry.HighWord.Bits.Type ^= (WINE_LDT_FLAGS_CODE ^ WINE_LDT_FLAGS_DATA);
191 wine_ldt_set_entry( selDst, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000192 return selDst;
193}
194
195
196/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000197 * AllocCStoDSAlias (KERNEL.170)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000198 * AllocAlias (KERNEL.172)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000199 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000200WORD WINAPI AllocCStoDSAlias16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000201{
202 WORD newsel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000203 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000204
Alexandre Julliardce131532003-02-26 20:34:45 +0000205 newsel = wine_ldt_alloc_entries( 1 );
Alexandre Julliard15657091999-05-23 10:25:25 +0000206 TRACE("(%04x): returning %04x\n",
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000207 sel, newsel );
208 if (!newsel) return 0;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000209 wine_ldt_get_entry( sel, &entry );
210 entry.HighWord.Bits.Type = WINE_LDT_FLAGS_DATA;
211 wine_ldt_set_entry( newsel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000212 return newsel;
213}
214
215
216/***********************************************************************
217 * AllocDStoCSAlias (KERNEL.171)
218 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000219WORD WINAPI AllocDStoCSAlias16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000220{
221 WORD newsel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000222 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000223
Alexandre Julliardce131532003-02-26 20:34:45 +0000224 newsel = wine_ldt_alloc_entries( 1 );
Alexandre Julliard15657091999-05-23 10:25:25 +0000225 TRACE("(%04x): returning %04x\n",
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000226 sel, newsel );
227 if (!newsel) return 0;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000228 wine_ldt_get_entry( sel, &entry );
229 entry.HighWord.Bits.Type = WINE_LDT_FLAGS_CODE;
230 wine_ldt_set_entry( newsel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000231 return newsel;
232}
233
234
235/***********************************************************************
236 * LongPtrAdd (KERNEL.180)
237 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000238void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000239{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000240 LDT_ENTRY entry;
241 wine_ldt_get_entry( SELECTOROF(ptr), &entry );
242 wine_ldt_set_base( &entry, (char *)wine_ldt_get_base(&entry) + add );
243 wine_ldt_set_entry( SELECTOROF(ptr), &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000244}
245
246
247/***********************************************************************
Jukka Heinonen56dff0d2002-11-20 19:40:12 +0000248 * GetSelectorBase (KERNEL.186)
Patrik Stridvallb5bb32c2002-09-24 18:29:39 +0000249 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000250DWORD WINAPI GetSelectorBase( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000251{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000252 void *base = wine_ldt_copy.base[sel >> __AHSHIFT];
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000253
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000254 /* if base points into DOSMEM, assume we have to
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000255 * return pointer into physical lower 1MB */
256
Alexandre Julliard914406f2000-11-14 01:54:49 +0000257 return DOSMEM_MapLinearToDos( base );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000258}
259
260
261/***********************************************************************
Jukka Heinonen56dff0d2002-11-20 19:40:12 +0000262 * SetSelectorBase (KERNEL.187)
Patrik Stridvallb5bb32c2002-09-24 18:29:39 +0000263 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000264WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000265{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000266 LDT_ENTRY entry;
267 wine_ldt_get_entry( sel, &entry );
268 wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
269 wine_ldt_set_entry( sel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000270 return sel;
271}
272
273
274/***********************************************************************
275 * GetSelectorLimit (KERNEL.188)
276 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000277DWORD WINAPI GetSelectorLimit16( WORD sel )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000278{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000279 return wine_ldt_copy.limit[sel >> __AHSHIFT];
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000280}
281
282
283/***********************************************************************
284 * SetSelectorLimit (KERNEL.189)
285 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000286WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000287{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000288 LDT_ENTRY entry;
289 wine_ldt_get_entry( sel, &entry );
290 wine_ldt_set_limit( &entry, limit );
291 wine_ldt_set_entry( sel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000292 return sel;
293}
294
295
296/***********************************************************************
297 * SelectorAccessRights (KERNEL.196)
298 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000299WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000300{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000301 LDT_ENTRY entry;
302 wine_ldt_get_entry( sel, &entry );
303
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000304 if (op == 0) /* get */
305 {
Alexandre Julliard914406f2000-11-14 01:54:49 +0000306 return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 << 8) & 0xf0);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000307 }
308 else /* set */
309 {
Alexandre Julliard914406f2000-11-14 01:54:49 +0000310 entry.HighWord.Bytes.Flags1 = LOBYTE(val) | 0xf0;
311 entry.HighWord.Bytes.Flags2 = (entry.HighWord.Bytes.Flags2 & 0x0f) | (HIBYTE(val) & 0xf0);
312 wine_ldt_set_entry( sel, &entry );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000313 return 0;
314 }
315}
316
317
318/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000319 * IsBadCodePtr (KERNEL.336)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000320 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000321BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000322{
323 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000324 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000325
326 sel = SELECTOROF(lpfn);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000327 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000328 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000329 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000330 /* check for code segment, ignoring conforming, read-only and accessed bits */
331 if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_CODE) & 0x18) return TRUE;
332 if (OFFSETOF(lpfn) > wine_ldt_get_limit(&entry)) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000333 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000334}
335
336
337/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000338 * IsBadStringPtr (KERNEL.337)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000339 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000340BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000341{
342 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000343 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000344
345 sel = SELECTOROF(ptr);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000346 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000347 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000348 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000349 /* check for data or readable code segment */
350 if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
351 if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
Alexandre Julliard982a2232000-12-13 20:20:09 +0000352 if (strlen(MapSL(ptr)) < size) size = strlen(MapSL(ptr)) + 1;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000353 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit(&entry))) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000354 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000355}
356
357
358/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000359 * IsBadHugeReadPtr (KERNEL.346)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000360 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000361BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000362{
363 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000364 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000365
366 sel = SELECTOROF(ptr);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000367 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000368 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000369 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000370 /* check for data or readable code segment */
371 if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
372 if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
373 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000374 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000375}
376
377
378/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000379 * IsBadHugeWritePtr (KERNEL.347)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000380 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000381BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000382{
383 WORD sel;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000384 LDT_ENTRY entry;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000385
386 sel = SELECTOROF(ptr);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000387 if (!sel) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000388 wine_ldt_get_entry( sel, &entry );
Alexandre Julliardce131532003-02-26 20:34:45 +0000389 if (wine_ldt_is_empty( &entry )) return TRUE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000390 /* check for writeable data segment, ignoring expand-down and accessed flags */
391 if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
392 if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000393 return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000394}
395
396/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000397 * IsBadReadPtr (KERNEL.334)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000398 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000399BOOL16 WINAPI IsBadReadPtr16( SEGPTR ptr, UINT16 size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000400{
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000401 return IsBadHugeReadPtr16( ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000402}
403
404
405/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000406 * IsBadWritePtr (KERNEL.335)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000407 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000408BOOL16 WINAPI IsBadWritePtr16( SEGPTR ptr, UINT16 size )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000409{
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000410 return IsBadHugeWritePtr16( ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000411}
412
413
414/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000415 * IsBadFlatReadWritePtr (KERNEL.627)
Ulrich Weigand98b5f771999-07-27 17:09:14 +0000416 */
417BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
418{
419 return bWrite? IsBadHugeWritePtr16( ptr, size )
420 : IsBadHugeReadPtr16( ptr, size );
421}
422
423
424/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000425 * MemoryRead (TOOLHELP.78)
426 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000427DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000428{
Alexandre Julliardce131532003-02-26 20:34:45 +0000429 LDT_ENTRY entry;
430 DWORD limit;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000431
Alexandre Julliardce131532003-02-26 20:34:45 +0000432 wine_ldt_get_entry( sel, &entry );
433 if (wine_ldt_is_empty( &entry )) return 0;
434 limit = wine_ldt_get_limit( &entry );
435 if (offset > limit) return 0;
436 if (offset + count > limit + 1) count = limit + 1 - offset;
437 memcpy( buffer, (char *)wine_ldt_get_base(&entry) + offset, count );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000438 return count;
439}
440
441
442/***********************************************************************
443 * MemoryWrite (TOOLHELP.79)
444 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000445DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000446{
Alexandre Julliardce131532003-02-26 20:34:45 +0000447 LDT_ENTRY entry;
448 DWORD limit;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000449
Alexandre Julliardce131532003-02-26 20:34:45 +0000450 wine_ldt_get_entry( sel, &entry );
451 if (wine_ldt_is_empty( &entry )) return 0;
452 limit = wine_ldt_get_limit( &entry );
453 if (offset > limit) return 0;
454 if (offset + count > limit) count = limit + 1 - offset;
455 memcpy( (char *)wine_ldt_get_base(&entry) + offset, buffer, count );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000456 return count;
457}
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000458
459/************************************* Win95 pointer mapping functions *
460 *
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000461 */
462
Alexandre Julliardb0f58612001-12-19 19:16:27 +0000463struct mapls_entry
464{
465 struct mapls_entry *next;
466 void *addr; /* linear address */
467 int count; /* ref count */
468 WORD sel; /* selector */
469};
470
471static struct mapls_entry *first_entry;
472
473
474/***********************************************************************
475 * MapLS (KERNEL32.@)
476 * MapLS (KERNEL.358)
477 *
478 * Maps linear pointer to segmented.
479 */
480SEGPTR WINAPI MapLS( LPCVOID ptr )
481{
482 struct mapls_entry *entry, *free = NULL;
483 void *base;
484 SEGPTR ret = 0;
485
486 if (!HIWORD(ptr)) return (SEGPTR)ptr;
487
488 base = (char *)ptr - ((unsigned int)ptr & 0x7fff);
489 HeapLock( GetProcessHeap() );
490 for (entry = first_entry; entry; entry = entry->next)
491 {
492 if (entry->addr == base) break;
493 if (!entry->count) free = entry;
494 }
495
496 if (!entry)
497 {
498 if (!free) /* no free entry found, create a new one */
499 {
500 if (!(free = HeapAlloc( GetProcessHeap(), 0, sizeof(*free) ))) goto done;
501 if (!(free->sel = SELECTOR_AllocBlock( base, 0x10000, WINE_LDT_FLAGS_DATA )))
502 {
503 HeapFree( GetProcessHeap(), 0, free );
504 goto done;
505 }
506 free->count = 0;
507 free->next = first_entry;
508 first_entry = free;
509 }
510 SetSelectorBase( free->sel, (DWORD)base );
511 free->addr = base;
512 entry = free;
513 }
514 entry->count++;
515 ret = MAKESEGPTR( entry->sel, (char *)ptr - (char *)entry->addr );
516 done:
517 HeapUnlock( GetProcessHeap() );
518 return ret;
519}
520
521/***********************************************************************
522 * UnMapLS (KERNEL32.@)
523 * UnMapLS (KERNEL.359)
524 *
525 * Free mapped selector.
526 */
527void WINAPI UnMapLS( SEGPTR sptr )
528{
529 struct mapls_entry *entry;
530 WORD sel = SELECTOROF(sptr);
531
532 if (sel)
533 {
534 HeapLock( GetProcessHeap() );
535 for (entry = first_entry; entry; entry = entry->next) if (entry->sel == sel) break;
536 if (entry && entry->count > 0) entry->count--;
537 HeapUnlock( GetProcessHeap() );
538 }
539}
540
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000541/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000542 * MapSL (KERNEL32.@)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000543 * MapSL (KERNEL.357)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000544 *
545 * Maps fixed segmented pointer to linear.
546 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000547LPVOID WINAPI MapSL( SEGPTR sptr )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000548{
Alexandre Julliard914406f2000-11-14 01:54:49 +0000549 return (char *)wine_ldt_copy.base[SELECTOROF(sptr) >> __AHSHIFT] + OFFSETOF(sptr);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000550}
551
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000552/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000553 * MapSLFix (KERNEL32.@)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000554 *
555 * FIXME: MapSLFix and UnMapSLFixArray should probably prevent
556 * unexpected linear address change when GlobalCompact() shuffles
557 * moveable blocks.
558 */
559
560LPVOID WINAPI MapSLFix( SEGPTR sptr )
561{
Alexandre Julliard982a2232000-12-13 20:20:09 +0000562 return MapSL(sptr);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000563}
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000564
565/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000566 * UnMapSLFixArray (KERNEL32.@)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000567 */
568
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000569void WINAPI UnMapSLFixArray( SEGPTR sptr[], INT length, CONTEXT86 *context )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000570{
Ulrich Weigand90c245c1999-02-02 10:34:46 +0000571 /* Must not change EAX, hence defined as 'register' function */
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000572}
573
574/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000575 * GetThreadSelectorEntry (KERNEL32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000576 */
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000577BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000578{
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000579#ifdef __i386__
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000580 BOOL ret;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000581
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000582 if (!(sel & 4)) /* GDT selector */
583 {
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000584 sel &= ~3; /* ignore RPL */
585 if (!sel) /* null selector */
586 {
587 memset( ldtent, 0, sizeof(*ldtent) );
588 return TRUE;
589 }
590 ldtent->BaseLow = 0;
591 ldtent->HighWord.Bits.BaseMid = 0;
592 ldtent->HighWord.Bits.BaseHi = 0;
593 ldtent->LimitLow = 0xffff;
594 ldtent->HighWord.Bits.LimitHi = 0xf;
595 ldtent->HighWord.Bits.Dpl = 3;
596 ldtent->HighWord.Bits.Sys = 0;
597 ldtent->HighWord.Bits.Pres = 1;
598 ldtent->HighWord.Bits.Granularity = 1;
599 ldtent->HighWord.Bits.Default_Big = 1;
600 ldtent->HighWord.Bits.Type = 0x12;
601 /* it has to be one of the system GDT selectors */
Alexandre Julliard59008672002-05-16 20:32:16 +0000602 if (sel == (wine_get_ds() & ~3)) return TRUE;
603 if (sel == (wine_get_ss() & ~3)) return TRUE;
604 if (sel == (wine_get_cs() & ~3))
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000605 {
606 ldtent->HighWord.Bits.Type |= 8; /* code segment */
607 return TRUE;
608 }
609 SetLastError( ERROR_NOACCESS );
610 return FALSE;
611 }
612
Alexandre Julliard67a74992001-02-27 02:09:16 +0000613 SERVER_START_REQ( get_selector_entry )
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000614 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000615 req->handle = hthread;
616 req->entry = sel >> __AHSHIFT;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000617 if ((ret = !wine_server_call_err( req )))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000618 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000619 if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000620 {
621 SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */
622 ret = FALSE;
623 }
624 else
625 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000626 wine_ldt_set_base( ldtent, (void *)reply->base );
627 wine_ldt_set_limit( ldtent, reply->limit );
628 wine_ldt_set_flags( ldtent, reply->flags );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000629 }
630 }
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000631 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000632 SERVER_END_REQ;
633 return ret;
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000634#else
Ulrich Weigandafd6a4b2000-06-04 01:48:05 +0000635 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +0000636 return FALSE;
637#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000638}
639
640
641/**********************************************************************
642 * SMapLS* (KERNEL32)
643 * These functions map linear pointers at [EBP+xxx] to segmented pointers
644 * and return them.
645 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
646 * unravel them at SUnMapLS. We just store the segmented pointer there.
647 */
648static void
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000649x_SMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
Vincent Béron9a624912002-05-31 23:06:46 +0000650 DWORD val,ptr;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000651
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000652 val =*(DWORD*)(context->Ebp + argoff);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000653 if (val<0x10000) {
654 ptr=val;
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000655 *(DWORD*)(context->Ebp + argoff) = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000656 } else {
657 ptr = MapLS((LPVOID)val);
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000658 *(DWORD*)(context->Ebp + argoff) = ptr;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000659 }
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000660 context->Eax = ptr;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000661}
662
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000663/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000664 * SMapLS_IP_EBP_8 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000665 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000666void WINAPI SMapLS_IP_EBP_8 (CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context, 8);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000667
668/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000669 * SMapLS_IP_EBP_12 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000670 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000671void WINAPI SMapLS_IP_EBP_12(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,12);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000672
673/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000674 * SMapLS_IP_EBP_16 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000675 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000676void WINAPI SMapLS_IP_EBP_16(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,16);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000677
678/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000679 * SMapLS_IP_EBP_20 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000680 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000681void WINAPI SMapLS_IP_EBP_20(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,20);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000682
683/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000684 * SMapLS_IP_EBP_24 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000685 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000686void WINAPI SMapLS_IP_EBP_24(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,24);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000687
688/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000689 * SMapLS_IP_EBP_28 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000690 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000691void WINAPI SMapLS_IP_EBP_28(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,28);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000692
693/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000694 * SMapLS_IP_EBP_32 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000695 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000696void WINAPI SMapLS_IP_EBP_32(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,32);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000697
698/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000699 * SMapLS_IP_EBP_36 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000700 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000701void WINAPI SMapLS_IP_EBP_36(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,36);}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000702
703/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000704 * SMapLS_IP_EBP_40 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000705 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000706void WINAPI SMapLS_IP_EBP_40(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,40);}
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000707
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000708/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000709 * SMapLS (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000710 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000711void WINAPI SMapLS( CONTEXT86 *context )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000712{
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000713 if (HIWORD(context->Eax))
714 {
715 context->Eax = MapLS( (LPVOID)context->Eax );
716 context->Edx = context->Eax;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000717 } else {
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000718 context->Edx = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000719 }
720}
721
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000722/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000723 * SUnMapLS (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000724 */
725
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000726void WINAPI SUnMapLS( CONTEXT86 *context )
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000727{
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000728 if (HIWORD(context->Eax)) UnMapLS( (SEGPTR)context->Eax );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000729}
730
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000731inline static void x_SUnMapLS_IP_EBP_x(CONTEXT86 *context,int argoff)
732{
733 SEGPTR *ptr = (SEGPTR *)(context->Ebp + argoff);
734 if (*ptr)
735 {
736 UnMapLS( *ptr );
737 *ptr = 0;
738 }
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000739}
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000740
741/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000742 * SUnMapLS_IP_EBP_8 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000743 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000744void WINAPI SUnMapLS_IP_EBP_8 (CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context, 8); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000745
746/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000747 * SUnMapLS_IP_EBP_12 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000748 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000749void WINAPI SUnMapLS_IP_EBP_12(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,12); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000750
751/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000752 * SUnMapLS_IP_EBP_16 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000753 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000754void WINAPI SUnMapLS_IP_EBP_16(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,16); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000755
756/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000757 * SUnMapLS_IP_EBP_20 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000758 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000759void WINAPI SUnMapLS_IP_EBP_20(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,20); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000760
761/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000762 * SUnMapLS_IP_EBP_24 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000763 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000764void WINAPI SUnMapLS_IP_EBP_24(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,24); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000765
766/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000767 * SUnMapLS_IP_EBP_28 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000768 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000769void WINAPI SUnMapLS_IP_EBP_28(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,28); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000770
771/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000772 * SUnMapLS_IP_EBP_32 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000773 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000774void WINAPI SUnMapLS_IP_EBP_32(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,32); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000775
776/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000777 * SUnMapLS_IP_EBP_36 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000778 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000779void WINAPI SUnMapLS_IP_EBP_36(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,36); }
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000780
781/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000782 * SUnMapLS_IP_EBP_40 (KERNEL32.@)
Patrik Stridvall54fe8382000-04-06 20:21:16 +0000783 */
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000784void WINAPI SUnMapLS_IP_EBP_40(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,40); }
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000785
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000786/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000787 * AllocMappedBuffer (KERNEL32.38)
788 *
Vincent Béron9a624912002-05-31 23:06:46 +0000789 * This is a undocumented KERNEL32 function that
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000790 * SMapLS's a GlobalAlloc'ed buffer.
791 *
792 * Input: EDI register: size of buffer to allocate
793 * Output: EDI register: pointer to buffer
794 *
Francois Gouget519346a2000-12-02 20:18:08 +0000795 * Note: The buffer is preceded by 8 bytes:
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000796 * ...
797 * edi+0 buffer
798 * edi-4 SEGPTR to buffer
799 * edi-8 some magic Win95 needs for SUnMapLS
800 * (we use it for the memory handle)
801 *
802 * The SEGPTR is used by the caller!
803 */
804
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000805void WINAPI AllocMappedBuffer( CONTEXT86 *context )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000806{
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000807 HGLOBAL handle = GlobalAlloc(0, context->Edi + 8);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000808 DWORD *buffer = (DWORD *)GlobalLock(handle);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000809 SEGPTR ptr = 0;
810
811 if (buffer)
812 if (!(ptr = MapLS(buffer + 2)))
813 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000814 GlobalUnlock(handle);
815 GlobalFree(handle);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000816 }
817
818 if (!ptr)
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000819 context->Eax = context->Edi = 0;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000820 else
821 {
Alexandre Julliard73755972002-07-31 19:26:03 +0000822 buffer[0] = (DWORD)handle;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000823 buffer[1] = ptr;
824
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000825 context->Eax = (DWORD) ptr;
826 context->Edi = (DWORD)(buffer + 2);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000827 }
828}
829
830/**********************************************************************
831 * FreeMappedBuffer (KERNEL32.39)
832 *
833 * Free a buffer allocated by AllocMappedBuffer
834 *
835 * Input: EDI register: pointer to buffer
836 */
837
Ulrich Weigandeb94c7d1999-11-13 23:54:04 +0000838void WINAPI FreeMappedBuffer( CONTEXT86 *context )
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000839{
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000840 if (context->Edi)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000841 {
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000842 DWORD *buffer = (DWORD *)context->Edi - 2;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000843
844 UnMapLS(buffer[1]);
845
Alexandre Julliard73755972002-07-31 19:26:03 +0000846 GlobalUnlock((HGLOBAL)buffer[0]);
847 GlobalFree((HGLOBAL)buffer[0]);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000848 }
849}