• VS2005控制台程序修改nb0文件


    VS2005控制台程序修改nb0文件

     

    我们要实现的功能就是通过CMD传递进来的值来在nb0文件末尾增加版本信息,新建控制台程序,自动生成的main函数如下,默认的代码非常简单:

    int _tmain(int argc, _TCHAR * argv[])
    {
             return0;
    }

    为了实现此功能,我们发现有两种实现的办法,差别在于使用TCHAR还是char,下面分别给出这两种方式的实现代码,这两种实现方式CMD端传递的参数都一样,如下:


    图1

     

    1.      采用TCHAR

     

    (1)    main函数

    int _tmain(int argc, _TCHAR * argv[])
    {
             TCHAR*pImageVersion;
             TCHAR*pFileDir;
             TCHAR*pFileName;
     
             pFileDir= argv[1];
             pFileName= argv[2];
             pImageVersion= argv[3];
            
             PIMG_CHECK_VERSION  pImg_check_version;
            
     
             printf("argc= %d
    ",argc);
            
             for(inti = 0; i < argc; i++)
             {
                       printf("argv[%d]:%s
    ",i,argv[i]);
             }
            
             wcscpy(pImg_check_version->ImageVersion,pImageVersion);
     
             AddDataToNb0File(pFileDir,pFileName,pImg_check_version);
             return0;
    }

    (2)    AddDataToNb0File

     

    BOOL AddDataToNb0File(TCHAR *pFileDir,TCHAR *pFileName, PIMG_CHECK_VERSION pCheckVersion)
             {
             BOOLret = FALSE;
             TCHARtFilePath[FILE_NAME_LEN];
             DWORDdwSize;
     
             memset((PBYTE)tFilePath,0,sizeof(tFilePath));
             wcscpy(tFilePath,pFileDir);
             wcscat(tFilePath,pFileName);
     
     
             HANDLEhfile = CreateFile(tFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
             if(hfile== INVALID_HANDLE_VALUE)
             {
                       printf("AddDataToNb0File()GetLastError=0x%x
    ",GetLastError());
                       gotoExit;
             }
     
             DWORDFileSize = GetFileSize (hfile, NULL) ;
     
             if(FileSize == 0xFFFFFFFF)
             {
                       gotoExit;
             }
     
     
             SetFilePointer(hfile,(FileSize- sizeof(IMG_CHECK_VERSION)),NULL,FILE_BEGIN);
             WriteFile(hfile,(PBYTE)pCheckVersion,sizeof(IMG_CHECK_VERSION),&dwSize,NULL);
             SetFilePointer(hfile,FileSize,NULL,FILE_BEGIN);
             SetEndOfFile(hfile);
     
             ret=  TRUE;
            
             Exit:
             if(hfile!= INVALID_HANDLE_VALUE)
             {
                       CloseHandle(hfile);
             }
             returnret;
    }

    (3)    IMG_CHECK_VERSION结构体的定义

    typedef struct _IMG_CHECK_VERSION_
    {
             TCHARImageVersion[VERSION_LEN];
    }IMG_CHECK_VERSION,*PIMG_CHECK_VERSION;

    见main函数的printf函数,我们的本意是输出传递进来参数的所有字符串内容的,但自己的输出却是:


    图2

    可见只输出对应参数的第一个字符,比如argv[2]是传递“stepldr.nb0”进来的,但只输出s,虽然我们想要的功能能够达到,但是调试起来如果想看这些信息比较不方便。

     

    修改之前stepldr.nb0文件最后一段全部为0,我们用UltraEdit文件打开如下:


    图3

    修改之后如下:


    图4

    由图4可知stepldr.nb0从0x1ff8到0x1fff这8个字节的数据由之前的0x00改为0x31、0x00、0x32、0x00、0x33、0x00、0x34、0x00,这对应于图1中传递进来的1234,为什么1个字符会占用两个字节呢?是因为我们的IMG_CHECK_VERSION结构体成员ImageVersion类型是TCHAR(相当于wchar_t),是宽字符,也就是说一个字符占用2个字节。

    2.      采用char

     

    (1)    main函数

    int main(int argc, char * argv[])
    {
             char*pImageVersion;
             char*pFileDir;
             char*pFileName;
     
             pFileDir= argv[1];
             pFileName= argv[2];
             pImageVersion= argv[3];
            
             PIMG_CHECK_VERSION  pImg_check_version;
            
     
             printf("argc= %d
    ",argc);
            
             for(inti = 0; i < argc; i++)
             {
                       printf("argv[%d]:%s
    ",i,argv[i]);
             }
            
             strcpy(pImg_check_version->ImageVersion,pImageVersion);
             AddDataToNb0File(pFileDir,pFileName,pImg_check_version);
            
             return0;
    }

    (2)    AddDataToNb0File函数

     

    BOOL AddDataToNb0File(char *pFileDir, char*pFileName, PIMG_CHECK_VERSION pCheckVersion)
    {
             BOOLret = FALSE;
             chartFilePath[FILE_NAME_LEN];
             DWORDdwSize;
     
             memset((PBYTE)tFilePath,0,sizeof(tFilePath));
             strcpy(tFilePath,pFileDir);
             strcat(tFilePath,pFileName);
     
             DWORDdwFileDirNum = MultiByteToWideChar (CP_ACP, 0, tFilePath, -1, NULL, 0);
             wchar_t*pFileDirAndName = new wchar_t[dwFileDirNum];
     
             MultiByteToWideChar(CP_ACP, 0, tFilePath, -1, pFileDirAndName, dwFileDirNum);
            
             printf("filedir and name : %s,dwFileDirNum=%d 
    ",pFileDirAndName,dwFileDirNum);
     
             HANDLEhfile = CreateFile(pFileDirAndName, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
             //HANDLEhfile = CreateFile((LPCTSTR)tFilePath, GENERIC_READ |GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
             if(hfile== INVALID_HANDLE_VALUE)
             {
                       printf("AddDataToNb0File()GetLastError=0x%x
    ",GetLastError());
                       gotoExit;
             }
     
             DWORDFileSize = GetFileSize (hfile, NULL) ;
     
             if(FileSize == 0xFFFFFFFF)
             {
                       gotoExit;
             }
     
     
             SetFilePointer(hfile,(FileSize- sizeof(IMG_CHECK_VERSION)),NULL,FILE_BEGIN);
             WriteFile(hfile,(PBYTE)pCheckVersion,sizeof(IMG_CHECK_VERSION),&dwSize,NULL);
             SetFilePointer(hfile,FileSize,NULL,FILE_BEGIN);
             SetEndOfFile(hfile);
     
             ret=  TRUE;
            
             Exit:
             if(hfile!= INVALID_HANDLE_VALUE)
             {
                       CloseHandle(hfile);
             }
             returnret;
    }

    这里要注意的是CreateFile函数的第1个参数类型要求是LPCTSTR,如果我们直接采用(LPCTSTR)tFilePath强制类型转换,GetLastError()返回值是2(ERROR_FILE_NOT_FOUND),表示找不到文件,采用MultiByteToWideChar函数转换为宽字符后就OK了。

     

    (3)    IMG_CHECK_VERSION结构体

    typedef struct _IMG_CHECK_VERSION_
    {
             charImageVersion[VERSION_LEN];
    }IMG_CHECK_VERSION,*PIMG_CHECK_VERSION;

    采用这样的方式修改stepldr.nb0后,如下:


    图5

    可见char占用一个字节,综合比较具体是采用哪种,根据需要来选择。

     

    遇到一个很奇怪的问题,我在A电脑上用VS2005创建的这个控制台程序,编译出来后在B电脑上运行是提示不能运行这个程序,然后我在B电脑上编译A电脑的这个工程,重新生成控制台程序就可以,然后我用B电脑上编译的在A电脑上也OK,目前不知道原因,先备注下。

  • 相关阅读:
    关于JS中判断两个数组相等
    用JS实现二叉树
    elementUI select组件 默认选择第一项
    angular [src] 绑定url或src 报XSS错误
    easy-mock本地搭建工程实操
    array splice split || string split slice 傻傻分不清楚=>终于弄清楚了
    循环=>轮回=>js循环比拼
    vue-cli 搭建工程配置 => 你想要这里都有
    git分支问题 查看、创建、关联、删除本地/远程分支
    vue知识点 && 错误点 => 持续更新
  • 原文地址:https://www.cnblogs.com/LoongEmbedded/p/5298492.html
Copyright © 2020-2023  润新知