Fungsi CreateProcessAsUserA (processthreadsapi.h)
Membuat proses baru dan utas utamanya. Proses baru berjalan dalam konteks keamanan pengguna yang diwakili oleh token yang ditentukan.
Biasanya, proses yang memanggil fungsi CreateProcessAsUser harus memiliki hak istimewa SE_INCREASE_QUOTA_NAME dan mungkin memerlukan hak istimewa SE_ASSIGNPRIMARYTOKEN_NAME jika token tidak dapat ditetapkan. Jika fungsi ini gagal dengan ERROR_PRIVILEGE_NOT_HELD (1314), gunakan fungsi CreateProcessWithLogonW sebagai gantinya. CreateProcessWithLogonW tidak memerlukan hak istimewa khusus, tetapi akun pengguna yang ditentukan harus diizinkan untuk masuk secara interaktif. Umumnya, yang terbaik adalah menggunakan CreateProcessWithLogonW untuk membuat proses dengan kredensial alternatif.
Sintaks
BOOL CreateProcessAsUserA(
[in, optional] HANDLE hToken,
[in, optional] LPCSTR lpApplicationName,
[in, out, optional] LPSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCSTR lpCurrentDirectory,
[in] LPSTARTUPINFOA lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
Parameter
[in, optional] hToken
Handel ke token utama yang mewakili pengguna. Handel harus memiliki hak akses TOKEN_QUERY, TOKEN_DUPLICATE, dan TOKEN_ASSIGN_PRIMARY . Untuk informasi selengkapnya, lihat Hak Akses untuk Objek Access-Token. Pengguna yang diwakili oleh token harus telah membaca dan menjalankan akses ke aplikasi yang ditentukan oleh lpApplicationName atau parameter lpCommandLine .
Untuk mendapatkan token utama yang mewakili pengguna yang ditentukan, panggil fungsi LogonUser . Atau, Anda dapat memanggil fungsi DuplicateTokenEx untuk mengonversi token peniruan menjadi token utama. Ini memungkinkan aplikasi server yang meniru klien untuk membuat proses yang memiliki konteks keamanan klien.
Jika hToken adalah versi terbatas dari token utama pemanggil, hak istimewa SE_ASSIGNPRIMARYTOKEN_NAME tidak diperlukan. Jika hak istimewa yang diperlukan belum diaktifkan, CreateProcessAsUser memungkinkannya selama panggilan. Untuk informasi selengkapnya, lihat Menjalankan dengan Hak Istimewa.
Layanan Terminal: Proses ini dijalankan dalam sesi yang ditentukan dalam token. Secara default, ini adalah sesi yang sama yang disebut LogonUser. Untuk mengubah sesi, gunakan fungsi SetTokenInformation .
[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. Dalam kasus nama parsial, fungsi menggunakan drive saat ini dan direktori saat ini untuk menyelesaikan spesifikasi. Fungsi tidak akan menggunakan jalur pencarian. Parameter ini harus menyertakan ekstensi nama file; tidak ada ekstensi default yang diasumsikan.
Parameter lpApplicationName dapat berupa NULL. Dalam hal ini, nama modul harus menjadi token pertama yang dibatasi spasi putih 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, pertimbangkan string "c:\program files\sub dir\program name". String ini dapat ditafsirkan dalam sejumlah cara. Sistem mencoba menafsirkan kemungkinan dalam urutan berikut:
c:\program.exec:\program files\sub.exec:\program files\sub dir\program.exec:\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 serta argumennya. Secara default, semua aplikasi berbasis Windows 16-bit yang dibuat oleh CreateProcessAsUser dijalankan dalam VDM terpisah (setara dengan CREATE_SEPARATE_WOW_VDM di CreateProcess).
[in, out, optional] lpCommandLine
Baris perintah yang akan dijalankan. Panjang maksimum string ini adalah 32K karakter. Jika lpApplicationName adalah NULL, bagian nama modul dari lpCommandLine terbatas pada MAX_PATH karakter.
Versi Unicode dari fungsi ini, CreateProcessAsUserW, dapat mengubah konten 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. Dalam hal ini, fungsi menggunakan string yang diacu 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 umumnya mengulangi nama modul sebagai token pertama di baris perintah.
Jika lpApplicationName adalah NULL, token spasi putih pertama 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 berakhiran 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, optional] lpProcessAttributes
Penunjuk ke struktur SECURITY_ATTRIBUTES yang menentukan pendeskripsi keamanan untuk objek proses baru dan menentukan apakah proses anak dapat mewarisi handel yang dikembalikan ke proses. Jika lpProcessAttributes adalah NULL atau lpSecurityDescriptor adalah NULL, prosesnya mendapatkan pendeskripsi keamanan default dan handel tidak dapat diwariskan. Deskriptor keamanan default adalah dari pengguna yang dirujuk dalam parameter hToken . Deskriptor keamanan ini mungkin tidak mengizinkan akses untuk pemanggil, dalam hal ini proses mungkin tidak dibuka lagi setelah dijalankan. Handel proses valid dan akan terus memiliki hak akses penuh.
[in, optional] lpThreadAttributes
Penunjuk ke struktur SECURITY_ATTRIBUTES yang menentukan deskriptor keamanan untuk objek utas baru dan menentukan apakah proses anak dapat mewarisi handel yang dikembalikan ke utas. Jika lpThreadAttributes adalah NULL atau lpSecurityDescriptor adalah NULL, utas mendapatkan deskriptor keamanan default dan handel tidak dapat diwariskan. Deskriptor keamanan default adalah dari pengguna yang dirujuk dalam parameter hToken . Deskriptor keamanan ini mungkin tidak mengizinkan akses untuk pemanggil.
[in] bInheritHandles
Jika parameter ini TRUE, setiap handel yang dapat diwariskan dalam proses panggilan diwariskan oleh proses baru. Jika parameter adalah FALSE, handel tidak diwariskan. Perhatikan bahwa handel yang diwariskan memiliki nilai dan hak akses yang sama dengan handel asli. Untuk diskusi tambahan tentang handel yang dapat diwariskan, lihat Keterangan.
Layanan Terminal: Anda tidak dapat mewarisi handel di seluruh sesi. Selain itu, jika parameter ini TRUE, Anda harus membuat proses dalam sesi yang sama dengan pemanggil.
Proses Cahaya Proses Terlindungi (PPL): Pewarisan handel generik diblokir ketika proses PPL membuat proses non-PPL karena PROCESS_DUP_HANDLE tidak diizinkan dari proses non-PPL ke proses PPL. Lihat Keamanan Proses dan Hak Akses
[in] dwCreationFlags
Bendera yang mengontrol kelas prioritas dan pembuatan proses. 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 mewarisi mode kesalahan pemanggil dan konsol induk.
- 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 bersama (VDM).
[in, optional] lpEnvironment
Pointer ke blok lingkungan untuk proses baru. Jika parameter ini NULL, proses baru menggunakan lingkungan proses panggilan.
Blok lingkungan terdiri dari blok string null-terminated dari string yang dihentikan null. Setiap string dalam bentuk berikut:
Nama=value\0
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.
Versi ANSI dari fungsi ini, CreateProcessAsUserA gagal jika ukuran total blok lingkungan untuk proses melebihi 32.767 karakter.
Perhatikan bahwa blok lingkungan ANSI dihentikan oleh dua byte nol: satu untuk string terakhir, satu lagi untuk mengakhiri blok. Blok lingkungan Unicode dihentikan oleh empat byte nol: dua untuk string terakhir, dua lagi untuk mengakhiri blok.
Windows Server 2003 dan Windows XP: Jika ukuran variabel lingkungan pengguna dan sistem gabungan melebihi 8192 byte, proses yang dibuat oleh CreateProcessAsUser tidak lagi berjalan dengan blok lingkungan yang diteruskan ke fungsi oleh proses induk. Sebaliknya, proses anak berjalan dengan blok lingkungan yang dikembalikan oleh fungsi CreateEnvironmentBlock .
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 akan memiliki drive dan direktori saat ini yang sama dengan proses pemanggilan. (Fitur ini disediakan terutama untuk shell yang perlu memulai aplikasi dan menentukan drive awal dan direktori kerjanya.)
[in] lpStartupInfo
Penunjuk ke struktur STARTUPINFO atau STARTUPINFOEX .
Pengguna harus memiliki akses penuh ke stasiun jendela dan desktop yang ditentukan. Jika Anda ingin prosesnya interaktif, tentukan winsta0\default. Jika anggota lpDesktop adalah NULL, proses baru mewarisi desktop dan stasiun jendela dari proses induknya. Jika anggota ini adalah string kosong, "", proses baru terhubung ke stasiun jendela menggunakan aturan yang dijelaskan dalam Koneksi Proses ke Stasiun Jendela.
Untuk mengatur atribut yang diperluas, gunakan struktur STARTUPINFOEX dan tentukan EXTENDED_STARTUPINFO_PRESENT dalam parameter dwCreationFlags .
Handel di STARTUPINFO atau STARTUPINFOEX harus ditutup dengan CloseHandle ketika tidak lagi diperlukan.
[out] lpProcessInformation
Penunjuk ke struktur PROCESS_INFORMATION yang menerima informasi identifikasi tentang proses baru.
Handel di PROCESS_INFORMATION harus ditutup dengan CloseHandle saat tidak lagi diperlukan.
Mengembalikan nilai
Jika fungsi berhasil, nilai yang dikembalikan bukan nol.
Jika fungsi gagal, nilai yang dikembalikan adalah 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
CreateProcessAsUser harus dapat membuka token utama proses panggilan dengan hak akses TOKEN_DUPLICATE dan TOKEN_IMPERSONATE .
Secara default, CreateProcessAsUser membuat proses baru pada stasiun jendela noninteraktif dengan desktop yang tidak terlihat dan tidak dapat menerima input pengguna. Untuk mengaktifkan interaksi pengguna dengan proses baru, Anda harus menentukan nama stasiun jendela interaktif default dan desktop, "winsta0\default", di anggota lpDesktop dari struktur STARTUPINFO . Selain itu, sebelum memanggil CreateProcessAsUser, Anda harus mengubah daftar kontrol akses diskresi (DACL) dari stasiun jendela interaktif default dan desktop default. DACL untuk stasiun jendela dan desktop harus memberikan akses ke pengguna atau sesi masuk yang diwakili oleh parameter hToken .
CreateProcessAsUser tidak memuat profil pengguna yang ditentukan ke dalam kunci registri HKEY_USERS . Oleh karena itu, untuk mengakses informasi di kunci registri HKEY_CURRENT_USER , Anda harus memuat informasi profil pengguna ke dalam HKEY_USERS dengan fungsi LoadUserProfile sebelum memanggil CreateProcessAsUser. Pastikan untuk memanggil UnloadUserProfile setelah proses baru keluar.
Jika parameter lpEnvironment adalah NULL, proses baru mewarisi lingkungan proses panggilan. CreateProcessAsUser tidak secara otomatis memodifikasi blok lingkungan untuk menyertakan variabel lingkungan khusus untuk pengguna yang diwakili oleh hToken. Misalnya, variabel USERNAME dan USERDOMAIN diwarisi dari proses panggilan jika lpEnvironment adalah NULL. Anda bertanggung jawab untuk menyiapkan blok lingkungan untuk proses baru dan menentukannya di lpEnvironment.
Fungsi CreateProcessWithLogonW dan CreateProcessWithTokenW mirip dengan CreateProcessAsUser, kecuali bahwa pemanggil tidak perlu memanggil fungsi LogonUser untuk mengautentikasi pengguna dan mendapatkan token.
CreateProcessAsUser memungkinkan Anda mengakses direktori yang ditentukan dan gambar yang dapat dieksekusi dalam konteks keamanan pemanggil atau pengguna target. Secara default, CreateProcessAsUser mengakses direktori dan gambar yang dapat dieksekusi dalam konteks keamanan pemanggil. Dalam hal ini, jika penelepon tidak memiliki akses ke direktori dan gambar yang dapat dieksekusi, fungsi gagal. Untuk mengakses direktori dan gambar yang dapat dieksekusi menggunakan konteks keamanan pengguna target, tentukan hToken dalam panggilan ke fungsi ImpersonateLoggedOnUser sebelum memanggil CreateProcessAsUser.
Proses ini diberi pengidentifikasi proses. Pengidentifikasi valid sampai proses berakhir. Ini dapat digunakan untuk mengidentifikasi proses, atau ditentukan dalam fungsi OpenProcess untuk membuka handel ke proses. Utas awal dalam proses ini 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 dalam sistem secara unik. Pengidentifikasi ini dikembalikan dalam struktur PROCESS_INFORMATION .
Utas panggilan dapat menggunakan fungsi WaitForInputIdle untuk menunggu sampai proses baru selesai diinisialisasi dan menunggu input pengguna tanpa input tertunda. Ini dapat berguna untuk sinkronisasi antara proses induk dan anak, karena CreateProcessAsUser kembali tanpa menunggu proses baru menyelesaikan 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 mendekati penghentian ke semua DLL yang terpasang pada proses. Cara lain untuk mematikan proses tidak memberi tahu DLL yang terpasang. Perhatikan bahwa ketika utas memanggil ExitProcess, utas proses lainnya dihentikan tanpa kesempatan untuk menjalankan kode tambahan apa pun (termasuk kode penghentian utas DARI DLL yang dilampirkan). Untuk informasi selengkapnya, lihat Mengakhiri Proses.
Secara default, meneruskan TRUE sebagai nilai parameter bInheritHandles menyebabkan semua handel yang dapat diwariskan diwariskan oleh proses baru. Ini bisa bermasalah untuk aplikasi yang membuat proses dari beberapa utas secara bersamaan namun menginginkan setiap proses untuk mewarisi handel yang berbeda. Aplikasi dapat menggunakan fungsi UpdateProcThreadAttributeList dengan parameter PROC_THREAD_ATTRIBUTE_HANDLE_LIST untuk menyediakan daftar handel yang akan diwarisi oleh proses tertentu.
Keterangan Keamanan
Parameter lpApplicationName dapat berupa NULL, dalam hal ini nama yang dapat dieksekusi harus menjadi string berbatas 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. Contoh berikut berbahaya karena fungsi akan mencoba menjalankan "Program.exe", jika ada, alih-alih "MyApp.exe". LPTSTR szCmdline[] = _tcsdup(TEXT("C:\\Program Files\\MyApp"));
CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/ );
Jika pengguna jahat membuat aplikasi yang disebut "Program.exe" pada sistem, program apa pun yang salah memanggil CreateProcessAsUser menggunakan direktori Program Files akan menjalankan aplikasi ini alih-alih aplikasi yang dimaksudkan.
Untuk menghindari masalah ini, jangan lulus NULL untuk lpApplicationName. Jika Anda melewati NULL untuk lpApplicationName, gunakan tanda kutip di sekitar jalur yang dapat dieksekusi di lpCommandLine, seperti yang ditunjukkan pada contoh di bawah ini.
LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/);
Powershell: Ketika fungsi CreateProcessAsUser digunakan untuk mengimplementasikan cmdlet di PowerShell versi 2.0, cmdlet beroperasi dengan benar untuk sesi jarak jauh fan-in dan fan-out. Namun, karena skenario keamanan tertentu, cmdlet yang diterapkan dengan CreateProcessAsUser hanya beroperasi dengan benar di PowerShell versi 3.0 untuk sesi jarak jauh fan-in; sesi jarak jauh fan-out akan gagal karena hak istimewa keamanan klien yang tidak memadai. Untuk menerapkan cmdlet yang berfungsi untuk sesi jarak jauh fan-in dan fan-out di PowerShell versi 3.0, gunakan fungsi CreateProcess .
Contoh
Misalnya, lihat Memulai Proses Klien Interaktif.
Catatan
Header processthreadsapi.h mendefinisikan CreateProcessAsUser sebagai alias yang secara otomatis memilih versi ANSI atau Unicode dari fungsi ini berdasarkan definisi konstanta praprosesor UNICODE. Mencampur penggunaan alias encoding-netral dengan kode yang tidak mengodekan-netral dapat menyebabkan ketidakcocokan yang mengakibatkan kesalahan kompilasi atau runtime. Untuk informasi selengkapnya, lihat Konvensi untuk Prototipe Fungsi.
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 | processthreadsapi.h (termasuk Windows.h) |
Pustaka | Advapi32.lib |
DLL | Advapi32.dll |