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.

540 lines
17 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation
  3. */
  4. #include "stdinc.h"
  5. #include "dbt.h"
  6. #include "devguid.h"
  7. #include "dialogs.h"
  8. #include "cassemblyrecoveryinfo.h"
  9. #include "protectionui.h"
  10. #include "recover.h"
  11. #include "sxsexceptionhandling.h"
  12. //
  13. // FAKERY
  14. //
  15. extern HINSTANCE g_hInstance;
  16. extern HANDLE g_hSxsLoginEvent;
  17. HDESK g_hDesktop = NULL;
  18. BOOL
  19. SxspSpinUntilValidDesktop()
  20. {
  21. FN_PROLOG_WIN32
  22. //
  23. // NTRAID#NTBUG9-219455-2000/12/13-MGrier Postponed to Blackcomb; the
  24. // current code does the same thing that WFP is doing; it's just that
  25. // we should really have them pass us the desktop.
  26. //
  27. // We should be relying on what WFP has already
  28. // found to be the 'proper' input desktop. Doing so, however requires a
  29. // change to the interface between SXS and SFC to pass along a pointer to
  30. // the WFP desktop handle. Not a bad thing, just .. not implemented yet.
  31. //
  32. while (g_hDesktop == NULL)
  33. {
  34. DWORD dwResult = ::WaitForSingleObject(g_hSxsLoginEvent, INFINITE);
  35. if (dwResult == WAIT_OBJECT_0)
  36. IFW32NULL_ORIGINATE_AND_EXIT(g_hDesktop = ::OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED));
  37. else if (dwResult == WAIT_FAILED)
  38. ORIGINATE_WIN32_FAILURE_AND_EXIT(WaitForSingleObject, ::FusionpGetLastWin32Error());
  39. }
  40. FN_EPILOG
  41. }
  42. CSXSMediaPromptDialog::CSXSMediaPromptDialog()
  43. : m_hOurWnd((HWND)INVALID_HANDLE_VALUE),
  44. m_pvDeviceChange(NULL),
  45. m_uiAutoRunMsg(0),
  46. m_DeviceChangeMask(0),
  47. m_DeviceChangeFlags(0),
  48. m_fIsCDROM(false),
  49. m_CodebaseInfo(NULL)
  50. {
  51. }
  52. CSXSMediaPromptDialog::~CSXSMediaPromptDialog()
  53. {
  54. }
  55. BOOL
  56. CSXSMediaPromptDialog::Initialize(
  57. const CCodebaseInformation* CodebaseInfo
  58. )
  59. {
  60. BOOL fSuccess = FALSE;
  61. FN_TRACE_WIN32(fSuccess);
  62. PARAMETER_CHECK(CodebaseInfo != NULL);
  63. SxsWFPResolveCodebase CodebaseType;
  64. IFW32FALSE_EXIT(CodebaseInfo->Win32GetType(CodebaseType));
  65. PARAMETER_CHECK(
  66. (CodebaseType == CODEBASE_RESOLVED_URLHEAD_FILE) ||
  67. (CodebaseType == CODEBASE_RESOLVED_URLHEAD_WINSOURCE) ||
  68. (CodebaseType == CODEBASE_RESOLVED_URLHEAD_CDROM));
  69. m_CodebaseInfo = CodebaseInfo;
  70. switch (CodebaseType)
  71. {
  72. case CODEBASE_RESOLVED_URLHEAD_CDROM:
  73. m_fIsCDROM = true;
  74. break;
  75. case CODEBASE_RESOLVED_URLHEAD_WINSOURCE:
  76. {
  77. CFusionRegKey hkSetupInfo;
  78. DWORD dwWasFromCDRom;
  79. IFREGFAILED_ORIGINATE_AND_EXIT(
  80. ::RegOpenKeyExW(
  81. HKEY_LOCAL_MACHINE,
  82. WINSXS_INSTALL_SOURCE_BASEDIR,
  83. 0,
  84. KEY_READ | FUSIONP_KEY_WOW64_64KEY,
  85. &hkSetupInfo));
  86. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - If the key isn't there, it's ok to assume not
  87. // from a CDROM but if it was out of resources etc. this should propagate an error.
  88. if (!::FusionpRegQueryDwordValueEx(
  89. 0,
  90. hkSetupInfo,
  91. WINSXS_INSTALL_SOURCE_IS_CDROM,
  92. &dwWasFromCDRom))
  93. {
  94. dwWasFromCDRom = 0;
  95. }
  96. m_fIsCDROM = (dwWasFromCDRom != 0);
  97. break;
  98. }
  99. case CODEBASE_RESOLVED_URLHEAD_FILE:
  100. {
  101. CSmallStringBuffer buffVolumePathName;
  102. IFW32FALSE_EXIT(
  103. ::SxspGetVolumePathName(
  104. 0,
  105. CodebaseInfo->GetCodebase(),
  106. buffVolumePathName));
  107. if (::GetDriveTypeW(buffVolumePathName) == DRIVE_CDROM)
  108. {
  109. m_fIsCDROM = true;
  110. }
  111. break;
  112. }
  113. }
  114. FN_EPILOG
  115. }
  116. BOOL
  117. CSXSMediaPromptDialog::DisplayMessage(
  118. HWND hDlg,
  119. UINT uContentText,
  120. UINT uDialogFlags,
  121. int &riResult
  122. )
  123. {
  124. FN_PROLOG_WIN32
  125. const SIZE_T BufferSize = (MAX_PATH * 2);
  126. CTinyStringBuffer wcTitle;
  127. CTinyStringBuffer wcContent;
  128. int iResult = 0;
  129. if (wcContent.Win32ResizeBuffer(BufferSize + 1, eDoNotPreserveBufferContents))
  130. {
  131. CStringBufferAccessor Accessor(&wcContent);
  132. IFW32ZERO_ORIGINATE_AND_EXIT(::LoadStringW(g_hInstance, uContentText, Accessor, BufferSize));
  133. }
  134. if (wcTitle.Win32ResizeBuffer(BufferSize, eDoNotPreserveBufferContents))
  135. {
  136. CStringBufferAccessor Accessor(&wcTitle);
  137. IFW32ZERO_ORIGINATE_AND_EXIT(::LoadStringW(g_hInstance, IDS_TITLE, Accessor, BufferSize));
  138. }
  139. IFW32ZERO_ORIGINATE_AND_EXIT(iResult = ::MessageBoxW(hDlg, wcContent, wcTitle, uDialogFlags));
  140. riResult = iResult;
  141. FN_EPILOG
  142. }
  143. BOOL
  144. CSXSMediaPromptDialog::ShowSelf(
  145. CSXSMediaPromptDialog::DialogResults &rResult
  146. )
  147. {
  148. FN_PROLOG_WIN32
  149. INT_PTR i;
  150. IFW32FALSE_EXIT(::SxspSpinUntilValidDesktop());
  151. IFW32FALSE_ORIGINATE_AND_EXIT(::SetThreadDesktop(g_hDesktop));
  152. i = ::DialogBoxParamW(
  153. g_hInstance,
  154. MAKEINTRESOURCEW(
  155. m_fIsCDROM ?
  156. IDD_SFC_CD_PROMPT :
  157. IDD_SFC_NETWORK_PROMPT),
  158. NULL,
  159. &CSXSMediaPromptDialog::OurDialogProc,
  160. (LPARAM)this);
  161. if (i == -1)
  162. ORIGINATE_WIN32_FAILURE_AND_EXIT(DialogBoxParamW, ::FusionpGetLastWin32Error());
  163. rResult = static_cast<DialogResults>(i);
  164. FN_EPILOG
  165. }
  166. BOOL
  167. SxspFindInstallWindowsSourcePath(
  168. OUT CBaseStringBuffer &rbuffTempStringBuffer
  169. )
  170. {
  171. FN_PROLOG_WIN32
  172. CFusionRegKey rhkInstallSource;
  173. rbuffTempStringBuffer.Clear();
  174. IFREGFAILED_ORIGINATE_AND_EXIT(
  175. ::RegOpenKeyExW(
  176. HKEY_LOCAL_MACHINE,
  177. WINSXS_INSTALL_SOURCE_BASEDIR,
  178. 0,
  179. KEY_READ | FUSIONP_KEY_WOW64_64KEY,
  180. &rhkInstallSource));
  181. IFW32FALSE_EXIT(
  182. ::FusionpRegQuerySzValueEx(
  183. FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING,
  184. rhkInstallSource,
  185. WINSXS_INSTALL_SOURCEPATH_REGKEY,
  186. rbuffTempStringBuffer));
  187. //
  188. // Now let's be really cheesy and find the fourth slash (\\foo\bar\), and
  189. // clip everything after that.
  190. //
  191. PCWSTR cursor = rbuffTempStringBuffer;
  192. ULONG ulSlashCount = 0;
  193. while ( *cursor && ulSlashCount < 4 )
  194. {
  195. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Should handle both slashes. I think we have
  196. // a macro for this.
  197. if (*cursor == L'\\')
  198. ulSlashCount++;
  199. cursor++;
  200. }
  201. //
  202. // If we got 3 or less, then it's \\foo\bar or \\foo, which should be
  203. // illegal. Otherwise, clip everything off past this point.
  204. //
  205. if (ulSlashCount > 3)
  206. {
  207. rbuffTempStringBuffer.Left(cursor - rbuffTempStringBuffer);
  208. IFW32FALSE_EXIT(rbuffTempStringBuffer.Win32RemoveTrailingPathSeparators());
  209. }
  210. FN_EPILOG
  211. }
  212. INT_PTR
  213. CALLBACK
  214. CSXSMediaPromptDialog::OurDialogProc(
  215. HWND hDlg,
  216. UINT uMsg,
  217. WPARAM wParam,
  218. LPARAM lParam
  219. )
  220. {
  221. FN_TRACE();
  222. INT_PTR iResult = 0;
  223. int iMessageBoxResult = 0;
  224. #define WM_TRYAGAIN (WM_USER + 1)
  225. static CSXSMediaPromptDialog *pThis = NULL;
  226. switch (uMsg)
  227. {
  228. case WM_INITDIALOG:
  229. {
  230. pThis = reinterpret_cast<CSXSMediaPromptDialog *>(lParam);
  231. FLASHWINFO winfo;
  232. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Shouldn't these be INTERNAL_ERROR_CHECKs?
  233. ASSERT(pThis != NULL);
  234. ASSERT(pThis->m_hOurWnd == INVALID_HANDLE_VALUE);
  235. pThis->m_hOurWnd = hDlg;
  236. //
  237. // Center the window, bring it forward
  238. //
  239. {
  240. RECT rcWindow;
  241. LONG x, y, w, h;
  242. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  243. ::GetWindowRect(hDlg, &rcWindow); // error check?
  244. w = rcWindow.right - rcWindow.left + 1;
  245. h = rcWindow.bottom - rcWindow.top + 1;
  246. x = (::GetSystemMetrics(SM_CXSCREEN) - w) / 2; // error check?
  247. y = (::GetSystemMetrics(SM_CYSCREEN) - h) / 2; // error check?
  248. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  249. ::MoveWindow(hDlg, x, y, w, h, FALSE); // error check?
  250. winfo.cbSize = sizeof(winfo);
  251. winfo.hwnd = hDlg;
  252. winfo.dwFlags = FLASHW_ALL;
  253. winfo.uCount = 3;
  254. winfo.dwTimeout = 0;
  255. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  256. ::SetForegroundWindow(hDlg); // error check?
  257. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  258. ::FlashWindowEx(&winfo); // error check?
  259. }
  260. //
  261. // Create the device-change notification
  262. //
  263. if (pThis->m_pvDeviceChange == NULL)
  264. {
  265. DEV_BROADCAST_DEVICEINTERFACE_W FilterData = { 0 };
  266. FilterData.dbcc_size = sizeof(FilterData);
  267. FilterData.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  268. FilterData.dbcc_classguid = GUID_DEVCLASS_CDROM;
  269. IFW32NULL_ORIGINATE_AND_EXIT(
  270. pThis->m_pvDeviceChange = ::RegisterDeviceNotificationW(
  271. hDlg,
  272. &FilterData,
  273. DEVICE_NOTIFY_WINDOW_HANDLE));
  274. }
  275. //
  276. // Turn off autorun
  277. //
  278. IFW32ZERO_ORIGINATE_AND_EXIT(pThis->m_uiAutoRunMsg = ::RegisterWindowMessageW(L"QueryCancelAutoPlay"));
  279. //
  280. // Fidget with the text in the popup dialog now
  281. //
  282. {
  283. CSmallStringBuffer sbFormatter;
  284. CSmallStringBuffer buffFormattedText;
  285. CStringBufferAccessor acc;
  286. //
  287. // It is ok if these memory allocations fail, the ui will degrade.
  288. // As well, that's a reason to leave the buffers "small" and not "tiny".
  289. // ?
  290. //
  291. sbFormatter.Win32ResizeBuffer(512, eDoNotPreserveBufferContents);
  292. buffFormattedText.Win32ResizeBuffer(512, eDoNotPreserveBufferContents);
  293. //
  294. // Set the "Insert your .... now"
  295. //
  296. sbFormatter.Clear();
  297. acc.Attach(&sbFormatter);
  298. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  299. ::GetDlgItemTextW( // error check?
  300. hDlg,
  301. IDC_MEDIA_NAME,
  302. acc,
  303. static_cast<DWORD>(sbFormatter.GetBufferCch()));
  304. acc.Detach();
  305. if (pThis->m_CodebaseInfo->GetPromptText().Cch() != 0)
  306. {
  307. IFW32FALSE_EXIT(buffFormattedText.Win32Format(
  308. sbFormatter,
  309. static_cast<PCWSTR>(pThis->m_CodebaseInfo->GetPromptText())));
  310. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  311. ::SetDlgItemTextW(hDlg, IDC_MEDIA_NAME, static_cast<PCWSTR>(buffFormattedText)); // error check?
  312. }
  313. else
  314. {
  315. #if DBG
  316. ::FusionpDbgPrintEx(
  317. FUSION_DBG_LEVEL_WFP,
  318. "SXS: %s - setting IDC_MEDIA_NAME to empty\n", __FUNCTION__);
  319. #endif
  320. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  321. ::SetDlgItemTextW(hDlg, IDC_MEDIA_NAME, L""); // error check?
  322. }
  323. //
  324. // Now, depending on what kind of box this is..
  325. //
  326. if (!pThis->m_fIsCDROM)
  327. {
  328. CSmallStringBuffer buffTempStringBuffer;
  329. SxsWFPResolveCodebase CodebaseType;
  330. sbFormatter.Clear();
  331. acc.Attach(&sbFormatter);
  332. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  333. ::GetDlgItemTextW( // error check?
  334. hDlg,
  335. IDC_NET_NAME,
  336. acc,
  337. static_cast<DWORD>(sbFormatter.GetBufferCch()));
  338. acc.Detach();
  339. IFW32FALSE_EXIT(pThis->m_CodebaseInfo->Win32GetType(CodebaseType));
  340. //
  341. // If this is the Windows install media, display something
  342. // pleasant to the user - \\server\share only!
  343. //
  344. if (CodebaseType == CODEBASE_RESOLVED_URLHEAD_WINSOURCE)
  345. {
  346. IFW32FALSE_EXIT(::SxspFindInstallWindowsSourcePath(buffTempStringBuffer));
  347. }
  348. else
  349. {
  350. IFW32FALSE_EXIT(buffTempStringBuffer.Win32Assign(pThis->m_CodebaseInfo->GetCodebase()));
  351. }
  352. if (buffTempStringBuffer.Cch() != 0)
  353. {
  354. IFW32FALSE_EXIT(buffFormattedText.Win32Format(sbFormatter, static_cast<PCWSTR>(buffTempStringBuffer)));
  355. IFW32FALSE_EXIT(::SetDlgItemTextW(hDlg, IDC_NET_NAME, buffFormattedText));
  356. }
  357. else
  358. {
  359. #if DBG
  360. ::FusionpDbgPrintEx(
  361. FUSION_DBG_LEVEL_WFP,
  362. "SXS: %s - setting IDC_NET_NAME to empty\n", __FUNCTION__);
  363. #endif
  364. IFW32FALSE_EXIT(::SetDlgItemTextW(hDlg, IDC_NET_NAME, L""));
  365. }
  366. }
  367. else
  368. {
  369. //
  370. // TODO (jonwis) : This is a CD-rom based install, so we should do
  371. // something sane about prompting for the windows CD.
  372. //
  373. }
  374. //
  375. // Now get the prompt from the resources.. we only have one, really.
  376. //
  377. sbFormatter.Clear();
  378. acc.Attach(&sbFormatter);
  379. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  380. ::LoadStringW( // error check?
  381. g_hInstance,
  382. IDS_RESTORE_TEXT,
  383. acc.GetBufferPtr(),
  384. acc.GetBufferCchAsDWORD());
  385. acc.Detach();
  386. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  387. ::SetDlgItemTextW(hDlg, IDC_PROMPT_TEXT, sbFormatter); // error check?
  388. }
  389. }
  390. break;
  391. case WM_COMMAND:
  392. switch (LOWORD(wParam))
  393. {
  394. case IDC_RETRY:
  395. pThis->m_DeviceChangeMask = static_cast<DWORD>(-1);
  396. pThis->m_DeviceChangeFlags = DBTF_MEDIA;
  397. IFW32FALSE_ORIGINATE_AND_EXIT(::PostMessageW(hDlg, WM_TRYAGAIN, 0, 0));
  398. break;
  399. case IDC_INFO:
  400. IFW32FALSE_EXIT(
  401. pThis->DisplayMessage(
  402. NULL,
  403. pThis->m_fIsCDROM ? IDS_MORE_INFORMATION_CD : IDS_MORE_INFORMATION_NET,
  404. MB_ICONINFORMATION | MB_SERVICE_NOTIFICATION | MB_OK,
  405. iMessageBoxResult));
  406. break;
  407. case IDCANCEL:
  408. IFW32FALSE_EXIT(
  409. pThis->DisplayMessage(
  410. hDlg,
  411. IDS_CANCEL_CONFIRM,
  412. MB_APPLMODAL | MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING,
  413. iMessageBoxResult));
  414. if (iMessageBoxResult == IDYES)
  415. {
  416. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  417. ::UnregisterDeviceNotification(pThis->m_pvDeviceChange); // error check?
  418. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  419. ::EndDialog(hDlg, CSXSMediaPromptDialog::DialogCancelled); // error check?
  420. }
  421. break;
  422. }
  423. break; // WM_COMMAND
  424. case WM_DEVICECHANGE:
  425. if (wParam == DBT_DEVICEARRIVAL)
  426. {
  427. DEV_BROADCAST_VOLUME *dbv = reinterpret_cast<DEV_BROADCAST_VOLUME*>(lParam);
  428. ASSERT(dbv != NULL);
  429. if (dbv->dbcv_devicetype == DBT_DEVTYP_VOLUME)
  430. {
  431. pThis->m_DeviceChangeMask = dbv->dbcv_unitmask;
  432. pThis->m_DeviceChangeFlags = dbv->dbcv_flags;
  433. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  434. ::PostMessageW(hDlg, WM_TRYAGAIN, 0, 0); // error check?
  435. }
  436. }
  437. break;
  438. case WM_TRYAGAIN:
  439. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  440. ::UnregisterDeviceNotification(pThis->m_pvDeviceChange); // error check?
  441. // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
  442. ::EndDialog(hDlg, CSXSMediaPromptDialog::DialogMediaFound); // error check?
  443. break;
  444. }
  445. Exit:
  446. return iResult;
  447. }