另一套备用的代码,通过service调用和登陆用户交互
结合这两个东东,应该差不多可以搞定我需要的事情啦。
因为更改不了service代码,所以希望从service调用的代码里,争脱出来,和本地登陆用户进行交互启动。
#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 service void 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) //遍历进程PID { PROCESSENTRY32 Pc = { sizeof(PROCESSENTRY32) }; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); if(Process32First(hSnapshot, &Pc)) { do { if(!_stricmp(Pc.szExeFile, szExeName)) { //返回explorer.exe进程的PID printf("explorer's PID=%d\n",Pc.th32ProcessID); 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 ,need system permission\n" "\tsession 1 D:\\callsession\\bin\\callsession.exe \n" "==================================\n"); } int main(int argc, char **argv) { ImpersonateActiveUserAndRun(); //遍历所有的session // 函数的句柄 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 函数,通过会话ID得到令牌 typedef BOOL (WINAPI *WTSQueryUserTokenPROC)(ULONG SessionId, PHANDLE phToken ); 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; } //遍历3389登录的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); //释放 if(argc==1) { Usage(); } else if(argc==3) //session 1 c:\win2003\temp\klog.exe { // 得到当前登录用户的令 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(); // 获取当前进程句柄 HANDLE hThisProcess = GetProcessHandle("explorer.exe"); if(hThisProcess == NULL) return 0; printf("hThisProcess %d\n",hThisProcess); // 打开当前进程令牌 OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis); // 复制一个进程令牌,目的是为了修改session id属性,以便在其它session中创建进程 DuplicateTokenEx(hTokenThis, TOKEN_ALL_ACCESS,NULL, SecurityIdentification, TokenPrimary, &hTokenDup); //获取活动session id,这里要注意,如果服务器还没有被登录而使用了远程桌面,这样用是可以的,如果有多个session存在, //不能简单使用此函数,需要枚举所有session并确定你需要的一个,或者干脆使用循环,针对每个session都执行后面的代码 dwSessionId=atoi(argv[1]); //与会话进行连接 bRes = SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD)); //把session id设置到备份的令牌中 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; } // 好了,现在要用新的令牌来创建一个服务进程。注意:是“服务”进程!如果需要以用户身份运行,必须在前面执行LogonUser来获取用户令牌 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; // 注意标志 //CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE); // 创建环境块 // 创建新的进程,这个进程就是你要弹出窗口的进程,它将工作在新的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; }
另一套备用的代码,通过service调用和登陆用户交互的更多相关文章
- 遇到很多次,要注意区分service调用,本地用户调用这些区别
WTSQueryUserToken返回1314 The WTSQueryUserToken function obtains the primary access token of the log ...
- 项目笔记---Windows Service调用Windows API问题
概要 此文来自于最近一个“诡异”的Windows API调用发现Windows Service在调用某些Windows API的过程中失效,在经过漫长的Baidu,之后终于在StackOverFlow ...
- Android 使用代码主动去调用控件的点击事件(模拟人手去触摸控件)
使用代码主动去调用控件的点击事件(模拟人手去触摸控件) //View 可以是LinearLayout,Button,TextView View.performClick();
- 基于CkEditor实现.net在线开发之路(2)编写C#代码,怎么调用它。
上一章简约的介绍了CkEditor编辑器,可以编辑js逻辑代码,css,html,C#代码,这章我根据实际例子,讲解怎么编写C#代码和怎么调用它. 大家都还记得刚刚接触程序编时的hello Word吧 ...
- Reporting Service 没有权限登陆
在配置好Reporting Service之后,登陆Report Mananger( http://localhost/Reports/Pages/Folder.aspx)出现一个异常,本地用户没有权 ...
- MSIL 教程(二):数组、分支、循环、使用不安全代码和如何调用Win32 API(转)
转自:http://www.cnblogs.com/Yahong111/archive/2007/08/16/857574.html 续上文[翻译]MSIL 教程(一) ,本文继续讲解数组.分支.循环 ...
- 用户交互与while循环<代码>
#用户交互1 age_oldboy = 56 guess_age = int(input(">>:")) if guess_age == age_oldboy: pri ...
- C# 脚本代码自动登录淘宝获取用户信息
C# 脚本代码自动登录淘宝获取用户信息 最近遇到的一个需求是如何让程序自动登录淘宝, 获取用户名称等信息. 其实这个利用SS (SpiderStudio的简称) 实现起来非常简单. 十数行代码就可 ...
- java 为什么wait(),notify(),notifyAll()必须在同步(Synchronized)方法/代码块中调用?
wait()作用:该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止.条件:在调用wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法.进入wai ...
随机推荐
- 洛谷 P1037 产生数
题目描述 给出一个整数n(n<10^30)和k个变换规则(k≤15). 规则: 一位数可变换成另一个一位数: 规则的右部不能为零. 例如:n=234.有规则(k=2): 2->53-> ...
- EditText(8)EditText中drawableRight图片的点击事件
参考: http://stackoverflow.com/questions/3554377/handling-click-events-on-a-drawable-within-an-edittex ...
- Geoserver常见问题总结
原文地址 :http://blog.csdn.net/mygisforum/article/details/8249093 http://www.cnblogs.com/wang985850293/p ...
- SQL数据库——静态成员
静态: 1.普通成员普通成员都是属于对象的用对象调用 2.静态成员静态成员是属于类的用类名调用 stactic 静态关键字 静态方法里面不能包含普通成员普通方法里面可以包含静态成员 静态: 1.普通成 ...
- go 语言开发环境的安装与配置
go 语言开发环境的安装与配置 编辑器选择 一直以来都是用sublime,但是听说sublime对于golang的插件支持并不是特别完善,并且VS Code只要在自身所带的扩展商店里安装go插件就可以 ...
- 2105. [NOIP2015] 信息传递
★☆ 输入文件:2015message.in 输出文件:2015message.out 简单对比 时间限制:1 s 内存限制:256 MB [题目描述] 有n个同学(编号为1到n)正在 ...
- PHP开发心得一
1,php获得服务器时间 $time= date('Y-m-d H:i'); echo $time; 一般写法如上,但发现打印出来的时间小时数总数不对,和机器的时间差几个小时.查资料发现,要设定时区. ...
- vuex的各个细节理解(因人而异)
应用级的状态集中放在store中: 改变状态的方式是提交mutations,这是个同步的事物: 异步逻辑应该封装在action中. const vuex_store = new Vuex.store( ...
- 413 Request Entity Too Large报错处理
修改nginx配置 这是最简单的一个做法,着报错原因是nginx不允许上传配置过大的文件,那么件把nginx的上传大小配置调高就好. 1.打开nginx主配置文件nginx.conf,一般在 ...
- 洛谷——P2236 [HNOI2002]彩票
P2236 [HNOI2002]彩票 给你$m$个数,从中挑$n$个数,使得这$n$个数的倒数之和恰好等于$\frac{x}{y}$ 常见的剪纸思路: 如果当前的倒数和加上最小可能的倒数和$>$ ...