应用程序类对象实例初始操作的分析

ATT&CK v10版本战术介绍-初始访问 在前几期文章中我们介绍了ATT&CK中侦察及资源开发战术理论知识及实战研究,通过实战场景验证行之有效的检测规则、防御措施,本期我们为大家介绍ATT&CK 14项战术中初始访问战术,后续会陆续介绍其他战术内容,敬请关注。 阅读详情
文档视图结构中,应用程序类对象实例初始操作的分析

BOOL CSomeApp::InitInstance()
{
Enable3dControls();
LoadStdProfileSettings();
AddDocTemplate(...) ...... ShowWindow(...);
m_pMainWnd->DragAcceptFiles();
EnableShellOpen();
RegisterShellFileTypes(TRUE);
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;
return TRUE;
}

  下面对InitInstance中的一些操作及其流程进行分析

  1.常规设置

  如:
  SetDialogBkColor()
  Enable3dControls()..
  (如果设置了后者,则前者就不必要了)
  SetRegistryKey(指定注册表键,替代INI文件)

  2.LoadStdProfileSettings()

  LoadStdProfileSettings 完成最近文件列表功能,在菜单中添加最近的文件作为菜单项过程:

  建立一个CRecentFileList从注册表或INI文件中读入最近文件列表;

  当菜单建立时,文件列表将添加到菜单中ID_FILE_MRU_FILE*位置;

  3.m_pMainWnd->DragAcceptFiles()接收文件拖入

  使主窗口能响应文件拖入消息WM_DROPFILES;

  当有文件拖入时, 框架窗口的OnDropFiles将处理,以打开这些文件。

void CFrameWnd::OnDropFiles(HDROP hDropInfo)
{
SetActiveWindow(); // activate us first !
UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);

CWinApp* pApp = AfxGetApp();
ASSERT(pApp != NULL);
for (UINT iFile = 0; iFile < nFiles; iFile++)
{
TCHAR szFileName[_MAX_PATH];
::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
//应用程序打开拖入文档
pApp->OpenDocumentFile(szFileName);
}
::DragFinish(hDropInfo);
}

  4.EnableShellOpen();

  为在Windows中使用外壳操作打开文件作准备

void CWinApp::EnableShellOpen()
{
ASSERT(m_atomApp == NULL && m_atomSystemTopic == NULL); // do once

m_atomApp = ::GlobalAddAtom(m_pszExeName);
m_atomSystemTopic = ::GlobalAddAtom(_T("system"));
}

  5.RegisterShellFileTypes

  向系统注册文件类型,以使用外壳操作。

  将调用m_pDocManager->RegisterShellFileTypes()

  (CDocManager::RegisterShellFileTypes()源码附后)

  要点:将所有文档模板的类型,外壳命令等写入注册表

  包括type ID、shell/open/ddeexec = [open("%1")]、shell/print/ddeexec = [print("%1")]、shell/printto/ddeexec = [printto("%1","%2","%3","%4")]等等。

  6.ProcessShellCommand

  处理命令行、外壳命令等

CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;

  ①先建立CCommandLineInfo对象

  ②再将命令行参数等分解到cmdInfo;

void CWinApp::ParseCommandLine(CCommandLineInfo& rCmdInfo)
{
for (int i = 1; i < __argc; i++)
{
LPCTSTR pszParam = __targv[i];
BOOL bFlag = FALSE;
BOOL bLast = ((i + 1) == __argc);
if (pszParam[0] == '-' || pszParam[0] == '/')
{
// remove flag specifier
bFlag = TRUE;
++pszParam;
}
rCmdInfo.ParseParam(pszParam, bFlag, bLast);
}
}

  通过该操作,命令行被转化为cmdInfo;

  命令行的意义
  app (新建文件)
  app filename(打开文件)
  app /p filename(打印文件)
  app /pt filename printer driver port (用指定的打印机打印)
  app /dde (运行并接收DDE命令)
  app /Automation (启动为自动化服务器)
  app /Embedding (内嵌式运行)

  ParseCommandLine后,操作类型(打开、新建、打印..)存放在m_nShellCommand; 文件名存放在m_strFileName......

  ③处理命令

  主要操作:

