CreateProcessWithLogonW-Funktion (winbase.h)
Erstellt einen neuen Prozess und seinen primären Thread. Anschließend führt der neue Prozess die angegebene ausführbare Datei im Sicherheitskontext der angegebenen Anmeldeinformationen (Benutzer, Domäne und Kennwort) aus. Optional kann das Benutzerprofil für einen angegebenen Benutzer geladen werden.
Diese Funktion ähnelt den Funktionen CreateProcessAsUser und CreateProcessWithTokenW , mit dem Unterschied, dass der Aufrufer die Funktion LogonUser nicht aufrufen muss, um den Benutzer zu authentifizieren und ein Token abzurufen.
Syntax
BOOL CreateProcessWithLogonW(
[in] LPCWSTR lpUsername,
[in, optional] LPCWSTR lpDomain,
[in] LPCWSTR lpPassword,
[in] DWORD dwLogonFlags,
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
Parameter
[in] lpUsername
Der Name des Benutzers. Dies ist der Name des Benutzerkontos, bei dem sie sich anmelden möchten. Wenn Sie das UPN-Format verwenden, benutzerseitig@DNS_domain_name, muss der lpDomain-Parameter NULL sein.
Das Benutzerkonto muss auf dem lokalen Computer über die Berechtigung Lokal anmelden verfügen. Diese Berechtigung wird allen Benutzern auf Arbeitsstationen und Servern gewährt, aber nur Administratoren auf Domänencontrollern.
[in, optional] lpDomain
Der Name der Domäne oder des Servers, deren Kontodatenbank das Konto lpUsername enthält. Wenn dieser Parameter NULL ist, muss der Benutzername im UPN-Format angegeben werden.
[in] lpPassword
Das Klartextkennwort für das lpUsername-Konto .
[in] dwLogonFlags
Die Anmeldeoption. Dieser Parameter kann 0 (null) oder einer der folgenden Werte sein.
[in, optional] lpApplicationName
Der Name des auszuführenden Moduls. Dieses Modul kann eine Windows-basierte Anwendung sein. Es kann sich um einen anderen Modultyp (z. B. MS-DOS oder OS/2) handeln, wenn das entsprechende Subsystem auf dem lokalen Computer verfügbar ist.
Die Zeichenfolge kann den vollständigen Pfad und Dateinamen des auszuführenden Moduls angeben oder einen teilweisen Namen angeben. Wenn es sich um einen teilweisen Namen handelt, verwendet die Funktion das aktuelle Laufwerk und das aktuelle Verzeichnis, um die Spezifikation zu erfüllen. Die Funktion verwendet nicht den Suchpfad. Dieser Parameter muss die Dateinamenerweiterung enthalten. es wird keine Standarderweiterung angenommen.
Der parameter lpApplicationName kann NULL sein, und der Modulname muss das erste durch Leerzeichen getrennte Token in der lpCommandLine-Zeichenfolge sein. Wenn Sie einen langen Dateinamen verwenden, der ein Leerzeichen enthält, verwenden Sie Anführungszeichen, um anzugeben, wo der Dateiname endet und die Argumente beginnen. Andernfalls ist der Dateiname mehrdeutig.
Beispielsweise kann die folgende Zeichenfolge auf unterschiedliche Weise interpretiert werden:
"c:\programme\sub dir\program name"
Das System versucht, die Möglichkeiten in folgender Reihenfolge zu interpretieren:
- c:\program.exe Dateien\Unterverzeichnis\Programmname
- c:\program files\sub.exe dir\Programmname
- c:\programme\sub dir\program.exe Name
- c:\programme\sub dir\program name.exe
Wenn es sich bei dem ausführbaren Modul um eine 16-Bit-Anwendung handelt, sollte lpApplicationName NULL sein, und die Zeichenfolge, auf die von lpCommandLine verwiesen wird, sollte das ausführbare Modul und seine Argumente angeben.
[in, out, optional] lpCommandLine
Die auszuführende Befehlszeile. Die maximale Länge dieser Zeichenfolge beträgt 1024 Zeichen. Wenn lpApplicationNameNULL ist, ist der Modulnameteil von lpCommandLine auf MAX_PATH Zeichen beschränkt.
Die Funktion kann den Inhalt dieser Zeichenfolge ändern. Daher kann dieser Parameter kein Zeiger auf schreibgeschützten Arbeitsspeicher (z. B. eine const-Variable oder eine Literalzeichenfolge) sein. Wenn es sich bei diesem Parameter um eine konstante Zeichenfolge handelt, kann die Funktion eine Zugriffsverletzung verursachen.
Der lpCommandLine-Parameter kann NULL sein, und die Funktion verwendet die Zeichenfolge, auf die von lpApplicationName als Befehlszeile verwiesen wird.
Wenn sowohl lpApplicationName als auch lpCommandLine nicht NULL sind, gibt *lpApplicationName das auszuführende Modul an, und *lpCommandLine gibt die Befehlszeile an. Der neue Prozess kann GetCommandLine verwenden, um die gesamte Befehlszeile abzurufen. Konsolenprozesse, die in C geschrieben wurden, können die Argumente argc und argv verwenden, um die Befehlszeile zu analysieren. Da argv[0] der Modulname ist, wiederholen C-Programmierer in der Regel den Modulnamen als erstes Token in der Befehlszeile.
Wenn lpApplicationNameNULL ist, gibt das erste leerzeichentrennte Token der Befehlszeile den Modulnamen an. Wenn Sie einen langen Dateinamen verwenden, der ein Leerzeichen enthält, verwenden Sie Anführungszeichen, um anzugeben, wo der Dateiname endet und die Argumente beginnen (siehe erklärung für den lpApplicationName-Parameter ). Wenn der Dateiname keine Erweiterung enthält, wird .exe angefügt. Wenn die Dateinamenerweiterung .com ist, muss dieser Parameter daher die .com-Erweiterung enthalten. Wenn der Dateiname in einem Punkt ohne Erweiterung endet oder der Dateiname einen Pfad enthält, wird .exe nicht angefügt. Wenn der Dateiname keinen Verzeichnispfad enthält, sucht das System nach der ausführbaren Datei in der folgenden Sequenz:
- Das Verzeichnis, aus dem die Anwendung geladen wurde.
- Das aktuelle Verzeichnis für den übergeordneten Prozess.
- Das 32-Bit-Windows-Systemverzeichnis. Verwenden Sie die GetSystemDirectory-Funktion , um den Pfad dieses Verzeichnisses abzurufen.
- Das 16-Bit-Windows-Systemverzeichnis. Es gibt keine Funktion, die den Pfad dieses Verzeichnisses abruft, aber es wird durchsucht.
- Das Windows-Verzeichnis. Verwenden Sie die GetWindowsDirectory-Funktion , um den Pfad dieses Verzeichnisses abzurufen.
- Die Verzeichnisse, die in der PATH-Umgebungsvariablen aufgeführt sind. Beachten Sie, dass diese Funktion nicht den anwendungsspezifischen Pfad durchsucht, der durch den Registrierungsschlüssel "App Paths" angegeben ist. Verwenden Sie die Funktion ShellExecute , um diesen Pfad pro Anwendung in die Suchsequenz aufzunehmen.
[in] dwCreationFlags
Die Flags, die steuern, wie der Prozess erstellt wird. Die Flags CREATE_DEFAULT_ERROR_MODE, CREATE_NEW_CONSOLE und CREATE_NEW_PROCESS_GROUP sind standardmäßig aktiviert. Eine Liste der Werte finden Sie unter Flags zur Prozesserstellung.
Dieser Parameter steuert auch die Prioritätsklasse des neuen Prozesses, die verwendet wird, um die Planungsprioritäten der Threads des Prozesses zu bestimmen. Eine Liste der Werte finden Sie unter GetPriorityClass. Wenn keines der Prioritätsklassenflags angegeben wird, wird die Prioritätsklasse standardmäßig auf NORMAL_PRIORITY_CLASS festgelegt, es sei denn, die Prioritätsklasse des Erstellungsprozesses ist IDLE_PRIORITY_CLASS oder BELOW_NORMAL_PRIORITY_CLASS. In diesem Fall erhält der untergeordnete Prozess die Standardprioritätsklasse des aufrufenden Prozesses.
Wenn der dwCreationFlags-Parameter den Wert 0 aufweist:
- Der Prozess ruft den Standardfehlermodus ab, erstellt eine neue Konsole und eine neue Prozessgruppe.
- Es wird davon ausgegangen, dass der Umgebungsblock für den neuen Prozess ANSI-Zeichen enthält (weitere Informationen finden Sie unter lpEnvironment-Parameter ).
- Eine 16-Bit-Windows-basierte Anwendung wird auf einem freigegebenen virtuellen DOS-Computer (VDM) ausgeführt.
[in, optional] lpEnvironment
Ein Zeiger auf einen Umgebungsblock für den neuen Prozess. Wenn dieser Parameter NULL ist, verwendet der neue Prozess eine Umgebung, die aus dem Profil des benutzers erstellt wurde, das durch lpUsername angegeben wurde.
Ein Umgebungsblock besteht aus einem null-beendeten Block mit NULL-Zeichenfolgen. Jede Zeichenfolge hat die folgende Form:
Namen=Wert
Da das Gleichheitszeichen (=) als Trennzeichen verwendet wird, darf es nicht im Namen einer Umgebungsvariablen verwendet werden.
Ein Umgebungsblock kann Unicode- oder ANSI-Zeichen enthalten. Wenn der Umgebungsblock, auf den lpEnvironment verweist, Unicode-Zeichen enthält, stellen Sie sicher, dass dwCreationFlagsCREATE_UNICODE_ENVIRONMENT enthält.
Ein ANSI-Umgebungsblock wird durch zwei 0 (null) Bytes beendet: eines für die letzte Zeichenfolge und ein weiteres zum Beenden des Blocks. Ein Unicode-Umgebungsblock wird durch vier Nullbytes beendet: zwei für die letzte Zeichenfolge und zwei weitere, um den Block zu beenden.
Verwenden Sie die Funktion CreateEnvironmentBlock , um eine Kopie des Umgebungsblocks für einen bestimmten Benutzer abzurufen.
[in, optional] lpCurrentDirectory
Der vollständige Pfad zum aktuellen Verzeichnis für den Prozess. Die Zeichenfolge kann auch einen UNC-Pfad angeben.
Wenn dieser Parameter NULL ist, verfügt der neue Prozess über dasselbe aktuelle Laufwerk und Verzeichnis wie der aufrufende Prozess. Dieses Feature wird in erster Linie für Shells bereitgestellt, die eine Anwendung starten und deren Anfängliches Laufwerk und Arbeitsverzeichnis angeben müssen.
[in] lpStartupInfo
Ein Zeiger auf eine STARTUPINFO-Struktur .
Die Anwendung muss der angegebenen Fensterstation und dem angegebenen Desktop berechtigungen für das angegebene Benutzerkonto hinzufügen, auch für WinSta0\Default.
Wenn das lpDesktop-ElementNULL oder eine leere Zeichenfolge ist, erbt der neue Prozess die Desktop- und Fensterstation des übergeordneten Prozesses. Die Anwendung muss der geerbten Fensterstation und dem desktop die Berechtigung für das angegebene Benutzerkonto hinzufügen.
Windows XP: CreateProcessWithLogonW fügt der geerbten Fensterstation und dem desktop die Berechtigung für das angegebene Benutzerkonto hinzu.
Handles in STARTUPINFO müssen mit CloseHandle geschlossen werden, wenn sie nicht mehr benötigt werden.
[out] lpProcessInformation
Ein Zeiger auf eine PROCESS_INFORMATION Struktur, die Identifikationsinformationen für den neuen Prozess empfängt, einschließlich eines Handles für den Prozess.
Handles in PROCESS_INFORMATION müssen mit der CloseHandle-Funktion geschlossen werden, wenn sie nicht benötigt werden.
Rückgabewert
Wenn die Funktion erfolgreich ist, ist der Rückgabewert ungleich Null.
Wenn die Funktion fehlerhaft ist, ist der Rückgabewert 0 (null). Um erweiterte Fehlerinformationen zu erhalten, rufen Sie GetLastError auf.
Beachten Sie, dass die Funktion zurückgibt, bevor die Initialisierung des Prozesses abgeschlossen ist. Wenn eine erforderliche DLL nicht gefunden werden kann oder nicht initialisiert werden kann, wird der Prozess beendet. Rufen Sie GetExitCodeProcess auf, um die beendigung status eines Prozesses zu erhalten.
Hinweise
Standardmäßig lädt CreateProcessWithLogonW das angegebene Benutzerprofil nicht in den HKEY_USERS Registrierungsschlüssel. Dies bedeutet, dass der Zugriff auf Informationen im HKEY_CURRENT_USER Registrierungsschlüssel möglicherweise keine Ergebnisse erzeugt, die mit einer normalen interaktiven Anmeldung konsistent sind. Es liegt in Ihrer Verantwortung, die Benutzerregistrierungsstruktur in HKEY_USERS zu laden, bevor CreateProcessWithLogonW aufgerufen wird, mithilfe von LOGON_WITH_PROFILE oder durch Aufrufen der LoadUserProfile-Funktion .
Wenn der lpEnvironment-Parameter NULL ist, verwendet der neue Prozess einen Umgebungsblock, der aus dem Profil des Benutzers erstellt wurde, das durch lpUserName angegeben wurde. Wenn die Variablen HOMEDRIVE und HOMEPATH nicht festgelegt sind, ändert CreateProcessWithLogonW den Umgebungsblock so, dass er das Laufwerk und den Pfad des Arbeitsverzeichnisses des Benutzers verwendet.
Bei der Erstellung erhalten die neuen Prozess- und Threadhandles Vollzugriffsrechte (PROCESS_ALL_ACCESS und THREAD_ALL_ACCESS). Wenn bei beiden Handles kein Sicherheitsdeskriptor bereitgestellt wird, kann das Handle in jeder Funktion verwendet werden, die ein Objekthandle dieses Typs erfordert. Wenn ein Sicherheitsdeskriptor bereitgestellt wird, wird eine Zugriffsüberprüfung für alle nachfolgenden Verwendungen des Handles durchgeführt, bevor der Zugriff gewährt wird. Wenn der Zugriff verweigert wird, kann der anfordernde Prozess das Handle nicht verwenden, um Zugriff auf den Prozess oder Thread zu erhalten.
Um ein Sicherheitstoken abzurufen, übergeben Sie das Prozesshandle in der PROCESS_INFORMATION-Struktur an die OpenProcessToken-Funktion .
Dem Prozess wird ein Prozessbezeichner zugewiesen. Der Bezeichner ist gültig, bis der Prozess beendet wird. Es kann verwendet werden, um den Prozess zu identifizieren, oder es kann in der OpenProcess-Funktion angegeben werden, um ein Handle für den Prozess zu öffnen. Dem anfänglichen Thread im Prozess wird auch ein Threadbezeichner zugewiesen. Es kann in der OpenThread-Funktion angegeben werden, um ein Handle für den Thread zu öffnen. Der Bezeichner ist gültig, bis der Thread beendet wird, und kann verwendet werden, um den Thread innerhalb des Systems eindeutig zu identifizieren. Diese Bezeichner werden in PROCESS_INFORMATION zurückgegeben.
Der aufrufende Thread kann die WaitForInputIdle-Funktion verwenden, um zu warten, bis der neue Prozess seine Initialisierung abgeschlossen hat und auf Benutzereingaben wartet, ohne dass eine Eingabe aussteht. Dies kann für die Synchronisierung zwischen übergeordneten und untergeordneten Prozessen nützlich sein, da CreateProcessWithLogonW zurückgibt, ohne darauf zu warten, dass der neue Prozess seine Initialisierung abgeschlossen hat. Beispielsweise verwendet der Erstellungsprozess WaitForInputIdle , bevor versucht wird, ein Fenster zu finden, das dem neuen Prozess zugeordnet ist.
Die bevorzugte Möglichkeit zum Herunterfahren eines Prozesses ist die Verwendung der ExitProcess-Funktion , da diese Funktion eine Benachrichtigung über die bevorstehende Beendigung an alle dlLs sendet, die an den Prozess angefügt sind. Andere Mittel zum Herunterfahren eines Prozesses benachrichtigen die angefügten DLLs nicht. Beachten Sie, dass, wenn ein Thread ExitProcess aufruft, andere Threads des Prozesses beendet werden, ohne dass zusätzlichen Code ausgeführt werden kann (einschließlich des Threadabschlusscodes der angefügten DLLs). Weitere Informationen finden Sie unter Beenden eines Prozesses.
CreateProcessWithLogonW greift im Sicherheitskontext des Zielbenutzers auf das angegebene Verzeichnis und das ausführbare Image zu. Wenn sich das ausführbare Image in einem Netzwerk befindet und ein Netzlaufwerkbuchstabe im Pfad angegeben ist, ist der Netzlaufwerkbuchstabe für den Zielbenutzer nicht verfügbar, da für jede Anmeldung Netzlaufwerkbuchstaben zugewiesen werden können. Wenn ein Netzlaufwerkbuchstabe angegeben wird, schlägt diese Funktion fehl. Wenn sich das ausführbare Image in einem Netzwerk befindet, verwenden Sie den UNC-Pfad.
Es gibt eine Beschränkung für die Anzahl der untergeordneten Prozesse, die von dieser Funktion erstellt und gleichzeitig ausgeführt werden können. Unter Windows XP ist dieser Grenzwert beispielsweise MAXIMUM_WAIT_OBJECTS*4. Aufgrund systemweiter Kontingentgrenzwerte können Sie jedoch möglicherweise nicht so viele Prozesse erstellen.
Windows XP mit SP2, Windows Server 2003 oder höher: Sie können CreateProcessWithLogonW nicht aus einem Prozess aufrufen, der unter dem Konto "LocalSystem" ausgeführt wird, da die Funktion die Anmelde-SID im Aufrufertoken verwendet und das Token für das Konto "LocalSystem" diese SID nicht enthält. Alternativ können Sie die Funktionen CreateProcessAsUser und LogonUser verwenden.
Um eine Anwendung zu kompilieren, die diese Funktion verwendet, definieren Sie _WIN32_WINNT als 0x0500 oder höher. Weitere Informationen finden Sie unter Verwenden der Windows-Header.
Sicherheitsbemerkungen
Der parameter lpApplicationName kann NULL sein, und der name der ausführbaren Datei muss die erste leerzeichentrennte Zeichenfolge in lpCommandLine sein. Wenn die ausführbare Datei oder der Pfadname ein Leerzeichen enthält, besteht aufgrund der Art und Weise, wie die Funktion Leerzeichen analysiert, das Risiko, dass eine andere ausführbare Datei ausgeführt werden kann. Vermeiden Sie das folgende Beispiel, da die Funktion versucht, "Program.exe" (sofern vorhanden) anstelle von "MyApp.exe" auszuführen.LPTSTR szCmdline[]=_tcsdup(TEXT("C:\\Program Files\\MyApp"));
CreateProcessWithLogonW(..., szCmdline, ...)
Wenn ein böswilliger Benutzer eine Anwendung namens "Program.exe" auf einem System erstellt, führt jedes Programm, das createProcessWithLogonW fälschlicherweise über das Verzeichnis Programme aufruft, die schädliche Benutzeranwendung anstelle der beabsichtigten Anwendung aus.
Um dieses Problem zu vermeiden, übergeben Sie null nicht für lpApplicationName. Wenn Sie NULL für lpApplicationName übergeben, verwenden Sie anführungszeichen um den ausführbaren Pfad in lpCommandLine, wie im folgenden Beispiel gezeigt:
LPTSTR szCmdline[]=_tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
CreateProcessWithLogonW(..., szCmdline, ...)
Beispiele
Im folgenden Beispiel wird veranschaulicht, wie diese Funktion aufgerufen wird.
#include <windows.h>
#include <stdio.h>
#include <userenv.h>
void DisplayError(LPWSTR pszAPI)
{
LPVOID lpvMessageBuffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&lpvMessageBuffer, 0, NULL);
//
//... now display this string
//
wprintf(L"ERROR: API = %s.\n", pszAPI);
wprintf(L" error code = %d.\n", GetLastError());
wprintf(L" message = %s.\n", (LPWSTR)lpvMessageBuffer);
//
// Free the buffer allocated by the system
//
LocalFree(lpvMessageBuffer);
ExitProcess(GetLastError());
}
void wmain(int argc, WCHAR *argv[])
{
DWORD dwSize;
HANDLE hToken;
LPVOID lpvEnv;
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
WCHAR szUserProfile[256] = L"";
si.cb = sizeof(STARTUPINFO);
if (argc != 4)
{
wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
wprintf(L"\n\n");
return;
}
//
// TO DO: change NULL to '.' to use local account database
//
if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, &hToken))
DisplayError(L"LogonUser");
if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
DisplayError(L"CreateEnvironmentBlock");
dwSize = sizeof(szUserProfile)/sizeof(WCHAR);
if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
DisplayError(L"GetUserProfileDirectory");
//
// TO DO: change NULL to '.' to use local account database
//
if (!CreateProcessWithLogonW(argv[1], NULL, argv[2],
LOGON_WITH_PROFILE, NULL, argv[3],
CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile,
&si, &pi))
DisplayError(L"CreateProcessWithLogonW");
if (!DestroyEnvironmentBlock(lpvEnv))
DisplayError(L"DestroyEnvironmentBlock");
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
Anforderungen
Anforderung | Wert |
---|---|
Unterstützte Mindestversion (Client) | Windows XP [nur Desktop-Apps] |
Unterstützte Mindestversion (Server) | Windows Server 2003 [nur Desktop-Apps] |
Zielplattform | Windows |
Kopfzeile | winbase.h (Windows.h einschließen) |
Bibliothek | Advapi32.lib |
DLL | Advapi32.dll |