Artifact Content

Not logged in

Artifact 683230bf72bb28e0385ce1301497bee83a0cfff0


     1  
     2  #include "stdafx.h"
     3  #include "../kilib/kilib.h"
     4  #include "resource.h"
     5  
     6  
     7  //-- 雑用Functions ----------------------------------------------------------
     8  
     9  void getProgramFiles( kiPath* path )
    10  {
    11  	// 1.レジストリから
    12  	kiRegKey key;
    13  	if( key.open( HKEY_CLASSES_ROOT, "Software\\Microsoft\\Windows\\CurrentVersion", KEY_QUERY_VALUE ) )
    14  		if( key.get( "ProgramFilesDir",  path )
    15  		 || key.get( "ProgramFilesPath", path ) )
    16  			return;
    17  
    18  	// 2.Windowsディレクトリからの類推
    19  	char buf[MAX_PATH];
    20  	if( ::GetWindowsDirectory( buf, MAX_PATH ) )
    21  	{
    22  		for( char* p=buf; *p!='\\' && *p; p++ );
    23  		*p='\0';
    24  
    25  		*path= buf, *path += '\\', *path += "Program Files";
    26  		if( ::GetFileAttributes( *path ) != 0xffffffff )
    27  			return;
    28  	}
    29  
    30  	// 3.しゃーないので起動ディレクトリ
    31  	path->beSpecialPath( kiPath::Exe );
    32  }
    33  
    34  void createShortCut( const kiPath& original, const kiPath& at, const char* name )
    35  {
    36  	IShellLink* psl;
    37  	if( SUCCEEDED(::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,IID_IShellLink,(void**)&psl)) )
    38  	{
    39  		psl->SetPath( original );
    40  
    41  		IPersistFile* ppf;
    42  		if( SUCCEEDED(psl->QueryInterface(IID_IPersistFile,(void**)&ppf)) )
    43  		{
    44  			WORD wsz[MAX_PATH]; 
    45  			kiPath lnkfile( at );
    46  			lnkfile += name, lnkfile += ".lnk";
    47  			::MultiByteToWideChar(CP_ACP,0,lnkfile,-1,wsz,MAX_PATH);
    48  			ppf->Save(wsz,TRUE);
    49  			ppf->Release();
    50  		}
    51  		psl->Release();
    52  	}
    53  }
    54  
    55  
    56  //-- メイン -------------------------------------------------------------------
    57  
    58  class CKInstApp : public kiApp, kiDialog // kiAppのコンストラクタが先に呼ばれないと死ぬ。よろしくない。
    59  {
    60  	CKInstApp() : kiDialog( IDD_MAIN ) {}
    61  	friend void kilib_create_new_app();
    62  
    63  //-- メインルーチン ---------
    64  
    65  	void run( kiCmdParser& cmd )
    66  	{
    67  		if( cmd.option().len() )
    68  			if( cmd.option()[0][1] == 'i' )
    69  			{
    70  				install();
    71  				return;
    72  			}
    73  			else if( cmd.option()[0][1] == 'u' && cmd.param().len() )
    74  			{
    75  				uninstall( cmd.param()[0] );
    76  				return;
    77  			}
    78  		boot_uninstaller();
    79  	}
    80  
    81  	void install()
    82  	{
    83  		doModal();
    84  		if( IDCANCEL == getEndCode() )
    85  			return;
    86  
    87  		if( !copy() )
    88  		{
    89  			msgBox( kiStr().loadRsrc(IDS_COPYFAIL) );
    90  			return;
    91  		}
    92  
    93  		if( !regist() )
    94  			msgBox( kiStr().loadRsrc(IDS_REGISTFAIL) );
    95  
    96  		do_caldix();
    97  
    98  		msgBox( kiStr().loadRsrc(IDS_INSTALLFINISH),"Noah",MB_OK|MB_ICONINFORMATION );
    99  	}
   100  
   101  	void uninstall( const char* dir )
   102  	{
   103  		m_destdir = dir;
   104  		for( int i=0; i!=sizeof(m_assoc)/sizeof(bool); i++ )
   105  			m_assoc[i]=false;
   106  		Sleep(200);
   107  		unregist();
   108  		remove();
   109  		kill_later( kiPath(kiPath::Exe_name) );
   110  		msgBox( kiStr().loadRsrc(IDS_UNINSTALLFINISH),"Noah",MB_OK|MB_ICONINFORMATION );
   111  	}
   112  
   113  	void boot_uninstaller()
   114  	{
   115  		if( IDNO==msgBox( kiStr(500).loadRsrc(IDS_UNINSTOK), "Noah", MB_YESNO|MB_ICONQUESTION ) )
   116  			return;
   117  
   118  		kiPath self(kiPath::Exe_name), to(kiPath::Tmp), pos(kiPath::Exe);
   119  		to += "noaunins.exe";
   120  		::CopyFile( self, to, FALSE );
   121  		to += " -u \"", to += pos, to+='"';
   122  
   123  		PROCESS_INFORMATION pi;
   124  		STARTUPINFO si;	ki_memzero( &si,sizeof(si) ); si.cb=sizeof(si);
   125  		if( !::CreateProcess( NULL,const_cast<char*>((const char*)to),
   126  			NULL,NULL,FALSE,CREATE_NEW_PROCESS_GROUP|NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi ) )
   127  			return; // 起動できなかった…。
   128  
   129  		::CloseHandle( pi.hThread );
   130  		::CloseHandle( pi.hProcess );
   131  
   132  		// レジストリのアンインストール情報削除
   133  		kiRegKey key;
   134  		if( key.open( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall" ) )
   135  			key.delSubKey( "Noah" );
   136  	}
   137  
   138  //-- メインダイアログの処理 --
   139  
   140  	bool onOK()
   141  	{
   142  		char str[MAX_PATH];
   143  		sendMsgToItem( IDC_INSTALLTO, WM_GETTEXT, MAX_PATH, (LPARAM)str );
   144  		if( str[1]!=':' || str[2]!='\\' )
   145  		{
   146  			msgBox( kiStr().loadRsrc(IDS_BADPATH) );
   147  			return false;
   148  		}
   149  
   150  		m_destdir = str;
   151  		m_destdir.beBackSlash(true);
   152  		for( UINT i=IDC_LZH; i<=IDC_DSK; i++ )
   153  			m_assoc[i-IDC_LZH] = (BST_CHECKED==sendMsgToItem( i, BM_GETCHECK ));
   154  		m_assoc[IDC_STT-IDC_LZH] = true;
   155  
   156  		return true;
   157  	}
   158  	BOOL onInit()
   159  	{
   160  		for( int j=0; j<18; j++ )
   161  			m_assoc[j] = true;
   162  
   163  		kiPath prg;
   164  		getPrevPos( &prg );
   165  		if( prg.len()==0 ) // 新規インストール
   166  			getProgramFiles( &prg ), prg.beBackSlash(true), prg += "Noah\\";
   167  		else // 既に存在してる場合
   168  		{
   169  			HINSTANCE hDLL = kiSUtil::loadLibrary( "NoahXt.dll" );
   170  			if( hDLL )
   171  			{
   172  				typedef bool (WINAPI * XT_IA)();
   173  				XT_IA Init = (XT_IA)::GetProcAddress( hDLL, "Init" );
   174  				if( Init() )
   175  				{
   176  					typedef void (WINAPI * XT_LS)(bool*,bool*);
   177  					typedef void (WINAPI * XT_AS)(bool*);
   178  					typedef void (WINAPI * XT_LSEX)(const char*,bool*);
   179  					XT_LS LoadSE    = (XT_LS)::GetProcAddress( hDLL, "LoadSE" );
   180  					XT_AS LoadAssoc = (XT_AS)::GetProcAddress( hDLL, "LoadAS" );
   181  					XT_LSEX LoadASEx = (XT_LSEX)::GetProcAddress( hDLL, "LoadASEx" );
   182  					LoadSE( &m_assoc[13], &m_assoc[14] );
   183  					LoadASEx( "7z\0", &m_assoc[12] );
   184  					LoadAssoc( m_assoc );
   185  				}
   186  				::FreeLibrary( hDLL );
   187  			}
   188  			m_assoc[15] = kiSUtil::exist( kiPath(kiPath::Snd)+="Noah.lnk" );
   189  			m_assoc[16] = kiSUtil::exist( kiPath(kiPath::Dsk)+="Noah.lnk" );
   190  		}
   191  
   192  		sendMsgToItem( IDC_INSTALLTO, WM_SETTEXT, 0, (LPARAM)(const char*)prg );
   193  		for( UINT i=IDC_LZH; i<=IDC_DSK; i++ )
   194  			if( m_assoc[i-IDC_LZH] )
   195  				sendMsgToItem( i, BM_SETCHECK, BST_CHECKED );
   196  		return FALSE;
   197  	}
   198  	BOOL CALLBACK proc( UINT msg, WPARAM wp, LPARAM lp )
   199  	{
   200  		if( msg != WM_COMMAND )
   201  			return FALSE;
   202  		switch( LOWORD(wp) )
   203  		{
   204  		case IDC_REF:{
   205  			char str[MAX_PATH];
   206  			sendMsgToItem( IDC_INSTALLTO, WM_GETTEXT, MAX_PATH, (LPARAM)str );
   207  			if( kiSUtil::getFolderDlg( str, hwnd(), kiStr().loadRsrc(IDS_DIR), str ) )
   208  			{
   209  				kiPath x(str); x.beBackSlash(true); x+="Noah\\";
   210  				sendMsgToItem( IDC_INSTALLTO, WM_SETTEXT, 0, (LPARAM)(const char*)x );
   211  			}
   212  			}break;
   213  		case IDC_ALL:{
   214  			for( UINT i=IDC_LZH; i<=IDC_DSK; i++ )
   215  				sendMsgToItem( i, BM_SETCHECK, BST_UNCHECKED );
   216  			}break;
   217  		default:
   218  			return FALSE;
   219  		}
   220  		return TRUE;
   221  	}
   222  
   223  //-- インストール ---------
   224  
   225  	bool m_assoc[18]; // LZH-JAK, 7Z, CMP MLT, SND DSK STT
   226  	kiPath m_destdir;
   227  
   228  	bool copy()
   229  	{
   230  		kiPath exe(kiPath::Exe,false), inst(m_destdir);
   231  		inst.beBackSlash(false);
   232  
   233  		// とりあえず全コピ
   234  		bool r = copy_dir2dir(exe,inst);
   235  
   236  		// manualの言語をてけとーに調整
   237  		kiPath manE(m_destdir), manJ(m_destdir);
   238  		manE.beBackSlash(true), manJ.beBackSlash(true);
   239  		manE += "manual-e.htm", manJ += "manual.htm";
   240  		if( ::GetACP() != 932 )
   241  			::CopyFile( manE, manJ, FALSE );
   242  		::DeleteFile( manE );
   243  
   244  		return r;
   245  	}
   246  
   247  	bool regist()
   248  	{
   249  		// NoahXt.dllによる処理
   250  		kiPath xtdll( m_destdir );
   251  		xtdll += "NoahXt.dll";
   252  		HINSTANCE hDLL = kiSUtil::loadLibrary( xtdll );
   253  		if( hDLL )
   254  		{
   255  			typedef bool (WINAPI * XT_IA)();
   256  			typedef void (WINAPI * XT_LS)(bool*,bool*);
   257  			typedef void (WINAPI * XT_SS)(bool,bool);
   258  			typedef void (WINAPI * XT_AS)(bool*);
   259  			typedef void (WINAPI * XT_SSEX)(const char*,bool);
   260  			XT_IA Init = (XT_IA)::GetProcAddress( hDLL, "Init" );
   261  			if( Init() )
   262  			{
   263  				XT_SS SaveSE = (XT_SS)::GetProcAddress( hDLL, "SaveSE" );
   264  				XT_AS SaveAssoc = (XT_AS)::GetProcAddress( hDLL, "SaveAS" );
   265  				XT_SSEX SaveASEx = (XT_SSEX)::GetProcAddress( hDLL, "SaveASEx" );
   266  				SaveSE( m_assoc[13], m_assoc[14] );
   267  				SaveASEx( "7z\0", m_assoc[12] );
   268  				SaveAssoc( m_assoc );
   269  			}
   270  			::FreeLibrary( hDLL );
   271  		}
   272  
   273  		// ショートカット
   274  		::CoInitialize( NULL );
   275  			kiPath tmp(m_destdir); tmp += "Noah.exe";
   276  			if( m_assoc[15] )
   277  				createShortCut( tmp, kiPath(kiPath::Snd), "Noah" );
   278  			if( m_assoc[16] )
   279  				createShortCut( tmp, kiPath(kiPath::Dsk), "Noah" );
   280  			if( m_assoc[17] )
   281  			{
   282  				kiPath StartMenu( CSIDL_PROGRAMS ),rsrc;
   283  				StartMenu += "Noah\\";
   284  				StartMenu.mkdir();
   285  
   286  				createShortCut( tmp, StartMenu, "Noah" );
   287  				tmp = m_destdir, tmp += "caldix.exe";
   288  				createShortCut( tmp, StartMenu, rsrc.loadRsrc(IDS_CALDIX) );
   289  				tmp = m_destdir, tmp += "manual.htm";
   290  				createShortCut( tmp, StartMenu, rsrc.loadRsrc(IDS_HELP) );
   291  				tmp = m_destdir, tmp += "uninst.exe";
   292  				createShortCut( tmp, StartMenu, rsrc.loadRsrc(IDS_UNINSTALLER) );
   293  			}
   294  		::CoUninitialize();
   295  
   296  		// アンインストール情報をレジストリへ
   297  		kiPath uninst( m_destdir );
   298  		uninst += "uninst.exe";
   299  
   300  		kiRegKey key;
   301  		if( !key.create( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Noah", KEY_WRITE ) )
   302  			return false;
   303  		key.set( "DisplayName", kiStr().loadRsrc(IDS_NOAH) );
   304  		key.set( "UninstallString", uninst );
   305  		return true;
   306  	}
   307  
   308  	void do_caldix()
   309  	{
   310  		if( IDYES==msgBox( kiStr(1000).loadRsrc(IDS_DLLINST),"Noah",MB_YESNO|MB_ICONQUESTION ) )
   311  		{
   312  			kiStr cld;
   313  			cld += '"';
   314  			cld += m_destdir;
   315  			cld += "caldix.exe";
   316  			cld += '"';
   317  
   318  			// プロセス開始
   319  			PROCESS_INFORMATION pi;
   320  			STARTUPINFO si;	ki_memzero( &si,sizeof(si) ); si.cb=sizeof(si);
   321  			if( !::CreateProcess( NULL,const_cast<char*>((const char*)cld),
   322  				NULL,NULL,FALSE,CREATE_NEW_PROCESS_GROUP|NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi ) )
   323  				return;
   324  
   325  			// 終了待機
   326  			::CloseHandle( pi.hThread );
   327  			::WaitForSingleObject( pi.hProcess, INFINITE );
   328  			::CloseHandle( pi.hProcess );
   329  		}
   330  	}
   331  
   332  	bool copy_dir2dir( kiPath& from, kiPath& to )
   333  	{
   334  		if( !kiSUtil::isdir(from) )
   335  		{
   336  			if( ::CopyFile( from, to, FALSE ) )
   337  				return true;
   338  			if( 0==ki_strcmpi( from.ext(), "dll" ) )
   339  				return copy_later(from, to);
   340  			return false;
   341  		}
   342  
   343  		from += '\\', to += '\\', to.mkdir();
   344  		if( !kiSUtil::isdir(to) )
   345  			return false;
   346  
   347  		kiFindFile find;
   348  		WIN32_FIND_DATA fd;
   349  		kiPath src, dst, wild(from); wild+="\\*";
   350  		for( find.begin( wild ); find.next(&fd); )
   351  		{
   352  			src = from, src+='\\', src += fd.cFileName;
   353  			dst = to  , dst+='\\', dst += fd.cFileName;
   354  			if( !copy_dir2dir( src, dst ) )
   355  				return false;
   356  		}
   357  		return true;
   358  	}
   359  
   360  	void getPrevPos( kiPath* path )
   361  	{
   362  		*path = "";
   363  
   364  		kiRegKey key;
   365  		if( !key.open( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Noah", KEY_READ ) )
   366  			return;
   367  		key.get( "UninstallString", path );
   368  		path->beDirOnly();
   369  	}
   370  
   371  //-- アンインストール ---------
   372  
   373  	typedef bool (WINAPI * XT_IA)();
   374  	typedef void (WINAPI * XT_LS)(bool*,bool*);
   375  	typedef void (WINAPI * XT_SS)(bool,bool);
   376  	typedef void (WINAPI * XT_AS)(bool*);
   377  	typedef void (WINAPI * XT_SAX)(const char*,bool);
   378  	typedef void (WINAPI * XT_LAX)(const char*,bool*);
   379  	bool unregist()
   380  	{
   381  		// NoahXt.dllによる処理
   382  		kiPath xtdll( m_destdir );
   383  		xtdll += "NoahXt.dll";
   384  		HINSTANCE hDLL = kiSUtil::loadLibrary( xtdll );
   385  		if( hDLL )
   386  		{
   387  			XT_IA Init = (XT_IA)::GetProcAddress( hDLL, "Init" );
   388  			if( Init() )
   389  			{
   390  				XT_SAX SaveASEx = (XT_SAX)::GetProcAddress( hDLL, "SaveASEx" );
   391  				XT_LAX LoadASEx = (XT_LAX)::GetProcAddress( hDLL, "LoadASEx" );
   392  				unregist_b2e( SaveASEx, LoadASEx );
   393  
   394  				XT_SS SaveSE = (XT_SS)::GetProcAddress( hDLL, "SaveSE" );
   395  				XT_AS SaveAssoc = (XT_AS)::GetProcAddress( hDLL, "SaveAS" );
   396  				SaveSE( m_assoc[13], m_assoc[14] );
   397  				SaveAssoc( m_assoc );
   398  			}
   399  			::FreeLibrary( hDLL );
   400  		}
   401  
   402  		// ショートカット
   403  		::CoInitialize( NULL );
   404  		kiPath snd(kiPath::Snd); snd += "Noah.lnk";
   405  		kiPath dsk(kiPath::Dsk); dsk += "Noah.lnk";
   406  		kiPath stt(CSIDL_PROGRAMS); stt += "Noah";
   407  		::DeleteFile(snd), ::DeleteFile(dsk), stt.remove();
   408  
   409  		return true;
   410  	}
   411  
   412  	static void crack_str( char* p )
   413  	{
   414  		for( ; *p; p=kiStr::next(p) )
   415  			if( *p=='.' )
   416  				*p++ = '\0';
   417  		*++p = '\0';
   418  	}
   419  
   420  	void unregist_b2e( XT_SAX SaveASEx, XT_LAX LoadASEx )
   421  	{
   422  		char* first_dot;
   423  		kiFindFile f;
   424  		WIN32_FIND_DATA fd;
   425  		kiPath b2ewild(m_destdir);
   426  		b2ewild.beBackSlash(true);
   427  
   428  		f.begin( b2ewild+="b2e\\*.b2e" );
   429  		while( f.next(&fd) )
   430  			if( fd.cFileName[0] != '#' ) // # 付きは圧縮専用
   431  			{
   432  				// 拡張子を切り出し
   433  				::CharLower( fd.cFileName );
   434  				first_dot = const_cast<char*>(kiPath::ext_all(fd.cFileName)-1);
   435  				*first_dot = '\0';
   436  				crack_str( fd.cFileName );
   437  				// 関連づけ削除
   438  				SaveASEx( fd.cFileName, false );
   439  			}
   440  		SaveASEx( "7z\0", false );
   441  	}
   442  
   443  	bool remove()
   444  	{
   445  		::SetCurrentDirectory( kiPath(kiPath::Exe) );
   446  
   447  		kiPath tmp;
   448  		m_destdir.beBackSlash(true);
   449  		// インストールしたモノだけ全削除
   450  		tmp=m_destdir, tmp+="Noah.exe",   ::DeleteFile(tmp);
   451  		tmp=m_destdir, tmp+="Noah.ini",   ::DeleteFile(tmp);
   452  		tmp=m_destdir, tmp+="uninst.exe", ::DeleteFile(tmp);
   453  		tmp=m_destdir, tmp+="caldix.exe", ::DeleteFile(tmp);
   454  		tmp=m_destdir, tmp+="caldix.ini", ::DeleteFile(tmp);
   455  		tmp=m_destdir, tmp+="ReadMe.txt", ::DeleteFile(tmp);
   456  		tmp=m_destdir, tmp+="manual.htm", ::DeleteFile(tmp);
   457  		tmp=m_destdir, tmp+="html",       tmp.remove();
   458  		tmp=m_destdir, tmp+="b2e\\jak.b2e",     ::DeleteFile(tmp);
   459  		tmp=m_destdir, tmp+="b2e\\aboutb2e.txt",::DeleteFile(tmp);
   460  		tmp=m_destdir, tmp+="b2e",        ::RemoveDirectory(tmp);
   461  		tmp=m_destdir, tmp+="NoahXt.dll", ::DeleteFile(tmp);
   462  		::RemoveDirectory(m_destdir);
   463  		// NoahXt.dllは再起動後に回すかも知れない
   464  		if( kiSUtil::exist(tmp) )
   465  		{
   466  			kill_later(tmp);
   467  			tmp.beDirOnly();
   468  			tmp.beBackSlash(false);
   469  			kill_later(tmp);
   470  		}
   471  
   472  		return true;
   473  	}
   474  
   475  	void kill_later( const char* pszFile )
   476  	{
   477  		// "MoveFileEx Not Supported in Windows 95 But Functionality Is"
   478  		if( ::MoveFileEx( pszFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT ) )
   479  			return;
   480  		char shortPath[MAX_PATH];
   481  		::GetShortPathName( pszFile, shortPath, sizeof(shortPath) );
   482  
   483  		kiPath inifile( kiPath::Win ); inifile+="wininit.ini";
   484  
   485  		char buf[30000];
   486  		::GetPrivateProfileSection( "Rename", buf, 30000, inifile ); 
   487  		char* p = buf; 
   488  		while(*p)while(*p++);
   489  
   490  		::lstrcpy( p, "NUL=" );
   491  		::lstrcat( p, shortPath );
   492  		while(*p++);
   493  		*p='\0'; 
   494  
   495  		::WritePrivateProfileSection( "Rename", buf, inifile );
   496  
   497  		// 確実に書き込む
   498  		::WritePrivateProfileString( NULL, NULL, NULL, inifile );
   499  	}
   500  
   501  	bool copy_later( const char* from, const char* to )
   502  	{
   503  		char from_temp[MAX_PATH];
   504  		::lstrcpy( from_temp, to );
   505  		::lstrcat( from_temp, ".new" );
   506  		if( !::CopyFile( from, from_temp, FALSE ) )
   507  			return false;
   508  
   509  		char shortFrom[MAX_PATH];
   510  		::GetShortPathName( from_temp, shortFrom, sizeof(shortFrom) );
   511  		char shortTo[MAX_PATH];
   512  		::GetShortPathName( to, shortTo, sizeof(shortTo) );
   513  		kiPath inifile( kiPath::Win ); inifile+="wininit.ini";
   514  
   515  		char buf[30000];
   516  		::GetPrivateProfileSection( "Rename", buf, 30000, inifile ); 
   517  		char* p = buf; 
   518  		while(*p)while(*p++);
   519  
   520  		::lstrcpy( p, "NUL=" );
   521  		::lstrcat( p, shortTo );
   522  		while(*p++);
   523  		*p++='\r',*p++='\n'; 
   524  		::lstrcpy( p, shortTo );
   525  		::lstrcat( p, "=" );
   526  		::lstrcat( p, shortFrom );
   527  		while(*p++);
   528  		*p='\0'; 
   529  
   530  		::WritePrivateProfileSection( "Rename", buf, inifile );
   531  
   532  		// 確実に書き込む
   533  		::WritePrivateProfileString( NULL, NULL, NULL, inifile );
   534  		return true;
   535  	}
   536  };
   537  
   538  void kilib_create_new_app()
   539  {
   540  	new CKInstApp;
   541  }