//===========================================================================
//スレッド実行
//===========================================================================
void __fastcall TAttacheCaseFileDecrypt1::Execute()
{

int i, c, len;
float ProgressPercentNumF;  //進捗パーセンテージ(浮動小数点)

// バッファ
char buffer[BUF_SIZE];
char source_buffer[BUF_SIZE];
char temp_buffer[BUF_SIZE];
char output_buffer[LARGE_BUF_SIZE];
char *headerbuffer;

//パスワード
bool fPasswordOk;

String FilePath, FileName;

// ファイルストリーム
TFileStream *fsIn;
TFileStream *fsOut;
bool fInputFileOpen = false;
bool fOutputFileOpen = false;

float free_space_required;
__int64 CurrentPos, TotalSize;
__int64 CurrentDriveFreeSpaceSize;

//処理する合計サイズ
AllTotalSize = 0;

int ret;	//バッファ出力の返値
int FileIndex = 0;

//Blowfish
CBlowFish *bf;

char token[17] = {0, };
const String PrefixString      = "Fn_";
const char charTokenString[17] = "_AttacheCaseData";         //復号の正否に使う
String AtcFileTokenString;                                   //暗号化ファイルのトークン(文字列)
String AtcFileCreateDateString;                              //暗号化ファイルの生成日時(文字列)

//同名ファイル/フォルダーはすべて上書きして復号する
//(ユーザーがダイアログで「すべてはい」を選択したとき = true )
fOverwirteYesToAll = false;
//「復号したファイルを関連付けされたソフトで開く」一時的な設定
fTempOpenFile = fOpenFile;
//フォルダーを一度開いたか(深いフォルダーすべてを開かないように)
fOpenFolderOnce = false;

// 出力するディレクトリ
OutDirPath = IncludeTrailingPathDelimiter(OutDirPath);

String TempRelativePath;


// 暗号化部分のヘッダサイズ
int EncryptHeaderSize = 0;

int DataVersion;        // ver.2.00~は "5", ver.2.70~は "6"

int flush, status;      // zlib
z_stream z;             // zlibライブラリとやりとりするための構造体
bool fInputEnd = false; // 入力ストリームの終了

//ヘッダデータから必要情報を取り出すための
TMemoryStream *pms;     // メモリストリーム

int idx;
TStringList *DataList;
TStringList *tsv;

TStringList *FileList = new TStringList();  // 0: ファイル名
__int64 *FileSizeList = 0;                  // 1: ファイルサイズ(フォルダは-1)
int *FileAttrList     = 0;                  // 2: 属性
int *FileAgeList      = 0;                  // 3: タイムスタンプ

int rest;
int buf_size;

//----------------------------------------------------------------------
// 平文のヘッダ内容チェック
try {
	fsIn = new TFileStream(AtcFilePath, fmOpenRead | fmShareDenyNone);
}
catch(...) {
	//'復号するファイルを開けません。他のアプリケーションが使用中の可能性があります。'
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_OPEN);
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	goto LabelError;
}

fInputFileOpen = true;

// 暗号部ヘッダサイズを取得
fsIn->Read(&EncryptHeaderSize, sizeof(int));
// トークンを取得
fsIn->Read(token, 16);

if (StrComp(token, charTokenString) != 0 ) {
	//--------------------------------------------------------
	//実は自己実行形式ファイル?(拡張子偽装されている場合も)
	//--------------------------------------------------------
	// サイズを再取得
	fsIn->Seek(-(__int64)sizeof(__int64), TSeekOrigin::soEnd);
	fsIn->Read(&AllTotalSize, sizeof(__int64));
	// 位置を戻す
	fsIn->Seek(-(AllTotalSize + sizeof(__int64)), TSeekOrigin::soEnd);
	// もう一度、暗号部ヘッダサイズを取得
	fsIn->Read(&EncryptHeaderSize, sizeof(int));
	// もう一度、トークンを取得
	fsIn->Read(token, 16);

	// トークンを再チェック
	if (StrComp(token, charTokenString) != 0 ) {
		// '暗号化ファイルではありません。アタッシェケースによって暗号化されたファイルでないか、'+#13+
		// 'ファイルが壊れている可能性があります。'
		MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_NOT_ATC);
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
		goto LabelError;
	}

}
else{
	AllTotalSize = fsIn->Size;
}

//-----------------------------------
// データバージョンチェック
//-----------------------------------
DataVersion = -1;
fsIn->Read(&DataVersion, sizeof(int));

if (DataVersion <= 103) {

	// Blowfishで暗号化されたファイル

}
else{
	//'バージョンがちがいます。復号できません。'+#13+
	//'ファイルはver.1のアタッシェケースで暗号化されていません。';
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_NOT_BLOWFISH_ENCRYPTION);
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	goto LabelError;
}

//-----------------------------------
// 復号の準備
//-----------------------------------

bf = new CBlowFish;
bf->Initialize( KeyString.c_str(), KeyString.Length() );   //初期化

//-----------------------------------
// 暗号部ヘッダの復号(ECBモード)
//-----------------------------------

pms = new TMemoryStream;

len = 0;
while (len < EncryptHeaderSize) {
	// 読み出しバッファ
	for (c = 0; c < BUF_SIZE; c++) {
		source_buffer[c] = 0;
	}
	// 暗号化されたデータブロックの読み出し
	len += fsIn->Read(source_buffer, BUF_SIZE);

	// 復号処理
	bf->Decode( source_buffer, buffer, BUF_SIZE);
	pms->Write(buffer, BUF_SIZE);
}

pms->Seek((__int64)0, TSeekOrigin::soBeginning);             //ポインタを先頭へ戻す
DataList = new TStringList;
DataList->LoadFromStream(pms, TEncoding::GetEncoding(932));  // shift-jis


//-----------------------------------
// 復号正否(復号できたか)
//-----------------------------------
if (DataList->Count == 0 || DataList->Strings[0].Pos("AttacheCase") == 0) {
	fPasswordOk = false;
}
else{
	fPasswordOk = true;   //パスワード合致
}

if ( fPasswordOk == false ) {
	//'パスワードがちがいます。復号できません。'+#13+
	//'場合によってはファイルが壊れている可能性もあります。';
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_PASSWORD_WRONG);
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	delete DataList;
	goto LabelTypeMiss;
}

//-----------------------------------
// 復号時のエンコーディング判定
//-----------------------------------
pms->Position = 0;
DataList->LoadFromStream(pms, TEncoding::GetEncoding(932));  // shift-jis


//===================================
// デバッグ
//ShowMessage(DataList->Text);
//===================================

delete pms;


//-----------------------------------
// 暗号化ファイルの生成日時
//-----------------------------------
//※特に今は使用していないが、将来的に
//  期限付きでファイルを復号できなくなる
//  などの機能を追加しても良いかも。
//-----------------------------------
AtcFileCreateDateString = DataList->Strings[1];

//-----------------------------------
// ヘッダデータからファイルリストや
// ファイル情報などを各変数を動的確保
//-----------------------------------

FileSizeList = new __int64[DataList->Count];  // 1: ファイルサイズ(フォルダは-1)
FileAttrList = new int[DataList->Count];      // 2: 属性
FileAgeList = new int[DataList->Count];       // 3: タイムスタンプ

