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