public DataLock(ref SERVICE_FAILURE_ACTIONSW data) { _data = data; int actionStructureSize = Marshal.SizeOf(typeof(SC_ACTION)); // Allocate a buffer with a bit of extra space at the end, so that if the first byte isn't aligned to a 64-bit // boundary, we can simply ignore the first few bytes and find the next 64-bit boundary. _buffer = Marshal.AllocHGlobal(data.lpsaActions.Length * actionStructureSize + 8); data.lpsaActionsPtr = _buffer; // Round up to the next multiple of 8 to get a 64-bit-aligned pointer. if ((data.lpsaActionsPtr.ToInt64() & 7) != 0) { data.lpsaActionsPtr += 8; data.lpsaActionsPtr -= (int)((long)data.lpsaActionsPtr & ~7); } // Copy the data from lpsaActions into the buffer. IntPtr elementPtr = data.lpsaActionsPtr; for (int i = 0; i < data.lpsaActions.Length; i++, elementPtr += actionStructureSize) { Marshal.StructureToPtr(data.lpsaActions[i], elementPtr, fDeleteOld: false); } // Replace the lpsaActions array with a dummy that contains only one element, otherwise the P/Invoke marshaller // will allocate a buffer of size 1 and then write lpsaActions.Length items to it and corrupt memory. _originalActionsArray = data.lpsaActions; data.lpsaActions = new SC_ACTION[1]; }
private SERVICE_FAILURE_ACTIONSW BuildFailureActionsStructure() { var ret = new SERVICE_FAILURE_ACTIONSW(); ret.dwResetPeriod = (int)Math.Round(this.ResetPeriod.TotalMilliseconds); ret.lpRebootMsg = this.RebootMessage ?? ""; ret.lpCommand = this.RestartCommand ?? ""; ret.cActions = this.Actions.Length; ret.lpsaActions = new SC_ACTION[this.Actions.Length]; for (int i = 0; i < this.Actions.Length; i++) { ret.lpsaActions[i] = new SC_ACTION() { Type = (SC_ACTION_TYPE)(int)this.Actions[i].Type, Delay = (int)Math.Round(this.Actions[i].DelayBeforeAction.TotalMilliseconds), }; } return(ret); }