// cap_stsTaskViewer.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include "cap_stsTaskViewer.h"

#include <commdlg.h>
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <mbstring.h>
#include <Commctrl.h>
#include <shellapi.h>
#include <shlwapi.h>
#include <shlobj.h>
#include <initguid.h>
#include <mstask.h>
#include <shlwapi.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

#define TASKS_TO_RETRIEVE          5

#pragma	comment(lib,"shlwapi.lib")
#pragma	comment(lib,"comctl32.lib")
#pragma	comment(lib,"shell32.lib")
#pragma	comment(lib,"shfolder.lib")

using namespace std;

#define MAX_LOADSTRING 100

#define ERROR_LIGHT	RGB(0xFF,0xE4,0xE1)
#define ERROR_DARK	RGB(0xFF,0xC0,0xCB)
#define NML_LIGHT	RGB(0xf4,0xf4,0xff)
#define NML_DARK	RGB(0xef,0xef,0xff)

typedef struct tagProg {
	int		Id;
	time_t	stime;
	time_t	etime;
	BOOL	bError;
	int		validate;
	string	stCh;
	string	stName;
	string  stParam;
	string  stTaskName;

	tagProg() {
		memset(this,0,sizeof(PROG_DATA));
	}
} PROG_DATA;
typedef vector<PROG_DATA> PROG_LIST;

// グローバル変数 :
HINSTANCE hInst;								// 現在のインターフェイス
TCHAR szTitle[MAX_LOADSTRING];					// タイトル バーのテキスト
TCHAR szWindowClass[MAX_LOADSTRING];			// メイン ウィンドウ クラス名
TCHAR m_szIniPath[256];
TCHAR m_szChannelPath[256];
PROG_LIST	m_ProgList;
map<string,string> m_ChannelMap;
map<string,string> m_StationMap;///

// このコード モジュールに含まれる関数の宣言を転送します :
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	TaskViewerDlgProc(HWND hWnd,UINT meg,WPARAM wp,LPARAM lp);
void SearchTaskScheduler(void);
void CheckCapStsTime(time_t now,char* argv,time_t* start_time,time_t* end_time);
BOOL CheckCapStsPara(char* szPara,char* szName,char* szTime,char* szCh,int* nId);

BOOL m_biEpgListSort[5] = {FALSE,FALSE,FALSE,FALSE,FALSE};

int CALLBACK iEpgListCompProc(LPARAM lp1, LPARAM lp2, LPARAM lp3);

int CALLBACK iEpgListCompProc(LPARAM lp1, LPARAM lp2, LPARAM lp3)
{
	int itNo1 = (int)lp1;
	int itNo2 = (int)lp2;
	int sub = (int)lp3;
	BOOL bSort = m_biEpgListSort[sub];
	int ret = 0;	

	switch(sub) {
		case 0:
			if(m_ProgList[itNo1].stCh > m_ProgList[itNo2].stCh)
				ret = 1;
			else if(m_ProgList[itNo1].stCh < m_ProgList[itNo2].stCh)
				ret = -1;
			break;
		case 1:
			if(m_ProgList[itNo1].stime > m_ProgList[itNo2].stime)
				ret = 1;
			else if(m_ProgList[itNo1].stime < m_ProgList[itNo2].stime)
				ret = -1;
			else {
				if(m_ProgList[itNo1].etime > m_ProgList[itNo2].etime)
					ret = 1;
				else if(m_ProgList[itNo1].etime < m_ProgList[itNo2].etime)
					ret = -1;
			}
			break;
		case 2:
			if(m_ProgList[itNo1].stName > m_ProgList[itNo2].stName)
				ret = 1;
			else if(m_ProgList[itNo1].stName < m_ProgList[itNo2].stName)
				ret = -1;
			break;
		case 3:
			if(m_ProgList[itNo1].Id > m_ProgList[itNo2].Id)
				ret = 1;
			else if(m_ProgList[itNo1].Id < m_ProgList[itNo2].Id)
				ret = -1;
			break;
		case 4:
			if(m_ProgList[itNo1].stParam > m_ProgList[itNo2].stParam)
				ret = 1;
			else if(m_ProgList[itNo1].stParam < m_ProgList[itNo2].stParam)
				ret = -1;
			break;
	}
	if(ret == 1 && !bSort)
		ret = -1;
	else if(ret == -1 && !bSort)
		ret = 1;
	return ret;
}

