From 0714037a83e27f6a93407d4ab30ac3a5dacd2281 Mon Sep 17 00:00:00 2001 From: DavidXanatos Date: Sun, 30 Sep 2018 20:21:26 +0200 Subject: [PATCH] --- CHANGELOG.md | 14 +- wumgr/Common/AppLog.cs | 5 + wumgr/Common/FileOps.cs | 120 ++++++++--------- wumgr/Common/HttpTask.cs | 6 +- wumgr/Common/ListViewExtended.cs | 70 +++++++--- wumgr/Common/PipeIPC.cs | 218 +++++++++++++++++++++++++++++++ wumgr/MsUpdate.cs | 81 +++++++----- wumgr/Program.cs | 103 ++++++--------- wumgr/UpdateDownloader.cs | 4 +- wumgr/UpdateInstaller.cs | 2 +- wumgr/WuAgent.cs | 52 ++++---- wumgr/WuMgr.Designer.cs | 117 ++++++++--------- wumgr/WuMgr.cs | 52 +++++--- wumgr/wumgr.csproj | 1 + 14 files changed, 560 insertions(+), 285 deletions(-) create mode 100644 wumgr/Common/PipeIPC.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c0e3d0..dd4faab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,19 +2,27 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.6b] - 2018-09-30 + +### Fixed +- issues only one instance restriction +- issues with list view separation + + ## [0.6] - 2018-09-30 ### Added - checkbox to hide the WU settings page instead of automatic operation - when access elevation fails the tool now asks for admin rights +- added tool entry to setup/remove windows defender update task ### Changed - ObjectListView.dll is not longer required instead a simple self contained control is used - +- replaced the app icon with a nicer one ### Fixed -- issue when UC bypass failed due to restriction to only one instance +- issue when UAC bypass failed due to restriction to only one instance - then starting a tool from the menu it sets working directory to the tool's directory -- fixed issues with -onclose now no console window is shown and metter "" parsing is implemented +- fixed issues with -onclose now no console window is shown and better "" parsing is implemented ## [0.5] - 2018-09-16 diff --git a/wumgr/Common/AppLog.cs b/wumgr/Common/AppLog.cs index 00c37d4..a04c6a9 100644 --- a/wumgr/Common/AppLog.cs +++ b/wumgr/Common/AppLog.cs @@ -9,6 +9,11 @@ class AppLog { private List mLogList = new List(); + static public void Line(string str, params object[] args) + { + Line(string.Format(str, args)); + } + static public void Line(String line) { if (mInstance != null) diff --git a/wumgr/Common/FileOps.cs b/wumgr/Common/FileOps.cs index 2feb2df..03fb236 100644 --- a/wumgr/Common/FileOps.cs +++ b/wumgr/Common/FileOps.cs @@ -124,65 +124,65 @@ static public void SetFileAdminSec(String filePath) File.SetAccessControl(filePath, fs); } - static string SID_null = "S-1-0-0"; // Null SID - static string SID_Worls = "S-1-1-0"; // World - static string SID_Local = "S-1-2-0"; // Local - static string SID_Console = "S-1-2-1"; // Console Logon - static string SID_OwnerID = "S-1-3-0"; // Creator Owner ID - static string SID_GroupeID = "S-1-3-1"; // Creator Group ID - static string SID_OwnerSvr = "S-1-3-2"; // Creator Owner Server - static string SID_CreatorSvr = "S-1-3-3"; // Creator Group Server - static string SID_OwnerRights = "S-1-3-4"; // Owner Rights - static string SID_NonUnique = "S-1-4"; // Non-unique Authority - static string SID_NTAuth = "S-1-5"; // NT Authority - static string SID_AllServices = "S-1-5-80-0"; // All Services - static string SID_DialUp = "S-1-5-1"; // Dialup - static string SID_LocalAcc = "S-1-5-113"; // Local account - static string SID_LocalAccAdmin = "S-1-5-114"; // Local account and member of Administrators group - static string SID_Net = "S-1-5-2"; // Network - static string SID_Natch = "S-1-5-3"; // Batch - static string SID_Interactive = "S-1-5-4"; // Interactive - //static string SID_ = "S-1-5-5- *X*- *Y* Logon Session - static string SID_Service = "S-1-5-6"; // Service - static string SID_AnonLogin = "S-1-5-7"; // Anonymous Logon - - static string SID_Proxy = "S-1-5-8"; // Proxy - static string SID_EDC = "S-1-5-9"; // Enterprise Domain Controllers - static string SID_Self = "S-1-5-10"; // Self - static string SID_AuthenticetedUser = "S-1-5-11"; // Authenticated Users - - static string SID_Restricted = "S-1-5-12"; // Restricted Code - static string SID_TermUser = "S-1-5-13"; // Terminal Server User - static string SID_RemoteLogin = "S-1-5-14"; // Remote Interactive Logon - static string SID_ThisORg = "S-1-5-15"; // This Organization - static string SID_IIS = "S-1-5-17"; // IIS_USRS - static string SID_System = "S-1-5-18"; // System(or LocalSystem) - - static string SID_NTAuthL = "S-1-5-19"; // NT Authority(LocalService) - static string SID_NetServices = "S-1-5-20"; // Network Service - - static string SID_Admins = "S-1-5-32-544"; // Administrators - static string SID_Users = "S-1-5-32-545"; // Users - static string SID_Guests = "S-1-5-32-546"; // Guests - static string SID_PowerUsers = "S-1-5-32-547"; // Power Users - static string SID_AccOps = "S-1-5-32-548"; // Account Operators - static string SID_ServerOps = "S-1-5-32-549"; // Server Operators - static string SID_PrintOps = "S-1-5-32-550"; // Print Operators - static string SID_BackupOps = "S-1-5-32-551"; // Backup Operators - static string SID_Replicators = "S-1-5-32-552"; // Replicators - static string SID_NTLM_Auth = "S-1-5-64-10"; // NTLM Authentication - static string SID_SCh_Auth = "S-1-5-64-14"; // SChannel Authentication - static string SID_DigestAuth = "S-1-5-64-21"; // Digest Authentication - static string SID_NT_Service = "S-1-5-80"; // NT Service - static string SID_All_Services = "S-1-5-80-0"; // All Services - static string SID_VM = "S-1-5-83-0"; // NT VIRTUAL MACHINE\Virtual Machines - static string SID_UntrustedLevel = "S-1-16-0"; // Untrusted Mandatory Level - static string SID_LowLevel = "S-1-16-4096"; // Low Mandatory Level - static string SID_MediumLevel = "S-1-16-8192"; // Medium Mandatory Level - static string SID_MediumPLevel = "S-1-16-8448"; // Medium Plus Mandatory Level - static string SID_HighLevel = "S-1-16-12288"; // High Mandatory Level - static string SID_SysLevel = "S-1-16-16384"; // System Mandatory Level - static string SID_PPLevel = "S-1-16-20480"; // Protected Process Mandatory Level - static string SID_SPLevel = "S-1-16-28672"; // Secure Process Mandatory Level + public static string SID_null = "S-1-0-0"; // Null SID + public static string SID_Worls = "S-1-1-0"; // World + public static string SID_Local = "S-1-2-0"; // Local + public static string SID_Console = "S-1-2-1"; // Console Logon + public static string SID_OwnerID = "S-1-3-0"; // Creator Owner ID + public static string SID_GroupeID = "S-1-3-1"; // Creator Group ID + public static string SID_OwnerSvr = "S-1-3-2"; // Creator Owner Server + public static string SID_CreatorSvr = "S-1-3-3"; // Creator Group Server + public static string SID_OwnerRights = "S-1-3-4"; // Owner Rights + public static string SID_NonUnique = "S-1-4"; // Non-unique Authority + public static string SID_NTAuth = "S-1-5"; // NT Authority + public static string SID_AllServices = "S-1-5-80-0"; // All Services + public static string SID_DialUp = "S-1-5-1"; // Dialup + public static string SID_LocalAcc = "S-1-5-113"; // Local account + public static string SID_LocalAccAdmin = "S-1-5-114"; // Local account and member of Administrators group + public static string SID_Net = "S-1-5-2"; // Network + public static string SID_Natch = "S-1-5-3"; // Batch + public static string SID_Interactive = "S-1-5-4"; // Interactive + //public static string SID_ = "S-1-5-5- *X*- *Y* Logon Session + public static string SID_Service = "S-1-5-6"; // Service + public static string SID_AnonLogin = "S-1-5-7"; // Anonymous Logon + + public static string SID_Proxy = "S-1-5-8"; // Proxy + public static string SID_EDC = "S-1-5-9"; // Enterprise Domain Controllers + public static string SID_Self = "S-1-5-10"; // Self + public static string SID_AuthenticetedUser = "S-1-5-11"; // Authenticated Users + + public static string SID_Restricted = "S-1-5-12"; // Restricted Code + public static string SID_TermUser = "S-1-5-13"; // Terminal Server User + public static string SID_RemoteLogin = "S-1-5-14"; // Remote Interactive Logon + public static string SID_ThisORg = "S-1-5-15"; // This Organization + public static string SID_IIS = "S-1-5-17"; // IIS_USRS + public static string SID_System = "S-1-5-18"; // System(or LocalSystem) + + public static string SID_NTAuthL = "S-1-5-19"; // NT Authority(LocalService) + public static string SID_NetServices = "S-1-5-20"; // Network Service + + public static string SID_Admins = "S-1-5-32-544"; // Administrators + public static string SID_Users = "S-1-5-32-545"; // Users + public static string SID_Guests = "S-1-5-32-546"; // Guests + public static string SID_PowerUsers = "S-1-5-32-547"; // Power Users + public static string SID_AccOps = "S-1-5-32-548"; // Account Operators + public static string SID_ServerOps = "S-1-5-32-549"; // Server Operators + public static string SID_PrintOps = "S-1-5-32-550"; // Print Operators + public static string SID_BackupOps = "S-1-5-32-551"; // Backup Operators + public static string SID_Replicators = "S-1-5-32-552"; // Replicators + public static string SID_NTLM_Auth = "S-1-5-64-10"; // NTLM Authentication + public static string SID_SCh_Auth = "S-1-5-64-14"; // SChannel Authentication + public static string SID_DigestAuth = "S-1-5-64-21"; // Digest Authentication + public static string SID_NT_Service = "S-1-5-80"; // NT Service + public static string SID_All_Services = "S-1-5-80-0"; // All Services + public static string SID_VM = "S-1-5-83-0"; // NT VIRTUAL MACHINE\Virtual Machines + public static string SID_UntrustedLevel = "S-1-16-0"; // Untrusted Mandatory Level + public static string SID_LowLevel = "S-1-16-4096"; // Low Mandatory Level + public static string SID_MediumLevel = "S-1-16-8192"; // Medium Mandatory Level + public static string SID_MediumPLevel = "S-1-16-8448"; // Medium Plus Mandatory Level + public static string SID_HighLevel = "S-1-16-12288"; // High Mandatory Level + public static string SID_SysLevel = "S-1-16-16384"; // System Mandatory Level + public static string SID_PPLevel = "S-1-16-20480"; // Protected Process Mandatory Level + public static string SID_SPLevel = "S-1-16-28672"; // Secure Process Mandatory Level } diff --git a/wumgr/Common/HttpTask.cs b/wumgr/Common/HttpTask.cs index d1c3685..5c336aa 100644 --- a/wumgr/Common/HttpTask.cs +++ b/wumgr/Common/HttpTask.cs @@ -134,7 +134,7 @@ private void Finish(int Success, int ErrCode, Exception Error = null) } catch { - AppLog.Line(MiscFunc.fmt("Failed to rename download {0}", mDlPath + @"\" + mDlName + ".tmp")); + AppLog.Line("Failed to rename download {0}", mDlPath + @"\" + mDlName + ".tmp"); mDlName += ".tmp"; } @@ -142,12 +142,12 @@ private void Finish(int Success, int ErrCode, Exception Error = null) } else if (Success == 2) { - AppLog.Line(MiscFunc.fmt("File already dowllaoded {0}", mDlPath + @"\" + mDlName)); + AppLog.Line("File already dowllaoded {0}", mDlPath + @"\" + mDlName); } else { try { File.Delete(mDlPath + @"\" + mDlName + ".tmp"); } catch { } // delete partial file - AppLog.Line(MiscFunc.fmt("Failed to download file {0}", mDlPath + @"\" + mDlName)); + AppLog.Line("Failed to download file {0}", mDlPath + @"\" + mDlName); } Finished?.Invoke(this, new FinishedEventArgs(Success > 0 ? 0 : Canceled ? -1 : ErrCode, Error)); diff --git a/wumgr/Common/ListViewExtended.cs b/wumgr/Common/ListViewExtended.cs index 18aedad..29e608d 100644 --- a/wumgr/Common/ListViewExtended.cs +++ b/wumgr/Common/ListViewExtended.cs @@ -37,7 +37,7 @@ public class ListViewExtended : ListView /// Windows 95/98/Me: SendMessageW is supported by the Microsoft Layer for Unicode (MSLU). To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems. /// [DllImport("User32.dll"), Description("Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message. To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.")] - private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, LVGROUP lParam); + private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); private static int? GetGroupID(ListViewGroup lstvwgrp) { @@ -58,7 +58,7 @@ public class ListViewExtended : ListView return rtnval; } - private static void setGrpState(ListViewGroup lstvwgrp, ListViewGroupState state) + public static void setGrpState(ListViewGroup lstvwgrp, ListViewGroupState state) { if (Environment.OSVersion.Version.Major < 6) //Only Vista and forward allows collaps of ListViewGroups return; @@ -74,23 +74,39 @@ private static void setGrpState(ListViewGroup lstvwgrp, ListViewGroupState state group.CbSize = Marshal.SizeOf(group); group.State = state; group.Mask = ListViewGroupMask.State; - if (GrpId != null) + + IntPtr ip = IntPtr.Zero; + try + { + ip = Marshal.AllocHGlobal(group.CbSize); + if (GrpId != null) + { + group.IGroupId = GrpId.Value; + Marshal.StructureToPtr(group, ip, false); + SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, (IntPtr)GrpId.Value, ip); + SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, (IntPtr)GrpId.Value, ip); + } + else + { + group.IGroupId = gIndex; + Marshal.StructureToPtr(group, ip, false); + SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, (IntPtr)gIndex, ip); + SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, (IntPtr)gIndex, ip); + } + lstvwgrp.ListView.Refresh(); + } + catch (Exception ex) { - group.IGroupId = GrpId.Value; - SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group); - SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group); + System.Diagnostics.Trace.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace); } - else + finally { - group.IGroupId = gIndex; - SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group); - SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group); + if (null != ip) Marshal.FreeHGlobal(ip); } - lstvwgrp.ListView.Refresh(); } } - private static void setGrpFooter(ListViewGroup lstvwgrp, string footer) + public static void setGrpFooter(ListViewGroup lstvwgrp, string footer) { if (Environment.OSVersion.Version.Major < 6) //Only Vista and forward allows footer on ListViewGroups return; @@ -106,15 +122,29 @@ private static void setGrpFooter(ListViewGroup lstvwgrp, string footer) group.CbSize = Marshal.SizeOf(group); group.PszFooter = footer; group.Mask = ListViewGroupMask.Footer; - if (GrpId != null) + + IntPtr ip = IntPtr.Zero; + try + { + ip = Marshal.AllocHGlobal(group.CbSize); + if (GrpId != null) + { + group.IGroupId = GrpId.Value; + SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, (IntPtr)GrpId.Value, ip); + } + else + { + group.IGroupId = gIndex; + SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, (IntPtr)gIndex, ip); + } + } + catch (Exception ex) { - group.IGroupId = GrpId.Value; - SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group); + System.Diagnostics.Trace.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace); } - else + finally { - group.IGroupId = gIndex; - SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group); + if (null != ip) Marshal.FreeHGlobal(ip); } } } @@ -127,7 +157,7 @@ public void SetGroupState(ListViewGroupState state) public void SetGroupFooter(ListViewGroup lvg, string footerText) { - setGrpFooter(lvg, footerText); + setGrpFooter(lvg, footerText); } protected override void WndProc(ref Message m) @@ -177,7 +207,7 @@ protected override void WndProc(ref Message m) /// The structure may or may not hold errors inside the code, so use at own risk. /// Reference url: http://msdn.microsoft.com/en-us/library/bb774769(VS.85).aspx /// - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), Description("LVGROUP StructureUsed to set and retrieve groups.")] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto), Description("LVGROUP StructureUsed to set and retrieve groups.")] public struct LVGROUP { /// diff --git a/wumgr/Common/PipeIPC.cs b/wumgr/Common/PipeIPC.cs new file mode 100644 index 0000000..fe4654c --- /dev/null +++ b/wumgr/Common/PipeIPC.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.IO.Pipes; +using System.Linq; +using System.Security.AccessControl; +using System.Security.Principal; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows.Threading; +using System.Collections.Concurrent; + +class PipeIPC +{ + string mPipeName = null; + + internal class PipeTmpl where T : PipeStream + { + protected T pipeStream = null; + public event EventHandler DataReceived; + public event EventHandler PipeClosed; + + public void Close() + { + pipeStream.Flush(); + pipeStream.WaitForPipeDrain(); + pipeStream.Close(); + pipeStream.Dispose(); + pipeStream = null; + } + + public bool IsConnected() { return pipeStream.IsConnected; } + + public Task Send(string str) + { + byte[] bytes = Encoding.UTF8.GetBytes(str); + byte[] data = BitConverter.GetBytes(bytes.Length); + byte[] buff = data.Concat(bytes).ToArray(); + + return pipeStream.WriteAsync(buff, 0, buff.Length); + } + + protected void initAsyncReader() + { + new Action>((p) => { p.RunAsyncByteReader((b) => { DataReceived?.Invoke(this, Encoding.UTF8.GetString(b).TrimEnd('\0')); }); })(this); + } + + protected void RunAsyncByteReader(Action asyncReader) + { + int len = sizeof(int); + byte[] buff = new byte[len]; + + // read the length + pipeStream.ReadAsync(buff, 0, len).ContinueWith((ret) => + { + if (ret.Result == 0) + { + PipeClosed?.Invoke(this, EventArgs.Empty); + return; + } + + // read the data + len = BitConverter.ToInt32(buff, 0); + buff = new byte[len]; + pipeStream.ReadAsync(buff, 0, len).ContinueWith((ret2) => + { + if (ret2.Result == 0) + { + PipeClosed?.Invoke(this, EventArgs.Empty); + return; + } + + asyncReader(buff); + RunAsyncByteReader(asyncReader); + }); + }); + } + + public void Flush() + { + pipeStream.Flush(); + } + } + + internal class PipeServer : PipeTmpl + { + public event EventHandler Connected; + + public PipeServer(string pipeName) + { + PipeSecurity pipeSa = new PipeSecurity(); + pipeSa.SetAccessRule(new PipeAccessRule(new SecurityIdentifier(FileOps.SID_Worls), PipeAccessRights.FullControl, AccessControlType.Allow)); + int buffLen = 1029; // 4 + 1024 + 1 + pipeStream = new NamedPipeServerStream(pipeName, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Message, PipeOptions.Asynchronous, buffLen, buffLen, pipeSa); + pipeStream.BeginWaitForConnection(new AsyncCallback(PipeConnected), null); + } + + protected void PipeConnected(IAsyncResult asyncResult) + { + pipeStream.EndWaitForConnection(asyncResult); + Connected?.Invoke(this, new EventArgs()); + initAsyncReader(); + } + } + + internal class PipeClient : PipeTmpl + { + public PipeClient(string serverName, string pipeName) + { + pipeStream = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous); + } + + public bool Connect(int TimeOut = 10000) + { + try + { + pipeStream.Connect(TimeOut); + } + catch + { + return false; // timeout + } + + DataReceived += (sndr, data) => { + MessageQueue.Push(data); + }; + + initAsyncReader(); + return true; + } + + private ConcurrentStack MessageQueue = new ConcurrentStack(); // LIFO + + public string Read(int TimeOut = 10000) + { + MessageQueue.Clear(); + // DateTime.Now.Ticks is in 100 ns, TimeOut is in ms + for (long ticksEnd = DateTime.Now.Ticks + TimeOut * 10000; ticksEnd > DateTime.Now.Ticks;) + { + Application.DoEvents(); + if (!IsConnected()) + break; + if (MessageQueue.Count > 0) + break; + } + return Read(); + } + + public string Read() + { + // the MessageQueue is a last in first out type of container, so we need to reverse it + string ret = string.Join("\0", MessageQueue.ToArray().Reverse()); + MessageQueue.Clear(); + return ret; + } + } + + private Dispatcher mDispatcher; + + private List serverPipes; + private List clientPipes; + + public PipeIPC(string PipeName) + { + mDispatcher = Dispatcher.CurrentDispatcher; + + mPipeName = PipeName; + + serverPipes = new List(); + clientPipes = new List(); + } + + // Delegate for passing received message back to caller + public delegate void DelegateMessage(PipeServer pipe, string data); + public event DelegateMessage PipeMessage; + + public void Listen() + { + PipeServer serverPipe = new PipeServer(mPipeName); + serverPipes.Add(serverPipe); + + serverPipe.DataReceived += (sndr, data) => { + mDispatcher.Invoke(new Action(() => { + PipeMessage?.Invoke(serverPipe, data); + })); + }; + + serverPipe.Connected += (sndr, args) => { + mDispatcher.Invoke(new Action(() => { + Listen(); + })); + }; + + serverPipe.PipeClosed += (sndr, args) => { + mDispatcher.Invoke(new Action(() => { + serverPipes.Remove(serverPipe); + })); + }; + } + + public PipeClient Connect(int TimeOut = 10000) + { + PipeClient clientPipe = new PipeClient(".", mPipeName); + if (!clientPipe.Connect(TimeOut)) + return null; + + clientPipes.Add(clientPipe); + + clientPipe.PipeClosed += (sndr, args) => { + mDispatcher.Invoke(new Action(() => { + clientPipes.Remove(clientPipe); + })); + }; + + return clientPipe; + } +} diff --git a/wumgr/MsUpdate.cs b/wumgr/MsUpdate.cs index 2289296..ec56886 100644 --- a/wumgr/MsUpdate.cs +++ b/wumgr/MsUpdate.cs @@ -16,56 +16,65 @@ public MsUpdate() public MsUpdate(IUpdate update, UpdateState state) { Entry = update; - UUID = update.Identity.UpdateID; - Title = update.Title; - Category = GetCategory(update.Categories); - Description = update.Description; - Size = update.MaxDownloadSize; - Date = update.LastDeploymentChangeTime; - KB = GetKB(update); - SupportUrl = update.SupportUrl; + try + { + UUID = update.Identity.UpdateID; - UpdateDownloads(); + Title = update.Title; + Category = GetCategory(update.Categories); + Description = update.Description; + Size = update.MaxDownloadSize; + Date = update.LastDeploymentChangeTime; + KB = GetKB(update); + SupportUrl = update.SupportUrl; - State = state; + UpdateDownloads(); - Attributes |= update.IsBeta ? (int)UpdateAttr.Beta : 0; - Attributes |= update.IsDownloaded ? (int)UpdateAttr.Downloaded : 0; - Attributes |= update.IsHidden ? (int)UpdateAttr.Hidden : 0; - Attributes |= update.IsInstalled ? (int)UpdateAttr.Installed : 0; - Attributes |= update.IsMandatory ? (int)UpdateAttr.Mandatory : 0; - Attributes |= update.IsUninstallable ? (int)UpdateAttr.Uninstallable : 0; - Attributes |= update.AutoSelectOnWebSites ? (int)UpdateAttr.AutoSelect : 0; + State = state; - if (update.InstallationBehavior.Impact == InstallationImpact.iiRequiresExclusiveHandling) - Attributes |= (int)UpdateAttr.Exclusive; + Attributes |= update.IsBeta ? (int)UpdateAttr.Beta : 0; + Attributes |= update.IsDownloaded ? (int)UpdateAttr.Downloaded : 0; + Attributes |= update.IsHidden ? (int)UpdateAttr.Hidden : 0; + Attributes |= update.IsInstalled ? (int)UpdateAttr.Installed : 0; + Attributes |= update.IsMandatory ? (int)UpdateAttr.Mandatory : 0; + Attributes |= update.IsUninstallable ? (int)UpdateAttr.Uninstallable : 0; + Attributes |= update.AutoSelectOnWebSites ? (int)UpdateAttr.AutoSelect : 0; - switch (update.InstallationBehavior.RebootBehavior) - { - case InstallationRebootBehavior.irbAlwaysRequiresReboot: - Attributes |= (int)UpdateAttr.Reboot; - break; - case InstallationRebootBehavior.irbCanRequestReboot: - case InstallationRebootBehavior.irbNeverReboots: - break; + if (update.InstallationBehavior.Impact == InstallationImpact.iiRequiresExclusiveHandling) + Attributes |= (int)UpdateAttr.Exclusive; + + switch (update.InstallationBehavior.RebootBehavior) + { + case InstallationRebootBehavior.irbAlwaysRequiresReboot: + Attributes |= (int)UpdateAttr.Reboot; + break; + case InstallationRebootBehavior.irbCanRequestReboot: + case InstallationRebootBehavior.irbNeverReboots: + break; + } } + catch { } } public MsUpdate(IUpdateHistoryEntry2 update) { - UUID = update.UpdateIdentity.UpdateID; + try + { + UUID = update.UpdateIdentity.UpdateID; - Title = update.Title; - Category = GetCategory(update.Categories); - Description = update.Description; - Date = update.Date; - SupportUrl = update.SupportUrl; + Title = update.Title; + Category = GetCategory(update.Categories); + Description = update.Description; + Date = update.Date; + SupportUrl = update.SupportUrl; - State = UpdateState.History; + State = UpdateState.History; - ResultCode = (int)update.ResultCode; - HResult = update.HResult; + ResultCode = (int)update.ResultCode; + HResult = update.HResult; + } + catch { } } public void UpdateDownloads() diff --git a/wumgr/Program.cs b/wumgr/Program.cs index 93b962e..7200287 100644 --- a/wumgr/Program.cs +++ b/wumgr/Program.cs @@ -12,6 +12,7 @@ using System.Windows.Forms; using TaskScheduler; using System.Collections.Specialized; +using System.Collections.Concurrent; namespace wumgr { @@ -25,19 +26,7 @@ static class Program public static string appPath = ""; private static string mINIPath = ""; public static WuAgent Agent = null; - - public const Int32 WM_USER = 0x0400; - public const Int32 WM_APP = 0x0800; // to 0xBFFF - [DllImport("user32.dll")] - static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); - [DllImport("user32.dll")] - public static extern IntPtr FindWindow(string lpClassName, String lpWindowName); - [DllImport("user32.dll")] - public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); - [DllImport("user32.dll")] - public static extern bool SetForegroundWindow(IntPtr hWnd); - [DllImport("user32.dll")] - public static extern int SendMessageTimeout(IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, uint flags, uint timeout, out IntPtr result); + public static PipeIPC ipc = null; /// /// Der Haupteinstiegspunkt für die Anwendung. @@ -55,64 +44,42 @@ static void Main(string[] args) return; } + if (TestArg("-dbg_wait")) + MessageBox.Show("Waiting for debugger. (press ok when attached)"); + Console.WriteLine("Starting..."); System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); mVersion = fvi.FileMajorPart + "." + fvi.FileMinorPart; + if (fvi.FileBuildPart != 0) + mVersion += (char)('a' + (fvi.FileBuildPart - 1)); AppLog Log = new AppLog(); - AppLog.Line(MiscFunc.fmt("{0}, Version v{1} by David Xanatos", mName, mVersion)); - AppLog.Line(MiscFunc.fmt("This Tool is Open Source under the GNU General Public License, Version 3\r\n")); + AppLog.Line("{0}, Version v{1} by David Xanatos", mName, mVersion); + AppLog.Line("This Tool is Open Source under the GNU General Public License, Version 3\r\n"); appPath = Path.GetDirectoryName(Application.ExecutablePath); - if (!TestArg("-NoUAC")) - { - Process current = Process.GetCurrentProcess(); - foreach (Process process in Process.GetProcessesByName(current.ProcessName)) - { - if (process.Id != current.Id) - { - AppLog.Line(MiscFunc.fmt("Application is already running. Only one instance of this application is allowed")); - //IntPtr WindowToFind = FindWindow(null, Program.mName); - IntPtr result = IntPtr.Zero; - if (SendMessageTimeout(process.MainWindowHandle, WM_APP, IntPtr.Zero, IntPtr.Zero, 0, 3000, out result) == 0) - { - MessageBox.Show(MiscFunc.fmt("Application is already running, but not responding.\r\nClose it using a task manager and restart.")); - } - //SetForegroundWindow(process.MainWindowHandle); - return; - } - } - } - - - mINIPath = appPath + @"\wumgr.ini"; + ipc = new PipeIPC("wumgr_pipe"); - /*switch(FileOps.TestFileAdminSec(mINIPath)) + var client = ipc.Connect(100); + if (client != null) { - case 0: - AppLog.Line(MiscFunc.fmt("Warning wumgr.ini was writable by non administrative users, it was renamed to wumgr.ini.old and replaced with a empty one.\r\n")); - if (!FileOps.MoveFile(mINIPath, mINIPath + ".old", true)) - return; - goto case 2; - case 2: // file missing, create - FileOps.SetFileAdminSec(mINIPath); - break; - case 1: // every thign's fine ini file is only writable by admins - break; - }*/ - -#if DEBUG - Test(); -#endif + AppLog.Line("Application is already running."); + client.Send("show"); + string ret = client.Read(1000); + if(!ret.Equals("ok", StringComparison.CurrentCultureIgnoreCase)) + MessageBox.Show(MiscFunc.fmt("Application is already running.")); + return; + } if (IsAdministrator() == false) { Console.WriteLine("Trying to get admin privilegs..."); if (!SkipUacRun()) { + Console.WriteLine("Trying to start with 'runas'..."); // Restart program and run as admin var exeName = Process.GetCurrentProcess().MainModule.FileName; string arguments = "\"" + string.Join("\" \"", args) + "\""; @@ -132,6 +99,22 @@ static void Main(string[] args) return; } + mINIPath = appPath + @"\wumgr.ini"; + + /*switch(FileOps.TestFileAdminSec(mINIPath)) + { + case 0: + AppLog.Line("Warning wumgr.ini was writable by non administrative users, it was renamed to wumgr.ini.old and replaced with a empty one.\r\n"); + if (!FileOps.MoveFile(mINIPath, mINIPath + ".old", true)) + return; + goto case 2; + case 2: // file missing, create + FileOps.SetFileAdminSec(mINIPath); + break; + case 1: // every thign's fine ini file is only writable by admins + break; + }*/ + Agent = new WuAgent(); ExecOnStart(); @@ -231,11 +214,6 @@ static public bool DoExec(ProcessStartInfo startInfo, bool wait = false) } - static private void Test() - { - - } - [DllImport("kernel32")] private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); public static void IniWriteValue(string Section, string Key, string Value, string INIPath = null) @@ -360,13 +338,14 @@ static public bool SkipUacEnable(bool is_enable) } catch (Exception err) { - AppLog.Line(MiscFunc.fmt("SkipUacEnable Error {0}", err.ToString())); + AppLog.Line("Enable SkipUAC Error {0}", err.ToString()); return false; } } static public bool SkipUacRun() { + bool silent = true; try { TaskScheduler.TaskScheduler service = new TaskScheduler.TaskScheduler(); @@ -374,6 +353,9 @@ static public bool SkipUacRun() ITaskFolder folder = service.GetFolder(@"\"); // root IRegisteredTask task = folder.GetTask(nTaskName); + silent = false; + AppLog.Line("Trying to SkipUAC ..."); + IExecAction action = (IExecAction)task.Definition.Actions[1]; if (action.Path.Equals(System.Reflection.Assembly.GetExecutingAssembly().Location, StringComparison.CurrentCultureIgnoreCase)) { @@ -397,7 +379,8 @@ static public bool SkipUacRun() } catch (Exception err) { - AppLog.Line(MiscFunc.fmt("SkipUacRun Error {0}", err.ToString())); + if(!silent) + AppLog.Line("SkipUAC Error {0}", err.ToString()); } return false; } diff --git a/wumgr/UpdateDownloader.cs b/wumgr/UpdateDownloader.cs index bbec1d9..43ccdd3 100644 --- a/wumgr/UpdateDownloader.cs +++ b/wumgr/UpdateDownloader.cs @@ -86,9 +86,9 @@ void OnFinished(object sender, HttpTask.FinishedEventArgs args) Task Download = mDownloads[mCurrentTask]; if (args.ErrCode != 0) { - AppLog.Line(MiscFunc.fmt("Download failed: {0}", args.GetError())); + AppLog.Line("Download failed: {0}", args.GetError()); if (File.Exists(mCurTask.DlPath + @"\" + mCurTask.DlName)) - AppLog.Line(MiscFunc.fmt("An older version is present and will be used.")); + AppLog.Line("An older version is present and will be used."); else Download.Failed = true; } diff --git a/wumgr/UpdateInstaller.cs b/wumgr/UpdateInstaller.cs index bffd68e..46e356e 100644 --- a/wumgr/UpdateInstaller.cs +++ b/wumgr/UpdateInstaller.cs @@ -84,7 +84,7 @@ public void Run(object parameters) else if (ext.Equals(".cab", StringComparison.CurrentCultureIgnoreCase)) ; else - AppLog.Line(MiscFunc.fmt("Unknown Update format: {0}", ext)); + AppLog.Line("Unknown Update format: {0}", ext); // TODO do install mDispatcher.BeginInvoke(new Action(() => { diff --git a/wumgr/WuAgent.cs b/wumgr/WuAgent.cs index cfe519b..fb50d83 100644 --- a/wumgr/WuAgent.cs +++ b/wumgr/WuAgent.cs @@ -58,7 +58,7 @@ public WuAgent() WindowsUpdateAgentInfo info = new WindowsUpdateAgentInfo(); var currentVersion = info.GetInfo("ApiMajorVersion").ToString().Trim() + "." + info.GetInfo("ApiMinorVersion").ToString().Trim() + " (" + info.GetInfo("ProductVersionString").ToString().Trim() + ")"; - AppLog.Line(MiscFunc.fmt("Windows Update Agent Version: {0}", currentVersion)); + AppLog.Line("Windows Update Agent Version: {0}", currentVersion); mUpdateSession = new UpdateSession(); mUpdateSession.ClientApplicationID = Program.mName; @@ -137,7 +137,7 @@ public bool LoadServices(bool cleanUp = false) private void LogError(Exception error) { uint errCode = (uint)error.HResult; - AppLog.Line(MiscFunc.fmt("Error 0x{0}: {1}", errCode.ToString("X").PadLeft(8,'0'), UpdateErrors.GetErrorStr(errCode))); + AppLog.Line("Error 0x{0}: {1}", errCode.ToString("X").PadLeft(8,'0'), UpdateErrors.GetErrorStr(errCode)); } public static string MsUpdGUID = "7971f918-a847-4430-9279-4a52d1efe18d"; // Microsoft Update @@ -213,7 +213,7 @@ private bool SetupOffline() { if (mOfflineService == null) { - AppLog.Line(MiscFunc.fmt("Setting up 'Offline Sync Service'")); + AppLog.Line("Setting up 'Offline Sync Service'"); // http://go.microsoft.com/fwlink/p/?LinkID=74689 mOfflineService = mUpdateServiceManager.AddScanPackageService(mMyOfflineSvc, dlPath + @"\wsusscn2.cab"); @@ -312,7 +312,7 @@ public bool SearchForUpdates(bool Download, bool IncludePotentiallySupersededUpd { OnProgress(-1, 0, 0, 0); - AppLog.Line(MiscFunc.fmt("downloading wsusscn2.cab")); + AppLog.Line("downloading wsusscn2.cab"); List downloads = new List(); UpdateDownloader.Task download = new UpdateDownloader.Task(); @@ -342,7 +342,7 @@ private void SearchForUpdates() mCallback = new UpdateCallback(this); - AppLog.Line(MiscFunc.fmt("Searching for updates")); + AppLog.Line("Searching for updates"); //for the above search criteria refer to // http://msdn.microsoft.com/en-us/library/windows/desktop/aa386526(v=VS.85).aspx mSearchJob = mUpdateSearcher.BeginSearch("(IsInstalled = 0 and IsHidden = 0) or (IsInstalled = 1 and IsHidden = 0) or (IsHidden = 1)", mCallback, null); @@ -414,7 +414,7 @@ public bool DownloadUpdatesOffline(List Updates, bool Install = false) { if (Update.Downloads.Count == 0) { - AppLog.Line(MiscFunc.fmt("Error: No Download Url's found for update {0}", Update.Title)); + AppLog.Line("Error: No Download Url's found for update {0}", Update.Title); continue; } @@ -471,7 +471,7 @@ void DownloadsFinished(object sender, UpdateDownloader.FinishedEventArgs args) { if (mCurOperation == AgentOperation.PreparingCheck) { - AppLog.Line(MiscFunc.fmt("wsusscn2.cab downloaded")); + AppLog.Line("wsusscn2.cab downloaded"); ClearOffline(); SetupOffline(); @@ -499,7 +499,7 @@ void DownloadsFinished(object sender, UpdateDownloader.FinishedEventArgs args) }*/ if (mCurOperation != AgentOperation.PreparingUpdates) - AppLog.Line(MiscFunc.fmt("Updates downloaded to {0}", dlPath)); + AppLog.Line("Updates downloaded to {0}", dlPath); else if (InstallUpdatesOffline(args.Updates, AllFiles)) return; @@ -516,7 +516,7 @@ void InstallFinished(object sender, UpdateInstaller.FinishedEventArgs args) { if (args.Success) { - AppLog.Line(MiscFunc.fmt("Updates (Un)Installed succesfully")); + AppLog.Line("Updates (Un)Installed succesfully"); foreach (MsUpdate Update in args.Updates) { @@ -539,10 +539,10 @@ void InstallFinished(object sender, UpdateInstaller.FinishedEventArgs args) } if (args.Reboot) - AppLog.Line(MiscFunc.fmt("Reboot is required for one of more updates")); + AppLog.Line("Reboot is required for one of more updates"); } else - AppLog.Line(MiscFunc.fmt("Updates failed to (Un)Install")); + AppLog.Line("Updates failed to (Un)Install"); OnUpdatesChanged(); @@ -578,7 +578,7 @@ public bool DownloadUpdates(List Updates, bool Install = false) if (mDownloader.Updates.Count == 0) { - AppLog.Line(MiscFunc.fmt("No updates selected for download")); + AppLog.Line("No updates selected for download"); return false; } @@ -588,7 +588,7 @@ public bool DownloadUpdates(List Updates, bool Install = false) mCallback = new UpdateCallback(this); - AppLog.Line(MiscFunc.fmt("Downloading Updates... This may take several minutes.")); + AppLog.Line("Downloading Updates... This may take several minutes."); mDownloadJob = mDownloader.BeginDownload(mCallback, mCallback, Updates); return true; } @@ -613,7 +613,7 @@ private bool InstallUpdates(List Updates) if (mInstaller.Updates.Count == 0) { - AppLog.Line(MiscFunc.fmt("No updates selected for instalation")); + AppLog.Line("No updates selected for instalation"); return false; } @@ -623,7 +623,7 @@ private bool InstallUpdates(List Updates) mCallback = new UpdateCallback(this); - AppLog.Line(MiscFunc.fmt("Installing Updates... This may take several minutes.")); + AppLog.Line("Installing Updates... This may take several minutes."); mInstalationJob = mInstaller.BeginInstall(mCallback, mCallback, Updates); return true; } @@ -645,14 +645,14 @@ public bool UnInstallUpdates(List Updates) if (!update.IsUninstallable) { - AppLog.Line(MiscFunc.fmt("Update can not be uninstalled: {0}", update.Title)); + AppLog.Line("Update can not be uninstalled: {0}", update.Title); continue; } mInstaller.Updates.Add(update); } if (mDownloader.Updates.Count == 0) { - AppLog.Line(MiscFunc.fmt("No updates selected or eligible for uninstallation")); + AppLog.Line("No updates selected or eligible for uninstallation"); return false; } @@ -662,7 +662,7 @@ public bool UnInstallUpdates(List Updates) mCallback = new UpdateCallback(this); - AppLog.Line(MiscFunc.fmt("Removing Updates... This may take several minutes.")); + AppLog.Line("Removing Updates... This may take several minutes."); mInstalationJob = mInstaller.BeginUninstall(mCallback, mCallback, Updates); return true; } @@ -724,7 +724,7 @@ protected void OnUpdatesFound(ISearchJob searchJob) } catch (Exception err) { - AppLog.Line(MiscFunc.fmt("Search for updats failed")); + AppLog.Line("Search for updats failed"); LogError(err); OnFinished(false); return; @@ -746,7 +746,7 @@ protected void OnUpdatesFound(ISearchJob searchJob) Console.WriteLine(update.Title); } - AppLog.Line(MiscFunc.fmt("Found {0} pending updates.", mPendingUpdates.Count)); + AppLog.Line("Found {0} pending updates.", mPendingUpdates.Count); OnUpdatesChanged(true); @@ -767,7 +767,7 @@ protected void OnUpdatesDownloaded(IDownloadJob downloadJob, List Upda } catch (Exception err) { - AppLog.Line(MiscFunc.fmt("Downloading updates failed")); + AppLog.Line("Downloading updates failed"); LogError(err); OnFinished(false); return; @@ -779,7 +779,7 @@ protected void OnUpdatesDownloaded(IDownloadJob downloadJob, List Upda InstallUpdates(Updates); else { - AppLog.Line(MiscFunc.fmt("Updates downloaded to %windir%\\SoftwareDistribution\\Download")); + AppLog.Line("Updates downloaded to %windir%\\SoftwareDistribution\\Download"); OnFinished(DownloadResults.ResultCode == OperationResultCode.orcSucceeded); } } @@ -802,7 +802,7 @@ protected void OnInstalationCompleted(IInstallationJob installationJob, List GetGraceDays()) @@ -470,12 +478,16 @@ void LoadList(List List) ListViewGroup lvg = updateView.Groups[Update.Category]; if (lvg == null) + { lvg = updateView.Groups.Add(Update.Category, Update.Category); + ListViewExtended.setGrpState(lvg, ListViewGroupState.Collapsible); + } items[i].Group = lvg; } updateView.Items.AddRange(items); - updateView.SetGroupState(ListViewGroupState.Collapsible); + // Note: this has caused issues in the past + //updateView.SetGroupState(ListViewGroupState.Collapsible); } public List GetUpdates() @@ -731,18 +743,28 @@ private void btnHide_Click(object sender, EventArgs e) private void btnGetLink_Click(object sender, EventArgs e) { + string Links = ""; foreach (MsUpdate Update in GetUpdates()) { - AppLog.Line(Update.Title); + Links += Update.Title + "\r\n"; foreach (string url in Update.Downloads) - AppLog.Line(url); - AppLog.Line(""); + Links += url + "\r\n"; + Links += "\r\n"; } + + if (Links.Length != 0) + { + Clipboard.SetText(Links); + AppLog.Line("Update Download Links copyed to clipboard"); + } + else + AppLog.Line("No updates sellected"); } private void btnCancel_Click(object sender, EventArgs e) { agent.CancelOperations(); + OnFinished(null, null); } void OnProgress(object sender, WuAgent.ProgressArgs args) diff --git a/wumgr/wumgr.csproj b/wumgr/wumgr.csproj index a49fb0b..b04b6e9 100644 --- a/wumgr/wumgr.csproj +++ b/wumgr/wumgr.csproj @@ -95,6 +95,7 @@ Component +