Fungsi CreateProcessWithLogonW (winbase.h)
Membuat proses baru dan utas utamanya. Kemudian proses baru menjalankan file yang dapat dieksekusi yang ditentukan dalam konteks keamanan kredensial yang ditentukan (pengguna, domain, dan kata sandi). Ini dapat secara opsional memuat profil pengguna untuk pengguna tertentu.
Fungsi ini mirip dengan fungsi CreateProcessAsUser dan CreateProcessWithTokenW , kecuali bahwa pemanggil tidak perlu memanggil fungsi LogonUser untuk mengautentikasi pengguna dan mendapatkan token.
Sintaks
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
Nama pengguna. Ini adalah nama akun pengguna yang akan masuk. Jika Anda menggunakan format UPN, DNS_domain_name pengguna@, parameter lpDomain harus NULL.
Akun pengguna harus memiliki izin Masuk Secara Lokal di komputer lokal. Izin ini diberikan kepada semua pengguna di stasiun kerja dan server, tetapi hanya untuk administrator pada pengendali domain.
[in, optional] lpDomain
Nama domain atau server yang database akunnya berisi akun lpUsername . Jika parameter ini NULL, nama pengguna harus ditentukan dalam format UPN.
[in] lpPassword
Kata sandi teks yang jelas untuk akun lpUsername .
[in] dwLogonFlags
Opsi masuk. Parameter ini bisa 0 (nol) atau salah satu nilai berikut.
[in, optional] lpApplicationName
Nama modul yang akan dijalankan. Modul ini bisa menjadi aplikasi berbasis Windows. Ini bisa menjadi beberapa jenis modul lain (misalnya, MS-DOS atau OS/2) jika subsistem yang sesuai tersedia di komputer lokal.
String dapat menentukan jalur lengkap dan nama file modul yang akan dijalankan atau dapat menentukan nama parsial. Jika ini adalah nama parsial, fungsi menggunakan drive saat ini dan direktori saat ini untuk menyelesaikan spesifikasi. Fungsi ini tidak menggunakan jalur pencarian. Parameter ini harus menyertakan ekstensi nama file; tidak ada ekstensi default yang diasumsikan.
Parameter lpApplicationName dapat berupa NULL, dan nama modul harus menjadi token spasi putih pertama yang dibatasi dalam string lpCommandLine . Jika Anda menggunakan nama file panjang yang berisi spasi, gunakan string yang dikutip untuk menunjukkan di mana nama file berakhir dan argumen dimulai; jika tidak, nama file ambigu.
Misalnya, string berikut dapat ditafsirkan dengan cara yang berbeda:
"c:\program files\sub dir\program name"
Sistem mencoba menafsirkan kemungkinan dalam urutan berikut:
- c:\program.exe files\sub dir\program name
- c:\program files\sub.exe dir\program name
- c:\program files\sub dir\program.exe name
- c:\program files\sub dir\program name.exe
Jika modul yang dapat dieksekusi adalah aplikasi 16-bit, lpApplicationName harus NULL, dan string yang ditunjukkan oleh lpCommandLine harus menentukan modul yang dapat dieksekusi dan argumennya.
[in, out, optional] lpCommandLine
Baris perintah yang akan dijalankan. Panjang maksimum string ini adalah 1024 karakter. Jika lpApplicationNameADALAH NULL, bagian nama modul lpCommandLine terbatas pada MAX_PATH karakter.
Fungsi ini dapat mengubah isi string ini. Oleh karena itu, parameter ini tidak dapat menjadi penunjuk ke memori baca-saja (seperti variabel const atau string literal). Jika parameter ini adalah string konstanta, fungsi dapat menyebabkan pelanggaran akses.
Parameter lpCommandLine dapat berupa NULL, dan fungsi menggunakan string yang ditujukkan oleh lpApplicationName sebagai baris perintah.
Jika lpApplicationName dan lpCommandLinenon-NULL, *lpApplicationName menentukan modul yang akan dijalankan, dan *lpCommandLine menentukan baris perintah. Proses baru dapat menggunakan GetCommandLine untuk mengambil seluruh baris perintah. Proses konsol yang ditulis dalam C dapat menggunakan argumen argc dan argv untuk mengurai baris perintah. Karena argv[0] adalah nama modul, programmer C biasanya mengulangi nama modul sebagai token pertama di baris perintah.
Jika lpApplicationName adalah NULL, token spasi putih pertama yang dibatasi dari baris perintah menentukan nama modul. Jika Anda menggunakan nama file panjang yang berisi spasi, gunakan string yang dikutip untuk menunjukkan di mana nama file berakhir dan argumen dimulai (lihat penjelasan untuk parameter lpApplicationName ). Jika nama file tidak berisi ekstensi, .exe ditambahkan. Oleh karena itu, jika ekstensi nama file .com, parameter ini harus menyertakan ekstensi .com. Jika nama file berakhir dalam titik tanpa ekstensi, atau jika nama file berisi jalur, .exe tidak ditambahkan. Jika nama file tidak berisi jalur direktori, sistem akan mencari file yang dapat dieksekusi dalam urutan berikut:
- Direktori tempat aplikasi dimuat.
- Direktori saat ini untuk proses induk.
- Direktori sistem Windows 32-bit. Gunakan fungsi GetSystemDirectory untuk mendapatkan jalur direktori ini.
- Direktori sistem Windows 16-bit. Tidak ada fungsi yang mendapatkan jalur direktori ini, tetapi dicari.
- Direktori Windows. Gunakan fungsi GetWindowsDirectory untuk mendapatkan jalur direktori ini.
- Direktori yang tercantum dalam variabel lingkungan PATH. Perhatikan bahwa fungsi ini tidak mencari jalur per aplikasi yang ditentukan oleh kunci registri Jalur Aplikasi . Untuk menyertakan jalur per aplikasi ini dalam urutan pencarian, gunakan fungsi ShellExecute .
[in] dwCreationFlags
Bendera yang mengontrol cara proses dibuat. Bendera CREATE_DEFAULT_ERROR_MODE, CREATE_NEW_CONSOLE, dan CREATE_NEW_PROCESS_GROUP diaktifkan secara default. Untuk daftar nilai, lihat Bendera Pembuatan Proses.
Parameter ini juga mengontrol kelas prioritas proses baru, yang digunakan untuk menentukan prioritas penjadwalan utas proses. Untuk daftar nilai, lihat GetPriorityClass. Jika tidak ada bendera kelas prioritas yang ditentukan, kelas prioritas default ke NORMAL_PRIORITY_CLASS kecuali kelas prioritas proses pembuatan IDLE_PRIORITY_CLASS atau BELOW_NORMAL_PRIORITY_CLASS. Dalam hal ini, proses anak menerima kelas prioritas default dari proses panggilan.
Jika parameter dwCreationFlags memiliki nilai 0:
- Proses ini mendapatkan mode kesalahan default, membuat konsol baru dan membuat grup proses baru.
- Blok lingkungan untuk proses baru diasumsikan berisi karakter ANSI (lihat parameter lpEnvironment untuk informasi tambahan).
- Aplikasi berbasis Windows 16-bit berjalan di komputer Virtual DOS (VDM) bersama.
[in, optional] lpEnvironment
Pointer ke blok lingkungan untuk proses baru. Jika parameter ini NULL, proses baru menggunakan lingkungan yang dibuat dari profil pengguna yang ditentukan oleh lpUsername.
Blok lingkungan terdiri dari blok string null-terminated null-terminated. Setiap string dalam bentuk berikut:
Nama=Nilai
Karena tanda sama dengan (=) digunakan sebagai pemisah, tanda tersebut tidak boleh digunakan dalam nama variabel lingkungan.
Blok lingkungan dapat berisi karakter Unicode atau ANSI. Jika blok lingkungan yang diarahkan oleh lpEnvironment berisi karakter Unicode, pastikan bahwa dwCreationFlags menyertakan CREATE_UNICODE_ENVIRONMENT.
Blok lingkungan ANSI dihentikan oleh dua byte 0 (nol): satu untuk string terakhir dan satu lagi untuk mengakhiri blok. Blok lingkungan Unicode dihentikan oleh empat byte nol: dua untuk string terakhir dan dua lagi untuk mengakhiri blok.
Untuk mengambil salinan blok lingkungan untuk pengguna tertentu, gunakan fungsi CreateEnvironmentBlock .
[in, optional] lpCurrentDirectory
Jalur lengkap ke direktori saat ini untuk proses tersebut. String juga dapat menentukan jalur UNC.
Jika parameter ini NULL, proses baru memiliki drive dan direktori saat ini yang sama dengan proses panggilan. Fitur ini disediakan terutama untuk shell yang perlu memulai aplikasi, dan menentukan drive awal dan direktori kerjanya.
[in] lpStartupInfo
Penunjuk ke struktur STARTUPINFO .
Aplikasi harus menambahkan izin untuk akun pengguna yang ditentukan ke stasiun jendela dan desktop yang ditentukan, bahkan untuk WinSta0\Default.
Jika anggota lpDesktop adalah NULL atau string kosong, proses baru mewarisi stasiun desktop dan jendela dari proses induknya. Aplikasi harus menambahkan izin untuk akun pengguna yang ditentukan ke stasiun jendela dan desktop yang diwariskan.
Windows XP: CreateProcessWithLogonW menambahkan izin untuk akun pengguna yang ditentukan ke stasiun jendela dan desktop yang diwariskan.
Handel di STARTUPINFO harus ditutup dengan CloseHandle ketika tidak lagi diperlukan.
[out] lpProcessInformation
Penunjuk ke struktur PROCESS_INFORMATION yang menerima informasi identifikasi untuk proses baru, termasuk handel ke proses.
Handel di PROCESS_INFORMATION harus ditutup dengan fungsi CloseHandle saat tidak diperlukan.
Mengembalikan nilai
Jika fungsi berhasil, nilai yang dikembalikan bukan nol.
Jika fungsi gagal, nilai yang dikembalikan adalah 0 (nol). Untuk mendapatkan informasi kesalahan yang diperluas, hubungi GetLastError.
Perhatikan bahwa fungsi kembali sebelum proses selesai diinisialisasi. Jika DLL yang diperlukan tidak dapat ditemukan atau gagal diinisialisasi, proses dihentikan. Untuk mendapatkan status penghentian proses, panggil GetExitCodeProcess.
Keterangan
Secara default, CreateProcessWithLogonW tidak memuat profil pengguna yang ditentukan ke dalam kunci registri HKEY_USERS . Ini berarti bahwa akses ke informasi dalam kunci registri HKEY_CURRENT_USER mungkin tidak menghasilkan hasil yang konsisten dengan masuk interaktif normal. Anda bertanggung jawab untuk memuat sarang registri pengguna ke HKEY_USERS sebelum memanggil CreateProcessWithLogonW, dengan menggunakan LOGON_WITH_PROFILE, atau dengan memanggil fungsi LoadUserProfile .
Jika parameter lpEnvironment adalah NULL, proses baru menggunakan blok lingkungan yang dibuat dari profil pengguna yang ditentukan oleh lpUserName. Jika variabel HOMEDRIVE dan HOMEPATH tidak diatur, CreateProcessWithLogonW memodifikasi blok lingkungan untuk menggunakan drive dan jalur direktori kerja pengguna.
Saat dibuat, proses baru dan handel utas menerima hak akses penuh (PROCESS_ALL_ACCESS dan THREAD_ALL_ACCESS). Untuk salah satu handel, jika deskriptor keamanan tidak disediakan, handel dapat digunakan dalam fungsi apa pun yang memerlukan handel objek dari jenis tersebut. Ketika deskriptor keamanan disediakan, pemeriksaan akses dilakukan pada semua penggunaan handel berikutnya sebelum akses diberikan. Jika akses ditolak, proses permintaan tidak dapat menggunakan handel untuk mendapatkan akses ke proses atau utas.
Untuk mengambil token keamanan, teruskan handel proses dalam struktur PROCESS_INFORMATION ke fungsi OpenProcessToken .
Proses ini diberi pengidentifikasi proses. Pengidentifikasi valid sampai proses berakhir. Ini dapat digunakan untuk mengidentifikasi proses, atau dapat ditentukan dalam fungsi OpenProcess untuk membuka handel ke proses. Utas awal dalam proses juga diberi pengidentifikasi utas. Ini dapat ditentukan dalam fungsi OpenThread untuk membuka handel ke utas. Pengidentifikasi valid sampai utas berakhir dan dapat digunakan untuk mengidentifikasi utas secara unik dalam sistem. Pengidentifikasi ini dikembalikan dalam PROCESS_INFORMATION.
Utas panggilan dapat menggunakan fungsi WaitForInputIdle untuk menunggu sampai proses baru menyelesaikan inisialisasinya dan menunggu input pengguna tanpa input tertunda. Ini dapat berguna untuk sinkronisasi antara proses induk dan anak, karena CreateProcessWithLogonW kembali tanpa menunggu proses baru selesai inisialisasinya. Misalnya, proses pembuatan akan menggunakan WaitForInputIdle sebelum mencoba menemukan jendela yang terkait dengan proses baru.
Cara yang disukai untuk mematikan proses adalah dengan menggunakan fungsi ExitProcess , karena fungsi ini mengirimkan pemberitahuan tentang penghentian mendekati ke semua DLL yang terpasang pada proses. Cara lain untuk mematikan proses tidak memberi tahu DLL yang terlampir. Perhatikan bahwa ketika utas memanggil ExitProcess, utas proses lainnya dihentikan tanpa kesempatan untuk menjalankan kode tambahan apa pun (termasuk kode penghentian utas DLL yang dilampirkan). Untuk informasi selengkapnya, lihat Mengakhiri Proses.
CreateProcessWithLogonW mengakses direktori yang ditentukan dan gambar yang dapat dieksekusi dalam konteks keamanan pengguna target. Jika gambar yang dapat dieksekusi berada di jaringan dan huruf kandar jaringan ditentukan di jalur, huruf kandar jaringan tidak tersedia untuk pengguna target, karena huruf drive jaringan dapat ditetapkan untuk setiap masuk. Jika huruf kandar jaringan ditentukan, fungsi ini gagal. Jika gambar yang dapat dieksekusi berada di jaringan, gunakan jalur UNC.
Ada batasan jumlah proses anak yang dapat dibuat oleh fungsi ini dan berjalan secara bersamaan. Misalnya, pada Windows XP, batas ini MAXIMUM_WAIT_OBJECTS*4. Namun, Anda mungkin tidak dapat membuat banyak proses ini karena batas kuota di seluruh sistem.
Windows XP dengan SP2, Windows Server 2003, atau yang lebih baru: Anda tidak dapat memanggil CreateProcessWithLogonW dari proses yang berjalan di bawah akun "LocalSystem", karena fungsi menggunakan SID masuk dalam token pemanggil, dan token untuk akun "LocalSystem" tidak berisi SID ini. Sebagai alternatif, gunakan fungsi CreateProcessAsUser dan LogonUser .
Untuk mengkompilasi aplikasi yang menggunakan fungsi ini, tentukan _WIN32_WINNT sebagai 0x0500 atau yang lebih baru. Untuk informasi selengkapnya, lihat Menggunakan Header Windows.
Keterangan Keamanan
Parameter lpApplicationName dapat berupa NULL, dan nama yang dapat dieksekusi harus berupa string yang dibatasi spasi putih pertama di lpCommandLine. Jika nama yang dapat dieksekusi atau jalur memiliki ruang di dalamnya, ada risiko bahwa executable yang berbeda dapat dijalankan karena cara fungsi mengurai spasi. Hindari contoh berikut, karena fungsi mencoba menjalankan "Program.exe", jika ada, alih-alih "MyApp.exe".LPTSTR szCmdline[]=_tcsdup(TEXT("C:\\Program Files\\MyApp"));
CreateProcessWithLogonW(..., szCmdline, ...)
Jika pengguna jahat membuat aplikasi yang disebut "Program.exe" pada sistem, program apa pun yang salah memanggil CreateProcessWithLogonW menggunakan direktori Program Files menjalankan aplikasi pengguna berbahaya alih-alih aplikasi yang dimaksudkan.
Untuk menghindari masalah ini, jangan lulus NULL untuk lpApplicationName. Jika Anda meneruskan NULL untuk lpApplicationName, gunakan tanda kutip di sekitar jalur yang dapat dieksekusi di lpCommandLine, seperti yang ditunjukkan dalam contoh berikut:
LPTSTR szCmdline[]=_tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
CreateProcessWithLogonW(..., szCmdline, ...)
Contoh
Contoh berikut menunjukkan cara memanggil fungsi ini.
#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);
}
Persyaratan
Persyaratan | Nilai |
---|---|
Klien minimum yang didukung | Windows XP [hanya aplikasi desktop] |
Server minimum yang didukung | Windows Server 2003 [hanya aplikasi desktop] |
Target Platform | Windows |
Header | winbase.h (termasuk Windows.h) |
Pustaka | Advapi32.lib |
DLL | Advapi32.dll |