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.

515 lines
14 KiB

  1. // EdtBindD.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "resource.h"
  5. #include "iiscnfg.h"
  6. #include "KeyObjs.h"
  7. #include "wrapmb.h"
  8. #include "cmnkey.h"
  9. #include "mdkey.h"
  10. #include "mdserv.h"
  11. #include "ListRow.h"
  12. #include "BindsDlg.h"
  13. #include "EdtBindD.h"
  14. #include "W3Key.h"
  15. #include "ipdlg.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CEditBindingDlg dialog
  23. //--------------------------------------------------------
  24. CEditBindingDlg::CEditBindingDlg(WCHAR* pszw, CWnd* pParent /*=NULL*/)
  25. : CDialog(CEditBindingDlg::IDD, pParent),
  26. m_fPopulatedPortDropdown( FALSE ),
  27. m_pszwMachineName( pszw )
  28. {
  29. //{{AFX_DATA_INIT(CEditBindingDlg)
  30. m_int_ip_option = -1;
  31. m_int_port_option = -1;
  32. m_cstring_port = _T("");
  33. //}}AFX_DATA_INIT
  34. }
  35. //--------------------------------------------------------
  36. void CEditBindingDlg::DoDataExchange(CDataExchange* pDX)
  37. {
  38. CDialog::DoDataExchange(pDX);
  39. //{{AFX_DATA_MAP(CEditBindingDlg)
  40. DDX_Control(pDX, IDC_PORT_DROP, m_ccombobox_port);
  41. DDX_Radio(pDX, IDC_ANY_IP, m_int_ip_option);
  42. DDX_Radio(pDX, IDC_ANY_PORT, m_int_port_option);
  43. DDX_CBString(pDX, IDC_PORT_DROP, m_cstring_port);
  44. //}}AFX_DATA_MAP
  45. }
  46. //--------------------------------------------------------
  47. BEGIN_MESSAGE_MAP(CEditBindingDlg, CDialog)
  48. //{{AFX_MSG_MAP(CEditBindingDlg)
  49. ON_BN_CLICKED(IDC_RD_IP, OnRdIp)
  50. ON_BN_CLICKED(IDC_RD_PORT, OnRdPort)
  51. ON_BN_CLICKED(IDC_ANY_IP, OnAnyIp)
  52. ON_BN_CLICKED(IDC_ANY_PORT, OnAnyPort)
  53. ON_CBN_DROPDOWN(IDC_PORT_DROP, OnDropdownPortDrop)
  54. ON_BN_CLICKED(IDC_BTN_SELECT_IPADDRESS, OnBtnSelectIpaddress)
  55. //}}AFX_MSG_MAP
  56. END_MESSAGE_MAP()
  57. //--------------------------------------------------------
  58. BOOL CEditBindingDlg::OnInitDialog()
  59. {
  60. CString szIP;
  61. CString szPort;
  62. int iColon;
  63. // call the parental oninitdialog
  64. BOOL f = CDialog::OnInitDialog();
  65. // the initial values of the dialog as appropriate
  66. // for the string that was passed. The easiest case
  67. // is that of the default string - so do that first.
  68. // check for the default
  69. if ( m_szBinding == MDNAME_DEFAULT )
  70. {
  71. m_int_ip_option = OPTION_ANY_UNASSIGNED;
  72. m_int_port_option = OPTION_ANY_UNASSIGNED;
  73. m_cstring_port.Empty();
  74. ClearIPAddress();
  75. }
  76. else
  77. {
  78. // the first thing we are going to do is seperate the IP and PORT into seperate strings
  79. // look for the : and seperate
  80. iColon = m_szBinding.Find(':');
  81. // if we got the colon, we can seperate easy
  82. if ( iColon >= 0 )
  83. {
  84. szIP = m_szBinding.Left(iColon);
  85. szPort = m_szBinding.Right(m_szBinding.GetLength() - iColon - 1);
  86. }
  87. // we did not get the colon, so it is one or the other, look for a '.' to get the IP
  88. else
  89. {
  90. if ( m_szBinding.Find('.') >= 0 )
  91. szIP = m_szBinding;
  92. else
  93. szPort = m_szBinding;
  94. }
  95. // put the strings into the appropriate places
  96. if ( szIP.IsEmpty() )
  97. {
  98. ClearIPAddress();
  99. m_int_ip_option = OPTION_ANY_UNASSIGNED;
  100. }
  101. else
  102. {
  103. FSetIPAddress( szIP );
  104. m_int_ip_option = OPTION_SPECIFIED;
  105. }
  106. // setting the port string is a bit easier
  107. m_cstring_port = szPort;
  108. if ( szPort.IsEmpty() )
  109. m_int_port_option = OPTION_ANY_UNASSIGNED;
  110. else
  111. m_int_port_option = OPTION_SPECIFIED;
  112. }
  113. // update the data in the dialog
  114. UpdateData( FALSE );
  115. // enable the items as appropriate
  116. EnableItems();
  117. // return the answer
  118. return f;
  119. }
  120. //--------------------------------------------------------
  121. // enable the itesm as appropriate
  122. void CEditBindingDlg::EnableItems()
  123. {
  124. // get the data so we are up-to-date
  125. UpdateData( TRUE );
  126. // handle the ip addressing items
  127. if ( m_int_ip_option == OPTION_ANY_UNASSIGNED )
  128. {
  129. GetDlgItem(IDC_IPA_IPADDRESS)->EnableWindow(FALSE);
  130. // m_cbutton_delete.EnableWindow( FALSE );
  131. }
  132. else
  133. {
  134. GetDlgItem(IDC_IPA_IPADDRESS)->EnableWindow(TRUE);
  135. // m_cbutton_delete.EnableWindow( TRUE );
  136. }
  137. // handle the port addressing items
  138. if ( m_int_port_option == OPTION_ANY_UNASSIGNED )
  139. {
  140. m_ccombobox_port.EnableWindow( FALSE );
  141. }
  142. else
  143. {
  144. m_ccombobox_port.EnableWindow( TRUE );
  145. }
  146. }
  147. //------------------------------------------------------------------------------
  148. // Set and get the ip STRING from the ip edit control
  149. BOOL CEditBindingDlg::FSetIPAddress( CString& szAddress )
  150. {
  151. DWORD dword, b1, b2, b3, b4;
  152. // break the string into 4 numerical bytes (reading left to right)
  153. dword = sscanf( szAddress, "%d.%d.%d.%d", &b1, &b2, &b3, &b4 );
  154. // if we didn't get all four, fail
  155. if ( dword != 4 )
  156. return FALSE;
  157. // make the numerical ip address out of the bytes
  158. dword = (DWORD)MAKEIPADDRESS(b1,b2,b3,b4);
  159. // set the ip address into the control
  160. SendDlgItemMessage( IDC_IPA_IPADDRESS, IPM_SETADDRESS, 0, dword );
  161. #ifdef _DEBUG
  162. dword = 0;
  163. // dword = SendDlgItemMessage( IDC_IPA_IPADDRESS, IPM_GETADDRESS, 0, 0 );
  164. #endif
  165. // return success
  166. return TRUE;
  167. }
  168. //------------------------------------------------------------------------------
  169. CString CEditBindingDlg::GetIPAddress()
  170. {
  171. CString szAnswer;
  172. DWORD dword, b1, b2, b3, b4;
  173. // get the ip address from the control
  174. SendDlgItemMessage( IDC_IPA_IPADDRESS, IPM_GETADDRESS, 0, (LPARAM)&dword );
  175. // get the constituent parts
  176. b1 = FIRST_IPADDRESS( dword );
  177. b2 = SECOND_IPADDRESS( dword );
  178. b3 = THIRD_IPADDRESS( dword );
  179. b4 = FOURTH_IPADDRESS( dword );
  180. // format the string
  181. if ( dword )
  182. szAnswer.Format( "%d.%d.%d.%d", b1, b2, b3, b4 );
  183. else
  184. szAnswer.Empty();
  185. return szAnswer;
  186. }
  187. //------------------------------------------------------------------------------
  188. // Set and get the ip STRING from the ip edit control
  189. void CEditBindingDlg::ClearIPAddress()
  190. {
  191. // clear the ip address control
  192. SendDlgItemMessage( IDC_IPA_IPADDRESS, IPM_CLEARADDRESS, 0, 0 );
  193. }
  194. //------------------------------------------------------------------------------
  195. BOOL CEditBindingDlg::FIsBindingSafeToUse( CString szBinding )
  196. {
  197. // start by testing the binding in the current dialog - uses
  198. // the localized version of "Default"
  199. if ( m_pBindingsDlg->FContainsBinding(szBinding) )
  200. {
  201. AfxMessageBox( IDS_THIS_KEY_HAS_BINDING, MB_OK );
  202. return FALSE;
  203. }
  204. // now we check to see if any other keys have the specified binding. If
  205. // they do, we ask the user if they want to give the binding to this key.
  206. // but first we have to find the key. This means scanning the list of
  207. // keys and asking each - but not this key - if they have the binding.
  208. CMDKey* pKeyLocal = m_pBindingsDlg->m_pKey;
  209. CMDKey* pKey;
  210. if ( !pKeyLocal->m_pService )
  211. return FALSE;
  212. // get the first key in the service list
  213. pKey = pKeyLocal->m_pService->GetFirstMDKey();
  214. // loop the keys, testing each in turn
  215. while ( pKey )
  216. {
  217. // if this is not the local key, test it
  218. if ( pKey != pKeyLocal )
  219. {
  220. // test it
  221. if ( pKey->FContainsBinding( szBinding ) )
  222. {
  223. // prepare the message for the user
  224. CString szMessage;
  225. AfxFormatString1( szMessage, IDS_ANOTHER_KEY_HAS_BINDING, pKey->m_szName );
  226. // ask the user what to do
  227. if ( AfxMessageBox( szMessage, MB_YESNO ) == IDYES )
  228. {
  229. // create a new removal object
  230. CBingingRemoval* pRemoval = new CBingingRemoval( pKey, szBinding );
  231. // add it to the queue
  232. m_pBindingsDlg->rgbRemovals.Add( pRemoval );
  233. // the key is safe use
  234. return TRUE;
  235. }
  236. else
  237. {
  238. // the user has thought better of this
  239. return FALSE;
  240. }
  241. }
  242. }
  243. // get the next key in the list
  244. pKey = pKeyLocal->m_pService->GetNextMDKey( pKey );
  245. }
  246. // no one else is using the binding. It is safe.
  247. return TRUE;
  248. }
  249. /////////////////////////////////////////////////////////////////////////////
  250. // CEditBindingDlg message handlers
  251. //------------------------------------------------------------------------------
  252. void CEditBindingDlg::OnOK()
  253. {
  254. CString szIP;
  255. CString szPort;
  256. // start by building the final binding string
  257. CString szBinding;
  258. // use the current data
  259. UpdateData( TRUE );
  260. // first things first. We need to make sure that, if used, the
  261. // custom fields actually have something in them
  262. // check the IP address first
  263. if ( m_int_ip_option == OPTION_SPECIFIED )
  264. {
  265. szIP = GetIPAddress();
  266. if ( szIP.IsEmpty() )
  267. {
  268. // tell the user about it
  269. AfxMessageBox( IDS_INVALID_IP );
  270. // hilight the IP box
  271. GetDlgItem( IDC_IPA_IPADDRESS )->SetFocus();
  272. // return without closing the dialog
  273. return;
  274. }
  275. }
  276. // check the port address second
  277. if ( m_int_port_option == OPTION_SPECIFIED )
  278. {
  279. if ( m_cstring_port.IsEmpty() )
  280. {
  281. // tell the user about it
  282. AfxMessageBox( IDS_INVALID_PORT );
  283. // hilight the port box
  284. m_ccombobox_port.SetFocus();
  285. m_ccombobox_port.SetEditSel(0,-1);
  286. // return without closing the dialog
  287. return;
  288. }
  289. }
  290. // the total default case is the easiest
  291. if ( m_int_ip_option == OPTION_ANY_UNASSIGNED &&
  292. m_int_port_option == OPTION_ANY_UNASSIGNED )
  293. {
  294. szBinding = MDNAME_DEFAULT;
  295. }
  296. else
  297. {
  298. // build from the ip and port pieces
  299. if ( m_int_ip_option == OPTION_SPECIFIED )
  300. szIP = GetIPAddress();
  301. if ( m_int_port_option == OPTION_SPECIFIED )
  302. szPort = m_cstring_port;
  303. // build the string start with the IP
  304. szBinding = szIP;
  305. // if both are there, add a colon
  306. if ( m_int_ip_option == OPTION_SPECIFIED &&
  307. m_int_port_option == OPTION_SPECIFIED )
  308. szBinding += ':';
  309. // finish with the port
  310. szBinding += szPort;
  311. }
  312. // finally, if the binding is safe to use, we can set the data and
  313. // close the dialog
  314. if ( FIsBindingSafeToUse(szBinding) )
  315. {
  316. // set the data
  317. m_szBinding = szBinding;
  318. // tell the dialog to close
  319. CDialog::OnOK();
  320. }
  321. }
  322. //------------------------------------------------------------------------------
  323. void CEditBindingDlg::OnRdIp()
  324. {
  325. EnableItems();
  326. }
  327. //------------------------------------------------------------------------------
  328. void CEditBindingDlg::OnRdPort()
  329. {
  330. EnableItems();
  331. }
  332. //------------------------------------------------------------------------------
  333. void CEditBindingDlg::OnAnyIp()
  334. {
  335. EnableItems();
  336. }
  337. //------------------------------------------------------------------------------
  338. void CEditBindingDlg::OnAnyPort()
  339. {
  340. EnableItems();
  341. }
  342. //------------------------------------------------------------------------------
  343. void CEditBindingDlg::OnDropdownPortDrop()
  344. {
  345. CString sz;
  346. DWORD dwPort;
  347. // if we have already been here, don't do anything
  348. if ( m_fPopulatedPortDropdown )
  349. return;
  350. // get the metabase going
  351. if ( !FInitMetabaseWrapper(m_pszwMachineName) )
  352. return;
  353. // create the metabase wrapper object
  354. CWrapMetaBase mbWrap;
  355. if ( !mbWrap.FInit() )
  356. {
  357. ASSERT( FALSE );
  358. return; // can't get to metabase
  359. }
  360. // we are now to populate the drop down menu
  361. m_fPopulatedPortDropdown = TRUE;
  362. // scan the available virtual servers and populate the drop down with
  363. // their secure port numbers
  364. for ( DWORD i = 1; TRUE; i++ )
  365. {
  366. // build the object name
  367. sz.Format( "%s%d", MD_W3BASE, i );
  368. // attempt to open the object in the metabase
  369. if ( !mbWrap.Open( sz, METADATA_PERMISSION_READ ) )
  370. break; // can't open - leave the loop
  371. // load the string representing the bindings
  372. DWORD cbData;
  373. PVOID pData;
  374. // extract the secure port address from the secure bindings stringlist
  375. pData = mbWrap.GetData( "", MD_SECURE_BINDINGS, IIS_MD_UT_SERVER, MULTISZ_METADATA, &cbData );
  376. if ( pData )
  377. {
  378. PTCHAR pBinding = (PTCHAR)pData;
  379. // walk the bindings in the list
  380. while ( TRUE )
  381. {
  382. sz = (PCHAR)pBinding;
  383. if ( sz.IsEmpty() )
  384. break;
  385. // get the port address
  386. sz = sz.Right( sz.GetLength() - sz.Find(':') - 1 );
  387. if ( sz.Find(':') )
  388. sz = sz.Left( sz.Find(':') );
  389. if ( !sz.IsEmpty() )
  390. {
  391. // append the string to the dropdown
  392. // but only if it isn't already there
  393. if ( m_ccombobox_port.FindStringExact(-1,sz) == CB_ERR )
  394. m_ccombobox_port.AddString( sz );
  395. }
  396. // advance the binding pointer
  397. pBinding += strlen(pBinding)+1;
  398. }
  399. // free the buffer
  400. mbWrap.FreeWrapData( pData );
  401. }
  402. // close the object
  403. mbWrap.Close();
  404. }
  405. // now close the metabase again. We will open it when we need it
  406. FCloseMetabaseWrapper();
  407. }
  408. //------------------------------------------------------------------------------
  409. void CEditBindingDlg::OnBtnSelectIpaddress()
  410. {
  411. // get the metabase going
  412. if ( !FInitMetabaseWrapper(m_pszwMachineName) )
  413. return;
  414. // run the choose ip dialog here
  415. CChooseIPDlg dlg;
  416. // set up the ip dialog member variables
  417. dlg.m_szIPAddress = GetIPAddress();
  418. // run the dialog
  419. if ( dlg.DoModal() == IDOK )
  420. {
  421. FSetIPAddress( dlg.m_szIPAddress );
  422. }
  423. // now close the metabase again. We will open it when we need it
  424. FCloseMetabaseWrapper();
  425. }