switch (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
OnFileNew()....
break;
case CCommandLineInfo::FileOpen:
OpenDocumentFile(rCmdInfo.m_strFileName)....
break;
case CCommandLineInfo::FilePrint:
case CCommandLineInfo::FilePrintTo:
打开文件,发送ID_FILE_PRINT_DIRECT,返回FALSE值(导致立即程序退出)
case CCommandLineInfo::FileDDE:
m_nCmdShow = SW_HIDE;(程序被运行,但被隐藏,m_nCmdShow作为ShowWindow的参数)
等等操作
}

  附一:CDocManager::RegisterShellFileTypes

void CDocManager::RegisterShellFileTypes(BOOL bCompat)
{
ASSERT(!m_templateList.IsEmpty()); // must have some doc templates

CString strPathName, strTemp;

AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);

POSITION pos = m_templateList.GetHeadPosition();
//针对每种文档模板进行注册
for (int nTemplateIndex = 1; pos != NULL; nTemplateIndex++)
{
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);

CString strOpenCommandLine = strPathName;
CString strPrintCommandLine = strPathName;
CString strPrintToCommandLine = strPathName;
CString strDefaultIconCommandLine = strPathName;

if (bCompat)
{
CString strIconIndex;
HICON hIcon = ::ExtractIcon(AfxGetInstanceHandle(), strPathName, nTemplateIndex);
if (hIcon != NULL)
{
strIconIndex.Format(_afxIconIndexFmt, nTemplateIndex);
DestroyIcon(hIcon);
}
else
{
strIconIndex.Format(_afxIconIndexFmt, DEFAULT_ICON_INDEX);
}
strDefaultIconCommandLine += strIconIndex;
}

CString strFilterExt, strFileTypeId, strFileTypeName;
if (pTemplate->GetDocString(strFileTypeId,
CDocTemplate::regFileTypeId) && !strFileTypeId.IsEmpty())
{
// enough info to register it
if (!pTemplate->GetDocString(strFileTypeName,
CDocTemplate::regFileTypeName))
strFileTypeName = strFileTypeId; // use id name

ASSERT(strFileTypeId.Find(' ') == -1); // no spaces allowed

// first register the type ID of our server
if (!_AfxSetRegKey(strFileTypeId, strFileTypeName))
continue; // just skip it

if (bCompat)
{
// path/DefaultIcon = path,1
strTemp.Format(_afxDefaultIconFmt, (LPCTSTR)strFileTypeId);
if (!_AfxSetRegKey(strTemp, strDefaultIconCommandLine))
continue; // just skip it
}

// If MDI Application
if (!pTemplate->GetDocString(strTemp, CDocTemplate::windowTitle) ||
strTemp.IsEmpty())
{
// path/shell/open/ddeexec = [open("%1")]
strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxDDEExec);
if (!_AfxSetRegKey(strTemp, _afxDDEOpen))
continue; // just skip it

if (bCompat)
{
// path/shell/print/ddeexec = [print("%1")]
strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxDDEExec);
if (!_AfxSetRegKey(strTemp, _afxDDEPrint))
continue; // just skip it

// path/shell/printto/ddeexec = [printto("%1","%2","%3","%4")]
strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxDDEExec);
if (!_AfxSetRegKey(strTemp, _afxDDEPrintTo))
continue; // just skip it

// path/shell/open/command = path /dde
// path/shell/print/command = path /dde
// path/shell/printto/command = path /dde
strOpenCommandLine += _afxDDEArg;
strPrintCommandLine += _afxDDEArg;
strPrintToCommandLine += _afxDDEArg;
}
else
{
strOpenCommandLine += _afxOpenArg;
}
}
else
{
// path/shell/open/command = path filename
// path/shell/print/command = path /p filename
// path/shell/printto/command = path /pt filename printer driver port
strOpenCommandLine += _afxOpenArg;
if (bCompat)
{
strPrintCommandLine += _afxPrintArg;
strPrintToCommandLine += _afxPrintToArg;
}
}

