Reactos当中的Rundll的实现

前端之家收集整理的这篇文章主要介绍了Reactos当中的Rundll的实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
RunDll32.exe是微软系统自带的一个小程序功能是加载系统中的dll,并且作为程序运行。控制面板里面有很多选项都可以由Rundll.exe进行加载运行。
现在,我们根据reactos当中的源代码对其实现进行分析。


首先看rundll32.exe调用进行调用函数原型(源文件当中对函数的UNICODE和ASCII进行了区分)。
typedef int (WINAPI *DllWinMainW)(
  HWND hWnd,HINSTANCE hInstance,LPWSTR lpwCmdLine,int nCmdShow
);

整个函数当中的最主要部分是CommandLineToArgv,通过函数名称可以知道这个函数就是对输入的命令行进行分析,并且分解成为相应的参数。

下面对其进行分步分析(完整的代码在我的CSDN资源里面)

第一步很简单,就是验证函数参数的有效性。

第二步,计算命令行当中参数的个数。因为有一个参数可能会被当做参数对DllWinMainW进行调用。所以参数数目可能是三个可能是四个。

// 计算参数的数目
    while (nNames < 4) {
        if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {
// 不在引号当中的空格表示新一行的开始,通过CMD命令行的DIR命令可以看到C盘下面的program file实际上市带引号的。
argc++;//此处由0开始递增,正好去掉第一个参数也就是rundll.exe

            // 跳过参数当中的空格
            while (*lpSrc == _T(' ') || *lpSrc == _T('\t') || (*lpSrc == _T(',') && nNames == 2))
                lpSrc++;
            if (*lpSrc == 0)
                break;
            if (nNames >= 3) {
                // 为最后一个参数进行递增
                argc++;
                break;
            }
            nBSlash = 0;//讲斜划线的计数清零,并且设置第一个字符标志为真
            bFirstChar = TRUE;
            continue;
        }
        else if (*lpSrc == _T('\\')) {
            // 递增连续的斜划线的计数
            nBSlash++;
            bFirstChar = FALSE;
        }
        else if (*lpSrc == _T('\"') && !(nBSlash & 1)) {//在斜划线为奇数的时候,那么表示对引号的转义字符
            // 只要遇到引号则在引号当中的状态需要发生改变
            bInQuotes = !bInQuotes;//引号实际不会改变第一个字符的状态
            nBSlash = 0;//因为引号状态改变之后,表明一类新的字符串开始,所以斜划线计数要清零
        }
        else {
            // 其他的字符
            nBSlash = 0;
            if (bFirstChar && ((*lpSrc != _T('/') && nNames <= 1) || nNames > 1))//这的的‘/’字符表示跟在rundll.exe后面的子命令
                nNames++;
            bFirstChar = FALSE;
        }
        lpSrc++;
}

第三步,分配内存,并且将参数按照顺序写到二位数组当中。

lpDest = lpArg = (LPTSTR)(argv + argc);//注意这里由于argv是二维数组,那么头部保存到各个一位数组的地址,这样可以节省内存


// 填充参数队列

while (nNames < 4) {

if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) ||((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {

// 不在引号当中的空格代表新一行的开始

// 参数的终结符

*lpDest++ = 0;//表明lpDest当中为一个参数序列

argv[argc++] = lpArg;//这里lparg实际上指向lpdest的头部,所以刚好放到argv当中去

// 跳过参数当中的空格

while (*lpSrc == _T(' ') || *lpSrc ==_T('\t') || (*lpSrc == _T(',') && nNames == 2))

lpSrc++;

if (*lpSrc == 0)

break;

lpArg = lpDest;//重新使得lpdest的头部等于lparg

if (nNames >= 3) {

// 首先将lparg当中的值赋给argv

argv[argc++] = lpArg;

_tcscpy(lpArg,lpSrc);因为是指针赋值,所以这里同样也是拷贝到argv[argc]

break;

}

nBSlash = 0;

bFirstChar = TRUE;

continue;

}

else if (*lpSrc == _T('\\')) {

*lpDest++ = _T('\\');

lpSrc++;

// 递增连续的斜划线

nBSlash++;

bFirstChar = FALSE;

}

else if (*lpSrc == _T('\"')) {

if (!(nBSlash & 1)) {

// 如果引号前面出现偶数个斜划线

// 那么引号将不会被输出

lpDest -= nBSlash / 2;

bInQuotes = !bInQuotes;

}

else {

// 如果奇数个斜划线出现在引号前面

// 将输出一个引号

lpDest -= (nBSlash + 1) / 2;

*lpDest++ = _T('\"');

bFirstChar = FALSE;

}

lpSrc++;

nBSlash = 0;

}

else {

// 拷贝其他的字符

if (bFirstChar && ((*lpSrc!= _T('/')&& nNames <= 1) || nNames > 1))

nNames++;

*lpDest++ = *lpSrc++;

nBSlash = 0;

bFirstChar = FALSE;

}

}

本文源代码地址:DUNDLL源代码

原文链接:https://www.f2er.com/react/308179.html

猜你在找的React相关文章