LRESULT CALLBACK	TaskViewerDlgProc(HWND hWnd,UINT meg,WPARAM wp,LPARAM lp)
{
	switch(meg) {
		case WM_INITDIALOG:
			{
				HMENU hSysMenu = GetSystemMenu(hWnd,FALSE);
				InsertMenu(hSysMenu,SC_CLOSE,MF_BYCOMMAND|MF_STRING,IDM_ABOUT,"バージョン情報(&A)...");

				HWND hList = GetDlgItem(hWnd,IDC_TASKLIST);

				DWORD dwStyle;
				dwStyle = ListView_GetExtendedListViewStyle(hList);
				dwStyle |= LVS_EX_FULLROWSELECT;
				ListView_SetExtendedListViewStyle(hList, dwStyle);

				LV_COLUMN lvcol;
				lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
				lvcol.fmt = LVCFMT_LEFT;
				lvcol.cx = GetPrivateProfileInt("cap_stsTaskViewer","CHW",100,m_szIniPath);
				lvcol.pszText = "CH";
				lvcol.iSubItem = 0;
				ListView_InsertColumn(hList, 0, &lvcol);

				lvcol.cx = GetPrivateProfileInt("cap_stsTaskViewer","DATEW",100,m_szIniPath);
				lvcol.pszText = "日時";
				lvcol.iSubItem = 1;
				ListView_InsertColumn(hList, 1, &lvcol);

				lvcol.cx = GetPrivateProfileInt("cap_stsTaskViewer","NAMEW",100,m_szIniPath);
				lvcol.pszText = "番組名";
				lvcol.iSubItem = 2;
				ListView_InsertColumn(hList, 2, &lvcol);

				lvcol.cx = GetPrivateProfileInt("cap_stsTaskViewer","IDW",100,m_szIniPath);
				lvcol.pszText = "ID";
				lvcol.iSubItem = 3;
				ListView_InsertColumn(hList, 3, &lvcol);

				lvcol.cx = GetPrivateProfileInt("cap_stsTaskViewer","COMMANDW",100,m_szIniPath);
				lvcol.pszText = "コマンド";
				lvcol.iSubItem = 4;
				ListView_InsertColumn(hList, 4, &lvcol);

				char szData[100];
				if(GetPrivateProfileString("cap_stsTaskViewer","WindowX","100",szData,100,m_szIniPath) > 0) {
					int x = atoi(szData);
					if(GetPrivateProfileString("cap_stsTaskViewer","WindowY","100",szData,100,m_szIniPath) > 0) {
						int y = atoi(szData);
						if(GetPrivateProfileString("cap_stsTaskViewer","WindowCX","930",szData,100,m_szIniPath) > 0) {
							int cx = atoi(szData);
							if(GetPrivateProfileString("cap_stsTaskViewer","WindowCY","500",szData,100,m_szIniPath) > 0) {
								int cy = atoi(szData);
								SetWindowPos(hWnd,NULL,x,y,cx,cy,SWP_NOZORDER);
							}
						}
					}
				}
				PostMessage(hWnd,WM_SIZE,0,0);
				PostMessage(hWnd,WM_COMMAND,IDOK,0);
			}
			break;
		case WM_GETMINMAXINFO:
			{
				RECT btnrct,listrct;
				POINT pos;
				GetWindowRect(GetDlgItem(hWnd,IDCANCEL),&btnrct);
				GetWindowRect(GetDlgItem(hWnd,IDC_TASKLIST),&listrct);
				pos.x = btnrct.right+16;
				pos.y = listrct.top+64;
				ScreenToClient(hWnd,&pos);

				LPMINMAXINFO lpmmi;

				lpmmi = (LPMINMAXINFO)lp;
				lpmmi->ptMinTrackSize.x = pos.x;
				lpmmi->ptMinTrackSize.y = pos.y;
				SetWindowLong(hWnd,DWL_MSGRESULT,0);
				return TRUE;
			}
			break;
		case WM_SIZE:
			{
				RECT dlgrct,listrct;
				POINT pos;
				GetClientRect(hWnd,&dlgrct);
				GetWindowRect(GetDlgItem(hWnd,IDC_TASKLIST),&listrct);
				pos.x = listrct.left;
				pos.y = listrct.top;
				ScreenToClient(hWnd,&pos);
				int dlgw = dlgrct.right-dlgrct.left;
				int dlgh = dlgrct.bottom-dlgrct.top;
				SetWindowPos(GetDlgItem(hWnd,IDC_TASKLIST),NULL,0,pos.y,dlgw,dlgh-pos.y,SWP_NOZORDER);
			}
			break;
		case WM_NOTIFY:
			{
				LPNMLVCUSTOMDRAW	lplvcd;
				LPNMLISTVIEW		lpnmlv;
				LPNMHDR				lpnmhdr;
				lpnmhdr = (LPNMHDR)lp;
				HWND hList=lpnmhdr->hwndFrom;
				if(hList != GetDlgItem(hWnd,IDC_TASKLIST))
					break;
				switch(lpnmhdr->code) {
					case LVN_COLUMNCLICK:
						{
							LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lp;
							m_biEpgListSort[pnmv->iSubItem] = !m_biEpgListSort[pnmv->iSubItem];
							ListView_SortItems(hList,iEpgListCompProc,pnmv->iSubItem);
						}
						break;
					case NM_CUSTOMDRAW :
					// ---- カスタムドローで、Listviewの色を設定。
						LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lp;
						switch (lplvcd->nmcd.dwDrawStage) {
							case CDDS_PREPAINT:     // 描画前にITEM情報をリクエスト
								SetWindowLong(hWnd,DWL_MSGRESULT,(long)CDRF_NOTIFYITEMDRAW);
								return TRUE;
							case CDDS_ITEMPREPAINT: // ITEM描画前にSUBITEM情報をリクエスト
								SetWindowLong(hWnd,DWL_MSGRESULT,(long)CDRF_NOTIFYSUBITEMDRAW);
								return TRUE;
							case CDDS_ITEMPREPAINT|CDDS_SUBITEM:    // SUBITEM描画イベント
								{
									LV_ITEM item;
									item.mask = LVIF_PARAM;
									item.iItem = lplvcd->nmcd.dwItemSpec;
									item.iSubItem = 0;
									ListView_GetItem(hList,&item);
									lplvcd->clrText = RGB(0,0,0);
									if(lplvcd->iSubItem == 1) {
										char szDate[100];
										ListView_GetItemText(hList,lplvcd->nmcd.dwItemSpec,1,szDate,100);
										if(strncmp(&szDate[11],"土",2) == 0)
											lplvcd->clrText = RGB(0,0,255);
										else if(strncmp(&szDate[11],"日",2) == 0)
											lplvcd->clrText = RGB(255,0,0);
									}
									COLORREF dark,light;
									if(m_ProgList[item.lParam].bError) {
										dark = ERROR_DARK;
										light = ERROR_LIGHT;
									}
									else {
										dark = NML_DARK;
										light = NML_LIGHT;
									}
									if(lplvcd->nmcd.dwItemSpec%2) {
										lplvcd->clrTextBk = dark;
									}
									else {
										lplvcd->clrTextBk = light;
									}
									SetWindowLong(hWnd,DWL_MSGRESULT,(long)CDRF_NEWFONT);
								}
								return TRUE;
						}
						break;
				}
			}
			break;
		case WM_SYSCOMMAND:
			switch (LOWORD(wp)) {
				case IDM_ABOUT:
					DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUTBOX),hWnd,(DLGPROC)About);
					break;
			}
			break;
	    case WM_COMMAND:
			if(HIWORD(wp) == 0x00) {
				switch ( LOWORD(wp) )
				{
///>
					case IDC_TASKCHG:
						{
							HWND hList = GetDlgItem(hWnd,IDC_TASKLIST);
							int selitem = ListView_GetNextItem(hList,-1,LVNI_ALL | LVNI_SELECTED);
							if(selitem < 0) break;
							
							LV_ITEM item;
							item.mask = LVIF_PARAM;
							item.iItem = selitem;
							item.iSubItem = 0;
							ListView_GetItem(hList,&item);
							
							char tmS[64],tmE[16];
							struct tm date;
							localtime_s(&date,&m_ProgList[item.lParam].stime);
							strftime(tmS, 64,
								"year: %Y\n"
								"month: %m\n"
								"date: %d\n"
								"start: %H:%M"
								,&date
							);
							localtime_s(&date,&m_ProgList[item.lParam].etime);
							strftime(tmE, 16,"end: %H:%M",&date);
							
							char *stName = "unknown";
							map<string,string>::iterator cit = m_StationMap.find(m_ProgList[item.lParam].stCh);
							if(cit != m_StationMap.end()) stName = (char*)cit->second.c_str();
							
							FILE *fp = fopen("$$$.tvpi","w");
							if ( fp == NULL ) break;///エラーメッセージ出すべきだけど.
							fprintf(fp,
								"Content-type: application/x-tv-program-info; charset=shift_jis\n"
								"version: 1\n"
								"station: %s"
								"%s\n"
								"%s\n"
								"program-title: %s\n"
								///以下の拡張はTaskSchedulerHelper1.7でサポート.
								"TASKNAME: %s\n"
								"FX2ID: %d\n"
								"\n"
								,stName
								,tmS
								,tmE
								,(char*)m_ProgList[item.lParam].stName.c_str()
								,(char*)m_ProgList[item.lParam].stTaskName.c_str()
								,m_ProgList[item.lParam].Id
							);
							fclose(fp);
							system("start TaskSchedulerHelper.exe $$$.tvpi");
						}
						break;
					case IDC_TASKS:
						{
							char tmp[32];
							char *srp = getenv("SystemRoot");
							
							sprintf(tmp,"start cmd /c start %s\\Tasks",srp);
							system(tmp);
						}
						break;
///<
					case IDC_TASKDEL:
						{
							HWND hList = GetDlgItem(hWnd,IDC_TASKLIST);
							int selitem = ListView_GetNextItem(hList,-1,LVNI_ALL | LVNI_SELECTED);
							if(selitem != -1) {
								LV_ITEM item;
								item.mask = LVIF_PARAM;
								item.iItem = selitem;
								item.iSubItem = 0;
								ListView_GetItem(hList,&item);
								char szMsg[512];
								wsprintf(szMsg,"タスク「%s」を削除しますか？",(char*)m_ProgList[item.lParam].stTaskName.c_str());
								if(MessageBox(hWnd,szMsg,"タスクの削除",MB_YESNO|MB_ICONQUESTION) == IDYES) {
									HRESULT hr = S_OK;
									ITaskScheduler *pITS;

									hr = CoInitialize(NULL);
									if (SUCCEEDED(hr)){
										hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &pITS);
										if (FAILED(hr)){
											CoUninitialize();
											break;
										}
									}else{
										break;
									}

									char* localeInfo = setlocale(LC_ALL, "Japanese_Japan.932");

									wchar_t	wTaskName[512];
									mbstowcs(wTaskName,(char*)m_ProgList[item.lParam].stTaskName.c_str(),512);
									pITS->Delete(wTaskName);
									pITS->Release();
									if (FAILED(hr)){
										CoUninitialize();
										break;
									}
									PostMessage(hWnd,WM_COMMAND,IDOK,0);
								}
							}
						}
						break;
					case IDOK:
						{
							m_ProgList.clear();
							SearchTaskScheduler();
							int itemNo = 0;
							HWND hList = GetDlgItem(hWnd,IDC_TASKLIST);
							ListView_DeleteAllItems(hList);
							int nhour,nmin;
							struct tm* enTime;
							struct tm* stTime;
							char* szwday[7] = {"日","月","火","水","木","金","土"};
							int ui = 0;
							PROG_LIST::iterator it = m_ProgList.begin();
							while(it != m_ProgList.end()) {
								LV_ITEM item;
								item.mask = LVIF_TEXT|LVIF_PARAM;
								map<string,string>::iterator cit = m_ChannelMap.find(it->stCh);
								if(cit != m_ChannelMap.end())
									item.pszText = (char*)cit->second.c_str();
								else
									item.pszText = (char*)it->stCh.c_str();
								item.iItem = itemNo;
								item.iSubItem = 0;
								item.lParam = ui++;
								ListView_InsertItem(hList,&item);
								char szDate[50];
								szDate[0] = 0x00;
								enTime = localtime( &it->etime );
								nhour =  enTime->tm_hour;
								nmin = enTime->tm_min;
								stTime = localtime( &it->stime );
								wsprintf(szDate,"%04d/%02d/%02d(%s) %02d:%02d〜%02d:%02d",stTime->tm_year+1900,stTime->tm_mon+1,stTime->tm_mday,szwday[stTime->tm_wday],stTime->tm_hour,stTime->tm_min,nhour,nmin);
								item.mask = LVIF_TEXT;
								item.pszText = szDate;
								item.iItem = itemNo;
								item.iSubItem = 1;
								ListView_SetItem(hList, &item);
								item.mask = LVIF_TEXT;
								item.pszText = (char*)it->stName.c_str();
								item.iItem = itemNo;
								item.iSubItem = 2;
								ListView_SetItem(hList, &item);
								wsprintf(szDate,"%d",it->Id);
								item.iItem = itemNo;
								item.pszText = szDate;
								item.iSubItem = 3;
								ListView_SetItem(hList, &item);
								item.iItem = itemNo;
								item.pszText = (char*)it->stParam.c_str();
								item.iSubItem = 4;
								ListView_SetItem(hList, &item);
								itemNo++;
								it++;
							}
							//ListView_EnsureVisible(hList,itemNo-1,FALSE);
						}
						break;
					case IDCANCEL:
						::EndDialog(hWnd,IDCANCEL);
						break;
				}
			}
			break;
		case WM_DESTROY:
			{
				char szData[100];
				HWND hList = GetDlgItem(hWnd,IDC_TASKLIST);
				wsprintf(szData,"%d",ListView_GetColumnWidth(hList,0));
				WritePrivateProfileString("cap_stsTaskViewer","CHW",szData,m_szIniPath);
				wsprintf(szData,"%d",ListView_GetColumnWidth(hList,1));
				WritePrivateProfileString("cap_stsTaskViewer","DATEW",szData,m_szIniPath);
				wsprintf(szData,"%d",ListView_GetColumnWidth(hList,2));
				WritePrivateProfileString("cap_stsTaskViewer","NAMEW",szData,m_szIniPath);
				wsprintf(szData,"%d",ListView_GetColumnWidth(hList,3));
				WritePrivateProfileString("cap_stsTaskViewer","IDW",szData,m_szIniPath);
				wsprintf(szData,"%d",ListView_GetColumnWidth(hList,4));
				WritePrivateProfileString("cap_stsTaskViewer","COMMANDW",szData,m_szIniPath);

				long style = GetWindowLong(hWnd,GWL_STYLE);
				if(!(style & WS_MINIMIZE || style & WS_MAXIMIZE)) {
					RECT dlgrct;
					GetWindowRect(hWnd,&dlgrct);
					wsprintf(szData,"%d",dlgrct.left);
					WritePrivateProfileString("cap_stsTaskViewer","WindowX",szData,m_szIniPath);
					wsprintf(szData,"%d",dlgrct.top);
					WritePrivateProfileString("cap_stsTaskViewer","WindowY",szData,m_szIniPath);
					wsprintf(szData,"%d",dlgrct.right-dlgrct.left);
					WritePrivateProfileString("cap_stsTaskViewer","WindowCX",szData,m_szIniPath);
					wsprintf(szData,"%d",dlgrct.bottom-dlgrct.top);
					WritePrivateProfileString("cap_stsTaskViewer","WindowCY",szData,m_szIniPath);
				}
			}
			break;
	}
	return 0;
}

