まず、前回の文字列のポインタを配列に保存するように直します。
■変更前
lpStr = ((LPSTR)pEventLogRecord) + pEventLogRecord->StringOffset;
for(j = 0; j < pEventLogRecord->NumStrings; j++) {
printf("%s\n", lpStr);
lpStr += lstrlen(lpStr) + 1;
}
■変更後
char **Args;
Args = GlobalAlloc(GPTR, sizeof(char *) * pEventLogRecord->NumStrings);
lpStr = ((LPSTR)pEventLogRecord) + pEventLogRecord->StringOffset;
for(j = 0; j < pEventLogRecord->NumStrings; j++) {
Args[j] = lpStr;
lpStr += lstrlen(lpStr) + 1;
} |
Argsの解放(GlobalFree)を適切な場所に追加しておくこと。
次にDLLのファイル名をレジストリから読み取るのだが、
レジストリキーは、
HKLM\SYSTEM\CurrentControlSet\Services\EventLog\
System
から取得する。
そのキーとソース名使ってサブキーを取得する。
EventMessageFileから取得すれば、DLLのファイル名となる。
ただし、ファイル名は、%SystemRoot%などの環境変数を使用しているので、
ExpandEnvironmentStringsにて展開する必要がある。
ここまでは以下のとおり。
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System",
0, KEY_READ, &hAppKey)) {
if(ERROR_SUCCESS == RegOpenKeyEx(hAppKey, lpSourcename, 0, KEY_READ, &hSourceKey)) {
if(ERROR_SUCCESS == RegQueryValueEx(hSourceKey, "EventMessageFile", NULL, NULL, szModuleName, &dwModuleNameSize)) {
ExpandEnvironmentStrings(szMoudleName, szExpandMouleName, sizeof(szExpandModuleName));
printf("dll:%s\n", szExpandModuleName);
}
RegCloseKey(hSourceKey);
}
RegCloseKey(hAppKey);
} |
あとは、DLLをロードして、文字列をフォーマットすればよい。
hModule = LoadLibraryEx(szExpandModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
if(hModule) {
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
hModule,
pEventLogRecord->EventID,
MAKELANGUID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&pMessage,
0,
(va_list *)Args);
if(pMessage) {
printf("%s\n", pMessage);
LocalFree(pMessage);
}
FreeLibrary(hModule);
} |
あとは、ソース名がWindows Update Agentのものだけを表示するように改良すれば完成かな?
(実際は個々部分を関数化したりしなければならないけど)
終わり。