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.

545 lines
16 KiB

  1. /*****************************************************************************\
  2. *
  3. * ftpprop.cpp - Property sheets
  4. *
  5. \*****************************************************************************/
  6. #include "priv.h"
  7. #include "ftpprop.h"
  8. #include "util.h"
  9. #include "resource.h"
  10. void CFtpProp::_HideCHMOD_UI(HWND hDlg)
  11. {
  12. // Now, so hide the UI.
  13. for (int nIndex = IDD_CHMOD; nIndex <= IDC_CHMOD_LAST; nIndex++)
  14. ShowEnableWindow(GetDlgItem(hDlg, nIndex), FALSE);
  15. }
  16. DWORD CFtpProp::_GetUnixPermissions(void)
  17. {
  18. DWORD dwPermissions = 0;
  19. LPCITEMIDLIST pidl = m_pflHfpl->GetPidl(0); // They don't give us a ref.
  20. if (pidl)
  21. {
  22. dwPermissions = FtpItemID_GetUNIXPermissions(ILGetLastID(pidl));
  23. }
  24. return dwPermissions;
  25. }
  26. static const DWORD c_dwUnixPermissionArray[] = {UNIX_CHMOD_READ_OWNER, UNIX_CHMOD_WRITE_OWNER, UNIX_CHMOD_EXEC_OWNER,
  27. UNIX_CHMOD_READ_GROUP, UNIX_CHMOD_WRITE_GROUP, UNIX_CHMOD_EXEC_GROUP,
  28. UNIX_CHMOD_READ_ALL, UNIX_CHMOD_WRITE_ALL, UNIX_CHMOD_EXEC_ALL};
  29. // NOTE: If we need to set focus rects for the check boxes, we can steal code from:
  30. // \\rastaman\ntwin\src\shell\security\aclui\chklist.cpp
  31. HRESULT CFtpProp::_SetCHMOD_UI(HWND hDlg)
  32. {
  33. DWORD dwUnixPermissions = _GetUnixPermissions();
  34. for (int nIndex = 0; nIndex < ARRAYSIZE(c_dwUnixPermissionArray); nIndex++)
  35. {
  36. // Is this permission set?
  37. CheckDlgButton(hDlg, (IDD_CHMOD + nIndex), (dwUnixPermissions & c_dwUnixPermissionArray[nIndex]));
  38. }
  39. return S_OK;
  40. }
  41. DWORD CFtpProp::_GetCHMOD_UI(HWND hDlg)
  42. {
  43. DWORD dwUnixPermissions = 0;
  44. for (int nIndex = 0; nIndex < ARRAYSIZE(c_dwUnixPermissionArray); nIndex++)
  45. {
  46. // Is it checked in the UI?
  47. if (IsDlgButtonChecked(hDlg, (IDD_CHMOD + nIndex)))
  48. {
  49. // Yes, so set the big.
  50. dwUnixPermissions |= c_dwUnixPermissionArray[nIndex];
  51. }
  52. }
  53. return dwUnixPermissions;
  54. }
  55. /*****************************************************************************\
  56. FUNCTION: _SetCHMOD_CB
  57. DESCRIPTION:
  58. If we were able to rename the file, return the output pidl.
  59. Also tell anybody who cares that this LPITEMIDLIST needs to be refreshed.
  60. The "A" emphasizes that the filename is received in ANSI.
  61. _UNDOCUMENTED_: The documentation on SetNameOf's treatment of
  62. the source pidl is random. It seems to suggest that the source
  63. pidl is ILFree'd by SetNameOf, but it isn't.
  64. \*****************************************************************************/
  65. HRESULT CFtpProp::_CommitCHMOD(HINTERNET hint, HINTPROCINFO * phpi, BOOL * pfReleaseHint)
  66. {
  67. HRESULT hr;
  68. HINTERNET hintResponse;
  69. WIRECHAR wFtpCommand[MAX_PATH];
  70. LPCITEMIDLIST pidl = m_pflHfpl->GetPidl(0); // They don't give us a ref.
  71. // 1. Create "SITE chmod <m_dwNewPermissions> <filename>" string
  72. wnsprintfA(wFtpCommand, ARRAYSIZE(wFtpCommand), FTP_CMD_SITE_CHMOD_TEMPL, m_dwNewPermissions, FtpPidl_GetLastItemWireName(pidl));
  73. hr = FtpCommandWrap(hint, FALSE, FALSE, FTP_TRANSFER_TYPE_ASCII, wFtpCommand, NULL, &hintResponse);
  74. if (SUCCEEDED(hr))
  75. {
  76. // Update the pidl with the new Permissions so our cache isn't out of date.
  77. CFtpDir * pfd = m_pff->GetFtpDir();
  78. FtpItemID_SetUNIXPermissions(pidl, m_dwNewPermissions);
  79. if (pfd)
  80. {
  81. pfd->ReplacePidl(pidl, pidl);
  82. FtpChangeNotify(m_hwnd, FtpPidl_DirChoose(pidl, SHCNE_RENAMEFOLDER, SHCNE_RENAMEITEM), m_pff, pfd, pidl, pidl, TRUE);
  83. pfd->Release();
  84. }
  85. InternetCloseHandleWrap(hintResponse, TRUE);
  86. }
  87. else
  88. {
  89. DisplayWininetError(m_hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_CHMOD, IDS_FTPERR_WININET, MB_OK, NULL);
  90. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  91. }
  92. return hr;
  93. }
  94. HRESULT CFtpProp::_CommitCHMOD_CB(HINTERNET hint, HINTPROCINFO * phpi, LPVOID pvData, BOOL * pfReleaseHint)
  95. {
  96. CFtpProp * pfp = (CFtpProp *) pvData;
  97. return pfp->_CommitCHMOD(hint, phpi, pfReleaseHint);
  98. }
  99. /*****************************************************************************\
  100. FUNCTION: OnInitDialog
  101. DESCRIPTION:
  102. Fill the dialog with cool stuff.
  103. \*****************************************************************************/
  104. BOOL CFtpProp::OnInitDialog(HWND hDlg)
  105. {
  106. EVAL(SUCCEEDED(m_ftpDialogTemplate.InitDialog(hDlg, TRUE, IDC_ITEM, m_pff, m_pflHfpl)));
  107. m_fChangeModeSupported = FALSE; // Default to false
  108. #ifdef FEATURE_CHANGE_PERMISSIONS
  109. // Is the correct number of items selected to possibly enable the CHMOD feature?
  110. if (1 == m_pflHfpl->GetCount())
  111. {
  112. // Yes, now the question is, is it supported by the server?
  113. CFtpDir * pfd = m_pff->GetFtpDir();
  114. if (pfd)
  115. {
  116. // Does the server support it?
  117. m_fChangeModeSupported = pfd->IsCHMODSupported();
  118. if (m_fChangeModeSupported)
  119. {
  120. // Yes, so hide the "Not supported by server" string.
  121. ShowEnableWindow(GetDlgItem(hDlg, IDC_CHMOD_NOT_ALLOWED), FALSE);
  122. _SetCHMOD_UI(hDlg); // Update the checkboxes with what's available.
  123. }
  124. else
  125. {
  126. // No, so hide the CHMOD UI. The warning that it's not supported by
  127. // the server is already visible.
  128. _HideCHMOD_UI(hDlg);
  129. }
  130. pfd->Release();
  131. }
  132. else
  133. {
  134. // No, so hide the CHMOD UI. This happens on the property sheet for
  135. // the server.
  136. _HideCHMOD_UI(hDlg);
  137. // Also remove the server not supported warning.
  138. ShowEnableWindow(GetDlgItem(hDlg, IDC_CHMOD_NOT_ALLOWED), FALSE);
  139. }
  140. }
  141. else
  142. {
  143. // No, so just remove that UI.
  144. _HideCHMOD_UI(hDlg);
  145. // Also remove the server not supported warning.
  146. ShowEnableWindow(GetDlgItem(hDlg, IDC_CHMOD_NOT_ALLOWED), FALSE);
  147. // Maybe we need a message saying, "Can't do this with this many items selected"
  148. }
  149. #endif // FEATURE_CHANGE_PERMISSIONS
  150. return 1;
  151. }
  152. /*****************************************************************************\
  153. FUNCTION: OnClose
  154. DESCRIPTION:
  155. \*****************************************************************************/
  156. BOOL CFtpProp::OnClose(HWND hDlg)
  157. {
  158. BOOL fResult = TRUE;
  159. #ifdef FEATURE_CHANGE_PERMISSIONS
  160. // Did m_ftpDialogTemplate.OnClose() finish all the work it needed in order
  161. // to close? This work currently changes the filename. If so, we
  162. // will then want to try to apply the UNIX Permission changes if any where
  163. // made.
  164. if (m_fChangeModeSupported)
  165. {
  166. // Now we need to apply the CHMOD.
  167. // TODO:
  168. DWORD dwCurPermissions = _GetUnixPermissions();
  169. m_dwNewPermissions = _GetCHMOD_UI(hDlg);
  170. // Did the user change the permissions
  171. if (dwCurPermissions != m_dwNewPermissions)
  172. {
  173. CFtpDir * pfd = m_pff->GetFtpDir();
  174. if (pfd)
  175. {
  176. // Yes, so commit those changes to the server.
  177. if (FAILED(pfd->WithHint(NULL, m_hwnd, _CommitCHMOD_CB, (LPVOID) this, NULL, m_pff)))
  178. {
  179. EVAL(SUCCEEDED(_SetCHMOD_UI(hDlg)));
  180. fResult = FALSE;
  181. }
  182. pfd->Release();
  183. }
  184. }
  185. }
  186. #endif // FEATURE_CHANGE_PERMISSIONS
  187. if (fResult)
  188. {
  189. m_ftpDialogTemplate.OnClose(hDlg, m_hwnd, m_pff, m_pflHfpl);
  190. }
  191. return fResult;
  192. }
  193. /*****************************************************************************\
  194. FUNCTION: OnDestroy
  195. DESCRIPTION:
  196. Fill the dialog with cool stuff.
  197. \*****************************************************************************/
  198. BOOL CFtpProp::OnDestroy(HWND hDlg)
  199. {
  200. m_ftpDialogTemplate.OnDestroy(hDlg, TRUE, IDC_ITEM, m_pff, m_pflHfpl);
  201. return TRUE;
  202. }
  203. #ifdef FEATURE_CHANGE_PERMISSIONS
  204. INT_PTR CFtpProp::_SetWhiteBGCtlColor(HWND hDlg, HDC hdc, HWND hwndCtl)
  205. {
  206. INT_PTR fResult = 0;
  207. if ((hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GROUPBOX)) ||
  208. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_LABEL_OWNER)) ||
  209. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_LABEL_GROUP)) ||
  210. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_LABEL_ALL)) ||
  211. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_OR)) ||
  212. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_OW)) ||
  213. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_OE)) ||
  214. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GR)) ||
  215. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GW)) ||
  216. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GE)) ||
  217. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_AR)) ||
  218. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_AW)) ||
  219. (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_AE)))
  220. {
  221. SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  222. SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  223. fResult = (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
  224. }
  225. return fResult;
  226. }
  227. #endif // FEATURE_CHANGE_PERMISSIONS
  228. /*****************************************************************************\
  229. * DlgProc
  230. \*****************************************************************************/
  231. INT_PTR CFtpProp::DlgProc(HWND hDlg, UINT wm, WPARAM wParam, LPARAM lParam)
  232. {
  233. INT_PTR fResult = 0; // not Handled
  234. CFtpProp * pfp = (CFtpProp *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  235. switch (wm)
  236. {
  237. case WM_INITDIALOG:
  238. {
  239. LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE) lParam;
  240. pfp = (CFtpProp *)ppsp->lParam;
  241. SetWindowLongPtr(hDlg, GWLP_USERDATA, (LPARAM)pfp);
  242. ASSERT(pfp);
  243. fResult = pfp->OnInitDialog(hDlg);
  244. }
  245. break;
  246. case WM_NOTIFY:
  247. if (lParam)
  248. {
  249. switch (((NMHDR *)lParam)->code)
  250. {
  251. case PSN_APPLY:
  252. if (pfp->OnClose(hDlg))
  253. {
  254. fResult = FALSE; // Tell comctl32 I'm happy
  255. }
  256. else
  257. {
  258. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
  259. fResult = TRUE; // Tell comctl32 to look at the error code and don't close.
  260. }
  261. break;
  262. case PSN_TRANSLATEACCELERATOR:
  263. if (pfp->m_ftpDialogTemplate.HasNameChanged(hDlg, pfp->m_pff, pfp->m_pflHfpl))
  264. PropSheet_Changed(GetParent(hDlg), hDlg);
  265. break;
  266. }
  267. }
  268. break;
  269. #ifdef FEATURE_CHANGE_PERMISSIONS
  270. case WM_CTLCOLORSTATIC:
  271. case WM_CTLCOLOREDIT:
  272. fResult = pfp->_SetWhiteBGCtlColor(hDlg, (HDC)wParam, (HWND)lParam);
  273. break;
  274. #endif // FEATURE_CHANGE_PERMISSIONS
  275. case WM_DESTROY:
  276. fResult = pfp->OnDestroy(hDlg);
  277. break;
  278. }
  279. return fResult;
  280. }
  281. /*****************************************************************************\
  282. * DoProp_OnThread
  283. *
  284. * Display a property sheet on the current thread.
  285. *
  286. * WARNING! VIOLATION OF OLE REFERENCE STUFF!
  287. *
  288. * The PFP that comes in must be Release()d when we're done.
  289. *
  290. * The reason is that the caller has "given us" the reference;
  291. * we now own it and are responsible for releasing it.
  292. \*****************************************************************************/
  293. DWORD CFtpProp::_PropertySheetThread(void)
  294. {
  295. HRESULT hrOleInit;
  296. PROPSHEETHEADER psh;
  297. PROPSHEETPAGE psp;
  298. TCHAR szTitle[MAX_PATH];
  299. hrOleInit = SHOleInitialize(0);
  300. ASSERT(SUCCEEDED(hrOleInit));
  301. // This will allow the dialog to work with items outside of the font.
  302. // So Date, Name, and URL can be in the correct font even through
  303. // it's not supported by the DLL's font.
  304. InitComctlForNaviteFonts();
  305. LoadString(HINST_THISDLL, IDS_PROP_SHEET_TITLE, szTitle, ARRAYSIZE(szTitle));
  306. // psh.hwndParent being NULL or valid will determine if the property
  307. // sheet appears in the taskbar. We do want it there to be consistent
  308. // with the shell.
  309. //
  310. // NOTE: Comctl32's property sheet code will make this act modal by
  311. // disabling the parent window (m_hwnd). We need to fix this
  312. // (#202885) by creating a dummy window and using that as the
  313. // parent.
  314. psh.hwndParent = SHCreateWorkerWindow(NULL, m_hwnd, 0, 0, NULL, NULL);
  315. psh.dwSize = sizeof(psh);
  316. psh.dwFlags = (PSH_PROPTITLE | PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP);
  317. psh.hInstance = g_hinst;
  318. psh.pszCaption = szTitle;
  319. psh.nPages = 1;
  320. psh.nStartPage = 0;
  321. psh.ppsp = &psp;
  322. psp.dwSize = sizeof(psp);
  323. psp.dwFlags = PSP_DEFAULT;
  324. psp.hInstance = g_hinst;
  325. psp.pszTemplate = MAKEINTRESOURCE(IDD_FILEPROP);
  326. psp.pfnDlgProc = CFtpProp::DlgProc;
  327. psp.lParam = (LPARAM)this;
  328. PropertySheet(&psh);
  329. DestroyWindow(psh.hwndParent);
  330. this->Release();
  331. SHOleUninitialize(hrOleInit);
  332. return 0;
  333. }
  334. /*****************************************************************************\
  335. * CFtpProp_DoProp
  336. *
  337. * Display a property sheet with stuff in it.
  338. \*****************************************************************************/
  339. HRESULT CFtpProp_DoProp(CFtpPidlList * pflHfpl, CFtpFolder * pff, HWND hwnd)
  340. {
  341. CFtpProp * pfp;
  342. HRESULT hres = CFtpProp_Create(pflHfpl, pff, hwnd, &pfp);
  343. if (SUCCEEDED(hres))
  344. {
  345. HANDLE hThread;
  346. DWORD id;
  347. hThread = CreateThread(0, 0, CFtpProp::_PropertySheetThreadProc, (LPVOID) pfp, 0, &id);
  348. if (hThread)
  349. {
  350. // It will release it self if the thread was created.
  351. CloseHandle(hThread);
  352. hres = S_OK;
  353. }
  354. else
  355. {
  356. pfp->Release();
  357. hres = E_UNEXPECTED;
  358. }
  359. }
  360. return hres;
  361. }
  362. /*****************************************************************************\
  363. * CFtpProp_Create
  364. *
  365. * Display a property sheet with stuff in it.
  366. \*****************************************************************************/
  367. HRESULT CFtpProp_Create(CFtpPidlList * pflHfpl, CFtpFolder * pff, HWND hwnd, CFtpProp ** ppfp)
  368. {
  369. HRESULT hr = E_OUTOFMEMORY;
  370. CFtpProp * pfp;
  371. pfp = *ppfp = new CFtpProp();
  372. if (pfp)
  373. {
  374. pfp->m_pff = pff;
  375. if (pff)
  376. pff->AddRef();
  377. pfp->m_pflHfpl = pflHfpl;
  378. if (pflHfpl)
  379. pflHfpl->AddRef();
  380. pfp->m_hwnd = hwnd;
  381. hr = S_OK;
  382. }
  383. return hr;
  384. }
  385. /****************************************************\
  386. Constructor
  387. \****************************************************/
  388. CFtpProp::CFtpProp() : m_cRef(1)
  389. {
  390. DllAddRef();
  391. // This needs to be allocated in Zero Inited Memory.
  392. // Assert that all Member Variables are inited to Zero.
  393. ASSERT(!m_pff);
  394. ASSERT(!m_hwnd);
  395. LEAK_ADDREF(LEAK_CFtpProp);
  396. }
  397. /****************************************************\
  398. Destructor
  399. \****************************************************/
  400. CFtpProp::~CFtpProp()
  401. {
  402. IUnknown_Set(&m_pff, NULL);
  403. IUnknown_Set(&m_pflHfpl, NULL);
  404. DllRelease();
  405. LEAK_DELREF(LEAK_CFtpProp);
  406. }
  407. //===========================
  408. // *** IUnknown Interface ***
  409. //===========================
  410. ULONG CFtpProp::AddRef()
  411. {
  412. m_cRef++;
  413. return m_cRef;
  414. }
  415. ULONG CFtpProp::Release()
  416. {
  417. ASSERT(m_cRef > 0);
  418. m_cRef--;
  419. if (m_cRef > 0)
  420. return m_cRef;
  421. delete this;
  422. return 0;
  423. }
  424. HRESULT CFtpProp::QueryInterface(REFIID riid, void **ppvObj)
  425. {
  426. if (IsEqualIID(riid, IID_IUnknown))
  427. {
  428. *ppvObj = SAFECAST(this, IUnknown *);
  429. }
  430. else
  431. {
  432. TraceMsg(TF_FTPQI, "CFtpProp::QueryInterface() failed.");
  433. *ppvObj = NULL;
  434. return E_NOINTERFACE;
  435. }
  436. AddRef();
  437. return S_OK;
  438. }