wince.cpp
资源名称:unzip540.zip [点击查看]
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:22k
源码类别:
压缩解压
开发平台:
MultiPlatform
- //******************************************************************************
- //
- // File: WINCE.CPP
- //
- // Description: This file implements all the Win32 APIs and C runtime functions
- // that the Info-ZIP code calls, but are not implemented natively
- // on Windows CE.
- //
- // Copyright: All the source files for Pocket UnZip, except for components
- // written by the Info-ZIP group, are copyrighted 1997 by Steve P.
- // Miller. The product "Pocket UnZip" itself is property of the
- // author and cannot be altered in any way without written consent
- // from Steve P. Miller.
- //
- // Disclaimer: All project files are provided "as is" with no guarantee of
- // their correctness. The authors are not liable for any outcome
- // that is the result of using this source. The source for Pocket
- // UnZip has been placed in the public domain to help provide an
- // understanding of its implementation. You are hereby granted
- // full permission to use this source in any way you wish, except
- // to alter Pocket UnZip itself. For comments, suggestions, and
- // bug reports, please write to stevemil@pobox.com.
- //
- // Functions: DebugOut
- // chmod
- // close
- // isatty
- // lseek
- // open
- // read
- // setmode
- // unlink
- // fflush
- // fgets
- // fileno
- // fopen
- // fprintf
- // fclose
- // putc
- // sprintf
- // _stricmp
- // _strupr
- // strrchr
- // localtime
- // isupper
- // stat
- // localtime
- // SafeGetTimeZoneInformation
- // GetTransitionTimeT
- // IsDST
- //
- //
- // Date Name History
- // -------- ------------ -----------------------------------------------------
- // 02/01/97 Steve Miller Created (Version 1.0 using Info-ZIP UnZip 5.30)
- //
- //******************************************************************************
- extern "C" {
- #include "punzip.h"
- }
- #include <tchar.h> // Must be outside of extern "C" block
- //******************************************************************************
- //***** For all platforms - Our debug output function
- //******************************************************************************
- #ifdef DEBUG // RETAIL version is __inline and does not generate any code.
- void DebugOut(LPCTSTR szFormat, ...) {
- TCHAR szBuffer[512] = TEXT("PUNZIP: ");
- va_list pArgs;
- va_start(pArgs, szFormat);
- _vsntprintf(szBuffer + 8, countof(szBuffer) - 10, szFormat, pArgs);
- va_end(pArgs);
- TCHAR *psz = szBuffer;
- while (psz = _tcschr(psz, TEXT('n'))) {
- *psz = TEXT('|');
- }
- psz = szBuffer;
- while (psz = _tcschr(psz, TEXT('r'))) {
- *psz = TEXT('|');
- }
- _tcscat(szBuffer, TEXT("rn"));
- OutputDebugString(szBuffer);
- }
- #endif // DEBUG
- //******************************************************************************
- //***** Windows CE Native
- //******************************************************************************
- #if defined(_WIN32_WCE)
- //******************************************************************************
- //***** Local Function Prototyopes
- //******************************************************************************
- void SafeGetTimeZoneInformation(TIME_ZONE_INFORMATION *ptzi);
- time_t GetTransitionTimeT(TIME_ZONE_INFORMATION *ptzi, int year, BOOL fStartDST);
- BOOL IsDST(TIME_ZONE_INFORMATION *ptzi, time_t localTime);
- //******************************************************************************
- //***** IO.H functions
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl chmod(const char *filename, int pmode) {
- // Called before unlink() to delete read-only files.
- DWORD dwAttribs = (pmode & _S_IWRITE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_READONLY;
- TCHAR szPath[_MAX_PATH];
- mbstowcs(szPath, filename, countof(szPath));
- return (SetFileAttributes(szPath, dwAttribs) ? 0 : -1);
- }
- //******************************************************************************
- //-- Called from process.c
- int __cdecl close(int handle) {
- return (CloseHandle((HANDLE)handle) ? 0 : -1);
- }
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl isatty(int handle) {
- // returns TRUE if handle is a terminal, console, printer, or serial port
- // called with 1 (stdout) and 2 (stderr)
- return 0;
- }
- //******************************************************************************
- //-- Called from extract.c, fileio.c, process.c
- long __cdecl lseek(int handle, long offset, int origin) {
- // SEEK_SET, SEEK_CUR, SEEK_END are equal to FILE_BEGIN, FILE_CURRENT, FILE_END
- return SetFilePointer((HANDLE)handle, offset, NULL, origin);
- }
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl open(const char *filename, int oflag, ...) {
- // The Info-Zip code currently only opens existing ZIP files for read using open().
- TCHAR szPath[_MAX_PATH];
- mbstowcs(szPath, filename, countof(szPath));
- HANDLE hFile = CreateFile(szPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- return ((hFile == INVALID_HANDLE_VALUE) ? -1 : (int)hFile);
- }
- //******************************************************************************
- //-- Called from extract.c, fileio.c, process.c
- int __cdecl read(int handle, void *buffer, unsigned int count) {
- DWORD dwRead = 0;
- return (ReadFile((HANDLE)handle, buffer, count, &dwRead, NULL) ? dwRead : -1);
- }
- //******************************************************************************
- //-- Called from extract.c
- int __cdecl setmode(int handle, int mode) {
- //TEXT/BINARY translation - currently always called with O_BINARY.
- return O_BINARY;
- }
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl unlink(const char *filename) {
- // Called to delete files before an extract overwrite.
- TCHAR szPath[_MAX_PATH];
- mbstowcs(szPath, filename, countof(szPath));
- return (DeleteFile(szPath) ? 0: -1);
- }
- //******************************************************************************
- //***** STDIO.H functions
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl fflush(FILE *stream) {
- return (FlushFileBuffers((HANDLE)stream) ? 0 : EOF);
- }
- //******************************************************************************
- //-- Called from extract.c
- char * __cdecl fgets(char *string, int n, FILE *stream) {
- // stream always equals "stdin" and fgets() should never be called.
- DebugOut(TEXT("WARNING: fgets(0x%08X, %d, %08X) called."), string, n, stream);
- return NULL;
- }
- //******************************************************************************
- //-- Called from extract.c
- int __cdecl fileno(FILE *stream) {
- return (int)stream;
- }
- //******************************************************************************
- //-- Called from fileio.c
- FILE * __cdecl fopen(const char *filename, const char *mode) {
- // fopen() is used to create all extracted files.
- DWORD dwAccess = 0;
- DWORD dwCreate = 0;
- BOOL fAppend = FALSE;
- if (strstr(mode, "r+")) {
- dwAccess = GENERIC_READ | GENERIC_WRITE;
- dwCreate = OPEN_EXISTING;
- } else if (strstr(mode, "w+")) {
- dwAccess = GENERIC_READ | GENERIC_WRITE;
- dwCreate = CREATE_ALWAYS;
- } else if (strstr(mode, "a+")) {
- dwAccess = GENERIC_READ | GENERIC_WRITE;
- dwCreate = OPEN_ALWAYS;
- fAppend = TRUE;
- } else if (strstr(mode, "r")) {
- dwAccess = GENERIC_READ;
- dwCreate = OPEN_EXISTING;
- } else if (strstr(mode, "w")) {
- dwAccess = GENERIC_WRITE;
- dwCreate = CREATE_ALWAYS;
- } else if (strstr(mode, "a")) {
- dwAccess = GENERIC_WRITE;
- dwCreate = OPEN_ALWAYS;
- fAppend = TRUE;
- }
- TCHAR szPath[_MAX_PATH];
- mbstowcs(szPath, filename, countof(szPath));
- HANDLE hFile = CreateFile(szPath, dwAccess, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) {
- return NULL;
- }
- if (fAppend) {
- SetFilePointer(hFile, 0, NULL, FILE_END);
- }
- return (FILE*)hFile;
- }
- //******************************************************************************
- //-- Called from unshrink.c
- int __cdecl fprintf(FILE *stream, const char *format, ...) {
- // All standard output/error in Info-ZIP is handled through fprintf()
- if ((stream == stdout) || (stream == stderr)) {
- return 1;
- }
- // "stream" always equals "stderr" or "stdout" - log error if we see otherwise.
- DebugOut(TEXT("WARNING: fprintf(0x%08X, "%S", ...) called."), stream, format);
- return 0;
- }
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl fclose(FILE *stream) {
- return (CloseHandle((HANDLE)stream) ? 0 : EOF);
- }
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl putc(int c, FILE *stream) {
- DebugOut(TEXT("WARNING: putc(%d, 0x%08X) called."), c, stream);
- return 0;
- }
- //******************************************************************************
- //-- Called from intrface.c, extract.c, fileio.c, list.c, process.c
- int __cdecl sprintf(char *buffer, const char *format, ...) {
- WCHAR wszBuffer[512], wszFormat[512];
- mbstowcs(wszFormat, format, countof(wszFormat));
- BOOL fPercent = FALSE;
- for (WCHAR *pwsz = wszFormat; *pwsz; pwsz++) {
- if (*pwsz == L'%') {
- fPercent = !fPercent;
- } else if (fPercent && (((*pwsz >= L'a') && (*pwsz <= L'z')) ||
- ((*pwsz >= L'A') && (*pwsz <= L'Z'))))
- {
- if (*pwsz == L's') {
- *pwsz = L'S';
- } else if (*pwsz == L'S') {
- *pwsz = L's';
- }
- fPercent = FALSE;
- }
- }
- va_list pArgs;
- va_start(pArgs, format);
- _vsntprintf(wszBuffer, countof(wszBuffer), wszFormat, pArgs);
- va_end(pArgs);
- wcstombs(buffer, wszBuffer, countof(wszBuffer));
- return 0;
- }
- //******************************************************************************
- //***** STRING.H functions
- //******************************************************************************
- //-- Called from winmain.c
- int __cdecl _stricmp(const char *string1, const char *string2) {
- while (*string1 && ((*string1 | 0x20) == (*string2 | 0x20))) {
- string1++;
- string2++;
- }
- return (*string1 - *string2);
- }
- //******************************************************************************
- //-- Called from winmain.c
- char* __cdecl _strupr(char *string) {
- while (*string) {
- if ((*string >= 'a') && (*string <= 'z')) {
- *string -= 'a' - 'A';
- }
- string++;
- }
- return string;
- }
- //******************************************************************************
- //-- Called from _interface.c and winmain.c
- char* __cdecl strrchr(const char *string, int c) {
- // Walk to end of string.
- for (char *p = (char*)string; *p; p++) {
- }
- // Walk backwards looking for character.
- for (p--; p >= string; p--) {
- if ((int)*p == c) {
- return p;
- }
- }
- return NULL;
- }
- //******************************************************************************
- //***** CTYPE.H functions
- //******************************************************************************
- //-- Called from fileio.c
- int __cdecl isupper(int c) {
- return ((c >= 'A') && (c <= 'Z'));
- }
- //******************************************************************************
- //***** STAT.H functions
- //******************************************************************************
- //-- Called fileio.c, process.c, intrface.c
- int __cdecl stat(const char *path, struct stat *buffer) {
- // stat() is called on both the ZIP files and extracred files.
- // Clear our stat buffer to be safe.
- ZeroMemory(buffer, sizeof(struct stat));
- // Find the file/direcotry and fill in a WIN32_FIND_DATA structure.
- WIN32_FIND_DATA w32fd;
- ZeroMemory(&w32fd, sizeof(w32fd));
- TCHAR szPath[_MAX_PATH];
- mbstowcs(szPath, path, countof(szPath));
- HANDLE hFind = FindFirstFile(szPath, &w32fd);
- // Bail out now if we could not find the file/directory.
- if (hFind == INVALID_HANDLE_VALUE) {
- return -1;
- }
- // Close the find.
- FindClose(hFind);
- // Mode flags that are currently used: S_IWRITE, S_IFMT, S_IFDIR, S_IEXEC
- if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- buffer->st_mode = _S_IFDIR | _S_IREAD | _S_IEXEC;
- } else {
- buffer->st_mode = _S_IFREG | _S_IREAD;
- }
- if (!(w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
- buffer->st_mode |= _S_IWRITE;
- }
- // Store the file size.
- buffer->st_size = (_off_t)w32fd.nFileSizeLow;
- // Convert the modified FILETIME to a time_t and store it.
- DWORDLONG dwl = *(DWORDLONG*)&w32fd.ftLastWriteTime;
- buffer->st_mtime = (time_t)((dwl - (DWORDLONG)116444736000000000) / (DWORDLONG)10000000);
- return 0;
- }
- //******************************************************************************
- //***** TIME.H functions
- //******************************************************************************
- // Evaluates to TRUE if 'y' is a leap year, otherwise FALSE
- // #define IS_LEAP_YEAR(y) ((((y) % 4 == 0) && ((y) % 100 != 0)) || ((y) % 400 == 0))
- // The macro below is a reduced version of the above macro. It is valid for
- // years between 1901 and 2099 which easily includes all years representable
- // by the current implementation of time_t.
- #define IS_LEAP_YEAR(y) (((y) & 3) == 0)
- #define BASE_DOW 4 // 1/1/1970 was a Thursday.
- #define SECONDS_IN_A_DAY (24L * 60L * 60L) // Number of seconds in one day.
- // Month to Year Day conversion array.
- int M2YD[] = {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
- };
- // Month to Leap Year Day conversion array.
- int M2LYD[] = {
- 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
- };
- //******************************************************************************
- //-- Called from list.c
- struct tm * __cdecl localtime(const time_t *timer) {
- // Return value for localtime(). Source currently never references
- // more than one "tm" at a time, so the single return structure is ok.
- static struct tm g_tm;
- ZeroMemory(&g_tm, sizeof(g_tm));
- // Get our time zone information.
- TIME_ZONE_INFORMATION tzi;
- SafeGetTimeZoneInformation(&tzi);
- // Create a time_t that has been corrected for our time zone.
- time_t localTime = *timer - (tzi.Bias * 60L);
- // Decide if value is in Daylight Savings Time.
- if (g_tm.tm_isdst = (int)IsDST(&tzi, localTime)) {
- localTime -= tzi.DaylightBias * 60L; // usually 60 minutes
- } else {
- localTime -= tzi.StandardBias * 60L; // usually 0 minutes
- }
- // time_t is a 32-bit value for the seconds since January 1, 1970
- // FILETIME is a 64-bit value for the number of 100-nanosecond intervals
- // since January 1, 1601
- // Compute the FILETIME for the given local time.
- DWORDLONG dwl = ((DWORDLONG)116444736000000000 +
- ((DWORDLONG)localTime * (DWORDLONG)10000000));
- FILETIME ft = *(FILETIME*)&dwl;
- // Convert the FILETIME to a SYSTEMTIME.
- SYSTEMTIME st;
- ZeroMemory(&st, sizeof(st));
- FileTimeToSystemTime(&ft, &st);
- // Finish filling in our "tm" structure.
- g_tm.tm_sec = (int)st.wSecond;
- g_tm.tm_min = (int)st.wMinute;
- g_tm.tm_hour = (int)st.wHour;
- g_tm.tm_mday = (int)st.wDay;
- g_tm.tm_mon = (int)st.wMonth - 1;
- g_tm.tm_year = (int)st.wYear - 1900;
- return &g_tm;
- }
- //******************************************************************************
- void SafeGetTimeZoneInformation(TIME_ZONE_INFORMATION *ptzi) {
- ZeroMemory(ptzi, sizeof(TIME_ZONE_INFORMATION));
- // Ask the OS for the standard/daylight rules for the current time zone.
- if ((GetTimeZoneInformation(ptzi) == 0xFFFFFFFF) ||
- (ptzi->StandardDate.wMonth > 12) || (ptzi->DaylightDate.wMonth > 12))
- {
- // If the OS fails us, we default to the United States' rules.
- ZeroMemory(ptzi, sizeof(TIME_ZONE_INFORMATION));
- ptzi->StandardDate.wMonth = 10; // October
- ptzi->StandardDate.wDay = 5; // Last Sunday (DOW == 0)
- ptzi->StandardDate.wHour = 2; // At 2:00 AM
- ptzi->DaylightBias = -60; // One hour difference
- ptzi->DaylightDate.wMonth = 4; // April
- ptzi->DaylightDate.wDay = 1; // First Sunday (DOW == 0)
- ptzi->DaylightDate.wHour = 2; // At 2:00 AM
- }
- }
- //******************************************************************************
- time_t GetTransitionTimeT(TIME_ZONE_INFORMATION *ptzi, int year, BOOL fStartDST) {
- // We only handle years within the range that time_t supports. We need to
- // handle the very end of 1969 since the local time could be up to 13 hours
- // into the previous year. In this case, our code will actually return a
- // negative value, but it will be compared to another negative value and is
- // handled correctly. The same goes for the 13 hours past a the max time_t
- // value of 0x7FFFFFFF (in the year 2038). Again, these values are handled
- // correctly as well.
- if ((year < 1969) || (year > 2038)) {
- return (time_t)0;
- }
- SYSTEMTIME *pst = fStartDST ? &ptzi->DaylightDate : &ptzi->StandardDate;
- // WORD wYear Year (0000 == 0)
- // WORD wMonth Month (January == 1)
- // WORD wDayOfWeek Day of week (Sunday == 0)
- // WORD wDay Month day (1 - 31)
- // WORD wHour Hour (0 - 23)
- // WORD wMinute Minute (0 - 59)
- // WORD wSecond Second (0 - 59)
- // WORD wMilliseconds Milliseconds (0 - 999)
- // Compute the number of days since 1/1/1970 to the beginning of this year.
- long daysToYear = ((year - 1970) * 365) // Tally up previous years.
- + ((year - 1969) >> 2); // Add few extra for the leap years.
- // Compute the number of days since the beginning of this year to the
- // beginning of the month. We will add to this value to get the actual
- // year day.
- long yearDay = IS_LEAP_YEAR(year) ? M2LYD[pst->wMonth - 1] :
- M2YD [pst->wMonth - 1];
- // Check for day-in-month format.
- if (pst->wYear == 0) {
- // Compute the week day for the first day of the month (Sunday == 0).
- long monthDOW = (daysToYear + yearDay + BASE_DOW) % 7;
- // Add the day offset of the transition day to the year day.
- if (monthDOW < pst->wDayOfWeek) {
- yearDay += (pst->wDayOfWeek - monthDOW) + (pst->wDay - 1) * 7;
- } else {
- yearDay += (pst->wDayOfWeek - monthDOW) + pst->wDay * 7;
- }
- // It is possible that we overshot the month, especially if pst->wDay
- // is 5 (which means the last instance of the day in the month). Check
- // if the year-day has exceeded the month and adjust accordingly.
- if ((pst->wDay == 5) &&
- (yearDay >= (IS_LEAP_YEAR(year) ? M2LYD[pst->wMonth] :
- M2YD [pst->wMonth])))
- {
- yearDay -= 7;
- }
- // If not day-in-month format, then we assume an absolute date.
- } else {
- // Simply add the month day to the current year day.
- yearDay += pst->wDay - 1;
- }
- // Tally up all our days, hours, minutes, and seconds since 1970.
- long seconds = ((SECONDS_IN_A_DAY * (daysToYear + yearDay)) +
- (3600L * (long)pst->wHour) +
- (60L * (long)pst->wMinute) +
- (long)pst->wSecond);
- // If we are checking for the end of DST, then we need to add the DST bias
- // since we are in DST when we chack this time stamp.
- if (!fStartDST) {
- seconds += ptzi->DaylightBias * 60L;
- }
- return (time_t)seconds;
- }
- //******************************************************************************
- BOOL IsDST(TIME_ZONE_INFORMATION *ptzi, time_t localTime) {
- // If either of the months is 0, then this usually means that the time zone
- // does not use DST. Unfortunately, Windows CE since it has a bug where it
- // never really fills in these fields with the correct values, so it appears
- // like we are never in DST. This is supposed to be fixed in future releases,
- // so hopefully this code will get some use then.
- if ((ptzi->StandardDate.wMonth == 0) || (ptzi->DaylightDate.wMonth == 0)) {
- return FALSE;
- }
- // time_t is a 32-bit value for the seconds since January 1, 1970
- // FILETIME is a 64-bit value for the number of 100-nanosecond intervals
- // since January 1, 1601
- // Compute the FILETIME for the given local time.
- DWORDLONG dwl = ((DWORDLONG)116444736000000000 +
- ((DWORDLONG)localTime * (DWORDLONG)10000000));
- FILETIME ft = *(FILETIME*)&dwl;
- // Convert the FILETIME to a SYSTEMTIME.
- SYSTEMTIME st;
- ZeroMemory(&st, sizeof(st));
- FileTimeToSystemTime(&ft, &st);
- // Get our start and end daylisght savings times.
- time_t timeStart = GetTransitionTimeT(ptzi, (int)st.wYear, TRUE);
- time_t timeEnd = GetTransitionTimeT(ptzi, (int)st.wYear, FALSE);
- // Check what hemisphere we are in.
- if (timeStart < timeEnd) {
- // Northern hemisphere ordering.
- return ((localTime >= timeStart) && (localTime < timeEnd));
- } else if (timeStart > timeEnd) {
- // Southern hemisphere ordering.
- return ((localTime < timeEnd) || (localTime >= timeStart));
- }
- // If timeStart equals timeEnd then this time zone does not support DST.
- return FALSE;
- }
- #endif // _WIN32_WCE