windows-nt/Source/XPSP1/NT/net/sfm/afp/server/macansi.c
2020-09-26 16:20:57 +08:00

926 lines
22 KiB
C

/*
Copyright (c) 1992 Microsoft Corporation
Module Name:
macansi.c
Abstract:
This module contains conversion routines from macintosh ansi to unicode
and vice versa
Author:
Jameel Hyder (microsoft!jameelh)
Revision History:
10 Jul 1992 Initial Version
Notes: Tab stop: 4
--*/
#define _MACANSI_LOCALS
#define FILENUM FILE_MACANSI
#include <afp.h>
#define FlagOn(x, y) ((x) & (y))
#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, AfpMacAnsiInit)
#pragma alloc_text( PAGE, AfpMacAnsiDeInit)
#pragma alloc_text( PAGE, AfpGetMacCodePage)
#pragma alloc_text( PAGE, AfpConvertStringToUnicode)
#pragma alloc_text( PAGE, AfpConvertStringToAnsi)
#pragma alloc_text( PAGE, AfpConvertStringToMungedUnicode)
#pragma alloc_text( PAGE, AfpConvertMungedUnicodeToAnsi)
#pragma alloc_text( PAGE, AfpConvertMacAnsiToHostAnsi)
#pragma alloc_text( PAGE, AfpConvertHostAnsiToMacAnsi)
#pragma alloc_text( PAGE, AfpIsLegalShortname)
#pragma alloc_text( PAGE, AfpIsProperSubstring)
#endif
/*** AfpMacAnsiInit
*
* Initialize the code page for macintosh ANSI.
*/
NTSTATUS
AfpMacAnsiInit(
VOID
)
{
NTSTATUS Status = STATUS_SUCCESS;
int i, SizeAltTbl;
// Allocate the table for the alternate unicode characters
SizeAltTbl = (AFP_INVALID_HIGH - AFP_INITIAL_INVALID_HIGH + 1) * sizeof(WCHAR);
if ((afpAltUnicodeTable = (PWCHAR)AfpAllocZeroedPagedMemory(SizeAltTbl)) == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
// Allocate and initialize the table for the reverse mapping table
SizeAltTbl = (AFP_INVALID_HIGH - AFP_INITIAL_INVALID_HIGH + 1)*sizeof(BYTE);
if ((afpAltAnsiTable = (PBYTE)AfpAllocZeroedPagedMemory(SizeAltTbl)) == NULL)
{
AfpFreeMemory(afpAltUnicodeTable);
afpAltUnicodeTable = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
// Initialize the tables for the alternate unicode characters
for (i = AFP_INITIAL_INVALID_HIGH + 1; i <= AFP_INVALID_HIGH; i++)
{
if (!FsRtlIsAnsiCharacterLegalNtfs((BYTE)i, False))
{
afpAltUnicodeTable[i-AFP_INITIAL_INVALID_HIGH] = afpLastAltChar;
afpAltAnsiTable[afpLastAltChar - (AFP_ALT_UNICODE_BASE + AFP_INITIAL_INVALID_HIGH)] = (BYTE)i;
afpLastAltChar++;
}
}
// HACK: Also add in a couple of codes for 'space' and 'period' - they are only
// used if they are at end. Another one for the 'apple' character
AfpMungedUnicodeSpace =
afpAltUnicodeTable[ANSI_SPACE-AFP_INITIAL_INVALID_HIGH] = afpLastAltChar;
afpAltAnsiTable[afpLastAltChar - (AFP_ALT_UNICODE_BASE + AFP_INITIAL_INVALID_HIGH)] = ANSI_SPACE;
afpLastAltChar ++;
AfpMungedUnicodePeriod =
afpAltUnicodeTable[ANSI_PERIOD-AFP_INITIAL_INVALID_HIGH] = afpLastAltChar;
afpAltAnsiTable[afpLastAltChar - (AFP_ALT_UNICODE_BASE + AFP_INITIAL_INVALID_HIGH)] = ANSI_PERIOD;
afpLastAltChar ++;
// This is yet another hack
afpAppleUnicodeChar = afpLastAltChar;
afpLastAltChar ++;
RtlZeroMemory(&AfpMacCPTableInfo, sizeof(AfpMacCPTableInfo));
return Status;
}
/*** AfpMacAnsiDeInit
*
* De-initialize the code page for macintosh ANSI.
*/
VOID
AfpMacAnsiDeInit(
VOID
)
{
PAGED_CODE( );
if (AfpTranslationTable != NULL)
{
AfpFreeMemory(AfpTranslationTable);
}
if (AfpCasePreserveTranslationTable != NULL)
{
AfpFreeMemory(AfpCasePreserveTranslationTable);
}
if (AfpRevTranslationTable != NULL)
{
AfpFreeMemory(AfpRevTranslationTable);
}
if (afpAltUnicodeTable != NULL)
{
AfpFreeMemory(afpAltUnicodeTable);
}
if (afpAltAnsiTable != NULL)
{
AfpFreeMemory(afpAltAnsiTable);
}
if (AfpMacCPBaseAddress != NULL)
{
AfpFreeMemory(AfpMacCPBaseAddress);
}
}
/*** AfpConvertStringToUnicode
*
* Convert a Mac ANSI string to a unicode string.
*/
AFPSTATUS FASTCALL
AfpConvertStringToUnicode(
IN PANSI_STRING pAnsiString,
OUT PUNICODE_STRING pUnicodeString
)
{
NTSTATUS Status;
ULONG ulCast;
PAGED_CODE( );
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
Status = RtlCustomCPToUnicodeN(&AfpMacCPTableInfo,
pUnicodeString->Buffer,
pUnicodeString->MaximumLength,
&ulCast, pAnsiString->Buffer,
pAnsiString->Length);
if (NT_SUCCESS(Status))
pUnicodeString->Length = (USHORT)ulCast;
else
{
AFPLOG_ERROR(AFPSRVMSG_MACANSI2UNICODE, Status, NULL, 0, NULL);
}
return Status;
}
/*** AfpConvertStringToAnsi
*
* Convert a unicode string to a Mac ANSI string.
*/
AFPSTATUS FASTCALL
AfpConvertStringToAnsi(
IN PUNICODE_STRING pUnicodeString,
OUT PANSI_STRING pAnsiString
)
{
NTSTATUS Status;
ULONG ulCast;
PAGED_CODE( );
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
Status = RtlUnicodeToCustomCPN(&AfpMacCPTableInfo,
pAnsiString->Buffer,
pAnsiString->MaximumLength,
&ulCast, pUnicodeString->Buffer,
pUnicodeString->Length);
if (NT_SUCCESS(Status))
pAnsiString->Length = (USHORT)ulCast;
else
{
AFPLOG_ERROR(AFPSRVMSG_UNICODE2MACANSI, Status, NULL, 0, NULL);
}
return Status;
}
/*** AfpConvertStringToMungedUnicode
*
* Convert a Mac ANSI string to a unicode string. If there are any characters
* in the ansi string which are invalid filesystem (NTFS) characters, then
* map them to alternate unicode characters based on the table.
*/
AFPSTATUS FASTCALL
AfpConvertStringToMungedUnicode(
IN PANSI_STRING pAnsiString,
OUT PUNICODE_STRING pUnicodeString
)
{
USHORT i, len;
BYTE c;
NTSTATUS Status;
ULONG ulCast;
PWCHAR pWBuf;
PAGED_CODE( );
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
ASSERT(afpAltUnicodeTable != NULL);
Status = RtlCustomCPToUnicodeN(&AfpMacCPTableInfo,
pUnicodeString->Buffer,
pUnicodeString->MaximumLength,
&ulCast,
pAnsiString->Buffer,
pAnsiString->Length);
if (NT_SUCCESS(Status))
pUnicodeString->Length = (USHORT)ulCast;
else
{
AFPLOG_ERROR(AFPSRVMSG_MACANSI2UNICODE, Status, NULL, 0, NULL);
return Status;
}
// Walk the ANSI string looking for the invalid characters and map it
// to the alternate set
for (i = 0, len = pAnsiString->Length, pWBuf = pUnicodeString->Buffer;
i < len;
i++, pWBuf ++)
{
c = pAnsiString->Buffer[i];
if (c == ANSI_APPLE_CHAR)
*pWBuf = afpAppleUnicodeChar;
else if (c < AFP_INITIAL_INVALID_HIGH)
*pWBuf = c + AFP_ALT_UNICODE_BASE;
else if (!FsRtlIsAnsiCharacterLegalNtfs(c, False))
{
ASSERT (c <= AFP_INVALID_HIGH);
*pWBuf = afpAltUnicodeTable[c - AFP_INITIAL_INVALID_HIGH];
}
/* MSKK eichim, Appended to handle DBCS trailing 0x5c, 03/16/95 */
#ifdef DBCS
if (FsRtlIsLeadDbcsCharacter(c))
i++;
#endif // DBCS
}
// HACK: Make sure the last character in the name is not a 'space' or a '.'
c = pAnsiString->Buffer[pAnsiString->Length - 1];
if ((c == ANSI_SPACE) || (c == ANSI_PERIOD))
/* MSKK hideyukn, Unicode char length not eqaul to ansi byte length in DBCS, 06/30/95 */
#ifdef DBCS
pUnicodeString->Buffer[(pUnicodeString->Length/sizeof(WCHAR)) - 1]
= afpAltUnicodeTable[c - AFP_INITIAL_INVALID_HIGH];
#else
pUnicodeString->Buffer[len - 1] = afpAltUnicodeTable[c - AFP_INITIAL_INVALID_HIGH];
#endif // DBCS
return STATUS_SUCCESS;
}
/*** AfpConvertMungedUnicodeToAnsi
*
* Convert a unicode string with possible alternate unicode characters
* to Mac Ansi.
* This is inverse of AfpConvertStringToMungedUnicode().
*/
NTSTATUS FASTCALL
AfpConvertMungedUnicodeToAnsi(
IN PUNICODE_STRING pUnicodeString,
OUT PANSI_STRING pAnsiString
)
{
USHORT i, len;
WCHAR wc;
NTSTATUS Status;
ULONG ulCast;
PBYTE pABuf;
PAGED_CODE( );
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
Status = RtlUnicodeToCustomCPN(&AfpMacCPTableInfo,
pAnsiString->Buffer,
pAnsiString->MaximumLength,
&ulCast, pUnicodeString->Buffer,
pUnicodeString->Length);
if (NT_SUCCESS(Status))
pAnsiString->Length = (USHORT)ulCast;
else
{
AFPLOG_ERROR(AFPSRVMSG_UNICODE2MACANSI, Status, NULL, 0, NULL);
}
// Walk the Unicode string looking for alternate unicode chars and
// replacing the ansi equivalents by the real ansi characters.
for (i = 0, len = pUnicodeString->Length/(USHORT)sizeof(WCHAR), pABuf = pAnsiString->Buffer;
i < len;
i++, pABuf++)
{
wc = pUnicodeString->Buffer[i];
if (wc == afpAppleUnicodeChar)
*pABuf = ANSI_APPLE_CHAR;
else if ((wc >= AFP_ALT_UNICODE_BASE) && (wc < afpLastAltChar))
{
wc -= AFP_ALT_UNICODE_BASE;
if (wc < AFP_INITIAL_INVALID_HIGH)
*pABuf = (BYTE)wc;
else *pABuf = afpAltAnsiTable[wc - AFP_INITIAL_INVALID_HIGH];
}
/* MSKK hideyukn, Unicode char length not eqaul to ansi byte length in DBCS, 06/30/95 */
#ifdef DBCS
if (FsRtlIsLeadDbcsCharacter(*pABuf))
pABuf++;
#endif // DBCS
}
return Status;
}
/*** AfpConvertMacAnsiToHostAnsi
*
* Convert a Mac ansi string to its host counterpart in uppercase OEM codepage.
* (in place). The name of this routine is misleading as a late bugfix was
* made to change the codepage used, but the name of the routine didn't change
* so none of the calling code had to be changed. It should really be called
* AfpConvertMacAnsiToUpcaseOem. This routine is only called to uppercase
* mac passwords for logon and changepassword.
*
*/
AFPSTATUS FASTCALL
AfpConvertMacAnsiToHostAnsi(
IN OUT PANSI_STRING pAnsiString
)
{
LONG i, Len;
BYTE *pBuf;
PAGED_CODE( );
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
// ASSERT (AfpTranslationTable != NULL);
ASSERT (AfpCasePreserveTranslationTable != NULL);
Len = pAnsiString->Length;
pBuf = pAnsiString->Buffer;
for (i = 0; i < Len; i++, pBuf++)
{
/* MSKK NaotoN Appended to handle DBCS Mac path name 11/10/93 */
#ifdef DBCS
if (FsRtlIsLeadDbcsCharacter( *pBuf )) {
i++ ;
pBuf++ ;
}
else
#endif // DBCS
*pBuf = AfpCasePreserveTranslationTable[*pBuf];
}
return AFP_ERR_NONE;
}
/*** AfpConvertHostAnsiToMacAnsi
*
* Convert a host unicode string to its mac counterpart in place.
* Only characters <= 0x20 and >= 0x80 are translated.
*
* NOTE: This is extremely hacky and intended for translating messages only.
*/
VOID FASTCALL
AfpConvertHostAnsiToMacAnsi(
IN OUT PANSI_STRING pAnsiString
)
{
LONG i, Len;
BYTE c, *pBuf;
PAGED_CODE( );
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
ASSERT (AfpRevTranslationTable != NULL);
Len = pAnsiString->Length;
pBuf = pAnsiString->Buffer;
for (i = 0; i < Len; i++, pBuf++)
{
c = *pBuf;
/* MSKK NaotoN Appended to skip if Kanji 12/17/93 */
#ifdef DBCS
if (FsRtlIsLeadDbcsCharacter( c )) {
i++ ;
pBuf++ ;
}
else
#endif // DBCS
if (c < 0x20)
{
*pBuf = AfpRevTranslationTable[c];
}
else if (c >= 0x80)
{
*pBuf = AfpRevTranslationTable[c-(0x80-0x20)];
}
}
}
/*** AfpEqualUnicodeString
*
* The AfpEqualUnicodeString function compares two counted unicode
* strings for equality using case SENSITIVE compare. This routine
* exists because it must be called at DPC level by the volume.c code
* for comparing 2 non-paged strings, and the RtlEqualUnicodeString
* routine that we would normally call is pageable code.
*
* Note that case INSENSITIVE compare would require accessing
* paged up-case table info, and therefore could not be done at DPC level.
*
* Arguments:
* String1 - Pointer to the first string.
* String2 - Pointer to the second string.
*
* Return Value:
* True if String1 equals String2 and False otherwise.
*
* Note: This is called at DPC level from volume.c and must not be made
* a pageable routine.
*/
BOOLEAN FASTCALL
AfpEqualUnicodeString(
IN PUNICODE_STRING String1,
IN PUNICODE_STRING String2
)
{
WCHAR *s1, *s2;
USHORT n1, n2;
n1 = (USHORT)(String1->Length/sizeof(WCHAR));
n2 = (USHORT)(String2->Length/sizeof(WCHAR));
if (n1 != n2)
{
return False;
}
s1 = String1->Buffer;
s2 = String2->Buffer;
while (n1--)
{
if (*s1++ != *s2++)
{
return False;
}
}
return True;
}
/*** AfpPrefixUnicodeString
*
* The AfpPrefixUnicodeString function determines if the String1
* counted string parameter is a prefix of the String2 counted string
* parameter using case SENSITIVE compare. This routine exists because it
* must be called at DPC level by the volume.c code for comparing
* two non-paged strings, and the RtlPrefixUnicodeString routine that we
* would normally call is pageable code.
*
* Note that case INSENSITIVE compare would require accessing
* paged up-case table info, and therefore could not be done at DPC level.
*
* Arguments:
* String1 - Pointer to the first unicode string.
* String2 - Pointer to the second unicode string.
*
* Return Value:
* True if String1 equals a prefix of String2 and False otherwise.
*
* Note: This is called at DPC level from volume.c and must not be made
* a pageable routine.
*/
BOOLEAN FASTCALL
AfpPrefixUnicodeString(
IN PUNICODE_STRING String1,
IN PUNICODE_STRING String2
)
{
PWSTR s1, s2;
ULONG n;
WCHAR c1, c2;
if (String2->Length < String1->Length)
{
return False;
}
s1 = String1->Buffer;
s2 = String2->Buffer;
n = String1->Length/sizeof(WCHAR);
while (n--)
{
c1 = *s1++;
c2 = *s2++;
if (c1 != c2)
{
return False;
}
}
return True;
}
/*** AfpGetMacCodePage
*
* Open the default macintosh codepage, create a section backed by that file,
* map a view to the section, and initialize the CodePage info structure
* that is used with the RtlCustomCP routines. Then create the Mac Ansi to
* Host Ansi mapping table.
*
* BEWARE!
* This routine may only be called ONCE! This will be called from the first
* admin call to ServerSetInfo. Therefore, there can be NO calls to the
* macansi routines within this module (except for MacAnsiInit) before that
* happens.
*/
NTSTATUS FASTCALL
AfpGetMacCodePage(
IN LPWSTR PathCP
)
{
NTSTATUS Status;
FILESYSHANDLE FileHandle;
UNICODE_STRING uPathCP, devPathCP;
ULONG viewsize = 0;
WCHAR UnicodeTable[2*AFP_XLAT_TABLE_SIZE];
BYTE AnsiTable[2*AFP_XLAT_TABLE_SIZE + 1];
UNICODE_STRING UnicodeString;
ANSI_STRING AnsiString;
LONG i;
PAGED_CODE( );
FileHandle.fsh_FileHandle = NULL;
UnicodeString.Length = AFP_XLAT_TABLE_SIZE * sizeof(WCHAR);
UnicodeString.MaximumLength = (AFP_XLAT_TABLE_SIZE + 1) * sizeof(WCHAR);
UnicodeString.Buffer = UnicodeTable;
RtlInitUnicodeString(&uPathCP, PathCP);
devPathCP.Length = 0;
devPathCP.MaximumLength = uPathCP.Length + DosDevices.Length + sizeof(WCHAR);
if ((devPathCP.Buffer = (PWSTR)AfpAllocPagedMemory(devPathCP.MaximumLength)) == NULL)
{
Status = STATUS_NO_MEMORY;
AFPLOG_ERROR(AFPSRVMSG_MAC_CODEPAGE, Status, NULL, 0, NULL);
return Status;
}
AfpCopyUnicodeString(&devPathCP, &DosDevices);
RtlAppendUnicodeStringToString(&devPathCP, &uPathCP);
do
{
FORKSIZE liCPlen;
LONG lCPlen, sizeread=0;
Status = AfpIoOpen(NULL,
AFP_STREAM_DATA,
FILEIO_OPEN_FILE,
&devPathCP,
FILEIO_ACCESS_READ,
FILEIO_DENY_NONE,
False,
&FileHandle);
if (!NT_SUCCESS(Status))
break;
if (!NT_SUCCESS(Status = AfpIoQuerySize(&FileHandle,
&liCPlen)))
break;
// NOTE: This assumes the codepage file will never be so big that
// the high bit of the LowPart of the size will be set
lCPlen = (LONG)liCPlen.LowPart;
if ((AfpMacCPBaseAddress = (PUSHORT)AfpAllocPagedMemory(lCPlen)) == NULL)
{
Status = STATUS_NO_MEMORY;
break;
}
Status = AfpIoRead(&FileHandle,
&LIZero,
lCPlen,
&sizeread,
(PBYTE)AfpMacCPBaseAddress);
AfpIoClose(&FileHandle);
if (!NT_SUCCESS(Status))
break;
if (sizeread != lCPlen)
{
Status = STATUS_UNSUCCESSFUL;
break;
}
RtlInitCodePageTable(AfpMacCPBaseAddress, &AfpMacCPTableInfo);
// Initialize mac ANSI to host upcase Oem translation table
// Start by allocating memory for the table and filling it up.
/* HitoshiT modify following line to keep Unicode translation table. 5/18/94 */
#ifdef DBCS
if ((AfpTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE*sizeof(USHORT) + 1)) == NULL)
#else
if ((AfpTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE + 1)) == NULL)
#endif // DBCS
{
Status = STATUS_NO_MEMORY;
break;
}
// Initialize mac ANSI to host Oem translation table
// Start by allocating memory for the table and filling it up.
#ifdef DBCS
if ((AfpCasePreserveTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE*sizeof(USHORT) + 1)) == NULL)
#else
if ((AfpCasePreserveTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE + 1)) == NULL)
#endif // DBCS
{
Status = STATUS_NO_MEMORY;
break;
}
for (i = 0; i < 2*AFP_XLAT_TABLE_SIZE; i++)
AnsiTable[i] = (BYTE)i;
// Now translate this from Mac ANSI to unicode
AnsiString.Length = 2*AFP_XLAT_TABLE_SIZE;
AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE + 1;
AnsiString.Buffer = AnsiTable;
UnicodeString.Length = 0;
UnicodeString.MaximumLength = sizeof(UnicodeTable);
UnicodeString.Buffer = UnicodeTable;
Status = AfpConvertStringToUnicode(&AnsiString, &UnicodeString);
if (!NT_SUCCESS(Status))
break;
// Now convert the entire table to uppercase host Oem Codepage
AnsiString.Length = 0;
/* HitoshiT modify following line to keep Unicode translation table 5/18/94 */
#ifdef DBCS
AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE * sizeof(USHORT) + 1;
#else
AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE + 1;
#endif // DBCS
AnsiString.Buffer = AfpTranslationTable;
Status = RtlUpcaseUnicodeStringToOemString(&AnsiString, &UnicodeString, False);
// Bug 342062
// Bug introduced due to RtlpDidUnicodeToOemWork check
// introduced in RtlUpcaseUnicodeStringToOemString
// We have characters which will be mapped to default characters
// and hence we should ignore STATUS_UNMAPPABLE_CHARACTER
if ((!NT_SUCCESS(Status))&&(Status!=STATUS_UNMAPPABLE_CHARACTER))
break;
// Now convert the entire table to host Oem Codepage
AnsiString.Length = 0;
#ifdef DBCS
AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE * sizeof(USHORT) + 1;
#else
AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE + 1;
#endif // DBCS
AnsiString.Buffer = AfpCasePreserveTranslationTable;
Status = RtlUnicodeStringToOemString(&AnsiString, &UnicodeString, False);
if ((!NT_SUCCESS(Status))&&(Status!=STATUS_UNMAPPABLE_CHARACTER))
break;
// Initialize host ANSI to mac ANSI translation table
// Start by allocating memory for the table and filling it up.
if ((AfpRevTranslationTable = AfpAllocPagedMemory(AFP_REV_XLAT_TABLE_SIZE + 1)) == NULL)
{
Status = STATUS_NO_MEMORY;
break;
}
for (i = 0; i < 0x20; i++)
AfpRevTranslationTable[i] = (BYTE)i;
for (i = 0x80; i < 256; i++)
AfpRevTranslationTable[i-(0x80-0x20)] = (BYTE)i;
// Get rid of the line feed char
AfpRevTranslationTable[0x0A] = 0;
// Now translate host ANSI to unicode
AnsiString.Length = AFP_REV_XLAT_TABLE_SIZE;
AnsiString.MaximumLength = AFP_REV_XLAT_TABLE_SIZE + 1;
AnsiString.Buffer = AfpRevTranslationTable;
UnicodeString.Length = 0;
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, False);
if (!NT_SUCCESS(Status))
break;
// and then translate from unicode to Mac ANSI
Status = AfpConvertStringToAnsi(&UnicodeString, &AnsiString);
} while (False);
if (!NT_SUCCESS(Status))
{
AFPLOG_ERROR(AFPSRVMSG_MAC_CODEPAGE, Status, NULL, 0, NULL);
if (AfpMacCPBaseAddress != NULL)
{
AfpFreeMemory(AfpMacCPBaseAddress);
AfpMacCPBaseAddress = NULL;
}
if (FileHandle.fsh_FileHandle != NULL)
{
AfpIoClose(&FileHandle);
}
if (AfpTranslationTable != NULL)
{
AfpFreeMemory(AfpTranslationTable);
AfpTranslationTable = NULL;
}
if (AfpCasePreserveTranslationTable != NULL)
{
AfpFreeMemory(AfpCasePreserveTranslationTable);
AfpCasePreserveTranslationTable = NULL;
}
if (AfpRevTranslationTable != NULL)
{
AfpFreeMemory(AfpRevTranslationTable);
AfpRevTranslationTable = NULL;
}
}
AfpFreeMemory(devPathCP.Buffer);
return Status;
}
/*** AfpIsLegalShortname
*
* Does a mac shortname conform to FAT 8.3 naming conventions?
*
*/
BOOLEAN FASTCALL
AfpIsLegalShortname(
IN PANSI_STRING pShortName // Mac ANSI string
)
{
return(FsRtlIsFatDbcsLegal(*pShortName, False, False, False));
}
/*** AfpIsProperSubstring
*
* This routine looks for the substring pSubString in pString. Both
* strings are in unicode, the comparison is done case insensitive
* (i.e. ignoring case). This is used by the AfpCatSearch code.
*
*/
BOOLEAN FASTCALL
AfpIsProperSubstring(
IN PUNICODE_STRING pString,
IN PUNICODE_STRING pSubString
)
{
WCHAR *s1, *s2, *ts1;
USHORT l1, l2, tl1;
WCHAR buf1[AFP_LONGNAME_LEN], buf2[AFP_LONGNAME_LEN];
UNICODE_STRING u1, u2;
PAGED_CODE( );
// see if this is a no-op?
if (pSubString->Length > pString->Length)
return False;
AfpSetEmptyUnicodeString(&u1, sizeof(buf1), buf1);
AfpSetEmptyUnicodeString(&u2, sizeof(buf2), buf2);
if (!NT_SUCCESS(RtlUpcaseUnicodeString(&u1, pString, False)) ||
!NT_SUCCESS(RtlUpcaseUnicodeString(&u2, pSubString, False)))
return False;
l1 = u1.Length/sizeof(WCHAR);
s1 = u1.Buffer;
do
{
l2 = u2.Length/sizeof(WCHAR);
s2 = u2.Buffer;
if (l2 > l1)
return False;
// look for the next occurrence of the first char of s2 in string s1
while (l1)
{
if (*s2 == *s1)
break;
s1++;
l1--;
}
if (l1 < l2)
return False;
if (l2 == 1)
return True;
l1--; l2--;
s1++; s2++;
ts1 = s1;
tl1 = l1;
while (l2)
{
// Look for substring s2 from current position in s1
if (*s2 != *ts1)
break;
tl1--; l2--;
ts1++; s2++;
}
if (l2 == 0)
return True;
} while (True);
// Should never get here
KeBugCheck(0);
}
/*** AfpStrChr
*
* DBCS sensitive strchr()
*
*/
PCHAR
AfpStrChr(
IN PBYTE String,
IN DWORD StringLen,
IN BYTE Char
)
{
DWORD BytesRemaining;
BytesRemaining = StringLen;
while (BytesRemaining > 0)
{
/* MSKK hideyukn, strchr() does not work with DBCS, 08/07/95 */
#ifdef DBCS
if (FsRtlIsLeadDbcsCharacter(*String))
{
String += 2;
continue;
}
#endif /* DBCS */
if (*String == Char)
{
return(String);
}
String++;
BytesRemaining--;
}
return(NULL);
}