Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss.
 From: Paul Gibson
  Where is Paul Gibson?
 United Kingdom
 Paul Gibson
Subject: Executing when impersonating
Thread ID: 416203 Message ID: 416203 # Views: 49 # Ratings: 0
Version: Visual FoxPro 9 SP2 Category: Win32API programming
Date: Tuesday, December 23, 2014 5:41:20 PM         

In another thread (Message ID: 415315) I asked a question about running applications as another user, especially where the username and password were known so I could semi-elevate tasks. Out of that thread I got two potential methods, one using PsExec which I have successfully implemented and I am happy with. I am having some teething troubles with the other method (using LogonUser(), ImpersonateLoggedOnUser() & RevertToSelf()). I always like to have fall-backs which is why I still want to get the second method working, even though the first method is working nicely.

The second method is described by Bernard in this blog post: https://www.foxite.com/faq/default.aspx?id=48 as a method for opening tables that should only be permitted for certain users as a way of stopping generic users just opening your DBFs. If I was using for that job then that would be fine, however I am trying to use it to then ShellExecute() an application when I am impersonating the other user. What I've found though is that WinAPI calls don't appear to behave as normal when you are impersonating another user.

For example if I impersonate another user and then try to declare the ShellExecute function from Shell32.dll then I get an error:

#1753: Cannot load 32-bit DLL SHELL32.Dll

I came across this before when I was implementing the LogonUser/ImpersonateLoggedOnUser/RevertToSelf facility in the first place as if I didn't declare all three functions before calling them then the DECLARE command would fail. Specifically if I waited until I was impersonating the other user before declaring RevertToSelf. The easy way around that was to ensure all WinAPI calls that I would need while impersonating another user would be DECLAREd before I started the impersonation.

So I tried that again, I ensured that I declared ShellExecute before I began the impersonation but sadly this just pushed the problem back a bit. Now I can declare ShellExecute because I do it early in the process but when I come to call ShellExecute (as the impersonated user) I get an error:

#1753: Cannot load 32-bit DLL c:\windows\system32\shell32.dll

but I've also managed to have it where it appeared to call ShellExecute but ShellExecute returned the number 2 which is an error code meaning: Invalid association or URL but I've not had that for a while, that might be a red-herring, I am mostly getting the Error 1753s. So I can't declare it afterwards and if I declare it before I can't call it afterwards. I obviously can't call if before because that would defeat the purpose of the impersonation so what is causing the problem?

The user I am impersonating is the domain administrator, who has logged onto my machine before and does have admin privileges on my machine and can see the hard drive fine so I'm curious why the error messages appear.

If I specifically load my VFP IDE as that same domain user I have no issue declaring or calling ShellExecute and no issues seeing the files and folders on the hard drive so that does make it look like the user itself is fine it's just when impersonating that user I can't do those things.

I have tried doing the execute using WScript.Shell instead of ShellExecute() but when impersonating I can't instantiate that object either and when instantiating before the impersonation then I get an OLE error code 0x80070542 when I try to call the Run method. I have traced that to a suggestion that the impersonation level is wrong and found this post which may explain what the problem is:


...some further testing seems to indicate that when impersonating another user Windows might lock things down quite tightly. That would suggest it is for security and that would make sense it's just that it makes it a bit more difficult to make this solution work for me.

Here is my test-bed:

Local lnToken, lcUser, lcDomain, lcPassword, lcApplication, loScriptHost, ;
	lnLogonType, lnStatus

* LogonUser Constants
#Define LOGON32_LOGON_BATCH       4
#Define LOGON32_LOGON_UNLOCK      7

Declare Integer LogonUser In AdvApi32.Dll ;
	String szUsername, ;
	String lpszDomain, ;
	String lpszPassword, ;
	Integer dwLogonType, ;
	Integer dwLogonProvider, ;
	Integer @phToken

Declare Integer ImpersonateLoggedOnUser In AdvApi32.Dll ;
	Integer hToken

Declare Integer ShellExecute In SHELL32.Dll ;
	Integer nWinHandle, ;
	String cOperation, ;
	String cFileName, ;
	String cParameters, ;
	String cDirectory, ;
	Integer nShowWindow

Declare Integer RevertToSelf In AdvApi32.Dll

Declare Integer CloseHandle In Kernel32.Dll ;
	Integer HANDLE_hObject

lcUser        = "Tom" && Change Me
lcDomain      = "Dick" && Change Me
lcPassword    = "Harry" && Change Me
lcApplication = "c:\folder\application.exe" && Change Me

loScriptHost = Createobject("WScript.Shell")

lnStatus = LogonUser(lcUser, lcDomain, lcPassword, lnLogonType, LOGON32_PROVIDER_DEFAULT, @lnToken)

If lnStatus > 0
	lnStatus = ImpersonateLoggedOnUser(lnToken)

? ""
? "type", lnLogonType, "status", lnStatus, Sys(0)
? "ShellExecute", ShellExecute(0, "open", lcApplication)
? "Scripting", loScriptHost.Run(lcApplication)
? "c:", Directory("c:\")
? "c:\windows", Directory("c:\windows")
? "c:\windows\system32", Directory("c:\windows\system32")
? "c:\windows\syswow64", Directory("c:\windows\syswow64")

If Vartype(lnToken) = "N" And lnToken > 0

I've tried a lot of things like changing the LogonType different executing methods and on every test I've found that when trying to go outside of VFP when impersonating there are brick walls.

Anyone know if there might be a way around this?


Executing when impersonating Posted by Paul Gibson @ 12/23/2014 5:41:20 PM