// path/shell/open/command = path filename
strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxCommand);
if (!_AfxSetRegKey(strTemp, strOpenCommandLine))
continue; // just skip it

if (bCompat)
{
// path/shell/print/command = path /p filename
strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxCommand);
if (!_AfxSetRegKey(strTemp, strPrintCommandLine))
continue; // just skip it

// path/shell/printto/command = path /pt filename printer driver port
strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxCommand);
if (!_AfxSetRegKey(strTemp, strPrintToCommandLine))
continue; // just skip it
}

pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt);
if (!strFilterExt.IsEmpty())
{
ASSERT(strFilterExt[0] == '.');

LONG lSize = _MAX_PATH * 2;
LONG lResult = ::RegQueryValue(HKEY_CLASSES_ROOT, strFilterExt,
strTemp.GetBuffer(lSize), &lSize);
strTemp.ReleaseBuffer();

if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() ||
strTemp == strFileTypeId)
{
// no association for that suffix
if (!_AfxSetRegKey(strFilterExt, strFileTypeId))
continue;

if (bCompat)
{
strTemp.Format(_afxShellNewFmt, (LPCTSTR)strFilterExt);
(void)_AfxSetRegKey(strTemp, _afxShellNewValue, _afxShellNewValueName);
}
}
}
}
}
}

  附二:CWinApp::ProcessShellCommand

BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)
{
BOOL bResult = TRUE;
switch (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))
OnFileNew();
if (m_pMainWnd == NULL)
bResult = FALSE;
break;

// If we've been asked to open a file, call OpenDocumentFile()

case CCommandLineInfo::FileOpen:
if (!OpenDocumentFile(rCmdInfo.m_strFileName))
bResult = FALSE;
break;

// If the user wanted to print, hide our main window and
// fire a message to ourselves to start the printing

case CCommandLineInfo::FilePrintTo:
case CCommandLineInfo::FilePrint:
m_nCmdShow = SW_HIDE;
ASSERT(m_pCmdInfo == NULL);
OpenDocumentFile(rCmdInfo.m_strFileName);
m_pCmdInfo = &rCmdInfo;
m_pMainWnd->SendMessage(WM_COMMAND, ID_FILE_PRINT_DIRECT);
m_pCmdInfo = NULL;
bResult = FALSE;
break;

// If we're doing DDE, hide ourselves

case CCommandLineInfo::FileDDE:
m_pCmdInfo = (CCommandLineInfo*)m_nCmdShow;
m_nCmdShow = SW_HIDE;
break;

// If we've been asked to unregister, unregister and then terminate
case CCommandLineInfo::AppUnregister:
{
UnregisterShellFileTypes();
BOOL bUnregistered = Unregister();

// if you specify /EMBEDDED, we won't make an success/failure box
// this use of /EMBEDDED is not related to OLE

if (!rCmdInfo.m_bRunEmbedded)
{
if (bUnregistered)
AfxMessageBox(AFX_IDP_UNREG_DONE);
else
AfxMessageBox(AFX_IDP_UNREG_FAILURE);
}
bResult = FALSE; // that's all we do

// If nobody is using it already, we can use it.
// We'll flag that we're unregistering and not save our state
// on the way out. This new object gets deleted by the
// app object destructor.

if (m_pCmdInfo == NULL)
{
m_pCmdInfo = new CCommandLineInfo;
m_pCmdInfo->m_nShellCommand = CCommandLineInfo::AppUnregister;
}
}
break;
}
return bResult;
}

 
初始标记和重新标记为何需要STW(Stop-The-World) —— 深入解析CMS垃圾回收的原理 在Java中,垃圾回收器负责自动管理内存,回收不再使用的对象。这种机制极大地简化了开发者的工作,但为了实现高效的垃圾回收,垃圾回收器必须面对如何在回收内存的同时,最大限度地减少对应用程序运行的影响这一挑战。垃圾回收的基本原理是:通过标记那些不可达的对象,然后将其回收。这一过程通常分为标记和清除标记阶段:识别哪些对象是存活的,哪些对象是可以被回收的。清除阶段:释放那些已标记为不可达的对象所占用的内存空间。 阅读详情

