372 lines
7.5 KiB
C
372 lines
7.5 KiB
C
#include "pch.h"
|
|
#include "userenvp.h" // needed until API becomes public
|
|
|
|
VOID
|
|
pFixSomeSidReferences (
|
|
PSID ExistingSid,
|
|
PSID NewSid
|
|
);
|
|
|
|
VOID
|
|
PrintMessage (
|
|
IN UINT MsgId,
|
|
IN PCTSTR *ArgArray
|
|
)
|
|
{
|
|
DWORD rc;
|
|
PTSTR MsgBuf;
|
|
|
|
rc = FormatMessageW (
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER|
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY|
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
(LPVOID) GetModuleHandle(NULL),
|
|
(DWORD) MsgId,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPVOID) &MsgBuf,
|
|
0,
|
|
(va_list *) ArgArray
|
|
);
|
|
|
|
if (rc) {
|
|
_tprintf (TEXT("%s"), MsgBuf);
|
|
LocalFree (MsgBuf);
|
|
}
|
|
}
|
|
|
|
|
|
PTSTR
|
|
GetErrorText (
|
|
IN UINT Error
|
|
)
|
|
{
|
|
DWORD rc;
|
|
PTSTR MsgBuf;
|
|
|
|
if (Error == ERROR_NONE_MAPPED) {
|
|
Error = ERROR_NO_SUCH_USER;
|
|
} else if (Error & 0xF0000000) {
|
|
Error = RtlNtStatusToDosError (Error);
|
|
}
|
|
|
|
rc = FormatMessageW (
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER|
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY|
|
|
FORMAT_MESSAGE_FROM_SYSTEM|
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
(DWORD) Error,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPVOID) &MsgBuf,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if (!rc) {
|
|
MsgBuf = NULL;
|
|
}
|
|
|
|
return MsgBuf;
|
|
}
|
|
|
|
|
|
VOID
|
|
HelpAndExit (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// This routine is called whenever command line args are wrong
|
|
//
|
|
|
|
PrintMessage (MSG_HELP, NULL);
|
|
|
|
exit (1);
|
|
}
|
|
|
|
|
|
PSID
|
|
GetSidFromName (
|
|
IN PCTSTR RemoteTo,
|
|
IN PCTSTR Name
|
|
)
|
|
{
|
|
DWORD Size;
|
|
PSID Buffer;
|
|
DWORD DomainSize;
|
|
PTSTR Domain;
|
|
SID_NAME_USE Use;
|
|
BOOL b = FALSE;
|
|
|
|
Size = 1024;
|
|
Buffer = (PSID) LocalAlloc (LPTR, Size);
|
|
if (!Buffer) {
|
|
return NULL;
|
|
}
|
|
|
|
DomainSize = 256;
|
|
Domain = (PTSTR) LocalAlloc (LPTR, DomainSize);
|
|
if (!Domain) {
|
|
LocalFree (Buffer);
|
|
return NULL;
|
|
}
|
|
|
|
b = LookupAccountName (
|
|
RemoteTo,
|
|
Name,
|
|
Buffer,
|
|
&Size,
|
|
Domain,
|
|
&DomainSize,
|
|
&Use
|
|
);
|
|
|
|
if (Size > 1024) {
|
|
LocalFree (Buffer);
|
|
Buffer = (PSID) LocalAlloc (LPTR, Size);
|
|
}
|
|
|
|
if (DomainSize > 256) {
|
|
LocalFree (Domain);
|
|
Domain = (PTSTR) LocalAlloc (LPTR, DomainSize);
|
|
|
|
if (!Domain) {
|
|
if (Buffer) {
|
|
LocalFree (Buffer);
|
|
}
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (Size > 1024 || DomainSize > 256) {
|
|
|
|
b = LookupAccountName (
|
|
RemoteTo,
|
|
Name,
|
|
Buffer,
|
|
&Size,
|
|
Domain,
|
|
&DomainSize,
|
|
&Use
|
|
);
|
|
}
|
|
|
|
LocalFree (Domain);
|
|
|
|
if (!b) {
|
|
if (Buffer) {
|
|
LocalFree (Buffer);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
return Buffer;
|
|
}
|
|
|
|
|
|
PCTSTR
|
|
pSkipUnc (
|
|
PCTSTR Path
|
|
)
|
|
{
|
|
if (Path[0] == TEXT('\\') && Path[1] == TEXT('\\')) {
|
|
return Path + 2;
|
|
}
|
|
|
|
return Path;
|
|
}
|
|
|
|
|
|
INT
|
|
__cdecl
|
|
_tmain (
|
|
INT argc,
|
|
PCTSTR argv[]
|
|
)
|
|
{
|
|
INT i;
|
|
DWORD Size;
|
|
PCTSTR User1 = NULL;
|
|
PCTSTR User2 = NULL;
|
|
TCHAR FixedUser1[MAX_PATH];
|
|
TCHAR FixedUser2[MAX_PATH];
|
|
TCHAR Computer[MAX_PATH];
|
|
BOOL Overwrite = FALSE;
|
|
INT c;
|
|
BOOL b;
|
|
PCTSTR RemoteTo = NULL;
|
|
NTSTATUS Status;
|
|
BYTE WasEnabled;
|
|
DWORD Error;
|
|
PCTSTR ArgArray[3];
|
|
TCHAR RemoteToBuf[MAX_PATH];
|
|
BOOL NoDecoration = FALSE;
|
|
BOOL ReAdjust = FALSE;
|
|
BOOL KeepLocalUser = FALSE;
|
|
DWORD Flags;
|
|
|
|
for (i = 1 ; i < argc ; i++) {
|
|
if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
|
|
|
|
c = _tcsnextc (argv[i] + 1);
|
|
|
|
switch (_totlower ((wint_t) c)) {
|
|
|
|
case TEXT('y'):
|
|
if (Overwrite) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
Overwrite = TRUE;
|
|
break;
|
|
|
|
case TEXT('d'):
|
|
if (NoDecoration) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
NoDecoration = TRUE;
|
|
break;
|
|
|
|
case TEXT('k'):
|
|
if (KeepLocalUser) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
KeepLocalUser = TRUE;
|
|
break;
|
|
|
|
case TEXT('c'):
|
|
if (RemoteTo) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
if (argv[i][2] == TEXT(':')) {
|
|
RemoteTo = &argv[i][3];
|
|
} else if ((i + 1) < argc) {
|
|
i++;
|
|
RemoteTo = argv[i];
|
|
} else {
|
|
HelpAndExit();
|
|
}
|
|
|
|
if (pSkipUnc (RemoteTo) == RemoteTo) {
|
|
RemoteToBuf[0] = TEXT('\\');
|
|
RemoteToBuf[1] = TEXT('\\');
|
|
lstrcpyn (RemoteToBuf + 2, RemoteTo, MAX_PATH-3);
|
|
RemoteTo = RemoteToBuf;
|
|
}
|
|
|
|
if (!(*RemoteTo)) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
HelpAndExit();
|
|
}
|
|
} else {
|
|
if (!User1) {
|
|
|
|
User1 = argv[i];
|
|
if (!(*User1)) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
} else if (!User2) {
|
|
|
|
User2 = argv[i];
|
|
if (!(*User2)) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
} else {
|
|
HelpAndExit();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!User2) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
Size = MAX_PATH;
|
|
GetComputerName (Computer, &Size);
|
|
|
|
if (NoDecoration || _tcschr (User1, TEXT('\\'))) {
|
|
lstrcpy (FixedUser1, User1);
|
|
} else {
|
|
wsprintf (FixedUser1, TEXT("%s\\%s"), RemoteTo ? pSkipUnc(RemoteTo) : Computer, User1);
|
|
}
|
|
|
|
if (NoDecoration || _tcschr (User2, TEXT('\\'))) {
|
|
lstrcpy (FixedUser2, User2);
|
|
} else {
|
|
wsprintf (FixedUser2, TEXT("%s\\%s"), RemoteTo ? pSkipUnc(RemoteTo) : Computer, User2);
|
|
}
|
|
|
|
b = TRUE;
|
|
|
|
if (b) {
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
ReAdjust = TRUE;
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
ArgArray[0] = FixedUser1;
|
|
ArgArray[1] = FixedUser2;
|
|
ArgArray[2] = RemoteTo;
|
|
|
|
if (!RemoteTo) {
|
|
PrintMessage (MSG_MOVING_PROFILE_LOCAL, ArgArray);
|
|
} else {
|
|
PrintMessage (MSG_MOVING_PROFILE_REMOTE, ArgArray);
|
|
}
|
|
|
|
Flags = 0;
|
|
|
|
if (KeepLocalUser) {
|
|
Flags |= REMAP_PROFILE_KEEPLOCALACCOUNT;
|
|
}
|
|
|
|
if (!Overwrite) {
|
|
Flags |= REMAP_PROFILE_NOOVERWRITE;
|
|
}
|
|
|
|
b = RemapAndMoveUser (
|
|
RemoteTo,
|
|
Flags,
|
|
FixedUser1,
|
|
FixedUser2
|
|
);
|
|
|
|
if (ReAdjust) {
|
|
Error = GetLastError();
|
|
RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
|
|
SetLastError (Error);
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
PrintMessage (MSG_SUCCESS, NULL);
|
|
} else {
|
|
Error = GetLastError();
|
|
ArgArray[0] = (PTSTR) IntToPtr (Error);
|
|
ArgArray[1] = GetErrorText (Error);
|
|
|
|
if (Error < 10000) {
|
|
PrintMessage (MSG_DECIMAL_ERROR, ArgArray);
|
|
} else {
|
|
PrintMessage (MSG_HEXADECIMAL_ERROR, ArgArray);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|