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 | } |