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.

485 lines
15 KiB

  1. // AppMapPg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include <iadmw.h>
  5. #include "cnfgprts.h"
  6. #include "ListRow.h"
  7. #include "AppMapPg.h"
  8. #include "AppEdMpD.h"
  9. #include "wrapmb.h"
  10. #include "metatool.h"
  11. #include <iiscnfg.h>
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. enum {
  18. COL_EXTENSION = 0,
  19. COL_PATH,
  20. COL_EXCLUSIONS
  21. };
  22. #define SZ_ROOT _T("/lm/w3svc")
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CAppMapPage property page
  25. IMPLEMENT_DYNCREATE(CAppMapPage, CPropertyPage)
  26. //----------------------------------------------------------------
  27. CAppMapPage::CAppMapPage() : CPropertyPage(CAppMapPage::IDD),
  28. m_fInitialized( FALSE ),
  29. m_fLocalMachine( FALSE )
  30. {
  31. //{{AFX_DATA_INIT(CAppMapPage)
  32. m_bool_cache_isapi = FALSE;
  33. //}}AFX_DATA_INIT
  34. }
  35. //----------------------------------------------------------------
  36. CAppMapPage::~CAppMapPage()
  37. {
  38. }
  39. //----------------------------------------------------------------
  40. void CAppMapPage::DoDataExchange(CDataExchange* pDX)
  41. {
  42. CPropertyPage::DoDataExchange(pDX);
  43. //{{AFX_DATA_MAP(CAppMapPage)
  44. DDX_Control(pDX, IDC_CHK_CACHE_ISAPI, m_btn_cache_isapi);
  45. DDX_Check(pDX, IDC_CHK_CACHE_ISAPI, m_bool_cache_isapi);
  46. DDX_Control(pDX, IDC_REMOVE, m_btn_remove);
  47. DDX_Control(pDX, IDC_EDIT, m_btn_edit);
  48. DDX_Control(pDX, IDC_LIST, m_clist_list);
  49. //}}AFX_DATA_MAP
  50. }
  51. //----------------------------------------------------------------
  52. BEGIN_MESSAGE_MAP(CAppMapPage, CPropertyPage)
  53. //{{AFX_MSG_MAP(CAppMapPage)
  54. ON_BN_CLICKED(IDC_CHK_CACHE_ISAPI, OnChkCacheIsapi)
  55. ON_BN_CLICKED(IDC_ADD, OnAdd)
  56. ON_BN_CLICKED(IDC_EDIT, OnEdit)
  57. ON_BN_CLICKED(IDC_REMOVE, OnRemove)
  58. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, OnItemchangedList)
  59. ON_NOTIFY(NM_DBLCLK, IDC_LIST, OnDblclkList)
  60. //}}AFX_MSG_MAP
  61. ON_COMMAND(ID_HELP_FINDER, DoHelp)
  62. ON_COMMAND(ID_HELP, DoHelp)
  63. ON_COMMAND(ID_CONTEXT_HELP, DoHelp)
  64. ON_COMMAND(ID_DEFAULT_HELP, DoHelp)
  65. END_MESSAGE_MAP()
  66. //---------------------------------------------------------------------------
  67. void CAppMapPage::DoHelp()
  68. {
  69. WinHelp( HIDD_APPMAPS_MAPS );
  70. }
  71. //----------------------------------------------------------------
  72. void CAppMapPage::Init()
  73. {
  74. CString sz;
  75. DWORD dw = 0;
  76. WCHAR* pData = NULL;
  77. CString szMap;
  78. CString szSection;
  79. int i = 0;
  80. UpdateData( TRUE );
  81. //
  82. // RONALDM: The word "ALL" is displayed for empty verb lists,
  83. // though it should not be written to the metabase.
  84. //
  85. VERIFY(m_szAll.LoadString(IDS_VERBS_ALL));
  86. // prepare the list for use
  87. sz.LoadString( IDS_APP_EXTENSION );
  88. i = m_clist_list.InsertColumn( COL_EXTENSION, sz, LVCFMT_LEFT, 58 );
  89. sz.LoadString( IDS_APP_EXE_PATH );
  90. i = m_clist_list.InsertColumn( COL_PATH, sz, LVCFMT_LEFT, 204 );
  91. sz.LoadString( IDS_APP_EXCLUSIONS );
  92. i = m_clist_list.InsertColumn( COL_EXCLUSIONS, sz, LVCFMT_LEFT, 72 );
  93. // we will just be pulling stuff out of the metabase here
  94. // prepare the metabase wrapper
  95. CWrapMetaBase mbWrap;
  96. if ( !mbWrap.FInit(m_pMB) ) return;
  97. // arg arg arg. For things like directories, the metapath may not exist
  98. // seperate the partial path from the base - the root is always SZ_ROOT
  99. sz = SZ_ROOT;
  100. m_szPartial = m_szMeta.Right(m_szMeta.GetLength() - sz.GetLength() );
  101. // open the target
  102. if ( mbWrap.Open( SZ_ROOT, METADATA_PERMISSION_READ ) )
  103. {
  104. // read the session timeout information
  105. if ( mbWrap.GetDword( m_szPartial, MD_CACHE_EXTENSIONS, IIS_MD_UT_FILE, &dw, METADATA_INHERIT | METADATA_PARTIAL_PATH ) )
  106. m_bool_cache_isapi = (BOOL)dw;
  107. else
  108. m_bool_cache_isapi = FALSE; // default
  109. // get the big script map string
  110. dw = 0;
  111. pData = (WCHAR*)mbWrap.GetData( m_szPartial, MD_SCRIPT_MAPS, IIS_MD_UT_FILE, MULTISZ_METADATA, &dw, METADATA_INHERIT | METADATA_PARTIAL_PATH );
  112. // close the metabase
  113. mbWrap.Close();
  114. }
  115. // set the data into place
  116. UpdateData( FALSE );
  117. // if we got the mappings string, parse it now - no need to keep the metabase open
  118. if ( pData )
  119. {
  120. WCHAR* pstr = (WCHAR*)pData;
  121. // loop through the sub-strings in the multi-sz
  122. i = -1;
  123. while( pstr[0] )
  124. {
  125. // get the sub-string
  126. szMap = pstr;
  127. // Get the sub-sections of the sub-string
  128. szSection = szMap.Left( szMap.Find(',') );
  129. szMap = szMap.Right( szMap.GetLength() - szSection.GetLength() - 1 );
  130. // add the extension to the list
  131. i = m_clist_list.InsertItem( i+1, szSection );
  132. // Get the sub-sections of the sub-string
  133. szSection = szMap.Left( szMap.Find(',') );
  134. szMap = szMap.Right( szMap.GetLength() - szSection.GetLength() - 1 );
  135. // add the path to the list
  136. m_clist_list.SetItemText( i, COL_PATH, szSection );
  137. // Get the sub-sections of the sub-string
  138. if ( szMap.Find(',') >= 0 )
  139. szSection = szMap.Left( szMap.Find(',') );
  140. else
  141. szSection = szMap;
  142. szMap = szMap.Right( szMap.GetLength() - szSection.GetLength() - 1 );
  143. // convert the flags string into a ddword
  144. swscanf( (PTCHAR)(LPCTSTR)szSection, _T("%d"), &dw );
  145. // save the dword on the list item
  146. m_clist_list.SetItemData( i, dw );
  147. // the remainder of the list is the list of ISAPI method exclusions
  148. // add the exclusions to the list
  149. //
  150. // RONALDM Change, Bug 178423: If no exclusions (and they're
  151. // now inclusions, rather than exclusions) are present, the word
  152. // "ALL" should be placed in the exclusions column.
  153. //
  154. m_clist_list.SetItemText(i, COL_EXCLUSIONS, (szMap.IsEmpty() ? m_szAll : szMap));
  155. // advance the pstr
  156. pstr += wcslen(pstr) + 1;
  157. }
  158. // now we can release the buffer
  159. mbWrap.FreeWrapData( pData );
  160. }
  161. // according to bug #152234 the cache ISAPI extensions should only be exposed on the
  162. // master properties or the virtual server level. So - we need to detect if we are on
  163. // this level and if we are NOT, then disable the control
  164. //
  165. // The easiest way to determin if we are deeper than the virtual server is to count
  166. // the slash characters. If there are more than 3, then we are at a virt dir or phys dir
  167. DWORD nLevels = 0;
  168. int iSlash;
  169. CString szPath = m_szMeta;
  170. while ( (iSlash = szPath.Find( _T('/') )) >= 0 )
  171. {
  172. nLevels++;
  173. szPath = szPath.Right( szPath.GetLength() - (iSlash + 1) );
  174. }
  175. // if the number of levels is greater than 3 then it is a virt dir. Disable the isapi cache option
  176. if ( nLevels > 3 )
  177. m_btn_cache_isapi.EnableWindow( FALSE );
  178. }
  179. //---------------------------------------------------------------------------
  180. void CAppMapPage::EnableItems()
  181. {
  182. UpdateData( TRUE );
  183. if ( m_clist_list.GetSelectedCount() == 1 )
  184. {
  185. m_btn_edit.EnableWindow( TRUE );
  186. m_btn_remove.EnableWindow( TRUE );
  187. }
  188. else
  189. {
  190. m_btn_edit.EnableWindow( FALSE );
  191. m_btn_remove.EnableWindow( FALSE );
  192. }
  193. }
  194. //----------------------------------------------------------------
  195. // blow away the parameters
  196. void CAppMapPage::BlowAwayParameters()
  197. {
  198. // prepare the metabase wrapper
  199. CWrapMetaBase mbWrap;
  200. if ( !mbWrap.FInit(m_pMB) ) return;
  201. // open the target
  202. if ( mbWrap.Open( m_szMeta, METADATA_PERMISSION_WRITE ) )
  203. {
  204. mbWrap.DeleteData( _T(""), MD_CACHE_EXTENSIONS, DWORD_METADATA );
  205. mbWrap.DeleteData( _T(""), MD_SCRIPT_MAPS, DWORD_METADATA );
  206. // mbWrap.DeleteData( _T(""), MD_CACHE_EXTENSIONS, IIS_MD_UT_FILE, DWORD_METADATA );
  207. // mbWrap.DeleteData( _T(""), MD_SCRIPT_MAPS, IIS_MD_UT_FILE, DWORD_METADATA );
  208. // close the metabase
  209. mbWrap.Close();
  210. }
  211. }
  212. /////////////////////////////////////////////////////////////////////////////
  213. // CAppMapPage message handlers
  214. //----------------------------------------------------------------
  215. BOOL CAppMapPage::OnApply()
  216. {
  217. LPTSTR lpszBuffer;
  218. DWORD dwSize;
  219. DWORD i;
  220. BOOL f;
  221. CString szExclude;
  222. CString szNewMap;
  223. CString szExtension;
  224. CString szPath;
  225. DWORD dw;
  226. UpdateData( TRUE );
  227. // build the multisz string. Use the * character as a seperator for now, then replace it with nulls
  228. CString szMappings;
  229. // build the string
  230. DWORD nItems = m_clist_list.GetItemCount();
  231. for ( i = 0; i < nItems; i++ )
  232. {
  233. // prep the optional ISAPI exclution string
  234. szExclude = m_clist_list.GetItemText(i, COL_EXCLUSIONS);
  235. //----------------------------------------------------------------------------------------
  236. //
  237. // RONALDM: The word "ALL" is a visual indicator that should be replaced
  238. // with an empty exclusion list.
  239. //
  240. szExclude.TrimLeft();
  241. szExclude.TrimRight();
  242. if (szExclude.CompareNoCase(m_szAll) == 0)
  243. {
  244. szExclude.Empty();
  245. }
  246. //----------------------------------------------------------------------------------------
  247. if ( !szExclude.IsEmpty() )
  248. szExclude = _T(',') + szExclude;
  249. szNewMap;
  250. szExtension = m_clist_list.GetItemText(i, COL_EXTENSION);
  251. szPath = m_clist_list.GetItemText(i, COL_PATH);
  252. // IA64 - OK to cast to DWORD as it is a small numerical flag
  253. dw = (DWORD)m_clist_list.GetItemData(i);
  254. szNewMap.Format( _T("%s,%s,%d%s\n"), szExtension, szPath, dw, szExclude );
  255. szMappings += szNewMap;
  256. }
  257. // put on the last delimiter
  258. szMappings += _T('\n');
  259. // record the length
  260. dwSize = szMappings.GetLength();
  261. // transform it into a multisz
  262. lpszBuffer = szMappings.GetBuffer(MAX_PATH+1);
  263. while( lpszBuffer[i] )
  264. {
  265. if ( lpszBuffer[i] == _T('\n') )
  266. lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
  267. i++;
  268. }
  269. // prepare the metabase wrapper
  270. CWrapMetaBase mbWrap;
  271. if ( !mbWrap.FInit(m_pMB) ) return FALSE;
  272. // script file size
  273. f = SetMetaDword(m_pMB, m_szServer, m_szMeta, _T(""), MD_CACHE_EXTENSIONS, IIS_MD_UT_FILE,
  274. m_bool_cache_isapi, TRUE);
  275. // script mappings
  276. f = SetMetaMultiSz(m_pMB, m_szServer, m_szMeta, _T(""), MD_SCRIPT_MAPS, IIS_MD_UT_FILE,
  277. lpszBuffer, dwSize, TRUE );
  278. // close the metabase
  279. mbWrap.Close();
  280. // clean up
  281. szMappings.ReleaseBuffer(-1);
  282. SetModified( FALSE );
  283. return CPropertyPage::OnApply();
  284. }
  285. //----------------------------------------------------------------
  286. BOOL CAppMapPage::OnSetActive()
  287. {
  288. if ( !m_fInitialized )
  289. {
  290. Init();
  291. m_fInitialized = TRUE;
  292. }
  293. return CPropertyPage::OnSetActive();
  294. }
  295. //----------------------------------------------------------------
  296. void CAppMapPage::OnChkCacheIsapi()
  297. {
  298. SetModified();
  299. }
  300. //----------------------------------------------------------------
  301. void CAppMapPage::OnAdd()
  302. {
  303. // set up a default edit box
  304. CAppEditMapDlg dlg;
  305. dlg.m_pList = &m_clist_list;
  306. dlg.m_fNewMapping = TRUE;
  307. dlg.m_fLocalMachine = m_fLocalMachine;
  308. dlg.m_dwFlags = MD_SCRIPTMAPFLAG_SCRIPT;
  309. // ask the user to edit the mapping
  310. if ( dlg.DoModal() == IDOK )
  311. {
  312. // we want to add the extension to the end of the list. So get the number that
  313. // are already there.
  314. DWORD numExtensions = m_clist_list.GetItemCount();
  315. // add the extension to the list
  316. DWORD i = m_clist_list.InsertItem( numExtensions, dlg.m_sz_extension );
  317. // add the path to the list
  318. m_clist_list.SetItemText( i, COL_PATH, dlg.m_sz_executable );
  319. // save the dword on the list item
  320. m_clist_list.SetItemData( i, dlg.m_dwFlags );
  321. // set the exclusion list
  322. m_clist_list.SetItemText(
  323. i,
  324. COL_EXCLUSIONS,
  325. (dlg.m_sz_exclusions.IsEmpty() ? m_szAll : dlg.m_sz_exclusions)
  326. );
  327. SetModified();
  328. }
  329. }
  330. //----------------------------------------------------------------
  331. void CAppMapPage::OnEdit()
  332. {
  333. // make sure something is selcted
  334. if ( m_clist_list.GetSelectedCount() != 1 )
  335. return;
  336. // get the index of the selected item
  337. int iSel = m_clist_list.GetNextItem( -1, LVNI_SELECTED );
  338. // set up a default edit box
  339. CAppEditMapDlg dlg;
  340. dlg.m_fLocalMachine = m_fLocalMachine;
  341. dlg.m_fNewMapping = FALSE;
  342. dlg.m_pList = &m_clist_list;
  343. // IA64 - OK to cast as this is a numerical flag 1,2,3,4 etc...
  344. dlg.m_dwFlags = (DWORD)m_clist_list.GetItemData( iSel );
  345. dlg.m_sz_extension = m_clist_list.GetItemText( iSel, COL_EXTENSION );
  346. dlg.m_sz_executable = m_clist_list.GetItemText( iSel, COL_PATH );
  347. dlg.m_sz_exclusions = m_clist_list.GetItemText( iSel, COL_EXCLUSIONS );
  348. //
  349. // RONALDM: Handle "(all)" exclusions cleanly
  350. //
  351. if (dlg.m_sz_exclusions.CompareNoCase(m_szAll) == 0)
  352. {
  353. dlg.m_sz_exclusions.Empty();
  354. }
  355. // run the edit box
  356. if ( dlg.DoModal() == IDOK )
  357. {
  358. // set the path to the list
  359. m_clist_list.SetItemText( iSel, COL_EXTENSION, dlg.m_sz_extension );
  360. // set the path to the list
  361. m_clist_list.SetItemText( iSel, COL_PATH, dlg.m_sz_executable );
  362. // set the dword on the list item
  363. m_clist_list.SetItemData( iSel, dlg.m_dwFlags );
  364. //
  365. // set the exclusion list
  366. //
  367. // RONALDM: blank == "(all)"
  368. //
  369. m_clist_list.SetItemText(
  370. iSel,
  371. COL_EXCLUSIONS,
  372. (dlg.m_sz_exclusions.IsEmpty() ? m_szAll : dlg.m_sz_exclusions)
  373. );
  374. SetModified();
  375. }
  376. }
  377. //----------------------------------------------------------------
  378. void CAppMapPage::OnRemove()
  379. {
  380. // make sure something is selcted
  381. if ( m_clist_list.GetSelectedCount() != 1 )
  382. return;
  383. // ask the user if that is what they really want to do
  384. if ( AfxMessageBox(IDS_APP_MAP_REMOVE_CONFIRM, MB_YESNO) != IDYES )
  385. return;
  386. // get the index of the selected item
  387. int iSel = m_clist_list.GetNextItem( -1, LVNI_SELECTED );
  388. // delete the item
  389. m_clist_list.DeleteItem( iSel );
  390. SetModified();
  391. }
  392. //----------------------------------------------------------------
  393. void CAppMapPage::OnItemchangedList(NMHDR* pNMHDR, LRESULT* pResult)
  394. {
  395. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  396. EnableItems();
  397. *pResult = 0;
  398. }
  399. //----------------------------------------------------------------
  400. void CAppMapPage::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
  401. {
  402. OnEdit();
  403. *pResult = 0;
  404. }