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.

1149 lines
36 KiB

  1. //+---------------------------------------------------------------------------
  2. /////////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 2000-2001.
  6. //
  7. // File: SaferEntryHashPropertyPage.cpp
  8. //
  9. // Contents: Implementation of CSaferEntryHashPropertyPage
  10. //
  11. //----------------------------------------------------------------------------
  12. // SaferEntryHashPropertyPage.cpp : implementation file
  13. //
  14. #include "stdafx.h"
  15. #include <gpedit.h>
  16. #include "certmgr.h"
  17. #include "compdata.h"
  18. #include "SaferEntryHashPropertyPage.h"
  19. #include "SaferUtil.h"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. PCWSTR pcszNEWLINE = L"\x00d\x00a";
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CSaferEntryHashPropertyPage property page
  28. CSaferEntryHashPropertyPage::CSaferEntryHashPropertyPage(
  29. CSaferEntry& rSaferEntry,
  30. LONG_PTR lNotifyHandle,
  31. LPDATAOBJECT pDataObject,
  32. bool bReadOnly,
  33. CCertMgrComponentData* pCompData,
  34. bool bIsMachine)
  35. : CHelpPropertyPage(CSaferEntryHashPropertyPage::IDD),
  36. m_rSaferEntry (rSaferEntry),
  37. m_bDirty (false),
  38. m_cbFileHash (0),
  39. m_lNotifyHandle (lNotifyHandle),
  40. m_pDataObject (pDataObject),
  41. m_bReadOnly (bReadOnly),
  42. m_bIsMachine (bIsMachine),
  43. m_hashAlgid (0),
  44. m_bFirst (true),
  45. m_pCompData (pCompData)
  46. {
  47. ::ZeroMemory (&m_nFileSize, sizeof (__int64));
  48. ::ZeroMemory (m_rgbFileHash, SAFER_MAX_HASH_SIZE);
  49. //{{AFX_DATA_INIT(CSaferEntryHashPropertyPage)
  50. // NOTE: the ClassWizard will add member initialization here
  51. //}}AFX_DATA_INIT
  52. m_rSaferEntry.AddRef ();
  53. m_rSaferEntry.IncrementOpenPageCount ();
  54. m_rSaferEntry.GetHash (m_rgbFileHash, m_cbFileHash, m_nFileSize,
  55. m_hashAlgid);
  56. }
  57. CSaferEntryHashPropertyPage::~CSaferEntryHashPropertyPage()
  58. {
  59. if ( m_lNotifyHandle )
  60. MMCFreeNotifyHandle (m_lNotifyHandle);
  61. m_rSaferEntry.DecrementOpenPageCount ();
  62. m_rSaferEntry.Release ();
  63. }
  64. void CSaferEntryHashPropertyPage::DoDataExchange(CDataExchange* pDX)
  65. {
  66. CHelpPropertyPage::DoDataExchange(pDX);
  67. //{{AFX_DATA_MAP(CSaferEntryHashPropertyPage)
  68. DDX_Control(pDX, IDC_HASH_ENTRY_HASHFILE_DETAILS, m_hashFileDetailsEdit);
  69. DDX_Control(pDX, IDC_HASH_ENTRY_DESCRIPTION, m_descriptionEdit);
  70. DDX_Control(pDX, IDC_HASH_ENTRY_SECURITY_LEVEL, m_securityLevelCombo);
  71. //}}AFX_DATA_MAP
  72. }
  73. BEGIN_MESSAGE_MAP(CSaferEntryHashPropertyPage, CHelpPropertyPage)
  74. //{{AFX_MSG_MAP(CSaferEntryHashPropertyPage)
  75. ON_BN_CLICKED(IDC_HASH_ENTRY_BROWSE, OnHashEntryBrowse)
  76. ON_EN_CHANGE(IDC_HASH_ENTRY_DESCRIPTION, OnChangeHashEntryDescription)
  77. ON_CBN_SELCHANGE(IDC_HASH_ENTRY_SECURITY_LEVEL, OnSelchangeHashEntrySecurityLevel)
  78. ON_EN_CHANGE(IDC_HASH_HASHED_FILE_PATH, OnChangeHashHashedFilePath)
  79. ON_EN_SETFOCUS(IDC_HASH_HASHED_FILE_PATH, OnSetfocusHashHashedFilePath)
  80. ON_EN_CHANGE(IDC_HASH_ENTRY_HASHFILE_DETAILS, OnChangeHashEntryHashfileDetails)
  81. //}}AFX_MSG_MAP
  82. END_MESSAGE_MAP()
  83. /////////////////////////////////////////////////////////////////////////////
  84. // CSaferEntryHashPropertyPage message handlers
  85. void CSaferEntryHashPropertyPage::DoContextHelp (HWND hWndControl)
  86. {
  87. _TRACE (1, L"Entering CSaferEntryHashPropertyPage::DoContextHelp\n");
  88. static const DWORD help_map[] =
  89. {
  90. IDC_HASH_ENTRY_HASHFILE_DETAILS, IDH_HASH_ENTRY_APPLICATION_NAME,
  91. IDC_HASH_ENTRY_BROWSE, IDH_HASH_ENTRY_BROWSE,
  92. IDC_HASH_ENTRY_DESCRIPTION, IDH_HASH_ENTRY_DESCRIPTION,
  93. IDC_HASH_ENTRY_LAST_MODIFIED, IDH_HASH_ENTRY_LAST_MODIFIED,
  94. IDC_HASH_HASHED_FILE_PATH, IDH_HASH_HASHED_FILE_PATH,
  95. IDC_HASH_ENTRY_SECURITY_LEVEL, IDH_HASH_ENTRY_SECURITY_LEVEL,
  96. 0, 0
  97. };
  98. switch (::GetDlgCtrlID (hWndControl))
  99. {
  100. case IDC_HASH_ENTRY_HASHFILE_DETAILS:
  101. case IDC_HASH_ENTRY_BROWSE:
  102. case IDC_HASH_ENTRY_DESCRIPTION:
  103. case IDC_HASH_ENTRY_LAST_MODIFIED:
  104. case IDC_HASH_HASHED_FILE_PATH:
  105. case IDC_HASH_ENTRY_SECURITY_LEVEL:
  106. if ( !::WinHelp (
  107. hWndControl,
  108. GetF1HelpFilename(),
  109. HELP_WM_HELP,
  110. (DWORD_PTR) help_map) )
  111. {
  112. _TRACE (0, L"WinHelp () failed: 0x%x\n", GetLastError ());
  113. }
  114. break;
  115. default:
  116. break;
  117. }
  118. _TRACE (-1, L"Leaving CSaferEntryHashPropertyPage::DoContextHelp\n");
  119. }
  120. BOOL CSaferEntryHashPropertyPage::OnInitDialog()
  121. {
  122. CHelpPropertyPage::OnInitDialog();
  123. DWORD dwFlags = 0;
  124. m_rSaferEntry.GetFlags (dwFlags);
  125. ASSERT (m_pCompData);
  126. if ( m_pCompData )
  127. {
  128. CPolicyKey policyKey (m_pCompData->m_pGPEInformation,
  129. SAFER_HKLM_REGBASE,
  130. m_bIsMachine);
  131. InitializeSecurityLevelComboBox (m_securityLevelCombo, false,
  132. m_rSaferEntry.GetLevel (), policyKey.GetKey (),
  133. m_pCompData->m_pdwSaferLevels,
  134. m_bIsMachine);
  135. m_hashFileDetailsEdit.SetWindowText (m_rSaferEntry.GetHashFriendlyName ());
  136. m_descriptionEdit.LimitText (SAFER_MAX_DESCRIPTION_SIZE);
  137. m_descriptionEdit.SetWindowText (m_rSaferEntry.GetDescription ());
  138. SetDlgItemText (IDC_HASH_ENTRY_LAST_MODIFIED, m_rSaferEntry.GetLongLastModified ());
  139. SendDlgItemMessage (IDC_HASH_HASHED_FILE_PATH, EM_LIMITTEXT, 64);
  140. if ( m_bReadOnly )
  141. {
  142. SendDlgItemMessage (IDC_HASH_HASHED_FILE_PATH, EM_SETREADONLY, TRUE);
  143. m_securityLevelCombo.EnableWindow (FALSE);
  144. GetDlgItem (IDC_HASH_ENTRY_BROWSE)->EnableWindow (FALSE);
  145. m_descriptionEdit.SendMessage (EM_SETREADONLY, TRUE);
  146. m_hashFileDetailsEdit.SendMessage (EM_SETREADONLY, TRUE);
  147. }
  148. if ( m_cbFileHash )
  149. {
  150. // Only allow editing on the creation of a new hash
  151. SendDlgItemMessage (IDC_HASH_HASHED_FILE_PATH, EM_SETREADONLY, TRUE);
  152. FormatAndDisplayHash ();
  153. CString szText;
  154. VERIFY (szText.LoadString (IDS_HASH_TITLE));
  155. SetDlgItemText (IDC_HASH_TITLE, szText);
  156. SetDlgItemText (IDC_HASH_INSTRUCTIONS, L"");
  157. }
  158. else
  159. SetDlgItemText (IDC_DATE_LAST_MODIFIED_LABEL, L"");
  160. }
  161. return TRUE; // return TRUE unless you set the focus to a control
  162. // EXCEPTION: OCX Property Pages should return FALSE
  163. }
  164. typedef struct tagVERHEAD {
  165. WORD wTotLen;
  166. WORD wValLen;
  167. WORD wType; /* always 0 */
  168. WCHAR szKey[(sizeof("VS_VERSION_INFO")+3)&~03];
  169. VS_FIXEDFILEINFO vsf;
  170. } VERHEAD ;
  171. /*
  172. * [alanau]
  173. *
  174. * MyGetFileVersionInfo: Maps a file directly without using LoadLibrary. This ensures
  175. * that the right version of the file is examined without regard to where the loaded image
  176. * is. Since this is a local function, it allocates the memory which is freed by the caller.
  177. * This makes it slightly more efficient than a GetFileVersionInfoSize/GetFileVersionInfo pair.
  178. */
  179. BOOL CSaferEntryHashPropertyPage::MyGetFileVersionInfo(LPTSTR lpszFilename, LPVOID *lpVersionInfo)
  180. {
  181. // VS_FIXEDFILEINFO *pvsFFI = NULL;
  182. // UINT uiBytes = 0;
  183. HINSTANCE hinst = 0;
  184. HRSRC hVerRes = 0;
  185. HANDLE FileHandle = NULL;
  186. HANDLE MappingHandle = NULL;
  187. LPVOID DllBase = NULL;
  188. VERHEAD *pVerHead = 0;
  189. BOOL bResult = FALSE;
  190. DWORD dwHandle = 0;
  191. DWORD dwLength = 0;
  192. if (!lpVersionInfo)
  193. return FALSE;
  194. *lpVersionInfo = NULL;
  195. FileHandle = CreateFile( lpszFilename,
  196. GENERIC_READ,
  197. FILE_SHARE_READ,
  198. NULL,
  199. OPEN_EXISTING,
  200. 0,
  201. NULL
  202. );
  203. if (FileHandle == INVALID_HANDLE_VALUE)
  204. goto Cleanup;
  205. MappingHandle = CreateFileMapping( FileHandle,
  206. NULL,
  207. PAGE_READONLY,
  208. 0,
  209. 0,
  210. NULL
  211. );
  212. if (MappingHandle == NULL)
  213. goto Cleanup;
  214. DllBase = MapViewOfFileEx( MappingHandle,
  215. FILE_MAP_READ,
  216. 0,
  217. 0,
  218. 0,
  219. NULL
  220. );
  221. if (DllBase == NULL)
  222. goto Cleanup;
  223. hinst = (HMODULE)((ULONG_PTR)DllBase | 0x00000001);
  224. __try {
  225. hVerRes = FindResource(hinst, MAKEINTRESOURCE(VS_VERSION_INFO), VS_FILE_INFO);
  226. if (hVerRes == NULL)
  227. {
  228. // Probably a 16-bit file. Fall back to system APIs.
  229. dwLength = GetFileVersionInfoSize(lpszFilename, &dwHandle);
  230. if( !dwLength )
  231. {
  232. if(!GetLastError())
  233. SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
  234. __leave;
  235. }
  236. *lpVersionInfo = ::LocalAlloc (LPTR, dwLength);
  237. if ( !(*lpVersionInfo) )
  238. __leave;
  239. if(!GetFileVersionInfo(lpszFilename, 0, dwLength, *lpVersionInfo))
  240. __leave;
  241. bResult = TRUE;
  242. __leave;
  243. }
  244. pVerHead = (VERHEAD*)LoadResource(hinst, hVerRes);
  245. if (pVerHead == NULL)
  246. __leave;
  247. *lpVersionInfo = ::LocalAlloc (LPTR, pVerHead->wTotLen + pVerHead->wTotLen/2);
  248. if (*lpVersionInfo == NULL)
  249. __leave;
  250. memcpy(*lpVersionInfo, (PVOID)pVerHead, pVerHead->wTotLen);
  251. bResult = TRUE;
  252. } __except (EXCEPTION_EXECUTE_HANDLER)
  253. {
  254. }
  255. Cleanup:
  256. if (FileHandle)
  257. CloseHandle(FileHandle);
  258. if (MappingHandle)
  259. CloseHandle(MappingHandle);
  260. if (DllBase)
  261. UnmapViewOfFile(DllBase);
  262. if (*lpVersionInfo && bResult == FALSE)
  263. ::LocalFree (*lpVersionInfo);
  264. return bResult;
  265. }
  266. ///////////////////////////////////////////////////////////////////////////////
  267. //
  268. // Method: OnHashEntryBrowse
  269. //
  270. // Purpose: Allow the user to browse for a file, then create a hash and an
  271. // output string for use as the friendly name, using the following
  272. // rules:
  273. //
  274. // If either the product name or description information is found in
  275. // the version resource, provide the following (in order):
  276. //
  277. // Description
  278. // Product name
  279. // Company name
  280. // File name
  281. // Fixed file version
  282. //
  283. // Details:
  284. // 1) Use the fixed file version, since that is what is shown in the
  285. // Windows Explorer properties.
  286. // 2) Prefer the long file name to the 8.3 name.
  287. // 3) Delimit the fields with '\n'.
  288. // 4) If the field is missing, don't output the field or the delimiter
  289. // 5) Instead of displaying the file version on a new line, display
  290. // it after the file name in parens, as in "Filename (1.0.0.0)"
  291. // 6) Since we are limited to 256 TCHARs, we have to accomodate long
  292. // text. First, format the text as described above to determine
  293. // its length. If it is too long, truncate one field at a time in
  294. // the following order: Company name, Description, Product name.
  295. // To truncate a field, set it to a maximum of 60 TCHARs, then
  296. // append a "...\n" to visually indicate that the field was
  297. // truncated. Lastly, if the text is still to long, use the 8.3
  298. // file name instead of the long filename.
  299. //
  300. // If neither the product name nor description information is found,
  301. // provide the following (in order):
  302. //
  303. // File name
  304. // File size
  305. // File last modified date
  306. //
  307. // Details:
  308. // 1) If the file size is < 1 KB, display the number in bytes, as in
  309. // "123 bytes". If the file size is >= 1 KB, display in KB, as in
  310. // "123 KB". Of course, 1 KB is 1024 bytes. Note that the older
  311. // style format "123K" is no longer used in Windows.
  312. // 2) For the last modified date, use the short format version in the
  313. // user's current locale.
  314. // 3) Delimit the fields with '\n'.
  315. // 4) If the field is missing, don't output the field or the delimiter
  316. //
  317. ///////////////////////////////////////////////////////////////////////////////
  318. void CSaferEntryHashPropertyPage::OnHashEntryBrowse()
  319. {
  320. CString szFileFilter;
  321. VERIFY (szFileFilter.LoadString (IDS_SAFER_PATH_ENTRY_FILE_FILTER));
  322. // replace "|" with 0;
  323. const size_t nFilterLen = wcslen (szFileFilter) + 1;
  324. PWSTR pszFileFilter = new WCHAR [nFilterLen];
  325. if ( pszFileFilter )
  326. {
  327. wcscpy (pszFileFilter, szFileFilter);
  328. for (int nIndex = 0; nIndex < nFilterLen; nIndex++)
  329. {
  330. if ( L'|' == pszFileFilter[nIndex] )
  331. pszFileFilter[nIndex] = 0;
  332. }
  333. WCHAR szFile[MAX_PATH];
  334. ::ZeroMemory (szFile, MAX_PATH * sizeof (WCHAR));
  335. wcscpy (szFile, m_szLastOpenedFile);
  336. OPENFILENAME ofn;
  337. ::ZeroMemory (&ofn, sizeof (OPENFILENAME));
  338. ofn.lStructSize = sizeof (OPENFILENAME);
  339. ofn.hwndOwner = m_hWnd;
  340. ofn.lpstrFilter = (PCWSTR) pszFileFilter;
  341. ofn.lpstrFile = szFile;
  342. ofn.nMaxFile = MAX_PATH;
  343. ofn.Flags = OFN_DONTADDTORECENT |
  344. OFN_FORCESHOWHIDDEN | OFN_HIDEREADONLY;
  345. CThemeContextActivator activator;
  346. BOOL bResult = ::GetOpenFileName (&ofn);
  347. if ( bResult )
  348. {
  349. m_szLastOpenedFile = ofn.lpstrFile;
  350. HANDLE hFile = ::CreateFile(
  351. ofn.lpstrFile, // file name
  352. GENERIC_READ, // access mode
  353. FILE_SHARE_READ, // share mode
  354. 0, // SD
  355. OPEN_EXISTING, // how to create
  356. FILE_ATTRIBUTE_NORMAL, // file attributes
  357. 0 ); // handle to template file
  358. if ( INVALID_HANDLE_VALUE != hFile )
  359. {
  360. bResult = GetFileSizeEx(
  361. hFile, // handle to file
  362. (PLARGE_INTEGER) &m_nFileSize); // file size
  363. if ( !bResult )
  364. {
  365. DWORD dwErr = GetLastError ();
  366. CloseHandle (hFile);
  367. _TRACE (0, L"GetFileSizeEx () failed: 0x%x\n", dwErr);
  368. CString text;
  369. CString caption;
  370. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  371. text.FormatMessage (IDS_CANNOT_GET_FILESIZE, ofn.lpstrFile,
  372. GetSystemMessage (dwErr));
  373. MessageBox (text, caption, MB_OK);
  374. return;
  375. }
  376. if ( 0 == m_nFileSize )
  377. {
  378. CString text;
  379. CString caption;
  380. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  381. text.FormatMessage (IDS_ZERO_BYTE_FILE_CANNOT_HASH, ofn.lpstrFile);
  382. MessageBox (text, caption, MB_OK);
  383. return;
  384. }
  385. FILETIME ftLastModified;
  386. bResult = ::GetFileTime (hFile, // handle to file
  387. 0, // creation time
  388. 0, // last access time
  389. &ftLastModified); // last write time
  390. ::ZeroMemory (m_rgbFileHash, SAFER_MAX_HASH_SIZE);
  391. HRESULT hr = GetSignedFileHash (ofn.lpstrFile, m_rgbFileHash,
  392. &m_cbFileHash, &m_hashAlgid);
  393. if ( FAILED (hr) )
  394. {
  395. m_hashAlgid = 0;
  396. hr = ComputeMD5Hash (hFile, m_rgbFileHash, m_cbFileHash);
  397. if ( SUCCEEDED (hr) )
  398. {
  399. if ( SHA1_HASH_LEN == m_cbFileHash )
  400. m_hashAlgid = CALG_SHA;
  401. else if ( MD5_HASH_LEN == m_cbFileHash )
  402. m_hashAlgid = CALG_MD5;
  403. else
  404. {
  405. ASSERT (0);
  406. }
  407. }
  408. }
  409. VERIFY (CloseHandle (hFile));
  410. hFile = 0;
  411. if ( SUCCEEDED (hr) )
  412. {
  413. FormatAndDisplayHash ();
  414. PBYTE pData = 0;
  415. bResult = MyGetFileVersionInfo (ofn.lpstrFile, (LPVOID*) &pData);
  416. if ( bResult )
  417. {
  418. CString infoString = BuildHashFileInfoString (pData);
  419. m_hashFileDetailsEdit.SetWindowText (infoString);
  420. m_bDirty = true;
  421. SetModified ();
  422. }
  423. else
  424. {
  425. CString infoString (wcsrchr(ofn.lpstrFile, L'\\') + 1);
  426. CString szDate;
  427. infoString += pcszNEWLINE;
  428. WCHAR szBuffer[32];
  429. CString szText;
  430. if ( m_nFileSize < 1024 )
  431. {
  432. wsprintf (szBuffer, L"%u", m_nFileSize);
  433. infoString += szBuffer;
  434. VERIFY (szText.LoadString (IDS_BYTES));
  435. infoString += L" ";
  436. infoString += szText;
  437. }
  438. else
  439. {
  440. __int64 nFileSize = m_nFileSize;
  441. nFileSize += 1024; // this causes us to round up
  442. nFileSize /= 1024;
  443. wsprintf (szBuffer, L"%u ", nFileSize);
  444. infoString += szBuffer;
  445. VERIFY (szText.LoadString (IDS_KB));
  446. infoString += L" ";
  447. infoString += szText;
  448. }
  449. hr = FormatDate (ftLastModified, szDate,
  450. DATE_SHORTDATE, true);
  451. if ( SUCCEEDED (hr) )
  452. {
  453. infoString += pcszNEWLINE;
  454. infoString += szDate;
  455. }
  456. m_hashFileDetailsEdit.SetWindowText (infoString);
  457. m_bDirty = true;
  458. SetModified ();
  459. }
  460. ::LocalFree (pData);
  461. }
  462. else
  463. {
  464. CString text;
  465. CString caption;
  466. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  467. text.FormatMessage (IDS_CANNOT_HASH_FILE, ofn.lpstrFile,
  468. GetSystemMessage (hr));
  469. MessageBox (text, caption, MB_OK);
  470. }
  471. }
  472. else
  473. {
  474. DWORD dwErr = GetLastError ();
  475. _TRACE (0, L"CreateFile (%s, OPEN_EXISTING) failed: 0x%x\n",
  476. ofn.lpstrFile, dwErr);
  477. CString text;
  478. CString caption;
  479. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  480. text.FormatMessage (IDS_FILE_CANNOT_BE_READ, ofn.lpstrFile,
  481. GetSystemMessage (dwErr));
  482. MessageBox (text, caption, MB_OK);
  483. }
  484. }
  485. delete [] pszFileFilter;
  486. }
  487. }
  488. /***************************************************************************\
  489. *
  490. * BuildHashFileInfoString()
  491. *
  492. * Given a file name, GetVersion retrieves the version
  493. * information from the specified file.
  494. *
  495. *
  496. \***************************************************************************/
  497. const PWSTR VERSION_INFO_KEY_ROOT = L"\\StringFileInfo\\";
  498. CString CSaferEntryHashPropertyPage::BuildHashFileInfoString (PVOID pData)
  499. {
  500. CString szInfoString;
  501. PVOID lpInfo = 0;
  502. UINT cch = 0;
  503. CString key;
  504. WCHAR szBuffer[10];
  505. CString keyBase;
  506. wsprintf (szBuffer, L"%04X", GetUserDefaultLangID ());
  507. wcscat (szBuffer, L"04B0");
  508. keyBase = VERSION_INFO_KEY_ROOT;
  509. keyBase += szBuffer;
  510. keyBase += L"\\";
  511. CString productName;
  512. CString description;
  513. CString companyName;
  514. CString fileName;
  515. CString fileVersion;
  516. key = keyBase + L"ProductName";
  517. if ( VerQueryValue (pData, const_cast <PWSTR>((PCWSTR) key), &lpInfo, &cch) )
  518. {
  519. productName = (PWSTR) lpInfo;
  520. }
  521. key = keyBase + L"FileDescription";
  522. if ( VerQueryValue (pData, const_cast <PWSTR>((PCWSTR) key), &lpInfo, &cch) )
  523. {
  524. description = (PWSTR) lpInfo;
  525. }
  526. key = keyBase + L"CompanyName";
  527. if ( VerQueryValue (pData, const_cast <PWSTR>((PCWSTR) key), &lpInfo, &cch) )
  528. {
  529. companyName = (PWSTR) lpInfo;
  530. }
  531. key = keyBase + L"OriginalFilename";
  532. if ( VerQueryValue (pData, const_cast <PWSTR>((PCWSTR) key), &lpInfo, &cch) )
  533. {
  534. fileName = (PWSTR) lpInfo;
  535. }
  536. // Get Fixedlength fileInfo
  537. VS_FIXEDFILEINFO *pFixedFileInfo = 0;
  538. if ( VerQueryValue (pData, L"\\", (PVOID*) &pFixedFileInfo, &cch) )
  539. {
  540. WCHAR szFileVer[32];
  541. wsprintf(szFileVer, L"%u.%u.%u.%u",
  542. HIWORD(pFixedFileInfo->dwFileVersionMS),
  543. LOWORD(pFixedFileInfo->dwFileVersionMS),
  544. HIWORD(pFixedFileInfo->dwFileVersionLS),
  545. LOWORD(pFixedFileInfo->dwFileVersionLS));
  546. fileVersion = szFileVer;
  547. }
  548. int nLen = 0;
  549. do {
  550. szInfoString = ConcatStrings (productName, description, companyName, fileName, fileVersion);
  551. nLen = szInfoString.GetLength ();
  552. if ( nLen >= SAFER_MAX_FRIENDLYNAME_SIZE )
  553. {
  554. if ( CheckLengthAndTruncateToken (companyName) )
  555. continue;
  556. if ( CheckLengthAndTruncateToken (description) )
  557. continue;
  558. if ( CheckLengthAndTruncateToken (productName) )
  559. continue;
  560. szInfoString.SetAt (SAFER_MAX_FRIENDLYNAME_SIZE-4, 0);
  561. szInfoString += L"...";
  562. }
  563. } while (nLen >= SAFER_MAX_FRIENDLYNAME_SIZE);
  564. return szInfoString;
  565. }
  566. bool CSaferEntryHashPropertyPage::CheckLengthAndTruncateToken (CString& token)
  567. {
  568. bool bResult = false;
  569. const int nMAX_ITEM_LEN = 60;
  570. int nItemLen = token.GetLength ();
  571. if ( nItemLen > nMAX_ITEM_LEN )
  572. {
  573. token.SetAt (nMAX_ITEM_LEN-5, 0);
  574. token += L"...";
  575. token += pcszNEWLINE;
  576. bResult = true;
  577. }
  578. return bResult;
  579. }
  580. CString CSaferEntryHashPropertyPage::ConcatStrings (
  581. const CString& productName,
  582. const CString& description,
  583. const CString& companyName,
  584. const CString& fileName,
  585. const CString& fileVersion)
  586. {
  587. CString szInfoString;
  588. if ( !description.IsEmpty () )
  589. szInfoString += description + pcszNEWLINE;
  590. if ( !productName.IsEmpty () )
  591. szInfoString += productName + pcszNEWLINE;
  592. if ( !companyName.IsEmpty () )
  593. szInfoString += companyName + pcszNEWLINE;
  594. if ( !fileName.IsEmpty () )
  595. szInfoString += fileName;
  596. if ( !fileVersion.IsEmpty () )
  597. {
  598. szInfoString += L" (";
  599. szInfoString += fileVersion + L")";;
  600. }
  601. return szInfoString;
  602. }
  603. BOOL CSaferEntryHashPropertyPage::OnApply()
  604. {
  605. CString szText;
  606. CThemeContextActivator activator;
  607. GetDlgItemText (IDC_HASH_HASHED_FILE_PATH, szText);
  608. if ( szText.IsEmpty () )
  609. {
  610. CString szCaption;
  611. VERIFY (szCaption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  612. VERIFY (szText.LoadString (IDS_USER_MUST_ENTER_HASH));
  613. MessageBox (szText, szCaption, MB_OK);
  614. GetDlgItem (IDC_HASH_HASHED_FILE_PATH)->SetFocus ();
  615. return FALSE;
  616. }
  617. if ( !m_bReadOnly && m_bDirty )
  618. {
  619. if ( !ConvertStringToHash ((PCWSTR) szText) )
  620. {
  621. GetDlgItem (IDC_HASH_HASHED_FILE_PATH)->SetFocus ();
  622. return FALSE;
  623. }
  624. // Get image size and hash type
  625. bool bBadFormat = false;
  626. int nFirstColon = szText.Find (L":", 0);
  627. if ( -1 != nFirstColon )
  628. {
  629. int nSecondColon = szText.Find (L":", nFirstColon+1);
  630. if ( -1 != nSecondColon )
  631. {
  632. CString szImageSize = szText.Mid (nFirstColon+1, nSecondColon - (nFirstColon + 1));
  633. CString szHashType = szText.Right (((int) wcslen (szText)) - (nSecondColon + 1));
  634. m_nFileSize = wcstol (szImageSize, 0, 10);
  635. m_hashAlgid = wcstol (szHashType, 0, 10);
  636. }
  637. else
  638. bBadFormat = true;
  639. }
  640. else
  641. bBadFormat = true;
  642. if ( bBadFormat )
  643. {
  644. CString caption;
  645. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  646. VERIFY (szText.LoadString (IDS_HASH_STRING_BAD_FORMAT));
  647. MessageBox (szText, caption, MB_OK);
  648. return FALSE;
  649. }
  650. if ( !m_cbFileHash )
  651. {
  652. CString caption;
  653. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  654. VERIFY (szText.LoadString (IDS_NO_APPLICATION_SELECTED));
  655. MessageBox (szText, caption, MB_OK);
  656. GetDlgItem (IDC_HASH_ENTRY_BROWSE)->SetFocus ();
  657. return FALSE;
  658. }
  659. if ( m_bDirty )
  660. {
  661. // Set the level
  662. int nCurSel = m_securityLevelCombo.GetCurSel ();
  663. ASSERT (CB_ERR != nCurSel);
  664. m_rSaferEntry.SetLevel ((DWORD) m_securityLevelCombo.GetItemData (nCurSel));
  665. // Set description
  666. m_descriptionEdit.GetWindowText (szText);
  667. m_rSaferEntry.SetDescription (szText);
  668. // Set friendly name
  669. m_hashFileDetailsEdit.GetWindowText (szText);
  670. m_rSaferEntry.SetHashFriendlyName (szText);
  671. // Get and save flags
  672. DWORD dwFlags = 0;
  673. m_rSaferEntry.SetFlags (dwFlags);
  674. m_rSaferEntry.SetHash (m_rgbFileHash, m_cbFileHash, m_nFileSize, m_hashAlgid);
  675. HRESULT hr = m_rSaferEntry.Save ();
  676. if ( SUCCEEDED (hr) )
  677. {
  678. if ( m_lNotifyHandle )
  679. MMCPropertyChangeNotify (
  680. m_lNotifyHandle, // handle to a notification
  681. (LPARAM) m_pDataObject); // unique identifier
  682. m_bDirty = false;
  683. }
  684. else
  685. {
  686. CString caption;
  687. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  688. if ( HRESULT_FROM_WIN32 (ERROR_INVALID_PARAMETER) != hr )
  689. szText.FormatMessage (IDS_ERROR_SAVING_ENTRY, GetSystemMessage (hr));
  690. else
  691. VERIFY (szText.LoadString (IDS_HASH_STRING_BAD_FORMAT));
  692. MessageBox (szText, caption, MB_OK);
  693. return FALSE;
  694. }
  695. }
  696. }
  697. return CHelpPropertyPage::OnApply();
  698. }
  699. void CSaferEntryHashPropertyPage::OnChangeHashEntryDescription()
  700. {
  701. m_bDirty = true;
  702. SetModified ();
  703. }
  704. void CSaferEntryHashPropertyPage::OnSelchangeHashEntrySecurityLevel()
  705. {
  706. m_bDirty = true;
  707. SetModified ();
  708. }
  709. void CSaferEntryHashPropertyPage::OnChangeHashHashedFilePath()
  710. {
  711. m_bDirty = true;
  712. SetModified ();
  713. }
  714. bool CSaferEntryHashPropertyPage::FormatMemBufToString(PWSTR *ppString, PBYTE pbData, DWORD cbData)
  715. {
  716. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  717. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  718. DWORD i = 0;
  719. PBYTE pb;
  720. *ppString = (LPWSTR) LocalAlloc (LPTR, ((cbData * 3) * sizeof(WCHAR)));
  721. if ( !*ppString )
  722. {
  723. return false;
  724. }
  725. //
  726. // copy to the buffer
  727. //
  728. pb = pbData;
  729. while (pb <= &(pbData[cbData-1]))
  730. {
  731. (*ppString)[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  732. (*ppString)[i++] = RgwchHex[*pb & 0x0f];
  733. pb++;
  734. }
  735. (*ppString)[i] = 0;
  736. return true;
  737. }
  738. bool CSaferEntryHashPropertyPage::ConvertStringToHash (PCWSTR pszString)
  739. {
  740. _TRACE (1, L"Entering CSaferEntryHashPropertyPage::ConvertStringToHash (%s)\n", pszString);
  741. bool bRetVal = true;
  742. BYTE rgbFileHash[SAFER_MAX_HASH_SIZE];
  743. ::ZeroMemory (rgbFileHash, SAFER_MAX_HASH_SIZE);
  744. DWORD cbFileHash = 0;
  745. DWORD dwNumHashChars = 0;
  746. bool bFirst = true;
  747. bool bEndOfHash = false;
  748. CThemeContextActivator activator;
  749. for (int nIndex = 0; !bEndOfHash && pszString[nIndex] && bRetVal; nIndex++)
  750. {
  751. if ( cbFileHash >= SAFER_MAX_HASH_SIZE )
  752. {
  753. CString caption;
  754. CString text;
  755. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  756. text.FormatMessage (IDS_HASH_STRING_TOO_LONG, SAFER_MAX_HASH_SIZE, SAFER_MAX_HASH_SIZE/4);
  757. _TRACE (0, L"%s", (PCWSTR) text);
  758. VERIFY (text.LoadString (IDS_HASH_STRING_BAD_FORMAT));
  759. MessageBox (text, caption, MB_ICONWARNING | MB_OK);
  760. bRetVal = false;
  761. break;
  762. }
  763. dwNumHashChars++;
  764. switch (pszString[nIndex])
  765. {
  766. case L'0':
  767. bFirst = !bFirst;
  768. break;
  769. case L'1':
  770. if ( bFirst )
  771. rgbFileHash[cbFileHash] |= 0x10;
  772. else
  773. rgbFileHash[cbFileHash] |= 0x01;
  774. bFirst = !bFirst;
  775. break;
  776. case L'2':
  777. if ( bFirst )
  778. rgbFileHash[cbFileHash] |= 0x20;
  779. else
  780. rgbFileHash[cbFileHash] |= 0x02;
  781. bFirst = !bFirst;
  782. break;
  783. case L'3':
  784. if ( bFirst )
  785. rgbFileHash[cbFileHash] |= 0x30;
  786. else
  787. rgbFileHash[cbFileHash] |= 0x03;
  788. bFirst = !bFirst;
  789. break;
  790. case L'4':
  791. if ( bFirst )
  792. rgbFileHash[cbFileHash] |= 0x40;
  793. else
  794. rgbFileHash[cbFileHash] |= 0x04;
  795. bFirst = !bFirst;
  796. break;
  797. case L'5':
  798. if ( bFirst )
  799. rgbFileHash[cbFileHash] |= 0x50;
  800. else
  801. rgbFileHash[cbFileHash] |= 0x05;
  802. bFirst = !bFirst;
  803. break;
  804. case L'6':
  805. if ( bFirst )
  806. rgbFileHash[cbFileHash] |= 0x60;
  807. else
  808. rgbFileHash[cbFileHash] |= 0x06;
  809. bFirst = !bFirst;
  810. break;
  811. case L'7':
  812. if ( bFirst )
  813. rgbFileHash[cbFileHash] |= 0x70;
  814. else
  815. rgbFileHash[cbFileHash] |= 0x07;
  816. bFirst = !bFirst;
  817. break;
  818. case L'8':
  819. if ( bFirst )
  820. rgbFileHash[cbFileHash] |= 0x80;
  821. else
  822. rgbFileHash[cbFileHash] |= 0x08;
  823. bFirst = !bFirst;
  824. break;
  825. case L'9':
  826. if ( bFirst )
  827. rgbFileHash[cbFileHash] |= 0x90;
  828. else
  829. rgbFileHash[cbFileHash] |= 0x09;
  830. bFirst = !bFirst;
  831. break;
  832. case L'a':
  833. case L'A':
  834. if ( bFirst )
  835. rgbFileHash[cbFileHash] |= 0xA0;
  836. else
  837. rgbFileHash[cbFileHash] |= 0x0A;
  838. bFirst = !bFirst;
  839. break;
  840. case L'b':
  841. case L'B':
  842. if ( bFirst )
  843. rgbFileHash[cbFileHash] |= 0xB0;
  844. else
  845. rgbFileHash[cbFileHash] |= 0x0B;
  846. bFirst = !bFirst;
  847. break;
  848. case L'c':
  849. case L'C':
  850. if ( bFirst )
  851. rgbFileHash[cbFileHash] |= 0xC0;
  852. else
  853. rgbFileHash[cbFileHash] |= 0x0C;
  854. bFirst = !bFirst;
  855. break;
  856. case L'd':
  857. case L'D':
  858. if ( bFirst )
  859. rgbFileHash[cbFileHash] |= 0xD0;
  860. else
  861. rgbFileHash[cbFileHash] |= 0x0D;
  862. bFirst = !bFirst;
  863. break;
  864. case L'e':
  865. case L'E':
  866. if ( bFirst )
  867. rgbFileHash[cbFileHash] |= 0xE0;
  868. else
  869. rgbFileHash[cbFileHash] |= 0x0E;
  870. bFirst = !bFirst;
  871. break;
  872. case L'f':
  873. case L'F':
  874. if ( bFirst )
  875. rgbFileHash[cbFileHash] |= 0xF0;
  876. else
  877. rgbFileHash[cbFileHash] |= 0x0F;
  878. bFirst = !bFirst;
  879. break;
  880. case L':':
  881. // end of hash
  882. bEndOfHash = true;
  883. bFirst = !bFirst;
  884. dwNumHashChars--; // ':' already counted, subtract it
  885. break;
  886. default:
  887. bRetVal = false;
  888. {
  889. CString caption;
  890. CString text;
  891. WCHAR szChar[2];
  892. szChar[0] = pszString[nIndex];
  893. szChar[1] = 0;
  894. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  895. text.FormatMessage (IDS_HASH_STRING_INVALID_CHAR, szChar);
  896. _TRACE (0, L"%s", (PCWSTR) text);
  897. VERIFY (text.LoadString (IDS_HASH_STRING_BAD_FORMAT));
  898. MessageBox (text, caption, MB_ICONWARNING | MB_OK);
  899. }
  900. break;
  901. }
  902. if ( bFirst )
  903. cbFileHash++;
  904. }
  905. if ( bRetVal )
  906. {
  907. // 2 characters map to 1 each byte in the hash
  908. if ( MD5_HASH_LEN != dwNumHashChars/2 && SHA1_HASH_LEN != dwNumHashChars/2 )
  909. {
  910. CString caption;
  911. CString text;
  912. VERIFY (caption.LoadString (IDS_SAFER_WINDOWS_NODE_NAME));
  913. VERIFY (text.LoadString (IDS_HASH_INVALID_LENGTH));
  914. _TRACE (0, L"%s", (PCWSTR) text);
  915. VERIFY (text.LoadString (IDS_HASH_STRING_BAD_FORMAT));
  916. MessageBox (text, caption, MB_ICONWARNING | MB_OK);
  917. bRetVal = false;
  918. }
  919. else
  920. {
  921. m_cbFileHash = cbFileHash;
  922. memcpy (m_rgbFileHash, rgbFileHash, SAFER_MAX_HASH_SIZE);
  923. }
  924. }
  925. _TRACE (-1, L"Leaving CSaferEntryHashPropertyPage::ConvertStringToHash (): %s\n",
  926. bRetVal ? L"true" : L"false");
  927. return bRetVal;
  928. }
  929. void CSaferEntryHashPropertyPage::OnSetfocusHashHashedFilePath()
  930. {
  931. if ( m_bFirst )
  932. {
  933. if ( true == m_bReadOnly )
  934. SendDlgItemMessage (IDC_HASH_HASHED_FILE_PATH, EM_SETSEL, (WPARAM) 0, 0);
  935. m_bFirst = false;
  936. }
  937. }
  938. void CSaferEntryHashPropertyPage::FormatAndDisplayHash ()
  939. {
  940. PWSTR pwszText = 0;
  941. if ( FormatMemBufToString (&pwszText, m_rgbFileHash, m_cbFileHash) )
  942. {
  943. WCHAR szAlgID[10];
  944. _ltow (m_hashAlgid, szAlgID, 10);
  945. PWSTR pszFormattedText = new WCHAR[wcslen (pwszText) + 50];
  946. if ( pszFormattedText )
  947. {
  948. wsprintf (pszFormattedText, L"%s:%ld:", pwszText,
  949. m_nFileSize);
  950. wcscat (pszFormattedText, szAlgID);
  951. SetDlgItemText (IDC_HASH_HASHED_FILE_PATH,
  952. pszFormattedText);
  953. delete [] pszFormattedText;
  954. }
  955. LocalFree (pwszText);
  956. }
  957. }
  958. void CSaferEntryHashPropertyPage::OnChangeHashEntryHashfileDetails()
  959. {
  960. SetModified ();
  961. m_bDirty = true;
  962. }