www.gusucode.com > VC2003开发的文件捆绑机-源码程序 > VC2003开发的文件捆绑机-源码程序\code\Binder\BinderDlg.cpp
//Download by http://www.NewXing.com // BinderDlg.cpp : 实现文件 // #include "stdafx.h" #include "Binder.h" #include "BinderDlg.h" #include ".\binderdlg.h" #include "IconDlg.h" #include "AESEncryption.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #include "zip/zip.h" // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialog { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CBinderDlg 对话框 CBinderDlg::CBinderDlg(CWnd* pParent /*=NULL*/) : CDialog(CBinderDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_IconFile = ""; strIcoIndex = new WCHAR[20]; memset(strIcoIndex, 0, 20); } void CBinderDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_List); DDX_Control(pDX, IDC_PROGRESS1, m_pro); DDX_Control(pDX, IDC_STATIC_LINK1, m_Link1); DDX_Control(pDX, IDC_CHK_DELETE, m_ChkDelete); } BEGIN_MESSAGE_MAP(CBinderDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BTN_ADD, OnBnClickedBtnAdd) ON_BN_CLICKED(IDC_BTN_DELETE, OnBnClickedBtnDelete) ON_BN_CLICKED(IDC_BTN_CLEAR, OnBnClickedBtnClear) ON_BN_CLICKED(IDC_BTN_EXECUTE, OnBnClickedBtnExecute) ON_BN_CLICKED(IDC_BTN_QUIT, OnBnClickedBtnQuit) ON_BN_CLICKED(IDC_BTN_ABOUT, OnBnClickedBtnAbout) ON_BN_CLICKED(IDC_BTN_ICON, OnBnClickedBtnIcon) END_MESSAGE_MAP() // CBinderDlg 消息处理程序 BOOL CBinderDlg::OnInitDialog() { CDialog::OnInitDialog(); // 将\“关于...\”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 this->InitListCtrl(); //初始化列表结构 m_Link1.SetURL(L"http://www.hacker.com.cn/"); return TRUE; // 除非设置了控件的焦点,否则返回 TRUE } void CBinderDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CBinderDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标显示。 HCURSOR CBinderDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } // 初始化列表结构 void CBinderDlg::InitListCtrl(void) { m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP); m_List.InsertColumn(0,A("文件名"),LVCFMT_LEFT,50); m_List.InsertColumn(1,A("大小(KB)"),LVCFMT_LEFT,50); m_List.InsertColumn(2,A("位置"),LVCFMT_LEFT,150); } //加入文件 void CBinderDlg::OnBnClickedBtnAdd() { int Count = 0; CString FileSize; CFile fe; long f_Size = 0; CFileDialog m_fd(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,A("推荐捆绑文件(*.exe,*.doc,*.xls,*.bat,*.url)|*.exe;*.doc;*.xls;*.bat;*.url|所有文件(*.*)|*.*||"),this,0); if (IDOK == m_fd.DoModal()) { Count = m_List.GetItemCount(); m_List.InsertItem(Count,m_fd.GetFileName(),0); //这里为了方便用 CFile 来获得文件名并显示 fe.Open(m_fd.GetPathName(),CFile::shareDenyRead); f_Size = (long)fe.GetLength(); FileSize.Format(A("%ld"),f_Size); fe.Close(); m_List.SetItemText(Count,1,FileSize); //显示文件位置 m_List.SetItemText(Count,2,m_fd.GetPathName()); } } //删除单个条目 void CBinderDlg::OnBnClickedBtnDelete() { int n = 0; //获得到选中的项的索引 POSITION nIndex = m_List.GetFirstSelectedItemPosition(); n = m_List.GetNextSelectedItem(nIndex); //删除 m_List.DeleteItem(n); } //清空列表 void CBinderDlg::OnBnClickedBtnClear() { int ret = MessageBox(A("您确定要删除全部的文件?"),A("提示"),MB_YESNO|MB_ICONQUESTION); if (IDYES == ret) m_List.DeleteAllItems(); } //执行捆绑 void CBinderDlg::OnBnClickedBtnExecute() { CString str_FilePath; CString str_FileName; void* pData = NULL; DWORD nSize = 0; DWORD n_AllSize = 0; int IsCheck = 0; char Info[4] = {0}; //如果列表为空,则警告并退出 if (0 == m_List.GetItemCount()) { MessageBox(A("请至少选择一个文件来捆绑"),A("错误"),MB_OK|MB_ICONERROR); return; } for (int i=0; i< m_List.GetItemCount(); i++) { //计算出所有文件加起来的大小 n_AllSize += _ttoi(m_List.GetItemText(i,1).GetBuffer(m_List.GetItemText(i,1).GetLength())); } BeginWaitCursor(); //初始化进度条 m_pro.SetRange(0,m_List.GetItemCount()+2); m_pro.SetStep(1); m_pro.SetPos(0); //设置提示文字 SetDlgItemText(IDC_INFO,A("创建压缩数据...")); //创建压缩文件。 //这里是内存创建,所以要指定一个足够大小的缓冲区,所以上面我计算所有文件加起来的大小 HZIP hZip = CreateZip(0,n_AllSize,NULL); m_pro.StepIt(); //走一步 //设置提示文字 SetDlgItemText(IDC_INFO,A("压缩数据中...")); for (int i=0; i< m_List.GetItemCount(); i++) { //循环得到所有文件的文件名和位置 str_FileName = m_List.GetItemText(i,0); str_FilePath = m_List.GetItemText(i,2); //调用压缩函数压缩 ZipAdd(hZip,str_FileName.GetBuffer(str_FileName.GetLength()),str_FilePath.GetBuffer(str_FilePath.GetLength())); //每压缩一个走一步 m_pro.StepIt(); } //从内存获得到得到的ZIP压缩包数据 ZipGetMemory(hZip,&pData,&nSize); /*ZIP文件格式中头两个字符分别为 PK 这样如果直接捆绑会被 WinRAR 认为成他的自解压格式文件,这个也是巧合发现的 所以我这里修改头两个字节为其他数据,但是考虑到可以用其保存配置信息,所以我用第一位做是否自删除的标志位*/ if (m_ChkDelete.GetCheck()) Info[0] = 0x01; //修改头两个字节 memcpy(pData,Info,4); CAESEncryption aes; DWORD eSize = 0; aes.Encryption(NULL, nSize, NULL, &eSize); char* lpData = new char[eSize]; memset(lpData, 0, eSize); aes.Encryption(pData, nSize, lpData, &eSize); //解压并替换资源 this->ReplaceResource(lpData,eSize); //关闭ZIP文件句柄 CloseZip(hZip); //进度条走到完成 m_pro.SetPos(m_List.GetItemCount()+2); EndWaitCursor(); MessageBox(A("捆绑完成!"),A("提示"),MB_OK|MB_ICONINFORMATION); SetDlgItemText(IDC_INFO,A("完成!")); } // 替换资源 bool CBinderDlg::ReplaceResource(void* ZipData,DWORD DataSize) { DWORD nByteWrite = 0; HRSRC hResInfo = FindResource(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_STUDIO),A("STUDIO")); if (NULL == hResInfo) return false; HGLOBAL hRes = LoadResource(AfxGetApp()->m_hInstance,hResInfo); if (NULL == hRes) return false; //找到并锁定资源 LPVOID pData = LockResource(hRes); //获得资源大小 DWORD nSize = SizeofResource(AfxGetApp()->m_hInstance,hResInfo); CFileDialog m_fd(FALSE,A(".exe"),NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,A("可执行文件(*.exe)|*.exe||"),this,0); if (IDOK != m_fd.DoModal()) //弹出保存对话框 return false; //将资源释放出来 HANDLE hFile = CreateFile(m_fd.GetPathName(),GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); WriteFile(hFile,pData,nSize,&nByteWrite,NULL); CloseHandle(hFile); //走一步 m_pro.StepIt(); SetDlgItemText(IDC_INFO,A("写入数据中...")); //替换资源 AAAA 为压缩好的ZIP数据 HANDLE hHandle = BeginUpdateResource(m_fd.GetPathName(),TRUE); UpdateResource(hHandle,A("AAAA"),MAKEINTRESOURCE(130),0,ZipData,DataSize); EndUpdateResource(hHandle,FALSE); //判断是否设置更改图标 if (m_IconFile.IsEmpty() == FALSE) { //获得到图标文件的扩展名 CString FileExt = m_IconFile.Mid(m_IconFile.GetLength()-3,3); FileExt.MakeLower(); //如果是 ICO 图标文件 if (FileExt == L"ico") { //调用通过 ICO 修改图标的函数 this->ChangeExeIcon(m_fd.GetPathName()); } //如果是 PE 文件 if (FileExt == L"exe" || FileExt == L"dll") { //调用通过 PE 文件修改图标的函数 this->ChangeExeIconFromExeDll(m_fd.GetPathName()); } } return true; } //退出 void CBinderDlg::OnBnClickedBtnQuit() { OnOK(); } //关于 void CBinderDlg::OnBnClickedBtnAbout() { CAboutDlg dlg; dlg.DoModal(); } //修改图标按钮 void CBinderDlg::OnBnClickedBtnIcon() { HICON hIcon = NULL; hIcon = BrowserIcon(); CStatic* m_pIcon = (CStatic*)GetDlgItem(IDC_STC_ICON); m_pIcon->SetIcon(hIcon); //调试用 // this->ChangeExeIcon(L"e:\\1.exe"); } // 通过 ICO 文件修改图标 bool CBinderDlg::ChangeExeIcon(CString ExeFile) { /* ICO 文件大致文件格式如下 ------------- * 图标头 ------------- * 图标索引一 ------------- * 图标索引二 ------------- * ....... ------------- * 图标索引N ------------- * 数据 ------------- */ ICONDIR stID; ICONDIRENTRY* lpIDE = NULL; GRPICONDIRENTRY* lpGID = NULL; HANDLE hFile = NULL; HANDLE hUpdate = NULL; DWORD nByteRead = 0; BOOL ret = 0; LPBYTE lpData = NULL; //打开 ico 文件 hFile = CreateFile(m_IconFile, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) goto error_label; //读取图标头 ZeroMemory(&stID, sizeof(ICONDIR)); ret = ReadFile(hFile, &stID, sizeof(ICONDIR), &nByteRead, NULL); if (ret == FALSE) goto error_label; //读取图标目录 lpIDE = (ICONDIRENTRY*)new BYTE[sizeof(ICONDIRENTRY) * stID.idCount]; ZeroMemory(lpIDE, sizeof(ICONDIRENTRY) * stID.idCount); ret = ReadFile(hFile, lpIDE, sizeof(ICONDIRENTRY) * stID.idCount, &nByteRead, NULL); if (ret == FALSE) goto error_label; //图标组目录 lpGID = (GRPICONDIRENTRY*)new BYTE[sizeof(GRPICONDIRENTRY) * stID.idCount]; ZeroMemory(lpGID, sizeof(GRPICONDIRENTRY) * stID.idCount); for (int i = 0; i < stID.idCount; i++) { //根据文件偏移读取出图标数据 lpData = new BYTE[lpIDE[i].dwBytesInRes]; ZeroMemory(lpData, lpIDE[i].dwBytesInRes); SetFilePointer(hFile, lpIDE[i].dwImageOffset, NULL, FILE_BEGIN); ret = ReadFile(hFile, lpData, lpIDE[i].dwBytesInRes, &nByteRead, NULL); if (FALSE == ret) goto error_label; //替换图标数据资源 hUpdate = BeginUpdateResource(ExeFile, false); ret = UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(i+1), 2052, (LPVOID)lpData, lpIDE[i].dwBytesInRes); EndUpdateResource(hUpdate, false); if (FALSE == ret) continue; //设置图标组目录 memcpy(&lpGID[i], &lpIDE[i], 12); lpGID[i].nID = i+1; DELPOINTER(lpData); } DELPOINTER(lpIDE); CloseHandle(hFile); //申请内存作为图标组数据 lpData = new BYTE[sizeof(ICONDIR) + stID.idCount * sizeof(GRPICONDIRENTRY)]; ZeroMemory(lpData, sizeof(ICONDIR) + stID.idCount * sizeof(GRPICONDIRENTRY)); //拷贝图标头 memcpy(lpData, &stID, sizeof(ICONDIR)); //拷贝图标组目录 memcpy(lpData+sizeof(ICONDIR), lpGID,sizeof(GRPICONDIRENTRY) * stID.idCount); DELPOINTER(lpGID); //更新图标组 hUpdate = BeginUpdateResource(ExeFile, false); ret = UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(2), 2052, (LPVOID)lpData, sizeof(GRPICONDIRENTRY) * stID.idCount + sizeof(ICONDIR)); EndUpdateResource(hUpdate, false); DELPOINTER(lpData); return true; error_label: CloseHandle(hFile); return false; } // 浏览图标 HICON CBinderDlg::BrowserIcon() { CIconDlg mDlg; CString FileExt; HINSTANCE hLibrary = NULL; HICON hIcon = NULL; HRSRC hRsrc = NULL; HGLOBAL hGlobal = NULL; LPVOID lpRes = NULL; int nID; //浏览图标对话框 if (IDOK == mDlg.DoModal()) { m_IconFile = mDlg.FilePath; //获得到文件位置 memset(strIcoIndex, 0, 20); wcscpy(strIcoIndex, mDlg.strIcoIndex.GetBuffer(0)); //资源名如果是数字 if (strIcoIndex[0] > 47 && strIcoIndex[0] < 58) { nIcoIndex = (LPTSTR)_wtoi(strIcoIndex); } else { nIcoIndex = strIcoIndex; } FileExt = m_IconFile.Mid(m_IconFile.GetLength()-3,3); //文件扩展 FileExt.MakeLower(); //如果是PE文件 if (FileExt == L"exe" || FileExt == L"dll") { //获得到图标的数据 hLibrary = LoadLibraryEx( m_IconFile, NULL, LOAD_LIBRARY_AS_DATAFILE ); if (hLibrary == NULL) { MessageBox( L"文件载入错误,必须是WIN32的文件!", L"错误", MB_OK | MB_ICONERROR); return HICON(); } if( (hRsrc = FindResource( hLibrary, nIcoIndex, RT_GROUP_ICON )) == NULL ) return NULL; if( (hGlobal = LoadResource( hLibrary, hRsrc )) == NULL ) return NULL; if( (lpRes = LockResource(hGlobal)) == NULL ) return NULL; nID = LookupIconIdFromDirectory((LPBYTE)lpRes, TRUE ); if( (hRsrc = FindResource( hLibrary, MAKEINTRESOURCE(nID), RT_ICON )) == NULL ) return NULL; if( (hGlobal = LoadResource( hLibrary, hRsrc )) == NULL ) return NULL; if( (lpRes = LockResource(hGlobal)) == NULL ) return NULL; //通过数据转换为 HICON 句柄 hIcon = CreateIconFromResource((LPBYTE) lpRes, SizeofResource(hLibrary,hRsrc), TRUE, 0x00030000 ); return hIcon; } //如果是 ico 文件 if (FileExt == L"ico") { //获得到 HICON 句柄 return ExtractIcon(AfxGetResourceHandle(), m_IconFile, (DWORD)nIcoIndex); } } else { //如果点的是取消 m_IconFile = ""; memset(strIcoIndex, 0, 20); nIcoIndex = NULL; //显示默认图标 return LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1)); } } //通过PE文件提取资源并替换 void CBinderDlg::ChangeExeIconFromExeDll(CString ExeFile) { HINSTANCE hLibrary = NULL; HRSRC hRsrc = NULL; HGLOBAL hGlobal = NULL; LPVOID lpRes = NULL; HANDLE hUpdate = NULL; BOOL ret = FALSE; ICONDIR IconDir; //加载 PE 文件找到图标组资源 hLibrary = LoadLibraryEx( m_IconFile, NULL, LOAD_LIBRARY_AS_DATAFILE ); if (hLibrary == NULL) { MessageBox(L"装入文件时出错 - 请选择一个WIN32的DLL或EXE文件!", L"错误", MB_OK | MB_ICONERROR ); return; } if( (hRsrc = FindResource( hLibrary, nIcoIndex, RT_GROUP_ICON )) == NULL ) { FreeLibrary( hLibrary ); return; } if( (hGlobal = LoadResource( hLibrary, hRsrc )) == NULL ) { FreeLibrary( hLibrary ); return; } if( (lpRes = LockResource(hGlobal)) == NULL ) { FreeLibrary( hLibrary ); return; } //设置指针方便操作数据 memset(&IconDir, 0, sizeof(ICONDIR)); //提取图标头 memcpy(&IconDir, (LPBYTE)lpRes, sizeof(ICONDIR)); //分配索引表 GRPICONDIRENTRY* pGID = (GRPICONDIRENTRY*)new BYTE[sizeof(GRPICONDIRENTRY) * IconDir.idCount]; //拷贝索引表 memcpy(pGID, (LPBYTE)lpRes+sizeof(ICONDIR), sizeof(GRPICONDIRENTRY) * IconDir.idCount); //解锁释放资源 UnlockResource(hGlobal); FreeResource(hGlobal); //根据图标数量 for (int i=0; i < IconDir.idCount; i++) { //根据 nID 获得到图标数据 if( (hRsrc = FindResource( hLibrary, MAKEINTRESOURCE(pGID[i].nID), RT_ICON )) == NULL ) return; if( (hGlobal = LoadResource( hLibrary, hRsrc )) == NULL ) return; if( (lpRes = LockResource(hGlobal)) == NULL ) return; //设置 nID 从1开始 pGID[i].nID = i+1; //更新图标 hUpdate = BeginUpdateResource(ExeFile, false); ret = UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(i+1), 2052, (LPVOID)lpRes, pGID[i].dwBytesInRes); EndUpdateResource(hUpdate, false); //释放图标数据资源 UnlockResource(hGlobal); FreeResource(hGlobal); } //图标组资源 LPBYTE pData = (LPBYTE)new BYTE[sizeof(GRPICONDIRENTRY) * IconDir.idCount + sizeof(ICONDIR)]; memset(pData, 0, sizeof(GRPICONDIRENTRY) * IconDir.idCount + sizeof(ICONDIR)); memcpy(pData, &IconDir, sizeof(ICONDIR)); memcpy(pData+sizeof(ICONDIR), pGID, sizeof(GRPICONDIRENTRY) * IconDir.idCount); //替换目标文件的索引表 hUpdate = BeginUpdateResource(ExeFile, false); ret = UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(2), 2052, (LPVOID)pData, sizeof(GRPICONDIRENTRY) * IconDir.idCount + sizeof(ICONDIR)); EndUpdateResource(hUpdate, false); DELPOINTER(pGID); DELPOINTER(pData); }