DataList->NameValueSeparator = ':';

tsv = new TStringList;
tsv->Delimiter = '\t';
tsv->StrictDelimiter = true;

char lpPath[MAX_PATH];

for (i = 0; i < DataList->Count; i++) {
	idx = DataList->IndexOfName(PrefixString+IntToStr(i));
	if (idx > 0) {
		tsv->DelimitedText = DataList->ValueFromIndex[idx];

		// ディレクトリ・トラバーサル対策(ver.2.8.5.0~)
		bool fDirectoryTraversal = false;
		AnsiString CanonicalizePath = AnsiString(OutDirPath + tsv->Strings[0]);

		if (CanonicalizePath.Length() < MAX_PATH) {
			// ファイルパスを正規化
			if (PathCanonicalize(lpPath, CanonicalizePath.c_str()) == true) {
				// 正規化したパスが保存先と一致するか
				if (AnsiString(lpPath).Pos(OutDirPath) != 1 ){
					fDirectoryTraversal = true;
				}
			}
			else{
				fDirectoryTraversal = true;
			}
		}
		else{
			fDirectoryTraversal = true;
		}

		if (fDirectoryTraversal == true) {
			//'不正なファイルパスが含まれています。復号できません。';
			MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_INVALID_FILE_PATH) +
								"\n" + CanonicalizePath;
			MsgType = mtError;
			MsgButtons = TMsgDlgButtons() << mbOK;
			MsgDefaultButton = mbOK;
			Synchronize(&PostConfirmMessageForm);
			delete DataList;
			goto LabelTypeMiss;
		}

		FileList->Add(tsv->Strings[0]);                        // 0: ファイルパス
		FileSizeList[i] = StrToIntDef(tsv->Strings[1], -1);    // 1: ファイルサイズ(フォルダは-1)
		FileAttrList[i] = StrToIntDef(tsv->Strings[2], -1);    // 2: 属性
		FileAgeList[i] = StrToIntDef(tsv->Strings[3], -1);     // 3: タイムスタンプ
	}
}

delete tsv;
delete DataList;


//-----------------------------------
//ディスクの空き容量チェック
//-----------------------------------
CurrentDriveFreeSpaceSize = GetDiskFreeSpaceNum(OutDirPath);

if (CurrentDriveFreeSpaceSize > -1) {
	if ( AllTotalSize > CurrentDriveFreeSpaceSize ) {
		//'復号する先のドライブの空き容量が足りません。'+#13+
		//'復号するには、約%dMBの空き容量が必要です。復号処理を中止します。';
		MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_DRIVE_NO_FREE_SPACE);
		free_space_required = (float)AllTotalSize/1024/1024;  // MB
		MsgText = String().sprintf(MsgText.c_str(), free_space_required);
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
		goto LabelError;
	}
}
else{
	// OK!
	//
}

//-----------------------------------
//複数フォルダ/ファイルを開こうとしているので確認
//-----------------------------------

//復号したファイルを関連付けされたソフトで開くか
if ( fTempOpenFile == true && FileList->Count > 4) {

	//'5つ以上のファイルを復号後に開こうとしていますが、処理を続けますか?'+#13+
	//'「いいえ」を選択すると、開かず復号します。';
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_CONFIRM_OPEN_DECRYPTED_FILES);
	MsgType = mtConfirmation;
	MsgButtons = TMsgDlgButtons() << mbYes << mbNo << mbCancel;
	MsgDefaultButton = mbCancel;
	Synchronize(&PostConfirmMessageForm);

	if ( MsgReturnVal == mrCancel ) {
		goto LabelStop;
	}
	else if ( MsgReturnVal == mrNo ) {
		fTempOpenFile = true;
	}

}

//-----------------------------------
// 復号開始
//-----------------------------------

//'復号しています...'
ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_DECRYPTING);
ProgressMsgText = ExtractFileName(AtcFilePath);

// ファイル(データ本体)サイズを取得する
AllTotalSize = fsIn->Size - fsIn->Position + 1;

// zlib 前準備
// 圧縮においてすべてのメモリ管理をライブラリに任せる
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;

if (inflateInit(&z) != Z_OK) {
	// エラー
	// zlibエラーは最後でまとめてメッセージ処理
	goto LabelError;
}

// 通常は deflate() の第2引数は Z_NO_FLUSH にして呼び出す
flush = Z_NO_FLUSH;

// 入出力バッファ
for (i = 0; i < LARGE_BUF_SIZE; i++) {
	output_buffer[i] = 0;
}

z.avail_in  = 0;               // 入力バッファ中のデータのバイト数
z.next_in   = Z_NULL;          // 入力バッファ中のデータのバイト数
z.next_out  = output_buffer;   // 出力バッファ残量
z.avail_out = LARGE_BUF_SIZE;  // 出力ポインタ(展開するので大きめに)
status      = Z_OK;

while (Terminated == false) {

	//-----------------------------------
	// 入力
	//-----------------------------------
	if (z.avail_in == 0) {

		TotalSize = InputBuffer(bf, len, source_buffer, fsIn, fInputFileOpen, TotalSize);
		z.avail_in = len;
		z.next_in = source_buffer;

		if ( len == 0 ) {  //入力ストリーム終了
			fInputEnd = true;
		}

	}

	//-----------------------------------
	// 展開
	//-----------------------------------
	status = inflate(&z, flush);

	//-----------------------------------
	// 処理ステータス
	//-----------------------------------
	if ( status == Z_OK ){

		if ( z.avail_out == 0 ) {

			ret = OutputBuffer(output_buffer, LARGE_BUF_SIZE,
												 fsOut, fOutputFileOpen,
												 FileList, FileIndex,
												 FileSizeList, FileAttrList, FileAgeList);

			if ( ret == 0) {
				z.next_out = output_buffer;
				z.avail_out = LARGE_BUF_SIZE;
			}
			else if (ret == -1) {
				goto LabelError;
			}
			else{
				goto LabelStop;
			}

		}//end if (z.avail_out == 0);

	}
	//-----------------------------------
	// バッファエラー
	//-----------------------------------
	else if ( status == Z_BUF_ERROR ) { //出力バッファがいっぱいの可能性

		//出力バッファをクリアにして継続させる
		len = LARGE_BUF_SIZE - z.avail_out;
		ret = OutputBuffer(output_buffer, len,
											 fsOut, fOutputFileOpen,
											 FileList, FileIndex,
											 FileSizeList, FileAttrList, FileAgeList);
		if (ret == 0) {
			z.next_out = output_buffer;
			z.avail_out = LARGE_BUF_SIZE;
		}
		else if ( ret == -1) {
			goto LabelError;
		}
		else{
			goto LabelStop;
		}

	}
	//-----------------------------------
	// 終了
	//-----------------------------------
	else if (status == Z_STREAM_END) {
		break;
	}
	//-----------------------------------
	// エラー
	//-----------------------------------
	else{
		// #define Z_OK              0
		// #define Z_STREAM_END      1
		// #define Z_NEED_DICT       2
		// #define Z_ERRNO         (-1)
		// #define Z_STREAM_ERROR  (-2)
		// #define Z_DATA_ERROR    (-3)
		// #define Z_MEM_ERROR     (-4)
		// #define Z_BUF_ERROR     (-5)
		// #define Z_VERSION_ERROR (-6)
		goto LabelError;
	}


	//-----------------------------------
	//進捗状況表示
	ProgressPercentNumF = (float)TotalSize/AllTotalSize;
	ProgressPercentNum = (int)(ProgressPercentNumF*100);
	if (AllTotalSize < 104857600) {	// 100MB未満
		ProgressPercentNumText = IntToStr(ProgressPercentNum)+"%";
	}
	else{
		ProgressPercentNumText = FloatToStrF(ProgressPercentNumF*100, ffNumber, 4, 1)+"%";
	}

	if ( fInputEnd == true) {
		break;
	}

}//while (!Terminated);

