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.
 
 
 
 
 
 

454 lines
15 KiB

/*++
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
UINT uCodePage,
#endif
PUNICODE_STRING FileName,
PVOID * ValueBuffer,
PULONG ValueLength
)
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING NtFileName;
LPWSTR s;
UNICODE_STRING MultiSource;
UNICODE_STRING MultiValue;
REG_UNICODE_FILE MultiSzFile;
ULONG MultiSzFileSize;
ZeroMemory(& NtFileName, sizeof(UNICODE_STRING));
if (ValueBuffer == NULL || ValueLength == NULL) {
Status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
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)) {
goto Cleanup;
}
MultiSzFileSize = (ULONG) (MultiSzFile.EndOfFile - MultiSzFile.NextLine + 1);
* ValueLength = 0;
* ValueBuffer = ALLOCMEM((MultiSzFileSize + 2) * sizeof(WCHAR));
if (* ValueBuffer == NULL) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
MultiSource.Buffer = MultiSzFile.NextLine;
if (MultiSzFileSize * sizeof(WCHAR) <= MAXUSHORT) {
MultiSource.Length = MultiSource.MaximumLength = (USHORT) MultiSzFileSize * sizeof(WCHAR);
}
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?
Cleanup:
if (NtFileName.Buffer != NULL) FREEMEM(NtFileName.Buffer);
if (MultiSzFile.FileContents != NULL) FREEMEM(MultiSzFile.FileContents);
return Status;
}
NTSTATUS
DatLoadAsciiFileAsUnicode(
#ifdef FE_SB
UINT uCodePage,
#endif
PUNICODE_STRING FileName,
PREG_UNICODE_FILE UnicodeFile
)
{
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatus;
HANDLE File = NULL;
FILE_BASIC_INFORMATION FileDateTimeInfo;
FILE_STANDARD_INFORMATION FileInformation;
SIZE_T BufferSize;
ULONG i, i1, LineCount;
PVOID BufferBase = NULL;
LPSTR szSource = NULL;
LPSTR Src = NULL;
LPSTR Src1;
LPWSTR Dst = NULL;
ZeroMemory(& FileDateTimeInfo, sizeof(FILE_BASIC_INFORMATION));
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)) {
goto Cleanup;
}
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)) {
goto Cleanup;
}
#ifdef FE_SB
BufferSize = FileInformation.EndOfFile.LowPart + 1;
#else
BufferSize = FileInformation.EndOfFile.LowPart + 1;
#endif
szSource = ALLOCMEM(BufferSize + 2);
BufferBase = ALLOCMEM((BufferSize + 2) * sizeof(WCHAR));
if (BufferBase != NULL && szSource != NULL) {
Src = (LPSTR) szSource;
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);
}
}
}
}
else {
Status = STATUS_NO_MEMORY;
}
if (! NT_SUCCESS(Status)) {
goto Cleanup;
}
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') {
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;
}
}
* 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;
}
Cleanup:
if (! NT_SUCCESS(Status)) {
if (BufferBase != NULL) FREEMEM(BufferBase);
}
if (szSource != NULL) FREEMEM(szSource);
if (File != NULL) NtClose(File);
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(
PUNICODE_STRING ValueString,
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.
--*/
{
BOOLEAN bReturn = FALSE;
DWORD dwLength = ValueString->Length / sizeof(WCHAR);
if (ValueString->Length != dwLength * sizeof(WCHAR)) {
// ValueString->Length should not be odd number, bail out.
goto Cleanup;
}
//
// Find the first quote mark.
//
while ((ValueString->Length > 0) && (* (ValueString->Buffer) != L'"')) {
++ ValueString->Buffer;
ValueString->Length -= sizeof(WCHAR);
ValueString->MaximumLength -= sizeof(WCHAR);
}
if (ValueString->Length == 0) {
goto Cleanup;
}
//
// 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->Length > 0) && (* (ValueString->Buffer) != L'"')) {
++ ValueString->Buffer;
ValueString->Length -= sizeof(WCHAR);
ValueString->MaximumLength -= sizeof(WCHAR);
MultiString->Length += sizeof(WCHAR);
MultiString->MaximumLength += sizeof(WCHAR);
}
if (ValueString->Length == 0) {
goto Cleanup;
}
++ ValueString->Buffer;
ValueString->Length -= sizeof(WCHAR);
ValueString->MaximumLength -= sizeof(WCHAR);
bReturn = TRUE;
Cleanup:
return bReturn;
}
#define EXTENSION_DELIMITER L'.'
BOOL
OutputIniData(
PUNICODE_STRING FileName,
LPWSTR OutFileCandidate,
DWORD dwOutFile,
PVOID pValueBuffer,
ULONG ValueLength
)
{
HANDLE hOutFile = NULL;
LPWSTR lpExtension = NULL;
DWORD nAmtWritten;
BOOL bSuccess = FALSE;
DWORD ErrorCode;
HRESULT hError;
// If output file not specified, derive from input file name
if (OutFileCandidate[0] == L'\0') {
if ((DWORD) (lstrlenW(FileName->Buffer) + 5) <= dwOutFile) {
LPWSTR lpDelimiter;
hError = StringCchCopyW(OutFileCandidate, dwOutFile, FileName->Buffer);
if (FAILED(hError)) goto Cleanup;
lpDelimiter = wcschr(OutFileCandidate, EXTENSION_DELIMITER);
if (lpDelimiter != NULL) {
nAmtWritten = dwOutFile - ((DWORD) (lpDelimiter - OutFileCandidate));
hError = StringCchCopyW(lpDelimiter, nAmtWritten, L".dat");
if (FAILED(hError)) goto Cleanup;
}
else {
hError = StringCchCatW(OutFileCandidate, dwOutFile, L".dat");
if (FAILED(hError)) goto Cleanup;
}
}
else {
goto Cleanup;
}
}
hOutFile = (HANDLE) CreateFileW(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));
goto Cleanup;
}
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));
}
Cleanup:
return bSuccess;
}