The combination of these two things, should almost be able to do what I need.
Because the service code cannot be changed, we want to get out of the code from the service call and start interactively with the local logged-on user.
#include <windows.h> #include <stdio.h> #include <process.h> #include <Tlhelp32.h> #include <tchar.h> #include <psapi.h> #include <stdio.h> #include <stdlib. h> #include <tlhelp32.h> #include <WtsApi32.h> #include <windows.h> #include <stdio.h># Include <Userenv.h> #include <Wtsapi32.h> #pragma comment (lib, "WtsApi32.lib") #pragma comment (lib, "Psapi" #pragma comment (lib, "User32.lib") #pragma comment (lib, "Advapi32.lib") #pragma comment (lib, "Ws2_32.lib") #pragma Comment (lib, "Ws2_32.lib")//function to run a process as active user from Windows Servicevoid impersonateactiveuserandrun ( ) {DWORD session_id =-1; DWORD session_count = 0; Wts_session_infoa *psession = NULL; if (wtsenumeratesessions (wts_current_server_handle, 0, 1, &psession, &session_count)) {printf ("pSession =====%d\n ", psession); printf ("session_count=====%d\n", Session_count); } else {printf ("WtsenumeraTesessions ===============failed \ n "); Return } for (DWORD i = 0; i < Session_count; i++) {session_id = Psession[i]. SessionId; printf ("session_id=====%d\n", session_id); Wts_connectstate_class wts_connect_state = wtsdisconnected; wts_connectstate_class* ptr_wts_connect_state = NULL; DWORD bytes_returned = 0; if (:: Wtsquerysessioninformation (Wts_current_server_handle, session_id, Wtsconnectstate, Reinterpret_cast<lptstr*> (&ptr_wts_connect_state), &bytes_returned)) { Wts_connect_state = *ptr_wts_connect_state; :: Wtsfreememory (Ptr_wts_connect_state); printf ("wts_connect_state=====%d\n", wts_connect_state); if (wts_connect_state! = wtsactive) Continue; } else {printf ("wtsquerysessioninformation ===============failed \ n"); Continue } HANDLE HimpersoNationtoken = 0; BOOL BRet = Wtsqueryusertoken (session_id, &himpersonationtoken); if (BRet = = False) {printf ("Wtsqueryusertoken ERROR:%d\n", GetLastError ()); } printf ("himpersonationtoken=====%d\n", Himpersonationtoken); Get Real token from impersonation token DWORD neededSize1 = 0; HANDLE *realtoken = new HANDLE; if (GetTokenInformation (Himpersonationtoken, (:: Token_information_class) Tokenlinkedtoken, RealToken, sizeof (HANDLE ) (&neededsize1)) {CloseHandle (Himpersonationtoken); Himpersonationtoken = *realtoken; } else {//log error continue; }}}bool Getsessiontoken (DWORD Dwsessionid, char token[256]) {LPTSTR pbuffer = NULL; DWORD Dwbufferlen; BOOL bRes = wtsquerysessioninformation (Wts_current_server_handle, Dwsessionid, Wtsoemid, &pbuffer, & Dwbufferlen); if (BRes = = False) {return false; } lstrcpy (token, pbuffer); Wtsfreememory (pbuffer); return true;} BOOL Getsessionusername (DWORD Dwsessionid, char username[256]) {LPTSTR pbuffer = NULL; DWORD Dwbufferlen; BOOL bRes = wtsquerysessioninformation (Wts_current_server_handle, Dwsessionid, Wtsusername, &pbuffer, & Dwbufferlen); if (BRes = = False) {return false; } lstrcpy (username, pbuffer); Wtsfreememory (pbuffer); return true;} BOOL Getsessiondomain (DWORD Dwsessionid, char domain[256]) {LPTSTR pbuffer = NULL; DWORD Dwbufferlen; BOOL bRes = wtsquerysessioninformation (Wts_current_server_handle, Dwsessionid, Wtsdomainname, &pBuffer, & Dwbufferlen); if (bRes = = FALSE) {printf ("wtsquerysessioninformation fail!\n"); return false; } lstrcpy (Domain,pbuffer); Wtsfreememory (pbuffer); return true;} HANDLE Getprocesshandle (LPSTR szexename)//Traverse process pid{PROCESSENTRY32 Pc = {sizeof (PROCESSENTRY32)}; HANDLE hSnapShot = Createtoolhelp32Snapshot (th32cs_snapall, 0); if (Process32First (hSnapShot, &pc)) {do {if (!_stricmp (Pc.szexefile, Szexename)) {//Return PID printf ("Explorer ' s pid=%d\n", pc.th32processid) of the Explorer.exe process; Return OpenProcess (process_all_access, TRUE, Pc.th32processid); }}while (Process32Next (hSnapShot, &pc)); } return NULL; void Usage (void) {fprintf (stderr, "==============================\n" "\tname:run Programe at any session, nee D system permission\n "" \tsession 1 d:\\callsession\\bin\\callsession.exe \ n "" ===================== =============\n ");} int main (int argc, char **argv) {impersonateactiveuserandrun (); Traverse all the session//function handles hmodule hInstKernel32 = NULL; hmodule hInstWtsapi32 = NULL; typedef DWORD (WINAPI *wtsgetactiveconsolesessionidproc) (); Wtsgetactiveconsolesessionidproc Wtsgetactiveconsolesessionid = NULL; HiNstKernel32 = LoadLibrary ("Kernel32.dll"); if (!hinstkernel32) {return FALSE; } Wtsgetactiveconsolesessionid = (Wtsgetactiveconsolesessionidproc) GetProcAddress (HInstKernel32, " Wtsgetactiveconsolesessionid "); printf ("wtsgetactiveconsolesessionid=====%d\n", Wtsgetactiveconsolesessionid); if (! Wtsgetactiveconsolesessionid) {return FALSE; }//Wtsqueryusertoken function, get token typedef BOOL (WINAPI *wtsqueryusertokenproc) via session ID (ULONG SessionId, Phandle p Htoken); Wtsqueryusertokenproc Wtsqueryusertoken = NULL; HINSTWTSAPI32 = LoadLibrary ("Wtsapi32.dll"); printf ("wtsqueryusertoken=====%d\n", Wtsqueryusertoken); printf ("hinstwtsapi32=====%d\n", hInstWtsapi32); if (!HINSTWTSAPI32) {return FALSE; } Wtsqueryusertoken = (Wtsqueryusertokenproc) GetProcAddress (hInstWtsapi32, "Wtsqueryusertoken"); printf ("wtsqueryusertoken=====%d\n", WtsqueRyusertoken); if (! Wtsqueryusertoken) {return FALSE; }//Traversal 3389 login SESSION:/* typedef struct _WTS_SESSION_INFO {DWORD SessionId; LPTSTR Pwinstationname; Wts_connectstate_class State; }wts_session_info, *pwts_session_info; */Wts_session_info *sessioninfo = NULL; DWORD Sessioninfocount; Char domain1[256]; Char username1[256]; Char token1[256]; BOOL result = wtsenumeratesessions (wts_current_server_handle, 0, 1, &sessioninfo, &sessioninfocount); unsigned int usercount (0); int num=0; for (unsigned int i = 0; i < Sessioninfocount; ++i) {if (Sessioninfo[i]. state = = wtsactive) && (Sessioninfo[i]. state = wtsdisconnected)) {printf ("Session%d information:\n", num++); printf ("\tsessioninfo.sessionid=%d\n", Sessioninfo[i]. SESSIONID); Getsessiondomain (Sessioninfo[i]. SessionId, domain1); printf ("\tsession Domain =%s\n", domain1); Getsessionusername (Sessioninfo[i]. SESSIONID,USERNAME1); printf ("\tsession user ' s name =%s\n", username1); Getsessiontoken (Sessioninfo[i]. SESSIONID,TOKEN1); printf ("\tsession user ' s token =%s\n", token1); HANDLE Himpersonationtoken; if (! Wtsqueryusertoken (Sessioninfo[i]. SessionId, &himpersonationtoken) {printf ("\thimpersonationtoken failed\n"); Continue } DWORD neededSize1 = 0; HANDLE *realtoken = new HANDLE; if (GetTokenInformation (Himpersonationtoken, (:: Token_information_class) Tokenlinkedtoken, RealToken, sizeof (HANDLE ) (&neededsize1)) {CloseHandle (Himpersonationtoken); Himpersonationtoken = *realToken; printf ("\thimpersonationtoken token =%s\n", Himpersonationtoken); } else {printf ("\tgettokeninformation failed\n"); Continue } usercount++; }} printf ("Session ' s number:%d\n\n", UserCount); Wtsfreememory (Sessioninfo); Release if (argc==1) {Usage (); } else if (argc==3)//session 1 C:\win2003\temp\klog.exe {//Gets the current logged on user's order HANDLE htokenthis = NULL; HANDLE htokendup = NULL; hmodule hInstKernel32 = NULL; hmodule hInstWtsapi32 = NULL; BOOL BRes; DWORD Dwsessionid = NULL; /* BRes = Wtsqueryusertoken (Dwsessionid, &htokendup); printf ("Wtsqueryusertoken%d\n", bRes); if (!bres) {printf ("Wtsqueryusertoken failed!%d\n", GetLastError ()); return FALSE; } bRes = ImpersonateLoggedOnUser (htokendUP); if (!bres) {printf ("impersonateloggedonuser!%d\n", GetLastError ()); return FALSE; } MessageBox (NULL, "test2", "Test1", MB_OK); System ("Winver.exe"); *///HANDLE hthisprocess = GetCurrentProcess (); Gets the current process handle HANDLE hthisprocess = Getprocesshandle ("explorer.exe"); if (hthisprocess = = NULL) return 0; printf ("Hthisprocess%d\n", hthisprocess); Open the current process token OpenProcessToken (hthisprocess, token_all_access, &htokenthis); A process token is copied to modify the session ID property to create a process Duplicatetokenex in another session (Htokenthis, Token_all_access,null, securityident Ification, Tokenprimary, &htokendup); To get the event session ID, it is important to note that if the server has not been logged in and uses Remote Desktop, so it is possible, if there are multiple sessions exist,//can not simply use this function, you need to enumerate all the session and determine the one you need, or simply use a loop, Execute the following code Dwsessionid=atoi (Argv[1]) for each session; Connect to session BRes = Settokeninformation (Htokendup, Tokensessionid, &dwsessionid, siZeof (DWORD)); Set the session ID to the backed up token in printf ("Htokenthis:%d\n", htokenthis); printf ("Htokendup:%d\n", htokendup); printf ("Dwsessionid:%d\n", Dwsessionid); printf ("tokensessionid==%d\n", Tokensessionid); if (!bres) {printf ("settokeninformation!%d\n", GetLastError ()); return FALSE; }//OK, now to create a service process with the new token. Note: is the "service" process! If you need to run as a user, you must execute LogonUser in front to get the user token startupinfo si; Process_information Pi; ZeroMemory (&si, sizeof (STARTUPINFO)); ZeroMemory (&pi, sizeof (process_information)); SI.CB = sizeof (STARTUPINFO); Si.lpdesktop = "Winsta0\\default"; LPVOID penv = NULL; DWORD Dwcreationflag = Normal_priority_class | Create_new_console; Note Flag//createenvironmentblock (&penv, Htokendup, FALSE); Create an environment block//Create a new process, this process is the process you want to pop up the window, it will work in the new session Char Path[max_path]; lstrcpy (path,argv[2]); CreateProcessAsUser (Htokendup, NULL, (char *) path, NULL, NULL, FALSE, Dwcreationflag, penv, NULL, &si, &PI); } else {printf ("argc value is:%d", argc); Usage (); } return 0;}
Another set of alternate code, via service call and login user interaction