/* ** utils.c - Miscellaneous utility routines used in compression / expansion ** modules. Theoretically these functions are DBCS-enabled. ** ** Author: DavidDi */ // Headers /////////// #ifndef LZA_DLL #include #include #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 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); }