In a VS2008 debug build of my Windows mobile 6 application, I'm getting an exception thrown whenever I try to write to a newly created CFile using a CArchive. The call stack, with relevant code inserted, is as follows;
MFC90UD.DLL!ATL::CTime::CTime(int nYear = 60056, int nMonth = 5, int nDay = 27, int nHour = 22, int nMin = 44, int nSec = 51, int nDST = -1) Line: 197, Byte Offsets: 0x474 C++
ATLTIME_INLINE CTime::CTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec,
int nDST)
{
#pragma warning (push)
#pragma warning (disable: 4127) // conditional expression constant
ATLENSURE( nYear >= 1900 );
ATLENSURE( nMonth >= 1 && nMonth <= 12 );
ATLENSURE( nDay >= 1 && nDay <= 31 );
ATLENSURE( nHour >= 0 && nHour <= 23 );
ATLENSURE( nMin >= 0 && nMin <= 59 );
ATLENSURE( nSec >= 0 && nSec <= 59 );
#pragma warning (pop)
struct tm atm;
atm.tm_sec = nSec;
atm.tm_min = nMin;
atm.tm_hour = nHour;
atm.tm_mday = nDay;
atm.tm_mon = nMonth - 1; // tm_mon is 0 based
atm.tm_year = nYear - 1900; // tm_year is 1900 based
atm.tm_isdst = nDST;
m_time = _mktime64(&atm);
ATLASSUME(m_time != -1); // indicates an illegal input time
if(m_time == -1)
{
AtlThrow(E_INVALIDARG); <--- we get an exception thrown here, due to the invalid year
}
}
MFC90UD.DLL!ATL::CTime::CTime(_SYSTEMTIME& sysTime = {...}, int nDST = -1) Line: 237, Byte Offsets: 0xd0 C++
ATLTIME_INLINE CTime::CTime(const SYSTEMTIME& sysTime, int nDST)
{
if (sysTime.wYear < 1900)
{
__time64_t time0 = 0L;
CTime timeT(time0);
*this = timeT;
}
else
{
CTime timeT(
(int)sysTime.wYear, (int)sysTime.wMonth, (int)sysTime.wDay,
(int)sysTime.wHour, (int)sysTime.wMinute, (int)sysTime.wSecond,
nDST);
*this = timeT;
}
}
MFC90UD.DLL!ATL::CTime::CTime(_FILETIME& fileTime = {...}, int nDST = -1) Line: 263, Byte Offsets: 0xc8 C++
ATLTIME_INLINE CTime::CTime(const FILETIME& fileTime, int nDST)
{
// first convert file time (UTC time) to local time
FILETIME localTime;
if (!FileTimeToLocalFileTime(&fileTime, &localTime))
{
m_time = 0;
AtlThrow(E_INVALIDARG);
return;
}
// then convert that time to system time
SYSTEMTIME sysTime;
if (!FileTimeToSystemTime(&localTime, &sysTime))
{
m_time = 0;
AtlThrow(E_INVALIDARG);
return;
}
// then convert the system time to a time_t (C-runtime local time)
CTime timeT(sysTime, nDST);
*this = timeT;
}
MFC90UD.DLL!CFile::GetStatus(CFileStatus& rStatus = {...}) Line: 151, Byte Offsets: 0x288 C++
if (CTime::IsValidFILETIME(ftAccess))
{
rStatus.m_atime = CTime(ftAccess);
}
else
{
rStatus.m_atime = CTime();
}
MFC90UD.DLL!CFile::GetFilePath(void) Line: 83, Byte Offsets: 0x48 C++
MFC90UD.DLL!CArchive::CArchive(CFile* pFile = 0x1b38ebd4, unsigned int nMode = 0, int nBufSize = 4096, void* lpBuf = 0x00000000) Line: 255, Byte Offsets: 0x64 C++
PDTMWM6.exe!CPocketDTMDoc::SaveToDisk(void) Line: 1625, Byte Offsets: 0x1e8 C++
The start of this stack in my own code is as follows;
CFile File(JobName,CFile::modeWrite | CFile::modeCreate | CFile::shareDenyNone);
CArchive Archive(&File,CArchive::store);
The file gets created ok, but CTime throws an exception when trying to convert from a file time. The root cause is that _mktime64
is failing because it is being passed an invalid year (60056), which in turn is being generated by FileTimeToSystemTime
being given a local time of {dwLowDateTime=2312828172 dwHighDateTime=4294967238}
, which is in turn being created by FileTimeToLocalFileTime
given a file time of {dwLowDateTime=2550019340 dwHighDateTime=9}
Now my guess is that the file time is Ok, but the FileTimeToLocalFileTime
is screwing up. Checking the settings on the emulator I'm using, the time and date seem fine, but checking the MSDN help for FileTimeToLocalFileTime
doesn't make any references to being Windows mobile compatible. Am I missing something obvious here, or is this a MFC bug? Any ideas of a workaround would be greatly appreciated.
Edit FWIW, I have reset the local time on the emulator to GMT and still get the same problem. I'm about to test it on an actual device, and will report back.
Edit2 Seems to work ok on a real Windows mobile device over ActiveSync. Bug appears to be restricted to the emulator. I'm running Windows XP which could be a factor, as given the binaries on the emulator and device are the same, the problem is perhaps O/S related.