if (Terminated == true) {
	//ユーザーキャンセルで抜けてきた
	goto LabelStop;
}

//----------------------------------------------------------------------
// 万が一、出力バッファに余りがある場合
//----------------------------------------------------------------------

len = LARGE_BUF_SIZE - z.avail_out;
ret = OutputBuffer(output_buffer, len,
									 fsOut, fOutputFileOpen,
									 FileList, FileIndex,
									 FileSizeList, FileAttrList, FileAgeList);
if ( ret == 0 ) {
}
else if ( ret == -1 ){
	goto LabelError;
}
else{
	goto LabelStop;
}


if (inflateEnd(&z) != Z_OK) {
	goto LabelError;
}

ProgressPercentNum = 100;
//'完了'
ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_COMPLETE);
ProgressMsgText = ExtractFileName(AtcFilePath);

if ( fInputFileOpen == true ) {
	delete fsIn;
	fInputFileOpen = false;
}
if ( fOutputFileOpen == true ) {
	delete fsOut;
	fOutputFileOpen = false;
}

delete FileList;
delete [] FileSizeList;      // 1: ファイルサイズ(フォルダは-1)
delete [] FileAttrList;      // 2: 属性
delete [] FileAgeList;       // 3: 更新日

//復号成功
StatusNum = 1;
return;


//-----------------------------------
//パスワード入力ミスの後始末
//-----------------------------------
LabelTypeMiss:

	ProgressPercentNum = 0;

	//'エラー'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_ERROR);
	//'復号に失敗しました。'
	ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_FAILED);

	if ( fInputFileOpen == true ) {
		delete fsIn;
		fInputFileOpen = false;
	}
	if ( fOutputFileOpen == true ) {
		delete fsOut;
		fOutputFileOpen = false;
	}

	delete FileList;
	delete [] FileSizeList;
	delete [] FileAttrList;
	delete [] FileAgeList;

	StatusNum = -1;
	return;


//-----------------------------------
//エラーの後始末
//-----------------------------------
LabelError:

	ProgressPercentNum = 0;

	if ( status < 0 ){
		//'zlibライブラリからエラーを返されました。'
		//'エラー番号:'
		MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_ZLIB) + IntToStr(status) + "\n" + z.msg;
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
	}
	//'エラー'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_ERROR);
	//'復号に失敗しました。'
	ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_FAILED);

	if ( fInputFileOpen == true ) {
		delete fsIn;
		fInputFileOpen = false;
	}
	if ( fOutputFileOpen == true ) {
		delete fsOut;
		fOutputFileOpen = false;
	}

	delete FileList;
	delete [] FileSizeList;
	delete [] FileAttrList;
	delete [] FileAgeList;

	StatusNum = -2;
	return;


