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.

399 lines
11 KiB

  1. /******************************************************************************
  2. *
  3. * CPROFILE.C
  4. *
  5. * Text based utility to clean user profiles. This utility will remove user
  6. * file associations if they are disabled for the system and re-write
  7. * the user profile truncating unused space.
  8. *
  9. * Copyright Citrix Systems Inc. 1995
  10. * Copyright (c) 1998-1999 Microsoft Corporation
  11. *
  12. * Author: Brad Anderson 01/20/97
  13. *
  14. * $Log: U:\NT\PRIVATE\UTILS\citrix\cprofile\VCS\cprofile.c $
  15. *
  16. * Rev 1.7 May 04 1998 18:06:14 bills
  17. * Fixes for MS bug #2109, OEM->ANSI conversion and moving strings to the rc file.
  18. *
  19. * Rev 1.6 Feb 09 1998 19:37:00 yufengz
  20. * change user profile from directory to file
  21. *
  22. * Rev 1.5 09 Oct 1997 19:04:14 scottn
  23. * Make help like MS.
  24. *
  25. * Rev 1.4 Jun 26 1997 18:18:32 billm
  26. * move to WF40 tree
  27. *
  28. * Rev 1.3 23 Jun 1997 16:13:18 butchd
  29. * update
  30. *
  31. * Rev 1.2 19 Feb 1997 15:55:32 BradA
  32. * Allow only administrators to run CPROFILE
  33. *
  34. * Rev 1.1 28 Jan 1997 20:06:28 BradA
  35. * Fixed up some problems related to WF 2.0 changes
  36. *
  37. * Rev 1.0 27 Jan 1997 20:37:46 BradA
  38. * Initial Versions
  39. *
  40. * Rev 1.0 27 Jan 1997 20:02:46 BradA
  41. * Initial Version
  42. *
  43. * Rev 1.0 Jan 27 1997 19:51:12 KenB
  44. * Initial version
  45. *
  46. *
  47. *******************************************************************************/
  48. #include "precomp.h"
  49. #pragma hdrstop
  50. #include <ntddkbd.h>
  51. #include <winstaw.h>
  52. #include <syslib.h>
  53. #include <assert.h>
  54. #include <time.h>
  55. #include <utilsub.h>
  56. #include <utildll.h>
  57. #include <string.h>
  58. #include <malloc.h>
  59. #include <locale.h>
  60. #include "cprofile.h"
  61. #include <printfoa.h>
  62. #define REG_PROFILELIST \
  63. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"
  64. #define USER_PROFILE L"NTUSER.DAT"
  65. FILELIST Files;
  66. int LocalProfiles_flag = FALSE;
  67. int Verbose_flag = FALSE;
  68. int Query_flag;
  69. int Help_flag = FALSE;
  70. TOKMAP ptm[] = {
  71. {L"/L", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &LocalProfiles_flag},
  72. {L"/V", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Verbose_flag},
  73. {L"/I", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Query_flag},
  74. {L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Help_flag},
  75. {L"/H", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Help_flag},
  76. {L" ", TMFLAG_OPTIONAL, TMFORM_FILES, sizeof(Files), &Files},
  77. {0, 0, 0, 0, 0}
  78. };
  79. #define INPUT_CONT 0
  80. #define INPUT_SKIP 1
  81. #define INPUT_QUIT 2
  82. int QueryUserInput();
  83. int ProcessFile( PWCHAR pFile );
  84. void Usage( BOOL ErrorOccured );
  85. /*******************************************************************************
  86. *
  87. * main
  88. *
  89. ******************************************************************************/
  90. int __cdecl
  91. main(INT argc, CHAR **argv)
  92. {
  93. WCHAR *CmdLine;
  94. WCHAR **argvW;
  95. ULONG rc;
  96. int i;
  97. BOOL Result;
  98. HANDLE hWin;
  99. int CurFile;
  100. int Abort_flag;
  101. setlocale(LC_ALL, ".OCP");
  102. /*
  103. * Massage the command line.
  104. */
  105. argvW = MassageCommandLine((DWORD)argc);
  106. if (argvW == NULL) {
  107. ErrorPrintf(IDS_ERROR_MALLOC);
  108. return(FAILURE);
  109. }
  110. /*
  111. * parse the cmd line without parsing the program name (argc-1, argv+1)
  112. */
  113. rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
  114. /*
  115. * Check for error from ParseCommandLine
  116. */
  117. if ( Help_flag || (rc & ~PARSE_FLAG_NO_PARMS) ||
  118. (!LocalProfiles_flag && (Files.argc == 0)) ) {
  119. if ( !Help_flag ) {
  120. Usage(TRUE);
  121. return(FAILURE);
  122. }
  123. else {
  124. Usage(FALSE);
  125. return(SUCCESS);
  126. }
  127. }
  128. if (!TestUserForAdmin(FALSE)) {
  129. ErrorPrintf(IDS_ERROR_NOT_ADMIN);
  130. return(FAILURE);
  131. }
  132. InitializeGlobalSids();
  133. /*
  134. * Verify if the user has the privilege to save the profile i.e.
  135. * SeBackupPrivilege
  136. */
  137. if (!EnablePrivilege(SE_BACKUP_PRIVILEGE, TRUE) ||
  138. !EnablePrivilege(SE_RESTORE_PRIVILEGE, TRUE)) {
  139. ErrorPrintf(IDS_ERROR_PRIVILEGE_NOT_AVAILABLE);
  140. return(FAILURE);
  141. }
  142. CurFile = 0;
  143. Abort_flag = FALSE;
  144. while ( !Abort_flag && Files.argc && (CurFile < Files.argc) ) {
  145. if ( ProcessFile(Files.argv[CurFile]) ) {
  146. Abort_flag = TRUE;
  147. break;
  148. }
  149. CurFile++;
  150. }
  151. if ( !Abort_flag && LocalProfiles_flag ) {
  152. // Enumerate local profiles
  153. LONG Status;
  154. HKEY hkeyProfileList;
  155. DWORD indx = 0;
  156. WCHAR wSubKeyName[MAX_PATH+sizeof(WCHAR)];
  157. DWORD Size;
  158. Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  159. REG_PROFILELIST,
  160. 0,
  161. KEY_READ,
  162. &hkeyProfileList);
  163. if ( Status != ERROR_SUCCESS ) {
  164. ErrorPrintf(IDS_ERROR_MISSING_PROFILE_LIST);
  165. Abort_flag = TRUE;
  166. hkeyProfileList = 0;
  167. }
  168. while ( !Abort_flag && (Status == ERROR_SUCCESS) ) {
  169. LONG Status2;
  170. Size = sizeof(wSubKeyName)/sizeof( WCHAR );
  171. Status = RegEnumKeyEx(hkeyProfileList,
  172. indx++,
  173. wSubKeyName,
  174. &Size,
  175. 0,
  176. NULL,
  177. NULL,
  178. NULL );
  179. if ( Status == ERROR_SUCCESS ) {
  180. HKEY hkeyProfile;
  181. Status2 = RegOpenKeyEx(hkeyProfileList,
  182. wSubKeyName,
  183. 0,
  184. KEY_READ,
  185. &hkeyProfile);
  186. if ( Status2 == ERROR_SUCCESS ) {
  187. DWORD type;
  188. WCHAR file[MAX_PATH], expandedFile[MAX_PATH];
  189. DWORD filelen = sizeof(file);
  190. Status2 = RegQueryValueExW(hkeyProfile,
  191. L"ProfileImagePath",
  192. 0,
  193. &type,
  194. (PBYTE)file,
  195. &filelen );
  196. if ( Status2 == ERROR_SUCCESS ) {
  197. if ( ExpandEnvironmentStrings(file, expandedFile,
  198. MAX_PATH) > 0) {
  199. //
  200. // Append the User Profile file "NTUSER.DAT"
  201. // to the end of the profile path.
  202. // Added by Yufeng Zheng
  203. //
  204. PWCHAR c;
  205. //
  206. // Find the trailing backslash '\' and
  207. // handle the appending according to the backslash.
  208. //
  209. if ((c = wcsrchr(expandedFile, L'\\')) == NULL) {
  210. wcscat(expandedFile, L"\\");
  211. wcscat(expandedFile, USER_PROFILE);
  212. }
  213. else if (c[1] == L'\0') {
  214. wcscat(expandedFile, USER_PROFILE);
  215. }
  216. else {
  217. wcscat(expandedFile, L"\\");
  218. wcscat(expandedFile, USER_PROFILE);
  219. }
  220. if ( ProcessFile(expandedFile) ) {
  221. Abort_flag = TRUE;
  222. }
  223. }
  224. }
  225. else {
  226. StringErrorPrintf(IDS_ERROR_MISSING_LPROFILE, wSubKeyName);
  227. }
  228. RegCloseKey(hkeyProfile);
  229. }
  230. else {
  231. StringErrorPrintf(IDS_ERROR_BAD_LPROFILE, wSubKeyName);
  232. }
  233. }
  234. }
  235. if ( hkeyProfileList ) {
  236. RegCloseKey(hkeyProfileList);
  237. }
  238. }
  239. return( Abort_flag );
  240. }
  241. /****************************************************************************
  242. *
  243. * ProcessFile( PWCHAR pFile )
  244. * Read the specified profile, eliminate the Software\Classes registry
  245. * key if Classes are disabled, and resave the profile such that it
  246. * is truncated.
  247. *
  248. * Arguments:
  249. * pFile Filename to process
  250. *
  251. * Returns:
  252. * FALSE If completed successfully
  253. * TRUE If there was an error, and the program should terminate.
  254. *
  255. ****************************************************************************/
  256. int
  257. ProcessFile( PWCHAR pFile )
  258. {
  259. PSID pUserSid;
  260. WCHAR tempbuf[100];
  261. int UserInput = INPUT_CONT;
  262. if ( Verbose_flag || Query_flag ) {
  263. StringMessage(IDS_MSG_PROCESSING, pFile );
  264. }
  265. if ( Query_flag ) {
  266. UserInput = QueryUserInput();
  267. }
  268. if ( UserInput == INPUT_CONT ) {
  269. if ( OpenUserProfile(pFile, &pUserSid) ) {
  270. ClearDisabledClasses();
  271. if ( ! SaveUserProfile(pUserSid, pFile) ) {
  272. StringErrorPrintf(IDS_ERROR_SAVING_PROFILE, pFile);
  273. }
  274. ClearTempUserProfile();
  275. }
  276. else {
  277. StringErrorPrintf(IDS_ERROR_OPENING_PROFILE, pFile);
  278. }
  279. }
  280. return ( UserInput == INPUT_QUIT );
  281. }
  282. int
  283. QueryUserInput()
  284. {
  285. WCHAR c, firstc;
  286. int Valid_flag = FALSE;
  287. int rc = INPUT_CONT;
  288. static int FirstTime = TRUE;
  289. static WCHAR yes[10], no[10], quit[10];
  290. if (FirstTime)
  291. {
  292. BOOLEAN error = FALSE;
  293. if ( !LoadString(NULL, IDS_UI_NO_CHAR, no, 2) ) {
  294. error = TRUE;
  295. }
  296. if ( !LoadString(NULL, IDS_UI_YES_CHAR, yes, 2) ) {
  297. error = TRUE;
  298. }
  299. if ( !LoadString(NULL, IDS_UI_QUIT_CHAR, quit, 2) ) {
  300. error = TRUE;
  301. }
  302. if ( error ) {
  303. ErrorPrintf(IDS_ERROR_MISSING_RESOURCES);
  304. return ( INPUT_QUIT );
  305. }
  306. FirstTime = FALSE;
  307. }
  308. fflush(stdin);
  309. Message(IDS_MSG_MODIFY_PROMPT);
  310. do {
  311. firstc = L'\0';
  312. while ( ((c = getwchar()) != L'\n') && (c != EOF) ) {
  313. if ( !firstc && !iswspace(c)) {
  314. firstc = c;
  315. }
  316. }
  317. if ( _wcsnicmp(yes, &firstc, 1) == 0 )
  318. {
  319. Valid_flag = TRUE;
  320. }
  321. else if ( _wcsnicmp(quit, &firstc, 1) == 0 ) {
  322. Valid_flag = TRUE;
  323. rc = INPUT_QUIT;
  324. }
  325. else if ( (_wcsnicmp(no, &firstc, 1) == 0) || (firstc == '\0') ) {
  326. rc = INPUT_SKIP;
  327. Valid_flag = TRUE;
  328. }
  329. else {
  330. ErrorPrintf(IDS_ERROR_INVALID_USER_RESP);
  331. }
  332. } while ( ! Valid_flag );
  333. return ( rc );
  334. }
  335. void Usage ( BOOL ErrorOccurred )
  336. {
  337. if ( ErrorOccurred ) {
  338. ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
  339. ErrorPrintf(IDS_USAGE_CMDLINE);
  340. } else {
  341. Message(IDS_USAGE_DESCR1);
  342. Message(IDS_USAGE_CMDLINE);
  343. Message(IDS_USAGE_DESCR2);
  344. Message(IDS_USAGE_OPTION_LIST);
  345. Message(IDS_USAGE_LOPTION);
  346. Message(IDS_USAGE_IOPTION);
  347. Message(IDS_USAGE_VOPTION);
  348. Message(IDS_USAGE_HOPTION);
  349. }
  350. }