Windows NT 4.0 source code leak
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.

307 lines
6.3 KiB

4 years ago
  1. #include "stdafx.h"
  2. #ifdef _DEBUG
  3. #undef THIS_FILE
  4. static char THIS_FILE[] = __FILE__;
  5. #endif // _DEBUG
  6. #ifndef _CTMPFILE_INCLUDED
  7. #include "ctmpfile.h"
  8. #endif
  9. const int CB_COPY_BUFFER = 4096 * 8; // 64K
  10. // If memory exceeds LARGEST_ALLOC then we switch to a real file
  11. static int LARGEST_ALLOC = (1024 * 1024 * 8) - 4096L; // 8 megs
  12. CTmpFile::CTmpFile(void)
  13. {
  14. cbAlloc = 4096;
  15. pmem = (PBYTE) VirtualAlloc(NULL, LARGEST_ALLOC, MEM_RESERVE,
  16. PAGE_READWRITE);
  17. if (!pmem)
  18. OOM();
  19. if (!VirtualAlloc(pmem, cbAlloc, MEM_COMMIT, PAGE_READWRITE))
  20. OOM();
  21. cbFile = 0;
  22. FilePtr = 0;
  23. hf = HFILE_ERROR;
  24. pszFileName = NULL;
  25. }
  26. CTmpFile::~CTmpFile(void)
  27. {
  28. if (pszFileName) {
  29. _lclose(hf);
  30. remove(pszFileName);
  31. lcFree(pszFileName);
  32. }
  33. if (pmem) {
  34. VirtualFree(pmem, LARGEST_ALLOC, MEM_DECOMMIT);
  35. VirtualFree(pmem, 0, MEM_RELEASE);
  36. }
  37. }
  38. int STDCALL CTmpFile::seek(int lPos, int Origin)
  39. {
  40. if (pszFileName)
  41. return _llseek(hf, lPos, Origin);
  42. // REVIEW (niklasb): Seeking past the end of a real file does
  43. // not grow the file until the next write operation. We should
  44. // probably do the same here, especially since the code in this
  45. // function chokes if we grow past LARGEST_ALLOC.
  46. //
  47. switch (Origin) {
  48. case SEEK_SET:
  49. #if 0 // don't grow file until next write
  50. if (lPos > cbAlloc) {
  51. // Create more memory, aligned on a 4K page boundary
  52. int cbNew = lPos / 4096 * 4096 + 4096;
  53. ASSERT(cbNew < LARGEST_ALLOC);
  54. if (!VirtualAlloc(pmem + cbAlloc, cbNew - cbAlloc,
  55. MEM_COMMIT, PAGE_READWRITE))
  56. OOM();
  57. cbAlloc = cbNew;
  58. }
  59. #endif
  60. FilePtr = lPos;
  61. break;
  62. case SEEK_CUR:
  63. #if 0 // don't grow file until next write
  64. if (FilePtr + lPos > cbAlloc) {
  65. // Create more memory, aligned on a 4K page boundary
  66. int cbNew = (FilePtr + lPos) / 4096 * 4096 + 4096;
  67. ASSERT(cbNew < LARGEST_ALLOC);
  68. if (!VirtualAlloc(pmem + cbAlloc, cbNew - cbAlloc,
  69. MEM_COMMIT, PAGE_READWRITE))
  70. OOM();
  71. cbAlloc = cbNew;
  72. }
  73. #endif
  74. FilePtr += lPos;
  75. break;
  76. case SEEK_END:
  77. ASSERT(cbFile + lPos < cbAlloc);
  78. FilePtr = cbFile + lPos;
  79. break;
  80. default:
  81. ASSERT(TRUE);
  82. break;
  83. }
  84. return FilePtr;
  85. }
  86. int STDCALL CTmpFile::write(void* qv, int lcb)
  87. {
  88. ASSERT(qv);
  89. // If this is a real file, just write the data; we no
  90. // longer track cbFile in this case.
  91. if (pszFileName)
  92. return (int) _lwrite(hf, (LPCSTR) qv, lcb);
  93. // Grow the pseudo-file if necessary.
  94. if (FilePtr + lcb > cbAlloc) {
  95. // Calculate the new committed size (always 4K aligned).
  96. int cbNew = (FilePtr + lcb) / 4096 * 4096 + 4096;
  97. // If > reserved size, create a real file.
  98. if (cbNew > LARGEST_ALLOC) {
  99. DBWIN("Switching CTmpFile to a real file.");
  100. pszFileName = (PSTR) FmNewTemp();
  101. if (!pszFileName)
  102. OOM();
  103. hf = _lcreat(pszFileName, 0);
  104. if (hf == HFILE_ERROR)
  105. return HFILE_ERROR;
  106. // Write all of our current data to the temp file.
  107. _lwrite(hf, (LPCSTR) pmem, cbFile);
  108. // Free all of the current memory
  109. VirtualFree(pmem, cbAlloc, MEM_DECOMMIT);
  110. VirtualFree(pmem, 0, MEM_RELEASE);
  111. pmem = NULL;
  112. // Add the new data
  113. _llseek(hf, FilePtr, SEEK_SET);
  114. return (int) _lwrite(hf, (LPCSTR) qv, lcb);
  115. }
  116. // We're still a pseudo-file: commit more memory.
  117. ASSERT(cbNew <= LARGEST_ALLOC);
  118. if (!VirtualAlloc(pmem + cbAlloc, cbNew - cbAlloc,
  119. MEM_COMMIT, PAGE_READWRITE))
  120. OOM();
  121. cbAlloc = cbNew;
  122. }
  123. // We're still a pseudo-file; and we either already
  124. // reallocated or don't need to.
  125. ASSERT(pmem && FilePtr + lcb <= cbAlloc);
  126. // Copy the new data to the pseudo-file.
  127. memcpy(pmem + FilePtr, qv, lcb);
  128. FilePtr += lcb;
  129. if (FilePtr > cbFile)
  130. cbFile = FilePtr;
  131. return lcb;
  132. }
  133. int STDCALL CTmpFile::read(void* qv, int lcb)
  134. {
  135. if (pszFileName)
  136. return _lread(hf, qv, lcb);
  137. else {
  138. if (lcb > cbFile)
  139. lcb = cbFile;
  140. memcpy(qv, pmem + FilePtr, lcb);
  141. FilePtr += lcb;
  142. return lcb;
  143. }
  144. }
  145. /***************************************************************************
  146. FUNCTION: CTmpFile::copyfromfile
  147. PURPOSE: Copy lcb bytes from a file into our temporary file buffer
  148. PARAMETERS:
  149. hfSrc
  150. lcb
  151. RETURNS:
  152. COMMENTS:
  153. REVIEW: now that we can handle up to 8 megs, we should read
  154. from the file directly into our memory rather then going through
  155. a temporary buffer.
  156. MODIFICATION DATES:
  157. 06-Jan-1994 [ralphw]
  158. ***************************************************************************/
  159. RC_TYPE STDCALL CTmpFile::copyfromfile(HFILE hfSrc, DWORD lcb)
  160. {
  161. CMem buf(CB_COPY_BUFFER);
  162. int cbRead = CB_COPY_BUFFER;
  163. while (lcb > CB_COPY_BUFFER) {
  164. if ((cbRead = _lread(hfSrc, buf.pb, CB_COPY_BUFFER)) == HFILE_ERROR)
  165. break;
  166. if (write(buf.pb, cbRead) != cbRead) {
  167. cbRead = HFILE_ERROR;
  168. break;
  169. }
  170. lcb -= cbRead;
  171. }
  172. if (cbRead != HFILE_ERROR && lcb &&
  173. (cbRead = _lread(hfSrc, buf.pb, lcb)) != HFILE_ERROR) {
  174. if (write(buf.pb, cbRead) != cbRead)
  175. cbRead = HFILE_ERROR;
  176. }
  177. if (cbRead == HFILE_ERROR) {
  178. if (SetFSErrorRc(RcGetIOError()) == RC_Success)
  179. SetFSErrorRc(RC_Invalid);
  180. }
  181. else
  182. SetFSErrorRc(RC_Success);
  183. return rcFSError;
  184. }
  185. /***************************************************************************
  186. FUNCTION: CTmpFile::copytofile
  187. PURPOSE: Copy from our temporary buffer into a real file
  188. PARAMETERS:
  189. hfDst
  190. lcb
  191. RETURNS:
  192. COMMENTS:
  193. MODIFICATION DATES:
  194. 06-Jan-1994 [ralphw]
  195. ***************************************************************************/
  196. RC_TYPE STDCALL CTmpFile::copytofile(HFILE hfDst, DWORD lcb)
  197. {
  198. int cbRead = CB_COPY_BUFFER;;
  199. if (hf == HFILE_ERROR) {
  200. // Not a real file, so just copy our entire buffer
  201. ASSERT(FilePtr == 0);
  202. if (_lwrite(hfDst, (LPCSTR) pmem, cbFile) != (UINT) cbFile)
  203. cbRead = HFILE_ERROR;
  204. }
  205. else {
  206. CMem buf(CB_COPY_BUFFER);
  207. #ifdef _DEBUG
  208. if (lcb > CB_COPY_BUFFER)
  209. DBWIN("CB_COPY_BUFFER wasn't large enough in copytofile.");
  210. #endif
  211. while (lcb > CB_COPY_BUFFER) {
  212. if ((cbRead = read(buf.pb, CB_COPY_BUFFER)) == HFILE_ERROR)
  213. break;
  214. if (_lwrite(hfDst, (LPCSTR) buf.pb, cbRead) != (UINT) cbRead) {
  215. cbRead = HFILE_ERROR;
  216. break;
  217. }
  218. lcb -= cbRead;
  219. }
  220. if (cbRead != HFILE_ERROR && lcb &&
  221. (cbRead = read(buf.pb, lcb)) != HFILE_ERROR) {
  222. if (_lwrite(hfDst, (LPCSTR) buf.pb, cbRead) != (UINT) cbRead)
  223. cbRead = HFILE_ERROR;
  224. }
  225. }
  226. if (cbRead == HFILE_ERROR) {
  227. if (SetFSErrorRc(RcGetIOError()) == RC_Success)
  228. SetFSErrorRc(RC_Invalid);
  229. }
  230. else
  231. SetFSErrorRc(RC_Success);
  232. return rcFSError;
  233. }