//-----------------------------------
//ユーザーキャンセルの後始末
//-----------------------------------
LabelStop:

	ProgressPercentNum = 0;
	//'キャンセル'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_USER_CANCEL);
	//'復号が中止されました。'
	ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_STOPPED);

	if ( fInputFileOpen == true ) {
		delete fsIn;
		fInputFileOpen = false;
	}
	if ( fOutputFileOpen == true ) {
		delete fsOut;
		fOutputFileOpen = false;
	}

	delete FileList;
	delete [] FileSizeList;
	delete [] FileAttrList;
	delete [] FileAgeList;

	StatusNum = 0;
	return;

}
//====================================================================
bool reg1test::importReg1test()
{
   //Create and Open File Stream
   try
   {
      THandleStream * hs = new THandleStream( ( int ) regContestFile );
      TStringList *sl = new TStringList;
      sl->LoadFromStream( hs );

      if ( !sl->Count )
      {
         return false;
      }

      enum reg1Stage {sStart, sHeader, sRemarks, sQSOs} stage = sStart;
      int nq = 0;
      int qcount = 0;
      // and here wade our way through
      for ( int lineno = 0; lineno < sl->Count; lineno++ )
      {
         String line = sl->Strings[ lineno ].Trim();

         if ( line.Length() == 0 )
         {
            continue;
         }
         if ( stage == sStart && line == "[REG1TEST;1]" )
         {
            stage = sHeader;
            continue;
         }
         if ( stage == sHeader && line == "[Remarks]" )
         {
            stage = sRemarks;
            continue;
         }
         if ( stage == sRemarks && line.SubString( 1, 12 ) == "[QSORecords;" )
         {
            for ( int i = remarks.size(); i < 4; i++ )
            {
               remarks.push_back( "" );
            }
            ct->entCondx1.setValue( remarks[ 0 ] );
            ct->entCondx2.setValue( remarks[ 1 ] );
            ct->entCondx3.setValue( remarks[ 2 ] );
            ct->entCondx4.setValue( remarks[ 3 ] );

            stage = sQSOs;
            nextBlock = 0;
            int endq = line.Pos( "]" );
            if ( endq == 0 )
            {
               return false;
            }
            String snq = line.SubString( 13, endq - 13 );
            nq = snq.ToIntDef( 0 );
            if ( !nq )
            {
               return false;
            }
            continue;
         }
         switch ( stage )
         {
            case sStart:
               {
                  // wait for the start - in case we have an email lead in
               }
               break;

            case sHeader:
               {
                  // parse out the header line and fill in the contest details
                  if ( !parseHeader( line ) )
                     return false;
               }
               break;

            case sRemarks:
               {
                  // read the remarks lines while they still come...
                  if ( !parseRemark( line ) )
                     return false;
               }
               break;

            case sQSOs:
               {
                  // parse out the QSO
                  if ( !parseQSO( line ) )
                  {
                     return false;
                  }
                  qcount++;
                  if ( nq == qcount )
                  {
                     return true;
                  }

               }
               break;

            default:     // there shouldn't be any others
               break;
         }
      }
      delete sl;
   }
   catch ( ... )
   {
      return false;
   }
   return true;
}
Exemple #3
0
bool __fastcall TMainForm::LoadHexToRAM(String fName, bool bLow)
{
  // Load all the text lines from the .hex file into a String List for easy
  // manipulation

  TStringList *sList = new TStringList;

  if (fName.Pos("VendAX")) {
    GetVendAX(sList);
  } else {
    TFileStream *srcStream = new TFileStream(fName,fmOpenRead | fmShareDenyWrite);
    if (srcStream == NULL) return false;
    sList->LoadFromStream(srcStream);
    delete srcStream;
  }


  String tmp;
  int v;

  // Delete non-data records
  for (int i=sList->Count - 1; i>=0; i--) {
    if (sList->Strings[i].Length()) {
      tmp = sList->Strings[i].SubString(8,2);   // Get the Record Type into v
      v = 0;  HexToBin(tmp.c_str(),(char *)&v,1); v *= 2;
      if (v) sList->Delete(i);                  // Data records are type == 0
    }
  }

  // Re-construct the strings to only contain the offset followed by the data
  for (int i=0; i<sList->Count; i++) {
    // Remove comments
    v = sList->Strings[i].Pos("//");
    if (v) sList->Strings[i].SetLength(v-1);

    // Build string that just contains the offset followed by the data bytes
    if (sList->Strings[i].Length()) {
      // Get the offset
      String sOffset = sList->Strings[i].SubString(4,4);

      // Get the string of data chars
      tmp = sList->Strings[i].SubString(2,2);
      v = 0;  HexToBin(tmp.c_str(),(char *)&v,1); v *= 2;
      String s = sList->Strings[i].SubString(10,v);

      // Replace the string in the list
      sList->Strings[i] = sOffset + s;
    }

  }

  if (bLow) ResetFX2(1);      // Stop the processor

  FX2Device->ControlEndPt->ReqCode = bLow ? 0xA0 : 0xA3;
  FX2Device->ControlEndPt->Index = 0;
  FX2Device->ControlEndPt->Value = 0;

  // Go through the list, loading data into RAM
  String DataString = "";
  WORD nxtoffset = 0;
  LONG xferLen = 0;

  WORD offset;
  int RamSize = 0x2000;  // 8KB

  UCHAR buf[MAX_CTLXFER_SIZE];

  char  c;
  PCHAR pc;

  for (int i=0; i<sList->Count; i++) {
    // Get the offset
    tmp = sList->Strings[i].SubString(1,4);
    HexToBin(tmp.c_str(),(char *)&offset,2);
    pc = (char *) &offset; c = pc[0]; pc[0]=pc[1]; pc[1]=c;  // Swap the bytes

    int sLen = sList->Strings[i].Length();

    // Handle a line that straddles the 8KB boundary
    int bytes = (sLen - 4)/2;
    LONG lastAddr = offset + bytes;

    // This case is the last segment to be sent to low memory
    if (bLow && (offset < RamSize) && (lastAddr > RamSize))
      bytes = RamSize - offset;

    // In this case, we found the first segment to be sent to the high memory
    if (!bLow && (offset < RamSize) && (lastAddr > RamSize)) {
      bytes = lastAddr - RamSize;
      String s = "xxxx"+sList->Strings[i].SubString(sLen - (bytes*2)+1,bytes*2);
      sList->Strings[i] = s;
      offset = RamSize;
    }

    if ((bLow &&  (offset < RamSize)) || // Below 8KB - internal RAM
       (!bLow && (offset >= RamSize)) ) {

      xferLen += bytes;

      if ((offset == nxtoffset) && (xferLen < MAX_CTLXFER_SIZE)) {
        DataString += sList->Strings[i].SubString(5,bytes*2);
      } else {
        LONG len = DataString.Length() / 2;
        if (len) {
          Hex2Bytes(DataString,buf);
          FX2Device->ControlEndPt->Write(buf, len);
        }

        FX2Device->ControlEndPt->Value = offset;  // The destination address

        DataString = sList->Strings[i].SubString(5,bytes*2);

        xferLen = bytes;

      }

      nxtoffset = offset + bytes;  // Where next contiguous data would sit
    }
  }

  // Send the last segment of bytes
  LONG len = DataString.Length() / 2;
  if (len) {
     Hex2Bytes(DataString,buf);
     FX2Device->ControlEndPt->Write(buf, len);
  }

  if (bLow) ResetFX2(0);      // Start running this new code

  return true;

}
//===========================================================================
//スレッド実行
//===========================================================================
void __fastcall TAttacheCaseFileDecrypt2::Execute()
{

int i, c, len;
float ProgressPercentNumF;  //進捗パーセンテージ(浮動小数点)

// バッファ
char source_buffer[BUF_SIZE];
char temp_buffer[BUF_SIZE];
char chain_buffer[BUF_SIZE];
char output_buffer[LARGE_BUF_SIZE];
char *headerbuffer;

//パスワード
bool fPasswordOk;
//const int KeyArrayNum = sizeof(key)/sizeof(key[0]);

String FilePath, FileName;

// ファイルストリーム
TFileStream *fsIn;
TFileStream *fsOut;

bool fInputFileOpen = false;
bool fOutputFileOpen = false;

float free_space_required;
__int64 CurrentPos, TotalSize;
__int64 CurrentDriveFreeSpaceSize;

//処理する合計サイズ
AllTotalSize = 0;

int ret;	//バッファ出力の返値
int FileIndex = 0;

char token[17] = {0, };
const char charTokenString[17] = "_AttacheCaseData";         //復号の正否に使う
const char charBrokenToken[17] = "_Atc_Broken_Data";         //ファイルが破壊されていることを示すトークン
String AtcFileTokenString;                                   //暗号化ファイルのトークン(文字列)
String AtcFileCreateDateString;                              //暗号化ファイルの生成日時(文字列)

//「復号したファイルを関連付けされたソフトで開く」一時的な設定
fTempOpenFile = fOpenFile;
//フォルダーを一度開いたか(深いフォルダーすべてを開かないように)
fOpenFolderOnce = false;

// 出力するディレクトリ
OutDirPath = IncludeTrailingPathDelimiter(OutDirPath);

String TempRelativePath;


// 平文ヘッダサイズ(データサブバージョン、破壊設定など)
int PlainHeaderSize = 0;
// 暗号化部分のヘッダサイズ
int EncryptHeaderSize = 0;

int DataVersion;        // ver.2.00~は "5", ver.2.70~は "6"
int AlgorismType;

char reserved;          // 0
//int TypeLimits;       // ミスタイプ回数 0~10  (グローバル:public宣言とした)
//bool fDestroy;        // 破壊するか否か 0 or 1 (グローバル:public宣言とした)

String PrefixString;	  //ファイルリストの接頭辞(Fn_*, U_*)

int flush, status;      // zlib
z_stream z;             // zlibライブラリとやりとりするための構造体
bool fInputEnd = false; // 入力ストリームの終了

//ヘッダデータから必要情報を取り出すための
TMemoryStream *pms;     // メモリストリーム

int idx;
TStringList *DataList;
TStringList *tsv;

TStringList *FileList = new TStringList();  // 0: ファイル名
__int64 *FileSizeList = 0;               // 1: ファイルサイズ(フォルダは-1)
int *FileAttrList     = 0;               // 2: 属性
int *FileDtChangeList = 0;               // 3: 更新日
int *FileTmChangeList = 0;               // 4: 更新時
int *FileDtCreateList = 0;               // 5: 作成日
int *FileTmCreateList = 0;               // 6: 作成時

int rest;
int buf_size;

//----------------------------------------------------------------------
// 平文のヘッダ内容チェック

try {
	fsIn = new TFileStream(AtcFilePath, fmOpenRead | fmShareDenyNone);
}
catch(...) {
	//'復号するファイルを開けません。他のアプリケーションが使用中の可能性があります。'
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_OPEN);
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	goto LabelError;
}

