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.
 
 
 
 
 
 

5443 lines
182 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
dllprof.c
Abstract:
This module contains the client side of the Win32 Initialization
File APIs
Author:
Steve Wood (stevewo) 24-Sep-1990
Revision History:
--*/
#include "basedll.h"
#include <limits.h>
#if DBG
BOOLEAN BaseDllDumpIniCalls;
#endif
PINIFILE_MAPPING BaseDllIniFileMapping;
PINIFILE_CACHE BaseDllIniFileCache;
UNICODE_STRING BaseDllIniUserKeyPath;
UNICODE_STRING BaseDllIniSoftwareKeyPath;
ULONG LockFileKey = 1;
struct {
PINIFILE_MAPPING_TARGET MappingTarget;
ULONG MappingFlags;
BOOLEAN WriteAccess;
UNICODE_STRING RegistryPath;
HANDLE RegistryKey;
CRITICAL_SECTION Lock;
} BaseDllRegistryCache;
NTSTATUS
BaseDllInitializeIniFileMappings(
PBASE_STATIC_SERVER_DATA StaticServerData
)
{
BaseDllIniFileMapping = (PINIFILE_MAPPING)StaticServerData->IniFileMapping;
BaseDllIniFileCache = NULL;
#if DBG
BaseDllDumpIniCalls = FALSE;
#endif
// BaseDllDumpIniCalls = TRUE;
BaseDllIniUserKeyPath.Length = 0;
BaseDllIniUserKeyPath.MaximumLength = 0;
BaseDllIniUserKeyPath.Buffer = NULL;
BaseDllIniSoftwareKeyPath.Length = sizeof (L"\\Registry\\Machine\\Software") - sizeof (WCHAR);
BaseDllIniSoftwareKeyPath.MaximumLength = BaseDllIniSoftwareKeyPath.Length;
BaseDllIniSoftwareKeyPath.Buffer = L"\\Registry\\Machine\\Software";
RtlZeroMemory( &BaseDllRegistryCache, sizeof( BaseDllRegistryCache ) );
BaseDllRegistryCache.RegistryKey = INVALID_HANDLE_VALUE;
InitializeCriticalSection(&BaseDllRegistryCache.Lock);
return STATUS_SUCCESS;
}
NTSTATUS
BaseDllReadWriteIniFile(
IN BOOLEAN Unicode,
IN BOOLEAN WriteOperation,
IN BOOLEAN SectionOperation,
IN PVOID FileName OPTIONAL,
IN PVOID ApplicationName OPTIONAL,
IN PVOID VariableName OPTIONAL,
IN OUT PVOID VariableValue OPTIONAL,
IN OUT PULONG VariableValueLength OPTIONAL
);
DWORD
WINAPI
GetPrivateProfileSectionNamesA(
LPSTR lpszReturnBuffer,
DWORD nSize,
LPCSTR lpFileName
)
{
return GetPrivateProfileStringA( NULL,
NULL,
NULL,
lpszReturnBuffer,
nSize,
lpFileName
);
}
DWORD
WINAPI
GetPrivateProfileSectionNamesW(
LPWSTR lpszReturnBuffer,
DWORD nSize,
LPCWSTR lpFileName
)
{
return GetPrivateProfileStringW( NULL,
NULL,
NULL,
lpszReturnBuffer,
nSize,
lpFileName
);
}
#define NibbleToChar(x) (N2C[x])
#define CharToNibble(x) ((x)>='0'&&(x)<='9' ? (x)-'0' : ((10+(x)-'A')&0x000f))
char N2C[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
};
BOOL
WINAPI
GetPrivateProfileStructA(
LPCSTR lpszSection,
LPCSTR lpszKey,
LPVOID lpStruct,
UINT uSizeStruct,
LPCSTR szFile
)
{
UCHAR szBuf[256];
LPSTR lpBuf, lpBufTemp, lpFreeBuffer;
UINT nLen;
BYTE checksum;
BOOL Result;
if ((INT_MAX - 5) < uSizeStruct) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
nLen = uSizeStruct*2 + 10;
if (nLen > sizeof( szBuf )) {
lpFreeBuffer = (LPSTR)RtlAllocateHeap( RtlProcessHeap(),
0,
nLen
);
if (!lpFreeBuffer) {
return FALSE;
}
lpBuf = lpFreeBuffer;
} else {
lpFreeBuffer = NULL;
lpBuf = (LPSTR)szBuf;
}
Result = FALSE;
nLen = GetPrivateProfileStringA( lpszSection,
lpszKey,
NULL,
lpBuf,
nLen,
szFile
);
if (nLen == uSizeStruct*2+2) {
/* Room for the one byte check sum */
uSizeStruct+=1;
checksum = 0;
for (lpBufTemp=lpBuf; uSizeStruct!=0; --uSizeStruct) {
BYTE bStruct;
BYTE cTemp;
cTemp = *lpBufTemp++;
bStruct = (BYTE)CharToNibble(cTemp);
cTemp = *lpBufTemp++;
bStruct = (BYTE)((bStruct<<4) | CharToNibble(cTemp));
if (uSizeStruct == 1) {
if (checksum == bStruct) {
Result = TRUE;
} else {
SetLastError( ERROR_INVALID_DATA );
}
break;
}
checksum += bStruct;
*((LPBYTE)lpStruct)++ = bStruct;
}
} else {
SetLastError( ERROR_BAD_LENGTH );
}
if (lpFreeBuffer) {
RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
}
return Result;
}
BOOL
WINAPI
GetPrivateProfileStructW(
LPCWSTR lpszSection,
LPCWSTR lpszKey,
LPVOID lpStruct,
UINT uSizeStruct,
LPCWSTR szFile
)
{
WCHAR szBuf[256];
PWSTR lpBuf, lpBufTemp, lpFreeBuffer;
UINT nLen;
BYTE checksum;
BOOL Result;
nLen = uSizeStruct*2 + 10;
if (nLen < uSizeStruct) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if ((nLen > sizeof( szBuf ))
|| ((nLen * sizeof( WCHAR )) > sizeof( szBuf ))) {
lpFreeBuffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(),
0,
nLen * sizeof( WCHAR )
);
if (!lpFreeBuffer) {
return FALSE;
}
lpBuf = lpFreeBuffer;
} else {
lpFreeBuffer = NULL;
lpBuf = (PWSTR)szBuf;
}
Result = FALSE;
nLen = GetPrivateProfileStringW( lpszSection,
lpszKey,
NULL,
lpBuf,
nLen,
szFile
);
if (nLen == uSizeStruct*2+2) {
/* Room for the one byte check sum */
uSizeStruct+=1;
checksum = 0;
for (lpBufTemp=lpBuf; uSizeStruct!=0; --uSizeStruct) {
BYTE bStruct;
WCHAR cTemp;
cTemp = *lpBufTemp++;
bStruct = (BYTE)CharToNibble(cTemp);
cTemp = *lpBufTemp++;
bStruct = (BYTE)((bStruct<<4) | CharToNibble(cTemp));
if (uSizeStruct == 1) {
if (checksum == bStruct) {
Result = TRUE;
} else {
SetLastError( ERROR_INVALID_DATA );
}
break;
}
checksum += bStruct;
*((LPBYTE)lpStruct)++ = bStruct;
}
} else {
SetLastError( ERROR_BAD_LENGTH );
}
if (lpFreeBuffer) {
RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
}
return Result;
}
BOOL
WINAPI
WritePrivateProfileStructA(
LPCSTR lpszSection,
LPCSTR lpszKey,
LPVOID lpStruct,
UINT uSizeStruct,
LPCSTR szFile
)
{
UCHAR szBuf[256];
LPSTR lpBuf, lpBufTemp, lpFreeBuffer;
UINT nLen;
BOOL Result;
BYTE checksum;
if (lpStruct == NULL) {
return WritePrivateProfileStringA( lpszSection,
lpszKey,
NULL,
szFile
);
}
nLen = uSizeStruct*2 + 3;
if (nLen < uSizeStruct) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (nLen > sizeof( szBuf )) {
lpFreeBuffer = (LPSTR)RtlAllocateHeap( RtlProcessHeap(),
0,
nLen
);
if (!lpFreeBuffer) {
return FALSE;
}
lpBuf = lpFreeBuffer;
} else {
lpFreeBuffer = NULL;
lpBuf = (LPSTR)szBuf;
}
checksum = 0;
for (lpBufTemp=lpBuf; uSizeStruct != 0; --uSizeStruct) {
BYTE bStruct;
bStruct = *((LPBYTE)lpStruct)++;
checksum = checksum + bStruct;
*lpBufTemp++ = NibbleToChar((bStruct>>4)&0x000f);
*lpBufTemp++ = NibbleToChar(bStruct&0x000f);
}
*lpBufTemp++ = NibbleToChar((checksum>>4)&0x000f);
*lpBufTemp++ = NibbleToChar(checksum&0x000f);
*lpBufTemp = '\0';
Result = WritePrivateProfileStringA( lpszSection,
lpszKey,
lpBuf,
szFile
);
if (lpFreeBuffer) {
RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
}
return Result;
}
BOOL
WINAPI
WritePrivateProfileStructW(
LPCWSTR lpszSection,
LPCWSTR lpszKey,
LPVOID lpStruct,
UINT uSizeStruct,
LPCWSTR szFile
)
{
WCHAR szBuf[256];
PWSTR lpBuf, lpBufTemp, lpFreeBuffer;
UINT nLen;
BOOL Result;
BYTE checksum;
if (lpStruct == NULL) {
return WritePrivateProfileStringW( lpszSection,
lpszKey,
NULL,
szFile
);
}
nLen = uSizeStruct*2 + 3;
if (nLen < uSizeStruct) {
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if ((nLen * sizeof( WCHAR )) > sizeof( szBuf )) {
lpFreeBuffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(),
0,
nLen * sizeof( WCHAR )
);
if (!lpFreeBuffer) {
return FALSE;
}
lpBuf = lpFreeBuffer;
} else {
lpFreeBuffer = NULL;
lpBuf = (PWSTR)szBuf;
}
checksum = 0;
for (lpBufTemp=lpBuf; uSizeStruct != 0; --uSizeStruct) {
BYTE bStruct;
bStruct = *((LPBYTE)lpStruct)++;
checksum = checksum + bStruct;
*lpBufTemp++ = (WCHAR)NibbleToChar((bStruct>>4)&0x000f);
*lpBufTemp++ = (WCHAR)NibbleToChar(bStruct&0x000f);
}
*lpBufTemp++ = (WCHAR)NibbleToChar((checksum>>4)&0x000f);
*lpBufTemp++ = (WCHAR)NibbleToChar(checksum&0x000f);
*lpBufTemp = L'\0';
Result = WritePrivateProfileStringW( lpszSection,
lpszKey,
lpBuf,
szFile
);
if (lpFreeBuffer) {
RtlFreeHeap( RtlProcessHeap(), 0, lpFreeBuffer );
}
return Result;
}
UINT
GetProfileIntA(
LPCSTR lpAppName,
LPCSTR lpKeyName,
INT nDefault
)
{
return( GetPrivateProfileIntA( lpAppName,
lpKeyName,
nDefault,
NULL
)
);
}
DWORD
GetProfileStringA(
LPCSTR lpAppName,
LPCSTR lpKeyName,
LPCSTR lpDefault,
LPSTR lpReturnedString,
DWORD nSize
)
{
return( GetPrivateProfileStringA( lpAppName,
lpKeyName,
lpDefault,
lpReturnedString,
nSize,
NULL
)
);
}
BOOL
WriteProfileStringA(
LPCSTR lpAppName,
LPCSTR lpKeyName,
LPCSTR lpString
)
{
return( WritePrivateProfileStringA( lpAppName,
lpKeyName,
lpString,
NULL
)
);
}
DWORD
GetProfileSectionA(
LPCSTR lpAppName,
LPSTR lpReturnedString,
DWORD nSize
)
{
return( GetPrivateProfileSectionA( lpAppName,
lpReturnedString,
nSize,
NULL
)
);
}
BOOL
WriteProfileSectionA(
LPCSTR lpAppName,
LPCSTR lpString
)
{
return( WritePrivateProfileSectionA( lpAppName,
lpString,
NULL
)
);
}
UINT
APIENTRY
GetProfileIntW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
INT nDefault
)
{
return( GetPrivateProfileIntW( lpAppName,
lpKeyName,
nDefault,
NULL
)
);
}
DWORD
APIENTRY
GetProfileStringW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize
)
{
return( GetPrivateProfileStringW( lpAppName,
lpKeyName,
lpDefault,
lpReturnedString,
nSize,
NULL
)
);
}
BOOL
APIENTRY
WriteProfileStringW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpString
)
{
return( WritePrivateProfileStringW( lpAppName,
lpKeyName,
lpString,
NULL
)
);
}
DWORD
APIENTRY
GetProfileSectionW(
LPCWSTR lpAppName,
LPWSTR lpReturnedString,
DWORD nSize
)
{
return( GetPrivateProfileSectionW( lpAppName,
lpReturnedString,
nSize,
NULL
)
);
}
BOOL
APIENTRY
WriteProfileSectionW(
LPCWSTR lpAppName,
LPCWSTR lpString
)
{
return( WritePrivateProfileSectionW( lpAppName,
lpString,
NULL
)
);
}
UINT
GetPrivateProfileIntA(
LPCSTR lpAppName,
LPCSTR lpKeyName,
INT nDefault,
LPCSTR lpFileName
)
{
NTSTATUS Status;
ULONG ReturnValue;
UCHAR ValueBuffer[ 256 ];
ULONG cb;
ReturnValue = 0;
cb = GetPrivateProfileStringA( lpAppName,
lpKeyName,
NULL,
ValueBuffer,
sizeof( ValueBuffer ),
lpFileName
);
if (cb == 0) {
ReturnValue = nDefault;
} else {
Status = RtlCharToInteger( ValueBuffer, 0, &ReturnValue );
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
} else {
SetLastError( NO_ERROR );
}
}
return ReturnValue;
}
DWORD
GetPrivateProfileStringA(
LPCSTR lpAppName,
LPCSTR lpKeyName,
LPCSTR lpDefault,
LPSTR lpReturnedString,
DWORD nSize,
LPCSTR lpFileName
)
{
NTSTATUS Status;
ULONG n;
if (lpDefault == NULL) {
lpDefault = "";
}
n = nSize;
Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
FALSE, // WriteOperation
FALSE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
RTL_CONST_CAST(PVOID)(lpKeyName),
lpReturnedString,
&n
);
if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
if (NT_SUCCESS( Status )) {
SetLastError( NO_ERROR );
n--;
} else
if (!lpAppName || !lpKeyName) {
if (nSize >= 2) {
n = nSize - 2;
lpReturnedString[ n+1 ] = '\0';
//
// GetPrivateProfileString(): don't leave 1st byte of double byte char alone
//
lpReturnedString[ n ] = '\0';
if ( n > 0 ) {
LPSTR pc = lpReturnedString;
LPSTR pcEnd = lpReturnedString + n - 1;
//
// if the last character is the 1st byte of
// double byte character, erase it.
//
while ( pc <= pcEnd ) {
pc += IsDBCSLeadByte( *pc ) ? 2 : 1;
}
if ( (pc - pcEnd ) == 2 ) {
*pcEnd = '\0';
}
}
return ( n );
} else {
n = 0;
}
} else {
if (nSize >= 1) {
n = nSize - 1;
} else {
n = 0;
}
}
} else {
n = strlen( lpDefault );
while (n > 0 && lpDefault[n-1] == ' ') {
n -= 1;
}
if (n >= nSize) {
n = nSize;
}
strncpy( lpReturnedString, lpDefault, n );
}
if (n < nSize) {
lpReturnedString[ n ] = '\0';
} else
if (nSize > 0) {
lpReturnedString[ nSize-1 ] = '\0';
}
return( n );
}
BOOL
WritePrivateProfileStringA(
LPCSTR lpAppName,
LPCSTR lpKeyName,
LPCSTR lpString,
LPCSTR lpFileName
)
{
NTSTATUS Status;
Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
TRUE, // WriteOperation
FALSE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
RTL_CONST_CAST(PVOID)(lpKeyName),
RTL_CONST_CAST(PVOID)(lpKeyName == NULL ? NULL : lpString),
NULL
);
if (NT_SUCCESS( Status )) {
return( TRUE );
} else {
if (Status == STATUS_INVALID_IMAGE_FORMAT) {
SetLastError( ERROR_INVALID_DATA );
} else {
BaseSetLastNTError( Status );
}
return( FALSE );
}
}
DWORD
GetPrivateProfileSectionA(
LPCSTR lpAppName,
LPSTR lpReturnedString,
DWORD nSize,
LPCSTR lpFileName
)
{
NTSTATUS Status;
ULONG n;
n = nSize;
Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
FALSE, // WriteOperation
TRUE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
NULL,
lpReturnedString,
&n
);
if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
if (NT_SUCCESS( Status )) {
SetLastError( NO_ERROR );
n--;
} else
if (nSize >= 2) {
n = nSize - 2;
lpReturnedString[ n+1 ] = '\0';
} else {
n = 0;
}
} else {
if (Status == STATUS_INVALID_IMAGE_FORMAT) {
SetLastError( ERROR_INVALID_DATA );
} else {
BaseSetLastNTError( Status );
}
n = 0;
}
if (n < nSize) {
lpReturnedString[ n ] = '\0';
} else
if (nSize > 0) {
lpReturnedString[ nSize-1 ] = '\0';
}
return( n );
}
BOOL
WritePrivateProfileSectionA(
LPCSTR lpAppName,
LPCSTR lpString,
LPCSTR lpFileName
)
{
NTSTATUS Status;
Status = BaseDllReadWriteIniFile( FALSE, // Unicode,
TRUE, // WriteOperation
TRUE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
NULL,
RTL_CONST_CAST(PVOID)(lpString),
NULL
);
if (NT_SUCCESS( Status )) {
return( TRUE );
} else {
if (Status == STATUS_INVALID_IMAGE_FORMAT) {
SetLastError( ERROR_INVALID_DATA );
} else {
BaseSetLastNTError( Status );
}
return( FALSE );
}
}
UINT
APIENTRY
GetPrivateProfileIntW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
INT nDefault,
LPCWSTR lpFileName
)
{
NTSTATUS Status;
ULONG ReturnValue;
WCHAR ValueBuffer[ 256 ];
UNICODE_STRING Value;
ANSI_STRING AnsiString;
ULONG cb;
ReturnValue = 0;
cb = GetPrivateProfileStringW( lpAppName,
lpKeyName,
NULL,
ValueBuffer,
sizeof( ValueBuffer ) / sizeof( WCHAR ),
lpFileName
);
if (cb == 0) {
ReturnValue = nDefault;
} else {
Value.Buffer = ValueBuffer;
Value.Length = (USHORT)(cb * sizeof( WCHAR ));
Value.MaximumLength = (USHORT)((cb + 1) * sizeof( WCHAR ));
Status = RtlUnicodeStringToAnsiString( &AnsiString,
&Value,
TRUE
);
if (NT_SUCCESS( Status )) {
Status = RtlCharToInteger( AnsiString.Buffer, 0, &ReturnValue );
RtlFreeAnsiString( &AnsiString );
}
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
} else {
SetLastError( NO_ERROR );
}
}
return ReturnValue;
}
DWORD
APIENTRY
GetPrivateProfileStringW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize,
LPCWSTR lpFileName
)
{
NTSTATUS Status;
ULONG n;
if (lpDefault == NULL) {
lpDefault = L"";
}
n = nSize;
Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
FALSE, // WriteOperation
FALSE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
RTL_CONST_CAST(PVOID)(lpKeyName),
lpReturnedString,
&n
);
if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
if (NT_SUCCESS( Status )) {
SetLastError( NO_ERROR );
n--;
} else
if (!lpAppName || !lpKeyName) {
if (nSize >= 2) {
n = nSize - 2;
lpReturnedString[ n+1 ] = UNICODE_NULL;
} else {
n = 0;
}
} else {
if (nSize >= 1) {
n = nSize - 1;
} else {
n = 0;
}
}
} else {
n = wcslen( lpDefault );
while (n > 0 && lpDefault[n-1] == L' ') {
n -= 1;
}
if (n >= nSize) {
n = nSize;
}
wcsncpy( lpReturnedString, lpDefault, n );
}
if (n < nSize) {
lpReturnedString[ n ] = UNICODE_NULL;
} else
if (nSize > 0) {
lpReturnedString[ nSize-1 ] = UNICODE_NULL;
}
return( n );
}
BOOL
APIENTRY
WritePrivateProfileStringW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpString,
LPCWSTR lpFileName
)
{
NTSTATUS Status;
Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
TRUE, // WriteOperation
FALSE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
RTL_CONST_CAST(PVOID)(lpKeyName),
RTL_CONST_CAST(PVOID)(lpKeyName == NULL ? NULL : lpString),
NULL
);
if (NT_SUCCESS( Status )) {
return( TRUE );
} else {
if (Status == STATUS_INVALID_IMAGE_FORMAT) {
SetLastError( ERROR_INVALID_DATA );
} else {
BaseSetLastNTError( Status );
}
return( FALSE );
}
}
DWORD
APIENTRY
GetPrivateProfileSectionW(
LPCWSTR lpAppName,
LPWSTR lpReturnedString,
DWORD nSize,
LPCWSTR lpFileName
)
{
NTSTATUS Status;
ULONG n;
n = nSize;
Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
FALSE, // WriteOperation
TRUE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
NULL,
lpReturnedString,
&n
);
if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
if (NT_SUCCESS( Status )) {
SetLastError( NO_ERROR );
n--;
} else
if (nSize >= 2) {
n = nSize - 2;
lpReturnedString[ n+1 ] = UNICODE_NULL;
} else {
n = 0;
}
} else {
if (Status == STATUS_INVALID_IMAGE_FORMAT) {
SetLastError( ERROR_INVALID_DATA );
} else {
BaseSetLastNTError( Status );
}
n = 0;
}
if (n < nSize) {
lpReturnedString[ n ] = UNICODE_NULL;
} else
if (nSize > 0) {
lpReturnedString[ nSize-1 ] = UNICODE_NULL;
}
return( n );
}
BOOL
APIENTRY
WritePrivateProfileSectionW(
LPCWSTR lpAppName,
LPCWSTR lpString,
LPCWSTR lpFileName
)
{
NTSTATUS Status;
Status = BaseDllReadWriteIniFile( TRUE, // Unicode,
TRUE, // WriteOperation
TRUE, // SectionOperation
RTL_CONST_CAST(PVOID)(lpFileName),
RTL_CONST_CAST(PVOID)(lpAppName),
NULL,
RTL_CONST_CAST(PVOID)(lpString),
NULL
);
if (NT_SUCCESS( Status )) {
return( TRUE );
} else {
if (Status == STATUS_INVALID_IMAGE_FORMAT) {
SetLastError( ERROR_INVALID_DATA );
} else {
BaseSetLastNTError( Status );
}
return( FALSE );
}
}
VOID
BaseDllFlushRegistryCache( VOID );
BOOL
CloseProfileUserMapping( VOID )
{
BaseDllFlushRegistryCache();
RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
if (BaseDllIniUserKeyPath.Buffer != NULL) {
RtlFreeUnicodeString( &BaseDllIniUserKeyPath );
RtlInitUnicodeString( &BaseDllIniUserKeyPath, NULL );
}
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
return TRUE;
}
BOOL
OpenProfileUserMapping( VOID )
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE Key;
BaseDllFlushRegistryCache();
RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
if (BaseDllIniUserKeyPath.Length == 0) {
Status = RtlFormatCurrentUserKeyPath( &BaseDllIniUserKeyPath );
if (NT_SUCCESS( Status )) {
InitializeObjectAttributes( &ObjectAttributes,
&BaseDllIniUserKeyPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey( &Key,
GENERIC_READ,
&ObjectAttributes
);
if (NT_SUCCESS( Status )) {
NtClose( Key );
} else {
RtlFreeUnicodeString( &BaseDllIniUserKeyPath );
RtlInitUnicodeString( &BaseDllIniUserKeyPath, NULL );
}
}
if (!NT_SUCCESS( Status )) {
if (!RtlCreateUnicodeString( &BaseDllIniUserKeyPath, L"\\REGISTRY\\USER\\.DEFAULT" )) {
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
return FALSE;
}
}
}
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
return TRUE;
}
#if DBG
char *xOperationNames[] = {
"FlushProfiles",
"ReadKeyValue",
"WriteKeyValue",
"DeleteKey",
"ReadKeyNames",
"ReadSectionNames",
"ReadSection",
"WriteSection",
"DeleteSection",
"RefreshIniFileMapping"
};
#endif
NTSTATUS
BaseDllCaptureIniFileParameters(
BOOLEAN UnicodeParameters,
INIFILE_OPERATION Operation,
BOOLEAN WriteOperation,
BOOLEAN MultiValueStrings,
PVOID FileName,
PVOID ApplicationName,
PVOID VariableName,
PVOID VariableValue,
PULONG ResultMaxChars OPTIONAL,
PINIFILE_PARAMETERS *ReturnedParameterBlock
);
NTSTATUS
BaseDllReadWriteIniFileViaMapping(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllReadWriteIniFileOnDisk(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllOpenIniFileOnDisk(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllCloseIniFileOnDisk(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllAppendNullToResultBuffer(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllAppendStringToResultBuffer(
IN PINIFILE_PARAMETERS a,
IN PANSI_STRING String OPTIONAL,
IN PUNICODE_STRING StringU OPTIONAL,
IN BOOLEAN IncludeNull
);
NTSTATUS
BaseDllAppendBufferToResultBuffer(
IN PINIFILE_PARAMETERS a,
IN PBYTE Buffer OPTIONAL,
IN PWSTR BufferU OPTIONAL,
IN ULONG Chars,
IN BOOLEAN IncludeNull
);
NTSTATUS
BaseDllReadWriteIniFile(
IN BOOLEAN Unicode,
IN BOOLEAN WriteOperation,
IN BOOLEAN SectionOperation,
IN PVOID FileName OPTIONAL,
IN PVOID ApplicationName OPTIONAL,
IN PVOID VariableName OPTIONAL,
IN OUT PVOID VariableValue OPTIONAL,
IN OUT PULONG VariableValueLength OPTIONAL
)
{
BOOLEAN MultiValueStrings;
INIFILE_OPERATION Operation;
PINIFILE_PARAMETERS a;
NTSTATUS Status;
if (SectionOperation) {
VariableName = NULL;
}
MultiValueStrings = FALSE;
if (WriteOperation) {
if (ARGUMENT_PRESENT( ApplicationName )) {
if (ARGUMENT_PRESENT( VariableName )) {
if (ARGUMENT_PRESENT( VariableValue )) {
Operation = WriteKeyValue;
} else {
Operation = DeleteKey;
}
} else {
if (ARGUMENT_PRESENT( VariableValue )) {
Operation = WriteSection;
MultiValueStrings = TRUE;
} else {
Operation = DeleteSection;
}
}
} else {
#if DBG
if (ARGUMENT_PRESENT( VariableName ) ||
ARGUMENT_PRESENT( VariableValue )
) {
return STATUS_INVALID_PARAMETER;
} else
#endif
if (ARGUMENT_PRESENT( FileName )) {
Operation = RefreshIniFileMapping;
} else {
Operation = FlushProfiles;
}
}
} else {
if (ARGUMENT_PRESENT( ApplicationName )) {
if (!ARGUMENT_PRESENT( VariableValue )) {
return STATUS_INVALID_PARAMETER;
} else
if (ARGUMENT_PRESENT( VariableName )) {
Operation = ReadKeyValue;
} else
if (SectionOperation) {
Operation = ReadSection;
MultiValueStrings = TRUE;
} else {
Operation = ReadKeyNames;
MultiValueStrings = TRUE;
}
} else
if (SectionOperation || !ARGUMENT_PRESENT( VariableValue )) {
return STATUS_INVALID_PARAMETER;
} else {
VariableName = NULL;
Operation = ReadSectionNames;
MultiValueStrings = TRUE;
}
}
#if DBG
if (WriteOperation) {
ASSERT( Operation == WriteKeyValue || Operation == WriteSection || Operation == DeleteKey || Operation == DeleteSection || Operation == FlushProfiles || Operation == RefreshIniFileMapping );
} else {
ASSERT( Operation == ReadKeyValue || Operation == ReadKeyNames || Operation == ReadSectionNames || Operation == ReadSection );
}
#endif
Status = BaseDllCaptureIniFileParameters( Unicode,
Operation,
WriteOperation,
MultiValueStrings,
FileName,
ApplicationName,
VariableName,
VariableValue,
VariableValueLength,
&a
);
if (!NT_SUCCESS( Status )) {
return Status;
}
#if DBG
if (BaseDllDumpIniCalls) {
DbgPrint( "BASEDLL: called with profile operation\n" );
DbgPrint( " Operation: %s Write: %u\n", xOperationNames[ a->Operation ], a->WriteOperation );
DbgPrint( " BaseFileName: %wZ\n", &a->BaseFileName );
DbgPrint( " IniFileNameMapping: %08x\n", a->IniFileNameMapping );
DbgPrint( " FileName: %wZ\n", &a->FileName );
DbgPrint( " NtFileName: %wZ\n", &a->NtFileName );
DbgPrint( " ApplicationName: %wZ (%Z)\n", &a->ApplicationNameU, &a->ApplicationName );
DbgPrint( " VariableName: %wZ (%Z)\n", &a->VariableNameU, &a->VariableName );
if (a->WriteOperation) {
DbgPrint( " VariableValue: %ws (%s)\n", a->ValueBufferU, a->ValueBuffer );
}
}
#endif // DBG
if (a->Operation == RefreshIniFileMapping) {
#if defined(BUILD_WOW6432)
Status = CsrBasepRefreshIniFileMapping(&a->BaseFileName);
#else
BASE_API_MSG m;
PBASE_REFRESHINIFILEMAPPING_MSG ap = &m.u.RefreshIniFileMapping;
PCSR_CAPTURE_HEADER CaptureBuffer;
CaptureBuffer = NULL;
if (a->BaseFileName.Length > (MAX_PATH * sizeof( WCHAR ))) {
Status = STATUS_INVALID_PARAMETER;
} else {
CaptureBuffer = CsrAllocateCaptureBuffer( 1,
a->BaseFileName.MaximumLength
);
if (CaptureBuffer == NULL) {
Status = STATUS_NO_MEMORY;
} else {
CsrCaptureMessageString( CaptureBuffer,
(PCHAR)a->BaseFileName.Buffer,
a->BaseFileName.Length,
a->BaseFileName.MaximumLength,
(PSTRING)&ap->IniFileName
);
Status = STATUS_SUCCESS;
}
}
if (NT_SUCCESS( Status )) {
CsrClientCallServer( (PCSR_API_MSG)&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
BasepRefreshIniFileMapping
),
sizeof( *ap )
);
Status = (NTSTATUS)m.ReturnValue;
}
CsrFreeCaptureBuffer( CaptureBuffer );
#endif
} else
if (a->IniFileNameMapping != NULL) {
Status = BaseDllReadWriteIniFileViaMapping( a );
#if DBG
if (BaseDllDumpIniCalls) {
if (NT_SUCCESS( Status ) ||
Status == STATUS_BUFFER_OVERFLOW ||
Status == STATUS_MORE_PROCESSING_REQUIRED
) {
if (!a->WriteOperation) {
if (a->Unicode) {
if (a->Operation == ReadKeyValue) {
DbgPrint( "BASEDLL: Returning value from registry - '%.*ws' (%u)\n", a->ResultChars, a->ResultBufferU, a->ResultChars );
} else {
PWSTR s;
DbgPrint( "BASEDLL: Return multi-value from registry: (%u)\n", a->ResultChars );
s = a->ResultBufferU;
s[ a->ResultChars ] = UNICODE_NULL;
while (*s) {
DbgPrint( " %ws\n", s );
while (*s++) {
}
}
}
} else {
if (a->Operation == ReadKeyValue) {
DbgPrint( "BASEDLL: Returning value from registry - '%.*s' (%u)\n", a->ResultChars, a->ResultBuffer, a->ResultChars );
} else {
PBYTE s;
DbgPrint( "BASEDLL: Return multi-value from registry: (%u)\n", a->ResultChars );
s = a->ResultBuffer;
s[ a->ResultChars ] = '\0';
while (*s) {
DbgPrint( " (%s)\n", s );
while (*s++) {
}
}
}
}
} else {
DbgPrint( "BASEDLL: Returning success for above write operation\n" );
}
if (Status == STATUS_BUFFER_OVERFLOW) {
DbgPrint( " *** above result partial as buffer too small.\n" );
} else
if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
DbgPrint( " *** above result partial and will now look on disk.\n" );
}
} else {
DbgPrint( "BASEDLL: Profile operation %s failed: Status == %x\n", xOperationNames[ a->Operation ], Status );
}
if (a->ValueBufferAllocated) {
if (a->Unicode) {
PWSTR s;
DbgPrint( "BASEDLL: Remaining Variables to write to disk:\n" );
s = a->ValueBufferU;
while (*s) {
DbgPrint( " %ws\n", s );
while (*s++) {
}
}
} else {
PBYTE s;
DbgPrint( "BASEDLL: Remaining Variables to write to disk:\n" );
s = a->ValueBuffer;
while (*s) {
DbgPrint( " (%s)\n", s );
while (*s++) {
}
}
}
}
}
#endif // DBG
} else {
Status = STATUS_MORE_PROCESSING_REQUIRED;
}
if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
Status = BaseDllReadWriteIniFileOnDisk( a );
#if DBG
if (BaseDllDumpIniCalls) {
if (NT_SUCCESS( Status ) ||
Status == STATUS_BUFFER_OVERFLOW
) {
if (!a->WriteOperation) {
if (a->Unicode) {
if (a->Operation == ReadKeyValue) {
DbgPrint( "BASEDLL: Returning value from disk - '%.*ws' (%u)\n", a->ResultChars, a->ResultBufferU, a->ResultChars );
} else {
PWSTR s;
DbgPrint( "BASEDLL: Return multi-value from disk: (%u)\n", a->ResultChars );
s = a->ResultBufferU;
s[ a->ResultChars ] = UNICODE_NULL;
while (*s) {
DbgPrint( " %ws\n", s );
while (*s++) {
}
}
}
} else {
if (a->Operation == ReadKeyValue) {
DbgPrint( "BASEDLL: Returning value from disk - '%.*s' (%u)\n", a->ResultChars, a->ResultBuffer, a->ResultChars );
} else {
PBYTE s;
DbgPrint( "BASEDLL: Return multi-value from disk: (%u)\n", a->ResultChars );
s = a->ResultBuffer;
s[ a->ResultChars ] = '\0';
while (*s) {
DbgPrint( " (%s)\n", s );
while (*s++) {
}
}
}
}
if (Status == STATUS_BUFFER_OVERFLOW) {
DbgPrint( " *** above result partial as buffer too small.\n" );
}
} else {
DbgPrint( "BASEDLL: Returning success for above write operation.\n" );
}
} else {
DbgPrint( "BASEDLL: Profile operation %s failed: Status == %x\n", xOperationNames[ a->Operation ], Status );
}
}
#endif // DBG
}
if (BaseRunningInServerProcess || a->Operation == FlushProfiles) {
BaseDllFlushRegistryCache();
}
if (NT_SUCCESS( Status )) {
if (a->Operation == ReadSectionNames ||
a->Operation == ReadKeyNames ||
a->Operation == ReadSection
) {
Status = BaseDllAppendNullToResultBuffer( a );
}
}
if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
if (a->WriteOperation) {
BaseIniFileUpdateCount++;
} else
if (ARGUMENT_PRESENT( VariableValueLength )) {
*VariableValueLength = a->ResultChars;
}
}
if (a->ValueBufferAllocated) {
if (a->Unicode) {
RtlFreeHeap( RtlProcessHeap(), 0, a->ValueBufferU );
} else {
RtlFreeHeap( RtlProcessHeap(), 0, a->ValueBuffer );
}
}
RtlFreeHeap( RtlProcessHeap(), 0, a );
return Status;
}
ULONG
BaseDllIniFileNameLength(
IN BOOLEAN Unicode,
IN PVOID *Name
);
NTSTATUS
BaseDllFindIniFileNameMapping(
IN PUNICODE_STRING FileName,
IN PUNICODE_STRING BaseFileName,
OUT PINIFILE_MAPPING_FILENAME *ReturnedFileNameMapping
);
BOOLEAN
BaseDllGetApplicationName(
IN PINIFILE_PARAMETERS a,
OUT PANSI_STRING *ApplicationName OPTIONAL,
OUT PUNICODE_STRING *ApplicationNameU OPTIONAL
);
BOOLEAN
BaseDllGetVariableName(
IN PINIFILE_PARAMETERS a,
OUT PANSI_STRING *VariableName OPTIONAL,
OUT PUNICODE_STRING *VariableNameU OPTIONAL
);
BOOLEAN
BaseDllGetVariableValue(
IN PINIFILE_PARAMETERS a,
OUT PBYTE *VariableValue OPTIONAL,
OUT PWSTR *VariableValueU OPTIONAL,
OUT PULONG VariableValueLength
);
NTSTATUS
BaseDllCaptureIniFileParameters(
BOOLEAN Unicode,
INIFILE_OPERATION Operation,
BOOLEAN WriteOperation,
BOOLEAN MultiValueStrings,
PVOID FileName OPTIONAL,
PVOID ApplicationName OPTIONAL,
PVOID VariableName OPTIONAL,
PVOID VariableValue OPTIONAL,
PULONG ResultMaxChars OPTIONAL,
PINIFILE_PARAMETERS *ReturnedParameterBlock
)
{
NTSTATUS Status;
PBYTE s;
PWSTR p, p1;
ULONG TotalSize,
CharSize,
NtFileNameLength,
FileNameLength,
ApplicationNameLength,
VariableNameLength,
VariableValueLength;
ANSI_STRING AnsiString;
PINIFILE_PARAMETERS a;
if (ARGUMENT_PRESENT( FileName )) {
if (Unicode) {
FileNameLength = wcslen( FileName );
} else {
FileNameLength = strlen( FileName );
}
} else {
FileNameLength = 0;
}
if (ARGUMENT_PRESENT( ApplicationName )) {
ApplicationNameLength = BaseDllIniFileNameLength( Unicode, &ApplicationName );
} else {
ApplicationNameLength = 0;
VariableName = NULL;
}
if (ARGUMENT_PRESENT( VariableName )) {
VariableNameLength = BaseDllIniFileNameLength( Unicode, &VariableName );
} else {
VariableNameLength = 0;
}
if (ARGUMENT_PRESENT( VariableValue )) {
if (ARGUMENT_PRESENT( ResultMaxChars )) {
VariableValueLength = 0;
} else {
if (!MultiValueStrings) {
if (Unicode) {
VariableValueLength = wcslen( VariableValue );
} else {
VariableValueLength = strlen( VariableValue );
}
} else {
if (Unicode) {
p = (PWSTR)VariableValue;
while (*p) {
while (*p++) {
;
}
}
VariableValueLength = (ULONG)(p - (PWSTR)VariableValue);
} else {
s = (PBYTE)VariableValue;
while (*s) {
while (*s++) {
;
}
}
VariableValueLength = (ULONG)(s - (PBYTE)VariableValue);
}
}
}
} else {
VariableValueLength = 0;
}
NtFileNameLength = RtlGetLongestNtPathLength() * sizeof( WCHAR );
TotalSize = sizeof( *a ) + NtFileNameLength;
if (!Unicode) {
TotalSize += (FileNameLength + 1 ) * sizeof( WCHAR );
}
// We have to allocate enough buffer for DBCS string.
CharSize = (Unicode ? sizeof(WORD) : sizeof( WCHAR ));
TotalSize += (ApplicationNameLength + 1 +
VariableNameLength + 1 +
VariableValueLength + 1
) * CharSize;
a = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), TotalSize );
if (a == NULL) {
KdPrint(( "BASE: Unable to allocate IniFile parameter buffer of %u bytes\n", TotalSize ));
return STATUS_NO_MEMORY;
}
a->Operation = Operation;
a->WriteOperation = WriteOperation;
a->Unicode = Unicode;
a->IniFile = NULL;
a->ValueBufferAllocated = FALSE;
a->MultiValueStrings = MultiValueStrings;
p = (PWSTR)(a + 1);
a->NtFileName.Buffer = p;
a->NtFileName.Length = 0;
a->NtFileName.MaximumLength = (USHORT)NtFileNameLength;
p = (PWSTR)((PCHAR)p + NtFileNameLength);
if (ARGUMENT_PRESENT( FileName )) {
a->FileName.MaximumLength = (USHORT)((FileNameLength + 1) * sizeof( UNICODE_NULL ));
if (Unicode) {
a->FileName.Length = (USHORT)(FileNameLength * sizeof( WCHAR ));
a->FileName.Buffer = FileName;
} else {
AnsiString.Buffer = FileName;
AnsiString.Length = (USHORT)FileNameLength;
AnsiString.MaximumLength = (USHORT)(AnsiString.Length + 1);
a->FileName.Buffer = p;
a->FileName.Length = 0;
p += FileNameLength + 1;
Status = Basep8BitStringToUnicodeString( &a->FileName, &AnsiString, FALSE );
if (!NT_SUCCESS( Status )) {
RtlFreeHeap( RtlProcessHeap(), 0, a );
return Status;
}
}
a->BaseFileName.Length = 0;
p1 = a->FileName.Buffer + FileNameLength;
if (FileNameLength != 0) {
while (--p1 > a->FileName.Buffer) {
if (*p1 == OBJ_NAME_PATH_SEPARATOR ||
*p1 == L'/' ||
*p1 == L':'
) {
p1++;
break;
}
}
}
a->BaseFileName.Buffer = p1;
a->BaseFileName.Length = (USHORT)((FileNameLength - (p1 - a->FileName.Buffer)) * sizeof( WCHAR ));
a->BaseFileName.MaximumLength = (USHORT)(a->BaseFileName.Length + sizeof( UNICODE_NULL ));
BaseDllFindIniFileNameMapping( &a->FileName,
&a->BaseFileName,
&a->IniFileNameMapping
);
} else {
RtlInitUnicodeString( &a->FileName, L"win.ini" );
a->BaseFileName = a->FileName;
a->IniFileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->WinIniFileMapping;
}
if (ARGUMENT_PRESENT( ApplicationName )) {
// We have to keep enough buffer for DBCS string.
a->ApplicationName.MaximumLength = (USHORT)((ApplicationNameLength * sizeof(WORD)) + 1);
a->ApplicationNameU.MaximumLength = (USHORT)(a->ApplicationName.MaximumLength * sizeof( UNICODE_NULL ));
if (Unicode) {
a->ApplicationNameU.Buffer = ApplicationName;
a->ApplicationNameU.Length = (USHORT)(ApplicationNameLength * sizeof( UNICODE_NULL ));
a->ApplicationName.Buffer = (PBYTE)p;
a->ApplicationName.Length = 0;
p = (PWSTR)((PCHAR)p + (ApplicationNameLength * sizeof(WORD)) + 1);
} else {
a->ApplicationName.Buffer = ApplicationName;
a->ApplicationName.Length = (USHORT)ApplicationNameLength;
a->ApplicationNameU.Buffer = p;
a->ApplicationNameU.Length = 0;
p += ApplicationNameLength + 1;
}
} else {
RtlInitAnsiString( &a->ApplicationName, NULL );
RtlInitUnicodeString( &a->ApplicationNameU, NULL );
}
if (ARGUMENT_PRESENT( VariableName )) {
// We have to keep enough buffer for DBCS string.
a->VariableName.MaximumLength = (USHORT)((VariableNameLength *sizeof(WORD)) + 1);
a->VariableNameU.MaximumLength = (USHORT)(a->VariableName.MaximumLength * sizeof( UNICODE_NULL ));
if (Unicode) {
a->VariableNameU.Buffer = VariableName;
a->VariableNameU.Length = (USHORT)(VariableNameLength * sizeof( UNICODE_NULL ));
a->VariableName.Buffer = (PBYTE)p;
a->VariableName.Length = 0;
p = (PWSTR)((PCHAR)p + (VariableNameLength * sizeof(WORD)) + 1);
} else {
a->VariableName.Buffer = VariableName;
a->VariableName.Length = (USHORT)VariableNameLength;
a->VariableNameU.Buffer = p;
a->VariableNameU.Length = 0;
p += VariableNameLength + 1;
}
} else {
RtlInitAnsiString( &a->VariableName, NULL );
RtlInitUnicodeString( &a->VariableNameU, NULL );
}
if (ARGUMENT_PRESENT( VariableValue )) {
if (a->WriteOperation) {
if (Unicode) {
a->ValueBufferU = VariableValue;
a->ValueLengthU = VariableValueLength * sizeof( WCHAR );
*(PBYTE)p = '\0';
a->ValueBuffer = (PBYTE)p;
a->ValueLength = 0;
} else {
a->ValueBuffer = VariableValue;
a->ValueLength = VariableValueLength;
*p = UNICODE_NULL;
a->ValueBufferU = p;
a->ValueLengthU = 0;
}
} else {
if (ARGUMENT_PRESENT( ResultMaxChars )) {
a->ResultMaxChars = *ResultMaxChars;
} else {
a->ResultMaxChars = 0;
}
a->ResultChars = 0;
if (Unicode) {
a->ResultBufferU = VariableValue;
a->ResultBuffer = NULL;
} else {
a->ResultBuffer = VariableValue;
a->ResultBufferU = NULL;
}
}
} else {
if (a->WriteOperation) {
a->ValueBuffer = NULL;
a->ValueLength = 0;
a->ValueBufferU = NULL;
a->ValueLengthU = 0;
} else {
a->ResultMaxChars = 0;
a->ResultChars = 0;
a->ResultBufferU = NULL;
a->ResultBuffer = NULL;
}
}
*ReturnedParameterBlock = a;
return STATUS_SUCCESS;
}
BOOLEAN
BaseDllGetApplicationName(
IN PINIFILE_PARAMETERS a,
OUT PANSI_STRING *ApplicationName OPTIONAL,
OUT PUNICODE_STRING *ApplicationNameU OPTIONAL
)
{
NTSTATUS Status;
if (ARGUMENT_PRESENT( ApplicationName )) {
if (a->ApplicationName.Length == 0) {
Status = RtlUnicodeStringToAnsiString( &a->ApplicationName, &a->ApplicationNameU, FALSE );
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", &a->ApplicationNameU, Status ));
return FALSE;
}
}
*ApplicationName = &a->ApplicationName;
return TRUE;
}
if (ARGUMENT_PRESENT( ApplicationNameU )) {
if (a->ApplicationNameU.Length == 0) {
Status = RtlAnsiStringToUnicodeString( &a->ApplicationNameU, &a->ApplicationName, FALSE );
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: AnsiToUnicode of %Z failed (%08x)\n", &a->ApplicationName, Status ));
return FALSE;
}
}
*ApplicationNameU = &a->ApplicationNameU;
return TRUE;
}
return FALSE;
}
BOOLEAN
BaseDllGetVariableName(
IN PINIFILE_PARAMETERS a,
OUT PANSI_STRING *VariableName OPTIONAL,
OUT PUNICODE_STRING *VariableNameU OPTIONAL
)
{
NTSTATUS Status;
if (ARGUMENT_PRESENT( VariableName )) {
if (a->VariableName.Length == 0) {
Status = RtlUnicodeStringToAnsiString( &a->VariableName, &a->VariableNameU, FALSE );
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", &a->VariableNameU, Status ));
return FALSE;
}
}
*VariableName = &a->VariableName;
return TRUE;
}
if (ARGUMENT_PRESENT( VariableNameU )) {
if (a->VariableNameU.Length == 0) {
Status = RtlAnsiStringToUnicodeString( &a->VariableNameU, &a->VariableName, FALSE );
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: AnsiToUnicode of %Z failed (%08x)\n", &a->VariableName, Status ));
return FALSE;
}
}
*VariableNameU = &a->VariableNameU;
return TRUE;
}
return FALSE;
}
BOOLEAN
BaseDllGetVariableValue(
IN PINIFILE_PARAMETERS a,
OUT PBYTE *VariableValue OPTIONAL,
OUT PWSTR *VariableValueU OPTIONAL,
OUT PULONG VariableValueLength
)
{
NTSTATUS Status;
ULONG Index;
if (ARGUMENT_PRESENT( VariableValue )) {
if (a->ValueLength == 0) {
if (a->ValueBufferU == NULL || a->ValueLengthU == 0) {
*VariableValue = "";
*VariableValueLength = 1;
return TRUE;
}
a->ValueLength = a->ValueLengthU;
Status = RtlUnicodeToMultiByteN( a->ValueBuffer,
a->ValueLength,
&Index,
a->ValueBufferU,
a->ValueLengthU
);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: UnicodeToAnsi of %.*ws failed (%08x)\n",
a->ValueLengthU / sizeof( WCHAR ), a->ValueBufferU, Status
));
return FALSE;
}
// Set real converted size
a->ValueLength = Index;
a->ValueBuffer[ Index ] = '\0'; // Null terminate converted value
} else {
Index = a->ValueLength;
}
*VariableValue = a->ValueBuffer;
*VariableValueLength = Index + 1;
return TRUE;
}
if (ARGUMENT_PRESENT( VariableValueU )) {
if (a->ValueLengthU == 0) {
if (a->ValueBuffer == NULL || a->ValueLength == 0) {
*VariableValueU = L"";
*VariableValueLength = sizeof( UNICODE_NULL );
return TRUE;
}
a->ValueLengthU = a->ValueLength * sizeof( WCHAR );
Status = RtlMultiByteToUnicodeN( a->ValueBufferU,
a->ValueLengthU,
&Index,
a->ValueBuffer,
a->ValueLength
);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: AnsiToUnicode of %.*s failed (%08x)\n",
a->ValueLength, a->ValueBuffer, Status
));
return FALSE;
}
Index = Index / sizeof( WCHAR );
a->ValueBufferU[ Index ] = UNICODE_NULL; // Null terminate converted value
} else {
Index = a->ValueLengthU / sizeof( WCHAR );
}
*VariableValueU = a->ValueBufferU;
*VariableValueLength = (Index + 1) * sizeof( WCHAR );
return TRUE;
}
return FALSE;
}
NTSTATUS
BaseDllAppendNullToResultBuffer(
IN PINIFILE_PARAMETERS a
)
{
return BaseDllAppendBufferToResultBuffer( a,
NULL,
NULL,
0,
TRUE
);
}
NTSTATUS
BaseDllAppendStringToResultBuffer(
IN PINIFILE_PARAMETERS a,
IN PANSI_STRING String OPTIONAL,
IN PUNICODE_STRING StringU OPTIONAL,
IN BOOLEAN IncludeNull
)
{
if (ARGUMENT_PRESENT( String )) {
if (ARGUMENT_PRESENT( StringU )) {
return STATUS_INVALID_PARAMETER;
} else {
return BaseDllAppendBufferToResultBuffer( a,
String->Buffer,
NULL,
String->Length,
IncludeNull
);
}
} else
if (ARGUMENT_PRESENT( StringU )) {
if (ARGUMENT_PRESENT( String )) {
return STATUS_INVALID_PARAMETER;
} else {
return BaseDllAppendBufferToResultBuffer( a,
NULL,
StringU->Buffer,
StringU->Length / sizeof( WCHAR ),
IncludeNull
);
}
} else {
return STATUS_INVALID_PARAMETER;
}
}
NTSTATUS
BaseDllAppendBufferToResultBuffer(
IN PINIFILE_PARAMETERS a,
IN PBYTE Buffer OPTIONAL,
IN PWSTR BufferU OPTIONAL,
IN ULONG Chars,
IN BOOLEAN IncludeNull
)
{
NTSTATUS Status, OverflowStatus;
ULONG Index;
OverflowStatus = STATUS_SUCCESS;
if (ARGUMENT_PRESENT( Buffer )) {
if (ARGUMENT_PRESENT( BufferU )) {
return STATUS_INVALID_PARAMETER;
} else {
ULONG CharsMbcs = Chars;
//
// In this point, Chars does not contains proper value for Unicode.
// because. Chars was computed based on DBCS string length,
// This is correct, sources string is DBCS, then
// if the source is not DBCS. we just adjust it here.
//
if (a->Unicode) {
Status = RtlMultiByteToUnicodeSize(&Chars,Buffer,Chars);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: AnsiToUnicodeSize of %.*s failed (%08x)\n", Chars, Buffer, Status ));
return Status;
}
Chars /= sizeof(WCHAR);
}
if (a->ResultChars + Chars >= a->ResultMaxChars) {
OverflowStatus = STATUS_BUFFER_OVERFLOW;
Chars = a->ResultMaxChars - a->ResultChars;
if (Chars) {
Chars -= 1;
}
}
if (Chars) {
if (a->Unicode) {
Status = RtlMultiByteToUnicodeN( a->ResultBufferU + a->ResultChars,
Chars * sizeof( WCHAR ),
&Index,
Buffer,
CharsMbcs
);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: AnsiToUnicode of %.*s failed (%08x)\n", Chars, Buffer, Status ));
return Status;
}
} else {
memcpy( a->ResultBuffer + a->ResultChars, Buffer, Chars );
}
a->ResultChars += Chars;
}
}
} else
if (ARGUMENT_PRESENT( BufferU )) {
if (ARGUMENT_PRESENT( Buffer )) {
return STATUS_INVALID_PARAMETER;
} else {
ULONG CharsUnicode = Chars;
//
// In this point, Chars does not contains proper value for DBCS.
// because. Chars was computed by just devide Unicode string length
// by two. This is correct, sources string is Unicode, then
// if the source is not Unicode. we just adjust it here.
//
if (!(a->Unicode)) {
Status = RtlUnicodeToMultiByteSize(&Chars,BufferU,Chars * sizeof(WCHAR));
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: UnicodeToAnsiSize of %.*ws failed (%08x)\n", Chars, BufferU, Status ));
return Status;
}
}
if (a->ResultChars + Chars >= a->ResultMaxChars) {
OverflowStatus = STATUS_BUFFER_OVERFLOW;
Chars = a->ResultMaxChars - a->ResultChars;
if (Chars) {
Chars -= 1;
}
}
if (Chars) {
if (a->Unicode) {
memcpy( a->ResultBufferU + a->ResultChars, BufferU, Chars * sizeof( WCHAR ) );
} else {
Status = RtlUnicodeToMultiByteN( a->ResultBuffer + a->ResultChars,
Chars,
&Index,
BufferU,
CharsUnicode * sizeof( WCHAR )
);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: UnicodeToAnsi of %.*ws failed (%08x)\n", Chars, BufferU, Status ));
return Status;
}
}
a->ResultChars += Chars;
}
}
}
if (IncludeNull) {
if (a->ResultChars + 1 >= a->ResultMaxChars) {
return STATUS_BUFFER_OVERFLOW;
}
if (a->Unicode) {
a->ResultBufferU[ a->ResultChars ] = UNICODE_NULL;
} else {
a->ResultBuffer[ a->ResultChars ] = '\0';
}
a->ResultChars += 1;
}
return OverflowStatus;
}
ULONG
BaseDllIniFileNameLength(
IN BOOLEAN Unicode,
IN PVOID *Name
)
{
if (Unicode) {
PWSTR p;
p = *Name;
while (*p == L' ') {
p++;
}
*Name = p;
while (*p != UNICODE_NULL) {
p++;
}
if (p > (PWSTR)*Name) {
while (*--p == L' ') {
}
p++;
}
return (ULONG)(p - (PWSTR)*Name);
} else {
PCH p;
p = *Name;
while (*p == ' ') {
p++;
}
*Name = p;
while (*p != '\0') {
p++;
}
if (p > (PCH)*Name) {
while (*--p == ' ') {
}
p++;
}
return (ULONG)(p - (PCH)*Name);
}
}
NTSTATUS
BaseDllFindIniFileNameMapping(
IN PUNICODE_STRING FileName,
IN PUNICODE_STRING BaseFileName,
OUT PINIFILE_MAPPING_FILENAME *ReturnedFileNameMapping
)
{
NTSTATUS Status;
PINIFILE_MAPPING_FILENAME FileNameMapping;
UNICODE_STRING WinIniString;
WCHAR TermSrvWindowsPath[MAX_PATH+1];
UNICODE_STRING TermsrvWindowsDir;
Status = STATUS_OBJECT_NAME_NOT_FOUND;
RtlInitUnicodeString(&WinIniString, L"win.ini");
//
// Only look in mapping if
// Unqualified name was specified OR
// Path specified exactly matches the name of the Windows directory OR
// Filename is not win.ini (special hack for Windows Sound System, which
// expects GetPrivateProfileString on C:\SNDSYS\WIN.INI to return the
// data from the file, not the registry)
//
if (gpTermsrvGetWindowsDirectoryW) {
if (gpTermsrvGetWindowsDirectoryW (TermSrvWindowsPath,MAX_PATH)) {
RtlInitUnicodeString(&TermsrvWindowsDir,TermSrvWindowsPath);
} else {
RtlInitUnicodeString(&TermsrvWindowsDir,L"");
}
}
if ((FileName->Buffer == BaseFileName->Buffer) ||
RtlPrefixUnicodeString( &BaseWindowsDirectory, FileName, TRUE ) ||
(!RtlEqualUnicodeString( BaseFileName, &WinIniString, TRUE )) ||
// Also check for in per user's windows directory
(IsTerminalServer() && RtlPrefixUnicodeString( &TermsrvWindowsDir, FileName, TRUE ))) {
FileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->FileNames;
while (FileNameMapping != NULL) {
BASE_READ_REMOTE_STR_TEMP(TempStr);
if (RtlEqualUnicodeString( BaseFileName,
BASE_READ_REMOTE_STR(FileNameMapping->Name, TempStr),
TRUE )) {
Status = STATUS_SUCCESS;
break;
}
FileNameMapping = (PINIFILE_MAPPING_FILENAME)FileNameMapping->Next;
}
if (FileNameMapping == NULL) {
FileNameMapping = (PINIFILE_MAPPING_FILENAME)BaseDllIniFileMapping->DefaultFileNameMapping;
}
*ReturnedFileNameMapping = FileNameMapping;
} else {
*ReturnedFileNameMapping = NULL;
}
return Status;
}
NTSTATUS
BaseDllOpenMappingTarget(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_VARNAME VarNameMapping,
IN PUNICODE_STRING ApplicationName OPTIONAL,
IN BOOLEAN WriteAccess,
OUT PHANDLE Key
);
PINIFILE_MAPPING_APPNAME
BaseDllFindAppNameMapping(
IN PINIFILE_MAPPING_FILENAME FileNameMapping,
IN PUNICODE_STRING ApplicationName
);
PINIFILE_MAPPING_VARNAME
BaseDllFindVarNameMapping(
IN PINIFILE_MAPPING_APPNAME AppNameMapping,
IN PUNICODE_STRING VariableName
);
NTSTATUS
BaseDllReadApplicationNames(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllCheckKeyNotEmpty(
IN HANDLE Key,
IN PUNICODE_STRING SubKeyName
);
NTSTATUS
BaseDllReadVariableNames(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
);
NTSTATUS
BaseDllReadVariableValue(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping,
IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
IN PUNICODE_STRING VariableName OPTIONAL
);
NTSTATUS
BaseDllReadApplicationVariables(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
);
NTSTATUS
BaseDllDeleteApplicationVariables(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
);
NTSTATUS
BaseDllWriteApplicationVariables(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
);
NTSTATUS
BaseDllWriteVariableValue(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping,
IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
IN PUNICODE_STRING VariableName OPTIONAL
);
NTSTATUS
BaseDllReadWriteIniFileViaMapping(
IN PINIFILE_PARAMETERS a
)
{
PINIFILE_MAPPING_APPNAME AppNameMapping;
PUNICODE_STRING ApplicationNameU;
if (a->Operation == FlushProfiles) {
return STATUS_SUCCESS;
} else
if (a->Operation == ReadSectionNames) {
return BaseDllReadApplicationNames( a );
} else
if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
return STATUS_INVALID_PARAMETER;
}
AppNameMapping = BaseDllFindAppNameMapping( a->IniFileNameMapping, ApplicationNameU );
if (AppNameMapping == NULL) {
return STATUS_MORE_PROCESSING_REQUIRED;
} else
if (a->Operation == ReadKeyValue) {
return BaseDllReadVariableValue( a, AppNameMapping, NULL, NULL );
} else
if (a->Operation == ReadKeyNames) {
return BaseDllReadVariableNames( a, AppNameMapping );
} else
if (a->Operation == ReadSection) {
return BaseDllReadApplicationVariables( a, AppNameMapping );
} else
if (a->Operation == WriteKeyValue || a->Operation == DeleteKey) {
return BaseDllWriteVariableValue( a, AppNameMapping, NULL, NULL );
} else
if (a->Operation == WriteSection || a->Operation == DeleteSection) {
return BaseDllWriteApplicationVariables( a, AppNameMapping );
}
return STATUS_INVALID_PARAMETER;
}
VOID
BaseDllFlushRegistryCache( VOID )
{
RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
BaseDllRegistryCache.MappingTarget = NULL;
BaseDllRegistryCache.MappingFlags = 0;
if (BaseDllRegistryCache.RegistryPath.Buffer != NULL) {
RtlFreeHeap( RtlProcessHeap(), 0, BaseDllRegistryCache.RegistryPath.Buffer );
RtlZeroMemory( &BaseDllRegistryCache.RegistryPath,
sizeof( BaseDllRegistryCache.RegistryPath )
);
}
if (BaseDllRegistryCache.RegistryKey != INVALID_HANDLE_VALUE) {
NtClose( BaseDllRegistryCache.RegistryKey );
BaseDllRegistryCache.RegistryKey = INVALID_HANDLE_VALUE;
}
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
return;
}
NTSTATUS
BaseDllOpenMappingTarget(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_VARNAME VarNameMapping,
IN PUNICODE_STRING ApplicationName OPTIONAL,
IN BOOLEAN WriteAccess,
OUT PHANDLE Key
)
{
NTSTATUS Status;
PINIFILE_MAPPING_TARGET MappingTarget;
ULONG MappingFlags;
BOOLEAN AppendApplicationName;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG CreateDisposition;
PUNICODE_STRING RegistryPathPrefix;
UNICODE_STRING RegistryPath;
KEY_BASIC_INFORMATION KeyBasicInfo;
ULONG ResultLength;
ULONG n;
BOOLEAN OperationRetried = FALSE;
BASE_READ_REMOTE_STR_TEMP(TempStr);
*Key = INVALID_HANDLE_VALUE;
MappingTarget = (PINIFILE_MAPPING_TARGET)VarNameMapping->MappingTarget;
MappingFlags = VarNameMapping->MappingFlags & (INIFILE_MAPPING_APPEND_BASE_NAME |
INIFILE_MAPPING_APPEND_APPLICATION_NAME |
INIFILE_MAPPING_SOFTWARE_RELATIVE |
INIFILE_MAPPING_USER_RELATIVE
);
if (MappingTarget == NULL || MappingTarget->RegistryPath.Length == 0) {
return STATUS_SUCCESS;
}
if (ARGUMENT_PRESENT( ApplicationName ) &&
(MappingFlags & INIFILE_MAPPING_APPEND_APPLICATION_NAME)
) {
AppendApplicationName = TRUE;
} else {
AppendApplicationName = FALSE;
}
RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
if (MappingFlags & INIFILE_MAPPING_USER_RELATIVE) {
if (!BaseRunningInServerProcess && BaseDllIniUserKeyPath.Length == 0) {
OpenProfileUserMapping();
}
if (BaseDllIniUserKeyPath.Length == 0) {
KdPrint(( "BASE: Attempt to access user profile specific portion of .INI file.\n" ));
KdPrint(( " when there is no current user defined.\n" ));
KdPrint(( " Path: %wZ\n",
&MappingTarget->RegistryPath
));
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
return STATUS_ACCESS_DENIED;
}
RegistryPathPrefix = &BaseDllIniUserKeyPath;
} else
if (MappingFlags & INIFILE_MAPPING_SOFTWARE_RELATIVE) {
RegistryPathPrefix = &BaseDllIniSoftwareKeyPath;
} else {
RegistryPathPrefix = NULL;
}
if (RegistryPathPrefix != NULL) {
n = RegistryPathPrefix->Length + sizeof( WCHAR );
} else {
n = 0;
}
n += sizeof( WCHAR ) + MappingTarget->RegistryPath.Length;
if (MappingFlags & INIFILE_MAPPING_APPEND_BASE_NAME) {
n += sizeof( WCHAR ) + a->BaseFileName.Length;
}
if (AppendApplicationName) {
n += sizeof( WCHAR ) + ApplicationName->Length;
}
n += sizeof( UNICODE_NULL );
RegistryPath.Buffer = RtlAllocateHeap( RtlProcessHeap(), 0, n );
if (RegistryPath.Buffer == NULL) {
KdPrint(( "BASE: Unable to allocate registry path buffer of %u bytes\n", n ));
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
return STATUS_NO_MEMORY;
}
RegistryPath.Length = 0;
RegistryPath.MaximumLength = (USHORT)n;
if (RegistryPathPrefix != NULL) {
RtlAppendUnicodeStringToString( &RegistryPath, RegistryPathPrefix );
RtlAppendUnicodeToString( &RegistryPath, L"\\" );
}
RtlAppendUnicodeStringToString( &RegistryPath,
BASE_READ_REMOTE_STR(MappingTarget->RegistryPath, TempStr)
);
if (MappingFlags & INIFILE_MAPPING_APPEND_BASE_NAME) {
RtlAppendUnicodeToString( &RegistryPath, L"\\" );
RtlAppendUnicodeStringToString( &RegistryPath, &a->BaseFileName );
}
if (AppendApplicationName) {
RtlAppendUnicodeToString( &RegistryPath, L"\\" );
RtlAppendUnicodeStringToString( &RegistryPath, ApplicationName );
}
if (BaseDllRegistryCache.RegistryKey != INVALID_HANDLE_VALUE &&
BaseDllRegistryCache.MappingTarget == MappingTarget &&
BaseDllRegistryCache.MappingFlags == MappingFlags &&
BaseDllRegistryCache.WriteAccess == WriteAccess &&
RtlEqualUnicodeString( &BaseDllRegistryCache.RegistryPath, &RegistryPath, TRUE )
) {
Status = NtQueryKey( BaseDllRegistryCache.RegistryKey,
KeyBasicInformation,
&KeyBasicInfo,
sizeof( KeyBasicInfo ),
&ResultLength
);
if (Status != STATUS_KEY_DELETED) {
RtlFreeHeap( RtlProcessHeap(), 0, RegistryPath.Buffer );
*Key = BaseDllRegistryCache.RegistryKey;
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
return STATUS_SUCCESS;
}
}
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
BaseDllFlushRegistryCache();
InitializeObjectAttributes( &ObjectAttributes,
&RegistryPath,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
NULL,
NULL
);
if (WriteAccess) {
repeatoperation:
Status = NtCreateKey( Key,
STANDARD_RIGHTS_WRITE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY,
&ObjectAttributes,
0,
NULL,
0,
&CreateDisposition
);
//
// There are cases where dorks delete the virtual ini file in the
// registry. To handle this, if we get object path not found, attempt
// to create the containing key and then repeat the operation
//
if ( Status == STATUS_OBJECT_NAME_NOT_FOUND && OperationRetried == FALSE ) {
NTSTATUS RetryStatus;
OBJECT_ATTRIBUTES RetryObjectAttributes;
ULONG RetryCreateDisposition;
UNICODE_STRING RetryRegistryPath;
HANDLE RetryKey;
RetryRegistryPath = RegistryPath;
while ( RetryRegistryPath.Buffer[RetryRegistryPath.Length>>1] != (WCHAR)'\\' ) {
RetryRegistryPath.Length -= sizeof(WCHAR);
}
InitializeObjectAttributes( &RetryObjectAttributes,
&RetryRegistryPath,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
NULL,
NULL
);
RetryStatus = NtCreateKey( &RetryKey,
STANDARD_RIGHTS_WRITE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY,
&RetryObjectAttributes,
0,
NULL,
0,
&RetryCreateDisposition
);
if ( NT_SUCCESS(RetryStatus) ) {
NtClose(RetryKey);
OperationRetried = TRUE;
goto repeatoperation;
}
}
} else {
Status = NtOpenKey( Key,
GENERIC_READ,
&ObjectAttributes
);
}
if (NT_SUCCESS( Status )) {
#if DBG
if (BaseDllDumpIniCalls) {
KdPrint(( "BASEDLL: Opened %wZ\n", &RegistryPath ));
}
#endif
RtlEnterCriticalSection(&BaseDllRegistryCache.Lock);
BaseDllRegistryCache.MappingTarget = MappingTarget;
BaseDllRegistryCache.MappingFlags = MappingFlags;
BaseDllRegistryCache.WriteAccess = WriteAccess;
BaseDllRegistryCache.RegistryPath = RegistryPath;
BaseDllRegistryCache.RegistryKey = *Key;
RtlLeaveCriticalSection(&BaseDllRegistryCache.Lock);
} else {
#if DBG
if (BaseDllDumpIniCalls || WriteAccess || Status != STATUS_OBJECT_NAME_NOT_FOUND) {
DbgPrint( "BASEDLL: Failed to open %wZ for %s - Status == %lx\n",
&RegistryPath,
WriteAccess ? "write" : "read",
Status
);
}
#endif
RtlFreeHeap( RtlProcessHeap(), 0, RegistryPath.Buffer );
}
return Status;
}
PINIFILE_MAPPING_APPNAME
BaseDllFindAppNameMapping(
IN PINIFILE_MAPPING_FILENAME FileNameMapping,
IN PUNICODE_STRING ApplicationName
)
{
PINIFILE_MAPPING_APPNAME AppNameMapping;
BASE_READ_REMOTE_STR_TEMP(TempStr);
AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->ApplicationNames;
while (AppNameMapping != NULL) {
if (RtlEqualUnicodeString( BASE_READ_REMOTE_STR(AppNameMapping->Name, TempStr),
ApplicationName,
TRUE )) {
return AppNameMapping;
}
AppNameMapping = (PINIFILE_MAPPING_APPNAME)AppNameMapping->Next;
}
return (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
}
PINIFILE_MAPPING_VARNAME
BaseDllFindVarNameMapping(
IN PINIFILE_MAPPING_APPNAME AppNameMapping,
IN PUNICODE_STRING VariableName
)
{
PINIFILE_MAPPING_VARNAME VarNameMapping;
BASE_READ_REMOTE_STR_TEMP(TempStr);
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
while (VarNameMapping != NULL) {
if (RtlEqualUnicodeString( BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr),
VariableName,
TRUE )) {
return VarNameMapping;
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
}
return (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
}
NTSTATUS
BaseDllReadApplicationNames(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
PINIFILE_MAPPING_APPNAME AppNameMapping;
HANDLE Key;
WCHAR Buffer[ 256 ];
PKEY_BASIC_INFORMATION KeyInformation;
ULONG SubKeyIndex;
ULONG ResultLength;
UNICODE_STRING SubKeyName;
BASE_READ_REMOTE_STR_TEMP(TempStr);
AppNameMapping = (PINIFILE_MAPPING_APPNAME)a->IniFileNameMapping->ApplicationNames;
while (AppNameMapping != NULL) {
Status = BaseDllAppendStringToResultBuffer( a,
NULL,
BASE_READ_REMOTE_STR(AppNameMapping->Name,TempStr),
TRUE
);
if (!NT_SUCCESS( Status )) {
return Status;
}
AppNameMapping = (PINIFILE_MAPPING_APPNAME)AppNameMapping->Next;
}
AppNameMapping = (PINIFILE_MAPPING_APPNAME)a->IniFileNameMapping->DefaultAppNameMapping;
if (AppNameMapping == NULL) {
return STATUS_MORE_PROCESSING_REQUIRED;
}
Status = BaseDllOpenMappingTarget( a,
(PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping,
NULL,
FALSE,
&Key
);
if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
return Status;
}
KeyInformation = (PKEY_BASIC_INFORMATION)Buffer;
for (SubKeyIndex = 0; TRUE; SubKeyIndex++) {
Status = NtEnumerateKey( Key,
SubKeyIndex,
KeyBasicInformation,
KeyInformation,
sizeof( Buffer ),
&ResultLength
);
if (Status == STATUS_NO_MORE_ENTRIES) {
break;
}
if (NT_SUCCESS( Status )) {
SubKeyName.Buffer = (PWSTR)&(KeyInformation->Name[0]);
SubKeyName.Length = (USHORT)KeyInformation->NameLength;
SubKeyName.MaximumLength = (USHORT)KeyInformation->NameLength;
Status = BaseDllCheckKeyNotEmpty( Key,
&SubKeyName
);
if (NT_SUCCESS( Status ) ) {
Status = BaseDllAppendStringToResultBuffer( a, NULL, &SubKeyName, TRUE );
} else
if (Status != STATUS_NO_MORE_ENTRIES) {
break;
} else {
Status = STATUS_SUCCESS;
}
}
if (!NT_SUCCESS( Status )) {
return Status;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
BaseDllCheckKeyNotEmpty(
IN HANDLE Key,
IN PUNICODE_STRING SubKeyName
)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE SubKey;
KEY_VALUE_BASIC_INFORMATION KeyValueInformation;
ULONG ResultLength;
InitializeObjectAttributes( &ObjectAttributes,
SubKeyName,
OBJ_CASE_INSENSITIVE,
Key,
NULL
);
Status = NtOpenKey( &SubKey,
GENERIC_READ,
&ObjectAttributes
);
if ( !NT_SUCCESS(Status) ) {
return Status;
}
Status = NtEnumerateValueKey( SubKey,
0,
KeyValueBasicInformation,
&KeyValueInformation,
sizeof( KeyValueInformation ),
&ResultLength
);
if (Status == STATUS_BUFFER_OVERFLOW) {
Status = STATUS_SUCCESS;
}
NtClose( SubKey );
return Status;
}
NTSTATUS
BaseDllReadVariableNames(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
)
{
NTSTATUS Status;
PINIFILE_MAPPING_VARNAME VarNameMapping;
PUNICODE_STRING ApplicationNameU;
WCHAR Buffer[ 256 ];
PKEY_VALUE_BASIC_INFORMATION KeyValueInformation;
ULONG ValueIndex;
ULONG ResultLength;
UNICODE_STRING VariableName;
HANDLE Key;
BASE_READ_REMOTE_STR_TEMP(TempStr);
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
while (VarNameMapping != NULL) {
Status = BaseDllAppendStringToResultBuffer( a,
NULL,
BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr),
TRUE
);
if (!NT_SUCCESS( Status )) {
return Status;
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
if (VarNameMapping == NULL) {
return STATUS_MORE_PROCESSING_REQUIRED;
}
if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
return STATUS_INVALID_PARAMETER;
}
Status = BaseDllOpenMappingTarget( a,
VarNameMapping,
ApplicationNameU,
FALSE,
&Key
);
if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
return Status;
}
KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
for (ValueIndex = 0; TRUE; ValueIndex++) {
Status = NtEnumerateValueKey( Key,
ValueIndex,
KeyValueBasicInformation,
KeyValueInformation,
sizeof( Buffer ),
&ResultLength
);
if (Status == STATUS_NO_MORE_ENTRIES) {
break;
} else
if (!NT_SUCCESS( Status )) {
return Status;
}
VariableName.Buffer = KeyValueInformation->Name;
VariableName.Length = (USHORT)KeyValueInformation->NameLength;
VariableName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
Status = BaseDllAppendStringToResultBuffer( a, NULL, &VariableName, TRUE );
if (!NT_SUCCESS( Status )) {
return Status;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
BaseDllReadVariableValue(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping,
IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
IN PUNICODE_STRING VariableName OPTIONAL
)
{
NTSTATUS Status;
PUNICODE_STRING ApplicationNameU;
KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
PKEY_VALUE_PARTIAL_INFORMATION p;
ULONG ResultLength;
UNICODE_STRING Value;
BOOLEAN OutputVariableName;
UNICODE_STRING EqualSign;
PWSTR s;
HANDLE Key;
if (ARGUMENT_PRESENT( VariableName )) {
RtlInitUnicodeString( &EqualSign, L"=" );
OutputVariableName = TRUE;
} else {
if (!BaseDllGetVariableName( a, NULL, &VariableName )) {
return STATUS_INVALID_PARAMETER;
}
OutputVariableName = FALSE;
}
if (!ARGUMENT_PRESENT( VarNameMapping )) {
VarNameMapping = BaseDllFindVarNameMapping( AppNameMapping, VariableName );
}
if (VarNameMapping == NULL) {
return STATUS_MORE_PROCESSING_REQUIRED;
}
if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
return STATUS_INVALID_PARAMETER;
}
Status = BaseDllOpenMappingTarget( a,
VarNameMapping,
ApplicationNameU,
FALSE,
&Key
);
if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
return Status;
}
Status = NtQueryValueKey( Key,
VariableName,
KeyValuePartialInformation,
&KeyValueInformation,
sizeof( KeyValueInformation ),
&ResultLength
);
if (!NT_SUCCESS( Status )) {
if (Status != STATUS_BUFFER_OVERFLOW) {
return Status;
}
p = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), ResultLength );
if (p == NULL) {
return STATUS_NO_MEMORY;
}
Status = NtQueryValueKey( Key,
VariableName,
KeyValuePartialInformation,
p,
ResultLength,
&ResultLength
);
} else {
p = &KeyValueInformation;
}
if (NT_SUCCESS( Status )) {
if (p->Type == REG_SZ) {
if (OutputVariableName) {
Status = BaseDllAppendStringToResultBuffer( a, NULL, VariableName, FALSE );
if (NT_SUCCESS( Status )) {
Status = BaseDllAppendStringToResultBuffer( a, NULL, &EqualSign, FALSE );
}
}
if (NT_SUCCESS( Status )) {
Value.Buffer = (PWSTR)&p->Data[ 0 ];
if (p->DataLength < sizeof( UNICODE_NULL )) {
Value.Length = 0;
} else {
Value.Length = (USHORT)(p->DataLength - sizeof( UNICODE_NULL ));
}
Value.MaximumLength = (USHORT)(p->DataLength);
s = (PWSTR)Value.Buffer;
if (a->Operation == ReadKeyValue &&
Value.Length >= (2 * sizeof( WCHAR )) &&
(s[ 0 ] == s[ (Value.Length - sizeof( WCHAR )) / sizeof( WCHAR ) ]) &&
(s[ 0 ] == L'"' || s[ 0 ] == L'\'')
) {
Value.Buffer += 1;
Value.Length -= (2 * sizeof( WCHAR ));
Value.MaximumLength -= (2 * sizeof( WCHAR ));
}
Status = BaseDllAppendStringToResultBuffer( a, NULL, &Value, TRUE );
}
} else {
KdPrint(( "BASE: Registry value %wZ not REG_SZ type (%u)\n", VariableName, p->Type ));
Status = STATUS_OBJECT_TYPE_MISMATCH;
}
}
if (p != &KeyValueInformation) {
RtlFreeHeap( RtlProcessHeap(), 0, p );
}
return Status;
}
NTSTATUS
BaseDllReadApplicationVariables(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
)
{
NTSTATUS Status;
PINIFILE_MAPPING_VARNAME VarNameMapping;
PUNICODE_STRING ApplicationNameU;
WCHAR Buffer[ 256 ];
PKEY_VALUE_BASIC_INFORMATION KeyValueInformation;
ULONG ValueIndex;
ULONG ResultLength;
UNICODE_STRING VariableName;
HANDLE Key;
BASE_READ_REMOTE_STR_TEMP(TempStr);
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
while (VarNameMapping != NULL) {
if (VarNameMapping->Name.Length != 0) {
Status = BaseDllReadVariableValue( a,
AppNameMapping,
VarNameMapping,
BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr)
);
if (!NT_SUCCESS( Status )) {
if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
Status == STATUS_OBJECT_TYPE_MISMATCH
) {
Status = STATUS_SUCCESS;
} else {
return Status;
}
}
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
if (VarNameMapping == NULL) {
return STATUS_MORE_PROCESSING_REQUIRED;
}
if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
return STATUS_INVALID_PARAMETER;
}
Status = BaseDllOpenMappingTarget( a,
VarNameMapping,
ApplicationNameU,
FALSE,
&Key
);
if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
return Status;
}
KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
for (ValueIndex = 0; TRUE; ValueIndex++) {
Status = NtEnumerateValueKey( Key,
ValueIndex,
KeyValueBasicInformation,
KeyValueInformation,
sizeof( Buffer ),
&ResultLength
);
if (Status == STATUS_NO_MORE_ENTRIES) {
break;
} else
if (!NT_SUCCESS( Status )) {
return Status;
}
VariableName.Buffer = KeyValueInformation->Name;
VariableName.Length = (USHORT)KeyValueInformation->NameLength;
VariableName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
Status = BaseDllReadVariableValue( a, AppNameMapping, NULL, &VariableName );
if (!NT_SUCCESS( Status ) &&
Status != STATUS_OBJECT_NAME_NOT_FOUND &&
Status != STATUS_OBJECT_TYPE_MISMATCH
) {
return Status;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
BaseDllDeleteApplicationVariables(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
)
{
NTSTATUS Status;
PINIFILE_MAPPING_VARNAME VarNameMapping;
WCHAR Buffer[ 256 ];
HANDLE Key;
PKEY_VALUE_BASIC_INFORMATION KeyValueInformation;
ULONG ResultLength;
PUNICODE_STRING ApplicationNameU;
UNICODE_STRING VariableName;
BASE_READ_REMOTE_STR_TEMP(TempStr);
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
while (VarNameMapping != NULL) {
if (VarNameMapping->Name.Length != 0) {
Status = BaseDllWriteVariableValue( a,
AppNameMapping,
VarNameMapping,
BASE_READ_REMOTE_STR(VarNameMapping->Name,TempStr)
);
if (!NT_SUCCESS( Status )) {
if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
return Status;
}
}
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
if (VarNameMapping == NULL) {
return STATUS_MORE_PROCESSING_REQUIRED;
}
if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
return STATUS_INVALID_PARAMETER;
}
Status = BaseDllOpenMappingTarget( a,
VarNameMapping,
ApplicationNameU,
TRUE,
&Key
);
if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
return Status;
}
KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer;
do {
//
// Enumerate the 0th key. Since we are deleting as we go
// this will always be a new key until we are out of entries.
//
Status = NtEnumerateValueKey( Key,
0,
KeyValueBasicInformation,
KeyValueInformation,
sizeof( Buffer ),
&ResultLength
);
if (NT_SUCCESS( Status )) {
VariableName.Buffer = KeyValueInformation->Name;
VariableName.Length = (USHORT)KeyValueInformation->NameLength;
VariableName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
Status = NtDeleteValueKey( Key,
&VariableName
);
//
// If we couldn't find VariableName, then somebody must be deleting
// at the same time we are and beat us to it, so we just ignore the error.
//
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
Status = STATUS_SUCCESS;
}
}
} while (NT_SUCCESS( Status ));
if (Status == STATUS_NO_MORE_ENTRIES) {
Status = STATUS_SUCCESS;
}
//
// We can't delete key, as if there are handles open to it,
// future attempts to recreate it will fail.
//
// Status = NtDeleteKey( Key );
//
BaseDllFlushRegistryCache();
return Status;
}
NTSTATUS
BaseDllWriteApplicationVariables(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping
)
{
NTSTATUS Status;
ULONG n;
PVOID SaveValueBuffer, NewValueBuffer, CurrentValueBuffer, CurrentVariableStart, FreeBuffer;
ULONG SaveValueLength, NewValueLength, CurrentValueLength, CurrentVariableLength;
if (a->Operation == DeleteSection) {
return BaseDllDeleteApplicationVariables( a, AppNameMapping );
}
if (a->ValueBuffer != NULL && a->ValueLength != 0) {
SaveValueBuffer = a->ValueBuffer;
SaveValueLength = a->ValueLength;
} else
if (a->ValueBufferU != NULL && a->ValueLengthU != 0) {
SaveValueBuffer = a->ValueBufferU;
SaveValueLength = a->ValueLengthU;
} else {
return STATUS_INVALID_PARAMETER;
}
NewValueBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), SaveValueLength );
if (NewValueBuffer == NULL) {
return STATUS_NO_MEMORY;
}
FreeBuffer = NULL;
try {
RtlMoveMemory( NewValueBuffer, SaveValueBuffer, NewValueLength = SaveValueLength );
CurrentValueBuffer = NewValueBuffer;
CurrentValueLength = NewValueLength;
NewValueLength = 0;
while (CurrentValueLength) {
if (a->Unicode) {
PWSTR s, s1;
s = CurrentValueBuffer;
n = CurrentValueLength / sizeof( WCHAR );
while (n && *s != UNICODE_NULL && *s <= L' ') {
n--;
s++;
}
if (!n || *s == UNICODE_NULL) {
break;
}
CurrentVariableStart = s;
a->VariableNameU.Buffer = s;
while (n && *s != L'=') {
n--;
s++;
}
if (!n) {
break;
}
s1 = s++;
n--;
while (s1 > a->VariableNameU.Buffer) {
if (s1[-1] > L' ') {
break;
}
s1 -= 1;
}
a->VariableNameU.Length = (USHORT)((PCHAR)s1 - (PCHAR)a->VariableNameU.Buffer);
if (a->VariableNameU.Length == 0) {
break;
}
a->VariableNameU.MaximumLength = a->VariableNameU.Length + sizeof( UNICODE_NULL );
while (n && *s == L' ') {
n--;
s++;
}
a->ValueBufferU = s;
while (n && *s != UNICODE_NULL) {
n--;
s++;
}
if (!n) {
break;
}
a->ValueLengthU = (USHORT)((PCHAR)s - (PCHAR)a->ValueBufferU);
n--;
s++;
CurrentVariableLength = (ULONG)((PCHAR)s - (PCHAR)CurrentVariableStart);
CurrentValueBuffer = s;
CurrentValueLength = n * sizeof( WCHAR );
} else {
PBYTE s, s1;
s = CurrentValueBuffer;
n = CurrentValueLength;
while (n && *s != '\0' && *s <= ' ') {
n--;
s++;
}
if (!n || *s == '\0') {
break;
}
CurrentVariableStart = s;
a->VariableName.Buffer = s;
while (n && *s != '=') {
n--;
s++;
}
if (!n) {
break;
}
s1 = s++;
n--;
while (s1 > a->VariableName.Buffer) {
if (s1[-1] > ' ') {
break;
}
s1 -= 1;
}
a->VariableName.Length = (USHORT)(s1 - a->VariableName.Buffer);
if (a->VariableName.Length == 0) {
break;
}
a->VariableName.MaximumLength = a->VariableName.Length + 1;
while (n && *s == ' ') {
n--;
s++;
}
a->ValueBuffer = s;
while (n && *s != '\0') {
n--;
s++;
}
if (!n) {
break;
}
a->ValueLength = (USHORT)(s - a->ValueBuffer);
n--;
s++;
CurrentVariableLength = (ULONG)(s - (PCHAR)CurrentVariableStart);
CurrentValueBuffer = s;
CurrentValueLength = n;
a->VariableNameU.MaximumLength = a->VariableName.MaximumLength * sizeof( WCHAR );
a->VariableNameU.Length = 0;
FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
MAKE_TAG( TMP_TAG ),
a->VariableNameU.MaximumLength +
((a->ValueLength+1) * sizeof( WCHAR ))
);
if (FreeBuffer == NULL) {
Status = STATUS_NO_MEMORY;
break;
}
a->VariableNameU.Buffer = FreeBuffer;
a->ValueBufferU = (PWSTR)((PCHAR)FreeBuffer + a->VariableNameU.MaximumLength );
}
Status = BaseDllWriteVariableValue( a, AppNameMapping, NULL, NULL );
if (FreeBuffer != NULL) {
RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
FreeBuffer = NULL;
RtlInitUnicodeString( &a->VariableNameU, NULL );
a->ValueBufferU = NULL;
a->ValueLengthU = 0;
}
if (!NT_SUCCESS( Status )) {
if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
break;
} else {
RtlMoveMemory( (PCHAR)NewValueBuffer + NewValueLength,
CurrentVariableStart,
CurrentVariableLength
);
NewValueLength += CurrentVariableLength;
Status = STATUS_SUCCESS;
}
}
}
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Status = GetExceptionCode();
}
if (NewValueLength) {
a->ValueBufferAllocated = TRUE;
if (a->Unicode) {
a->ValueBufferU = NewValueBuffer;
a->ValueLengthU = NewValueLength;
} else {
a->ValueBuffer = NewValueBuffer;
a->ValueLength = NewValueLength;
}
} else {
RtlFreeHeap( RtlProcessHeap(), 0, NewValueBuffer );
}
return Status;
}
NTSTATUS
BaseDllWriteVariableValue(
IN PINIFILE_PARAMETERS a,
IN PINIFILE_MAPPING_APPNAME AppNameMapping,
IN PINIFILE_MAPPING_VARNAME VarNameMapping OPTIONAL,
IN PUNICODE_STRING VariableName OPTIONAL
)
{
NTSTATUS Status;
PUNICODE_STRING ApplicationNameU;
PWSTR VariableValueU;
ULONG VariableValueLength;
HANDLE Key;
KEY_VALUE_BASIC_INFORMATION KeyValueInformation;
ULONG ResultLength;
if (!ARGUMENT_PRESENT( VariableName )) {
if (!BaseDllGetVariableName( a, NULL, &VariableName )) {
return STATUS_INVALID_PARAMETER;
}
}
if (!ARGUMENT_PRESENT( VarNameMapping )) {
VarNameMapping = BaseDllFindVarNameMapping( AppNameMapping, VariableName );
}
if (VarNameMapping == NULL) {
return STATUS_MORE_PROCESSING_REQUIRED;
}
if (!BaseDllGetApplicationName( a, NULL, &ApplicationNameU )) {
return STATUS_INVALID_PARAMETER;
}
Status = BaseDllOpenMappingTarget( a,
VarNameMapping,
ApplicationNameU,
TRUE,
&Key
);
if (!NT_SUCCESS( Status ) || Key == INVALID_HANDLE_VALUE) {
return Status;
}
Status = NtQueryValueKey( Key,
VariableName,
KeyValueBasicInformation,
&KeyValueInformation,
sizeof( KeyValueInformation ),
&ResultLength
);
if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_OVERFLOW) {
if (KeyValueInformation.Type != REG_SZ) {
return STATUS_OBJECT_TYPE_MISMATCH;
}
}
if (a->Operation == WriteKeyValue || a->Operation == WriteSection) {
if (!BaseDllGetVariableValue( a, NULL, &VariableValueU, &VariableValueLength )) {
Status = STATUS_INVALID_PARAMETER;
} else {
Status = NtSetValueKey( Key,
VariableName,
0,
REG_SZ,
VariableValueU,
VariableValueLength
);
}
} else {
Status = NtDeleteValueKey( Key,
VariableName
);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
Status = STATUS_SUCCESS;
}
}
if (NT_SUCCESS( Status ) && (VarNameMapping->MappingFlags & INIFILE_MAPPING_WRITE_TO_INIFILE_TOO)) {
#if 0
DbgPrint( "BASEDLL: WriteToProfileToo for [%wZ] %wZ . %wZ\n",
&a->FileName,
ApplicationNameU,
VariableName
);
#endif
return STATUS_MORE_PROCESSING_REQUIRED;
} else {
return Status;
}
}
NTSTATUS
BaseDllReadSectionNames(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllReadKeywordNames(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllReadKeywordValue(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllReadSection(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllWriteSection(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllWriteKeywordValue(
IN PINIFILE_PARAMETERS a,
IN PUNICODE_STRING VariableName OPTIONAL
);
#define BYTE_ORDER_MARK 0xFEFF
#define REVERSE_BYTE_ORDER_MARK 0xFFFE
NTSTATUS
BaseDllReadWriteIniFileOnDisk(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
ULONG PartialResultChars;
if (!a->WriteOperation) {
PartialResultChars = a->ResultChars;
}
Status = BaseDllOpenIniFileOnDisk( a );
if (NT_SUCCESS( Status )) {
try {
a->TextEnd = (PCHAR)a->IniFile->BaseAddress + a->IniFile->EndOfFile;
a->TextCurrent = a->IniFile->BaseAddress;
if (a->IniFile->UnicodeFile &&
((*(PWCHAR)a->TextCurrent == BYTE_ORDER_MARK) ||
(*(PWCHAR)a->TextCurrent == REVERSE_BYTE_ORDER_MARK)))
{
// Skip past the BOM.
((PWCHAR)a->TextCurrent)++;
}
if (a->Operation == ReadSectionNames) {
Status = BaseDllReadSectionNames( a );
} else
if (a->Operation == ReadKeyValue) {
Status = BaseDllReadKeywordValue( a );
} else
if (a->Operation == ReadKeyNames) {
Status = BaseDllReadKeywordNames( a );
} else
if (a->Operation == ReadSection) {
Status = BaseDllReadSection( a );
} else
if (a->Operation == WriteKeyValue || a->Operation == DeleteKey) {
Status = BaseDllWriteKeywordValue( a, NULL );
} else
if (a->Operation == WriteSection || a->Operation == DeleteSection) {
Status = BaseDllWriteSection( a );
} else {
Status = STATUS_INVALID_PARAMETER;
}
}
finally {
NTSTATUS CloseStatus;
CloseStatus = BaseDllCloseIniFileOnDisk( a );
if (NT_SUCCESS( Status )) {
Status = CloseStatus;
}
}
}
if (IsTerminalServer()) {
// The entry they were looking for wasn't found, see if we need to sync
// up the ini file
if (!NT_SUCCESS(Status) && ((a->Operation == ReadSectionNames) ||
(a->Operation == ReadKeyValue) ||
(a->Operation == ReadKeyNames) ||
(a->Operation == ReadSection))) {
// Sync up the ini file (if necessary), if we updated it, retry the
// original request
if (TermsrvSyncUserIniFile(a)) {
BaseDllReadWriteIniFileOnDisk(a);
}
} else if (NT_SUCCESS(Status) && ((a->Operation == WriteKeyValue) ||
(a->Operation == DeleteKey) ||
(a->Operation == WriteSection) ||
(a->Operation == DeleteSection)) &&
TermsrvAppInstallMode()) {
// Update log of installed files
if (gpTermsrvLogInstallIniFile) {
gpTermsrvLogInstallIniFile(&a->NtFileName);
}
}
}
if (Status == STATUS_OBJECT_NAME_NOT_FOUND &&
!a->WriteOperation &&
PartialResultChars != 0
) {
Status = STATUS_SUCCESS;
}
return Status;
}
NTSTATUS
BaseDllOpenIniFileOnDisk(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
UNICODE_STRING FullFileName;
ULONG n;
PWSTR FilePart;
PINIFILE_CACHE IniFile;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER ByteOffset, Length;
a->NtFileName.Length = 0;
if ((a->FileName.Length > sizeof( WCHAR ) &&
a->FileName.Buffer[ 1 ] == L':'
) ||
(a->FileName.Length != 0 &&
wcscspn( a->FileName.Buffer, L"\\/" ) != (a->FileName.Length / sizeof( WCHAR ))
)
) {
n = GetFullPathNameW( a->FileName.Buffer,
a->NtFileName.MaximumLength / sizeof( WCHAR ),
a->NtFileName.Buffer,
&FilePart
);
if (n > a->NtFileName.MaximumLength) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
a->NtFileName.Length = (USHORT)(n * sizeof( WCHAR ));
Status = STATUS_SUCCESS;
}
/*
* If the base windows directory was specified,
* redirect to user's directory
*/
if (gpTermsrvConvertSysRootToUserDir) {
gpTermsrvConvertSysRootToUserDir( &a->NtFileName, &BaseWindowsDirectory );
}
} else {
//
// get user based ini file
//
if (!gpTermsrvBuildIniFileName ||
!(NT_SUCCESS(Status = gpTermsrvBuildIniFileName( &a->NtFileName, &a->BaseFileName )))) {
RtlCopyUnicodeString( &a->NtFileName,
&BaseWindowsDirectory
);
Status = RtlAppendUnicodeToString( &a->NtFileName,
L"\\"
);
if (NT_SUCCESS( Status )) {
Status = RtlAppendUnicodeStringToString( &a->NtFileName,
&a->BaseFileName
);
}
}
}
IniFile = NULL;
if (NT_SUCCESS( Status )) {
if (RtlDosPathNameToNtPathName_U( a->NtFileName.Buffer,
&FullFileName,
&FilePart,
NULL
)
) {
RtlCopyUnicodeString( &a->NtFileName, &FullFileName );
RtlFreeUnicodeString( &FullFileName );
IniFile = RtlAllocateHeap( RtlProcessHeap(),
MAKE_TAG( INI_TAG ) | HEAP_ZERO_MEMORY,
sizeof( *IniFile ) + a->NtFileName.MaximumLength
);
if (IniFile == NULL) {
return STATUS_NO_MEMORY;
}
IniFile->NtFileName.Buffer = (PWSTR)(IniFile + 1);
IniFile->NtFileName.MaximumLength = a->NtFileName.MaximumLength;
RtlCopyUnicodeString( &IniFile->NtFileName, &a->NtFileName );
IniFile->FileMapping = a->IniFileNameMapping;
IniFile->WriteAccess = a->WriteOperation;
if (gpTermsrvCORIniFile) {
/*
* We call a function who handles copy on reference INI files
* before attempting the open.
*/
gpTermsrvCORIniFile( &IniFile->NtFileName );
}
InitializeObjectAttributes( &ObjectAttributes,
&IniFile->NtFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
if (IniFile->WriteAccess) {
Status = NtCreateFile( &IniFile->FileHandle,
SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT |
FILE_NON_DIRECTORY_FILE,
NULL,
0
);
} else {
Status = NtOpenFile( &IniFile->FileHandle,
SYNCHRONIZE | GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_SYNCHRONOUS_IO_NONALERT |
FILE_NON_DIRECTORY_FILE
);
}
#if DBG
if (!NT_SUCCESS( Status )) {
if (BaseDllDumpIniCalls) {
KdPrint(( "BASEDLL: Unable to open %wZ - Status == %x\n", &a->NtFileName, Status ));
}
}
#endif // DBG
} else {
Status = STATUS_OBJECT_PATH_NOT_FOUND;
}
}
if (NT_SUCCESS( Status )) {
IniFile->LockedFile = FALSE;
ByteOffset.QuadPart = 0;
Length.QuadPart = -1;
Status = NtLockFile( IniFile->FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
&ByteOffset,
&Length,
LockFileKey,
FALSE,
IniFile->WriteAccess
);
if (!NT_SUCCESS( Status )) {
if (Status == STATUS_NOT_SUPPORTED) {
//
// Go naked on downlevel servers since they can't do anything useful
// to help.
//
Status = STATUS_SUCCESS;
}
} else {
IniFile->LockedFile = TRUE;
}
if (NT_SUCCESS( Status )) {
Status = NtQueryInformationFile( IniFile->FileHandle,
&IoStatusBlock,
&IniFile->StandardInformation,
sizeof( IniFile->StandardInformation ),
FileStandardInformation
);
if (Status == STATUS_BUFFER_OVERFLOW) {
Status = STATUS_SUCCESS;
} else
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: Unable to QueryInformation for %wZ - Status == %x\n", &a->NtFileName, Status ));
}
}
}
if (!NT_SUCCESS( Status )) {
#if DBG
if (BaseDllDumpIniCalls) {
KdPrint(( "BASEDLL: Open of %wZ failed - Status == %x\n",
&IniFile->NtFileName,
Status
));
}
#endif // DBG
if (IniFile != NULL) {
if (IniFile->LockedFile) {
ByteOffset.QuadPart = 0;
Length.QuadPart = -1;
NtUnlockFile( IniFile->FileHandle,
&IoStatusBlock,
&ByteOffset,
&Length,
LockFileKey
);
}
NtClose( IniFile->FileHandle );
RtlFreeHeap( RtlProcessHeap(), 0, IniFile );
}
return Status;
}
IniFile->EndOfFile = IniFile->StandardInformation.EndOfFile.LowPart;
IniFile->CommitSize = IniFile->EndOfFile + (4 * (IniFile->UnicodeFile ? sizeof( WCHAR ) : 1));
IniFile->RegionSize = IniFile->CommitSize + 0x100000; // Room for 256KB of growth
Status = NtAllocateVirtualMemory( NtCurrentProcess(),
&IniFile->BaseAddress,
0,
&IniFile->RegionSize,
MEM_RESERVE,
PAGE_READWRITE
);
if (NT_SUCCESS( Status )) {
Status = NtAllocateVirtualMemory( NtCurrentProcess(),
&IniFile->BaseAddress,
0,
&IniFile->CommitSize,
MEM_COMMIT,
PAGE_READWRITE
);
if (NT_SUCCESS( Status )) {
Status = NtReadFile( IniFile->FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
IniFile->BaseAddress,
IniFile->EndOfFile,
NULL,
&LockFileKey
);
if (NT_SUCCESS( Status ) && IoStatusBlock.Information != IniFile->EndOfFile) {
Status = STATUS_END_OF_FILE;
}
}
}
if (NT_SUCCESS( Status )) {
// We would like to check the possibility of IS_TEXT_UNICODE_DBCS_LEADBYTE.
INT iResult = ~0x0;
IniFile->UpdateOffset = 0xFFFFFFFF;
IniFile->UpdateEndOffset = 0;
IniFile->UnicodeFile = RtlIsTextUnicode( IniFile->BaseAddress, IniFile->EndOfFile, &iResult );
if (IniFile->UnicodeFile) {
PWSTR Src;
Src = (PWSTR)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
while (Src > (PWSTR)IniFile->BaseAddress && Src[ -1 ] <= L' ') {
if (Src[-1] == L'\r' || Src[-1] == L'\n') {
break;
}
IniFile->EndOfFile -= sizeof( WCHAR );
Src -= 1;
}
Src = (PWSTR)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
if (Src > (PWSTR)IniFile->BaseAddress) {
if (Src[-1] != L'\n') {
*Src++ = L'\r';
*Src++ = L'\n';
IniFile->UpdateOffset = IniFile->EndOfFile;
IniFile->UpdateEndOffset = IniFile->UpdateOffset + 2 * sizeof( WCHAR );
IniFile->EndOfFile = IniFile->UpdateEndOffset;
}
}
} else {
PBYTE Src;
Src = (PBYTE)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
while (Src > (PBYTE)IniFile->BaseAddress && Src[ -1 ] <= ' ') {
if (Src[-1] == '\r' || Src[-1] == '\n') {
break;
}
IniFile->EndOfFile -= 1;
Src -= 1;
}
Src = (PBYTE)((PCHAR)IniFile->BaseAddress + IniFile->EndOfFile);
if (Src > (PBYTE)IniFile->BaseAddress) {
if (Src[-1] != '\n') {
*Src++ = '\r';
*Src++ = '\n';
IniFile->UpdateOffset = IniFile->EndOfFile;
IniFile->UpdateEndOffset = IniFile->UpdateOffset + 2;
IniFile->EndOfFile = IniFile->UpdateEndOffset;
}
}
}
a->IniFile = IniFile;
} else {
KdPrint(( "BASEDLL: Read of %wZ failed - Status == %x\n",
&IniFile->NtFileName,
Status
));
if (IniFile->LockedFile) {
ByteOffset.QuadPart = 0;
Length.QuadPart = -1;
NtUnlockFile( IniFile->FileHandle,
&IoStatusBlock,
&ByteOffset,
&Length,
LockFileKey
);
}
NtClose( IniFile->FileHandle );
RtlFreeHeap( RtlProcessHeap(), 0, IniFile );
}
return Status;
}
NTSTATUS
BaseDllCloseIniFileOnDisk(
IN PINIFILE_PARAMETERS a
)
{
PINIFILE_CACHE IniFile;
NTSTATUS Status;
NTSTATUS CloseStatus;
IO_STATUS_BLOCK IoStatusBlock;
ULONG UpdateLength;
LARGE_INTEGER ByteOffset, Length;
Status = STATUS_SUCCESS;
IniFile = a->IniFile;
if (IniFile != NULL) {
ASSERT( IniFile->FileHandle != NULL );
if (IniFile->BaseAddress != NULL) {
if (IniFile->UpdateOffset != 0xFFFFFFFF && IniFile->WriteAccess) {
ByteOffset.HighPart = 0;
ByteOffset.LowPart = IniFile->UpdateOffset;
UpdateLength = IniFile->UpdateEndOffset - IniFile->UpdateOffset;
Status = NtWriteFile( IniFile->FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
(PCHAR)(IniFile->BaseAddress) + IniFile->UpdateOffset,
UpdateLength,
&ByteOffset,
&LockFileKey
);
if (NT_SUCCESS( Status )) {
if (IoStatusBlock.Information != UpdateLength) {
Status = STATUS_DISK_FULL;
} else {
Length.QuadPart = IniFile->EndOfFile;
Status = NtSetInformationFile( IniFile->FileHandle,
&IoStatusBlock,
&Length,
sizeof( Length ),
FileEndOfFileInformation
);
}
}
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: Unable to write changes for %wZ to disk - Status == %x\n",
&IniFile->NtFileName,
Status
));
}
}
NtFreeVirtualMemory( NtCurrentProcess(),
&IniFile->BaseAddress,
&IniFile->RegionSize,
MEM_RELEASE
);
IniFile->BaseAddress = NULL;
IniFile->CommitSize = 0;
IniFile->RegionSize = 0;
}
if (IniFile->LockedFile) {
ByteOffset.QuadPart = 0;
Length.QuadPart = -1;
NtUnlockFile( IniFile->FileHandle,
&IoStatusBlock,
&ByteOffset,
&Length,
HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread)
);
}
CloseStatus = NtClose( IniFile->FileHandle );
if (NT_SUCCESS( Status )) {
Status = CloseStatus;
}
IniFile->FileHandle = NULL;
RtlFreeHeap( RtlProcessHeap(), 0, IniFile );
}
return Status;
}
#define STOP_AT_SECTION 1
#define STOP_AT_KEYWORD 2
#define STOP_AT_NONSECTION 3
NTSTATUS
BaseDllFindSection(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllFindKeyword(
IN PINIFILE_PARAMETERS a
);
NTSTATUS
BaseDllAdvanceTextPointer(
IN PINIFILE_PARAMETERS a,
IN ULONG StopAt
);
NTSTATUS
BaseDllReadSectionNames(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
Status = STATUS_SUCCESS;
while (NT_SUCCESS( Status )) {
Status = BaseDllAdvanceTextPointer( a, STOP_AT_SECTION );
if (Status == STATUS_MORE_ENTRIES) {
Status = BaseDllAppendStringToResultBuffer( a,
a->AnsiSectionName,
a->UnicodeSectionName,
TRUE
);
} else {
if (Status == STATUS_NO_MORE_ENTRIES) {
Status = STATUS_SUCCESS;
}
break;
}
}
return Status;
}
NTSTATUS
BaseDllReadKeywordNames(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
Status = BaseDllFindSection( a );
while (NT_SUCCESS( Status )) {
Status = BaseDllAdvanceTextPointer( a, STOP_AT_KEYWORD );
if (Status == STATUS_MORE_ENTRIES) {
Status = BaseDllAppendStringToResultBuffer( a,
a->AnsiKeywordName,
a->UnicodeKeywordName,
TRUE
);
} else {
if (Status == STATUS_NO_MORE_ENTRIES) {
Status = STATUS_SUCCESS;
}
break;
}
}
return Status;
}
NTSTATUS
BaseDllReadKeywordValue(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
Status = BaseDllFindSection( a );
if (!NT_SUCCESS( Status )) {
return Status;
}
Status = BaseDllFindKeyword( a );
if (!NT_SUCCESS( Status )) {
return Status;
}
if (a->IniFile->UnicodeFile) {
PWSTR Src;
Src = (PWSTR)a->UnicodeKeywordValue->Buffer;
while (*Src <= L' ' && a->UnicodeKeywordValue->Length) {
Src += 1;
a->UnicodeKeywordValue->Buffer = Src;
a->UnicodeKeywordValue->Length -= sizeof( WCHAR );
a->UnicodeKeywordValue->MaximumLength -= sizeof( WCHAR );
}
if (a->UnicodeKeywordValue->Length >= (2 * sizeof( WCHAR )) &&
(Src[ 0 ] == Src[ (a->UnicodeKeywordValue->Length - sizeof( WCHAR )) / sizeof( WCHAR ) ]) &&
(Src[ 0 ] == L'"' || Src[ 0 ] == L'\'')
) {
a->UnicodeKeywordValue->Buffer += 1;
a->UnicodeKeywordValue->Length -= (2 * sizeof( WCHAR ));
a->UnicodeKeywordValue->MaximumLength -= (2 * sizeof( WCHAR ));
}
} else {
PBYTE Src;
Src = (PBYTE)a->AnsiKeywordValue->Buffer;
while (*Src <= ' ' && a->AnsiKeywordValue->Length) {
Src += 1;
a->AnsiKeywordValue->Buffer = Src;
a->AnsiKeywordValue->Length -= sizeof( UCHAR );
a->AnsiKeywordValue->MaximumLength -= sizeof( UCHAR );
}
if (a->AnsiKeywordValue->Length >= (2 * sizeof( UCHAR )) &&
(Src[ 0 ] == Src[ (a->AnsiKeywordValue->Length - sizeof( UCHAR )) / sizeof( UCHAR ) ]) &&
(Src[ 0 ] == '"' || Src[ 0 ] == '\'')
) {
a->AnsiKeywordValue->Buffer += 1;
a->AnsiKeywordValue->Length -= (2 * sizeof( UCHAR ));
a->AnsiKeywordValue->MaximumLength -= (2 * sizeof( UCHAR ));
}
}
return BaseDllAppendStringToResultBuffer( a,
a->AnsiKeywordValue,
a->UnicodeKeywordValue,
TRUE
);
}
NTSTATUS
BaseDllReadSection(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
Status = BaseDllFindSection( a );
if (!NT_SUCCESS( Status )) {
return Status;
}
while (TRUE) {
Status = BaseDllAdvanceTextPointer( a, STOP_AT_NONSECTION );
if (Status == STATUS_MORE_ENTRIES) {
if (a->AnsiKeywordName || a->UnicodeKeywordName) {
Status = BaseDllAppendStringToResultBuffer( a,
a->AnsiKeywordName,
a->UnicodeKeywordName,
FALSE
);
if (!NT_SUCCESS( Status )) {
return Status;
}
Status = BaseDllAppendBufferToResultBuffer( a,
a->Unicode ? NULL : "=",
a->Unicode ? L"=" : NULL,
1,
FALSE
);
if (!NT_SUCCESS( Status )) {
return Status;
}
}
if (a->IniFile->UnicodeFile) {
PWSTR Src;
Src = (PWSTR)a->UnicodeKeywordValue->Buffer;
while (*Src <= L' ' && a->UnicodeKeywordValue->Length) {
Src += 1;
a->UnicodeKeywordValue->Buffer = Src;
a->UnicodeKeywordValue->Length -= sizeof( WCHAR );
a->UnicodeKeywordValue->MaximumLength -= sizeof( WCHAR );
}
} else {
PBYTE Src;
Src = (PBYTE)a->AnsiKeywordValue->Buffer;
while (*Src <= ' ' && a->AnsiKeywordValue->Length) {
Src += 1;
a->AnsiKeywordValue->Buffer = Src;
a->AnsiKeywordValue->Length -= sizeof( UCHAR );
a->AnsiKeywordValue->MaximumLength -= sizeof( UCHAR );
}
}
Status = BaseDllAppendStringToResultBuffer( a,
a->AnsiKeywordValue,
a->UnicodeKeywordValue,
TRUE
);
if (!NT_SUCCESS( Status )) {
return Status;
}
} else {
if (Status == STATUS_NO_MORE_ENTRIES) {
Status = STATUS_SUCCESS;
}
break;
}
}
return Status;
}
NTSTATUS
BaseDllModifyMappedFile(
IN PINIFILE_PARAMETERS a,
IN PVOID AddressInFile,
IN ULONG SizeToRemove,
IN PVOID InsertBuffer,
IN ULONG InsertAmount
);
NTSTATUS
BaseDllWriteSection(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
BOOLEAN InsertSectionName;
PVOID InsertBuffer;
ULONG InsertAmount, n;
PANSI_STRING AnsiSectionName;
PUNICODE_STRING UnicodeSectionName;
PBYTE AnsiKeywordValue, s;
PWSTR UnicodeKeywordValue, w;
ULONG ValueLength, SizeToRemove;
PVOID AddressInFile;
InsertAmount = 0;
Status = BaseDllFindSection( a );
if (!NT_SUCCESS( Status )) {
if (a->Operation == DeleteSection) {
return STATUS_SUCCESS;
}
AddressInFile = a->TextEnd;
if (a->IniFile->UnicodeFile) {
if (!BaseDllGetApplicationName( a, NULL, &UnicodeSectionName )) {
return STATUS_INVALID_PARAMETER;
}
//
// Add in size of [SectionName]\r\n
//
InsertAmount += (1 + 1 + 2) * sizeof( WCHAR );
InsertAmount += UnicodeSectionName->Length;
} else {
if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL )) {
return STATUS_INVALID_PARAMETER;
}
//
// Add in size of [SectionName]\r\n
//
InsertAmount += (1 + 1 + 2) * sizeof( UCHAR );
InsertAmount += AnsiSectionName->Length;
}
InsertSectionName = TRUE;
SizeToRemove = 0;
} else {
if (a->Operation == DeleteSection) {
AddressInFile = a->TextStart;
} else {
AddressInFile = a->TextCurrent;
}
while (TRUE) {
//
// For delete operations need to iterate all lines in section,
// not just those that have an = on them. Otherwise sections like
// [foo]
// a
// b = c
// d
//
// don't get deleted properly.
//
Status = BaseDllAdvanceTextPointer(
a,
(a->Operation == DeleteSection) ? STOP_AT_NONSECTION : STOP_AT_KEYWORD
);
if (Status == STATUS_MORE_ENTRIES) {
} else
if (Status == STATUS_NO_MORE_ENTRIES) {
SizeToRemove = (ULONG)((PCHAR)a->TextCurrent - (PCHAR)AddressInFile);
break;
} else {
return Status;
}
}
InsertSectionName = FALSE;
}
if (a->Operation == DeleteSection) {
InsertBuffer = NULL;
} else {
if (a->IniFile->UnicodeFile) {
if (!BaseDllGetVariableValue( a, NULL, &UnicodeKeywordValue, &ValueLength )) {
return STATUS_INVALID_PARAMETER;
}
ValueLength -= sizeof( WCHAR );
//
// Add in size of value, + \r\n for each line
//
w = UnicodeKeywordValue;
InsertAmount += ValueLength;
while (*w) {
while (*w++) {
}
InsertAmount += (2-1) * sizeof( WCHAR ); // Subtract out NULL byte already in ValueLength
}
} else {
if (!BaseDllGetVariableValue( a, &AnsiKeywordValue, NULL, &ValueLength )) {
return STATUS_INVALID_PARAMETER;
}
ValueLength -= sizeof( UCHAR );
//
// Add in size of value, + \r\n for each line
//
s = AnsiKeywordValue;
InsertAmount += ValueLength;
while (*s) {
while (*s++) {
}
InsertAmount += 2 - 1; // Subtract out NULL byte already in ValueLength
}
}
InsertBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), InsertAmount + sizeof( UNICODE_NULL ) );
if (InsertBuffer == NULL) {
return STATUS_NO_MEMORY;
}
if (a->IniFile->UnicodeFile) {
PWSTR Src, Dst;
Dst = InsertBuffer;
if (InsertSectionName) {
*Dst++ = L'[';
Src = UnicodeSectionName->Buffer;
n = UnicodeSectionName->Length / sizeof( WCHAR );
while (n--) {
*Dst++ = *Src++;
}
*Dst++ = L']';
*Dst++ = L'\r';
*Dst++ = L'\n';
}
Src = UnicodeKeywordValue;
while (*Src) {
while (*Dst = *Src++) {
Dst += 1;
}
*Dst++ = L'\r';
*Dst++ = L'\n';
}
} else {
PBYTE Src, Dst;
Dst = InsertBuffer;
if (InsertSectionName) {
*Dst++ = '[';
Src = AnsiSectionName->Buffer;
n = AnsiSectionName->Length;
while (n--) {
*Dst++ = *Src++;
}
*Dst++ = ']';
*Dst++ = '\r';
*Dst++ = '\n';
}
Src = AnsiKeywordValue;
while (*Src) {
while (*Dst = *Src++) {
Dst += 1;
}
*Dst++ = '\r';
*Dst++ = '\n';
}
}
}
Status = BaseDllModifyMappedFile( a,
AddressInFile,
SizeToRemove,
InsertBuffer,
InsertAmount
);
RtlFreeHeap( RtlProcessHeap(), 0, InsertBuffer );
return Status;
}
NTSTATUS
BaseDllCalculateDeleteLength(
IN PINIFILE_PARAMETERS a
)
{
ULONG DeleteLength;
if (a->IniFile->UnicodeFile) {
DeleteLength = (ULONG)((PCHAR)a->TextCurrent -
(PCHAR)a->UnicodeKeywordName->Buffer);
} else {
DeleteLength = (ULONG)((PCHAR)a->TextCurrent -
a->AnsiKeywordName->Buffer);
}
return DeleteLength;
}
NTSTATUS
BaseDllWriteKeywordValue(
IN PINIFILE_PARAMETERS a,
IN PUNICODE_STRING VariableName OPTIONAL
)
{
NTSTATUS Status;
BOOLEAN InsertSectionName;
BOOLEAN InsertKeywordName;
PVOID InsertBuffer;
ULONG InsertAmount, n;
PANSI_STRING AnsiSectionName;
PANSI_STRING AnsiKeywordName;
PUNICODE_STRING UnicodeSectionName;
PUNICODE_STRING UnicodeKeywordName;
PBYTE AnsiKeywordValue;
PWSTR UnicodeKeywordValue;
ULONG ValueLength;
ULONG DeleteLength;
PVOID AddressInFile;
InsertAmount = 0;
Status = BaseDllFindSection( a );
if (!NT_SUCCESS( Status )) {
if (a->Operation == DeleteKey) {
return STATUS_SUCCESS;
}
AddressInFile = a->TextEnd;
if (a->IniFile->UnicodeFile) {
if (!BaseDllGetApplicationName( a, NULL, &UnicodeSectionName )) {
return STATUS_INVALID_PARAMETER;
}
//
// Add in size of [SectionName]\r\n
//
InsertAmount += (1 + 1 + 2) * sizeof( WCHAR );
InsertAmount += UnicodeSectionName->Length;
} else {
if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL )) {
return STATUS_INVALID_PARAMETER;
}
//
// Add in size of [SectionName]\r\n
//
InsertAmount += (1 + 1 + 2) * sizeof( UCHAR );
InsertAmount += AnsiSectionName->Length;
}
InsertSectionName = TRUE;
} else {
InsertSectionName = FALSE;
Status = BaseDllFindKeyword( a );
}
if (!NT_SUCCESS( Status )) {
if (a->Operation == DeleteKey) {
return STATUS_SUCCESS;
}
if (!InsertSectionName) {
AddressInFile = a->TextCurrent;
}
if (a->IniFile->UnicodeFile) {
if (!BaseDllGetVariableName( a, NULL, &UnicodeKeywordName )) {
return STATUS_INVALID_PARAMETER;
}
//
// Add in size of Keyword=\r\n
//
InsertAmount += (1 + 2) * sizeof( WCHAR );
InsertAmount += UnicodeKeywordName->Length;
} else {
if (!BaseDllGetVariableName( a, &AnsiKeywordName, NULL )) {
return STATUS_INVALID_PARAMETER;
}
//
// Add in size of Keyword=\r\n
//
InsertAmount += (1 + 2) * sizeof( UCHAR );
InsertAmount += AnsiKeywordName->Length;
}
InsertKeywordName = TRUE;
} else {
if (a->IniFile->UnicodeFile) {
if (a->Operation == DeleteKey) {
DeleteLength = BaseDllCalculateDeleteLength( a );
return BaseDllModifyMappedFile( a,
a->UnicodeKeywordName->Buffer,
DeleteLength,
NULL,
0
);
} else {
AddressInFile = a->UnicodeKeywordValue->Buffer;
}
} else {
if (a->Operation == DeleteKey) {
DeleteLength = BaseDllCalculateDeleteLength( a );
return BaseDllModifyMappedFile( a,
a->AnsiKeywordName->Buffer,
DeleteLength,
NULL,
0
);
} else {
AddressInFile = a->AnsiKeywordValue->Buffer;
}
}
InsertKeywordName = FALSE;
}
if (a->IniFile->UnicodeFile) {
if (!BaseDllGetVariableValue( a, NULL, &UnicodeKeywordValue, &ValueLength )) {
return STATUS_INVALID_PARAMETER;
}
ValueLength -= sizeof( WCHAR );
if (InsertAmount == 0) {
return BaseDllModifyMappedFile( a,
a->UnicodeKeywordValue->Buffer,
a->UnicodeKeywordValue->Length,
UnicodeKeywordValue,
ValueLength
);
}
//
// Add in size of value
//
InsertAmount += ValueLength;
} else {
if (!BaseDllGetVariableValue( a, &AnsiKeywordValue, NULL, &ValueLength )) {
return STATUS_INVALID_PARAMETER;
}
ValueLength -= sizeof( UCHAR );
if (InsertAmount == 0) {
return BaseDllModifyMappedFile( a,
a->AnsiKeywordValue->Buffer,
a->AnsiKeywordValue->Length,
AnsiKeywordValue,
ValueLength
);
}
//
// Add in size of value
//
InsertAmount += ValueLength;
}
InsertBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), InsertAmount + sizeof( UNICODE_NULL ) );
if (InsertBuffer == NULL) {
return STATUS_NO_MEMORY;
}
if (a->IniFile->UnicodeFile) {
PWSTR Src, Dst;
Dst = InsertBuffer;
if (InsertSectionName) {
*Dst++ = L'[';
Src = UnicodeSectionName->Buffer;
n = UnicodeSectionName->Length / sizeof( WCHAR );
while (n--) {
*Dst++ = *Src++;
}
*Dst++ = L']';
*Dst++ = L'\r';
*Dst++ = L'\n';
}
if (InsertKeywordName) {
Src = UnicodeKeywordName->Buffer;
n = UnicodeKeywordName->Length / sizeof( WCHAR );
while (n--) {
*Dst++ = *Src++;
}
*Dst++ = L'=';
}
Src = UnicodeKeywordValue;
n = ValueLength / sizeof( WCHAR );
while (n--) {
*Dst++ = *Src++;
}
if (InsertKeywordName) {
*Dst++ = L'\r';
*Dst++ = L'\n';
}
} else {
PBYTE Src, Dst;
Dst = InsertBuffer;
if (InsertSectionName) {
*Dst++ = '[';
Src = AnsiSectionName->Buffer;
n = AnsiSectionName->Length;
while (n--) {
*Dst++ = *Src++;
}
*Dst++ = ']';
*Dst++ = '\r';
*Dst++ = '\n';
}
if (InsertKeywordName) {
Src = AnsiKeywordName->Buffer;
n = AnsiKeywordName->Length;
while (n--) {
*Dst++ = *Src++;
}
*Dst++ = '=';
}
Src = AnsiKeywordValue;
n = ValueLength;
while (n--) {
*Dst++ = *Src++;
}
if (InsertKeywordName) {
*Dst++ = '\r';
*Dst++ = '\n';
}
}
Status = BaseDllModifyMappedFile( a,
AddressInFile,
0,
InsertBuffer,
InsertAmount
);
RtlFreeHeap( RtlProcessHeap(), 0, InsertBuffer );
return Status;
}
NTSTATUS
BaseDllFindSection(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
PANSI_STRING AnsiSectionName;
PUNICODE_STRING UnicodeSectionName;
BOOL FreeAnsiBuffer;
while (TRUE) {
Status = BaseDllAdvanceTextPointer( a, STOP_AT_SECTION );
if (Status == STATUS_MORE_ENTRIES) {
FreeAnsiBuffer = FALSE;
if (a->AnsiSectionName) {
// Ansi ini file -- get the ansi parm
if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL )) {
return STATUS_INVALID_PARAMETER;
}
} else {
// Unicode ini file
if (a->Unicode) {
// Unicode parm - we just need the unicode section name...
if (!BaseDllGetApplicationName( a, NULL, &UnicodeSectionName )) {
return STATUS_INVALID_PARAMETER;
}
} else {
// ansi parm - convert the unicode section name to ansi
if (!BaseDllGetApplicationName( a, &AnsiSectionName, NULL ))
return STATUS_INVALID_PARAMETER;
a->AnsiSectionName = &a->SectionName;
Status = RtlUnicodeStringToAnsiString( a->AnsiSectionName,
a->UnicodeSectionName,
TRUE
);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", a->UnicodeSectionName, Status ));
return Status;
}
FreeAnsiBuffer = TRUE;
}
}
if (a->AnsiSectionName == NULL && a->Unicode) {
if (RtlEqualUnicodeString( UnicodeSectionName,
a->UnicodeSectionName,
TRUE
)
) {
Status = STATUS_SUCCESS;
} else {
Status = STATUS_MORE_ENTRIES;
}
} else {
if (RtlEqualString( AnsiSectionName, a->AnsiSectionName, TRUE )) {
Status = STATUS_SUCCESS;
} else {
Status = STATUS_MORE_ENTRIES;
}
}
if (FreeAnsiBuffer) {
RtlFreeAnsiString( a->AnsiSectionName );
}
if (Status != STATUS_MORE_ENTRIES) {
return Status;
}
} else {
return STATUS_OBJECT_NAME_NOT_FOUND;
}
}
}
NTSTATUS
BaseDllFindKeyword(
IN PINIFILE_PARAMETERS a
)
{
NTSTATUS Status;
PANSI_STRING AnsiKeywordName;
PUNICODE_STRING UnicodeKeywordName;
BOOL FreeAnsiBuffer;
while (TRUE) {
Status = BaseDllAdvanceTextPointer( a, STOP_AT_KEYWORD );
if (Status == STATUS_MORE_ENTRIES) {
FreeAnsiBuffer = FALSE;
// Here's the deal. We don't want to compare in Unicode
// unless both the ini and the input parm are Unicode,
// because we want to avoid the round-trip problem (we
// lose data when we convert Unicode -> Ansi (on disk) ->
// Unicode; since we don't get back the original Unicode
// string, lookups of previously stored data fail -- bug
// 426754). So if both are Unicode, great! -- use Unicode.
// Otherwise, use ansi for everything.
if (a->AnsiKeywordName) {
// Ansi ini file -- get the ansi parm
if (!BaseDllGetVariableName( a, &AnsiKeywordName, NULL )) {
return STATUS_INVALID_PARAMETER;
}
} else {
// Unicode ini
if (a->Unicode) {
// Unicode parm - great, get the Unicode parm.
if (!BaseDllGetVariableName( a, NULL, &UnicodeKeywordName )) {
return STATUS_INVALID_PARAMETER;
}
} else {
// Ansi parm - convert the unicode ini keyword to ansi.
if (!BaseDllGetVariableName( a, &AnsiKeywordName, NULL )) {
return STATUS_INVALID_PARAMETER;
}
a->AnsiKeywordName = &a->KeywordName;
Status = RtlUnicodeStringToAnsiString( a->AnsiKeywordName,
a->UnicodeKeywordName,
TRUE
);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: UnicodeToAnsi of %wZ failed (%08x)\n", a->UnicodeKeywordName, Status ));
return Status;
}
FreeAnsiBuffer = TRUE;
}
}
if (a->AnsiKeywordName == NULL && a->Unicode) {
if (RtlEqualUnicodeString( UnicodeKeywordName,
a->UnicodeKeywordName,
TRUE
)
) {
Status = STATUS_SUCCESS;
} else {
Status = STATUS_MORE_ENTRIES;
}
} else {
if (RtlEqualString( AnsiKeywordName, a->AnsiKeywordName, TRUE )) {
Status = STATUS_SUCCESS;
} else {
Status = STATUS_MORE_ENTRIES;
}
}
if (FreeAnsiBuffer) {
RtlFreeAnsiString( a->AnsiKeywordName );
}
if (Status != STATUS_MORE_ENTRIES) {
return Status;
}
} else {
return STATUS_OBJECT_NAME_NOT_FOUND;
}
}
}
NTSTATUS
BaseDllAdvanceTextPointer(
IN PINIFILE_PARAMETERS a,
IN ULONG StopAt
)
{
BOOLEAN AllowNoEquals;
if (StopAt == STOP_AT_NONSECTION) {
StopAt = STOP_AT_KEYWORD;
AllowNoEquals = TRUE;
} else {
AllowNoEquals = FALSE;
}
if (a->IniFile->UnicodeFile) {
PWSTR Src, EndOfLine, EqualSign, EndOfFile;
PWSTR Name, EndOfName, Value, EndOfValue;
#define INI_TEXT(quote) L##quote
Src = a->TextCurrent;
EndOfFile = a->TextEnd;
while (Src < EndOfFile) {
//
// Find first non-blank character on a line. Skip blank lines
//
while (Src < EndOfFile && *Src <= INI_TEXT(' ')) {
Src++;
}
if (Src >= EndOfFile) {
a->TextCurrent = Src;
break;
}
EndOfLine = Src;
EqualSign = NULL;
a->TextStart = Src;
while (EndOfLine < EndOfFile) {
if (EqualSign == NULL && *EndOfLine == INI_TEXT('=')) {
EqualSign = ++EndOfLine;
} else
if (*EndOfLine == INI_TEXT('\r') || *EndOfLine == INI_TEXT('\n')) {
if (*EndOfLine == INI_TEXT('\r')) {
EndOfLine++;
}
if (*EndOfLine == INI_TEXT('\n')) {
EndOfLine++;
}
break;
} else {
EndOfLine++;
}
}
if (*Src != INI_TEXT(';')) {
if (*Src == INI_TEXT('[')) {
Name = Src + 1;
while (Name < EndOfLine && *Name <= INI_TEXT(' ')) {
Name++;
}
EndOfName = Name;
while (EndOfName < EndOfLine && *EndOfName != INI_TEXT(']')) {
EndOfName++;
}
while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
EndOfName--;
}
a->SectionNameU.Buffer = Name;
a->SectionNameU.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
a->SectionNameU.MaximumLength = a->SectionNameU.Length;
a->AnsiSectionName = NULL;
a->UnicodeSectionName = &a->SectionNameU;
if (StopAt == STOP_AT_SECTION) {
a->TextCurrent = EndOfLine;
return STATUS_MORE_ENTRIES;
} else
if (StopAt == STOP_AT_KEYWORD) {
return STATUS_NO_MORE_ENTRIES;
}
} else
if (AllowNoEquals || (EqualSign != NULL) ) {
if (EqualSign != NULL) {
Name = Src;
EndOfName = EqualSign - 1;
while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
EndOfName--;
}
a->KeywordNameU.Buffer = Name;
a->KeywordNameU.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
a->KeywordNameU.MaximumLength = a->KeywordNameU.Length;
a->AnsiKeywordName = NULL;
a->UnicodeKeywordName = &a->KeywordNameU;
Value = EqualSign;
} else {
Value = Src;
a->AnsiKeywordName = NULL;
a->UnicodeKeywordName = NULL;
}
EndOfValue = EndOfLine;
while (EndOfValue > Value && EndOfValue[ -1 ] <= INI_TEXT(' ')) {
EndOfValue--;
}
a->KeywordValueU.Buffer = Value;
a->KeywordValueU.Length = (USHORT)((PCHAR)EndOfValue - (PCHAR)Value);
a->KeywordValueU.MaximumLength = a->KeywordValueU.Length;
a->AnsiKeywordValue = NULL;
a->UnicodeKeywordValue = &a->KeywordValueU;
if (StopAt == STOP_AT_KEYWORD) {
a->TextCurrent = EndOfLine;
return STATUS_MORE_ENTRIES;
}
}
}
Src = EndOfLine;
}
} else {
PBYTE Src, EndOfLine, EqualSign, EndOfFile;
PBYTE Name, EndOfName, Value, EndOfValue;
#undef INI_TEXT
#define INI_TEXT(quote) quote
Src = a->TextCurrent;
EndOfFile = a->TextEnd;
while (Src < EndOfFile) {
//
// Find first non-blank character on a line. Skip blank lines
//
while (Src < EndOfFile && *Src <= INI_TEXT(' ')) {
Src++;
}
if (Src >= EndOfFile) {
a->TextCurrent = Src;
break;
}
EndOfLine = Src;
EqualSign = NULL;
a->TextStart = Src;
while (EndOfLine < EndOfFile) {
if (EqualSign == NULL && *EndOfLine == INI_TEXT('=')) {
EqualSign = ++EndOfLine;
} else
if (*EndOfLine == INI_TEXT('\r') || *EndOfLine == INI_TEXT('\n')) {
if (*EndOfLine == INI_TEXT('\r')) {
EndOfLine++;
}
if (*EndOfLine == INI_TEXT('\n')) {
EndOfLine++;
}
break;
} else {
EndOfLine++;
}
}
if (*Src != INI_TEXT(';')) {
if (*Src == INI_TEXT('[')) {
Name = Src + 1;
while (Name < EndOfLine && *Name <= INI_TEXT(' ')) {
Name++;
}
EndOfName = Name;
while (EndOfName < EndOfLine) {
if (*EndOfName == INI_TEXT(']')) {
break;
}
if (IsDBCSLeadByte(*EndOfName)) {
EndOfName++;
}
EndOfName++;
}
while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
EndOfName--;
}
a->SectionName.Buffer = Name;
a->SectionName.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
a->SectionName.MaximumLength = a->SectionName.Length;
a->AnsiSectionName = &a->SectionName;
a->UnicodeSectionName = NULL;
if (StopAt == STOP_AT_SECTION) {
a->TextCurrent = EndOfLine;
return STATUS_MORE_ENTRIES;
} else
if (StopAt == STOP_AT_KEYWORD) {
return STATUS_NO_MORE_ENTRIES;
}
} else
if (AllowNoEquals || (EqualSign != NULL)) {
if (EqualSign != NULL) {
Name = Src;
EndOfName = EqualSign - 1;
while (EndOfName > Name && EndOfName[ -1 ] <= INI_TEXT(' ')) {
EndOfName--;
}
a->KeywordName.Buffer = Name;
a->KeywordName.Length = (USHORT)((PCHAR)EndOfName - (PCHAR)Name);
a->KeywordName.MaximumLength = a->KeywordName.Length;
a->AnsiKeywordName = &a->KeywordName;
a->UnicodeKeywordName = NULL;
Value = EqualSign;
} else {
Value = Src;
a->AnsiKeywordName = NULL;
a->UnicodeKeywordName = NULL;
}
EndOfValue = EndOfLine;
while (EndOfValue > Value && EndOfValue[ -1 ] <= INI_TEXT(' ')) {
EndOfValue--;
}
a->KeywordValue.Buffer = Value;
a->KeywordValue.Length = (USHORT)((PCHAR)EndOfValue - (PCHAR)Value);
a->KeywordValue.MaximumLength = a->KeywordValue.Length;
a->AnsiKeywordValue = &a->KeywordValue;
a->UnicodeKeywordValue = NULL;
if (StopAt == STOP_AT_KEYWORD) {
a->TextCurrent = EndOfLine;
return STATUS_MORE_ENTRIES;
}
}
}
Src = EndOfLine;
}
}
return STATUS_NO_MORE_ENTRIES;
}
NTSTATUS
BaseDllModifyMappedFile(
IN PINIFILE_PARAMETERS a,
IN PVOID AddressInFile,
IN ULONG SizeToRemove,
IN PVOID InsertBuffer,
IN ULONG InsertAmount
)
{
NTSTATUS Status;
ULONG NewEndOfFile, UpdateOffset, UpdateLength;
NewEndOfFile = a->IniFile->EndOfFile - SizeToRemove + InsertAmount;
if (NewEndOfFile > a->IniFile->CommitSize) {
if (NewEndOfFile > a->IniFile->RegionSize) {
return STATUS_BUFFER_OVERFLOW;
}
a->IniFile->CommitSize = NewEndOfFile;
Status = NtAllocateVirtualMemory( NtCurrentProcess(),
&a->IniFile->BaseAddress,
0,
&a->IniFile->CommitSize,
MEM_COMMIT,
PAGE_READWRITE
);
if (!NT_SUCCESS( Status )) {
KdPrint(( "BASEDLL: Unable to allocate memory to grow %wZ - Status == %x\n",
&a->IniFile->NtFileName,
Status
));
return Status;
}
a->IniFile->EndOfFile = NewEndOfFile;
}
UpdateOffset = (ULONG)((PCHAR)AddressInFile - (PCHAR)(a->IniFile->BaseAddress)),
UpdateLength = (ULONG)((PCHAR)a->TextEnd - (PCHAR)AddressInFile) + InsertAmount - SizeToRemove;
//
// Are we deleting more than we are inserting?
//
if (SizeToRemove > InsertAmount) {
//
// Yes copy over insert string.
//
RtlMoveMemory( AddressInFile, InsertBuffer, InsertAmount );
//
// Delete remaining text after insertion string by moving it
// up
//
RtlMoveMemory( (PCHAR)AddressInFile + InsertAmount,
(PCHAR)AddressInFile + SizeToRemove,
UpdateLength - InsertAmount
);
} else
if (InsertAmount > 0) {
//
// Are we deleting less than we are inserting?
//
if (SizeToRemove < InsertAmount) {
//
// Move text down to make room for insertion
//
RtlMoveMemory( (PCHAR)AddressInFile + InsertAmount - SizeToRemove,
(PCHAR)AddressInFile,
UpdateLength - InsertAmount + SizeToRemove
);
} else {
//
// Deleting and inserting same amount, update just that text as
// no shifting was done.
//
UpdateLength = InsertAmount;
}
//
// Copy over insert string
//
RtlMoveMemory( AddressInFile, InsertBuffer, InsertAmount );
} else {
//
// Nothing to change, as InsertAmount and SizeToRemove are zero
//
return STATUS_SUCCESS;
}
if (a->IniFile->EndOfFile != NewEndOfFile) {
a->IniFile->EndOfFile = NewEndOfFile;
}
if (UpdateOffset < a->IniFile->UpdateOffset) {
a->IniFile->UpdateOffset = UpdateOffset;
}
if ((UpdateOffset + UpdateLength) > a->IniFile->UpdateEndOffset) {
a->IniFile->UpdateEndOffset = UpdateOffset + UpdateLength;
}
return STATUS_SUCCESS;
}
#if DBG
VOID
BaseDllDumpIniFileMappings(
PINIFILE_MAPPING IniFileMapping
);
VOID
BaseDllPrintMappingTarget(
IN PINIFILE_MAPPING_VARNAME VarNameMapping
);
VOID
BaseDllDumpIniFileMappings(
PINIFILE_MAPPING IniFileMapping
)
{
PINIFILE_MAPPING_FILENAME FileNameMapping;
PINIFILE_MAPPING_APPNAME AppNameMapping;
PINIFILE_MAPPING_VARNAME VarNameMapping;
DbgPrint( "IniFileMapping\n" );
FileNameMapping = (PINIFILE_MAPPING_FILENAME)IniFileMapping->DefaultFileNameMapping;
if (FileNameMapping != NULL) {
AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
DbgPrint( " " );
BaseDllPrintMappingTarget( VarNameMapping );
}
FileNameMapping = (PINIFILE_MAPPING_FILENAME)IniFileMapping->FileNames;
while (FileNameMapping) {
BASE_READ_REMOTE_STR_TEMP(TempStr);
DbgPrint( " %wZ\n",
BASE_READ_REMOTE_STR(FileNameMapping->Name,TempStr)
);
AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->DefaultAppNameMapping;
if (AppNameMapping != NULL) {
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
DbgPrint( " " );
BaseDllPrintMappingTarget( VarNameMapping );
}
AppNameMapping = (PINIFILE_MAPPING_APPNAME)FileNameMapping->ApplicationNames;
while (AppNameMapping) {
BASE_READ_REMOTE_STR_TEMP(TempStr);
DbgPrint( " %wZ\n",
BASE_READ_REMOTE_STR(AppNameMapping->Name,TempStr)
);
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping;
if (VarNameMapping != NULL) {
DbgPrint( " " );
BaseDllPrintMappingTarget( VarNameMapping );
}
VarNameMapping = (PINIFILE_MAPPING_VARNAME)AppNameMapping->VariableNames;
while (VarNameMapping) {
BASE_READ_REMOTE_STR_TEMP(TempStr);
DbgPrint( " %wZ ",
BASE_READ_REMOTE_STR(VarNameMapping->Name, TempStr) );
BaseDllPrintMappingTarget( VarNameMapping );
VarNameMapping = (PINIFILE_MAPPING_VARNAME)VarNameMapping->Next;
}
AppNameMapping = (PINIFILE_MAPPING_APPNAME)AppNameMapping->Next;
}
FileNameMapping = (PINIFILE_MAPPING_FILENAME)FileNameMapping->Next;
}
return;
}
VOID
BaseDllPrintMappingTarget(
IN PINIFILE_MAPPING_VARNAME VarNameMapping
)
{
DbgPrint( "= " );
if (VarNameMapping->MappingFlags &INIFILE_MAPPING_WRITE_TO_INIFILE_TOO) {
DbgPrint( "!" );
}
if (VarNameMapping->MappingFlags &INIFILE_MAPPING_INIT_FROM_INIFILE) {
DbgPrint( "#" );
}
if (VarNameMapping->MappingFlags &INIFILE_MAPPING_READ_FROM_REGISTRY_ONLY) {
DbgPrint( "@" );
}
if (VarNameMapping->MappingFlags &INIFILE_MAPPING_USER_RELATIVE) {
DbgPrint( "USR:" );
}
if (VarNameMapping->MappingFlags &INIFILE_MAPPING_SOFTWARE_RELATIVE) {
DbgPrint( "SYS:" );
}
if (VarNameMapping->MappingTarget) {
BASE_READ_REMOTE_STR_TEMP(TempStr);
DbgPrint( "%wZ",
BASE_READ_REMOTE_STR((((PINIFILE_MAPPING_TARGET)(VarNameMapping->MappingTarget))->RegistryPath), TempStr)
);
}
if (VarNameMapping->MappingFlags &INIFILE_MAPPING_APPEND_BASE_NAME) {
DbgPrint( " (Append Base Name)" );
}
if (VarNameMapping->MappingFlags &INIFILE_MAPPING_APPEND_APPLICATION_NAME) {
DbgPrint( " (Append App Name)" );
}
DbgPrint( "\n" );
}
#endif // DBG