2011年5月31日 星期二

[C++] Iterator Patterns 例子

Autostart registry entries: contains values used to load applications when Windows is started.

Example: TROJ_DASMIN.C 在 HKLM\Software\Microsoft\Windows\CurrentVersion\Run 寫入 MSConfigr = "%System%\JDBGMRG.EXE" 和 VirusCheckII = "%System%\AVIRCHK.EXE",因此每次系統啟動時,TROJ_DASMIN.C 就會被執行。

怎麼找出這些威脅呢?當然就是列舉所有的 autostart registry entries。這讓我想到 iterator patterns: provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. [GoF]

有想法之後,該怎麼用 C++ 實做出來呢?首先先偷 [chrome]/trunk/src/base/win/registry.h,稍微修改一下,接著寫自己的 autostart_reg_iterator.h:
// The author disclaims copyright to this source code.

#ifndef MODULE_AUTOSTART_REG_ITERATOR_H_
#define MODULE_AUTOSTART_REG_ITERATOR_H_
#pragma once

#include <windows.h>

#include "base/basictypes.h"

#include <vector>

namespace base {
namespace win {
class RegValueIterator;
}
}

namespace module {

// Iterates the autostart entries.
class AutostartRegIterator {
public:
AutostartRegIterator();

~AutostartRegIterator();

DWORD ValueCount() const;

// True while the iterator is valid.
bool Valid() const;

// Advances to the next entry.
void Next();

const wchar_t* Key() const;
const wchar_t* Name() const;
const wchar_t* Value() const;
DWORD ValueSize() const;
DWORD Type() const;

private:
// All iterators of autostart registry iterator.
std::vector<base::win::RegValueIterator*> iterators_;

// Current index of iterators.
int index_;

DISALLOW_COPY_AND_ASSIGN(AutostartRegIterator);
};

} // namespace module

#endif // MODULE_AUTOSTART_REG_ITERATOR_H_
底下是 .cc 檔:
// The author disclaims copyright to this source code.

#include "module/autostart_reg_iterator.h"

#include "module/reg_value_iterator_factory.h"
#include "base/win/reg.h"

namespace module {

using base::win::RegValueIterator;

const wchar_t* kAutostartRegKey[] = { ... };

AutostartRegIterator::AutostartRegIterator() {
RegValueIteratorFactory factory;
for (int i = 0; i != arraysize(kAutostartRegKey); ++i) {
iterators_.push_back(factory.Create(kAutostartRegKey[i]));
}
index_ = iterators_.size() - 1;
}

AutostartRegIterator::~AutostartRegIterator() {
for (int i = 0; i != arraysize(kAutostartRegKey); ++i) {
delete iterators_.at(i);
}
iterators_.clear();
}

DWORD AutostartRegIterator::ValueCount() const {
DWORD count = 0;
for (int i = 0; i != arraysize(kAutostartRegKey); ++i) {
count += iterators_.at(i)->ValueCount();
}
return count;
}

bool AutostartRegIterator::Valid() const {
return index_ > 0 || iterators_.at(0)->Valid();
}

void AutostartRegIterator::Next() {
if (index_ > 0 && !iterators_.at(index_)->Valid()) {
--index_;
} else {
iterators_.at(index_)->Next();
}
}

const wchar_t* AutostartRegIterator::Key() const {
return kAutostartRegKey[index_];
}

const wchar_t* AutostartRegIterator::Name() const {
return iterators_.at(index_)->Name();
}

const wchar_t* AutostartRegIterator::Value() const {
return iterators_.at(index_)->Value();
}

DWORD AutostartRegIterator::ValueSize() const {
return iterators_.at(index_)->ValueSize();
}

DWORD AutostartRegIterator::Type() const {
return iterators_.at(index_)->Type();
}

} // namespace module
有些細節就略過了,重點就是如何用大的 iterator 包住小的 base::win::RegValueIterator iterators,如何實做 multiple traversals of aggregate objects。

沒有留言:

張貼留言