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.

1270 lines
35 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: KernelResources.cpp
  3. //
  4. // Copyright (c) 1999-2000, Microsoft Corporation
  5. //
  6. // General class definitions that assist in resource management. These are
  7. // typically stack based objects where constructors initialize to a known
  8. // state. Member functions operate on that resource. Destructors release
  9. // resources when the object goes out of scope.
  10. //
  11. // History: 1999-08-18 vtan created
  12. // 1999-11-16 vtan separate file
  13. // 2000-02-01 vtan moved from Neptune to Whistler
  14. // --------------------------------------------------------------------------
  15. #include "StandardHeader.h"
  16. #include "KernelResources.h"
  17. #include "StatusCode.h"
  18. // --------------------------------------------------------------------------
  19. // CHandle::CHandle
  20. //
  21. // Arguments: <none>
  22. //
  23. // Returns: <none>
  24. //
  25. // Purpose: Initializes the CHandle object.
  26. //
  27. // History: 1999-08-18 vtan created
  28. // --------------------------------------------------------------------------
  29. CHandle::CHandle (HANDLE handle) :
  30. _handle(handle)
  31. {
  32. }
  33. // --------------------------------------------------------------------------
  34. // CHandle::~CHandle
  35. //
  36. // Arguments: <none>
  37. //
  38. // Returns: <none>
  39. //
  40. // Purpose: Releases resources used by the CHandle object.
  41. //
  42. // History: 1999-08-18 vtan created
  43. // --------------------------------------------------------------------------
  44. CHandle::~CHandle (void)
  45. {
  46. ReleaseHandle(_handle);
  47. }
  48. // --------------------------------------------------------------------------
  49. // CHandle::operator HANDLE
  50. //
  51. // Arguments: <none>
  52. //
  53. // Returns: <none>
  54. //
  55. // Purpose: Magically converts a CHandle to a HANDLE.
  56. //
  57. // History: 1999-08-18 vtan created
  58. // --------------------------------------------------------------------------
  59. CHandle::operator HANDLE (void) const
  60. {
  61. return(_handle);
  62. }
  63. // --------------------------------------------------------------------------
  64. // CEvent::CEvent
  65. //
  66. // Arguments: <none>
  67. //
  68. // Returns: <none>
  69. //
  70. // Purpose: Initializes the CEvent object. No event is created.
  71. //
  72. // History: 1999-08-18 vtan created
  73. // --------------------------------------------------------------------------
  74. CEvent::CEvent (void) :
  75. _hEvent(NULL)
  76. {
  77. }
  78. // --------------------------------------------------------------------------
  79. // CEvent::CEvent
  80. //
  81. // Arguments: copyObject = Object to copy on construction.
  82. //
  83. // Returns: <none>
  84. //
  85. // Purpose: Copy constructor for the CEvent object. An event is
  86. // duplicated.
  87. //
  88. // History: 1999-08-18 vtan created
  89. // --------------------------------------------------------------------------
  90. CEvent::CEvent (const CEvent& copyObject) :
  91. _hEvent(NULL)
  92. {
  93. *this = copyObject;
  94. }
  95. // --------------------------------------------------------------------------
  96. // CEvent::CEvent
  97. //
  98. // Arguments: pszName = Optional name of an event object to create on
  99. // construction.
  100. //
  101. // Returns: <none>
  102. //
  103. // Purpose: Initializes the CEvent object. A named event is created.
  104. //
  105. // History: 1999-08-18 vtan created
  106. // --------------------------------------------------------------------------
  107. CEvent::CEvent (const TCHAR *pszName) :
  108. _hEvent(NULL)
  109. {
  110. TSTATUS(Create(pszName));
  111. }
  112. // --------------------------------------------------------------------------
  113. // CEvent::~CEvent
  114. //
  115. // Arguments: <none>
  116. //
  117. // Returns: <none>
  118. //
  119. // Purpose: Releases resources used by the CEvent object.
  120. //
  121. // History: 1999-08-18 vtan created
  122. // --------------------------------------------------------------------------
  123. CEvent::~CEvent (void)
  124. {
  125. TSTATUS(Close());
  126. }
  127. // --------------------------------------------------------------------------
  128. // CEvent::operator =
  129. //
  130. // Arguments: assignObject = Object being assigned.
  131. //
  132. // Returns: const CEvent&
  133. //
  134. // Purpose: Overloaded operator = to ensure that the event is properly
  135. // duplicated with another handle referencing the same object.
  136. //
  137. // History: 1999-08-18 vtan created
  138. // --------------------------------------------------------------------------
  139. const CEvent& CEvent::operator = (const CEvent& assignObject)
  140. {
  141. if (this != &assignObject)
  142. {
  143. TSTATUS(Close());
  144. TBOOL(DuplicateHandle(GetCurrentProcess(), assignObject._hEvent, GetCurrentProcess(), &_hEvent, 0, FALSE, DUPLICATE_SAME_ACCESS));
  145. }
  146. return(*this);
  147. }
  148. // --------------------------------------------------------------------------
  149. // CEvent::operator HANDLE
  150. //
  151. // Arguments: <none>
  152. //
  153. // Returns: <none>
  154. //
  155. // Purpose: Magically converts a CEvent to a HANDLE.
  156. //
  157. // History: 1999-09-21 vtan created
  158. // --------------------------------------------------------------------------
  159. CEvent::operator HANDLE (void) const
  160. {
  161. return(_hEvent);
  162. }
  163. // --------------------------------------------------------------------------
  164. // CEvent::Open
  165. //
  166. // Arguments: pszName = Optional name of the event object to open.
  167. // dwAccess = Access level required.
  168. //
  169. // Returns: NTSTATUS
  170. //
  171. // Purpose: Opens the event object.
  172. //
  173. // History: 1999-10-26 vtan created
  174. // --------------------------------------------------------------------------
  175. NTSTATUS CEvent::Open (const TCHAR *pszName, DWORD dwAccess)
  176. {
  177. NTSTATUS status;
  178. TSTATUS(Close());
  179. _hEvent = OpenEvent(dwAccess, FALSE, pszName);
  180. if (_hEvent != NULL)
  181. {
  182. status = STATUS_SUCCESS;
  183. }
  184. else
  185. {
  186. status = CStatusCode::StatusCodeOfLastError();
  187. }
  188. return(status);
  189. }
  190. // --------------------------------------------------------------------------
  191. // CEvent::Create
  192. //
  193. // Arguments: pszName = Optional name of the event object to create. It
  194. // is possible to create un-named events.
  195. //
  196. // Returns: NTSTATUS
  197. //
  198. // Purpose: Creates the event object. The event is manually reset and NOT
  199. // signaled initially.
  200. //
  201. // History: 1999-08-18 vtan created
  202. // --------------------------------------------------------------------------
  203. NTSTATUS CEvent::Create (const TCHAR *pszName)
  204. {
  205. NTSTATUS status;
  206. TSTATUS(Close());
  207. _hEvent = CreateEvent(NULL, TRUE, FALSE, pszName);
  208. if (_hEvent != NULL)
  209. {
  210. status = STATUS_SUCCESS;
  211. }
  212. else
  213. {
  214. status = CStatusCode::StatusCodeOfLastError();
  215. }
  216. return(status);
  217. }
  218. // --------------------------------------------------------------------------
  219. // CEvent::Set
  220. //
  221. // Arguments: <none>
  222. //
  223. // Returns: NTSTATUS
  224. //
  225. // Purpose: Set the event object state to signaled.
  226. //
  227. // History: 1999-08-18 vtan created
  228. // --------------------------------------------------------------------------
  229. NTSTATUS CEvent::Set (void) const
  230. {
  231. NTSTATUS status;
  232. ASSERTMSG(_hEvent != NULL, "No event object in CEvent::Set");
  233. if (SetEvent(_hEvent) != FALSE)
  234. {
  235. status = STATUS_SUCCESS;
  236. }
  237. else
  238. {
  239. status = CStatusCode::StatusCodeOfLastError();
  240. }
  241. return(status);
  242. }
  243. // --------------------------------------------------------------------------
  244. // CEvent::Reset
  245. //
  246. // Arguments: <none>
  247. //
  248. // Returns: NTSTATUS
  249. //
  250. // Purpose: Clears the event object state to NOT signaled.
  251. //
  252. // History: 1999-08-18 vtan created
  253. // --------------------------------------------------------------------------
  254. NTSTATUS CEvent::Reset (void) const
  255. {
  256. NTSTATUS status;
  257. ASSERTMSG(_hEvent != NULL, "No event object in CEvent::Reset");
  258. if (ResetEvent(_hEvent) != FALSE)
  259. {
  260. status = STATUS_SUCCESS;
  261. }
  262. else
  263. {
  264. status = CStatusCode::StatusCodeOfLastError();
  265. }
  266. return(status);
  267. }
  268. // --------------------------------------------------------------------------
  269. // CEvent::Pulse
  270. //
  271. // Arguments: <none>
  272. //
  273. // Returns: NTSTATUS
  274. //
  275. // Purpose: Set the event object state to signaled, releases any threads
  276. // waiting on this event and clears the event object state to
  277. // NOT signaled.
  278. //
  279. // History: 1999-08-18 vtan created
  280. // --------------------------------------------------------------------------
  281. NTSTATUS CEvent::Pulse (void) const
  282. {
  283. NTSTATUS status;
  284. ASSERTMSG(_hEvent != NULL, "No event object in CEvent::Pulse");
  285. if (PulseEvent(_hEvent) != FALSE)
  286. {
  287. status = STATUS_SUCCESS;
  288. }
  289. else
  290. {
  291. status = CStatusCode::StatusCodeOfLastError();
  292. }
  293. return(status);
  294. }
  295. // --------------------------------------------------------------------------
  296. // CEvent::Wait
  297. //
  298. // Arguments: dwMilliseconds = Number of milliseconds to wait until the
  299. // event becomes signaled.
  300. // pdwWaitResult = Result from kernel32!WaitForSingleObject.
  301. //
  302. // Returns: NTSTATUS
  303. //
  304. // Purpose: Waits for the event object to become signaled.
  305. //
  306. // History: 1999-08-18 vtan created
  307. // --------------------------------------------------------------------------
  308. NTSTATUS CEvent::Wait (DWORD dwMilliseconds, DWORD *pdwWaitResult) const
  309. {
  310. NTSTATUS status;
  311. DWORD dwWaitResult;
  312. ASSERTMSG(_hEvent != NULL, "No event object in CEvent::Wait");
  313. dwWaitResult = WaitForSingleObject(_hEvent, dwMilliseconds);
  314. if (pdwWaitResult != NULL)
  315. {
  316. *pdwWaitResult = dwWaitResult;
  317. }
  318. if (dwWaitResult == WAIT_OBJECT_0)
  319. {
  320. status = STATUS_SUCCESS;
  321. }
  322. else
  323. {
  324. status = CStatusCode::StatusCodeOfLastError();
  325. }
  326. return(status);
  327. }
  328. // --------------------------------------------------------------------------
  329. // CEvent::Wait
  330. //
  331. // Arguments: dwMilliseconds = Number of milliseconds to wait until the
  332. // event becomes signaled.
  333. // pdwWaitResult = Result from kernel32!WaitForSingleObject.
  334. //
  335. // Returns: NTSTATUS
  336. //
  337. // Purpose: Waits for the event object to become signaled.
  338. //
  339. // History: 1999-08-18 vtan created
  340. // --------------------------------------------------------------------------
  341. NTSTATUS CEvent::WaitWithMessages (DWORD dwMilliseconds, DWORD *pdwWaitResult) const
  342. {
  343. NTSTATUS status;
  344. DWORD dwWaitResult;
  345. do
  346. {
  347. // When waiting for the object check to see that it's not signaled.
  348. // If signaled then abandon the wait loop. Otherwise allow user32
  349. // to continue processing messages for this thread.
  350. dwWaitResult = WaitForSingleObject(_hEvent, 0);
  351. if (dwWaitResult != WAIT_OBJECT_0)
  352. {
  353. dwWaitResult = MsgWaitForMultipleObjects(1, &_hEvent, FALSE, dwMilliseconds, QS_ALLINPUT);
  354. if (dwWaitResult == WAIT_OBJECT_0 + 1)
  355. {
  356. MSG msg;
  357. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE)
  358. {
  359. (BOOL)TranslateMessage(&msg);
  360. (LRESULT)DispatchMessage(&msg);
  361. }
  362. }
  363. }
  364. } while (dwWaitResult == WAIT_OBJECT_0 + 1);
  365. if (pdwWaitResult != NULL)
  366. {
  367. *pdwWaitResult = dwWaitResult;
  368. }
  369. if (dwWaitResult == WAIT_OBJECT_0)
  370. {
  371. status = STATUS_SUCCESS;
  372. }
  373. else
  374. {
  375. status = CStatusCode::StatusCodeOfLastError();
  376. }
  377. return(status);
  378. }
  379. // --------------------------------------------------------------------------
  380. // CEvent::IsSignaled
  381. //
  382. // Arguments: <none>
  383. //
  384. // Returns: bool
  385. //
  386. // Purpose: Returns whether the event is signaled without waiting.
  387. //
  388. // History: 2000-08-09 vtan created
  389. // --------------------------------------------------------------------------
  390. bool CEvent::IsSignaled (void) const
  391. {
  392. return(WAIT_OBJECT_0 == WaitForSingleObject(_hEvent, 0));
  393. }
  394. // --------------------------------------------------------------------------
  395. // CEvent::Close
  396. //
  397. // Arguments: <none>
  398. //
  399. // Returns: NTSTATUS
  400. //
  401. // Purpose: Closes the event object HANDLE.
  402. //
  403. // History: 1999-08-18 vtan created
  404. // --------------------------------------------------------------------------
  405. NTSTATUS CEvent::Close (void)
  406. {
  407. ReleaseHandle(_hEvent);
  408. return(STATUS_SUCCESS);
  409. }
  410. // --------------------------------------------------------------------------
  411. // CJob::CJob
  412. //
  413. // Arguments: pszName = Optional name of an event object to create on
  414. // construction.
  415. //
  416. // Returns: <none>
  417. //
  418. // Purpose: Initializes the CJob object. A named event is created.
  419. //
  420. // History: 1999-10-07 vtan created
  421. // --------------------------------------------------------------------------
  422. CJob::CJob (const TCHAR *pszName) :
  423. _hJob(NULL)
  424. {
  425. _hJob = CreateJobObject(NULL, pszName);
  426. ASSERTMSG(_hJob != NULL, "Job object creation failed iN CJob::CJob");
  427. }
  428. // --------------------------------------------------------------------------
  429. // CJob::~CJob
  430. //
  431. // Arguments: <none>
  432. //
  433. // Returns: <none>
  434. //
  435. // Purpose: Releases resources used by the CJob object.
  436. //
  437. // History: 1999-10-07 vtan created
  438. // --------------------------------------------------------------------------
  439. CJob::~CJob (void)
  440. {
  441. ReleaseHandle(_hJob);
  442. }
  443. // --------------------------------------------------------------------------
  444. // CJob::AddProcess
  445. //
  446. // Arguments: hProcess = Handle to the process to add to this job.
  447. //
  448. // Returns: NTSTATUS
  449. //
  450. // Purpose: Adds the process to this job.
  451. //
  452. // History: 1999-10-07 vtan created
  453. // --------------------------------------------------------------------------
  454. NTSTATUS CJob::AddProcess (HANDLE hProcess) const
  455. {
  456. NTSTATUS status;
  457. ASSERTMSG(_hJob != NULL, "Must have job object in CJob::AddProcess");
  458. if (AssignProcessToJobObject(_hJob, hProcess) != FALSE)
  459. {
  460. status = STATUS_SUCCESS;
  461. }
  462. else
  463. {
  464. status = CStatusCode::StatusCodeOfLastError();
  465. }
  466. return(status);
  467. }
  468. // --------------------------------------------------------------------------
  469. // CJob::SetCompletionPort
  470. //
  471. // Arguments: hCompletionPort = IO completion port for job completion
  472. // messages.
  473. //
  474. // Returns: NTSTATUS
  475. //
  476. // Purpose: Set the IO completion port for this job. The caller should
  477. // watch this port for messages related to this job.
  478. //
  479. // History: 1999-10-07 vtan created
  480. // --------------------------------------------------------------------------
  481. NTSTATUS CJob::SetCompletionPort (HANDLE hCompletionPort) const
  482. {
  483. NTSTATUS status;
  484. JOBOBJECT_ASSOCIATE_COMPLETION_PORT associateCompletionPort;
  485. ASSERTMSG(_hJob != NULL, "Must have job object in CJob::SetCompletionPort");
  486. associateCompletionPort.CompletionKey = NULL;
  487. associateCompletionPort.CompletionPort = hCompletionPort;
  488. // If the job completion port cannot be set then don't use it.
  489. if (SetInformationJobObject(_hJob, JobObjectAssociateCompletionPortInformation, &associateCompletionPort, sizeof(associateCompletionPort)) != FALSE)
  490. {
  491. status = STATUS_SUCCESS;
  492. }
  493. else
  494. {
  495. status = CStatusCode::StatusCodeOfLastError();
  496. }
  497. return(status);
  498. }
  499. // --------------------------------------------------------------------------
  500. // CJob:SetActiveProcessLimit
  501. //
  502. // Arguments: dwActiveProcessLimit = Maximum number of processes.
  503. //
  504. // Returns: NTSTATUS
  505. //
  506. // Purpose: Sets the limit for the number of processes related to this
  507. // job. Typically you can use this to restrict a process from
  508. // starting another process whena quota (such as 1) is reached.
  509. //
  510. // History: 1999-10-07 vtan created
  511. // --------------------------------------------------------------------------
  512. NTSTATUS CJob::SetActiveProcessLimit (DWORD dwActiveProcessLimit) const
  513. {
  514. NTSTATUS status;
  515. DWORD dwReturnLength;
  516. JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimitInformation;
  517. ASSERTMSG(_hJob != NULL, "Must have job object in CJob::SetActiveProcessLimit");
  518. if (QueryInformationJobObject(_hJob,
  519. JobObjectBasicLimitInformation,
  520. &basicLimitInformation,
  521. sizeof(basicLimitInformation),
  522. &dwReturnLength) != FALSE)
  523. {
  524. if (dwActiveProcessLimit == 0)
  525. {
  526. basicLimitInformation.LimitFlags &= ~JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
  527. basicLimitInformation.ActiveProcessLimit = 0;
  528. }
  529. else
  530. {
  531. basicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
  532. basicLimitInformation.ActiveProcessLimit = dwActiveProcessLimit;
  533. }
  534. if (SetInformationJobObject(_hJob, JobObjectBasicLimitInformation, &basicLimitInformation, sizeof(basicLimitInformation)) != FALSE)
  535. {
  536. status = STATUS_SUCCESS;
  537. }
  538. else
  539. {
  540. status = CStatusCode::StatusCodeOfLastError();
  541. }
  542. }
  543. else
  544. {
  545. status = CStatusCode::StatusCodeOfLastError();
  546. }
  547. return(status);
  548. }
  549. NTSTATUS CJob::SetPriorityClass (DWORD dwPriorityClass) const
  550. {
  551. NTSTATUS status;
  552. DWORD dwReturnLength;
  553. JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimitInformation;
  554. ASSERTMSG(_hJob != NULL, "Must have job object in CJob::SetPriorityClass");
  555. if (QueryInformationJobObject(_hJob,
  556. JobObjectBasicLimitInformation,
  557. &basicLimitInformation,
  558. sizeof(basicLimitInformation),
  559. &dwReturnLength) != FALSE)
  560. {
  561. if (dwPriorityClass == 0)
  562. {
  563. basicLimitInformation.LimitFlags &= ~JOB_OBJECT_LIMIT_PRIORITY_CLASS;
  564. basicLimitInformation.PriorityClass = NORMAL_PRIORITY_CLASS;
  565. }
  566. else
  567. {
  568. basicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
  569. basicLimitInformation.PriorityClass = dwPriorityClass;
  570. }
  571. if (SetInformationJobObject(_hJob, JobObjectBasicLimitInformation, &basicLimitInformation, sizeof(basicLimitInformation)) != FALSE)
  572. {
  573. status = STATUS_SUCCESS;
  574. }
  575. else
  576. {
  577. status = CStatusCode::StatusCodeOfLastError();
  578. }
  579. }
  580. else
  581. {
  582. status = CStatusCode::StatusCodeOfLastError();
  583. }
  584. return(status);
  585. }
  586. // --------------------------------------------------------------------------
  587. // CJob:RestrictAccessUIAll
  588. //
  589. // Arguments: <none>
  590. //
  591. // Returns: NTSTATUS
  592. //
  593. // Purpose: Restricts process in the job from accessing UI components.
  594. // Take care when using this feature.
  595. //
  596. // History: 1999-10-07 vtan created
  597. // --------------------------------------------------------------------------
  598. NTSTATUS CJob::RestrictAccessUIAll (void) const
  599. {
  600. NTSTATUS status;
  601. JOBOBJECT_BASIC_UI_RESTRICTIONS basicUIRestrictions;
  602. ASSERTMSG(_hJob != NULL, "Must have job object in CJob::RestrictAccessUIAll");
  603. basicUIRestrictions.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP |
  604. JOB_OBJECT_UILIMIT_DISPLAYSETTINGS |
  605. JOB_OBJECT_UILIMIT_EXITWINDOWS |
  606. JOB_OBJECT_UILIMIT_GLOBALATOMS |
  607. JOB_OBJECT_UILIMIT_HANDLES |
  608. JOB_OBJECT_UILIMIT_READCLIPBOARD |
  609. JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS |
  610. JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
  611. if (SetInformationJobObject(_hJob, JobObjectBasicUIRestrictions, &basicUIRestrictions, sizeof(basicUIRestrictions)) != FALSE)
  612. {
  613. status = STATUS_SUCCESS;
  614. }
  615. else
  616. {
  617. status = CStatusCode::StatusCodeOfLastError();
  618. }
  619. return(status);
  620. }
  621. // --------------------------------------------------------------------------
  622. // CMutex::Initialize
  623. //
  624. // Arguments: pszMutexName = Name of the mutex to create.
  625. //
  626. // Returns: NTSTATUS
  627. //
  628. // Purpose: Create or open a mutex object. It always tries to create the
  629. // mutex so a name MUST be specified.
  630. //
  631. // History: 1999-10-13 vtan created
  632. // --------------------------------------------------------------------------
  633. NTSTATUS CMutex::Initialize (const TCHAR *pszMutexName)
  634. {
  635. NTSTATUS status;
  636. ASSERTMSG(pszMutexName != NULL, "Must specify a mutex name in CMutex::Initialize");
  637. _hMutex = CreateMutex(NULL, FALSE, pszMutexName);
  638. if (_hMutex != NULL)
  639. {
  640. status = STATUS_SUCCESS;
  641. }
  642. else
  643. {
  644. status = CStatusCode::StatusCodeOfLastError();
  645. }
  646. return(status);
  647. }
  648. // --------------------------------------------------------------------------
  649. // CMutex::Terminate
  650. //
  651. // Arguments: <none>
  652. //
  653. // Returns: NTSTATUS
  654. //
  655. // Purpose: Releases the mutex object resource.
  656. //
  657. // History: 1999-10-13 vtan created
  658. // --------------------------------------------------------------------------
  659. NTSTATUS CMutex::Terminate (void)
  660. {
  661. ReleaseHandle(_hMutex);
  662. return(STATUS_SUCCESS);
  663. }
  664. // --------------------------------------------------------------------------
  665. // CMutex::Acquire
  666. //
  667. // Arguments: <none>
  668. //
  669. // Returns: <none>
  670. //
  671. // Purpose: Acquires the mutex object. This will block indefinitely and
  672. // will also block a message pump. Use this with caution!
  673. //
  674. // History: 1999-10-13 vtan created
  675. // --------------------------------------------------------------------------
  676. void CMutex::Acquire (void)
  677. {
  678. if (_hMutex != NULL)
  679. {
  680. (DWORD)WaitForSingleObject(_hMutex, INFINITE);
  681. }
  682. }
  683. // --------------------------------------------------------------------------
  684. // CMutex::Release
  685. //
  686. // Arguments: <none>
  687. //
  688. // Returns: <none>
  689. //
  690. // Purpose: Releases ownership of the mutex object.
  691. //
  692. // History: 1999-10-13 vtan created
  693. // --------------------------------------------------------------------------
  694. void CMutex::Release (void)
  695. {
  696. if (_hMutex != NULL)
  697. {
  698. TBOOL(ReleaseMutex(_hMutex));
  699. }
  700. }
  701. // --------------------------------------------------------------------------
  702. // CCriticalSection::CCriticalSection
  703. //
  704. // Arguments: <none>
  705. //
  706. // Returns: <none>
  707. //
  708. // Purpose: Initializes the critical section object.
  709. //
  710. // History: 1999-11-06 vtan created
  711. // --------------------------------------------------------------------------
  712. CCriticalSection::CCriticalSection (void)
  713. {
  714. _status = RtlInitializeCriticalSection(&_criticalSection);
  715. }
  716. // --------------------------------------------------------------------------
  717. // CCriticalSection::~CCriticalSection
  718. //
  719. // Arguments: <none>
  720. //
  721. // Returns: <none>
  722. //
  723. // Purpose: Destroys the critical section object.
  724. //
  725. // History: 1999-11-06 vtan created
  726. // --------------------------------------------------------------------------
  727. CCriticalSection::~CCriticalSection (void)
  728. {
  729. if (NT_SUCCESS(_status))
  730. {
  731. TSTATUS(RtlDeleteCriticalSection(&_criticalSection));
  732. }
  733. }
  734. // --------------------------------------------------------------------------
  735. // CCriticalSection::Acquire
  736. //
  737. // Arguments: <none>
  738. //
  739. // Returns: <none>
  740. //
  741. // Purpose: Acquire the critical section object.
  742. //
  743. // History: 1999-11-06 vtan created
  744. // --------------------------------------------------------------------------
  745. void CCriticalSection::Acquire (void)
  746. {
  747. if (NT_SUCCESS(_status))
  748. {
  749. EnterCriticalSection(&_criticalSection);
  750. }
  751. }
  752. // --------------------------------------------------------------------------
  753. // CCriticalSection::Release
  754. //
  755. // Arguments: <none>
  756. //
  757. // Returns: <none>
  758. //
  759. // Purpose: Release the critical section object.
  760. //
  761. // History: 1999-11-06 vtan created
  762. // --------------------------------------------------------------------------
  763. void CCriticalSection::Release (void)
  764. {
  765. if (NT_SUCCESS(_status))
  766. {
  767. LeaveCriticalSection(&_criticalSection);
  768. }
  769. }
  770. // --------------------------------------------------------------------------
  771. // CCriticalSection::Status
  772. //
  773. // Arguments: <none>
  774. //
  775. // Returns: NTSTATUS
  776. //
  777. // Purpose: Returns the construction status.
  778. //
  779. // History: 2000-12-09 vtan created
  780. // --------------------------------------------------------------------------
  781. NTSTATUS CCriticalSection::Status (void) const
  782. {
  783. return(_status);
  784. }
  785. // --------------------------------------------------------------------------
  786. // CCriticalSection::IsOwned
  787. //
  788. // Arguments: <none>
  789. //
  790. // Returns: bool
  791. //
  792. // Purpose: Returns whether the critical section is owned.
  793. //
  794. // History: 2001-04-05 vtan created
  795. // --------------------------------------------------------------------------
  796. bool CCriticalSection::IsOwned (void) const
  797. {
  798. return(NT_SUCCESS(_status) && (_criticalSection.OwningThread == NtCurrentTeb()->ClientId.UniqueThread));
  799. }
  800. // --------------------------------------------------------------------------
  801. // CModule::CModule
  802. //
  803. // Arguments: <none>
  804. //
  805. // Returns: <none>
  806. //
  807. // Purpose: Initializes the CModule object. Opens the given dynamic link
  808. // library.
  809. //
  810. // History: 1999-08-18 vtan created
  811. // --------------------------------------------------------------------------
  812. CModule::CModule (const TCHAR *pszModuleName) :
  813. _hModule(NULL)
  814. {
  815. _hModule = LoadLibrary(pszModuleName);
  816. }
  817. // --------------------------------------------------------------------------
  818. // CModule::~CModule
  819. //
  820. // Arguments: <none>
  821. //
  822. // Returns: <none>
  823. //
  824. // Purpose: Releases resources used by the CModule object. Closes the
  825. // library if opened.
  826. //
  827. // History: 1999-08-18 vtan created
  828. // --------------------------------------------------------------------------
  829. CModule::~CModule (void)
  830. {
  831. if (_hModule != NULL)
  832. {
  833. TBOOL(FreeLibrary(_hModule));
  834. _hModule = NULL;
  835. }
  836. }
  837. // --------------------------------------------------------------------------
  838. // CModule::operator HMODULE
  839. //
  840. // Arguments: <none>
  841. //
  842. // Returns: HMODULE
  843. //
  844. // Purpose: Returns the HMODULE for the loaded library.
  845. //
  846. // History: 2000-10-12 vtan created
  847. // --------------------------------------------------------------------------
  848. CModule::operator HMODULE (void) const
  849. {
  850. return(_hModule);
  851. }
  852. // --------------------------------------------------------------------------
  853. // CModule::GetProcAddress
  854. //
  855. // Arguments: pszProcName = Name of function entry point to retrieve
  856. // in the given dynamic link library. This is
  857. // ANSI by definition.
  858. //
  859. // Returns: void* = Address of the function if it exists or NULL if
  860. // failed.
  861. //
  862. // Purpose: Retrieves the function entry point in a dynamic link library.
  863. //
  864. // History: 1999-08-18 vtan created
  865. // --------------------------------------------------------------------------
  866. void* CModule::GetProcAddress (LPCSTR pszProcName) const
  867. {
  868. void* pfnResult;
  869. pfnResult = NULL;
  870. if (_hModule != NULL)
  871. {
  872. pfnResult = ::GetProcAddress(_hModule, pszProcName);
  873. }
  874. return(pfnResult);
  875. }
  876. // --------------------------------------------------------------------------
  877. // CFile::CFile
  878. //
  879. // Arguments: <none>
  880. //
  881. // Returns: <none>
  882. //
  883. // Purpose: Initializes the CFile object.
  884. //
  885. // History: 1999-08-18 vtan created
  886. // --------------------------------------------------------------------------
  887. CFile::CFile (void) :
  888. _hFile(NULL)
  889. {
  890. }
  891. // --------------------------------------------------------------------------
  892. // CFile::~CFile
  893. //
  894. // Arguments: <none>
  895. //
  896. // Returns: <none>
  897. //
  898. // Purpose: Releases resources used by the CFile object.
  899. //
  900. // History: 1999-08-18 vtan created
  901. // --------------------------------------------------------------------------
  902. CFile::~CFile (void)
  903. {
  904. ReleaseHandle(_hFile);
  905. }
  906. // --------------------------------------------------------------------------
  907. // CFile::Open
  908. //
  909. // Arguments: See the platform SDK under kernel32!CreateFile.
  910. //
  911. // Returns: LONG
  912. //
  913. // Purpose: See kernel32!CreateFile.
  914. //
  915. // History: 1999-08-18 vtan created
  916. // --------------------------------------------------------------------------
  917. LONG CFile::Open (const TCHAR *pszFilepath, DWORD dwDesiredAccess, DWORD dwShareMode)
  918. {
  919. LONG errorCode;
  920. ASSERTMSG((_hFile == NULL) || (_hFile == INVALID_HANDLE_VALUE), "Open file HANDLE exists in CFile::GetSize");
  921. _hFile = CreateFile(pszFilepath, dwDesiredAccess, dwShareMode, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  922. if (_hFile != INVALID_HANDLE_VALUE)
  923. {
  924. errorCode = ERROR_SUCCESS;
  925. }
  926. else
  927. {
  928. errorCode = GetLastError();
  929. }
  930. return(errorCode);
  931. }
  932. // --------------------------------------------------------------------------
  933. // CFile::GetSize
  934. //
  935. // Arguments: See the platform SDK under kernel32!GetFileSize.
  936. //
  937. // Returns: LONG
  938. //
  939. // Purpose: See kernel32!GetFileSize.
  940. //
  941. // History: 1999-08-18 vtan created
  942. // --------------------------------------------------------------------------
  943. LONG CFile::GetSize (DWORD& dwLowSize, DWORD *pdwHighSize) const
  944. {
  945. LONG errorCode;
  946. ASSERTMSG((_hFile != NULL) && (_hFile != INVALID_HANDLE_VALUE), "No open file HANDLE in CFile::GetSize");
  947. dwLowSize = GetFileSize(_hFile, pdwHighSize);
  948. if (dwLowSize != static_cast<DWORD>(-1))
  949. {
  950. errorCode = ERROR_SUCCESS;
  951. }
  952. else
  953. {
  954. errorCode = GetLastError();
  955. }
  956. return(errorCode);
  957. }
  958. // --------------------------------------------------------------------------
  959. // CFile::Read
  960. //
  961. // Arguments: See the platform SDK under kernel32!ReadFile.
  962. //
  963. // Returns: LONG
  964. //
  965. // Purpose: See kernel32!ReadFile.
  966. //
  967. // History: 1999-08-18 vtan created
  968. // --------------------------------------------------------------------------
  969. LONG CFile::Read (void *pvBuffer, DWORD dwBytesToRead, DWORD *pdwBytesRead) const
  970. {
  971. LONG errorCode;
  972. ASSERTMSG((_hFile != NULL) && (_hFile != INVALID_HANDLE_VALUE), "No open file HANDLE in CFile::GetSize");
  973. if (ReadFile(_hFile, pvBuffer, dwBytesToRead, pdwBytesRead, NULL) != FALSE)
  974. {
  975. errorCode = ERROR_SUCCESS;
  976. }
  977. else
  978. {
  979. errorCode = GetLastError();
  980. }
  981. return(errorCode);
  982. }
  983. // --------------------------------------------------------------------------
  984. // CDesktop::CDesktop
  985. //
  986. // Arguments: <none>
  987. //
  988. // Returns: <none>
  989. //
  990. // Purpose: Constructor for CDesktop. Saves the current thread's desktop.
  991. //
  992. // History: 2001-02-06 vtan created
  993. // --------------------------------------------------------------------------
  994. CDesktop::CDesktop (void) :
  995. _hDeskCurrent(GetThreadDesktop(GetCurrentThreadId())),
  996. _hDesk(NULL)
  997. {
  998. }
  999. // --------------------------------------------------------------------------
  1000. // CDesktop::~CDesktop
  1001. //
  1002. // Arguments: <none>
  1003. //
  1004. // Returns: <none>
  1005. //
  1006. // Purpose: Destructor for CDesktop. Restores the thread's desktop to
  1007. // its previous state prior to the object's scope.
  1008. //
  1009. // History: 2001-02-06 vtan created
  1010. // --------------------------------------------------------------------------
  1011. CDesktop::~CDesktop (void)
  1012. {
  1013. TBOOL(SetThreadDesktop(_hDeskCurrent));
  1014. if (_hDesk != NULL)
  1015. {
  1016. TBOOL(CloseDesktop(_hDesk));
  1017. _hDesk = NULL;
  1018. }
  1019. _hDeskCurrent = NULL;
  1020. }
  1021. // --------------------------------------------------------------------------
  1022. // CDesktop::Set
  1023. //
  1024. // Arguments: pszName = Name of desktop to set the thread to.
  1025. //
  1026. // Returns: NTSTATUS
  1027. //
  1028. // Purpose: Opens the named desktop with MAXIMUM_ALLOWED access and sets
  1029. // the current thread's desktop to it.
  1030. //
  1031. // History: 2001-02-06 vtan created
  1032. // --------------------------------------------------------------------------
  1033. NTSTATUS CDesktop::Set (const TCHAR *pszName)
  1034. {
  1035. NTSTATUS status;
  1036. _hDesk = OpenDesktop(pszName, 0, FALSE, MAXIMUM_ALLOWED);
  1037. if (_hDesk != NULL)
  1038. {
  1039. status = Set();
  1040. }
  1041. else
  1042. {
  1043. status = CStatusCode::StatusCodeOfLastError();
  1044. }
  1045. return(status);
  1046. }
  1047. // --------------------------------------------------------------------------
  1048. // CDesktop::SetInput
  1049. //
  1050. // Arguments: <none>
  1051. //
  1052. // Returns: NTSTATUS
  1053. //
  1054. // Purpose: Opens the input desktop and sets the current thread's desktop
  1055. // to it.
  1056. //
  1057. // History: 2001-02-06 vtan created
  1058. // --------------------------------------------------------------------------
  1059. NTSTATUS CDesktop::SetInput (void)
  1060. {
  1061. NTSTATUS status;
  1062. _hDesk = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
  1063. if (_hDesk != NULL)
  1064. {
  1065. status = Set();
  1066. }
  1067. else
  1068. {
  1069. status = CStatusCode::StatusCodeOfLastError();
  1070. }
  1071. return(status);
  1072. }
  1073. // --------------------------------------------------------------------------
  1074. // CDesktop::Set
  1075. //
  1076. // Arguments: <none>
  1077. //
  1078. // Returns: NTSTATUS
  1079. //
  1080. // Purpose: Sets the thread's desktop to the given HDESK.
  1081. //
  1082. // History: 2001-02-06 vtan created
  1083. // --------------------------------------------------------------------------
  1084. NTSTATUS CDesktop::Set (void)
  1085. {
  1086. NTSTATUS status;
  1087. if (SetThreadDesktop(_hDesk) != FALSE)
  1088. {
  1089. status = STATUS_SUCCESS;
  1090. }
  1091. else
  1092. {
  1093. status = CStatusCode::StatusCodeOfLastError();
  1094. }
  1095. return(status);
  1096. }