How to get info from Control Panel files(*.cpl)?

  • Thread starter Thread starter yxq
  • Start date Start date
Y

yxq

Hello
I want to retrive the Name & Description from a Control Panel file(*.cpl)
how to do?

Thanks
 
Mattias,

I was looking into this for my personal interest, but I can't get
CPL_NEWINQUIRE to fill the NEWCPLINFO structure passed as pointer.

Here's what I'm talking about:

NEWCPLINFO newcplinfo = new NEWCPLINFO();

newcplinfo.dwSize = Marshal.SizeOf(newcplinfo);

IntPtr ptr;
ptr = Marshal.AllocHGlobal(newcplinfo.dwSize);
Marshal.StructureToPtr(newcplinfo, ptr, false);

IntPtr hr = (IntPtr)appletType.InvokeMember( "CPlApplet",
BindingFlags.InvokeMethod, null, appletInstance, new Object[] { hwndCPl,
this.CPL_NEWINQUIRE, 0, ptr} );

NEWCPLINFO n =
(NEWCPLINFO)Marshal.PtrToStructure(ptr,typeof(NEWCPLINFO));

The struct "n" should contain the applet information, but instead is empty
(besides the value of dwSize). Any suggestion?

Thank you,

Gabriele
 
Hi,

I wrote a little DLL in managed C++ to get name and description of a control
panel application. It's much easier than fighting with platform invoke. Let
me know if you're still interested.

Regards,

Gabriele
 
Gabriele,

How did you declare the NEWCPLINFO struct? Which applet are you trying
it on? What does it return? Are you sure it handles CPL_NEWINQUIRE,
and not just CPL_INQUIRE?



Mattias
 
How did you declare the NEWCPLINFO struct?

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct NEWCPLINFO
{
public int dwSize;
public int dwFlags;
public int dwHelpContext;
public IntPtr lpData;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]public String szName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]public String szInfo;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]public String
szHelpFile;
}
Which applet are you trying it on?

I tried with joy.cpl and desk.cpl
Are you sure it handles CPL_NEWINQUIRE, and not just CPL_INQUIRE?

I tried both, without success. It's probably something with my code, but I
can't figure out what. Here's the code of the ControlPanelApplet class (I
apologize for the quality of the code, I wrote it just to test the idea).

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;

namespace ControlPanelTest
{
public class ControlPanelApplet
{
private string appletName;
private string appletDLL;
private static ModuleBuilder appletModuleBuilder;
private Type appletType;
private Object appletInstance;

public string Name;
public string Info;

public int CPL_INIT = 1;
public int CPL_GETCOUNT = 2;
public int CPL_NEWINQUIRE = 8;
public int CPL_STOP = 6;
public int CPL_EXIT = 7;

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CPLINFO
{
public int idIcon;
public int idName;
public int idInfo;
public IntPtr lpData;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct NEWCPLINFO
{
public int dwSize;
public int dwFlags;
public int dwHelpContext;
public IntPtr lpData;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]public String szName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]public String szInfo;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]public String
szHelpFile;
}

public ControlPanelApplet()
{
appletName = "";
appletDLL = "";
}

public ControlPanelApplet(string name, string dll)
{
appletName = name;
appletDLL = dll;
}

public void Initialize()
{
MethodBuilder methodBuilder;

if( appletModuleBuilder == null )
{
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = appletName;
AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly( assemblyName,
AssemblyBuilderAccess.Run );
appletModuleBuilder = assemblyBuilder.DefineDynamicModule(
"DynamicModule" );
}

TypeBuilder typeBuilder = appletModuleBuilder.DefineType( appletName );

Type[] methodType =
{typeof(IntPtr),typeof(int),typeof(int),typeof(IntPtr)};

methodBuilder = typeBuilder.DefinePInvokeMethod( "CPlApplet", appletDLL,
MethodAttributes.Public | MethodAttributes.Static |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard, typeof(IntPtr), methodType,
CallingConvention.Winapi, CharSet.Auto );

methodBuilder.SetImplementationFlags( MethodImplAttributes.PreserveSig |
methodBuilder.GetMethodImplementationFlags() );
appletType = typeBuilder.CreateType();
appletInstance = Activator.CreateInstance( appletType );
}

