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.

674 lines
17 KiB

  1. // this is the internal content - specific stuff related to the
  2. // CShellExt object
  3. #include "priv.h"
  4. #include <tchar.h>
  5. #include <iiscnfgp.h>
  6. //
  7. #include <inetinfo.h>
  8. #include <winsvc.h>
  9. #include <iwamreg.h>
  10. #include <shlwapi.h>
  11. #include "wrapmb.h"
  12. #include "Sink.h"
  13. #include "eddir.h"
  14. #include "shellext.h"
  15. #include "wrapmb.h"
  16. //the key type string for the virtual directories
  17. #define MDSZ_W3_VDIR_TYPE _T("IIsWebVirtualDir")
  18. extern HINSTANCE g_hmodThisDll;
  19. //Handle to this DLL itself.
  20. BOOL MakeWAMApplication (IN LPCTSTR pszPath, IN BOOL fCreate);
  21. BOOL MyFormatString1 (IN LPTSTR pszSource, IN DWORD cchMax, LPTSTR pszReplace);
  22. //---------------------------------------------------------------
  23. INT_PTR CALLBACK
  24. EditDirDlgProc (HWND hDlg,
  25. UINT uMessage,
  26. WPARAM wParam,
  27. LPARAM lParam)
  28. {
  29. //the pointer to the object is passed in as the private lParam, store it away
  30. if (uMessage == WM_INITDIALOG)
  31. {
  32. SetWindowLongPtr (hDlg, DWLP_USER, lParam);
  33. }
  34. //dialog object pointer from the window
  35. CEditDirectory * pdlg = (CEditDirectory *) GetWindowLongPtr (hDlg, DWLP_USER);
  36. if (!pdlg)
  37. return FALSE;
  38. //let the object do the work
  39. return pdlg->OnMessage (hDlg, uMessage, wParam, lParam);
  40. }
  41. //=====================================================================================
  42. //---------------------------------------------------------------
  43. CEditDirectory::CEditDirectory (HWND hParent):
  44. m_hParent (hParent),
  45. m_bool_read (FALSE),
  46. m_bool_write (FALSE),
  47. m_bool_dirbrowse (FALSE),
  48. m_bool_source (FALSE),
  49. m_bool_oldSource (FALSE),
  50. m_int_AppPerms (APPPERM_NONE),
  51. // m_pMBCom (NULL),
  52. m_fNewItem (FALSE),
  53. m_hDlg (NULL)
  54. {
  55. }
  56. //---------------------------------------------------------------
  57. CEditDirectory::~CEditDirectory ()
  58. {
  59. }
  60. //---------------------------------------------------------------
  61. INT_PTR CEditDirectory::DoModal ()
  62. {
  63. return DialogBoxParam (
  64. g_hmodThisDll, //handle to application instance
  65. MAKEINTRESOURCE (IDD_ALIAS), //identifies dialog box template
  66. m_hParent, //handle to owner window
  67. EditDirDlgProc, //pointer to dialog box procedure
  68. (LPARAM) this // initialization value
  69. );
  70. }
  71. //---------------------------------------------------------------
  72. //return FALSE if we do NOT handle the message
  73. BOOL CEditDirectory::OnMessage (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  74. {
  75. switch (uMsg)
  76. {
  77. case WM_INITDIALOG:
  78. //return success
  79. return OnInitDialog (hDlg);
  80. case WM_COMMAND:
  81. switch (LOWORD (wParam))
  82. {
  83. case IDC_FULLCONTROL:
  84. OnSource (hDlg);
  85. return TRUE;
  86. case IDC_READ:
  87. OnRead (hDlg);
  88. return TRUE;
  89. case IDC_WRITE:
  90. OnWrite (hDlg);
  91. return TRUE;
  92. case IDOK:
  93. OnOK (hDlg);
  94. return TRUE;
  95. case IDCANCEL:
  96. EndDialog (IDCANCEL);
  97. return TRUE;
  98. }
  99. break;
  100. };
  101. //return whether or not we handled the message
  102. return FALSE;
  103. }
  104. //----------------------------------------------------------------
  105. //CDialog simulation routines
  106. void CEditDirectory::UpdateData (BOOL fDialogToData)
  107. {
  108. //get the data from the dialog
  109. if (fDialogToData)
  110. {
  111. //get the text items first
  112. GetWindowText (m_hEditAlias, m_sz_alias, MAX_PATH);
  113. GetWindowText (m_hEditPath, m_sz_path, MAX_PATH);
  114. //read the checkboxes
  115. m_bool_read = (SendMessage (m_hChkRead, BM_GETCHECK, 0, 0) == BST_CHECKED);
  116. m_bool_write = (SendMessage (m_hChkWrite, BM_GETCHECK, 0, 0) == BST_CHECKED);
  117. m_bool_dirbrowse = (SendMessage (m_hChkDirBrowse, BM_GETCHECK, 0, 0) == BST_CHECKED);
  118. m_bool_source = (SendMessage (m_hChkSource, BM_GETCHECK, 0, 0) == BST_CHECKED);
  119. //read the AppPerm radio buttons
  120. if (SendMessage (m_hRdoScripts, BM_GETCHECK, 0, 0) == BST_CHECKED)
  121. {
  122. m_int_AppPerms = APPPERM_SCRIPTS;
  123. }
  124. else if (SendMessage (m_hRdoExecute, BM_GETCHECK, 0, 0) == BST_CHECKED)
  125. {
  126. m_int_AppPerms = APPPERM_EXECUTE;
  127. }
  128. else
  129. {
  130. m_int_AppPerms = APPPERM_NONE;
  131. }
  132. }
  133. else
  134. {
  135. //put it back into the dialog
  136. // set the text items first
  137. SetWindowText (m_hEditAlias, m_sz_alias);
  138. SetWindowText (m_hEditPath, m_sz_path);
  139. //set the checkboxes
  140. SendMessage (m_hChkRead, BM_SETCHECK, m_bool_read ? BST_CHECKED :
  141. BST_UNCHECKED, 0);
  142. SendMessage (m_hChkWrite, BM_SETCHECK, m_bool_write ? BST_CHECKED :
  143. BST_UNCHECKED, 0);
  144. SendMessage (m_hChkDirBrowse, BM_SETCHECK, m_bool_dirbrowse ?
  145. BST_CHECKED : BST_UNCHECKED, 0);
  146. SendMessage (m_hChkSource, BM_SETCHECK, m_bool_source ? BST_CHECKED
  147. : BST_UNCHECKED, 0);
  148. //set the AppPerm radio buttons
  149. SendMessage (m_hRdoNone, BM_SETCHECK,
  150. (m_int_AppPerms == APPPERM_NONE) ? BST_CHECKED : BST_UNCHECKED, 0);
  151. SendMessage (m_hRdoScripts, BM_SETCHECK,
  152. (m_int_AppPerms == APPPERM_SCRIPTS) ? BST_CHECKED : BST_UNCHECKED, 0);
  153. SendMessage (m_hRdoExecute, BM_SETCHECK,
  154. (m_int_AppPerms == APPPERM_EXECUTE) ? BST_CHECKED : BST_UNCHECKED, 0);
  155. }
  156. }
  157. //----------------------------------------------------------------
  158. BOOL CEditDirectory::InitHandles (HWND hDlg)
  159. {
  160. m_hDlg = hDlg;
  161. m_hEditAlias = GetDlgItem (hDlg, IDC_ALIAS);
  162. m_hEditPath = GetDlgItem (hDlg, IDC_PATH);
  163. m_hChkRead = GetDlgItem (hDlg, IDC_READ);
  164. m_hChkWrite = GetDlgItem (hDlg, IDC_WRITE);
  165. m_hChkDirBrowse = GetDlgItem (hDlg, IDC_DIRBROWSE);
  166. m_hChkSource = GetDlgItem (hDlg, IDC_FULLCONTROL);
  167. m_hRdoNone = GetDlgItem (hDlg, IDC_RDO_NONE);
  168. m_hRdoExecute = GetDlgItem (hDlg, IDC_RDO_EXECUTE);
  169. m_hRdoScripts = GetDlgItem (hDlg, IDC_RDO_SCRIPTS);
  170. return TRUE;
  171. }
  172. //----------------------------------------------------------------
  173. BOOL CEditDirectory::OnInitDialog (HWND hDlg)
  174. {
  175. BOOL f = FALSE;
  176. CWrapMetaBase mb;
  177. DWORD dword;
  178. TCHAR sz[MAX_PATH];
  179. InitHandles (hDlg);
  180. ZeroMemory (sz, MAX_PATH);
  181. //keep a copy of the original alias for later verification
  182. StrCpy (m_szOrigAlias,
  183. *m_sz_alias == _T ('/') ? m_sz_alias + 1 : m_sz_alias);
  184. StrCpy (m_sz_alias, m_szOrigAlias);
  185. //open up the metabase and read in the initial values
  186. // first things first.init the mb object
  187. if (!mb.FInit (m_pMBCom))
  188. {
  189. goto cleanup;
  190. }
  191. //build the metapath
  192. StrCpy (sz, m_szRoot);
  193. StrCat (sz, _T ("/"));
  194. StrCat (sz, m_sz_alias);
  195. //open the object - use root defaults if this is a new item
  196. if (m_fNewItem || !mb.Open (sz))
  197. {
  198. //if the node doesn 't exist - get the default values of the root
  199. if (!mb.Open (m_szRoot))
  200. {
  201. //if that doesn 't work - fail
  202. goto cleanup;
  203. }
  204. }
  205. //read the flags
  206. if (mb.GetDword (_T (""), MD_ACCESS_PERM, IIS_MD_UT_FILE, &dword, METADATA_INHERIT))
  207. {
  208. //interpret that thing
  209. m_bool_read = (dword & MD_ACCESS_READ) > 0;
  210. m_bool_write = (dword & MD_ACCESS_WRITE) > 0;
  211. m_bool_source = (dword & MD_ACCESS_SOURCE) > 0;
  212. //choose the correct app permissions radio button
  213. m_int_AppPerms = APPPERM_NONE;
  214. if (dword & MD_ACCESS_EXECUTE)
  215. {
  216. m_int_AppPerms = APPPERM_EXECUTE;
  217. }
  218. else if (dword & MD_ACCESS_SCRIPT)
  219. {
  220. m_int_AppPerms = APPPERM_SCRIPTS;
  221. }
  222. }
  223. //the dir browsing flag is stored in a different field
  224. if (mb.GetDword (_T (""), MD_DIRECTORY_BROWSING, IIS_MD_UT_FILE, &dword, METADATA_INHERIT))
  225. {
  226. m_bool_dirbrowse = (dword & MD_DIRBROW_ENABLED) > 0;
  227. }
  228. //close the metabase
  229. mb.Close ();
  230. //if this is a new item, force the app perms to scripts
  231. if (m_fNewItem)
  232. {
  233. m_int_AppPerms = APPPERM_SCRIPTS;
  234. }
  235. //set the data into place
  236. UpdateData (FALSE);
  237. //prep the source control button
  238. m_bool_oldSource = m_bool_source;
  239. EnableSourceControl ();
  240. cleanup:
  241. return f;
  242. }
  243. //----------------------------------------------------------------
  244. //we need to make sure that there is something in the alias field
  245. // an empty alias is not OK
  246. void CEditDirectory::OnOK (HWND hDlg)
  247. {
  248. BOOL f;
  249. DWORD err;
  250. DWORD dword;
  251. int iPar;
  252. CWrapMetaBase mb;
  253. TCHAR szPath[MAX_PATH];
  254. TCHAR szParent[MAX_PATH];
  255. TCHAR sz[MAX_PATH];
  256. TCHAR szCaption[MAX_PATH];
  257. ZeroMemory (sz, MAX_PATH);
  258. ZeroMemory (szPath, MAX_PATH);
  259. ZeroMemory (szParent, MAX_PATH);
  260. ZeroMemory (szCaption, MAX_PATH);
  261. UpdateData (TRUE);
  262. //trim leading and trailing spaces
  263. TrimLeft (m_sz_alias);
  264. TrimRight (m_sz_alias);
  265. //first test is to see if there is anything in it
  266. if (*m_sz_alias == 0)
  267. {
  268. LoadString (g_hmodThisDll, IDS_PAGE_TITLE, szCaption, MAX_PATH);
  269. LoadString (g_hmodThisDll, IDS_EMPTY_ALIAS, sz, MAX_PATH);
  270. MessageBox (hDlg, sz, szCaption, MB_OK);
  271. goto cleanup;
  272. }
  273. //at this point we need to check if write and execute / script are set as this
  274. // could open a potential security hole.If they are set, then alert the user
  275. // and ask if they reall really want to do that
  276. if ( m_bool_write
  277. && ((m_int_AppPerms == APPPERM_SCRIPTS) || (m_int_AppPerms == APPPERM_EXECUTE))
  278. )
  279. {
  280. LoadString (g_hmodThisDll, IDS_WRITEEXECUTE_WARNING, sz, MAX_PATH);
  281. LoadString (g_hmodThisDll, IDS_WARNING, szCaption, MAX_PATH);
  282. if (MessageBox (hDlg, sz, szCaption, MB_YESNO |
  283. MB_ICONEXCLAMATION) != IDYES)
  284. goto cleanup;
  285. }
  286. //get ready
  287. if (!mb.FInit (m_pMBCom))
  288. goto cleanup;
  289. //next, if a parent has been specified, it must exist
  290. // the alias may not contain a '/' character
  291. if (NULL != StrPBrk (m_sz_alias, _T ("\\/")))
  292. {
  293. LPTSTR pPar = StrRChr (m_sz_alias, NULL, _T ('/'));
  294. if (NULL == pPar)
  295. pPar = StrRChr (m_sz_alias, NULL, _T ('\\'));
  296. //make the parental path
  297. StrCpy (szParent, m_szRoot);
  298. StrCat (szParent, _T ("/"));
  299. StrCatN (szParent, m_sz_alias, m_sz_alias - pPar);
  300. //make sure the parent is there
  301. if (!mb.Open (szParent))
  302. {
  303. LoadString (g_hmodThisDll, IDS_PAGE_TITLE, szCaption, MAX_PATH);
  304. LoadString (g_hmodThisDll, IDS_NO_PARENT, sz, MAX_PATH);
  305. MessageBox (hDlg, sz, szCaption, MB_OK);
  306. goto cleanup;
  307. }
  308. //close right away - we are ok
  309. mb.Close ();
  310. }
  311. //Now we need to make sure that alias isn 't already taken
  312. _tcscpy (szPath, m_szRoot);
  313. _tcscat (szPath, _T ("/"));
  314. _tcscat (szPath, m_sz_alias);
  315. //try to open the object
  316. // however, if it is not a new object, and the alias has not changed,
  317. // do not see if the object is there becuase we know that it is and it is ok in this case
  318. if (_tcsicmp (m_sz_alias, m_szOrigAlias) || m_fNewItem)
  319. {
  320. if (mb.Open (szPath))
  321. {
  322. //we did open it ! Close it right away
  323. mb.Close ();
  324. //tell the user to pick another name
  325. LoadString (g_hmodThisDll, IDS_ALIAS_IS_TAKEN, sz, MAX_PATH);
  326. LoadString (g_hmodThisDll, IDS_PAGE_TITLE, szCaption, MAX_PATH);
  327. MyFormatString1 (sz, MAX_PATH, m_sz_alias);
  328. MessageBox (hDlg, sz, szCaption, MB_OK);
  329. goto cleanup;
  330. }
  331. }
  332. SetCursor (LoadCursor (NULL, IDC_WAIT));
  333. //if the name has changed, delete the old one
  334. if (_tcscmp (m_szOrigAlias, m_sz_alias) && !m_fNewItem)
  335. {
  336. //first we have to open the root
  337. if (mb.Open (m_szRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE))
  338. {
  339. MakeWAMApplication (m_szOrigAlias, FALSE);
  340. f = mb.DeleteObject (m_szOrigAlias);
  341. mb.Close ();
  342. }
  343. }
  344. //if we are creating a new object - then do so
  345. if (_tcscmp (m_szOrigAlias, m_sz_alias) || m_fNewItem)
  346. {
  347. //first we have to open the root
  348. if (mb.Open (m_szRoot, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE))
  349. {
  350. f = mb.AddObject (m_sz_alias);
  351. //set the key type
  352. f = mb.SetString (m_sz_alias, MD_KEY_TYPE, IIS_MD_UT_SERVER,
  353. MDSZ_W3_VDIR_TYPE, 0);
  354. mb.Close ();
  355. //create the WAM application at the new virtual directory location
  356. MakeWAMApplication (szPath, TRUE);
  357. }
  358. else
  359. err = GetLastError ();
  360. }
  361. //make sure we have the right path again
  362. _tcscpy (szPath, m_szRoot);
  363. _tcscat (szPath, _T ("/"));
  364. _tcscat (szPath, m_sz_alias);
  365. //open the target new item and write out its parameters
  366. if (mb.Open (szPath, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE))
  367. {
  368. //set the path into place
  369. f = mb.SetString (_T (""), MD_VR_PATH, IIS_MD_UT_FILE, m_sz_path);
  370. //put the access flags into place.There are other flags than the ones that are manupulated
  371. // here, so be careful to read the value first, then flip the flags, then write it back
  372. dword = 0;
  373. mb.GetDword (_T (""), MD_ACCESS_PERM, IIS_MD_UT_FILE, &dword, METADATA_INHERIT);
  374. //read permissions
  375. if (m_bool_read)
  376. dword |= MD_ACCESS_READ;
  377. else
  378. dword &= ~MD_ACCESS_READ;
  379. // write permissions
  380. if (m_bool_write)
  381. dword |= MD_ACCESS_WRITE;
  382. else
  383. dword &= ~MD_ACCESS_WRITE;
  384. // source read permissions
  385. if (m_bool_source)
  386. dword |= MD_ACCESS_SOURCE;
  387. else
  388. dword &= ~MD_ACCESS_SOURCE;
  389. // since the app permissions are now a set of radio buttons, use a case to discern
  390. switch (m_int_AppPerms)
  391. {
  392. case APPPERM_NONE:
  393. dword &= ~MD_ACCESS_SCRIPT;
  394. dword &= ~MD_ACCESS_EXECUTE;
  395. break;
  396. case APPPERM_SCRIPTS:
  397. dword |= MD_ACCESS_SCRIPT;
  398. dword &= ~MD_ACCESS_EXECUTE;
  399. break;
  400. case APPPERM_EXECUTE:
  401. dword |= MD_ACCESS_SCRIPT;
  402. dword |= MD_ACCESS_EXECUTE;
  403. break;
  404. };
  405. //write the dword back into the metabase
  406. f = mb.SetDword (_T (""), MD_ACCESS_PERM, IIS_MD_UT_FILE, dword);
  407. //------------------
  408. //the dir browsing flag is stored in a different field - so do it again
  409. dword = 0;
  410. mb.GetDword (_T (""), MD_DIRECTORY_BROWSING, IIS_MD_UT_FILE, &dword, METADATA_INHERIT);
  411. //script permissions
  412. if (m_bool_dirbrowse)
  413. dword |= MD_DIRBROW_ENABLED;
  414. else
  415. dword &= ~MD_DIRBROW_ENABLED;
  416. // write the dword back into the metabase
  417. f = mb.SetDword (_T (""), MD_DIRECTORY_BROWSING, IIS_MD_UT_FILE, dword);
  418. //finish up
  419. mb.Close ();
  420. }
  421. //make sure the string goes back
  422. UpdateData (FALSE);
  423. // do the default...
  424. EndDialog (IDOK);
  425. //cleanup the strings
  426. cleanup:
  427. SetCursor (LoadCursor (NULL, IDC_ARROW));
  428. }
  429. //----------------------------------------------------------------
  430. void CEditDirectory::EnableSourceControl ()
  431. {
  432. //get the currect button values
  433. UpdateData (TRUE);
  434. //if both read and write are unchecked, then we clear and disable source control
  435. if (!m_bool_read && !m_bool_write)
  436. {
  437. //save the value of source control
  438. m_bool_oldSource = m_bool_source;
  439. //clear the source control
  440. m_bool_source = FALSE;
  441. UpdateData (FALSE);
  442. //disable the source control window
  443. EnableWindow (m_hChkSource, FALSE);
  444. }
  445. else
  446. {
  447. //we enable source control
  448. // disable the source control window
  449. EnableWindow (m_hChkSource, TRUE);
  450. //and set the value back
  451. m_bool_source = m_bool_oldSource;
  452. UpdateData (FALSE);
  453. }
  454. }
  455. //----------------------------------------------------------------
  456. void CEditDirectory::OnRead (HWND hDlg)
  457. {
  458. EnableSourceControl ();
  459. }
  460. //----------------------------------------------------------------
  461. void CEditDirectory::OnWrite (HWND hDlg)
  462. {
  463. EnableSourceControl ();
  464. }
  465. //----------------------------------------------------------------
  466. void CEditDirectory::OnSource (HWND hDlg)
  467. {
  468. UpdateData (TRUE);
  469. m_bool_oldSource = m_bool_source;
  470. }
  471. //----------------------------------------------------------------
  472. //return an index to the position of first ch in pszSearch in the string
  473. // or return -1 if none are there
  474. int CEditDirectory::FindOneOf (LPTSTR psz, LPCTSTR pszSearch)
  475. {
  476. PTCHAR p = _tcspbrk (psz, pszSearch);
  477. if (!p)
  478. return -1;
  479. return (int) (p - psz);
  480. }
  481. //----------------------------------------------------------------
  482. //return an index to the position of ch in the string
  483. // or return -1 if it is not there
  484. int CEditDirectory::FindLastChr (LPTSTR psz, TCHAR ch)
  485. {
  486. PTCHAR p = _tcsrchr (psz, ch);
  487. if (!p)
  488. return -1;
  489. return (int) (p - psz);
  490. }
  491. //----------------------------------------------------------------
  492. //trim leading whitespace
  493. void CEditDirectory::TrimLeft (LPTSTR psz)
  494. {
  495. TCHAR buf[8];
  496. ZeroMemory (&buf, sizeof (buf));
  497. //copy over the first character
  498. _tcsncpy (buf, psz, 1);
  499. //and compare
  500. while (_tcscmp (buf, _T (" ")) == 0)
  501. {
  502. _tcscpy (psz, _tcsinc (psz));
  503. _tcsncpy (buf, psz, 1);
  504. }
  505. }
  506. //----------------------------------------------------------------
  507. //trim trailing whitespace
  508. void CEditDirectory::TrimRight (LPTSTR psz)
  509. {
  510. TCHAR buf[8];
  511. DWORD len;
  512. ZeroMemory (&buf, sizeof (buf));
  513. //copy over the last character
  514. len = _tcslen (psz);
  515. _tcsncpy (buf, _tcsninc (psz, len - 1), 1);
  516. //and compare
  517. while (_tcscmp (buf, _T (" ")) == 0)
  518. {
  519. //truncate the string
  520. *(_tcsninc (psz, len - 1)) = 0;
  521. //start over
  522. len = _tcslen (psz);
  523. _tcsncpy (buf, _tcsninc (psz, len - 1), 1);
  524. }
  525. }
  526. #if 0
  527. //----------------------------------------------------------------
  528. //trim trailing whitespace
  529. void CEditDirectory::TrimRight (LPTSTR psz)
  530. {
  531. TCHAR buf[8];
  532. DWORD len;
  533. ZeroMemory (&buf, sizeof (buf));
  534. //copy over the last character
  535. len = _tcslen (psz);
  536. _tcsncpy (buf, _tcsninc (psz, len - 1), 1);
  537. //and compare
  538. while (_tcscmp (buf, _T (" ")) == 0)
  539. {
  540. //truncate the string
  541. *(_tcsninc (psz, len - 1)) = 0;
  542. //start over
  543. len = _tcslen (psz);
  544. _tcsncpy (buf, _tcsninc (psz, len - 1), 1);
  545. }
  546. }
  547. #endif