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

#pragma once
#include "bcl_common.h"
#ifndef RTL_SXS_KERNEL_MODE
#include "nturtl.h"
#include "windows.h"
#include "bcl_w32unicodeinlinestringbuffer.h"
#ifndef NUMBER_OF
#define NUMBER_OF(q) (sizeof(q) / sizeof(*q))
#endif
class CWin32Environment
{
public:
typedef CWin32Environment CEnv;
typedef DWORD StatusCode;
typedef BCL::CMutablePointerAndCountPair<BYTE, SIZE_T> CByteRegion;
typedef BCL::CConstantPointerAndCountPair<BYTE, SIZE_T> CConstantByteRegion;
typedef BCL::CMutablePointerAndCountPair<WCHAR, SIZE_T> CUnicodeStringPair;
typedef BCL::CConstantPointerAndCountPair<WCHAR, SIZE_T> CConstantUnicodeStringPair;
typedef BCL::CWin32BaseUnicodeInlineStringBuffer<128> CStringBuffer;
static const CConstantUnicodeStringPair s_FileSystemSeperator;
enum {
SuccessCode = ERROR_SUCCESS,
InvalidParameter = ERROR_INVALID_PARAMETER,
NotEnoughBuffer = ERROR_INSUFFICIENT_BUFFER,
OutOfMemory = ERROR_NOT_ENOUGH_MEMORY,
NotFound = ERROR_NOT_FOUND,
NotImplemented = ERROR_INVALID_FUNCTION
};
//
// Case-sensitive
//
static StatusCode CompareStrings(const CConstantUnicodeStringPair &Left, const CConstantUnicodeStringPair &Right, int &iResult)
{
iResult = 0;
int iInternalResult = CompareStringW(
GetThreadLocale(),
0,
Left.GetPointer(),
Left.GetCount(),
Right.GetPointer(),
Right.GetCount());
switch (iInternalResult)
{
case CSTR_EQUAL:
iResult = 0;
break;
case CSTR_GREATER_THAN:
iResult = 1;
break;
case CSTR_LESS_THAN:
iResult = -1;
break;
case 0:
return ::GetLastError();
}
return SuccessCode;
}
static StatusCode CompareStringsCaseInsensitive(const CConstantUnicodeStringPair &Left, const CConstantUnicodeStringPair &Right, int &iResult)
{
iResult = 0;
int iInternalResult = CompareStringW(
GetThreadLocale(),
NORM_IGNORECASE,
Left.GetPointer(),
Left.GetCount(),
Right.GetPointer(),
Right.GetCount());
switch (iInternalResult)
{
case CSTR_EQUAL:
iResult = 0;
break;
case CSTR_GREATER_THAN:
iResult = 1;
break;
case CSTR_LESS_THAN:
iResult = -1;
break;
case 0:
return ::GetLastError();
}
return SuccessCode;
}
static StatusCode CreateDirectory(SIZE_T ItemCount, const CConstantUnicodeStringPair *Listing) {
PWSTR pwszWorkingBuffer = NULL, pwszCursor;
SIZE_T i = 0;
SIZE_T cchRequired = 0;
StatusCode Result;
//
// Figure out how large the buffer is that we need here
//
for (i = 0; i < ItemCount; i++)
{
if (i != 0)
cchRequired += s_FileSystemSeperator.GetCount();
cchRequired += Listing[i].GetCount();
}
Result = CEnv::AllocateHeap((cchRequired + 1) * sizeof(WCHAR), (PVOID*)&pwszWorkingBuffer, NULL);
if (CEnv::DidFail(Result))
return Result;
pwszCursor = pwszWorkingBuffer;
//
// Now for each path segment, start copying it into the
// working buffer and creating paths from it.
//
for (i = 0; i < ItemCount; i++)
{
const CConstantUnicodeStringPair &Me = Listing[i];
if (i != 0)
{
memcpy(pwszCursor, s_FileSystemSeperator.GetPointer(), s_FileSystemSeperator.GetCount() * sizeof(WCHAR));
pwszCursor += s_FileSystemSeperator.GetCount();
}
memcpy(pwszCursor, Me.GetPointer(), Me.GetCount() * sizeof(WCHAR));
pwszCursor += Me.GetCount();
*pwszCursor = UNICODE_NULL;
if (!::CreateDirectoryW(pwszWorkingBuffer, NULL) && (::GetLastError() == ERROR_ALREADY_EXISTS))
{
Result = ::GetLastError();
goto Exit;
}
}
Result = CEnv::SuccessCode;
Exit:
if (pwszWorkingBuffer)
CEnv::FreeHeap(pwszWorkingBuffer, NULL);
return Result;
}
static CConstantUnicodeStringPair StringFrom(const UNICODE_STRING *pus) {
return CConstantUnicodeStringPair(pus->Buffer, pus->Length);
}
static CConstantUnicodeStringPair StringFrom(PCWSTR pcwszInput) {
return CConstantUnicodeStringPair(pcwszInput, ::wcslen(pcwszInput));
}
static CConstantUnicodeStringPair StringFrom(const CConstantUnicodeStringPair& src) {
return src;
}
static StatusCode Compare(const CConstantUnicodeStringPair &Left, const CConstantUnicodeStringPair &Right, int &Result) {
if (((Left.GetCount() / sizeof(WCHAR)) > USHRT_MAX) || ((Right.GetCount() / sizeof(WCHAR)) > USHRT_MAX))
return InvalidParameter;
// Evil casting is required b/c UNICODE_STRING requires it.
const UNICODE_STRING TheLeft = { (USHORT)Left.GetCount(), 0, (PWSTR)Left.GetPointer() };
const UNICODE_STRING TheRight = { (SHORT)Right.GetCount(), 0, (PWSTR)Right.GetPointer() };
Result = RtlCompareUnicodeString(&TheLeft, &TheRight, FALSE);
return SuccessCode;
}
static bool DidFail(StatusCode dwCode) { return (dwCode != SuccessCode); }
static StatusCode VirtualAlloc(PVOID pvAddress, SIZE_T cbSize, DWORD flAllocationType, DWORD flProtect, PVOID *ppvRegion) {
if (NULL == (*ppvRegion = ::VirtualAlloc(pvAddress, cbSize, flAllocationType, flProtect))) {
return ::GetLastError();
}
else {
return SuccessCode;
}
}
static StatusCode VirtualFree(PVOID pvAddress, SIZE_T cbSize, DWORD dwFreeType) {
if (!::VirtualFree(pvAddress, cbSize, dwFreeType)) {
return ::GetLastError();
}
else {
return SuccessCode;
}
}
static NTSTATUS FASTCALL AllocateHeap(SIZE_T cb, CByteRegion &Recipient, PVOID pvContext) {
PVOID pvAcquired = NULL;
CEnv::StatusCode Result;
Recipient.SetPointerAndCount(NULL, 0);
if (CEnv::DidFail(Result = CEnv::AllocateHeap(cb, &pvAcquired, pvContext)))
return Result;
Recipient.SetPointerAndCount((CByteRegion::TMutableArray)pvAcquired, cb);
return Result;
}
static NTSTATUS FASTCALL AllocateHeap(SIZE_T cb, PVOID *ppvTarget, PVOID pvContext) {
if (NULL == (*ppvTarget = RtlAllocateHeap(RtlProcessHeap(), 0, cb))) {
return STATUS_INVALID_PARAMETER;
}
else {
return SuccessCode;
}
}
static NTSTATUS FASTCALL FreeHeap(PVOID ppvTarget, PVOID pvContext) {
if (!RtlFreeHeap(RtlProcessHeap(), 0, ppvTarget)) {
return STATUS_INVALID_PARAMETER;
}
else {
return SuccessCode;
}
}
static StatusCode CloseHandle(HANDLE h) {
if (!::CloseHandle(h)) {
return ::GetLastError();
}
else {
return SuccessCode;
}
}
static StatusCode GetFileHandle(HANDLE* pHandle, const CConstantUnicodeStringPair &FileName, DWORD dwRights, DWORD dwSharing, DWORD dwCreation) {
PCWSTR pcwszTemp = NULL;
PCWSTR pcwszInput = NULL;
StatusCode dwRetVal = SuccessCode;
*pHandle = INVALID_HANDLE_VALUE;
pcwszInput = FileName.GetPointer();
if (!pcwszInput || (FileName.GetCount() == 0) ||
(pcwszInput[FileName.GetCount() - 1] != UNICODE_NULL))
{
PWSTR pwszAllocTemp = NULL;
dwRetVal = AllocateHeap((FileName.GetCount() + 1) * sizeof(WCHAR), (PVOID*)&pwszAllocTemp, NULL);
if (dwRetVal != SuccessCode) {
return dwRetVal;
}
RtlCopyMemory(pwszAllocTemp, pcwszInput, FileName.GetCount() * sizeof(WCHAR));
pwszAllocTemp[FileName.GetCount()] = UNICODE_NULL;
pcwszTemp = pwszAllocTemp;
}
else {
pcwszTemp = pcwszInput;
}
*pHandle = CreateFileW(pcwszTemp, dwRights, dwSharing, NULL, dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
if (*pHandle == INVALID_HANDLE_VALUE) {
dwRetVal = ::GetLastError();
}
else {
dwRetVal = SuccessCode;
}
if (pcwszTemp != pcwszInput) {
FreeHeap((PVOID)pcwszTemp, NULL);
}
return dwRetVal;
}
static StatusCode ReadFile(HANDLE hFile, CEnv::CByteRegion &Target, SIZE_T &cbDidRead) {
return CEnv::ReadFile(hFile, Target.GetPointer(), Target.GetCount(), cbDidRead);
}
static StatusCode ReadFile(HANDLE hFile, PVOID pvTarget, SIZE_T cbToRead, SIZE_T &cbDidRead) {
DWORD dwToRead, dwDidRead;
cbDidRead = 0;
if (cbToRead > 0xFFFFFFFF) {
return InvalidParameter;
}
dwToRead = (DWORD)cbToRead;
if (!::ReadFile(hFile, pvTarget, dwToRead, &dwDidRead, NULL)) {
return ::GetLastError();
}
cbDidRead = dwDidRead;
return SuccessCode;
}
static StatusCode WriteFile(HANDLE hFile, const CEnv::CConstantByteRegion &Source, SIZE_T &cbDidWrite) {
return CEnv::WriteFile(hFile, (PVOID)Source.GetPointer(), Source.GetCount(), cbDidWrite);
}
static StatusCode WriteFile(HANDLE hFile, const PVOID pvSource, SIZE_T cbToWrite, SIZE_T &cbDidWrite) {
DWORD dwToWrite, dwDidWrite;
cbDidWrite = 0;
if (cbDidWrite > 0xFFFFFFFF) {
return InvalidParameter;
}
dwToWrite = (DWORD)cbToWrite;
if (!::WriteFile(hFile, pvSource, dwToWrite, &dwDidWrite, NULL)) {
return GetLastError();
}
cbDidWrite = dwDidWrite;
return SuccessCode;
}
static StatusCode GetFileSize(HANDLE hFile, PLARGE_INTEGER pcbFileSize) {
if (GetFileSizeEx(hFile, pcbFileSize)) {
return SuccessCode;
}
else {
return ::GetLastError();
}
}
};
__declspec(selectany) const CWin32Environment::CConstantUnicodeStringPair CWin32Environment::s_FileSystemSeperator(L"\\", 1);
#endif
class CNtEnvironment {
public:
typedef NTSTATUS StatusCode;
enum {
SuccessCode = STATUS_SUCCESS,
InvalidParameter = STATUS_INVALID_PARAMETER,
NotEnoughBuffer = STATUS_BUFFER_TOO_SMALL,
};
template <typename T> static T ConvertStatusToOther(StatusCode src);
template <> static CWin32Environment::StatusCode ConvertStatusToOther(StatusCode src) {
return RtlNtStatusToDosError(src);
}
template <> static CNtEnvironment::StatusCode ConvertStatusToOther(StatusCode src) {
return src;
}
static bool DidFail(StatusCode status) { return (status < 0); }
};
#ifndef RTLSXS_USE_KERNEL_MODE
typedef CWin32Environment CEnv;
typedef CNtEnvironment COtherEnv;
#else
typedef CNtEnvironment CEnv;
typedef CWin32Environment COtherEnv;
#endif