void SearchTaskScheduler(void)
{
	HRESULT hr = S_OK;
	ITaskScheduler *pITS;

	hr = CoInitialize(NULL);
	if (SUCCEEDED(hr)){
		hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &pITS);
		if (FAILED(hr)){
			CoUninitialize();
			return;
		}
	}else{
		return;
	}

	char* localeInfo = setlocale(LC_ALL, "Japanese_Japan.932");

	IEnumWorkItems *pIEnum;
	hr = pITS->Enum(&pIEnum);
	if (FAILED(hr)){
		CoUninitialize();
		return;
	}

	time_t nowTime = time(NULL);
	LPWSTR *lpwszNames;
	DWORD dwFetchedTasks = 0;
	SYSTEMTIME stBegin,stEnd;
	SYSTEMTIME *rgstTaskTime;
	WORD wCount;
	time_t nowt = time(NULL);
	time_t lastt = nowt + (28 * 24 * 60 * 60);
	struct tm* tmt = localtime(&nowt);
	stBegin.wYear = tmt->tm_year + 1900;
	stBegin.wMonth = tmt->tm_mon + 1;
	stBegin.wDay = tmt->tm_mday;
	stBegin.wDayOfWeek = tmt->tm_wday;
	stBegin.wHour = tmt->tm_hour;
	stBegin.wMinute = tmt->tm_min;
	stBegin.wSecond = tmt->tm_sec;
	stBegin.wMilliseconds = 0;
	tmt = localtime(&lastt);
	stEnd.wYear = tmt->tm_year + 1900;
	stEnd.wMonth = tmt->tm_mon + 1;
	stEnd.wDay = tmt->tm_mday;
	stEnd.wDayOfWeek = tmt->tm_wday;
	stEnd.wHour = tmt->tm_hour;
	stEnd.wMinute = tmt->tm_min;
	stEnd.wSecond = tmt->tm_sec;
	stEnd.wMilliseconds = 0;
	while (SUCCEEDED(pIEnum->Next(TASKS_TO_RETRIEVE, &lpwszNames, &dwFetchedTasks)) && (dwFetchedTasks != 0)){
		while (dwFetchedTasks){
			char szTskName[256];
			wcstombs(szTskName,lpwszNames[--dwFetchedTasks],256);
			ITask *pITask;
			hr = pITS->Activate(lpwszNames[dwFetchedTasks],IID_ITask,(IUnknown**)&pITask);
			if (FAILED(hr)) {
				CoTaskMemFree(lpwszNames[dwFetchedTasks]);
				continue;
			}
			char szFullPath[256],szAppName[256];
			LPWSTR wApName;
			pITask->GetApplicationName(&wApName);
			wcstombs(szFullPath,wApName,256);
			_splitpath(szFullPath,NULL,NULL,szAppName,NULL);
			CoTaskMemFree(wApName);
			if(strnicmp(szAppName,"cap_sts",7) == 0) {
				ITaskTrigger* pTaskTrigger;
				hr = pITask->GetTrigger(0,&pTaskTrigger);
				if (FAILED(hr)) {
					pITask->Release();
					CoTaskMemFree(lpwszNames[dwFetchedTasks]);
					continue;
				}
				int rCount = 0;
				struct tm rtm;
				time_t runTime[101];
				HRESULT hrStatus;
				hr = pITask->GetStatus(&hrStatus);
				if (FAILED(hr)) {
					pITask->Release();
					CoTaskMemFree(lpwszNames[dwFetchedTasks]);
					continue;
				}
				WORD status = (WORD)HRESULT_CODE(hrStatus);
				// 実行中の物も予約リストに乗せる
				if(SCHED_S_TASK_RUNNING == hrStatus) {
					TASK_TRIGGER Trigger;
					pTaskTrigger->GetTrigger(&Trigger);
					if (FAILED(hr)) {
						pITask->Release();
						CoTaskMemFree(lpwszNames[dwFetchedTasks]);
						continue;
					}
					rtm.tm_year = Trigger.wBeginYear - 1900;
					rtm.tm_mon = Trigger.wBeginMonth - 1;
					rtm.tm_mday = Trigger.wBeginDay;
					rtm.tm_hour = Trigger.wStartHour;
					rtm.tm_min = Trigger.wStartMinute;
					rtm.tm_sec = 0;
					runTime[rCount++] = mktime(&rtm);
				}
				wCount = 100;
				hr = pITask->GetRunTimes(&stBegin,&stEnd,&wCount,&rgstTaskTime);
				if (FAILED(hr)) {
					pITask->Release();
					CoTaskMemFree(lpwszNames[dwFetchedTasks]);
					continue;
				}
				if(wCount > 0) {
					for(int i = 0;i < wCount;i++) {
						rtm.tm_year = rgstTaskTime[i].wYear - 1900;
						rtm.tm_mon = rgstTaskTime[i].wMonth - 1;
						rtm.tm_mday = rgstTaskTime[i].wDay;
						rtm.tm_hour = rgstTaskTime[i].wHour;
						rtm.tm_min = rgstTaskTime[i].wMinute;
						rtm.tm_sec = rgstTaskTime[i].wSecond;
						runTime[rCount++] = mktime(&rtm);
					}
				}
				CoTaskMemFree(rgstTaskTime);
				wCount = rCount;
				if(wCount > 0) {
					wchar_t *wPara;
					hr = pITask->GetParameters(&wPara);
					if (FAILED(hr)) {
						pITask->Release();
						CoTaskMemFree(lpwszNames[dwFetchedTasks]);
						continue;
					}
					char szPara[256],sztmp[256],szTime[20],szCh[10];
					int id;
					wcstombs(szPara,wPara,256);
					if(CheckCapStsPara(szPara,sztmp,szTime,szCh,&id)) {
						time_t nowt = time(NULL);
						PROG_DATA prog;
						prog.Id = id;
						prog.stName = sztmp;
						prog.stCh = szCh;
						prog.stParam = szPara;
						prog.stTaskName = szTskName;
						prog.validate = 1;
						for(int i = 0;i < wCount;i++) {
							prog.bError = FALSE;
							CheckCapStsTime(runTime[i],szTime,&prog.stime,&prog.etime);
							if(nowt <= prog.etime) {
								int pos = -1;
								PROG_LIST::iterator it = m_ProgList.begin();
								for(int i = 0;it != m_ProgList.end();i++) {
									BOOL bIns = FALSE;
									if(!it->validate || !prog.validate || it->Id != prog.Id);
									else if(it->etime <= prog.stime);
									else if(it->stime >=prog.etime);
									else {
										prog.bError = TRUE;
										it->bError = TRUE;
									}
									if(pos == -1) {
										if(it->stime > prog.stime)
											bIns = TRUE;
										else if(it->stime == prog.stime && it->etime > prog.etime)
											bIns = TRUE;
										if(bIns)
											pos = i;
									}
									if(it->stime >= prog.etime)
										break;
									it++;
								}
								if(pos == -1)
									m_ProgList.push_back(prog);
								else
									m_ProgList.insert(m_ProgList.begin()+pos,prog);  
							}
						}
					}
				}
				pITask->Release();
			}
			CoTaskMemFree(lpwszNames[dwFetchedTasks]);
		}
		CoTaskMemFree(lpwszNames);
	}
	pIEnum->Release();
	pITS->Release();
}

