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.

456 lines
13 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. genpage.cpp
  5. Abstract:
  6. This module implements CGeneralPage -- the snapin startup wizard page
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "devmgr.h"
  12. #include "genpage.h"
  13. UINT g_cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  14. const DWORD g_a102HelpIDs[]=
  15. {
  16. IDC_GENERAL_SELECT_TEXT, IDH_DISABLEHELP,
  17. IDC_GENERAL_SELECTGROUP, IDH_DISABLEHELP,
  18. IDC_GENERAL_OVERRIDE_MACHINENAME, idh_devmgr_manage_command_line, // Device Manager: "Allo&w the selected computer to be changed when launching from the command line. This only applies if you save the console." (Button)
  19. IDC_GENERAL_LOCALMACHINE, idh_devmgr_manage_local, // Device Manager: "&Local computer: (the computer this console is running on)" (Button)
  20. IDC_GENERAL_OTHERMACHINE, idh_devmgr_manage_remote, // Device Manager: "&Another computer:" (Button)
  21. IDC_GENERAL_MACHINENAME, idh_devmgr_manage_remote_name, // Device Manager: "" (Edit)
  22. IDC_GENERAL_BROWSE_MACHINENAMES, idh_devmgr_manage_remote_browse, // Device Manager: "B&rowse..." (Button)
  23. 0, 0
  24. };
  25. CGeneralPage::CGeneralPage() : CPropSheetPage(g_hInstance, IDD_GENERAL_PAGE)
  26. {
  27. m_lConsoleHandle = 0;
  28. m_pstrMachineName = NULL;
  29. m_pct = NULL;
  30. m_MachineName[0] = _T('\0');
  31. m_IsLocalMachine = TRUE;
  32. m_ct = COOKIE_TYPE_SCOPEITEM_DEVMGR;
  33. }
  34. HPROPSHEETPAGE
  35. CGeneralPage::Create(
  36. LONG_PTR lConsoleHandle
  37. )
  38. {
  39. m_lConsoleHandle = lConsoleHandle;
  40. // override PROPSHEETPAGE structure here...
  41. m_psp.lParam = (LPARAM)this;
  42. return CPropSheetPage::CreatePage();
  43. }
  44. BOOL
  45. CGeneralPage::OnInitDialog(
  46. LPPROPSHEETPAGE ppsp
  47. )
  48. {
  49. ASSERT(m_hDlg);
  50. // intiallly, enable the local machine and disable the
  51. // "other" machine.
  52. ::CheckDlgButton(m_hDlg, IDC_GENERAL_LOCALMACHINE, BST_CHECKED);
  53. ::CheckDlgButton(m_hDlg, IDC_GENERAL_OTHERMACHINE, BST_UNCHECKED);
  54. ::EnableWindow(GetControl(IDC_GENERAL_MACHINENAME), FALSE);
  55. // Default is local machine and view-all. Since everything
  56. // is valud at the beginning, we have to enable the
  57. // finish button.
  58. ::SendMessage(::GetParent(m_hDlg), PSM_SETWIZBUTTONS, 0, PSWIZB_FINISH);
  59. ::ShowWindow(GetControl(IDC_GENERAL_OVERRIDE_MACHINENAME), SW_HIDE);
  60. ::EnableWindow(GetControl(IDC_GENERAL_BROWSE_MACHINENAMES), FALSE);
  61. return TRUE;
  62. }
  63. BOOL
  64. CGeneralPage::OnReset(
  65. void
  66. )
  67. {
  68. m_MachineName[0] = _T('\0');
  69. m_ct = COOKIE_TYPE_SCOPEITEM_DEVMGR;
  70. SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, 0L);
  71. return FALSE;
  72. }
  73. BOOL
  74. CGeneralPage::OnCommand(
  75. WPARAM wParam,
  76. LPARAM lParam
  77. )
  78. {
  79. switch (LOWORD(wParam)) {
  80. case IDC_GENERAL_LOCALMACHINE:
  81. if (BN_CLICKED == HIWORD(wParam)) {
  82. ::EnableWindow(GetControl(IDC_GENERAL_BROWSE_MACHINENAMES), FALSE);
  83. ::EnableWindow(GetControl(IDC_GENERAL_MACHINENAME), FALSE);
  84. ::SendMessage(::GetParent(m_hDlg), PSM_SETWIZBUTTONS, 0, PSWIZB_FINISH);
  85. m_IsLocalMachine = TRUE;
  86. return TRUE;
  87. }
  88. break;
  89. case IDC_GENERAL_OTHERMACHINE:
  90. if (BN_CLICKED == HIWORD(wParam)) {
  91. ::EnableWindow(GetControl(IDC_GENERAL_BROWSE_MACHINENAMES), TRUE);
  92. ::EnableWindow(GetControl(IDC_GENERAL_MACHINENAME), TRUE);
  93. if (GetWindowTextLength(GetControl(IDC_GENERAL_MACHINENAME)))
  94. ::SendMessage(::GetParent(m_hDlg), PSM_SETWIZBUTTONS, 0, PSWIZB_FINISH);
  95. else
  96. ::SendMessage(::GetParent(m_hDlg), PSM_SETWIZBUTTONS, 0, PSWIZB_DISABLEDFINISH);
  97. m_IsLocalMachine = FALSE;
  98. return TRUE;
  99. }
  100. break;
  101. case IDC_GENERAL_MACHINENAME:
  102. if (EN_CHANGE == HIWORD(wParam)) {
  103. // edit control change, see if there are any text in the
  104. // control at all. It it does, enable the finish button,
  105. // otherwise, disable it.
  106. //
  107. if (GetWindowTextLength((HWND)lParam))
  108. {
  109. // there are some text in the edit control
  110. // enable the finish button
  111. ::SendMessage(::GetParent(m_hDlg), PSM_SETWIZBUTTONS, 0, PSWIZB_FINISH);
  112. }
  113. else
  114. {
  115. // no text in the edit control
  116. // disable the finish button
  117. ::SendMessage(::GetParent(m_hDlg), PSM_SETWIZBUTTONS, 0, PSWIZB_DISABLEDFINISH);
  118. }
  119. }
  120. break;
  121. case IDC_GENERAL_BROWSE_MACHINENAMES:
  122. DoBrowse();
  123. return TRUE;
  124. break;
  125. }
  126. return FALSE;
  127. }
  128. BOOL
  129. CGeneralPage::OnWizFinish(
  130. void
  131. )
  132. {
  133. BOOL bSuccess = TRUE;
  134. //
  135. // First figure out the machine name
  136. //
  137. m_MachineName[0] = _T('\0');
  138. if (!m_IsLocalMachine)
  139. {
  140. GetWindowText(GetControl(IDC_GENERAL_MACHINENAME), m_MachineName,
  141. sizeof(m_MachineName) / sizeof(TCHAR));
  142. if (_T('\0') != m_MachineName[0])
  143. {
  144. if (_T('\\') != m_MachineName[0])
  145. {
  146. //
  147. // Insert machine name signature to the fron of the name
  148. //
  149. int len = lstrlen(m_MachineName);
  150. if (len + 2 < sizeof(m_MachineName) / sizeof(TCHAR))
  151. {
  152. //
  153. // Move the existing string so that we can insert
  154. // the signature in the first two locations.
  155. // the move includes the terminated null char.
  156. //
  157. for (int i = len + 2; i >= 2; i--) {
  158. m_MachineName[i] = m_MachineName[i - 2];
  159. }
  160. m_MachineName[0] = _T('\\');
  161. m_MachineName[1] = _T('\\');
  162. }
  163. }
  164. //
  165. // Now verify the machine name. If the machine name is invalid
  166. // or can be reached, use the local computer;
  167. //
  168. if (!VerifyMachineName(m_MachineName))
  169. {
  170. TCHAR WarningFormat[MAX_PATH * 3];
  171. TCHAR WarningMsg[MAX_PATH * 3];
  172. LPVOID lpLastError = NULL;
  173. if (LoadString(g_hInstance,
  174. IDS_INVALID_COMPUTER_NAME,
  175. WarningFormat,
  176. ARRAYLEN(WarningFormat)
  177. ) &&
  178. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  179. FORMAT_MESSAGE_FROM_SYSTEM |
  180. FORMAT_MESSAGE_IGNORE_INSERTS,
  181. NULL,
  182. GetLastError(),
  183. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  184. (LPTSTR)&lpLastError,
  185. 0,
  186. NULL)) {
  187. StringCchPrintf(WarningMsg,
  188. ARRAYLEN(WarningMsg),
  189. WarningFormat,
  190. m_MachineName,
  191. lpLastError
  192. );
  193. MessageBox(m_hDlg,
  194. (LPCTSTR)WarningMsg,
  195. (LPCTSTR)g_strDevMgr,
  196. MB_ICONERROR | MB_OK
  197. );
  198. bSuccess = FALSE;
  199. }
  200. if (lpLastError) {
  201. LocalFree(lpLastError);
  202. }
  203. m_MachineName[0] = _T('\0');
  204. }
  205. }
  206. }
  207. try
  208. {
  209. if (m_lConsoleHandle)
  210. {
  211. //
  212. // A console handle is created for the property sheet,
  213. // use the handle to notify the snapin about the new
  214. // startup information.
  215. //
  216. BufferPtr<BYTE> Buffer(sizeof(PROPERTY_CHANGE_INFO) + sizeof(STARTUP_INFODATA));
  217. PPROPERTY_CHANGE_INFO pPCI = (PPROPERTY_CHANGE_INFO)(BYTE*)Buffer;
  218. PSTARTUP_INFODATA pSI = (PSTARTUP_INFODATA)&pPCI->InfoData;
  219. if (_T('\0') != m_MachineName[0]) {
  220. lstrcpy(pSI->MachineName, m_MachineName);
  221. }
  222. pSI->ct = m_ct;
  223. pSI->Size = sizeof(STARTUP_INFODATA);
  224. pPCI->Type = PCT_STARTUP_INFODATA;
  225. //
  226. // Notify IComponentData about what we have here.
  227. //
  228. MMCPropertyChangeNotify(m_lConsoleHandle, reinterpret_cast<LONG_PTR>(&pPCI));
  229. }
  230. else if (m_pstrMachineName && m_pct)
  231. {
  232. //
  233. // No console is provided for the property sheet.
  234. // send the new startup info in the given buffer if it is
  235. // provided.
  236. //
  237. *m_pstrMachineName = m_MachineName;
  238. *m_pct = m_ct;
  239. }
  240. else
  241. {
  242. //
  243. // Nobody is listening to what we have to say. Something must be
  244. // wrong!
  245. //
  246. ASSERT(FALSE);
  247. }
  248. }
  249. catch (CMemoryException* e)
  250. {
  251. e->Delete();
  252. MsgBoxParam(m_hDlg, 0, 0, 0);
  253. }
  254. SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, bSuccess ? 0L : -1L);
  255. return TRUE;
  256. }
  257. BOOL
  258. CGeneralPage::OnHelp(
  259. LPHELPINFO pHelpInfo
  260. )
  261. {
  262. WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP,
  263. (ULONG_PTR)g_a102HelpIDs);
  264. return FALSE;
  265. }
  266. BOOL
  267. CGeneralPage::OnContextMenu(
  268. HWND hWnd,
  269. WORD xPos,
  270. WORD yPos
  271. )
  272. {
  273. WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU,
  274. (ULONG_PTR)g_a102HelpIDs);
  275. return FALSE;
  276. }
  277. void
  278. CGeneralPage::DoBrowse(
  279. void
  280. )
  281. {
  282. HRESULT hr;
  283. static const int SCOPE_INIT_COUNT = 1;
  284. DSOP_SCOPE_INIT_INFO aScopeInit[SCOPE_INIT_COUNT];
  285. ZeroMemory(aScopeInit, sizeof(DSOP_SCOPE_INIT_INFO) * SCOPE_INIT_COUNT);
  286. //
  287. // Since we just want computer objects from every scope, combine them
  288. // all in a single scope initializer.
  289. //
  290. aScopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  291. aScopeInit[0].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN
  292. | DSOP_SCOPE_TYPE_GLOBAL_CATALOG
  293. | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN
  294. | DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN
  295. | DSOP_SCOPE_TYPE_WORKGROUP
  296. | DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE
  297. | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE;
  298. aScopeInit[0].FilterFlags.Uplevel.flBothModes =
  299. DSOP_FILTER_COMPUTERS;
  300. aScopeInit[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS;
  301. //
  302. // Put the scope init array into the object picker init array
  303. //
  304. DSOP_INIT_INFO InitInfo;
  305. ZeroMemory(&InitInfo, sizeof(InitInfo));
  306. InitInfo.cbSize = sizeof(InitInfo);
  307. InitInfo.pwzTargetComputer = NULL; // NULL == local machine
  308. InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
  309. InitInfo.aDsScopeInfos = aScopeInit;
  310. //
  311. // Note object picker makes its own copy of InitInfo. Also note
  312. // that Initialize may be called multiple times, last call wins.
  313. //
  314. IDsObjectPicker *pDsObjectPicker = NULL;
  315. IDataObject *pdo = NULL;
  316. bool fGotStgMedium = false;
  317. STGMEDIUM stgmedium =
  318. {
  319. TYMED_HGLOBAL,
  320. NULL,
  321. NULL
  322. };
  323. do {
  324. hr = CoCreateInstance(CLSID_DsObjectPicker,
  325. NULL,
  326. CLSCTX_INPROC_SERVER,
  327. IID_IDsObjectPicker,
  328. (void **) &pDsObjectPicker);
  329. hr = pDsObjectPicker->Initialize(&InitInfo);
  330. hr = pDsObjectPicker->InvokeDialog(m_hDlg, &pdo);
  331. // Quit if user hit Cancel
  332. if (hr == S_FALSE)
  333. {
  334. break;
  335. }
  336. FORMATETC formatetc =
  337. {
  338. (CLIPFORMAT)g_cfDsObjectPicker,
  339. NULL,
  340. DVASPECT_CONTENT,
  341. -1,
  342. TYMED_HGLOBAL
  343. };
  344. hr = pdo->GetData(&formatetc, &stgmedium);
  345. fGotStgMedium = true;
  346. PDS_SELECTION_LIST pDsSelList =
  347. (PDS_SELECTION_LIST) GlobalLock(stgmedium.hGlobal);
  348. if (!pDsSelList)
  349. {
  350. break;
  351. }
  352. ULONG i;
  353. ASSERT(pDsSelList->cItems == 1);
  354. //
  355. // Put the machine name in the edit control
  356. //
  357. ::SetDlgItemText(m_hDlg, IDC_GENERAL_MACHINENAME, pDsSelList->aDsSelection[0].pwzName);
  358. GlobalUnlock(stgmedium.hGlobal);
  359. } while (0);
  360. if (fGotStgMedium)
  361. {
  362. ReleaseStgMedium(&stgmedium);
  363. }
  364. if (pDsObjectPicker)
  365. {
  366. pDsObjectPicker->Release();
  367. }
  368. }