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.

1640 lines
44 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. gmem.c
  5. Abstract:
  6. This module contains the Win32 Global Memory Management APIs
  7. Author:
  8. Steve Wood (stevewo) 24-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. #pragma hdrstop
  13. #include "winuserp.h"
  14. #include "wowuserp.h"
  15. #include <wow64t.h>
  16. PFNWOWGLOBALFREEHOOK pfnWowGlobalFreeHook = NULL;
  17. VOID
  18. WINAPI
  19. RegisterWowBaseHandlers(
  20. PFNWOWGLOBALFREEHOOK pfn
  21. )
  22. {
  23. pfnWowGlobalFreeHook = pfn;
  24. }
  25. #if i386
  26. #pragma optimize("y",off)
  27. #endif
  28. HGLOBAL
  29. WINAPI
  30. GlobalAlloc(
  31. UINT uFlags,
  32. SIZE_T dwBytes
  33. )
  34. {
  35. PBASE_HANDLE_TABLE_ENTRY HandleEntry;
  36. HANDLE hMem;
  37. LPSTR p;
  38. ULONG Flags;
  39. if (uFlags & ~GMEM_VALID_FLAGS) {
  40. SetLastError( ERROR_INVALID_PARAMETER );
  41. return( NULL );
  42. }
  43. Flags = 0;
  44. if (uFlags & GMEM_ZEROINIT) {
  45. Flags |= HEAP_ZERO_MEMORY;
  46. }
  47. if (!(uFlags & GMEM_MOVEABLE)) {
  48. if (uFlags & GMEM_DDESHARE) {
  49. Flags |= BASE_HEAP_FLAG_DDESHARE;
  50. }
  51. p = RtlAllocateHeap( BaseHeap,
  52. MAKE_TAG( GMEM_TAG ) | Flags,
  53. dwBytes ? dwBytes : 1
  54. );
  55. if (p == NULL) {
  56. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  57. }
  58. return p;
  59. }
  60. p = NULL;
  61. RtlLockHeap( BaseHeap );
  62. Flags |= HEAP_NO_SERIALIZE | HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;
  63. try {
  64. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &BaseHeapHandleTable, NULL );
  65. if (HandleEntry == NULL) {
  66. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  67. goto Fail;
  68. }
  69. hMem = (HANDLE)&HandleEntry->Object;
  70. if (dwBytes != 0) {
  71. p = (LPSTR)RtlAllocateHeap( BaseHeap, MAKE_TAG( GMEM_TAG ) | Flags, dwBytes );
  72. if (p == NULL) {
  73. HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
  74. RtlFreeHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
  75. HandleEntry = NULL;
  76. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  77. }
  78. else {
  79. RtlSetUserValueHeap( BaseHeap, HEAP_NO_SERIALIZE, p, hMem );
  80. }
  81. }
  82. Fail: ;
  83. }
  84. except (EXCEPTION_EXECUTE_HANDLER) {
  85. BaseSetLastNTError( GetExceptionCode() );
  86. }
  87. RtlUnlockHeap( BaseHeap );
  88. if (HandleEntry != NULL) {
  89. HandleEntry->Object = p;
  90. if (p != NULL) {
  91. HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
  92. }
  93. else {
  94. HandleEntry->Flags = RTL_HANDLE_ALLOCATED | BASE_HANDLE_DISCARDED;
  95. }
  96. if (uFlags & GMEM_DISCARDABLE) {
  97. HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;
  98. }
  99. if (uFlags & GMEM_MOVEABLE) {
  100. HandleEntry->Flags |= BASE_HANDLE_MOVEABLE;
  101. }
  102. if (uFlags & GMEM_DDESHARE) {
  103. HandleEntry->Flags |= BASE_HANDLE_SHARED;
  104. }
  105. p = (LPSTR)hMem;
  106. }
  107. return( (HANDLE)p );
  108. }
  109. HGLOBAL
  110. WINAPI
  111. GlobalReAlloc(
  112. HANDLE hMem,
  113. SIZE_T dwBytes,
  114. UINT uFlags
  115. )
  116. {
  117. PBASE_HANDLE_TABLE_ENTRY HandleEntry;
  118. HANDLE Handle;
  119. LPSTR p;
  120. ULONG Flags;
  121. if ((uFlags & ~(GMEM_VALID_FLAGS | GMEM_MODIFY)) ||
  122. ((uFlags & GMEM_DISCARDABLE) && !(uFlags & GMEM_MODIFY))
  123. ) {
  124. #if DBG
  125. DbgPrint( "*** GlobalReAlloc( %lx ) - invalid flags\n", uFlags );
  126. BaseHeapBreakPoint();
  127. #endif
  128. SetLastError( ERROR_INVALID_PARAMETER );
  129. return( NULL );
  130. }
  131. Flags = 0;
  132. if (uFlags & GMEM_ZEROINIT) {
  133. Flags |= HEAP_ZERO_MEMORY;
  134. }
  135. if (!(uFlags & GMEM_MOVEABLE)) {
  136. Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
  137. }
  138. RtlLockHeap( BaseHeap );
  139. Flags |= HEAP_NO_SERIALIZE;
  140. try {
  141. if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {
  142. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
  143. CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
  144. if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
  145. #if DBG
  146. DbgPrint( "*** GlobalReAlloc( %lx ) - invalid handle\n", hMem );
  147. BaseHeapBreakPoint();
  148. #endif
  149. SetLastError( ERROR_INVALID_HANDLE );
  150. hMem = NULL;
  151. }
  152. else
  153. if (uFlags & GMEM_MODIFY) {
  154. if (uFlags & GMEM_DISCARDABLE) {
  155. HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;
  156. }
  157. else {
  158. HandleEntry->Flags &= ~BASE_HANDLE_DISCARDABLE;
  159. }
  160. }
  161. else {
  162. p = HandleEntry->Object;
  163. if (dwBytes == 0) {
  164. hMem = NULL;
  165. if (p != NULL) {
  166. if ((uFlags & GMEM_MOVEABLE) && HandleEntry->LockCount == 0) {
  167. if (RtlFreeHeap( BaseHeap, Flags, p )) {
  168. HandleEntry->Object = NULL;
  169. HandleEntry->Flags |= BASE_HANDLE_DISCARDED;
  170. hMem = (HANDLE)&HandleEntry->Object;
  171. }
  172. }
  173. else {
  174. #if DBG
  175. DbgPrint( "*** GlobalReAlloc( %lx ) - failing with locked handle\n", &HandleEntry->Object );
  176. BaseHeapBreakPoint();
  177. #endif
  178. }
  179. }
  180. else {
  181. hMem = (HANDLE)&HandleEntry->Object;
  182. }
  183. }
  184. else {
  185. Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;
  186. if (p == NULL) {
  187. p = RtlAllocateHeap( BaseHeap, MAKE_TAG( GMEM_TAG ) | Flags, dwBytes );
  188. if (p != NULL) {
  189. RtlSetUserValueHeap( BaseHeap, HEAP_NO_SERIALIZE, p, hMem );
  190. }
  191. }
  192. else {
  193. if (!(uFlags & GMEM_MOVEABLE) &&
  194. HandleEntry->LockCount != 0
  195. ) {
  196. Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
  197. }
  198. else {
  199. Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY;
  200. }
  201. #pragma prefast(suppress: 308, "Realloc is allowed to lose this pointer")
  202. p = RtlReAllocateHeap( BaseHeap, MAKE_TAG( GMEM_TAG ) | Flags, p, dwBytes );
  203. }
  204. if (p != NULL) {
  205. HandleEntry->Object = p;
  206. HandleEntry->Flags &= ~BASE_HANDLE_DISCARDED;
  207. }
  208. else {
  209. hMem = NULL;
  210. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  211. }
  212. }
  213. }
  214. }
  215. else
  216. if (uFlags & GMEM_MODIFY) {
  217. if (uFlags & GMEM_MOVEABLE) {
  218. Handle = hMem;
  219. if (RtlGetUserInfoHeap( BaseHeap, HEAP_NO_SERIALIZE, (PVOID)hMem, &Handle, NULL )) {
  220. if (Handle == hMem || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
  221. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &BaseHeapHandleTable,
  222. NULL
  223. );
  224. if (HandleEntry == NULL) {
  225. hMem = NULL;
  226. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  227. }
  228. else {
  229. dwBytes = RtlSizeHeap( BaseHeap, HEAP_NO_SERIALIZE, hMem );
  230. Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;
  231. HandleEntry->Object = (PVOID)RtlAllocateHeap( BaseHeap,
  232. MAKE_TAG( GMEM_TAG ) | Flags,
  233. dwBytes
  234. );
  235. if (HandleEntry->Object == NULL) {
  236. HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
  237. RtlFreeHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
  238. hMem = NULL;
  239. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  240. }
  241. else {
  242. RtlMoveMemory( HandleEntry->Object, hMem, dwBytes );
  243. RtlFreeHeap( BaseHeap, HEAP_NO_SERIALIZE, hMem );
  244. hMem = (HANDLE)&HandleEntry->Object;
  245. HandleEntry->LockCount = 0;
  246. HandleEntry->Flags = RTL_HANDLE_ALLOCATED | BASE_HANDLE_MOVEABLE;
  247. if (uFlags & GMEM_DISCARDABLE) {
  248. HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;
  249. }
  250. if ((ULONG_PTR)Handle & GMEM_DDESHARE) {
  251. HandleEntry->Flags |= BASE_HANDLE_SHARED;
  252. }
  253. RtlSetUserValueHeap( BaseHeap,
  254. HEAP_NO_SERIALIZE,
  255. HandleEntry->Object,
  256. hMem
  257. );
  258. }
  259. }
  260. }
  261. }
  262. }
  263. }
  264. else {
  265. #pragma prefast(suppress: 308, "Realloc is allowed to lose this pointer")
  266. hMem = RtlReAllocateHeap( BaseHeap,
  267. MAKE_TAG( GMEM_TAG ) | Flags | HEAP_NO_SERIALIZE,
  268. (PVOID)hMem,
  269. dwBytes
  270. );
  271. if (hMem == NULL) {
  272. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  273. }
  274. }
  275. }
  276. except (EXCEPTION_EXECUTE_HANDLER) {
  277. hMem = NULL;
  278. BaseSetLastNTError( GetExceptionCode() );
  279. }
  280. RtlUnlockHeap( BaseHeap );
  281. return( (LPSTR)hMem );
  282. }
  283. LPVOID
  284. WINAPI
  285. GlobalLock(
  286. HGLOBAL hMem
  287. )
  288. {
  289. PBASE_HANDLE_TABLE_ENTRY HandleEntry;
  290. LPSTR p;
  291. if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {
  292. RtlLockHeap( BaseHeap );
  293. try {
  294. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
  295. CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
  296. if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
  297. #if DBG
  298. DbgPrint( "*** GlobalLock( %lx ) - invalid handle\n", hMem );
  299. BaseHeapBreakPoint();
  300. #endif
  301. SetLastError( ERROR_INVALID_HANDLE );
  302. p = NULL;
  303. }
  304. else {
  305. p = HandleEntry->Object;
  306. if (p != NULL) {
  307. if (HandleEntry->LockCount++ == GMEM_LOCKCOUNT) {
  308. HandleEntry->LockCount--;
  309. }
  310. }
  311. else {
  312. SetLastError( ERROR_DISCARDED );
  313. }
  314. }
  315. }
  316. except (EXCEPTION_EXECUTE_HANDLER) {
  317. p = NULL;
  318. BaseSetLastNTError( GetExceptionCode() );
  319. }
  320. RtlUnlockHeap( BaseHeap );
  321. return( p );
  322. }
  323. else {
  324. if ( (ULONG_PTR)hMem >= SystemRangeStart ) {
  325. SetLastError( ERROR_INVALID_HANDLE );
  326. return NULL;
  327. }
  328. if (IsBadReadPtr( hMem, 1 )) {
  329. SetLastError( ERROR_INVALID_HANDLE );
  330. return NULL;
  331. }
  332. return( (LPSTR)hMem );
  333. }
  334. }
  335. HANDLE
  336. WINAPI
  337. GlobalHandle(
  338. LPCVOID pMem
  339. )
  340. {
  341. HANDLE Handle;
  342. ULONG Flags;
  343. RtlLockHeap( BaseHeap );
  344. try {
  345. Handle = NULL;
  346. if (!RtlGetUserInfoHeap( BaseHeap, HEAP_NO_SERIALIZE, (LPVOID)pMem, &Handle, &Flags )) {
  347. SetLastError( ERROR_INVALID_HANDLE );
  348. }
  349. else
  350. if (Handle == NULL || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
  351. Handle = (HANDLE)pMem;
  352. }
  353. }
  354. except (EXCEPTION_EXECUTE_HANDLER) {
  355. BaseSetLastNTError( GetExceptionCode() );
  356. }
  357. RtlUnlockHeap( BaseHeap );
  358. return( Handle );
  359. }
  360. BOOL
  361. WINAPI
  362. GlobalUnlock(
  363. HANDLE hMem
  364. )
  365. {
  366. PBASE_HANDLE_TABLE_ENTRY HandleEntry;
  367. BOOL Result;
  368. Result = TRUE;
  369. if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {
  370. RtlLockHeap( BaseHeap );
  371. try {
  372. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
  373. CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
  374. if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
  375. #if DBG
  376. PVOID ImageBase;
  377. //
  378. // If passed address is NOT part of an image file, then display
  379. // a debug message. This prevents apps that call GlobalUnlock
  380. // with the return value of LockResource from displaying the
  381. // message.
  382. //
  383. if (!RtlPcToFileHeader( (PVOID)hMem, &ImageBase)) {
  384. DbgPrint( "*** GlobalUnlock( %lx ) - invalid handle\n", hMem );
  385. BaseHeapBreakPoint();
  386. }
  387. #endif
  388. SetLastError( ERROR_INVALID_HANDLE );
  389. }
  390. else
  391. if (HandleEntry->LockCount-- == 0) {
  392. HandleEntry->LockCount++;
  393. SetLastError( ERROR_NOT_LOCKED );
  394. Result = FALSE;
  395. }
  396. else
  397. if (HandleEntry->LockCount == 0) {
  398. SetLastError( NO_ERROR );
  399. Result = FALSE;
  400. }
  401. }
  402. except (EXCEPTION_EXECUTE_HANDLER) {
  403. BaseSetLastNTError( GetExceptionCode() );
  404. }
  405. RtlUnlockHeap( BaseHeap );
  406. }
  407. return( Result );
  408. }
  409. SIZE_T
  410. WINAPI
  411. GlobalSize(
  412. HANDLE hMem
  413. )
  414. {
  415. PBASE_HANDLE_TABLE_ENTRY HandleEntry;
  416. PVOID Handle;
  417. ULONG Flags;
  418. SIZE_T dwSize;
  419. dwSize = MAXULONG_PTR;
  420. Flags = 0;
  421. RtlLockHeap( BaseHeap );
  422. try {
  423. if (!((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT)) {
  424. Handle = NULL;
  425. if (!RtlGetUserInfoHeap( BaseHeap, Flags, hMem, &Handle, &Flags )) {
  426. }
  427. else
  428. if (Handle == NULL || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
  429. dwSize = RtlSizeHeap( BaseHeap, HEAP_NO_SERIALIZE, (PVOID)hMem );
  430. }
  431. else {
  432. hMem = Handle;
  433. }
  434. }
  435. if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {
  436. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
  437. CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
  438. if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
  439. #if DBG
  440. DbgPrint( "*** GlobalSize( %lx ) - invalid handle\n", hMem );
  441. BaseHeapBreakPoint();
  442. #endif
  443. SetLastError( ERROR_INVALID_HANDLE );
  444. }
  445. else
  446. if (HandleEntry->Flags & BASE_HANDLE_DISCARDED) {
  447. dwSize = HandleEntry->Size;
  448. }
  449. else {
  450. dwSize = RtlSizeHeap( BaseHeap, HEAP_NO_SERIALIZE, HandleEntry->Object );
  451. }
  452. }
  453. }
  454. except (EXCEPTION_EXECUTE_HANDLER) {
  455. BaseSetLastNTError( GetExceptionCode() );
  456. }
  457. RtlUnlockHeap( BaseHeap );
  458. if (dwSize == MAXULONG_PTR) {
  459. SetLastError( ERROR_INVALID_HANDLE );
  460. return 0;
  461. }
  462. else {
  463. return dwSize;
  464. }
  465. }
  466. UINT
  467. WINAPI
  468. GlobalFlags(
  469. HANDLE hMem
  470. )
  471. {
  472. PBASE_HANDLE_TABLE_ENTRY HandleEntry;
  473. HANDLE Handle;
  474. ULONG Flags;
  475. UINT uFlags;
  476. uFlags = GMEM_INVALID_HANDLE;
  477. RtlLockHeap( BaseHeap );
  478. try {
  479. if (!((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT)) {
  480. Handle = NULL;
  481. Flags = 0;
  482. if (!RtlGetUserInfoHeap( BaseHeap, Flags, hMem, &Handle, &Flags )) {
  483. }
  484. else
  485. if (Handle == NULL || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
  486. uFlags = 0;
  487. }
  488. else {
  489. hMem = Handle;
  490. }
  491. }
  492. if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {
  493. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
  494. CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
  495. if (RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
  496. uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT;
  497. if (HandleEntry->Flags & BASE_HANDLE_DISCARDED) {
  498. uFlags |= GMEM_DISCARDED;
  499. }
  500. if (HandleEntry->Flags & BASE_HANDLE_DISCARDABLE) {
  501. uFlags |= GMEM_DISCARDABLE;
  502. }
  503. if (HandleEntry->Flags & BASE_HANDLE_SHARED) {
  504. uFlags |= GMEM_DDESHARE;
  505. }
  506. }
  507. }
  508. if (uFlags == GMEM_INVALID_HANDLE) {
  509. #if DBG
  510. DbgPrint( "*** GlobalFlags( %lx ) - invalid handle\n", hMem );
  511. BaseHeapBreakPoint();
  512. #endif
  513. SetLastError( ERROR_INVALID_HANDLE );
  514. }
  515. }
  516. except (EXCEPTION_EXECUTE_HANDLER) {
  517. BaseSetLastNTError( GetExceptionCode() );
  518. }
  519. RtlUnlockHeap( BaseHeap );
  520. return( uFlags );
  521. }
  522. HGLOBAL
  523. WINAPI
  524. GlobalFree(
  525. HGLOBAL hMem
  526. )
  527. {
  528. PBASE_HANDLE_TABLE_ENTRY HandleEntry;
  529. LPSTR p;
  530. try {
  531. if (pfnWowGlobalFreeHook != NULL) {
  532. if (!(*pfnWowGlobalFreeHook)(hMem)) {
  533. return NULL;
  534. }
  535. }
  536. if (!((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT)) {
  537. if (RtlFreeHeap( BaseHeap, 0, (PVOID)hMem )) {
  538. return NULL;
  539. }
  540. else {
  541. SetLastError( ERROR_INVALID_HANDLE );
  542. return hMem;
  543. }
  544. }
  545. }
  546. except (EXCEPTION_EXECUTE_HANDLER) {
  547. BaseSetLastNTError( GetExceptionCode() );
  548. return hMem;
  549. }
  550. RtlLockHeap( BaseHeap );
  551. try {
  552. if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {
  553. HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
  554. CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
  555. if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
  556. #if DBG
  557. DbgPrint( "*** GlobalFree( %lx ) - invalid handle\n", hMem );
  558. BaseHeapBreakPoint();
  559. #endif
  560. SetLastError( ERROR_INVALID_HANDLE );
  561. p = NULL;
  562. }
  563. else {
  564. #if DBG
  565. if (HandleEntry->LockCount != 0) {
  566. DbgPrint( "BASE: GlobalFree called with a locked object.\n" );
  567. BaseHeapBreakPoint();
  568. }
  569. #endif
  570. p = HandleEntry->Object;
  571. RtlFreeHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
  572. if (p == NULL) {
  573. hMem = NULL;
  574. }
  575. }
  576. }
  577. else {
  578. p = (LPSTR)hMem;
  579. }
  580. if (p != NULL) {
  581. if (RtlFreeHeap( BaseHeap, HEAP_NO_SERIALIZE, p )) {
  582. hMem = NULL;
  583. }
  584. else {
  585. SetLastError( ERROR_INVALID_HANDLE );
  586. }
  587. }
  588. }
  589. except (EXCEPTION_EXECUTE_HANDLER) {
  590. BaseSetLastNTError( GetExceptionCode() );
  591. }
  592. RtlUnlockHeap( BaseHeap );
  593. return( hMem );
  594. }
  595. SIZE_T
  596. WINAPI
  597. GlobalCompact(
  598. DWORD dwMinFree
  599. )
  600. {
  601. return RtlCompactHeap( BaseHeap, 0 );
  602. }
  603. VOID
  604. WINAPI
  605. GlobalFix(
  606. HGLOBAL hMem
  607. )
  608. {
  609. if (hMem != (HGLOBAL)-1) {
  610. GlobalLock( hMem );
  611. }
  612. return;
  613. }
  614. VOID
  615. WINAPI
  616. GlobalUnfix(
  617. HGLOBAL hMem
  618. )
  619. {
  620. if (hMem != (HGLOBAL)-1) {
  621. GlobalUnlock( hMem );
  622. }
  623. return;
  624. }
  625. LPVOID
  626. WINAPI
  627. GlobalWire(
  628. HGLOBAL hMem
  629. )
  630. {
  631. return GlobalLock( hMem );
  632. }
  633. BOOL
  634. WINAPI
  635. GlobalUnWire(
  636. HGLOBAL hMem
  637. )
  638. {
  639. return GlobalUnlock( hMem );
  640. }
  641. VOID
  642. WINAPI
  643. GlobalMemoryStatus(
  644. LPMEMORYSTATUS lpBuffer
  645. )
  646. {
  647. DWORD NumberOfPhysicalPages;
  648. SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
  649. VM_COUNTERS VmCounters;
  650. QUOTA_LIMITS QuotaLimits;
  651. NTSTATUS Status;
  652. PPEB Peb;
  653. PIMAGE_NT_HEADERS NtHeaders;
  654. DWORDLONG Memory64;
  655. Status = NtQuerySystemInformation(
  656. SystemPerformanceInformation,
  657. &PerfInfo,
  658. sizeof(PerfInfo),
  659. NULL);
  660. ASSERT(NT_SUCCESS(Status));
  661. lpBuffer->dwLength = sizeof( *lpBuffer );
  662. //
  663. // Capture the number of physical pages as it can change dynamically.
  664. // If it goes up or down in the middle of this routine, the results may
  665. // look strange (ie: available > total, etc), but it will quickly
  666. // right itself.
  667. //
  668. NumberOfPhysicalPages = USER_SHARED_DATA->NumberOfPhysicalPages;
  669. #if defined(BUILD_WOW6432)
  670. //
  671. // Convert the number of physical pages from the native system to
  672. // the emulation system.
  673. //
  674. NumberOfPhysicalPages = NumberOfPhysicalPages * (Wow64GetSystemNativePageSize() / BASE_SYSINFO.PageSize);
  675. #endif
  676. //
  677. // Determine the memory load. < 100 available pages is 100
  678. // Otherwise load is ((TotalPhys - AvailPhys) * 100) / TotalPhys
  679. //
  680. if (PerfInfo.AvailablePages < 100) {
  681. lpBuffer->dwMemoryLoad = 100;
  682. } else {
  683. lpBuffer->dwMemoryLoad =
  684. ((DWORD)(NumberOfPhysicalPages - PerfInfo.AvailablePages) * 100) /
  685. NumberOfPhysicalPages;
  686. }
  687. //
  688. // Determine the physical memory sizes.
  689. //
  690. Memory64 = (DWORDLONG)NumberOfPhysicalPages * BASE_SYSINFO.PageSize;
  691. lpBuffer->dwTotalPhys = (SIZE_T) __min(Memory64, MAXULONG_PTR);
  692. Memory64 = ((DWORDLONG)PerfInfo.AvailablePages * (DWORDLONG)BASE_SYSINFO.PageSize);
  693. lpBuffer->dwAvailPhys = (SIZE_T) __min(Memory64, MAXULONG_PTR);
  694. if (gpTermsrvAdjustPhyMemLimits) {
  695. gpTermsrvAdjustPhyMemLimits(&(lpBuffer->dwTotalPhys),
  696. &(lpBuffer->dwAvailPhys),
  697. BASE_SYSINFO.PageSize);
  698. }
  699. //
  700. // Zero returned values in case the query process fails.
  701. //
  702. RtlZeroMemory (&QuotaLimits, sizeof (QUOTA_LIMITS));
  703. RtlZeroMemory (&VmCounters, sizeof (VM_COUNTERS));
  704. Status = NtQueryInformationProcess (NtCurrentProcess(),
  705. ProcessQuotaLimits,
  706. &QuotaLimits,
  707. sizeof(QUOTA_LIMITS),
  708. NULL);
  709. ASSERT(NT_SUCCESS(Status));
  710. Status = NtQueryInformationProcess (NtCurrentProcess(),
  711. ProcessVmCounters,
  712. &VmCounters,
  713. sizeof(VM_COUNTERS),
  714. NULL);
  715. ASSERT(NT_SUCCESS(Status));
  716. //
  717. // Determine the total page file space with respect to this process.
  718. //
  719. Memory64 = __min(PerfInfo.CommitLimit, QuotaLimits.PagefileLimit);
  720. Memory64 *= BASE_SYSINFO.PageSize;
  721. lpBuffer->dwTotalPageFile = (SIZE_T)__min(Memory64, MAXULONG_PTR);
  722. //
  723. // Determine remaining page file space with respect to this process.
  724. //
  725. Memory64 = __min(PerfInfo.CommitLimit - PerfInfo.CommittedPages,
  726. QuotaLimits.PagefileLimit - VmCounters.PagefileUsage);
  727. Memory64 *= BASE_SYSINFO.PageSize;
  728. lpBuffer->dwAvailPageFile = (SIZE_T) __min(Memory64, MAXULONG_PTR);
  729. lpBuffer->dwTotalVirtual = (BASE_SYSINFO.MaximumUserModeAddress -
  730. BASE_SYSINFO.MinimumUserModeAddress) + 1;
  731. lpBuffer->dwAvailVirtual = lpBuffer->dwTotalVirtual - VmCounters.VirtualSize;
  732. #if !defined(_WIN64)
  733. //
  734. // Lie about available memory if application can't handle large (>2GB) addresses
  735. //
  736. Peb = NtCurrentPeb();
  737. NtHeaders = RtlImageNtHeader( Peb->ImageBaseAddress );
  738. if (NtHeaders && !(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) {
  739. if (BASE_SYSINFO.MaximumUserModeAddress > 0x7FFEFFFF) {
  740. //
  741. // Booted /3GB, but the application can't handle large virtual
  742. // addresses so remove the portion above 2GB. Note this portion
  743. // is variable from zero up to 1GB (depending on the /USERVA value).
  744. //
  745. lpBuffer->dwAvailVirtual -= (BASE_SYSINFO.MaximumUserModeAddress - 0x7FFEFFFF);
  746. }
  747. if (lpBuffer->dwTotalPhys > 0x7FFFFFFF) {
  748. lpBuffer->dwTotalPhys = 0x7FFFFFFF;
  749. }
  750. if (lpBuffer->dwAvailPhys > 0x7FFFFFFF) {
  751. lpBuffer->dwAvailPhys = 0x7FFFFFFF;
  752. }
  753. if (lpBuffer->dwTotalVirtual > 0x7FFFFFFF) {
  754. lpBuffer->dwTotalVirtual = 0x7FFFFFFF;
  755. }
  756. if (lpBuffer->dwAvailVirtual > 0x7FFFFFFF) {
  757. lpBuffer->dwAvailVirtual = 0x7FFFFFFF;
  758. }
  759. }
  760. #endif
  761. return;
  762. }
  763. PVOID
  764. WINAPI
  765. VirtualAlloc(
  766. PVOID lpAddress,
  767. SIZE_T dwSize,
  768. DWORD flAllocationType,
  769. DWORD flProtect
  770. )
  771. {
  772. return VirtualAllocEx(
  773. NtCurrentProcess(),
  774. lpAddress,
  775. dwSize,
  776. flAllocationType,
  777. flProtect
  778. );
  779. }
  780. BOOL
  781. WINAPI
  782. VirtualFree(
  783. LPVOID lpAddress,
  784. SIZE_T dwSize,
  785. DWORD dwFreeType
  786. )
  787. {
  788. return VirtualFreeEx(NtCurrentProcess(),lpAddress,dwSize,dwFreeType);
  789. }
  790. PVOID
  791. WINAPI
  792. VirtualAllocEx(
  793. HANDLE hProcess,
  794. PVOID lpAddress,
  795. SIZE_T dwSize,
  796. DWORD flAllocationType,
  797. DWORD flProtect
  798. )
  799. {
  800. NTSTATUS Status;
  801. if (lpAddress != NULL && (ULONG_PTR)lpAddress < BASE_SYSINFO.AllocationGranularity) {
  802. SetLastError( ERROR_INVALID_PARAMETER );
  803. return( NULL );
  804. }
  805. try {
  806. Status = NtAllocateVirtualMemory( hProcess,
  807. &lpAddress,
  808. 0,
  809. &dwSize,
  810. flAllocationType,
  811. flProtect
  812. );
  813. } except( EXCEPTION_EXECUTE_HANDLER ) {
  814. Status = GetExceptionCode();
  815. }
  816. if (NT_SUCCESS( Status )) {
  817. return( lpAddress );
  818. } else {
  819. BaseSetLastNTError( Status );
  820. return( NULL );
  821. }
  822. }
  823. BOOL
  824. WINAPI
  825. VirtualFreeEx(
  826. HANDLE hProcess,
  827. LPVOID lpAddress,
  828. SIZE_T dwSize,
  829. DWORD dwFreeType
  830. )
  831. {
  832. NTSTATUS Status;
  833. if ( (dwFreeType & MEM_RELEASE ) && dwSize != 0 ) {
  834. BaseSetLastNTError( STATUS_INVALID_PARAMETER );
  835. return FALSE;
  836. }
  837. Status = NtFreeVirtualMemory( hProcess,
  838. &lpAddress,
  839. &dwSize,
  840. dwFreeType
  841. );
  842. if (NT_SUCCESS( Status )) {
  843. return( TRUE );
  844. }
  845. else {
  846. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  847. if (hProcess == NtCurrentProcess()) {
  848. //
  849. // Unlock any pages that were locked with MmSecureVirtualMemory.
  850. // This is useful for SANs.
  851. //
  852. if (RtlFlushSecureMemoryCache(lpAddress, dwSize)) {
  853. Status = NtFreeVirtualMemory( hProcess,
  854. &lpAddress,
  855. &dwSize,
  856. dwFreeType
  857. );
  858. if (NT_SUCCESS( Status )) {
  859. return( TRUE );
  860. }
  861. }
  862. }
  863. }
  864. BaseSetLastNTError( Status );
  865. return( FALSE );
  866. }
  867. }
  868. BOOL
  869. WINAPI
  870. VirtualProtect(
  871. PVOID lpAddress,
  872. SIZE_T dwSize,
  873. DWORD flNewProtect,
  874. PDWORD lpflOldProtect
  875. )
  876. {
  877. return VirtualProtectEx( NtCurrentProcess(),
  878. lpAddress,
  879. dwSize,
  880. flNewProtect,
  881. lpflOldProtect
  882. );
  883. }
  884. BOOL
  885. WINAPI
  886. VirtualProtectEx(
  887. HANDLE hProcess,
  888. PVOID lpAddress,
  889. SIZE_T dwSize,
  890. DWORD flNewProtect,
  891. PDWORD lpflOldProtect
  892. )
  893. {
  894. NTSTATUS Status;
  895. Status = NtProtectVirtualMemory( hProcess,
  896. &lpAddress,
  897. &dwSize,
  898. flNewProtect,
  899. lpflOldProtect
  900. );
  901. if (NT_SUCCESS( Status )) {
  902. return( TRUE );
  903. }
  904. else {
  905. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  906. if (hProcess == NtCurrentProcess()) {
  907. //
  908. // Unlock any pages that were locked with MmSecureVirtualMemory.
  909. // This is useful for SANs.
  910. //
  911. if (RtlFlushSecureMemoryCache(lpAddress, dwSize)) {
  912. Status = NtProtectVirtualMemory( hProcess,
  913. &lpAddress,
  914. &dwSize,
  915. flNewProtect,
  916. lpflOldProtect
  917. );
  918. if (NT_SUCCESS( Status )) {
  919. return( TRUE );
  920. }
  921. }
  922. }
  923. }
  924. BaseSetLastNTError( Status );
  925. return( FALSE );
  926. }
  927. }
  928. SIZE_T
  929. WINAPI
  930. VirtualQuery(
  931. LPCVOID lpAddress,
  932. PMEMORY_BASIC_INFORMATION lpBuffer,
  933. SIZE_T dwLength
  934. )
  935. {
  936. return VirtualQueryEx( NtCurrentProcess(),
  937. lpAddress,
  938. (PMEMORY_BASIC_INFORMATION)lpBuffer,
  939. dwLength
  940. );
  941. }
  942. SIZE_T
  943. WINAPI
  944. VirtualQueryEx(
  945. HANDLE hProcess,
  946. LPCVOID lpAddress,
  947. PMEMORY_BASIC_INFORMATION lpBuffer,
  948. SIZE_T dwLength
  949. )
  950. {
  951. NTSTATUS Status;
  952. SIZE_T ReturnLength;
  953. Status = NtQueryVirtualMemory( hProcess,
  954. (LPVOID)lpAddress,
  955. MemoryBasicInformation,
  956. (PMEMORY_BASIC_INFORMATION)lpBuffer,
  957. dwLength,
  958. &ReturnLength
  959. );
  960. if (NT_SUCCESS( Status )) {
  961. return( ReturnLength );
  962. }
  963. else {
  964. BaseSetLastNTError( Status );
  965. return( 0 );
  966. }
  967. }
  968. BOOL
  969. WINAPI
  970. VirtualLock(
  971. LPVOID lpAddress,
  972. SIZE_T dwSize
  973. )
  974. /*++
  975. Routine Description:
  976. This API may be used to lock the specified range of the processes
  977. address space into memory. This range is present whenever the
  978. application is running. All pages covered by the range must be
  979. commited. VirtialLock is in now way related to LocalLock or
  980. GlobalLock. It does not perform a handle translation. Its function
  981. is to lock memory in the "working set" of the calling process.
  982. Note that the specified range is used to compute the range of pages
  983. covered by the lock. A 2 byte lock that straddles a page boundry
  984. ends up locking both of the pages covered by the range. Also note
  985. that calls to VirtualLock do not nest.
  986. Arguments:
  987. lpAddress - Supplies the base address of the region being locked.
  988. dwSize - Supplies the number of bytes being locked.
  989. Return Value:
  990. TRUE - The operation was was successful.
  991. FALSE - The operation failed. Extended error status is available
  992. using GetLastError.
  993. --*/
  994. {
  995. NTSTATUS Status;
  996. PVOID BaseAddress;
  997. SIZE_T RegionSize;
  998. BOOL ReturnValue;
  999. ReturnValue = TRUE;
  1000. BaseAddress = lpAddress;
  1001. RegionSize = dwSize;
  1002. Status = NtLockVirtualMemory(
  1003. NtCurrentProcess(),
  1004. &lpAddress,
  1005. &RegionSize,
  1006. MAP_PROCESS
  1007. );
  1008. if ( !NT_SUCCESS(Status) ) {
  1009. BaseSetLastNTError(Status);
  1010. ReturnValue = FALSE;
  1011. }
  1012. return ReturnValue;
  1013. }
  1014. BOOL
  1015. WINAPI
  1016. VirtualUnlock(
  1017. LPVOID lpAddress,
  1018. SIZE_T dwSize
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. This API may be used to unlock the specified range of the processes
  1023. address space from memory. This call is used to reveres the effects of
  1024. a previous call to VirtualLock. The range specified need not match
  1025. a range passed to a previous VirtualLock call, but it must specify
  1026. a locked range" for this API to be successful.
  1027. Note that the specified range is used to compute the range of pages
  1028. covered by the unlock. A 2 byte unlock that straddles a page boundry
  1029. ends up unlocking both of the pages covered by the range.
  1030. Arguments:
  1031. lpAddress - Supplies the base address of the region being unlocked.
  1032. dwSize - Supplies the number of bytes being unlocked.
  1033. Return Value:
  1034. TRUE - The operation was was successful.
  1035. FALSE - The operation failed. Extended error status is available
  1036. using GetLastError.
  1037. --*/
  1038. {
  1039. NTSTATUS Status;
  1040. PVOID BaseAddress;
  1041. SIZE_T RegionSize;
  1042. BOOL ReturnValue;
  1043. ReturnValue = TRUE;
  1044. BaseAddress = lpAddress;
  1045. RegionSize = dwSize;
  1046. Status = NtUnlockVirtualMemory(
  1047. NtCurrentProcess(),
  1048. &lpAddress,
  1049. &RegionSize,
  1050. MAP_PROCESS
  1051. );
  1052. if ( !NT_SUCCESS(Status) ) {
  1053. BaseSetLastNTError(Status);
  1054. ReturnValue = FALSE;
  1055. }
  1056. return ReturnValue;
  1057. }
  1058. BOOL
  1059. WINAPI
  1060. FlushInstructionCache(
  1061. HANDLE hProcess,
  1062. LPCVOID lpBaseAddress,
  1063. SIZE_T dwSize
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. This function flushes the instruction cache for the specified process.
  1068. Arguments:
  1069. hProcess - Supplies a handle to the process in which the instruction
  1070. cache is to be flushed.
  1071. lpBaseAddress - Supplies an optional pointer to base of the region that
  1072. is flushed.
  1073. dwSize - Supplies the length of the region that is flushed if the base
  1074. address is specified.
  1075. Return Value:
  1076. TRUE - The operation was was successful.
  1077. FALSE - The operation failed. Extended error status is available
  1078. using GetLastError.
  1079. --*/
  1080. {
  1081. NTSTATUS Status;
  1082. BOOL ReturnValue = TRUE;
  1083. Status = NtFlushInstructionCache(
  1084. hProcess,
  1085. (LPVOID)lpBaseAddress,
  1086. dwSize
  1087. );
  1088. if ( !NT_SUCCESS(Status) ) {
  1089. BaseSetLastNTError(Status);
  1090. ReturnValue = FALSE;
  1091. }
  1092. return ReturnValue;
  1093. }
  1094. BOOL
  1095. WINAPI
  1096. AllocateUserPhysicalPages(
  1097. HANDLE hProcess,
  1098. PULONG_PTR NumberOfPages,
  1099. PULONG_PTR PageArray
  1100. )
  1101. {
  1102. NTSTATUS Status;
  1103. Status = NtAllocateUserPhysicalPages( hProcess,
  1104. NumberOfPages,
  1105. PageArray);
  1106. if (NT_SUCCESS( Status )) {
  1107. return( TRUE );
  1108. }
  1109. else {
  1110. BaseSetLastNTError( Status );
  1111. return( FALSE );
  1112. }
  1113. }
  1114. BOOL
  1115. WINAPI
  1116. FreeUserPhysicalPages(
  1117. HANDLE hProcess,
  1118. PULONG_PTR NumberOfPages,
  1119. PULONG_PTR PageArray
  1120. )
  1121. {
  1122. NTSTATUS Status;
  1123. Status = NtFreeUserPhysicalPages( hProcess,
  1124. NumberOfPages,
  1125. PageArray);
  1126. if (NT_SUCCESS( Status )) {
  1127. return( TRUE );
  1128. }
  1129. else {
  1130. BaseSetLastNTError( Status );
  1131. return( FALSE );
  1132. }
  1133. }
  1134. BOOL
  1135. WINAPI
  1136. MapUserPhysicalPages(
  1137. PVOID VirtualAddress,
  1138. ULONG_PTR NumberOfPages,
  1139. PULONG_PTR PageArray
  1140. )
  1141. {
  1142. NTSTATUS Status;
  1143. Status = NtMapUserPhysicalPages( VirtualAddress,
  1144. NumberOfPages,
  1145. PageArray);
  1146. if (NT_SUCCESS( Status )) {
  1147. return( TRUE );
  1148. } else {
  1149. BaseSetLastNTError( Status );
  1150. return( FALSE );
  1151. }
  1152. }
  1153. BOOL
  1154. WINAPI
  1155. MapUserPhysicalPagesScatter(
  1156. PVOID *VirtualAddresses,
  1157. ULONG_PTR NumberOfPages,
  1158. PULONG_PTR PageArray
  1159. )
  1160. {
  1161. NTSTATUS Status;
  1162. Status = NtMapUserPhysicalPagesScatter( VirtualAddresses,
  1163. NumberOfPages,
  1164. PageArray);
  1165. if (NT_SUCCESS( Status )) {
  1166. return( TRUE );
  1167. } else {
  1168. BaseSetLastNTError( Status );
  1169. return( FALSE );
  1170. }
  1171. }
  1172. BOOL
  1173. WINAPI
  1174. GlobalMemoryStatusEx(
  1175. LPMEMORYSTATUSEX lpBuffer
  1176. )
  1177. {
  1178. DWORD NumberOfPhysicalPages;
  1179. SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
  1180. VM_COUNTERS VmCounters;
  1181. QUOTA_LIMITS QuotaLimits;
  1182. DWORDLONG AvailPageFile;
  1183. DWORDLONG PhysicalMemory;
  1184. NTSTATUS Status;
  1185. DWORD Success;
  1186. DWORDLONG address64;
  1187. if (lpBuffer->dwLength != sizeof(*lpBuffer)) {
  1188. SetLastError( ERROR_INVALID_PARAMETER );
  1189. return FALSE;
  1190. }
  1191. Status = NtQuerySystemInformation (SystemPerformanceInformation,
  1192. &PerfInfo,
  1193. sizeof(PerfInfo),
  1194. NULL);
  1195. if (!NT_SUCCESS (Status)) {
  1196. BaseSetLastNTError (Status);
  1197. return FALSE;
  1198. }
  1199. //
  1200. // Capture the number of physical pages as it can change dynamically.
  1201. // If it goes up or down in the middle of this routine, the results may
  1202. // look strange (ie: available > total, etc), but it will quickly
  1203. // right itself.
  1204. //
  1205. NumberOfPhysicalPages = USER_SHARED_DATA->NumberOfPhysicalPages;
  1206. #if defined(BUILD_WOW6432)
  1207. //
  1208. // Convert the number of physical pages from the native system to
  1209. // the emulation system.
  1210. //
  1211. NumberOfPhysicalPages = NumberOfPhysicalPages * (Wow64GetSystemNativePageSize() / BASE_SYSINFO.PageSize);
  1212. #endif
  1213. PhysicalMemory = (DWORDLONG)NumberOfPhysicalPages * BASE_SYSINFO.PageSize;
  1214. //
  1215. // Determine the memory load. < 100 available pages is 100
  1216. // Otherwise load is ((TotalPhys - AvailPhys) * 100) / TotalPhys
  1217. //
  1218. if (PerfInfo.AvailablePages < 100) {
  1219. lpBuffer->dwMemoryLoad = 100;
  1220. } else {
  1221. lpBuffer->dwMemoryLoad =
  1222. ((DWORD)(NumberOfPhysicalPages - PerfInfo.AvailablePages) * 100) /
  1223. NumberOfPhysicalPages;
  1224. }
  1225. lpBuffer->ullTotalPhys = PhysicalMemory;
  1226. PhysicalMemory = PerfInfo.AvailablePages;
  1227. PhysicalMemory *= BASE_SYSINFO.PageSize;
  1228. lpBuffer->ullAvailPhys = PhysicalMemory;
  1229. //
  1230. // Zero returned values in case the query process fails.
  1231. //
  1232. RtlZeroMemory (&QuotaLimits, sizeof (QUOTA_LIMITS));
  1233. RtlZeroMemory (&VmCounters, sizeof (VM_COUNTERS));
  1234. Status = NtQueryInformationProcess (NtCurrentProcess(),
  1235. ProcessQuotaLimits,
  1236. &QuotaLimits,
  1237. sizeof(QUOTA_LIMITS),
  1238. NULL );
  1239. if (!NT_SUCCESS (Status)) {
  1240. BaseSetLastNTError (Status);
  1241. return FALSE;
  1242. }
  1243. Status = NtQueryInformationProcess (NtCurrentProcess(),
  1244. ProcessVmCounters,
  1245. &VmCounters,
  1246. sizeof(VM_COUNTERS),
  1247. NULL );
  1248. if (!NT_SUCCESS (Status)) {
  1249. BaseSetLastNTError (Status);
  1250. return FALSE;
  1251. }
  1252. //
  1253. // Determine the total page file space with respect to this process.
  1254. //
  1255. lpBuffer->ullTotalPageFile = PerfInfo.CommitLimit;
  1256. if (QuotaLimits.PagefileLimit < PerfInfo.CommitLimit) {
  1257. lpBuffer->ullTotalPageFile = QuotaLimits.PagefileLimit;
  1258. }
  1259. lpBuffer->ullTotalPageFile *= BASE_SYSINFO.PageSize;
  1260. //
  1261. // Determine remaining page file space with respect to this process.
  1262. //
  1263. AvailPageFile = PerfInfo.CommitLimit - PerfInfo.CommittedPages;
  1264. lpBuffer->ullAvailPageFile =
  1265. QuotaLimits.PagefileLimit - VmCounters.PagefileUsage;
  1266. if ((ULONG)lpBuffer->ullAvailPageFile > (ULONG)AvailPageFile) {
  1267. lpBuffer->ullAvailPageFile = AvailPageFile;
  1268. }
  1269. lpBuffer->ullAvailPageFile *= BASE_SYSINFO.PageSize;
  1270. lpBuffer->ullTotalVirtual = (BASE_SYSINFO.MaximumUserModeAddress -
  1271. BASE_SYSINFO.MinimumUserModeAddress) + 1;
  1272. lpBuffer->ullAvailVirtual = lpBuffer->ullTotalVirtual - VmCounters.VirtualSize;
  1273. lpBuffer->ullAvailExtendedVirtual = 0;
  1274. return TRUE;
  1275. }
  1276. WINBASEAPI
  1277. UINT
  1278. WINAPI
  1279. GetWriteWatch(
  1280. DWORD dwFlags,
  1281. PVOID lpBaseAddress,
  1282. SIZE_T dwRegionSize,
  1283. PVOID *addresses,
  1284. ULONG_PTR *count,
  1285. LPDWORD granularity
  1286. )
  1287. {
  1288. NTSTATUS Status;
  1289. Status = NtGetWriteWatch ( NtCurrentProcess(),
  1290. dwFlags,
  1291. lpBaseAddress,
  1292. dwRegionSize,
  1293. addresses,
  1294. count,
  1295. granularity
  1296. );
  1297. //
  1298. // Note these return codes are taken straight from Win9x.
  1299. //
  1300. if (NT_SUCCESS( Status )) {
  1301. return( 0 );
  1302. }
  1303. else {
  1304. BaseSetLastNTError( Status );
  1305. return (UINT)-1;
  1306. }
  1307. }
  1308. WINBASEAPI
  1309. UINT
  1310. WINAPI
  1311. ResetWriteWatch(
  1312. LPVOID lpBaseAddress,
  1313. SIZE_T dwRegionSize
  1314. )
  1315. {
  1316. NTSTATUS Status;
  1317. Status = NtResetWriteWatch ( NtCurrentProcess(),
  1318. lpBaseAddress,
  1319. dwRegionSize
  1320. );
  1321. //
  1322. // Note these return codes are taken straight from Win9x.
  1323. //
  1324. if (NT_SUCCESS( Status )) {
  1325. return( 0 );
  1326. }
  1327. else {
  1328. BaseSetLastNTError( Status );
  1329. return (UINT)-1;
  1330. }
  1331. }
  1332. SIZE_T
  1333. WINAPI
  1334. GetLargePageMinimum (
  1335. VOID
  1336. )
  1337. /*++
  1338. Routine Description:
  1339. This function returns the size in bytes of the minimum large
  1340. page size and address alignment that can be used with the
  1341. VirtualAlloc MEM_LARGE_PAGES flag.
  1342. Arguments:
  1343. None.
  1344. Return Value:
  1345. The size in bytes of the minimum large page or zero if no large page
  1346. is supported by the underlying hardware.
  1347. --*/
  1348. {
  1349. return (SIZE_T) USER_SHARED_DATA->LargePageMinimum;
  1350. }