WindowsXP/Source/XPSP1/NT/sdktools/cntrtext/initodat/fileutl.c

544 lines
15 KiB
C
Raw Normal View History

2024-08-03 16:30:48 +02:00
/*++
Copyright (c) 1993-1994 Microsoft Corporation
Module Name:
fileutl.c
Abstract:
Routines for getting data from ini file
Author:
HonWah Chan (a-honwah) October, 1993
Revision History:
--*/
#include "initodat.h"
#include "strids.h"
#include "common.h"
#include "winerror.h"
NTSTATUS
DatReadMultiSzFile(
#ifdef FE_SB
IN UINT uCodePage,
#endif
IN PUNICODE_STRING FileName,
OUT PVOID *ValueBuffer,
OUT PULONG ValueLength
)
{
NTSTATUS Status;
UNICODE_STRING NtFileName;
PWSTR s;
UNICODE_STRING MultiSource;
UNICODE_STRING MultiValue;
REG_UNICODE_FILE MultiSzFile;
ULONG MultiSzFileSize;
if (ValueBuffer == NULL || ValueLength == NULL) {
return STATUS_INVALID_PARAMETER;
}
FileName->Buffer[ FileName->Length/sizeof(WCHAR) ] = UNICODE_NULL;
RtlDosPathNameToNtPathName_U( FileName->Buffer,
&NtFileName,
NULL,
NULL );
#ifdef FE_SB
Status = DatLoadAsciiFileAsUnicode( uCodePage, &NtFileName, &MultiSzFile );
#else
Status = DatLoadAsciiFileAsUnicode( &NtFileName, &MultiSzFile );
#endif
if (!NT_SUCCESS( Status )) {
return( Status );
}
MultiSzFileSize = (ULONG)(MultiSzFile.EndOfFile -
MultiSzFile.NextLine) * sizeof(WCHAR);
*ValueLength = 0;
*ValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0,
MultiSzFileSize);
if (* ValueBuffer == NULL) {
return STATUS_NO_MEMORY;
}
MultiSource.Buffer = MultiSzFile.NextLine;
if (MultiSzFileSize <= MAXUSHORT) {
MultiSource.Length =
MultiSource.MaximumLength = (USHORT)MultiSzFileSize;
} else {
MultiSource.Length =
MultiSource.MaximumLength = MAXUSHORT;
}
while (DatGetMultiString(&MultiSource, &MultiValue)) {
RtlMoveMemory( (PUCHAR)*ValueBuffer + *ValueLength,
MultiValue.Buffer,
MultiValue.Length );
*ValueLength += MultiValue.Length;
s = MultiSource.Buffer;
while ( *s != L'"' &&
*s != L',' &&
((s - MultiSource.Buffer) * sizeof(WCHAR)) <
MultiSource.Length ) s++;
if ( ((s - MultiSource.Buffer) * sizeof(WCHAR)) ==
MultiSource.Length ||
*s == L',' ||
*s == L';' ) {
((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] =
UNICODE_NULL;
*ValueLength += sizeof(UNICODE_NULL);
if ( *s == L';' ) {
break;
}
}
if ( (MultiSzFile.EndOfFile - MultiSource.Buffer) * sizeof(WCHAR) >=
MAXUSHORT ) {
MultiSource.Length =
MultiSource.MaximumLength = MAXUSHORT;
} else {
MultiSource.Length =
MultiSource.MaximumLength =
(USHORT)((MultiSzFile.EndOfFile - MultiSource.Buffer) *
sizeof(WCHAR));
}
}
((PWSTR)*ValueBuffer)[ *ValueLength / sizeof(WCHAR) ] = UNICODE_NULL;
*ValueLength += sizeof(UNICODE_NULL);
// Virtual memory for reading of MultiSzFile freed at process
// death?
return( TRUE );
}
NTSTATUS
DatLoadAsciiFileAsUnicode(
#ifdef FE_SB
IN UINT uCodePage,
#endif
IN PUNICODE_STRING FileName,
OUT PREG_UNICODE_FILE UnicodeFile
)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatus;
HANDLE File;
FILE_BASIC_INFORMATION FileDateTimeInfo;
FILE_STANDARD_INFORMATION FileInformation;
SIZE_T BufferSize;
ULONG i, i1, LineCount;
PVOID BufferBase;
PCHAR Src = NULL;
PCHAR Src1;
PWSTR Dst = NULL;
memset (&FileDateTimeInfo, 0, sizeof(FileDateTimeInfo));
InitializeObjectAttributes( &ObjectAttributes,
FileName,
OBJ_CASE_INSENSITIVE,
(HANDLE)NULL,
NULL
);
Status = NtOpenFile( &File,
SYNCHRONIZE | GENERIC_READ,
&ObjectAttributes,
&IoStatus,
FILE_SHARE_DELETE |
FILE_SHARE_READ |
FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT |
FILE_NON_DIRECTORY_FILE
);
if (!NT_SUCCESS( Status )) {
return( Status );
}
Status = NtQueryInformationFile( File,
&IoStatus,
(PVOID)&FileInformation,
sizeof( FileInformation ),
FileStandardInformation
);
if (NT_SUCCESS( Status )) {
if (FileInformation.EndOfFile.HighPart) {
Status = STATUS_BUFFER_OVERFLOW;
}
}
if (!NT_SUCCESS( Status )) {
NtClose( File );
return( Status );
}
#ifdef FE_SB
BufferSize = FileInformation.EndOfFile.LowPart * sizeof( WCHAR ) * 2;
#else
BufferSize = FileInformation.EndOfFile.LowPart * sizeof( WCHAR );
#endif
BufferSize += sizeof( UNICODE_NULL );
BufferBase = NULL;
Status = NtAllocateVirtualMemory( NtCurrentProcess(),
(PVOID *)&BufferBase,
0,
&BufferSize,
MEM_COMMIT,
PAGE_READWRITE
);
if (NT_SUCCESS( Status )) {
Src = (PCHAR)BufferBase + ((FileInformation.EndOfFile.LowPart+1) & ~1);
Dst = (PWSTR)BufferBase;
Status = NtReadFile( File,
NULL,
NULL,
NULL,
&IoStatus,
Src,
FileInformation.EndOfFile.LowPart,
NULL,
NULL
);
if (NT_SUCCESS( Status )) {
Status = IoStatus.Status;
if (NT_SUCCESS( Status )) {
if (IoStatus.Information != FileInformation.EndOfFile.LowPart) {
Status = STATUS_END_OF_FILE;
}
else {
Status = NtQueryInformationFile( File,
&IoStatus,
(PVOID)&FileDateTimeInfo,
sizeof( FileDateTimeInfo ),
FileBasicInformation
);
}
}
}
if (!NT_SUCCESS( Status )) {
NtFreeVirtualMemory( NtCurrentProcess(),
(PVOID *)&BufferBase,
&BufferSize,
MEM_RELEASE
);
}
}
NtClose( File );
if (!NT_SUCCESS( Status )) {
return( Status );
}
i = 0;
while (i < FileInformation.EndOfFile.LowPart) {
if (i > 1 && (Src[-2] == ' ' || Src[-2] == '\t') &&
Src[-1] == '\\' && (*Src == '\r' || *Src == '\n')
) {
if (Dst[-1] == L'\\') {
--Dst;
}
while (Dst > (PWSTR)BufferBase) {
if (Dst[-1] > L' ') {
break;
}
Dst--;
}
LineCount = 0;
while (i < FileInformation.EndOfFile.LowPart) {
if (*Src == '\n') {
i++;
Src++;
LineCount++;
}
else
if (*Src == '\r' &&
(i+1) < FileInformation.EndOfFile.LowPart &&
Src[ 1 ] == '\n'
) {
i += 2;
Src += 2;
LineCount++;
}
else {
break;
}
}
if (LineCount > 1) {
*Dst++ = L'\n';
}
else {
*Dst++ = L' ';
while (i < FileInformation.EndOfFile.LowPart && (*Src == ' ' || *Src == '\t')) {
i++;
Src++;
}
}
if (i >= FileInformation.EndOfFile.LowPart) {
break;
}
}
else
if ((*Src == '\r' && Src[1] == '\n') || *Src == '\n') {
#pragma warning ( disable : 4127 )
while (TRUE) {
while (i < FileInformation.EndOfFile.LowPart && (*Src == '\r' || *Src == '\n')) {
i++;
Src++;
}
Src1 = Src;
i1 = i;
while (i1 < FileInformation.EndOfFile.LowPart && (*Src1 == ' ' || *Src1 == '\t')) {
i1++;
Src1++;
}
if (i1 < FileInformation.EndOfFile.LowPart &&
(*Src1 == '\r' && Src1[1] == '\n') || *Src1 == '\n'
) {
Src = Src1;
i = i1;
}
else {
break;
}
}
#pragma warning ( default : 4127 )
*Dst++ = L'\n';
}
else {
#ifdef FE_SB
WCHAR UnicodeCharacter;
LONG cbCharSize = IsDBCSLeadByteEx(uCodePage,*Src) ? 2 : 1;
if ( MultiByteToWideChar(
uCodePage,
0,
Src,
cbCharSize,
&UnicodeCharacter,
1) == 0) {
//
// Check for error - The only time this will happen is if there is
// a leadbyte without a trail byte.
//
UnicodeCharacter = 0x0020;
}
i += cbCharSize;
Src += cbCharSize;
*Dst++ = UnicodeCharacter;
#else
i++;
*Dst++ = RtlAnsiCharToUnicodeChar( &Src );
#endif
}
}
if (NT_SUCCESS( Status )) {
*Dst = UNICODE_NULL;
UnicodeFile->FileContents = BufferBase;
UnicodeFile->EndOfFile = Dst;
UnicodeFile->BeginLine = NULL;
UnicodeFile->EndOfLine = NULL;
UnicodeFile->NextLine = BufferBase;
UnicodeFile->LastWriteTime = FileDateTimeInfo.LastWriteTime;
}
else {
NtFreeVirtualMemory( NtCurrentProcess(),
(PVOID *)&BufferBase,
&BufferSize,
MEM_RELEASE
);
}
return( Status );
}
//
// Define an upcase macro for temporary use by the upcase routines
//
#define upcase(C) (WCHAR )(((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C)))
BOOLEAN
DatGetMultiString(
IN OUT PUNICODE_STRING ValueString,
OUT PUNICODE_STRING MultiString
)
/*++
Routine Description:
This routine parses multi-strings of the form
"foo" "bar" "bletch"
Each time it is called, it strips the first string in quotes from
the input string, and returns it as the multi-string.
INPUT ValueString: "foo" "bar" "bletch"
OUTPUT ValueString: "bar" "bletch"
MultiString: foo
Arguments:
ValueString - Supplies the string from which the multi-string will be
parsed
- Returns the remaining string after the multi-string is
removed
MultiString - Returns the multi-string removed from ValueString
Return Value:
TRUE - multi-string found and removed.
FALSE - no more multi-strings remaining.
--*/
{
//
// Find the first quote mark.
//
while ((*(ValueString->Buffer) != L'"') &&
(ValueString->Length > 0)) {
++ValueString->Buffer;
ValueString->Length -= sizeof(WCHAR);
ValueString->MaximumLength -= sizeof(WCHAR);
}
if (ValueString->Length == 0) {
return(FALSE);
}
//
// We have found the start of the multi-string. Now find the end,
// building up our return MultiString as we go.
//
++ValueString->Buffer;
ValueString->Length -= sizeof(WCHAR);
ValueString->MaximumLength -= sizeof(WCHAR);
MultiString->Buffer = ValueString->Buffer;
MultiString->Length = 0;
MultiString->MaximumLength = 0;
while ((*(ValueString->Buffer) != L'"') &&
(ValueString->Length > 0)) {
++ValueString->Buffer;
ValueString->Length -= sizeof(WCHAR);
ValueString->MaximumLength -= sizeof(WCHAR);
MultiString->Length += sizeof(WCHAR);
MultiString->MaximumLength += sizeof(WCHAR);
}
if (ValueString->Length == 0) {
return(FALSE);
}
++ValueString->Buffer;
ValueString->Length -= sizeof(WCHAR);
ValueString->MaximumLength -= sizeof(WCHAR);
return( TRUE );
}
#define EXTENSION_DELIMITER TEXT('.')
LPTSTR
FindFileExtension (
IN PUNICODE_STRING FileName
)
{
LPTSTR lpszDelimiter ;
lpszDelimiter = _tcsrchr ((LPCTSTR)FileName->Buffer, (TCHAR)EXTENSION_DELIMITER) ;
if (lpszDelimiter)
return lpszDelimiter;
else
return (LPTSTR)((PBYTE)FileName->Buffer + FileName->Length - sizeof(WCHAR));
}
BOOL
OutputIniData (
IN PUNICODE_STRING FileName,
IN LPTSTR OutFileCandidate,
IN PVOID pValueBuffer,
IN ULONG ValueLength
)
{
HANDLE hOutFile = NULL;
LPTSTR lpExtension = NULL;
DWORD nAmtWritten ;
BOOL bSuccess ;
DWORD ErrorCode ;
// If output file not specified, derive from input file name
if (! lstrcmp(OutFileCandidate, (LPCWSTR)L"\0")) {
lpExtension = FindFileExtension (FileName);
lstrcpy (lpExtension, (LPCTSTR)TEXT(".dat"));
lstrcpy (OutFileCandidate, FileName->Buffer);
}
hOutFile = (HANDLE) CreateFile (
OutFileCandidate,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if ((hOutFile == NULL) || (hOutFile == INVALID_HANDLE_VALUE)) {
ErrorCode = GetLastError();
printf (GetFormatResource(LC_CANT_CREATE), ErrorCode);
if (ErrorCode == ERROR_ACCESS_DENIED)
printf ("%ws\n", GetStringResource(LC_ACCESS_DENIED));
return FALSE;
}
bSuccess = WriteFile (
hOutFile,
pValueBuffer,
ValueLength,
&nAmtWritten,
NULL) ;
bSuccess = bSuccess && (nAmtWritten == ValueLength) ;
CloseHandle( hOutFile );
if (!bSuccess) {
ErrorCode = GetLastError();
printf (GetFormatResource(LC_CANT_WRITE), ErrorCode);
if (ErrorCode == ERROR_DISK_FULL)
printf ("%ws\n", GetStringResource(LC_DISK_FULL));
}
return bSuccess;
}