Reputation: 165
I would like to know how I can programmatically set SeCreateGlobalPrivilege
to a none session0
process that's trying to open a MemoryMappedFile
with Global\
prefix, which will be used to share some data between 2 processes, one running with session0
(Windows Service) and other being a process that is started by invoking CreateProcessAsUser
upon a user logging on to the system.
The access token passed to CreateProcessAsUser
function is duplicated from the process of "explorer" whose sessionId
matches the result of WTSGetActiveConsoleSessionId()
.
I have this Owin middleware which runs under session0
that returns contents of MemoryMappedFile
allocated by a user process that continuously monitors a specific local file which is mapped to an url that is used to access the data from outside using HTTP.
I can't have the Windows Service process open the MemoryMappedFile as it would create some arbitrary place that is unknown to that none sesison0 process.
The following is the code snippet that I'm trying to make it work under this specific circumstance. It only works if both of the aforementioned processes run with the same sessionId, regardless of whether there is a Global prefix or not.
public class FileView
{
private readonly AutoResetEvent _run = new AutoResetEvent(false);
private readonly AutoResetEvent _update = new AutoResetEvent(false);
private ILog logger = LogManager.GetLogger("weldR");
private bool IsDisposed { get; set; }
private byte[] Data { get; set; }
private string MapName { get; set; }
private string MutexName { get; set; }
private MemoryMappedFileSecurity Security { get; set; }
public FileView(string url)
{
if (url.StartsWith("/"))
{
url = url.Substring(1);
}
MapName = string.Format("Global\\{0}",String.Concat("pipe://", url));
MutexName = string.Format("Global\\{0}", url.GetHashCode().ToString("x"));
Security = new MemoryMappedFileSecurity();
Security.AddAccessRule(new System.Security.AccessControl.AccessRule<MemoryMappedFileRights>("everyone",
MemoryMappedFileRights.FullControl, System.Security.AccessControl.AccessControlType.Allow));
Task.Factory.StartNew(Run);
}
void Run()
{
while (!IsDisposed)
{
if(Data != null)
{
Process process = Process.GetCurrentProcess();
using (new PrivilegeEnabler(process, Privilege.CreateGlobal))
{
var mutex = new Mutex(true, MutexName);
using (var mmf = MemoryMappedFile.CreateNew(MapName, Data.Length + 8,
MemoryMappedFileAccess.ReadWriteExecute, MemoryMappedFileOptions.None, Security, HandleInheritability.Inheritable))
{
using (var viewAccessor = mmf.CreateViewAccessor())
{
try
{
var size = Data.Length.Bytes();
viewAccessor.WriteArray(0, size, 0, size.Length);
viewAccessor.WriteArray(size.Length + 1, Data, 0, Data.Length);
}
catch (Exception e)
{
logger.ErrorFormat(e.ToString());
}
}
mutex.ReleaseMutex();
_update.Set();
_run.WaitOne();
mutex.WaitOne();
}
}
}
else
{
_run.WaitOne();
}
}
}
public void Update(byte[] data)
{
Data = data;
_run.Set();
_update.WaitOne();
}
public void Dispose()
{
IsDisposed = true;
_run.Set();
_update.Set();
}
}
private static Action<OwinRequest, OwinResponse> Serve(string path)
{
return (request, response) =>
{
//var pipename = String.Concat("pipe://", path);
// var pipemutex = path.GetHashCode().ToString("x");
var pipename = string.Format("Global\\{0}", String.Concat("pipe://", path));
var pipemutex = string.Format("Global\\{0}", path.GetHashCode().ToString("x"));
using (var mmf = MemoryMappedFile.OpenExisting(pipename))
{
using (var mutex = Mutex.OpenExisting(pipemutex))
{
try
{
mutex.WaitOne();
using (var accessor = mmf.CreateViewAccessor())
{
var offset = 0;
var fileLength = new byte[4];
accessor.ReadArray(offset, fileLength, 0, fileLength.Length);
offset += fileLength.Length;
var size = fileLength.Int32();
var buff = new byte[size];
accessor.ReadArray(offset, buff, 0, buff.Length);
var lastWriteTimeUtc = new DateTime();
var etag = string.Concat("\"", lastWriteTimeUtc.Ticks.ToString("x"), "\"");
var lastModified = lastWriteTimeUtc.ToString("R");
if ("HEAD".Equals(request.Method, StringComparison.OrdinalIgnoreCase))
return;
//if (CacheHelpers.ReturnNotModified(etag, lastWriteTimeUtc, context))
//{
// mutex.ReleaseMutex();
// return TaskHelpers.Completed();
//}
response.AddHeader("ETag", etag);
response.AddHeader("Last-Modified", lastModified);
response.AddHeader("Content-Type", Mime.MimeTypeFromExtension(path, "text/plain"));
response.AddHeader("Content-Length", size.ToString(CultureInfo.InvariantCulture));
response.Body.Write(buff, 0, buff.Length);
}
}
finally
{
mutex.ReleaseMutex();
}
}
}
};
}
I get the following Exception when the Window Service process try to open the MemoryMappedFile created by user session process.
2014-02-27 11:21:18,677 [1704|22|DEBUG] XXX: System.IO.FileNotFoundException: 指定されたファイルが見つかりません。 場所 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 場所 System.IO.MemoryMappedFiles.MemoryMappedFile.OpenCore(String mapName, HandleInheritability inheritability, Int32 desiredAccessRights, Boolean createOrOpen) 場所 System.IO.MemoryMappedFiles.MemoryMappedFile.OpenExisting(String mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability) 場所 System.IO.MemoryMappedFiles.MemoryMappedFile.OpenExisting(String mapName)
Upvotes: 0
Views: 2078
Reputation: 165
This seems impossible. I'm just guessing however, I see other blog posts and forum entries that suggest Opening a MemoryMappedFile with Global\ prefix is only allowed by a process with admin privilege.
Upvotes: 2