994 lines
27 KiB
C
994 lines
27 KiB
C
/*++
|
|
|
|
Copyright (c) 1991-1996, Microsoft Corporation All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
util.c
|
|
|
|
Abstract:
|
|
|
|
This file contains utility functions that are shared across NLS's code
|
|
modules, but are not necessarily part of any of the existing code
|
|
modules.
|
|
|
|
External Routines found in this file:
|
|
IsValidSeparatorString
|
|
IsValidCalendarType
|
|
IsValidCalendarTypeStr
|
|
GetUserInfo
|
|
GetPreComposedChar
|
|
GetCompositeChars
|
|
InsertPreComposedForm
|
|
InsertFullWidthPreComposedForm
|
|
InsertCompositeForm
|
|
NlsStrCpyW
|
|
NlsStrCatW
|
|
NlsStrLenW
|
|
NlsStrNCatW
|
|
NlsStrEqualW
|
|
NlsStrNEqualW
|
|
|
|
Revision History:
|
|
|
|
05-31-91 JulieB Created.
|
|
|
|
--*/
|
|
|
|
|
|
|
|
//
|
|
// Include Files.
|
|
//
|
|
|
|
#include "nls.h"
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------//
|
|
// EXTERNAL ROUTINES //
|
|
//-------------------------------------------------------------------------//
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsValidSeparatorString
|
|
//
|
|
// Returns TRUE if the given string is valid. Otherwise, it returns FALSE.
|
|
//
|
|
// A valid string is one that does NOT contain any code points between
|
|
// L'0' and L'9', and does NOT have a length greater than the maximum.
|
|
//
|
|
// NOTE: The string must be a null terminated string.
|
|
//
|
|
// 10-12-93 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsValidSeparatorString(
|
|
LPCWSTR pString,
|
|
ULONG MaxLength,
|
|
BOOL fCheckZeroLen)
|
|
|
|
{
|
|
WCHAR wch; // wide character
|
|
ULONG Length; // string length
|
|
LPWSTR pCur; // ptr to current position in string
|
|
|
|
|
|
//
|
|
// Search down the string to see if the chars are valid.
|
|
// Save the length of the string.
|
|
//
|
|
pCur = (LPWSTR)pString;
|
|
while (wch = *pCur)
|
|
{
|
|
if ((wch >= NLS_CHAR_ZERO) && (wch <= NLS_CHAR_NINE))
|
|
{
|
|
//
|
|
// String is NOT valid.
|
|
//
|
|
return (FALSE);
|
|
}
|
|
pCur++;
|
|
}
|
|
Length = pCur - (LPWSTR)pString;
|
|
|
|
//
|
|
// Make sure the length is not greater than the maximum allowed.
|
|
//
|
|
if (Length >= MaxLength)
|
|
{
|
|
//
|
|
// String is NOT valid.
|
|
//
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Check for 0 length string (if appropriate).
|
|
//
|
|
if ((fCheckZeroLen) && (Length == 0))
|
|
{
|
|
//
|
|
// String is NOT valid.
|
|
//
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// String is valid.
|
|
//
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsValidCalendarType
|
|
//
|
|
// Returns the pointer to the optional calendar structure if the given
|
|
// calendar type is valid for the given locale. Otherwise, it returns NULL.
|
|
//
|
|
// 10-12-93 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPWORD IsValidCalendarType(
|
|
PLOC_HASH pHashN,
|
|
CALID CalId)
|
|
|
|
{
|
|
LPWORD pOptCal; // ptr to list of optional calendars
|
|
LPWORD pEndOptCal; // ptr to end of list of optional calendars
|
|
|
|
|
|
//
|
|
// Make sure the Cal Id is not zero, since that may be in the
|
|
// optional calendar section (meaning no optional calendars).
|
|
//
|
|
if (CalId == 0)
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
//
|
|
// Search down the list of optional calendars.
|
|
//
|
|
pOptCal = (LPWORD)(pHashN->pLocaleHdr) + pHashN->pLocaleHdr->IOptionalCal;
|
|
pEndOptCal = (LPWORD)(pHashN->pLocaleHdr) + pHashN->pLocaleHdr->SDayName1;
|
|
while (pOptCal < pEndOptCal)
|
|
{
|
|
//
|
|
// Check the calendar ids.
|
|
//
|
|
if (CalId == ((POPT_CAL)pOptCal)->CalId)
|
|
{
|
|
//
|
|
// Calendar id is valid for the given locale.
|
|
//
|
|
return (pOptCal);
|
|
}
|
|
|
|
//
|
|
// Increment to the next optional calendar.
|
|
//
|
|
pOptCal += ((POPT_CAL)pOptCal)->Offset;
|
|
}
|
|
|
|
//
|
|
// Calendar id is NOT valid if this point is reached.
|
|
//
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsValidCalendarTypeStr
|
|
//
|
|
// Converts the calendar string to an integer and validates the calendar
|
|
// id for the given locale. It return a pointer to the optional calendar
|
|
// structure, or null if the calendar id was invalid.
|
|
//
|
|
// 10-19-93 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPWORD IsValidCalendarTypeStr(
|
|
PLOC_HASH pHashN,
|
|
LPCWSTR pCalStr)
|
|
|
|
{
|
|
UNICODE_STRING ObUnicodeStr; // value string
|
|
CALID CalNum; // calendar id
|
|
|
|
|
|
//
|
|
// Convert the string to an integer value.
|
|
//
|
|
RtlInitUnicodeString(&ObUnicodeStr, pCalStr);
|
|
if (RtlUnicodeStringToInteger(&ObUnicodeStr, 10, &CalNum))
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
//
|
|
// Validate the calendar id and return the pointer to the
|
|
// optional calendar structure.
|
|
//
|
|
return (IsValidCalendarType(pHashN, CalNum));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetUserInfo
|
|
//
|
|
// Gets the information from the registry for the given locale and user
|
|
// value entry.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL GetUserInfo(
|
|
LCID Locale,
|
|
LPWSTR pCacheString,
|
|
LPWSTR pOutput,
|
|
BOOL fCheckNull)
|
|
{
|
|
BOOL fCacheValid; // flag for cache validity
|
|
|
|
|
|
//
|
|
// Check to be sure the current user is running in the given locale.
|
|
//
|
|
if (Locale != pNlsUserInfo->UserLocaleId)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Get the cache mutant.
|
|
// Copy the data to the output buffer.
|
|
// Get the validity of the cache.
|
|
// Release the cache mutant.
|
|
//
|
|
NtWaitForSingleObject(hNlsCacheMutant, FALSE, NULL);
|
|
wcscpy(pOutput, pCacheString);
|
|
fCacheValid = pNlsUserInfo->fCacheValid;
|
|
NtReleaseMutant(hNlsCacheMutant, NULL);
|
|
|
|
//
|
|
// Make sure the cache is valid.
|
|
//
|
|
// Also, check for an invalid entry. An invalid entry is marked
|
|
// with NLS_INVALID_INFO_CHAR in the first position of the string
|
|
// array.
|
|
//
|
|
if ((fCacheValid == FALSE) ||
|
|
(*pOutput == NLS_INVALID_INFO_CHAR))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// See if we need to check for a null string.
|
|
//
|
|
if ((fCheckNull) && (*pOutput == 0))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetPreComposedChar
|
|
//
|
|
// Gets the precomposed character form of a given base character and
|
|
// nonspacing character. If there is no precomposed form for the given
|
|
// character, it returns 0.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
WCHAR FASTCALL GetPreComposedChar(
|
|
WCHAR wcNonSp,
|
|
WCHAR wcBase)
|
|
{
|
|
PCOMP_INFO pComp; // ptr to composite information
|
|
WORD BSOff = 0; // offset of base char in grid
|
|
WORD NSOff = 0; // offset of nonspace char in grid
|
|
int Index; // index into grid
|
|
|
|
|
|
//
|
|
// Store the ptr to the composite information. No need to check if
|
|
// it's a NULL pointer since all tables in the Unicode file are
|
|
// constructed during initialization.
|
|
//
|
|
pComp = pTblPtrs->pComposite;
|
|
|
|
//
|
|
// Traverse 8:4:4 table for Base character offset.
|
|
//
|
|
BSOff = TRAVERSE_844_W(pComp->pBase, wcBase);
|
|
if (!BSOff)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Traverse 8:4:4 table for NonSpace character offset.
|
|
//
|
|
NSOff = TRAVERSE_844_W(pComp->pNonSp, wcNonSp);
|
|
if (!NSOff)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Get wide character value out of 2D grid.
|
|
// If there is no precomposed character at the location in the
|
|
// grid, it will return 0.
|
|
//
|
|
Index = (BSOff - 1) * pComp->NumNonSp + (NSOff - 1);
|
|
return ((pComp->pGrid)[Index]);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetCompositeChars
|
|
//
|
|
// Gets the composite characters of a given wide character. If the
|
|
// composite form is found, it returns TRUE. Otherwise, it returns
|
|
// FALSE.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL FASTCALL GetCompositeChars(
|
|
WCHAR wch,
|
|
WCHAR *pNonSp,
|
|
WCHAR *pBase)
|
|
{
|
|
PPRECOMP pPreComp; // ptr to precomposed information
|
|
|
|
|
|
//
|
|
// Store the ptr to the precomposed information. No need to check if
|
|
// it's a NULL pointer since all tables in the Unicode file are
|
|
// constructed during initialization.
|
|
//
|
|
pPreComp = pTblPtrs->pPreComposed;
|
|
|
|
//
|
|
// Traverse 8:4:4 table for base and nonspace character translation.
|
|
//
|
|
TRAVERSE_844_D(pPreComp, wch, *pNonSp, *pBase);
|
|
|
|
//
|
|
// Return success if found. Otherwise, error.
|
|
//
|
|
return ((*pNonSp) && (*pBase));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InsertPreComposedForm
|
|
//
|
|
// Gets the precomposed form of a given wide character string, places it in
|
|
// the given wide character, and returns the number of composite characters
|
|
// used to form the precomposed form. If there is no precomposed form for
|
|
// the given character, nothing is written into pPreComp and it returns 1
|
|
// for the number of characters used.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int FASTCALL InsertPreComposedForm(
|
|
LPCWSTR pWCStr,
|
|
LPWSTR pEndWCStr,
|
|
LPWSTR pPreComp)
|
|
{
|
|
WCHAR wch; // precomposed character
|
|
LPWSTR pPos; // ptr to position in string
|
|
|
|
|
|
//
|
|
// If no precomposed form can be found, return 1 character used
|
|
// (base character).
|
|
//
|
|
if (((pWCStr + 1) >= pEndWCStr) ||
|
|
(!(wch = GetPreComposedChar(*(pWCStr + 1), *pWCStr))))
|
|
{
|
|
return (1);
|
|
}
|
|
|
|
//
|
|
// Get the precomposed character from the given wide character string.
|
|
// Must check for multiple nonspacing characters for the same
|
|
// precomposed character.
|
|
//
|
|
*pPreComp = wch;
|
|
pPos = (LPWSTR)pWCStr + 2;
|
|
while ((pPos < pEndWCStr) &&
|
|
(wch = GetPreComposedChar(*pPos, *pPreComp)))
|
|
{
|
|
*pPreComp = wch;
|
|
pPos++;
|
|
}
|
|
|
|
//
|
|
// Return the number of characters used to form the precomposed
|
|
// character.
|
|
//
|
|
return (pPos - (LPWSTR)pWCStr);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InsertFullWidthPreComposedForm
|
|
//
|
|
// Gets the full width precomposed form of a given wide character string,
|
|
// places it in the given wide character, and returns the number of
|
|
// composite characters used to form the precomposed form. If there is
|
|
// no precomposed form for the given character, only the full width conversion
|
|
// of the first code point is written into pPreComp and it returns 1 for
|
|
// the number of characters used.
|
|
//
|
|
// 11-04-93 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int FASTCALL InsertFullWidthPreComposedForm(
|
|
LPCWSTR pWCStr,
|
|
LPWSTR pEndWCStr,
|
|
LPWSTR pPreComp,
|
|
PCASE pCase)
|
|
{
|
|
WCHAR wch; // nonspace character
|
|
LPWSTR pPos; // ptr to position in string
|
|
|
|
|
|
//
|
|
// Get the case (if necessary).
|
|
//
|
|
*pPreComp = (pCase) ? GET_LOWER_UPPER_CASE(pCase, *pWCStr) : *pWCStr;
|
|
|
|
//
|
|
// Get the full width.
|
|
//
|
|
*pPreComp = GET_FULL_WIDTH(pTblPtrs->pFullWidth, *pPreComp);
|
|
|
|
if ((pPos = ((LPWSTR)pWCStr + 1)) >= pEndWCStr)
|
|
{
|
|
return (1);
|
|
}
|
|
|
|
while (pPos < pEndWCStr)
|
|
{
|
|
wch = (pCase) ? GET_LOWER_UPPER_CASE(pCase, *pPos) : *pPos;
|
|
wch = GET_FULL_WIDTH(pTblPtrs->pFullWidth, wch);
|
|
if (wch = GetPreComposedChar(wch, *pPreComp))
|
|
{
|
|
*pPreComp = wch;
|
|
pPos++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the number of characters used to form the precomposed
|
|
// character.
|
|
//
|
|
return (pPos - (LPWSTR)pWCStr);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InsertCompositeForm
|
|
//
|
|
// Gets the composite form of a given wide character, places it in the
|
|
// wide character string, and returns the number of characters written.
|
|
// If there is no composite form for the given character, the wide character
|
|
// string is not touched. It will return 1 for the number of characters
|
|
// written, since the base character was already written.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int FASTCALL InsertCompositeForm(
|
|
LPWSTR pWCStr,
|
|
LPWSTR pEndWCStr)
|
|
{
|
|
WCHAR Base; // base character
|
|
WCHAR NonSp; // non space character
|
|
int wcCount = 0; // number of wide characters written
|
|
LPWSTR pEndComp; // ptr to end of composite form
|
|
int ctr; // loop counter
|
|
|
|
|
|
//
|
|
// If no composite form can be found, return 1 for the base
|
|
// character that was already written.
|
|
//
|
|
if (!GetCompositeChars(*pWCStr, &NonSp, &Base))
|
|
{
|
|
return (1);
|
|
}
|
|
|
|
//
|
|
// Get the composite characters and write them to the pWCStr
|
|
// buffer. Must check for multiple breakdowns of the precomposed
|
|
// character into more than 2 characters (multiple nonspacing
|
|
// characters).
|
|
//
|
|
pEndComp = pWCStr;
|
|
do
|
|
{
|
|
//
|
|
// Make sure pWCStr is big enough to hold the nonspacing
|
|
// character.
|
|
//
|
|
if (pEndComp < (pEndWCStr - 1))
|
|
{
|
|
//
|
|
// Addition of next breakdown of nonspacing characters
|
|
// are to be added right after the base character. So,
|
|
// move all nonspacing characters ahead one position
|
|
// to make room for the next nonspacing character.
|
|
//
|
|
pEndComp++;
|
|
for (ctr = 0; ctr < wcCount; ctr++)
|
|
{
|
|
*(pEndComp - ctr) = *(pEndComp - (ctr + 1));
|
|
}
|
|
|
|
//
|
|
// Fill in the new base form and the new nonspacing character.
|
|
//
|
|
*pWCStr = Base;
|
|
*(pWCStr + 1) = NonSp;
|
|
wcCount++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure we don't get into an infinite loop if the
|
|
// destination buffer isn't large enough.
|
|
//
|
|
break;
|
|
}
|
|
} while (GetCompositeChars(*pWCStr, &NonSp, &Base));
|
|
|
|
//
|
|
// Return number of wide characters written. Add 1 to include the
|
|
// base character.
|
|
//
|
|
return (wcCount + 1);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsStrCpyW
|
|
//
|
|
// This routine copies the source wide character string to the destination
|
|
// wide character string buffer.
|
|
//
|
|
// NOTE: This routine is here to avoid any dependencies on other DLLs
|
|
// during initialization.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPWSTR FASTCALL NlsStrCpyW(
|
|
LPWSTR pwszDest,
|
|
LPCWSTR pwszSrc)
|
|
{
|
|
LPWSTR pwszRet = pwszDest; // ptr to beginning of string
|
|
|
|
loop:
|
|
if (!(pwszDest[0x0] = pwszSrc[0x0])) goto done;
|
|
if (!(pwszDest[0x1] = pwszSrc[0x1])) goto done;
|
|
if (!(pwszDest[0x2] = pwszSrc[0x2])) goto done;
|
|
if (!(pwszDest[0x3] = pwszSrc[0x3])) goto done;
|
|
if (!(pwszDest[0x4] = pwszSrc[0x4])) goto done;
|
|
if (!(pwszDest[0x5] = pwszSrc[0x5])) goto done;
|
|
if (!(pwszDest[0x6] = pwszSrc[0x6])) goto done;
|
|
if (!(pwszDest[0x7] = pwszSrc[0x7])) goto done;
|
|
if (!(pwszDest[0x8] = pwszSrc[0x8])) goto done;
|
|
if (!(pwszDest[0x9] = pwszSrc[0x9])) goto done;
|
|
if (!(pwszDest[0xA] = pwszSrc[0xA])) goto done;
|
|
if (!(pwszDest[0xB] = pwszSrc[0xB])) goto done;
|
|
if (!(pwszDest[0xC] = pwszSrc[0xC])) goto done;
|
|
if (!(pwszDest[0xD] = pwszSrc[0xD])) goto done;
|
|
if (!(pwszDest[0xE] = pwszSrc[0xE])) goto done;
|
|
if (!(pwszDest[0xF] = pwszSrc[0xF])) goto done;
|
|
|
|
pwszDest+= 0x10;
|
|
pwszSrc+= 0x10;
|
|
|
|
goto loop;
|
|
|
|
done:
|
|
return (pwszRet);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsStrCatW
|
|
//
|
|
// This routine attaches the second string to the first string.
|
|
//
|
|
// NOTE: This routine is here to avoid any dependencies on other DLLs
|
|
// during initialization.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPWSTR FASTCALL NlsStrCatW(
|
|
LPWSTR pwsz1,
|
|
LPCWSTR pwsz2)
|
|
{
|
|
LPWSTR pwszRet = pwsz1; // ptr to beginning of string
|
|
|
|
strlen_loop:
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
if (!*pwsz1) goto cat_loop;
|
|
pwsz1++;
|
|
|
|
goto strlen_loop;
|
|
|
|
cat_loop:
|
|
if (!(pwsz1[0x00] = pwsz2[0x00])) goto done;
|
|
if (!(pwsz1[0x01] = pwsz2[0x01])) goto done;
|
|
if (!(pwsz1[0x02] = pwsz2[0x02])) goto done;
|
|
if (!(pwsz1[0x03] = pwsz2[0x03])) goto done;
|
|
if (!(pwsz1[0x04] = pwsz2[0x04])) goto done;
|
|
if (!(pwsz1[0x05] = pwsz2[0x05])) goto done;
|
|
if (!(pwsz1[0x06] = pwsz2[0x06])) goto done;
|
|
if (!(pwsz1[0x07] = pwsz2[0x07])) goto done;
|
|
if (!(pwsz1[0x08] = pwsz2[0x08])) goto done;
|
|
if (!(pwsz1[0x09] = pwsz2[0x09])) goto done;
|
|
if (!(pwsz1[0x0A] = pwsz2[0x0A])) goto done;
|
|
if (!(pwsz1[0x0B] = pwsz2[0x0B])) goto done;
|
|
if (!(pwsz1[0x0C] = pwsz2[0x0C])) goto done;
|
|
if (!(pwsz1[0x0D] = pwsz2[0x0D])) goto done;
|
|
if (!(pwsz1[0x0E] = pwsz2[0x0E])) goto done;
|
|
if (!(pwsz1[0x0F] = pwsz2[0x0F])) goto done;
|
|
|
|
pwsz1 += 0x10;
|
|
pwsz2 += 0x10;
|
|
goto cat_loop;
|
|
|
|
done:
|
|
return (pwszRet);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsStrLenW
|
|
//
|
|
// This routine returns the length of the given wide character string.
|
|
// The length does NOT include the null terminator.
|
|
//
|
|
// NOTE: This routine is here to avoid any dependencies on other DLLs
|
|
// during initialization.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int FASTCALL NlsStrLenW(
|
|
LPCWSTR pwsz)
|
|
{
|
|
LPCWSTR pwszStart = pwsz; // ptr to beginning of string
|
|
|
|
loop:
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
if (!*pwsz) goto done;
|
|
pwsz++;
|
|
|
|
goto loop;
|
|
|
|
done:
|
|
return (pwsz - pwszStart);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsStrNCatW
|
|
//
|
|
// This routine concatenates two wide character strings for the count of
|
|
// characters given. It copies "Count" characters from the back string to
|
|
// the end of the "front" string.
|
|
//
|
|
// NOTE: This routine is here to avoid any dependencies on other DLLs
|
|
// during initialization.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPWSTR FASTCALL NlsStrNCatW(
|
|
LPWSTR pwszFront,
|
|
LPCWSTR pwszBack,
|
|
int Count)
|
|
{
|
|
LPWSTR pwszStart = pwszFront; // ptr to beginning of string
|
|
|
|
strlen_loop:
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
if (!*pwszFront) goto cat_loop;
|
|
pwszFront++;
|
|
|
|
goto strlen_loop;
|
|
|
|
cat_loop:
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
if (Count == 0 || !(*pwszFront = *pwszBack)) goto done;
|
|
pwszFront++; pwszBack++; Count--;
|
|
|
|
goto cat_loop;
|
|
|
|
done:
|
|
*pwszFront = (WCHAR)0;
|
|
|
|
return (pwszStart);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsStrEqualW
|
|
//
|
|
// This routine compares two strings to see if they are exactly identical.
|
|
// It returns 1 if they are identical, 0 if they are different.
|
|
//
|
|
// NOTE: This routine is here to avoid any dependencies on other DLLs
|
|
// during initialization.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int FASTCALL NlsStrEqualW(
|
|
LPCWSTR pwszFirst,
|
|
LPCWSTR pwszSecond)
|
|
{
|
|
loop:
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
|
|
goto loop;
|
|
|
|
|
|
error:
|
|
//
|
|
// Return error.
|
|
//
|
|
return (0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// NlsStrNEqualW
|
|
//
|
|
// This routine compares two strings to see if they are exactly identical
|
|
// for the count of characters given.
|
|
// It returns 1 if they are identical, 0 if they are different.
|
|
//
|
|
// NOTE: This routine is here to avoid any dependencies on other DLLs
|
|
// during initialization.
|
|
//
|
|
// 05-31-91 JulieB Created.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int FASTCALL NlsStrNEqualW(
|
|
LPCWSTR pwszFirst,
|
|
LPCWSTR pwszSecond,
|
|
int Count)
|
|
{
|
|
loop:
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
if (Count == 0) return (1);
|
|
if (*pwszFirst != *pwszSecond) goto error;
|
|
if (!*pwszFirst) return (1);
|
|
pwszFirst++;
|
|
pwszSecond++;
|
|
Count--;
|
|
|
|
goto loop;
|
|
|
|
|
|
error:
|
|
//
|
|
// Return error.
|
|
//
|
|
return (0);
|
|
}
|
|
|
|
|