Re: managed / unmanged - StringToHGlobalAnsi / PtrToStringAnsi



I've put the code together with dllimports and struct into a test
project, hope you see what's wrong.

Bram.

[StructLayout(LayoutKind.Sequential)]
public struct SERVICE_FAILURE_ACTIONS
{
[MarshalAs(UnmanagedType.U4)]
public int dwResetPeriod;
//[MarshalAs(UnmanagedType.LPTStr)]
//public string lpRebootMsg;
//[MarshalAs(UnmanagedType.LPTStr)]
//public string lpCommand;
[MarshalAs(UnmanagedType.U4)]
public int lpRebootMsg;
[MarshalAs(UnmanagedType.U4)]
public int lpCommand;
[MarshalAs(UnmanagedType.U4)]
public int cActions;
[MarshalAs(UnmanagedType.U4)]
public int lpsaActions;
}

[DllImport("advapi32.dll")]
public static extern IntPtr OpenSCManager(string lpMachineName, string
lpDatabaseName, int dwDesiredAccess);

[DllImport("advapi32.dll")]
public static extern IntPtr OpenService(IntPtr hSCManager, string
lpServiceName, int dwDesiredAccess);

[DllImport("advapi32.dll")]
public static extern IntPtr LockServiceDatabase(IntPtr hSCManager);

[DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig2")]
public static extern bool ChangeServiceFailureActions(IntPtr hService,
int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref
SERVICE_FAILURE_ACTIONS lpInfo);

[DllImport("advapi32.dll", EntryPoint = "QueryServiceConfig2A", CharSet
= CharSet.Ansi)]
public static extern bool QueryServiceConfiguration(IntPtr hService,
int dwInfoLevel, IntPtr lpInfo, uint size, ref uint bytesneeded);

[DllImport("advapi32.dll")]
public static extern bool CloseServiceHandle(IntPtr hSCObject);

[DllImport("advapi32.dll")]
public static extern bool UnlockServiceDatabase(IntPtr hSCManager);

private const int SC_MANAGER_ALL_ACCESS = 0xF003F;
private const int SERVICE_ALL_ACCESS = 0xF01FF;
private const int SERVICE_CONFIG_FAILURE_ACTIONS = 0x2;
private const int SERVICE_NO_CHANGE = -1;
private const int ERROR_ACCESS_DENIED = 5;

public ArrayList FailureActions;

private void SetFailureActions()
{ //Register the failure actions
FailureActions.Clear();
FailureActions.Add(new FailureAction(RecoverAction.Restart,
60000));
FailureActions.Add(new FailureAction(RecoverAction.RunCommand,
2000));
FailureActions.Add(new FailureAction(RecoverAction.None, 3000));

IntPtr scmHndl = IntPtr.Zero;
IntPtr svcHndl = IntPtr.Zero;
IntPtr tmpBuf = IntPtr.Zero;
IntPtr svcLock = IntPtr.Zero;
IntPtr tmpMsg = IntPtr.Zero;
IntPtr tmpCmd = IntPtr.Zero;

try
{
scmHndl = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
svcLock = LockServiceDatabase(scmHndl);
svcHndl = OpenService(scmHndl, "MyServiceName",
SERVICE_ALL_ACCESS);

int numActions = FailureActions.Count;
int[] actions = new int[numActions * 2];
int currInd = 0;
foreach (FailureAction fa in FailureActions)
{
actions[currInd] = (int)fa.Type;
actions[++currInd] = fa.Delay;
currInd++;
//If the FailureActions is reboot then Grand shutdown
privilege
}

tmpBuf = Marshal.AllocHGlobal(numActions * 8);
Marshal.Copy(actions, 0, tmpBuf, numActions * 2);

tmpCmd = Marshal.StringToHGlobalAnsi("MyCommand.exe");
tmpMsg = Marshal.StringToHGlobalAnsi("Time to reboot!");
//tmpMsg = Marshal.StringToHGlobalUni("Time to reboot!");

SERVICE_FAILURE_ACTIONS sfa = new SERVICE_FAILURE_ACTIONS();

sfa.cActions = numActions;
sfa.dwResetPeriod = SERVICE_NO_CHANGE;
//sfa.lpCommand = "My Test Command";
//sfa.lpRebootMsg = "My Reboot Message";
sfa.lpCommand = tmpCmd.ToInt32();
sfa.lpRebootMsg = tmpMsg.ToInt32();
sfa.lpsaActions = tmpBuf.ToInt32();

bool rslt = ChangeServiceFailureActions(svcHndl,
SERVICE_CONFIG_FAILURE_ACTIONS, ref sfa);
Marshal.FreeHGlobal(tmpBuf); tmpBuf = IntPtr.Zero;
}
catch (Exception ex)
{ Console.WriteLine(ex.Message); }
finally
{
if (scmHndl != IntPtr.Zero)
{ if (svcLock != IntPtr.Zero)
{ UnlockServiceDatabase(svcLock);
svcLock = IntPtr.Zero; }
CloseServiceHandle(scmHndl);
scmHndl = IntPtr.Zero; }
if (svcHndl != IntPtr.Zero)
{ CloseServiceHandle(svcHndl);
svcHndl = IntPtr.Zero; }
if (tmpBuf != IntPtr.Zero)
{ Marshal.FreeHGlobal(tmpBuf);
tmpBuf = IntPtr.Zero; }
}
}

private void GetFailureActions()
{
IntPtr scmHndl = IntPtr.Zero;
IntPtr svcHndl = IntPtr.Zero;
IntPtr tmpBuf = IntPtr.Zero;
IntPtr nullValue = new IntPtr(0);

try
{
scmHndl = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
svcHndl = OpenService(scmHndl, "MyServiceName",
SERVICE_ALL_ACCESS);

uint dwBytesNeeded = 8192;
SERVICE_FAILURE_ACTIONS sfa;

bool fRet = QueryServiceConfiguration(svcHndl,
SERVICE_CONFIG_FAILURE_ACTIONS, nullValue, 0, ref dwBytesNeeded);

IntPtr unmanagedArray =
Marshal.AllocHGlobal((int)dwBytesNeeded);
fRet = QueryServiceConfiguration(svcHndl,
SERVICE_CONFIG_FAILURE_ACTIONS, unmanagedArray, dwBytesNeeded, ref
dwBytesNeeded);

sfa =
(SERVICE_FAILURE_ACTIONS)Marshal.PtrToStructure(unmanagedArray,
typeof(SERVICE_FAILURE_ACTIONS));

//Why are the sfa.lpRebootMsg and lpCommand Pointers below,
incorrect??
string reboot = Marshal.PtrToStringAnsi(new
IntPtr(sfa.lpRebootMsg));
string command = Marshal.PtrToStringAnsi(new
IntPtr(sfa.lpCommand));
//string command = Marshal.PtrToStringUni(new
IntPtr(sfa.lpCommand));

Int32[] bins = new Int32[sfa.cActions * 2];
int offset = sfa.lpsaActions;

for (int i = 0; i < sfa.cActions * 2; i++)
{ bins[i]=((Int32)Marshal.ReadIntPtr(new IntPtr(offset + i *
4))); }
Marshal.Release(unmanagedArray);
}
catch (Exception ex)
{ Console.WriteLine(ex.Message); }
}


