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.
 
 
 
 
 
 

1507 lines
39 KiB

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
common.h
Abstract:
This file contains structures and functions used in Ntdll.dll and advapi32.dll
--*/
#define STRSAFE_NO_DEPRECATE
#include <strsafe.h>
#define EtwpNtStatusToDosError(Status) ((ULONG)((Status == STATUS_SUCCESS)?ERROR_SUCCESS:RtlNtStatusToDosError(Status)))
#define DEFAULT_ALLOC_SIZE 4096
#define MAXSTR 1024
#if !defined (_NTDLLBUILD_)
extern void EtwpCallHWConfig(ULONG Reason);
#endif
HANDLE EtwpWin32Event;
__inline
ULONG
EtwpSetDosError(
IN ULONG DosError
)
{
#if defined (_NTDLLBUILD_)
EtwpSetLastError(DosError);
#else
SetLastError(DosError);
#endif
return DosError;
}
#if defined (_NTDLLBUILD_)
extern
RTL_CRITICAL_SECTION UMLogCritSect;
BOOLEAN EtwLocksInitialized = FALSE;
#endif
HINSTANCE DllInstanceHandle;
extern HANDLE EtwpKMHandle;
#if DBG
#define MOFLISTSIZEGUESS 1
BOOLEAN EtwpLoggingEnabled = FALSE;
#else
#define MOFLISTSIZEGUESS 10
#endif
#ifndef MEMPHIS
RTL_CRITICAL_SECTION PMCritSect;
HANDLE EtwpCBInProgressEvent = NULL;
PVOID EtwpProcessHeap = NULL;
HANDLE EtwpDeviceHandle;
#else
HANDLE PMMutex;
#endif
NTSTATUS EtwpInitializeDll(
void
)
/*+++
Routine Description:
Arguments:
Return Value:
---*/
{
#ifdef MEMPHIS
NTSTATUS Status;
OBJECT_ATTRIBUTES Obja;
Status = NtCreateMutant(&PMMutex,
MUTANT_ALL_ACCESS,
BaseFormatObjectAttributes(&Obja, NULL, NULL)
FALSE);
if (! NT_SUCCESS(Status))
{
return(Status);
}
#else
NTSTATUS Status;
Status = RtlInitializeCriticalSection(&PMCritSect);
if (! NT_SUCCESS(Status))
{
return(Status);
}
Status = NtCreateEvent(&EtwpCBInProgressEvent,
EVENT_ALL_ACCESS,
NULL,
NotificationEvent,
TRUE);
if (! NT_SUCCESS(Status))
{
RtlDeleteCriticalSection(&PMCritSect); // Delete PMCritSec.
return (Status);
}
#if defined (_NTDLLBUILD_)
Status = RtlInitializeCriticalSection(&UMLogCritSect);
if (! NT_SUCCESS(Status))
{
RtlDeleteCriticalSection(&PMCritSect); // Delete PMCritSec.
NtClose(EtwpCBInProgressEvent);
EtwpCBInProgressEvent = NULL;
return(Status);
}
EtwLocksInitialized = TRUE;
#endif
#endif
return(STATUS_SUCCESS);
}
void EtwpDeinitializeDll(
void
)
/*+++
Routine Description:
Arguments:
Return Value:
---*/
{
#ifdef MEMPHIS
CloseHandle(PMMutex);
#else
#if defined (_NTDLLBUILD_)
if(EtwLocksInitialized){
EtwLocksInitialized = FALSE;
#endif
RtlDeleteCriticalSection(&PMCritSect);
NtClose(EtwpCBInProgressEvent);
EtwpCBInProgressEvent = NULL;
#if defined (_NTDLLBUILD_)
RtlDeleteCriticalSection(&UMLogCritSect);
}
#endif
if ((EtwpProcessHeap != NULL) &&
(EtwpProcessHeap != RtlProcessHeap()))
{
RtlDestroyHeap(EtwpProcessHeap);
EtwpProcessHeap = NULL;
}
if (EtwpDeviceHandle != NULL)
{
#if defined (_NTDLLBUILD_)
EtwpCloseHandle(EtwpDeviceHandle);
#else
CloseHandle(EtwpDeviceHandle);
#endif
EtwpDeviceHandle = NULL;
}
#endif
if (EtwpWin32Event != NULL)
{
#if defined (_NTDLLBUILD_)
EtwpCloseHandle(EtwpWin32Event);
#else
CloseHandle(EtwpWin32Event);
#endif
EtwpWin32Event = NULL;
}
}
NTSTATUS
EtwpRegOpenKey(
IN PCWSTR lpKeyName,
OUT PHANDLE KeyHandle
)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
RtlInitUnicodeString( &KeyName, lpKeyName );
RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
return NtOpenKey( KeyHandle, KEY_READ, &ObjectAttributes );
}
NTSTATUS
EtwpRegQueryValueKey(
IN HANDLE KeyHandle,
IN LPWSTR lpValueName,
IN ULONG Length,
OUT PVOID KeyValue,
OUT PULONG ResultLength
)
{
UNICODE_STRING ValueName;
ULONG BufferLength;
NTSTATUS Status;
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
RtlInitUnicodeString( &ValueName, lpValueName );
BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + Length;
KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
RtlAllocateHeap (RtlProcessHeap(),0,BufferLength);
if (KeyValueInformation == NULL) {
return STATUS_NO_MEMORY;
}
Status = NtQueryValueKey(
KeyHandle,
&ValueName,
KeyValuePartialInformation,
KeyValueInformation,
BufferLength,
ResultLength
);
if (NT_SUCCESS(Status)) {
RtlCopyMemory(KeyValue,
KeyValueInformation->Data,
KeyValueInformation->DataLength
);
*ResultLength = KeyValueInformation->DataLength;
if (KeyValueInformation->Type == REG_SZ) {
if (KeyValueInformation->DataLength + sizeof(WCHAR) > Length) {
KeyValueInformation->DataLength -= sizeof(WCHAR);
}
((PUCHAR)KeyValue)[KeyValueInformation->DataLength++] = 0;
((PUCHAR)KeyValue)[KeyValueInformation->DataLength] = 0;
*ResultLength = KeyValueInformation->DataLength + sizeof(WCHAR);
}
}
RtlFreeHeap(RtlProcessHeap(),0,KeyValueInformation);
return Status;
}
#if DBG
NTSTATUS EtwpGetRegistryValue(
TCHAR *ValueName,
PULONG Value
)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG DataLength;
HANDLE Handle = INVALID_HANDLE_VALUE;
Status = EtwpRegOpenKey(WmiRegKeyText, &Handle);
if (NT_SUCCESS(Status)) {
Status = EtwpRegQueryValueKey(Handle,
ValueName,
sizeof(DWORD),
(PVOID)Value,
&DataLength
);
NtClose(Handle);
}
return Status;
}
#endif
BOOLEAN
WmiDllInitialize(
IN PVOID DllBase,
IN ULONG Reason,
IN PCONTEXT Context OPTIONAL
)
/*++
Routine Description:
This function implements Win32 base dll initialization.
Arguments:
DllHandle -
Reason - attach\detach
Context - Not Used
Return Value:
STATUS_SUCCESS
--*/
{
//
// NOTE : Do not use WMI heap in this function
// or in any of the routines called subsequently
// as WMI Heap is not initialized until any ETW API
// is called.
//
NTSTATUS Status = STATUS_SUCCESS;
ULONG Foo;
DllInstanceHandle = (HINSTANCE)DllBase;
if (Reason == DLL_PROCESS_ATTACH)
{
#if DBG
Foo = EtwpLoggingEnabled ? 1 : 0;
EtwpGetRegistryValue(LoggingEnableValueText,
&Foo);
EtwpLoggingEnabled = (Foo == 0) ? FALSE : TRUE;
#endif
Status = EtwpInitializeDll();
} else if (Reason == DLL_PROCESS_DETACH) {
//
// Don't need to clean up if process is exiting
//
if (Context == NULL)
{
EtwpDeinitializeDll();
}
if (EtwpKMHandle != (HANDLE)NULL)
{
#if defined (_NTDLLBUILD_)
EtwpCloseHandle(EtwpKMHandle);
#else
CloseHandle(EtwpKMHandle);
#endif
}
}
#if !defined (_NTDLLBUILD_)
EtwpCallHWConfig(Reason);
#endif
return(NT_SUCCESS(Status));
}
#ifndef MEMPHIS
VOID
EtwpCreateHeap(
void
)
{
EtwpEnterPMCritSection();
if (EtwpProcessHeap == NULL)
{
EtwpProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
NULL,
DLLRESERVEDHEAPSIZE,
DLLCOMMITHEAPSIZE,
NULL,
NULL);
if (EtwpProcessHeap == NULL)
{
EtwpDebugPrint(("WMI: Cannot create EtwpProcessHeap, using process default\n"));
EtwpProcessHeap = RtlProcessHeap();
}
}
EtwpLeavePMCritSection();
//
// This has been copied to this function as in ntdll
// we cannot execute WmiInitializeDll codepath. And
// EtwpLoggingEnabled has to be checked only once.
// So this place should be okay to initialze
// EtwpLoggingEnabled
//
#if DBG && defined(_NTDLLBUILD_)
{
ULONG Foo;
Foo = EtwpLoggingEnabled ? 1 : 0;
EtwpGetRegistryValue(&LoggingEnableValueText, &Foo);
EtwpLoggingEnabled = (Foo == 0) ? FALSE : TRUE;
}
#endif
}
#endif
ULONG
EtwpGetMofResourceList(
PWMIMOFLIST *MofListPtr
)
{
ULONG MofListSize;
PWMIMOFLIST MofList;
ULONG RetSize=0;
ULONG Status;
//
// Make an intelligent guess as to the size needed to get all of
// the MOF resources
//
*MofListPtr = NULL;
MofListSize = MOFLISTSIZEGUESS * (sizeof(WMIMOFLIST) +
(MAX_PATH +
MAX_PATH) * sizeof(WCHAR));
MofList = EtwpAlloc(MofListSize);
if (MofList != NULL)
{
Status = EtwpSendWmiKMRequest(NULL,
IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
NULL,
0,
MofList,
MofListSize,
&RetSize,
NULL);
if ((Status == ERROR_SUCCESS) && (RetSize == sizeof(ULONG)))
{
//
// The buffer was too small, but we now know how much we'll
// need.
//
MofListSize = MofList->MofListCount;
EtwpFree(MofList);
MofList = EtwpAlloc(MofListSize);
if (MofList != NULL)
{
//
// Now lets retry the query
//
Status = EtwpSendWmiKMRequest(NULL,
IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
NULL,
0,
MofList,
MofListSize,
&RetSize,
NULL);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
}
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
if (Status == ERROR_SUCCESS)
{
if (RetSize >= sizeof(WMIMOFLIST))
{
*MofListPtr = MofList;
} else {
Status = ERROR_INVALID_PARAMETER;
EtwpFree(MofList);
}
} else if (MofList != NULL) {
EtwpFree(MofList);
}
return(Status);
}
PWCHAR EtwpRegistryToImagePath(
PWCHAR ImagePath,
PWCHAR RegistryPath
)
/*++
Routine Description:
This routine will determine the location of the device driver's image file
from its registry path
Arguments:
RegistryPath is a pointer to the driver's registry path
ImagePath is buffer of length MAX_PATH and returns the image path
Return Value:
pointer to Image path of driver or NULL if image path is unavailable
--*/
{
#define SystemRoot TEXT("\\SystemRoot\\")
#ifdef MEMPHIS
#define SystemRootDirectory TEXT("%WinDir%\\")
#else
#define SystemRootDirectory TEXT("%SystemRoot%\\")
#endif
#define SystemRootCharSize (( sizeof(SystemRoot) / sizeof(WCHAR) ) - 1)
#define DriversDirectory TEXT("\\System32\\Drivers\\")
#define NdisDriversDirectory TEXT("\\System\\")
#define QuestionPrefix TEXT("\\??\\")
#define QuestionPrefixSize (( sizeof(QuestionPrefix) / sizeof(WCHAR) ) - 1)
#define RegistryPrefix TEXT("\\Registry")
HKEY RegKey;
PWCHAR ImagePathPtr = NULL;
ULONG ValueType;
ULONG Size;
PWCHAR DriverName;
ULONG Len;
BOOLEAN DefaultImageName;
PWCHAR DriversDirectoryPath;
WCHAR *Buffer;
WCHAR *FullRegistryPath;
WCHAR RegBuffer[DEFAULT_ALLOC_SIZE];
Buffer = (PTCHAR)EtwpAlloc(2 * MAX_PATH * sizeof(WCHAR));
if (Buffer != NULL)
{
FullRegistryPath = Buffer + MAX_PATH;
//
// Get the driver file name or the MOF image path from the KM
// registry path. Here are the rules:
//
// 1. First check the MofImagePath value in the registry in case the
// mof resource is in a different file from the driver.
// 2. Next check the ImagePath value since the mof resource is assumed
// to be part of the driver image.
// 3. If no MofImagePath or ImagePath values then assume the mof resource
// is in the driver file and compose the driver file name as
// %SystemRoot%\System32\driver.sys.
// 4. If MofImagePath or ImagePath was specified then
// - Check first char for % or second character for :, or prefix
// of \??\ and if so use EtwpExpandEnvironmentStringsW
// - Check first part of path for \SystemRoot\, if so rebuild string
// as %SystemRoot%\ and use ExpandEnvironementStrings
// - Assume format D below and prepend %SystemRoot%\ and use
// EtwpExpandEnvironmentStringsW
// If MofImagePath or ImagePath value is present and it is a REG_EXPAND_SZ
// then it is used to locate the file that holds the mof resource. It
// can be in one of the following formats:
// Format A - %SystemRoot%\System32\Foo.Dll
// Format B -C:\WINNT\SYSTEM32\Drivers\Foo.SYS
// Format C - \SystemRoot\System32\Drivers\Foo.SYS
// Format D - System32\Drivers\Foo.Sys
// Format E - \??\c:\foo.sys
Len = wcslen(RegistryPath);
if (Len > 0)
{
DriverName = RegistryPath + Len;
while ((*(--DriverName) != '\\') && (--Len > 0)) ;
}
if (Len == 0)
{
EtwpDebugPrint(("WMI: Badly formed registry path %ws\n", RegistryPath));
EtwpFree(Buffer);
return(NULL);
}
DriverName++;
StringCchCopyW(FullRegistryPath,
MAX_PATH,
TEXT("System\\CurrentControlSet\\Services\\"));
StringCchCatW(FullRegistryPath,
MAX_PATH,
DriverName);
DefaultImageName = TRUE;
#if defined(_NTDLLBUILD_)
StringCbPrintfW(RegBuffer,
DEFAULT_ALLOC_SIZE,
L"%ws\\%ws",
L"\\REGISTRY\\MACHINE",
FullRegistryPath);
if (EtwpRegOpenKey(RegBuffer, &RegKey) == ERROR_SUCCESS)
{
ULONG cbSize;
PKEY_VALUE_PARTIAL_INFORMATION Buf;
Size = MAX_PATH * sizeof(WCHAR);
cbSize = Size + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
Buf = EtwpAlloc(cbSize);
if( Buf ) {
UNICODE_STRING UnicodeString;
RtlInitUnicodeString(&UnicodeString, L"MofImagePath");
if( NtQueryValueKey(RegKey,
&UnicodeString,
KeyValuePartialInformation,
Buf,
Size,
&Size) == ERROR_SUCCESS)
{
RtlCopyMemory(ImagePath, &Buf->Data[0], Buf->DataLength);
ValueType = Buf->Type;
DefaultImageName = FALSE;
} else {
RtlInitUnicodeString(&UnicodeString, L"ImagePath");
if( NtQueryValueKey(RegKey,
&UnicodeString,
KeyValuePartialInformation,
Buf,
Size,
&Size) == ERROR_SUCCESS)
{
RtlCopyMemory(ImagePath, &Buf->Data[0], Buf->DataLength);
ValueType = Buf->Type;
DefaultImageName = FALSE;
}
}
}
EtwpFree(Buf);
}
#else
if (RegOpenKey(HKEY_LOCAL_MACHINE,
FullRegistryPath,
&RegKey) == ERROR_SUCCESS)
{
Size = MAX_PATH * sizeof(WCHAR);
if (RegQueryValueEx(RegKey,
TEXT("MofImagePath"),
NULL,
&ValueType,
(PBYTE)ImagePath,
&Size) == ERROR_SUCCESS)
{
DefaultImageName = FALSE;
} else {
Size = MAX_PATH * sizeof(WCHAR);
if (RegQueryValueEx(RegKey,
TEXT("ImagePath"),
NULL,
&ValueType,
(PBYTE)ImagePath,
&Size) == ERROR_SUCCESS)
{
DefaultImageName = FALSE;
}
}
NtClose(RegKey);
}
#endif
if ((DefaultImageName) ||
((ValueType != REG_EXPAND_SZ) && (ValueType != REG_SZ)) ||
(Size < (2 * sizeof(WCHAR))))
{
//
// No special ImagePath or MofImagePath so assume image file is
// %SystemRoot%\System32\Drivers\Driver.Sys
StringCchCopyW(Buffer,
MAX_PATH,
TEXT("%SystemRoot%\\System32\\Drivers\\"));
StringCchCatW(Buffer, MAX_PATH, DriverName);
StringCchCatW(Buffer, MAX_PATH, TEXT(".SYS"));
} else {
if (_wcsnicmp(ImagePath,
SystemRoot,
SystemRootCharSize) == 0)
{
//
// Looks like format C
StringCchCopyW(Buffer, MAX_PATH, SystemRootDirectory);
StringCchCatW(Buffer, MAX_PATH, &ImagePath[SystemRootCharSize]);
} else if ((*ImagePath == '%') ||
( (Size > 3*sizeof(WCHAR)) && ImagePath[1] == TEXT(':')) )
{
//
// Looks like format B or format A
StringCchCopyW(Buffer, MAX_PATH, ImagePath);
} else if (_wcsnicmp(ImagePath,
QuestionPrefix,
QuestionPrefixSize) == 0)
{
//
// Looks like format E
StringCchCopyW(Buffer, MAX_PATH, ImagePath+QuestionPrefixSize);
} else {
//
// Assume format D
StringCchCopyW(Buffer, MAX_PATH, SystemRootDirectory);
StringCchCatW(Buffer, MAX_PATH, ImagePath);
}
}
#if defined(_NTDLLBUILD_)
Size = EtwpExpandEnvironmentStringsW(Buffer,
ImagePath,
MAX_PATH);
#else
Size = ExpandEnvironmentStrings(Buffer,
ImagePath,
MAX_PATH);
#endif
#ifdef MEMPHIS
EtwpDebugPrint(("WMI: %s has mof in %s\n",
DriverName, ImagePath));
#else
EtwpDebugPrint(("WMI: %ws has mof in %ws\n",
DriverName, ImagePath));
#endif
EtwpFree(Buffer);
} else {
ImagePath = NULL;
}
return(ImagePath);
}
BOOLEAN
EtwpCopyMRString(
PWCHAR Buffer,
ULONG BufferRemaining,
PULONG BufferUsed,
PWCHAR SourceString
)
{
BOOLEAN BufferNotFull;
ULONG len;
len = wcslen(SourceString) + 1;
if (len <= BufferRemaining)
{
wcscpy(Buffer, SourceString);
*BufferUsed = len;
BufferNotFull = TRUE;
} else {
BufferNotFull = FALSE;
}
return(BufferNotFull);
}
BOOLEAN
EtwpFileExists(
PWCHAR FileName
)
{
HANDLE FindHandle;
BOOLEAN Found;
PWIN32_FIND_DATA FindData;
FindData = (PWIN32_FIND_DATA)EtwpAlloc(sizeof(WIN32_FIND_DATA));
if (FindData != NULL)
{
//
// Now we need to make sure that the file a ctually exists
//
#if defined(_NTDLLBUILD_)
FindHandle = EtwpFindFirstFileW(FileName, FindData);
#else
FindHandle = FindFirstFile(FileName, FindData);
#endif
if (FindHandle == INVALID_HANDLE_VALUE)
{
Found = FALSE;
} else {
#if defined(_NTDLLBUILD_)
EtwpFindClose(FindHandle);
#else
FindClose(FindHandle);
#endif
Found = TRUE;
}
EtwpFree(FindData);
} else {
Found = FALSE;
}
return(Found);
}
ULONG EtwpGetWindowsDirectory(
PWCHAR *s,
PWCHAR Static,
ULONG StaticSize
)
{
ULONG Size;
ULONG Status = ERROR_SUCCESS;
#if defined(_NTDLLBUILD_)
Size = EtwpGetSystemWindowsDirectoryW(Static, StaticSize);
#else
Size = GetWindowsDirectory(Static, StaticSize);
#endif
if (Size > StaticSize)
{
Size += sizeof(UNICODE_NULL);
*s = EtwpAlloc(Size * sizeof(WCHAR));
if (*s != NULL)
{
#if defined(_NTDLLBUILD_)
Size = EtwpGetSystemWindowsDirectoryW(*s, Size);
#else
Size = GetWindowsDirectory(*s, Size);
#endif
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
} else if (Size == 0) {
#if defined(_NTDLLBUILD_)
Status = EtwpGetLastError();
#else
Status = GetLastError();
#endif
} else {
*s = Static;
}
if (Status == ERROR_SUCCESS)
{
if ( (*s)[Size-1] == L'\\')
{
(*s)[Size-1] = 0;
}
}
return(Status);
}
ULONG
EtwpBuildMUIPath(
PWCHAR Buffer,
ULONG BufferRemaining,
PULONG BufferUsed,
PWCHAR EnglishPath,
PWCHAR Language,
PBOOLEAN BufferNotFull
)
{
#define FallbackDir L"\\MUI\\Fallback\\"
#define MUIPath L"\\MUI\\"
#define MUITail L".mui"
ULONG EnglishLen;
PWCHAR WinDir;
PWCHAR s, p;
ULONG len;
ULONG Status, SizeNeeded;
PWCHAR LanguagePath;
PWCHAR WinDirStatic;
ULONG WinDirStaticSize;
WinDirStaticSize = MAX_PATH+1;
WinDirStatic = EtwpAlloc(WinDirStaticSize * sizeof(WCHAR));
if (WinDirStatic != NULL)
{
Status = ERROR_FILE_NOT_FOUND;
LanguagePath = Buffer;
EtwpDebugPrint(("WMI: Building MUI path for %ws in language %ws\n",
EnglishPath, Language));
EnglishLen = wcslen(EnglishPath);
p = EnglishPath + EnglishLen;
len = EnglishLen;
//
// Work from the end of the string to try to find the last \ so
// we can then slip in the language name
//
while ( (len != 0) && (*p != L'\\'))
{
len--;
p--;
}
if (len != 0)
{
p++;
}
EtwpDebugPrint(("WMI: Tail of %ws is %ws\n", EnglishPath, p));
//
// First try looking in <path>\\MUI\\<lang id> which is where 3rd
// parties will install their resource only drivers. We look for
// foo.sys and then foo.sys.mui.
//
SizeNeeded = len + wcslen(Language) + wcslen(MUIPath) + 1 + wcslen(p) + 1 + wcslen(MUITail);
if (SizeNeeded <= BufferRemaining)
{
if (len != 0)
{
wcsncpy(LanguagePath, EnglishPath, len);
LanguagePath[len] = 0;
wcscat(LanguagePath, MUIPath);
} else {
LanguagePath[len] = 0;
}
wcscat(LanguagePath, Language);
wcscat(LanguagePath, L"\\");
wcscat(LanguagePath, p);
if (EtwpFileExists(LanguagePath))
{
*BufferUsed = wcslen(LanguagePath) + 1;
*BufferNotFull = TRUE;
Status = ERROR_SUCCESS;
EtwpDebugPrint(("WMI: #1 - Found %ws\n", LanguagePath));
} else {
wcscat(LanguagePath, MUITail);
if (EtwpFileExists(LanguagePath))
{
*BufferUsed = wcslen(LanguagePath) + 1;
*BufferNotFull = TRUE;
Status = ERROR_SUCCESS;
EtwpDebugPrint(("WMI: #2 - Found %ws\n", LanguagePath));
}
}
} else {
*BufferNotFull = FALSE;
Status = ERROR_SUCCESS;
}
if (Status != ERROR_SUCCESS)
{
//
// Next lets check the fallback directory,
// %windir%\MUI\Fallback\<lang id>. This is where system components
// are installed by default.
//
Status = EtwpGetWindowsDirectory(&WinDir,
WinDirStatic,
WinDirStaticSize);
if (Status == ERROR_SUCCESS)
{
SizeNeeded = wcslen(WinDir) +
wcslen(FallbackDir) +
wcslen(Language) +
1 +
wcslen(p) + 1 +
wcslen(MUITail);
if (SizeNeeded <= BufferRemaining)
{
wcscpy(LanguagePath, WinDir);
wcscat(LanguagePath, FallbackDir);
wcscat(LanguagePath, Language);
wcscat(LanguagePath, L"\\");
wcscat(LanguagePath, p);
wcscat(LanguagePath, MUITail);
if ( EtwpFileExists(LanguagePath))
{
*BufferUsed = wcslen(LanguagePath) + 1;
*BufferNotFull = TRUE;
Status = ERROR_SUCCESS;
EtwpDebugPrint(("WMI: #3 - Found %ws\n", LanguagePath));
} else {
Status = ERROR_FILE_NOT_FOUND;
}
} else {
*BufferNotFull = FALSE;
Status = ERROR_SUCCESS;
}
if (WinDir != WinDirStatic)
{
EtwpFree(WinDir);
}
}
}
EtwpFree(WinDirStatic);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return(Status);
}
typedef struct
{
ULONG Count;
ULONG MaxCount;
PWCHAR *List;
} ENUMLANGCTX, *PENUMLANGCTX;
BOOL EnumUILanguageCallback(
LPWSTR Language,
LONG_PTR Context
)
{
PENUMLANGCTX EnumLangCtx = (PENUMLANGCTX)Context;
PWCHAR *p;
PWCHAR w;
ULONG NewMaxCount;
if (EnumLangCtx->Count == EnumLangCtx->MaxCount)
{
NewMaxCount = EnumLangCtx->MaxCount * 2;
p = EtwpAlloc( sizeof(PWCHAR) * NewMaxCount);
if (p != NULL)
{
memset(p, 0, sizeof(PWCHAR) * NewMaxCount);
memcpy(p, EnumLangCtx->List, EnumLangCtx->Count * sizeof(PWCHAR));
EtwpFree(EnumLangCtx->List);
EnumLangCtx->List = p;
EnumLangCtx->MaxCount = NewMaxCount;
} else {
return(FALSE);
}
}
w = EtwpAlloc( (wcslen(Language)+1) * sizeof(WCHAR) );
if (w != NULL)
{
EnumLangCtx->List[EnumLangCtx->Count++] = w;
wcscpy(w, Language);
} else {
return(FALSE);
}
return(TRUE);
}
ULONG
EtwpGetLanguageList(
PWCHAR **List,
PULONG Count
)
{
ENUMLANGCTX EnumLangCtx;
BOOL b;
ULONG Status;
*List = NULL;
*Count = 0;
EnumLangCtx.Count = 0;
EnumLangCtx.MaxCount = 8;
EnumLangCtx.List = EtwpAlloc( 8 * sizeof(PWCHAR) );
if (EnumLangCtx.List != NULL)
{
#if defined(_NTDLLBUILD_)
b = EtwpEnumUILanguages(EnumUILanguageCallback,
0,
(LONG_PTR)&EnumLangCtx);
#else
b = EnumUILanguages(EnumUILanguageCallback,
0,
(LONG_PTR)&EnumLangCtx);
#endif
if (b)
{
*Count = EnumLangCtx.Count;
*List = EnumLangCtx.List;
Status = ERROR_SUCCESS;
} else {
if (EnumLangCtx.List != NULL)
{
EtwpFree(EnumLangCtx.List);
}
#if defined(_NTDLLBUILD_)
Status = EtwpGetLastError();
#else
Status = GetLastError();
#endif
}
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return(Status);
}
BOOL
EtwpSynchReadFile(
HANDLE LogFile,
LPVOID Buffer,
DWORD NumberOfBytesToRead,
LPDWORD NumberOfBytesRead,
LPOVERLAPPED Overlapped
)
/*++
Routine Description:
This routine performs synchronous read on a given file. Since logfile is opened for
asychronous IO, current file position is not available. Thus, for synch read, we need
to use this.
Arguments:
LogFile - handle to file
Buffer - data buffer
NumberOfBytesToRead - number of bytes to read
NumberOfBytesRead - number of bytes read
Overlapped - overlapped structure
Returned Value:
TRUE if succeeded.
--*/
{
BOOL ReadSuccess;
if (Overlapped == NULL || Overlapped->hEvent == NULL || Overlapped->hEvent == INVALID_HANDLE_VALUE) {
return FALSE;
}
#if defined (_NTDLLBUILD_)
if (!EtwpResetEvent(Overlapped->hEvent)) {
return FALSE;
}
ReadSuccess = EtwpReadFile(LogFile,
Buffer,
NumberOfBytesToRead,
NULL,
Overlapped);
if (ReadSuccess || EtwpGetLastError() == ERROR_IO_PENDING) {
ReadSuccess = EtwpGetOverlappedResult(LogFile, Overlapped, NumberOfBytesRead, TRUE);
if (!ReadSuccess && EtwpGetLastError() == ERROR_HANDLE_EOF) {
*NumberOfBytesRead = 0;
EtwpSetEvent(Overlapped->hEvent);
}
return ReadSuccess;
}
else {
*NumberOfBytesRead = 0;
EtwpSetEvent(Overlapped->hEvent);
return FALSE;
}
#else
if (!ResetEvent(Overlapped->hEvent)) {
return FALSE;
}
ReadSuccess = ReadFile(LogFile,
Buffer,
NumberOfBytesToRead,
NULL,
Overlapped);
if (ReadSuccess || GetLastError() == ERROR_IO_PENDING) {
ReadSuccess = GetOverlappedResult(LogFile, Overlapped, NumberOfBytesRead, TRUE);
if (!ReadSuccess && GetLastError() == ERROR_HANDLE_EOF) {
*NumberOfBytesRead = 0;
SetEvent(Overlapped->hEvent);
}
return ReadSuccess;
}
else {
*NumberOfBytesRead = 0;
SetEvent(Overlapped->hEvent);
return FALSE;
}
#endif
}
PVOID
EtwpMemReserve(
IN SIZE_T Size
)
{
NTSTATUS Status;
PVOID lpAddress = NULL;
try {
Status = NtAllocateVirtualMemory(
NtCurrentProcess(),
&lpAddress,
0,
&Size,
MEM_RESERVE,
PAGE_READWRITE);
}
except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
if (NT_SUCCESS(Status)) {
return lpAddress;
}
else {
EtwpSetDosError(EtwpNtStatusToDosError(Status));
return NULL;
}
}
PVOID
EtwpMemCommit(
IN PVOID Buffer,
IN SIZE_T Size
)
{
NTSTATUS Status;
try {
Status = NtAllocateVirtualMemory(
NtCurrentProcess(),
&Buffer,
0,
&Size,
MEM_COMMIT,
PAGE_READWRITE);
}
except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
if (NT_SUCCESS(Status)) {
return Buffer;
}
else {
EtwpSetDosError(EtwpNtStatusToDosError(Status));
return NULL;
}
}
ULONG
EtwpMemFree(
IN PVOID Buffer
)
{
NTSTATUS Status;
SIZE_T Size = 0;
HANDLE hProcess = NtCurrentProcess();
if (Buffer == NULL) {
EtwpSetDosError(ERROR_INVALID_PARAMETER);
return FALSE;
}
try {
Status = NtFreeVirtualMemory( hProcess, &Buffer, &Size, MEM_RELEASE);
}
except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
if (NT_SUCCESS(Status)) {
return TRUE;
}
else {
if (Status == STATUS_INVALID_PAGE_PROTECTION) {
if (RtlFlushSecureMemoryCache(Buffer, Size)) {
Status = NtFreeVirtualMemory(
hProcess, Buffer, &Size, MEM_RELEASE);
if (NT_SUCCESS(Status)) {
return TRUE;
}
}
}
EtwpSetDosError(EtwpNtStatusToDosError(Status));
return FALSE;
}
}
ULONG EtwpConvertWADToAnsi(
PWNODE_ALL_DATA Wnode
)
/*+++
Routine Description:
This routine will convert the instance names in a WNODE_ALL_DATA to
ansi. The conversion is done in place since we can assume that ansi
strings are no longer than unicode strings.
Arguments:
Wnode is the WNODE_ALL_DATA whose instance names are to be converted to
ANSI
Return Value:
Returns ERROR_SUCCESS or an error code.
---*/
{
ULONG i;
ULONG Linkage;
ULONG InstanceCount;
PULONG InstanceNameOffsets;
PWCHAR Ptr;
ULONG Status = ERROR_SUCCESS;
EtwpAssert(!(Wnode->WnodeHeader.Flags & WNODE_FLAG_ANSI_INSTANCENAMES));
do
{
Wnode->WnodeHeader.Flags |= WNODE_FLAG_ANSI_INSTANCENAMES;
InstanceCount = Wnode->InstanceCount;
InstanceNameOffsets = (PULONG)(((PUCHAR)Wnode) +
Wnode->OffsetInstanceNameOffsets);
for (i = 0; i < InstanceCount; i++)
{
Ptr = (PWCHAR)(((PUCHAR)Wnode) + InstanceNameOffsets[i]);
try
{
Status = EtwpCountedUnicodeToCountedAnsi(Ptr, (PCHAR)Ptr);
} except(EXCEPTION_EXECUTE_HANDLER) {
// Wnode->WnodeHeader.Flags |= WNODE_FLAG_INVALID;
return(ERROR_SUCCESS);
}
if (Status != ERROR_SUCCESS)
{
#if defined (_NTDLLBUILD_)
EtwpSetLastError(Status);
#else
SetLastError(Status);
#endif
goto Done;
}
}
Linkage = Wnode->WnodeHeader.Linkage;
Wnode = (PWNODE_ALL_DATA)(((PUCHAR)Wnode) + Linkage);
} while (Linkage != 0);
Done:
return(Status);
}
ULONG EtwpUnicodeToAnsi(
LPCWSTR pszW,
LPSTR * ppszA,
ULONG *AnsiSizeInBytes OPTIONAL
){
ANSI_STRING DestinationString;
UNICODE_STRING SourceString;
NTSTATUS Status;
BOOLEAN AllocateString;
ULONG AnsiLength;
//
// If output is null then return error as we don't have
// any place to put output string
//
if( ppszA==NULL ){
return(STATUS_INVALID_PARAMETER_2);
}
//
// If input is null then just return the same.
//
if (pszW == NULL)
{
*ppszA = NULL;
return(ERROR_SUCCESS);
}
//
// We ASSUME that if *ppszA!=NULL then we have sufficient
// amount of memory to copy
//
AllocateString = ((*ppszA) == NULL );
RtlInitUnicodeString(&SourceString,(LPWSTR)pszW);
AnsiLength = RtlUnicodeStringToAnsiSize(&SourceString);
if ( AnsiLength > MAXUSHORT ) {
return STATUS_INVALID_PARAMETER_1;
}
DestinationString.Length = (USHORT)(AnsiLength - 1);
DestinationString.MaximumLength = (USHORT)AnsiLength;
DestinationString.Buffer = EtwpAlloc(AnsiLength);
if ( DestinationString.Buffer == NULL ) {
return STATUS_NO_MEMORY;
}
Status = RtlUnicodeStringToAnsiString( &DestinationString, &SourceString, FALSE);
if( NT_SUCCESS(Status) ) {
if( AllocateString ) {
*ppszA = DestinationString.Buffer;
} else {
memcpy((*ppszA),DestinationString.Buffer,AnsiLength);
EtwpFree(DestinationString.Buffer);
}
if (AnsiSizeInBytes != NULL){
*AnsiSizeInBytes = DestinationString.Length;
}
} else {
EtwpFree(DestinationString.Buffer);
}
return Status;
}
ULONG EtwpCountedUnicodeToCountedAnsi(
PWCHAR Unicode,
PCHAR Ansi
)
/*++
Routine Description:
Translate a counted ansi string into a counted unicode string.
Conversion may be done inplace, that is Ansi == Unicode.
Arguments:
Unicode is the counted unicode string to convert to ansi
Ansi is the buffer to place the converted string into
Return Value:
ERROR_SUCCESS or an error code
--*/
{
PCHAR APtr;
PWCHAR WPtr;
ULONG AnsiSize, UnicodeSize;
ULONG Status;
UnicodeSize = *Unicode;
WPtr = EtwpAlloc(UnicodeSize + sizeof(WCHAR));
if (WPtr != NULL)
{
memcpy(WPtr, Unicode + 1, UnicodeSize);
WPtr[UnicodeSize/sizeof(WCHAR)] = UNICODE_NULL;
APtr = NULL;
Status = EtwpUnicodeToAnsi(WPtr, &APtr, &AnsiSize);
if (Status == ERROR_SUCCESS)
{
*((PUSHORT)Ansi) = (USHORT)AnsiSize;
memcpy(Ansi+sizeof(USHORT), APtr, AnsiSize);
Status = ERROR_SUCCESS;
EtwpFree(APtr);
}
EtwpFree(WPtr);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return(Status);
}