fInputFileOpen = true;

// 平文ヘッダサイズを取得
fsIn->Read(&PlainHeaderSize, sizeof(int));
// トークンを取得
fsIn->Read(token, 16);

if (StrComp(token, charTokenString) != 0 ) {
	//--------------------------------------------------------
	//実は自己実行形式ファイル?(拡張子偽装されている場合も)
	//--------------------------------------------------------
	// サイズを再取得
	fsIn->Seek(-(__int64)sizeof(__int64), TSeekOrigin::soEnd);
	fsIn->Read(&AllTotalSize, sizeof(__int64));
	// 位置を戻す
	fsIn->Seek(-(AllTotalSize + sizeof(__int64)), TSeekOrigin::soEnd);
	// もう一度、平文ヘッダサイズを読み込む
	fsIn->Read(&PlainHeaderSize, sizeof(int));
	// もう一度、トークンを取得
	fsIn->Read(token, 16);

	// トークンを再チェック
	if (StrComp(token, charTokenString) != 0 ) {

		if ( StrComp(token, charBrokenToken) == 0 ) {
			//'復号するファイルを開けません。この暗号化ファイルは破壊されています。'
			MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_BROKEN);
			MsgType = mtError;
			MsgButtons = TMsgDlgButtons() << mbOK;
			MsgDefaultButton = mbOK;
			Synchronize(&PostConfirmMessageForm);
		}
		else {
			// '暗号化ファイルではありません。アタッシェケースによって暗号化されたファイルでないか、'+#13+
			// 'ファイルが壊れている可能性があります。'
			MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_NOT_ATC);
			MsgType = mtError;
			MsgButtons = TMsgDlgButtons() << mbOK;
			MsgDefaultButton = mbOK;
			Synchronize(&PostConfirmMessageForm);
		}
		goto LabelError;
	}

}

//-----------------------------------
// データバージョンチェック
//-----------------------------------
DataVersion = -1;
fsIn->Read(&DataVersion, sizeof(int));

if (DataVersion > ATC_DATA_FILE_VERSION && DataVersion < 200) {
	//'データバージョンがちがいます。復号できません。'+#13+
	//'ファイルは上位バージョンのアタッシェケースで暗号化されています。'+#13+
	//'最新版を入手して復号を試みてください。';
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_HIGHER_VERSION);
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	goto LabelError;
}
else if (DataVersion <= 103) {

	// Blowfishで暗号化されたファイル
	// 正式版では正常に復号されるが、ここではエラーとする

	//'データバージョンがちがいます。復号できません。'+#13+
	//'ファイルはver.1のアタッシェケースで暗号化されています。'+#13+
	//'古いバージョン(ver.2.75以前)か正式版を入手して復号を試みてください。';
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_LOWER_VERSION);
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	goto LabelError;

}
else {

	// 104 ~
	// Rijndaelで暗号化されている

	// アルゴリズムタイプ
	fsIn->Read(&AlgorismType, sizeof(int));
	// ヘッダサイズを読み込む
	fsIn->Read(&EncryptHeaderSize, sizeof(int));
	// int型からポインタキャストでchar配列を取り出す
	headerbuffer = (char*) & PlainHeaderSize;
	// データサブバージョンチェック(ver.2.70~)
	if (headerbuffer[0] >= 6) {
		TypeLimits = (int)headerbuffer[2];
		fDestroy = (bool)headerbuffer[3];
		// 有効範囲(1~10)かチェック
		if (TypeLimits < 1 || 10 < TypeLimits) {
			TypeLimits = 3; // デフォルト
		}
	}
	else { // headerbuffer[0] == 5            //旧バージョン
		TypeLimits = 3;
		fDestroy = false;
	}
}


//-----------------------------------
// 復号の準備
//-----------------------------------

// テーブル生成
gentables();

// パスワードのセット
gkey(8, 8, key);

//-----------------------------------
// 暗号部ヘッダの復号
//-----------------------------------

pms = new TMemoryStream;

// IVの読み込み
fsIn->Read(chain_buffer, BUF_SIZE);

len = 0;

while (len < EncryptHeaderSize) {

	// 読み出しバッファ
	for (c = 0; c < BUF_SIZE; c++) {
		source_buffer[c] = 0;
	}
	// 暗号化されたデータブロックの読み出し
	len += fsIn->Read(source_buffer, BUF_SIZE);

	for (c = 0; c < BUF_SIZE; c++) {
		// あとのxorのためによけておく
		temp_buffer[c] = source_buffer[c];
	}

	// 復号処理
	rijndael_decrypt(source_buffer);

	// xor
	for (c = 0; c < BUF_SIZE; c++) {
		source_buffer[c] ^= chain_buffer[c];
		chain_buffer[c] = temp_buffer[c]; // CBC
	}

	pms->Write(source_buffer, BUF_SIZE);

}

pms->Seek((__int64)0, TSeekOrigin::soBeginning);  //ポインタを先頭へ戻す
DataList = new TStringList;
DataList->LoadFromStream(pms, TEncoding::GetEncoding(932));  // shift-jis

//-----------------------------------
// 復号正否(復号できたか)
//-----------------------------------

//MsgText = DataList->Strings[0];
//MsgType = mtError;
//MsgButtons = TMsgDlgButtons() << mbOK;
//MsgDefaultButton = mbOK;
//Synchronize(&PostConfirmMessageForm);

if (DataList->Count == 0 || DataList->Strings[0].Pos("AttacheCase") == 0) {
	fPasswordOk = false;
}
else{
	fPasswordOk = true;   //パスワード合致
}

if ( fPasswordOk == false ) {
	//'パスワードがちがいます。復号できません。'+#13+
	//'場合によってはファイルが壊れている可能性もあります。';
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_PASSWORD_WRONG);
	if ( fCompare == true ) {
		//メッセージに'コンペアに失敗しました。'を追加
		MsgText += "\n" + LoadResourceString(&Msgdecrypt::_MSG_ERROR_COMPARE_FILE);
	}
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	delete DataList;
	goto LabelTypeMiss;
}

//-----------------------------------
// 復号時のエンコーディング判定
//-----------------------------------
pms->Position = 0;
//DataList->LoadFromStream(pms, TEncoding::UTF8);
DataList->LoadFromStream(pms, TEncoding::GetEncoding(65001));

PrefixString = "Fn_";
for (i = 0; i < DataList->Count; i++) {
	if ( DataList->Strings[i].Pos("U_0") == 1){
		PrefixString = "U_";	//新バージョン(ver.2.8.0~)で暗号化されているようだ
		break;
	}
}

// Unicodeではないので従来のShift-JISで再度読み直し
if (PrefixString == "Fn_") {
	pms->Position = 0;
	DataList->LoadFromStream(pms, TEncoding::GetEncoding(932));
}

//===================================
// デバッグ
//ShowMessage(DataList->Text);
//===================================

#ifdef _DEBUG
DataList->SaveToFile(OutDirPath + ExtractFileName(AtcFilePath) + ".txt");
#endif

delete pms;


