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];
            }
예제 #2
0
        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);
        }