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.
1785 lines
52 KiB
1785 lines
52 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
autologon.c
|
|
|
|
Abstract:
|
|
|
|
This is a command-line utility munges that settings related to the
|
|
Windows NT/2000 Autologon functionality
|
|
|
|
if PRIVATE_VERSION is defined, password info will be displayed on the output
|
|
For general distribution, this should not be defined
|
|
|
|
Author:
|
|
Jason Garms (jasong) 12 October 2000
|
|
|
|
History:
|
|
Cristian Ilac (crisilac) 11 November 2001 Made spec changes
|
|
Jason Garms (jasong) 12 October 2000 Created
|
|
--*/
|
|
|
|
#include "common.h"
|
|
#include <wincred.h>
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Prototypes
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Command functions
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
typedef DWORD (*CommandFn)();
|
|
|
|
DWORD
|
|
DumpCmd();
|
|
|
|
DWORD
|
|
MigratePassword();
|
|
|
|
DWORD
|
|
Delete();
|
|
|
|
DWORD
|
|
EnableAutoLogon();
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
DWORD
|
|
DumpAutoLogonInfo();
|
|
#endif
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Data/Options set functions
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
SetCommand(
|
|
UINT uCommand);
|
|
|
|
DWORD
|
|
SetQuietMode(
|
|
WCHAR* pszData);
|
|
|
|
DWORD
|
|
SetUserName(
|
|
WCHAR* pszData);
|
|
|
|
DWORD
|
|
SetCount(
|
|
WCHAR* pszData);
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
DWORD
|
|
SetMachineName(
|
|
WCHAR* pszData);
|
|
|
|
#endif
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Other functions
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
CheckWinVersion();
|
|
|
|
DWORD
|
|
GetPassword();
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Global command table
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
#define COMMAND_HELP 0
|
|
#define COMMAND_MIGRATE 1
|
|
#define COMMAND_LSA_DELETE 2
|
|
#define COMMAND_LSA_ENABLE 3
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
#define COMMAND_DUMP 4
|
|
#define COMMAND_NOT_SET 5
|
|
#else
|
|
#define COMMAND_NOT_SET 4
|
|
#endif
|
|
|
|
#define COMMAND_SIZE COMMAND_NOT_SET
|
|
|
|
CommandFn g_Commands[COMMAND_SIZE] = {
|
|
DumpCmd,
|
|
MigratePassword,
|
|
Delete,
|
|
EnableAutoLogon,
|
|
#ifdef PRIVATE_VERSION
|
|
DumpAutoLogonInfo
|
|
#endif
|
|
};
|
|
|
|
//+----------------------------------------------------------------------------//
|
|
//
|
|
// Global data
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
WCHAR g_UserName[MAX_STRING] = {0};
|
|
|
|
WCHAR g_DomainName[MAX_STRING] = {0};
|
|
|
|
WCHAR g_Password[MAX_STRING] = {0};
|
|
|
|
DWORD g_AutoLogonCount = 0;
|
|
|
|
WCHAR g_TempString[MAX_STRING] = {0};
|
|
WCHAR g_ErrorString[MAX_STRING] = {0};
|
|
WCHAR g_FailureLocation[MAX_STRING] = {0};
|
|
|
|
BOOL g_QuietMode = FALSE;
|
|
BOOL g_FullHelp = FALSE;
|
|
|
|
BOOL g_SetDefaultPIN = FALSE;
|
|
|
|
UINT g_uCommand = COMMAND_NOT_SET;
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
BOOL g_RemoteOperation = FALSE;
|
|
WCHAR g_RemoteComputerName[MAX_STRING] = {0};
|
|
#endif
|
|
|
|
// various strings
|
|
WCHAR g_PasswordSecretName[] = L"DefaultPassword";
|
|
WCHAR g_PinSecretName[] = L"DefaultPIN";
|
|
WCHAR g_AutoAdminLogonName[] = L"AutoAdminLogon";
|
|
WCHAR g_DefaultUserName[] = L"DefaultUserName";
|
|
WCHAR g_DefaultDomainName[] = L"DefaultDomainName";
|
|
WCHAR g_AutoLogonCountName[] = L"AutoLogonCount";
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Functions
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
|
|
int
|
|
__cdecl
|
|
wmain(
|
|
int argc,
|
|
WCHAR *argv[]
|
|
)
|
|
{
|
|
UINT uCommandPosition = 0;
|
|
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
|
|
//
|
|
// loop through all command line arguments and check for known ones
|
|
// - if one argument is identified continue the loop
|
|
// - if unknown arguments are passed break the loop and fail
|
|
//
|
|
while( ++uCommandPosition < (UINT)argc )
|
|
{
|
|
if( !_wcsicmp(argv[uCommandPosition], L"/?") )
|
|
{
|
|
g_FullHelp = TRUE;
|
|
dwRetCode = SetCommand(COMMAND_HELP);
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsicmp(argv[uCommandPosition], L"/Q") ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Quiet")
|
|
)
|
|
{
|
|
dwRetCode = SetQuietMode(argv[uCommandPosition]);
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsicmp(argv[uCommandPosition], L"/M") ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Migrate") )
|
|
{
|
|
dwRetCode = SetCommand(COMMAND_MIGRATE);
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsicmp(argv[uCommandPosition], L"/D") ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Delete") )
|
|
{
|
|
dwRetCode = SetCommand(COMMAND_LSA_DELETE);
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsicmp(argv[uCommandPosition], L"/S") ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Set") )
|
|
{
|
|
dwRetCode = SetCommand(COMMAND_LSA_ENABLE);
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsnicmp(argv[uCommandPosition], L"/U:", wcslen(L"/U:")) ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/U") ||
|
|
!_wcsnicmp(argv[uCommandPosition], L"/UserName:", wcslen(L"/UserName:")) ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Username") )
|
|
{
|
|
dwRetCode = SetUserName(argv[uCommandPosition]);
|
|
if( ERROR_FILE_NOT_FOUND == dwRetCode )
|
|
{
|
|
//
|
|
// it may be because there was a column followed by spaces
|
|
// Try to recover
|
|
//
|
|
if( uCommandPosition + 1 < (UINT)argc )
|
|
{
|
|
//
|
|
// only if not another parameter
|
|
//
|
|
if( argv[uCommandPosition + 1][0] != '/' )
|
|
{
|
|
dwRetCode = SetUserName(argv[++uCommandPosition]);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(L"Command line: Missing Username.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsnicmp(argv[uCommandPosition], L"/C:", wcslen(L"/C:")) ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/C") ||
|
|
!_wcsnicmp(argv[uCommandPosition], L"/Count:", wcslen(L"/Count:")) ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Count") )
|
|
{
|
|
dwRetCode = SetCount(argv[uCommandPosition]);
|
|
if( ERROR_FILE_NOT_FOUND == dwRetCode )
|
|
{
|
|
//
|
|
// it may be because there was no column or a column
|
|
// followed by spaces. Try to recover by moving on.
|
|
//
|
|
if( uCommandPosition + 1 < (UINT)argc )
|
|
{
|
|
//
|
|
// only if not another parameter
|
|
//
|
|
if( argv[uCommandPosition + 1][0] != '/' )
|
|
{
|
|
dwRetCode = SetCount(argv[++uCommandPosition]);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(L"Command line: Missing count.\n");
|
|
}
|
|
}
|
|
}
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsicmp(argv[uCommandPosition], L"/P") ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Pin") )
|
|
{
|
|
g_SetDefaultPIN = TRUE;
|
|
dwRetCode = SetCommand(COMMAND_LSA_ENABLE);
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
if( !_wcsnicmp(argv[uCommandPosition], L"/T:", wcslen(L"/T:")) ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/T") ||
|
|
!_wcsnicmp(argv[uCommandPosition], L"/Target:", wcslen(L"/Target:")) ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/Target") )
|
|
{
|
|
dwRetCode = SetMachineName(argv[uCommandPosition]);
|
|
if( ERROR_FILE_NOT_FOUND == dwRetCode )
|
|
{
|
|
//
|
|
// it may be because there was no column or a column
|
|
// followed by spaces. Try to recover by moving on.
|
|
//
|
|
if( uCommandPosition + 1 < (UINT)argc )
|
|
{
|
|
//
|
|
// only if not another parameter
|
|
//
|
|
if( argv[uCommandPosition + 1][0] != '/' )
|
|
{
|
|
dwRetCode = SetMachineName(argv[++uCommandPosition]);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(L"Command line: Missing machine name.\n");
|
|
}
|
|
}
|
|
}
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !_wcsicmp(argv[uCommandPosition], L"/L") ||
|
|
!_wcsicmp(argv[uCommandPosition], L"/List") )
|
|
{
|
|
dwRetCode = SetCommand(COMMAND_DUMP);
|
|
if( ERROR_SUCCESS == dwRetCode )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
// unknown argument, set the help as command and break
|
|
// we have to use this parameter as the command might
|
|
// have already been set
|
|
//
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Invalid command: %s\n",
|
|
argv[uCommandPosition]);
|
|
DisplayMessage(g_TempString);
|
|
|
|
SetCommand(COMMAND_NOT_SET);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Display usage if no command switch is present
|
|
//
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
DumpCmd();
|
|
}
|
|
else
|
|
{
|
|
if( COMMAND_NOT_SET == g_uCommand ) {
|
|
SetCommand(COMMAND_HELP);
|
|
}
|
|
|
|
dwRetCode = g_Commands[g_uCommand]();
|
|
|
|
//
|
|
// bad arguments passed to the command, display help
|
|
//
|
|
if( ERROR_BAD_ARGUMENTS == dwRetCode )
|
|
{
|
|
DumpCmd();
|
|
}
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// MigratePassword
|
|
//
|
|
// - reads the registry password, deletes it and sets the LSA secret
|
|
// - works only on certain win versions
|
|
// - if no password present fails
|
|
// - if any ops fail does not roll back
|
|
// - if pwd read fails - nothing happens
|
|
// - if LSA secret set fails - pretty much nothing happens as well.
|
|
// - if RegDelete fails - there is no need to delete the LSA secret...
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
MigratePassword()
|
|
{
|
|
WCHAR Password[MAX_STRING];
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
BOOL fMigratedPIN = FALSE;
|
|
|
|
if( ERROR_SUCCESS != CheckWinVersion() ) {
|
|
dwRetCode = ERROR_OLD_WIN_VERSION;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// get the DefaultPIN registry key from the local
|
|
// or remote system and store it in a local string
|
|
// As this is not something we document we do not display any errors
|
|
// We also do not display any success messages. The only case where
|
|
// we have to display smth PIN related is when we can migrate the PIN
|
|
// but there is no password. We can't fail and we have to display something.
|
|
//
|
|
dwRetCode = GetRegValueSZ(g_PinSecretName, Password, MAX_STRING - 1);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
//
|
|
// we won't migrate the PIN and silently move on
|
|
// this is something we do not document for the tool
|
|
//
|
|
#ifdef PRIVATE_VERSION
|
|
if( ERROR_FILE_NOT_FOUND != dwRetCode )
|
|
{
|
|
DisplayMessage(L"Migrate: DefaultPIN key cannot be read.\n");
|
|
}
|
|
#endif
|
|
dwRetCode = ERROR_SUCCESS;
|
|
goto MigratePassword;
|
|
}
|
|
|
|
//
|
|
// Set the DefaultPassword LSASecret to the value we retrieved
|
|
// from the registry
|
|
//
|
|
dwRetCode = SetSecret(Password, FALSE, g_PinSecretName);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
#ifdef PRIVATE_VERSION
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Migrate: Could not set DefaultPIN LSASecret: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
#endif
|
|
dwRetCode = ERROR_SUCCESS;
|
|
goto MigratePassword;
|
|
}
|
|
|
|
// Delete the DefaultPassword registry key
|
|
dwRetCode = ClearRegValue(g_PinSecretName);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
//
|
|
// delete the secret if could not remove the password.
|
|
//
|
|
(void)SetSecret(NULL, TRUE, g_PinSecretName);
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Migrate: Could not delete DefaultPIN key: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
#endif
|
|
|
|
dwRetCode = ERROR_SUCCESS;
|
|
goto MigratePassword;
|
|
}
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
DisplayMessage(L"Pin migrated from Registry to LSASecret\n");
|
|
#endif
|
|
fMigratedPIN = TRUE;
|
|
|
|
MigratePassword:
|
|
|
|
// Get the DefaultPassword registry key from the local
|
|
// or remote system and store it in a local string
|
|
dwRetCode = GetRegValueSZ(g_PasswordSecretName, Password, MAX_STRING - 1);
|
|
if( ERROR_FILE_NOT_FOUND == dwRetCode )
|
|
{
|
|
if( fMigratedPIN )
|
|
{
|
|
DisplayMessage(L"Migrate: Migrated PIN, DefaultPassword does not exist.\n");
|
|
dwRetCode = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(L"Migrate failed: DefaultPassword does not exist.\n");
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Migrate failed: Could not read DefaultPassword: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Set the DefaultPassword LSASecret to the value we retrieved
|
|
// from the registry
|
|
//
|
|
dwRetCode = SetSecret(Password, FALSE, g_PasswordSecretName);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Migrate failed: Could not set DefaultPassword LSASecret: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
// Delete the DefaultPassword registry key
|
|
dwRetCode = ClearRegValue(g_PasswordSecretName);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
//
|
|
// delete the secret if could not remove the password.
|
|
//
|
|
(void)SetSecret(NULL, TRUE, g_PasswordSecretName);
|
|
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Migrate Failed: Could not delete DefaultPassword key: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
DisplayMessage(L"Password migrated from Registry to LSASecret\n");
|
|
|
|
cleanup:
|
|
// zero out the password so it's not left in memory
|
|
SecureZeroMemory(Password, MAX_STRING * sizeof(WCHAR));
|
|
return dwRetCode;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Delete
|
|
//
|
|
// - Deletes the secret and the autoadmin logon value
|
|
// - Silently ignores the file not found cases
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
Delete()
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
|
|
//
|
|
// make sure we're running against a correct version of NT
|
|
//
|
|
if (CheckWinVersion() != ERROR_SUCCESS) {
|
|
dwRetCode = ERROR_OLD_WIN_VERSION;
|
|
goto cleanup;
|
|
}
|
|
|
|
dwRetCode = ClearRegValue(g_PasswordSecretName);
|
|
|
|
if( (ERROR_SUCCESS != dwRetCode) &&
|
|
(ERROR_FILE_NOT_FOUND != dwRetCode) )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Delete: Registry default password delete failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
dwRetCode = SetSecret(NULL, TRUE, g_PasswordSecretName);
|
|
if( (ERROR_SUCCESS != dwRetCode) &&
|
|
(ERROR_FILE_NOT_FOUND != dwRetCode) )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Delete: LSA Secret delete failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
dwRetCode = ClearRegValue(g_PinSecretName);
|
|
if( (ERROR_SUCCESS != dwRetCode) &&
|
|
(ERROR_FILE_NOT_FOUND != dwRetCode) )
|
|
{
|
|
#ifdef PRIVATE_VERSION
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Delete: Registry default pin delete failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
#endif
|
|
}
|
|
|
|
dwRetCode = SetSecret(NULL, TRUE, g_PinSecretName);
|
|
if( (ERROR_SUCCESS != dwRetCode) &&
|
|
(ERROR_FILE_NOT_FOUND != dwRetCode) )
|
|
{
|
|
#ifdef PRIVATE_VERSION
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Delete: LSA Secret(PIN) delete failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// disable the autologon - if it fails don't recover - the autologon
|
|
// will pretty much fail anyway
|
|
//
|
|
dwRetCode = SetRegValueSZ(g_AutoAdminLogonName, L"0");
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Delete: AutoAdminLogon reg value reset failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
dwRetCode = ClearRegValue(g_AutoLogonCountName);
|
|
if( (ERROR_SUCCESS != dwRetCode) &&
|
|
(ERROR_FILE_NOT_FOUND != dwRetCode) )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : Set Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
dwRetCode = ERROR_SUCCESS;
|
|
DisplayMessage(L"AutoAdminLogon disabled.\n");
|
|
|
|
cleanup:
|
|
return dwRetCode;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// EnableAutoLogon
|
|
//
|
|
// - gets the username/pwd
|
|
// - sets the username/domain
|
|
// - sets the autlogon count if specified and != 0
|
|
// - sets the LSA secret
|
|
// - sets the autoadminlogon
|
|
// - if autoadminlogon fails then tries to delete the LSA secret
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
EnableAutoLogon()
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
WCHAR* pBackSlash = NULL;
|
|
WCHAR* pAtSign = NULL;
|
|
|
|
//
|
|
// make sure we're running against a correct version of NT
|
|
//
|
|
if (CheckWinVersion() != ERROR_SUCCESS) {
|
|
dwRetCode = ERROR_OLD_WIN_VERSION;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// fill in the user name: try both NameUserPrincipal and NameSamCompatible
|
|
//
|
|
if( !*g_UserName )
|
|
{
|
|
ULONG uSize = MAX_STRING - 1;
|
|
if( !GetUserNameEx(NameUserPrincipal,
|
|
g_UserName,
|
|
&uSize) )
|
|
{
|
|
uSize = MAX_STRING - 1;
|
|
if( !GetUserNameEx(NameSamCompatible,
|
|
g_UserName,
|
|
&uSize) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Set: Could not get the logged on user name: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure we have correct information passed in
|
|
//
|
|
if( !g_SetDefaultPIN && !*g_UserName )
|
|
{
|
|
DisplayMessage(L"Set: Failed: Username does not exist.\n");
|
|
dwRetCode = ERROR_BAD_ARGUMENTS;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// this call uses CredMan on XP
|
|
//
|
|
dwRetCode = GetPassword();
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Set: Failed to get the password: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
if( !g_SetDefaultPIN )
|
|
{
|
|
//
|
|
// if a domain specified in the form of domain\username extract it
|
|
// Proper formats are
|
|
// Case 1: /username:JohnDoe
|
|
// Case 2: /username: [email protected]
|
|
// Case 3: /username:Domain\JohnDoe
|
|
//
|
|
|
|
//
|
|
// is '\' present?
|
|
//
|
|
pBackSlash = wcschr(g_UserName, '\\');
|
|
if( NULL != pBackSlash )
|
|
{
|
|
//
|
|
// Case 3, copy into both user and domain buffer
|
|
// Domain is first as we don't want to overwrite the buffer
|
|
// Yes, wcsncpy works from beggining to the end ;-)
|
|
//
|
|
wcsncpy(g_DomainName, g_UserName,
|
|
__min(MAX_STRING - 1, (pBackSlash - g_UserName)) );
|
|
g_DomainName[MAX_STRING - 1] = 0;
|
|
|
|
wcsncpy(g_UserName, pBackSlash + 1, MAX_STRING - 1);
|
|
g_UserName[MAX_STRING - 1] = 0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// if we have @ in the user name delete the domain
|
|
//
|
|
pAtSign = wcschr(g_UserName, '@');
|
|
g_DomainName[0] = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Deletes the reg password value
|
|
//
|
|
if( g_SetDefaultPIN )
|
|
{
|
|
dwRetCode = ClearRegValue(g_PinSecretName);
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ClearRegValue(g_PasswordSecretName);
|
|
}
|
|
|
|
if( (ERROR_SUCCESS != dwRetCode) &&
|
|
(ERROR_FILE_NOT_FOUND != dwRetCode) )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"RegPassword : Reset Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
if( !g_SetDefaultPIN )
|
|
{
|
|
//
|
|
// sets the username
|
|
//
|
|
dwRetCode = SetRegValueSZ(g_DefaultUserName, g_UserName);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"UserName : Set Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"UserName : %s\n",
|
|
g_UserName);
|
|
DisplayMessage(g_TempString);
|
|
}
|
|
|
|
if( !g_SetDefaultPIN )
|
|
{
|
|
//
|
|
// sets the domain, if any or pAtSign is not NULL
|
|
//
|
|
if( *g_DomainName || pAtSign )
|
|
{
|
|
SetRegValueSZ(g_DefaultDomainName, g_DomainName);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DomainName : Set Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DomainName : %s\n",
|
|
g_DomainName);
|
|
DisplayMessage(g_TempString);
|
|
}
|
|
}
|
|
|
|
//
|
|
// set the AutoLogonCount if not 0
|
|
//
|
|
if( g_AutoLogonCount )
|
|
{
|
|
dwRetCode = SetRegValueDWORD(g_AutoLogonCountName, g_AutoLogonCount);
|
|
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : Set Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : %#x\n",
|
|
g_AutoLogonCount);
|
|
DisplayMessage(g_TempString);
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = ClearRegValue(g_AutoLogonCountName);
|
|
|
|
if( (ERROR_SUCCESS != dwRetCode) &&
|
|
(ERROR_FILE_NOT_FOUND != dwRetCode) )
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : Clear Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : (Disabled)\n");
|
|
DisplayMessage(g_TempString);
|
|
}
|
|
|
|
//
|
|
// set the password
|
|
//
|
|
if( g_SetDefaultPIN )
|
|
{
|
|
dwRetCode = SetSecret(g_Password, FALSE, g_PinSecretName);
|
|
}
|
|
else
|
|
{
|
|
dwRetCode = SetSecret(g_Password, FALSE, g_PasswordSecretName);
|
|
}
|
|
|
|
if( ERROR_SUCCESS != dwRetCode)
|
|
{
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret : Set Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret : %s\n",
|
|
g_Password);
|
|
#else
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret : (set)\n");
|
|
#endif
|
|
DisplayMessage(g_TempString);
|
|
|
|
if( !g_SetDefaultPIN )
|
|
{
|
|
//
|
|
// set the AutoAdminLogon regvalue to 1
|
|
//
|
|
dwRetCode = SetRegValueSZ(g_AutoAdminLogonName, L"1");
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
//
|
|
// (try to) clear the secret if this fails
|
|
//
|
|
(void)SetSecret(NULL, TRUE, g_PasswordSecretName);
|
|
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoAdminLogon: Set Failed: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
DisplayMessage(L"AutoAdminLogon : 1\n");
|
|
}
|
|
|
|
cleanup:
|
|
SecureZeroMemory(g_Password, MAX_STRING * sizeof(WCHAR));
|
|
return dwRetCode;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// DumpCmd
|
|
//
|
|
// - Help
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
DumpCmd()
|
|
{
|
|
if (g_QuietMode)
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
wprintf(L"\nAUTOLOGON v1.00 : (c) 2001, Microsoft Corporation\n\n");
|
|
wprintf(L"DESCRIPTION:\n");
|
|
wprintf(L" Used to configure encrypted autologon functionality\n\n");
|
|
wprintf(L"USAGE:\n");
|
|
wprintf(L" AUTOLOGON [/?] [/Quiet] [/Migrate] [/Delete] [/Set]\n");
|
|
wprintf(L" [/Username:username] [/Count:count]\n");
|
|
wprintf(L" Options:\n");
|
|
wprintf(L" /? Display complete help documentation\n");
|
|
wprintf(L" /Quiet Enable quiet mode, which supresses all output\n");
|
|
wprintf(L" /Migrate Migrate cleartext password from registry to LSASecret\n");
|
|
wprintf(L" /Delete Deletes the default password and disable AutoAdminLogon \n");
|
|
wprintf(L" /Set Set the DefaultPassword LSASecret and enable AutoAdminLogon\n");
|
|
wprintf(L" /Username The username to set in Default UserName.\n");
|
|
wprintf(L" /Count Set the logoncount\n");
|
|
#ifdef PRIVATE_VERSION
|
|
wprintf(L" /Pin Set the DefaultPin LSASecret\n");
|
|
wprintf(L" /List List autologon settings\n");
|
|
wprintf(L" /Target The remote computer name\n");
|
|
#endif
|
|
|
|
if( g_FullHelp )
|
|
{
|
|
wprintf(L"\nNOTES:\n");
|
|
wprintf(L" 1.The /Migrate /Delete /Set commands are exclusive.\n");
|
|
wprintf(L" You will always be prompted for a password.\n");
|
|
wprintf(L" If a username is not specified the currently logged on user is assumed.\n");
|
|
wprintf(L" If no count is specified a count of 0 is implicitely assumed.\n\n");
|
|
wprintf(L" 2.You need to be running as a member of the local administrators group for\n");
|
|
wprintf(L" this utility to work properly.\n\n");
|
|
wprintf(L" 3.When setting a password that has special characters in it, such as \"|>&\n");
|
|
wprintf(L" make sure that you escape these characters. Also, passwords with spaces \n");
|
|
wprintf(L" should be enclosed in double quotes.\n\n");
|
|
wprintf(L" 4.Setting the logoncount to 0 means an autologon will be performed until\n");
|
|
wprintf(L" the secret is deleted.\n\n");
|
|
}
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// DumpAutoLogonInfo
|
|
//
|
|
// - Dumps relevant data
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
#ifdef PRIVATE_VERSION
|
|
DWORD
|
|
DumpAutoLogonInfo()
|
|
{
|
|
WCHAR wcsTempString[MAX_STRING];
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
|
|
//
|
|
// make sure we're running against a correct version of NT
|
|
//
|
|
if (CheckWinVersion() != ERROR_SUCCESS) {
|
|
dwRetCode = ERROR_OLD_WIN_VERSION;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the username
|
|
//
|
|
dwRetCode = GetRegValueSZ(g_DefaultUserName, wcsTempString, MAX_STRING - 1);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case ERROR_FILE_NOT_FOUND:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultUserName : (regvalue does not exist)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultUserName : %s\n",
|
|
wcsTempString);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and end
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultUserName : Failed to query regkey: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the DefaultDomainName
|
|
//
|
|
dwRetCode = GetRegValueSZ(g_DefaultDomainName, wcsTempString, MAX_STRING - 1);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case ERROR_FILE_NOT_FOUND:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultDomainName: (regvalue does not exist)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultDomainName: %s\n",
|
|
wcsTempString);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and end
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultDomainName: Failed to query regkey: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the DefaultPassword
|
|
//
|
|
dwRetCode = GetRegValueSZ(g_PasswordSecretName,
|
|
wcsTempString, MAX_STRING - 1);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case ERROR_FILE_NOT_FOUND:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultPassword : (regvalue does not exist)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultPassword : %s\n",
|
|
wcsTempString);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and end
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultPassword : Failed to query regkey: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the DefaultPin - display it only if there
|
|
//
|
|
dwRetCode = GetRegValueSZ(g_PinSecretName,
|
|
wcsTempString, MAX_STRING - 1);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case ERROR_FILE_NOT_FOUND:
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"DefaultPIN : %s\n",
|
|
wcsTempString);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and continue
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the AutoAdminLogonCount
|
|
//
|
|
dwRetCode = GetRegValueDWORD(g_AutoLogonCountName, &g_AutoLogonCount);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case ERROR_FILE_NOT_FOUND:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : (regvalue does not exist)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : %#x\n",
|
|
g_AutoLogonCount);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and end
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoLogonCount : Failed to query regkey: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the LSASecret DefaultPassword
|
|
//
|
|
dwRetCode = GetSecret(wcsTempString, MAX_STRING - 1, g_PasswordSecretName);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case STATUS_OBJECT_NAME_NOT_FOUND:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret : (secret does not exist)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch this case and continue
|
|
case ERROR_ACCESS_DENIED:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret : (access denied)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret : %s\n",
|
|
wcsTempString);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and end
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret : Failed to query LSASecret: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the LSASecret DefaultPin
|
|
//
|
|
dwRetCode = GetSecret(wcsTempString, MAX_STRING - 1, g_PinSecretName);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case STATUS_OBJECT_NAME_NOT_FOUND:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret(PIN) : (secret does not exist)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch this case and continue
|
|
case ERROR_ACCESS_DENIED:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret(PIN) : (access denied)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret(PIN) : %s\n",
|
|
wcsTempString);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and end
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"LSASecret(PIN) : Failed to query LSASecret: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the AutoAdminLogon
|
|
//
|
|
dwRetCode = GetRegValueSZ(g_AutoAdminLogonName, wcsTempString, MAX_STRING - 1);
|
|
switch (dwRetCode) {
|
|
// catch this case and continue
|
|
case ERROR_FILE_NOT_FOUND:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoAdminLogon : (regvalue does not exist)\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// On success, print the regkey and continue to next item
|
|
case ERROR_SUCCESS:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoAdminLogon : %s\n",
|
|
wcsTempString);
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
|
|
// catch all the generic errors and end
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"AutoAdminLogon : Failed to query regkey: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
SecureZeroMemory(g_TempString, MAX_STRING * sizeof(WCHAR));
|
|
SecureZeroMemory(wcsTempString, MAX_STRING * sizeof(WCHAR));
|
|
return dwRetCode;
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// SetCommand
|
|
//
|
|
// - Sets the command
|
|
// - if there are two successive calls to this it will fail - as in two
|
|
// commands passed in the command line
|
|
// - a call greater with than COMMAND line resets the command to COMMAND_HELP
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
SetCommand(UINT uCommand)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
if( COMMAND_NOT_SET == uCommand )
|
|
{
|
|
g_uCommand = COMMAND_NOT_SET;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// if already set, fail
|
|
//
|
|
if( COMMAND_NOT_SET != g_uCommand )
|
|
{
|
|
dwRetCode = ERROR_BAD_ARGUMENTS;
|
|
goto cleanup;
|
|
}
|
|
|
|
if( g_uCommand > COMMAND_SIZE )
|
|
{
|
|
//
|
|
// assert?
|
|
//
|
|
g_uCommand = COMMAND_HELP;
|
|
}
|
|
else
|
|
{
|
|
g_uCommand = uCommand;
|
|
}
|
|
|
|
cleanup:
|
|
return dwRetCode;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// SetQuietMode
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
SetQuietMode(WCHAR* pszData)
|
|
{
|
|
UNREFERENCED_PARAMETER(pszData);
|
|
|
|
g_QuietMode = TRUE;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// SetUserName
|
|
//
|
|
// - Sets the username
|
|
// - Proper formats are combinations of
|
|
// /username:"user name"
|
|
// /username username
|
|
// /username: " user name"
|
|
//
|
|
// - returns ERROR_FILE_NOT_FOUND when the arg is missing so the caller can
|
|
// move on to the next parameter
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
SetUserName(WCHAR* pszData)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
WCHAR* pCh = NULL;
|
|
|
|
//
|
|
// is ":" present?
|
|
//
|
|
pCh = wcschr(pszData, ':');
|
|
if( NULL == pCh )
|
|
{
|
|
pCh = pszData;
|
|
}
|
|
else
|
|
{
|
|
pCh++;
|
|
}
|
|
|
|
//
|
|
// scan past any leading spaces - we KNOW this is NULL terminated
|
|
//
|
|
while( iswspace(*pCh) )
|
|
{
|
|
pCh++;
|
|
}
|
|
|
|
//
|
|
// column followed by spaces only
|
|
//
|
|
if( !*pCh )
|
|
{
|
|
dwRetCode = ERROR_FILE_NOT_FOUND;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// if we're still at the leading '/' then it means we have the
|
|
// /U username case
|
|
//
|
|
if( '/' == *pCh )
|
|
{
|
|
dwRetCode = ERROR_FILE_NOT_FOUND;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
wcsncpy(g_UserName, pCh, MAX_STRING - 1);
|
|
g_UserName[MAX_STRING - 1] = 0;
|
|
|
|
cleanup:
|
|
return dwRetCode;
|
|
}
|
|
|
|
#ifdef PRIVATE_VERSION
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// SetMachineName
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
SetMachineName(WCHAR* pszData)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
WCHAR* pCh = NULL;
|
|
|
|
//
|
|
// is ":" present?
|
|
//
|
|
pCh = wcschr(pszData, ':');
|
|
if( NULL == pCh )
|
|
{
|
|
pCh = pszData;
|
|
}
|
|
else
|
|
{
|
|
pCh++;
|
|
}
|
|
|
|
//
|
|
// scan past any leading spaces - we KNOW this is NULL terminated
|
|
//
|
|
while( iswspace(*pCh) )
|
|
{
|
|
pCh++;
|
|
}
|
|
|
|
//
|
|
// column followed by spaces only
|
|
//
|
|
if( !*pCh )
|
|
{
|
|
dwRetCode = ERROR_FILE_NOT_FOUND;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// if we're still at the leading '/' then it means we have the
|
|
// /U username case
|
|
//
|
|
if( '/' == *pCh )
|
|
{
|
|
dwRetCode = ERROR_FILE_NOT_FOUND;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
g_RemoteOperation = TRUE;
|
|
wcsncpy(g_RemoteComputerName, pCh, MAX_STRING - 1);
|
|
g_RemoteComputerName[MAX_STRING - 1] = 0;
|
|
|
|
cleanup:
|
|
return dwRetCode;
|
|
}
|
|
#endif
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// SetCount
|
|
//
|
|
// - Sets the count
|
|
// - Proper formats are combinations of
|
|
// /Count:300
|
|
// /Count 300
|
|
// /Count: 300
|
|
//
|
|
// - returns ERROR_FILE_NOT_FOUND when the arg is missing so the caller can
|
|
// move on to the next parameter
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
SetCount(WCHAR* pszData)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
WCHAR* pEndString = NULL;
|
|
UINT Count = 0;
|
|
|
|
//
|
|
// is ":" present?
|
|
//
|
|
WCHAR* pCh = wcschr(pszData, ':');
|
|
if( NULL == pCh )
|
|
{
|
|
pCh = pszData;
|
|
}
|
|
else
|
|
{
|
|
pCh++;
|
|
}
|
|
|
|
//
|
|
// scan past any leading spaces - we KNOW this is NULL terminated
|
|
//
|
|
while ( iswspace(*pCh) )
|
|
{
|
|
pCh++;
|
|
}
|
|
|
|
//
|
|
// column followed by spaces only
|
|
//
|
|
if( !*pCh )
|
|
{
|
|
dwRetCode = ERROR_FILE_NOT_FOUND;
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
Count = wcstoul(pCh, &pEndString, 0);
|
|
if( *pEndString )
|
|
{
|
|
if( pEndString != pCh )
|
|
{
|
|
//
|
|
// If the input is incorrect
|
|
//
|
|
dwRetCode = ERROR_BAD_ARGUMENTS;
|
|
DisplayMessage(L"Count: Failed: Not a number.\n");
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// this means we run into a "/C 100" case and we have to move
|
|
// to the next argument
|
|
//
|
|
dwRetCode = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Ignore if 0
|
|
//
|
|
if( Count )
|
|
{
|
|
g_AutoLogonCount = (DWORD)Count;
|
|
}
|
|
|
|
cleanup:
|
|
return dwRetCode;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// CredMan call data
|
|
//
|
|
// We have to dinamically load the dll and call into it as it is not present
|
|
// Win2k, NT4
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
//
|
|
// CredMan function
|
|
//
|
|
typedef DWORD (*PCredUIFunction) (
|
|
PCTSTR pszTargetName,
|
|
PCtxtHandle Reserved,
|
|
DWORD dwAuthError,
|
|
PCTSTR pszUserName,
|
|
ULONG ulUserNameMaxChars,
|
|
PCTSTR pszPassword,
|
|
ULONG ulPasswordMaxChars,
|
|
PBOOL pfSave,
|
|
DWORD dwFlags
|
|
);
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// GetPassword
|
|
//
|
|
// - tries to load credui dll and if not there
|
|
// falls back on regular console functions
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD GetPassword()
|
|
{
|
|
DWORD dwRetCode = ERROR_INVALID_FUNCTION;
|
|
BOOL fSave = FALSE;
|
|
PCredUIFunction pCredUICmdLinePromptForCredentials = NULL;
|
|
HMODULE hModule = NULL;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Try see if CredMan is present
|
|
//
|
|
hModule = LoadLibrary(L"credui.dll");
|
|
|
|
if( NULL == hModule )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// get function pointer
|
|
//
|
|
pCredUICmdLinePromptForCredentials =
|
|
(PCredUIFunction)GetProcAddress(
|
|
hModule,
|
|
"CredUICmdLinePromptForCredentialsW");
|
|
|
|
if( NULL == pCredUICmdLinePromptForCredentials )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// CREDUI_FLAGS_DO_NOT_PERSIST - autologon pwd should not be persisted
|
|
// CREDUI_FLAGS_VALIDATE_USERNAME - just a precaution
|
|
// CREDUI_FLAGS_EXCLUDE_CERTIFICATES - we don't want this for autologon
|
|
// CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS - prevents 'connect to'
|
|
// string to be displayed and since target is AutoAdminLogon
|
|
// it boils down to a nice prompt. Note that this flag will skip
|
|
// the user name, but we assume the username is already filled in
|
|
//
|
|
dwRetCode = pCredUICmdLinePromptForCredentials(
|
|
L"AutoAdminLogon", // PCTSTR pszTargetName
|
|
NULL, // PCtxtHandle Reserved
|
|
NO_ERROR, // DWORD dwAuthError
|
|
g_UserName, // PCTSTR pszUserName
|
|
MAX_STRING - 1, // ULONG ulUserNameMaxChars
|
|
g_Password, // PCTSTR pszPassword
|
|
MAX_STRING - 1, // ULONG ulPasswordMaxChars
|
|
&fSave, // PBOOL pfSave,
|
|
// DWORD dwFlags
|
|
CREDUI_FLAGS_DO_NOT_PERSIST |
|
|
CREDUI_FLAGS_VALIDATE_USERNAME |
|
|
CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
|
|
CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS
|
|
);
|
|
|
|
} while( FALSE );
|
|
|
|
//
|
|
// if CredMan is not present then just try the console input;
|
|
// pass similar strings (though non localized)
|
|
//
|
|
if( ERROR_INVALID_FUNCTION == dwRetCode )
|
|
{
|
|
//
|
|
// if user has not been specified
|
|
//
|
|
if( !*g_UserName )
|
|
{
|
|
dwRetCode = GetConsoleStr(g_UserName, MAX_STRING - 1,
|
|
FALSE,
|
|
L"Enter the user name for AutoAdminLogon: ",
|
|
NULL);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
dwRetCode = GetConsoleStr(g_Password, MAX_STRING - 1,
|
|
TRUE,
|
|
L"Enter the password for AutoAdminLogon: ",
|
|
NULL);
|
|
if( ERROR_SUCCESS != dwRetCode )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
goto cleanup;
|
|
|
|
cleanup:
|
|
if( hModule )
|
|
{
|
|
FreeLibrary(hModule);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// CheckWinVersion
|
|
// - currently any OS post NT4/SP7 supports this.
|
|
// - the remote case (which we do not support yet) assumes remote NT4
|
|
// as being pre-SP7...
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
DWORD
|
|
CheckWinVersion()
|
|
{
|
|
DWORD dwMachineVerNumber = 0;
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
OSVERSIONINFOEX versionInfoEx;
|
|
NET_API_STATUS status;
|
|
|
|
// Make sure it's a Win2k box
|
|
#ifdef PRIVATE_VERSION
|
|
if (g_RemoteOperation) {
|
|
status = GetMajorNTVersion(&dwMachineVerNumber,
|
|
g_RemoteComputerName);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
status = GetMajorNTVersion(&dwMachineVerNumber,
|
|
NULL);
|
|
}
|
|
|
|
switch (dwMachineVerNumber) {
|
|
case 3:
|
|
dwRetCode = ERROR_OLD_WIN_VERSION;
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Error: Running NT3.x\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
case 4:
|
|
//
|
|
// Verify SP7 - only locally for now
|
|
//
|
|
#ifdef PRIVATE_VERSION
|
|
if( !g_RemoteOperation )
|
|
#endif
|
|
{
|
|
//
|
|
// GetVersionInfoEx call for getting the SP information
|
|
//
|
|
SecureZeroMemory(&versionInfoEx, sizeof(OSVERSIONINFOEX));
|
|
versionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
|
|
if( !GetVersionEx((LPOSVERSIONINFO)(&versionInfoEx)) )
|
|
{
|
|
dwRetCode = GetLastError();
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Error: Running NT4, can't query SP version: %s\n",
|
|
GetErrorString(dwRetCode));
|
|
DisplayMessage(g_TempString);
|
|
}
|
|
|
|
if( versionInfoEx.wServicePackMajor < 7 )
|
|
{
|
|
dwRetCode = ERROR_OLD_WIN_VERSION;
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Error: Running NT4 pre SP7\n");
|
|
DisplayMessage(g_TempString);
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case 5:
|
|
break;
|
|
default:
|
|
_snwprintf(g_TempString, MAX_STRING - 1,
|
|
L"Error: Unknown target machine version (%#x).\n",
|
|
status);
|
|
DisplayMessage(g_TempString);
|
|
dwRetCode = ERROR_OLD_WIN_VERSION;
|
|
break;
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|