home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip540.zip / wince / wince.cpp < prev    next >
C/C++ Source or Header  |  1997-04-26  |  22KB  |  638 lines

  1. //******************************************************************************
  2. //
  3. // File:        WINCE.CPP
  4. //
  5. // Description: This file implements all the Win32 APIs and C runtime functions
  6. //              that the Info-ZIP code calls, but are not implemented natively
  7. //              on Windows CE.
  8. //
  9. // Copyright:   All the source files for Pocket UnZip, except for components
  10. //              written by the Info-ZIP group, are copyrighted 1997 by Steve P.
  11. //              Miller.  The product "Pocket UnZip" itself is property of the
  12. //              author and cannot be altered in any way without written consent
  13. //              from Steve P. Miller.
  14. //
  15. // Disclaimer:  All project files are provided "as is" with no guarantee of
  16. //              their correctness.  The authors are not liable for any outcome
  17. //              that is the result of using this source.  The source for Pocket
  18. //              UnZip has been placed in the public domain to help provide an
  19. //              understanding of its implementation.  You are hereby granted
  20. //              full permission to use this source in any way you wish, except
  21. //              to alter Pocket UnZip itself.  For comments, suggestions, and
  22. //              bug reports, please write to stevemil@pobox.com.
  23. //
  24. // Functions:   DebugOut
  25. //              chmod
  26. //              close
  27. //              isatty
  28. //              lseek
  29. //              open
  30. //              read
  31. //              setmode
  32. //              unlink
  33. //              fflush
  34. //              fgets
  35. //              fileno
  36. //              fopen
  37. //              fprintf
  38. //              fclose
  39. //              putc
  40. //              sprintf
  41. //              _stricmp
  42. //              _strupr
  43. //              strrchr
  44. //              localtime
  45. //              isupper
  46. //              stat
  47. //              localtime
  48. //              SafeGetTimeZoneInformation
  49. //              GetTransitionTimeT
  50. //              IsDST
  51. //
  52. //
  53. // Date      Name          History
  54. // --------  ------------  -----------------------------------------------------
  55. // 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)
  56. //
  57. //******************************************************************************
  58.  
  59.  
  60. extern "C" {
  61. #include "punzip.h"
  62. }
  63. #include <tchar.h> // Must be outside of extern "C" block
  64.  
  65.  
  66. //******************************************************************************
  67. //***** For all platforms - Our debug output function
  68. //******************************************************************************
  69.  
  70. #ifdef DEBUG // RETAIL version is __inline and does not generate any code.
  71.  
  72. void DebugOut(LPCTSTR szFormat, ...) {
  73.    TCHAR szBuffer[512] = TEXT("PUNZIP: ");
  74.  
  75.    va_list pArgs; 
  76.    va_start(pArgs, szFormat);
  77.    _vsntprintf(szBuffer + 8, countof(szBuffer) - 10, szFormat, pArgs);
  78.    va_end(pArgs);
  79.  
  80.    TCHAR *psz = szBuffer;
  81.    while (psz = _tcschr(psz, TEXT('\n'))) {
  82.       *psz = TEXT('|');
  83.    }
  84.    psz = szBuffer;
  85.    while (psz = _tcschr(psz, TEXT('\r'))) {
  86.       *psz = TEXT('|');
  87.    }
  88.  
  89.    _tcscat(szBuffer, TEXT("\r\n"));
  90.  
  91.    OutputDebugString(szBuffer);
  92. }
  93.  
  94. #endif // DEBUG
  95.  
  96.  
  97. //******************************************************************************
  98. //***** Windows CE Native
  99. //******************************************************************************
  100.  
  101. #if defined(_WIN32_WCE)
  102.  
  103. //******************************************************************************
  104. //***** Local Function Prototyopes
  105. //******************************************************************************
  106.  
  107. void SafeGetTimeZoneInformation(TIME_ZONE_INFORMATION *ptzi);
  108. time_t GetTransitionTimeT(TIME_ZONE_INFORMATION *ptzi, int year, BOOL fStartDST);
  109. BOOL IsDST(TIME_ZONE_INFORMATION *ptzi, time_t localTime);
  110.  
  111. //******************************************************************************
  112. //***** IO.H functions
  113. //******************************************************************************
  114.  
  115. //-- Called from fileio.c
  116. int __cdecl chmod(const char *filename, int pmode) {
  117.    // Called before unlink() to delete read-only files.
  118.  
  119.    DWORD dwAttribs = (pmode & _S_IWRITE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_READONLY;
  120.  
  121.    TCHAR szPath[_MAX_PATH];
  122.    mbstowcs(szPath, filename, countof(szPath));
  123.    return (SetFileAttributes(szPath, dwAttribs) ? 0 : -1);
  124. }
  125.  
  126. //******************************************************************************
  127. //-- Called from process.c
  128. int __cdecl close(int handle) {
  129.    return (CloseHandle((HANDLE)handle) ? 0 : -1);
  130. }
  131.  
  132. //******************************************************************************
  133. //-- Called from fileio.c
  134. int __cdecl isatty(int handle) {
  135.    // returns TRUE if handle is a terminal, console, printer, or serial port
  136.    // called with 1 (stdout) and 2 (stderr)
  137.    return 0;
  138. }
  139.  
  140. //******************************************************************************
  141. //-- Called from extract.c, fileio.c, process.c
  142. long __cdecl lseek(int handle, long offset, int origin) {
  143.    // SEEK_SET, SEEK_CUR, SEEK_END are equal to FILE_BEGIN, FILE_CURRENT, FILE_END   
  144.    return SetFilePointer((HANDLE)handle, offset, NULL, origin);
  145. }
  146.                  
  147. //******************************************************************************
  148. //-- Called from fileio.c
  149. int __cdecl open(const char *filename, int oflag, ...) {
  150.  
  151.    // The Info-Zip code currently only opens existing ZIP files for read using open().
  152.  
  153.    TCHAR szPath[_MAX_PATH];
  154.    mbstowcs(szPath, filename, countof(szPath));
  155.    HANDLE hFile = CreateFile(szPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  156.                              NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  157.    return ((hFile == INVALID_HANDLE_VALUE) ? -1 : (int)hFile);
  158. }
  159.  
  160. //******************************************************************************
  161. //-- Called from extract.c, fileio.c, process.c
  162. int __cdecl read(int handle, void *buffer, unsigned int count) {
  163.    DWORD dwRead = 0;
  164.    return (ReadFile((HANDLE)handle, buffer, count, &dwRead, NULL) ? dwRead : -1);
  165. }
  166.  
  167. //******************************************************************************
  168. //-- Called from extract.c
  169. int __cdecl setmode(int handle, int mode) {
  170.    //TEXT/BINARY translation - currently always called with O_BINARY.
  171.    return O_BINARY;
  172. }
  173.  
  174. //******************************************************************************
  175. //-- Called from fileio.c
  176. int __cdecl unlink(const char *filename) {
  177.  
  178.    // Called to delete files before an extract overwrite.
  179.  
  180.    TCHAR szPath[_MAX_PATH];
  181.    mbstowcs(szPath, filename, countof(szPath));
  182.    return (DeleteFile(szPath) ? 0: -1);
  183. }
  184.  
  185. //******************************************************************************
  186. //***** STDIO.H functions
  187. //******************************************************************************
  188.  
  189. //-- Called from fileio.c
  190. int __cdecl fflush(FILE *stream) {
  191.    return (FlushFileBuffers((HANDLE)stream) ? 0 : EOF);
  192. }
  193.  
  194. //******************************************************************************
  195. //-- Called from extract.c
  196. char * __cdecl fgets(char *string, int n, FILE *stream) {
  197.    // stream always equals "stdin" and fgets() should never be called.
  198.    DebugOut(TEXT("WARNING: fgets(0x%08X, %d, %08X) called."), string, n, stream);
  199.    return NULL;
  200. }
  201.  
  202. //******************************************************************************
  203. //-- Called from extract.c
  204. int __cdecl fileno(FILE *stream) {
  205.    return (int)stream;
  206. }
  207.  
  208. //******************************************************************************
  209. //-- Called from fileio.c
  210. FILE * __cdecl fopen(const char *filename, const char *mode) {
  211.  
  212.    // fopen() is used to create all extracted files.
  213.  
  214.    DWORD dwAccess = 0;
  215.    DWORD dwCreate = 0;
  216.    BOOL  fAppend  = FALSE;
  217.  
  218.    if (strstr(mode, "r+")) {
  219.       dwAccess = GENERIC_READ | GENERIC_WRITE;
  220.       dwCreate = OPEN_EXISTING;
  221.    } else if (strstr(mode, "w+")) {
  222.       dwAccess = GENERIC_READ | GENERIC_WRITE;
  223.       dwCreate = CREATE_ALWAYS;
  224.    } else if (strstr(mode, "a+")) {
  225.       dwAccess = GENERIC_READ | GENERIC_WRITE;
  226.       dwCreate = OPEN_ALWAYS;
  227.       fAppend = TRUE;
  228.    } else if (strstr(mode, "r")) {
  229.       dwAccess = GENERIC_READ;
  230.       dwCreate = OPEN_EXISTING;
  231.    } else if (strstr(mode, "w")) {
  232.       dwAccess = GENERIC_WRITE;
  233.       dwCreate = CREATE_ALWAYS;
  234.    } else if (strstr(mode, "a")) {
  235.       dwAccess = GENERIC_WRITE;
  236.       dwCreate = OPEN_ALWAYS;
  237.       fAppend  = TRUE;
  238.    }
  239.  
  240.    TCHAR szPath[_MAX_PATH];
  241.    mbstowcs(szPath, filename, countof(szPath));
  242.    HANDLE hFile = CreateFile(szPath, dwAccess, FILE_SHARE_READ | FILE_SHARE_WRITE,
  243.                              NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);
  244.  
  245.    if (hFile == INVALID_HANDLE_VALUE) {
  246.       return NULL;
  247.    }
  248.  
  249.    if (fAppend) {
  250.       SetFilePointer(hFile, 0, NULL, FILE_END);
  251.    }
  252.  
  253.    return (FILE*)hFile;
  254. }
  255.  
  256. //******************************************************************************
  257. //-- Called from unshrink.c
  258. int __cdecl fprintf(FILE *stream, const char *format, ...) {
  259.    
  260.    // All standard output/error in Info-ZIP is handled through fprintf()
  261.    if ((stream == stdout) || (stream == stderr)) {
  262.       return 1;
  263.    }
  264.  
  265.    // "stream" always equals "stderr" or "stdout" - log error if we see otherwise.
  266.    DebugOut(TEXT("WARNING: fprintf(0x%08X, \"%S\", ...) called."), stream, format);
  267.    return 0;
  268. }
  269.  
  270. //******************************************************************************
  271. //-- Called from fileio.c
  272. int __cdecl fclose(FILE *stream) {
  273.    return (CloseHandle((HANDLE)stream) ? 0 : EOF);
  274. }
  275.  
  276. //******************************************************************************
  277. //-- Called from fileio.c
  278. int __cdecl putc(int c, FILE *stream) {
  279.    DebugOut(TEXT("WARNING: putc(%d, 0x%08X) called."), c, stream);
  280.    return 0;
  281. }
  282.  
  283. //******************************************************************************
  284. //-- Called from intrface.c, extract.c, fileio.c, list.c, process.c
  285. int __cdecl sprintf(char *buffer, const char *format, ...) {
  286.  
  287.    WCHAR wszBuffer[512], wszFormat[512];
  288.  
  289.    mbstowcs(wszFormat, format, countof(wszFormat));
  290.    BOOL fPercent = FALSE;
  291.    for (WCHAR *pwsz = wszFormat; *pwsz; pwsz++) {
  292.       if (*pwsz == L'%') {
  293.          fPercent = !fPercent;
  294.       } else if (fPercent && (((*pwsz >= L'a') && (*pwsz <= L'z')) || 
  295.                               ((*pwsz >= L'A') && (*pwsz <= L'Z')))) 
  296.       {
  297.          if (*pwsz == L's') {
  298.             *pwsz = L'S';
  299.          } else if (*pwsz == L'S') {
  300.             *pwsz = L's';
  301.          }
  302.          fPercent = FALSE;
  303.       }
  304.    }
  305.  
  306.    va_list pArgs; 
  307.    va_start(pArgs, format);
  308.    _vsntprintf(wszBuffer, countof(wszBuffer), wszFormat, pArgs);
  309.    va_end(pArgs);
  310.  
  311.    wcstombs(buffer, wszBuffer, countof(wszBuffer));
  312.  
  313.    return 0;
  314. }
  315.  
  316. //******************************************************************************
  317. //***** STRING.H functions
  318. //******************************************************************************
  319.  
  320. //-- Called from winmain.c
  321. int __cdecl _stricmp(const char *string1, const char *string2) {
  322.    while (*string1 && ((*string1 | 0x20) == (*string2 | 0x20))) {
  323.       string1++;
  324.       string2++;
  325.    }
  326.    return (*string1 - *string2);
  327. }
  328.  
  329. //******************************************************************************
  330. //-- Called from winmain.c
  331. char* __cdecl _strupr(char *string) {
  332.    while (*string) {
  333.       if ((*string >= 'a') && (*string <= 'z')) {
  334.          *string -= 'a' - 'A';
  335.       }
  336.       string++;
  337.    }
  338.    return string;
  339. }
  340.  
  341. //******************************************************************************
  342. //-- Called from _interface.c and winmain.c
  343. char* __cdecl strrchr(const char *string, int c) {
  344.  
  345.    // Walk to end of string.
  346.    for (char *p = (char*)string; *p; p++) {
  347.    }
  348.  
  349.    // Walk backwards looking for character.
  350.    for (p--; p >= string; p--) {
  351.       if ((int)*p == c) {
  352.          return p;
  353.       }
  354.    }
  355.  
  356.    return NULL;
  357. }
  358.  
  359. //******************************************************************************
  360. //***** CTYPE.H functions
  361. //******************************************************************************
  362.  
  363. //-- Called from fileio.c
  364. int __cdecl isupper(int c) {
  365.    return ((c >= 'A') && (c <= 'Z'));
  366. }
  367.  
  368. //******************************************************************************
  369. //***** STAT.H functions
  370. //******************************************************************************
  371.  
  372. //-- Called fileio.c, process.c, intrface.c
  373. int __cdecl stat(const char *path, struct stat *buffer) {
  374.  
  375.    // stat() is called on both the ZIP files and extracred files.
  376.  
  377.    // Clear our stat buffer to be safe.
  378.    ZeroMemory(buffer, sizeof(struct stat));
  379.  
  380.    // Find the file/direcotry and fill in a WIN32_FIND_DATA structure.
  381.    WIN32_FIND_DATA w32fd;
  382.    ZeroMemory(&w32fd, sizeof(w32fd));
  383.  
  384.    TCHAR szPath[_MAX_PATH];
  385.    mbstowcs(szPath, path, countof(szPath));
  386.    HANDLE hFind = FindFirstFile(szPath, &w32fd);
  387.  
  388.    // Bail out now if we could not find the file/directory.
  389.    if (hFind == INVALID_HANDLE_VALUE) {
  390.       return -1;
  391.    }
  392.  
  393.    // Close the find.
  394.    FindClose(hFind);
  395.  
  396.    // Mode flags that are currently used: S_IWRITE, S_IFMT, S_IFDIR, S_IEXEC
  397.    if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  398.       buffer->st_mode = _S_IFDIR | _S_IREAD | _S_IEXEC;
  399.    } else {
  400.       buffer->st_mode = _S_IFREG | _S_IREAD;
  401.    }
  402.    if (!(w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
  403.       buffer->st_mode |= _S_IWRITE;
  404.    }
  405.  
  406.    // Store the file size.
  407.    buffer->st_size  = (_off_t)w32fd.nFileSizeLow;
  408.  
  409.    // Convert the modified FILETIME to a time_t and store it.
  410.    DWORDLONG dwl = *(DWORDLONG*)&w32fd.ftLastWriteTime;
  411.    buffer->st_mtime = (time_t)((dwl - (DWORDLONG)116444736000000000) / (DWORDLONG)10000000);
  412.  
  413.    return 0;
  414. }
  415.  
  416. //******************************************************************************
  417. //***** TIME.H functions
  418. //******************************************************************************
  419.  
  420. // Evaluates to TRUE if 'y' is a leap year, otherwise FALSE
  421. // #define IS_LEAP_YEAR(y) ((((y) % 4 == 0) && ((y) % 100 != 0)) || ((y) % 400 == 0))
  422.  
  423. // The macro below is a reduced version of the above macro.  It is valid for
  424. // years between 1901 and 2099 which easily includes all years representable
  425. // by the current implementation of time_t.
  426. #define IS_LEAP_YEAR(y) (((y) & 3) == 0) 
  427.  
  428. #define BASE_DOW          4                  // 1/1/1970 was a Thursday.
  429. #define SECONDS_IN_A_DAY  (24L * 60L * 60L)  // Number of seconds in one day.
  430.  
  431. // Month to Year Day conversion array.
  432. int M2YD[] = {
  433.    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  434. };
  435.  
  436. // Month to Leap Year Day conversion array.
  437. int M2LYD[] = {
  438.    0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
  439. };
  440.  
  441. //******************************************************************************
  442. //-- Called from list.c
  443. struct tm * __cdecl localtime(const time_t *timer) {
  444.  
  445.    // Return value for localtime().  Source currently never references
  446.    // more than one "tm" at a time, so the single return structure is ok.
  447.    static struct tm g_tm; 
  448.    ZeroMemory(&g_tm, sizeof(g_tm));
  449.  
  450.    // Get our time zone information.
  451.    TIME_ZONE_INFORMATION tzi;
  452.    SafeGetTimeZoneInformation(&tzi);
  453.  
  454.    // Create a time_t that has been corrected for our time zone.
  455.    time_t localTime = *timer - (tzi.Bias * 60L);
  456.  
  457.    // Decide if value is in Daylight Savings Time.
  458.    if (g_tm.tm_isdst = (int)IsDST(&tzi, localTime)) {
  459.       localTime -= tzi.DaylightBias * 60L; // usually 60 minutes
  460.    } else {
  461.       localTime -= tzi.StandardBias * 60L; // usually  0 minutes
  462.    }
  463.  
  464.    // time_t   is a 32-bit value for the seconds since January 1, 1970
  465.    // FILETIME is a 64-bit value for the number of 100-nanosecond intervals
  466.    //          since January 1, 1601
  467.  
  468.    // Compute the FILETIME for the given local time.
  469.    DWORDLONG dwl = ((DWORDLONG)116444736000000000 + 
  470.                    ((DWORDLONG)localTime * (DWORDLONG)10000000));
  471.    FILETIME ft = *(FILETIME*)&dwl;
  472.  
  473.    // Convert the FILETIME to a SYSTEMTIME.
  474.    SYSTEMTIME st;
  475.    ZeroMemory(&st, sizeof(st));
  476.    FileTimeToSystemTime(&ft, &st);
  477.  
  478.    // Finish filling in our "tm" structure.
  479.    g_tm.tm_sec  = (int)st.wSecond;
  480.    g_tm.tm_min  = (int)st.wMinute;
  481.    g_tm.tm_hour = (int)st.wHour;
  482.    g_tm.tm_mday = (int)st.wDay;
  483.    g_tm.tm_mon  = (int)st.wMonth - 1;
  484.    g_tm.tm_year = (int)st.wYear - 1900;
  485.  
  486.    return &g_tm;
  487. }
  488.  
  489. //******************************************************************************
  490. void SafeGetTimeZoneInformation(TIME_ZONE_INFORMATION *ptzi) {
  491.  
  492.    ZeroMemory(ptzi, sizeof(TIME_ZONE_INFORMATION));
  493.  
  494.    // Ask the OS for the standard/daylight rules for the current time zone.
  495.    if ((GetTimeZoneInformation(ptzi) == 0xFFFFFFFF) ||
  496.        (ptzi->StandardDate.wMonth > 12) || (ptzi->DaylightDate.wMonth > 12))
  497.    {
  498.       // If the OS fails us, we default to the United States' rules.
  499.       ZeroMemory(ptzi, sizeof(TIME_ZONE_INFORMATION));
  500.       ptzi->StandardDate.wMonth =  10;  // October
  501.       ptzi->StandardDate.wDay   =   5;  // Last Sunday (DOW == 0)
  502.       ptzi->StandardDate.wHour  =   2;  // At 2:00 AM
  503.       ptzi->DaylightBias        = -60;  // One hour difference
  504.       ptzi->DaylightDate.wMonth =   4;  // April
  505.       ptzi->DaylightDate.wDay   =   1;  // First Sunday (DOW == 0)
  506.       ptzi->DaylightDate.wHour  =   2;  // At 2:00 AM
  507.    }
  508. }
  509.  
  510. //******************************************************************************
  511. time_t GetTransitionTimeT(TIME_ZONE_INFORMATION *ptzi, int year, BOOL fStartDST) {
  512.  
  513.    // We only handle years within the range that time_t supports.  We need to 
  514.    // handle the very end of 1969 since the local time could be up to 13 hours
  515.    // into the previous year.  In this case, our code will actually return a
  516.    // negative value, but it will be compared to another negative value and is
  517.    // handled correctly.  The same goes for the 13 hours past a the max time_t
  518.    // value of 0x7FFFFFFF (in the year 2038).  Again, these values are handled
  519.    // correctly as well.
  520.  
  521.    if ((year < 1969) || (year > 2038)) {
  522.       return (time_t)0;
  523.    }
  524.  
  525.    SYSTEMTIME *pst = fStartDST ? &ptzi->DaylightDate : &ptzi->StandardDate;
  526.  
  527.    // WORD wYear          Year (0000 == 0)
  528.    // WORD wMonth         Month (January == 1)
  529.    // WORD wDayOfWeek     Day of week (Sunday == 0)
  530.    // WORD wDay           Month day (1 - 31)
  531.    // WORD wHour          Hour (0 - 23)
  532.    // WORD wMinute        Minute (0 - 59)
  533.    // WORD wSecond        Second (0 - 59)
  534.    // WORD wMilliseconds  Milliseconds (0 - 999)
  535.  
  536.    // Compute the number of days since 1/1/1970 to the beginning of this year.
  537.    long daysToYear = ((year - 1970) * 365) // Tally up previous years.
  538.                    + ((year - 1969) >> 2); // Add few extra for the leap years.
  539.  
  540.    // Compute the number of days since the beginning of this year to the
  541.    // beginning of the month.  We will add to this value to get the actual
  542.    // year day.
  543.    long yearDay = IS_LEAP_YEAR(year) ? M2LYD[pst->wMonth - 1] : 
  544.                                        M2YD [pst->wMonth - 1];
  545.  
  546.    // Check for day-in-month format.
  547.    if (pst->wYear == 0) {
  548.  
  549.       // Compute the week day for the first day of the month (Sunday == 0).
  550.       long monthDOW = (daysToYear + yearDay + BASE_DOW) % 7;
  551.  
  552.       // Add the day offset of the transition day to the year day.
  553.       if (monthDOW < pst->wDayOfWeek) {
  554.          yearDay += (pst->wDayOfWeek - monthDOW) + (pst->wDay - 1) * 7;
  555.       } else {
  556.          yearDay += (pst->wDayOfWeek - monthDOW) + pst->wDay * 7;
  557.       }
  558.  
  559.       // It is possible that we overshot the month, especially if pst->wDay
  560.       // is 5 (which means the last instance of the day in the month). Check
  561.       // if the year-day has exceeded the month and adjust accordingly.
  562.       if ((pst->wDay == 5) &&
  563.           (yearDay >= (IS_LEAP_YEAR(year) ? M2LYD[pst->wMonth] : 
  564.                                             M2YD [pst->wMonth])))
  565.       {
  566.          yearDay -= 7;
  567.       }
  568.  
  569.    // If not day-in-month format, then we assume an absolute date.
  570.    } else {
  571.  
  572.       // Simply add the month day to the current year day.
  573.       yearDay += pst->wDay - 1;
  574.    }
  575.  
  576.    // Tally up all our days, hours, minutes, and seconds since 1970.
  577.    long seconds = ((SECONDS_IN_A_DAY * (daysToYear + yearDay)) + 
  578.                    (3600L * (long)pst->wHour) + 
  579.                    (60L * (long)pst->wMinute) +
  580.                    (long)pst->wSecond);
  581.    
  582.    // If we are checking for the end of DST, then we need to add the DST bias
  583.    // since we are in DST when we chack this time stamp.
  584.    if (!fStartDST) {
  585.       seconds += ptzi->DaylightBias * 60L;
  586.    }
  587.  
  588.    return (time_t)seconds;
  589. }
  590.  
  591. //******************************************************************************
  592. BOOL IsDST(TIME_ZONE_INFORMATION *ptzi, time_t localTime) {
  593.  
  594.    // If either of the months is 0, then this usually means that the time zone
  595.    // does not use DST.  Unfortunately, Windows CE since it has a bug where it
  596.    // never really fills in these fields with the correct values, so it appears
  597.    // like we are never in DST.  This is supposed to be fixed in future releases,
  598.    // so hopefully this code will get some use then.
  599.    if ((ptzi->StandardDate.wMonth == 0) || (ptzi->DaylightDate.wMonth == 0)) {
  600.       return FALSE;
  601.    }
  602.  
  603.    // time_t   is a 32-bit value for the seconds since January 1, 1970
  604.    // FILETIME is a 64-bit value for the number of 100-nanosecond intervals
  605.    //          since January 1, 1601
  606.  
  607.    // Compute the FILETIME for the given local time.
  608.    DWORDLONG dwl = ((DWORDLONG)116444736000000000 + 
  609.                    ((DWORDLONG)localTime * (DWORDLONG)10000000));
  610.    FILETIME ft = *(FILETIME*)&dwl;
  611.  
  612.    // Convert the FILETIME to a SYSTEMTIME.
  613.    SYSTEMTIME st;
  614.    ZeroMemory(&st, sizeof(st));
  615.    FileTimeToSystemTime(&ft, &st);
  616.  
  617.    // Get our start and end daylisght savings times. 
  618.    time_t timeStart = GetTransitionTimeT(ptzi, (int)st.wYear, TRUE);
  619.    time_t timeEnd   = GetTransitionTimeT(ptzi, (int)st.wYear, FALSE);
  620.  
  621.    // Check what hemisphere we are in.
  622.    if (timeStart < timeEnd) {
  623.  
  624.       // Northern hemisphere ordering.
  625.       return ((localTime >= timeStart) && (localTime < timeEnd));
  626.  
  627.    } else if (timeStart > timeEnd) {
  628.  
  629.       // Southern hemisphere ordering.
  630.       return ((localTime < timeEnd) || (localTime >= timeStart));
  631.    }
  632.  
  633.    // If timeStart equals timeEnd then this time zone does not support DST.
  634.    return FALSE;
  635. }
  636.  
  637. #endif // _WIN32_WCE
  638.