Reactos
at master 424 lines 9.4 kB view raw
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}