public enum RecoverAction{ None=0, Restart=1, Reboot=2, RunCommand=3 }

public class FailureAction
{
private RecoverAction type = RecoverAction.None;
private int delay=0;
public FailureAction(){}
public FailureAction( RecoverAction actionType, int actionDelay ){
this.type = actionType;
this.delay = actionDelay;
}

public RecoverAction Type{ get{ return type; } set{ type = value;}
}
public int Delay{ get{ return delay; } set{ delay = value;} }
}

.



Relevant Pages

  • Re: C# HID and Vista 64
    ... Vista 32, and Vista 64. ... public int cbSize; ... For calling the this method, SetupDiEnumDeviceInterfaces, in the SetupAPI.dll; however most exaple has Reserved as just an Int and on a 64 bit platform that doesn't give you the correct size for an IntPtr. ... static public extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, int DeviceInterfaceDetailDataSize, ref int RequiredSize, IntPtr DeviceInfoData); ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: C# HID and Vista 64
    ... public int cbSize; ... bit platform that doesn't give you the correct size for an IntPtr. ... DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: AcquireCredentialsHandle interop
    ... NotSupportedException is a clear sign of something fishy in the P/Invoke type definition, like Long or string in the structure or something. ... Those need to be marshalled by hand as IntPtr ... public int DomainLength; ...
    (microsoft.public.dotnet.framework.compactframework)
  • C# HID and Vista 64
    ... Well I am working on trying to get some HID code to work on Windows XP, Vista 32, and Vista 64. ... public int cbSize; ... For calling the this method, SetupDiEnumDeviceInterfaces, in the SetupAPI.dll; however most exaple has Reserved as just an Int and on a 64 bit platform that doesn't give you the correct size for an IntPtr. ... static public extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, int DeviceInterfaceDetailDataSize, ref int RequiredSize, IntPtr DeviceInfoData); ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: C# HID and Vista 64
    ... public int cbSize; ... bit platform that doesn't give you the correct size for an IntPtr. ... DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr ...
    (microsoft.public.dotnet.languages.csharp)