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.

496 lines
16 KiB

  1. //**********************************************************************
  2. // File name: reboot.cpp
  3. //
  4. // Desktop manipulation functions
  5. //
  6. // Functions:
  7. //
  8. // Copyright (c) 1992 - 1998 Microsoft Corporation. All rights reserved.
  9. //**********************************************************************
  10. #include "pre.h"
  11. #include <shlobj.h>
  12. extern TCHAR g_szProductCode[];
  13. extern TCHAR g_szPromoCode[];
  14. extern TCHAR g_szOemCode[];
  15. extern TCHAR* g_pszCmdLine;
  16. #define SHELL_LINK_NAME TEXT("icwstart.lnk")
  17. #define KEYVALUE_SIGNUPID TEXT("iSignUp")
  18. #define MsgBox(m,s) MessageBox(NULL,GetSz(m),GetSz(IDS_APPNAME),s)
  19. #define MB_MYERROR (MB_APPLMODAL | MB_ICONERROR | MB_SETFOREGROUND)
  20. class RegEntry
  21. {
  22. public:
  23. RegEntry(LPCTSTR pszSubKey, HKEY hkey = HKEY_CURRENT_USER);
  24. ~RegEntry();
  25. long GetError() { return _error; }
  26. long SetValue(LPCTSTR pszValue, LPCTSTR string);
  27. LPTSTR GetString(LPCTSTR pszValue, LPTSTR string, unsigned long length);
  28. long DeleteValue(LPCTSTR pszValue);
  29. private:
  30. HKEY _hkey;
  31. long _error;
  32. BOOL bhkeyValid;
  33. };
  34. RegEntry::RegEntry(LPCTSTR pszSubKey, HKEY hkey)
  35. {
  36. _error = RegCreateKey(hkey, pszSubKey, &_hkey);
  37. if (_error) {
  38. bhkeyValid = FALSE;
  39. }
  40. else {
  41. bhkeyValid = TRUE;
  42. }
  43. }
  44. RegEntry::~RegEntry()
  45. {
  46. if (bhkeyValid) {
  47. RegCloseKey(_hkey);
  48. }
  49. }
  50. long RegEntry::SetValue(LPCTSTR pszValue, LPCTSTR string)
  51. {
  52. if (bhkeyValid) {
  53. _error = RegSetValueEx(_hkey, pszValue, 0, REG_SZ, (LPBYTE) string,
  54. sizeof(TCHAR)*(lstrlen(string)+1));
  55. }
  56. return _error;
  57. }
  58. LPTSTR RegEntry::GetString(LPCTSTR pszValue, LPTSTR string, unsigned long length)
  59. {
  60. DWORD dwType = REG_SZ;
  61. if (bhkeyValid) {
  62. _error = RegQueryValueEx(_hkey, (LPTSTR) pszValue, 0, &dwType, (LPBYTE)string,
  63. &length);
  64. }
  65. if (_error) {
  66. *string = '\0';
  67. return NULL;
  68. }
  69. return string;
  70. }
  71. long RegEntry::DeleteValue(LPCTSTR pszValue)
  72. {
  73. if (bhkeyValid) {
  74. _error = RegDeleteValue(_hkey, (LPTSTR) pszValue);
  75. }
  76. return _error;
  77. }
  78. /*******************************************************************
  79. ARULM -- copied from JeremyS's UTIL.C in original INETCFG.DLL
  80. NAME: PrepareForRunOnceApp
  81. SYNOPSIS: Copies wallpaper value in registry to make the runonce
  82. app happy
  83. NOTES: The runonce app (the app that displays a list of apps
  84. that are run once at startup) has a bug. At first boot,
  85. it wants to change the wallpaper from the setup wallpaper
  86. to what the user had before running setup. Setup tucks
  87. the "old" wallpaper away in a private key, then changes
  88. the wallpaper to the setup wallpaper. After the runonce
  89. app finishes, it looks in the private key to get the old
  90. wallpaper and sets that to be the current wallpaper.
  91. However, it does this all the time, not just at first boot!
  92. The end effect is that whenever you do anything that
  93. causes runonce.exe to run (add stuff thru add/remove
  94. programs control panel), your wallpaper gets set back to
  95. whatever it was when you installed win 95. This is
  96. especially bad for Plus!, since wallpaper settings are an
  97. important part of the product.
  98. To work around this bug, we copy the current wallpaper settings
  99. (which we want preserved) to setup's private key. When
  100. runonce runs it will say "aha!" and copy those values back
  101. to the current settings.
  102. ********************************************************************/
  103. // "Control Panel\\Desktop"
  104. static const TCHAR szRegPathDesktop[] = REGSTR_PATH_DESKTOP;
  105. // "Software\\Microsoft\\Windows\\CurrentVersion\\Setup"
  106. static const TCHAR szRegPathSetupWallpaper[] = REGSTR_PATH_SETUP REGSTR_KEY_SETUP;
  107. static const TCHAR szRegValWallpaper[] = TEXT("Wallpaper");
  108. static const TCHAR szRegValTileWallpaper[] = TEXT("TileWallpaper");
  109. #define LD_USEDESC 0x00000001
  110. #define LD_USEARGS 0x00000002
  111. #define LD_USEICON 0x00000004
  112. #define LD_USEWORKDIR 0x00000008
  113. #define LD_USEHOTKEY 0x00000010
  114. #define LD_USESHOWCMD 0x00000020
  115. typedef struct {
  116. // Mandatory members
  117. LPTSTR pszPathname; // Pathname of original object
  118. DWORD fdwFlags; // LD_* flags ORed together for optional members
  119. // Optional members
  120. LPTSTR pszDesc; // Description of link file (its filename)
  121. LPTSTR pszArgs; // command-line arguments
  122. LPTSTR pszIconPath; // Pathname of file containing the icon
  123. LPTSTR pszWorkingDir; // Working directory when process starts
  124. int nIconIndex; // Index of icon in pszIconPath
  125. int nShowCmd; // How to show the initial window
  126. WORD wHotkey; // Hot key for the link
  127. } LINKDATA, *PLINKDATA;
  128. HRESULT WINAPI Shell_CreateLink (LPCTSTR pszLinkFilePathname, PLINKDATA pld);
  129. VOID PrepareForRunOnceApp(VOID)
  130. {
  131. // open a key to the current wallpaper settings
  132. RegEntry reDesktop(szRegPathDesktop,HKEY_CURRENT_USER);
  133. Assert(reDesktop.GetError() == ERROR_SUCCESS);
  134. // open a key to the private setup section
  135. RegEntry reSetup(szRegPathSetupWallpaper,HKEY_LOCAL_MACHINE);
  136. Assert(reSetup.GetError() == ERROR_SUCCESS);
  137. if (reDesktop.GetError() == ERROR_SUCCESS &&
  138. reSetup.GetError() == ERROR_SUCCESS) {
  139. TCHAR szWallpaper[MAX_PATH+1] = TEXT("");
  140. TCHAR szTiled[10] = TEXT(""); // big enough for "1" + slop
  141. // get the current wallpaper name
  142. if (reDesktop.GetString(szRegValWallpaper,szWallpaper,
  143. sizeof(szWallpaper))) {
  144. // set the current wallpaper name in setup's private section
  145. UINT uRet=reSetup.SetValue(szRegValWallpaper,szWallpaper);
  146. Assert(uRet == ERROR_SUCCESS);
  147. // get the current 'tiled' value.
  148. reDesktop.GetString(szRegValTileWallpaper,szTiled,
  149. sizeof(szTiled));
  150. // set the 'tiled' value in setup's section
  151. if (lstrlen(szTiled)) {
  152. uRet=reSetup.SetValue(szRegValTileWallpaper,szTiled);
  153. Assert(uRet == ERROR_SUCCESS);
  154. }
  155. }
  156. }
  157. }
  158. //+----------------------------------------------------------------------------
  159. //
  160. // Function SetStartUpCommand
  161. //
  162. // Synopsis On an NT machine the RunOnce method is not reliable. Therefore
  163. // we will restart the ICW by placing a .BAT file in the common
  164. // startup directory.
  165. //
  166. // Arguments lpCmd - command line used to restart the ICW
  167. //
  168. // Returns TRUE if it worked
  169. // FALSE otherwise.
  170. //
  171. // History 1-10-97 ChrisK Created
  172. //
  173. //-----------------------------------------------------------------------------
  174. BOOL SetStartUpCommand(LPTSTR lpCmd, LPTSTR lpArgs)
  175. {
  176. BOOL bRC = FALSE;
  177. TCHAR szCommandLine[MAX_PATH + 1];
  178. LPITEMIDLIST lpItemDList = NULL;
  179. HRESULT hr = ERROR_SUCCESS;
  180. IMalloc *pMalloc = NULL;
  181. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_STARTUP,&lpItemDList)))
  182. {
  183. if (SHGetPathFromIDList(lpItemDList, szCommandLine))
  184. {
  185. // make sure there is a trailing \ character
  186. if ('\\' != szCommandLine[lstrlen(szCommandLine)-1])
  187. lstrcat(szCommandLine, TEXT("\\"));
  188. lstrcat(szCommandLine,SHELL_LINK_NAME);
  189. //Setup our link structure
  190. LINKDATA ld;
  191. ld.pszPathname = lpCmd;
  192. ld.fdwFlags = LD_USEARGS;
  193. ld.pszArgs = lpArgs;
  194. //Create the shorLD_USEWORKDIRtcut in start-up
  195. if(SUCCEEDED(Shell_CreateLink(szCommandLine, &ld)))
  196. bRC = TRUE;
  197. }
  198. // Free up the memory allocated for LPITEMIDLIST
  199. if (SUCCEEDED (SHGetMalloc (&pMalloc)))
  200. {
  201. //Don't worry about the return value of the function
  202. //since even if we can't clean up the mem the shortcut was
  203. //created so in that sense the function "succeded"
  204. pMalloc->Free (lpItemDList);
  205. pMalloc->Release ();
  206. }
  207. }
  208. return bRC;
  209. }
  210. HRESULT WINAPI Shell_CreateLink (LPCTSTR pszLinkFilePathname, PLINKDATA pld)
  211. {
  212. HRESULT hres;
  213. IShellLink* psl;
  214. IPersistFile* ppf;
  215. hres = CoInitialize(NULL); // Create a shell link object
  216. hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (PVOID *) &psl);
  217. if (SUCCEEDED(hres))
  218. { // Initialize the shell link object
  219. psl->SetPath(pld->pszPathname);
  220. if (pld->fdwFlags & LD_USEARGS)
  221. psl->SetArguments(pld->pszArgs);
  222. if (pld->fdwFlags & LD_USEDESC)
  223. psl->SetDescription(pld->pszDesc);
  224. if (pld->fdwFlags & LD_USEICON)
  225. psl->SetIconLocation(pld->pszIconPath, pld->nIconIndex);
  226. if (pld->fdwFlags & LD_USEWORKDIR)
  227. psl->SetWorkingDirectory(pld->pszWorkingDir);
  228. if (pld->fdwFlags & LD_USESHOWCMD)
  229. psl->SetShowCmd(pld->nShowCmd);
  230. if (pld->fdwFlags & LD_USEHOTKEY)
  231. psl->SetHotkey(pld->wHotkey);
  232. // Save the shell link object on the disk
  233. hres = psl->QueryInterface(IID_IPersistFile, (PVOID *) &ppf);
  234. if (SUCCEEDED(hres))
  235. {
  236. hres = ppf->Save(A2W(pszLinkFilePathname), TRUE);
  237. ppf->Release();
  238. }
  239. psl->Release();
  240. }
  241. CoUninitialize();
  242. return(hres);
  243. }
  244. //+----------------------------------------------------------------------------
  245. //
  246. // Function: DeleteStartUpCommand
  247. //
  248. // Synopsis: After restart the ICW we need to delete the .bat file from
  249. // the common startup directory
  250. //
  251. // Arguements: None
  252. //
  253. // Returns: None
  254. //
  255. // History: 1-10-97 ChrisK Created
  256. //
  257. //-----------------------------------------------------------------------------
  258. void DeleteStartUpCommand ()
  259. {
  260. TCHAR szFileName[MAX_PATH + 1];
  261. LPITEMIDLIST lpItemDList = NULL;
  262. IMalloc *pMalloc = NULL;
  263. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL,CSIDL_STARTUP,&lpItemDList)))
  264. {
  265. if (SHGetPathFromIDList(lpItemDList, szFileName))
  266. {
  267. // make sure there is a trailing \ character
  268. if ('\\' != szFileName[lstrlen(szFileName)-1])
  269. lstrcat(szFileName,TEXT("\\"));
  270. lstrcat(szFileName,SHELL_LINK_NAME);
  271. //delete the shortcut
  272. DeleteFile(szFileName);
  273. }
  274. // Free up the memory allocated for LPITEMIDLIST
  275. if (SUCCEEDED (SHGetMalloc (&pMalloc)))
  276. {
  277. //Don't worry about the return value of the function
  278. //since even if we can't clean up the mem the shortcut was
  279. //created so in that sense the function "succeded"
  280. pMalloc->Free (lpItemDList);
  281. pMalloc->Release ();
  282. }
  283. }
  284. }
  285. // Function CopyUntil
  286. //
  287. // Synopsis Copy from source until destination until running out of source
  288. // or until the next character of the source is the chend character
  289. //
  290. // Arguments dest - buffer to recieve characters
  291. // src - source buffer
  292. // lpdwLen - length of dest buffer
  293. // chend - the terminating character
  294. //
  295. // Returns FALSE - ran out of room in dest buffer
  296. //
  297. // Histroy 10/25/96 ChrisK Created
  298. //-----------------------------------------------------------------------------
  299. static BOOL CopyUntil(LPTSTR *dest, LPTSTR *src, LPDWORD lpdwLen, TCHAR chend)
  300. {
  301. while (('\0' != **src) && (chend != **src) && (0 != *lpdwLen))
  302. {
  303. **dest = **src;
  304. (*lpdwLen)--;
  305. (*dest)++;
  306. (*src)++;
  307. }
  308. return (0 != *lpdwLen);
  309. }
  310. //+----------------------------------------------------------------------------
  311. //
  312. // Function: FGetSystemShutdownPrivledge
  313. //
  314. // Synopsis: For windows NT the process must explicitly ask for permission
  315. // to reboot the system.
  316. //
  317. // Arguements: none
  318. //
  319. // Return: TRUE - privledges granted
  320. // FALSE - DENIED
  321. //
  322. // History: 8/14/96 ChrisK Created
  323. //
  324. // Note: BUGBUG for Win95 we are going to have to softlink to these
  325. // entry points. Otherwise the app won't even load.
  326. // Also, this code was originally lifted out of MSDN July96
  327. // "Shutting down the system"
  328. //-----------------------------------------------------------------------------
  329. BOOL FGetSystemShutdownPrivledge()
  330. {
  331. HANDLE hToken = NULL;
  332. TOKEN_PRIVILEGES tkp;
  333. BOOL bRC = FALSE;
  334. OSVERSIONINFO osver;
  335. ZeroMemory(&osver,sizeof(osver));
  336. osver.dwOSVersionInfoSize = sizeof(osver);
  337. if (GetVersionEx(&osver))
  338. {
  339. if (VER_PLATFORM_WIN32_NT == osver.dwPlatformId)
  340. {
  341. //
  342. // Get the current process token handle
  343. // so we can get shutdown privilege.
  344. //
  345. if (!OpenProcessToken(GetCurrentProcess(),
  346. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  347. goto FGetSystemShutdownPrivledgeExit;
  348. //
  349. // Get the LUID for shutdown privilege.
  350. //
  351. ZeroMemory(&tkp,sizeof(tkp));
  352. LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
  353. &tkp.Privileges[0].Luid);
  354. tkp.PrivilegeCount = 1; /* one privilege to set */
  355. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  356. //
  357. // Get shutdown privilege for this process.
  358. //
  359. AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
  360. (PTOKEN_PRIVILEGES) NULL, 0);
  361. if (ERROR_SUCCESS == GetLastError())
  362. bRC = TRUE;
  363. }
  364. else
  365. {
  366. bRC = TRUE;
  367. }
  368. }
  369. FGetSystemShutdownPrivledgeExit:
  370. if (hToken) CloseHandle(hToken);
  371. return bRC;
  372. }
  373. BOOL SetupForReboot(long lRebootType)
  374. {
  375. UINT uRebootFlags;
  376. TCHAR* pszNewArgs = NULL;
  377. switch (lRebootType)
  378. {
  379. case 0:
  380. uRebootFlags = EWX_REBOOT;
  381. break;
  382. case 1:
  383. uRebootFlags = EWX_LOGOFF;
  384. break;
  385. }
  386. //
  387. // twiddle the registry to work around a bug
  388. // where it trashes the wallpaper
  389. //
  390. PrepareForRunOnceApp();
  391. LPTSTR lpRunOnceCmd;
  392. lpRunOnceCmd = (LPTSTR)GlobalAlloc(GPTR,MAX_PATH*2 + 1);
  393. if (lpRunOnceCmd)
  394. {
  395. GetModuleFileName(NULL, lpRunOnceCmd, MAX_PATH);
  396. //for smart reboot
  397. pszNewArgs = (TCHAR*)malloc((lstrlen(g_pszCmdLine)+MAX_PATH)*sizeof(TCHAR));
  398. if(pszNewArgs)
  399. {
  400. lstrcpy(pszNewArgs, g_pszCmdLine);
  401. lstrcat(pszNewArgs, TEXT(" "));
  402. lstrcat(pszNewArgs, SMARTREBOOT_CMD);
  403. lstrcat(pszNewArgs, TEXT(" "));
  404. if (gpWizardState->cmnStateData.dwFlags & ICW_CFGFLAG_SMARTREBOOT_NEWISP)
  405. lstrcat(pszNewArgs, NEWISP_SR);
  406. else if (gpWizardState->cmnStateData.dwFlags & ICW_CFGFLAG_SMARTREBOOT_AUTOCONFIG)
  407. lstrcat(pszNewArgs, AUTO_SR);
  408. else if (gpWizardState->cmnStateData.dwFlags & ICW_CFGFLAG_SMARTREBOOT_MANUAL)
  409. lstrcat(pszNewArgs, MANUAL_SR);
  410. else if (gpWizardState->cmnStateData.dwFlags & ICW_CFGFLAG_SMARTREBOOT_LAN)
  411. lstrcat(pszNewArgs, LAN_SR);
  412. }
  413. if (FALSE == SetStartUpCommand(lpRunOnceCmd, (pszNewArgs ? pszNewArgs : g_pszCmdLine)))
  414. MsgBox(IDS_CANTSAVEKEY,MB_MYERROR);
  415. else
  416. {
  417. if (!FGetSystemShutdownPrivledge() ||
  418. !ExitWindowsEx(uRebootFlags,0))
  419. {
  420. MsgBox(IDS_EXITFAILED, MB_MYERROR);
  421. }
  422. }
  423. if(pszNewArgs)
  424. free(pszNewArgs);
  425. }
  426. return TRUE;
  427. }