来源:http://topic.youkuaiyun.com/u/20090908 ... 4-322d0a5886ca.html可以查到:URL、标题、访问时间、更新时间、过期时间。访问次数暂时没搞定。 #include <windows.h> #include <tchar.h> #include <ShlObj.h> #include <stdio.h> #define OUTPUT_HISTORY_FILE "C://url_history.txt" #define ONLY_QUERY_HTTP // 只显示网页URL纪录,否则会包括本地文件等。 FILE *g_fp; errno_t errno_open; #define DEF_EMPTY_STR(arg, n) / TCHAR arg[n]; / ZeroMemory(arg, ((n) * sizeof(TCHAR))) #define DEF_EMPTY_STR_A(arg, n) / char arg[n]; / ZeroMemory(arg, ((n) * sizeof(char))) #define DEF_EMPTY_STR_W(arg, n) / wchar_t arg[n]; / ZeroMemory(arg, ((n) * sizeof(wchar_t))) LPVOID MapCache(char *szFileName, DWORD &dwCacheLen) { HANDLE hFile = NULL, hMapFile = NULL; hFile = CreateFileA( szFileName, GENERIC_READ, // open for reading FILE_SHARE_READ | FILE_SHARE_WRITE, // share for reading NULL, // no security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if (hFile == INVALID_HANDLE_VALUE) { return NULL; } hMapFile = CreateFileMapping(hFile, // Current file handle. NULL, // Default security. PAGE_READONLY, // Read/write permission. 0, // Max. object size. 0, // Size of hFile. _T("MappingCache")); // Name of mapping object. if (hMapFile == NULL) { return NULL; } LPVOID lpCache = MapViewOfFile( hMapFile, // Handle to mapping object. FILE_MAP_READ, // Read/write permission 0, // Max. object size. 0, // Size of hFile. 0); // Map entire file. if (lpCache == NULL) { return NULL; } CloseHandle(hFile); CloseHandle(hMapFile); //get cache file size dwCacheLen = *(DWORD *)((BYTE *)lpCache + 0x1c); return lpCache; } bool GetHistory(const BYTE *lpUrl) { if (memcmp(lpUrl, "URL ", 4) != 0) { return false; } //get url history size(=*0x80 bytes) DWORD dwLen = *(DWORD *)(lpUrl + 4); if (dwLen <= 0) { return false; } //get URL char *szUrl1 = (char *)(lpUrl + 0x68); char *szUrl = strstr(szUrl1, "@"); if (szUrl == NULL) { return false; } szUrl++; //get last visited, last updated, expires FILETIME ftVis = *(FILETIME *)(lpUrl + 0x8); FILETIME ftUpd = *(FILETIME *)(lpUrl + 0x10); DWORD dwExpire = *(DWORD *)(lpUrl + 0x18); FILETIME ftExp = ftUpd; ftExp.dwLowDateTime += dwExpire; SYSTEMTIME stVisit = {0}, stUpdate = {0}, stExpire = {0}; if (!FileTimeToSystemTime(&ftVis, &stVisit) || !FileTimeToSystemTime(&ftUpd, &stUpdate) || !FileTimeToSystemTime(&ftExp, &stExpire)) { return false; } DEF_EMPTY_STR_A(szTmVisitA, MAX_PATH); sprintf_s(szTmVisitA, MAX_PATH, "%d-%d-%d_%d:%d:%d", stVisit.wYear, stVisit.wMonth, stVisit.wDay, stVisit.wHour, stVisit.wMinute, stVisit.wSecond); DEF_EMPTY_STR_A(szTmUpdateA, MAX_PATH); sprintf_s(szTmUpdateA, MAX_PATH, "%d-%d-%d_%d:%d:%d", stUpdate.wYear, stUpdate.wMonth, stUpdate.wDay, stUpdate.wHour, stUpdate.wMinute, stUpdate.wSecond); DEF_EMPTY_STR_A(szTmExpireA, MAX_PATH); sprintf_s(szTmExpireA, MAX_PATH, "%d-%d-%d_%d:%d:%d", stExpire.wYear, stExpire.wMonth, stExpire.wDay, stExpire.wHour, stExpire.wMinute, stExpire.wSecond); //get Title char *szTitle = NULL; LPCWSTR wchTitle = NULL; DWORD dwTitleOff = *(DWORD *)(lpUrl + 0x44); DWORD dwTitleLen = *(DWORD *)(lpUrl + 0x48); if (dwTitleLen - 0x14 <= 0) { szTitle = "NULL"; } else if (dwTitleOff > 0 && dwTitleOff < dwLen * 0x80) { const WORD *pwEnd = (const WORD *)(lpUrl + dwTitleOff + dwTitleLen); const WORD *pwCheck = (const WORD *)(lpUrl + dwTitleOff + 18); while (*pwCheck != 0x1f10 && pwCheck < pwEnd) { pwCheck++; } if (pwCheck < pwEnd && *pwCheck == 0x1f10) { wchTitle = (LPCWSTR)(pwCheck + 1); int nCharSize = WideCharToMultiByte(936, 0, wchTitle, wcslen(wchTitle), NULL, 0, NULL, NULL); if (nCharSize > 0) { szTitle = new char[nCharSize + 2]; if (szTitle == NULL) { szTitle = "NULL"; } else { memset(szTitle, 0, nCharSize+2); WideCharToMultiByte(936, 0, wchTitle, wcslen(wchTitle), szTitle, nCharSize, NULL, NULL); } } } } #ifdef ONLY_QUERY_HTTP if (NULL != g_fp && (szUrl == strstr(szUrl, "http"))) { #else if (NULL != g_fp) { #endif fprintf_s(g_fp, "%s/t%s/tvisit=%s/tupdate=%s/texpire=%s/n", szUrl, szTitle, szTmVisitA, szTmUpdateA, szTmExpireA); } if (szTitle != NULL && strcmp(szTitle, "NULL") != 0) { delete [] szTitle; } return true; } bool ParseIndexDat(LPCTSTR szFile) { if (NULL != g_fp) { _ftprintf_s(g_fp, _T("/nIndex file : %s/n/n"), szFile); } DEF_EMPTY_STR_A(szFileA, MAX_PATH); #ifdef _UNICODE WideCharToMultiByte(CP_ACP, 0, szFile, _tcslen(szFile), szFileA, MAX_PATH, 0, 0); #else strcpy_s(szFileA, MAX_PATH, szFile); #endif DWORD dwCacheLen = 0; LPVOID lpCache = MapCache(szFileA, dwCacheLen); if (NULL == lpCache) { return false; } if (lpCache == NULL || dwCacheLen <= 0) { return false; } //get the first hash table offset DWORD dwHashOff = *(DWORD *)((BYTE *)lpCache + 0x20); if (dwHashOff == 0 || dwHashOff > dwCacheLen) { return false; } BYTE *lpHash = (BYTE *)lpCache + dwHashOff; DWORD dwHashLen = 0, dwNextOff = 0, dwUrlOff = 0, dwHash = 0; //get hash tables one by one while (true) { if (memcmp(lpHash, "HASH", 4) != 0) { break; } dwHashLen = *(DWORD *)(lpHash + 4); //hash table size dwNextOff = *(DWORD *)(lpHash + 8); //the next hashtable offset //get hash and offset for (DWORD i = 0; i < dwHashLen * 16; i++) //dwHashLen*0x80/8 { dwHash = *(DWORD *)(lpHash + 0x10 + i * 8); //get table tail if (dwHash == 0x0) { break; } //unused hash if (dwHash == 0x3) { continue; } dwUrlOff = *(DWORD *)(lpHash + 0x10 + i * 8 + 4); if (dwUrlOff != 0 && dwUrlOff != 0x3 && dwUrlOff < dwCacheLen) { GetHistory((const BYTE *)lpCache + dwUrlOff); } } if (dwNextOff == 0 || dwNextOff > dwCacheLen) { break; } lpHash = (BYTE *)lpCache + dwNextOff; } return true; } void Traverse(LPCTSTR dir) { WIN32_FIND_DATA ffd; HANDLE hFind; TCHAR szPattern[MAX_PATH]; _stprintf_s(szPattern, _T("%s//*"), dir); hFind = ::FindFirstFile(szPattern, &ffd); if (INVALID_HANDLE_VALUE == hFind) { return; } do { if (_tcscmp(_T("."), ffd.cFileName) == 0 || _tcscmp(_T(".."), ffd.cFileName) == 0) { continue; } if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { TCHAR subDir[MAX_PATH]; _stprintf_s(subDir, _T("%s//%s"), dir, ffd.cFileName); Traverse(subDir); } else if (_tcsicmp(ffd.cFileName, _T("index.dat")) == 0) { TCHAR fileName[MAX_PATH]; _stprintf_s(fileName, _T("%s//%s"), dir, ffd.cFileName); if (!ParseIndexDat(fileName)) { _tprintf_s(_T("error processing file /'%s/'/n"), fileName); } } } while (FindNextFile(hFind, &ffd)); } int _tmain(int argc, TCHAR **argv) { g_fp = NULL; errno_open = fopen_s(&g_fp, OUTPUT_HISTORY_FILE, "wt"); DEF_EMPTY_STR(szHistoryDir, MAX_PATH); if (SHGetSpecialFolderPath(NULL, szHistoryDir, CSIDL_HISTORY, FALSE)) { Traverse(szHistoryDir); } if (0 == errno_open && NULL != g_fp) { ShellExecuteA(NULL, "open", OUTPUT_HISTORY_FILE, NULL, NULL, SW_SHOWNORMAL); fclose(g_fp); } return 0; }