windows-nt/Source/XPSP1/NT/base/win32/lz32/winlza/utils.c

366 lines
10 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
** utils.c - Miscellaneous utility routines used in compression / expansion
** modules. Theoretically these functions are DBCS-enabled.
**
** Author: DavidDi
*/
// Headers
///////////
#ifndef LZA_DLL
#include <ctype.h>
#include <string.h>
#endif
#include "lz_common.h"
/*
** char ARG_PTR *ExtractFileName(char ARG_PTR pszPathName);
**
** Find the file name in a fully specified path name.
**
** Arguments: pszPathName - path string from which to extract file name
**
** Returns: char ARG_PTR * - Pointer to file name in pszPathName.
**
** Globals: none
*/
LPWSTR
ExtractFileNameW(
LPWSTR pszPathName)
{
LPWSTR pszLastComponent, psz;
for (pszLastComponent = psz = pszPathName; *psz != L'\0'; psz++)
{
if (*psz == L'\\' || *psz == L':')
pszLastComponent = psz + 1;
}
return(pszLastComponent);
}
CHAR ARG_PTR *ExtractFileName(CHAR ARG_PTR *pszPathName)
{
CHAR ARG_PTR *pszLastComponent, ARG_PTR *psz;
for (pszLastComponent = psz = pszPathName; *psz != '\0'; psz = CharNext(psz))
{
if (! IsDBCSLeadByte(*psz) && (ISSLASH(*psz) || *psz == COLON))
pszLastComponent = CharNext(psz);
}
return(pszLastComponent);
}
/*
** char ARG_PTR *ExtractExtension(char ARG_PTR *pszFileName);
**
** Find the extension of a file name.
**
** Arguments: pszFileName - file name to examine
**
** Returns: char ARG_PTR * - Pointer to file name extension if one exists.
** NULL if the file name doesn't include an
** extension.
**
** Globals: none
*/
LPWSTR
ExtractExtensionW(
LPWSTR pszFileName)
{
WCHAR *psz;
// Make sure we have an isolated file name.
psz = ExtractFileNameW(pszFileName);
while (*psz != L'\0' && *psz != L'.')
psz++;
if (*psz == L'.')
return(psz + 1);
else
return(NULL);
}
CHAR ARG_PTR *ExtractExtension(CHAR ARG_PTR *pszFileName)
{
CHAR ARG_PTR *psz;
// Make sure we have an isolated file name.
psz = ExtractFileName(pszFileName);
while (IsDBCSLeadByte(*psz) || (*psz != '\0' && *psz != PERIOD))
psz = CharNext(psz);
if (*psz == PERIOD)
return(psz + 1);
else
return(NULL);
}
/*
** void MakePathName(char ARG_PTR *pszPath, char ARG_PTR *pszFileName);
**
** Append a filename to a path string.
**
** Arguments: pszPath - path string to which pszFileName will be appended
** pszFileName - file name to append
**
** Returns: void
**
** Globals: none
*/
VOID MakePathName(CHAR ARG_PTR *pszPath, CHAR ARG_PTR *pszFileName)
{
CHAR chLastPathChar;
// Make sure we have an isolated file name.
pszFileName = ExtractFileName(pszFileName);
// Dont append to a NULL string or a single ".".
if (*pszFileName != '\0' &&
! (! IsDBCSLeadByte(pszFileName[0]) && pszFileName[0] == PERIOD &&
! IsDBCSLeadByte(pszFileName[1]) && pszFileName[1] == '\0'))
{
chLastPathChar = *CharPrev(pszPath, pszPath + STRLEN(pszPath));
//NTRAID:MSKKBUG #3411 Nov.09.93 v-hajimy
if (! ISSLASH(chLastPathChar) && chLastPathChar != COLON)
STRCAT(pszPath, SEP_STR);
STRCAT(pszPath, pszFileName);
}
}
/*
** char MakeCompressedName(char ARG_PTR *pszFileName);
**
** Make a file name into the corresponding compressed file name.
**
** Arguments: pszOriginalName - file name to convert to compressed file name
**
** Returns: char - Uncompressed file name extension character that was
** replaced. '\0' if no character needed to be replaced.
**
** Globals: none
**
** N.b., assumes pszFileName's buffer is long enough to hold an extra two
** characters ("._").
**
** For DBCS filenames, we know we can have at most one DBCS character in the
** extension. So instead of just blindly replacing the last character of a
** three-byte extension with an underscore, we replace the last single-byte
** character with an underscore.
*/
#define chEXTENSION_CHARW L'_'
#define pszEXTENSION_STRW L"_"
#define pszNULL_EXTENSIONW L"._"
WCHAR
MakeCompressedNameW(
LPWSTR pszFileName)
{
WCHAR chReplaced = L'\0';
WCHAR ARG_PTR *pszExt;
if ((pszExt = ExtractExtensionW(pszFileName)) != NULL)
{
if (lstrlenW(pszExt) >= 3)
{
chReplaced = pszExt[lstrlenW(pszExt) - 1];
pszExt[lstrlenW(pszExt) - 1] = chEXTENSION_CHARW;
}
else
lstrcatW(pszExt, pszEXTENSION_STRW);
}
else
lstrcatW(pszFileName, pszNULL_EXTENSIONW);
return(chReplaced);
}
CHAR MakeCompressedName(CHAR ARG_PTR *pszFileName)
{
CHAR chReplaced = '\0';
ULONG NameLength = STRLEN( pszFileName );
ULONG DotIndex = NameLength;
while (( DotIndex > 0 ) && ( pszFileName[ --DotIndex ] != '.' )) {
if (( pszFileName[ DotIndex ] == '\\' ) ||
( pszFileName[ DotIndex ] == ':' )) { // end of filename part of path
DotIndex = 0; // name has no extension
break;
}
}
if ( DotIndex > 0 ) { // name has an extension
if (( NameLength - DotIndex ) <= 3 ) { // extension less than 3 chars
pszFileName[ NameLength++ ] = '_'; // append '_' to extension
pszFileName[ NameLength ] = 0; // terminate
}
else { // extension more than 3 chars
chReplaced = pszFileName[ NameLength - 1 ]; // return original
pszFileName[ NameLength - 1 ] = '_'; // replace last char with '_'
}
}
else { // name has no extension
pszFileName[ NameLength++ ] = '.'; // append '.'
pszFileName[ NameLength++ ] = '_'; // append '_'
pszFileName[ NameLength ] = 0; // terminate
}
return(chReplaced);
}
/*
** void MakeExpandedName(char ARG_PTR *pszFileName, BYTE byteExtensionChar);
**
** Create expanded output file name.
**
** Arguments: pszFileName - expanded file name to change
** byteExtensionChar - expanded file name extension character to
** use
**
** Returns: void
**
** Globals: none
*/
VOID MakeExpandedName(CHAR ARG_PTR *pszFileName, BYTE byteExtensionChar)
{
CHAR ARG_PTR *pszExt;
INT nExtLen;
// Is there any extension to change?
if ((pszExt = ExtractExtension(pszFileName)) != NULL)
{
// Determine case of extension character. Match case of first non-DB
// character in name. If all characters are DB, leave case alone.
if (ISLETTER(byteExtensionChar))
{
// Find first alphabetic character in name.
while (*pszFileName)
{
if (IsDBCSLeadByte(*pszFileName))
pszFileName += 2;
else if (ISLETTER(*pszFileName))
break;
else
pszFileName++;
}
// Here pszFileName points to the first alphabetic character in the
// name or to the null terminator. Set the case of the extension
// character.
if (ISLOWER(*pszFileName))
byteExtensionChar = (BYTE)TOLOWERCASE(byteExtensionChar);
else if (ISUPPER(*pszFileName))
byteExtensionChar = (BYTE)TOUPPERCASE(byteExtensionChar);
}
if ((nExtLen = STRLEN(pszExt)) > 0)
{
// Find the underscore character to replace, if it exists.
// Assert: The underscore is either the last character in the
// extension, or it is the first character in the extension followed
// by a double-byte character.
if (! IsDBCSLeadByte(*pszExt) && *pszExt == chEXTENSION_CHAR &&
IsDBCSLeadByte(pszExt[1]))
// Here the underscore is followed by a double-byte character.
*pszExt = byteExtensionChar;
else
{
// Here the underscore is the last character in the extension, if
// there is an underscore at all.
CHAR ARG_PTR *psz, *pszPrevious;
for (psz = pszPrevious = pszExt; *psz != '\0'; psz = CharNext(psz))
pszPrevious = psz;
if (! IsDBCSLeadByte(*pszPrevious) &&
*pszPrevious == chEXTENSION_CHAR)
*pszPrevious = byteExtensionChar;
}
}
// Get rid of trailing dot with no extension.
if (*pszExt == '\0' && *(pszExt - 1) == PERIOD)
*(pszExt - 1) = '\0';
}
}
/*
** int CopyDateTimeStamp(INT_PTR doshFrom, INT_PTR doshTo);
**
** Copy date and time stamp from one file to another.
**
** Arguments: doshFrom - date and time stamp source DOS file handle
** doshTo - target DOS file handle
**
** Returns: TRUE if successful. LZERROR_BADINHANDLE or
** LZERROR_BADOUTHANDLE if unsuccessful.
**
** Globals: none
**
** N.b., stream-style I/O routines like fopen() and fclose() may counter the
** intended effect of this function. fclose() writes the current date to any
** file it's called with which was opened in write "w" or append "a" mode.
** One way to get around this in order to modify the date of a file opened
** for writing or appending by fopen() is to fclose() the file and fopen() it
** again in read "r" mode. Then set its date and time stamp with
** CopyDateTimeStamp().
*/
INT CopyDateTimeStamp(INT_PTR doshFrom, INT_PTR doshTo)
{
#ifdef ORGCODE
// DOS prototypes from <dos.h>
extern DWORD _dos_getftime(INT dosh, DWORD *puDate, DWORD *puTime);
extern DWORD _dos_setftime(INT dosh, DWORD uDate, DWORD uTime);
#ifdef LZA_DLL
static
#endif
DWORD uFrom_date, // temporary storage for date
uFrom_time; // and time stamps
if (_dos_getftime(doshFrom, &uFrom_date, &uFrom_time) != 0u)
return((INT)LZERROR_BADINHANDLE);
if (_dos_setftime(doshTo, uFrom_date, uFrom_time) != 0u)
return((INT)LZERROR_BADOUTHANDLE);
#else
FILETIME lpCreationTime, lpLastAccessTime, lpLastWriteTime;
if(!GetFileTime((HANDLE) doshFrom, &lpCreationTime, &lpLastAccessTime,
&lpLastWriteTime)){
return((INT)LZERROR_BADINHANDLE);
}
if(!SetFileTime((HANDLE) doshTo, &lpCreationTime, &lpLastAccessTime,
&lpLastWriteTime)){
return((INT)LZERROR_BADINHANDLE);
}
#endif
return(TRUE);
}