2 * Selector manipulation functions
4 * Copyright 1995 Alexandre Julliard
10 #include "selectors.h"
11 #include "stackframe.h"
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 /* Mark selector as allocated */
34 while (size
--) ldt_flags_copy
[i
--] |= LDT_FLAGS_ALLOCATED
;
35 return ENTRY_TO_SELECTOR( i
+ 1 );
39 /***********************************************************************
40 * AllocSelector (KERNEL.175)
42 WORD
AllocSelector( WORD sel
)
44 WORD newsel
, count
, i
;
46 count
= sel
? ((GET_SEL_LIMIT(sel
) >> 16) + 1) : 1;
47 newsel
= AllocSelectorArray( count
);
48 dprintf_selector( stddeb
, "AllocSelector(%04x): returning %04x\n",
50 if (!newsel
) return 0;
51 if (!sel
) return newsel
; /* nothing to copy */
52 for (i
= 0; i
< count
; i
++)
55 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
56 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
) + i
, &entry
);
62 /***********************************************************************
63 * FreeSelector (KERNEL.176)
65 WORD
FreeSelector( WORD sel
)
70 dprintf_selector( stddeb
, "FreeSelector(%04x)\n", sel
);
71 if (IS_SELECTOR_FREE(sel
)) return sel
; /* error */
72 count
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
73 memset( &entry
, 0, sizeof(entry
) ); /* clear the LDT entries */
74 /* FIXME: is it correct to free the whole array? */
75 for (i
= SELECTOR_TO_ENTRY(sel
); count
; i
++, count
--)
77 LDT_SetEntry( i
, &entry
);
78 ldt_flags_copy
[i
] &= ~LDT_FLAGS_ALLOCATED
;
81 /* Clear the saved 16-bit selector */
85 /* FIXME: maybe we ought to walk up the stack and fix all frames */
86 if (CURRENT_STACK16
->ds
== sel
) CURRENT_STACK16
->ds
= 0;
87 if (CURRENT_STACK16
->es
== sel
) CURRENT_STACK16
->es
= 0;
94 /***********************************************************************
97 * Set the LDT entries for an array of selectors.
99 static void SELECTOR_SetEntries( WORD sel
, void *base
, DWORD size
,
100 enum seg_type type
, BOOL is32bit
,
106 /* The limit for the first selector is the whole */
107 /* block. The next selectors get a 64k limit. */
108 entry
.base
= (unsigned long)base
;
110 entry
.seg_32bit
= is32bit
;
111 entry
.read_only
= readonly
;
112 entry
.limit_in_pages
= (size
> 0x100000);
113 if (entry
.limit_in_pages
) entry
.limit
= ((size
+ 0xfff) >> 12) - 1;
114 else entry
.limit
= size
- 1;
115 count
= (size
+ 0xffff) / 0x10000;
116 for (i
= 0; i
< count
; i
++)
118 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
119 entry
.base
+= 0x10000;
121 entry
.limit
= (size
> 0x10000) ? 0xffff : size
-1;
122 entry
.limit_in_pages
= 0;
127 /***********************************************************************
128 * SELECTOR_AllocBlock
130 * Allocate selectors for a block of linear memory.
132 WORD
SELECTOR_AllocBlock( void *base
, DWORD size
, enum seg_type type
,
133 BOOL is32bit
, BOOL readonly
)
138 count
= (size
+ 0xffff) / 0x10000;
139 sel
= AllocSelectorArray( count
);
140 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, type
, is32bit
, readonly
);
145 /***********************************************************************
146 * SELECTOR_ReallocBlock
148 * Change the size of a block of selectors.
150 WORD
SELECTOR_ReallocBlock( WORD sel
, void *base
, DWORD size
,
151 enum seg_type type
, BOOL is32bit
, BOOL readonly
)
153 WORD i
, oldcount
, newcount
;
157 oldcount
= (GET_SEL_LIMIT(sel
) >> 16) + 1;
158 newcount
= (size
+ 0xffff) >> 16;
160 if (oldcount
< newcount
) /* We need to add selectors */
162 /* Check if the next selectors are free */
163 if (SELECTOR_TO_ENTRY(sel
) + newcount
> LDT_SIZE
) i
= oldcount
;
165 for (i
= oldcount
; i
< newcount
; i
++)
166 if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel
)+i
)) break;
168 if (i
< newcount
) /* they are not free */
171 sel
= AllocSelectorArray( newcount
);
173 else /* mark the selectors as allocated */
175 for (i
= oldcount
; i
< newcount
; i
++)
176 ldt_flags_copy
[SELECTOR_TO_ENTRY(sel
)+i
] |=LDT_FLAGS_ALLOCATED
;
179 else if (oldcount
> newcount
) /* We need to remove selectors */
181 memset( &entry
, 0, sizeof(entry
) ); /* clear the LDT entries */
182 for (i
= oldcount
; i
< newcount
; i
++)
184 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
) + i
, &entry
);
185 ldt_flags_copy
[SELECTOR_TO_ENTRY(sel
) + i
] &= ~LDT_FLAGS_ALLOCATED
;
188 if (sel
) SELECTOR_SetEntries( sel
, base
, size
, type
, is32bit
, readonly
);
193 /***********************************************************************
194 * PrestoChangoSelector (KERNEL.177)
196 WORD
PrestoChangoSelector( WORD selSrc
, WORD selDst
)
199 LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc
), &entry
);
200 entry
.type
^= SEGMENT_CODE
; /* toggle the executable bit */
201 LDT_SetEntry( SELECTOR_TO_ENTRY( selDst
), &entry
);
206 /***********************************************************************
207 * AllocCStoDSAlias (KERNEL.170)
209 WORD
AllocCStoDSAlias( WORD sel
)
214 newsel
= AllocSelectorArray( 1 );
215 dprintf_selector( stddeb
, "AllocCStoDSAlias(%04x): returning %04x\n",
217 if (!newsel
) return 0;
218 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
219 entry
.type
= SEGMENT_DATA
;
220 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
225 /***********************************************************************
226 * AllocDStoCSAlias (KERNEL.171)
228 WORD
AllocDStoCSAlias( WORD sel
)
233 newsel
= AllocSelectorArray( 1 );
234 dprintf_selector( stddeb
, "AllocDStoCSAlias(%04x): returning %04x\n",
236 if (!newsel
) return 0;
237 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
238 entry
.type
= SEGMENT_CODE
;
239 LDT_SetEntry( SELECTOR_TO_ENTRY(newsel
), &entry
);
244 /***********************************************************************
245 * LongPtrAdd (KERNEL.180)
247 void LongPtrAdd( DWORD ptr
, DWORD add
)
250 LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
252 LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr
)), &entry
);
256 /***********************************************************************
257 * GetSelectorBase (KERNEL.186)
259 DWORD
GetSelectorBase( WORD sel
)
261 return GET_SEL_BASE(sel
);
265 /***********************************************************************
266 * SetSelectorBase (KERNEL.187)
268 WORD
SetSelectorBase( WORD sel
, DWORD base
)
271 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
273 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
278 /***********************************************************************
279 * GetSelectorLimit (KERNEL.188)
281 DWORD
GetSelectorLimit( WORD sel
)
283 return GET_SEL_LIMIT(sel
);
287 /***********************************************************************
288 * SetSelectorLimit (KERNEL.189)
290 WORD
SetSelectorLimit( WORD sel
, DWORD limit
)
293 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
295 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
300 /***********************************************************************
301 * SelectorAccessRights (KERNEL.196)
303 WORD
SelectorAccessRights( WORD sel
, WORD op
, WORD val
)
306 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
307 if (op
== 0) /* get */
309 return 1 /* accessed */ |
310 (entry
.read_only
<< 1) |
312 (entry
.seg_32bit
<< 14) |
313 (entry
.limit_in_pages
<< 15);
317 entry
.read_only
= val
& 2;
318 entry
.type
= (val
>> 2) & 3;
319 entry
.seg_32bit
= val
& 0x4000;
320 entry
.limit_in_pages
= val
& 0x8000;
321 LDT_SetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
327 /***********************************************************************
328 * IsBadCodePtr (KERNEL.336)
330 BOOL
IsBadCodePtr( SEGPTR lpfn
)
335 sel
= SELECTOROF(lpfn
);
336 if (!sel
) return TRUE
;
337 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
338 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
339 if (entry
.type
!= SEGMENT_CODE
) return TRUE
;
340 if (OFFSETOF(lpfn
) > entry
.limit
) return TRUE
;
345 /***********************************************************************
346 * IsBadStringPtr (KERNEL.337)
348 BOOL
IsBadStringPtr( SEGPTR ptr
, WORD size
)
353 sel
= SELECTOROF(ptr
);
354 if (!sel
) return TRUE
;
355 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
356 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
357 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
358 if (strlen(PTR_SEG_TO_LIN(ptr
)) < size
) size
= strlen(PTR_SEG_TO_LIN(ptr
));
359 if (OFFSETOF(ptr
) + size
> entry
.limit
) return TRUE
;
364 /***********************************************************************
365 * IsBadHugeReadPtr (KERNEL.346)
367 BOOL
IsBadHugeReadPtr( SEGPTR ptr
, DWORD size
)
372 sel
= SELECTOROF(ptr
);
373 if (!sel
) return TRUE
;
374 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
375 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
376 if ((entry
.type
== SEGMENT_CODE
) && entry
.read_only
) return TRUE
;
377 if (OFFSETOF(ptr
) + size
> entry
.limit
) return TRUE
;
382 /***********************************************************************
383 * IsBadHugeWritePtr (KERNEL.347)
385 BOOL
IsBadHugeWritePtr( SEGPTR ptr
, DWORD size
)
390 sel
= SELECTOROF(ptr
);
391 if (!sel
) return TRUE
;
392 if (IS_SELECTOR_FREE(sel
)) return TRUE
;
393 LDT_GetEntry( SELECTOR_TO_ENTRY(sel
), &entry
);
394 if ((entry
.type
== SEGMENT_CODE
) || entry
.read_only
) return TRUE
;
395 if (OFFSETOF(ptr
) + size
> entry
.limit
) return TRUE
;
399 /***********************************************************************
400 * IsBadReadPtr (KERNEL.334)
402 BOOL
IsBadReadPtr( SEGPTR ptr
, WORD size
)
404 return IsBadHugeReadPtr( ptr
, size
);
408 /***********************************************************************
409 * IsBadWritePtr (KERNEL.335)
411 BOOL
IsBadWritePtr( SEGPTR ptr
, WORD size
)
413 return IsBadHugeWritePtr( ptr
, size
);
417 /***********************************************************************
418 * MemoryRead (TOOLHELP.78)
420 DWORD
MemoryRead( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
422 if (IS_SELECTOR_FREE(sel
)) return 0;
423 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
424 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
425 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
426 memcpy( buffer
, ((char *)GET_SEL_BASE(sel
)) + offset
, count
);
431 /***********************************************************************
432 * MemoryWrite (TOOLHELP.79)
434 DWORD
MemoryWrite( WORD sel
, DWORD offset
, void *buffer
, DWORD count
)
436 if (IS_SELECTOR_FREE(sel
)) return 0;
437 if (offset
> GET_SEL_LIMIT(sel
)) return 0;
438 if (offset
+ count
> GET_SEL_LIMIT(sel
) + 1)
439 count
= GET_SEL_LIMIT(sel
) + 1 - offset
;
440 memcpy( ((char *)GET_SEL_BASE(sel
)) + offset
, buffer
, count
);