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 */ 15 ULONG gcSizeDdHmgr = 1024; 16 PDD_ENTRY gpentDdHmgr = NULL; 17 18 ULONG gcMaxDdHmgr = 0; 19 PDD_ENTRY gpentDdHmgrLast = NULL; 20 21 /* next free ddhmg handle number available to reuse */ 22 ULONG ghFreeDdHmgr = 0; 23 HSEMAPHORE ghsemHmgr = NULL; 24 25 BOOL 26 FASTCALL 27 VerifyObjectOwner(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 *--*/ 47 BOOL 48 FASTCALL 49 DdHmgCreate(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 *--*/ 93 BOOL 94 FASTCALL 95 DdHmgDestroy(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 *--*/ 145 PVOID 146 FASTCALL 147 DdHmgLock(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 */ 201 PVOID 202 FASTCALL 203 DdAllocateObject(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 */ 233 VOID 234 FASTCALL 235 DdFreeObject(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 *--*/ 257 HANDLE 258 FASTCALL 259 DdGetFreeHandle(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 *--*/ 338 HANDLE 339 FASTCALL 340 DdHmgAlloc(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 *--*/ 401 VOID 402 FASTCALL 403 DdHmgFree(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 } 425