2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
10 #include "selectors.h"
14 ldt_copy_entry ldt_copy[LDT_SIZE] = { {0,0}, };
16 #define FIRST_LDT_ENTRY_TO_ALLOC 6
19 /***********************************************************************
20 * AllocSelectorArray (KERNEL.206)
22 WORD AllocSelectorArray( WORD count )
27 for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
29 if (!IS_LDT_ENTRY_FREE(i)) size = 0;
30 else if (++size >= count) break;
32 if (i == LDT_SIZE) return 0;
33 return ENTRY_TO_SELECTOR( i - size + 1 );
37 /***********************************************************************
38 * AllocSelector (KERNEL.175)
40 WORD AllocSelector( WORD sel )
42 WORD newsel, count, i;
44 count = sel ? ((GET_SEL_LIMIT(sel) >> 16) + 1) : 1;
45 newsel = AllocSelectorArray( count );
46 dprintf_selector( stddeb, "AllocSelector(%04x): returning %04x\n",
48 if (!newsel) return 0;
49 if (!sel) return newsel; /* nothing to copy */
50 for (i = 0; i < count; i++)
53 LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
54 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
60 /***********************************************************************
61 * FreeSelector (KERNEL.176)
63 WORD FreeSelector( WORD sel )
68 dprintf_selector( stddeb, "FreeSelector(%04x)\n", sel );
69 if (IS_SELECTOR_FREE(sel)) return sel; /* error */
70 count = (GET_SEL_LIMIT(sel) >> 16) + 1;
71 memset( &entry, 0, sizeof(entry) ); /* clear the LDT entries */
72 for (i = 0; i < count; i++)
73 LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
78 /***********************************************************************
81 * Set the LDT entries for an array of selectors.
83 static void SELECTOR_SetEntries( WORD sel, void *base, DWORD size,
84 enum seg_type type, BOOL is32bit,
90 /* The limit for the first selector is the whole */
91 /* block. The next selectors get a 64k limit. */
92 entry.base = (unsigned long)base;
94 entry.seg_32bit = is32bit;
95 entry.read_only = readonly;
96 entry.limit_in_pages = (size > 0x100000);
97 if (entry.limit_in_pages) entry.limit = ((size + 0xfff) >> 12) - 1;
98 else entry.limit = size - 1;
99 count = (size + 0xffff) / 0x10000;
100 for (i = 0; i < count; i++)
102 LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
103 entry.base += 0x10000;
105 entry.limit = (size > 0x10000) ? 0xffff : size-1;
106 entry.limit_in_pages = 0;
111 /***********************************************************************
112 * SELECTOR_ReallocArray
114 * Change the size of an allocated selector array.
116 static WORD SELECTOR_ReallocArray( WORD sel, WORD newcount )
121 oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
122 if (oldcount < newcount) /* We need to add selectors */
124 /* Check if the next selectors are free */
125 for (i = oldcount; i < newcount; i++)
126 if (!IS_SELECTOR_FREE(sel+i)) break;
130 sel = AllocSelectorArray( newcount );
133 else if (oldcount > newcount) /* We need to remove selectors */
135 memset( &entry, 0, sizeof(entry) ); /* clear the LDT entries */
136 for (i = oldcount; i < newcount; i++)
137 LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
143 /***********************************************************************
144 * SELECTOR_AllocBlock
146 * Allocate selectors for a block of linear memory.
148 WORD SELECTOR_AllocBlock( void *base, DWORD size, enum seg_type type,
149 BOOL is32bit, BOOL readonly )
154 count = (size + 0xffff) / 0x10000;
155 sel = AllocSelectorArray( count );
156 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
161 /***********************************************************************
162 * SELECTOR_ReallocBlock
164 * Change the size of a block of selectors.
166 WORD SELECTOR_ReallocBlock( WORD sel, void *base, DWORD size,
167 enum seg_type type, BOOL is32bit, BOOL readonly )
176 count = (size + 0xffff) / 0x10000;
177 sel = SELECTOR_ReallocArray( sel, count );
178 if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
183 /***********************************************************************
184 * PrestoChangoSelector (KERNEL.177)
186 WORD PrestoChangoSelector( WORD selSrc, WORD selDst )
189 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc ), &entry );
190 entry.type ^= SEGMENT_CODE; /* toggle the executable bit */
191 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst ), &entry );
196 /***********************************************************************
197 * AllocCStoDSAlias (KERNEL.170)
199 WORD AllocCStoDSAlias( WORD sel )
204 newsel = AllocSelectorArray( 1 );
205 dprintf_selector( stddeb, "AllocCStoDSAlias(%04x): returning %04x\n",
207 if (!newsel) return 0;
208 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
209 entry.type = SEGMENT_DATA;
210 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
215 /***********************************************************************
216 * AllocDStoCSAlias (KERNEL.171)
218 WORD AllocDStoCSAlias( WORD sel )
223 newsel = AllocSelectorArray( 1 );
224 dprintf_selector( stddeb, "AllocDStoCSAlias(%04x): returning %04x\n",
226 if (!newsel) return 0;
227 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
228 entry.type = SEGMENT_CODE;
229 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
234 /***********************************************************************
235 * LongPtrAdd (KERNEL.180)
237 void LongPtrAdd( DWORD ptr, DWORD add )
240 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
242 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
246 /***********************************************************************
247 * GetSelectorBase (KERNEL.186)
249 DWORD GetSelectorBase( WORD sel )
251 return GET_SEL_BASE(sel);
255 /***********************************************************************
256 * SetSelectorBase (KERNEL.187)
258 WORD SetSelectorBase( WORD sel, DWORD base )
261 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
263 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
268 /***********************************************************************
269 * GetSelectorLimit (KERNEL.188)
271 DWORD GetSelectorLimit( WORD sel )
273 return GET_SEL_LIMIT(sel);
277 /***********************************************************************
278 * SetSelectorLimit (KERNEL.189)
280 WORD SetSelectorLimit( WORD sel, DWORD limit )
283 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
285 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
290 /***********************************************************************
291 * SelectorAccessRights (KERNEL.196)
293 WORD SelectorAccessRights( WORD sel, WORD op, WORD val )
296 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
297 if (op == 0) /* get */
299 return 1 /* accessed */ |
300 (entry.read_only << 1) |
302 (entry.seg_32bit << 14) |
303 (entry.limit_in_pages << 15);
307 entry.read_only = val & 2;
308 entry.type = (val >> 2) & 3;
309 entry.seg_32bit = val & 0x4000;
310 entry.limit_in_pages = val & 0x8000;
311 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
317 /***********************************************************************
318 * IsBadCodePtr (KERNEL.336)
320 BOOL IsBadCodePtr( SEGPTR lpfn )
325 sel = SELECTOROF(lpfn);
326 if (!sel) return FALSE;
327 if (IS_SELECTOR_FREE(sel)) return FALSE;
328 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
329 if (entry.type != SEGMENT_CODE) return FALSE;
330 if (OFFSETOF(lpfn) > entry.limit) return FALSE;
335 /***********************************************************************
336 * IsBadStringPtr (KERNEL.337)
338 BOOL IsBadStringPtr( SEGPTR ptr, WORD size )
343 sel = SELECTOROF(ptr);
344 if (!sel) return FALSE;
345 if (IS_SELECTOR_FREE(sel)) return FALSE;
346 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
347 if ((entry.type == SEGMENT_CODE) && entry.read_only) return FALSE;
348 if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr));
349 if (OFFSETOF(ptr) + size > entry.limit) return FALSE;
354 /***********************************************************************
355 * IsBadHugeReadPtr (KERNEL.346)
357 BOOL IsBadHugeReadPtr( SEGPTR ptr, DWORD size )
362 sel = SELECTOROF(ptr);
363 if (!sel) return FALSE;
364 if (IS_SELECTOR_FREE(sel)) return FALSE;
365 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
366 if ((entry.type == SEGMENT_CODE) && entry.read_only) return FALSE;
367 if (OFFSETOF(ptr) + size > entry.limit) return FALSE;
372 /***********************************************************************
373 * IsBadHugeWritePtr (KERNEL.347)
375 BOOL IsBadHugeWritePtr( SEGPTR ptr, DWORD size )
380 sel = SELECTOROF(ptr);
381 if (!sel) return FALSE;
382 if (IS_SELECTOR_FREE(sel)) return FALSE;
383 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
384 if ((entry.type == SEGMENT_CODE) || entry.read_only) return FALSE;
385 if (OFFSETOF(ptr) + size > entry.limit) return FALSE;
389 /***********************************************************************
390 * IsBadReadPtr (KERNEL.334)
392 BOOL IsBadReadPtr( SEGPTR ptr, WORD size )
394 return IsBadHugeReadPtr( ptr, size );
398 /***********************************************************************
399 * IsBadWritePtr (KERNEL.335)
401 BOOL IsBadWritePtr( SEGPTR ptr, WORD size )
403 return IsBadHugeWritePtr( ptr, size );
407 /***********************************************************************
408 * MemoryRead (TOOLHELP.78)
410 DWORD MemoryRead( WORD sel, DWORD offset, void *buffer, DWORD count )
412 if (IS_SELECTOR_FREE(sel)) return 0;
413 if (offset > GET_SEL_LIMIT(sel)) return 0;
414 if (offset + count > GET_SEL_LIMIT(sel) + 1)
415 count = GET_SEL_LIMIT(sel) + 1 - offset;
416 memcpy( buffer, ((char *)GET_SEL_BASE(sel)) + offset, count );
421 /***********************************************************************
422 * MemoryWrite (TOOLHELP.79)
424 DWORD MemoryWrite( WORD sel, DWORD offset, void *buffer, DWORD count )
426 if (IS_SELECTOR_FREE(sel)) return 0;
427 if (offset > GET_SEL_LIMIT(sel)) return 0;
428 if (offset + count > GET_SEL_LIMIT(sel) + 1)
429 count = GET_SEL_LIMIT(sel) + 1 - offset;
430 memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );