Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2840 lines
82 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: os.cxx *
  3. * *
  4. * Convenient functions to access the OS interface. *
  5. * *
  6. * Created: 29-Aug-1989 19:59:05 *
  7. * Author: Charles Whitmer [chuckwh] *
  8. * *
  9. * Copyright (c) 1989-1999 Microsoft Corporation *
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. #include "muclean.hxx"
  13. #include "winstaw.h"
  14. extern BOOL G_fConsole;
  15. extern PFILE_OBJECT G_RemoteVideoFileObject;
  16. extern "C" USHORT gProtocolType;
  17. /******************************Public*Routine******************************\
  18. * EngGetProcessHandle
  19. *
  20. * Returns the current thread of the application.
  21. *
  22. * History:
  23. * 24-Jan-1996 -by- Andre Vachon [andreva]
  24. * Wrote it.
  25. \**************************************************************************/
  26. HANDLE APIENTRY EngGetProcessHandle()
  27. {
  28. return (HANDLE) NULL;
  29. }
  30. /******************************Public*Routine******************************\
  31. * EngGetCurrentProcessId
  32. *
  33. * Returns the current process id of the application.
  34. *
  35. * History:
  36. * 28-May-1999 -by- Barton House [bhouse]
  37. * Wrote it.
  38. \**************************************************************************/
  39. HANDLE APIENTRY EngGetCurrentProcessId()
  40. {
  41. return PsGetCurrentProcessId();
  42. }
  43. /******************************Public*Routine******************************\
  44. * EngGetCurrentThreadId
  45. *
  46. * Returns the current thread id of the application.
  47. *
  48. * History:
  49. * 28-May-1999 -by- Barton House [bhouse]
  50. * Wrote it.
  51. \**************************************************************************/
  52. HANDLE APIENTRY EngGetCurrentThreadId()
  53. {
  54. return PsGetCurrentThreadId();
  55. }
  56. #if !defined(_GDIPLUS_)
  57. // Kernel-mode version
  58. /******************************Public*Routine******************************\
  59. * GreCreateSemaphore
  60. *
  61. * Create a semaphore with tracking.
  62. *
  63. * For use by GDI internal code. Tracking
  64. * allows semaphores to be released during MultiUserNtGreCleanup (Hydra)
  65. * cleanup.
  66. *
  67. * Warning! For code dealing with pool/semaphore tracking, as
  68. * in pooltrk.cxx and muclean.cxx, do not create semaphores with
  69. * this function, as it may call functions which use those semaphores. Instead,
  70. * use GreCreateSemaphoreNonTracked and GreDeleteSemaphoreNonTracked.
  71. *
  72. * Return Value:
  73. *
  74. * Handle for new semaphore or NULL
  75. *
  76. * History:
  77. *
  78. * 25-May-1995 - Changed to PERESOURCE
  79. * 19-May-1998 - Changed to HSEMAPHORE.
  80. * Merged AcquireGreResource with hsemCreateTracked
  81. * to create this function.
  82. *
  83. \**************************************************************************/
  84. HSEMAPHORE
  85. GreCreateSemaphore()
  86. {
  87. return GreCreateSemaphoreInternal(OBJ_ENGINE_CREATED);
  88. }
  89. HSEMAPHORE
  90. GreCreateSemaphoreInternal(ULONG CreateFlag)
  91. {
  92. PERESOURCE pres;
  93. ULONGSIZE_T cj = sizeof(ERESOURCE);
  94. //
  95. // Adjust size to include ENGTRACKHDR header.
  96. //
  97. cj += sizeof(ENGTRACKHDR);
  98. //
  99. // Allocate ERESOURCE (must be nonpaged pool).
  100. //
  101. pres = (PERESOURCE) GdiAllocPoolNonPagedNS(cj, 'mesG');
  102. if (pres)
  103. {
  104. //
  105. // Adjust resource to exclude the ENGTRACKHDR.
  106. //
  107. // Buffer
  108. // pethNew --> +----------------+
  109. // | ENGTRACKHDR |
  110. // pres --> +----------------+
  111. // | ERESOURCE |
  112. // | |
  113. // +----------------+
  114. //
  115. // Note that pethNew always points to base of allocation.
  116. //
  117. ENGTRACKHDR *pethNew = (ENGTRACKHDR *) pres;
  118. pres = (PERESOURCE) (pethNew + 1);
  119. //
  120. // Initialize the resource.
  121. //
  122. if (NT_SUCCESS(ExInitializeResourceLite(pres)))
  123. {
  124. //
  125. // Track the resource.
  126. //
  127. if (CreateFlag & OBJ_DRIVER_CREATED) {
  128. MultiUserGreTrackAddEngResource(pethNew, ENGTRACK_DRIVER_SEMAPHORE);
  129. } else {
  130. MultiUserGreTrackAddEngResource(pethNew, ENGTRACK_SEMAPHORE);
  131. }
  132. }
  133. else
  134. {
  135. GdiFreePool(pethNew);
  136. pres = NULL;
  137. }
  138. }
  139. return (HSEMAPHORE) pres;
  140. }
  141. /******************************Public*Routine******************************\
  142. * GreDeleteSemaphore
  143. *
  144. * Deletes the given semaphore.
  145. *
  146. \**************************************************************************/
  147. VOID
  148. GreDeleteSemaphore(
  149. HSEMAPHORE hsem
  150. )
  151. {
  152. PERESOURCE pres = (PERESOURCE) hsem;
  153. if (pres)
  154. {
  155. ENGTRACKHDR *pethVictim = (ENGTRACKHDR *) pres;
  156. //
  157. // Need to adjust peth pointer to header.
  158. //
  159. // Note: whether Hydra or non-Hydra, pethVictim will always
  160. // point to the base of the allocation.
  161. //
  162. //
  163. // Remove victim from tracking list.
  164. //
  165. pethVictim -= 1;
  166. MultiUserGreTrackRemoveEngResource(pethVictim);
  167. ASSERTGDI(pres->OwnerThreads[0].OwnerThread
  168. != (ERESOURCE_THREAD) PsGetCurrentThread(),
  169. "The resource is being deleted while it's still held!");
  170. ExDeleteResourceLite(pres);
  171. GdiFreePool(pethVictim);
  172. }
  173. }
  174. /******************************Public*Routine******************************\
  175. * GreCreateSemaphoreNonTracked
  176. *
  177. * Create a semaphore, without pool-tracking or semaphore-tracking.
  178. *
  179. * Only for use by the pool-tracking and semaphore-tracking code. This
  180. * avoids the circular dependency which using GreCreateSemaphore would
  181. * cause.
  182. *
  183. * Return Value:
  184. *
  185. * Handle for new semaphore or NULL
  186. *
  187. \**************************************************************************/
  188. HSEMAPHORE
  189. GreCreateSemaphoreNonTracked()
  190. {
  191. PERESOURCE pres;
  192. pres = (PERESOURCE) ExAllocatePoolWithTag(
  193. (POOL_TYPE)NonPagedPool,
  194. sizeof(ERESOURCE), 'mesG');
  195. if (pres)
  196. {
  197. if (!NT_SUCCESS(ExInitializeResourceLite(pres)))
  198. {
  199. ExFreePool(pres);
  200. pres = NULL;
  201. }
  202. }
  203. return (HSEMAPHORE) pres;
  204. }
  205. /******************************Public*Routine******************************\
  206. * GreDeleteSemaphoreNonTracked
  207. *
  208. * Deletes the given non-tracked semaphore.
  209. *
  210. \**************************************************************************/
  211. VOID
  212. GreDeleteSemaphoreNonTracked(
  213. HSEMAPHORE hsem
  214. )
  215. {
  216. PERESOURCE pres = (PERESOURCE) hsem;
  217. if (pres)
  218. {
  219. ASSERTGDI(pres->OwnerThreads[0].OwnerThread
  220. != (ERESOURCE_THREAD) PsGetCurrentThread(),
  221. "The resource is being deleted while it's still held!");
  222. ExDeleteResourceLite(pres);
  223. ExFreePool(pres);
  224. }
  225. }
  226. #ifdef VALIDATE_LOCKS
  227. BOOL gDebugSem = TRUE;
  228. BOOL gDebugSemBreak = FALSE;
  229. #define SEM_HISTORY_LENGTH 4
  230. typedef struct {
  231. const char *name;
  232. const char *func;
  233. const char *file;
  234. int line;
  235. } SemHistory;
  236. typedef struct SemEntry {
  237. HSEMAPHORE hsem;
  238. ULONG count;
  239. ULONG order;
  240. HSEMAPHORE parent;
  241. #if SEM_HISTORY_LENGTH
  242. SemHistory Acquired[SEM_HISTORY_LENGTH];
  243. #endif
  244. } SemEntry;
  245. #define kMaxSemEntries 64
  246. typedef struct SemTable {
  247. FLONG flags;
  248. ULONG numEntries;
  249. SemEntry entries[kMaxSemEntries];
  250. } SemTable;
  251. /******************************Public*Routine******************************\
  252. * SemTrace::SemTrace *
  253. \**************************************************************************/
  254. SemTrace::SemTrace(FLONG SetFlags)
  255. {
  256. DontClearMask = ~0;
  257. if (gDebugSem && gDebugSemBreak)
  258. {
  259. pThread = W32GetCurrentThread();
  260. if(pThread != NULL)
  261. {
  262. SemTable *pSemTable = (SemTable *) pThread->pSemTable;
  263. if(pSemTable != NULL)
  264. {
  265. DontClearMask = pSemTable->flags | ~SetFlags;
  266. if (DontClearMask != ~0)
  267. {
  268. DbgPrint(" ** Enabling additional sem tracing for W32THREAD @ %p, SemTable @ %p\n", pThread, pSemTable);
  269. pSemTable->flags |= SetFlags;
  270. }
  271. }
  272. }
  273. }
  274. }
  275. /******************************Public*Routine******************************\
  276. * SemTrace::~SemTrace *
  277. \**************************************************************************/
  278. SemTrace::~SemTrace()
  279. {
  280. // Have anything to clear?
  281. if (DontClearMask != ~0)
  282. {
  283. SemTable *pSemTable = (SemTable *)pThread->pSemTable;
  284. if (pSemTable)
  285. {
  286. DbgPrint(" ** Disabling additional sem tracing for W32THREAD @ %p, SemTable @ %p\n", pThread, pSemTable);
  287. pSemTable->flags &= DontClearMask;
  288. }
  289. else
  290. {
  291. DbgPrint(" ** Couldn't disable added sem tracing for W32THREAD @ %p; SemTable is NULL\n", pThread);
  292. }
  293. }
  294. }
  295. /*****************************Private*Routine******************************\
  296. * FindSemEntry *
  297. \**************************************************************************/
  298. SemEntry * FindSemEntry(SemTable * pTable, HSEMAPHORE hsem)
  299. {
  300. SemEntry * entry = pTable->entries;
  301. SemEntry * sentry = entry + pTable->numEntries;
  302. while(entry < sentry)
  303. {
  304. if(entry->hsem == hsem)
  305. return entry;
  306. entry++;
  307. }
  308. return NULL;
  309. }
  310. /*****************************Private*Routine******************************\
  311. * RemoveSemEntry *
  312. \**************************************************************************/
  313. void
  314. RemoveSemEntry(
  315. SemTable *pTable,
  316. SemEntry *entry,
  317. const char *name,
  318. const char *func,
  319. const char *file,
  320. int line
  321. )
  322. {
  323. SemEntry *sentry;
  324. SemEntry OldEntry;
  325. ASSERTGDI(pTable->numEntries > 0, "numEntries is invalid");
  326. ASSERTGDI(entry < pTable->entries + pTable->numEntries, "entry is invalid");
  327. OldEntry = *entry;
  328. pTable->numEntries--;
  329. sentry = &pTable->entries[pTable->numEntries];
  330. if (entry != sentry)
  331. {
  332. DbgPrint("Locks released out of acquisition order\n");
  333. DbgPrint(" Now releasing order %4d %s (%X) in %s @ %s:%d\n",
  334. entry->order, name, entry->hsem, func, file, line);
  335. while (entry < sentry)
  336. {
  337. *entry = *(entry + 1);
  338. #if SEM_HISTORY_LENGTH
  339. DbgPrint(" Warning: Still holding order %4d %s (%X) %u times\n"
  340. " First acquired in %s @ %s:%d\n",
  341. entry->order,
  342. entry->Acquired[0].name,
  343. entry->hsem,
  344. entry->count,
  345. entry->Acquired[0].func,
  346. entry->Acquired[0].file,
  347. entry->Acquired[0].line
  348. );
  349. #else
  350. DbgPrint(" Warning: Still holding order %4d %s (%X) %u times\n",
  351. entry->order, entry->hsem, entry->count
  352. );
  353. #endif
  354. if (OldEntry.hsem == entry->parent)
  355. {
  356. DbgPrint(" * Error: Releasing parent before child.\n");
  357. }
  358. else if (OldEntry.parent == entry->parent && OldEntry.order < entry->order)
  359. {
  360. DbgPrint(" * Error: Higher order semaphore is still held.\n");
  361. }
  362. entry++;
  363. }
  364. if (gDebugSemBreak)
  365. {
  366. DbgBreakPoint();
  367. }
  368. }
  369. if (pTable->flags & ST_SAVE_RELEASES)
  370. {
  371. // Maintain a history of released locks
  372. //
  373. sentry = &pTable->entries[kMaxSemEntries-1];
  374. while(entry < sentry)
  375. {
  376. *entry = *(entry + 1);
  377. entry++;
  378. }
  379. *sentry = OldEntry;
  380. }
  381. }
  382. /******************************Public*Routine******************************\
  383. * GreReleaseSemaphoreAndValidate *
  384. * *
  385. * Call via GreAcquireSemaphoreEx with VALIDATE_LOCKS enabled. *
  386. \**************************************************************************/
  387. VOID
  388. GreAcquireSemaphoreAndValidate(
  389. HSEMAPHORE hsem,
  390. ULONG order,
  391. HSEMAPHORE parent,
  392. const char *name,
  393. const char *func,
  394. const char *file,
  395. int line
  396. )
  397. {
  398. GDIFunctionID(GreAcquireSemaphoreAndValidate);
  399. GreAcquireSemaphore(hsem);
  400. if(gDebugSem)
  401. {
  402. PW32THREAD pThread = W32GetCurrentThread();
  403. if(pThread != NULL)
  404. {
  405. SemTable *pSemTable = (SemTable *) pThread->pSemTable;
  406. if(pSemTable == NULL)
  407. {
  408. pThread->pSemTable = PALLOCMEM(sizeof(SemTable), 'dtdG');
  409. pSemTable = (SemTable *) pThread->pSemTable;
  410. if(pSemTable != NULL)
  411. {
  412. pThread->pSemTable = (PVOID)pSemTable;
  413. pSemTable->flags = ST_DEFAULT;
  414. pSemTable->numEntries = 0;
  415. }
  416. }
  417. if(pSemTable != NULL)
  418. {
  419. SemEntry *pSemEntry = FindSemEntry(pSemTable, hsem);
  420. if(pSemEntry != NULL)
  421. {
  422. if (pSemTable->flags & ST_VERBOSE)
  423. {
  424. DbgPrint("SemTrace: Reacquire (%d) order %4d %24s (%X) in %s @ %s:%d\n",
  425. pSemEntry->count, order, name, hsem, func, file, line);
  426. }
  427. if (order != pSemEntry->order)
  428. {
  429. DbgPrint("* Different order specification (%d) for %24s (%X) in %s @ %s:%d\n"
  430. " Originally acquired with order %d as %s in %s @ %s:%d (%d acquisitions)\n",
  431. order, name, hsem, func, file, line,
  432. pSemEntry->order,
  433. pSemEntry->Acquired[0].name,
  434. pSemEntry->Acquired[0].func,
  435. pSemEntry->Acquired[0].file,
  436. pSemEntry->Acquired[0].line,
  437. pSemEntry->count
  438. );
  439. }
  440. #if SEM_HISTORY_LENGTH > 1
  441. if (pSemEntry->count < SEM_HISTORY_LENGTH)
  442. {
  443. pSemEntry->Acquired[pSemEntry->count].name = name;
  444. pSemEntry->Acquired[pSemEntry->count].func = func;
  445. pSemEntry->Acquired[pSemEntry->count].file = file;
  446. pSemEntry->Acquired[pSemEntry->count].line = line;
  447. }
  448. #endif
  449. pSemEntry->count++;
  450. }
  451. else
  452. {
  453. if (pSemTable->flags & ST_VERBOSE)
  454. {
  455. DbgPrint("SemTrace: Now acquiring order %4d %24s (%X) in %s @ %s:%d\n",
  456. order, name, hsem, func, file, line);
  457. }
  458. ASSERTGDI(pSemTable->numEntries < kMaxSemEntries, "too many entries");
  459. pSemEntry = &pSemTable->entries[pSemTable->numEntries++];
  460. pSemEntry->hsem = hsem;
  461. pSemEntry->order = order;
  462. pSemEntry->parent = parent;
  463. pSemEntry->count = 1;
  464. #if SEM_HISTORY_LENGTH
  465. pSemEntry->Acquired[0].name = name;
  466. pSemEntry->Acquired[0].func = func;
  467. pSemEntry->Acquired[0].file = file;
  468. pSemEntry->Acquired[0].line = line;
  469. #endif
  470. // Check order
  471. if(parent != NULL)
  472. {
  473. if(FindSemEntry(pSemTable, parent) == NULL)
  474. {
  475. DbgPrint("Parent semaphore not acquired");
  476. if (gDebugSemBreak)
  477. {
  478. DbgBreakPoint();
  479. }
  480. }
  481. }
  482. SemEntry * entry = pSemTable->entries;
  483. SemEntry * sentry = entry + pSemTable->numEntries;
  484. BOOL Misordered = FALSE;
  485. while(entry < sentry)
  486. {
  487. if(entry->parent == parent && entry->order > order)
  488. {
  489. if (!Misordered)
  490. {
  491. DbgPrint("Locks obtained out of order\n");
  492. if (!(pSemTable->flags & ST_VERBOSE))
  493. {
  494. DbgPrint(" Now acqquiring order %4d %24s (%X) in %s @ %s:%d\n",
  495. order, name, hsem, func, file, line);
  496. }
  497. Misordered = TRUE;
  498. }
  499. #if SEM_HISTORY_LENGTH
  500. DbgPrint(" Conflicts with order %4d %24s (%X) first acquired in %s @ %s:%d with %d acquisitions\n",
  501. entry->order,
  502. entry->Acquired[0].name,
  503. entry->hsem,
  504. entry->Acquired[0].func,
  505. entry->Acquired[0].file,
  506. entry->Acquired[0].line,
  507. entry->count
  508. );
  509. #else
  510. DbgPrint(" Conflicts with order %4d (%X)\n",
  511. entry->order, entry->hsem
  512. );
  513. #endif
  514. }
  515. entry++;
  516. }
  517. if (Misordered && gDebugSemBreak)
  518. {
  519. DbgBreakPoint();
  520. }
  521. }
  522. }
  523. }
  524. }
  525. }
  526. /******************************Public*Routine******************************\
  527. * GreReleaseSemaphoreAndValidate *
  528. * *
  529. * Call via GreReleaseSemaphoreEx with VALIDATE_LOCKS enabled. *
  530. \**************************************************************************/
  531. VOID
  532. GreReleaseSemaphoreAndValidate(
  533. HSEMAPHORE hsem,
  534. const char *name,
  535. const char *func,
  536. const char *file,
  537. int line
  538. )
  539. {
  540. GDIFunctionID(GreReleaseSemaphoreAndValidate);
  541. if(gDebugSem)
  542. {
  543. PW32THREAD pThread = W32GetCurrentThread();
  544. if(pThread != NULL)
  545. {
  546. SemTable * pSemTable = (SemTable *) pThread->pSemTable;
  547. if(pSemTable != NULL)
  548. {
  549. SemEntry * pSemEntry = FindSemEntry(pSemTable, hsem);
  550. ASSERTGDI(pSemEntry != NULL, "error finding sem");
  551. if(pSemEntry != NULL)
  552. {
  553. pSemEntry->count--;
  554. if (pSemTable->flags & ST_VERBOSE)
  555. {
  556. if (pSemEntry->count)
  557. {
  558. DbgPrint("TraceSem: Releasing (%d) order %4d %24s (%X) in %s @ %s:%d\n",
  559. pSemEntry->count, pSemEntry->order, name, hsem, func, file, line);
  560. }
  561. else
  562. {
  563. DbgPrint("TraceSem: Fully release order %4d %24s (%X) in %s @ %s:%d\n",
  564. pSemEntry->order, name, hsem, func, file, line);
  565. }
  566. }
  567. #if SEM_HISTORY_LENGTH > 1
  568. if (pSemTable->flags & ST_SAVE_RELEASES)
  569. {
  570. // Maintain a history of releases
  571. //
  572. SemHistory *entry = &pSemEntry->Acquired[pSemEntry->count];
  573. SemHistory *sentry = &pSemEntry->Acquired[SEM_HISTORY_LENGTH-1];
  574. SemHistory OldAcquisition = *entry;
  575. while(entry < sentry)
  576. {
  577. *entry = *(entry + 1);
  578. entry++;
  579. }
  580. *sentry = OldAcquisition;
  581. }
  582. #endif
  583. if(pSemEntry->count == 0)
  584. {
  585. RemoveSemEntry(pSemTable, pSemEntry, name, func, file, line);
  586. }
  587. }
  588. }
  589. }
  590. }
  591. GreReleaseSemaphore(hsem);
  592. }
  593. #endif
  594. /******************************Public*Routine******************************\
  595. * GreAcquireSemaphore *
  596. \**************************************************************************/
  597. VOID
  598. FASTCALL GreAcquireSemaphore(
  599. HSEMAPHORE hsem
  600. )
  601. {
  602. //
  603. // This if is here for cleanup code
  604. // Generic cleanup code needs to
  605. // acquire the semaphore, but in some cases
  606. // the semaphore either hasn't been created or it
  607. // has been thrown away already.
  608. //
  609. if (hsem)
  610. {
  611. KeEnterCriticalRegion();
  612. ExAcquireResourceExclusiveLite((PERESOURCE) hsem, TRUE);
  613. }
  614. else
  615. {
  616. #if DBG
  617. if (G_fConsole)
  618. {
  619. RIP("Tried to acquire a non-existant or deleted semaphore\n");
  620. }
  621. else
  622. {
  623. WARNING("Tried to acquire a non-existant or deleted semaphore\n");
  624. }
  625. #endif
  626. }
  627. }
  628. /******************************Public*Routine******************************\
  629. * GreAcquireSemaphoreShared *
  630. \**************************************************************************/
  631. VOID
  632. FASTCALL GreAcquireSemaphoreShared(
  633. HSEMAPHORE hsem
  634. )
  635. {
  636. //
  637. // This if is here for cleanup code
  638. // Generic cleanup code needs to
  639. // acquire the semaphore, but in some cases
  640. // the semaphore either hasn't been created or it
  641. // has been thrown away already.
  642. //
  643. if (hsem)
  644. {
  645. KeEnterCriticalRegion();
  646. ExAcquireResourceSharedLite((PERESOURCE) hsem, TRUE);
  647. }
  648. else
  649. {
  650. #if DBG
  651. if (G_fConsole)
  652. {
  653. RIP("Tried to acquire a non-existant or deleted semaphore\n");
  654. }
  655. else
  656. {
  657. WARNING("Tried to acquire a non-existant or deleted semaphore\n");
  658. }
  659. #endif
  660. }
  661. }
  662. /******************************Public*Routine******************************\
  663. * GreReleaseSemaphore *
  664. \**************************************************************************/
  665. VOID
  666. FASTCALL GreReleaseSemaphore(
  667. HSEMAPHORE hsem
  668. )
  669. {
  670. //
  671. // This if is here for cleanup code
  672. // Generic cleanup code needs to
  673. // acquire the semaphore, but in some cases
  674. // the semaphore either hasn't been created or it
  675. // has been thrown away already.
  676. //
  677. if (hsem)
  678. {
  679. ExReleaseResourceLite((PERESOURCE) hsem);
  680. KeLeaveCriticalRegion();
  681. }
  682. else
  683. {
  684. #if DBG
  685. if (G_fConsole)
  686. {
  687. RIP("Tried to release a non-existant or deleted semaphore\n");
  688. }
  689. else
  690. {
  691. WARNING("Tried to release a non-existant or deleted semaphore\n");
  692. }
  693. #endif
  694. }
  695. }
  696. /******************************Public*Routine******************************\
  697. * GreIsSemaphoreOwned *
  698. * *
  699. * Returns TRUE if the semaphore is currently held. *
  700. * *
  701. \**************************************************************************/
  702. BOOL
  703. GreIsSemaphoreOwned(
  704. HSEMAPHORE hsem
  705. )
  706. {
  707. return ((PERESOURCE) hsem)->ActiveCount != 0;
  708. }
  709. /******************************Public*Routine******************************\
  710. * GreIsSemaphoreOwnedByCurrentThread *
  711. * *
  712. * Returns TRUE if the current thread owns the semaphore, FALSE *
  713. * otherwise. *
  714. * *
  715. \**************************************************************************/
  716. BOOL
  717. GreIsSemaphoreOwnedByCurrentThread(
  718. HSEMAPHORE hsem
  719. )
  720. {
  721. return ((PERESOURCE) hsem)->OwnerThreads[0].OwnerThread ==
  722. (ERESOURCE_THREAD) PsGetCurrentThread();
  723. }
  724. /******************************Public*Routine******************************\
  725. * GreIsSemaphoreSharedByCurrentThread *
  726. * *
  727. * Returns TRUE if the current thread owns the semaphore, FALSE *
  728. * otherwise. *
  729. * *
  730. \**************************************************************************/
  731. BOOL
  732. GreIsSemaphoreSharedByCurrentThread(
  733. HSEMAPHORE hsem
  734. )
  735. {
  736. return ExIsResourceAcquiredSharedLite((PERESOURCE) hsem);
  737. }
  738. /******************************Public*Routine******************************\
  739. * GreCreateFastMutex *
  740. * *
  741. * Creates a fast mutex. Exactly like a semaphore, except it is not *
  742. * reentrant. Fast mutexes are not tracked either (since they do not need *
  743. * to be destroyed by the kernel.) Their pool may be tracked. *
  744. * *
  745. \**************************************************************************/
  746. HFASTMUTEX
  747. GreCreateFastMutex()
  748. {
  749. PFAST_MUTEX pfm;
  750. pfm = (PFAST_MUTEX) GdiAllocPoolNonPagedNS(sizeof(FAST_MUTEX),
  751. 'msfG');
  752. if (pfm)
  753. {
  754. ExInitializeFastMutex(pfm);
  755. }
  756. return (HFASTMUTEX) pfm;
  757. }
  758. /******************************Public*Routine******************************\
  759. * GreDeleteFastMutex *
  760. * *
  761. \**************************************************************************/
  762. VOID
  763. GreDeleteFastMutex(
  764. HFASTMUTEX hfm
  765. )
  766. {
  767. if (hfm) {
  768. GdiFreePool(hfm);
  769. }
  770. }
  771. /******************************Public*Routine******************************\
  772. * GreAcquireFastMutex *
  773. * *
  774. \**************************************************************************/
  775. VOID
  776. GreAcquireFastMutex(
  777. HFASTMUTEX hfm
  778. )
  779. {
  780. KeEnterCriticalRegion();
  781. ExAcquireFastMutex((PFAST_MUTEX) hfm);
  782. }
  783. /******************************Public*Routine******************************\
  784. * GreReleaseFastMutex *
  785. * *
  786. \**************************************************************************/
  787. VOID
  788. GreReleaseFastMutex(
  789. HFASTMUTEX hfm
  790. )
  791. {
  792. ExReleaseFastMutex((PFAST_MUTEX) hfm);
  793. KeLeaveCriticalRegion();
  794. }
  795. #else // _GDIPLUS_
  796. // User-mode version
  797. /******************************Public*Routine******************************\
  798. * GreCreateSemaphore
  799. *
  800. * Create a semaphore with tracking.
  801. *
  802. * For use by GDI internal code. Tracking
  803. * allows semaphores to be released during MultiUserNtGreCleanup
  804. * cleanup.
  805. *
  806. * Warning! For code dealing with pool/semaphore tracking, as
  807. * in pooltrk.cxx and muclean.cxx, do not create semaphores with
  808. * this function, as it may call functions which use those semaphores. Instead,
  809. * use GreCreateSemaphoreNonTracked and GreDeleteSemaphoreNonTracked.
  810. *
  811. * Return Value:
  812. *
  813. * Handle for new semaphore or NULL
  814. *
  815. \**************************************************************************/
  816. HSEMAPHORE
  817. GreCreateSemaphore()
  818. {
  819. return GreCreateSemaphoreInternal(OBJ_ENGINE_CREATED);
  820. }
  821. HSEMAPHORE
  822. GreCreateSemaphoreInternal(ULONG CreateFlag)
  823. {
  824. LPCRITICAL_SECTION pcs;
  825. SIZE_T cj = sizeof(CRITICAL_SECTION);
  826. //
  827. // Adjust size to include ENGTRACKHDR header.
  828. //
  829. >>
  830. cj += sizeof(ENGTRACKHDR);
  831. pcs = (LPCRITICAL_SECTION) RtlAllocateHeap(RtlProcessHeap(),
  832. 0,
  833. == sizeof(CRITICAL_SECTION));
  834. if (pcs)
  835. {
  836. //
  837. // Adjust semaphore to exclude the ENGTRACKHDR.
  838. //
  839. // Buffer
  840. // pethNew --> +------------------+
  841. // | ENGTRACKHDR |
  842. // pcs --> +------------------+
  843. // | CRITICAL_SECTION |
  844. // | |
  845. // +------------------+
  846. //
  847. // Note that pethNew always points to base of allocation.
  848. //
  849. ENGTRACKHDR *pethNew = (ENGTRACKHDR *) pcs;
  850. >>
  851. pcs = (LPCRITICAL_SECTION) (pethNew + 1);
  852. == //
  853. // Initialize the semaphore.
  854. //
  855. InitializeCriticalSection(pcs);
  856. //
  857. // Track the semaphore
  858. //
  859. >>
  860. if (CreateFlag & OBJ_DRIVER_CREATED) {
  861. MultiUserGreTrackAddEngResource(pethNew, ENGTRACK_DRIVER_SEMAPHORE);
  862. } else {
  863. MultiUserGreTrackAddEngResource(pethNew, ENGTRACK_SEMAPHORE);
  864. }
  865. == }
  866. return (HSEMAPHORE) pcs;
  867. }
  868. /******************************Public*Routine******************************\
  869. * GreDeleteSemaphore
  870. *
  871. * Deletes the given semaphore.
  872. *
  873. \**************************************************************************/
  874. VOID
  875. GreDeleteSemaphore(
  876. HSEMAPHORE hsem
  877. )
  878. {
  879. LPCRITICAL_SECTION pcs = (LPCRITICAL_SECTION) hsem;
  880. if (pcs)
  881. {
  882. ENGTRACKHDR *pethVictim = (ENGTRACKHDR *) pcs;
  883. //
  884. // Need to adjust peth pointer to header.
  885. //
  886. // Note: whether Hydra or non-Hydra, pethVictim will always
  887. // point to the base of the allocation.
  888. //
  889. >>
  890. //
  891. // Remove victim from tracking list.
  892. //
  893. pethVictim -= 1;
  894. MultiUserGreTrackRemoveEngResource(pethVictim);
  895. == DeleteCriticalSection(pcs);
  896. RtlFreeHeap(RtlProcessHeap(), 0, pethVictim);
  897. }
  898. }
  899. /******************************Public*Routine******************************\
  900. * GreCreateSemaphoreNonTracked
  901. *
  902. * Create a semaphore, without pool-tracking or semaphore-tracking.
  903. *
  904. * Only for use by the pool-tracking and semaphore-tracking code. This
  905. * avoids the circular dependency which using GreCreateSemaphore would
  906. * cause.
  907. *
  908. * Return Value:
  909. *
  910. * Handle for new semaphore or NULL
  911. *
  912. \**************************************************************************/
  913. HSEMAPHORE
  914. GreCreateSemaphoreNonTracked()
  915. {
  916. LPCRITICAL_SECTION pcs;
  917. pcs = (LPCRITICAL_SECTION) RtlAllocateHeap(RtlProcessHeap(),
  918. 0,
  919. sizeof(CRITICAL_SECTION));
  920. if (pcs)
  921. {
  922. //
  923. // Initialize the semaphore.
  924. //
  925. InitializeCriticalSection(pcs);
  926. }
  927. return (HSEMAPHORE) pcs;
  928. }
  929. /******************************Public*Routine******************************\
  930. * GreDeleteSemaphoreNonTracked
  931. *
  932. * Deletes the given non-tracked semaphore.
  933. *
  934. \**************************************************************************/
  935. VOID
  936. GreDeleteSemaphoreNonTracked(
  937. HSEMAPHORE hsem
  938. )
  939. {
  940. LPCRITICAL_SECTION pcs = (LPCRITICAL_SECTION) hsem;
  941. if (pcs)
  942. {
  943. DeleteCriticalSection(pcs);
  944. RtlFreeHeap(RtlProcessHeap(), 0, pcs);
  945. }
  946. }
  947. /******************************Public*Routine******************************\
  948. * GreAcquireSemaphore *
  949. \**************************************************************************/
  950. VOID
  951. GreAcquireSemaphore(
  952. HSEMAPHORE hsem
  953. )
  954. {
  955. EnterCriticalSection((LPCRITICAL_SECTION) hsem);
  956. }
  957. /******************************Public*Routine******************************\
  958. * GreReleaseSemaphore *
  959. \**************************************************************************/
  960. VOID
  961. GreReleaseSemaphore(
  962. HSEMAPHORE hsem
  963. )
  964. {
  965. LeaveCriticalSection((LPCRITICAL_SECTION) hsem);
  966. }
  967. /******************************Public*Routine******************************\
  968. * GreIsSemaphoreOwned *
  969. * *
  970. * Returns TRUE if the semaphore is currently held. *
  971. * *
  972. \**************************************************************************/
  973. BOOL
  974. GreIsSemaphoreOwned(
  975. HSEMAPHORE hsem
  976. )
  977. {
  978. return ((RTL_CRITICAL_SECTION *) hsem)->LockCount != -1;
  979. }
  980. /******************************Public*Routine******************************\
  981. * GreIsSemaphoreOwnedByCurrentThread *
  982. * *
  983. * Returns TRUE if the current thread owns the semaphore, FALSE *
  984. * otherwise. *
  985. * *
  986. \**************************************************************************/
  987. BOOL
  988. GreIsSemaphoreOwnedByCurrentThread(
  989. HSEMAPHORE hsem
  990. )
  991. {
  992. return ((RTL_CRITICAL_SECTION *) hsem)->OwningThread ==
  993. (HANDLE) GetCurrentThreadId();
  994. }
  995. /******************************Public*Routine******************************\
  996. * GreCreateFastMutex *
  997. * *
  998. * Creates a fast mutex. In this, the user mode version, it is exactly *
  999. * the same as a non-tracked semaphore.
  1000. * *
  1001. \**************************************************************************/
  1002. HFASTMUTEX
  1003. GreCreateFastMutex()
  1004. {
  1005. LPCRITICAL_SECTION pcs;
  1006. pcs = (LPCRITICAL_SECTION) RtlAllocateHeap(RtlProcessHeap(),
  1007. 0,
  1008. sizeof(CRITICAL_SECTION));
  1009. if (pcs)
  1010. {
  1011. //
  1012. // Initialize the semaphore.
  1013. //
  1014. InitializeCriticalSection(pcs);
  1015. }
  1016. return (HFASTMUTEX) pcs;
  1017. }
  1018. /******************************Public*Routine******************************\
  1019. * GreDeleteFastMutex *
  1020. * *
  1021. \**************************************************************************/
  1022. VOID
  1023. GreDeleteFastMutex(
  1024. HFASTMUTEX hfm
  1025. )
  1026. {
  1027. LPCRITICAL_SECTION pcs = (LPCRITICAL_SECTION) hfm;
  1028. if (pcs)
  1029. {
  1030. DeleteCriticalSection(pcs);
  1031. RtlFreeHeap(RtlProcessHeap(), 0, pcs);
  1032. }
  1033. }
  1034. /******************************Public*Routine******************************\
  1035. * GreAcquireFastMutex *
  1036. * *
  1037. \**************************************************************************/
  1038. VOID
  1039. GreAcquireFastMutex(
  1040. HFASTMUTEX hfm
  1041. )
  1042. {
  1043. EnterCriticalSection((LPCRITICAL_SECTION) hfm);
  1044. }
  1045. /******************************Public*Routine******************************\
  1046. * GreReleaseFastMutex *
  1047. * *
  1048. \**************************************************************************/
  1049. VOID
  1050. GreReleaseFastMutex(
  1051. HFASTMUTEX hfm
  1052. )
  1053. {
  1054. LeaveCriticalSection((LPCRITICAL_SECTION) hfm);
  1055. }
  1056. #endif // _GDIPLUS_
  1057. /******************************Public*Routines*****************************\
  1058. * GreAcquireHmgrSemaphore *
  1059. * GreReleaseHmgrSemaphore *
  1060. * *
  1061. * Convenience functions for the handle manager semaphore. *
  1062. * *
  1063. \**************************************************************************/
  1064. VOID
  1065. GreAcquireHmgrSemaphore()
  1066. {
  1067. GDIFunctionID(GreAcquireHmgrSemaphore);
  1068. GreAcquireSemaphoreEx(ghsemHmgr, SEMORDER_HMGR, NULL);
  1069. }
  1070. VOID
  1071. GreReleaseHmgrSemaphore()
  1072. {
  1073. GDIFunctionID(GreReleaseHmgrSemaphore);
  1074. GreReleaseSemaphoreEx(ghsemHmgr);
  1075. }
  1076. /******************************Public*Routine******************************\
  1077. * EngCreateSemaphore()
  1078. *
  1079. * History:
  1080. * 22-Feb-1995 -by- Andre Vachon [andreva]
  1081. * Wrote it.
  1082. \**************************************************************************/
  1083. HSEMAPHORE
  1084. EngCreateSemaphore(
  1085. VOID
  1086. )
  1087. {
  1088. return GreCreateSemaphoreInternal(OBJ_DRIVER_CREATED);
  1089. }
  1090. VOID
  1091. EngAcquireSemaphore(
  1092. HSEMAPHORE hsem
  1093. )
  1094. {
  1095. GreAcquireSemaphore(hsem);
  1096. W32THREAD * pThread = W32GetCurrentThread();
  1097. #ifdef CHECK_SEMAPHORE_USAGE
  1098. pThread->dwEngAcquireCount++;
  1099. #endif
  1100. }
  1101. VOID
  1102. EngReleaseSemaphore(
  1103. HSEMAPHORE hsem
  1104. )
  1105. {
  1106. W32THREAD * pThread = W32GetCurrentThread();
  1107. #ifdef CHECK_SEMAPHORE_USAGE
  1108. pThread->dwEngAcquireCount--;
  1109. #endif
  1110. GreReleaseSemaphore(hsem);
  1111. }
  1112. #ifdef CHECK_SEMAPHORE_USAGE
  1113. VOID
  1114. GreCheckSemaphoreUsage(
  1115. VOID
  1116. )
  1117. {
  1118. W32THREAD * pThread = W32GetCurrentThread();
  1119. ASSERTGDI(pThread->dwEngAcquireCount == 0, "EngAcquireCount non-zero\n");
  1120. }
  1121. #endif
  1122. VOID
  1123. EngDeleteSemaphore(
  1124. HSEMAPHORE hsem
  1125. )
  1126. {
  1127. GreDeleteSemaphore(hsem);
  1128. }
  1129. BOOL
  1130. EngIsSemaphoreOwned(
  1131. HSEMAPHORE hsem
  1132. )
  1133. {
  1134. return(GreIsSemaphoreOwned(hsem));
  1135. }
  1136. BOOL
  1137. EngIsSemaphoreOwnedByCurrentThread(
  1138. HSEMAPHORE hsem
  1139. )
  1140. {
  1141. return(GreIsSemaphoreOwnedByCurrentThread(hsem));
  1142. }
  1143. /******************************Public*Routine******************************\
  1144. *
  1145. * EngInitializeSafeSemaphore
  1146. * EngDeleteSafeSemaphore
  1147. *
  1148. * Manages semaphore lifetime in a reference-counted thread-safe manner.
  1149. *
  1150. * History:
  1151. * Wed Apr 16 18:23:40 1997 -by- Drew Bliss [drewb]
  1152. * Created
  1153. *
  1154. \**************************************************************************/
  1155. BOOL
  1156. EngInitializeSafeSemaphore(ENGSAFESEMAPHORE *pssem)
  1157. {
  1158. // Do create/destroy inside the handle manager global lock
  1159. // as a convenient way to synchronize them.
  1160. MLOCKFAST mlf;
  1161. ASSERTGDI(pssem->lCount >= 0, "InitSafeSem: bad lCount\n");
  1162. if (pssem->lCount == 0)
  1163. {
  1164. ASSERTGDI(pssem->hsem == NULL, "InitSafeSem: overwriting hsem\n");
  1165. pssem->hsem = GreCreateSemaphoreInternal(OBJ_DRIVER_CREATED);
  1166. if (pssem->hsem == NULL)
  1167. {
  1168. return FALSE;
  1169. }
  1170. }
  1171. pssem->lCount++;
  1172. return TRUE;
  1173. }
  1174. void
  1175. EngDeleteSafeSemaphore(ENGSAFESEMAPHORE *pssem)
  1176. {
  1177. // Do create/destroy inside the handle manager global lock
  1178. // as a convenient way to synchronize them.
  1179. MLOCKFAST mlf;
  1180. ASSERTGDI(pssem->lCount >= 1, "DeleteSafeSem: lCount underflow\n");
  1181. if (pssem->lCount == 1)
  1182. {
  1183. ASSERTGDI(pssem->hsem != NULL, "DeleteSafeSem: No hsem\n");
  1184. GreDeleteSemaphore(pssem->hsem);
  1185. pssem->hsem = NULL;
  1186. }
  1187. pssem->lCount--;
  1188. }
  1189. /******************************Public*Routine******************************\
  1190. * EngSetLastError
  1191. *
  1192. * Saves Error code passed in.
  1193. *
  1194. * History:
  1195. * Sat 31-Oct-1992 -by- Patrick Haluptzok [patrickh]
  1196. * Remove wrapper.
  1197. *
  1198. * 28-Oct-1992 -by- Bodin Dresevic [BodinD]
  1199. * Wrote it.
  1200. \**************************************************************************/
  1201. VOID EngSetLastError(ULONG iError)
  1202. {
  1203. //
  1204. // Warning: NtCurrentTeb() accesses the TEB structure via the
  1205. // KPCR structure. However, during session shutdown, the
  1206. // TEB ptr is set to zero in the TCB, but not the KPCR. So if
  1207. // code is callable during session shutdown, cannot invoke
  1208. // NtCurrentTeb. Use KeGetCurrentThread()->Teb instead.
  1209. //
  1210. PTEB pteb = (PTEB) PsGetCurrentThreadTeb();
  1211. if (pteb)
  1212. pteb->LastErrorValue = iError;
  1213. #if DBG
  1214. PSZ psz;
  1215. switch (iError)
  1216. {
  1217. case ERROR_INVALID_HANDLE:
  1218. psz = "ERROR_INVALID_HANDLE";
  1219. break;
  1220. case ERROR_NOT_ENOUGH_MEMORY:
  1221. psz = "ERROR_NOT_ENOUGH_MEMORY";
  1222. break;
  1223. case ERROR_INVALID_PARAMETER:
  1224. psz = "ERROR_INVALID_PARAMETER";
  1225. break;
  1226. case ERROR_BUSY:
  1227. psz = "ERROR_BUSY";
  1228. break;
  1229. case ERROR_ARITHMETIC_OVERFLOW:
  1230. psz = "ERROR_ARITHMETIC_OVERFLOW";
  1231. break;
  1232. case ERROR_INVALID_FLAGS:
  1233. psz = "ERROR_INVALID_FLAGS";
  1234. break;
  1235. case ERROR_CAN_NOT_COMPLETE:
  1236. psz = "ERROR_CAN_NOT_COMPLETE";
  1237. break;
  1238. default:
  1239. psz = "unknown error code";
  1240. break;
  1241. }
  1242. // DbgPrint("GRE Err: %s = 0x%04X\n", psz, (USHORT) iError);
  1243. #endif
  1244. }
  1245. /******************************Public*Routine******************************\
  1246. *
  1247. * History:
  1248. * 27-Jun-1995 -by- Eric Kutter [erick]
  1249. * Wrote it.
  1250. \**************************************************************************/
  1251. ULONG APIENTRY EngGetLastError()
  1252. {
  1253. ULONG ulError = 0;
  1254. //
  1255. // Warning: NtCurrentTeb() accesses the TEB structure via the
  1256. // KPCR structure. However, during session shutdown, the
  1257. // TEB ptr is set to zero in the TCB, but not the KPCR. So if
  1258. // code is callable during session shutdown, cannot invoke
  1259. // NtCurrentTeb. Use KeGetCurrentThread()->Teb instead.
  1260. //
  1261. PTEB pteb = (PTEB) PsGetCurrentThreadTeb();
  1262. if (pteb)
  1263. ulError = pteb->LastErrorValue;
  1264. return(ulError);
  1265. }
  1266. /******************************Public*Routine******************************\
  1267. * GreLockDisplay()
  1268. *
  1269. * History:
  1270. * 01-Nov-1994 -by- Andre Vachon [andreva]
  1271. * Wrote it.
  1272. \**************************************************************************/
  1273. VOID
  1274. APIENTRY
  1275. GreLockDisplay(
  1276. HDEV hdev
  1277. )
  1278. {
  1279. GDIFunctionID(GreLockDisplay);
  1280. PDEVOBJ pdo(hdev);
  1281. GreAcquireSemaphoreEx(pdo.hsemDevLock(), SEMORDER_DEVLOCK, NULL);
  1282. GreEnterMonitoredSection(pdo.ppdev, WD_DEVLOCK);
  1283. }
  1284. /******************************Public*Routine******************************\
  1285. * GreUnlockDisplay()
  1286. *
  1287. * History:
  1288. * 01-Nov-1994 -by- Andre Vachon [andreva]
  1289. * Wrote it.
  1290. \**************************************************************************/
  1291. VOID
  1292. APIENTRY
  1293. GreUnlockDisplay(
  1294. HDEV hdev
  1295. )
  1296. {
  1297. GDIFunctionID(GreUnlockDisplay);
  1298. PDEVOBJ pdo(hdev);
  1299. GreExitMonitoredSection(pdo.ppdev, WD_DEVLOCK);
  1300. GreReleaseSemaphoreEx(pdo.hsemDevLock());
  1301. }
  1302. #if DBG
  1303. /******************************Public*Routine******************************\
  1304. * GreIsDisplayLocked()
  1305. *
  1306. * History:
  1307. * 10-Jun-1998 -by- Lingyun Wang [lingyunw]
  1308. * Wrote it.
  1309. \**************************************************************************/
  1310. BOOL
  1311. APIENTRY
  1312. GreIsDisplayLocked(
  1313. HDEV hdev
  1314. )
  1315. {
  1316. PDEVOBJ pdo(hdev);
  1317. if (GreIsSemaphoreOwnedByCurrentThread(pdo.hsemDevLock()))
  1318. {
  1319. return (TRUE);
  1320. }
  1321. else
  1322. {
  1323. return (FALSE);
  1324. }
  1325. }
  1326. #endif
  1327. /***************************************************************************\
  1328. * EngDebugPrint
  1329. *
  1330. * History:
  1331. * 02-Feb-1995 -by- Andre Vachon [andreva]
  1332. * Wrote it.
  1333. \***************************************************************************/
  1334. VOID
  1335. EngDebugPrint(
  1336. PCHAR StandardPrefix,
  1337. PCHAR DebugMessage,
  1338. va_list ap
  1339. )
  1340. {
  1341. char buffer[256];
  1342. int len;
  1343. //
  1344. // We prepend the STANDARD_DEBUG_PREFIX to each string, and
  1345. // append a new-line character to the end:
  1346. //
  1347. DbgPrint(StandardPrefix);
  1348. vsprintf(buffer, DebugMessage, ap);
  1349. DbgPrint(buffer);
  1350. }
  1351. /******************************Public*Routine******************************\
  1352. * EngDebugBreak()
  1353. *
  1354. * History:
  1355. * 16-Feb-1995 -by- Andre Vachon [andreva]
  1356. * Wrote it.
  1357. \**************************************************************************/
  1358. VOID
  1359. APIENTRY
  1360. EngDebugBreak(
  1361. VOID
  1362. )
  1363. {
  1364. DbgBreakPoint();
  1365. }
  1366. /******************************Public*Routine******************************\
  1367. * EngDebugBreak()
  1368. *
  1369. * History:
  1370. * 7-Dec-2001 -by- Jonathan Schwartz [JSchwart]
  1371. * Wrote it.
  1372. \**************************************************************************/
  1373. VOID
  1374. APIENTRY
  1375. EngBugCheckEx(
  1376. IN ULONG BugCheckCode,
  1377. IN ULONG_PTR P1,
  1378. IN ULONG_PTR P2,
  1379. IN ULONG_PTR P3,
  1380. IN ULONG_PTR P4
  1381. )
  1382. {
  1383. KeBugCheckEx(BugCheckCode, P1, P2, P3, P4);
  1384. }
  1385. /******************************Public*Routine******************************\
  1386. * EngAllocMem()
  1387. *
  1388. * History:
  1389. * 27-May-1995 -by- Tom Zakrajsek [tomzak]
  1390. * Added a flags parameter to allow zeroing of memory.
  1391. *
  1392. * 02-Feb-1995 -by- Andre Vachon [andreva]
  1393. * Wrote it.
  1394. \**************************************************************************/
  1395. PVOID
  1396. EngAllocMem(
  1397. ULONG fl,
  1398. ULONG cj,
  1399. ULONG tag
  1400. )
  1401. {
  1402. PVOID pvRet;
  1403. //
  1404. // Don't trust the driver to only ask for non-zero length buffers.
  1405. //
  1406. if (cj == 0)
  1407. return(NULL);
  1408. //
  1409. // Adjust size to include ENGTRACKHDR header.
  1410. //
  1411. // Sundown note: sizeof(ENGTRACKHDR) will fit in 32-bit, so ULONG cast OK
  1412. //
  1413. if (cj <= (MAXULONG - sizeof(ENGTRACKHDR)))
  1414. cj += ((ULONG) sizeof(ENGTRACKHDR));
  1415. else
  1416. return(NULL);
  1417. if (cj >= (PAGE_SIZE * 10000))
  1418. {
  1419. WARNING("EngAllocMem: temp buffer >= 10000 pages");
  1420. return(NULL);
  1421. }
  1422. if (fl & FL_NONPAGED_MEMORY)
  1423. {
  1424. pvRet = GdiAllocPoolNonPaged(cj,tag);
  1425. }
  1426. else
  1427. {
  1428. pvRet = GdiAllocPool(cj,tag);
  1429. }
  1430. if (fl & FL_ZERO_MEMORY)
  1431. {
  1432. if (pvRet)
  1433. {
  1434. RtlZeroMemory(pvRet,cj);
  1435. }
  1436. }
  1437. if (pvRet)
  1438. {
  1439. //
  1440. // Add allocation to the tracking list.
  1441. //
  1442. ENGTRACKHDR *pethNew = (ENGTRACKHDR *) pvRet;
  1443. MultiUserGreTrackAddEngResource(pethNew, ENGTRACK_ALLOCMEM);
  1444. //
  1445. // Adjust return pointer to hide the LIST_ENTRY header.
  1446. //
  1447. pvRet = (PVOID) (pethNew + 1);
  1448. }
  1449. return pvRet;
  1450. }
  1451. /******************************Public*Routine******************************\
  1452. * EngFreeMem()
  1453. *
  1454. * History:
  1455. * 02-Feb-1995 -by- Andre Vachon [andreva]
  1456. * Wrote it.
  1457. \**************************************************************************/
  1458. VOID
  1459. EngFreeMem(
  1460. PVOID pv
  1461. )
  1462. {
  1463. if (pv)
  1464. {
  1465. //
  1466. // Remove victim from tracking list.
  1467. //
  1468. ENGTRACKHDR *pethVictim = ((ENGTRACKHDR *) pv) - 1;
  1469. MultiUserGreTrackRemoveEngResource(pethVictim);
  1470. //
  1471. // Adjust pointer to base of allocation.
  1472. //
  1473. pv = (PVOID) pethVictim;
  1474. VFREEMEM(pv);
  1475. }
  1476. return;
  1477. }
  1478. /******************************Public*Routine******************************\
  1479. * EngProbeForRead()
  1480. *
  1481. * History:
  1482. * 02-Oct-1995 -by- Andre Vachon [andreva]
  1483. * Wrote it.
  1484. \**************************************************************************/
  1485. VOID
  1486. EngProbeForRead(
  1487. PVOID Address,
  1488. ULONG Length,
  1489. ULONG Alignment
  1490. )
  1491. {
  1492. ProbeForRead(Address, Length, Alignment);
  1493. }
  1494. /******************************Public*Routine******************************\
  1495. * GDIEngUserMemAllocNodeCompare()
  1496. *
  1497. * History:
  1498. * 18-Sep-2001 -by- Pravin Santiago [pravins]
  1499. * Wrote it.
  1500. \**************************************************************************/
  1501. RTL_GENERIC_COMPARE_RESULTS
  1502. GDIEngUserMemAllocNodeCompare(RTL_AVL_TABLE *Table,
  1503. PVOID FirstStruct,
  1504. PVOID SecondStruct)
  1505. {
  1506. PGDIENGUSERMEMALLOCNODE p1 = (PGDIENGUSERMEMALLOCNODE)FirstStruct;
  1507. PGDIENGUSERMEMALLOCNODE p2 = (PGDIENGUSERMEMALLOCNODE)SecondStruct;
  1508. return (p1->pUserMem > p2->pUserMem ) ? GenericGreaterThan : (p1->pUserMem < p2->pUserMem ) ? GenericLessThan : GenericEqual;
  1509. }
  1510. /******************************Public*Routine******************************\
  1511. * GDIEngUserMemAllocNodeAlloc()
  1512. *
  1513. * History:
  1514. * 18-Sep-2001 -by- Pravin Santiago [pravins]
  1515. * Wrote it.
  1516. \**************************************************************************/
  1517. PVOID
  1518. GDIEngUserMemAllocNodeAlloc(RTL_AVL_TABLE *Table,
  1519. CLONG Size)
  1520. {
  1521. return PALLOCNOZ(Size,'amUG');
  1522. }
  1523. /******************************Public*Routine******************************\
  1524. * GDIEngUserMemAllocNodeFree()
  1525. *
  1526. * History:
  1527. * 18-Sep-2001 -by- Pravin Santiago [pravins]
  1528. * Wrote it.
  1529. \**************************************************************************/
  1530. VOID
  1531. GDIEngUserMemAllocNodeFree(RTL_AVL_TABLE *Table,
  1532. PVOID Buffer)
  1533. {
  1534. VFREEMEM(Buffer);
  1535. }
  1536. /******************************Public*Routine******************************\
  1537. * EngAllocUserMem()
  1538. *
  1539. * This routine allocates a piece of memory for USER mode and locks it
  1540. * down. A driver must be very careful with this memory as it is only
  1541. * valid for this process.
  1542. *
  1543. * History:
  1544. * 10-Sep-1995 -by- Eric Kutter [erick]
  1545. * Wrote it.
  1546. \**************************************************************************/
  1547. PVOID
  1548. EngAllocUserMem(
  1549. SIZE_T cj, //ZwAllocateVirtualMemory uses SIZE_T, change accordingly
  1550. ULONG tag
  1551. )
  1552. {
  1553. NTSTATUS status;
  1554. PVOID pv = NULL;
  1555. HANDLE hSecure;
  1556. //
  1557. // Don't trust the driver to only ask for non-zero length buffers.
  1558. //
  1559. if (cj == 0)
  1560. return(NULL);
  1561. status = ZwAllocateVirtualMemory(
  1562. NtCurrentProcess(),
  1563. &pv,
  1564. 0,
  1565. &cj,
  1566. MEM_COMMIT | MEM_RESERVE,
  1567. PAGE_READWRITE);
  1568. if (NT_SUCCESS(status))
  1569. {
  1570. hSecure = MmSecureVirtualMemory(pv,cj,PAGE_READWRITE);
  1571. if (hSecure)
  1572. {
  1573. // Add the new allocation to the Process's GDIEngUserMemAllocTable
  1574. PW32PROCESS pW32Process = W32GetCurrentProcess();
  1575. GDIENGUSERMEMALLOCNODE tmpNode;
  1576. PGDIENGUSERMEMALLOCNODE pNewNode = 0;
  1577. BOOLEAN bNew = FALSE;
  1578. tmpNode.pUserMem = pv;
  1579. tmpNode.hSecure = hSecure;
  1580. tmpNode.cj = cj;
  1581. SIMPLELOCK sl(&pW32Process->GDIEngUserMemAllocTableLock);
  1582. pNewNode = (PGDIENGUSERMEMALLOCNODE)
  1583. RtlInsertElementGenericTableAvl(&pW32Process->GDIEngUserMemAllocTable,
  1584. &tmpNode,
  1585. sizeof(tmpNode),
  1586. &bNew);
  1587. ASSERTGDI((pNewNode && !bNew) != TRUE, "EngAllocUserMem: (pNewNode && !bNew) == TRUE\n");
  1588. if (pNewNode == 0 || bNew == FALSE)
  1589. {
  1590. MmUnsecureVirtualMemory(hSecure);
  1591. ZwFreeVirtualMemory(
  1592. NtCurrentProcess(),
  1593. &pv,
  1594. &cj,
  1595. MEM_RELEASE);
  1596. pv = NULL;
  1597. }
  1598. }
  1599. else
  1600. {
  1601. ZwFreeVirtualMemory(
  1602. NtCurrentProcess(),
  1603. &pv,
  1604. &cj,
  1605. MEM_RELEASE);
  1606. pv = NULL;
  1607. }
  1608. }
  1609. return(pv);
  1610. }
  1611. /******************************Public*Routize******************************\
  1612. * EngSecureMem()
  1613. *
  1614. * History:
  1615. * 02-Oct-1995 -by- Andre Vachon [andreva]
  1616. * Wrote it.
  1617. \**************************************************************************/
  1618. HANDLE
  1619. APIENTRY
  1620. EngSecureMem(
  1621. PVOID Address,
  1622. ULONG Length
  1623. )
  1624. {
  1625. return (MmSecureVirtualMemory(Address, Length, PAGE_READWRITE));
  1626. }
  1627. /******************************Public*Routine******************************\
  1628. * EngUnsecureMem()
  1629. *
  1630. * History:
  1631. * 02-Oct-1995 -by- Andre Vachon [andreva]
  1632. * Wrote it.
  1633. *
  1634. * Note: Forwarder only - no code needed
  1635. \**************************************************************************/
  1636. /******************************Public*Routine******************************\
  1637. * EngFreeUserMem()
  1638. *
  1639. * History:
  1640. * 10-Sep-1995 -by- Eric Kutter [erick]
  1641. * Wrote it.
  1642. \**************************************************************************/
  1643. VOID
  1644. EngFreeUserMem(
  1645. PVOID pv
  1646. )
  1647. {
  1648. if (pv)
  1649. {
  1650. // Lookup the allocation in the Process's GDIEngUserMemAllocTable
  1651. PW32PROCESS pW32Process = W32GetCurrentProcess();
  1652. GDIENGUSERMEMALLOCNODE lookupNode;
  1653. PGDIENGUSERMEMALLOCNODE pFoundNode;
  1654. lookupNode.pUserMem = pv;
  1655. SIMPLELOCK sl(&pW32Process->GDIEngUserMemAllocTableLock);
  1656. pFoundNode = (PGDIENGUSERMEMALLOCNODE)
  1657. RtlLookupElementGenericTableAvl(&pW32Process->GDIEngUserMemAllocTable,
  1658. &lookupNode);
  1659. // If found, Unsecure it, free it and remove entry from
  1660. // GDIEngUserMemAllocTable
  1661. if (pFoundNode)
  1662. {
  1663. ULONG_PTR cj = (ULONG_PTR) pFoundNode->cj;
  1664. HANDLE hSecure = pFoundNode->hSecure;
  1665. MmUnsecureVirtualMemory(hSecure);
  1666. ZwFreeVirtualMemory(
  1667. NtCurrentProcess(),
  1668. &pv,
  1669. &cj,
  1670. MEM_RELEASE);
  1671. lookupNode.pUserMem = pv;
  1672. RtlDeleteElementGenericTableAvl(&pW32Process->GDIEngUserMemAllocTable,
  1673. &lookupNode);
  1674. }
  1675. }
  1676. return;
  1677. }
  1678. /******************************Public*Routine******************************\
  1679. * EngDeviceIoControl()
  1680. *
  1681. * History:
  1682. * 04-Feb-1995 -by- Andre Vachon [andreva]
  1683. * Wrote it.
  1684. \**************************************************************************/
  1685. NTSTATUS
  1686. GreDeviceIoControl(
  1687. HANDLE hDevice,
  1688. DWORD dwIoControlCode,
  1689. LPVOID lpInBuffer,
  1690. DWORD nInBufferSize,
  1691. LPVOID lpOutBuffer,
  1692. DWORD nOutBufferSize,
  1693. LPDWORD lpBytesReturned
  1694. )
  1695. {
  1696. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  1697. IO_STATUS_BLOCK Iosb;
  1698. PIRP pIrp;
  1699. KEVENT event;
  1700. if (hDevice == NULL) {
  1701. return STATUS_INVALID_HANDLE;
  1702. }
  1703. if ( (nInBufferSize >= (PAGE_SIZE * 10000) ) ||
  1704. (nOutBufferSize >= (PAGE_SIZE * 10000)) ||
  1705. ((nInBufferSize + nOutBufferSize) >= (PAGE_SIZE * 10000))) {
  1706. WARNING("EngDeviceIoControl is asked to allocate >= 10000 pages");
  1707. return (STATUS_INVALID_PARAMETER);
  1708. }
  1709. KeInitializeEvent(&event,
  1710. SynchronizationEvent,
  1711. FALSE);
  1712. pIrp = IoBuildDeviceIoControlRequest(
  1713. dwIoControlCode,
  1714. (PDEVICE_OBJECT) hDevice,
  1715. lpInBuffer,
  1716. nInBufferSize,
  1717. lpOutBuffer,
  1718. nOutBufferSize,
  1719. FALSE,
  1720. &event,
  1721. &Iosb);
  1722. if (pIrp)
  1723. {
  1724. /*
  1725. * Even though the remote video channel emulates a video port, this
  1726. * code doesn't actually use a HANDLE it just uses a DEVICE_OBJECT.
  1727. * Unfortueately, there's only one of those for the remote video driver
  1728. * and so it's not Multi-Session enabled. Remember the file
  1729. * object handle and stuff it in the call here. (This code could
  1730. * be called from any process, but globals are in Session space.)
  1731. */
  1732. PIO_STACK_LOCATION irpSp;
  1733. if ( gProtocolType != PROTOCOL_CONSOLE ) {
  1734. irpSp = IoGetNextIrpStackLocation( pIrp );
  1735. irpSp->FileObject = G_RemoteVideoFileObject;
  1736. }
  1737. Status = IoCallDriver((PDEVICE_OBJECT) hDevice,
  1738. pIrp);
  1739. //
  1740. // If the call is synchronous, the IO is always completed
  1741. // and the Status is the same as the Iosb.Status.
  1742. //
  1743. if (Status == STATUS_PENDING) {
  1744. Status = KeWaitForSingleObject(&event,
  1745. UserRequest,
  1746. KernelMode,
  1747. TRUE,
  1748. NULL);
  1749. Status = Iosb.Status;
  1750. }
  1751. *lpBytesReturned = (DWORD)Iosb.Information;
  1752. }
  1753. return (Status);
  1754. }
  1755. DWORD
  1756. EngDeviceIoControl(
  1757. HANDLE hDevice,
  1758. DWORD dwIoControlCode,
  1759. LPVOID lpInBuffer,
  1760. DWORD nInBufferSize,
  1761. LPVOID lpOutBuffer,
  1762. DWORD nOutBufferSize,
  1763. LPDWORD lpBytesReturned
  1764. )
  1765. {
  1766. DWORD retStatus;
  1767. NTSTATUS Status = GreDeviceIoControl(hDevice,
  1768. dwIoControlCode,
  1769. lpInBuffer,
  1770. nInBufferSize,
  1771. lpOutBuffer,
  1772. nOutBufferSize,
  1773. lpBytesReturned);
  1774. //
  1775. // Do the inverse translation to what the video port does
  1776. // so that we can have the original win32 status codes.
  1777. //
  1778. // Maybe, somehow, we can completely eliminate this double
  1779. // translation - but I don't care for now. It's just a bit
  1780. // longer on the very odd failiure case
  1781. //
  1782. switch (Status) {
  1783. case STATUS_SUCCESS:
  1784. retStatus = NO_ERROR;
  1785. break;
  1786. case STATUS_NOT_IMPLEMENTED:
  1787. retStatus = ERROR_INVALID_FUNCTION;
  1788. break;
  1789. case STATUS_INSUFFICIENT_RESOURCES:
  1790. retStatus = ERROR_NOT_ENOUGH_MEMORY;
  1791. break;
  1792. case STATUS_INVALID_PARAMETER:
  1793. retStatus = ERROR_INVALID_PARAMETER;
  1794. break;
  1795. case STATUS_BUFFER_TOO_SMALL:
  1796. retStatus = ERROR_INSUFFICIENT_BUFFER;
  1797. break;
  1798. case STATUS_BUFFER_OVERFLOW:
  1799. retStatus = ERROR_MORE_DATA;
  1800. break;
  1801. case STATUS_PENDING:
  1802. retStatus = ERROR_IO_PENDING;
  1803. break;
  1804. case STATUS_DEVICE_DOES_NOT_EXIST:
  1805. retStatus = ERROR_DEV_NOT_EXIST;
  1806. break;
  1807. default:
  1808. retStatus = Status;
  1809. break;
  1810. }
  1811. return retStatus;
  1812. }
  1813. VOID
  1814. EngMultiByteToUnicodeN(
  1815. PWSTR UnicodeString,
  1816. ULONG MaxBytesInUnicodeString,
  1817. PULONG BytesInUnicodeString,
  1818. PCHAR MultiByteString,
  1819. ULONG BytesInMultiByteString
  1820. )
  1821. {
  1822. RtlMultiByteToUnicodeN(UnicodeString,
  1823. MaxBytesInUnicodeString,
  1824. BytesInUnicodeString,
  1825. MultiByteString,
  1826. BytesInMultiByteString);
  1827. }
  1828. VOID
  1829. EngUnicodeToMultiByteN(
  1830. PCHAR MultiByteString,
  1831. ULONG MaxBytesInMultiByteString,
  1832. PULONG BytesInMultiByteString,
  1833. PWSTR UnicodeString,
  1834. ULONG BytesInUnicodeString
  1835. )
  1836. {
  1837. RtlUnicodeToMultiByteN( MultiByteString,
  1838. MaxBytesInMultiByteString,
  1839. BytesInMultiByteString,
  1840. UnicodeString,
  1841. BytesInUnicodeString );
  1842. }
  1843. /******************************Public*Routine******************************\
  1844. * EngQueryPerformanceCounter
  1845. *
  1846. * Queries the performance counter.
  1847. *
  1848. * It would have been preferable to use 'KeQueryTickCount,' but has a
  1849. * resolution of about 10ms on an x86, which is not sufficient for
  1850. * getting an accurate measure of the time between vertical blanks, which
  1851. * is typically between 8ms and 17ms.
  1852. *
  1853. * NOTE: Use this routine sparingly, calling it as infrequently as possible!
  1854. * Calling this routine too frequently can degrade I/O performance
  1855. * for the calling driver and for the system as a whole.
  1856. *
  1857. * History:
  1858. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1859. * Wrote it.
  1860. \**************************************************************************/
  1861. VOID
  1862. APIENTRY
  1863. EngQueryPerformanceCounter(
  1864. LONGLONG *pPerformanceCount
  1865. )
  1866. {
  1867. LARGE_INTEGER li;
  1868. li = KeQueryPerformanceCounter(NULL);
  1869. *pPerformanceCount = *((LONGLONG*) &li);
  1870. }
  1871. /******************************Public*Routine******************************\
  1872. * EngQueryPerformanceFrequency
  1873. *
  1874. * Queries the resolution of the performance counter.
  1875. *
  1876. * History:
  1877. * 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
  1878. * Wrote it.
  1879. \**************************************************************************/
  1880. VOID
  1881. APIENTRY
  1882. EngQueryPerformanceFrequency(
  1883. LONGLONG *pFrequency
  1884. )
  1885. {
  1886. KeQueryPerformanceCounter((LARGE_INTEGER*) pFrequency);
  1887. }
  1888. /******************************Public*Routine******************************\
  1889. * EngAllocSectionMem
  1890. *
  1891. * Allocate mapped memory in session space.
  1892. *
  1893. * History:
  1894. * 23-Oct-2000 -by- Chenyin Zhong [chenyz]
  1895. * Wrote it.
  1896. \**************************************************************************/
  1897. PVOID
  1898. EngAllocSectionMem(
  1899. PVOID *pSectionObject,
  1900. ULONG fl,
  1901. ULONG cj,
  1902. ULONG tag
  1903. )
  1904. {
  1905. LARGE_INTEGER SectionSize;
  1906. PVOID pMappedBase;
  1907. NTSTATUS Status;
  1908. HANDLE hSecure;
  1909. SIZE_T MemSize = 0;
  1910. //
  1911. // Don't trust the driver to only ask for non-zero length buffers.
  1912. //
  1913. if (cj == 0)
  1914. return(NULL);
  1915. SectionSize.LowPart = cj;
  1916. SectionSize.HighPart = 0;
  1917. Status = Win32CreateSection(
  1918. pSectionObject,
  1919. SECTION_ALL_ACCESS,
  1920. (POBJECT_ATTRIBUTES)NULL,
  1921. &SectionSize,
  1922. PAGE_READWRITE,
  1923. SEC_COMMIT,
  1924. (HANDLE)NULL,
  1925. NULL,
  1926. tag);
  1927. if (!NT_SUCCESS(Status))
  1928. {
  1929. KdPrint(("MmCreateSection fails in EngAllocSectionMem with error code: 0x%x\n", Status));
  1930. return(NULL);
  1931. }
  1932. cj = 0;
  1933. pMappedBase = NULL;
  1934. Status = Win32MapViewInSessionSpace(*pSectionObject, &pMappedBase, &MemSize);
  1935. if (!NT_SUCCESS(Status))
  1936. {
  1937. KdPrint(("MmMapViewInSessionSpace fails in EngAllocSectionMem with error code: 0x%x\n", Status));
  1938. Win32DestroySection(*pSectionObject);
  1939. pMappedBase = NULL;
  1940. *pSectionObject = NULL;
  1941. }
  1942. cj = (ULONG)MemSize;
  1943. if (fl & FL_ZERO_MEMORY)
  1944. {
  1945. if (pMappedBase)
  1946. {
  1947. RtlZeroMemory(pMappedBase,cj);
  1948. }
  1949. }
  1950. return pMappedBase;
  1951. }
  1952. /******************************Public*Routine******************************\
  1953. * EngFreeSectionMem()
  1954. *
  1955. * History:
  1956. * 25-Oct-2000 -by- Chenyin Zhong [chenyz]
  1957. * Wrote it.
  1958. * 24-Jul-2002 -by- Ivan Leichtling [ivanlei]
  1959. * Added return value
  1960. \**************************************************************************/
  1961. BOOL
  1962. EngFreeSectionMem(
  1963. PVOID SectionObject,
  1964. PVOID pv
  1965. )
  1966. {
  1967. NTSTATUS Status;
  1968. BOOL bRet = TRUE;
  1969. if(pv)
  1970. {
  1971. Status = Win32UnmapViewInSessionSpace(pv);
  1972. if (!NT_SUCCESS(Status))
  1973. {
  1974. KdPrint(("MmUnmapViewInSessionSpace fails in EngFreeSectionMem with error code: 0x%x\n", Status));
  1975. RIP("MmUnmapViewInSessionSpace failed!");
  1976. bRet = FALSE;
  1977. }
  1978. }
  1979. if(SectionObject)
  1980. {
  1981. Win32DestroySection(SectionObject);
  1982. }
  1983. return bRet;
  1984. }
  1985. /******************************Public*Routine******************************\
  1986. * EngMapSection()
  1987. *
  1988. * History:
  1989. * 25-Oct-2000 -by- Chenyin Zhong [chenyz]
  1990. * Wrote it.
  1991. \**************************************************************************/
  1992. BOOL
  1993. EngMapSection(
  1994. PVOID SectionObject,
  1995. BOOL bMap,
  1996. HANDLE ProcessHandle,
  1997. PVOID *pMapBase
  1998. )
  1999. {
  2000. NTSTATUS Status;
  2001. PEPROCESS Process;
  2002. LARGE_INTEGER SectionOffset;
  2003. ULONG AllocationType = 0L;
  2004. SIZE_T ViewSize = 0;
  2005. SectionOffset.LowPart = 0;
  2006. SectionOffset.HighPart = 0;
  2007. Status = ObReferenceObjectByHandle(ProcessHandle,
  2008. PROCESS_VM_OPERATION,
  2009. NULL,
  2010. KernelMode,
  2011. (PVOID *)&Process,
  2012. NULL);
  2013. if(!NT_SUCCESS(Status))
  2014. {
  2015. return FALSE;
  2016. }
  2017. if(bMap) //Map section memory
  2018. {
  2019. *pMapBase = NULL;
  2020. Status = MmMapViewOfSection(SectionObject, // SectionToMap,
  2021. Process, // process
  2022. pMapBase, // CapturedBase,
  2023. 0L, // ZeroBits,
  2024. 0L, // CommitSize,
  2025. &SectionOffset, // SectionOffset,
  2026. &ViewSize, // CapturedViewSize,
  2027. ViewShare, // InheritDisposition,
  2028. AllocationType, // AllocationType,
  2029. PAGE_READWRITE); // Allow writing on this view
  2030. if(!NT_SUCCESS(Status))
  2031. {
  2032. ObDereferenceObject(Process);
  2033. *pMapBase = NULL;
  2034. KdPrint(("MmMapViewofSection fails in EngMapSection with error code: %u\n", Status));
  2035. return FALSE;
  2036. }
  2037. }
  2038. else //Unmap section memory
  2039. {
  2040. Status = MmUnmapViewOfSection (Process, *pMapBase);
  2041. if (!NT_SUCCESS(Status))
  2042. {
  2043. ObDereferenceObject(Process);
  2044. return FALSE;
  2045. }
  2046. }
  2047. ObDereferenceObject (Process);
  2048. return TRUE;
  2049. }
  2050. /******************************Public*Routine******************************\
  2051. * EngSave/RestoreFloatingPointState
  2052. *
  2053. * Saves the floating point state so that drivers can do floating point
  2054. * operations. If the state were no preserved and floating point operations
  2055. * were used, we would be corrupting the thread's user-mode state!
  2056. *
  2057. * History:
  2058. * 17-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  2059. * Wrote it.
  2060. \**************************************************************************/
  2061. typedef struct {
  2062. BOOL bSaved;
  2063. KFLOATING_SAVE fsFpState;
  2064. } FP_STATE_SAVE;
  2065. ULONG
  2066. APIENTRY
  2067. EngSaveFloatingPointState(
  2068. VOID *pBuffer,
  2069. ULONG cjBufferSize // Must be zero initialized
  2070. )
  2071. {
  2072. ULONG ulRet = 0;
  2073. FP_STATE_SAVE* pFpStateSave;
  2074. KFLOATING_SAVE fsTestState;
  2075. pFpStateSave = (FP_STATE_SAVE*) pBuffer;
  2076. if ((pFpStateSave == NULL) || (cjBufferSize == 0))
  2077. {
  2078. // Check to see if the processor supports floating point by
  2079. // simply seeing whether or not KeSaveFloatingPointState
  2080. // succeeds:
  2081. if (!NT_SUCCESS(KeSaveFloatingPointState(&fsTestState)))
  2082. {
  2083. // No floating point hardware.
  2084. return(ulRet);
  2085. }
  2086. KeRestoreFloatingPointState(&fsTestState);
  2087. return(sizeof(FP_STATE_SAVE));
  2088. }
  2089. if (cjBufferSize < sizeof(FP_STATE_SAVE))
  2090. {
  2091. KdPrint(("EngSaveFloatingPointState: The driver's buffer is too small.\n"));
  2092. KdPrint(("Floating point corruption in the application may result."));
  2093. RIP("The driver must be fixed!");
  2094. return(ulRet);
  2095. }
  2096. if (pFpStateSave->bSaved)
  2097. {
  2098. KdPrint(("EngSaveFloatingPointState: Your driver called save twice in a row.\n"));
  2099. KdPrint(("(Either that or it didn't zero initialize the buffer.)\n"));
  2100. KdPrint(("Floating point corruption in the application may result."));
  2101. RIP("The driver must be fixed!");
  2102. // No point in returning failure because at this point they're just
  2103. // plain hosed if they called Save twice in succession. If however
  2104. // they simply did not zero initialize the buffer, things would still
  2105. // be okay, because KeSaveFloatingPointState itself doesn't need the
  2106. // buffer to be zero initialized.
  2107. }
  2108. ulRet = NT_SUCCESS(KeSaveFloatingPointState(&pFpStateSave->fsFpState));
  2109. pFpStateSave->bSaved = (ulRet != 0);
  2110. return(ulRet);
  2111. }
  2112. BOOL
  2113. APIENTRY
  2114. EngRestoreFloatingPointState(
  2115. VOID *pBuffer
  2116. )
  2117. {
  2118. FP_STATE_SAVE* pFpStateSave;
  2119. pFpStateSave = (FP_STATE_SAVE*) pBuffer;
  2120. if (!pFpStateSave->bSaved)
  2121. {
  2122. KdPrint(("EngRestoreFloatingPointState: Your driver called restore "
  2123. "twice in a row or called restore without a preceeding "
  2124. "successful call to save.\n"));
  2125. KdPrint(("Floating point corruption in the application may result."));
  2126. RIP("The driver must be fixed!");
  2127. return(FALSE);
  2128. }
  2129. pFpStateSave->bSaved = FALSE;
  2130. return(NT_SUCCESS(KeRestoreFloatingPointState(&pFpStateSave->fsFpState)));
  2131. }
  2132. /******************************Public*Routine******************************\
  2133. *
  2134. * EngQuerySystemAttribute
  2135. *
  2136. * Can be used by a driver to query certain processor or system specific
  2137. * capabilities.
  2138. *
  2139. \**************************************************************************/
  2140. BOOL
  2141. EngQuerySystemAttribute(
  2142. ENG_SYSTEM_ATTRIBUTE CapNum,
  2143. PDWORD pCapability)
  2144. {
  2145. switch (CapNum) {
  2146. case EngProcessorFeature: {
  2147. SYSTEM_PROCESSOR_INFORMATION spi;
  2148. if (NT_SUCCESS(ZwQuerySystemInformation(
  2149. SystemProcessorInformation,
  2150. &spi,
  2151. sizeof(SYSTEM_PROCESSOR_INFORMATION),
  2152. NULL))) {
  2153. *pCapability = spi.ProcessorFeatureBits;
  2154. return TRUE;
  2155. }
  2156. break;
  2157. }
  2158. case EngNumberOfProcessors: {
  2159. SYSTEM_BASIC_INFORMATION sbi;
  2160. if (NT_SUCCESS(ZwQuerySystemInformation(
  2161. SystemBasicInformation,
  2162. &sbi,
  2163. sizeof(SYSTEM_BASIC_INFORMATION),
  2164. NULL))) {
  2165. *pCapability = sbi.NumberOfProcessors;
  2166. return TRUE;
  2167. }
  2168. break;
  2169. }
  2170. case EngOptimumAvailableUserMemory:
  2171. case EngOptimumAvailableSystemMemory:
  2172. break;
  2173. default:
  2174. break;
  2175. }
  2176. return FALSE;
  2177. }
  2178. #if defined(_GDIPLUS_)
  2179. VOID
  2180. GreQuerySystemTime(
  2181. PLARGE_INTEGER CurrentTime
  2182. )
  2183. {
  2184. GetSystemTimeAsFileTime((PFILETIME) CurrentTime);
  2185. }
  2186. VOID
  2187. GreSystemTimeToLocalTime (
  2188. PLARGE_INTEGER SystemTime,
  2189. PLARGE_INTEGER LocalTime
  2190. )
  2191. {
  2192. FileTimeToLocalFileTime((PFILETIME) SystemTime, (PFILETIME) LocalTime);
  2193. }
  2194. #else // !_GDIPLUS_
  2195. VOID
  2196. GreQuerySystemTime(
  2197. PLARGE_INTEGER CurrentTime
  2198. )
  2199. {
  2200. KeQuerySystemTime(CurrentTime);
  2201. }
  2202. VOID
  2203. GreSystemTimeToLocalTime (
  2204. PLARGE_INTEGER SystemTime,
  2205. PLARGE_INTEGER LocalTime
  2206. )
  2207. {
  2208. ExSystemTimeToLocalTime (SystemTime, LocalTime);
  2209. }
  2210. #endif // _GDIPLUS_
  2211. #ifdef DDI_WATCHDOG
  2212. /******************************Public*Routine******************************\
  2213. *
  2214. * GreCreateWatchdogs
  2215. *
  2216. * Creates an array of WATCHDOG_DATA objects pool, and creates and
  2217. * initializes associated DPC and DEFERRED_WATCHDOG objects.
  2218. *
  2219. * Return Value:
  2220. *
  2221. * A pointer the new array or NULL
  2222. *
  2223. * Note:
  2224. *
  2225. * dpcCallback must be in non-pagable, non-session kernel memory.
  2226. * DPC objects must be in non-paged, non-session kernel memory.
  2227. * Watchdog objects must be in non-paged, non-session kernel memory.
  2228. * Deferred context must be in non-paged, non-session kernel memory.
  2229. *
  2230. \**************************************************************************/
  2231. PWATCHDOG_DATA
  2232. GreCreateWatchdogs(
  2233. PDEVICE_OBJECT pDeviceObject,
  2234. ULONG ulNumberOfWatchdogs,
  2235. LONG lPeriod,
  2236. PKDEFERRED_ROUTINE dpcCallback,
  2237. PWSTR pwszDriverName,
  2238. HANDLE hDriver,
  2239. PLDEV *ppldevDriverList
  2240. )
  2241. {
  2242. PWATCHDOG_DATA pWatchdogData;
  2243. if (NULL == pwszDriverName)
  2244. {
  2245. return NULL;
  2246. }
  2247. pWatchdogData = (PWATCHDOG_DATA)GdiAllocPool(ulNumberOfWatchdogs * sizeof (WATCHDOG_DATA), GDITAG_WATCHDOG);
  2248. if (pWatchdogData)
  2249. {
  2250. PWD_GDI_DPC_CONTEXT pvContext;
  2251. SIZE_T stSize;
  2252. ULONG ulLength;
  2253. ULONG i;
  2254. ulLength = wcslen(pwszDriverName);
  2255. stSize = sizeof(WD_GDI_DPC_CONTEXT) + ((ulLength + 1) * sizeof(WCHAR));
  2256. //
  2257. // Zero out in case we won't be able to create all we need and we'll have to back off.
  2258. //
  2259. RtlZeroMemory(pWatchdogData, ulNumberOfWatchdogs * sizeof (WATCHDOG_DATA));
  2260. for (i = 0; i < ulNumberOfWatchdogs; i++)
  2261. {
  2262. //
  2263. // Allocate DPC object from non-paged, non-session pool.
  2264. //
  2265. pWatchdogData[i].pDpc = (PKDPC)GdiAllocPoolNonPagedNS(sizeof (KDPC), GDITAG_WATCHDOG);
  2266. if (NULL == pWatchdogData[i].pDpc)
  2267. {
  2268. //
  2269. // Allocation failed - delete what we created so far and bail out.
  2270. //
  2271. GreDeleteWatchdogs(pWatchdogData, i);
  2272. pWatchdogData = NULL;
  2273. break;
  2274. }
  2275. //
  2276. // Allocate deferred watchdog object.
  2277. //
  2278. pWatchdogData[i].pWatchdog = WdAllocateDeferredWatchdog(pDeviceObject, WdKernelTime, GDITAG_WATCHDOG);
  2279. if (NULL == pWatchdogData[i].pWatchdog)
  2280. {
  2281. //
  2282. // Allocation failed - delete what we created so far and bail out.
  2283. // Note: We have to free last DPC object here.
  2284. //
  2285. GdiFreePool(pWatchdogData[i].pDpc);
  2286. pWatchdogData[i].pDpc = NULL;
  2287. GreDeleteWatchdogs(pWatchdogData, i);
  2288. pWatchdogData = NULL;
  2289. break;
  2290. }
  2291. //
  2292. // Attach and initialize watchdog context.
  2293. //
  2294. pvContext = (PWD_GDI_DPC_CONTEXT)WdAttachContext(pWatchdogData[i].pWatchdog, (ULONG)stSize);
  2295. if (pvContext)
  2296. {
  2297. pvContext->ppldevDrivers = ppldevDriverList;
  2298. pvContext->hDriver = hDriver;
  2299. //
  2300. // Stuff UNICODE_STRING and driver name into the context attached to watchdog object.
  2301. //
  2302. RtlCopyMemory(pvContext+1,
  2303. pwszDriverName,
  2304. (ulLength + 1) * sizeof(WCHAR));
  2305. RtlInitUnicodeString(&pvContext->DisplayDriverName,
  2306. (PCWSTR)(pvContext+1));
  2307. }
  2308. else
  2309. {
  2310. //
  2311. // Context creation failed - delete what we created so far and bail out.
  2312. //
  2313. GreDeleteWatchdogs(pWatchdogData, i + 1);
  2314. pWatchdogData = NULL;
  2315. break;
  2316. }
  2317. //
  2318. // Initialize DPC object and start deferred watch.
  2319. //
  2320. KeInitializeDpc(pWatchdogData[i].pDpc, dpcCallback, pvContext);
  2321. WdStartDeferredWatch(pWatchdogData[i].pWatchdog, pWatchdogData[i].pDpc, lPeriod);
  2322. }
  2323. }
  2324. return pWatchdogData;
  2325. }
  2326. /******************************Public*Routine******************************\
  2327. *
  2328. * GreDeleteWatchdogs
  2329. *
  2330. * Stops watchdogs and deletes an array of WATCHDOG_DATA objects.
  2331. *
  2332. \**************************************************************************/
  2333. VOID
  2334. GreDeleteWatchdogs(
  2335. PWATCHDOG_DATA pWatchdogData,
  2336. ULONG ulNumberOfWatchdogs
  2337. )
  2338. {
  2339. if (NULL != pWatchdogData)
  2340. {
  2341. ULONG i;
  2342. for (i = 0; i < ulNumberOfWatchdogs; i++)
  2343. {
  2344. if (NULL != pWatchdogData[i].pWatchdog)
  2345. {
  2346. //
  2347. // Stop and free deferred watchdog.
  2348. //
  2349. WdStopDeferredWatch(pWatchdogData[i].pWatchdog);
  2350. WdFreeDeferredWatchdog(pWatchdogData[i].pWatchdog);
  2351. pWatchdogData[i].pWatchdog = NULL;
  2352. }
  2353. if (NULL != pWatchdogData[i].pDpc)
  2354. {
  2355. //
  2356. // Free pool allocated for DPC object.
  2357. //
  2358. GdiFreePool(pWatchdogData[i].pDpc);
  2359. pWatchdogData[i].pDpc = NULL;
  2360. }
  2361. }
  2362. //
  2363. // Free pool allocated for WatchdogData array.
  2364. //
  2365. GdiFreePool(pWatchdogData);
  2366. }
  2367. }
  2368. #endif // DDI_WATCHDOG