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.

176 lines
4.7 KiB

  1. #include "stdinc.h"
  2. #include "win32file.h"
  3. #include "atlbase.h"
  4. #include "atlconv.h"
  5. #define IS_NT() ((GetVersion() & 0x80000000) == 0)
  6. using std::wstring;
  7. void Win32File::snarfFullFile(wstring& output)
  8. {
  9. output = L"";
  10. CByteVector bytes;
  11. DWORD dwReadSize = 0;
  12. bytes.resize(filesize() - filepointer());
  13. if (!ReadFile(_hFile, &bytes.front(), bytes.size(), &dwReadSize, NULL))
  14. {
  15. throw new ReadWriteError(false, ::GetLastError());
  16. }
  17. // Otherwise, bash the byte vector into a wstring for output
  18. output = ConvertToWstring(bytes, _type);
  19. }
  20. void Win32File::writeLine(const wstring& dump)
  21. {
  22. CByteVector vb;
  23. DWORD dwWritten;
  24. vb = ConvertWstringToDestination(dump, _type);
  25. if (!WriteFile(_hFile, &vb.front(), vb.size(), &dwWritten, NULL))
  26. throw new ReadWriteError(true, ::GetLastError());
  27. }
  28. bool Win32File::eof() { return false; }
  29. void
  30. Win32File::openForRead(wstring wstname)
  31. {
  32. USES_CONVERSION;
  33. if (_hFile != INVALID_HANDLE_VALUE)
  34. {
  35. throw new AlreadyOpened;
  36. }
  37. const PCWSTR pcwstr = wstname.c_str();
  38. const DWORD Flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
  39. _hFile =
  40. IS_NT() ? CreateFileW(pcwstr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, Flags, NULL)
  41. : CreateFileA(W2A(pcwstr), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, Flags, NULL);
  42. if (_hFile == INVALID_HANDLE_VALUE || _hFile == NULL)
  43. {
  44. throw new OpeningError(GetLastError());
  45. }
  46. // If this was for reading, then sniff the first few bytes and see what kind
  47. // of file it is.
  48. DWORD dwReadBytes = 0;
  49. BYTE bBuffer[256];
  50. if (!ReadFile(_hFile, bBuffer, sizeof(bBuffer), &dwReadBytes, NULL))
  51. {
  52. throw new ReadWriteError(true, GetLastError());
  53. }
  54. // Now let's determine what kind of buffer we've got
  55. _type = DetermineFileTypeFromBuffer(bBuffer, dwReadBytes);
  56. _bOpenForRead = true;
  57. // Let's zip the file pointer past the first gunk
  58. SetFilePointer(_hFile, DetermineFileTypeSigSize(_type), NULL, FILE_BEGIN);
  59. }
  60. void
  61. Win32File::openForWrite(wstring wstname, FileContentType fct, bool bOverwrite)
  62. {
  63. USES_CONVERSION;
  64. if (_hFile != INVALID_HANDLE_VALUE)
  65. {
  66. throw new AlreadyOpened;
  67. }
  68. const DWORD OpenOrCreate = bOverwrite ? CREATE_ALWAYS : CREATE_NEW;
  69. const DWORD Flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
  70. PCWSTR pcwstr = wstname.c_str();
  71. _hFile =
  72. IS_NT() ? CreateFileW(pcwstr, GENERIC_WRITE, FILE_SHARE_READ, NULL, OpenOrCreate, Flags, NULL)
  73. : CreateFileA(W2A(pcwstr), GENERIC_WRITE, FILE_SHARE_READ, NULL, OpenOrCreate, Flags, NULL);
  74. if (_hFile == INVALID_HANDLE_VALUE || _hFile == NULL)
  75. {
  76. throw new OpeningError(GetLastError());
  77. }
  78. // Now that we have an open file, let's blop the signature bytes into it.
  79. DWORD dwWritten;
  80. DWORD dwToWrite;
  81. PCVOID pvWriteBuffer;
  82. switch (fct) {
  83. case FileContentsUnicode:
  84. pvWriteBuffer = UNICODE_SIGNATURE;
  85. dwToWrite = sizeof(UNICODE_SIGNATURE);
  86. break;
  87. case FileContentsUnicodeBigEndian:
  88. pvWriteBuffer = UNICODE_BIG_ENDIAN_SIGNATURE;
  89. dwToWrite = sizeof(UNICODE_BIG_ENDIAN_SIGNATURE);
  90. break;
  91. case FileContentsUTF8:
  92. pvWriteBuffer = NULL;
  93. dwToWrite = 0;
  94. break;
  95. default:
  96. pvWriteBuffer = UNICODE_SIGNATURE;
  97. dwToWrite = 0;
  98. break;
  99. }
  100. if (!WriteFile(_hFile, pvWriteBuffer, dwToWrite, &dwWritten, NULL) || (dwWritten != dwToWrite)) {
  101. throw new ReadWriteError(false, GetLastError());
  102. }
  103. _bOpenForRead = false;
  104. _type = fct;
  105. }
  106. Win32File::Win32File()
  107. : _hFile(INVALID_HANDLE_VALUE), _type(FileContentsUTF8),
  108. _bOpenForRead(false), _bEof(false)
  109. {
  110. }
  111. Win32File::~Win32File() { if (_hFile != INVALID_HANDLE_VALUE) { CloseHandle(_hFile); } };
  112. FileContentType DetermineFileTypeFromBuffer(unsigned char *data, int length)
  113. {
  114. #define CHECKMARK(tp, ct) if ((length > sizeof(tp)) && (memcmp(data, tp, sizeof(tp)) == 0)) return ct;
  115. CHECKMARK(UNICODE_SIGNATURE, FileContentsUnicode);
  116. CHECKMARK(UNICODE_BIG_ENDIAN_SIGNATURE, FileContentsUnicodeBigEndian);
  117. CHECKMARK(UTF8_SIGNATURE, FileContentsUTF8);
  118. return FileContentsUTF8;
  119. }
  120. int DetermineFileTypeSigSize(FileContentType type)
  121. {
  122. switch (type)
  123. {
  124. case FileContentsUnicode: return sizeof(UNICODE_SIGNATURE);
  125. case FileContentsUnicodeBigEndian: return sizeof(UNICODE_BIG_ENDIAN_SIGNATURE);
  126. case FileContentsUTF8:
  127. default: return 0;
  128. }
  129. }