BOOL CheckCapStsPara(char* szPara,char* szName,char* szTime,char* szCh,int* nId)
{
	*nId = 0;
	szTime[0] = 0;
	szName[0] = 0;
	szCh[0] = 0;
	char argv[256];
	for(int i = 0;i < strlen(szPara);i++) {
		int ii;
		if(szPara[i] == ' ')
			continue;
		if(szPara[i] == '\"') {
			i++;
			for(ii = i;ii < strlen(szPara) && szPara[ii] != '\"';ii++);
		}
		else {
			for(ii = i;ii < strlen(szPara) && szPara[ii] != ' ';ii++);
		}
		strncpy(argv,&szPara[i],ii-i);
		argv[ii-i] = 0x00;
		i = ii;
		if(('0' <= argv[0]) && (argv[0] <= '9')){
			//時間
			strcpy(szTime,argv);
		}
		else if(argv[0] == '@'){
			// チャンネル指定
			strcpy(szCh,argv);
			_mbslwr((unsigned char *)szCh);
		}
		else if(strcmpi(argv, "b") == 0){
			//BCASログ指定
		}
		else if(strcmpi(argv, "b25") == 0){
			//B25指定
		}
		else if(strcmpi(argv, "sel") == 0){
			//sel指定
		}
		else if(strcmpi(argv, "p") == 0){
			//開始時PON指定
		}
		else if(strcmpi(argv, "poff") == 0){
		}
		else if(strcmpi(argv, "stop") == 0){
			//終了要求指定
		}
		else if((argv[0] == 'r' || argv[0] == 'R')&&(isdigit(argv[1]))){
			// リモコンNo.
		}
		else if(strcmpi(argv, "suspend") == 0){
			//サスペンド
		}
		else if(argv[0] == 'v' && argv[1] == 'l' && argv[2] == 'c' && argv[3] == ':'){
			//Network出力
		}
		else if(argv[0] == 'f' && argv[1] == 'f' && argv[2] == 'm' && argv[3] == 'p' && argv[4] == 'e' && argv[5] == 'g' && argv[6] == ':'){
			//Network出力
		}
		else if((argv[0] == 'i' || argv[0] == 'I')&&(isdigit(argv[1]))&&(argv[2]==0)){
			//カメFX2　ID指定
			char *s;
			*nId = (int)strtol(argv+1, &s, 10);
		}
		else {
			_splitpath(argv,NULL,NULL,szName,NULL);
		}
	}
	if(szTime[0] == 0x00 || szName[0] == 0x00 || szCh[0] == 0x00)
		return FALSE;
	return TRUE;
}

