?
Solved

How to execute code with current user privilege on the service application.

Posted on 2009-07-08
5
Medium Priority
?
731 Views
Last Modified: 2012-05-07
Hello.
I made a serivce application. ( it is executed with System user account )

When i trying to some jobs on the service application, the code does not work.
Because of service application has limitted privileges.
So, i must made other win32 program which is executed by service application with current logon user system privileges.

I think this way is not efficient. Because i must made another program.

So, I looking for the solution that execute some procedure or function with current logon user privileges at the service application.

For Example)
// Service application body
begin
....
   do_excute_some_code( parameter 1 ); // this procedure will execute with current logon user privileges

end;

Is this possible ???
If you know how to do this, please let me know or give me some example code.

Thanks.
0
Comment
Question by:schiva
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
5 Comments
 
LVL 14

Expert Comment

by:SteveBay
ID: 24813662
I am almost certain you will not be able to change the account under which you are running while running.
Is there a reason why you can not just run the entire service from a user's account with all of the approriate priveleges?

As an alternative you could perhaps write two services and run them under different accounts and have service1 send a message to service2 that will then execute some code but it sounds like alot of work.
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24815866
you need to change to the user you need with impersonate user and then run that task

  if LogonUser(user, domain or empty string , pass, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h) then
  try
    if ImpersonateLoggedOnUser(h) then
    try
      do whatever as user
    finally
      if not RevertToSelf then// either this, or exit the thread
        showmessage(syserrormessage(getlasterror));
    end
    else
      showmessage(syserrormessage(getlasterror));
  finally
    closehandle(h);        
  end;

Open in new window

0
 
LVL 2

Accepted Solution

by:
Wegelin earned 2000 total points
ID: 24912639
I have a class wher you can do both
Run a Process as logged on user  or run Code as loggen on user
Import the Class ProcessAsUser

How you can Start a Process as Logged On User ?

ProcessAsUser.launch("c:\wondos\notepad.exe")


How you run Code as logged On User ?



WindowsImpersonationContext impctx = WindowsIdentity.Impersonate(ProcessAsUser.GetUserToken);

 do_excute_some_code( parameter 1 ); // this procedure will execute with current logon user privileges

impctx.Undo();

Imports System.Runtime.InteropServices
Imports System.Security.Permissions
Imports System.Reflection
Public Class ProcessAsUser
    <StructLayout(LayoutKind.Sequential)> _