相关推荐

VB WinSock 实例:完整的聊天应用程序设计

在现代网络应用中,VB(Visual Basic)语言虽然不如之前那样风靡,但其WinSock组件仍是一个强大的工具,用于实现基于Windows平台的网络通信功能。VB WinSock组件基于Windows Sockets API,它允许VB应用程序连接到网络,发送和接收数据。本章我们将介绍WinSock组件的基础知识,为后续章节深入探讨VB网络编程和TCP/IP协议的应用打下基础。

weixin_28922227的博客 598

windows应用(vc++2022)MFC基础到实战(3)-基础(3)

框架会将这些文件名存储在与您的项目同名的注册表或 .ini 文件中,并在您的应用程序启动时从文件中读取它们。如果你的应用程序是 MDI 应用程序,并且你为该应用程序创建的文件指定了扩展名,MFC 应用程序向导会将对 CWinApp 的 RegisterShellFileTypes 和 EnableShellOpen 成员函数的调用添加到它为你编写的 InitInstance 替代。对于任何给定的命令,调用的代码可能是你的,也可能是框架的。创建的类和文件名称基于你在 MFC 应用程序向导中提供的项目名称。

The research on computer technolog 1881

VC中建立程序的关联文件

当我们双击一个txt文件的图标时,系统就会用记事本打开该文件,这就是程序的关联。那我们自己编写的程序如何建立关联文件呢?<br /><br />第一步:设置自己程序关联的文件类型<br />打开资源下的String Table,找到其中的IDR_MAINFRAME,双击该项,修改它的值,设它原来的值是:<br />TextEditor/n/nTextEd/n/n/nTextEditor.Document/nTextEd Document<br />若你关联的文件类型为.txt,则把它改为:<br />Tex

liushuiwu_001的专栏 1079

文件操作的一些知识点

一.基本文件操作char ch[5]="lisi";const char*pStr=ch;            指向常量的指针char const *pStr=ch  和上面的效果是一样的*pStr=w;//ERROR  指针的内容不可变pStr="sd";//RIGHT  指针的值可以修改char * const pStr=ch;          指向指针的常量    *pStr

wangbaojun52024029的专栏 562

CWinApp 应用程序

CWinApp 应用程序类共63个成员(由Cobject-CCmdTarget-CWinThread派生)#include CWinApp类是你派生Windows应用程序对象的基类。应用程序对象提供初始化你的应用程序(及其每个实例)的成员函数,并运行该应用程序。每个使用MFC类的应用程序只能包含一个CWinApp派生类对象。当Windows调用由MFC库提供的WinMain函数时,其它C++全局对

blueblood_jing的专栏 4315

CWinApp类的初步认识

CWinApp类的初步认识,报错图标、光标资源管理,explicit:语法,工程名

weixin_43411789的博客 1098

