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.
1594 lines
42 KiB
1594 lines
42 KiB
// --------------------------------------------------------------------------
|
|
// Strutil.cpp
|
|
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
|
|
// Steven J. Bailey
|
|
// --------------------------------------------------------------------------
|
|
#include "pch.hxx"
|
|
#include <iert.h>
|
|
#include "dllmain.h"
|
|
#include "oertpriv.h"
|
|
#include <wininet.h>
|
|
#include <shlwapi.h>
|
|
#include <shlwapip.h>
|
|
#include <qstrcmpi.h>
|
|
#include <shlwapi.h>
|
|
#include "unicnvrt.h"
|
|
#include <BadStrFunctions.h>
|
|
|
|
// conversion from 'int' to 'unsigned short', possible loss of data
|
|
#pragma warning (disable:4244)
|
|
|
|
// --------------------------------------------------------------------------
|
|
// g_szMonths
|
|
// --------------------------------------------------------------------------
|
|
static const LPSTR g_szMonths[] = {
|
|
"Jan", "Feb", "Mar",
|
|
"Apr", "May", "Jun",
|
|
"Jul", "Aug", "Sep",
|
|
"Oct", "Nov", "Dec"
|
|
};
|
|
|
|
// --------------------------------------------------------------------------
|
|
// g_szDays
|
|
// --------------------------------------------------------------------------
|
|
static const LPSTR g_szDays[] = {
|
|
"Sun",
|
|
"Mon",
|
|
"Tue",
|
|
"Wed",
|
|
"Thu",
|
|
"Fri",
|
|
"Sat"
|
|
};
|
|
|
|
// --------------------------------------------------------------------------
|
|
// g_rgZones
|
|
// --------------------------------------------------------------------------
|
|
static const INETTIMEZONE g_rgZones[] = {
|
|
{ "UT", 0, 0 },
|
|
{ "GMT", 0, 0 },
|
|
{ "EST", 5, 0 },
|
|
{ "EDT", 4, 0 },
|
|
{ "CST", 6, 0 },
|
|
{ "CDT", 5, 0 },
|
|
{ "MST", 7, 0 },
|
|
{ "MDT", 6, 0 },
|
|
{ "PST", 8, 0 },
|
|
{ "PDT", 7, 0 },
|
|
{ "KST", -9, 0 },
|
|
{ "JST", -9, 0 },
|
|
{ NULL, 0, 0 }
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// How big is the thread local storage string buffer
|
|
// -------------------------------------------------------------------------------
|
|
#define CBMAX_THREAD_TLS_BUFFER 512
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ThreadAllocateTlsMsgBuffer
|
|
// -------------------------------------------------------------------------------
|
|
void ThreadAllocateTlsMsgBuffer(void)
|
|
{
|
|
if (g_dwTlsMsgBuffIndex != 0xffffffff)
|
|
TlsSetValue(g_dwTlsMsgBuffIndex, NULL);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ThreadFreeTlsMsgBuffer
|
|
// -------------------------------------------------------------------------------
|
|
void ThreadFreeTlsMsgBuffer(void)
|
|
{
|
|
if (g_dwTlsMsgBuffIndex != 0xffffffff)
|
|
{
|
|
LPSTR psz = (LPSTR)TlsGetValue(g_dwTlsMsgBuffIndex);
|
|
SafeMemFree(psz);
|
|
SideAssert(0 != TlsSetValue(g_dwTlsMsgBuffIndex, NULL));
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// PszGetTlsBuffer
|
|
// -------------------------------------------------------------------------------
|
|
LPSTR PszGetTlsBuffer(void)
|
|
{
|
|
// Get the buffer
|
|
LPSTR pszBuffer = (LPSTR)TlsGetValue(g_dwTlsMsgBuffIndex);
|
|
|
|
// If buffer has not been allocated
|
|
if (NULL == pszBuffer)
|
|
{
|
|
// Allocate it
|
|
pszBuffer = (LPSTR)g_pMalloc->Alloc(CBMAX_THREAD_TLS_BUFFER);
|
|
|
|
// Store it
|
|
Assert(pszBuffer);
|
|
SideAssert(0 != TlsSetValue(g_dwTlsMsgBuffIndex, pszBuffer));
|
|
}
|
|
|
|
// Done
|
|
return pszBuffer;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// _MSG - Used to build a string from variable length args, thread-safe
|
|
// -------------------------------------------------------------------------------
|
|
OESTDAPI_(LPCSTR) _MSG(LPSTR pszFormat, ...)
|
|
{
|
|
// Locals
|
|
va_list arglist;
|
|
LPSTR pszBuffer=NULL;
|
|
|
|
// I use tls to hold the buffer
|
|
if (g_dwTlsMsgBuffIndex != 0xffffffff)
|
|
{
|
|
// Setup the arglist
|
|
va_start(arglist, pszFormat);
|
|
|
|
// Get the Buffer
|
|
pszBuffer = PszGetTlsBuffer();
|
|
|
|
// If we have a buffer
|
|
if (pszBuffer)
|
|
{
|
|
// Format the data
|
|
wvnsprintf(pszBuffer, (CBMAX_THREAD_TLS_BUFFER - sizeof(pszBuffer[0])), pszFormat, arglist);
|
|
}
|
|
|
|
// End the arglist
|
|
va_end(arglist);
|
|
}
|
|
|
|
return ((LPCSTR)pszBuffer);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// StrChrExA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPCSTR) StrChrExA(UINT codepage, LPCSTR pszString, CHAR ch)
|
|
{
|
|
// Locals
|
|
LPSTR pszT=(LPSTR)pszString;
|
|
|
|
// Loop for ch in pszString
|
|
while(*pszT)
|
|
{
|
|
// Lead Byte
|
|
if (IsDBCSLeadByteEx(codepage, *pszT))
|
|
pszT++;
|
|
else if (*pszT == ch)
|
|
return pszT;
|
|
pszT++;
|
|
}
|
|
|
|
// Not Found
|
|
return NULL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszDayFromIndex
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPCSTR) PszDayFromIndex(ULONG ulIndex)
|
|
{
|
|
// Invalid Arg
|
|
Assert(ulIndex <= 6);
|
|
|
|
// Adjust ulIndex
|
|
ulIndex = (ulIndex > 6) ? 0 : ulIndex;
|
|
|
|
// Return
|
|
return g_szDays[ulIndex];
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszMonthFromIndex (ulIndex is one-based)
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPCSTR) PszMonthFromIndex(ULONG ulIndex)
|
|
{
|
|
// Invalid Arg
|
|
Assert(ulIndex >= 1 && ulIndex <= 12);
|
|
|
|
// Adjust ulIndex
|
|
ulIndex = (ulIndex < 1 || ulIndex > 12) ? 0 : ulIndex - 1;
|
|
|
|
// Return
|
|
return g_szMonths[ulIndex];
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// HrFindInetTimeZone
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(HRESULT) HrFindInetTimeZone(LPCSTR pszTimeZone, LPINETTIMEZONE pTimeZone)
|
|
{
|
|
// Invalid Arg
|
|
Assert(pszTimeZone && pTimeZone);
|
|
|
|
// Loop timezone table
|
|
for (ULONG iZoneCode=0; g_rgZones[iZoneCode].lpszZoneCode!=NULL; iZoneCode++)
|
|
{
|
|
// Is this the code...
|
|
if (lstrcmpi(pszTimeZone, g_rgZones[iZoneCode].lpszZoneCode) == 0)
|
|
{
|
|
CopyMemory(pTimeZone, &g_rgZones[iZoneCode], sizeof(INETTIMEZONE));
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// Not Found
|
|
return E_FAIL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// HrIndexOfMonth
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(HRESULT) HrIndexOfMonth(LPCSTR pszMonth, ULONG *pulIndex)
|
|
{
|
|
// Invalid Arg
|
|
Assert(pszMonth && pulIndex);
|
|
|
|
// Loop the Months
|
|
for (ULONG iMonth=0; iMonth < ARRAYSIZE(g_szMonths); iMonth++)
|
|
{
|
|
// Is this the month
|
|
if (OEMstrcmpi(pszMonth, g_szMonths[iMonth]) == 0)
|
|
{
|
|
// Set It
|
|
*pulIndex = (iMonth + 1);
|
|
|
|
// Validate
|
|
AssertSz(*pulIndex >= 1 && *pulIndex <= 12, "HrIndexOfMonth - Bad Month");
|
|
|
|
// Done
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
*pulIndex = 0;
|
|
|
|
// Not Found
|
|
return E_FAIL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// HrIndexOfWeek
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(HRESULT) HrIndexOfWeek(LPCSTR pszDay, ULONG *pulIndex)
|
|
{
|
|
// Invalid Arg
|
|
Assert(pszDay && pulIndex);
|
|
|
|
// Loop the Days
|
|
for (ULONG iDayOfWeek=0; iDayOfWeek < ARRAYSIZE(g_szDays); iDayOfWeek++)
|
|
{
|
|
// Is this the day
|
|
if (OEMstrcmpi(pszDay, g_szDays[iDayOfWeek]) == 0)
|
|
{
|
|
// Set Day Of Week
|
|
*pulIndex = iDayOfWeek;
|
|
|
|
// Validate
|
|
AssertSz(((int) *pulIndex) >= 0 && ((int) *pulIndex) <= 6, "HrIndexOfDay - Bad day of week");
|
|
|
|
// Done
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
*pulIndex = 0;
|
|
|
|
// Failure
|
|
return E_FAIL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszEscapeMenuStringA
|
|
//
|
|
// Escapes & characters with another & so that they show up correctly when shown
|
|
// in a menu.
|
|
// --------------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszEscapeMenuStringA(LPCSTR pszSource, LPSTR pszQuoted, int cchMax)
|
|
{
|
|
LPSTR pszT=pszQuoted;
|
|
int cch = 1; // 1 is intentional
|
|
|
|
Assert(pszSource);
|
|
Assert(pszQuoted);
|
|
|
|
while((cch < cchMax) && (*pszSource))
|
|
{
|
|
if (IsDBCSLeadByte(*pszSource))
|
|
{
|
|
cch++;
|
|
// Is there only space for lead byte?
|
|
if (cch == cchMax)
|
|
// Yes, don't write it
|
|
break;
|
|
else
|
|
*pszT++ = *pszSource++;
|
|
}
|
|
else if ('&' == *pszSource)
|
|
{
|
|
cch++;
|
|
if (cch == cchMax)
|
|
break;
|
|
else
|
|
*pszT++ = '&';
|
|
}
|
|
|
|
// Only way this could fail is if there was a DBCSLeadByte with no trail byte
|
|
Assert(*pszSource);
|
|
|
|
*pszT++ = *pszSource++;
|
|
cch++;
|
|
}
|
|
*pszT = 0;
|
|
|
|
return pszQuoted;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// PszSkipWhiteA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszSkipWhiteA(LPSTR psz)
|
|
{
|
|
while(*psz && (*psz == ' ' || *psz == '\t'))
|
|
psz++;
|
|
return psz;
|
|
}
|
|
|
|
OESTDAPI_(LPWSTR) PszSkipWhiteW(LPWSTR psz)
|
|
{
|
|
while(*psz && (*psz == L' ' || *psz == L'\t'))
|
|
psz++;
|
|
return psz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszScanToWhiteA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszScanToWhiteA(LPSTR psz)
|
|
{
|
|
while(*psz && ' ' != *psz && '\t' != *psz)
|
|
psz++;
|
|
return psz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszScanToCharA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszScanToCharA(LPSTR psz, CHAR ch)
|
|
{
|
|
while(*psz && ch != *psz)
|
|
psz++;
|
|
return psz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszDupLenA
|
|
// duplicates a string with upto cchMax characters in (and a null term)
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszDupLenA(LPCSTR pcszSource, int cchMax)
|
|
{
|
|
// Locals
|
|
LPSTR pszDup=NULL;
|
|
|
|
// No Source
|
|
if (pcszSource == NULL || cchMax == 0)
|
|
goto exit;
|
|
|
|
// the amount to copy if the min of the max and the
|
|
// source
|
|
cchMax = min(lstrlen(pcszSource), cchMax);
|
|
|
|
// Allocate the String
|
|
pszDup = PszAllocA(cchMax+1); // +1 for null term
|
|
if (!pszDup)
|
|
goto exit;
|
|
|
|
// Copy the data, leave room for the null-term
|
|
CopyMemory(pszDup, pcszSource, cchMax);
|
|
|
|
// null terminate
|
|
pszDup[cchMax] = 0;
|
|
|
|
exit:
|
|
// Done
|
|
return pszDup;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszFromANSIStreamA - pstm is assumed to be an ANSI stream
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszFromANSIStreamA(LPSTREAM pstm)
|
|
{
|
|
// Locals
|
|
HRESULT hr;
|
|
LPSTR psz=NULL;
|
|
ULONG cb;
|
|
|
|
// Get stream size
|
|
hr = HrGetStreamSize(pstm, &cb);
|
|
if (FAILED(hr))
|
|
{
|
|
Assert(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
// Rewind the stream
|
|
HrRewindStream(pstm);
|
|
|
|
// Allocate a buffer
|
|
if ((psz = PszAllocA(cb + 1)) != NULL)
|
|
{
|
|
// Read a buffer from stream
|
|
hr = pstm->Read(psz, cb, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
Assert(FALSE);
|
|
MemFree(psz);
|
|
return NULL;
|
|
}
|
|
|
|
// Null Terminate
|
|
*(psz + cb) = '\0';
|
|
}
|
|
|
|
// Done
|
|
return psz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszFromANSIStreamW - pstm is assumed to be an ANSI stream
|
|
// --------------------------------------------------------------------------
|
|
LPWSTR PszFromANSIStreamW(UINT cp, LPSTREAM pstm)
|
|
{
|
|
// Get ANSI string
|
|
LPSTR psz = PszFromANSIStreamA(pstm);
|
|
if (NULL == psz)
|
|
return NULL;
|
|
|
|
// Convert to unicode
|
|
LPWSTR pwsz = PszToUnicode(cp, psz);
|
|
|
|
// Done
|
|
return pwsz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ConvertFromHex - Converts a hexdigit into a numerica value
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(CHAR) ChConvertFromHex (CHAR ch)
|
|
{
|
|
if (ch >= '0' && ch <= '9')
|
|
return CHAR((ch - '0'));
|
|
|
|
else if (ch >= 'A'&& ch <= 'F')
|
|
return CHAR(((ch - 'A') + 10));
|
|
|
|
else if (ch >= 'a' && ch <= 'f')
|
|
return CHAR(((ch - 'a') + 10));
|
|
|
|
else
|
|
return ((CHAR)(BYTE)255);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// FIsValidRegKeyNameA
|
|
// --------------------------------------------------------------------------
|
|
BOOL FIsValidRegKeyNameA(LPSTR pszKey)
|
|
{
|
|
// Locals
|
|
LPSTR psz=pszKey;
|
|
|
|
// If Empty...
|
|
if (FIsEmptyA(pszKey))
|
|
return FALSE;
|
|
|
|
// Check for backslashes
|
|
while(*psz)
|
|
{
|
|
if (*psz == '\\')
|
|
return FALSE;
|
|
psz = CharNextA(psz);
|
|
}
|
|
|
|
// Its ok
|
|
return TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// FIsValidRegKeyNameW
|
|
// --------------------------------------------------------------------------
|
|
BOOL FIsValidRegKeyNameW(LPWSTR pwszKey)
|
|
{
|
|
// Locals
|
|
LPWSTR pwsz=pwszKey;
|
|
|
|
// If Empty...
|
|
if (FIsEmptyW(pwszKey))
|
|
return FALSE;
|
|
|
|
// Check for backslashes
|
|
while(*pwsz)
|
|
{
|
|
if (*pwsz == L'\\')
|
|
return FALSE;
|
|
pwsz = CharNextW(pwsz);
|
|
}
|
|
|
|
// Its ok
|
|
return TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// FIsSpaceA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(BOOL) FIsSpaceA(LPSTR psz)
|
|
{
|
|
WORD wType = 0;
|
|
|
|
if (IsDBCSLeadByte(*psz))
|
|
SideAssert(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
else
|
|
SideAssert(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
return (wType & C1_SPACE);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// FIsSpaceW
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(BOOL) FIsSpaceW(LPWSTR pwsz)
|
|
{
|
|
BOOL result = FALSE;
|
|
|
|
if (S_OK == IsPlatformWinNT())
|
|
{
|
|
WORD wType = 0;
|
|
SideAssert(GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, pwsz, 1, &wType));
|
|
result = (wType & C1_SPACE);
|
|
}
|
|
else
|
|
{
|
|
LPSTR psz = PszToANSI(CP_ACP, pwsz);
|
|
if (psz)
|
|
result = FIsSpaceA(psz);
|
|
MemFree(psz);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// FIsEmptyA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(BOOL) FIsEmptyA(LPCSTR pcszString)
|
|
{
|
|
// Locals
|
|
LPSTR psz;
|
|
|
|
// Bad Pointer
|
|
if (!pcszString)
|
|
return TRUE;
|
|
|
|
// Check for All spaces
|
|
psz = (LPSTR)pcszString;
|
|
while (*psz)
|
|
{
|
|
if (FIsSpaceA(psz) == FALSE)
|
|
return FALSE;
|
|
psz++;
|
|
}
|
|
|
|
// Done
|
|
return TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// FIsEmptyW
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(BOOL) FIsEmptyW(LPCWSTR pcwszString)
|
|
{
|
|
// Locals
|
|
LPWSTR pwsz;
|
|
|
|
// Bad Pointer
|
|
if (!pcwszString)
|
|
return TRUE;
|
|
|
|
// Check for All spaces
|
|
pwsz = (LPWSTR)pcwszString;
|
|
while (*pwsz)
|
|
{
|
|
if (FIsSpaceW(pwsz) == FALSE)
|
|
return FALSE;
|
|
pwsz++;
|
|
}
|
|
|
|
// Done
|
|
return TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszAllocA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszAllocA(INT nLen)
|
|
{
|
|
// Locals
|
|
LPSTR psz=NULL;
|
|
|
|
// Empty ?
|
|
if (nLen == 0)
|
|
goto exit;
|
|
|
|
// Allocate
|
|
if (FAILED(HrAlloc((LPVOID *)&psz, (nLen + 1) * sizeof (CHAR))))
|
|
goto exit;
|
|
|
|
exit:
|
|
// Done
|
|
return psz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszAllocW
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPWSTR) PszAllocW(INT nLen)
|
|
{
|
|
// Locals
|
|
LPWSTR pwsz=NULL;
|
|
|
|
// Empty ?
|
|
if (nLen == 0)
|
|
goto exit;
|
|
|
|
// Allocate
|
|
if (FAILED(HrAlloc((LPVOID *)&pwsz, (nLen + 1) * sizeof (WCHAR))))
|
|
goto exit;
|
|
|
|
exit:
|
|
// Done
|
|
return pwsz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszToUnicode
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPWSTR) PszToUnicode(UINT cp, LPCSTR pcszSource)
|
|
{
|
|
// Locals
|
|
INT cchNarrow,
|
|
cchWide;
|
|
LPWSTR pwszDup=NULL;
|
|
|
|
// No Source
|
|
if (pcszSource == NULL)
|
|
goto exit;
|
|
|
|
// Length
|
|
cchNarrow = lstrlenA(pcszSource) + 1;
|
|
|
|
// Determine how much space is needed for translated widechar
|
|
cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, NULL, 0);
|
|
|
|
// Error
|
|
if (cchWide == 0)
|
|
goto exit;
|
|
|
|
// Alloc temp buffer
|
|
pwszDup = PszAllocW(cchWide + 1);
|
|
if (!pwszDup)
|
|
goto exit;
|
|
|
|
// Do the actual translation
|
|
cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, pwszDup, cchWide+1);
|
|
|
|
// Error
|
|
if (cchWide == 0)
|
|
{
|
|
SafeMemFree(pwszDup);
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
// Done
|
|
return pwszDup;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszToANSI
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszToANSI(UINT cp, LPCWSTR pcwszSource)
|
|
{
|
|
// Locals
|
|
INT cchNarrow,
|
|
cchWide;
|
|
LPSTR pszDup=NULL;
|
|
|
|
// No Source
|
|
if (pcwszSource == NULL)
|
|
goto exit;
|
|
|
|
// Length
|
|
cchWide = lstrlenW(pcwszSource)+1;
|
|
|
|
// Determine how much space is needed for translated widechar
|
|
cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, NULL, 0, NULL, NULL);
|
|
|
|
// Error
|
|
if (cchNarrow == 0)
|
|
goto exit;
|
|
|
|
// Alloc temp buffer
|
|
pszDup = PszAllocA(cchNarrow + 1);
|
|
if (!pszDup)
|
|
goto exit;
|
|
|
|
// Do the actual translation
|
|
cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, pszDup, cchNarrow+1, NULL, NULL);
|
|
|
|
// Error
|
|
if (cchNarrow == 0)
|
|
{
|
|
SafeMemFree(pszDup);
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
// Done
|
|
return pszDup;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszDupA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) PszDupA(LPCSTR pcszSource)
|
|
{
|
|
// Locals
|
|
INT nLen;
|
|
LPSTR pszDup=NULL;
|
|
|
|
// No Source
|
|
if (pcszSource == NULL)
|
|
goto exit;
|
|
|
|
// Get String Length
|
|
nLen = lstrlenA(pcszSource) + 1;
|
|
|
|
// Allocate the String
|
|
pszDup = PszAllocA(nLen);
|
|
if (!pszDup)
|
|
goto exit;
|
|
|
|
// Copy the data
|
|
CopyMemory(pszDup, pcszSource, nLen);
|
|
|
|
exit:
|
|
// Done
|
|
return pszDup;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// PszDupW
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPWSTR) PszDupW(LPCWSTR pcwszSource)
|
|
{
|
|
// Locals
|
|
INT nLen;
|
|
LPWSTR pwszDup=NULL;
|
|
|
|
// No Source
|
|
if (pcwszSource == NULL)
|
|
goto exit;
|
|
|
|
// Get String Length
|
|
nLen = lstrlenW(pcwszSource) + 1;
|
|
|
|
// Allocate the String
|
|
pwszDup = PszAllocW(nLen);
|
|
if (!pwszDup)
|
|
goto exit;
|
|
|
|
// Copy the data
|
|
CopyMemory(pwszDup, pcwszSource, nLen * sizeof(WCHAR));
|
|
|
|
exit:
|
|
// Done
|
|
return pwszDup;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// StripCRLF
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(void) StripCRLF(LPSTR lpsz, ULONG *pcb)
|
|
{
|
|
// Null ?
|
|
AssertSz (lpsz && pcb, "NULL Parameter");
|
|
|
|
// If length is zero, then return
|
|
if (!lpsz || !pcb || (*pcb == 0))
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
// Check last three characters of the string, last char might or might not be a null-term
|
|
LONG iLast = (*pcb) - 2;
|
|
if (iLast < 0)
|
|
iLast = 0;
|
|
for (LONG i=(*pcb); i>=iLast; i--)
|
|
{
|
|
// Is end character a '\n'
|
|
if (lpsz[i] == chLF)
|
|
{
|
|
lpsz[i] = '\0';
|
|
(*pcb)--;
|
|
}
|
|
|
|
// Is end character a '\r'
|
|
if (lpsz[i] == chCR)
|
|
{
|
|
lpsz[i] = '\0';
|
|
(*pcb)--;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ToUpper
|
|
// --------------------------------------------------------------------------
|
|
TCHAR ToUpper(TCHAR c)
|
|
{
|
|
return (TCHAR)LOWORD(CharUpper(MAKEINTRESOURCE(c)));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// IsPrint
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(int) IsPrint(LPSTR psz)
|
|
{
|
|
WORD wType;
|
|
if (IsDBCSLeadByte(*psz))
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
else
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
return !(wType & C1_CNTRL);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// IsDigit
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(int) IsDigit(LPSTR psz)
|
|
{
|
|
WORD wType;
|
|
if (IsDBCSLeadByte(*psz))
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
else
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
return (wType & C1_DIGIT);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// IsXDigit
|
|
// --------------------------------------------------------------------------
|
|
int IsXDigit(LPSTR psz)
|
|
{
|
|
WORD wType;
|
|
if (IsDBCSLeadByte(*psz))
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
else
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
return (wType & C1_XDIGIT);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// IsUpper
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(INT) IsUpper(LPSTR psz)
|
|
{
|
|
WORD wType;
|
|
if (IsDBCSLeadByte(*psz))
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
else
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
return (wType & C1_UPPER);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// IsAlpha
|
|
// --------------------------------------------------------------------------
|
|
int IsAlpha(LPSTR psz)
|
|
{
|
|
WORD wType;
|
|
if (IsDBCSLeadByte(*psz))
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
else
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
return (wType & C1_ALPHA);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// IsPunct
|
|
// --------------------------------------------------------------------------
|
|
int IsPunct(LPSTR psz)
|
|
{
|
|
WORD wType;
|
|
if (IsDBCSLeadByte(*psz))
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
else
|
|
SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
return (wType & C1_PUNCT);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// strsave
|
|
// --------------------------------------------------------------------------
|
|
char *strsave(char *s)
|
|
{
|
|
char *p;
|
|
|
|
if (!s)
|
|
return NULL;
|
|
|
|
DWORD cchSize = (lstrlen(s)+1);
|
|
if (MemAlloc((LPVOID*)&p, cchSize * sizeof(p[0])))
|
|
{
|
|
StrCpyN(p, s, cchSize);
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// strtrim
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(LPSTR) strtrim(char *s)
|
|
{
|
|
char *p;
|
|
|
|
for (p = s; *p; p++)
|
|
;
|
|
for (--p ; (p>=s) && StrChr(" \t\r\n",*p); --p)
|
|
*p = '\0';
|
|
while (*s && StrChr(" \t\r\n",*s))
|
|
++s;
|
|
return s;
|
|
}
|
|
|
|
OESTDAPI_(LPWSTR) strtrimW(WCHAR *s)
|
|
{
|
|
WCHAR *p;
|
|
|
|
for (p = s; *p; p++)
|
|
;
|
|
for (--p ; (p>=s) && StrChrW(L" \t\r\n",*p); --p)
|
|
*p = '\0';
|
|
while (*s && StrChrW(L" \t\r\n",*s))
|
|
++s;
|
|
return s;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// strappend
|
|
// --------------------------------------------------------------------------
|
|
void strappend(char **pp, char *s)
|
|
{
|
|
char *p;
|
|
|
|
Assert(pp);
|
|
|
|
if (!s)
|
|
return;
|
|
|
|
if (!*pp)
|
|
{
|
|
DWORD cchSize = (lstrlen(s)+1);
|
|
if (!MemAlloc((LPVOID*)&p, cchSize * sizeof(p[0])))
|
|
return;
|
|
StrCpyNA(p, s, cchSize);
|
|
}
|
|
else
|
|
{
|
|
DWORD cchSize = (lstrlen(s) + lstrlen(*pp) + 2);
|
|
if (!MemAlloc((LPVOID*)&p, cchSize * sizeof(p[0])))
|
|
return;
|
|
StrCpyNA(p, *pp, cchSize);
|
|
StrCatBuffA(p, "\r", cchSize);
|
|
StrCatBuffA(p, s, cchSize);
|
|
MemFree(*pp);
|
|
}
|
|
|
|
*pp = p;
|
|
}
|
|
|
|
OESTDAPI_(ULONG) UlStripWhitespace(LPTSTR lpsz, BOOL fLeading, BOOL fTrailing, ULONG *pcb)
|
|
{
|
|
// Locals
|
|
ULONG cb;
|
|
LPTSTR psz;
|
|
|
|
Assert(lpsz != NULL);
|
|
Assert(fLeading || fTrailing);
|
|
|
|
// Did the user pass in the length
|
|
if (pcb)
|
|
cb = *pcb;
|
|
else
|
|
cb = lstrlen (lpsz);
|
|
|
|
if (cb == 0)
|
|
return cb;
|
|
|
|
if (fLeading)
|
|
{
|
|
psz = lpsz;
|
|
|
|
while (FIsSpace(psz))
|
|
{
|
|
psz++;
|
|
cb--;
|
|
}
|
|
|
|
if (psz != lpsz)
|
|
// get the NULL at the end too
|
|
MoveMemory(lpsz, psz, (cb + 1) * sizeof(TCHAR));
|
|
}
|
|
|
|
if (fTrailing)
|
|
{
|
|
psz = lpsz + cb;
|
|
|
|
while (cb > 0)
|
|
{
|
|
if (!FIsSpace(psz-1))
|
|
break;
|
|
psz--;
|
|
cb--;
|
|
}
|
|
|
|
// NULL Term
|
|
*psz = '\0';
|
|
}
|
|
|
|
// Set String Size
|
|
if (pcb)
|
|
*pcb = cb;
|
|
|
|
// Done
|
|
return cb;
|
|
}
|
|
|
|
OESTDAPI_(ULONG) UlStripWhitespaceW(LPWSTR lpwsz, BOOL fLeading, BOOL fTrailing, ULONG *pcb)
|
|
{
|
|
// Locals
|
|
ULONG cb;
|
|
LPWSTR pwsz;
|
|
|
|
Assert(lpwsz != NULL);
|
|
Assert(fLeading || fTrailing);
|
|
|
|
// Did the user pass in the length
|
|
if (pcb)
|
|
cb = *pcb;
|
|
else
|
|
cb = lstrlenW(lpwsz)* sizeof(WCHAR) ; // multiply by sizeof(WCHAR) to get correct byte size.
|
|
|
|
if (cb == 0)
|
|
return cb;
|
|
|
|
if (fLeading)
|
|
{
|
|
pwsz = lpwsz;
|
|
|
|
while (FIsSpaceW(pwsz))
|
|
{
|
|
pwsz++;
|
|
cb -= sizeof(*pwsz);
|
|
}
|
|
|
|
if (pwsz != lpwsz)
|
|
// get the NULL at the end too
|
|
MoveMemory(lpwsz, pwsz, cb + sizeof(WCHAR));
|
|
}
|
|
|
|
if (fTrailing)
|
|
{
|
|
pwsz = lpwsz + cb / sizeof(WCHAR); // Divided by size of WCHAR to get right pointer
|
|
|
|
while (cb > 0)
|
|
{
|
|
if (!FIsSpaceW(pwsz - 1))
|
|
break;
|
|
pwsz--;
|
|
cb -= sizeof(*pwsz);
|
|
}
|
|
|
|
// NULL Term
|
|
*pwsz = L'\0';
|
|
}
|
|
|
|
// Set String Size
|
|
if (pcb)
|
|
*pcb = cb;
|
|
|
|
// Done
|
|
return cb;
|
|
}
|
|
|
|
// =============================================================================================
|
|
// Converts first two characters of lpcsz to a WORD
|
|
// =============================================================================================
|
|
SHORT ASCII_NFromSz (LPCSTR lpcsz)
|
|
{
|
|
char acWordStr[3];
|
|
Assert (lpcsz);
|
|
CopyMemory (acWordStr, lpcsz, 2 * sizeof (char));
|
|
acWordStr[2] = '\0';
|
|
return ((SHORT) (StrToInt (acWordStr)));
|
|
}
|
|
|
|
|
|
|
|
// =================================================================================
|
|
// Adjust the time at lpSysTime by adding the given lHoursToAdd &
|
|
// lMinutesToAdd. Returns the adjusted time at lpFileTime.
|
|
// =================================================================================
|
|
HRESULT HrAdjustTime (LPSYSTEMTIME lpSysTime, LONG lHoursToAdd, LONG lMinutesToAdd, LPFILETIME lpFileTime)
|
|
{
|
|
// Locals
|
|
HRESULT hr = S_OK;
|
|
BOOL bResult = FALSE;
|
|
LONG lUnitsToAdd = 0;
|
|
LARGE_INTEGER liTime;
|
|
LONGLONG liHoursToAdd = 1i64, liMinutesToAdd = 1i64;
|
|
|
|
// Check Params
|
|
AssertSz (lpSysTime && lpFileTime, "Null Parameter");
|
|
|
|
// Convert sys time to file time
|
|
if (!SystemTimeToFileTime (lpSysTime, lpFileTime))
|
|
{
|
|
hr = TRAPHR (E_FAIL);
|
|
DebugTrace( "SystemTimeToFileTime() failed, dwError=%d.\n", GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
// Init
|
|
liTime.LowPart = lpFileTime->dwLowDateTime;
|
|
liTime.HighPart = lpFileTime->dwHighDateTime;
|
|
|
|
// Adjust the hour
|
|
if (lHoursToAdd != 0)
|
|
{
|
|
lUnitsToAdd = lHoursToAdd * 3600;
|
|
liHoursToAdd *= lUnitsToAdd;
|
|
liHoursToAdd *= 10000000i64;
|
|
liTime.QuadPart += liHoursToAdd;
|
|
}
|
|
|
|
// Adjust the minutes
|
|
if (lMinutesToAdd != 0)
|
|
{
|
|
lUnitsToAdd = lMinutesToAdd * 60;
|
|
liMinutesToAdd *= lUnitsToAdd;
|
|
liMinutesToAdd *= 10000000i64;
|
|
liTime.QuadPart += liMinutesToAdd;
|
|
}
|
|
|
|
// Assign the result to FILETIME
|
|
lpFileTime->dwLowDateTime = liTime.LowPart;
|
|
lpFileTime->dwHighDateTime = liTime.HighPart;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
// =================================================================================
|
|
// Addjust the time at lpSysTime according to the given Zone info,
|
|
// Returns the adjusted time at lpFileTime.
|
|
// =================================================================================
|
|
BOOL ProcessZoneInfo (LPSTR lpszZoneInfo, INT *lpcHoursToAdd, INT *lpcMinutesToAdd)
|
|
{
|
|
// Locals
|
|
ULONG cbZoneInfo;
|
|
BOOL bResult;
|
|
|
|
// Init
|
|
*lpcHoursToAdd = 0;
|
|
*lpcMinutesToAdd = 0;
|
|
cbZoneInfo = lstrlen (lpszZoneInfo);
|
|
bResult = TRUE;
|
|
|
|
// +hhmm or -hhmm
|
|
if ((*lpszZoneInfo == '-' || *lpszZoneInfo == '+') && cbZoneInfo <= 5)
|
|
{
|
|
// Take off
|
|
cbZoneInfo-=1;
|
|
|
|
// determine the hour/minute offset
|
|
if (cbZoneInfo == 4)
|
|
{
|
|
*lpcMinutesToAdd = (INT)StrToInt (lpszZoneInfo+3);
|
|
*(lpszZoneInfo+3) = 0x00;
|
|
*lpcHoursToAdd = (INT)StrToInt(lpszZoneInfo+1);
|
|
}
|
|
|
|
// 3
|
|
else if (cbZoneInfo == 3)
|
|
{
|
|
*lpcMinutesToAdd = (INT)StrToInt (lpszZoneInfo+2);
|
|
*(lpszZoneInfo+2) = 0x00;
|
|
*lpcHoursToAdd = (INT)StrToInt (lpszZoneInfo+1);
|
|
}
|
|
|
|
// 2
|
|
else if (cbZoneInfo == 2 || cbZoneInfo == 1)
|
|
{
|
|
*lpcMinutesToAdd = 0;
|
|
*lpcHoursToAdd = (INT)StrToInt(lpszZoneInfo+1);
|
|
}
|
|
|
|
if (*lpszZoneInfo == '+')
|
|
{
|
|
*lpcHoursToAdd = -*lpcHoursToAdd;
|
|
*lpcMinutesToAdd = -*lpcMinutesToAdd;
|
|
}
|
|
}
|
|
|
|
// Xenix conversion: TZ = current time zone or other unknown tz types.
|
|
else if (lstrcmpi (lpszZoneInfo, "TZ") == 0 ||
|
|
lstrcmpi (lpszZoneInfo, "LOCAL") == 0 ||
|
|
lstrcmpi (lpszZoneInfo, "UNDEFINED") == 0)
|
|
{
|
|
TIME_ZONE_INFORMATION tzi ;
|
|
DWORD dwRet = GetTimeZoneInformation (&tzi);
|
|
if (dwRet != 0xFFFFFFFF)
|
|
{
|
|
LONG cMinuteBias = tzi.Bias;
|
|
|
|
if (dwRet == TIME_ZONE_ID_STANDARD)
|
|
cMinuteBias += tzi.StandardBias ;
|
|
|
|
else if (dwRet == TIME_ZONE_ID_DAYLIGHT)
|
|
cMinuteBias += tzi.DaylightBias ;
|
|
|
|
*lpcHoursToAdd = cMinuteBias / 60 ;
|
|
*lpcMinutesToAdd = cMinuteBias % 60 ;
|
|
}
|
|
else
|
|
{
|
|
AssertSz (FALSE, "Why would this happen");
|
|
bResult = FALSE;
|
|
}
|
|
}
|
|
|
|
// Loop through known time zone standards
|
|
else
|
|
{
|
|
for (INT i=0; g_rgZones[i].lpszZoneCode!=NULL; i++)
|
|
{
|
|
if (lstrcmpi (lpszZoneInfo, g_rgZones[i].lpszZoneCode) == 0)
|
|
{
|
|
*lpcHoursToAdd = g_rgZones[i].cHourOffset;
|
|
*lpcMinutesToAdd = g_rgZones[i].cMinuteOffset;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (g_rgZones[i].lpszZoneCode == NULL)
|
|
{
|
|
DebugTrace( "Unrecognized zone info: [%s]\n", lpszZoneInfo );
|
|
bResult = FALSE;
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
#define IS_DIGITA(ch) (ch >= '0' && ch <= '9')
|
|
#define IS_DIGITW(ch) (ch >= L'0' && ch <= L'9')
|
|
|
|
// ---------------------------------------------------------------------------------------
|
|
// StrToUintA
|
|
// ---------------------------------------------------------------------------------------
|
|
OESTDAPI_(UINT) StrToUintA(LPCSTR lpSrc)
|
|
{
|
|
UINT n = 0;
|
|
|
|
Assert(*lpSrc != '-');
|
|
|
|
while (IS_DIGITA(*lpSrc))
|
|
{
|
|
n *= 10;
|
|
n += *lpSrc - '0';
|
|
lpSrc++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------
|
|
// StrToUintW
|
|
// ---------------------------------------------------------------------------------------
|
|
OESTDAPI_(UINT) StrToUintW(LPCWSTR lpSrc)
|
|
{
|
|
UINT n = 0;
|
|
|
|
Assert(*lpSrc != '-');
|
|
|
|
while (IS_DIGITW(*lpSrc))
|
|
{
|
|
n *= 10;
|
|
n += *lpSrc - L'0';
|
|
lpSrc++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------
|
|
// FIsValidFileNameCharW
|
|
// ---------------------------------------------------------------------------------------
|
|
OESTDAPI_(BOOL) FIsValidFileNameCharW(WCHAR wch)
|
|
{
|
|
// Locals
|
|
LPWSTR pwsz;
|
|
static const WCHAR s_pwszBad[] = L"<>:\"/\\|?*";
|
|
|
|
pwsz = (LPWSTR)s_pwszBad;
|
|
while(*pwsz)
|
|
{
|
|
if (wch == *pwsz)
|
|
return FALSE;
|
|
pwsz++;
|
|
}
|
|
|
|
// Shouldn't allow any control chars
|
|
if ((wch >= 0x0000) && (wch < 0x0020))
|
|
return FALSE;
|
|
|
|
// Done
|
|
return TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// FIsValidFileNameCharA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(BOOL) FIsValidFileNameCharA(UINT codepage, CHAR ch)
|
|
{
|
|
// Locals
|
|
LPSTR psz;
|
|
static const CHAR s_szBad[] = "<>:\"/\\|?*";
|
|
|
|
psz = (LPSTR)s_szBad;
|
|
while(*psz)
|
|
{
|
|
if (IsDBCSLeadByteEx(codepage, *psz))
|
|
psz++;
|
|
else if (ch == *psz)
|
|
return FALSE;
|
|
psz++;
|
|
}
|
|
|
|
// Shouldn't allow any control chars
|
|
if ((ch >= 0x00) && (ch < 0x20))
|
|
return FALSE;
|
|
|
|
// Done
|
|
return TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CleanupFileNameInPlaceA
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(ULONG) EXPORT_16 CleanupFileNameInPlaceA(UINT codepage, LPSTR psz)
|
|
{
|
|
UINT ich=0;
|
|
UINT cch=lstrlen(psz);
|
|
|
|
// Fixup codepage?
|
|
if (1200 == codepage)
|
|
codepage = CP_ACP;
|
|
|
|
// Loop and remove invalid chars
|
|
while (ich < cch)
|
|
{
|
|
// If lead byte, skip it, its leagal
|
|
if (IsDBCSLeadByteEx(codepage, psz[ich]))
|
|
ich+=2;
|
|
|
|
// Illeagl file name character ?
|
|
else if (!FIsValidFileNameCharA(codepage, psz[ich]))
|
|
{
|
|
MoveMemory (psz + ich, psz + (ich + 1), cch - ich);
|
|
cch--;
|
|
}
|
|
else
|
|
ich++;
|
|
}
|
|
|
|
// Return the Length
|
|
return cch;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CleanupFileNameInPlaceW
|
|
// --------------------------------------------------------------------------
|
|
OESTDAPI_(ULONG) EXPORT_16 CleanupFileNameInPlaceW(LPWSTR pwsz)
|
|
{
|
|
// Locals
|
|
ULONG ich=0;
|
|
ULONG cch=lstrlenW(pwsz);
|
|
|
|
// Loop and remove invalids
|
|
while (ich < cch)
|
|
{
|
|
// Illeagl file name character ?
|
|
if (!FIsValidFileNameCharW(pwsz[ich]))
|
|
pwsz[ich]=L'_';
|
|
|
|
ich++;
|
|
}
|
|
|
|
// Return the length
|
|
return cch;
|
|
}
|
|
|
|
// =============================================================================================
|
|
// ReplaceChars
|
|
// =============================================================================================
|
|
OESTDAPI_(INT) EXPORT_16 ReplaceChars(LPCSTR pszString, CHAR chFind, CHAR chReplace)
|
|
{
|
|
// Locals
|
|
LPSTR pszT=(LPSTR)pszString;
|
|
DWORD nCount=0;
|
|
|
|
// Loop for ch in pszString
|
|
while(*pszT)
|
|
{
|
|
// Lead Byte
|
|
if (IsDBCSLeadByte(*pszT))
|
|
pszT++;
|
|
else if (*pszT == chFind)
|
|
{
|
|
*pszT = chReplace;
|
|
nCount++;
|
|
}
|
|
pszT++;
|
|
}
|
|
|
|
// Not Found
|
|
return nCount;
|
|
}
|
|
|
|
OESTDAPI_(INT) EXPORT_16 ReplaceCharsW(LPCWSTR pszString, WCHAR chFind, WCHAR chReplace)
|
|
{
|
|
// Locals
|
|
LPWSTR pszT = (LPWSTR)pszString;
|
|
DWORD nCount=0;
|
|
|
|
// Loop for ch in pszString
|
|
while(*pszT)
|
|
{
|
|
if (*pszT == chFind)
|
|
{
|
|
*pszT = chReplace;
|
|
nCount++;
|
|
}
|
|
pszT++;
|
|
}
|
|
|
|
// Not Found
|
|
return nCount;
|
|
}
|
|
|
|
OESTDAPI_(BOOL) IsValidFileIfFileUrl(LPSTR pszUrl)
|
|
{
|
|
TCHAR rgch[MAX_PATH];
|
|
ULONG cch=ARRAYSIZE(rgch);
|
|
|
|
// pathCreate from url execpts a cannonicalised url with file:// infront
|
|
if (UrlCanonicalizeA(pszUrl, rgch, &cch, 0)==S_OK)
|
|
{
|
|
cch = ARRAYSIZE(rgch);
|
|
if (PathCreateFromUrlA(rgch, rgch, &cch, 0)==S_OK &&
|
|
!PathFileExistsA(rgch))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
OESTDAPI_(BOOL) IsValidFileIfFileUrlW(LPWSTR pwszUrl)
|
|
{
|
|
WCHAR wsz[MAX_PATH];
|
|
ULONG cch=ARRAYSIZE(wsz);
|
|
|
|
// pathCreate from url execpts a cannonicalised url with file:// infront
|
|
if (UrlCanonicalizeW(pwszUrl, wsz, &cch, 0)==S_OK)
|
|
{
|
|
cch = ARRAYSIZE(wsz);
|
|
if (PathCreateFromUrlW(wsz, wsz, &cch, 0)==S_OK &&
|
|
!PathFileExistsW(wsz))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/***
|
|
*char *StrTokEx(pstring, control) - tokenize string with delimiter in control
|
|
*
|
|
*Purpose:
|
|
* StrTokEx considers the string to consist of a sequence of zero or more
|
|
* text tokens separated by spans of one or more control chars. the first
|
|
* call, with string specified, returns a pointer to the first char of the
|
|
* first token, and will write a null char into pstring immediately
|
|
* following the returned token. when no tokens remain
|
|
* in pstring a NULL pointer is returned. remember the control chars with a
|
|
* bit map, one bit per ascii char. the null char is always a control char.
|
|
*
|
|
*Entry:
|
|
* char **pstring - ptr to ptr to string to tokenize
|
|
* char *control - string of characters to use as delimiters
|
|
*
|
|
*Exit:
|
|
* returns pointer to first token in string,
|
|
* returns NULL when no more tokens remain.
|
|
* pstring points to the beginning of the next token.
|
|
*
|
|
*WARNING!!!
|
|
* upon exit, the first delimiter in the input string will be replaced with '\0'
|
|
*
|
|
*******************************************************************************/
|
|
char * __cdecl StrTokEx (char ** ppszIn, const char * pcszCtrlIn)
|
|
{
|
|
unsigned char *psz;
|
|
const unsigned char *pszCtrl = (const unsigned char *)pcszCtrlIn;
|
|
unsigned char map[32] = {0};
|
|
|
|
LPSTR pszToken;
|
|
|
|
if(*ppszIn == NULL)
|
|
return NULL;
|
|
|
|
/* Set bits in delimiter table */
|
|
do
|
|
{
|
|
map[*pszCtrl >> 3] |= (1 << (*pszCtrl & 7));
|
|
}
|
|
while (*pszCtrl++);
|
|
|
|
/* Initialize str. */
|
|
psz = (unsigned char*)*ppszIn;
|
|
|
|
/* Find beginning of token (skip over leading delimiters). Note that
|
|
* there is no token if this loop sets str to point to the terminal
|
|
* null (*str == '\0') */
|
|
while ((map[*psz >> 3] & (1 << (*psz & 7))) && *psz)
|
|
psz++;
|
|
|
|
pszToken = (LPSTR)psz;
|
|
|
|
/* Find the end of the token. If it is not the end of the string,
|
|
* put a null there. */
|
|
for (; *psz ; psz++)
|
|
{
|
|
if (map[*psz >> 3] & (1 << (*psz & 7)))
|
|
{
|
|
*psz++ = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* string now points to beginning of next token */
|
|
*ppszIn = (LPSTR)psz;
|
|
|
|
/* Determine if a token has been found. */
|
|
if (pszToken == (LPSTR)psz)
|
|
return NULL;
|
|
else
|
|
return pszToken;
|
|
}
|