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.

524 lines
15 KiB

  1. //--------------------------------------------------------------
  2. //
  3. // File: common
  4. //
  5. // Contents: Functions shared between ScanState and LoadState.
  6. //
  7. //---------------------------------------------------------------
  8. #include <common.hxx>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <errno.h>
  12. #include <io.h>
  13. #include <malloc.h>
  14. #include <objerror.h>
  15. #include <stdlib.h>
  16. //---------------------------------------------------------------
  17. // Constants.
  18. const DWORD LINEBUFSIZE = 1024;
  19. //---------------------------------------------------------------
  20. // Types.
  21. typedef struct
  22. {
  23. TOKEN_PRIVILEGES tp;
  24. LUID_AND_ATTRIBUTES luid2;
  25. } TOKEN_PRIVILEGES2;
  26. //---------------------------------------------------------------
  27. // Globals.
  28. HANDLE Console = INVALID_HANDLE_VALUE;
  29. BOOL CopyFiles = TRUE;
  30. BOOL CopySystem = TRUE;
  31. BOOL CopyUser = TRUE;
  32. HKEY CurrentUser = NULL;
  33. BOOL DebugOutput = FALSE;
  34. BOOL ExcludeByDefault = TRUE;
  35. HINF InputInf = INVALID_HANDLE_VALUE;
  36. HANDLE LogFile = INVALID_HANDLE_VALUE;
  37. BOOL OutputAnsi = FALSE;
  38. HANDLE OutputFile = INVALID_HANDLE_VALUE;
  39. char *MigrationPath = NULL;
  40. WCHAR wcsMigrationPath[MAX_PATH + 1];
  41. BOOL ReallyCopyFiles = TRUE;
  42. BOOL SchedSystem = TRUE;
  43. HANDLE STDERR = INVALID_HANDLE_VALUE;
  44. BOOL TestMode = FALSE;
  45. BOOL UserPortion = FALSE;
  46. BOOL Verbose = FALSE;
  47. BOOL VerboseReg = FALSE;
  48. BOOL Win9x = TRUE;
  49. MRtlConvertSidToUnicodeString GRtlConvertSidToUnicodeString = NULL;
  50. MRtlInitUnicodeString GRtlInitUnicodeString = NULL;
  51. MRtlFreeUnicodeString GRtlFreeUnicodeString = NULL;
  52. MDuplicateTokenEx GDuplicateTokenEx = NULL;
  53. //---------------------------------------------------------------
  54. DWORD OpenFiles()
  55. {
  56. DWORD result = ERROR_SUCCESS;
  57. // Open the console.
  58. Console = CreateFileA( "CONOUT$", GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
  59. 0, NULL );
  60. if (Console == INVALID_HANDLE_VALUE)
  61. {
  62. result = GetLastError();
  63. goto cleanup;
  64. }
  65. STDERR = GetStdHandle(STD_ERROR_HANDLE);
  66. cleanup:
  67. return result;
  68. }
  69. //---------------------------------------------------------------
  70. void CloseFiles()
  71. {
  72. // Don't close Console.
  73. if (InputInf != INVALID_HANDLE_VALUE)
  74. SetupCloseInfFile( InputInf );
  75. if (LogFile != INVALID_HANDLE_VALUE)
  76. CloseHandle( LogFile );
  77. if (OutputFile != INVALID_HANDLE_VALUE)
  78. CloseHandle( OutputFile );
  79. }
  80. //---------------------------------------------------------------
  81. DWORD EnableBackupPrivilege()
  82. {
  83. HANDLE process = NULL;
  84. HANDLE process2 = NULL;
  85. TOKEN_PRIVILEGES2 tp;
  86. LUID backup;
  87. LUID restore;
  88. BOOL success;
  89. DWORD result = ERROR_SUCCESS;
  90. // Do nothing on Win9x.
  91. if (Win9x)
  92. return ERROR_SUCCESS;
  93. result = NtImports();
  94. LOG_ASSERT( result );
  95. // Get the process token
  96. success = OpenProcessToken( GetCurrentProcess(),
  97. TOKEN_DUPLICATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  98. &process );
  99. LOG_ASSERT_GLE( success, result );
  100. // Convert it into an impersonation token.
  101. success = GDuplicateTokenEx( process,
  102. MAXIMUM_ALLOWED,
  103. NULL, SecurityImpersonation, TokenImpersonation,
  104. &process2 );
  105. LOG_ASSERT_GLE( success, result );
  106. // Get LUID for backup privilege.
  107. success = LookupPrivilegeValue(
  108. NULL, // lookup privilege on local system
  109. SE_BACKUP_NAME,
  110. &backup );
  111. LOG_ASSERT_GLE( success, result );
  112. // Get LUID for restore privilege.
  113. success = LookupPrivilegeValue(
  114. NULL, // lookup privilege on local system
  115. SE_RESTORE_NAME,
  116. &restore );
  117. LOG_ASSERT_GLE( success, result );
  118. // Fill in the token privilege structure.
  119. tp.tp.PrivilegeCount = 2;
  120. tp.tp.Privileges[0].Luid = backup;
  121. tp.tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  122. tp.tp.Privileges[1].Luid = restore;
  123. tp.tp.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
  124. // Enable the privilege or disable all privileges.
  125. success = AdjustTokenPrivileges( process2, FALSE, &tp.tp, 0, NULL, NULL );
  126. LOG_ASSERT_GLE( success, result );
  127. // Save the token on the thread.
  128. success = SetThreadToken( NULL, process2 );
  129. LOG_ASSERT_GLE( success, result );
  130. // Close the token handles.
  131. cleanup:
  132. if (process != NULL)
  133. CloseHandle( process );
  134. if (process2 != NULL)
  135. CloseHandle( process2 );
  136. return result;
  137. }
  138. //---------------------------------------------------------------
  139. DWORD MakeUnicode( char *buffer, WCHAR **wbuffer )
  140. {
  141. DWORD len;
  142. DWORD wlen;
  143. // Allocate a buffer to hold the unicode string.
  144. len = strlen( buffer ) + 1;
  145. wlen = MultiByteToWideChar( CP_ACP, 0, buffer, len, NULL, 0 );
  146. *wbuffer = (WCHAR *) malloc( wlen*sizeof(WCHAR) );
  147. if (*wbuffer == NULL)
  148. return ERROR_NOT_ENOUGH_MEMORY;
  149. // Convert the buffer to unicode.
  150. wlen = MultiByteToWideChar( CP_ACP, 0, buffer, len, *wbuffer, wlen );
  151. if (wlen == 0)
  152. return GetLastError();
  153. return ERROR_SUCCESS;
  154. }
  155. //---------------------------------------------------------------
  156. DWORD NtImports()
  157. {
  158. DWORD result = ERROR_SUCCESS;
  159. HINSTANCE ntdll;
  160. HINSTANCE advapi32;
  161. // Do nothing on Win9x.
  162. if (Win9x || GRtlConvertSidToUnicodeString != NULL)
  163. return ERROR_SUCCESS;
  164. // Load ntdll.dll
  165. ntdll = LoadLibraryA( "ntdll.dll" );
  166. if (ntdll == NULL)
  167. {
  168. result = GetLastError();
  169. goto cleanup;
  170. }
  171. // Get the functions
  172. GRtlConvertSidToUnicodeString = (MRtlConvertSidToUnicodeString) GetProcAddress( ntdll, "RtlConvertSidToUnicodeString" );
  173. GRtlInitUnicodeString = (MRtlInitUnicodeString) GetProcAddress( ntdll, "RtlInitUnicodeString" );
  174. GRtlFreeUnicodeString = (MRtlFreeUnicodeString) GetProcAddress( ntdll, "RtlFreeUnicodeString" );
  175. // Make sure all the functions were found.
  176. if ( GRtlConvertSidToUnicodeString == NULL
  177. || GRtlInitUnicodeString == NULL
  178. || GRtlFreeUnicodeString == NULL
  179. )
  180. {
  181. result = GetLastError();
  182. goto cleanup;
  183. }
  184. // Load advapi32.dll
  185. advapi32 = LoadLibraryA( "advapi32.dll" );
  186. if (advapi32 == NULL)
  187. {
  188. result = GetLastError();
  189. goto cleanup;
  190. }
  191. // Get the functions.
  192. GDuplicateTokenEx = (MDuplicateTokenEx) GetProcAddress( advapi32, "DuplicateTokenEx" );
  193. if (GDuplicateTokenEx == NULL)
  194. {
  195. result = GetLastError();
  196. goto cleanup;
  197. }
  198. cleanup:
  199. if (result != ERROR_SUCCESS)
  200. {
  201. GRtlConvertSidToUnicodeString = NULL;
  202. GRtlInitUnicodeString = NULL;
  203. GRtlFreeUnicodeString = NULL;
  204. GDuplicateTokenEx = NULL;
  205. }
  206. return result;
  207. }
  208. //---------------------------------------------------------------
  209. DWORD OpenInf( char *file )
  210. {
  211. BOOL success;
  212. UINT errorline;
  213. DWORD result = ERROR_SUCCESS;
  214. char *error;
  215. // If there have not been any INF files, open this as the first.
  216. if (InputInf == INVALID_HANDLE_VALUE)
  217. {
  218. InputInf = SetupOpenInfFileA( file, NULL, INF_STYLE_WIN4, &errorline );
  219. success = InputInf != INVALID_HANDLE_VALUE;
  220. }
  221. else
  222. success = SetupOpenAppendInfFileA( file, InputInf, &errorline );
  223. // If the open failed, print a message and exit.
  224. if (!success)
  225. {
  226. result = GetLastError();
  227. Win32PrintfResourceA( Console, IDS_OPEN_INF_ERROR, file );
  228. error = NULL;
  229. FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  230. 0, result,
  231. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  232. (char *)&error, 0, NULL );
  233. if (error != NULL)
  234. {
  235. Win32Printf( Console, error );
  236. LocalFree( error );
  237. }
  238. }
  239. return result;
  240. }
  241. //---------------------------------------------------------------
  242. BOOL PopupError( char *expr, char *file, DWORD line )
  243. {
  244. char szModuleName[128];
  245. char errMessage[128]; // generated error string
  246. DWORD tid = GetCurrentThreadId();
  247. DWORD pid = GetCurrentProcessId();
  248. char *pszModuleName;
  249. // Compute the name of the process.
  250. if (GetModuleFileNameA(NULL, szModuleName, 128))
  251. {
  252. pszModuleName = strrchr(szModuleName, '\\');
  253. if (!pszModuleName)
  254. {
  255. pszModuleName = szModuleName;
  256. }
  257. else
  258. {
  259. pszModuleName++;
  260. }
  261. }
  262. else
  263. {
  264. pszModuleName = "Unknown";
  265. }
  266. // Compute a title for the popup.
  267. wsprintfA(errMessage,"Process: %s File: %s line %u, thread id %d.%d",
  268. pszModuleName, file, line, pid, tid);
  269. // Return the result of the message bux.
  270. return MessageBoxA( NULL, expr, errMessage,
  271. MB_SETFOREGROUND | MB_TASKMODAL | MB_ICONEXCLAMATION |
  272. MB_OKCANCEL );
  273. }
  274. //---------------------------------------------------------------
  275. void PrintHelp( BOOL scan )
  276. {
  277. Win32PrintfResourceA( Console, IDS_WHAT );
  278. Win32PrintfResourceA( Console, scan ? IDS_CMD1S : IDS_CMD1L );
  279. Win32PrintfResourceA( Console, IDS_CMD2 );
  280. Win32PrintfResourceA( Console, IDS_CMD_I );
  281. Win32PrintfResourceA( Console, IDS_CMD_L );
  282. Win32PrintfResourceA( Console, IDS_CMD_V );
  283. if ( Verbose | VerboseReg | DebugOutput )
  284. Win32PrintfResourceA( Console, IDS_CMD_V_BITS );
  285. Win32PrintfResourceA( Console, IDS_CMD_X );
  286. Win32PrintfResourceA( Console, IDS_CMD_U );
  287. Win32PrintfResourceA( Console, IDS_CMD_F );
  288. Win32PrintfResourceA( Console, IDS_CMD_PATH );
  289. }
  290. //---------------------------------------------------------------
  291. // This function converts a Win32 result into a resource id.
  292. DWORD ResultToRC( DWORD result )
  293. {
  294. if (result == ERROR_WRITE_FAULT)
  295. return IDS_WRITE_FAULT;
  296. else if (result == ERROR_NOT_ENOUGH_MEMORY)
  297. return IDS_NOT_ENOUGH_MEMORY;
  298. else if (result == ERROR_ACCESS_DENIED ||
  299. result == ERROR_PRIVILEGE_NOT_HELD)
  300. return IDS_MUST_BE_ADMIN;
  301. else if (result == SPAPI_E_SECTION_NOT_FOUND)
  302. return IDS_SECTION_NOT_FOUND;
  303. else
  304. return IDS_FAILED;
  305. }
  306. //---------------------------------------------------------------
  307. // This function prints from a resource string as a format string
  308. // to a unicode win32 file handle. It is not thread safe.
  309. // %s in a format string means a ascii parameter.
  310. DWORD Win32PrintfResourceA( HANDLE file, DWORD resource_id, ... )
  311. {
  312. BOOL success;
  313. DWORD len;
  314. va_list va;
  315. char *buffer = NULL;
  316. DWORD written;
  317. DWORD wlen;
  318. WCHAR *wbuffer = NULL;
  319. DWORD result = ERROR_SUCCESS;
  320. CHAR PrintBuffer[LINEBUFSIZE];
  321. // Try to load the string.
  322. len = LoadStringA( NULL, resource_id, PrintBuffer, LINEBUFSIZE );
  323. DEBUG_ASSERT( len != 0 && len < LINEBUFSIZE );
  324. // Format the message.
  325. va_start( va, resource_id );
  326. success = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  327. PrintBuffer, 0,
  328. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  329. (char *) &buffer, 0, &va );
  330. va_end( va );
  331. DEBUG_ASSERT( success );
  332. if (!success)
  333. {
  334. result = GetLastError();
  335. goto cleanup;
  336. }
  337. // When printing to the console or logfile use ascii.
  338. // When printing to the migration file use Unicode.
  339. len = strlen(buffer);
  340. if (file != OutputFile)
  341. {
  342. wbuffer = (WCHAR *) buffer;
  343. wlen = len;
  344. }
  345. else
  346. {
  347. // Allocate a buffer to hold the unicode string.
  348. wlen = MultiByteToWideChar( CP_ACP, 0, buffer, len, NULL, 0 );
  349. wbuffer = (WCHAR *) _alloca( wlen*sizeof(WCHAR) );
  350. if (wbuffer == NULL)
  351. {
  352. result = ERROR_NOT_ENOUGH_MEMORY;
  353. goto cleanup;
  354. }
  355. // Convert the buffer to unicode.
  356. wlen = MultiByteToWideChar( CP_ACP, 0, buffer, len, wbuffer, wlen );
  357. if (wlen == 0)
  358. {
  359. result = GetLastError();
  360. goto cleanup;
  361. }
  362. wlen *= sizeof(WCHAR);
  363. }
  364. // Write the unicode string.
  365. success = WriteFile( file, wbuffer, wlen, &written, NULL );
  366. if (!success || wlen != written)
  367. {
  368. result = GetLastError();
  369. goto cleanup;
  370. }
  371. if (file == STDERR)
  372. {
  373. //Also write to the log file for these
  374. success = WriteFile( LogFile, wbuffer, wlen, &written, NULL );
  375. if (!success || wlen != written)
  376. {
  377. result = GetLastError();
  378. goto cleanup;
  379. }
  380. }
  381. cleanup:
  382. if (buffer != NULL)
  383. LocalFree( buffer );
  384. return result;
  385. }
  386. //---------------------------------------------------------------
  387. // This function prints from a resource string as a format string
  388. // to a unicode win32 file handle. It is not thread safe.
  389. // %s in a format string means a unicode parameter.
  390. DWORD Win32PrintfResourceW( HANDLE file, DWORD resource_id, ... )
  391. {
  392. BOOL success;
  393. DWORD len;
  394. va_list va;
  395. CHAR *buffer = NULL;
  396. DWORD written;
  397. DWORD wlen;
  398. WCHAR *wbuffer = NULL;
  399. DWORD result = ERROR_SUCCESS;
  400. WCHAR PrintBuffer[LINEBUFSIZE];
  401. // Try to load the string.
  402. wlen = LoadStringW( NULL, resource_id, PrintBuffer, LINEBUFSIZE );
  403. DEBUG_ASSERT( wlen != 0 && wlen < LINEBUFSIZE );
  404. // Format the message.
  405. va_start( va, resource_id );
  406. success = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  407. PrintBuffer, 0,
  408. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  409. (WCHAR *) &wbuffer, 0, &va );
  410. va_end( va );
  411. DEBUG_ASSERT( success && "The resource ids are probably wrong, try doing a clean compile" );
  412. if (!success)
  413. {
  414. result = GetLastError();
  415. goto cleanup;
  416. }
  417. // When printing to the console or logfile use ascii.
  418. // When printing to the migration file use Unicode.
  419. wlen = wcslen(wbuffer);
  420. if (file == OutputFile)
  421. {
  422. buffer = (CHAR *) wbuffer;
  423. len = wlen * sizeof(WCHAR);
  424. }
  425. else
  426. {
  427. // Allocate a buffer to hold the ascii string.
  428. len = WideCharToMultiByte( CP_ACP, 0, wbuffer, wlen, NULL, 0, NULL, NULL );
  429. buffer = (CHAR *) _alloca( len );
  430. if (buffer == NULL)
  431. {
  432. result = ERROR_NOT_ENOUGH_MEMORY;
  433. goto cleanup;
  434. }
  435. // Convert the buffer to unicode.
  436. len = WideCharToMultiByte( CP_ACP, 0, wbuffer, wlen, buffer, len, NULL, NULL );
  437. if (len == 0)
  438. {
  439. result = GetLastError();
  440. goto cleanup;
  441. }
  442. }
  443. // Write the unicode string.
  444. success = WriteFile( file, buffer, len, &written, NULL );
  445. if (!success || len != written)
  446. {
  447. result = GetLastError();
  448. goto cleanup;
  449. }
  450. if (file == STDERR)
  451. {
  452. //Also write to the log file for these
  453. success = WriteFile( LogFile, wbuffer, wlen, &written, NULL );
  454. if (!success || wlen != written)
  455. {
  456. result = GetLastError();
  457. goto cleanup;
  458. }
  459. }
  460. cleanup:
  461. if (wbuffer != NULL)
  462. LocalFree( wbuffer );
  463. return result;
  464. }