//-----------------------------------
// 暗号化ファイルの生成日時
//-----------------------------------
//※特に今は使用していないが、将来的に
//  期限付きでファイルを復号できなくなる
//  などの機能を追加しても良いかも。
//-----------------------------------
AtcFileCreateDateString = DataList->Strings[1];

//-----------------------------------
// ヘッダデータからファイルリストや
// ファイル情報などを各変数を動的確保
//-----------------------------------

FileSizeList = new __int64[DataList->Count];  // 1: ファイルサイズ(フォルダは-1)
FileAttrList = new int[DataList->Count];      // 2: 属性
FileDtChangeList = new int[DataList->Count];  // 3: 更新日
FileTmChangeList = new int[DataList->Count];  // 4: 更新時
FileDtCreateList = new int[DataList->Count];  // 5: 作成日
FileTmCreateList = new int[DataList->Count];  // 6: 作成時

DataList->NameValueSeparator = ':';

tsv = new TStringList;
tsv->Delimiter = '\t';
tsv->StrictDelimiter = true;

char lpPath[MAX_PATH];

for (i = 0; i < DataList->Count; i++) {
	idx = DataList->IndexOfName(PrefixString+IntToStr(i));
	if (idx > 0) {
		tsv->DelimitedText = DataList->ValueFromIndex[idx];

		// ディレクトリ・トラバーサル対策(ver.2.8.5.0~)
		bool fDirectoryTraversal = false;
		AnsiString CanonicalizePath = AnsiString(OutDirPath + tsv->Strings[0]);

		if (CanonicalizePath.Length() < MAX_PATH) {
			// ファイルパスを正規化
			if (PathCanonicalize(lpPath, CanonicalizePath.c_str()) == true) {
				// 正規化したパスが保存先と一致するか
				if (AnsiString(lpPath).Pos(OutDirPath) != 1 ){
					fDirectoryTraversal = true;
				}
			}
			else{
				fDirectoryTraversal = true;
			}
		}
		else{
			fDirectoryTraversal = true;
		}

		if (fDirectoryTraversal == true) {
			//'不正なファイルパスが含まれています。復号できません。';
			MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_INVALID_FILE_PATH) +
								"\n" + CanonicalizePath;
			MsgType = mtError;
			MsgButtons = TMsgDlgButtons() << mbOK;
			MsgDefaultButton = mbOK;
			Synchronize(&PostConfirmMessageForm);
			delete DataList;
			goto LabelTypeMiss;
		}

		FileList->Add(tsv->Strings[0]);                        // 0: ファイルパス
		FileSizeList[i] = StrToIntDef(tsv->Strings[1], -1);    // 1: ファイルサイズ(フォルダは-1)
		FileAttrList[i] = StrToIntDef(tsv->Strings[2], -1);    // 2: 属性
		FileDtChangeList[i] = StrToIntDef(tsv->Strings[3], -1);// 3: 更新日
		FileTmChangeList[i] = StrToIntDef(tsv->Strings[4], -1);// 4: 更新時
		FileDtCreateList[i] = StrToIntDef(tsv->Strings[5], -1);// 5: 作成日
		FileTmCreateList[i] = StrToIntDef(tsv->Strings[6], -1);// 6: 作成時
	}

}

delete tsv;
delete DataList;


//-----------------------------------
//ディスクの空き容量チェック
//-----------------------------------

CurrentDriveFreeSpaceSize = GetDiskFreeSpaceNum(OutDirPath);

if (CurrentDriveFreeSpaceSize > -1 && fCompare == false) {
	if ( AllTotalSize > CurrentDriveFreeSpaceSize ) {
		//'復号する先のドライブの空き容量が足りません。'+#13+
		//'復号するには、約%dMBの空き容量が必要です。復号処理を中止します。';
		MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_DRIVE_NO_FREE_SPACE);
		free_space_required = (float)AllTotalSize/1024/1024;  // MB
		MsgText = String().sprintf(MsgText.c_str(), free_space_required);
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
		goto LabelError;
	}
}
else{
	// OK!
	//
}

//-----------------------------------
//複数フォルダ/ファイルを開こうとしているので確認
//-----------------------------------

//復号したファイルを関連付けされたソフトで開くか
if ( fTempOpenFile == true && FileList->Count > 4 && fCompare == false) {

	//'5つ以上のファイルを復号後に開こうとしていますが、処理を続けますか?'+#13+
	//'「いいえ」を選択すると、開かず復号します。';
	MsgText = LoadResourceString(&Msgdecrypt::_MSG_CONFIRM_OPEN_DECRYPTED_FILES);
	MsgType = mtConfirmation;
	MsgButtons = TMsgDlgButtons() << mbYes << mbNo << mbCancel;
	MsgDefaultButton = mbCancel;
	Synchronize(&PostConfirmMessageForm);

	if ( MsgReturnVal == mrCancel ) {
		goto LabelStop;
	}
	else if ( MsgReturnVal == mrNo ) {
		fTempOpenFile = true;
	}

}

//-----------------------------------
// 復号開始
//-----------------------------------

if (fCompare == false) {
	//'復号しています...'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_DECRYPTING);
	ProgressMsgText = ExtractFileName(AtcFilePath);
}
else{
	//'コンペアしています...'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_COMPARING);
	ProgressMsgText = ExtractFileName(AtcFilePath);
}

// ファイル(データ本体)サイズを取得する
AllTotalSize = fsIn->Size - fsIn->Position + 1;
// 初期化ベクトルの読み出し
TotalSize = fsIn->Read(chain_buffer, BUF_SIZE);

// zlib 前準備
// 圧縮においてすべてのメモリ管理をライブラリに任せる
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;

if (inflateInit(&z) != Z_OK) {
	// エラー
	// zlibエラーは最後でまとめてメッセージ処理
	goto LabelError;
}

// 通常は deflate() の第2引数は Z_NO_FLUSH にして呼び出す
flush = Z_NO_FLUSH;

// 入出力バッファ
for (i = 0; i < LARGE_BUF_SIZE; i++) {
	output_buffer[i] = 0;
}

z.avail_in  = 0;               // 入力バッファ中のデータのバイト数
z.next_in   = Z_NULL;          // 入力バッファ中のデータのバイト数
z.next_out  = output_buffer;   // 出力バッファ残量
z.avail_out = LARGE_BUF_SIZE;  // 出力ポインタ(展開するので大きめに)
status      = Z_OK;

