最後進行交叉分析 - 可以使用regex_search
,但搜索需要在發現模式後繼續從下一個char *開始重試。
下面幾乎是在運行時加載.reg文件的完整示例,我使用的是MFC的CString
,因爲它比std::string
稍微容易使用,並且當前不需要可移植性。
#include "stdafx.h"
#include <afx.h> //CFile
#include "TestRegex.h"
#include <fstream>
#include <string>
#include <regex>
#include <map>
CWinApp theApp;
using namespace std;
typedef enum
{
eREG_DWORD = REG_DWORD,
eREG_QWORD = REG_QWORD,
eREG_BINARY = REG_BINARY,
eREG_SZ = REG_SZ
}eRegType;
class RegVariant
{
public:
eRegType type;
union
{
DWORD dw;
__int64 qw;
};
CStringA str;
};
class RegKeyNode
{
public:
// Paths to next nodes
map<CStringA, RegKeyNode> keyToNode;
// Values of current key
map<CStringA, RegVariant> keyValues;
};
map<HKEY, RegKeyNode> g_registry;
int char2int(char input)
{
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return 0;
}
void hexToBin(const char* hex, CStringA& bin, int maxSize = -1)
{
int size = (strlen(hex) + 1)/ 3;
if(maxSize != -1 && size > maxSize)
size = maxSize;
unsigned char* buf = (unsigned char*)bin.GetBuffer(size);
for(int i = 0; i < size; i++)
buf[i] = char2int(hex[ i*3 ]) * 16 + char2int(hex[i * 3 + 1]);
bin.ReleaseBuffer();
}
int main()
{
HMODULE hModule = ::GetModuleHandle(nullptr);
AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0);
//
// Load .reg file.
//
CString fileName = L"test1.reg";
CStringA file;
CFile cfile;
if (cfile.Open(fileName, CFile::modeRead | CFile::shareDenyNone))
{
int len = (int)cfile.GetLength();
cfile.Read(file.GetBuffer(len), len);
file.ReleaseBuffer();
}
cfile.Close();
file.Replace("\r\n", "\n");
const char* pbuf = file.GetBuffer();
regex reSection("\\[(.*?)\\]([^]*?)\n\n");
regex reLine("^\\s*\"(.*?)\"\\s*=\\s*(.*)$");
regex reTypedValue("^(hex|dword|hex\\(b\\)):(.*)$");
regex reStringValue("^\"(.*)\"$");
cmatch cmSection, cmLine;
//
// For each section:
//
// [registry path]
// "value1"="value 1"
// "value2"="value 1"
//
while(regex_search(pbuf, pbuf + strlen(pbuf), cmSection, reSection))
{
CStringA path = cmSection[1].str().c_str();
string key_values = cmSection[2].str();
const char* pkv = key_values.c_str();
int iPath = 0;
CStringA hkeyName = path.Tokenize("\\", iPath).MakeUpper();
RegKeyNode* rnode;
if(hkeyName.Compare("HKEY_LOCAL_MACHINE") == 0)
rnode = &g_registry[HKEY_LOCAL_MACHINE];
else
rnode = &g_registry[HKEY_CURRENT_USER]; // Don't support other HKEY roots.
//
// Locate path where to place values.
//
for(; hkeyName = path.Tokenize("\\", iPath);)
{
if(hkeyName.IsEmpty())
break;
rnode = &rnode->keyToNode[hkeyName];
}
//
// Scan "key"="value" pairs.
//
while(regex_search(pkv, pkv+strlen(pkv), cmLine, reLine))
{
CStringA key = cmLine[1].str().c_str();
string valueType = cmLine[2].str();
smatch cmTypeValue;
RegVariant* rvValue = &rnode->keyValues[key];
//
// Extract type and value.
//
if(regex_search(valueType, cmTypeValue, reTypedValue))
{
string type = cmTypeValue[1].str();
string value = cmTypeValue[2].str();
if(type == "dword")
{
rvValue->type = eREG_DWORD;
rvValue->dw = (DWORD)strtoul(value.c_str(), 0, 16);
}
else if (type == "hex(b)")
{
rvValue->type = eREG_QWORD;
rvValue->qw = 0;
if(value.size() == 8 * 2 + 7)
{
CStringA v;
hexToBin(value.c_str(), v, sizeof(__int64));
rvValue->qw = *((__int64*)v.GetBuffer());
}
} else //if (type == "hex")
{
rvValue->type = eREG_BINARY;
hexToBin(value.c_str(), rvValue->str);
}
} else if(regex_search(valueType, cmTypeValue, reStringValue))
{
rvValue->type = eREG_SZ;
rvValue->str = cmTypeValue[1].str().c_str();
}
pkv = cmLine[2].second;
} //while
pbuf = cmSection[2].second;
} //while
return 0;
}