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.

2584 lines
67 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1995.
  5. //
  6. // File: shrpage.cxx
  7. //
  8. // Contents: "Sharing" shell property page extension
  9. //
  10. // History: 6-Apr-95 BruceFo Created
  11. // 12-Jul-00 JonN fixed 140878, MSG_MULTIDEL debounce
  12. // 06-Oct-00 jeffreys Split CShareBase out of CSharingPropertyPage
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "headers.hxx"
  16. #pragma hdrstop
  17. #include "resource.h"
  18. #include "helpids.h"
  19. #include "dlgnew.hxx"
  20. #include "cache.hxx"
  21. #include "share.hxx"
  22. #include "acl.hxx"
  23. #include "shrinfo.hxx"
  24. #include "shrpage.hxx"
  25. #include "util.hxx"
  26. void _MyShow( HWND hwndParent, INT idControl, BOOL fShow )
  27. {
  28. HWND hwndChild = GetDlgItem( hwndParent, idControl );
  29. appAssert( NULL != hwndChild );
  30. ShowWindow( hwndChild, (fShow) ? SW_SHOW : SW_HIDE );
  31. EnableWindow( hwndChild, fShow );
  32. }
  33. ////////////////////////////////////////////////////////////////////////////
  34. ////////////////////////////////////////////////////////////////////////////
  35. STDMETHODIMP CShareBase::QueryInterface(REFIID riid, void **ppvObj)
  36. {
  37. static const QITAB qit[] = {
  38. QITABENT(CShareBase, IOleWindow), // IID_IOleWindow
  39. { 0 }
  40. };
  41. return QISearch(this, qit, riid, ppvObj);
  42. }
  43. STDMETHODIMP_(ULONG) CShareBase::AddRef()
  44. {
  45. return InterlockedIncrement(&_cRef);
  46. }
  47. STDMETHODIMP_(ULONG) CShareBase::Release()
  48. {
  49. if (InterlockedDecrement(&_cRef))
  50. return _cRef;
  51. delete this;
  52. return 0;
  53. }
  54. STDMETHODIMP CShareBase::GetWindow(HWND *phwnd)
  55. {
  56. *phwnd = _GetFrameWindow();
  57. return S_OK;
  58. }
  59. STDMETHODIMP CShareBase::ContextSensitiveHelp(BOOL /*fEnterMode*/)
  60. {
  61. return E_NOTIMPL;
  62. }
  63. //+-------------------------------------------------------------------------
  64. //
  65. // Method: CShareBase::PageCallback, static public
  66. //
  67. // Synopsis:
  68. //
  69. //--------------------------------------------------------------------------
  70. UINT CALLBACK
  71. CShareBase::PageCallback(
  72. IN HWND hwnd,
  73. IN UINT uMsg,
  74. IN LPPROPSHEETPAGE ppsp
  75. )
  76. {
  77. switch (uMsg)
  78. {
  79. case PSPCB_CREATE:
  80. return 1; // allow creation
  81. case PSPCB_RELEASE:
  82. {
  83. CShareBase* pThis = (CShareBase*)ppsp->lParam;
  84. pThis->Release(); // do this LAST!
  85. return 0; // ignored
  86. }
  87. case PSPCB_ADDREF:
  88. // Should probably implement some refcounting, but we only get
  89. // addref'd once and released once.
  90. return 0;
  91. default:
  92. appDebugOut((DEB_ERROR, "CShareBase::PageCallback, unknown page callback message %d\n", uMsg));
  93. return 0;
  94. } // end switch
  95. }
  96. //+-------------------------------------------------------------------------
  97. //
  98. // Method: CShareBase::DlgProcPage, static public
  99. //
  100. // Synopsis: Dialog Procedure for all sharing dialogs/pages
  101. //
  102. //--------------------------------------------------------------------------
  103. INT_PTR CALLBACK
  104. CShareBase::DlgProcPage(
  105. IN HWND hwnd,
  106. IN UINT msg,
  107. IN WPARAM wParam,
  108. IN LPARAM lParam
  109. )
  110. {
  111. CShareBase* pThis = NULL;
  112. if (msg==WM_INITDIALOG)
  113. {
  114. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam;
  115. pThis = (CShareBase*)psp->lParam;
  116. SetWindowLongPtr(hwnd,GWLP_USERDATA,(LPARAM)pThis);
  117. }
  118. else
  119. {
  120. pThis = (CShareBase*) GetWindowLongPtr(hwnd,GWLP_USERDATA);
  121. }
  122. if (pThis != NULL)
  123. {
  124. return pThis->_PageProc(hwnd,msg,wParam,lParam);
  125. }
  126. else
  127. {
  128. return FALSE;
  129. }
  130. }
  131. //+--------------------------------------------------------------------------
  132. //
  133. // Method: CShareBase::CShareBase, public
  134. //
  135. // Synopsis: Constructor
  136. //
  137. //---------------------------------------------------------------------------
  138. CShareBase::CShareBase(
  139. IN PWSTR pszPath,
  140. IN BOOL bDialog // called as a dialog, not a property page?
  141. )
  142. :
  143. _cRef(1),
  144. _pszPath(pszPath), // take ownership!
  145. _hwndPage(NULL),
  146. _fInitializingPage(0), // JonN 7/11/00 140878
  147. _bDirty(FALSE),
  148. _pInfoList(NULL),
  149. _pReplaceList(NULL),
  150. _pCurInfo(NULL),
  151. _cShares(0),
  152. _bNewShare(TRUE),
  153. _bDialog(bDialog)
  154. {
  155. INIT_SIG(CShareBase);
  156. appAssert(NULL != _pszPath);
  157. }
  158. //+--------------------------------------------------------------------------
  159. //
  160. // Method: CShareBase::~CShareBase, public
  161. //
  162. // Synopsis: Destructor
  163. //
  164. //---------------------------------------------------------------------------
  165. CShareBase::~CShareBase()
  166. {
  167. CHECK_SIG(CShareBase);
  168. // delete the the list of shares
  169. appAssert(NULL != _pInfoList);
  170. DeleteShareInfoList(_pInfoList, TRUE);
  171. _pInfoList = NULL;
  172. _pCurInfo = NULL;
  173. // delete the "replacement" list
  174. appAssert(NULL != _pReplaceList);
  175. DeleteShareInfoList(_pReplaceList, TRUE);
  176. _pReplaceList = NULL;
  177. delete[] _pszPath;
  178. _pszPath = NULL;
  179. }
  180. //+-------------------------------------------------------------------------
  181. //
  182. // Method: CShareBase::InitInstance, public
  183. //
  184. // Synopsis: Part II of the constuctor process
  185. //
  186. // Notes: We don't want to handle any errors in constuctor, so this
  187. // method is necessary for the second phase error detection.
  188. //
  189. //--------------------------------------------------------------------------
  190. HRESULT
  191. CShareBase::InitInstance(
  192. VOID
  193. )
  194. {
  195. CHECK_SIG(CShareBase);
  196. appDebugOut((DEB_ITRACE, "CShareBase::InitInstance\n"));
  197. _pInfoList = new CShareInfo(); // dummy head node
  198. if (NULL == _pInfoList)
  199. {
  200. return E_OUTOFMEMORY;
  201. }
  202. _pReplaceList = new CShareInfo(); // dummy head node
  203. if (NULL == _pReplaceList)
  204. {
  205. return E_OUTOFMEMORY;
  206. }
  207. return S_OK;
  208. }
  209. //+-------------------------------------------------------------------------
  210. //
  211. // Method: CShareBase::_PageProc, private
  212. //
  213. // Synopsis: Dialog Procedure for this object
  214. //
  215. //--------------------------------------------------------------------------
  216. BOOL
  217. CShareBase::_PageProc(
  218. IN HWND hwnd,
  219. IN UINT msg,
  220. IN WPARAM wParam,
  221. IN LPARAM lParam
  222. )
  223. {
  224. CHECK_SIG(CShareBase);
  225. switch (msg)
  226. {
  227. case WM_INITDIALOG:
  228. _hwndPage = hwnd;
  229. //
  230. // We know this drive is allowed to be shared. However, someone may
  231. // have changed the number or characteristics of the share using the
  232. // command line or winfile or server manager or the new file server
  233. // tool, and the cache may not have been refreshed. Force a refresh
  234. // now, to pick up any new shares for this path.
  235. //
  236. // Note that for the SharingDialog() API, this is the first time the
  237. // cache gets loaded. If the server is not running, we nuke the dialog
  238. // and return an error code.
  239. //
  240. g_ShareCache.Refresh();
  241. if (_bDialog && !g_fSharingEnabled)
  242. {
  243. EndDialog(hwnd, -1);
  244. }
  245. _ConstructShareList();
  246. return _OnInitDialog(hwnd, (HWND)wParam, lParam);
  247. case WM_COMMAND:
  248. return _OnCommand(hwnd, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
  249. case WM_NOTIFY:
  250. return _OnNotify(hwnd, (int)wParam, (LPNMHDR)lParam);
  251. case WM_HELP:
  252. return _OnHelp(hwnd, (LPHELPINFO)lParam);
  253. case WM_CONTEXTMENU:
  254. return _OnContextMenu(hwnd, (HWND)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  255. } // end switch (msg)
  256. return FALSE;
  257. }
  258. //+-------------------------------------------------------------------------
  259. //
  260. // Method: CShareBase::_OnCommand, private
  261. //
  262. // Synopsis: WM_COMMAND handler
  263. //
  264. //--------------------------------------------------------------------------
  265. BOOL
  266. CShareBase::_OnCommand(
  267. IN HWND hwnd,
  268. IN WORD wNotifyCode,
  269. IN WORD wID,
  270. IN HWND hwndCtl
  271. )
  272. {
  273. CHECK_SIG(CShareBase);
  274. //
  275. // Commands only used when this page is invoked as a dialog box, via the
  276. // SharingDialog() API:
  277. //
  278. if (_bDialog)
  279. {
  280. switch (wID)
  281. {
  282. case IDCANCEL:
  283. if (!_DoCancel(hwnd))
  284. {
  285. // We might consider not going away. But instead, go away anyway.
  286. }
  287. EndDialog(hwnd, FALSE);
  288. return TRUE;
  289. case IDOK:
  290. if (!_ValidatePage(hwnd))
  291. {
  292. // don't go away
  293. return TRUE;
  294. }
  295. if (!_DoApply(hwnd, TRUE))
  296. {
  297. // don't go away
  298. return TRUE;
  299. }
  300. EndDialog(hwnd, TRUE);
  301. return TRUE;
  302. default:
  303. break;
  304. }
  305. }
  306. return FALSE;
  307. }
  308. //+-------------------------------------------------------------------------
  309. //
  310. // Method: CShareBase::_OnNotify, private
  311. //
  312. // Synopsis: WM_NOTIFY handler
  313. //
  314. //--------------------------------------------------------------------------
  315. BOOL
  316. CShareBase::_OnNotify(
  317. IN HWND hwnd,
  318. IN int idCtrl,
  319. IN LPNMHDR phdr
  320. )
  321. {
  322. CHECK_SIG(CShareBase);
  323. // assume a property sheet notification
  324. return _OnPropertySheetNotify(hwnd, phdr);
  325. }
  326. //+-------------------------------------------------------------------------
  327. //
  328. // Method: CShareBase::_OnPropertySheetNotify, private
  329. //
  330. // Synopsis: WM_NOTIFY handler for the property sheet notification
  331. //
  332. //--------------------------------------------------------------------------
  333. BOOL
  334. CShareBase::_OnPropertySheetNotify(
  335. IN HWND hwnd,
  336. IN LPNMHDR phdr
  337. )
  338. {
  339. CHECK_SIG(CShareBase);
  340. switch (phdr->code)
  341. {
  342. case PSN_RESET: // cancel
  343. if (_DoCancel(hwnd))
  344. {
  345. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); // go away
  346. }
  347. else
  348. {
  349. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_INVALID);
  350. }
  351. return TRUE;
  352. case PSN_KILLACTIVE: // change to another page
  353. if (_ValidatePage(hwnd))
  354. {
  355. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  356. return FALSE;
  357. }
  358. else
  359. {
  360. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  361. return TRUE;
  362. }
  363. case PSN_APPLY:
  364. if (_DoApply(hwnd, !!(((LPPSHNOTIFY)phdr)->lParam)))
  365. {
  366. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); // go away
  367. }
  368. else
  369. {
  370. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_INVALID);
  371. }
  372. return TRUE;
  373. } // end switch (phdr->code)
  374. return FALSE;
  375. }
  376. //+-------------------------------------------------------------------------
  377. //
  378. // Method: CShareBase::_DoApply, public
  379. //
  380. // Synopsis: If anything has changed, apply the data
  381. //
  382. //--------------------------------------------------------------------------
  383. BOOL
  384. CShareBase::_DoApply(
  385. IN HWND hwnd,
  386. IN BOOL /*bClose*/
  387. )
  388. {
  389. CHECK_SIG(CShareBase);
  390. if (_bDirty)
  391. {
  392. _bDirty = FALSE;
  393. PropSheet_UnChanged(_GetFrameWindow(),_hwndPage);
  394. }
  395. return TRUE;
  396. }
  397. //+-------------------------------------------------------------------------
  398. //
  399. // Method: CShareBase::_DoCancel, public
  400. //
  401. // Synopsis: Do whatever is necessary to cancel the changes
  402. //
  403. //--------------------------------------------------------------------------
  404. BOOL
  405. CShareBase::_DoCancel(
  406. IN HWND hwnd
  407. )
  408. {
  409. CHECK_SIG(CShareBase);
  410. if (_bDirty)
  411. {
  412. _bDirty = FALSE;
  413. PropSheet_UnChanged(_GetFrameWindow(),_hwndPage);
  414. }
  415. return TRUE;
  416. }
  417. //+-------------------------------------------------------------------------
  418. //
  419. // Method: CShareBase::_MarkPageDirty, private
  420. //
  421. // Synopsis: A change has made such that the page is now dirty
  422. //
  423. //--------------------------------------------------------------------------
  424. VOID
  425. CShareBase::_MarkPageDirty(
  426. VOID
  427. )
  428. {
  429. CHECK_SIG(CShareBase);
  430. if (!_fInitializingPage)
  431. {
  432. if (!_bDirty)
  433. {
  434. appDebugOut((DEB_ITRACE, "Marking Sharing page dirty\n"));
  435. _bDirty = TRUE;
  436. PropSheet_Changed(_GetFrameWindow(),_hwndPage);
  437. }
  438. }
  439. }
  440. //+-------------------------------------------------------------------------
  441. //
  442. // Method: CShareBase::_ConnstructShareList, private
  443. //
  444. // Synopsis: Construct the list of shares for the current path by
  445. // iterating through the entire cache of shares and adding an
  446. // element for every path that matches.
  447. //
  448. //--------------------------------------------------------------------------
  449. HRESULT
  450. CShareBase::_ConstructShareList(
  451. VOID
  452. )
  453. {
  454. CHECK_SIG(CShareBase);
  455. appDebugOut((DEB_ITRACE, "_ConstructShareList\n"));
  456. // This routine sets _cShares, and _bNewShare, and adds to
  457. // the _pInfoList list
  458. HRESULT hr;
  459. DeleteShareInfoList(_pInfoList);
  460. _pCurInfo = NULL;
  461. _bNewShare = FALSE;
  462. appAssert(_pInfoList->IsSingle());
  463. appAssert(_pCurInfo == NULL);
  464. appAssert(_pszPath != NULL);
  465. hr = g_ShareCache.ConstructList(_pszPath, _pInfoList, &_cShares);
  466. if (SUCCEEDED(hr) && _cShares == 0)
  467. {
  468. // There are no existing shares. Construct an element to be used
  469. // by the UI to stash the new share's data
  470. hr = _ConstructNewShareInfo();
  471. }
  472. return hr;
  473. }
  474. //+-------------------------------------------------------------------------
  475. //
  476. // Method: CShareBase::_ConstructNewShareInfo, private
  477. //
  478. // Synopsis: Construct an element to be used by the UI to stash the new
  479. // share's data
  480. //
  481. //--------------------------------------------------------------------------
  482. HRESULT
  483. CShareBase::_ConstructNewShareInfo(
  484. VOID
  485. )
  486. {
  487. CHECK_SIG(CShareBase);
  488. HRESULT hr;
  489. CShareInfo* pNewInfo = new CShareInfo();
  490. if (NULL == pNewInfo)
  491. {
  492. return E_OUTOFMEMORY;
  493. }
  494. hr = pNewInfo->InitInstance();
  495. CHECK_HRESULT(hr);
  496. if (FAILED(hr))
  497. {
  498. delete pNewInfo;
  499. return hr;
  500. }
  501. hr = pNewInfo->SetPath(_pszPath);
  502. CHECK_HRESULT(hr);
  503. if (FAILED(hr))
  504. {
  505. delete pNewInfo;
  506. return hr;
  507. }
  508. NET_API_STATUS ret = pNewInfo->ReadCacheFlags ();
  509. if ( NERR_Success != ret )
  510. {
  511. delete pNewInfo;
  512. return HRESULT_FROM_WIN32 (ret);
  513. }
  514. _bNewShare = TRUE;
  515. pNewInfo->SetDirtyFlag(SHARE_FLAG_ADDED);
  516. pNewInfo->InsertBefore(_pInfoList);
  517. //NOTE: leave the count of shares to be zero. The count of shares only
  518. // reflects the number of committed shares (?)
  519. // Get the shell's name for the folder to use as the share name. This
  520. // gives us localized names for things like "Shared Documents".
  521. //
  522. // Sometimes the shell's name contains invalid characters, such
  523. // as when we're looking at the root of the drive. In that case
  524. // SHGetFileInfo returns "label (X:)" and IsValidShareName fails
  525. // on the colon. For those, try calling shell32's PathCleanupSpec
  526. // to make the name valid.
  527. //
  528. // If SHGetFileInfo and PathCleanupSpec fail to give us a good name,
  529. // fall back on the old method, which is...
  530. //
  531. // Give the share a default name. For paths like "X:\", use the default
  532. // "X", for paths like "X:\foo\bar\baz", use the default "baz".
  533. // For everything else, juse leave it blank. Also, check that the
  534. // computed default is not already a share name. If it is, leave it
  535. // blank.
  536. appAssert(NULL != _pszPath);
  537. WCHAR szDefault[2] = L"";
  538. PWSTR pszDefault = NULL;
  539. SHFILEINFOW sfi = {0};
  540. if (SHGetFileInfoW(_pszPath, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME))
  541. {
  542. if (IsValidShareName(sfi.szDisplayName, &hr))
  543. {
  544. pszDefault = sfi.szDisplayName;
  545. }
  546. else
  547. {
  548. int iResult = PathCleanupSpec(NULL, sfi.szDisplayName);
  549. if (0 == (iResult & (PCS_TRUNCATED|PCS_PATHTOOLONG|PCS_FATAL))
  550. && IsValidShareName(sfi.szDisplayName, &hr))
  551. {
  552. pszDefault = sfi.szDisplayName;
  553. }
  554. }
  555. //
  556. // NTRAID#NTBUG9-225755-2000/12/19-jeffreys
  557. //
  558. // Win9x boxes can't see the share if the name is long
  559. //
  560. if (NULL != pszDefault && wcslen(pszDefault) > LM20_NNLEN)
  561. {
  562. // Go back to the old way below
  563. pszDefault = NULL;
  564. }
  565. }
  566. if (NULL == pszDefault)
  567. {
  568. pszDefault = szDefault;
  569. int len = wcslen(_pszPath);
  570. if (len == 3 && _pszPath[1] == L':' && _pszPath[2] == L'\\')
  571. {
  572. szDefault[0] = _pszPath[0];
  573. }
  574. else
  575. {
  576. PWSTR pszTmp = wcsrchr(_pszPath, L'\\');
  577. if (pszTmp != NULL)
  578. {
  579. pszDefault = pszTmp + 1;
  580. }
  581. }
  582. }
  583. if (g_ShareCache.IsShareNameUsed(pszDefault))
  584. {
  585. pszDefault = szDefault;
  586. szDefault[0] = L'\0';
  587. }
  588. hr = pNewInfo->SetNetname(pszDefault);
  589. CHECK_HRESULT(hr);
  590. if (FAILED(hr))
  591. {
  592. // FEATURE: error handling?
  593. _bNewShare = FALSE;
  594. pNewInfo->Unlink();
  595. delete pNewInfo;
  596. return hr;
  597. }
  598. return hr;
  599. }
  600. //+-------------------------------------------------------------------------
  601. //
  602. // Method: CShareBase::_ValidateNewShareName, protected
  603. //
  604. // Synopsis: Return TRUE if the sharename is valid, performing
  605. // confirmations if necessary
  606. //
  607. //--------------------------------------------------------------------------
  608. BOOL
  609. CShareBase::_ValidateNewShareName(
  610. VOID
  611. )
  612. {
  613. CHECK_SIG(CShareBase);
  614. if (!_bNewShare)
  615. {
  616. // nothing to do
  617. return TRUE;
  618. }
  619. appAssert(NULL != _pCurInfo);
  620. if (NULL == _pCurInfo) // JonN 5/2/01 384155
  621. return FALSE;
  622. PWSTR pszShareName = _pCurInfo->GetNetname();
  623. appAssert(NULL != pszShareName);
  624. if ((NULL == pszShareName) || (0 == wcslen(pszShareName))) // PREFIX 240253
  625. {
  626. MyErrorDialog(_hwndPage, IERR_BlankShareName);
  627. return FALSE;
  628. }
  629. HRESULT uTemp;
  630. if (!IsValidShareName(pszShareName, &uTemp))
  631. {
  632. MyErrorDialog(_hwndPage, uTemp);
  633. return FALSE;
  634. }
  635. // Trying to create a reserved share?
  636. if (0 == _wcsicmp(g_szIpcShare, pszShareName))
  637. {
  638. MyErrorDialog(_hwndPage, IERR_SpecialShare);
  639. return FALSE;
  640. }
  641. if (0 == _wcsicmp(g_szAdminShare, pszShareName))
  642. {
  643. // We will let the admin create the admin$ share if they create
  644. // it in the directory specified by GetWindowsDirectory().
  645. WCHAR szWindowsDir[MAX_PATH];
  646. UINT err = GetWindowsDirectory(szWindowsDir, ARRAYLEN(szWindowsDir));
  647. if (err == 0)
  648. {
  649. // oh well, give them this error
  650. MyErrorDialog(_hwndPage, IERR_SpecialShare);
  651. return FALSE;
  652. }
  653. if (0 != _wcsicmp(_pCurInfo->GetPath(), szWindowsDir))
  654. {
  655. MyErrorDialog(_hwndPage, IERR_SpecialShare);
  656. return FALSE;
  657. }
  658. // otherwise, it is the right directory. Let them create it.
  659. }
  660. /* removed JonN 10/5/98
  661. // Check for downlevel accessibility
  662. // we should really get rid of this at some point -- JonN 7/18/97
  663. ULONG nType;
  664. if (NERR_Success != NetpPathType(NULL, pszShareName, &nType, INPT_FLAGS_OLDPATHS))
  665. {
  666. DWORD id = MyConfirmationDialog(
  667. _hwndPage,
  668. IERR_InaccessibleByDos,
  669. MB_YESNO | MB_ICONEXCLAMATION,
  670. pszShareName);
  671. if (id == IDNO)
  672. {
  673. return FALSE;
  674. }
  675. }
  676. */
  677. WCHAR szOldPath[PATHLEN+1];
  678. if (g_ShareCache.IsExistingShare(pszShareName, _pCurInfo->GetPath(), szOldPath))
  679. {
  680. DWORD id = ConfirmReplaceShare(_hwndPage, pszShareName, szOldPath, _pCurInfo->GetPath());
  681. if (id != IDYES)
  682. {
  683. return FALSE;
  684. }
  685. // User said to replace the old share. We need to add
  686. // a "delete" record for the old share.
  687. HRESULT hr;
  688. CShareInfo* pNewInfo = new CShareInfo();
  689. if (NULL == pNewInfo)
  690. {
  691. return FALSE;
  692. }
  693. hr = pNewInfo->InitInstance();
  694. CHECK_HRESULT(hr);
  695. if (FAILED(hr))
  696. {
  697. delete pNewInfo;
  698. return FALSE;
  699. }
  700. // only need net name for delete; ignore other fields
  701. hr = pNewInfo->SetNetname(pszShareName);
  702. CHECK_HRESULT(hr);
  703. if (FAILED(hr))
  704. {
  705. delete pNewInfo;
  706. return FALSE;
  707. }
  708. hr = pNewInfo->SetPath(szOldPath);
  709. CHECK_HRESULT(hr);
  710. if (FAILED(hr))
  711. {
  712. delete pNewInfo;
  713. return FALSE;
  714. }
  715. NET_API_STATUS ret = pNewInfo->ReadCacheFlags ();
  716. if ( NERR_Success != ret )
  717. {
  718. delete pNewInfo;
  719. return HRESULT_FROM_WIN32 (ret);
  720. }
  721. pNewInfo->SetDirtyFlag(SHARE_FLAG_REMOVE);
  722. pNewInfo->InsertBefore(_pReplaceList); // add to end of replace list
  723. }
  724. return TRUE;
  725. }
  726. //+-------------------------------------------------------------------------
  727. //
  728. // Method: CShareBase::_CommitShares, protected
  729. //
  730. // Synopsis: Commit outstanding share edits. Note that this method does
  731. // not reset _bDirty.
  732. //
  733. //--------------------------------------------------------------------------
  734. VOID
  735. CShareBase::_CommitShares(
  736. IN BOOL bNotShared
  737. )
  738. {
  739. CHECK_SIG(CShareBase);
  740. if (!_bDirty)
  741. {
  742. // nothing to do
  743. return;
  744. }
  745. if (bNotShared)
  746. {
  747. // When the user hits "Not Shared" after having had "Shared As"
  748. // selected, we don't actually delete anything (or even mark it
  749. // for deletion). This is so the user can hit "Shared As" again
  750. // and they haven't lost anything. However, if they subsequently
  751. // apply changes, we must go through and actually delete anything
  752. // that they wanted to delete. So, fix up our list to do this.
  753. // Delete SHARE_FLAG_ADDED nodes, and mark all others as
  754. // SHARE_FLAG_REMOVE.
  755. for (CShareInfo* p = (CShareInfo*) _pInfoList->Next();
  756. p != _pInfoList;
  757. )
  758. {
  759. CShareInfo* pNext = (CShareInfo*)p->Next();
  760. if (p->GetFlag() == SHARE_FLAG_ADDED)
  761. {
  762. // get rid of p
  763. p->Unlink();
  764. delete p;
  765. }
  766. else
  767. {
  768. p->SetDirtyFlag(SHARE_FLAG_REMOVE);
  769. }
  770. p = pNext;
  771. }
  772. }
  773. //
  774. // Commit the changes!
  775. //
  776. HRESULT hr;
  777. CShareInfo* p;
  778. // Delete all "replace" shares first. These are all the shares whos
  779. // names are being reused to share a different directory.
  780. // These replace deletes have already been confirmed.
  781. for (p = (CShareInfo*) _pReplaceList->Next();
  782. p != _pReplaceList;
  783. p = (CShareInfo*) p->Next())
  784. {
  785. appAssert(p->GetFlag() == SHARE_FLAG_REMOVE);
  786. NET_API_STATUS ret = p->Commit(NULL);
  787. if (ret != NERR_Success)
  788. {
  789. DisplayError(_hwndPage, IERR_CANT_DEL_SHARE, ret, p->GetNetname());
  790. // We've got a problem here because we couldn't delete a
  791. // share that will be added subsequently. Oh well...
  792. }
  793. // Note that we don't delete this list because we need to notify
  794. // the shell (*after* all changes) that all these guys have
  795. // changed (and get rid of those little hands)...
  796. }
  797. // Now, do all add/delete/modify of the current
  798. for (p = (CShareInfo*) _pInfoList->Next();
  799. p != _pInfoList;
  800. )
  801. {
  802. CShareInfo* pNext = (CShareInfo*)p->Next();
  803. if (0 != p->GetFlag())
  804. {
  805. if (SHARE_FLAG_REMOVE == p->GetFlag())
  806. {
  807. // confirm the delete, if there are connections
  808. DWORD id = ConfirmStopShare(_hwndPage, MB_YESNO, p->GetNetname());
  809. if (id != IDYES)
  810. {
  811. p->SetDirtyFlag(0); // don't do anything to it
  812. }
  813. }
  814. NET_API_STATUS ret = p->Commit(NULL);
  815. if (ret != NERR_Success)
  816. {
  817. HRESULT hrMsg = 0;
  818. switch (p->GetFlag())
  819. {
  820. case SHARE_FLAG_ADDED: hrMsg = IERR_CANT_ADD_SHARE; break;
  821. case SHARE_FLAG_MODIFY: hrMsg = IERR_CANT_MODIFY_SHARE; break;
  822. case SHARE_FLAG_REMOVE: hrMsg = IERR_CANT_DEL_SHARE; break;
  823. default:
  824. appAssert(!"Illegal flag for a failed commit!");
  825. }
  826. DisplayError(_hwndPage, hrMsg, ret, p->GetNetname());
  827. }
  828. else
  829. {
  830. if (p->GetFlag() == SHARE_FLAG_REMOVE)
  831. {
  832. // nuke it!
  833. p->Unlink();
  834. delete p;
  835. }
  836. else
  837. {
  838. p->SetDirtyFlag(0); // clear flag on success
  839. }
  840. }
  841. }
  842. p = pNext;
  843. }
  844. if (_bNewShare)
  845. {
  846. _bNewShare = FALSE;
  847. _cShares = 1;
  848. }
  849. // I refresh the cache, even though the shell comes back and asks
  850. // for a refresh after every SHChangeNotify. However, SHChangeNotify
  851. // is asynchronous, and I need the cache refreshed immediately so I
  852. // can display the new share information, if the "apply" button was
  853. // hit and the page didn't go away.
  854. g_ShareCache.Refresh();
  855. appDebugOut((DEB_TRACE,
  856. "Changed share for path %ws, notifying shell\n",
  857. _pszPath));
  858. SHChangeNotify(SHCNE_NETSHARE, SHCNF_PATH, _pszPath, NULL);
  859. // FEATURE: might want to use SHCNE_NETUNSHARE, but the shell doesn't
  860. // distinguish them
  861. // Now, notify the shell about all the paths we got rid of to be able
  862. // to use their share names ...
  863. for (p = (CShareInfo*) _pReplaceList->Next();
  864. p != _pReplaceList;
  865. )
  866. {
  867. appAssert(p->GetFlag() == SHARE_FLAG_REMOVE);
  868. appDebugOut((DEB_TRACE,
  869. "Got rid of share on path %ws, notifying shell\n",
  870. p->GetPath()));
  871. // We're going to be asked by the shell to refresh the cache once
  872. // for every notify. But, seeing as how the average case is zero
  873. // of these notifies, don't worry about it.
  874. SHChangeNotify(SHCNE_NETSHARE, SHCNF_PATH, p->GetPath(), NULL);
  875. CShareInfo* pNext = (CShareInfo*) p->Next();
  876. p->Unlink();
  877. delete p;
  878. p = pNext;
  879. }
  880. _ConstructShareList();
  881. }
  882. //+-------------------------------------------------------------------------
  883. //
  884. // Member: CSharingPropertyPage::SizeWndProc, public
  885. //
  886. // Synopsis: "allow" edit window subclass proc to disallow non-numeric
  887. // characters.
  888. //
  889. // History: 5-Apr-95 BruceFo Created
  890. //
  891. //--------------------------------------------------------------------------
  892. LRESULT CALLBACK
  893. CSharingPropertyPage::SizeWndProc(
  894. IN HWND hwnd,
  895. IN UINT wMsg,
  896. IN WPARAM wParam,
  897. IN LPARAM lParam
  898. )
  899. {
  900. switch (wMsg)
  901. {
  902. case WM_CHAR:
  903. {
  904. WCHAR chCharCode = (WCHAR)wParam;
  905. if ( (chCharCode == TEXT('\t'))
  906. || (chCharCode == TEXT('\b'))
  907. || (chCharCode == TEXT('\n'))
  908. // || (chCharCode == TEXT('\x1b')) // ESCAPE key
  909. )
  910. {
  911. break;
  912. }
  913. if (chCharCode < TEXT('0') || chCharCode > TEXT('9'))
  914. {
  915. // bad key: ignore it
  916. MessageBeep(0xffffffff); // let user know it's an illegal char
  917. return FALSE;
  918. }
  919. break;
  920. }
  921. } // end of switch
  922. CSharingPropertyPage* pThis = (CSharingPropertyPage*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
  923. appAssert(NULL != pThis);
  924. appAssert(NULL != pThis->_pfnAllowProc);
  925. return CallWindowProc(pThis->_pfnAllowProc, hwnd, wMsg, wParam, lParam);
  926. }
  927. //+--------------------------------------------------------------------------
  928. //
  929. // Method: CSharingPropertyPage::CSharingPropertyPage, public
  930. //
  931. // Synopsis: Constructor
  932. //
  933. //---------------------------------------------------------------------------
  934. CSharingPropertyPage::CSharingPropertyPage(
  935. IN PWSTR pszPath,
  936. IN BOOL bDialog // called as a dialog, not a property page?
  937. )
  938. :
  939. CShareBase(pszPath, bDialog),
  940. _wIDSelected(0), // JonN 7/12/00 140878
  941. _bItemDirty(FALSE),
  942. _bShareNameChanged(FALSE),
  943. _bCommentChanged(FALSE),
  944. _bUserLimitChanged(FALSE),
  945. _wMaxUsers(DEFAULT_MAX_USERS),
  946. _pfnAllowProc(NULL),
  947. _bIsCachingSupported (false)
  948. {
  949. INIT_SIG(CSharingPropertyPage);
  950. }
  951. //+--------------------------------------------------------------------------
  952. //
  953. // Method: CSharingPropertyPage::~CSharingPropertyPage, public
  954. //
  955. // Synopsis: Destructor
  956. //
  957. //---------------------------------------------------------------------------
  958. CSharingPropertyPage::~CSharingPropertyPage()
  959. {
  960. CHECK_SIG(CSharingPropertyPage);
  961. }
  962. //+-------------------------------------------------------------------------
  963. //
  964. // Method: CSharingPropertyPage::_PageProc, private
  965. //
  966. // Synopsis: Dialog Procedure for this object
  967. //
  968. //--------------------------------------------------------------------------
  969. BOOL
  970. CSharingPropertyPage::_PageProc(
  971. IN HWND hwnd,
  972. IN UINT msg,
  973. IN WPARAM wParam,
  974. IN LPARAM lParam
  975. )
  976. {
  977. CHECK_SIG(CSharingPropertyPage);
  978. switch (msg)
  979. {
  980. case WM_VSCROLL:
  981. // The up/down control changed the edit control: select it again
  982. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
  983. return TRUE;
  984. case WM_CLOSE:
  985. // NOTE: There is a bug where hitting "ESCAPE" with the focus on the
  986. // MLE for the "allow" text doesn't kill the property sheet unless we
  987. // forward the WM_CLOSE message on to the property sheet root dialog.
  988. return (BOOL)SendMessage(_GetFrameWindow(), msg, wParam, lParam);
  989. case WM_DESTROY:
  990. // restore original subclass to window.
  991. appAssert(NULL != GetDlgItem(hwnd,IDC_SHARE_ALLOW_VALUE));
  992. SetWindowLongPtr(GetDlgItem(hwnd,IDC_SHARE_ALLOW_VALUE), GWLP_WNDPROC, (LONG_PTR)_pfnAllowProc);
  993. break;
  994. } // end switch (msg)
  995. return CShareBase::_PageProc(hwnd, msg, wParam, lParam);
  996. }
  997. //+-------------------------------------------------------------------------
  998. //
  999. // Method: CSharingPropertyPage::_OnInitDialog, private
  1000. //
  1001. // Synopsis: WM_INITDIALOG handler
  1002. //
  1003. //--------------------------------------------------------------------------
  1004. BOOL
  1005. CSharingPropertyPage::_OnInitDialog(
  1006. IN HWND hwnd,
  1007. IN HWND hwndFocus,
  1008. IN LPARAM lInitParam
  1009. )
  1010. {
  1011. CHECK_SIG(CSharingPropertyPage);
  1012. appDebugOut((DEB_ITRACE, "_OnInitDialog\n"));
  1013. // Subclass allow edit control to disallow non-positive numbers
  1014. _pfnAllowProc = (WNDPROC)SetWindowLongPtr(
  1015. GetDlgItem(hwnd, IDC_SHARE_ALLOW_VALUE),
  1016. GWLP_WNDPROC,
  1017. (LONG_PTR)&SizeWndProc);
  1018. // use LanMan API constants to set maximum share name & comment lengths
  1019. SendDlgItemMessage(hwnd, IDC_SHARE_SHARENAME, EM_LIMITTEXT, NNLEN, 0L);
  1020. SendDlgItemMessage(hwnd, IDC_SHARE_COMMENT, EM_LIMITTEXT, MAXCOMMENTSZ, 0L);
  1021. if (_bDialog)
  1022. {
  1023. SetWindowText(hwnd, _pszPath);
  1024. }
  1025. else
  1026. {
  1027. _MyShow( hwnd, IDOK, FALSE );
  1028. _MyShow( hwnd, IDCANCEL, FALSE );
  1029. }
  1030. _InitializeControls(hwnd);
  1031. // #if DBG == 1
  1032. // Dump(L"_OnInitDialog finished");
  1033. // #endif // DBG == 1
  1034. return TRUE;
  1035. }
  1036. //+-------------------------------------------------------------------------
  1037. //
  1038. // Method: CSharingPropertyPage::_OnCommand, private
  1039. //
  1040. // Synopsis: WM_COMMAND handler
  1041. //
  1042. //--------------------------------------------------------------------------
  1043. BOOL
  1044. CSharingPropertyPage::_OnCommand(
  1045. IN HWND hwnd,
  1046. IN WORD wNotifyCode,
  1047. IN WORD wID,
  1048. IN HWND hwndCtl
  1049. )
  1050. {
  1051. CHECK_SIG(CSharingPropertyPage);
  1052. switch (wID)
  1053. {
  1054. //
  1055. // Notifications
  1056. //
  1057. case IDC_SHARE_NOTSHARED:
  1058. {
  1059. if (BN_CLICKED == wNotifyCode)
  1060. {
  1061. if ( (!_fInitializingPage)
  1062. && (IDC_SHARE_NOTSHARED != _wIDSelected) // JonN 7/11/00 140878
  1063. // JonN 7/11/00 140878
  1064. // sometimes you get BN_CLICKED even before the
  1065. // button is selected according to IsDlgButtonChecked
  1066. && (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_NOTSHARED))
  1067. )
  1068. {
  1069. _wIDSelected = IDC_SHARE_NOTSHARED;
  1070. _ReadControls(hwnd);
  1071. // Delete all shares from the combo box; convert the combo box
  1072. // to the edit control (default state), and then disable
  1073. // all the controls. Cache whatever shares we had, so if
  1074. // the user hits "Shared As", we can put them back.
  1075. if (_cShares > 1)
  1076. {
  1077. // JonN 7/11/00 140878
  1078. // Additional BN_CLICKED notifications are coming in while
  1079. // the MSG_MULTIDEL dialog is still onscreen, resulting
  1080. // in multiple copies of the dialog.
  1081. _fInitializingPage++; // JonN 7/11/00 140878
  1082. DWORD id = MyConfirmationDialog(
  1083. hwnd,
  1084. MSG_MULTIDEL,
  1085. MB_YESNO | MB_ICONQUESTION);
  1086. if (IDNO == id)
  1087. {
  1088. CheckRadioButton(
  1089. hwnd,
  1090. IDC_SHARE_NOTSHARED,
  1091. IDC_SHARE_SHAREDAS,
  1092. IDC_SHARE_SHAREDAS);
  1093. //
  1094. // JonN 3/8/01 140878 part 2 (unit-test 3/9/01)
  1095. // At this point, IDC_SHARE_SHAREDAS is selected,
  1096. // but focus is still on IDC_SHARE_NOTSHARED and
  1097. // _wIDSelected == IDC_SHARE_NOTSHARED.
  1098. // Correct this, but stay in the _fInitializingPage
  1099. // block so that the page will not be marked dirty.
  1100. //
  1101. SendMessage(hwnd, WM_NEXTDLGCTL,
  1102. (WPARAM)GetDlgItem(hwnd,IDC_SHARE_SHAREDAS),
  1103. (LPARAM)TRUE);
  1104. _wIDSelected = IDC_SHARE_SHAREDAS;
  1105. _fInitializingPage--; // JonN 7/11/00 140878
  1106. return TRUE;
  1107. }
  1108. _fInitializingPage--; // JonN 7/11/00 140878
  1109. }
  1110. //
  1111. // Next, regenerate the UI
  1112. //
  1113. _SetControlsFromData(hwnd, NULL);
  1114. _MarkPageDirty();
  1115. }
  1116. }
  1117. return TRUE;
  1118. }
  1119. case IDC_SHARE_SHAREDAS:
  1120. {
  1121. if (BN_CLICKED == wNotifyCode)
  1122. {
  1123. if ( (!_fInitializingPage)
  1124. && (IDC_SHARE_SHAREDAS != _wIDSelected) // JonN 7/11/00 140878
  1125. // JonN 7/11/00 140878
  1126. // Sometimes you get BN_CLICKED even before the
  1127. // button is selected according to IsDlgButtonChecked
  1128. && (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_SHAREDAS))
  1129. )
  1130. {
  1131. _wIDSelected = IDC_SHARE_SHAREDAS;
  1132. // if there were shares there that we just hid when the user
  1133. // pressed "Not Shared", then put them back.
  1134. //
  1135. // Regenerate the UI
  1136. //
  1137. _SetControlsFromData(hwnd, NULL);
  1138. _MarkPageDirty();
  1139. }
  1140. }
  1141. return TRUE;
  1142. }
  1143. case IDC_SHARE_SHARENAME:
  1144. {
  1145. if (EN_CHANGE == wNotifyCode)
  1146. {
  1147. if (!_fInitializingPage)
  1148. {
  1149. _bShareNameChanged = TRUE;
  1150. _MarkItemDirty();
  1151. }
  1152. EnableWindow (GetDlgItem(hwnd, IDC_SHARE_CACHING),
  1153. IsCachingSupported ());
  1154. }
  1155. return TRUE;
  1156. }
  1157. case IDC_SHARE_COMMENT:
  1158. {
  1159. if (EN_CHANGE == wNotifyCode)
  1160. {
  1161. if (!_fInitializingPage)
  1162. {
  1163. _bCommentChanged = TRUE;
  1164. _MarkItemDirty();
  1165. }
  1166. }
  1167. return TRUE;
  1168. }
  1169. case IDC_SHARE_SHARENAME_COMBO:
  1170. {
  1171. if (CBN_SELCHANGE == wNotifyCode)
  1172. {
  1173. _ReadControls(hwnd);
  1174. HWND hwndCombo = GetDlgItem(hwnd, IDC_SHARE_SHARENAME_COMBO);
  1175. int item = ComboBox_GetCurSel(hwndCombo);
  1176. LRESULT itemData = ComboBox_GetItemData(hwndCombo, item);
  1177. _pCurInfo = (CB_ERR == itemData) ? NULL : (CShareInfo *)itemData;
  1178. appAssert(NULL != _pCurInfo);
  1179. _SetFieldsFromCurrent(hwnd);
  1180. }
  1181. return TRUE;
  1182. }
  1183. case IDC_SHARE_MAXIMUM:
  1184. if (BN_CLICKED == wNotifyCode)
  1185. {
  1186. // Take away WS_TABSTOP from the "allow users" edit control
  1187. HWND hwndEdit = GetDlgItem(hwnd, IDC_SHARE_ALLOW_VALUE);
  1188. SetWindowLong(hwndEdit, GWL_STYLE, GetWindowLong(hwndEdit, GWL_STYLE) & ~WS_TABSTOP);
  1189. _CacheMaxUses(hwnd);
  1190. SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");
  1191. _bUserLimitChanged = TRUE;
  1192. _MarkItemDirty();
  1193. }
  1194. return TRUE;
  1195. case IDC_SHARE_ALLOW:
  1196. if (BN_CLICKED == wNotifyCode)
  1197. {
  1198. // Give WS_TABSTOP to the "allow users" edit control
  1199. HWND hwndEdit = GetDlgItem(hwnd, IDC_SHARE_ALLOW_VALUE);
  1200. SetWindowLong(hwndEdit, GWL_STYLE, GetWindowLong(hwndEdit, GWL_STYLE) | WS_TABSTOP);
  1201. // let the spin control set the edit control
  1202. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));
  1203. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
  1204. _bUserLimitChanged = TRUE;
  1205. _MarkItemDirty();
  1206. }
  1207. return TRUE;
  1208. case IDC_SHARE_ALLOW_VALUE:
  1209. {
  1210. if (EN_CHANGE == wNotifyCode)
  1211. {
  1212. _bUserLimitChanged = TRUE;
  1213. _MarkItemDirty();
  1214. }
  1215. if (EN_SETFOCUS == wNotifyCode)
  1216. {
  1217. if (1 != IsDlgButtonChecked(hwnd, IDC_SHARE_ALLOW))
  1218. {
  1219. CheckRadioButton(
  1220. hwnd,
  1221. IDC_SHARE_MAXIMUM,
  1222. IDC_SHARE_ALLOW,
  1223. IDC_SHARE_ALLOW);
  1224. }
  1225. // let the spin control set the edit control
  1226. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));
  1227. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
  1228. _bUserLimitChanged = TRUE;
  1229. _MarkItemDirty();
  1230. }
  1231. if (EN_KILLFOCUS == wNotifyCode)
  1232. {
  1233. _CacheMaxUses(hwnd);
  1234. }
  1235. return TRUE;
  1236. }
  1237. case IDC_SHARE_ALLOW_SPIN:
  1238. if (UDN_DELTAPOS == wNotifyCode)
  1239. {
  1240. if (1 != IsDlgButtonChecked(hwnd, IDC_SHARE_ALLOW))
  1241. {
  1242. CheckRadioButton(
  1243. hwnd,
  1244. IDC_SHARE_MAXIMUM,
  1245. IDC_SHARE_ALLOW,
  1246. IDC_SHARE_ALLOW);
  1247. }
  1248. _bUserLimitChanged = TRUE;
  1249. _MarkItemDirty();
  1250. }
  1251. return TRUE;
  1252. //
  1253. // Commands
  1254. //
  1255. case IDC_SHARE_PERMISSIONS:
  1256. return _OnPermissions(hwnd);
  1257. case IDC_SHARE_REMOVE:
  1258. return _OnRemove(hwnd);
  1259. case IDC_SHARE_NEWSHARE:
  1260. return _OnNewShare(hwnd);
  1261. case IDC_SHARE_CACHING:
  1262. return _OnCaching(hwnd);
  1263. default:
  1264. break;
  1265. }
  1266. return CShareBase::_OnCommand(hwnd, wNotifyCode, wID, hwndCtl);
  1267. }
  1268. //+-------------------------------------------------------------------------
  1269. //
  1270. // Method: CSharingPropertyPage::_OnHelp, private
  1271. //
  1272. // Synopsis: WM_HELP handler
  1273. //
  1274. //--------------------------------------------------------------------------
  1275. static const DWORD aHelpIds[] =
  1276. {
  1277. IDOK, HC_OK,
  1278. IDCANCEL, HC_CANCEL,
  1279. IDC_SHARE_SHARENAME, HC_SHARE_SHARENAME,
  1280. IDC_SHARE_SHARENAME_TEXT, HC_SHARE_SHARENAME,
  1281. IDC_SHARE_COMMENT, HC_SHARE_COMMENT,
  1282. IDC_SHARE_COMMENT_TEXT, HC_SHARE_COMMENT,
  1283. IDC_SHARE_MAXIMUM, HC_SHARE_MAXIMUM,
  1284. IDC_SHARE_ALLOW, HC_SHARE_ALLOW,
  1285. IDC_SHARE_ALLOW_VALUE, HC_SHARE_ALLOW_VALUE,
  1286. IDC_SHARE_ALLOW_SPIN, -1L, // 257807 by request of JillZ
  1287. IDC_SHARE_PERMISSIONS, HC_SHARE_PERMISSIONS,
  1288. IDC_SHARE_LIMIT, HC_SHARE_LIMIT,
  1289. IDC_SHARE_NOTSHARED, HC_SHARE_NOTSHARED,
  1290. IDC_SHARE_SHAREDAS, HC_SHARE_SHAREDAS,
  1291. IDC_SHARE_SHARENAME_COMBO, HC_SHARE_SHARENAME_COMBO,
  1292. IDC_SHARE_REMOVE, HC_SHARE_REMOVE,
  1293. IDC_SHARE_NEWSHARE, HC_SHARE_NEWSHARE,
  1294. IDC_SHARE_ICON, -1L, // 311328 JillZ
  1295. IDC_SHARE_TOPTEXT, -1L, // 311328 JillZ
  1296. 0,0
  1297. };
  1298. static const DWORD aCSCUIHelpIds[] =
  1299. {
  1300. IDC_SHARE_CACHING, IDH_SHARE_CACHING_BTN,
  1301. IDC_SHARE_CACHING_TEXT, IDH_SHARE_CACHING_BTN,
  1302. 0,0
  1303. };
  1304. BOOL
  1305. CSharingPropertyPage::_OnHelp(
  1306. IN HWND hwnd,
  1307. IN LPHELPINFO lphi
  1308. )
  1309. {
  1310. if (lphi->iContextType == HELPINFO_WINDOW) // a control
  1311. {
  1312. WCHAR szHelp[50];
  1313. if ( IDC_SHARE_CACHING == lphi->iCtrlId || IDC_SHARE_CACHING_TEXT == lphi->iCtrlId )
  1314. {
  1315. LoadString(g_hInstance, IDS_CSCUI_HELPFILENAME, szHelp, ARRAYLEN(szHelp));
  1316. WinHelp(
  1317. (HWND)lphi->hItemHandle,
  1318. szHelp,
  1319. HELP_WM_HELP,
  1320. (DWORD_PTR)aCSCUIHelpIds);
  1321. }
  1322. else
  1323. {
  1324. LoadString(g_hInstance, IDS_HELPFILENAME, szHelp, ARRAYLEN(szHelp));
  1325. WinHelp(
  1326. (HWND)lphi->hItemHandle,
  1327. szHelp,
  1328. HELP_WM_HELP,
  1329. (DWORD_PTR)aHelpIds);
  1330. }
  1331. }
  1332. return TRUE;
  1333. }
  1334. #define _AfxGetDlgCtrlID(hWnd) ((UINT)(WORD)::GetDlgCtrlID(hWnd))
  1335. HWND MyChildWindowFromPoint(HWND hWnd, POINT pt)
  1336. {
  1337. appAssert(hWnd != NULL);
  1338. // check child windows
  1339. ::ClientToScreen(hWnd, &pt);
  1340. HWND hWndChild = ::GetWindow(hWnd, GW_CHILD);
  1341. for (; hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
  1342. {
  1343. if (_AfxGetDlgCtrlID(hWndChild) != (WORD)-1 &&
  1344. (::GetWindowLong(hWndChild, GWL_STYLE) & WS_VISIBLE))
  1345. {
  1346. // see if point hits the child window
  1347. RECT rect;
  1348. ::GetWindowRect(hWndChild, &rect);
  1349. if (PtInRect(&rect, pt))
  1350. return hWndChild;
  1351. }
  1352. }
  1353. return NULL; // not found
  1354. }
  1355. //+-------------------------------------------------------------------------
  1356. //
  1357. // Method: CSharingPropertyPage::_OnContextMenu, private
  1358. //
  1359. // Synopsis: WM_CONTEXTMENU handler
  1360. //
  1361. //--------------------------------------------------------------------------
  1362. BOOL
  1363. CSharingPropertyPage::_OnContextMenu(
  1364. IN HWND hwnd,
  1365. IN HWND hCtrlWnd,
  1366. IN int xPos,
  1367. IN int yPos
  1368. )
  1369. {
  1370. WCHAR szHelp[50];
  1371. int ctrlID = 0;
  1372. if ( hwnd == hCtrlWnd )
  1373. {
  1374. POINT point;
  1375. point.x = xPos;
  1376. point.y = yPos;
  1377. if ( ScreenToClient (hwnd, &point) )
  1378. {
  1379. hCtrlWnd = MyChildWindowFromPoint (hwnd, point); // takes client coords
  1380. if ( !hCtrlWnd )
  1381. hCtrlWnd = hwnd;
  1382. }
  1383. }
  1384. ctrlID = GetDlgCtrlID (hCtrlWnd);
  1385. if ( IDC_SHARE_CACHING == ctrlID || IDC_SHARE_CACHING_TEXT == ctrlID )
  1386. {
  1387. LoadString(g_hInstance, IDS_CSCUI_HELPFILENAME, szHelp, ARRAYLEN(szHelp));
  1388. WinHelp(
  1389. hCtrlWnd,
  1390. szHelp,
  1391. HELP_CONTEXTMENU,
  1392. (DWORD_PTR)aCSCUIHelpIds);
  1393. }
  1394. else
  1395. {
  1396. LoadString(g_hInstance, IDS_HELPFILENAME, szHelp, ARRAYLEN(szHelp));
  1397. WinHelp(
  1398. hCtrlWnd,
  1399. szHelp,
  1400. HELP_CONTEXTMENU,
  1401. (DWORD_PTR)aHelpIds);
  1402. }
  1403. return TRUE;
  1404. }
  1405. //+-------------------------------------------------------------------------
  1406. //
  1407. // Method: CSharingPropertyPage::_OnPermissions, private
  1408. //
  1409. // Synopsis: WM_COMMAND handler: the permissions button
  1410. //
  1411. //--------------------------------------------------------------------------
  1412. BOOL
  1413. CSharingPropertyPage::_OnPermissions(
  1414. IN HWND hwnd
  1415. )
  1416. {
  1417. CHECK_SIG(CSharingPropertyPage);
  1418. appAssert(NULL != _pCurInfo);
  1419. if (NULL == _pCurInfo) // JonN 5/2/01 384155
  1420. return TRUE;
  1421. if (STYPE_SPECIAL & _pCurInfo->GetType())
  1422. {
  1423. MyErrorDialog(hwnd, IERR_AdminShare);
  1424. return TRUE;
  1425. }
  1426. WCHAR szShareName[NNLEN + 1];
  1427. if (_cShares > 0)
  1428. {
  1429. wcscpy(szShareName, _pCurInfo->GetNetname());
  1430. }
  1431. else
  1432. {
  1433. GetDlgItemText(hwnd, IDC_SHARE_SHARENAME, szShareName, ARRAYLEN(szShareName));
  1434. // don't trim spaces, this might be an existing share with spaces in its name
  1435. }
  1436. PSECURITY_DESCRIPTOR pNewSecDesc = NULL;
  1437. PSECURITY_DESCRIPTOR pSecDesc = _pCurInfo->GetSecurityDescriptor();
  1438. appAssert(NULL == pSecDesc || IsValidSecurityDescriptor(pSecDesc));
  1439. BOOL bSecDescChanged;
  1440. LONG err = EditShareAcl(
  1441. hwnd,
  1442. NULL,
  1443. szShareName,
  1444. pSecDesc,
  1445. &bSecDescChanged,
  1446. &pNewSecDesc);
  1447. if (bSecDescChanged)
  1448. {
  1449. appAssert(IsValidSecurityDescriptor(pNewSecDesc));
  1450. _pCurInfo->TransferSecurityDescriptor(pNewSecDesc);
  1451. _MarkPageDirty();
  1452. }
  1453. return TRUE;
  1454. }
  1455. //+-------------------------------------------------------------------------
  1456. //
  1457. // Method: CSharingPropertyPage::_OnRemove, private
  1458. //
  1459. // Synopsis: WM_COMMAND handler: the Remove button
  1460. //
  1461. //--------------------------------------------------------------------------
  1462. BOOL
  1463. CSharingPropertyPage::_OnRemove(
  1464. IN HWND hwnd
  1465. )
  1466. {
  1467. CHECK_SIG(CSharingPropertyPage);
  1468. appAssert(_cShares > 1);
  1469. appAssert(_pCurInfo != NULL);
  1470. if (NULL == _pCurInfo) // JonN 5/2/01 384155
  1471. return TRUE;
  1472. //
  1473. // Alter the data structures
  1474. //
  1475. if (_pCurInfo->GetFlag() == SHARE_FLAG_ADDED)
  1476. {
  1477. // Something that was added this session is being removed: get rid of
  1478. // it from our list.
  1479. _pCurInfo->Unlink();
  1480. delete _pCurInfo;
  1481. _pCurInfo = NULL;
  1482. // the _SetControlsFromData call resets the _pCurInfo pointer
  1483. }
  1484. else
  1485. {
  1486. // if the state was MODIFY or no state, then set it to REMOVE
  1487. _pCurInfo->SetDirtyFlag(SHARE_FLAG_REMOVE);
  1488. }
  1489. --_cShares;
  1490. //
  1491. // Next, regenerate the UI
  1492. //
  1493. _SetControlsFromData(hwnd, NULL);
  1494. _MarkPageDirty();
  1495. return TRUE;
  1496. }
  1497. //+-------------------------------------------------------------------------
  1498. //
  1499. // Method: CSharingPropertyPage::_OnNewShare, private
  1500. //
  1501. // Synopsis: WM_COMMAND handler: the New Share button
  1502. //
  1503. //--------------------------------------------------------------------------
  1504. BOOL
  1505. CSharingPropertyPage::_OnNewShare(
  1506. IN HWND hwnd
  1507. )
  1508. {
  1509. CHECK_SIG(CSharingPropertyPage);
  1510. //
  1511. // First, create an object to put the new share into.
  1512. // FEATURE: for out of memory errors, should we pop up an error box?
  1513. //
  1514. HRESULT hr;
  1515. CShareInfo* pNewInfo = new CShareInfo();
  1516. if (NULL == pNewInfo)
  1517. {
  1518. return FALSE;
  1519. }
  1520. hr = pNewInfo->InitInstance();
  1521. CHECK_HRESULT(hr);
  1522. if (FAILED(hr))
  1523. {
  1524. delete pNewInfo;
  1525. return FALSE;
  1526. }
  1527. hr = pNewInfo->SetPath(_pszPath);
  1528. CHECK_HRESULT(hr);
  1529. if (FAILED(hr))
  1530. {
  1531. delete pNewInfo;
  1532. return FALSE;
  1533. }
  1534. NET_API_STATUS ret = pNewInfo->ReadCacheFlags ();
  1535. if ( NERR_Success != ret )
  1536. {
  1537. delete pNewInfo;
  1538. return HRESULT_FROM_WIN32 (ret);
  1539. }
  1540. pNewInfo->SetDirtyFlag(SHARE_FLAG_ADDED);
  1541. CDlgNewShare dlg(hwnd);
  1542. dlg.m_pInfoList = _pInfoList;
  1543. dlg.m_pReplaceList = _pReplaceList;
  1544. dlg.m_pShareInfo = pNewInfo;
  1545. if (dlg.DoModal())
  1546. {
  1547. _ReadControls(hwnd); // read current stuff
  1548. //
  1549. // Add the new one to the list
  1550. //
  1551. pNewInfo->InsertBefore(_pInfoList); // add to end of list
  1552. ++_cShares; // one more share in the list...
  1553. //
  1554. // Next, regenerate the UI
  1555. //
  1556. _SetControlsFromData(hwnd, pNewInfo->GetNetname());
  1557. _MarkPageDirty();
  1558. }
  1559. else
  1560. {
  1561. // user hit "cancel"
  1562. delete pNewInfo;
  1563. }
  1564. return TRUE;
  1565. }
  1566. //+-------------------------------------------------------------------------
  1567. //
  1568. // Method: CSharingPropertyPage::_OnCaching, private
  1569. //
  1570. // Synopsis: WM_COMMAND handler: the Caching button
  1571. //
  1572. //--------------------------------------------------------------------------
  1573. BOOL
  1574. CSharingPropertyPage::_OnCaching(
  1575. IN HWND hwnd
  1576. )
  1577. {
  1578. CHECK_SIG(CSharingPropertyPage);
  1579. // show wait cursor ??
  1580. HINSTANCE hInstance = ::LoadLibrary (L"FileMgmt.dll");
  1581. if ( hInstance )
  1582. {
  1583. typedef HRESULT (*PfnCacheSettingsDlg)(HWND hwndParent, DWORD & dwFlags);
  1584. PfnCacheSettingsDlg pfn = (PfnCacheSettingsDlg) ::GetProcAddress (
  1585. hInstance, "CacheSettingsDlg");
  1586. appAssert( NULL != _pCurInfo );
  1587. if ( pfn && NULL != _pCurInfo) // JonN 5/2/01 384155
  1588. {
  1589. DWORD dwFlags = _pCurInfo->GetCacheFlags ();
  1590. HRESULT hResult = pfn (hwnd, dwFlags);
  1591. if ( S_OK == hResult )
  1592. {
  1593. _pCurInfo->SetCacheFlags (dwFlags);
  1594. _MarkPageDirty();
  1595. }
  1596. }
  1597. ::FreeLibrary (hInstance);
  1598. return FALSE;
  1599. }
  1600. else
  1601. return FALSE;
  1602. return TRUE;
  1603. }
  1604. //+-------------------------------------------------------------------------
  1605. //
  1606. // Method: CSharingPropertyPage::_InitializeControls, private
  1607. //
  1608. // Synopsis: Initialize the controls from scratch
  1609. //
  1610. //--------------------------------------------------------------------------
  1611. VOID
  1612. CSharingPropertyPage::_InitializeControls(
  1613. IN HWND hwnd
  1614. )
  1615. {
  1616. CHECK_SIG(CSharingPropertyPage);
  1617. //
  1618. // Set defaults first
  1619. //
  1620. _SetControlsToDefaults(hwnd);
  1621. _fInitializingPage++; // JonN 7/11/00 140878
  1622. CheckRadioButton(
  1623. hwnd,
  1624. IDC_SHARE_NOTSHARED,
  1625. IDC_SHARE_SHAREDAS,
  1626. (_cShares > 0) ? IDC_SHARE_SHAREDAS : IDC_SHARE_NOTSHARED);
  1627. _fInitializingPage--; // JonN 7/11/00 140878
  1628. _SetControlsFromData(hwnd, NULL);
  1629. }
  1630. //+-------------------------------------------------------------------------
  1631. //
  1632. // Method: CSharingPropertyPage::_SetControlsToDefaults, private
  1633. //
  1634. // Synopsis: Set all the controls on the page to their default values
  1635. //
  1636. //--------------------------------------------------------------------------
  1637. VOID
  1638. CSharingPropertyPage::_SetControlsToDefaults(
  1639. IN HWND hwnd
  1640. )
  1641. {
  1642. CHECK_SIG(CSharingPropertyPage);
  1643. _fInitializingPage++; // JonN 7/11/00 140878
  1644. // Make "Maximum" the default number of users, and clear the value field
  1645. // (which the spin button set on creation?).
  1646. CheckRadioButton(
  1647. hwnd,
  1648. IDC_SHARE_MAXIMUM,
  1649. IDC_SHARE_ALLOW,
  1650. IDC_SHARE_MAXIMUM);
  1651. SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");
  1652. // set the spin control range: 1 <--> large number
  1653. SendDlgItemMessage(
  1654. hwnd,
  1655. IDC_SHARE_ALLOW_SPIN,
  1656. UDM_SETRANGE,
  1657. 0,
  1658. MAKELONG(g_uiMaxUsers, 1));
  1659. _HideControls(hwnd, 0);
  1660. HWND hwndCombo = GetDlgItem(hwnd, IDC_SHARE_SHARENAME_COMBO);
  1661. ComboBox_ResetContent(hwndCombo);
  1662. SetDlgItemText(hwnd, IDC_SHARE_SHARENAME, L"");
  1663. SetDlgItemText(hwnd, IDC_SHARE_COMMENT, L"");
  1664. SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");
  1665. _fInitializingPage--; // JonN 7/11/00 140878
  1666. }
  1667. //+-------------------------------------------------------------------------
  1668. //
  1669. // Method: CSharingPropertyPage::SetControlsFromData, private
  1670. //
  1671. // Synopsis: From the class variables and current state of the radio
  1672. // buttons, set the enabled/disabled state of the buttons, as
  1673. // well as filling the controls with the appropriate values.
  1674. //
  1675. //--------------------------------------------------------------------------
  1676. VOID
  1677. CSharingPropertyPage::_SetControlsFromData(
  1678. IN HWND hwnd,
  1679. IN PWSTR pszPreferredSelection
  1680. )
  1681. {
  1682. CHECK_SIG(CSharingPropertyPage);
  1683. BOOL bIsShared = (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_SHAREDAS));
  1684. _EnableControls(hwnd, bIsShared);
  1685. if (bIsShared)
  1686. {
  1687. appDebugOut((DEB_ITRACE, "_SetControlsFromData: path is shared\n"));
  1688. _HideControls(hwnd, _cShares);
  1689. //
  1690. // Now, set controls based on actual data
  1691. //
  1692. _fInitializingPage++; // JonN 7/11/00 140878
  1693. // if there is a new share, we only show the edit control for the
  1694. // share name, not the combo box.
  1695. if (_cShares == 0)
  1696. {
  1697. _pCurInfo = (CShareInfo*)_pInfoList->Next();
  1698. appAssert(NULL != _pCurInfo);
  1699. if (NULL != _pCurInfo) // JonN 5/2/01 384155
  1700. SetDlgItemText(hwnd, IDC_SHARE_SHARENAME, _pCurInfo->GetNetname());
  1701. }
  1702. else // (_cShares > 0)
  1703. {
  1704. // in the combo box, the "item data" is the CShareInfo pointer of
  1705. // the item.
  1706. // fill the combo.
  1707. HWND hwndCombo = GetDlgItem(hwnd, IDC_SHARE_SHARENAME_COMBO);
  1708. ComboBox_ResetContent(hwndCombo);
  1709. for (CShareInfo* p = (CShareInfo*) _pInfoList->Next();
  1710. p != _pInfoList;
  1711. p = (CShareInfo*) p->Next())
  1712. {
  1713. if (p->GetFlag() != SHARE_FLAG_REMOVE)
  1714. {
  1715. int item = ComboBox_AddString(hwndCombo, p->GetNetname());
  1716. if (CB_ERR == item || CB_ERRSPACE == item)
  1717. {
  1718. // FEATURE: how to recover here?
  1719. break;
  1720. }
  1721. if (CB_ERR == ComboBox_SetItemData(hwndCombo, item, p))
  1722. {
  1723. // FEATURE: how to recover here?
  1724. }
  1725. }
  1726. }
  1727. int sel = 0;
  1728. if (NULL != pszPreferredSelection)
  1729. {
  1730. sel = ComboBox_FindStringExact(hwndCombo, -1, pszPreferredSelection);
  1731. if (CB_ERR == sel)
  1732. {
  1733. sel = 0;
  1734. }
  1735. }
  1736. ComboBox_SetCurSel(hwndCombo, sel);
  1737. _pCurInfo = (CShareInfo*)ComboBox_GetItemData(hwndCombo, sel);
  1738. appAssert(NULL != _pCurInfo);
  1739. }
  1740. _fInitializingPage--; // JonN 7/11/00 140878
  1741. // From the current item, set the rest of the fields
  1742. _SetFieldsFromCurrent(hwnd);
  1743. // This must be called after the share name field is initialized.
  1744. EnableWindow(GetDlgItem(hwnd, IDC_SHARE_CACHING), IsCachingSupported ());
  1745. }
  1746. else
  1747. {
  1748. appDebugOut((DEB_ITRACE, "_SetControlsFromData: path is not shared\n"));
  1749. _pCurInfo = NULL;
  1750. }
  1751. }
  1752. //+-------------------------------------------------------------------------
  1753. //
  1754. // Method: CSharingPropertyPage::_EnableControls, private
  1755. //
  1756. // Synopsis: Enable/disable controls
  1757. //
  1758. //--------------------------------------------------------------------------
  1759. VOID
  1760. CSharingPropertyPage::_EnableControls(
  1761. IN HWND hwnd,
  1762. IN BOOL bEnable
  1763. )
  1764. {
  1765. CHECK_SIG(CSharingPropertyPage);
  1766. int idControls[] =
  1767. {
  1768. IDC_SHARE_SHARENAME_TEXT,
  1769. IDC_SHARE_SHARENAME,
  1770. IDC_SHARE_SHARENAME_COMBO,
  1771. IDC_SHARE_COMMENT_TEXT,
  1772. IDC_SHARE_COMMENT,
  1773. IDC_SHARE_LIMIT,
  1774. IDC_SHARE_MAXIMUM,
  1775. IDC_SHARE_ALLOW,
  1776. IDC_SHARE_ALLOW_SPIN,
  1777. IDC_SHARE_ALLOW_VALUE,
  1778. IDC_SHARE_REMOVE,
  1779. IDC_SHARE_NEWSHARE,
  1780. IDC_SHARE_PERMISSIONS
  1781. };
  1782. for (int i = 0; i < ARRAYLEN(idControls); i++)
  1783. {
  1784. EnableWindow(GetDlgItem(hwnd, idControls[i]), bEnable);
  1785. }
  1786. EnableWindow(GetDlgItem(hwnd, IDC_SHARE_CACHING),
  1787. bEnable && IsCachingSupported ());
  1788. }
  1789. //+-------------------------------------------------------------------------
  1790. //
  1791. // Method: CSharingPropertyPage::_HideControls, private
  1792. //
  1793. // Synopsis: Hide or show the controls based on the current number
  1794. // of shares.
  1795. //
  1796. //--------------------------------------------------------------------------
  1797. VOID
  1798. CSharingPropertyPage::_HideControls(
  1799. IN HWND hwnd,
  1800. IN int cShares
  1801. )
  1802. {
  1803. CHECK_SIG(CSharingPropertyPage);
  1804. _MyShow( hwnd, IDC_SHARE_REMOVE, !!(cShares > 1) );
  1805. _MyShow( hwnd, IDC_SHARE_NEWSHARE, !!(cShares >= 1) );
  1806. _MyShow( hwnd, IDC_SHARE_SHARENAME, !!(cShares < 1) );
  1807. _MyShow( hwnd, IDC_SHARE_SHARENAME_COMBO, !!(cShares >= 1) );
  1808. }
  1809. //+-------------------------------------------------------------------------
  1810. //
  1811. // Method: CSharingPropertyPage::_SetFieldsFromCurrent, private
  1812. //
  1813. // Synopsis: From the currently selected share, set the property page
  1814. // controls.
  1815. //
  1816. //--------------------------------------------------------------------------
  1817. VOID
  1818. CSharingPropertyPage::_SetFieldsFromCurrent(
  1819. IN HWND hwnd
  1820. )
  1821. {
  1822. CHECK_SIG(CSharingPropertyPage);
  1823. appAssert(NULL != _pCurInfo);
  1824. _fInitializingPage++; // JonN 7/11/00 140878
  1825. SetDlgItemText(hwnd, IDC_SHARE_COMMENT,
  1826. (NULL == _pCurInfo) ? L'\0' : _pCurInfo->GetRemark());
  1827. DWORD dwLimit = (NULL == _pCurInfo) // JonN 5/2/01 384155
  1828. ? SHI_USES_UNLIMITED : _pCurInfo->GetMaxUses();
  1829. if (dwLimit == SHI_USES_UNLIMITED)
  1830. {
  1831. _wMaxUsers = DEFAULT_MAX_USERS;
  1832. appDebugOut((DEB_ITRACE, "_SetFieldsFromCurrent: unlimited users\n"));
  1833. CheckRadioButton(
  1834. hwnd,
  1835. IDC_SHARE_MAXIMUM,
  1836. IDC_SHARE_ALLOW,
  1837. IDC_SHARE_MAXIMUM);
  1838. SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");
  1839. }
  1840. else
  1841. {
  1842. _wMaxUsers = (WORD)dwLimit;
  1843. appDebugOut((DEB_ITRACE,
  1844. "_SetFieldsFromCurrent: max users = %d\n",
  1845. _wMaxUsers));
  1846. CheckRadioButton(
  1847. hwnd,
  1848. IDC_SHARE_MAXIMUM,
  1849. IDC_SHARE_ALLOW,
  1850. IDC_SHARE_ALLOW);
  1851. // let the spin control set the edit control
  1852. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));
  1853. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
  1854. }
  1855. _fInitializingPage--; // JonN 7/11/00 140878
  1856. }
  1857. //+-------------------------------------------------------------------------
  1858. //
  1859. // Method: CSharingPropertyPage::_ReadControls, private
  1860. //
  1861. // Synopsis: Load the data in the controls into internal data structures.
  1862. //
  1863. //--------------------------------------------------------------------------
  1864. BOOL
  1865. CSharingPropertyPage::_ReadControls(
  1866. IN HWND hwnd
  1867. )
  1868. {
  1869. CHECK_SIG(CSharingPropertyPage);
  1870. if (!_bItemDirty)
  1871. {
  1872. // nothing to read
  1873. appDebugOut((DEB_ITRACE, "_ReadControls: item not dirty\n"));
  1874. return TRUE;
  1875. }
  1876. appDebugOut((DEB_ITRACE, "_ReadControls: item dirty\n"));
  1877. appAssert(NULL != _pCurInfo);
  1878. if (NULL == _pCurInfo) // JonN 5/2/01 384155
  1879. return TRUE;
  1880. if (_bShareNameChanged)
  1881. {
  1882. appDebugOut((DEB_ITRACE, "_ReadControls: share name changed\n"));
  1883. WCHAR szShareName[NNLEN + 1];
  1884. GetDlgItemText(hwnd, IDC_SHARE_SHARENAME, szShareName, ARRAYLEN(szShareName));
  1885. TrimLeadingAndTrailingSpaces(szShareName);
  1886. _pCurInfo->SetNetname(szShareName);
  1887. _bShareNameChanged = FALSE;
  1888. }
  1889. if (_bCommentChanged)
  1890. {
  1891. appDebugOut((DEB_ITRACE, "_ReadControls: comment changed\n"));
  1892. WCHAR szComment[MAXCOMMENTSZ + 1];
  1893. GetDlgItemText(hwnd, IDC_SHARE_COMMENT, szComment, ARRAYLEN(szComment));
  1894. _pCurInfo->SetRemark(szComment);
  1895. _bCommentChanged = FALSE;
  1896. }
  1897. if (_bUserLimitChanged)
  1898. {
  1899. appDebugOut((DEB_ITRACE, "_ReadControls: user limit changed\n"));
  1900. if (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_MAXIMUM))
  1901. {
  1902. _pCurInfo->SetMaxUses(SHI_USES_UNLIMITED);
  1903. }
  1904. else if (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_ALLOW))
  1905. {
  1906. _CacheMaxUses(hwnd);
  1907. _pCurInfo->SetMaxUses(_wMaxUsers);
  1908. }
  1909. _bUserLimitChanged = FALSE;
  1910. }
  1911. _bItemDirty = FALSE;
  1912. return TRUE;
  1913. }
  1914. //+-------------------------------------------------------------------------
  1915. //
  1916. // Method: CSharingPropertyPage::_MarkItemDirty, private
  1917. //
  1918. // Synopsis: A change has made such that the current item (and page)
  1919. // is now dirty
  1920. //
  1921. //--------------------------------------------------------------------------
  1922. VOID
  1923. CSharingPropertyPage::_MarkItemDirty(
  1924. VOID
  1925. )
  1926. {
  1927. CHECK_SIG(CSharingPropertyPage);
  1928. if (!_fInitializingPage)
  1929. {
  1930. if (!_bItemDirty)
  1931. {
  1932. appDebugOut((DEB_ITRACE, "Marking Sharing page---current item---dirty\n"));
  1933. _bItemDirty = TRUE;
  1934. }
  1935. _MarkPageDirty();
  1936. }
  1937. }
  1938. //+-------------------------------------------------------------------------
  1939. //
  1940. // Method: CSharingPropertyPage::_ValidatePage, private
  1941. //
  1942. // Synopsis: Return TRUE if the current page is valid
  1943. //
  1944. //--------------------------------------------------------------------------
  1945. BOOL
  1946. CSharingPropertyPage::_ValidatePage(
  1947. IN HWND hwnd
  1948. )
  1949. {
  1950. CHECK_SIG(CSharingPropertyPage);
  1951. _ReadControls(hwnd); // read current stuff
  1952. if (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_SHAREDAS))
  1953. {
  1954. // If the user is creating a share on the property sheet (as
  1955. // opposed to using the "new share" dialog), we must validate the
  1956. // share.... Note that _bNewShare is still TRUE if the the user has
  1957. // clicked on "Not Shared", so we must check that too.
  1958. // Validate the share
  1959. if (!_ValidateNewShareName())
  1960. {
  1961. SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
  1962. return FALSE;
  1963. }
  1964. }
  1965. #if DBG == 1
  1966. Dump(L"_ValidatePage finished");
  1967. #endif // DBG == 1
  1968. return TRUE;
  1969. }
  1970. //+-------------------------------------------------------------------------
  1971. //
  1972. // Method: CSharingPropertyPage::_DoApply, public
  1973. //
  1974. // Synopsis: If anything has changed, apply the data
  1975. //
  1976. //--------------------------------------------------------------------------
  1977. BOOL
  1978. CSharingPropertyPage::_DoApply(
  1979. IN HWND hwnd,
  1980. IN BOOL bClose
  1981. )
  1982. {
  1983. CHECK_SIG(CSharingPropertyPage);
  1984. if (_bDirty)
  1985. {
  1986. BOOL bNotShared = (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_NOTSHARED));
  1987. if (!bNotShared)
  1988. {
  1989. _ReadControls(hwnd);
  1990. }
  1991. _CommitShares(bNotShared);
  1992. CShareBase::_DoApply(hwnd, bClose);
  1993. if (!bClose)
  1994. {
  1995. _InitializeControls(hwnd);
  1996. }
  1997. }
  1998. return TRUE;
  1999. }
  2000. //+-------------------------------------------------------------------------
  2001. //
  2002. // Method: CSharingPropertyPage::_DoCancel, public
  2003. //
  2004. // Synopsis: Do whatever is necessary to cancel the changes
  2005. //
  2006. //--------------------------------------------------------------------------
  2007. BOOL
  2008. CSharingPropertyPage::_DoCancel(
  2009. IN HWND hwnd
  2010. )
  2011. {
  2012. CHECK_SIG(CSharingPropertyPage);
  2013. if (_bDirty)
  2014. {
  2015. _bItemDirty = FALSE;
  2016. _bShareNameChanged = FALSE;
  2017. _bCommentChanged = FALSE;
  2018. _bUserLimitChanged = FALSE;
  2019. }
  2020. return CShareBase::_DoCancel(hwnd);
  2021. }
  2022. //+-------------------------------------------------------------------------
  2023. //
  2024. // Method: CSharingPropertyPage::_CacheMaxUses, private
  2025. //
  2026. // Synopsis:
  2027. //
  2028. //--------------------------------------------------------------------------
  2029. VOID
  2030. CSharingPropertyPage::_CacheMaxUses(
  2031. IN HWND hwnd
  2032. )
  2033. {
  2034. CHECK_SIG(CSharingPropertyPage);
  2035. DWORD dwRet = (DWORD)SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_GETPOS, 0, 0);
  2036. if (HIWORD(dwRet) != 0)
  2037. {
  2038. _wMaxUsers = DEFAULT_MAX_USERS;
  2039. // Reset the edit control to the new value
  2040. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));
  2041. SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
  2042. }
  2043. else
  2044. {
  2045. _wMaxUsers = LOWORD(dwRet);
  2046. }
  2047. }
  2048. //+-------------------------------------------------------------------------
  2049. //
  2050. // Method: CSharingPropertyPage::IsCachingSupported
  2051. //
  2052. // Synopsis: Does the operating system support caching on this share?
  2053. // This method initializes _bIsCachingSupported, if it is not already true
  2054. //
  2055. //--------------------------------------------------------------------------
  2056. bool CSharingPropertyPage::IsCachingSupported()
  2057. {
  2058. if (!_bIsCachingSupported)
  2059. {
  2060. LPWSTR pszShareName = 0;
  2061. WCHAR szShareName[NNLEN + 1];
  2062. UINT nRet = GetDlgItemText (_hwndPage, IDC_SHARE_SHARENAME, szShareName,
  2063. ARRAYLEN(szShareName));
  2064. if ( nRet > 0 )
  2065. pszShareName = szShareName;
  2066. else if ( _pCurInfo )
  2067. pszShareName = _pCurInfo->GetNetname ();
  2068. if ( pszShareName )
  2069. {
  2070. SHARE_INFO_501* pshi501 = NULL;
  2071. //
  2072. // On pre-NT5 systems (per IsaacHe), NetShareGetInfo will return
  2073. // ERROR_INVALID_LEVEL for info level 501 regardless of the share
  2074. // name provided. This is because the net code validates the
  2075. // requested level *before* validating the share name.
  2076. // Therefore, passing a blank share name works for our purposes
  2077. // here. If NetShareGetInfo returns ERROR_INVALID_LEVEL, this
  2078. // means level 501 is not supported which means the system
  2079. // isn't NT5 which means caching is not supported. No need to
  2080. // query the contents of *pshi501 because we're not interested in
  2081. // the level of caching at this point. [brianau - 8/11/98]
  2082. //
  2083. NET_API_STATUS retval = ::NetShareGetInfo(
  2084. L"", // machine name
  2085. L"", // share name
  2086. 501,
  2087. (LPBYTE*)&pshi501);
  2088. if (ERROR_INVALID_LEVEL != retval)
  2089. {
  2090. _bIsCachingSupported = true;
  2091. }
  2092. if ( pshi501 )
  2093. {
  2094. ::NetApiBufferFree (pshi501);
  2095. }
  2096. }
  2097. }
  2098. return _bIsCachingSupported;
  2099. }
  2100. #if DBG == 1
  2101. //+-------------------------------------------------------------------------
  2102. //
  2103. // Method: CSharingPropertyPage::Dump, private
  2104. //
  2105. // Synopsis:
  2106. //
  2107. //--------------------------------------------------------------------------
  2108. VOID
  2109. CSharingPropertyPage::Dump(
  2110. IN PWSTR pszCaption
  2111. )
  2112. {
  2113. CHECK_SIG(CSharingPropertyPage);
  2114. appDebugOut((DEB_TRACE,
  2115. "CSharingPropertyPage::Dump, %ws\n",
  2116. pszCaption));
  2117. appDebugOut((DEB_TRACE | DEB_NOCOMPNAME,
  2118. "\t This: 0x%08lx\n"
  2119. "\t Path: %ws\n"
  2120. "\t Page: 0x%08lx\n"
  2121. "\t Initializing?: %ws\n"
  2122. "\t Dirty?: %ws\n"
  2123. "\t Item dirty?: %ws\n"
  2124. "\t Share changed?: %ws\n"
  2125. "\tComment changed?: %ws\n"
  2126. "\tUsr Lim changed?: %ws\n"
  2127. "\t Max uses: %d\n"
  2128. "\t _pInfoList: 0x%08lx\n"
  2129. "\t _pCurInfo: 0x%08lx\n"
  2130. "\t Shares: %d\n"
  2131. ,
  2132. this,
  2133. _pszPath,
  2134. _hwndPage,
  2135. _fInitializingPage ? L"yes" : L"no",
  2136. _bDirty ? L"yes" : L"no",
  2137. _bItemDirty ? L"yes" : L"no",
  2138. _bShareNameChanged ? L"yes" : L"no",
  2139. _bCommentChanged ? L"yes" : L"no",
  2140. _bUserLimitChanged ? L"yes" : L"no",
  2141. _wMaxUsers,
  2142. _pInfoList,
  2143. _pCurInfo,
  2144. _cShares
  2145. ));
  2146. CShareInfo* p;
  2147. for (p = (CShareInfo*) _pInfoList->Next();
  2148. p != _pInfoList;
  2149. p = (CShareInfo*) p->Next())
  2150. {
  2151. p->Dump(L"Prop page list");
  2152. }
  2153. for (p = (CShareInfo*) _pReplaceList->Next();
  2154. p != _pReplaceList;
  2155. p = (CShareInfo*) p->Next())
  2156. {
  2157. p->Dump(L"Replace list");
  2158. }
  2159. }
  2160. #endif // DBG == 1