I'm searching for the solution for hours, but the documentation being sparse, I'm unable to find what I need.
If I have a file or a directory, how can I, in C# with P/Invoke, duplicate the permissions (ie. the owner and SIDs with their permissions) from one file to another or from one directory to another, assuming that those files and directories are either on the same machine or the network controlled by the same Active Directory server?
Here's an example using GetNamedSecurityInfo and
SetNamedSecurityInfo.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
namespace PermissionsExample
{
class Program
{
static void Main(string[] args)
{
string source = "C:\\source.txt";
string dest = "C:\\dest.txt";
string result = CopyPermissions(source, dest);
if (!string.IsNullOrEmpty(result)) { Console.WriteLine(result); }
else { Console.WriteLine("SUCCESS"); }
}
public static string CopyPermissions(string source_file, string dest_file)
{
string errmsg = string.Empty;
IntPtr sidOwner = IntPtr.Zero;
IntPtr sidOwnerDescriptor = IntPtr.Zero;
IntPtr sidGroup = IntPtr.Zero;
IntPtr sidGroupDescriptor = IntPtr.Zero;
IntPtr dacl = IntPtr.Zero;
IntPtr daclDescriptor = IntPtr.Zero;
IntPtr sacl = IntPtr.Zero;
try
{
int result = GetNamedSecurityInfo(source_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfos.DiscretionaryAcl, out sidOwner, out sidGroup, out dacl, out sacl, out daclDescriptor);
if (result != 0)
{
Win32Exception e = new Win32Exception(result);
errmsg = "ERROR: " + e.Message;
return errmsg;
}
result = GetNamedSecurityInfo(source_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfos.Owner, out sidOwner, out sidGroup, out dacl, out sacl, out sidGroupDescriptor);
if (result != 0)
{
Win32Exception e = new Win32Exception(result);
errmsg = "ERROR: " + e.Message;
return errmsg;
}
result = GetNamedSecurityInfo(source_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfos.Group, out sidOwner, out sidGroup, out dacl, out sacl, out sidGroupDescriptor);
if (result != 0)
{
Win32Exception e = new Win32Exception(result);
errmsg = "ERROR: " + e.Message;
return errmsg;
}
SecurityInfos info = SecurityInfos.DiscretionaryAcl | SecurityInfos.Group | SecurityInfos.Owner;
result = SetNamedSecurityInfo(dest_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, info, sidOwner, sidGroup, dacl, sacl);
if (result != 0)
{
Win32Exception e = new Win32Exception(result);
errmsg = "ERROR: " + e.Message;
return errmsg;
}
}
finally
{
if (sidOwnerDescriptor != IntPtr.Zero && LocalFree(sidOwnerDescriptor) != IntPtr.Zero)
{
int err = Marshal.GetLastWin32Error();
Win32Exception e = new Win32Exception(err);
errmsg += "ERROR: " + e.Message;
}
if (sidGroupDescriptor != IntPtr.Zero && LocalFree(sidGroupDescriptor) != IntPtr.Zero)
{
int err = Marshal.GetLastWin32Error();
Win32Exception e = new Win32Exception(err);
errmsg += "ERROR: " + e.Message;
}
if (daclDescriptor != IntPtr.Zero && LocalFree(daclDescriptor) != IntPtr.Zero)
{
int err = Marshal.GetLastWin32Error();
Win32Exception e = new Win32Exception(err);
errmsg += "ERROR: " + e.Message;
}
}
return errmsg;
}
public enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY
}
[DllImport("advapi32.dll", EntryPoint = "GetNamedSecurityInfoW", ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern int GetNamedSecurityInfo(string objectName, SE_OBJECT_TYPE objectType,
System.Security.AccessControl.SecurityInfos securityInfo, out IntPtr sidOwner,
out IntPtr sidGroup, out IntPtr dacl, out IntPtr sacl, out IntPtr securityDescriptor);
[DllImport("advapi32.dll", EntryPoint = "SetNamedSecurityInfoW", ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern int SetNamedSecurityInfo(string objectName, SE_OBJECT_TYPE objectType,
System.Security.AccessControl.SecurityInfos securityInfo, IntPtr sidOwner,
IntPtr sidGroup, IntPtr dacl, IntPtr sacl);
[DllImport("kernel32.dll", EntryPoint = "LocalFree", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr LocalFree(IntPtr hMem);
}
}
Related
I have done a virtual printer by using some sample code. But I don't know how to get data from it when it starts printing.
When it starts printing It gives notification that ERROR IN PRITNING.
And Why there is "C:/MyLocalPort.txt".
Anyone Help me to get data this virtual printer sets to print.
Here is the Sample Code:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Management;
namespace virtualPrinter
{
public static class PrinterClass // class which carries SetDefaultPrinter function
{
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetDefaultPrinter(string Printer);
}
class myPrinterClass
{
public static void getPrinterNames()
{
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
MessageBox.Show(printer);
}
}
public static void installPrinter(string printerName) //works on win 7,8,8.1,10 on both x84 and x64
{
Winspool.AddLocalPort(#"C:\MyLocalPort.txt");
//https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/rundll32-printui
// /if Installs a printer by using an .inf file.
// /b[name] Specifies the base printer name.
// /#[file] Specifies a command-line argument file and directly inserts the text in that file into the command line.
// /f[file] Species the Universal Naming Convention (UNC) path and name of the .inf file name or the output file name, depending on the task that you are performing. Use /F[file] to specify a dependent .inf file.
// /r[port] Specifies the port name.
// /m[model] Specifies the driver model name. (This value can be specified in the .inf file.)
string arg;
arg = "printui.dll , PrintUIEntry /if /b " + "\"" + printerName + "\"" + #" /f C:\Windows\inf\ntprint.inf /r " + "\"" + #"C:\MyLocalPort.txt" + "\"" + " /m " + "\"" + "Generic / Text Only" + "\""; //initial arg
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = "rundll32.exe";
p.Arguments = arg;
p.WindowStyle = ProcessWindowStyle.Hidden;
try
{
Process.Start(p);
MessageBox.Show(printerName + " installed succesfully!");
}
catch (Exception ex)
{
MessageBox.Show("Something went wrong. Try again!" );
}
}
public static bool printerExists(string printerName)
{
bool res = false;
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
if (printer == printerName)
{
res = true;
}
}
return res;
}
public static void uninstallPrinter(string printerName)
{
string arg;
ProcessStartInfo p = new ProcessStartInfo();
arg = "printui.dll, PrintUIEntry /dl /n " + "\"" + printerName + "\"";
if (printerExists(printerName))
{
p.FileName = "rundll32.exe";
p.Arguments = arg;
p.WindowStyle = ProcessWindowStyle.Hidden;
try
{
Process.Start(p);
MessageBox.Show(printerName + " unistalled successfully");
}
catch (Exception ex)
{
MessageBox.Show(ex.InnerException.ToString());
}
p = null;
}
}
public static string GetLocalIPAddress() //erxomeno feature
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("No network adapters with an IPv4 address in the system!");
}
public static class Winspool
{
[StructLayout(LayoutKind.Sequential)]
private class PRINTER_DEFAULTS
{
public string pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[DllImport("winspool.drv", EntryPoint = "XcvDataW", SetLastError = true)]
private static extern bool XcvData(
IntPtr hXcv,
[MarshalAs(UnmanagedType.LPWStr)] string pszDataName,
IntPtr pInputData,
uint cbInputData,
IntPtr pOutputData,
uint cbOutputData,
out uint pcbOutputNeeded,
out uint pwdStatus);
[DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true)]
private static extern int OpenPrinter(
string pPrinterName,
ref IntPtr phPrinter,
PRINTER_DEFAULTS pDefault);
[DllImport("winspool.drv", EntryPoint = "ClosePrinter")]
private static extern int ClosePrinter(IntPtr hPrinter);
public static int AddLocalPort(string portName)
{
PRINTER_DEFAULTS def = new PRINTER_DEFAULTS();
def.pDatatype = null;
def.pDevMode = IntPtr.Zero;
def.DesiredAccess = 1; //Server Access Administer
IntPtr hPrinter = IntPtr.Zero;
int n = OpenPrinter(",XcvMonitor Local Port", ref hPrinter, def);
if (n == 0)
return Marshal.GetLastWin32Error();
if (!portName.EndsWith("\0"))
portName += "\0"; // Must be a null terminated string
// Must get the size in bytes. Rememeber .NET strings are formed by 2-byte characters
uint size = (uint)(portName.Length * 2);
// Alloc memory in HGlobal to set the portName
IntPtr portPtr = Marshal.AllocHGlobal((int)size);
Marshal.Copy(portName.ToCharArray(), 0, portPtr, portName.Length);
uint needed; // Not that needed in fact...
uint xcvResult; // Will receive de result here
XcvData(hPrinter, "AddPort", portPtr, size, IntPtr.Zero, 0, out needed, out xcvResult);
ClosePrinter(hPrinter);
Marshal.FreeHGlobal(portPtr);
return (int)xcvResult;
}
}
}
}
Ok, I Can't do this that way.
First I have to create a port monitor I have used mfilemon.dll
Then I created a port with that port monitor
Then Pasted All Driver files in System Driver Dictionary.
Then finally Added Printer And Done.
You can refer this
https://github.com/Gohulan/Virtual-Printer/blob/main/PrinterSetup/SpoolerHelper.cs
This contains all the steps to create a virtual printer to make a print to pdf virtual printer
I am trying to start a process with CreateProcessAsUser and works fine BUT in case a command line arguments is present the function fails and the last error is set to ERROR_UNKNOWN_REVISION.
I have tried multiple combinations for command line with no luck.
Here is the code
var CMD_ARGS = Environment.GetCommandLineArgs();
string FILE_NAME = EntryPoint.PRCOESS_FILE_NAME;
string WORKING_DIRECTORY = EntryPoint.PROCESS_DIRECTORY;
string ARGUMENTS = CMD_ARGS.Skip(1).Aggregate((first,next)=> ' ' + first + ' ' + next);
IntPtr USER_TOKEN = IntPtr.Zero;
IntPtr ENVIRONMENT=IntPtr.Zero;
try
{
var consoleSession = Kernel32.WTSGetActiveConsoleSessionId();
if (consoleSession == 0xFFFFFFFF)
return;
if (!Wtsapi32.WTSQueryUserToken(consoleSession, out USER_TOKEN))
throw new Win32Exception();
if (!Userenv.CreateEnvironmentBlock(out ENVIRONMENT, USER_TOKEN, true))
throw new Win32Exception();
//initialize structures
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.nLength = Marshal.SizeOf(sa);
//initialize startup
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
//initialize process info
var PROCESS_INFO = new PROCESS_INFORMATION();
int dwCreationFlags = NORMAL_PRIORITY_CLASS | (int)(PROCESS_CREATE_FLAG.CREATE_NEW_CONSOLE | PROCESS_CREATE_FLAG.CREATE_UNICODE_ENVIRONMENT);
if (!AdvApi32.CreateProcessAsUser(USER_TOKEN,
FILE_NAME,
ARGUMENTS,
ref sa,
ref sa,
true,
dwCreationFlags,
ENVIRONMENT,
WORKING_DIRECTORY,
ref si,
out PROCESS_INFO))
throw new Win32Exception();
if (PROCESS_INFO.hThread != IntPtr.Zero)
{
ClientProcessId = PROCESS_INFO.dwProcessId;
ClientSessionId = consoleSession;
Trace.WriteLine($"{PROCESS_INFO.dwProcessId}");
}
}
catch(Exception ex)
{
throw;
}
finally
{
Userenv.DestroyEnvironmentBlock(ENVIRONMENT);
Kernel32.CloseHandle(USER_TOKEN);
}
I have a folder in Windows Server with subfolders and ≈50000 files. When I click the right mouse button and choose delete (or shift+delete) – all files are deleted in 10-20 seconds.
When I delete files using code – 1500-4000 seconds.
Delete large number of files – don't work for me.
My code:
string folderPath = #"C://myFolder";
DirectoryInfo folderInfo = new DirectoryInfo(folderPath);
folderInfo.Delete(true); // true - recursive, with sub-folders
How to delete files faster?
A much faster way to delete files is to use the Windows functions instead of the .NET ones.
You will need to first import the function:
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteFile(string lpFileName);
And then you can do this:
string[] files = Directory.EnumerateFiles(path, "*". SearchOption.AllDirectories);
foreach (string file in files)
{
DeleteFile(file);
}
Once the files are deleted, which is the slowest part by using the managed APIs, you can call Directory.DeleteFolder(path, true) to delete the empty folders.
Since the question is actually about deleting network shared folders and it's stated that the explorer based delete is much faster than the C# internal delete mechanism, it might help to just invoke a windows shell based delete.
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C rd /s /q \"<your-path>\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
Ofcourse, you have to replace <your-path>.
However, I don't have the infrastructure and files available to test the performance myself right now.
Not quite sure why the method DirectoryInfo.Delete() takes too much time when deleting folders that have a lot of files and sub-folders. I suspect that the method may also do quite a few things that are unnecessary.
I write a small class to to use Win API without doing too many unnecessary things to test my idea. It takes about 40 seconds to delete a folder that have 50,000 files and sub-folders. So, hope it helps.
I use this PowerScript to generate the testing files.
$folder = "d:\test1";
For ($i=0; $i -lt 50000; $i++)
{
New-Item -Path $folder -Name "test$i.txt" -ItemType "file" -Value $i.ToString();
}
The following is the code in C#.
using System;
using System.Collections.Generic;
//
using System.Runtime.InteropServices;
using System.IO;
//
namespace TestFileDelete
{
class FileDelete
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct WIN32_FIND_DATAW
{
public FileAttributes dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public UInt32 nFileSizeHigh; // DWORD
public UInt32 nFileSizeLow; // DWORD
public UInt32 dwReserved0; // DWORD
public UInt32 dwReserved1; // DWORD
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public String cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public String cAlternateFileName;
};
static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr FindFirstFileW(String lpFileName, out WIN32_FIND_DATAW lpFindFileData);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern Boolean FindNextFileW(IntPtr hFindFile, out WIN32_FIND_DATAW lpFindFileData);
[DllImport("kernel32.dll")]
private static extern Boolean FindClose(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean DeleteFileW(String lpFileName); // Deletes an existing file
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern Boolean RemoveDirectoryW(String lpPathName); // Deletes an existing empty directory
// This method check to see if the given folder is empty or not.
public static Boolean IsEmptyFolder(String folder)
{
Boolean res = true;
if (folder == null && folder.Length == 0)
{
throw new Exception(folder + "is invalid");
}
WIN32_FIND_DATAW findFileData;
String searchFiles = folder + #"\*.*";
IntPtr searchHandle = FindFirstFileW(searchFiles, out findFileData);
if (searchHandle == INVALID_HANDLE_VALUE)
{
throw new Exception("Cannot check folder " + folder);
}
do
{
if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
{
// found a sub folder
if (findFileData.cFileName != "." && findFileData.cFileName != "..")
{
res = false;
break;
}
} // if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
else
{
// found a file
res = false;
break;
}
} while (FindNextFileW(searchHandle, out findFileData));
FindClose(searchHandle);
return res;
} // public static Boolean IsEmptyFolder(String folder)
// This method deletes the given folder
public static Boolean DeleteFolder(String folder)
{
Boolean res = true;
// keep non-empty folders to delete later (after we delete everything inside)
Stack<String> nonEmptyFolder = new Stack<String>();
String currentFolder = folder;
do
{
Boolean isEmpty = false;
try
{
isEmpty = IsEmptyFolder(currentFolder);
}
catch (Exception ex)
{
// Something wrong
res = false;
break;
}
if (!isEmpty)
{
nonEmptyFolder.Push(currentFolder);
WIN32_FIND_DATAW findFileData;
IntPtr searchHandle = FindFirstFileW(currentFolder + #"\*.*", out findFileData);
if (searchHandle != INVALID_HANDLE_VALUE)
{
do
{ // for each folder, find all of its sub folders and files
String foundPath = currentFolder + #"\" + findFileData.cFileName;
if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
{
// found a sub folder
if (findFileData.cFileName != "." && findFileData.cFileName != "..")
{
if (IsEmptyFolder(foundPath))
{ // found an empty folder, delete it
if (!(res = RemoveDirectoryW(foundPath)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
else
{ // found a non-empty folder
nonEmptyFolder.Push(foundPath);
}
} // if (findFileData.cFileName != "." && findFileData.cFileName != "..")
} // if ((findFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
else
{
// found a file, delete it
if (!(res = DeleteFileW(foundPath)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
} while (FindNextFileW(searchHandle, out findFileData));
FindClose(searchHandle);
} // if (searchHandle != INVALID_HANDLE_VALUE)
}// if (!IsEmptyFolder(folder))
else
{
if (!(res = RemoveDirectoryW(currentFolder)))
{
Int32 error = Marshal.GetLastWin32Error();
break;
}
}
if (nonEmptyFolder.Count > 0)
{
currentFolder = nonEmptyFolder.Pop();
}
else
{
currentFolder = null;
}
} while (currentFolder != null && res);
return res;
} // public static Boolean DeleteFolder(String folder)
};
class Program
{
static void Main(string[] args)
{
DateTime t1 = DateTime.Now;
try
{
Boolean b = FileDelete.DeleteFolder(#"d:\test1");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
DateTime t2 = DateTime.Now;
TimeSpan ts = t2 - t1;
Console.WriteLine(ts.Seconds);
}
}
}
i am trying to track active Application/File on my system using Windows application(c#).
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
private string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString() + " " + handle;
}
return null;
}
private string GetActiveWindowPath()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
int handleint = int.Parse(handle + "");
SHDocVw.ShellWindows explorer = new SHDocVw.ShellWindows();
//var xy = new SHDocVw.InternetExplorerMedium();
var xpl = explorer.Cast<SHDocVw.InternetExplorerMedium>().Where(hwnd => hwnd.HWND == handleint).FirstOrDefault();
if (xpl != null)
{
string path = new Uri(xpl.LocationURL).LocalPath;
return ("location:" + xpl.LocationName + " path:" + path);
}
return "HWND" + handleint;
}
But by using the above code i only getting file title not the complete file name with extension and by using other method i am just getting folder info.
But i am trying to get the file extension with path
Eg: D:\New Folder\sampleFile.txt
public static string GetMainModuleFilepath(int processId)
{
string wmiQueryString = "SELECT * FROM Win32_Process WHERE ProcessId = " + processId;
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
{
using (var results = searcher.Get())
{
ManagementObject mo = results.Cast<ManagementObject>().FirstOrDefault();
if (mo != null)
{
return (string)mo["CommandLine"];
}
}
}
Process testProcess = Process.GetProcessById(processId);
return null;
}
by using this function you will get a string like
"c:..\notepade.exe" D:\New Folder\sampleFile.txt"
after that split as you like to get the path.
I have written this code for office 2007 you guys can debug and find the proper path for the higher versions.
I am trying to impersonate a specific user to perform some sql operations in our server. This is not a ASP.Net application. I used the provided code before and it worked. But, recently we have upgraded our environment from windows server 2000 to windows server 2008 R2. After that upgrade this code is not working for me. I need some help in understanding this problem and help solving it. Any and every help will be appreciated. Thanks.
The provided code is a pseudo code, trying to write to a file and do a sql operation.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using System.Security.Principal;
using System.Security.Permissions;
[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)]
[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
public class Test
{
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_BATCH = 4;
const int LOGON32_LOGON_SERVICE = 5;
const int LOGON32_LOGON_UNLOCK = 7;
const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken
);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int ImpersonateLoggedOnUser(
IntPtr hToken
);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RevertToSelf();
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
public void TestImpersonation()
{
IntPtr lnToken = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
StringBuilder sb = new StringBuilder();
int TResult = LogonUser("itservices", "DFC", "St4hls345t", LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, out lnToken);
if (TResult > 0)
{
bool retVal = DuplicateToken(lnToken, SecurityImpersonation, ref dupeTokenHandle);
if (false == retVal)
{
CloseHandle(lnToken);
Console.WriteLine("Exception thrown in trying to duplicate token.");
return;
}
WindowsIdentity newId = new WindowsIdentity(dupeTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
writeLog(DateTime.Now.ToString(#"MM-dd-yyyy HH:mm:ss") + " - Impersonation Applied" + Environment.NewLine);
runQuery();
impersonatedUser.Undo();
writeLog(DateTime.Now.ToString(#"MM-dd-yyyy HH:mm:ss") + " - Impersonation Reverted" + Environment.NewLine);
runQuery();
CloseHandle(lnToken);
}
else
{
writeLog(DateTime.Now.ToString(#"MM-dd-yyyy HH:mm:ss") + " - Impersonation not Applied" + Environment.NewLine);
}
return;
}
void writeLog(string message)
{
try
{
string filePath = #"E:\Impersonate\Testlog.txt";
File.AppendAllText(filePath, message);
}
catch
{
Console.WriteLine();
}
}
void runQuery()
{
SQLOperations sqlUtill = new SQLOperations();
string cmdTxt = "SELECT * FROM [tblChildOrder] where [StahlsWorkOrderID] = 'DREAMFUL0015799'";
DataTable dt = sqlUtill.executeQuery(cmdTxt);
if (dt != null)
{
Console.WriteLine();
}
else
{
Console.WriteLine();
}
}
}
Most upgrade that broke my code usually was caused by the upgrade changing permission to users. Double check the users, the permission they have and you should find the problem.