reactos/drivers/filesystems/cdfs/misc.c
Timo Kreuzer 912ce51ae6 [CMAKE]
Sync with trunk head (r48826)

svn path=/branches/cmake-bringup/; revision=48831
2010-09-20 17:27:52 +00:00

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 */