callsession新功能版

可以getopt解析参数。

也实现了将参数用空格分隔,来传给进程。

注意string和LPSTR数据类型的转换方法:

LPSTR(lpCmdLine.c_str())

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <Userenv.h>
#include <Wtsapi32.h>
#pragma comment(lib, "WtsApi32.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "userenv.lib")
using namespace std;

#define EPR                 fprintf(stderr,
#define ERR(str, chr)       if(opterr){EPR "%s%c\n", str, chr);}
int     opterr = 1;
int     optind = 1;
int    optopt;
char    *optarg;

int getopt (int argc, char *const argv[], char *opts)
{
    static int sp = 1;
    int c;
    char *cp;

    if (sp == 1)
        if (optind >= argc ||
           argv[optind][0] != ‘-‘ || argv[optind][1] == ‘\0‘)
            return -1;
        else if (strcmp(argv[optind], "--") == 0) {
            optind++;
            return -1;
        }
    optopt = c = argv[optind][sp];
    if (c == ‘:‘ || (cp=strchr(opts, c)) == 0) {
        ERR (": illegal option -- ", c);
        if (argv[optind][++sp] == ‘\0‘) {
            optind++;
            sp = 1;
        }
        return ‘?‘;
    }
    if (*++cp == ‘:‘) {
        if (argv[optind][sp+1] != ‘\0‘)
            optarg = &argv[optind++][sp+1];
        else if (++optind >= argc) {
            ERR (": option requires an argument -- ", c);
            sp = 1;
            return ‘?‘;
        } else
            optarg = argv[optind++];
        sp = 1;
    } else {
        if (argv[optind][++sp] == ‘\0‘) {
            sp = 1;
            optind++;
        }
        optarg = 0;
    }
    return c;
}

HANDLE GetUserToken(DWORD dwSessionId)
{
    HANDLE hImpersonationToken = 0;
    if (!WTSQueryUserToken(dwSessionId, &hImpersonationToken))
    {
        printf(" WTSQueryUserToken ERROR: %d\n", GetLastError());
        return FALSE;
    }
    DWORD dwNeededSize = 0;
    HANDLE *realToken = new HANDLE;
    TOKEN_USER *pTokenUser = NULL;
    PTOKEN_GROUPS pGroups = NULL;
    //twice call function
    if (!GetTokenInformation(hImpersonationToken, TokenUser, NULL, 0, &dwNeededSize))
    {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && dwNeededSize > 0)
        {
            pTokenUser = (TOKEN_USER*)new BYTE[dwNeededSize];
            if (!GetTokenInformation(hImpersonationToken, TokenUser, pTokenUser, dwNeededSize, &dwNeededSize))
            {
                printf("GetTokenInformation ERROR: %d", GetLastError());
            }
        }
        return hImpersonationToken;
    }
    return hImpersonationToken;
}

bool GetSessionUserName(DWORD dwSessionId, char username[256])
{
    LPTSTR pBuffer = NULL;
    DWORD dwBufferLen;
    if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionId, WTSUserName, &pBuffer, &dwBufferLen))
    {
        printf(" WTSQuerySessionInformation ERROR: %d\n", GetLastError());
        return FALSE;
    }
    lstrcpy(username ,pBuffer);
    WTSFreeMemory(pBuffer);
    return TRUE;
}

void Usage(void)
{
    printf("**********************usage******************\n");
    printf("USAGE: path:\\callsession.exe sxxxn path-exe-file arg1 arg2 arg3 ... \n");
    printf("**********************usage******************\n");
}