while (Terminated == false) {

	//-----------------------------------
	// 入力
	//-----------------------------------
	if (z.avail_in == 0) {

		TotalSize = InputBuffer(len, source_buffer, chain_buffer, fsIn, fInputFileOpen, TotalSize);
		z.avail_in = len;
		z.next_in = source_buffer;

		if ( len == 0 ) {  //入力ストリーム終了
			fInputEnd = true;
		}

	}

	//-----------------------------------
	// 展開
	//-----------------------------------
	status = inflate(&z, flush);


	//-----------------------------------
	// 処理ステータス
	//-----------------------------------
	if ( status == Z_OK ){

		if ( z.avail_out == 0 ) {

			ret = OutputBuffer(output_buffer, LARGE_BUF_SIZE,
												 fsOut, fOutputFileOpen,
												 FileList, FileIndex,
												 FileSizeList, FileAttrList,
												 FileDtChangeList, FileTmChangeList,
												 FileDtCreateList, FileTmCreateList);

			if ( ret == 0) {
				z.next_out = output_buffer;
				z.avail_out = LARGE_BUF_SIZE;
			}
			else if (ret == -1) {
				goto LabelError;
			}
			else{
				goto LabelStop;
			}

		}//end if (z.avail_out == 0);


	}
	//-----------------------------------
	// バッファエラー
	//-----------------------------------
	else if ( status == Z_BUF_ERROR ) { //出力バッファがいっぱいの可能性

		//出力バッファをクリアにして継続させる
		len = LARGE_BUF_SIZE - z.avail_out;
		ret = OutputBuffer(output_buffer, len,
											 fsOut, fOutputFileOpen,
											 FileList, FileIndex,
											 FileSizeList, FileAttrList,
											 FileDtChangeList, FileTmChangeList,
											 FileDtCreateList, FileTmCreateList);
		if (ret == 0) {
			z.next_out = output_buffer;
			z.avail_out = LARGE_BUF_SIZE;
		}
		else if ( ret == -1) {
			goto LabelError;
		}
		else{
			goto LabelStop;
		}

	}
	//-----------------------------------
	// 終了
	//-----------------------------------
	else if (status == Z_STREAM_END) {
		break;
	}
	//-----------------------------------
	// エラー
	//-----------------------------------
	else{
		// #define Z_OK              0
		// #define Z_STREAM_END      1
		// #define Z_NEED_DICT       2
		// #define Z_ERRNO         (-1)
		// #define Z_STREAM_ERROR  (-2)
		// #define Z_DATA_ERROR    (-3)
		// #define Z_MEM_ERROR     (-4)
		// #define Z_BUF_ERROR     (-5)
		// #define Z_VERSION_ERROR (-6)
		goto LabelError;
	}


	//-----------------------------------
	//進捗状況表示
	ProgressPercentNumF = (float)TotalSize/AllTotalSize;
	ProgressPercentNum = (int)(ProgressPercentNumF*100);
	if (AllTotalSize < 104857600) {	// 100MB未満
		ProgressPercentNumText = IntToStr(ProgressPercentNum)+"%";
	}
	else{
		ProgressPercentNumText = FloatToStrF(ProgressPercentNumF*100, ffNumber, 4, 1)+"%";
	}

	if ( fInputEnd == true) {
		break;
	}

}//while (!Terminated);

if (Terminated == true) {
	//ユーザーキャンセルで抜けてきた
	goto LabelStop;
}

//----------------------------------------------------------------------
// 万が一、出力バッファに余りがある場合
//----------------------------------------------------------------------

len = LARGE_BUF_SIZE - z.avail_out;
ret = OutputBuffer(output_buffer, len,
									 fsOut, fOutputFileOpen,
									 FileList, FileIndex,
									 FileSizeList, FileAttrList,
									 FileDtChangeList, FileTmChangeList,
									 FileDtCreateList, FileTmCreateList);
if ( ret == 0 ) {
}
else if ( ret == -1 ){
	goto LabelError;
}
else{
	goto LabelStop;
}


if (inflateEnd(&z) != Z_OK) {
	goto LabelError;
}

ProgressPercentNum = 100;
//'完了'
ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_COMPLETE);
ProgressMsgText = ExtractFileName(AtcFilePath);

if ( fInputFileOpen == true ) {
	delete fsIn;
	fInputFileOpen = false;
}
if ( fOutputFileOpen == true ) {
	delete fsOut;
	fOutputFileOpen = false;
}

delete FileList;
delete [] FileSizeList;      // 1: ファイルサイズ(フォルダは-1)
delete [] FileAttrList;      // 2: 属性
delete [] FileDtChangeList;  // 3: 更新日
delete [] FileTmChangeList;  // 4: 更新時
delete [] FileDtCreateList;  // 5: 作成日
delete [] FileTmCreateList;  // 6: 作成時

//復号成功
StatusNum = 1;
return;


//-----------------------------------
//パスワード入力ミスの後始末
//-----------------------------------
LabelTypeMiss:

	ProgressPercentNum = 0;

	//'エラー'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_ERROR);
	//'復号に失敗しました。'
	ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_FAILED);

	if ( fInputFileOpen == true ) {
		delete fsIn;
		fInputFileOpen = false;
	}
	if ( fOutputFileOpen == true ) {
		delete fsOut;
		fOutputFileOpen = false;
	}

	delete FileList;
	delete [] FileSizeList;
	delete [] FileAttrList;
	delete [] FileDtChangeList;
	delete [] FileTmChangeList;
	delete [] FileDtCreateList;
	delete [] FileTmCreateList;

	StatusNum = -1;
	return;


//-----------------------------------
//エラーの後始末
//-----------------------------------
LabelError:

	ProgressPercentNum = 0;

	if ( status < 0 ){
		//'zlibライブラリからエラーを返されました。'
		//'エラー番号:'
		MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_ZLIB) + IntToStr(status) + "\n" + z.msg;
		if ( fCompare == true ) {
			//メッセージに'コンペアに失敗しました。'を追加
			MsgText += "\n" + LoadResourceString(&Msgdecrypt::_MSG_ERROR_COMPARE_FILE);
		}
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
	}

	//'エラー'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_ERROR);

	if (fCompare == true) {
		//'コンペアで問題を見つけたようです。';
		ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_COMPARE_FAILED);
	}
	else{
		//'復号に失敗しました。'
		ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_FAILED);
	}

	if ( fInputFileOpen == true ) {
		delete fsIn;
		fInputFileOpen = false;
	}
	if ( fOutputFileOpen == true ) {
		delete fsOut;
		fOutputFileOpen = false;
	}

	delete FileList;
	delete [] FileSizeList;
	delete [] FileAttrList;
	delete [] FileDtChangeList;
	delete [] FileTmChangeList;
	delete [] FileDtCreateList;
	delete [] FileTmCreateList;

	StatusNum = -2;
	return;