public IntPtr Call(string method, IntPtr hwndCPl, int uMsg, int lParam1,
int lParam2)
{
IntPtr hr = (IntPtr)appletType.InvokeMember( method,
BindingFlags.InvokeMethod, null,
appletInstance, new Object[] { hwndCPl, uMsg, lParam1 , new
IntPtr(lParam2) } );

if ( (int)hr != 0 ) Marshal.ThrowExceptionForHR( (int)hr );

return hr;
}

public IntPtr Init( IntPtr hwndCPl )
{
IntPtr hr = (IntPtr)appletType.InvokeMember( "CPlApplet",
BindingFlags.InvokeMethod, null,
appletInstance, new Object[] { hwndCPl, this.CPL_INIT, 0, new
IntPtr(0) } );

if ( (int)hr != 0 ) Marshal.ThrowExceptionForHR( (int)hr );

return hr;
}

public IntPtr Inquiry( IntPtr hwndCPl, int lParam1 )
{
CPLINFO cplinfo = new CPLINFO();

IntPtr ptr;
ptr = Marshal.AllocHGlobal(Marshal.SizeOf(cplinfo));
Marshal.StructureToPtr(cplinfo, ptr, false);

IntPtr hr = (IntPtr)appletType.InvokeMember( "CPlApplet",
BindingFlags.InvokeMethod, null,
appletInstance, new Object[] { hwndCPl, this.CPL_NEWINQUIRE, lParam1-1,
ptr} );

if ( (int)hr != 0 ) Marshal.ThrowExceptionForHR( (int)hr );

CPLINFO n = (CPLINFO)Marshal.PtrToStructure(ptr,typeof(CPLINFO));

this.Name = n.idName.ToString();
this.Info = n.idInfo.ToString();

return hr;
}

public IntPtr NewInquiry( IntPtr hwndCPl, int lParam1 )
{
NEWCPLINFO newcplinfo = new NEWCPLINFO();

newcplinfo.dwSize = Marshal.SizeOf(newcplinfo);

IntPtr ptr;
ptr = Marshal.AllocHGlobal(newcplinfo.dwSize);
Marshal.StructureToPtr(newcplinfo, ptr, false);

IntPtr hr = (IntPtr)appletType.InvokeMember( "CPlApplet",
BindingFlags.InvokeMethod, null,
appletInstance, new Object[] { hwndCPl, this.CPL_NEWINQUIRE, lParam1-1,
ptr} );

if ( (int)hr != 0 ) Marshal.ThrowExceptionForHR( (int)hr );

NEWCPLINFO n =
(NEWCPLINFO)Marshal.PtrToStructure(ptr,typeof(NEWCPLINFO));

this.Name = n.szName;
this.Info = n.szInfo;

return hr;
}

}
}

Thank you,

Gabriele
 
Gabriele,

There were a few issues with your code, for example that you sent
CPL_NEWINQUIRE in the Inquiry method, I assume you meant CPL_INQUIRE.

Also, you only used the ANSI version of the NEWCPLINFO struct. Most
applets on recent NT based versions of Windows expect the larger
Unicode version. Ideally you should handle both by checking the dwSize
member.

Rather than to correct your code, I wrote this almost from scratch.
It's a little less fancy than yours, no dynamic assemblies or OOP
involved, just straight procedural code. But hopefully it helps you
get yours working, as it should work the same with a dynamicly
generated P/Invoke method.

Note that I don't bother to check the return values from the
CPL_(NEW)INQUIRE messages, because a lot of applets don't seem to
follow the SDK rules and return 0 to indicate success.


public struct CPLINFO
{
public int idIcon;
public int idName;
public int idInfo;
public IntPtr lpData;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct NEWCPLINFOA
{
public int dwSize;
public int dwFlags;
public int dwHelpContext;
public IntPtr lpData;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String
szName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)] public String
szInfo;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public String
szHelpFile;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct NEWCPLINFOW
{
public int dwSize;
public int dwFlags;
public int dwHelpContext;
public IntPtr lpData;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String
szName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)] public String
szInfo;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public String
szHelpFile;
}

