Leaked source code of windows server 2003
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.

456 lines
11 KiB

  1. // File: history.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "dirutil.h"
  5. #include "upropdlg.h"
  6. #include "history.h"
  7. // CCallLogEntry flags:
  8. const DWORD CLEF_ACCEPTED = 0x00000001;
  9. const DWORD CLEF_REJECTED = 0x00000002;
  10. const DWORD CLEF_AUTO_ACCEPTED = 0x00000004; // call was auto-accepted
  11. const DWORD CLEF_TIMED_OUT = 0x00000008; // call was rejected due to timeout
  12. const DWORD CLEF_SECURE = 0x00000010; // call was secure
  13. const DWORD CLEF_NO_CALL = 0x40000000; // No call back information
  14. const DWORD CLEF_DELETED = 0x80000000; // Record marked for deletion
  15. const WCHAR g_cszwULS[] = L"ULS:";
  16. static const int _rgIdMenu[] = {
  17. IDM_DLGCALL_DELETE,
  18. 0
  19. };
  20. /* C H I S T O R Y */
  21. /*-------------------------------------------------------------------------
  22. %%Function: CHISTORY
  23. -------------------------------------------------------------------------*/
  24. CHISTORY::CHISTORY() :
  25. CALV(IDS_DLGCALL_HISTORY, II_HISTORY, _rgIdMenu)
  26. {
  27. DbgMsg(iZONE_OBJECTS, "CHISTORY - Constructed(%08X)", this);
  28. RegEntry re(LOG_INCOMING_KEY, HKEY_CURRENT_USER);
  29. m_pszFile = PszAlloc(re.GetString(REGVAL_LOG_FILE));
  30. // Make sure file exists and can be read/written
  31. m_hFile = OpenLogFile();
  32. SetAvailable(NULL != m_hFile);
  33. }
  34. CHISTORY::~CHISTORY()
  35. {
  36. if (NULL != m_hFile)
  37. {
  38. CloseHandle(m_hFile);
  39. }
  40. delete m_pszFile;
  41. DbgMsg(iZONE_OBJECTS, "CHISTORY - Destroyed(%08X)", this);
  42. }
  43. int
  44. CHISTORY::Compare
  45. (
  46. LPARAM param1,
  47. LPARAM param2
  48. )
  49. {
  50. int ret = 0;
  51. LPTSTR pszName1, pszAddress1;
  52. LPTSTR pszName2, pszAddress2;
  53. LOGHDR logHdr1, logHdr2;
  54. if (SUCCEEDED(ReadEntry((DWORD)param1, &logHdr1, &pszName1, &pszAddress1)))
  55. {
  56. if (SUCCEEDED(ReadEntry((DWORD)param2, &logHdr2, &pszName2, &pszAddress2)))
  57. {
  58. FILETIME ft1, ft2;
  59. SystemTimeToFileTime(&logHdr1.sysTime, &ft1);
  60. SystemTimeToFileTime(&logHdr2.sysTime, &ft2);
  61. // Sort in reverse order so most recent is at the top
  62. ret = -CompareFileTime(&ft1, &ft2);
  63. delete pszName2;
  64. delete pszAddress2;
  65. }
  66. delete pszName1;
  67. delete pszAddress1;
  68. }
  69. return(ret);
  70. }
  71. int
  72. CALLBACK
  73. CHISTORY::StaticCompare
  74. (
  75. LPARAM param1,
  76. LPARAM param2,
  77. LPARAM pThis
  78. )
  79. {
  80. return(reinterpret_cast<CHISTORY*>(pThis)->Compare(param1, param2));
  81. }
  82. ///////////////////////////////////////////////////////////////////////////
  83. // CALV methods
  84. /* S H O W I T E M S */
  85. /*-------------------------------------------------------------------------
  86. %%Function: ShowItems
  87. -------------------------------------------------------------------------*/
  88. VOID CHISTORY::ShowItems(HWND hwnd)
  89. {
  90. CALV::SetHeader(hwnd, IDS_ADDRESS);
  91. TCHAR szReceived[CCHMAXSZ];
  92. if( FLoadString(IDS_RECEIVED, szReceived, CCHMAX(szReceived)) )
  93. {
  94. LV_COLUMN lvc;
  95. ClearStruct(&lvc);
  96. lvc.mask = LVCF_TEXT | LVCF_SUBITEM;
  97. lvc.pszText = szReceived;
  98. lvc.iSubItem = IDI_MISC1;
  99. ListView_InsertColumn(hwnd, IDI_MISC1, &lvc);
  100. }
  101. if (!FAvailable())
  102. return;
  103. LoadFileData(hwnd);
  104. ListView_SortItems( hwnd, StaticCompare, (LPARAM) this );
  105. }
  106. VOID CHISTORY::ClearItems(void)
  107. {
  108. CALV::ClearItems();
  109. HWND hWndListView = GetHwnd();
  110. if( IsWindow(hWndListView) )
  111. {
  112. ListView_DeleteColumn(hWndListView, IDI_MISC1);
  113. }
  114. }
  115. VOID CHISTORY::OnCommand(WPARAM wParam, LPARAM lParam)
  116. {
  117. switch (GET_WM_COMMAND_ID(wParam, lParam))
  118. {
  119. case IDM_DLGCALL_DELETE:
  120. CmdDelete();
  121. break;
  122. case IDM_DLGCALL_PROPERTIES:
  123. CmdProperties();
  124. break;
  125. default:
  126. CALV::OnCommand(wParam, lParam);
  127. break;
  128. }
  129. }
  130. VOID CHISTORY::CmdDelete(void)
  131. {
  132. int iItem = GetSelection();
  133. if (-1 == iItem)
  134. return;
  135. LPARAM lParam = LParamFromItem(iItem);
  136. if (SUCCEEDED(DeleteEntry((DWORD)lParam)))
  137. {
  138. DeleteItem(iItem);
  139. }
  140. }
  141. UINT CHISTORY::GetStatusString(DWORD dwCLEF)
  142. {
  143. if (CLEF_ACCEPTED & dwCLEF)
  144. return IDS_HISTORY_ACCEPTED;
  145. if (CLEF_TIMED_OUT & dwCLEF)
  146. return IDS_HISTORY_NOT_ANSWERED;
  147. ASSERT(CLEF_REJECTED & dwCLEF);
  148. return IDS_HISTORY_IGNORED;
  149. }
  150. VOID CHISTORY::CmdProperties(void)
  151. {
  152. int iItem = GetSelection();
  153. if (-1 == iItem)
  154. return;
  155. LPTSTR pszName;
  156. LPTSTR pszAddress;
  157. TCHAR szStatus[CCHMAXSZ];
  158. TCHAR szTime[CCHMAXSZ];
  159. LOGHDR logHdr;
  160. PBYTE pbCert = NULL;
  161. PCCERT_CONTEXT pCert = NULL;
  162. LPARAM lParam = LParamFromItem(iItem);
  163. if (SUCCEEDED(ReadEntry((DWORD)lParam, &logHdr, &pszName, &pszAddress)))
  164. {
  165. if (logHdr.dwCLEF & CLEF_SECURE) // is secure call
  166. {
  167. ASSERT(logHdr.cbCert);
  168. pbCert = new BYTE[logHdr.cbCert];
  169. if (FSetFilePos(lParam+sizeof(logHdr)+logHdr.cbName+logHdr.cbData))
  170. {
  171. if (FReadData(pbCert, logHdr.cbCert))
  172. {
  173. pCert = CertCreateCertificateContext(X509_ASN_ENCODING, pbCert, logHdr.cbCert);
  174. if (NULL == pCert)
  175. {
  176. WARNING_OUT(("Certificate in Call Log is damaged."));
  177. }
  178. }
  179. }
  180. delete []pbCert;
  181. }
  182. FLoadString(GetStatusString(logHdr.dwCLEF), szStatus, CCHMAX(szStatus));
  183. FmtDateTime(&logHdr.sysTime, szTime, CCHMAX(szTime));
  184. if (NULL == pszAddress)
  185. {
  186. pszAddress = PszLoadString(IDS_HISTORY_NO_ADDRESS);
  187. }
  188. UPROPDLGENTRY rgProp[] = {
  189. {IDS_UPROP_ADDRESS, pszAddress},
  190. {IDS_UPROP_STATUS, szStatus},
  191. {IDS_UPROP_RECEIVED, szTime},
  192. };
  193. CUserPropertiesDlg dlgUserProp(GetHwnd(), IDI_LARGE);
  194. dlgUserProp.DoModal(rgProp, ARRAY_ELEMENTS(rgProp), pszName, pCert);
  195. }
  196. if ( pCert )
  197. CertFreeCertificateContext ( pCert );
  198. delete pszName;
  199. delete pszAddress;
  200. }
  201. ///////////////////////////////////////////////////////////////////////////
  202. /* O P E N L O G F I L E */
  203. /*-------------------------------------------------------------------------
  204. %%Function: OpenLogFile
  205. Open the log file and return a handle to file.
  206. Return NULL if there was a problem.
  207. -------------------------------------------------------------------------*/
  208. HANDLE CHISTORY::OpenLogFile(VOID)
  209. {
  210. HANDLE hFile = CreateFile(m_pszFile, GENERIC_READ | GENERIC_WRITE,
  211. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  212. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  213. if (INVALID_HANDLE_VALUE == hFile)
  214. {
  215. ERROR_OUT(("OpenLogFile: Unable to open call log file"));
  216. hFile = NULL;
  217. }
  218. return hFile;
  219. }
  220. BOOL CHISTORY::FSetFilePos(DWORD dwOffset)
  221. {
  222. ASSERT(NULL != m_hFile);
  223. return (INVALID_FILE_SIZE != SetFilePointer(m_hFile, dwOffset, NULL, FILE_BEGIN));
  224. }
  225. /* L O A D F I L E D A T A */
  226. /*-------------------------------------------------------------------------
  227. %%Function: LoadFileData
  228. Load the call log data from the file
  229. -------------------------------------------------------------------------*/
  230. VOID CHISTORY::LoadFileData(HWND hwnd)
  231. {
  232. HANDLE hFile = OpenLogFile();
  233. if (NULL == hFile)
  234. return;
  235. LPTSTR pszName, pszAddress;
  236. LOGHDR logHdr;
  237. DWORD dwOffset = 0;
  238. HRESULT hr = S_OK;
  239. while (SUCCEEDED(hr))
  240. {
  241. hr = ReadEntry(dwOffset, &logHdr, &pszName, &pszAddress);
  242. if (S_OK == hr)
  243. {
  244. TCHAR szTime[CCHMAXSZ];
  245. FmtDateTime(&logHdr.sysTime, szTime, CCHMAX(szTime));
  246. DlgCallAddItem(hwnd, pszName, pszAddress, II_COMPUTER, dwOffset, 0,
  247. szTime);
  248. }
  249. dwOffset += logHdr.dwSize;
  250. delete pszName;
  251. pszName = NULL;
  252. delete pszAddress;
  253. pszAddress = NULL;
  254. }
  255. CloseHandle(hFile);
  256. }
  257. /* R E A D E N T R Y */
  258. /*-------------------------------------------------------------------------
  259. %%Function: ReadEntry
  260. Read the next entry from the file.
  261. Return Values:
  262. S_OK - data was read successfully
  263. S_FALSE - data exists, but was deleted
  264. E_FAIL - problem reading file
  265. -------------------------------------------------------------------------*/
  266. HRESULT CHISTORY::ReadEntry(DWORD dwOffset,
  267. LOGHDR * pLogHdr, LPTSTR * ppszName, LPTSTR * ppszAddress)
  268. {
  269. ASSERT(NULL != m_hFile);
  270. *ppszName = NULL;
  271. *ppszAddress = NULL;
  272. if (!FSetFilePos(dwOffset))
  273. return E_FAIL;
  274. // Read record header
  275. if (!FReadData(pLogHdr, sizeof(LOGHDR)) )
  276. return E_FAIL;
  277. // Read Name
  278. WCHAR szwName[CCHMAXSZ_NAME];
  279. if (!FReadData(szwName, min(pLogHdr->cbName, sizeof(szwName))))
  280. return E_FAIL;
  281. *ppszName = PszFromBstr(szwName);
  282. if (FReadData(szwName, min(pLogHdr->cbData, sizeof(szwName))))
  283. {
  284. LPCWSTR pchw = _StrStrW(szwName, g_cszwULS);
  285. if (NULL != pchw)
  286. {
  287. pchw += CCHMAX(g_cszwULS)-1; // -1 for NULL
  288. *ppszAddress = PszFromBstr(pchw);
  289. }
  290. }
  291. return (0 == (pLogHdr->dwCLEF & CLEF_DELETED)) ? S_OK : S_FALSE;
  292. }
  293. /* R E A D D A T A */
  294. /*-------------------------------------------------------------------------
  295. %%Function: FReadData
  296. -------------------------------------------------------------------------*/
  297. BOOL CHISTORY::FReadData(PVOID pv, UINT cb)
  298. {
  299. DWORD cbRead;
  300. ASSERT(NULL != m_hFile);
  301. ASSERT(NULL != pv);
  302. if (0 == cb)
  303. return TRUE;
  304. if (!ReadFile(m_hFile, pv, cb, &cbRead, NULL))
  305. return FALSE;
  306. return (cb == cbRead);
  307. }
  308. /* D E L E T E E N T R Y */
  309. /*-------------------------------------------------------------------------
  310. %%Function: DeleteEntry
  311. Delete a single entry.
  312. -------------------------------------------------------------------------*/
  313. HRESULT CHISTORY::DeleteEntry(DWORD dwOffset)
  314. {
  315. // Calculate offset to "CLEF"
  316. dwOffset += FIELD_OFFSET(LOGHDR,dwCLEF);
  317. if (!FSetFilePos(dwOffset))
  318. return E_FAIL;
  319. DWORD dwFlags;
  320. if (!FReadData(&dwFlags, sizeof(dwFlags)))
  321. return E_FAIL;
  322. dwFlags = dwFlags | CLEF_DELETED;
  323. if (!FSetFilePos(dwOffset))
  324. return E_FAIL;
  325. return WriteData(&dwOffset, &dwFlags, sizeof(dwFlags));
  326. }
  327. /* W R I T E D A T A */
  328. /*-------------------------------------------------------------------------
  329. %%Function: WriteData
  330. Write the data to the file.
  331. The file will be automatically opened/close if hFile is NULL.
  332. -------------------------------------------------------------------------*/
  333. HRESULT CHISTORY::WriteData(LPDWORD pdwOffset, PVOID pv, DWORD cb)
  334. {
  335. ASSERT(NULL != m_hFile);
  336. ASSERT(0 != cb);
  337. ASSERT(NULL != pv);
  338. ASSERT(NULL != pdwOffset);
  339. ASSERT(INVALID_FILE_SIZE != *pdwOffset);
  340. HRESULT hr = E_FAIL;
  341. if (FSetFilePos(*pdwOffset))
  342. {
  343. DWORD cbWritten;
  344. if (WriteFile(m_hFile, pv, cb, &cbWritten, NULL) && (cb == cbWritten))
  345. {
  346. *pdwOffset += cbWritten;
  347. hr = S_OK;
  348. }
  349. }
  350. return hr;
  351. }