另一套备用的代码,通过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 ...
随机推荐
- cookie使用详解
cookie是用来保存客户资料的好方法,与同样可以用来保存客户资料的 session不同的是,session是把资料保存在服务器端,而cookie是把资料保存在客户端,我们平常接触的最多的cookie ...
- 图片预览------photoswipe 使用
photoswipe 使用 预览图片后,需要点击关闭按钮才能关闭,点击图片事件效果是放大图片,和微信的效果不一致,最后改用微信预览图片的接口了,但是例子可以用,记录一下!! http://www.cn ...
- Ant安装以及环境配置以及使用[windows环境]
一.安装ant 官方主页http://ant.apache.org下载新版的ant. *下载对应的版本,解压到我们的硬盘. 二.配置环境变量 Window中设置ant环境变量: ANT_HOME ...
- golang 并发锁的陷阱
错误代码示例 package main import ( "sync" "strconv" "fmt" ) type Node struct ...
- arduino 字符解析
Arduino String.h库函数详解 此库中包含1 charAT()2 compareTo()3 concat()4 endsWith()5 equals()6 equalslgnoreCa ...
- C/c++中 数组全局变量的定义声明 与 引用声明
数组声明一次,所有的 定义声明 有切仅有一次! 别人遇到的问题如下: 在声明定义时,定义数组如下: int G_glob[100]; 在其他文件引用时声明如下: int *G_glob; 这样的操 ...
- Spartan6系列之器件引脚功能详述
1. Spartan-6系列封装概述 Spartan-6系列具有低成本.省空间的封装形式,能使用户引脚密度最大化.所有Spartan-6 LX器件之间的引脚分配是兼容的,所有Spartan-6 L ...
- 自定义 Java Annotation ,读取注解值
1. 首先是自定义注解: package cn.veji.hibernate.po; import java.lang.annotation.ElementType; import java.lang ...
- (转) 淘淘商城系列——redis-desktop-manager的使用
http://blog.csdn.net/yerenyuan_pku/article/details/72849791 实际工作环境中,redis会安装在服务器上,我们想使用redis服务就要使用re ...
- swift 工作日志
开发问题汇总: tableview.register(CEImpWalletHomeCell.self, forCellReuseIdentifier: "cell") var c ...