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.

372 lines
12 KiB

  1. #pragma once
  2. #include "bcl_common.h"
  3. #ifndef RTL_SXS_KERNEL_MODE
  4. #include "nturtl.h"
  5. #include "windows.h"
  6. #include "bcl_w32unicodeinlinestringbuffer.h"
  7. #ifndef NUMBER_OF
  8. #define NUMBER_OF(q) (sizeof(q) / sizeof(*q))
  9. #endif
  10. class CWin32Environment
  11. {
  12. public:
  13. typedef CWin32Environment CEnv;
  14. typedef DWORD StatusCode;
  15. typedef BCL::CMutablePointerAndCountPair<BYTE, SIZE_T> CByteRegion;
  16. typedef BCL::CConstantPointerAndCountPair<BYTE, SIZE_T> CConstantByteRegion;
  17. typedef BCL::CMutablePointerAndCountPair<WCHAR, SIZE_T> CUnicodeStringPair;
  18. typedef BCL::CConstantPointerAndCountPair<WCHAR, SIZE_T> CConstantUnicodeStringPair;
  19. typedef BCL::CWin32BaseUnicodeInlineStringBuffer<128> CStringBuffer;
  20. static const CConstantUnicodeStringPair s_FileSystemSeperator;
  21. enum {
  22. SuccessCode = ERROR_SUCCESS,
  23. InvalidParameter = ERROR_INVALID_PARAMETER,
  24. NotEnoughBuffer = ERROR_INSUFFICIENT_BUFFER,
  25. OutOfMemory = ERROR_NOT_ENOUGH_MEMORY,
  26. NotFound = ERROR_NOT_FOUND,
  27. NotImplemented = ERROR_INVALID_FUNCTION
  28. };
  29. //
  30. // Case-sensitive
  31. //
  32. static StatusCode CompareStrings(const CConstantUnicodeStringPair &Left, const CConstantUnicodeStringPair &Right, int &iResult)
  33. {
  34. iResult = 0;
  35. int iInternalResult = CompareStringW(
  36. GetThreadLocale(),
  37. 0,
  38. Left.GetPointer(),
  39. Left.GetCount(),
  40. Right.GetPointer(),
  41. Right.GetCount());
  42. switch (iInternalResult)
  43. {
  44. case CSTR_EQUAL:
  45. iResult = 0;
  46. break;
  47. case CSTR_GREATER_THAN:
  48. iResult = 1;
  49. break;
  50. case CSTR_LESS_THAN:
  51. iResult = -1;
  52. break;
  53. case 0:
  54. return ::GetLastError();
  55. }
  56. return SuccessCode;
  57. }
  58. static StatusCode CompareStringsCaseInsensitive(const CConstantUnicodeStringPair &Left, const CConstantUnicodeStringPair &Right, int &iResult)
  59. {
  60. iResult = 0;
  61. int iInternalResult = CompareStringW(
  62. GetThreadLocale(),
  63. NORM_IGNORECASE,
  64. Left.GetPointer(),
  65. Left.GetCount(),
  66. Right.GetPointer(),
  67. Right.GetCount());
  68. switch (iInternalResult)
  69. {
  70. case CSTR_EQUAL:
  71. iResult = 0;
  72. break;
  73. case CSTR_GREATER_THAN:
  74. iResult = 1;
  75. break;
  76. case CSTR_LESS_THAN:
  77. iResult = -1;
  78. break;
  79. case 0:
  80. return ::GetLastError();
  81. }
  82. return SuccessCode;
  83. }
  84. static StatusCode CreateDirectory(SIZE_T ItemCount, const CConstantUnicodeStringPair *Listing) {
  85. PWSTR pwszWorkingBuffer = NULL, pwszCursor;
  86. SIZE_T i = 0;
  87. SIZE_T cchRequired = 0;
  88. StatusCode Result;
  89. //
  90. // Figure out how large the buffer is that we need here
  91. //
  92. for (i = 0; i < ItemCount; i++)
  93. {
  94. if (i != 0)
  95. cchRequired += s_FileSystemSeperator.GetCount();
  96. cchRequired += Listing[i].GetCount();
  97. }
  98. Result = CEnv::AllocateHeap((cchRequired + 1) * sizeof(WCHAR), (PVOID*)&pwszWorkingBuffer, NULL);
  99. if (CEnv::DidFail(Result))
  100. return Result;
  101. pwszCursor = pwszWorkingBuffer;
  102. //
  103. // Now for each path segment, start copying it into the
  104. // working buffer and creating paths from it.
  105. //
  106. for (i = 0; i < ItemCount; i++)
  107. {
  108. const CConstantUnicodeStringPair &Me = Listing[i];
  109. if (i != 0)
  110. {
  111. memcpy(pwszCursor, s_FileSystemSeperator.GetPointer(), s_FileSystemSeperator.GetCount() * sizeof(WCHAR));
  112. pwszCursor += s_FileSystemSeperator.GetCount();
  113. }
  114. memcpy(pwszCursor, Me.GetPointer(), Me.GetCount() * sizeof(WCHAR));
  115. pwszCursor += Me.GetCount();
  116. *pwszCursor = UNICODE_NULL;
  117. if (!::CreateDirectoryW(pwszWorkingBuffer, NULL) && (::GetLastError() == ERROR_ALREADY_EXISTS))
  118. {
  119. Result = ::GetLastError();
  120. goto Exit;
  121. }
  122. }
  123. Result = CEnv::SuccessCode;
  124. Exit:
  125. if (pwszWorkingBuffer)
  126. CEnv::FreeHeap(pwszWorkingBuffer, NULL);
  127. return Result;
  128. }
  129. static CConstantUnicodeStringPair StringFrom(const UNICODE_STRING *pus) {
  130. return CConstantUnicodeStringPair(pus->Buffer, pus->Length);
  131. }
  132. static CConstantUnicodeStringPair StringFrom(PCWSTR pcwszInput) {
  133. return CConstantUnicodeStringPair(pcwszInput, ::wcslen(pcwszInput));
  134. }
  135. static CConstantUnicodeStringPair StringFrom(const CConstantUnicodeStringPair& src) {
  136. return src;
  137. }
  138. static StatusCode Compare(const CConstantUnicodeStringPair &Left, const CConstantUnicodeStringPair &Right, int &Result) {
  139. if (((Left.GetCount() / sizeof(WCHAR)) > USHRT_MAX) || ((Right.GetCount() / sizeof(WCHAR)) > USHRT_MAX))
  140. return InvalidParameter;
  141. // Evil casting is required b/c UNICODE_STRING requires it.
  142. const UNICODE_STRING TheLeft = { (USHORT)Left.GetCount(), 0, (PWSTR)Left.GetPointer() };
  143. const UNICODE_STRING TheRight = { (SHORT)Right.GetCount(), 0, (PWSTR)Right.GetPointer() };
  144. Result = RtlCompareUnicodeString(&TheLeft, &TheRight, FALSE);
  145. return SuccessCode;
  146. }
  147. static bool DidFail(StatusCode dwCode) { return (dwCode != SuccessCode); }
  148. static StatusCode VirtualAlloc(PVOID pvAddress, SIZE_T cbSize, DWORD flAllocationType, DWORD flProtect, PVOID *ppvRegion) {
  149. if (NULL == (*ppvRegion = ::VirtualAlloc(pvAddress, cbSize, flAllocationType, flProtect))) {
  150. return ::GetLastError();
  151. }
  152. else {
  153. return SuccessCode;
  154. }
  155. }
  156. static StatusCode VirtualFree(PVOID pvAddress, SIZE_T cbSize, DWORD dwFreeType) {
  157. if (!::VirtualFree(pvAddress, cbSize, dwFreeType)) {
  158. return ::GetLastError();
  159. }
  160. else {
  161. return SuccessCode;
  162. }
  163. }
  164. static NTSTATUS FASTCALL AllocateHeap(SIZE_T cb, CByteRegion &Recipient, PVOID pvContext) {
  165. PVOID pvAcquired = NULL;
  166. CEnv::StatusCode Result;
  167. Recipient.SetPointerAndCount(NULL, 0);
  168. if (CEnv::DidFail(Result = CEnv::AllocateHeap(cb, &pvAcquired, pvContext)))
  169. return Result;
  170. Recipient.SetPointerAndCount((CByteRegion::TMutableArray)pvAcquired, cb);
  171. return Result;
  172. }
  173. static NTSTATUS FASTCALL AllocateHeap(SIZE_T cb, PVOID *ppvTarget, PVOID pvContext) {
  174. if (NULL == (*ppvTarget = RtlAllocateHeap(RtlProcessHeap(), 0, cb))) {
  175. return STATUS_INVALID_PARAMETER;
  176. }
  177. else {
  178. return SuccessCode;
  179. }
  180. }
  181. static NTSTATUS FASTCALL FreeHeap(PVOID ppvTarget, PVOID pvContext) {
  182. if (!RtlFreeHeap(RtlProcessHeap(), 0, ppvTarget)) {
  183. return STATUS_INVALID_PARAMETER;
  184. }
  185. else {
  186. return SuccessCode;
  187. }
  188. }
  189. static StatusCode CloseHandle(HANDLE h) {
  190. if (!::CloseHandle(h)) {
  191. return ::GetLastError();
  192. }
  193. else {
  194. return SuccessCode;
  195. }
  196. }
  197. static StatusCode GetFileHandle(HANDLE* pHandle, const CConstantUnicodeStringPair &FileName, DWORD dwRights, DWORD dwSharing, DWORD dwCreation) {
  198. PCWSTR pcwszTemp = NULL;
  199. PCWSTR pcwszInput = NULL;
  200. StatusCode dwRetVal = SuccessCode;
  201. *pHandle = INVALID_HANDLE_VALUE;
  202. pcwszInput = FileName.GetPointer();
  203. if (!pcwszInput || (FileName.GetCount() == 0) ||
  204. (pcwszInput[FileName.GetCount() - 1] != UNICODE_NULL))
  205. {
  206. PWSTR pwszAllocTemp = NULL;
  207. dwRetVal = AllocateHeap((FileName.GetCount() + 1) * sizeof(WCHAR), (PVOID*)&pwszAllocTemp, NULL);
  208. if (dwRetVal != SuccessCode) {
  209. return dwRetVal;
  210. }
  211. RtlCopyMemory(pwszAllocTemp, pcwszInput, FileName.GetCount() * sizeof(WCHAR));
  212. pwszAllocTemp[FileName.GetCount()] = UNICODE_NULL;
  213. pcwszTemp = pwszAllocTemp;
  214. }
  215. else {
  216. pcwszTemp = pcwszInput;
  217. }
  218. *pHandle = CreateFileW(pcwszTemp, dwRights, dwSharing, NULL, dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
  219. if (*pHandle == INVALID_HANDLE_VALUE) {
  220. dwRetVal = ::GetLastError();
  221. }
  222. else {
  223. dwRetVal = SuccessCode;
  224. }
  225. if (pcwszTemp != pcwszInput) {
  226. FreeHeap((PVOID)pcwszTemp, NULL);
  227. }
  228. return dwRetVal;
  229. }
  230. static StatusCode ReadFile(HANDLE hFile, CEnv::CByteRegion &Target, SIZE_T &cbDidRead) {
  231. return CEnv::ReadFile(hFile, Target.GetPointer(), Target.GetCount(), cbDidRead);
  232. }
  233. static StatusCode ReadFile(HANDLE hFile, PVOID pvTarget, SIZE_T cbToRead, SIZE_T &cbDidRead) {
  234. DWORD dwToRead, dwDidRead;
  235. cbDidRead = 0;
  236. if (cbToRead > 0xFFFFFFFF) {
  237. return InvalidParameter;
  238. }
  239. dwToRead = (DWORD)cbToRead;
  240. if (!::ReadFile(hFile, pvTarget, dwToRead, &dwDidRead, NULL)) {
  241. return ::GetLastError();
  242. }
  243. cbDidRead = dwDidRead;
  244. return SuccessCode;
  245. }
  246. static StatusCode WriteFile(HANDLE hFile, const CEnv::CConstantByteRegion &Source, SIZE_T &cbDidWrite) {
  247. return CEnv::WriteFile(hFile, (PVOID)Source.GetPointer(), Source.GetCount(), cbDidWrite);
  248. }
  249. static StatusCode WriteFile(HANDLE hFile, const PVOID pvSource, SIZE_T cbToWrite, SIZE_T &cbDidWrite) {
  250. DWORD dwToWrite, dwDidWrite;
  251. cbDidWrite = 0;
  252. if (cbDidWrite > 0xFFFFFFFF) {
  253. return InvalidParameter;
  254. }
  255. dwToWrite = (DWORD)cbToWrite;
  256. if (!::WriteFile(hFile, pvSource, dwToWrite, &dwDidWrite, NULL)) {
  257. return GetLastError();
  258. }
  259. cbDidWrite = dwDidWrite;
  260. return SuccessCode;
  261. }
  262. static StatusCode GetFileSize(HANDLE hFile, PLARGE_INTEGER pcbFileSize) {
  263. if (GetFileSizeEx(hFile, pcbFileSize)) {
  264. return SuccessCode;
  265. }
  266. else {
  267. return ::GetLastError();
  268. }
  269. }
  270. };
  271. __declspec(selectany) const CWin32Environment::CConstantUnicodeStringPair CWin32Environment::s_FileSystemSeperator(L"\\", 1);
  272. #endif
  273. class CNtEnvironment {
  274. public:
  275. typedef NTSTATUS StatusCode;
  276. enum {
  277. SuccessCode = STATUS_SUCCESS,
  278. InvalidParameter = STATUS_INVALID_PARAMETER,
  279. NotEnoughBuffer = STATUS_BUFFER_TOO_SMALL,
  280. };
  281. template <typename T> static T ConvertStatusToOther(StatusCode src);
  282. template <> static CWin32Environment::StatusCode ConvertStatusToOther(StatusCode src) {
  283. return RtlNtStatusToDosError(src);
  284. }
  285. template <> static CNtEnvironment::StatusCode ConvertStatusToOther(StatusCode src) {
  286. return src;
  287. }
  288. static bool DidFail(StatusCode status) { return (status < 0); }
  289. };
  290. #ifndef RTLSXS_USE_KERNEL_MODE
  291. typedef CWin32Environment CEnv;
  292. typedef CNtEnvironment COtherEnv;
  293. #else
  294. typedef CNtEnvironment CEnv;
  295. typedef CWin32Environment COtherEnv;
  296. #endif