void CheckCapStsTime(time_t now,char* argv,time_t* start_time,time_t* end_time)
{
	long sleep=0;
	if(('0' <= argv[0]) && (argv[0] <= '9')){
		//時間
		if(strchr(argv, ':')!=NULL){//nn:nn指定
			struct tm *nt;
			long st_h,st_m,en_h,en_m;
			nt = localtime( &now );	//時刻を tm 構造体形式に変換
			if(sscanf(argv, "%d:%d-%d:%d", &st_h, &st_m, &en_h, &en_m) == 4){//正常処理
				if((st_h * 60 + st_m) < (nt->tm_hour * 60 + nt->tm_min)){
					//翌日分なので24時間追加
					st_h += 24;
					en_h += 24;
				}
				if((st_h * 60 + st_m) > (en_h * 60+ en_m))
					//終了時刻が日付をまたぐので
					en_h += 24;
				//何秒後？
				sleep = (st_h * 60*60 + st_m * 60) - (nt->tm_hour * 60*60 + nt->tm_min * 60 + nt->tm_sec);
				*end_time = now + sleep + ((en_h * 60*60 + en_m * 60) - (st_h * 60*60 + st_m * 60));
				int min = (en_h * 60 + en_m) - (st_h * 60 + st_m);
				st_m = sleep - (sleep/(60*60))*(60*60);
			}
		}
		else{
			char *s;
			int min = strtol(argv, &s, 10);
			*end_time = now + min*60;
		}
	}
	*start_time = now + sleep;
	if(*end_time == 0) {
		*end_time = *start_time + 20;	//デフォルト記録時間は20秒
	}
}

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
 	// TODO: ここにコードを挿入してください。
	HACCEL hAccelTable;

	// グローバル文字列を初期化しています。
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_CAP_STSTASKVIEWER, szWindowClass, MAX_LOADSTRING);

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CAP_STSTASKVIEWER);

	InitCommonControls();

	char szModulePath[256],drv[10],path[256],name[256],ext[256];
	GetModuleFileName(NULL,szModulePath,256);
	_splitpath(szModulePath,drv,path,name,ext);
	_makepath(m_szIniPath,drv,path,name,".ini");
	_makepath(m_szChannelPath,drv,path,"channel",".txt");

	m_ChannelMap.clear();
	m_StationMap.clear();
	FILE *fp = fopen(m_szChannelPath,"rt");
	if(fp != NULL) {
		char szText[1024];
		while(fgets(szText,1024,fp) != NULL) {
			char szCh[10];
			char* pPos = strchr(szText,',');
			if(pPos != NULL) {
				char* pPos2 = strchr(pPos+1,',');
				if(pPos2 != NULL)
					*pPos2 = 0x00;
				if(pPos[1] >= '0' && pPos[1] <= '9')
					wsprintf(szCh,"@%d",atoi(&pPos[1]));
				else {
					if(pPos[1] == 'B')
						pPos[1] = 'b';
					if(pPos[1] == 'C')
						pPos[1] = 'c';
					wsprintf(szCh,"@%s",&pPos[1]);
				}
				string chkey = szCh;
				*pPos = 0x00;
				m_ChannelMap[chkey] = szText;
				m_StationMap[chkey] = pPos2 + 1;
			}
		}
		fclose(fp);
	}

	return (int) DialogBox(hInstance,MAKEINTRESOURCE(IDD_TASKVIEWER_DLG),	NULL,(DLGPROC)TaskViewerDlgProc);
}


// バージョン情報ボックスのメッセージ ハンドラです。
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		return TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
		{
			EndDialog(hDlg, LOWORD(wParam));
			return TRUE;
		}
		break;
	}
	return FALSE;
}
