Source code of Windows XP (NT5)
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.

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