本文將告訴您,如何以程式設計方式使建立而不需要互動式的登入的使用者的設定檔。
預設情況下,新使用者設定檔不會建立使用者登入電腦之前以互動方式。當使用者登入到電腦藉由按下
CTRL + ALT + DEL 來存取透過 Winlogon] 對話方塊時,就會發生互動式登入。
很可能以程式設計的方式會造成使用者的設定檔,而不需要互動式的登入呼叫 LoadUserProfile() API 來建立。在 Windows 2000 和 Windows XP,此函式是公開平台 SDK 標頭檔內,並記載在 MSDN 程式庫。在 Windows NT 4.0 上未公開 LoadUserProfile() API,但是它仍然可以藉由動態載入 Userenv.dll 文件庫,並取得函式指標呼叫。
呼叫在 Windows NT 4.0 上 LoadUserProfile()本文的其餘部分將示範如何在 Windows NT 4.0 上使用使用者設定檔結構和函式。這些結構和函式的完整資訊,請參閱平台 SDK 文件最新版本中的 MSDN 程式庫。
PROFILEINFO 結構
PROFILEINFO 結構提供使用者設定檔的相關資訊:
typedef struct _PROFILEINFO {
DWORD dwSize; // size of structure
DWORD dwFlags; // flags
LPTSTR lpUserName; // user name
LPTSTR lpProfilePath; // roaming profile path
LPTSTR lpDefaultPath; // default user profile path
LPTSTR lpServerName; // validating domain controller name
LPTSTR lpPolicyPath; // Windows NT 4.0-style policy file
HANDLE hProfile; // registry key handle
} PROFILEINFO, FAR * LPPROFILEINFO;
dwSize 指定之結構的大小 (以位元組為單位)。
dwFlags 可以是下列旗標的其中一個:
PI_NOUI (1)--防止顯示的設定檔錯誤訊息。
PI_APPLYPOLICY (2)--套用 Windows NT 4.0 樣式原則。
lpUserName 是指標,使用者的名稱。
lpProfilePath 是指標,漫遊設定檔路徑。
lpDefaultPath 是預設使用者設定檔路徑指標。
lpServerName 是指標,驗證的網域控制器中 NetBIOS 格式的名稱。
lpPolicyPath 是指標,原則檔的路徑。
hProfile 將包含 HKEY_CURRENT_USER 登錄金鑰控制代碼在成功傳回時。
LoadUserProfile() 函式
LoadUserProfile() 函式會載入指定的使用者設定檔。如果不還存在設定檔操作系統將會建立它。呼叫端必須在電腦上擁有系統管理員權限。
BOOL LoadUserProfile(
HANDLE hToken,
LPPROFILEINFO lpProfileInfo
);
hToken is a token for the user. The token must have TOKEN_IMPERSONATE
access.
lpProfileInfo is a pointer to a PROFILEINFO structure.
如果函式成功,傳回值是零。如果函式失敗,傳回的值會是零。若要延伸的錯誤資訊呼叫 GetLastError()。
在成功傳回時
PROFILEINFO hProfile 成員就是登錄機碼控點開啟使用者的登錄區的根目錄。請勿關閉 hProfile 控點。而是,將它傳遞給
UnloadUserProfile() 函數。
UnloadUserProfile() 函式
UnloadUserProfile 函式卸載
LoadUserProfile 函式所載入的使用者的設定檔。呼叫端必須在電腦上擁有系統管理員權限。
BOOL UnloadUserProfile(
HANDLE hToken,
HANDLE hProfile
);
hToken 為使用者的語彙基元。語彙基元必須 TOKEN_IMPERSONATE 存取。
hProfile 就是 PROFILEINFO 結構的 hProfile 成員之後 LoadUserProfile() 成功的呼叫。
如果函式成功,傳回值是零。如果函式失敗,傳回的值會是零。若要延伸的錯誤資訊呼叫 GetLastError()。
GetUserProfileDirectory() 函式
GetUserProfileDirectory 函式會傳回至指定的使用者設定檔的根目錄的路徑。
BOOL GetUserProfileDirectory(
HANDLE hToken,
LPTSTR lpProfileDir,
LPDWORD lpcchSize
);hToken 為使用者的語彙基元。語彙基元必須 TOKEN_IMPERSONATE 存取。
lpProfilesDir 是指標,緩衝區會接收到指定的使用者設定檔目錄路徑。
lpcchSize 指定 lpProfilesDir] 緩衝區的大小 (以位元組為單位)。
如果函式成功,傳回值是零。如果函式失敗,傳回的值會是零。若要延伸的錯誤資訊呼叫 GetLastError()。
範例程式碼
下列範例程式碼可以編譯為主控台應用程式,Windows NT 4.0。這個相同的方法仍可在 Windows 2000 和 Windows XP 上運作,但通常會更容易地包括 userenv.h 標頭檔和直接與 userenv.lib 程式庫的連結。隱含連結是較佳,因為它不需要動態載入 DLL,並為使用者設定檔 API 擷取函數指標。
這個程式碼會示範如何以程式設計方式建立新的使用者帳戶、 強制設定檔至] 為新的使用者建立及擷取新的設定檔目錄:
//**********************************************************************
//
// This program creates a new user account, forces a profile to be
// created for the new user, and retrieves the new profile directory
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) 1998 Microsoft Corporation. All rights reserved.
// Author: Jonathan Russ (jruss)
//
//**********************************************************************
// NOTE: This code must be linked with netapi32.lib
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <lm.h>
// Declarations based on USERENV.H for Windows 2000 Beta 2
#define PI_NOUI 0x00000001 // Prevents displaying of messages
#define PI_APPLYPOLICY 0x00000002 // Apply NT4 style policy
typedef struct _PROFILEINFO {
DWORD dwSize; // Must be set to sizeof(PROFILEINFO)
DWORD dwFlags; // See flags above
LPTSTR lpUserName; // User name (required)
LPTSTR lpProfilePath; // Roaming profile path
LPTSTR lpDefaultPath; // Default user profile path
LPTSTR lpServerName; // Validating DC name in netbios format
LPTSTR lpPolicyPath; // Path to the NT4 style policy file
HANDLE hProfile; // Registry key handle - filled by function
} PROFILEINFO, FAR * LPPROFILEINFO;
// Typedefs for function pointers in USERENV.DLL
typedef BOOL (STDMETHODCALLTYPE FAR * LPFNLOADUSERPROFILE) (
HANDLE hToken,
LPPROFILEINFO lpProfileInfo
);
typedef BOOL (STDMETHODCALLTYPE FAR * LPFNUNLOADUSERPROFILE) (
HANDLE hToken,
HANDLE hProfile
);
typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) (
HANDLE hToken,
LPTSTR lpProfileDir,
LPDWORD lpcchSize
);
HMODULE g_hUserEnvLib = NULL;
LPFNLOADUSERPROFILE LoadUserProfile = NULL;
LPFNUNLOADUSERPROFILE UnloadUserProfile = NULL;
LPFNGETUSERPROFILEDIR GetUserProfileDirectory = NULL;
//**********************************************************************
//
// FUNCTION: InitUserEnv - This function dynamically links to
// USERENV.DLL and sets up the required function pointers
//
// PARAMETERS: none
//
// RETURN VALUE: TRUE if successful. Otherwise, FALSE.
//
//**********************************************************************
BOOL InitUserEnv( void ) {
g_hUserEnvLib = LoadLibrary( _T("userenv.dll") );
if ( !g_hUserEnvLib ) {
_tprintf( _T("LoadLibrary(userenv.dll) failed. Error %d\n"),
GetLastError() );
return FALSE;
}
#ifdef UNICODE
LoadUserProfile =
(LPFNLOADUSERPROFILE) GetProcAddress( g_hUserEnvLib,
"LoadUserProfileW" );
#else
LoadUserProfile =
(LPFNLOADUSERPROFILE) GetProcAddress( g_hUserEnvLib,
"LoadUserProfileA" );
#endif
if (!LoadUserProfile) {
_tprintf( _T("GetProcAddress(%s) failed. Error %d\n"),
"LoadUserProfile", GetLastError() );
return FALSE;
}
UnloadUserProfile =
(LPFNUNLOADUSERPROFILE) GetProcAddress( g_hUserEnvLib,
"UnloadUserProfile" );
if (!UnloadUserProfile) {
_tprintf( _T("GetProcAddress(%s) failed. Error %d\n"),
"UnloadUserProfile", GetLastError() );
return FALSE;
}
#ifdef UNICODE
GetUserProfileDirectory =
(LPFNGETUSERPROFILEDIR) GetProcAddress( g_hUserEnvLib,
"GetUserProfileDirectoryW" );
#else
GetUserProfileDirectory =
(LPFNGETUSERPROFILEDIR) GetProcAddress( g_hUserEnvLib,
"GetUserProfileDirectoryA" );
#endif
if (!GetUserProfileDirectory) {
_tprintf( _T("GetProcAddress(%s) failed. Error %d\n"),
"GetUserProfileDirectory", GetLastError() );
return FALSE;
}
return TRUE;
}
//**********************************************************************
//
// FUNCTION: _tmain - This is the entry point for the program.
//
// PARAMETERS: argc - the number of command-line arguments
// argv - an array of null-terminated strings specifying
// the command-line arguments
// envp - an array of null-terminated strings specifying
// the environment strings
//
// RETURN VALUE: Zero if successful. Otherwise, non-zero.
//
//**********************************************************************
#ifdef __cplusplus
extern "C"
#endif
#ifdef UNICODE
int _cdecl
#else
int
#endif
_tmain(int argc, _TCHAR **argv, _TCHAR **envp) {
USER_INFO_1 ui1;
DWORD dwError;
HANDLE hToken;
PROFILEINFO pi;
TCHAR szProfilePath[1024];
DWORD cchPath = 1024;
WCHAR szUserName[20];
WCHAR szPassword[20];
// Check for the required command-line arguments
if (argc < 2) {
_tprintf( _T("Usage: AddUser <user> [password]\n") );
return -1;
}
// Set USERENV.DLL function pointers
if ( !InitUserEnv() ) {
_tprintf( _T("Failed to set USERENV.DLL function pointers.\n") );
return -1;
}
// Create local copies of the user name and password
#ifdef UNICODE
_tcscpy( szUserName, argv[1] );
if ( argc == 2 ) {
_tcscpy( szPassword, szUserName );
} else {
_tcscpy( szPassword, argv[2] );
}
#else
{
int n;
n = MultiByteToWideChar(0, 0, argv[1], -1, szUserName, 20);
if (n == 0)
{
_tprintf( _T("Failed to convert username to unicode\n"));
return -1;
}
if ( argc == 2 ) {
n = MultiByteToWideChar(0, 0, argv[1], -1, szPassword, 20);
} else {
n = MultiByteToWideChar(0, 0, argv[2], -1, szPassword, 20);
}
if (n == 0)
{
_tprintf( _T("Failed to convert password to unicode\n"));
return -1;
}
}
#endif
// Set up the USER_INFO_1 structure that will be used to create the
// new user account
ZeroMemory( &ui1, sizeof(ui1) );
ui1.usri1_name = szUserName;
ui1.usri1_password = szPassword;
ui1.usri1_priv = USER_PRIV_USER;
ui1.usri1_flags = UF_NORMAL_ACCOUNT | UF_SCRIPT;
// Create the new user account
dwError = NetUserAdd(
NULL, // target computer name
1, // info level
(LPBYTE) &ui1, // address of user info structure
NULL ); // index to invalid parameter
if ( dwError != NERR_Success ) {
_tprintf( _T("NetUserAdd() failed. Error %d\n"), dwError );
dwError = ERROR_ACCESS_DENIED;
return -1;
}
// Do a network logon because most systems do not grant new users
// the right to logon interactively (SE_INTERACTIVE_LOGON_NAME)
// but they do grant the right to do a network logon
// (SE_NETWORK_LOGON_NAME). A network logon has the added advantage
// of being quicker.
// NOTE: To call LogonUser(), the current user must have the
// SE_TCB_NAME privilege
if ( !LogonUser(
argv[1], // user name
_T("."), // domain or server
(argc == 2) ? argv[1]:argv[2], // password
LOGON32_LOGON_NETWORK, // type of logon operation
LOGON32_PROVIDER_DEFAULT, // logon provider
&hToken ) ) { // pointer to token handle
_tprintf( _T("LogonUser() failed. Error %d\n"), GetLastError() );
return -1;
}
// Set up the PROFILEINFO structure that will be used to load the
// new user's profile
ZeroMemory( &pi, sizeof(pi) );
pi.dwSize = sizeof(pi);
#ifdef UNICODE
pi.lpUserName = szUserName;
#else
pi.lpUserName = argv[1];
#endif
pi.dwFlags = PI_NOUI;
// Load the profile. Since it doesn't exist, it will be created
if ( !LoadUserProfile(
hToken, // token for the user
&pi ) ) { // pointer to PROFILEINFO structure
_tprintf( _T("LoadUserProfile() failed. Error %d\n"),
GetLastError() );
return -1;
}
// Unload the profile when it is no longer needed
if ( !UnloadUserProfile(
hToken, // token for the user
pi.hProfile ) ) { // registry key handle
_tprintf( _T("UnloadUserProfile() failed. Error %d\n"),
GetLastError() );
return -1;
}
// Retrieve the new user's profile directory
if ( !GetUserProfileDirectory( hToken, szProfilePath, &cchPath ) ) {
_tprintf( _T("GetProfilePath() failed. Error %d\n"),
GetLastError() );
return -1;
}
// Display the new user's profile directory
_tprintf( _T("The new user's profile path is %s\n"), szProfilePath );
// Release USERENV.DLL
if ( g_hUserEnvLib ) {
FreeLibrary( g_hUserEnvLib );
}
return 0;
}