MFC应用程序类对象实例初始操作分析

 首先看看InitInstance()函数:BOOL CSomeApp::InitInstance()...{Enable3dControls();LoadStdProfileSettings();AddDocTemplate(...) ...... ShowWindow(...);m_pMainWnd->DragAcceptFiles();EnableShellOpen();Regi

yuyazhang的专栏 1361

ESP32的应用程序启动与PSRAM初始分析

测试记录 PSRAM的启动,占用了MUC从上电到进如app_main的大部分时间。 在低功耗产品中,PSARM的待机电流并不小,以乐鑫的PSARM手册来看,待机电流200uA 涉及两点 PSRAM的默认上电启动,影响进入应用程序的速度(需要500+ms,初始化+TSET) PSRAM如果长期待机,功耗不低,如果电源受控,启动过程需加电源IO控制 所以PSRAM的上电时机,最好由MCU应用程序控制,而ESP-IDF的默认初始化PSRAM却在BOOT之后,在app_main之前。 分析PSRAM默认的启动

DJZ1992的博客 6634

如何优化 Vue 应用程序以提高初始加载性能?

通过实施上述策略中的一个或多个,你可以显著改善 Vue 应用程序初始加载时间。选择最适合你项目需求的方法,并不断测试和迭代以找到最佳组合。优化 Vue 应用程序初始加载性能可以通过多种方法实现。

Pmyx_wyh的博客 749

【WPF.NET开发】优化性能:应用程序启动时间

启动 WPF 应用程序所需的时间可能存在极大差异。本主题介绍用于减少 Windows Presentation Foundation (WPF) 应用程序假设启动时间和实际启动时间的各种技巧。

Coding life, Coding world, Coding feature. 2739

wp之动态初始屏幕

使用过windows phone版QQ的开发者,对于QQ的动态初始屏幕肯定都很关注是如何实现的,关于这个问题首先必须要了解Windows Phone的应用程序生命周期,对于相关的文章博客园内已经有大牛给出了详细的分析,这里就不多说了,详细请看Terry 龙的windows phone7不温不火学习系列文章。   Windows Phone初始屏幕可以通过替换根目录下的SplashScreen

In me the tiger sniffs the rose 811

Java的HashMap初始容量设置技巧?

本文探讨了Java中HashMap初始容量的设置技巧。HashMap作为常用的键值对存储结构,其初始容量直接影响程序性能和内存使用。文章提出了四点设置建议:明确应用需求和数据规模、选择合适的哈希算法、参考经验值(几十到几百KB)、结合具体场景调整。特别强调了要避免容量过大或过小,并考虑并*况下的线程安全问题。通过合理设置初始容量,开发者可以在程序性能和内存使用之间取得最佳平衡。

searchboy2025的博客 67

RimSort项目中的RimWorld初始配置文件处理机制分析

RimSort是一款为RimWorld游戏设计的模组管理工具,它能够帮助玩家更高效地管理和组织游戏模组。在实际使用过程中,开发者发现了一个与RimWorld初始配置文件相关的边界条件问题,值得深入探讨。 ## 问题本质 当用户首次安装RimWorld游戏后,游戏会生成一个初始的ModsConfig.xml配置文件。这个初始文件仅包含基本的XML结构,没有包含任何实际的模组信息,包括核心(Cor...

gitblog_07056的博客 977

ATT&CK v10版本战术介绍:初始访问的九种技术

初始访问是攻击者使用各种方法在网络中获得攻击入口的技术,包括网络钓鱼和利用公司对外的Web网站的漏洞。通过初始访问获得的攻击入口可能允许攻击者继续进行深入的渗透,例如获取有效的帐户信息和对外提供的远程服务,或者通过多次尝试口令锁住用户账户限制用户使用等。初始访问包括9种技术,下面逐一介绍下这九种技术。

2201_75735270的博客 553

详解查看JVM初始和最终的参数

详解查看JVM初始和最终的参数

FuncPlotCalc 584

初始RAG

大型语言模型(LLMs)已经成为我们生活和工作的一部分,它们以惊人的多功能性和智能化改变了我们与信息的互动方式。然而,尽管它们的能力令人印象深刻,但它们也存在时效性(可能会产生幻觉问题)、准确性、算力效率、隐私保护方面还面临着一些挑战和局限性。在现实世界的应用中,数据需要不断更新以反映最新的发展,生成的内容必须是透明可追溯的,以便控制成本并保护数据隐私。因此,简单依赖于这些 “黑盒” 模型是不够的,我们需要更精细的解决方案来满足这些复杂的需求。

weixin_41962319的博客 1970
上一篇: 一般线性链表类的C++实现
下一篇: MFC基本操作
tigercopy
博客等级 码龄20年 15粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值