views:

141

answers:

1

I'm attempting to use Redmon http://www.winimage.com/misc/redmon/ to send print jobs to a custom C# application. Redmon "runs" (actually the Print Spooler) as SYSTEM but has an option to Run As User to allow your application to run under the user that printed the job. The problem is that it doesn't appear to load the user's environment. So calling functions like Path.GetTempPath() points to \windows\temp instead of the user's. Also when attempting to run Outlook 2007+ via MAPI calls (to add attachments) it reports form errors due to, I think, the temp folder location.

Is there a way to "reload" a profile or atleast get your environment vars within the Impersonated application? The only ideas I've had so far is to rebuild the vars directly from the registry, but I want to avoid this since it's a hack around (avoiding implementation details and all that). Or making a stub program that Redmon calls which then properly Run As User with full profile the custom application.

Any other items or tricks?

+3  A: 

I ended up finding a way to load the user's EnvironmentBlock, extract each variable and load them into my existing environment. Based on code and ideas from several pages:

Excuse my C# code, any tweaks appreciated:

[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(ref IntPtr lpEnvironment, IntPtr hToken, bool bInherit); 

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, ref IntPtr TokenHandle); 
private const uint TOKEN_QUERY = 0x0008; 

[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);

private static void ReloadEnviroVars()
{
  IntPtr hToken = IntPtr.Zero;
  IntPtr envBlock = IntPtr.Zero;

  //Load this user's environment variables
  OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, ref hToken);
  bool retVal = CreateEnvironmentBlock(ref envBlock, hToken, false);

  //Extract each environment variable from the envroblock and add it to
  // our running program's environment vars
  int offset = 0;
  while (true) {
    //EnviroBlock is an array of null-terminated unicode strings
    IntPtr ptr = new IntPtr(envBlock.ToInt32() + offset);
    string Enviro = Marshal.PtrToStringUni(ptr);
    offset += Encoding.Unicode.GetByteCount(Enviro) + 2;
    if (string.IsNullOrEmpty(Enviro))
      break;
    string EnviroKey = Enviro.Substring(0, Enviro.IndexOf("="));
    string EnviroValue = Enviro.Substring(Enviro.IndexOf("=") + 1,  Enviro.Length - 1 - Enviro.IndexOf("="));
    Environment.SetEnvironmentVariable(EnviroKey, EnviroValue);
  }

  CloseHandle(hToken);
}
catfish