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.

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