mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
5eb25b5c24
svn path=/branches/audio-bringup/; revision=49478
233 lines
6.9 KiB
C
233 lines
6.9 KiB
C
/*
|
|
* ReactOS kernel
|
|
* Copyright (C) 2002, 2004 ReactOS Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
/* $Id$
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: services/fs/cdfs/misc.c
|
|
* PURPOSE: CDROM (ISO 9660) filesystem driver
|
|
* PROGRAMMER: Eric Kohl
|
|
* UPDATE HISTORY:
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include "cdfs.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
VOID
|
|
CdfsSwapString(PWCHAR Out,
|
|
PUCHAR In,
|
|
ULONG Count)
|
|
{
|
|
PUCHAR t = (PUCHAR)Out;
|
|
ULONG i;
|
|
|
|
for (i = 0; i < Count; i += 2)
|
|
{
|
|
t[i] = In[i+1];
|
|
t[i+1] = In[i];
|
|
if (t[i+1] == 0 && t[i] == ';')
|
|
break;
|
|
}
|
|
if ((i>2)&&(t[i-2] == '.'))
|
|
{
|
|
t[i-2] = 0;
|
|
t[i-1] = 0;
|
|
}
|
|
t[i] = 0;
|
|
t[i+1] = 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
CdfsDateTimeToSystemTime(PFCB Fcb,
|
|
PLARGE_INTEGER SystemTime)
|
|
{
|
|
TIME_FIELDS TimeFields;
|
|
LARGE_INTEGER LocalTime;
|
|
|
|
TimeFields.Milliseconds = 0;
|
|
TimeFields.Second = Fcb->Entry.Second;
|
|
TimeFields.Minute = Fcb->Entry.Minute;
|
|
TimeFields.Hour = Fcb->Entry.Hour;
|
|
|
|
TimeFields.Day = Fcb->Entry.Day;
|
|
TimeFields.Month = Fcb->Entry.Month;
|
|
TimeFields.Year = Fcb->Entry.Year + 1900;
|
|
|
|
RtlTimeFieldsToTime(&TimeFields,
|
|
&LocalTime);
|
|
ExLocalTimeToSystemTime(&LocalTime, SystemTime);
|
|
}
|
|
|
|
|
|
VOID
|
|
CdfsFileFlagsToAttributes(PFCB Fcb,
|
|
PULONG FileAttributes)
|
|
{
|
|
/* FIXME: Fix attributes */
|
|
|
|
*FileAttributes = // FILE_ATTRIBUTE_READONLY |
|
|
((Fcb->Entry.FileFlags & FILE_FLAG_HIDDEN) ? FILE_ATTRIBUTE_HIDDEN : 0) |
|
|
((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : 0) |
|
|
((Fcb->Entry.FileFlags & FILE_FLAG_SYSTEM) ? FILE_ATTRIBUTE_SYSTEM : 0) |
|
|
((Fcb->Entry.FileFlags & FILE_FLAG_READONLY) ? FILE_ATTRIBUTE_READONLY : 0);
|
|
}
|
|
|
|
BOOLEAN
|
|
CdfsIsNameLegalDOS8Dot3(IN UNICODE_STRING FileName
|
|
)
|
|
{
|
|
ULONG i;
|
|
STRING DbcsName;
|
|
CHAR DbcsNameBuffer[12];
|
|
|
|
/* 8dot3 filename is max 12 length */
|
|
if (FileName.Length / sizeof(WCHAR) > 12)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < FileName.Length / sizeof(WCHAR) ; i++)
|
|
{
|
|
/* Don't allow spaces in FileName */
|
|
if (FileName.Buffer[i] == L' ')
|
|
return FALSE;
|
|
}
|
|
|
|
/* If FileName is finishing with a dot, remove it */
|
|
if (FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1] == '.')
|
|
{
|
|
FileName.Length -= sizeof(WCHAR);
|
|
}
|
|
|
|
/* Finally, convert the string to call the FsRtl function */
|
|
DbcsName.MaximumLength = 12;
|
|
DbcsName.Buffer = DbcsNameBuffer;
|
|
if (!NT_SUCCESS(RtlUnicodeStringToCountedOemString(&DbcsName,
|
|
&FileName,
|
|
FALSE )))
|
|
{
|
|
|
|
return FALSE;
|
|
}
|
|
return FsRtlIsFatDbcsLegal(DbcsName, FALSE, FALSE, FALSE);
|
|
}
|
|
|
|
VOID
|
|
CdfsShortNameCacheGet
|
|
(PFCB DirectoryFcb,
|
|
PLARGE_INTEGER StreamOffset,
|
|
PUNICODE_STRING LongName,
|
|
PUNICODE_STRING ShortName)
|
|
{
|
|
PLIST_ENTRY Entry;
|
|
PCDFS_SHORT_NAME ShortNameEntry;
|
|
GENERATE_NAME_CONTEXT Context = { 0 };
|
|
|
|
DPRINT("CdfsShortNameCacheGet(%I64u,%wZ)\n", StreamOffset->QuadPart, LongName);
|
|
|
|
/* Get the name list resource */
|
|
ExAcquireResourceExclusiveLite(&DirectoryFcb->NameListResource, TRUE);
|
|
|
|
/* Try to find the name in our cache */
|
|
for (Entry = DirectoryFcb->ShortNameList.Flink;
|
|
Entry != &DirectoryFcb->ShortNameList;
|
|
Entry = Entry->Flink)
|
|
{
|
|
ShortNameEntry = CONTAINING_RECORD(Entry, CDFS_SHORT_NAME, Entry);
|
|
if (ShortNameEntry->StreamOffset.QuadPart == StreamOffset->QuadPart)
|
|
{
|
|
/* Cache hit */
|
|
RtlCopyMemory
|
|
(ShortName->Buffer, ShortNameEntry->Name.Buffer,
|
|
ShortNameEntry->Name.Length);
|
|
ShortName->Length = ShortNameEntry->Name.Length;
|
|
ExReleaseResourceLite(&DirectoryFcb->NameListResource);
|
|
DPRINT("Yield short name %wZ from cache\n", ShortName);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Cache miss */
|
|
if (!CdfsIsNameLegalDOS8Dot3(*LongName))
|
|
{
|
|
RtlGenerate8dot3Name(LongName, FALSE, &Context, ShortName);
|
|
}
|
|
else
|
|
{
|
|
/* copy short name */
|
|
RtlUpcaseUnicodeString
|
|
(ShortName,
|
|
LongName,
|
|
FALSE);
|
|
}
|
|
|
|
DPRINT("Initial Guess %wZ\n", ShortName);
|
|
|
|
/* Make it unique by scanning the cache and bumping */
|
|
/* Note that incrementing the ambiguous name is enough, since we add new
|
|
* entries at the tail. We'll scan over all collisions. */
|
|
/* XXX could perform better. */
|
|
for (Entry = DirectoryFcb->ShortNameList.Flink;
|
|
Entry != &DirectoryFcb->ShortNameList;
|
|
Entry = Entry->Flink)
|
|
{
|
|
ShortNameEntry = CONTAINING_RECORD(Entry, CDFS_SHORT_NAME, Entry);
|
|
if (RtlCompareUnicodeString
|
|
(ShortName,
|
|
&ShortNameEntry->Name,
|
|
TRUE) == 0) /* Match */
|
|
{
|
|
RtlGenerate8dot3Name(LongName, FALSE, &Context, ShortName);
|
|
DPRINT("Collide; try %wZ\n", ShortName);
|
|
}
|
|
}
|
|
|
|
/* We've scanned over all entries and now have a unique one. Cache it. */
|
|
ShortNameEntry = ExAllocatePoolWithTag(PagedPool, sizeof(CDFS_SHORT_NAME), TAG_FCB);
|
|
if (!ShortNameEntry)
|
|
{
|
|
/* We couldn't cache it, but we can return it. We run the risk of
|
|
* generating a non-unique name later. */
|
|
ExReleaseResourceLite(&DirectoryFcb->NameListResource);
|
|
DPRINT1("Couldn't cache potentially clashing 8.3 name %wZ\n", ShortName);
|
|
return;
|
|
}
|
|
|
|
ShortNameEntry->StreamOffset = *StreamOffset;
|
|
ShortNameEntry->Name.Buffer = ShortNameEntry->NameBuffer;
|
|
ShortNameEntry->Name.Length = ShortName->Length;
|
|
ShortNameEntry->Name.MaximumLength = sizeof(ShortNameEntry->NameBuffer);
|
|
RtlCopyMemory
|
|
(ShortNameEntry->NameBuffer,
|
|
ShortName->Buffer,
|
|
ShortName->Length);
|
|
InsertTailList(&DirectoryFcb->ShortNameList, &ShortNameEntry->Entry);
|
|
ExReleaseResourceLite(&DirectoryFcb->NameListResource);
|
|
|
|
DPRINT("Returning short name %wZ for long name %wZ\n", ShortName, LongName);
|
|
}
|
|
|
|
/* EOF */
|