[DXG] Implement DdAllocateObject, DdFreeObject, DdGetFreeHandle, DdHmgAlloc, DdHmgFre...
[reactos.git] / reactos / win32ss / reactx / dxg / ddhmg.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Native driver for dxg implementation
5 * FILE: win32ss/reactx/dxg/ddhmg.c
6 * PROGRAMER: Magnus olsen (magnus@greatlord.com)
7 * REVISION HISTORY:
8 * 30/12-2007 Magnus Olsen
9 */
10
11 #include <dxg_int.h>
12
13 /* The DdHmgr manger stuff */
14 ULONG gcSizeDdHmgr = 1024;
15 PDD_ENTRY gpentDdHmgr = NULL;
16
17 ULONG gcMaxDdHmgr = 0;
18 PDD_ENTRY gpentDdHmgrLast = NULL;
19
20 /* next free ddhmg handle number available to reuse */
21 ULONG ghFreeDdHmgr = 0;
22 HSEMAPHORE ghsemHmgr = NULL;
23
24 BOOL
25 FASTCALL
26 VerifyObjectOwner(PDD_ENTRY pEntry)
27 {
28 DWORD Pid = (DWORD)(DWORD_PTR)PsGetCurrentProcessId() & 0xFFFFFFFC;
29 DWORD check = (DWORD)pEntry->Pid & 0xFFFFFFFE;
30 return ( (check == Pid) || (!check));
31 }
32
33 /*++
34 * @name DdHmgCreate
35 * @implemented
36 *
37 * The function DdHmgCreate is used internally in dxg.sys
38 * It creates all DX kernel objects that are need it for creation of DX objects.
39 *
40 * @return
41 * Return FALSE for failure and TRUE for success in creating the DX object
42 *
43 * @remarks.
44 * Only used internally in dxg.sys
45 *--*/
46 BOOL
47 FASTCALL
48 DdHmgCreate(VOID)
49 {
50 gpentDdHmgr = EngAllocMem(FL_ZERO_MEMORY, gcSizeDdHmgr * sizeof(DD_ENTRY), TAG_THDD);
51 ghFreeDdHmgr = 0;
52 gcMaxDdHmgr = 1;
53
54 if (gpentDdHmgr)
55 {
56 ghsemHmgr = EngCreateSemaphore();
57
58 if (ghsemHmgr)
59 {
60 gpLockShortDelay = EngAllocMem(FL_ZERO_MEMORY | FL_NONPAGED_MEMORY, sizeof(LARGE_INTEGER), TAG_GINI);
61
62 if (gpLockShortDelay)
63 {
64 gpLockShortDelay->HighPart = -1;
65 return TRUE;
66 }
67
68 EngDeleteSemaphore(ghsemHmgr);
69 ghsemHmgr = NULL;
70 }
71
72 EngFreeMem(gpentDdHmgr);
73 gpentDdHmgr = NULL;
74 }
75
76 return FALSE;
77 }
78
79 /*++
80 * @name DdHmgDestroy
81 * @implemented
82 *
83 * The function DdHmgDestroy is used internally in dxg.sys
84 * It destroys all DX kernel objects
85 *
86 * @return
87 * Always returns true, as a failure here would result in a BSOD.
88 *
89 * @remarks.
90 * Only used internally in dxg.sys
91 *--*/
92 BOOL
93 FASTCALL
94 DdHmgDestroy(VOID)
95 {
96 gcMaxDdHmgr = 0;
97 gcSizeDdHmgr = 0;
98 ghFreeDdHmgr = 0;
99 gpentDdHmgrLast = NULL;
100
101 if (gpentDdHmgr)
102 {
103 EngFreeMem(gpentDdHmgr);
104 gpentDdHmgr = NULL;
105 }
106
107 if (ghsemHmgr)
108 {
109 EngDeleteSemaphore(ghsemHmgr);
110 ghsemHmgr = NULL;
111 }
112
113 return TRUE;
114 }
115
116 /*++
117 * @name DdHmgLock
118 * @implemented
119 *
120 * The function DdHmgLock is used internally in dxg.sys
121 * It locks a DX kernel object
122 *
123 * @param HANDLE DdHandle
124 * The handle we want locked
125 *
126 * @param UCHAR ObjectType
127 * The type of the object we expected the handle to contain
128 * value 0 is for ?
129 * value 1 is for EDD_DIRECTDRAW_LOCAL
130 * value 2 is for EDD_SURFACE
131 * value 3 is for ?
132 * value 4 is for EDD_VIDEOPORT
133 * value 5 is for EDD_MOTIONCOMP
134
135 * @param BOOLEAN LockOwned
136 * If it needs to call EngAcquireSemaphore or not
137 *
138 * @return
139 * Returns an EDD_* object, or NULL if it fails
140 *
141 * @remarks.
142 * Only used internally in dxg.sys
143 *--*/
144 PVOID
145 FASTCALL
146 DdHmgLock(HANDLE DdHandle, UCHAR ObjectType, BOOLEAN LockOwned)
147 {
148 DWORD Index = DDHMG_HTOI(DdHandle);
149
150 PDD_ENTRY pEntry = NULL;
151 PVOID Object = NULL;
152
153 if ( !LockOwned )
154 {
155 EngAcquireSemaphore(ghsemHmgr);
156 }
157
158 if ( Index < gcMaxDdHmgr )
159 {
160 pEntry = (PDD_ENTRY)((PBYTE)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
161
162 if ( VerifyObjectOwner(pEntry) )
163 {
164 if ( ( pEntry->Objt == ObjectType ) &&
165 ( pEntry->FullUnique == (((ULONG)DdHandle >> 21) & 0x7FF) ) &&
166 ( !pEntry->pobj->cExclusiveLock ) )
167 {
168 InterlockedIncrement((VOID*)&pEntry->pobj->cExclusiveLock);
169 pEntry->pobj->Tid = KeGetCurrentThread();
170 Object = pEntry->pobj;
171 }
172 }
173 }
174
175 if ( !LockOwned )
176 {
177 EngDeleteSemaphore(ghsemHmgr);
178 }
179
180 return Object;
181 }
182
183 /*++
184 * @name DdAllocateObject
185 * @implemented
186 *
187 * The function DdAllocateObject is used internally in dxg.sys
188 * It allocates memory for a DX kernel object
189 *
190 * @param UINT32 oSize
191 * Size of memory to be allocated
192 * @param UCHAR oType
193 * Object type
194 * @param BOOLEAN oZeroMemory
195 * Zero memory
196 *
197 * @remarks.
198 * Only used internally in dxg.sys
199 */
200 PVOID
201 FASTCALL
202 DdAllocateObject(ULONG objSize, UCHAR objType, BOOLEAN objZeroMemory)
203 {
204 PVOID pObject = NULL;
205
206 if (objZeroMemory)
207 pObject = EngAllocMem(FL_ZERO_MEMORY, objSize, ((ULONG)objType << 24) + TAG_DH_0);
208 else
209 pObject = EngAllocMem(0, objSize, ((ULONG)objType << 24) + TAG_DH_0);
210
211 if (!pObject)
212 {
213 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
214 }
215
216 return pObject;
217 }
218
219 /*++
220 * @name DdFreeObject
221 * @implemented
222 *
223 * The function DdFreeObject is used internally in dxg.sys
224 * It frees memory of DX kernel object
225 *
226 * @param PVOID pObject
227 * Object memory to be freed
228 *
229 * @remarks.
230 * Only used internally in dxg.sys
231 */
232 VOID
233 FASTCALL
234 DdFreeObject(PVOID pObject)
235 {
236 EngFreeMem(pObject);
237 }
238
239
240 /*++
241 * @name DdGetFreeHandle
242 * @implemented
243 *
244 * The function DdGetFreeHandle is used internally in dxg.sys
245 * It allocates new handle for specified object type
246 *
247 * @param UCHAR oType
248 * Object type
249 *
250 * @return
251 * Returns handle or 0 if it fails.
252 *
253 * @remarks.
254 * Only used internally in dxg.sys
255 *--*/
256 HANDLE
257 FASTCALL
258 DdGetFreeHandle(UCHAR objType)
259 {
260 PVOID mAllocMem = NULL;
261 ULONG mAllocEntries = 0;
262 PDD_ENTRY pEntry = NULL;
263 ULONG retVal;
264 ULONG index;
265
266 // check if memory is allocated
267 if (!gpentDdHmgr)
268 return 0;
269
270 // check if we reached maximum handle index
271 if (gcMaxDdHmgr == DDHMG_HANDLE_LIMIT)
272 return 0;
273
274 // check if we have free handle to reuse
275 if (ghFreeDdHmgr)
276 {
277 index = ghFreeDdHmgr;
278 pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * index));
279
280 // put next free index to our global variable
281 ghFreeDdHmgr = pEntry->NextFree;
282
283 // build handle
284 pEntry->FullUnique = objType | 8;
285 retVal = (pEntry->FullUnique << 21) | index;
286 return (HANDLE)retVal;
287 }
288
289 // if all pre-allocated memory is already used then allocate more
290 if (gcSizeDdHmgr == gcMaxDdHmgr)
291 {
292 // allocate buffer for next 1024 handles
293 mAllocEntries = gcSizeDdHmgr + 1024;
294 mAllocMem = EngAllocMem(FL_ZERO_MEMORY, sizeof(DD_ENTRY) * (mAllocEntries), TAG_THDD);
295 if (!mAllocMem)
296 return 0;
297
298 memmove(&mAllocMem, gpentDdHmgr, sizeof(DD_ENTRY) * gcSizeDdHmgr);
299 gcSizeDdHmgr = mAllocEntries;
300 gpentDdHmgrLast = gpentDdHmgr;
301 EngFreeMem(gpentDdHmgr);
302 gpentDdHmgr = mAllocMem;
303 }
304
305 pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * gcMaxDdHmgr));
306
307 // build handle
308 pEntry->FullUnique = objType | 8;
309 retVal = (pEntry->FullUnique << 21) | gcMaxDdHmgr;
310 gcMaxDdHmgr = gcMaxDdHmgr + 1;
311
312 return (HANDLE)retVal;
313 }
314
315 /*++
316 * @name DdHmgAlloc
317 * @implemented
318 *
319 * The function DdHmgAlloc is used internally in dxg.sys
320 * It allocates object
321 *
322 * @param ULONG objSize
323 * Size of memory to be allocated
324 * @param CHAR objType
325 * Object type
326 * @param UINT objFlags
327 * Object flags
328 *
329 * @return
330 * Handle if object is not locked by objFlags
331 * Object if lock is set in objFlags
332 * 0 if it fails.
333 *
334 * @remarks.
335 * Only used internally in dxg.sys
336 *--*/
337 HANDLE
338 FASTCALL
339 DdHmgAlloc(ULONG objSize, CHAR objType, UINT objFlags)
340 {
341 PVOID pObject = NULL;
342 HANDLE DdHandle = NULL;
343 PDD_ENTRY pEntry = NULL;
344 DWORD Index;
345
346 pObject = DdAllocateObject(objSize, objType, TRUE);
347 if (!pObject)
348 return 0;
349
350 EngAcquireSemaphore(ghsemHmgr);
351
352 /* Get next free handle */
353 DdHandle = DdGetFreeHandle(objType);
354
355 if (DdHandle)
356 {
357 Index = DDHMG_HTOI(DdHandle);
358
359 pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
360
361 pEntry->pobj = pObject;
362 pEntry->Objt = objType;
363
364 pEntry->Pid = (HANDLE)(((ULONG)PsGetCurrentProcessId() & 0xFFFFFFFC) | ((ULONG)(pEntry->Pid) & 1));
365
366 if (objFlags & 1)
367 pEntry->pobj->Tid = KeGetCurrentThread();
368
369 pEntry->pobj->cExclusiveLock = objFlags & 1;
370 pEntry->pobj->hHmgr = DdHandle;
371
372 EngReleaseSemaphore(ghsemHmgr);
373
374 /* Return handle if object not locked */
375 if (!(objFlags & 1))
376 return DdHandle;
377
378 return (HANDLE)pEntry;
379 }
380
381 EngReleaseSemaphore(ghsemHmgr);
382 DdFreeObject(pObject);
383 return 0;
384 }
385
386 /*++
387 * @name DdHmgFree
388 * @implemented
389 *
390 * The function DdHmgFree is used internally in dxg.sys
391 * It frees DX object and memory allocated to it
392 *
393 * @param HANDLE DdHandle
394 * DX object handle
395 *
396 * @remarks.
397 * Only used internally in dxg.sys
398 *--*/
399 VOID
400 FASTCALL
401 DdHmgFree(HANDLE DdHandle)
402 {
403 PDD_ENTRY pEntry = NULL;
404
405 DWORD Index = DDHMG_HTOI(DdHandle);
406
407 EngAcquireSemaphore(ghsemHmgr);
408
409 pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
410
411 // check if we have object that should be freed
412 if (pEntry->pobj)
413 DdFreeObject(pEntry->pobj);
414
415 pEntry->NextFree = ghFreeDdHmgr;
416
417 // reset process ID
418 pEntry->Pid = (HANDLE)((DWORD)pEntry->Pid & 1);
419 ghFreeDdHmgr = Index;
420
421 EngReleaseSemaphore(ghsemHmgr);
422 }