public class ControlPanelAppletInfo
{
const string APPLET_DLL = @"e:\WINDOWS\system32\timedate.cpl";

[DllImport(APPLET_DLL)]
static extern uint CPlApplet(IntPtr hwndCpl, uint msg, uint lParam1,
IntPtr lParam2);

[DllImport(APPLET_DLL)]
static extern uint CPlApplet(IntPtr hwndCpl, uint msg, uint lParam1,
out CPLINFO lParam2);

const uint CPL_INIT = 1;
const uint CPL_GETCOUNT = 2;
const uint CPL_INQUIRE = 3;
const uint CPL_NEWINQUIRE = 8;
const uint CPL_EXIT = 7;

static void Main()
{
IntPtr hwnd = IntPtr.Zero;

// Buffer should be big enough to hold the largest of the two
NEWCPLINFO versions, NEWCPLINFOW
int BUFFER_SIZE = Marshal.SizeOf( typeof(NEWCPLINFOW) );

if ( CPlApplet( hwnd, CPL_INIT, 0, IntPtr.Zero ) != 0 ) {
uint count = CPlApplet( hwnd, CPL_GETCOUNT, 0, IntPtr.Zero );
for ( uint i = 0; i < count; i++ ) {
Console.WriteLine( "--- Applet #{0} ---", i );

// Try CPL_INQUIRE
CPLINFO cplinfo;
uint ret = CPlApplet( hwnd, CPL_INQUIRE, i, out cplinfo );
Console.WriteLine( "CPL_INQUIRE returned " + ret );
Console.WriteLine( "CPLINFO: idIcon = {0}, idName = {1},
idInfo = {2}, lpData = {0:X}",
cplinfo.idIcon, cplinfo.idName, cplinfo.idInfo,
(int)cplinfo.lpData );

// Try CPL_NEWINQUIRE
IntPtr buffer = IntPtr.Zero;
try {
buffer = Marshal.AllocHGlobal( BUFFER_SIZE );
Marshal.WriteInt32( buffer, 0 ); // ->dwSize = 0

ret = CPlApplet( hwnd, CPL_NEWINQUIRE, i, buffer );
Console.WriteLine( "CPL_NEWINQUIRE returned " + ret );
int size = Marshal.ReadInt32( buffer );
if ( size == BUFFER_SIZE ) { // sizeof(NEWCPLINFOW)
NEWCPLINFOW infow = (NEWCPLINFOW)Marshal.PtrToStructure(
buffer, typeof(NEWCPLINFOW) );
Console.WriteLine( "NEWCPLINFOW: hIcon = {0:X}, szName =
'{1}', szInfo = '{2}', lpData = {0:X}",
(int)infow.hIcon, infow.szName, infow.szInfo,
(int)infow.lpData );
}
else if ( size == Marshal.SizeOf( typeof(NEWCPLINFOA) ) ) {
NEWCPLINFOA infoa = (NEWCPLINFOA)Marshal.PtrToStructure(
buffer, typeof(NEWCPLINFOA) );
Console.WriteLine( "NEWCPLINFOA: hIcon = {0:X}, szName =
'{1}', szInfo = '{2}', lpData = {0:X}",
(int)infoa.hIcon, infoa.szName, infoa.szInfo,
(int)infoa.lpData );
}
else
Console.WriteLine( "Unknown NEWCPLINFO size " + size );
}
finally {
if ( buffer != IntPtr.Zero ) Marshal.FreeHGlobal( buffer );
}
}
CPlApplet( hwnd, CPL_EXIT, 0, IntPtr.Zero );
}
else
Console.WriteLine( "CPL_INIT failed" );
}

}



Mattias
 
Mattias,

Thank you very much for taking some of your time to look into this issue. I
know you are a busy guy.

Gabriele
 
Back
Top