// wtmsload.cpp : Defines the initialization routines for the DLL. // #include "stdafx.h" #include "errcodes.h" #include #include "guidestore.h" #include "services.h" #include "channels.h" #include "programs.h" #include "schedules.h" #include "tmsparse.h" #include "servchan.h" #include "progschd.h" #include "wtmsload.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // // Note! // // If this DLL is dynamically linked against the MFC // DLLs, any functions exported from this DLL which // call into MFC must have the AFX_MANAGE_STATE macro // added at the very beginning of the function. // // For example: // // extern "C" BOOL PASCAL EXPORT ExportedFunction() // { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // normal function body here // } // // It is very important that this macro appear in each // function, prior to any calls into MFC. This means that // it must appear as the first statement within the // function, even before any object variable declarations // as their constructors may generate calls into the MFC // DLL. // // Please see MFC Technical Notes 33 and 58 for additional // details. // ///////////////////////////////////////////////////////////////////////////// // CWtmsloadApp BEGIN_MESSAGE_MAP(CWtmsloadApp, CWinApp) //{{AFX_MSG_MAP(CWtmsloadApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CWtmsloadApp construction CWtmsloadApp::CWtmsloadApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CWtmsloadApp object CWtmsloadApp theApp; ///////////////////////////////////////////////////////////////////////// // // METHOD: InitProcessors // // PARAMETERS: [IN] VOID // // PURPOSE: Instantiates the guide data record processors (parsers) // // RETURNS: SUCCESS/FAILURE // ///////////////////////////////////////////////////////////////////////// // ULONG CWtmsloadApp::InitProcessors(VOID) { ULONG ulRet = ERROR_FAIL; // Open the processors // // TODO: Exeception handler // m_DataFile = new CDataFileProcessor; if (NULL == m_DataFile) { goto Open_Exit; } m_srpHeaders = new CHeaderRecordProcessor; if (NULL == m_srpHeaders) { goto Open_Exit; } m_scrpStatChans = new CStatChanRecordProcessor; if (NULL == m_scrpStatChans) { goto Open_Exit; } m_etEpTs = new CEpisodeTimeSlotRecordProcessor; if (NULL == m_etEpTs) { goto Open_Exit; } ulRet = INIT_SUCCEEDED; Open_Exit: return ulRet; } ///////////////////////////////////////////////////////////////////////// // // METHOD: CloseProcessors // // PARAMETERS: [IN] VOID // // PURPOSE: Frees the guide data record processors (parsers) // // RETURNS: SUCCESS/FAILURE // ///////////////////////////////////////////////////////////////////////// // void CWtmsloadApp::CloseProcessors(VOID) { // close the processors // // TODO: Exeception handler // if (NULL != m_DataFile) { delete m_DataFile; m_DataFile = NULL; } if (NULL != m_scrpStatChans) { delete m_scrpStatChans; m_scrpStatChans = NULL; } if (NULL != m_srpHeaders) { delete m_srpHeaders; m_srpHeaders = NULL; } if (NULL != m_etEpTs) { delete m_etEpTs; m_etEpTs = NULL; } } ///////////////////////////////////////////////////////////////////////// // // METHOD: OpenGuideStore // // PARAMETERS: [IN] lpGuideStoreDB - the Guide Store DB File // // PURPOSE: Opens the Guide Store - // // RETURNS: SUCCESS/FAILURE // ///////////////////////////////////////////////////////////////////////// // ULONG CWtmsloadApp::OpenGuideStore(LPCTSTR lpGuideStoreDB) { return m_gsp.Init(lpGuideStoreDB); } ///////////////////////////////////////////////////////////////////////// // // METHOD: GetGuideStoreInterfaces // // PARAMETERS: [IN] VOID // // PURPOSE: Gets all the Guide Store Interfaces needed by the loader // to import guide data into the store // 1. Initializes Services collection and related props // 2. Initializes ChannelLineups collection and related props // 3. Initializes Programs collection and related props // 4. Initializes ScheduleEntries collection and related props // NOTE: The Channels collection and related properties // are initialized afer the ChannelLineup has been set // (tmsparse.cpp) // // RETURNS: SUCCESS/FAILURE // ///////////////////////////////////////////////////////////////////////// // ULONG CWtmsloadApp::GetGuideStoreInterfaces(VOID) { IGuideStorePtr pGuideStore = m_gsp.GetGuideStorePtr(); ULONG ulRet = ERROR_FAIL; if (NULL != pGuideStore) { // Initialize the services collection // ulRet = m_pgsServices.Init(pGuideStore); if (INIT_SUCCEEDED != ulRet) { goto Get_Exit; } // Initialize the ChannelLineups collection // ulRet = m_pgsChannelLineups.Init(pGuideStore); if (INIT_SUCCEEDED != ulRet) { goto Get_Exit; } // Initialize the Programs collection // ulRet = m_pgsPrograms.Init(pGuideStore); if (INIT_SUCCEEDED != ulRet) { goto Get_Exit; } // Initialize the ScheduleEntries collection // ulRet = m_pgsScheduleEntries.Init(pGuideStore); if (INIT_SUCCEEDED != ulRet) { goto Get_Exit; } } Get_Exit: return ulRet; } ///////////////////////////////////////////////////////////////////////// // // METHOD: Init // // PARAMETERS: [IN] lpGuideStoreDB - Guide Store DB File // // PURPOSE: Performs initializations for the import // 1. Setups the timezone adjustments // 2. Opens the Guide data file processors (parsers) // 3. Opens the guide store // 4. Sets the Guide store interfaces // // RETURNS: SUCCESS/FAILURE // ///////////////////////////////////////////////////////////////////////// // ULONG CWtmsloadApp::InitImport(LPCTSTR lpGuideStoreDB) { ULONG ulRet = ERROR_FAIL; TIME_ZONE_INFORMATION tzi; DWORD tzrc; // incoming data is all gmt. set up app class time info // for conversions // tzrc = ::GetTimeZoneInformation(&tzi); CTimeSpan bias(0, 0, tzi.Bias, 0); switch (tzrc) { case TIME_ZONE_ID_UNKNOWN: #ifdef _DEBUG afxDump << "Time Zone Info not set on this machine.\r\nAll db times will be in UTC\r\n"; #endif break; case TIME_ZONE_ID_DAYLIGHT: { CTimeSpan temp(0, 0, tzi.DaylightBias, 0); bias += temp; } break; case TIME_ZONE_ID_STANDARD: { CTimeSpan temp(0, 0, tzi.StandardBias, 0); bias += temp; } break; default: return 1; break; } // Set the time zone adjustments // m_odtsTimeZoneAdjust.SetDateTimeSpan(bias.GetDays(), bias.GetHours(), bias.GetMinutes(), bias.GetSeconds()); // Guide store Start time - init to invalid // m_codtGuideStartTime.SetStatus(COleDateTime::invalid); // Guide store End time - init to invalid // m_codtGuideEndTime.SetStatus(COleDateTime::invalid); // Open the guide data file parsers // ulRet = InitProcessors(); if (INIT_SUCCEEDED != ulRet) { goto INIT_EXIT; } // Open the guide store // ulRet = OpenGuideStore(lpGuideStoreDB); if (INIT_SUCCEEDED == ulRet) { // Get the guide store interfaces // ulRet = GetGuideStoreInterfaces(); } INIT_EXIT: return ulRet; } void CWtmsloadApp::ExitImport(void) { // Cleanup Processing data objects // CloseProcessors(); } ULONG CWtmsloadApp::ProcessInput(LPCTSTR lpGuideDataFile) { ULONG ulRet = IMPORT_SUCCEEDED; CDataFileProcessor cdfGuideDataProcessor; // TODO: Profile COleDateTime m_odtStart(COleDateTime::GetCurrentTime()); m_covNow = m_odtStart + m_odtsTimeZoneAdjust; HANDLE hFile = CreateFile(lpGuideDataFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) { #ifdef _DEBUG afxDump << "\r\nCreateFile failed: " << GetLastError() << "\r\n"; #endif return ERROR_FILE_OPEN; } // Try to get the file's modification time. If we can't then just use // the current time FILETIME ftModificationTime; if (GetFileTime(hFile, NULL, NULL, &ftModificationTime)) { CTime ctModificationTime = CTime(ftModificationTime); } else { CTime ctCurrentTime = CTime::GetCurrentTime(); #ifdef _DEBUG afxDump << "\r\nGetFileTime failed: " << GetLastError() << "\r\n"; #endif } HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); SYSTEM_INFO si; GetSystemInfo(&si); BYTE *pbFile = NULL; DWORD dwBytesInBlock = 0; int nUpdateErr = ERROR_FAIL; // TODO: Profile if (hFileMapping == NULL) { // do regular I/O BOOL fReadResult; pbFile = new BYTE[si.dwAllocationGranularity]; do { // Attempt to read the file // fReadResult = ReadFile(hFile, pbFile, si.dwAllocationGranularity, &dwBytesInBlock, NULL); #ifdef _DUMP_LOADER wsprintf(szDiagBuff, "Writing Guide Data: %d\r\n", dwBytesInBlock); if (NULL != hDiagFile) { WriteFile(hDiagFile, szDiagBuff, lstrlen(szDiagBuff), &dwBytesWritten, 0); } #endif if (0 < dwBytesInBlock) { // Parse the guide data file and update the store // nUpdateErr = cdfGuideDataProcessor.m_Process((LPCTSTR) pbFile, dwBytesInBlock); if (STATE_RECORDS_FAIL == nUpdateErr) { ulRet = ERROR_STORE_UPDATE; break; } } } while (fReadResult && dwBytesInBlock); delete[] pbFile; } else { // do memory-mapped file I/O DWORD dwFileSizeHigh; __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh); qwFileSize += (((__int64) dwFileSizeHigh) << 32); __int64 qwFileOffset = 0; while (0 < qwFileSize) { if (qwFileSize < si.dwAllocationGranularity) dwBytesInBlock = (DWORD) qwFileSize; else dwBytesInBlock = si.dwAllocationGranularity; pbFile = (BYTE *) MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD) (qwFileOffset >> 32), (DWORD) (qwFileOffset & 0xFFFFFFFF), dwBytesInBlock); if (NULL != pbFile) { #ifdef _DUMP_LOADER wsprintf(szDiagBuff, "Writing Guide Data: %d\r\n", dwBytesInBlock); if (NULL != hDiagFile) { WriteFile(hDiagFile, szDiagBuff, lstrlen(szDiagBuff), &dwBytesWritten, 0); } #endif // Parse the guide data file and update the store // nUpdateErr = cdfGuideDataProcessor.m_Process((LPCTSTR) pbFile, dwBytesInBlock); if (STATE_RECORDS_FAIL == nUpdateErr) { ulRet = ERROR_STORE_UPDATE; break; } UnmapViewOfFile(pbFile); } qwFileOffset += dwBytesInBlock; qwFileSize -= dwBytesInBlock; } CloseHandle(hFileMapping); } // TODO: Profile CloseHandle(hFile); // TODO: Profile return ulRet; } ///////////////////////////////////////////////////////////////////////// // // METHOD: ImportProgramListings // // PARAMETERS: [IN] lpGuideDataFile - The input guide data file // [IN] lpGuideStoreDB - The Guide Store DB file // // PURPOSE: ImportProgramListings Performs the following tasks: // 1. Initializes the import by opening the GuideStore // and setting up all the primary interfaces // 2. Starting the import of the guide data file into the // GuideStore // // RETURNS: SUCCESS/FAILURE // ///////////////////////////////////////////////////////////////////////// // ULONG ImportProgramListings(LPCTSTR lpGuideDataFile, LPCTSTR lpGuideStoreDB) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ULONG ulRet = S_OK; if (NULL == lpGuideDataFile) { return ERROR_INVALID_PARAMETER; } // Initialize the import // ulRet = theApp.InitImport(lpGuideStoreDB); if (INIT_SUCCEEDED == ulRet) { // Import all the program guide records into the // guide store // ulRet = theApp.ProcessInput(lpGuideDataFile); } return ulRet; }