544 lines
15 KiB
C
544 lines
15 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|