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.

705 lines
20 KiB

  1. #include "init.h"
  2. #include <emptyvc.h>
  3. #include <regstr.h>
  4. #include "general.h"
  5. #include "dlg.h"
  6. #include "emptyvol.h"
  7. #include "parseinf.h"
  8. #define MAX_DRIVES 26 // there are 26 letters only
  9. // {8369AB20-56C9-11d0-94E8-00AA0059CE02}
  10. const CLSID CLSID_EmptyControlVolumeCache = {
  11. 0x8369ab20, 0x56c9, 0x11d0,
  12. 0x94, 0xe8, 0x0, 0xaa, 0x0,
  13. 0x59, 0xce, 0x2};
  14. /******************************************************************************
  15. class CEmptyControlVolumeCache
  16. ******************************************************************************/
  17. class CEmptyControlVolumeCache : public IEmptyVolumeCache
  18. {
  19. public:
  20. // IUnknown Methods
  21. STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
  22. STDMETHODIMP_(ULONG) AddRef();
  23. STDMETHODIMP_(ULONG) Release();
  24. // IEmptyVolumeCache Methods
  25. STDMETHODIMP Initialize(HKEY hRegKey, LPCWSTR pszVolume,
  26. LPWSTR *ppszDisplayName, LPWSTR *ppszDescription, DWORD *pdwFlags);
  27. STDMETHODIMP GetSpaceUsed(DWORDLONG *pdwSpaceUsed,
  28. IEmptyVolumeCacheCallBack *picb);
  29. STDMETHODIMP Purge(DWORDLONG dwSpaceToFree,
  30. IEmptyVolumeCacheCallBack *picb);
  31. STDMETHODIMP ShowProperties(HWND hwnd);
  32. STDMETHODIMP Deactivate(DWORD *pdwFlags);
  33. // Attributes
  34. public:
  35. static HRESULT IsControlExpired(HANDLE hControl, BOOL fUseCache = TRUE);
  36. // Implementation
  37. public:
  38. // Constructor and destructor
  39. CEmptyControlVolumeCache();
  40. virtual ~CEmptyControlVolumeCache();
  41. protected:
  42. // implementation data helpers
  43. // Note. Write operations are only perfomed by the private functions
  44. // prefixed cpl_XXX. Read access is not restricted.
  45. LPCACHE_PATH_NODE m_pPathsHead,
  46. m_pPathsTail;
  47. // Note. Write operations are only perfomed by the private functions
  48. // prefixed chl_XXX. Read access is not restricted.
  49. LPCONTROL_HANDLE_NODE m_pControlsHead,
  50. m_pControlsTail;
  51. WCHAR m_szVol[4];
  52. DWORDLONG m_dwTotalSize;
  53. ULONG m_cRef;
  54. // implementation helper routines
  55. // cpl prefix stands for CachePathsList
  56. HRESULT cpl_Add(LPCTSTR pszCachePath);
  57. void cpl_Remove();
  58. HRESULT cpl_CreateForVolume(LPCWSTR pszVolume = NULL);
  59. // chl prefix stands for ControlHandlesList
  60. HRESULT chl_Find(HANDLE hControl,
  61. LPCONTROL_HANDLE_NODE *rgp = NULL, UINT nSize = 1) const;
  62. HRESULT chl_Add(HANDLE hControl);
  63. void chl_Remove(LPCONTROL_HANDLE_NODE rgp[2]);
  64. HRESULT chl_Remove(HANDLE hControl = NULL);
  65. HRESULT chl_CreateForPath(LPCTSTR pszCachePath,
  66. DWORDLONG *pdwUsedInFolder = NULL);
  67. friend HRESULT _stdcall EmptyControl_CreateInstance(IUnknown *pUnkOuter,
  68. REFIID riid, LPVOID* ppv);
  69. // friend BOOL CALLBACK EmptyControl_PropertiesDlgProc(HWND hDlg,
  70. // UINT msg, WPARAM wp, LPARAM lp);
  71. };
  72. STDAPI EmptyControl_CreateInstance(IUnknown *pUnkOuter, REFIID riid, LPVOID* ppv)
  73. {
  74. *ppv = NULL;
  75. if (pUnkOuter != NULL)
  76. return CLASS_E_NOAGGREGATION;
  77. CEmptyControlVolumeCache *pCRC = new CEmptyControlVolumeCache;
  78. if (pCRC == NULL)
  79. return E_OUTOFMEMORY;
  80. HRESULT hr = pCRC->QueryInterface(riid, ppv);
  81. pCRC->Release();
  82. return hr;
  83. }
  84. /////////////////////////////////////////////////////////////////////////////
  85. // CEmptyControlVolumeCache constructor and destructor
  86. CEmptyControlVolumeCache::CEmptyControlVolumeCache()
  87. {
  88. DllAddRef();
  89. m_pPathsHead = m_pPathsTail = NULL;
  90. m_pControlsHead = m_pControlsTail = NULL;
  91. m_szVol[0] = L'\0';
  92. m_dwTotalSize = 0;
  93. m_cRef = 1;
  94. }
  95. CEmptyControlVolumeCache::~CEmptyControlVolumeCache()
  96. {
  97. ASSERT(m_cRef == 0);
  98. cpl_Remove();
  99. chl_Remove();
  100. DllRelease();
  101. }
  102. /////////////////////////////////////////////////////////////////////////////
  103. // CEmptyControlVolumeCache attributes
  104. // CEmptyControlVolumeCache::IsControlExpired
  105. // Check if a control has not been accessed for more than N days. If there is
  106. // no registry entry, default is DEFAULT_DAYS_BEFORE_EXPIRE.
  107. //
  108. // Parameters: fUseCache can be used to not go to the registry for the value
  109. // of N above.
  110. //
  111. // Returns: either the Win32 error converted to HRESULT or
  112. // S_OK if control is expired and S_FALSE if not;
  113. //
  114. // Used by: only by CEmptyControlVolumeCache::chl_CreateForPath
  115. //
  116. HRESULT CEmptyControlVolumeCache::IsControlExpired(HANDLE hControl,
  117. BOOL fUseCache /*= TRUE*/)
  118. {
  119. SYSTEMTIME stNow;
  120. FILETIME ftNow;
  121. FILETIME ftLastAccess;
  122. LARGE_INTEGER timeExpire;
  123. HRESULT hr = S_OK;
  124. ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
  125. // don't expire controls with uncertain access time.
  126. if (FAILED(GetLastAccessTime(hControl, &ftLastAccess)))
  127. return S_FALSE;
  128. //----- Time calculations (wierd looking) -----
  129. // Add to last access date the length of time before a control expires
  130. timeExpire.LowPart = ftLastAccess.dwLowDateTime;
  131. timeExpire.HighPart = ftLastAccess.dwHighDateTime;
  132. timeExpire.QuadPart += (((CCacheItem*)hControl)->GetExpireDays() * 864000000000L); //24*3600*10^7
  133. GetLocalTime(&stNow);
  134. SystemTimeToFileTime(&stNow, &ftNow);
  135. return CompareFileTime((FILETIME*)&timeExpire, &ftNow) <= 0 ?
  136. S_OK : S_FALSE;
  137. }
  138. /////////////////////////////////////////////////////////////////////////////
  139. // CEmptyControlVolumeCache CachePathsList routines
  140. // CEmptyControlVolumeCache::cpl_Add
  141. // Check if a control has not been accessed for more than N days. If there is
  142. // no registry entry, default is DEFAULT_DAYS_BEFORE_EXPIRE.
  143. //
  144. // Parameters: a cache folder path to add.
  145. //
  146. // Returns: E_OUTOFMEMORY or
  147. // S_FALSE if path is already in the list or S_OK if added.
  148. //
  149. // Used by: only by CEmptyControlVolumeCache::cpl_CreateForVolume
  150. //
  151. HRESULT CEmptyControlVolumeCache::cpl_Add(LPCTSTR pszCachePath)
  152. {
  153. LPCACHE_PATH_NODE pNode;
  154. ASSERT(pszCachePath != NULL);
  155. for (pNode = m_pPathsHead; pNode != NULL; pNode = pNode->pNext)
  156. if (lstrcmpi(pNode->szCachePath, pszCachePath) == 0)
  157. break;
  158. if (pNode != NULL)
  159. return S_FALSE;
  160. pNode = new CACHE_PATH_NODE;
  161. if (pNode == NULL)
  162. return E_OUTOFMEMORY;
  163. lstrcpyn(pNode->szCachePath, pszCachePath, MAX_PATH);
  164. pNode->pNext = NULL;
  165. if (m_pPathsHead == NULL)
  166. m_pPathsHead = pNode;
  167. else
  168. m_pPathsTail->pNext = pNode;
  169. m_pPathsTail = pNode;
  170. return S_OK;
  171. }
  172. // CEmptyControlVolumeCache::cpl_Remove
  173. // Remove all paths from the internal list.
  174. //
  175. // Parameters: none;
  176. //
  177. // Returns: void;
  178. //
  179. // Used by: several obvious places
  180. //
  181. void CEmptyControlVolumeCache::cpl_Remove()
  182. {
  183. // remove cache path list
  184. for (LPCACHE_PATH_NODE pCur = m_pPathsHead;
  185. m_pPathsHead != NULL;
  186. pCur = m_pPathsHead) {
  187. m_pPathsHead = m_pPathsHead->pNext;
  188. delete[] pCur;
  189. }
  190. m_pPathsTail = NULL;
  191. }
  192. // CEmptyControlVolumeCache::cpl_CreateForVolume
  193. // Build a list of paths to cache folders.
  194. //
  195. // Parameters: volume (or drive) where these folders are;
  196. //
  197. // Returns: S_OK or one out of the bunch of obvious errors;
  198. //
  199. // Used by: only by IEmptyVolumeCache::GetSpaceUsed
  200. //
  201. HRESULT CEmptyControlVolumeCache::cpl_CreateForVolume(LPCWSTR pszVolume)
  202. {
  203. HKEY hkey = NULL;
  204. HRESULT hr = E_FAIL;
  205. int iDriveNum;
  206. ASSERT(pszVolume != NULL);
  207. iDriveNum = PathGetDriveNumberW(pszVolume);
  208. if (iDriveNum < 0)
  209. return E_INVALIDARG;
  210. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_ACTIVEX_CACHE, 0,
  211. KEY_READ, &hkey) != ERROR_SUCCESS)
  212. return E_FAIL;
  213. TCHAR szCachePath[MAX_PATH],
  214. szValue[MAX_PATH];
  215. DWORD dwIndex = 0,
  216. dwValueLen = MAX_PATH, dwLen = MAX_PATH;
  217. cpl_Remove();
  218. while (RegEnumValue(hkey, dwIndex++, szValue, &dwValueLen, NULL, NULL,
  219. (LPBYTE)szCachePath, &dwLen) == ERROR_SUCCESS) {
  220. dwLen = dwValueLen = MAX_PATH;
  221. if (PathGetDriveNumber(szCachePath) != iDriveNum)
  222. continue;
  223. // we must have added at least one successfully to get a success code..
  224. hr = cpl_Add(szCachePath);
  225. if (FAILED(hr))
  226. break;
  227. }
  228. RegCloseKey(hkey);
  229. if (FAILED(hr))
  230. cpl_Remove();
  231. return hr;
  232. }
  233. /////////////////////////////////////////////////////////////////////////////
  234. // CEmptyControlVolumeCache ControlHandlesList routines
  235. // CEmptyControlVolumeCache::chl_Find
  236. // Find and return a location for the specified handle in the internal list.
  237. // if (rgp == NULL), only result matters;
  238. // if (rgp != NULL),
  239. // if (nSize == 1), *rgp is going to have found item (if it's there)
  240. // if (nSize >= 2), *rgp[0] = prev to the found item, and *rgp[1] is the
  241. // item.
  242. //
  243. // Parameters: explained above;
  244. //
  245. // Returns: S_OK if the item is found, S_FALSE otherwise or
  246. // one out of the bunch of obvious errors;
  247. //
  248. // Used by: CEmptyControlVolumeCache::chl_Add and
  249. // CEmptyControlVolumeCache::chl_Remove
  250. //
  251. HRESULT CEmptyControlVolumeCache::chl_Find(HANDLE hControl,
  252. LPCONTROL_HANDLE_NODE *rgp /*= NULL*/, UINT nSize /*= 1*/) const
  253. {
  254. LPCONTROL_HANDLE_NODE pCur,
  255. pPrev = NULL;
  256. ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
  257. for (pCur = m_pControlsHead; pCur != NULL; pCur = pCur->pNext) {
  258. if (pCur->hControl == hControl)
  259. break;
  260. pPrev = pCur;
  261. }
  262. if (pCur == NULL)
  263. pPrev = NULL; // zero out possible return
  264. if (rgp != NULL && nSize > 0)
  265. if (nSize == 1)
  266. *rgp = pCur;
  267. else { /* if (nSize >= 2) */
  268. rgp[0] = pPrev;
  269. rgp[1] = pCur;
  270. }
  271. return (pCur != NULL) ? S_OK : E_FAIL;
  272. }
  273. HRESULT CEmptyControlVolumeCache::chl_Add(HANDLE hControl)
  274. {
  275. LPCONTROL_HANDLE_NODE pNode;
  276. DWORD dwSize;
  277. // Note. Retail build assumes that handle is not in the list.
  278. ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
  279. ASSERT(FAILED(chl_Find(hControl)));
  280. pNode = new CONTROL_HANDLE_NODE;
  281. if (pNode == NULL)
  282. return E_OUTOFMEMORY;
  283. GetControlInfo(hControl, GCI_SIZESAVED, &dwSize, NULL, 0);
  284. pNode->hControl = hControl;
  285. pNode->pNext = NULL;
  286. if (m_pControlsHead == NULL)
  287. m_pControlsHead = pNode;
  288. else {
  289. ASSERT(m_pControlsHead != NULL);
  290. m_pControlsTail->pNext = pNode;
  291. }
  292. m_pControlsTail = pNode;
  293. m_dwTotalSize += dwSize;
  294. return S_OK;
  295. }
  296. void CEmptyControlVolumeCache::chl_Remove(LPCONTROL_HANDLE_NODE rgp[2])
  297. {
  298. DWORD dwSize;
  299. if (m_pControlsHead == NULL || (rgp[0] != NULL && rgp[1] == NULL))
  300. return;
  301. if (rgp[0] != NULL)
  302. rgp[0]->pNext = rgp[1]->pNext;
  303. else {
  304. rgp[1] = m_pControlsHead;
  305. m_pControlsHead = m_pControlsHead->pNext;
  306. }
  307. if (rgp[1] == m_pControlsTail)
  308. m_pControlsTail = rgp[0];
  309. if (GetControlInfo(rgp[1]->hControl, GCI_SIZESAVED, &dwSize, NULL, 0))
  310. {
  311. // only proceeed if GetControlInfo succeeds
  312. // Note. This code assumes that the size of a control didn't change since
  313. // it was added.
  314. m_dwTotalSize -= dwSize;
  315. }
  316. ReleaseControlHandle(rgp[1]->hControl);
  317. delete rgp[1];
  318. }
  319. HRESULT CEmptyControlVolumeCache::chl_Remove(HANDLE hControl /*= NULL*/)
  320. {
  321. LPCONTROL_HANDLE_NODE rgp[2] = { NULL, NULL };
  322. HRESULT hr;
  323. ASSERT(hControl != INVALID_HANDLE_VALUE);
  324. if (hControl != NULL) {
  325. hr = chl_Find(hControl, rgp, 2);
  326. if (FAILED(hr))
  327. return hr;
  328. chl_Remove(rgp);
  329. return S_OK;
  330. }
  331. while (m_pControlsHead != NULL)
  332. chl_Remove(rgp);
  333. ASSERT(m_pControlsHead == NULL && m_pControlsTail == NULL);
  334. return S_OK;
  335. }
  336. // CEmptyControlVolumeCache::chl_CreateForPath
  337. // Calculate the size in bytes taken up by controls in the control cache
  338. // folder specified.
  339. //
  340. // Parameters: pszCachePath is a path to the controls cache folder;
  341. // pdwSpaceUsed is the result
  342. //
  343. // Used by: only by IEmptyVolumeCache::GetSpaceUsed
  344. //
  345. HRESULT CEmptyControlVolumeCache::chl_CreateForPath(LPCTSTR pszCachePath,
  346. DWORDLONG *pdwUsedInFolder /*= NULL*/)
  347. {
  348. DWORDLONG dwCopy;
  349. HANDLE hFind = NULL,
  350. hControl = NULL;
  351. LONG lResult;
  352. BOOL fCache = FALSE;
  353. dwCopy = m_dwTotalSize;
  354. for (lResult = FindFirstControl(hFind, hControl, pszCachePath);
  355. lResult == ERROR_SUCCESS;
  356. lResult = FindNextControl(hFind, hControl)) {
  357. lResult = HRESULT_CODE(IsControlExpired(hControl, fCache));
  358. fCache = TRUE;
  359. if (lResult != ERROR_SUCCESS)
  360. continue;
  361. lResult = HRESULT_CODE(chl_Add(hControl));
  362. if (lResult != ERROR_SUCCESS)
  363. break;
  364. }
  365. FindControlClose(hFind);
  366. if (lResult == ERROR_NO_MORE_ITEMS)
  367. lResult = ERROR_SUCCESS;
  368. if (pdwUsedInFolder != NULL) {
  369. *pdwUsedInFolder = m_dwTotalSize - dwCopy;
  370. }
  371. return HRESULT_FROM_WIN32(lResult);
  372. }
  373. /******************************************************************************
  374. IUnknown Methods
  375. ******************************************************************************/
  376. STDMETHODIMP CEmptyControlVolumeCache::QueryInterface(REFIID iid, void** ppv)
  377. {
  378. if (ppv == NULL)
  379. return E_POINTER;
  380. *ppv = NULL;
  381. if (iid != IID_IUnknown && iid != IID_IEmptyVolumeCache)
  382. return E_NOINTERFACE;
  383. *ppv = (void *)this;
  384. AddRef();
  385. return S_OK;
  386. }
  387. STDMETHODIMP_(ULONG) CEmptyControlVolumeCache::AddRef()
  388. {
  389. return (++m_cRef);
  390. }
  391. STDMETHODIMP_(ULONG) CEmptyControlVolumeCache::Release()
  392. {
  393. if (--m_cRef)
  394. return m_cRef;
  395. delete this;
  396. return 0;
  397. }
  398. /******************************************************************************
  399. IEmptyVolumeCache Methods
  400. ******************************************************************************/
  401. STDMETHODIMP CEmptyControlVolumeCache::Initialize(HKEY hRegKey,
  402. LPCWSTR pszVolume, LPWSTR *ppszDisplayName, LPWSTR *ppszDescription,
  403. DWORD *pdwFlags)
  404. {
  405. if (pszVolume == NULL)
  406. return E_POINTER;
  407. if (ppszDisplayName == NULL || ppszDescription == NULL)
  408. return E_POINTER;
  409. if (pdwFlags == NULL)
  410. return E_POINTER;
  411. StrCpyNW(m_szVol, pszVolume, ARRAYSIZE(m_szVol));
  412. cpl_Remove();
  413. chl_Remove();
  414. if (lstrlenW(m_szVol) == 0) {
  415. return E_UNEXPECTED;
  416. }
  417. if (FAILED(cpl_CreateForVolume(m_szVol))) {
  418. return E_FAIL;
  419. }
  420. *ppszDisplayName = *ppszDescription = NULL;
  421. *pdwFlags = EVCF_HASSETTINGS | EVCF_ENABLEBYDEFAULT |
  422. EVCF_ENABLEBYDEFAULT_AUTO;
  423. return S_OK;
  424. }
  425. STDMETHODIMP CEmptyControlVolumeCache::GetSpaceUsed(DWORDLONG *pdwSpaceUsed,
  426. IEmptyVolumeCacheCallBack *picb)
  427. {
  428. LPCACHE_PATH_NODE pCur;
  429. HRESULT hr = S_OK;
  430. if (pdwSpaceUsed == NULL) {
  431. hr = E_POINTER;
  432. goto LastNotification;
  433. }
  434. *pdwSpaceUsed = 0;
  435. if (lstrlenW(m_szVol) == 0) {
  436. hr = E_UNEXPECTED;
  437. goto LastNotification;
  438. }
  439. for (pCur = m_pPathsHead; pCur != NULL; pCur = pCur->pNext) {
  440. DWORDLONG dwlThisItem = 0;
  441. if (FAILED(chl_CreateForPath(pCur->szCachePath, &dwlThisItem)))
  442. hr = S_FALSE; // at least one failed
  443. m_dwTotalSize += dwlThisItem;
  444. if (picb != NULL)
  445. picb->ScanProgress(m_dwTotalSize, 0, NULL);
  446. }
  447. // cpl_Remove(); // because of ShowProperties
  448. *pdwSpaceUsed = m_dwTotalSize;
  449. LastNotification:
  450. if (picb != NULL)
  451. picb->ScanProgress(m_dwTotalSize, EVCCBF_LASTNOTIFICATION, NULL);
  452. return hr;
  453. }
  454. STDMETHODIMP CEmptyControlVolumeCache::Purge(DWORDLONG dwSpaceToFree,
  455. IEmptyVolumeCacheCallBack *picb)
  456. {
  457. LPCONTROL_HANDLE_NODE rgp[2] = { NULL, NULL };
  458. DWORDLONG dwSpaceFreed;
  459. HANDLE hControl;
  460. DWORD dwSize;
  461. HRESULT hr;
  462. if (m_pControlsHead == NULL) {
  463. DWORDLONG dwSpaceUsed;
  464. hr = GetSpaceUsed(&dwSpaceUsed, picb);
  465. if (FAILED(hr) || m_pControlsHead == NULL)
  466. hr = FAILED(hr) ? hr : STG_E_NOMOREFILES;
  467. if (picb != NULL)
  468. picb->PurgeProgress(0, dwSpaceToFree, EVCCBF_LASTNOTIFICATION,
  469. NULL);
  470. return hr;
  471. }
  472. dwSpaceFreed = 0;
  473. ASSERT(m_pControlsHead != NULL);
  474. while (m_pControlsHead != NULL) {
  475. hControl = m_pControlsHead->hControl;
  476. ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
  477. GetControlInfo(hControl, GCI_SIZESAVED, &dwSize, NULL, 0);
  478. hr = RemoveControlByHandle2(hControl, FALSE, TRUE);
  479. if (SUCCEEDED(hr)) {
  480. dwSpaceFreed += dwSize;
  481. if (picb != NULL)
  482. picb->PurgeProgress(dwSpaceFreed, dwSpaceToFree, 0, NULL);
  483. }
  484. chl_Remove(rgp);
  485. if (dwSpaceFreed >= dwSpaceToFree)
  486. break;
  487. }
  488. if (picb != NULL)
  489. picb->PurgeProgress(dwSpaceFreed, dwSpaceToFree, 0, NULL);
  490. return S_OK;
  491. }
  492. // Note. This function opens the last cache folder in the internal list.
  493. STDMETHODIMP CEmptyControlVolumeCache::ShowProperties(HWND hwnd)
  494. {
  495. // Note. (According to SeanF) The codedownload engine will query
  496. // ActiveXCache key under HKLM\SOFTWARE\Microsoft\Windows\
  497. // CurrentVersion\Internet Settings. The value of this key should
  498. // be equal to the last item in the CachePathsList which is why
  499. // navigation below is done for the tail.
  500. if (m_pPathsTail == NULL || m_pPathsTail->szCachePath == NULL)
  501. return E_UNEXPECTED;
  502. ShellExecute(hwnd, NULL, m_pPathsTail->szCachePath, NULL, NULL, SW_SHOW);
  503. return S_OK;
  504. /*
  505. int iDlgResult;
  506. iDlgResult = MLDialogBoxWrap(MLGetHinst(), MAKEINTRESOURCE(IDD_PROP_EXPIRE), hwnd,
  507. EmptyControl_PropertiesDlgProc);
  508. return iDlgResult == IDOK ? S_OK : S_FALSE;
  509. */
  510. }
  511. STDMETHODIMP CEmptyControlVolumeCache::Deactivate(DWORD *pdwFlags)
  512. {
  513. if (pdwFlags == NULL)
  514. return E_INVALIDARG;
  515. *pdwFlags = 0;
  516. return S_OK;
  517. }
  518. /////////////////////////////////////////////////////////////////////////////
  519. // Implementation helpers routines (private)
  520. /*
  521. static void msg_OnInitDialog(HWND hDlg);
  522. static BOOL msg_OnCommand(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
  523. static BOOL cmd_OnOK(HWND hDlg);
  524. INT_PTR CALLBACK EmptyControl_PropertiesDlgProc(HWND hDlg,
  525. UINT msg, WPARAM wp, LPARAM lp)
  526. {
  527. static MSD rgmsd[] = {
  528. { WM_INITDIALOG, ms_vh, (PFN)msg_OnInitDialog },
  529. { WM_COMMAND, ms_bwwwl, (PFN)msg_OnCommand },
  530. { WM_NULL, ms_end, (PFN)NULL }
  531. };
  532. return Dlg_MsgProc(rgmsd, hDlg, msg, wp, lp);
  533. }
  534. void msg_OnInitDialog(HWND hDlg)
  535. {
  536. UINT nDays;
  537. CEmptyControlVolumeCache::GetDaysBeforeExpire(&nDays);
  538. SetDlgItemInt(hDlg, IDC_EDIT_EXPIRE, nDays, FALSE);
  539. }
  540. BOOL msg_OnCommand(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
  541. {
  542. static CMD rgcmd[] = {
  543. { IDOK, 0, ms_bh, (PFN)cmd_OnOK },
  544. { 0, 0, ms_end, (PFN)NULL }
  545. };
  546. return Msg_OnCmd(rgcmd, hDlg, msg, wp, lp);
  547. }
  548. BOOL cmd_OnOK(HWND hDlg)
  549. {
  550. UINT nDays;
  551. BOOL fWorked;
  552. nDays = GetDlgItemInt(hDlg, IDC_EDIT_EXPIRE, &fWorked, FALSE);
  553. if (!fWorked) {
  554. MessageBeep(-1);
  555. SetFocus(GetDlgItem(hDlg, IDC_EDIT_EXPIRE));
  556. return FALSE;
  557. }
  558. CEmptyControlVolumeCache::SetDaysBeforeExpire(nDays);
  559. return TRUE;
  560. }
  561. */