HOWTO: Manage Computer Accounts Programmatically in Windows NT |
Q136867
The ability to manage Windows NT computer accounts can be accomplished by using the Windows NT server manager utility. The server manager (srvmgr) can be used to create and delete various computer accounts, including the following account types:
UF_SERVER_TRUST_ACCOUNT (Backup domain controller)The following list of APIs can be used to manage computer accounts in the target domain:
UF_WORKSTATION_TRUST_ACCOUNT (Workstation and server)
UF_INTERDOMAIN_TRUST_ACCOUNT (Interdomain trust account)
// works compiled ansi or unicode
#define UNICODE
#define _UNICODE
#define RTN_OK 0
#define RTN_USAGE 1
#define RTN_ERROR 13
/*++
The following sample code adds the specified workstation computer account
to the specified domain. If no domain is specified, the computer account is
created on the local computer.
netapi32.lib
advapi32.lib
#include <windows.h>
#include <stdio.h>
#include <lm.h>
BOOL
AddMachineAccount(
LPWSTR wTargetComputer,
LPWSTR MachineAccount,
DWORD AccountType
);
BOOL SetCurrentPrivilege(
LPWSTR TargetComputer, // target of privilege operation
LPCWSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
);
int wmain(int argc, wchar_t *argv[])
{
LPWSTR wMachineAccount;
LPWSTR wPrimaryDC;
LPWSTR wMachineAccountPrivilege = L"SeMachineAccountPrivilege";
DWORD dwError;
BOOL bSuccess;
if (argc < 2)
{
fprintf(stderr, "Usage: %ls <machineaccountname> [domain]\n",
argv[0]);
return RTN_USAGE;
}
wMachineAccount = argv[1];
//
// default will operate on local machine. Non-NULL wPrimaryDC will
// cause buffer to be freed
//
wPrimaryDC = NULL;
//
// if a domain name was specified, fetch the computer name of the
// primary domain controller
//
if (argc == 3) {
dwError = NetGetDCName(NULL, argv[2], (LPBYTE *)&wPrimaryDC);
if(dwError != NO_ERROR) {
fprintf(stderr,"NetGetDCName error! (rc=%lu)\n", dwError);
return RTN_ERROR;
}
}
bSuccess=AddMachineAccount(
wPrimaryDC, // primary DC computer name
wMachineAccount, // computer account name
UF_WORKSTATION_TRUST_ACCOUNT // computer account type
);
if(!bSuccess && GetLastError() == ERROR_ACCESS_DENIED ) {
//
// try to enable the SeMachineAccountPrivilege
//
if(SetCurrentPrivilege(
wPrimaryDC, wMachineAccountPrivilege, TRUE )) {
//
// enabled the privilege. retry the add operation
//
bSuccess=AddMachineAccount(
wPrimaryDC,
wMachineAccount,
UF_WORKSTATION_TRUST_ACCOUNT
);
//
// disable the privilege
//
SetCurrentPrivilege(
wPrimaryDC, wMachineAccountPrivilege, FALSE);
}
}
//
// free the buffer allocated for the PDC computer name
//
if(wPrimaryDC) NetApiBufferFree(wPrimaryDC);
if(!bSuccess)
{
fprintf(stderr,"AddMachineAccount error! (rc=%lu)\n",
GetLastError());
return RTN_ERROR;
}
return RTN_OK;
}
BOOL
AddMachineAccount(
LPWSTR wTargetComputer,
LPWSTR MachineAccount,
DWORD AccountType
)
{
LPWSTR wAccount;
LPWSTR wPassword;
USER_INFO_1 ui;
DWORD cbAccount;
DWORD cbLength;
DWORD dwError;
//
// ensure a valid computer account type was passed
// TODO SetLastError
//
if (AccountType != UF_WORKSTATION_TRUST_ACCOUNT &&
AccountType != UF_SERVER_TRUST_ACCOUNT &&
AccountType != UF_INTERDOMAIN_TRUST_ACCOUNT
) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// obtain number of chars in computer account name
//
cbLength = cbAccount = lstrlenW(MachineAccount);
//
// ensure computer name doesn't exceed maximum length
//
if(cbLength > MAX_COMPUTERNAME_LENGTH) {
SetLastError(ERROR_INVALID_ACCOUNT_NAME);
return FALSE;
}
//
// allocate storage to contain Unicode representation of
// computer account name + trailing $ + NULL
//
wAccount=(LPWSTR)HeapAlloc(GetProcessHeap(), 0,
(cbAccount + 1 + 1) * sizeof(WCHAR) // Account + '$' + NULL
);
if(wAccount == NULL) return FALSE;
//
// password is the computer account name converted to lowercase
// you will convert the passed MachineAccount in place
//
wPassword = MachineAccount;
//
// copy MachineAccount to the wAccount buffer allocated while
// converting computer account name to uppercase.
// convert password (inplace) to lowercase
//
while(cbAccount--) {
wAccount[cbAccount] = towupper( MachineAccount[cbAccount] );
wPassword[cbAccount] = towlower( wPassword[cbAccount] );
}
//
// computer account names have a trailing Unicode '$'
//
wAccount[cbLength] = L'$';
wAccount[cbLength + 1] = L'\0'; // terminate the string
//
// if the password is greater than the max allowed, truncate
//
if(cbLength > LM20_PWLEN) wPassword[LM20_PWLEN] = L'\0';
//
// initialize USER_INFO_x structure
//
ZeroMemory(&ui, sizeof(ui));
ui.usri1_name = wAccount;
ui.usri1_password = wPassword;
ui.usri1_flags = AccountType | UF_SCRIPT;
ui.usri1_priv = USER_PRIV_USER;
dwError=NetUserAdd(
wTargetComputer, // target computer name
1, // info level
(LPBYTE) &ui, // buffer
NULL
);
//
// free allocated memory
//
if(wAccount) HeapFree(GetProcessHeap(), 0, wAccount);
//
// indicate whether it was successful
//
if(dwError == NO_ERROR)
return TRUE;
else {
SetLastError(dwError);
return FALSE;
}
}
BOOL SetCurrentPrivilege(
LPWSTR TargetComputer, // target of privilege operation
LPCWSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
BOOL bSuccess=FALSE;
if(!LookupPrivilegeValueW(TargetComputer, Privilege, &luid))
return FALSE;
if(!OpenProcessToken(
GetCurrentProcess(),
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
&hToken
)) return FALSE;
//
// first pass. get current privilege setting
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);
if(GetLastError() == ERROR_SUCCESS) {
//
// second pass. set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if(bEnablePrivilege) {
tpPrevious.Privileges[0].Attributes |=
(SE_PRIVILEGE_ENABLED);
}
else {
tpPrevious.Privileges[0].Attributes ^=
(SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL
);
if (GetLastError() == ERROR_SUCCESS) bSuccess=TRUE;
}
CloseHandle(hToken);
return bSuccess;
}
Additional query words: account server workstation trust
Keywords : kbnetwork kbKernBase kbLSA kbOSWinNT351 kbOSWinNT400 kbOSWin2000 kbSDKPlatform kbSecurity kbNetAPI kbDSupport kbCodeSam kbGrpDSKernBase
Issue type : kbhowto
Technology : kbWin32SDKSearch kbAudDeveloper kbSDKSearch kbWin32sSearch
|
Last Reviewed: January 7, 2000 © 2001 Microsoft Corporation. All rights reserved. Terms of Use. |