Skip to content

Commit f96cda5

Browse files
committed
Change to safer native PenHelper call
1 parent e63dd4f commit f96cda5

File tree

4 files changed

+13
-42
lines changed

4 files changed

+13
-42
lines changed

Source/ExcelDna.IntelliSense.Host/ExcelDna.IntelliSense.Host.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
<ExcelDna32BitAddInSuffix>32</ExcelDna32BitAddInSuffix>
1414
<ExcelDna64BitAddInSuffix>64</ExcelDna64BitAddInSuffix>
1515
<ExcelDnaPackXllSuffix></ExcelDnaPackXllSuffix>
16+
<ExcelDnaPack32BitXllName>ExcelDna.IntelliSense</ExcelDnaPack32BitXllName>
17+
<ExcelDnaPack64BitXllName>ExcelDna.IntelliSense64</ExcelDnaPack64BitXllName>
1618
</PropertyGroup>
1719

1820
<ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">

Source/ExcelDna.IntelliSense/IntelliSenseServer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace ExcelDna.IntelliSense
3030
// REMEMBER: COM events are not necessarily safe macro contexts.
3131
public static class IntelliSenseServer
3232
{
33-
const string ServerVersion = "1.7.1"; // TODO: Define and manage this somewhere else
33+
const string ServerVersion = "1.7.2"; // TODO: Define and manage this somewhere else
3434

3535
// NOTE: Do not change these constants in custom versions.
3636
// They are part of the co-operative safety mechanism allowing different add-ins providing IntelliSense to work together safely.
@@ -157,7 +157,7 @@ static void CurrentDomain_ProcessExit(object sender, EventArgs e)
157157
if (_isActive)
158158
{
159159
// Parachute in asap a call to prevent further XLPenHelper calls
160-
XlCall.ShutdownStarted();
160+
XlCallHelper.ShutdownStarted();
161161

162162
// Don't try to clean up clean up on process exit - all our resources are in-process anyway
163163
// Leads to an error with the main thread SynchronizationContext, which might be shut down already.

Source/ExcelDna.IntelliSense/UIMonitor/FormulaEditWatcher.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ void UpdateEditState(bool moveOnly = false)
329329

330330
void UpdateEditStateImpl(bool moveOnly = false)
331331
{
332-
Logger.WindowWatcher.Verbose($"> FormulaEdit UpdateEditState - Thread {Thread.CurrentThread.ManagedThreadId}");
332+
// Logger.WindowWatcher.Verbose($"> FormulaEdit UpdateEditState - Thread {Thread.CurrentThread.ManagedThreadId}");
333333
Logger.WindowWatcher.Verbose($"FormulaEdit UpdateEditState - Focus: {_formulaEditFocus} Window: {(_formulaEditFocus == FormulaEditFocus.FormulaBar ? _hwndFormulaBar : _hwndInCellEdit)}");
334334

335335
IntPtr hwnd = IntPtr.Zero;
@@ -365,7 +365,7 @@ void UpdateEditStateImpl(bool moveOnly = false)
365365
IsEditingFormula = true;
366366
}
367367

368-
var newPrefix = XlCall.GetFormulaEditPrefix(); // What thread do we have to use here ...?
368+
var newPrefix = XlCallHelper.GetFormulaEditPrefix(); // This call must be on the main thread
369369
if (CurrentPrefix != newPrefix)
370370
{
371371
CurrentPrefix = newPrefix;

Source/ExcelDna.IntelliSense/UIMonitor/XlCall.cs renamed to Source/ExcelDna.IntelliSense/UIMonitor/XlCallHelper.cs

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,13 @@
1-
using System;
1+
using ExcelDna.Integration;
2+
using System;
23
using System.Diagnostics;
34
using System.Runtime.ExceptionServices;
45
using System.Runtime.InteropServices;
56

67
namespace ExcelDna.IntelliSense
78
{
8-
class XlCall
9+
class XlCallHelper
910
{
10-
[DllImport("XLCALL32.DLL")]
11-
static extern int LPenHelper(int wCode, ref FmlaInfo fmlaInfo); // 'long' return value means 'int' in C (so why different?)
12-
13-
const int xlSpecial = 0x4000;
14-
const int xlGetFmlaInfo = (14 | xlSpecial);
15-
16-
// Edit Modes
17-
const int xlModeReady = 0; // not in edit mode
18-
const int xlModeEnter = 1; // enter mode
19-
const int xlModeEdit = 2; // edit mode
20-
const int xlModePoint = 4; // point mode
21-
22-
[StructLayout(LayoutKind.Sequential)]
23-
struct FmlaInfo
24-
{
25-
public int wPointMode; // current edit mode. 0 => rest of struct undefined
26-
public int cch; // count of characters in formula
27-
public IntPtr lpch; // pointer to formula characters. READ ONLY!!!
28-
public int ichFirst; // char offset to start of selection
29-
public int ichLast; // char offset to end of selection (may be > cch)
30-
public int ichCaret; // char offset to blinking caret
31-
}
32-
3311
// This give a global mechanism to indicate shutdown as early as possible
3412
// Maybe helps with debugging...
3513
static bool _shutdownStarted = false;
@@ -38,21 +16,17 @@ public static void ShutdownStarted()
3816
_shutdownStarted = true;
3917
}
4018

19+
// This call must be made on the main thread
4120
// Returns null if not in edit mode
42-
// TODO: What do we know about the threading constraints on this call?
43-
44-
// NOTE: I've only seen this crash during shutdown
45-
// We enable handling of the AccessViolation as best we can
46-
[HandleProcessCorruptedStateExceptions]
4721
public static string GetFormulaEditPrefix()
4822
{
4923
if (_shutdownStarted)
5024
return null;
5125

5226
try
5327
{
54-
var fmlaInfo = new FmlaInfo();
55-
var result = LPenHelper(xlGetFmlaInfo, ref fmlaInfo);
28+
var fmlaInfo = new XlCall.FmlaInfo();
29+
var result = XlCall.PenHelper(XlCall.xlGetFmlaInfo, ref fmlaInfo);
5630
if (result != 0)
5731
{
5832
Logger.WindowWatcher.Warn($"LPenHelper Failed. Result: {result}");
@@ -62,7 +36,7 @@ public static string GetFormulaEditPrefix()
6236
// throw new InvalidOperationException("LPenHelper Failed. Result: " + result);
6337
return null;
6438
}
65-
if (fmlaInfo.wPointMode == xlModeReady)
39+
if (fmlaInfo.wPointMode == XlCall.xlModeReady)
6640
{
6741
Logger.WindowWatcher.Verbose($"LPenHelper PointMode Ready");
6842
return null;
@@ -76,11 +50,6 @@ public static string GetFormulaEditPrefix()
7650
var prefixLen = Math.Min(Math.Max(fmlaInfo.ichCaret, fmlaInfo.ichLast), fmlaInfo.cch); // I've never seen ichLast > cch !?
7751
return Marshal.PtrToStringUni(fmlaInfo.lpch, prefixLen);
7852
}
79-
catch (AccessViolationException)
80-
{
81-
Logger.WindowWatcher.Warn("LPenHelper - Access Violation!");
82-
return null;
83-
}
8453
catch (Exception ex)
8554
{
8655
// Some unexpected error - for now we log as an error and re-throw

0 commit comments

Comments
 (0)