SHOW:
|
|
- or go back to the newest paste.
| 1 | ||
| 2 | //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ | |
| 3 | // SmesaMmfIpc.cs from SmesaNewTab.cs | |
| 4 | // v2.6.1.34 Features Memory Mapped file | |
| 5 | // form of Inter-Process-Communications. | |
| 6 | //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ | |
| 7 | // v2.6.0.32 15-Feb-2018 -JpE- | |
| 8 | // v2.6.1.32 20-Feb-2018 0151 Threading. | |
| 9 | // v3.0.0.36 28-Feb-2018 0420 MyApp WPF. | |
| 10 | // v3.0.1.37 01-Mar-2018 Reverted Hybrid | |
| 11 | // v3.1.1.39 08-Mar-2018 Awesome and | |
| 12 | // Inspiring! Args passed while running! | |
| 13 | // v3.1.3.41 19-Mar-2018 2331 Final Adj! | |
| 14 | // v3.1.3.43 20-Mar-2018 PrefClick Code. | |
| 15 | // v3.3.5.48 21-Apr-18 Integrated w/PB+ | |
| 16 | // v4.3.5.49 22-Apr-2018 Integrated. | |
| 17 | // v4.4.5.53 14-May Bring to Front mods. | |
| 18 | // v4.7.0.71 19-Sep About Colors. | |
| 19 | // v4.7.0.72 21-Sep-2018 RC | |
| 20 | // v4.8.1.79 11-Oct Peruse & Polish. | |
| 21 | // v4.8.2.80 15-Oct B2F Mechanism | |
| 22 | // v4.8.2.81 23-Oct Mapper2 interfaced | |
| 23 | // v4.8.3.85 09-Nov-2018 Favorites Mods. | |
| 24 | // v4.9.4.90 27-Nov-2018 ReadRemovals() and | |
| 25 | // GetSelectedIndex() integration completed. | |
| 26 | // NOTE: See calls to GetSelectedIndex(); | |
| 27 | //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ | |
| 28 | ||
| 29 | using System; | |
| 30 | using System.IO; | |
| 31 | using System.Linq; | |
| 32 | using System.Text; | |
| 33 | using System.Diagnostics; | |
| 34 | using System.Windows.Forms; | |
| 35 | using System.Collections.Generic; | |
| 36 | using System.Security.Permissions; | |
| 37 | using System.IO.MemoryMappedFiles; | |
| 38 | using System.Collections.ObjectModel; | |
| 39 | using System.Runtime.InteropServices; | |
| 40 | ||
| 41 | // Custom NameSpace & Class Library (.dll) | |
| 42 | using MyCustomLibrary; | |
| 43 | ||
| 44 | // Aliases | |
| 45 | using MCD = MyCustomLibrary.Dialogs; | |
| 46 | using SMS = MyEditor.Properties.Settings; | |
| 47 | using SMR = MyEditor.Properties.Resources; | |
| 48 | using SNM = MyCustomLibrary.SafeNativeMethods; | |
| 49 | ||
| 50 | namespace MyEditor | |
| 51 | {
| |
| 52 | public partial class Smesa | |
| 53 | {
| |
| 54 | #region Server side IPC MsgN Mods v4.8.2.81.G03 | |
| 55 | ||
| 56 | /// <summary> if (byte 8190 was flipped | |
| 57 | /// to 1) then bring Editor to front. | |
| 58 | /// I correctly assumed that | |
| 59 | /// 0 is same as null in byte files. | |
| 60 | /// SO, I will call B2F if 1 and rewrite | |
| 61 | /// a zero. If 0 is found return back! | |
| 62 | /// If something else found, from 2-255, | |
| 63 | /// then that's future growth. | |
| 64 | /// v4.8.2.81.G02 : 2018-Oct-23 | |
| 65 | /// Purposely Designed to leave many uses | |
| 66 | /// for other msgs to Smesa from abroad | |
| 67 | /// as reuses of the same Watcher | |
| 68 | /// Event/Delegate & !Handler. | |
| 69 | /// </summary> | |
| 70 | /// <param name="length"></param> | |
| 71 | private int CheckForMsgN(long length) | |
| 72 | {
| |
| 73 | Mx2.WaitOne(); | |
| 74 | var file = Mapped; | |
| 75 | var args = new object[] | |
| 76 | { file, SMS.Default.EditorSize,
| |
| 77 | SMS.Default.EditorOffset1 -2, | |
| 78 | // See Note Above about ^ this. | |
| 79 | length, true, Path | |
| 80 | .GetFileNameWithoutExtension( | |
| 81 | file), false }; | |
| 82 | var bites = MemoryMapper | |
| 83 | .ReverseReadBytes(args); | |
| 84 | if (bites.Count == 0) | |
| 85 | { Mx2.ReleaseMutex();
| |
| 86 | return 4; } | |
| 87 | if (bites.Count == 1) | |
| 88 | { if ( bites[0] == 0)
| |
| 89 | { Mx2.ReleaseMutex();
| |
| 90 | return 3; } | |
| 91 | if ( bites[0] == 1) | |
| 92 | { if (TabControl.InvokeRequired)
| |
| 93 | Invoke(new Invoker3(B2F)); | |
| 94 | else B2F(); | |
| 95 | // ^ Bring M.E. to Front. Then | |
| 96 | // Reset v bites to 0. (aka NULL) | |
| 97 | args[3] = new Collection<byte> {0};
| |
| 98 | if (!MemoryMapper | |
| 99 | .ReverseWriteBytes(args)) | |
| 100 | { MessageBox.Show(SMR.MsgN);
| |
| 101 | Mx2.ReleaseMutex(); | |
| 102 | return 2; } } | |
| 103 | if (bites[0] > 1) PbSignal(bites[0]); | |
| 104 | } else BatchRead(bites); | |
| 105 | Mx2.ReleaseMutex(); // NOTE: | |
| 106 | return 1; | |
| 107 | } | |
| 108 | ||
| 109 | // todo future <byte> msgs to Smesa from abroad. | |
| 110 | #region Future Mods | |
| 111 | ||
| 112 | /* Don't forget that you're going to want | |
| 113 | * to Zero out any other bites used, or NOT. | |
| 114 | * Some may become resident as things evolve. | |
| 115 | * v4.8.2.81 23-Oct-2018 | |
| 116 | */ | |
| 117 | ||
| 118 | private static void PbSignal(byte p) | |
| 119 | {
| |
| 120 | if (p == 2) DoThis(); | |
| 121 | if (p == 3) DoThat(); | |
| 122 | // etc, etc. | |
| 123 | } | |
| 124 | ||
| 125 | private static void DoThat() | |
| 126 | {
| |
| 127 | const string x = "Doing that!"; | |
| 128 | MessageBox.Show(x); | |
| 129 | ||
| 130 | // expansion ready | |
| 131 | } | |
| 132 | ||
| 133 | private static void DoThis() | |
| 134 | {
| |
| 135 | const string x = "Doing this!"; | |
| 136 | MessageBox.Show(x); | |
| 137 | ||
| 138 | // expansion ready | |
| 139 | } | |
| 140 | ||
| 141 | private static void | |
| 142 | BatchRead(IList<byte> result) | |
| 143 | {
| |
| 144 | const string x = "Batch Read!"; | |
| 145 | MessageBox.Show( | |
| 146 | string.Format( | |
| 147 | x + "\n\ndefault = {0}\n\n" +
| |
| 148 | "Count is {1}", result[0],
| |
| 149 | result.Count)); | |
| 150 | // extreme expansion ready | |
| 151 | } | |
| 152 | #endregion Future Mods using MsgN & IPC | |
| 153 | ||
| 154 | #endregion IPC MsgN Mods v4.8.2.81.G03 | |
| 155 | //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ | |
| 156 | ||
| 157 | ||
| 158 | #region Server-Side MMF-IPC Handling | |
| 159 | ||
| 160 | // Inter-Process-Communications (IPC) with | |
| 161 | // Memory Mapped File (MMF) & File Watcher. | |
| 162 | // Smesa is Owner & 1st Instance Server-Side | |
| 163 | // Code MmfClientSideWrite is Client for 2nd | |
| 164 | // Instances of MyEditor. (Now in MCT2) | |
| 165 | ||
| 166 | ||
| 167 | /// <summary> | |
| 168 | /// Only ran, once at launch, and | |
| 169 | /// whenever a msg comes in from abroad. | |
| 170 | /// This creates _mmf, Delegate, Eventhandler | |
| 171 | /// & a Reader for it. 2nd instances just | |
| 172 | /// never see this Server-Side code period. | |
| 173 | /// </summary> | |
| 174 | /// <param name="read"></param> | |
| 175 | [ComVisible(false)] | |
| 176 | private void MmfServerSide(bool read = false) | |
| 177 | {
| |
| 178 | if (Watcher != null) | |
| 179 | Watcher.EnableRaisingEvents = false; | |
| 180 | var temp = MmfManage(read); | |
| 181 | // NOTE: Clean Exit if not a Mail Run. | |
| 182 | if (temp.Count < 1) // v MsgN Hook v48281 | |
| 183 | {
| |
| 184 | if (read && CheckForMsgN(1) > 2) | |
| 185 | CheckForRemovals(); // <===<< v49386 | |
| 186 | } | |
| 187 | else ServerSideMsgReceived(temp); | |
| 188 | // Mail Received ^ acting on it! | |
| 189 | if (Watcher != null) Watcher | |
| 190 | .EnableRaisingEvents = true; | |
| 191 | } | |
| 192 | ||
| 193 | // FOR RELEASE TESTING & DEBUGGING PRINTBLASTER | |
| 194 | private static void SetPaths(string mapped) | |
| 195 | {
| |
| 196 | var pb = BlasterPath = | |
| 197 | WriteShared.AppRoot + SMR.PrintApp; | |
| 198 | var dir = string.IsNullOrEmpty(pb) | |
| 199 | || !File.Exists(pb) | |
| 200 | ? Path.GetDirectoryName(mapped) | |
| 201 | : Path.GetDirectoryName(BlasterPath); | |
| 202 | EditorPath = dir + SMR.EdApp; | |
| 203 | var docs = MyToolbox.GetDocFolder; | |
| 204 | var file = docs + SMR.PathMe; | |
| 205 | File.WriteAllText(file, EditorPath); | |
| 206 | File.SetLastAccessTime( | |
| 207 | file, DateTime.Now); | |
| 208 | var path = docs + SMR.PathEd; | |
| 209 | var maps = dir + "\\" + | |
| 210 | Path.GetFileName(mapped); | |
| 211 | File.WriteAllText(path, maps); | |
| 212 | File.SetLastAccessTime( | |
| 213 | path, DateTime.Now); | |
| 214 | // v4.8.2.80 | |
| 215 | dir = Path.GetDirectoryName(mapped); | |
| 216 | var me = dir + SMR.ME; | |
| 217 | File.WriteAllText(me, dir); | |
| 218 | } | |
| 219 | ||
| 220 | private static void LogOut() | |
| 221 | {
| |
| 222 | var dir = Path.GetDirectoryName(Mapped); | |
| 223 | var log = dir + SMR.ME; | |
| 224 | if (File.Exists(log)) File.Delete(log); | |
| 225 | } | |
| 226 | ||
| 227 | /// <summary> Args passed in from 2nd Instance! | |
| 228 | /// Acts on Msg Passed from 2nd Instance client. | |
| 229 | /// Awesome and inspiring mods! (Rev3.4) | |
| 230 | /// </summary> | |
| 231 | /// <param name="temp"></param> | |
| 232 | private void ServerSideMsgReceived( | |
| 233 | ICollection<string> temp) | |
| 234 | {
| |
| 235 | if (TabControl.InvokeRequired) | |
| 236 | { // If Called From Worker Thread
| |
| 237 | Invoke(new Invoker1(TabPrompt)); | |
| 238 | temp.Add(Convert.ToString(_tab)); | |
| 239 | _myContext.Post(MultiSelect, temp); | |
| 240 | Invoke(new Invoker3(B2F)); } | |
| 241 | else // also handles UI thread (test) calls. | |
| 242 | { temp.Add(Convert.ToString(
| |
| 243 | TabPrompt(TabControl.SelectedIndex))); | |
| 244 | MultiSelect(temp); | |
| 245 | B2F(); } } | |
| 246 | ||
| 247 | /// <summary> This has 2b seperate for | |
| 248 | /// Invokers (as above) re-written for | |
| 249 | /// SafeNativeCode Class: Must be static. | |
| 250 | /// v4.4.5.53 15-May-2018 | |
| 251 | /// </summary> | |
| 252 | private static void B2F() | |
| 253 | {
| |
| 254 | SNM.B2F(Process | |
| 255 | .GetCurrentProcess() | |
| 256 | .MainWindowHandle); | |
| 257 | } | |
| 258 | ||
| 259 | private static Collection<string> | |
| 260 | MmfManage(bool read) | |
| 261 | {
| |
| 262 | var size = SMS.Default.EditorSize; | |
| 263 | var temp = new Collection<string>(); | |
| 264 | using (var t = | |
| 265 | MemoryMappedFile.CreateFromFile( | |
| 266 | Mapped, FileMode.OpenOrCreate, | |
| 267 | Path.GetFileNameWithoutExtension( | |
| 268 | Mapped), size)) | |
| 269 | { if (read)
| |
| 270 | { // 1st instance Gets Msg from
| |
| 271 | // 2nd instance OR other Apps. | |
| 272 | #region Read Mail | |
| 273 | ||
| 274 | var view = SMS.Default.EditorView1; | |
| 275 | var offset = SMS.Default.EditorOffset1; | |
| 276 | using (var reader = t.CreateViewAccessor( | |
| 277 | offset, view, MemoryMappedFileAccess.ReadWrite)) | |
| 278 | {
| |
| 279 | // Assessor itself is now Offset. | |
| 280 | var position = 0; | |
| 281 | while (position <= view) | |
| 282 | {
| |
| 283 | var strl = reader.ReadUInt16(position); | |
| 284 | // ^^^^ = This next byte-array's length. | |
| 285 | if (strl < 1) break; // No More Are Used. | |
| 286 | var buff = new byte[strl]; | |
| 287 | reader.ReadArray( | |
| 288 | position += 2, buff, 0, strl); | |
| 289 | position += strl; | |
| 290 | var str = Encoding.UTF32.GetString(buff); | |
| 291 | if (string.IsNullOrEmpty(str)) break; | |
| 292 | temp.Add(str); | |
| 293 | } // Remember how many bytes were used... | |
| 294 | var used = position; // <-= Speed Enhancement! | |
| 295 | // Mail Read, Now Shred only the bytes used. | |
| 296 | position = 0; | |
| 297 | // REM: ^ Accessor itself is now offset. | |
| 298 | while (position <= used // was < | |
| 299 | // stops at end ^^^^ of current msg... | |
| 300 | && position <= view) //<-= or file. | |
| 301 | {
| |
| 302 | // then zeros v out used bytes for next write. | |
| 303 | reader.Write(position, (ushort) 0); | |
| 304 | position += 2; | |
| 305 | } | |
| 306 | } | |
| 307 | #endregion Reader | |
| 308 | } | |
| 309 | } | |
| 310 | return temp; | |
| 311 | } | |
| 312 | ||
| 313 | /* Only seen by the 1st Instance of our App. */ | |
| 314 | private void WaitForProcess2() | |
| 315 | {
| |
| 316 | if (InvokeRequired) | |
| 317 | Invoke(new Invoker1(WaitCursor)); | |
| 318 | else // Display v Spinning Blue Donut! | |
| 319 | Cursor = Cursors.WaitCursor; | |
| 320 | List<Process> pros; | |
| 321 | var p = Process.GetCurrentProcess(); | |
| 322 | do { p.WaitForExit(250);
| |
| 323 | pros = Process.GetProcessesByName( | |
| 324 | Process.GetCurrentProcess() | |
| 325 | .ProcessName).ToList(); | |
| 326 | } while (pros.Count > 1); | |
| 327 | if (InvokeRequired) | |
| 328 | Invoke(new Invoker1(ArrowCursor)); | |
| 329 | else Cursor = Cursors.Arrow; | |
| 330 | } | |
| 331 | ||
| 332 | private void ArrowCursor() | |
| 333 | {
| |
| 334 | Cursor = Cursors.Arrow; | |
| 335 | } | |
| 336 | ||
| 337 | private void WaitCursor() | |
| 338 | {
| |
| 339 | Cursor = Cursors.WaitCursor; | |
| 340 | } | |
| 341 | #endregion Server-Side MMF-IPC | |
| 342 | //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ | |
| 343 | ||
| 344 | ||
| 345 | #region Server-Side MMF Watcher, Event & Handler | |
| 346 | ||
| 347 | /* Only seen by the 1st Instance of our App. */ | |
| 348 | ||
| 349 | private void MmfChangedEventHandler( | |
| 350 | object sender, EventArgs e) | |
| 351 | {
| |
| 352 | if (!SMS.Default.MultiTab) return; | |
| 353 | // It's a Mail Run, brb! | |
| 354 | WaitForProcess2(); | |
| 355 | // Okay, Mail Read and Shred, Bye! | |
| 356 | MmfServerSide(true); | |
| 357 | } | |
| 358 | ||
| 359 | // Only seen by the 1st Instance of our App. | |
| 360 | [PermissionSet(SecurityAction.Demand, | |
| 361 | Name = "FullTrust")] | |
| 362 | private void MmfEventDelegate() | |
| 363 | {
| |
| 364 | var m = Mapped; | |
| 365 | Watcher.NotifyFilter = | |
| 366 | NotifyFilters.LastWrite; | |
| 367 | Watcher.InternalBufferSize = 2048; | |
| 368 | //SMS.Default.EditorSize | |
| 369 | Watcher.EnableRaisingEvents = false; | |
| 370 | // Setup File System Watcher: | |
| 371 | Watcher.Path = // for Mapped File. | |
| 372 | Path.GetDirectoryName(m); | |
| 373 | Watcher.Filter = Path.GetFileName(m); | |
| 374 | if (File.Exists(m)) File.Delete(m); | |
| 375 | // Setup Server-Side of memory-mapped-file: | |
| 376 | MmfServerSide(); | |
| 377 | // Create Eventhandler... | |
| 378 | Watcher.Changed += MmfChangedEventHandler; | |
| 379 | Watcher.EnableRaisingEvents = true; | |
| 380 | } | |
| 381 | #endregion SS MMF Watcher, Event & Handler | |
| 382 | //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ | |
| 383 | ||
| 384 | ||
| 385 | } | |
| 386 | } |