int main(int argc, char** argv)
{
    if(argc == 1)
    {
        Usage();
        return FALSE;
    }
    else if(argc > 1)
    {
        /* get opt comment if we need [email protected] at 2016-08-23
        int c;

        while ((c = getopt(argc, argv, "MNOVv+I:D:U:F:lg")) != -1)
            switch (c) {
            case ‘N‘:

                break;
            case ‘I‘:
                puts(optarg);

                break;
            case ‘D‘:
            case ‘U‘:
                puts(optarg);
                break;
            case ‘M‘:

                break;
            case ‘v‘:

                break;
            case ‘V‘:

                break;
            case ‘+‘:

                break;
            default:
                break;
            }
        */
        int i;
        string lpCmdLine = "";
        LPSTR lpUsername;
        DWORD session_id = -1;
        DWORD session_count = 0;
        WTS_SESSION_INFOA *pSession = NULL;
        char username[256];
        BOOL blFound = FALSE;
        lpUsername = argv[1];
        // add all $2 $3 $4 $5 ... as second argument to program.
        for (i=2; i < argc; i++)
        {
            // printf("argument %d is %s.\n", i, argv[i]);
            lpCmdLine += argv[i];
            lpCmdLine += " ";
        }
        // printf("argument is %s\n", lpCmdLine);

        //EnumerateSessions
        if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
        {
            printf("WTSEnumerateSessions ERROR: %d", GetLastError());
            return FALSE;
        }
        //Get the right user and his session id
        for(DWORD i = 0; i < session_count; ++i)
        {
            GetSessionUserName(pSession[i].SessionId,username);
            //if( (pSession[i].State == WTSActive) && (pSession[i].State != WTSDisconnected) )
            if(!strcmp(lpUsername, username))
            {
                printf("\tSession user name = %s\n",username);
                session_id = pSession[i].SessionId;
                printf("\tsession_id = %d\n",session_id);
                blFound = TRUE;
                break;
            }
        }
        if (!blFound){
            printf("No login username %s found.", lpUsername);
            return FALSE;
        }
        WTSFreeMemory(pSession); //free meme heap
        //Duplicate User Token
        HANDLE hTokenThis = GetUserToken(session_id);
        HANDLE hTokenDup = NULL;
        if (!DuplicateTokenEx(hTokenThis, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
        {
            printf("DuplicateTokenEx ERROR: %d\n", GetLastError());
            return FALSE;
        }
        if (!SetTokenInformation(hTokenDup, TokenSessionId, &session_id, sizeof(DWORD)))
        {
             printf("SetTokenInformation Error === %d\n",GetLastError());
             return FALSE;
        }
        //init this process info
        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);
        if (!CreateProcessAsUser(hTokenDup, NULL, LPSTR(lpCmdLine.c_str()), NULL, NULL, FALSE, dwCreationFlag, NULL, NULL, &si, &pi))
        {
            printf("CreateProcessAsUser Error === %d\n",GetLastError());
            return FALSE;
        }
        printf("%s--%s--%s", lpUsername, LPSTR(lpCmdLine.c_str()), "OK");
    }

    return 0;
}

  

时间: 2024-08-26 15:47:35

callsession新功能版的相关文章

VS2015预览版中的C#6.0 新功能(二)

VS2015预览版中的C#6.0 新功能(一) VS2015预览版中的C#6.0 新功能(三) 自动属性的增强 只读自动属性 以前自动属性必须同时提供setter和getter方法,因而只读属性只能通过先声明field,然后property只提供getter方法来实现,无法通过自动属性来实现.在c#6.0中,可以通过如下的形式声明只读的自动属性: public string FirstName { get; } 对于只读的自动属性,其backing field是readonly的,其值可以在属性

Android Studio 2.3 正式版新功能,你不来看看?!

2017.3.3 Google老大发布了Android Studio 2.3正式版. 在许多2.3beta版本的基础上修复了bug然后推出了正式版.提供了一些新特性,和对部分已有功能的修改完善. Build Instant Run Improvements and UI Changes 之前的版本,会默认勾选上Instant Run 选项,然后在控制面板上只有一个Run 和Debug按钮.编译器自动判断是否需要Instant Run.2.3.0正式版在控制面板上多出了一个Instant Run按

即将到来的Autodesk 主要产品2015版 产品和API新功能在线培训(免费)

一年一度的Autodesk主要产品和API在线培训课程在5月份即将開始.我们呈献给大家5个课程. 1. Revit 2015 产品新功能及API 概览 2. Vault 2015产品新功能及API 概要 3. AutoCAD 2015产品新功能及API 概要 4. Civil3D 2015产品新功能及API 概要 5. Inventor 2015产品新功能及API 概要 报名參加请到这个页面去了解具体信息,请登记报名.课程免费參加,仅仅要有网络就能够參加. Revit API课程在5月16日下午

微软发布了一系列网络安全新功能(关于Windows和Office 365)

微软在旧金山召开的大规模RSA安全会议中发布了一系列新的网络安全功能,Windows和Office 365的新功能旨在帮助企业实现网络安全. 在Windows前端增加了使用Windows Hello的本地Active Directory功能,并允许Windows 10系统登录.微软还推出了新的工具,通过向企业提供将组织策略迁移到云托管的工具来帮助他们更好的使用移动设备来管理产品.(InfoWorld:你需要正确设置Windows 10组策略.新的操作系统:终极Windows 10 Survivo

Docker 1.12.0将要发布的新功能

导读 按计划,6/14 是1.12.0版本的 feature冻结 的日子,再有两个星期Docker 1.12.0也该发布了.这里列出来的新功能,都是已经合并到主分支的功能,不出意外,下一个版本的Docker应该是能体验到了. 下周2016 DockerCon也该开始了,好像也有一场专门来讲Docker新特性的,不过在这之前,我们就可以抢先一步,浏览一下这些新功能.新特性.尤其是前两个,都是比较吸引人的功能. Swarmkit集成 前几天Docker刚刚发布了 Swarmkit ,也就是Swarm

Atitit.&#160;visual&#160;studio&#160;vs2003&#160;vs2005&#160;vs2008&#160;&#160;VS2010&#160;vs2012&#160;vs2015新特性&#160;新功能.doc

Atitit. visual studio vs2003 vs2005 vs2008  VS2010 vs2012 vs2015新特性 新功能.doc 1.1. Visual Studio2 1.2. Visual Studio 972 1.3. Visual Studio 6.02 1.4. Vs20022 1.5. Vs20032 1.6. Vs20052 1.6.1. 数据访问  Web开发     Windows Forms 方面的开发特性增强2 1.6.2. Refactoring 2

Red Hat Enterprise Linux 7的新功能

?? 简介红帽最新版本的旗舰平台交付显著增强的可用性. 性能和可靠性. 丰富的新功能为架构. 系统管理员和开发人员提供所需的资源以更高效地进行创新和管理.架构师: 红帽® 企业 Linux® 7 适合您选择的任意基础架构, 它可以高效地与其他操作环境. 身份验证和管理系统集成到一起. 无论您是要构建网络密集型应用程序. 可大规模扩展的数据资料库, 亦或是一次构建而成但会频繁部署的并在物理. 虚拟和云环境中表现良好的解决方案, 红帽企业 Linux 7 都提供了必要的功能来支持您的项目.系统管理员

WSS存储服务器(Windows Storage Server) 2012新功能解析

虽然最近一段时间有关微软的新闻大多数集中在Windows 8以及Surface平板设备身上,但数周之前Windows Server 2012新版本中所包含的Windows Storage Server 2012同样值得我们关注.这款产品分类两个版本,工作组版与标准版.工作组版本主要针对小型用户群组,授权许可中将其业务连接数量上限设置为250个.它同时也对底层硬件做出限制,要求用户使用单CPU插槽.最高32GB内存及最多六块磁盘驱动器. 其标准版则在功能与特性方面与Windows Server 2

MySQL Database on Azure新功能

本月中国版的MySQL Database on Azure发布了两项新功能: 1.主从复制——只读实例 在这之前Azure上的MySQL数据库也是支持主从复制的,但是只能作为on-premises部署的MySQL的slave实例——Azure上的MySQL数据库是不可以作为master来使用的. 经过本次更新,我们可以给Azure上的MySQL数据库创建一个或者多个slave实例,即:只读实例. 这样就方便用户为使用MySQL的应用实施读写分离,例如:从slave中检索报表.同时也进一步提高了M