in windows 10, redirect port monitor (redmon), run as user doesn't work

7.2k Views Asked by At

I have a redirected printer port that use redmon (redirect port monitor) with a postscript printer driver to convert postscript to pdf and apply some other effects like watermarks, overlays, etc. In win 7 all work fine but in windows 10 the process run under system user account. In the configuration window of the printer port there is a flag called "Run as user" and in win7, checking this flag let the job running under the user account. In Windows 10 it seems not working. Any suggestion will be very appreciated. Thank you. Roy

1

There are 1 best solutions below

4
On

I had a similar problem. I needed the user that printed the document to select the type of document and a patient ID. Then print the document to our EHR system as a PDF. Works in Windows 7 when "Run as User" is checked, but not on Windows 10. Redmon always runs the program as "SYSTEM". So I added a bit to the beginning of the program to check the user name. If it is "SYSTEM" the program looks for the an interactive user on the system by finding an instance of explorer.exe. If more than one interactive user is logged onto the system this will fail. Not a problem for my task. The program then starts another instance of itself running as the same user as explorer.exe, passing the same command line. A pipe is used so that stdin from the first instance can be piped to stdin on the second instance. Another limitation is that on a 64 bit OS, a 64 bit version of the program must be used. Otherwise explorer.exe may not be found.

The following code is what I placed at the beginning of my program. Don't be fooled by the program starting at main(). I am using a GUII toolkit that has WinMain() in it and then calls main(). I have only tested the code on ASCII programs. I tried to use the ASCII version of calls so that it would work with non-ASCII programs, but I am not sure I got all of them.

The LogInfoSys("Hello World"); function just writes to a log file.

Good luck.

#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <time.h>
#include <direct.h>
#include <process.h>
#include <sqlext.h>
#include <Psapi.h>
#include <tlhelp32.h>

int main(int argc, char *argv[])
{
    int                                         error;
    char                                        msg[1024];

    DWORD                                       *processIDs;
    int                                         processCount;
    HANDLE                                      hProcess = NULL;
    HANDLE                                      hToken;
    char                                        userName[64];
    char                                        progName[1024];
    int                                         i, j;
    char                                        nameMe[256];
    char                                        domainMe[256];
    PTOKEN_USER                                 ptuMe = NULL;
    PROCESS_INFORMATION                         procInfo;
    STARTUPINFO                                 startUpInfo;
    HMODULE                                     *hMod;
    DWORD                                       cbNeeded;
    SECURITY_ATTRIBUTES                         saAttr;
    HANDLE                                      hChildStd_IN_Rd = NULL;
    HANDLE                                      hChildStd_IN_Wr = NULL;

    i = 64;                                 // Get user name, if it is "SYSTEM" redirect input to output to a new instance of the program
    GetUserNameA(userName, &i);
    if (_stricmp(userName, "system") == 0)
    {
        LogInfoSys("Running as SYSTEM");
        processIDs = (DWORD *)calloc(16384, sizeof(DWORD));                             // Look for explorer.exe running.  If found that should be the user we want to run as.
        EnumProcesses(processIDs, sizeof(DWORD) * 16384, &i);                           // If there is more than one that is OK as long as they are both being run by the same
        processCount = i / sizeof(DWORD);                                               // user.  If more than one user is logged on, this will be a problem.

        hMod = (HMODULE *)calloc(4096, sizeof(HMODULE));

        hProcess = NULL;
        for (i = 0; (i < processCount) && (hProcess == NULL); i++)
        {
            if (processIDs[i] == 11276)
                Sleep(0);
            if (processIDs[i] != 0)
            {
                hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
                if (hProcess != NULL)
                {
                    cbNeeded = 0;
                    error = EnumProcessModules(hProcess, hMod, sizeof(HMODULE) * 4096, &cbNeeded);
                    if (error == 0)
                    {
                        error = GetLastError();
                        Sleep(0);
                    }
                    progName[0] = 0;
                    error = GetModuleBaseNameA(hProcess, hMod[0], progName, 1024);
                    if (error == 0)
                    {
                        error = GetLastError();
                        Sleep(0);
                    }
                    if (_stricmp(progName, "explorer.exe") != 0)
                    {
                        CloseHandle(hProcess);
                        hProcess = NULL;
                    }
                    else
                    {
                        LogInfoSys("Found explorer.exe");
                    }
                }
            }
        }

        LogInfoSys("After looking for processes.");
        nameMe[0] = domainMe[0] = 0;
        if (hProcess != NULL)
        {
            saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
            saAttr.bInheritHandle = TRUE;
            saAttr.lpSecurityDescriptor = NULL;

            if (!CreatePipe(&hChildStd_IN_Rd, &hChildStd_IN_Wr, &saAttr, 0))        // Create a pipe for the child process's STDIN.
                LogInfoSys("Stdin CreatePipe error");

            if (!SetHandleInformation(hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))     // Ensure the write handle to the pipe for STDIN is not inherited. 
                LogInfoSys("Stdin SetHandleInformation errir");

            if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken) != 0)
            {
                GetStartupInfo(&startUpInfo);
                startUpInfo.cb = sizeof(STARTUPINFO);
                startUpInfo.lpReserved = NULL;
                startUpInfo.lpDesktop = NULL;
                startUpInfo.lpTitle = NULL;
                startUpInfo.dwX = startUpInfo.dwY = 0;
                startUpInfo.dwXSize = 0;
                startUpInfo.dwYSize = 0;
                startUpInfo.dwXCountChars = 0;
                startUpInfo.dwYCountChars = 0;
                startUpInfo.dwFillAttribute = 0;
                startUpInfo.dwFlags |= STARTF_USESTDHANDLES;
                startUpInfo.wShowWindow = 0;
                startUpInfo.cbReserved2 = 0;
                startUpInfo.lpReserved = NULL;
                startUpInfo.hStdInput = hChildStd_IN_Rd;
                startUpInfo.hStdOutput = NULL;
                startUpInfo.hStdError = NULL;

                GetModuleFileName(NULL, progName, 1024);
                i = CreateProcessAsUserA(hToken, progName, GetCommandLine(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &startUpInfo, &procInfo);
                if (i == 0)
                {
                    i = GetLastError();
                }

                do
                {
                    i = (int)fread(msg, 1, 1024, stdin);
                    if (i > 0)
                        WriteFile(hChildStd_IN_Wr, msg, i, &j, NULL);
                } while (i > 0);
            }
        }
        LogInfoSys("End of running as SYSTEM.");
        exit(0);
    }


    /**********************************************************************************************************
    *
    *   End of running as SYSTEM and start of running as the user that printed the document (I hope).
    *
    **********************************************************************************************************/
    exit(0);
}