windows-nt/Source/XPSP1/NT/shell/ext/webcheck/test/trackvw/trackvw.cpp
2020-09-26 16:20:57 +08:00

509 lines
14 KiB
C++

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <inetreg.h>
#include <stdio.h>
#include <wininet.h>
#include "trackvw.h"
//Helper functions
BOOL ListTreeView(HWND hwnd);
BOOL ListEditView(HWND hwnd, LPSTR lpUrl);
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
//extern HINSTANCE g_hinst;
static char lpPfx[] = "Log:";
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "UrlTrack Cache Viewer";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
HACCEL hAccel;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH);
wndclass.lpszMenuName = MAKEINTRESOURCE(TRACKMENU);
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wndclass);
hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
hAccel = LoadAccelerators (hInstance, "TrackVw");
while(GetMessage(&msg, NULL, 0, 0))
{
if(!TranslateAccelerator(hwnd, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInstance;
static HWND hwndTreeView, hwndEdit = NULL;
RECT rcClientWnd, rcTreeWnd, rcEditWnd = {0};
switch(iMsg)
{
case WM_CREATE:
{
OleInitialize(NULL);
InitCommonControls();
hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
GetClientRect(hwnd, &rcClientWnd);
rcTreeWnd.right = rcClientWnd.right / 2; // Set the right edge for the Tree control to one half the client window space
rcTreeWnd.bottom = rcClientWnd.bottom;
rcEditWnd.left = rcTreeWnd.right + 5; // Leave space from the left frame for the resize bar
rcEditWnd.right = rcClientWnd.right - (rcTreeWnd.right + 5);
rcEditWnd.bottom = rcClientWnd.bottom;
hwndTreeView = CreateWindow(WC_TREEVIEW, "", WS_VISIBLE | WS_CHILD
| TVS_HASLINES | WS_BORDER | TVS_SHOWSELALWAYS, 0, 0, rcTreeWnd.right,
rcTreeWnd.bottom, hwnd, (HMENU) 1, hInstance, NULL);
if (!hwndTreeView)
break;
ShowWindow(hwndTreeView, SW_SHOW);
hwndEdit = CreateWindow("EDIT", NULL, WS_BORDER | WS_VISIBLE | WS_CHILD
| WS_HSCROLL | WS_VSCROLL | ES_MULTILINE, rcEditWnd.left, 0,
rcEditWnd.right, rcEditWnd.bottom, hwnd, (HMENU) 2, hInstance, NULL);
if (!hwndEdit)
break;
ShowWindow(hwndEdit, SW_SHOW);
if (!ListTreeView(hwndTreeView))
break;
SetFocus(hwndTreeView);
return 0;
}
case WM_SIZE:
{
GetClientRect(hwnd, &rcClientWnd);
rcTreeWnd.right = rcClientWnd.right / 2; // Set the right edge for the Tree control to one half the client window space
rcTreeWnd.bottom = rcClientWnd.bottom;
rcEditWnd.left = rcTreeWnd.right + 3; // Leave space from the left frame for the resize bar
rcEditWnd.right = rcClientWnd.right - (rcTreeWnd.right + 5);
rcEditWnd.bottom = rcClientWnd.bottom;
SetWindowPos(hwndTreeView, HWND_TOP, 0, 0, rcTreeWnd.right, rcTreeWnd.bottom,
SWP_SHOWWINDOW);
SetWindowPos(hwndEdit, HWND_TOP, rcEditWnd.left, 0, rcEditWnd.right,
rcEditWnd.bottom, SWP_SHOWWINDOW);
break;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case ID_EXIT:
{
SendMessage(hwnd, WM_CLOSE, 0, 0L);
return 0;
}
case ID_REFRESH:
{
TreeView_DeleteAllItems(hwndTreeView);
if (!ListTreeView(hwndTreeView))
break;
}
}
break;
}
case WM_NOTIFY:
{
switch (((LPNMHDR)lParam)->code)
{
case TVN_SELCHANGED:
{
// Get the Text of the URL which was selected, add our prefix to it
// and get the CacheEntryInfo for the URL. Then open the file it points to
// and display the contents in the edit window.
char lpTempBuf[MY_MAX_STRING_LEN];
char lpUrl[MY_MAX_STRING_LEN];
((NM_TREEVIEW *)lParam)->itemNew.mask = TVIF_TEXT;
((NM_TREEVIEW *)lParam)->itemNew.pszText = lpTempBuf;
((NM_TREEVIEW *)lParam)->itemNew.cchTextMax = MY_MAX_STRING_LEN;
TreeView_GetItem(hwndTreeView, &((NM_TREEVIEW *)lParam)->itemNew);
lstrcpy(lpUrl, lpPfx);
lstrcat(lpUrl, ((NM_TREEVIEW *)lParam)->itemNew.pszText);
ListEditView(hwndEdit, lpUrl);
break;
} //TVN_SELCHANGED
}
break;
}
case WM_DESTROY:
{
OleUninitialize();
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
BOOL ListTreeView(HWND hwnd)
{
LPSTR lpUrl = NULL;
BYTE cei[MY_CACHE_ENTRY_INFO_SIZE];
LPINTERNET_CACHE_ENTRY_INFO lpCE = (LPINTERNET_CACHE_ENTRY_INFO)cei;
HTREEITEM htItem = NULL;
DWORD cbSize = MY_CACHE_ENTRY_INFO_SIZE;
HANDLE hCacheEntry = NULL;
TV_ITEM tvi = {0};
TV_INSERTSTRUCT tvins = {0};
hCacheEntry = FindFirstUrlCacheEntry(lpPfx, lpCE, &cbSize);
if (!hCacheEntry)
return FALSE;
// sanity check
char sztmp[10];
lstrcpyn(sztmp, lpCE->lpszSourceUrlName, lstrlen(lpPfx)+1);
if (lstrcmpi(sztmp, lpPfx))
{
FindCloseUrlCache(hCacheEntry);
return TRUE;
}
lpUrl = (LPSTR)GlobalAlloc(GPTR, MY_MAX_STRING_LEN);
// add the length of the cache prefix string to the source url
// name to skip the cache prefix .. was the quickest way to strip
// the prefix from the url.
lstrcpy(lpUrl, lpCE->lpszSourceUrlName+lstrlen(lpPfx));
tvi.mask = TVIF_HANDLE | TVIF_TEXT;
tvi.pszText = lpUrl;
tvi.cchTextMax = lstrlen(lpUrl);
tvins.item = tvi;
tvins.hInsertAfter = TVI_FIRST;
tvins.hParent = TVI_ROOT;
TreeView_InsertItem(hwnd, &tvins);
for ( ; ; )
{
cbSize = MY_CACHE_ENTRY_INFO_SIZE;
if (!FindNextUrlCacheEntry(hCacheEntry, lpCE, &cbSize))
break;
lstrcpy(lpUrl, lpCE->lpszSourceUrlName+lstrlen(lpPfx));
tvi.pszText = lpUrl;
tvi.cchTextMax = lstrlen(lpUrl);
tvins.item = tvi;
tvins.hInsertAfter = TVI_LAST;
TreeView_InsertItem(hwnd, &tvins);
}
FindCloseUrlCache(hCacheEntry);
htItem = TreeView_GetRoot(hwnd);
TreeView_SelectItem(hwnd, htItem);
if (lpUrl)
{
GlobalFree(lpUrl);
lpUrl = NULL;
}
return TRUE;
}
BOOL ListEditView(HWND hwnd, LPSTR lpUrl)
{
BYTE cei[MY_CACHE_ENTRY_INFO_SIZE];
LPINTERNET_CACHE_ENTRY_INFO lpCE = (LPINTERNET_CACHE_ENTRY_INFO)cei;
DWORD cbSize = MY_CACHE_ENTRY_INFO_SIZE;
HANDLE hFile = NULL;
DWORD dwFileSize = 0;
// erase Edit window content
Edit_SetText(hwnd, NULL);
if(!GetUrlCacheEntryInfo(lpUrl, lpCE, &cbSize))
return FALSE;
hFile = CreateFile(lpCE->lpszLocalFileName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == 0)
{
CloseHandle(hFile);
return FALSE;
}
LPTSTR lpBuf;
DWORD dwBytesRead = 0;
lpBuf = (LPTSTR)GlobalAlloc(LPTR, dwFileSize);
if (!lpBuf)
{
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, lpBuf, dwFileSize, &dwBytesRead, NULL) || dwBytesRead == 0)
{
CloseHandle(hFile);
return FALSE;
}
/*
// First to avoid displaying any leading spaces we'll walk through the file
// we find the first non space character. When we find it, we'll set the file
// pointer back 1 so the next time we call ReadFile getting the next byte we'll
// be at the non-space character.
DWORD dwBytesRead = 0;
char ch;
do
{
if (!ReadFile(hFile, &ch, 1, &dwBytesRead, NULL))
{
CloseHandle(hFile);
return FALSE;
}
if (dwBytesRead == 0) // reach end-of-file, return now.
{
CloseHandle(hFile);
return TRUE;
}
}
while (ch == ' ');
if (ch != ' ')
SetFilePointer(hFile, -1, NULL, FILE_CURRENT);
// Alloc a buffer large enough for the file plus 2 characters per line
LPSTR lpBuffer = NULL;
lpBuffer = (LPSTR)GlobalAlloc(GPTR, dwFileSize*2);
if (!lpBuffer)
{
CloseHandle(hFile);
return FALSE;
}
//lpBuffer = "\0";
cbSize = 0;
int cch = 0;
BOOL bIsLeadChar = FALSE;
BOOL bIsSecondChar = FALSE;
char tmp[1024];
LPSTR lpTmp = lpBuffer;
tmp[0] = '\0';
// N 1 08-19-1997 15:28:45 00:00:05\r\nN 1 08-19-1997 15:30:25 00:00:01
for (;;)
{
if (!ReadFile(hFile, &ch, 1, &dwBytesRead, NULL))
{
// choked here,
CloseHandle(hFile);
GlobalFree(lpBuffer);
return FALSE;
}
if (dwBytesRead == 0) // reach end-of-file
break;
switch (ch)
{
case '\n':
wsprintf(tmp, "%c\r\n", ch);
lstrcat(lpBuffer, tmp);
break;
case ' ':
tmp[cch] = ch;
cch ++;
if (bIsLeadChar && bIsSecondChar)
{
if (cch == 5)
{
lpTmp[cbSize ++] = '\r';
lpTmp[cbSize ++] = '\n';
for (int i=1; i<cch; i++)
lpTmp[cbSize ++] = tmp[i];
cch = 0;
}
bIsLeadChar = FALSE;
bIsSecondChar = FALSE;
}
break;
case 'N':
case 'S':
case 'D':
case 'T':
case 'U':
bIsLeadChar = (bIsSecondChar) ? FALSE : TRUE;
tmp[cch] = ch;
cch ++;
break;
case '1':
case '0':
bIsSecondChar = (bIsLeadChar) ? TRUE : FALSE;
tmp[cch] = ch;
cch ++;
break;
default:
tmp[cch] = ch;
cch ++;
for (int i=0; i<cch; i++)
lpTmp[cbSize++] = tmp[i];
cch = 0;
break;
}
}
lpTmp[cbSize] = '\0';
*/
Edit_SetText(hwnd, lpBuf);
CloseHandle(hFile);
if (lpBuf)
GlobalFree(lpBuf);
return TRUE;
}
/*
// No need to read the cache prefix from the registry so we'll hard code it Log:
//lpPfx = (LPSTR)GlobalAlloc(GPTR, lstrlen("Log:")+1);
//lstrcpy(lpPfx, "Log:");
#if 0
lret = RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_TRACKING, 0,
KEY_READ, &hKey);
if (lret != ERROR_SUCCESS)
{
lret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_TRACKING, 0,
KEY_READ, &hKey);
}
if (lret == ERROR_SUCCESS)
{
lret = RegQueryValueEx(hKey, REGSTR_VAL_CACHEPREFIX, 0, NULL, NULL, &cbPfx);
if (lret == ERROR_SUCCESS)
{
lpPfx = (LPSTR)GlobalAlloc(GPTR, cbPfx+1);
if (lpPfx)
{
lret = RegQueryValueEx(hKey, REGSTR_VAL_CACHEPREFIX, 0, NULL,
(LPBYTE)lpPfx, &cbPfx);
}
}
}
if (hKey)
{
RegCloseKey(hKey);
hKey = NULL;
}
#endif //0
/////////////////////////////////////////////////////////////////////////////
// Function: Hacked ModuleEntry for sources file
/////////////////////////////////////////////////////////////////////////////
HANDLE g_hProcessHeap = NULL;
extern "C" int _stdcall ModuleEntry(void)
{
int i;
STARTUPINFOA si;
LPTSTR pszCmdLine;
pszCmdLine = GetCommandLine();
g_hProcessHeap = GetProcessHeap();
//
// We don't want the "No disk in drive X:" requesters, so we set
// the critical error mask such that calls will just silently fail
//
SetErrorMode(SEM_FAILCRITICALERRORS);
if ( *pszCmdLine == TEXT('\"') ) {
//
// Scan, and skip over, subsequent characters until
// another double-quote or a null is encountered.
//
while ( *++pszCmdLine && (*pszCmdLine
!= TEXT('\"')) );
//
// If we stopped on a double-quote (usual case), skip
// over it.
//
if ( *pszCmdLine == TEXT('\"') )
pszCmdLine++;
}
else {
while (*pszCmdLine > TEXT(' '))
pszCmdLine++;
}
//
// Skip past any white space preceeding the second token.
//
while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) {
pszCmdLine++;
}
si.dwFlags = 0;
GetStartupInfoA(&si);
i = WinMain(GetModuleHandle(NULL), NULL, pszCmdLine,
si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
// Since we now have a way for an extension to tell us when it is finished,
// we will terminate all processes when the main thread goes away.
ExitProcess(i);
// DebugMsg(DM_TRACE, TEXT("c.me: Cabinet main thread exiting without ExitProcess."));
return i;
}
*/