Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

508 lines
14 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <commctrl.h>
  4. #include <inetreg.h>
  5. #include <stdio.h>
  6. #include <wininet.h>
  7. #include "trackvw.h"
  8. //Helper functions
  9. BOOL ListTreeView(HWND hwnd);
  10. BOOL ListEditView(HWND hwnd, LPSTR lpUrl);
  11. LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  12. //extern HINSTANCE g_hinst;
  13. static char lpPfx[] = "Log:";
  14. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
  15. {
  16. static char szAppName[] = "UrlTrack Cache Viewer";
  17. HWND hwnd;
  18. MSG msg;
  19. WNDCLASSEX wndclass;
  20. HACCEL hAccel;
  21. wndclass.cbSize = sizeof(wndclass);
  22. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  23. wndclass.lpfnWndProc = WndProc;
  24. wndclass.cbClsExtra = 0;
  25. wndclass.cbWndExtra = 0;
  26. wndclass.hInstance = hInstance;
  27. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  28. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  29. wndclass.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH);
  30. wndclass.lpszMenuName = MAKEINTRESOURCE(TRACKMENU);
  31. wndclass.lpszClassName = szAppName;
  32. wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  33. RegisterClassEx(&wndclass);
  34. hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  35. CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
  36. ShowWindow(hwnd, iCmdShow);
  37. UpdateWindow(hwnd);
  38. hAccel = LoadAccelerators (hInstance, "TrackVw");
  39. while(GetMessage(&msg, NULL, 0, 0))
  40. {
  41. if(!TranslateAccelerator(hwnd, hAccel, &msg))
  42. {
  43. TranslateMessage(&msg);
  44. DispatchMessage(&msg);
  45. }
  46. }
  47. return msg.wParam;
  48. }
  49. LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  50. {
  51. static HINSTANCE hInstance;
  52. static HWND hwndTreeView, hwndEdit = NULL;
  53. RECT rcClientWnd, rcTreeWnd, rcEditWnd = {0};
  54. switch(iMsg)
  55. {
  56. case WM_CREATE:
  57. {
  58. OleInitialize(NULL);
  59. InitCommonControls();
  60. hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
  61. GetClientRect(hwnd, &rcClientWnd);
  62. rcTreeWnd.right = rcClientWnd.right / 2; // Set the right edge for the Tree control to one half the client window space
  63. rcTreeWnd.bottom = rcClientWnd.bottom;
  64. rcEditWnd.left = rcTreeWnd.right + 5; // Leave space from the left frame for the resize bar
  65. rcEditWnd.right = rcClientWnd.right - (rcTreeWnd.right + 5);
  66. rcEditWnd.bottom = rcClientWnd.bottom;
  67. hwndTreeView = CreateWindow(WC_TREEVIEW, "", WS_VISIBLE | WS_CHILD
  68. | TVS_HASLINES | WS_BORDER | TVS_SHOWSELALWAYS, 0, 0, rcTreeWnd.right,
  69. rcTreeWnd.bottom, hwnd, (HMENU) 1, hInstance, NULL);
  70. if (!hwndTreeView)
  71. break;
  72. ShowWindow(hwndTreeView, SW_SHOW);
  73. hwndEdit = CreateWindow("EDIT", NULL, WS_BORDER | WS_VISIBLE | WS_CHILD
  74. | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE, rcEditWnd.left, 0,
  75. rcEditWnd.right, rcEditWnd.bottom, hwnd, (HMENU) 2, hInstance, NULL);
  76. if (!hwndEdit)
  77. break;
  78. ShowWindow(hwndEdit, SW_SHOW);
  79. if (!ListTreeView(hwndTreeView))
  80. break;
  81. SetFocus(hwndTreeView);
  82. return 0;
  83. }
  84. case WM_SIZE:
  85. {
  86. GetClientRect(hwnd, &rcClientWnd);
  87. rcTreeWnd.right = rcClientWnd.right / 2; // Set the right edge for the Tree control to one half the client window space
  88. rcTreeWnd.bottom = rcClientWnd.bottom;
  89. rcEditWnd.left = rcTreeWnd.right + 3; // Leave space from the left frame for the resize bar
  90. rcEditWnd.right = rcClientWnd.right - (rcTreeWnd.right + 5);
  91. rcEditWnd.bottom = rcClientWnd.bottom;
  92. SetWindowPos(hwndTreeView, HWND_TOP, 0, 0, rcTreeWnd.right, rcTreeWnd.bottom,
  93. SWP_SHOWWINDOW);
  94. SetWindowPos(hwndEdit, HWND_TOP, rcEditWnd.left, 0, rcEditWnd.right,
  95. rcEditWnd.bottom, SWP_SHOWWINDOW);
  96. break;
  97. }
  98. case WM_COMMAND:
  99. {
  100. switch(LOWORD(wParam))
  101. {
  102. case ID_EXIT:
  103. {
  104. SendMessage(hwnd, WM_CLOSE, 0, 0L);
  105. return 0;
  106. }
  107. case ID_REFRESH:
  108. {
  109. TreeView_DeleteAllItems(hwndTreeView);
  110. if (!ListTreeView(hwndTreeView))
  111. break;
  112. }
  113. }
  114. break;
  115. }
  116. case WM_NOTIFY:
  117. {
  118. switch (((LPNMHDR)lParam)->code)
  119. {
  120. case TVN_SELCHANGED:
  121. {
  122. // Get the Text of the URL which was selected, add our prefix to it
  123. // and get the CacheEntryInfo for the URL. Then open the file it points to
  124. // and display the contents in the edit window.
  125. char lpTempBuf[MY_MAX_STRING_LEN];
  126. char lpUrl[MY_MAX_STRING_LEN];
  127. ((NM_TREEVIEW *)lParam)->itemNew.mask = TVIF_TEXT;
  128. ((NM_TREEVIEW *)lParam)->itemNew.pszText = lpTempBuf;
  129. ((NM_TREEVIEW *)lParam)->itemNew.cchTextMax = MY_MAX_STRING_LEN;
  130. TreeView_GetItem(hwndTreeView, &((NM_TREEVIEW *)lParam)->itemNew);
  131. lstrcpy(lpUrl, lpPfx);
  132. lstrcat(lpUrl, ((NM_TREEVIEW *)lParam)->itemNew.pszText);
  133. ListEditView(hwndEdit, lpUrl);
  134. break;
  135. } //TVN_SELCHANGED
  136. }
  137. break;
  138. }
  139. case WM_DESTROY:
  140. {
  141. OleUninitialize();
  142. PostQuitMessage(0);
  143. return 0;
  144. }
  145. }
  146. return DefWindowProc(hwnd, iMsg, wParam, lParam);
  147. }
  148. BOOL ListTreeView(HWND hwnd)
  149. {
  150. LPSTR lpUrl = NULL;
  151. BYTE cei[MY_CACHE_ENTRY_INFO_SIZE];
  152. LPINTERNET_CACHE_ENTRY_INFO lpCE = (LPINTERNET_CACHE_ENTRY_INFO)cei;
  153. HTREEITEM htItem = NULL;
  154. DWORD cbSize = MY_CACHE_ENTRY_INFO_SIZE;
  155. HANDLE hCacheEntry = NULL;
  156. TV_ITEM tvi = {0};
  157. TV_INSERTSTRUCT tvins = {0};
  158. hCacheEntry = FindFirstUrlCacheEntry(lpPfx, lpCE, &cbSize);
  159. if (!hCacheEntry)
  160. return FALSE;
  161. // sanity check
  162. char sztmp[10];
  163. lstrcpyn(sztmp, lpCE->lpszSourceUrlName, lstrlen(lpPfx)+1);
  164. if (lstrcmpi(sztmp, lpPfx))
  165. {
  166. FindCloseUrlCache(hCacheEntry);
  167. return TRUE;
  168. }
  169. lpUrl = (LPSTR)GlobalAlloc(GPTR, MY_MAX_STRING_LEN);
  170. // add the length of the cache prefix string to the source url
  171. // name to skip the cache prefix .. was the quickest way to strip
  172. // the prefix from the url.
  173. lstrcpy(lpUrl, lpCE->lpszSourceUrlName+lstrlen(lpPfx));
  174. tvi.mask = TVIF_HANDLE | TVIF_TEXT;
  175. tvi.pszText = lpUrl;
  176. tvi.cchTextMax = lstrlen(lpUrl);
  177. tvins.item = tvi;
  178. tvins.hInsertAfter = TVI_FIRST;
  179. tvins.hParent = TVI_ROOT;
  180. TreeView_InsertItem(hwnd, &tvins);
  181. for ( ; ; )
  182. {
  183. cbSize = MY_CACHE_ENTRY_INFO_SIZE;
  184. if (!FindNextUrlCacheEntry(hCacheEntry, lpCE, &cbSize))
  185. break;
  186. lstrcpy(lpUrl, lpCE->lpszSourceUrlName+lstrlen(lpPfx));
  187. tvi.pszText = lpUrl;
  188. tvi.cchTextMax = lstrlen(lpUrl);
  189. tvins.item = tvi;
  190. tvins.hInsertAfter = TVI_LAST;
  191. TreeView_InsertItem(hwnd, &tvins);
  192. }
  193. FindCloseUrlCache(hCacheEntry);
  194. htItem = TreeView_GetRoot(hwnd);
  195. TreeView_SelectItem(hwnd, htItem);
  196. if (lpUrl)
  197. {
  198. GlobalFree(lpUrl);
  199. lpUrl = NULL;
  200. }
  201. return TRUE;
  202. }
  203. BOOL ListEditView(HWND hwnd, LPSTR lpUrl)
  204. {
  205. BYTE cei[MY_CACHE_ENTRY_INFO_SIZE];
  206. LPINTERNET_CACHE_ENTRY_INFO lpCE = (LPINTERNET_CACHE_ENTRY_INFO)cei;
  207. DWORD cbSize = MY_CACHE_ENTRY_INFO_SIZE;
  208. HANDLE hFile = NULL;
  209. DWORD dwFileSize = 0;
  210. // erase Edit window content
  211. Edit_SetText(hwnd, NULL);
  212. if(!GetUrlCacheEntryInfo(lpUrl, lpCE, &cbSize))
  213. return FALSE;
  214. hFile = CreateFile(lpCE->lpszLocalFileName, GENERIC_READ,
  215. FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  216. if (hFile == INVALID_HANDLE_VALUE)
  217. return FALSE;
  218. dwFileSize = GetFileSize(hFile, NULL);
  219. if (dwFileSize == 0)
  220. {
  221. CloseHandle(hFile);
  222. return FALSE;
  223. }
  224. LPTSTR lpBuf;
  225. DWORD dwBytesRead = 0;
  226. lpBuf = (LPTSTR)GlobalAlloc(LPTR, dwFileSize);
  227. if (!lpBuf)
  228. {
  229. CloseHandle(hFile);
  230. return FALSE;
  231. }
  232. if (!ReadFile(hFile, lpBuf, dwFileSize, &dwBytesRead, NULL) || dwBytesRead == 0)
  233. {
  234. CloseHandle(hFile);
  235. return FALSE;
  236. }
  237. /*
  238. // First to avoid displaying any leading spaces we'll walk through the file
  239. // we find the first non space character. When we find it, we'll set the file
  240. // pointer back 1 so the next time we call ReadFile getting the next byte we'll
  241. // be at the non-space character.
  242. DWORD dwBytesRead = 0;
  243. char ch;
  244. do
  245. {
  246. if (!ReadFile(hFile, &ch, 1, &dwBytesRead, NULL))
  247. {
  248. CloseHandle(hFile);
  249. return FALSE;
  250. }
  251. if (dwBytesRead == 0) // reach end-of-file, return now.
  252. {
  253. CloseHandle(hFile);
  254. return TRUE;
  255. }
  256. }
  257. while (ch == ' ');
  258. if (ch != ' ')
  259. SetFilePointer(hFile, -1, NULL, FILE_CURRENT);
  260. // Alloc a buffer large enough for the file plus 2 characters per line
  261. LPSTR lpBuffer = NULL;
  262. lpBuffer = (LPSTR)GlobalAlloc(GPTR, dwFileSize*2);
  263. if (!lpBuffer)
  264. {
  265. CloseHandle(hFile);
  266. return FALSE;
  267. }
  268. //lpBuffer = "\0";
  269. cbSize = 0;
  270. int cch = 0;
  271. BOOL bIsLeadChar = FALSE;
  272. BOOL bIsSecondChar = FALSE;
  273. char tmp[1024];
  274. LPSTR lpTmp = lpBuffer;
  275. tmp[0] = '\0';
  276. // N 1 08-19-1997 15:28:45 00:00:05\r\nN 1 08-19-1997 15:30:25 00:00:01
  277. for (;;)
  278. {
  279. if (!ReadFile(hFile, &ch, 1, &dwBytesRead, NULL))
  280. {
  281. // choked here,
  282. CloseHandle(hFile);
  283. GlobalFree(lpBuffer);
  284. return FALSE;
  285. }
  286. if (dwBytesRead == 0) // reach end-of-file
  287. break;
  288. switch (ch)
  289. {
  290. case '\n':
  291. wsprintf(tmp, "%c\r\n", ch);
  292. lstrcat(lpBuffer, tmp);
  293. break;
  294. case ' ':
  295. tmp[cch] = ch;
  296. cch ++;
  297. if (bIsLeadChar && bIsSecondChar)
  298. {
  299. if (cch == 5)
  300. {
  301. lpTmp[cbSize ++] = '\r';
  302. lpTmp[cbSize ++] = '\n';
  303. for (int i=1; i<cch; i++)
  304. lpTmp[cbSize ++] = tmp[i];
  305. cch = 0;
  306. }
  307. bIsLeadChar = FALSE;
  308. bIsSecondChar = FALSE;
  309. }
  310. break;
  311. case 'N':
  312. case 'S':
  313. case 'D':
  314. case 'T':
  315. case 'U':
  316. bIsLeadChar = (bIsSecondChar) ? FALSE : TRUE;
  317. tmp[cch] = ch;
  318. cch ++;
  319. break;
  320. case '1':
  321. case '0':
  322. bIsSecondChar = (bIsLeadChar) ? TRUE : FALSE;
  323. tmp[cch] = ch;
  324. cch ++;
  325. break;
  326. default:
  327. tmp[cch] = ch;
  328. cch ++;
  329. for (int i=0; i<cch; i++)
  330. lpTmp[cbSize++] = tmp[i];
  331. cch = 0;
  332. break;
  333. }
  334. }
  335. lpTmp[cbSize] = '\0';
  336. */
  337. Edit_SetText(hwnd, lpBuf);
  338. CloseHandle(hFile);
  339. if (lpBuf)
  340. GlobalFree(lpBuf);
  341. return TRUE;
  342. }
  343. /*
  344. // No need to read the cache prefix from the registry so we'll hard code it Log:
  345. //lpPfx = (LPSTR)GlobalAlloc(GPTR, lstrlen("Log:")+1);
  346. //lstrcpy(lpPfx, "Log:");
  347. #if 0
  348. lret = RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_TRACKING, 0,
  349. KEY_READ, &hKey);
  350. if (lret != ERROR_SUCCESS)
  351. {
  352. lret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_TRACKING, 0,
  353. KEY_READ, &hKey);
  354. }
  355. if (lret == ERROR_SUCCESS)
  356. {
  357. lret = RegQueryValueEx(hKey, REGSTR_VAL_CACHEPREFIX, 0, NULL, NULL, &cbPfx);
  358. if (lret == ERROR_SUCCESS)
  359. {
  360. lpPfx = (LPSTR)GlobalAlloc(GPTR, cbPfx+1);
  361. if (lpPfx)
  362. {
  363. lret = RegQueryValueEx(hKey, REGSTR_VAL_CACHEPREFIX, 0, NULL,
  364. (LPBYTE)lpPfx, &cbPfx);
  365. }
  366. }
  367. }
  368. if (hKey)
  369. {
  370. RegCloseKey(hKey);
  371. hKey = NULL;
  372. }
  373. #endif //0
  374. /////////////////////////////////////////////////////////////////////////////
  375. // Function: Hacked ModuleEntry for sources file
  376. /////////////////////////////////////////////////////////////////////////////
  377. HANDLE g_hProcessHeap = NULL;
  378. extern "C" int _stdcall ModuleEntry(void)
  379. {
  380. int i;
  381. STARTUPINFOA si;
  382. LPTSTR pszCmdLine;
  383. pszCmdLine = GetCommandLine();
  384. g_hProcessHeap = GetProcessHeap();
  385. //
  386. // We don't want the "No disk in drive X:" requesters, so we set
  387. // the critical error mask such that calls will just silently fail
  388. //
  389. SetErrorMode(SEM_FAILCRITICALERRORS);
  390. if ( *pszCmdLine == TEXT('\"') ) {
  391. //
  392. // Scan, and skip over, subsequent characters until
  393. // another double-quote or a null is encountered.
  394. //
  395. while ( *++pszCmdLine && (*pszCmdLine
  396. != TEXT('\"')) );
  397. //
  398. // If we stopped on a double-quote (usual case), skip
  399. // over it.
  400. //
  401. if ( *pszCmdLine == TEXT('\"') )
  402. pszCmdLine++;
  403. }
  404. else {
  405. while (*pszCmdLine > TEXT(' '))
  406. pszCmdLine++;
  407. }
  408. //
  409. // Skip past any white space preceeding the second token.
  410. //
  411. while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) {
  412. pszCmdLine++;
  413. }
  414. si.dwFlags = 0;
  415. GetStartupInfoA(&si);
  416. i = WinMain(GetModuleHandle(NULL), NULL, pszCmdLine,
  417. si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
  418. // Since we now have a way for an extension to tell us when it is finished,
  419. // we will terminate all processes when the main thread goes away.
  420. ExitProcess(i);
  421. // DebugMsg(DM_TRACE, TEXT("c.me: Cabinet main thread exiting without ExitProcess."));
  422. return i;
  423. }
  424. */