Friend Structure PROCESS_INFORMATION
        Public hProcess As IntPtr
        Public hThread As IntPtr
        Public dwProcessId As Int32
        Public dwThreadId As Int32
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure SECURITY_ATTRIBUTES
        Public nLength As Int32
        Public lpSecurityDescriptor As IntPtr
        Public bInheritHandle As Boolean
    End Structure
 
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure STARTUPINFO
        Public cb As Int32
        Public lpReserved As String
        Public lpDesktop As String
        Public lpTitle As String
        Public dwX As Int32
        Public dwY As Int32
        Public dwXSize As Int32
        Public dwYSize As Int32
        Public dwXCountChars As Int32
        Public dwYCountChars As Int32
        Public dwFillAttribute As Int32
        Public dwFlags As Int32
        Public wShowWindow As Short
        Public cbReserved2 As Short
        Public lpReserved2 As IntPtr
        Public hStdInput As IntPtr
        Public hStdOutput As IntPtr
        Public hStdError As IntPtr
    End Structure
 
    Public Enum SECURITY_IMPERSONATION_LEVEL
        SecurityAnonymous
        SecurityIdentification
        SecurityImpersonation
        SecurityDelegation
    End Enum
    Public Enum TOKEN_TYPE
 
        TokenPrimary = 1
 
        TokenImpersonation
    End Enum
 
    Private Shared STANDARD_RIGHTS_REQUIRED As UInteger = 983040
 
    Private Shared STANDARD_RIGHTS_READ As UInteger = 131072
 
    Private Shared TOKEN_ASSIGN_PRIMARY As UInteger = 1
 
    Private Shared TOKEN_DUPLICATE As UInteger = 2
 
    Private Shared TOKEN_IMPERSONATE As UInteger = 4
 
    Private Shared TOKEN_QUERY As UInteger = 8
 
    Private Shared TOKEN_QUERY_SOURCE As UInteger = 16
 
    Private Shared TOKEN_ADJUST_PRIVILEGES As UInteger = 32
 
    Private Shared TOKEN_ADJUST_GROUPS As UInteger = 64
 
    Private Shared TOKEN_ADJUST_DEFAULT As UInteger = 128
 
    Private Shared TOKEN_ADJUST_SESSIONID As UInteger = 256
 
    Private Shared TOKEN_READ As UInteger = (STANDARD_RIGHTS_READ Or TOKEN_QUERY)
    Private Shared TOKEN_ALL_ACCESS As UInteger = (STANDARD_RIGHTS_REQUIRED _
                   Or (TOKEN_ASSIGN_PRIMARY _
                   Or (TOKEN_DUPLICATE _
                   Or (TOKEN_IMPERSONATE _
                   Or (TOKEN_QUERY _
                   Or (TOKEN_QUERY_SOURCE _
                   Or (TOKEN_ADJUST_PRIVILEGES _
                   Or (TOKEN_ADJUST_GROUPS _
                   Or (TOKEN_ADJUST_DEFAULT Or TOKEN_ADJUST_SESSIONID)))))))))
 
    ' Private Declare Auto Function CreateProcessAsUser Lib "advapi32.dll" (ByVal token As IntPtr, ByVal applicationName As String, ByVal commandLine As String, ByRef processAttributes As SECURITY_ATTRIBUTES, ByRef threadAttributes As SECURITY_ATTRIBUTES, ByVal inheritHandles As Boolean, ByVal creationFlags As UInteger, ByVal environment As IntPtr, ByVal currentDirectory As String, ByRef startupInfo As STARTUPINFO, ByRef processInformation As PROCESS_INFORMATION) As Boolean
    Private Declare Auto Function CreateProcessAsUser Lib "advapi32" ( _
      ByVal hToken As IntPtr, _
      ByVal strApplicationName As String, _
      ByVal strCommandLine As String, _
      ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _
      ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
      ByVal bInheritHandles As Boolean, _
      ByVal dwCreationFlags As Integer, _
      ByVal lpEnvironment As IntPtr, _
      ByVal lpCurrentDriectory As String, _
      ByRef lpStartupInfo As STARTUPINFO, _
      ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean
 
    Public Declare Function DuplicateTokenEx Lib "advapi32.dll" (ByVal existingToken As IntPtr, ByVal desiredAccess As UInteger, ByVal tokenAttributes As IntPtr, ByVal impersonationLevel As SECURITY_IMPERSONATION_LEVEL, ByVal tokenType As TOKEN_TYPE, ByRef newToken As IntPtr) As Boolean
    Declare Function CreateEnvironmentBlock Lib "userenv.dll" (ByRef lpEnvironment As IntPtr, ByVal hToken As IntPtr, ByVal bInherit As Boolean) As Boolean
    Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, ByRef TokenHandle As IntPtr) As Boolean
    Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
 
    Declare Function DestroyEnvironmentBlock Lib "userenv.dll" (ByVal lpEnvironment As IntPtr) As Boolean
    Private Const SW_SHOW As Short = 5
    Private Const SW_SHOWMAXIMIZED As Short = 7
    ' Private Const TOKEN_QUERY = 8
    'Private Const TOKEN_DUPLICATE = 2
    'Private Const TOKEN_ASSIGN_PRIMARY = 1
    Private Const GENERIC_ALL_ACCESS = 268435456
    Private Const STARTF_USESHOWWINDOW = 1
    Private Const STARTF_FORCEONFEEDBACK = 64
    Private Const CREATE_UNICODE_ENVIRONMENT = 1024
    Public Shared ErrStr As String = ""
 
    Private Shared Function LaunchProcessAsUser(ByVal cmdLine As String, ByVal _
      token As IntPtr, ByVal envBlock As IntPtr) As Boolean
        Dim result As Boolean = False
        Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
        Dim saProcess As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
        Dim saThread As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
 
        saProcess.nLength = Marshal.SizeOf(saProcess)
        saThread.nLength = Marshal.SizeOf(saThread)
        Dim si As STARTUPINFO = New STARTUPINFO
        si.cb = Marshal.SizeOf(si)
        'si.lpDesktop = "WinSta0\Default"
        si.lpDesktop = Nothing
        si.dwFlags = STARTF_USESHOWWINDOW Or STARTF_FORCEONFEEDBACK
        si.wShowWindow = SW_SHOW
        result = CreateProcessAsUser(token, cmdLine, "", saProcess, saThread, _
          False, CREATE_UNICODE_ENVIRONMENT, envBlock, Nothing, si, pi)
        If result = False Then
            Dim iError As Integer = Marshal.GetLastWin32Error
            ErrStr = String.Format("CreateProcessAsUser Error:" & _
              "{0}", iError)
            ' Debug.WriteLine(message)
        Else
            CloseHandle(token)
        End If
        Return result
    End Function
 
    Private Shared Function GetPrimaryToken(ByVal processId As Integer) As  _
      IntPtr
        Dim token As IntPtr = IntPtr.Zero
        Dim primaryToken As IntPtr = IntPtr.Zero
        Dim retVal As Boolean = False
        Dim p As Process = Nothing
        Try
            p = Process.GetProcessById(processId)
        Catch generatedExceptionVariable0 As ArgumentException
            Dim details As String = String.Format("ProcessID {0} Not" & _
              "Available", processId)
            Debug.WriteLine(details)
            Return primaryToken
        End Try
        retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, token)
        If retVal = True Then
            Dim sa As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
            sa.nLength = Marshal.SizeOf(sa)
            retVal = DuplicateTokenEx(token, TOKEN_ASSIGN_PRIMARY Or _
              TOKEN_DUPLICATE Or TOKEN_QUERY, IntPtr.Zero, CType( _
              SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Integer), _
              CType(TOKEN_TYPE.TokenPrimary, Integer), primaryToken)
            If retVal = False Then
                ErrStr = String.Format("DuplicateTokenEx Error:" & _
                  "{0}", Marshal.GetLastWin32Error)
 
                'Debug.WriteLine(message)
            End If
        Else
            ErrStr = String.Format("OpenProcessToken Error:" & _
              "{0}", Marshal.GetLastWin32Error)
            'Debug.WriteLine(message)
        End If
        Return primaryToken
    End Function
 
    Private Shared Function GetEnvironmentBlock(ByVal token As IntPtr) As IntPtr
        Dim envBlock As IntPtr = IntPtr.Zero
        Dim retVal As Boolean = CreateEnvironmentBlock(envBlock, token, False)
        If retVal = False Then
            Dim message As String = String.Format("CreateEnvironmentBlock" & _
              "Error: {0}", Marshal.GetLastWin32Error)
            ' Debug.WriteLine(message)
        End If
        Return envBlock
    End Function
 
    Public Shared Function Launch(ByVal appCmdLine As String) As Boolean
        Dim ret As Boolean = False
        Dim ps As Process() = Process.GetProcessesByName("explorer")
        Dim processId As Integer = -1
        If ps.Length > 0 Then
            processId = ps(0).Id
        End If
        If processId > 1 Then
            Dim token As IntPtr = GetPrimaryToken(processId)
            If Not (token.Equals(IntPtr.Zero)) Then
                Dim envBlock As IntPtr = GetEnvironmentBlock(token)
                ret = LaunchProcessAsUser(appCmdLine, token, envBlock)
                If Not (envBlock.Equals(IntPtr.Zero)) Then
                    DestroyEnvironmentBlock(envBlock)
                End If
            End If
        End If
        Return ret
    End Function
    Public Shared Function GetUserToken() As IntPtr
        ErrStr = ""
        Dim token As IntPtr
        Dim ps As Process() = Process.GetProcessesByName("explorer")
        Dim processId As Integer = -1
        If ps.Length > 0 Then
            processId = ps(0).Id
        End If
        If processId > 1 Then
            token = GetPrimaryToken(processId)
 
        End If
 
        Return token
    End Function
 
    Public Sub New()
        MyBase.New()
    End Sub
End Class

Open in new window

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 25138086
lol, mlmcc
accepting a VB solution in a Delphi zone

ahh, there is general programming languages too
0

Featured Post

Get real performance insights from real users

Key features:
- Total Pages Views and Load times
- Top Pages Viewed and Load Times
- Real Time Site Page Build Performance
- Users’ Browser and Platform Performance
- Geographic User Breakdown
- And more

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Suggested Courses

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question