//-----------------------------------
//ユーザーキャンセルの後始末
//-----------------------------------
LabelStop:

	ProgressPercentNum = 0;
	//'キャンセル'
	ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_USER_CANCEL);
	//'復号が中止されました。'
	ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_STOPPED);

	if ( fInputFileOpen == true ) {
		delete fsIn;
		fInputFileOpen = false;
	}
	if ( fOutputFileOpen == true ) {
		delete fsOut;
		fOutputFileOpen = false;
	}

	delete FileList;
	delete [] FileSizeList;
	delete [] FileAttrList;
	delete [] FileDtChangeList;
	delete [] FileTmChangeList;
	delete [] FileDtCreateList;
	delete [] FileTmCreateList;

	StatusNum = 0;
	return;

}
bool LoggerContestLog::importLOG( HANDLE hLogFile )
{
   THandleStream * hs = new THandleStream( ( int ) hLogFile );
   TStringList *ls = new TStringList();
   ls->LoadFromStream( hs );

   TEMPBUFF( temp, 100 );
   // Import from LOG format
   // Needs modification for "new" log format

   locValid = false;
   //   save();
   // read remainder of lines; write each line as we go

   long next_block = 1;

   bool started = false;

   DisplayContestContact *ct = 0;
   int lineNo = -1;
   while ( ++lineNo < ls->Count )
   {
      // skip new format header information, until we can cope
      // properly with it
      std::string stemp = trimr( ls->Strings[ lineNo ].c_str() );
      if ( stemp.length() == 0 || ( !started && !isdigit( ls->Strings[ lineNo ][ 1 ] ) ) )
      {
         // GJV.LOG

         /*
         Contest Title                        : VHFNFD
         Band in MHz                          : 432
         Section Entered                      : Multi Operator
         Name of Entrant/Club/Contest Group   : Bracknell Amateur Radio Club
         Band in MHz                          : %band%
         Section Entered                      : %section%
         Callsign Used                        : %call%
         QRH Locator Sent                     : %locator%
         Location as sent(District or QTH)    : %QTH%
         Brief Details of Transmitter Used    : %Transmitter%
         Brief Details of Receiver Used       : %Receiver%
         Power Output (Watts)                 : %power%
         Antenna Type                         : %Antenna%
         Antenna Height AGL(metres)           : %AGL%
         QTH Height ASL(metres)               : %ASL%

         Difficult ones:
         Name and Callsign of all Operators   :
         G0GJV  G4AUC  G0FCT  G0HVS
         Name, Callsign, Telephone Number, Address for Correspondence :
                                     : M. J. Goodey
                                     : G0GJV
                                     : 62, Rose Hill
                                     : Binfield
                                     : Berkshire
                                     : RG42 5LG
                               Phone : 01344 428614
                               Email : [email protected]

         */
         unsigned int spos = stemp.find( ":" );
         if ( spos != std::string::npos )
         {
            std::string text = trim( stemp.substr( spos + 1, stemp.size() ) );

            if ( strupr( stemp ).find( "CONTEST TITLE" ) == 0 )
            {
               name.setValue( text );
            }
            else
               if ( strupr( stemp ).find( "BAND IN MHZ" ) == 0 )
               {
                  band.setValue( text );
               }
               else
                  if ( strupr( stemp ).find( "SECTION ENTERED" ) == 0 )
                  {
                     entSect.setValue( text );
                  }
                  else
                     if ( strupr( stemp ).find( "NAME OF ENTRANT/CLUB/CONTEST GROUP" ) == 0 )
                     {
                        entrant.setValue( text );
                     }
                     else
                        if ( strupr( stemp ).find( "CALLSIGN USED" ) == 0 )
                        {
                           // we need to tail clip the callsign - or we end up with things like
                           // M1DUD/QRP        CLASS : SO  /   50MHZ FIXED
                           unsigned int spos = text.find( " " );
                           if ( spos != std::string::npos )
                           {
                              text = trim( text.substr( 0, spos ) );
                           }
                           mycall.fullCall.setValue( strupr( text ) );
                           mycall.valRes = CS_NOT_VALIDATED;
                           mycall.validate();

                        }
                        else
                           if ( strupr( stemp ).find( "QRH LOCATOR SENT" ) == 0 ||
                                strupr( stemp ).find( "QTH LOCATOR SENT" ) == 0 )
                           {
                              // yes, contestx DOES say QRH!
                              myloc.loc.setValue( strupr( text ) );
                              validateLoc();
                           }
                           else
                              if ( strupr( stemp ).find( "POWER OUTPUT" ) == 0 )
                              {
                                 power.setValue( text );
                              }
                              else
                                 if ( strupr( stemp ).find( "LOCATION AS SENT" ) == 0 )
                                 {
                                    location.setValue( text );
                                 }
                                 else
                                    if ( strupr( stemp ).find( "ANTENNA TYPE" ) == 0 )
                                    {
                                       entAnt.setValue( text );
                                    }
                                    else
                                       if ( strupr( stemp ).find( "ANTENNA HEIGHT" ) == 0 )
                                       {
                                          entAGL.setValue( text );
                                       }
                                       else
                                          if ( strupr( stemp ).find( "QTH HEIGHT" ) == 0 )
                                          {
                                             entASL.setValue( text );
                                          }
                                          else
                                             if ( strupr( stemp ).find( "BRIEF DETAILS OF TRANSMITTER USED" ) == 0 )
                                             {
                                                entTx.setValue( text );
                                             }
                                             else
                                                if ( strupr( stemp ).find( "BRIEF DETAILS OF RECEIVER USED" ) == 0 )
                                                {
                                                   entRx.setValue( text );
                                                }
         }
         continue;
      }
      started = true;

      makeContact( false, ( BaseContact * ) ct );
      ct->setLogSequence( 0 );

      stemp += std::string( 200, ' ' );   // make sure there is plenty more...
      const char *lbuff = stemp.c_str();
      // parse contact line in

      strcpysp( temp, &lbuff[ 0 ], 6 );
      ct->time.setDate( temp, DTGLOG );
      strcpysp( temp, &lbuff[ 7 ], 4 );
      ct->time.setTime( temp, DTGLOG );
      strcpysp( temp, &lbuff[ 21 ], 15 );
      ct->cs = callsign( strupr( temp ) );
      ct->cs.valRes = CS_NOT_VALIDATED;
      strcpysp( temp, &lbuff[ 37 ], 3 );
      ct->reps.setValue( temp );
      strcpysp( temp, &lbuff[ 41 ], 4 );
      ct->serials.setValue( temp );

      int maxct = atoi( ct->serials.getValue().c_str() );
      if ( maxct > maxSerial )
         maxSerial = maxct;

      strcpysp( temp, &lbuff[ 46 ], 3 );
      ct->repr.setValue( temp );
      strcpysp( temp, &lbuff[ 51 ], 4 );
      ct->serialr.setValue( temp );

      // here is the score field
      strcpysp( temp, &lbuff[ 59 ], 5 );
      if ( atoi( temp ) == 0 )
         ct->contactFlags.setValue( NON_SCORING );

      strcpysp( temp, &lbuff[ 65 ], 6 );
      ct->op1.setValue( temp );

      strcpysp( temp, &lbuff[ 72 ], 6 );
      ct->loc.loc.setValue( temp );
      ct->loc.valRes = LOC_NOT_VALIDATED;

      //ct->comments = "";

      TEMPBUFF( extra, EXTRALENGTH + 1 );
      TEMPBUFF( comments, COMMENTLENGTH + 1 );

      strcpysp( extra, &lbuff[ 81 ], 2 );          // 81 is district code
      if ( extra[ 0 ] && extra[ 1 ] && ( extra[ 0 ] != ' ' && extra[ 1 ] != ' ' ) )
      {
         // we always attempt to import the district mult field
         strcpysp( comments, &lbuff[ 93 ], COMMENTLENGTH );
         ct->comments.setValue( comments );

      }
      else
      {
         strcpysp( extra, &lbuff[ 93 ], EXTRALENGTH );
      }
      ct->extraText.setValue( extra );

      //	   strcpysp(ct->power, power, 7);
      //      ct->PowerWatts = PowerWatts;
      // save contact

      // we have to have logSequence set before we insert - or it will cause
      // duplicates

      next_block++ ;
      ct->setLogSequence( next_block << 16 );

      ctList.insert( ct );
   }
   delete ls;
   delete hs;
   return true;
}