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.

414 lines
12 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 <winnlsp.h>
  61. #include "cprofile.h"
  62. #include <printfoa.h>
  63. #define REG_PROFILELIST \
  64. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"
  65. #define USER_PROFILE L"NTUSER.DAT"
  66. FILELIST Files;
  67. int LocalProfiles_flag = FALSE;
  68. int Verbose_flag = FALSE;
  69. int Query_flag;
  70. int Help_flag = FALSE;
  71. TOKMAP ptm[] = {
  72. {L"/L", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &LocalProfiles_flag},
  73. {L"/V", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Verbose_flag},
  74. {L"/I", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Query_flag},
  75. {L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Help_flag},
  76. {L"/H", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &Help_flag},
  77. {L" ", TMFLAG_OPTIONAL, TMFORM_FILES, sizeof(Files), &Files},
  78. {0, 0, 0, 0, 0}
  79. };
  80. #define INPUT_CONT 0
  81. #define INPUT_SKIP 1
  82. #define INPUT_QUIT 2
  83. int QueryUserInput();
  84. int ProcessFile( PWCHAR pFile );
  85. void Usage( BOOL ErrorOccured );
  86. // max length of the locale string
  87. #define MAX_LOCALE_STRING 64
  88. /*******************************************************************************
  89. *
  90. * main
  91. *
  92. ******************************************************************************/
  93. int __cdecl
  94. main(INT argc, CHAR **argv)
  95. {
  96. WCHAR *CmdLine;
  97. WCHAR **argvW;
  98. ULONG rc;
  99. int i;
  100. BOOL Result;
  101. HANDLE hWin;
  102. int CurFile;
  103. int Abort_flag;
  104. WCHAR wszString[MAX_LOCALE_STRING + 1];
  105. setlocale(LC_ALL, ".OCP");
  106. // We don't want LC_CTYPE set the same as the others or else we will see
  107. // garbage output in the localized version, so we need to explicitly
  108. // set it to correct console output code page
  109. _snwprintf(wszString, sizeof(wszString)/sizeof(WCHAR), L".%d", GetConsoleOutputCP());
  110. wszString[sizeof(wszString)/sizeof(WCHAR) - 1] = L'\0';
  111. _wsetlocale(LC_CTYPE, wszString);
  112. SetThreadUILanguage(0);
  113. /*
  114. * Massage the command line.
  115. */
  116. argvW = MassageCommandLine((DWORD)argc);
  117. if (argvW == NULL) {
  118. ErrorPrintf(IDS_ERROR_MALLOC);
  119. return(FAILURE);
  120. }
  121. /*
  122. * parse the cmd line without parsing the program name (argc-1, argv+1)
  123. */
  124. rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
  125. /*
  126. * Check for error from ParseCommandLine
  127. */
  128. if ( Help_flag || (rc & ~PARSE_FLAG_NO_PARMS) ||
  129. (!LocalProfiles_flag && (Files.argc == 0)) ) {
  130. if ( !Help_flag ) {
  131. Usage(TRUE);
  132. return(FAILURE);
  133. }
  134. else {
  135. Usage(FALSE);
  136. return(SUCCESS);
  137. }
  138. }
  139. if (!TestUserForAdmin(FALSE)) {
  140. ErrorPrintf(IDS_ERROR_NOT_ADMIN);
  141. return(FAILURE);
  142. }
  143. InitializeGlobalSids();
  144. /*
  145. * Verify if the user has the privilege to save the profile i.e.
  146. * SeBackupPrivilege
  147. */
  148. if (!EnablePrivilege(SE_BACKUP_PRIVILEGE, TRUE) ||
  149. !EnablePrivilege(SE_RESTORE_PRIVILEGE, TRUE)) {
  150. ErrorPrintf(IDS_ERROR_PRIVILEGE_NOT_AVAILABLE);
  151. return(FAILURE);
  152. }
  153. CurFile = 0;
  154. Abort_flag = FALSE;
  155. while ( !Abort_flag && Files.argc && (CurFile < Files.argc) ) {
  156. if ( ProcessFile(Files.argv[CurFile]) ) {
  157. Abort_flag = TRUE;
  158. break;
  159. }
  160. CurFile++;
  161. }
  162. if ( !Abort_flag && LocalProfiles_flag ) {
  163. // Enumerate local profiles
  164. LONG Status;
  165. HKEY hkeyProfileList;
  166. DWORD indx = 0;
  167. WCHAR wSubKeyName[MAX_PATH+sizeof(WCHAR)];
  168. DWORD Size;
  169. Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  170. REG_PROFILELIST,
  171. 0,
  172. KEY_READ,
  173. &hkeyProfileList);
  174. if ( Status != ERROR_SUCCESS ) {
  175. ErrorPrintf(IDS_ERROR_MISSING_PROFILE_LIST);
  176. Abort_flag = TRUE;
  177. hkeyProfileList = 0;
  178. }
  179. while ( !Abort_flag && (Status == ERROR_SUCCESS) ) {
  180. LONG Status2;
  181. Size = sizeof(wSubKeyName)/sizeof( WCHAR );
  182. Status = RegEnumKeyEx(hkeyProfileList,
  183. indx++,
  184. wSubKeyName,
  185. &Size,
  186. 0,
  187. NULL,
  188. NULL,
  189. NULL );
  190. if ( Status == ERROR_SUCCESS ) {
  191. HKEY hkeyProfile;
  192. Status2 = RegOpenKeyEx(hkeyProfileList,
  193. wSubKeyName,
  194. 0,
  195. KEY_READ,
  196. &hkeyProfile);
  197. if ( Status2 == ERROR_SUCCESS ) {
  198. DWORD type;
  199. WCHAR file[MAX_PATH], expandedFile[MAX_PATH];
  200. DWORD filelen = sizeof(file);
  201. Status2 = RegQueryValueExW(hkeyProfile,
  202. L"ProfileImagePath",
  203. 0,
  204. &type,
  205. (PBYTE)file,
  206. &filelen );
  207. if ( Status2 == ERROR_SUCCESS ) {
  208. if ( ExpandEnvironmentStrings(file, expandedFile,
  209. MAX_PATH) > 0) {
  210. //
  211. // Append the User Profile file "NTUSER.DAT"
  212. // to the end of the profile path.
  213. // Added by Yufeng Zheng
  214. //
  215. PWCHAR c;
  216. //
  217. // Find the trailing backslash '\' and
  218. // handle the appending according to the backslash.
  219. //
  220. if ((c = wcsrchr(expandedFile, L'\\')) == NULL) {
  221. wcscat(expandedFile, L"\\");
  222. wcscat(expandedFile, USER_PROFILE);
  223. }
  224. else if (c[1] == L'\0') {
  225. wcscat(expandedFile, USER_PROFILE);
  226. }
  227. else {
  228. wcscat(expandedFile, L"\\");
  229. wcscat(expandedFile, USER_PROFILE);
  230. }
  231. if ( ProcessFile(expandedFile) ) {
  232. Abort_flag = TRUE;
  233. }
  234. }
  235. }
  236. else {
  237. StringErrorPrintf(IDS_ERROR_MISSING_LPROFILE, wSubKeyName);
  238. }
  239. RegCloseKey(hkeyProfile);
  240. }
  241. else {
  242. StringErrorPrintf(IDS_ERROR_BAD_LPROFILE, wSubKeyName);
  243. }
  244. }
  245. }
  246. if ( hkeyProfileList ) {
  247. RegCloseKey(hkeyProfileList);
  248. }
  249. }
  250. return( Abort_flag );
  251. }
  252. /****************************************************************************
  253. *
  254. * ProcessFile( PWCHAR pFile )
  255. * Read the specified profile, eliminate the Software\Classes registry
  256. * key if Classes are disabled, and resave the profile such that it
  257. * is truncated.
  258. *
  259. * Arguments:
  260. * pFile Filename to process
  261. *
  262. * Returns:
  263. * FALSE If completed successfully
  264. * TRUE If there was an error, and the program should terminate.
  265. *
  266. ****************************************************************************/
  267. int
  268. ProcessFile( PWCHAR pFile )
  269. {
  270. PSID pUserSid;
  271. WCHAR tempbuf[100];
  272. int UserInput = INPUT_CONT;
  273. if ( Verbose_flag || Query_flag ) {
  274. StringMessage(IDS_MSG_PROCESSING, pFile );
  275. }
  276. if ( Query_flag ) {
  277. UserInput = QueryUserInput();
  278. }
  279. if ( UserInput == INPUT_CONT ) {
  280. if ( OpenUserProfile(pFile, &pUserSid) ) {
  281. ClearDisabledClasses();
  282. if ( ! SaveUserProfile(pUserSid, pFile) ) {
  283. StringErrorPrintf(IDS_ERROR_SAVING_PROFILE, pFile);
  284. }
  285. ClearTempUserProfile();
  286. }
  287. else {
  288. StringErrorPrintf(IDS_ERROR_OPENING_PROFILE, pFile);
  289. }
  290. }
  291. return ( UserInput == INPUT_QUIT );
  292. }
  293. int
  294. QueryUserInput()
  295. {
  296. WCHAR c, firstc;
  297. int Valid_flag = FALSE;
  298. int rc = INPUT_CONT;
  299. static int FirstTime = TRUE;
  300. static WCHAR yes[10], no[10], quit[10];
  301. if (FirstTime)
  302. {
  303. BOOLEAN error = FALSE;
  304. if ( !LoadString(NULL, IDS_UI_NO_CHAR, no, 2) ) {
  305. error = TRUE;
  306. }
  307. if ( !LoadString(NULL, IDS_UI_YES_CHAR, yes, 2) ) {
  308. error = TRUE;
  309. }
  310. if ( !LoadString(NULL, IDS_UI_QUIT_CHAR, quit, 2) ) {
  311. error = TRUE;
  312. }
  313. if ( error ) {
  314. ErrorPrintf(IDS_ERROR_MISSING_RESOURCES);
  315. return ( INPUT_QUIT );
  316. }
  317. FirstTime = FALSE;
  318. }
  319. fflush(stdin);
  320. Message(IDS_MSG_MODIFY_PROMPT);
  321. do {
  322. firstc = L'\0';
  323. while ( ((c = getwchar()) != L'\n') && (c != EOF) ) {
  324. if ( !firstc && !iswspace(c)) {
  325. firstc = c;
  326. }
  327. }
  328. if ( _wcsnicmp(yes, &firstc, 1) == 0 )
  329. {
  330. Valid_flag = TRUE;
  331. }
  332. else if ( _wcsnicmp(quit, &firstc, 1) == 0 ) {
  333. Valid_flag = TRUE;
  334. rc = INPUT_QUIT;
  335. }
  336. else if ( (_wcsnicmp(no, &firstc, 1) == 0) || (firstc == '\0') ) {
  337. rc = INPUT_SKIP;
  338. Valid_flag = TRUE;
  339. }
  340. else {
  341. ErrorPrintf(IDS_ERROR_INVALID_USER_RESP);
  342. }
  343. } while ( ! Valid_flag );
  344. return ( rc );
  345. }
  346. void Usage ( BOOL ErrorOccurred )
  347. {
  348. if ( ErrorOccurred ) {
  349. ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
  350. ErrorPrintf(IDS_USAGE_CMDLINE);
  351. } else {
  352. Message(IDS_USAGE_DESCR1);
  353. Message(IDS_USAGE_CMDLINE);
  354. Message(IDS_USAGE_DESCR2);
  355. Message(IDS_USAGE_OPTION_LIST);
  356. Message(IDS_USAGE_LOPTION);
  357. Message(IDS_USAGE_IOPTION);
  358. Message(IDS_USAGE_VOPTION);
  359. Message(IDS_USAGE_HOPTION);
  360. }
  361. }