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.

208 lines
5.6 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1992, Microsoft Corporation
  6. *
  7. * WKMEM.C
  8. * WOW32 KRNL386 Virtual Memory Management Functions
  9. *
  10. * History:
  11. * Created 3-Dec-1992 by Matt Felton (mattfe)
  12. *
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include "memapi.h"
  17. MODNAME(wkman.c);
  18. // some apps free global memory
  19. LPVOID glpvDelayFree[4]; // which is in turn freed by kernel as the asks it
  20. DWORD gdwDelayFree; // but then app comes back and tries to access it
  21. // this is our hack variables to accomodate them
  22. ULONG FASTCALL WK32VirtualAlloc(PVDMFRAME pFrame)
  23. {
  24. PVIRTUALALLOC16 parg16;
  25. ULONG lpBaseAddress;
  26. #ifndef i386
  27. NTSTATUS Status;
  28. #endif
  29. GETARGPTR(pFrame, sizeof(VIRTUALALLOC16), parg16);
  30. #ifndef i386
  31. Status = VdmAllocateVirtualMemory(&lpBaseAddress,
  32. parg16->cbSize,
  33. TRUE);
  34. if (!NT_SUCCESS(Status)) {
  35. if (Status == STATUS_NOT_IMPLEMENTED) {
  36. #endif // i386
  37. lpBaseAddress = (ULONG) VirtualAlloc((LPVOID)parg16->lpvAddress,
  38. parg16->cbSize,
  39. parg16->fdwAllocationType,
  40. parg16->fdwProtect);
  41. #ifndef i386
  42. } else {
  43. lpBaseAddress = 0;
  44. }
  45. }
  46. #endif // i386
  47. #ifdef i386
  48. //BUGBUG we need to either get this working on the new emulator, or
  49. // fix the problem the "other" way, by letting the app fault and
  50. // zap in just enough 'WOW's to avoid the problem.
  51. if (lpBaseAddress) {
  52. // Virtual alloc Zero's the allocated memory. We un-zero it by
  53. // filling in with ' WOW'. This is required for Lotus Improv.
  54. // When no printer is installed, Lotus Improv dies with divide
  55. // by zero error (while opening the expenses.imp file) because
  56. // it doesn't initialize a relevant portion of its data area.
  57. //
  58. // So we decided that this a convenient place to initialize
  59. // the memory to a non-zero value.
  60. // - Nanduri
  61. //
  62. // Dbase 5.0 for windows erroneously loops through (past its valid
  63. // data) its data buffer till it finds a '\0' at some location -
  64. // Most of the time the loop terminates before it reaches the segment
  65. // limit. However if the block that was allocated is a 'fresh' block' ie
  66. // the block is filled with ' WOW' it never finds a NULL in the buffer
  67. // and thus loops past the segment limit to its death
  68. //
  69. // So we initialize the buffer with '\0WOW' instead of ' WOW'.
  70. // - Nanduri
  71. WOW32ASSERT((parg16->cbSize % 4) == 0); // DWORD aligned?
  72. RtlFillMemoryUlong((PVOID)lpBaseAddress, parg16->cbSize, (ULONG)'\0WOW');
  73. }
  74. #endif
  75. FREEARGPTR(parg16);
  76. return (lpBaseAddress);
  77. }
  78. ULONG FASTCALL WK32VirtualFree(PVDMFRAME pFrame)
  79. {
  80. PVIRTUALFREE16 parg16;
  81. ULONG fResult;
  82. #ifndef i386
  83. NTSTATUS Status;
  84. #endif
  85. // Delay free
  86. // some apps, ntbug 90849 CreateScreenSavers Quick and Easy
  87. // free 16 bit global heap then try to access it again
  88. // but kernel has already freed/compacted global heap
  89. // this will delay that process for a while (something similar to DisableHeapLookAside in nt
  90. // Millenium implemented something similar
  91. // -jarbats
  92. if( NULL != glpvDelayFree[gdwDelayFree])
  93. {
  94. #ifndef i386
  95. Status = VdmFreeVirtualMemory( glpvDelayFree[gdwDelayFree]);
  96. fResult = NT_SUCCESS(Status);
  97. if (Status == STATUS_NOT_IMPLEMENTED) {
  98. #endif // i386
  99. fResult = VirtualFree(glpvDelayFree[gdwDelayFree],
  100. 0,
  101. MEM_RELEASE);
  102. #ifndef i386
  103. }
  104. #endif // i386
  105. }
  106. GETARGPTR(pFrame, sizeof(VIRTUALFREE16), parg16);
  107. glpvDelayFree[gdwDelayFree] = (LPVOID) parg16->lpvAddress;
  108. gdwDelayFree++;
  109. gdwDelayFree &= 3;
  110. FREEARGPTR(parg16);
  111. return (TRUE);
  112. }
  113. #if 0
  114. ULONG FASTCALL WK32VirtualLock(PVDMFRAME pFrame)
  115. {
  116. PVIRTUALLOCK16 parg16;
  117. BOOL fResult;
  118. WOW32ASSERT(FALSE); //BUGBUG we don't appear to ever use this function
  119. GETARGPTR(pFrame, sizeof(VIRTUALLOCK16), parg16);
  120. fResult = VirtualLock((LPVOID)parg16->lpvAddress,
  121. parg16->cbSize);
  122. FREEARGPTR(parg16);
  123. return (fResult);
  124. }
  125. ULONG FASTCALL WK32VirtualUnLock(PVDMFRAME pFrame)
  126. {
  127. PVIRTUALUNLOCK16 parg16;
  128. BOOL fResult;
  129. WOW32ASSERT(FALSE); //BUGBUG we don't appear to ever use this function
  130. GETARGPTR(pFrame, sizeof(VIRTUALUNLOCK16), parg16);
  131. fResult = VirtualUnlock((LPVOID)parg16->lpvAddress,
  132. parg16->cbSize);
  133. FREEARGPTR(parg16);
  134. return (fResult);
  135. }
  136. #endif
  137. ULONG FASTCALL WK32GlobalMemoryStatus(PVDMFRAME pFrame)
  138. {
  139. PGLOBALMEMORYSTATUS16 parg16;
  140. LPMEMORYSTATUS pMemStat;
  141. GETARGPTR(pFrame, sizeof(GLOBALMEMORYSTATUS16), parg16);
  142. GETVDMPTR(parg16->lpmstMemStat, 32, pMemStat);
  143. GlobalMemoryStatus(pMemStat);
  144. //
  145. // if /3GB switch is enabled in boot.ini, GlobalmemoryStatus may return
  146. // 0x7fffffff dwTotalVirtual and dwAvailVirtal. This will confuse some apps
  147. // in thinking something is wrong.
  148. //
  149. if (pMemStat->dwAvailVirtual == 0x7fffffff &&
  150. pMemStat->dwTotalVirtual == 0x7fffffff ) { // yes we need to check dwTotalVirtual too
  151. pMemStat->dwAvailVirtual -= 0x500000;
  152. }
  153. FREEVDMPTR(pMemStat);
  154. FREEARGPTR(parg16);
  155. return 0; // unused
  156. }