Minor changes.
[reactos.git] / reactos / lib / kernel32 / mem / global.c
1 /* $Id: global.c,v 1.4 2000/07/01 17:07:00 ea Exp $
2 *
3 * Win32 Global/Local heap functions (GlobalXXX, LocalXXX).
4 * These functions included in Win32 for compatibility with 16 bit Windows
5 * Especially the moveable blocks and handles are oldish.
6 * But the ability to directly allocate memory with GPTR and LPTR is widely
7 * used.
8 */
9
10 #include <windows.h>
11
12 #define NDEBUG
13 #include <kernel32/kernel32.h>
14
15 #define MAGIC_GLOBAL_USED 0x5342BEEF
16 #define GLOBAL_LOCK_MAX 0xFF
17
18 typedef struct __GLOBAL_LOCAL_HANDLE
19 {
20 ULONG Magic;
21 LPVOID Pointer;
22 BYTE Flags;
23 BYTE LockCount;
24 } GLOBAL_HANDLE, LOCAL_HANDLE, *PGLOBAL_HANDLE, *PLOCAL_HANDLE;
25
26 /*********************************************************************
27 * GlobalAlloc -- KERNEL32 *
28 *********************************************************************/
29 HGLOBAL WINAPI GlobalAlloc(UINT flags, DWORD size)
30 {
31 PGLOBAL_HANDLE phandle;
32 LPVOID palloc;
33
34 DPRINT("GlobalAlloc( 0x%X, 0x%lX )\n", flags, size );
35
36 if((flags & GMEM_MOVEABLE)==0) /* POINTER */
37 {
38 palloc=HeapAlloc(__ProcessHeap, 0, size);
39 return (HGLOBAL) palloc;
40 }
41 else /* HANDLE */
42 {
43 HeapLock(__ProcessHeap);
44
45
46 phandle=__HeapAllocFragment(__ProcessHeap, 0, sizeof(GLOBAL_HANDLE));
47 if(size)
48 {
49 palloc=HeapAlloc(__ProcessHeap, 0, size+sizeof(HANDLE));
50 *(PHANDLE)palloc=(HANDLE) &(phandle->Pointer);
51 phandle->Pointer=palloc+sizeof(HANDLE);
52 }
53 else
54 phandle->Pointer=NULL;
55 phandle->Magic=MAGIC_GLOBAL_USED;
56 phandle->Flags=flags>>8;
57 phandle->LockCount=0;
58 HeapUnlock(__ProcessHeap);
59
60 return (HGLOBAL) &(phandle->Pointer);
61 }
62 }
63
64 /*********************************************************************
65 * GlobalLock -- KERNEL32 *
66 *********************************************************************/
67 LPVOID WINAPI GlobalLock(HGLOBAL hmem)
68 {
69 PGLOBAL_HANDLE phandle;
70 LPVOID palloc;
71
72 DPRINT("GlobalLock( 0x%lX )\n", (ULONG) hmem );
73
74 if(((ULONG)hmem%8)==0)
75 return (LPVOID) hmem;
76
77 HeapLock(__ProcessHeap);
78 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
79 if(phandle->Magic==MAGIC_GLOBAL_USED)
80 {
81 if(phandle->LockCount<GLOBAL_LOCK_MAX)
82 phandle->LockCount++;
83 palloc=phandle->Pointer;
84 }
85 else
86 {
87 DPRINT("GlobalLock: invalid handle\n");
88 palloc=(LPVOID) hmem;
89 }
90 HeapUnlock(__ProcessHeap);
91 return palloc;
92 }
93
94 /*********************************************************************
95 * GlobalUnlock -- KERNEL32 *
96 *********************************************************************/
97 BOOL WINAPI GlobalUnlock(HGLOBAL hmem)
98 {
99 PGLOBAL_HANDLE phandle;
100 BOOL locked;
101
102 DPRINT("GlobalUnlock( 0x%lX )\n", (ULONG) hmem );
103
104 if(((ULONG)hmem%8)==0)
105 return FALSE;
106
107 HeapLock(__ProcessHeap);
108 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
109 if(phandle->Magic==MAGIC_GLOBAL_USED)
110 {
111 if((phandle->LockCount<GLOBAL_LOCK_MAX)&&(phandle->LockCount>0))
112 phandle->LockCount--;
113
114 locked=(phandle->LockCount==0) ? TRUE : FALSE;
115 }
116 else
117 {
118 DPRINT("GlobalUnlock: invalid handle\n");
119 locked=FALSE;
120 }
121 HeapUnlock(__ProcessHeap);
122 return locked;
123 }
124
125 /*********************************************************************
126 * GlobalHandle -- KERNEL32 *
127 *********************************************************************/
128 HGLOBAL WINAPI GlobalHandle(LPCVOID pmem)
129 {
130 DPRINT("GlobalHandle( 0x%lX )\n", (ULONG) pmem );
131
132 if(((ULONG)pmem%8)==0) /* FIXED */
133 return (HGLOBAL) pmem;
134 else /* MOVEABLE */
135 return (HGLOBAL) *(LPVOID *)(pmem-sizeof(HANDLE));
136 }
137
138 /*********************************************************************
139 * GlobalReAlloc -- KERNEL32 *
140 *********************************************************************/
141 HGLOBAL WINAPI GlobalReAlloc(HGLOBAL hmem, DWORD size, UINT flags)
142 {
143 LPVOID palloc;
144 HGLOBAL hnew;
145 PGLOBAL_HANDLE phandle;
146
147 DPRINT("GlobalReAlloc( 0x%lX, 0x%lX, 0x%X )\n", (ULONG) hmem, size, flags );
148
149 hnew=NULL;
150 HeapLock(__ProcessHeap);
151 if(flags & GMEM_MODIFY) /* modify flags */
152 {
153 if( (((ULONG)hmem%8)==0) && (flags & GMEM_MOVEABLE))
154 {
155 /* make a fixed block moveable
156 * actually only NT is able to do this. And it's soo simple
157 */
158 size=HeapSize(__ProcessHeap, 0, (LPVOID) hmem);
159 hnew=GlobalAlloc( flags, size);
160 palloc=GlobalLock(hnew);
161 memcpy(palloc, (LPVOID) hmem, size);
162 GlobalUnlock(hnew);
163 GlobalHeapFree(GetProcessHeap(),0,hmem);
164 }
165 else if((((ULONG)hmem%8) != 0)&&(flags & GMEM_DISCARDABLE))
166 {
167 /* change the flags to make our block "discardable" */
168 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
169 phandle->Flags = phandle->Flags | (GMEM_DISCARDABLE >> 8);
170 hnew=hmem;
171 }
172 else
173 {
174 SetLastError(ERROR_INVALID_PARAMETER);
175 hnew=NULL;
176 }
177 }
178 else
179 {
180 if(((ULONG)hmem%8)!=0)
181 {
182 /* reallocate fixed memory */
183 hnew=(HANDLE)HeapReAlloc(__ProcessHeap, 0, (LPVOID) hmem, size);
184 }
185 else
186 {
187 /* reallocate a moveable block */
188 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
189 if(phandle->LockCount!=0)
190 SetLastError(ERROR_INVALID_HANDLE);
191 else if(size!=0)
192 {
193 hnew=hmem;
194 if(phandle->Pointer)
195 {
196 palloc=HeapReAlloc(__ProcessHeap, 0,
197 phandle->Pointer-sizeof(HANDLE),
198 size+sizeof(HANDLE) );
199 phandle->Pointer=palloc+sizeof(HANDLE);
200 }
201 else
202 {
203 palloc=HeapAlloc(__ProcessHeap, 0, size+sizeof(HANDLE));
204 *(PHANDLE)palloc=hmem;
205 phandle->Pointer=palloc+sizeof(HANDLE);
206 }
207 }
208 else
209 {
210 if(phandle->Pointer)
211 {
212 HeapHeapFree(GetProcessHeap(),0,__ProcessHeap, 0, phandle->Pointer-sizeof(HANDLE));
213 phandle->Pointer=NULL;
214 }
215 }
216 }
217 }
218 HeapUnlock(__ProcessHeap);
219 return hnew;
220 }
221
222 /*********************************************************************
223 * GlobalFree -- KERNEL32 *
224 *********************************************************************/
225 HGLOBAL WINAPI GlobalHeapFree(GetProcessHeap(),0,HGLOBAL hmem)
226 {
227 PGLOBAL_HANDLE phandle;
228
229 DPRINT("GlobalHeapFree(GetProcessHeap(),0, 0x%lX )\n", (ULONG) hmem );
230
231 if(((ULONG)hmem%4)==0) /* POINTER */
232 {
233 HeapHeapFree(GetProcessHeap(),0,__ProcessHeap, 0, (LPVOID) hmem);
234 }
235 else /* HANDLE */
236 {
237 HeapLock(__ProcessHeap);
238 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
239 if(phandle->Magic==MAGIC_GLOBAL_USED)
240 {
241 HeapLock(__ProcessHeap);
242 if(phandle->LockCount!=0)
243 SetLastError(ERROR_INVALID_HANDLE);
244 if(phandle->Pointer)
245 HeapHeapFree(GetProcessHeap(),0,__ProcessHeap, 0, phandle->Pointer-sizeof(HANDLE));
246 __HeapFreeFragment(__ProcessHeap, 0, phandle);
247 }
248 HeapUnlock(__ProcessHeap);
249 }
250 return hmem;
251 }
252
253 /*********************************************************************
254 * GlobalSize -- KERNEL32 *
255 *********************************************************************/
256 DWORD WINAPI GlobalSize(HGLOBAL hmem)
257 {
258 DWORD retval;
259 PGLOBAL_HANDLE phandle;
260
261 DPRINT("GlobalSize( 0x%lX )\n", (ULONG) hmem );
262
263 if(((ULONG)hmem%8)==0)
264 {
265 retval=HeapSize(__ProcessHeap, 0, hmem);
266 }
267 else
268 {
269 HeapLock(__ProcessHeap);
270 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
271 if(phandle->Magic==MAGIC_GLOBAL_USED)
272 {
273 retval=HeapSize(__ProcessHeap, 0, (phandle->Pointer)-sizeof(HANDLE))-4;
274 }
275 else
276 {
277 DPRINT("GlobalSize: invalid handle\n");
278 retval=0;
279 }
280 HeapUnlock(__ProcessHeap);
281 }
282 return retval;
283 }
284
285 /*********************************************************************
286 * GlobalWire -- KERNEL32 *
287 *********************************************************************/
288 LPVOID WINAPI GlobalWire(HGLOBAL hmem)
289 {
290 return GlobalLock( hmem );
291 }
292
293 /*********************************************************************
294 * GlobalUnWire -- KERNEL32 *
295 *********************************************************************/
296 BOOL WINAPI GlobalUnWire(HGLOBAL hmem)
297 {
298 return GlobalUnlock( hmem);
299 }
300
301 /*********************************************************************
302 * GlobalFix -- KERNEL32 *
303 *********************************************************************/
304 VOID WINAPI GlobalFix(HGLOBAL hmem)
305 {
306 GlobalLock( hmem );
307 }
308
309 /*********************************************************************
310 * GlobalUnfix -- KERNEL32 *
311 *********************************************************************/
312 VOID WINAPI GlobalUnfix(HGLOBAL hmem)
313 {
314 GlobalUnlock( hmem);
315 }
316
317 /*********************************************************************
318 * GlobalFlags -- KERNEL32 *
319 *********************************************************************/
320 UINT WINAPI GlobalFlags(HGLOBAL hmem)
321 {
322 return LocalFlags( (HLOCAL) hmem);
323 }
324
325 /* EOF */