using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const int SystemPowerInformation = 11;
const uint STATUS_SUCCESS = 0;
[StructLayout(LayoutKind.Sequential)]
struct PROCESSOR_POWER_INFORMATION
{
public uint Number;
public uint MaxMhz;
public uint CurrentMhz;
public uint MhzLimit;
public uint MaxIdleState;
public uint CurrentIdleState;
}
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
[MarshalAs(UnmanagedType.LPArray)]
out byte[] lpOutputBuffer,
int nOutputBufferSize
);
static void Main(string[] args)
{
byte[] buffer = new byte[4 * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))];
uint retval = CallNtPowerInformation(
SystemPowerInformation,
IntPtr.Zero,
0,
out buffer,
4 * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
);
if (retval == STATUS_SUCCESS)
Console.WriteLine(buffer);
}
}
}
I am trying to get some data out of CallNtPowerInformation. I tried to create a struct and call CallNtPowerInformation and marshal the data from it, but that didn't work. So I am trying to see if I can get the data into a byte array, but I get the following:
Object reference not set to an instance of an object.
I believe I am allocating the memory to the buffer.
I am not sure why. Any pointers would be helpful.
Your constant named SystemPowerInformation with value 11 has the wrong name. It should be named ProcessorInformation.
You should declare the p/invoke like this:
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
[Out] PROCESSOR_POWER_INFORMATION[] processorPowerInformation,
int nOutputBufferSize
);
In order to call the function you need to allocate a suitably sized array of PROCESSOR_POWER_INFORMATION structs. Like this:
PROCESSOR_POWER_INFORMATION[] powerInfo =
new PROCESSOR_POWER_INFORMATION[procCount];
The documentation for CallNtPowerInformation tells you to use GetSystemInfo to work out how many processors you have. You can use Environment.ProcessorCount.
Then you call the function like this:
uint retval = CallNtPowerInformation(
ProcessorInformation,
IntPtr.Zero,
0,
powerInfo,
powerInfo.Length*Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
);
Here's a complete program:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const int ProcessorInformation = 11;
const uint STATUS_SUCCESS = 0;
[StructLayout(LayoutKind.Sequential)]
struct PROCESSOR_POWER_INFORMATION
{
public uint Number;
public uint MaxMhz;
public uint CurrentMhz;
public uint MhzLimit;
public uint MaxIdleState;
public uint CurrentIdleState;
}
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
[Out] PROCESSOR_POWER_INFORMATION[] lpOutputBuffer,
int nOutputBufferSize
);
static void Main(string[] args)
{
int procCount = Environment.ProcessorCount;
PROCESSOR_POWER_INFORMATION[] procInfo =
new PROCESSOR_POWER_INFORMATION[procCount];
uint retval = CallNtPowerInformation(
ProcessorInformation,
IntPtr.Zero,
0,
procInfo,
procInfo.Length * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
);
if (retval == STATUS_SUCCESS)
{
foreach (var item in procInfo)
{
Console.WriteLine(item.CurrentMhz);
}
}
}
}
}
Change the parameter type of your umnanaged call to IntPtr:
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
IntPtr lpOutputBuffer,
int nOutputBufferSize
);
And use this before calling it:
GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
Then call it passing that IntPtr as the parameter.
Don't forget to release after use!
Related
I'd like to list out all CSP and CNG providers installed on a system, but I can't find a good method for doing so in C#. For CSP, I can enumerate a certain registry key (inelegant, but functional), but I've been unable to find any way to get a list of CNG providers.
Is there anything remotely like System.Security.Cryptography.Get[CSP/CNG]Providers() or similarly logical/straightforward in .NET that could be used? Thanks!
To my knowledge, there isn't anything like that in .NET Framework.
For CSP providers, enumerate the subkeys of:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider
For CNG providers, enumerate the subkeys of:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Cryptography\Providers
Use this to enumerate CSP providers and containers:
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
namespace CspSample
{
struct Provider
{
public string Name { get; set; }
public int Type { get; set; }
}
class CspUtils
{
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool CryptEnumProviderTypes(
uint dwIndex,
uint pdwReserved,
uint dwFlags,
[In] ref uint pdwProvType,
StringBuilder pszTypeName,
[In] ref uint pcbTypeName);
[DllImport("Advapi32.dll")]
private static extern bool CryptEnumProviders(
int dwIndex,
IntPtr pdwReserved,
int dwFlags,
ref int pdwProvType,
StringBuilder pszProvName,
ref int pcbProvName);
public static List<Provider> ListAllProviders()
{
List<Provider> installedCSPs = new List<Provider>();
int cbName;
int dwType;
int dwIndex;
StringBuilder pszName;
dwIndex = 0;
dwType = 1;
cbName = 0;
while (CryptEnumProviders(dwIndex, IntPtr.Zero, 0, ref dwType, null, ref cbName))
{
pszName = new StringBuilder(cbName);
if (CryptEnumProviders(dwIndex++, IntPtr.Zero, 0, ref dwType, pszName, ref cbName))
{
installedCSPs.Add(new Provider { Name = pszName.ToString(), Type = dwType });
}
}
return installedCSPs;
}
const int PP_ENUMCONTAINERS = 2;
const int PROV_RSA_FULL = 1;
const int ERROR_MORE_DATA = 234;
const int ERROR_NO_MORE_ITEMS = 259;
const int CRYPT_FIRST = 1;
const int CRYPT_NEXT = 2;
//TODO: Find how to disable this flag (not machine keystore)
const int CRYPT_MACHINE_KEYSET = 0x20;
const int CRYPT_VERIFYCONTEXT = unchecked((int)0xF0000000);
public static IList<string> EnumerateKeyContainers(string providerName, int providerType)
{
ProvHandle prov;
if (!CryptAcquireContext(out prov, null, providerName, providerType, CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT))
throw new Win32Exception(Marshal.GetLastWin32Error());
List<string> list = new List<string>();
IntPtr data = IntPtr.Zero;
try
{
int flag = CRYPT_FIRST;
int len = 0;
if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, IntPtr.Zero, ref len, flag))
{
if (Marshal.GetLastWin32Error() != ERROR_MORE_DATA)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
data = Marshal.AllocHGlobal(len);
do
{
if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, data, ref len, flag))
{
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS)
break;
//throw new Win32Exception(Marshal.GetLastWin32Error());
}
list.Add(Marshal.PtrToStringAnsi(data));
flag = CRYPT_NEXT;
}
while (true);
}
finally
{
if (data != IntPtr.Zero)
{
Marshal.FreeHGlobal(data);
}
prov.Dispose();
}
return list;
}
private sealed class ProvHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public ProvHandle()
: base(true)
{
}
protected override bool ReleaseHandle()
{
return CryptReleaseContext(handle, 0);
}
[DllImport("advapi32.dll")]
private static extern bool CryptReleaseContext(IntPtr hProv, int dwFlags);
}
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CryptAcquireContext(out ProvHandle phProv, string pszContainer, string pszProvider, int dwProvType, int dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CryptGetProvParam(ProvHandle hProv, int dwParam, IntPtr pbData, ref int pdwDataLen, int dwFlags);
}
}
I'm trying to marshal the MIB_TCPTABLE_OWNER_MODULE struct from a P/Invoked' call into GetExtendedTcpTable, defined in iphlpapi.dll.
My P/Invoke signature is defined as this:
[DllImport("iphlpapi.dll", SetLastError = true)]
private static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwSize, bool sort, int ipVersion, int tableClass, int reserved);
According to the documentation on MSDN (and looking through the header files), this should set the pTcpTable parameter to the address of a MIB_TCPTABLE_OWNER_MODULE structure, who has a member which is an array of MIB_TCPROW_OWNER_MODULE structures. From tcpmib.h:
typedef struct _MIB_TCPTABLE_OWNER_MODULE
{
DWORD dwNumEntries;
MIB_TCPROW_OWNER_MODULE table[ANY_SIZE];
} MIB_TCPTABLE_OWNER_MODULE, *PMIB_TCPTABLE_OWNER_MODULE;
ANY_SIZE is defined to be 1.
Here is my problem; I've defined the MIB_TCPTABLE_OWNER_MODULE and MIB_TCPROW_OWNER_MODULE structs in C# like so:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_MODULE
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_MODULE table;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_MODULE
{
public uint dwState;
public uint dwLocalAddr;
public uint dwLocalPort;
public uint dwRemoteAddr;
public uint dwRemotePort;
public uint dwOwningPid;
public ulong liCreateTimestamp;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TCPIP_OWNING_MODULE_SIZE)]
public ulong[] OwningModuleInfo;
}
Since I won't know the size of the returned MIB_TCPTABLE_OWNER_MODULE's table member at declaration, my plan was to increment the IntPtr and use Marshal.PtrToStructure to extract each array member from the table member.
The call to Marshal.PtrToStructure returns (no memory violation exceptions), but I wind up with garbage values in the struct members. Here is my complete code:
[DllImport("iphlpapi.dll", SetLastError = true)]
private static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwSize, bool sort, int ipVersion, int tableClass, int reserved);
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_MODULE
{
public uint dwState;
public uint dwLocalAddr;
public uint dwLocalPort;
public uint dwRemoteAddr;
public uint dwRemotePort;
public uint dwOwningPid;
public ulong liCreateTimestamp;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TCPIP_OWNING_MODULE_SIZE)]
public ulong[] OwningModuleInfo;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_MODULE
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_MODULE table;
}
private const int TCPIP_OWNING_MODULE_SIZE = 16;
private const int AF_INET = 2;
private const int TCP_TABLE_OWNER_MODULE_ALL = 8;
public static void GetConnectionDetails()
{
var bufferSize = 0;
var ret = GetExtendedTcpTable(IntPtr.Zero, ref bufferSize, true, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0);
var tableBuffer = Marshal.AllocHGlobal(bufferSize);
try
{
ret = GetExtendedTcpTable(tableBuffer, ref bufferSize, true, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0);
if (ret != 0)
throw new Exception("Oh noes!");
var convertedTable = (MIB_TCPTABLE_OWNER_MODULE)Marshal.PtrToStructure(tableBuffer, typeof (MIB_TCPTABLE_OWNER_MODULE));
var finalTable = new MIB_TCPROW_OWNER_MODULE[convertedTable.dwNumEntries];
var rowPtr = (IntPtr) ((long) tableBuffer + Marshal.SizeOf(convertedTable.dwNumEntries));
for (int i = 0; i < convertedTable.dwNumEntries; i++)
{
var row = (MIB_TCPROW_OWNER_MODULE)Marshal.PtrToStructure(rowPtr, typeof (MIB_TCPROW_OWNER_MODULE));
finalTable[i] = row;
rowPtr = (IntPtr) ((long) rowPtr + Marshal.SizeOf(row)); // Move to the next entry
}
foreach (var entry in finalTable)
{
// do something with each entry
Console.WriteLine(entry.dwState);
Console.WriteLine(entry.dwRemoteAddr);
}
}
finally
{
Marshal.FreeHGlobal(tableBuffer);
}
}
Comparing memory between this and an unmanaged version (that works properly), I do see some differences in the memory of the marshaled struct that I can't account for; there are a few bytes different.
Any assistance is most appreciated!
Consider this struct:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_MODULE
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_MODULE table;
}
You are assuming that the offset of table is equal to the size of dwNumEntries. But you are forgetting about alignment. Since the largest type in MIB_TCPROW_OWNER_MODULE is 8 bytes wide, that type has alignment of 8. Which means that in order for it to be aligned it must be placed at an offset that is a multiple of 8. And hence there is padding between dwNumEntries and table. You need to allow for that padding.
So, at this point:
var rowPtr = (IntPtr) ((long) tableBuffer +
Marshal.SizeOf(convertedTable.dwNumEntries));
you add 4 to the address held in tableBuffer. You actually need to add 8. You should use Marshal.OffsetOf to calculate the offset:
var rowPtr = (IntPtr)((long)tableBuffer +
(long)Marshal.OffsetOf(typeof(MIB_TCPTABLE_OWNER_MODULE), "table"));
I've been searching for a c# library that gets the icon of a given path with many sizes, finally when I got exactly the class that I need, It has a problem:
This method gets icon of a given path:
public static BitmapSource GetIcon(string FileName, bool small, bool checkDisk, bool addOverlay)
{
SHFILEINFO shinfo = new SHFILEINFO();
uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
uint SHGFI_LINKOVERLAY = 0x000008000;
uint flags;
if (small)
{
flags = SHGFI_ICON | SHGFI_SMALLICON;
}
else
{
flags = SHGFI_ICON | SHGFI_LARGEICON;
}
if (!checkDisk)
flags |= SHGFI_USEFILEATTRIBUTES;
if (addOverlay)
flags |= SHGFI_LINKOVERLAY;
var res = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), flags);
if (res == 0)
{
throw (new System.IO.FileNotFoundException());
}
var ico = System.Drawing.Icon.FromHandle(shinfo.hIcon); //**Here**
var bs = BitmapFromIcon(ico);
ico.Dispose();
bs.Freeze();
DestroyIcon(shinfo.hIcon);
// CloseHandle(shinfo.hIcon); it always give exception
return bs;
}
public static extern Boolean CloseHandle(IntPtr handle);
The previous code as it is in this question works as it suppose to, however AFTER getting the icons of file paths in a directory successfully, it gives an exception on this line :
var ico = System.Drawing.Icon.FromHandle(shinfo.hIcon);
An exception of type 'System.IO.FileNotFoundException' occurred in WPF_REMOTE.exe but was not handled in user code
Additional information: Unable to find the specified file.
So Why is this happening?
Update: I found out that it happened because there were a path that contains unicode characters and i need to use SHFILEINFOW instead, still can't figure how to change SHFILEINFO to SHFILEINFOW
another question about the line CloseHandle(shinfo.hIcon); always give an exception :
An exception of type 'System.Runtime.InteropServices.SEHException' occurred in WPF_REMOTE.exe but was not handled in user code
Additional information: External component has thrown an exception.
I'm wondering why it's not working! and why should I use it if the method is already working without it.
also if you have any improvement I could use in this class tell me, Thanks in Advance.
After editing some code I get it, you can get the icons easily from this library, in my case i needed the icon as byte[]
public class IconHelper
{
// Constants that we need in the function call
private const int SHGFI_ICON = 0x100;
private const int SHGFI_SMALLICON = 0x1;
private const int SHGFI_LARGEICON = 0x0;
private const int SHIL_JUMBO = 0x4;
private const int SHIL_EXTRALARGE = 0x2;
// This structure will contain information about the file
public struct SHFILEINFO
{
// Handle to the icon representing the file
public IntPtr hIcon;
// Index of the icon within the image list
public int iIcon;
// Various attributes of the file
public uint dwAttributes;
// Path to the file
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szDisplayName;
// File type
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
[System.Runtime.InteropServices.DllImport("Kernel32.dll")]
public static extern Boolean CloseHandle(IntPtr handle);
private struct IMAGELISTDRAWPARAMS
{
public int cbSize;
public IntPtr himl;
public int i;
public IntPtr hdcDst;
public int x;
public int y;
public int cx;
public int cy;
public int xBitmap; // x offest from the upperleft of bitmap
public int yBitmap; // y offset from the upperleft of bitmap
public int rgbBk;
public int rgbFg;
public int fStyle;
public int dwRop;
public int fState;
public int Frame;
public int crEffect;
}
[StructLayout(LayoutKind.Sequential)]
private struct IMAGEINFO
{
public IntPtr hbmImage;
public IntPtr hbmMask;
public int Unused1;
public int Unused2;
public Rect rcImage;
}
[DllImport("shell32.dll", EntryPoint = "#727")]
private extern static int SHGetImageList(
int iImageList,
ref Guid riid,
out IImageList ppv
);
// The signature of SHGetFileInfo (located in Shell32.dll)
[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);
[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHGetFileInfo(IntPtr pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);
[DllImport("shell32.dll", SetLastError = true)]
static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, Int32 nFolder,
ref IntPtr ppidl);
[DllImport("user32")]
public static extern int DestroyIcon(IntPtr hIcon);
public struct pair
{
public System.Drawing.Icon icon { get; set; }
public IntPtr iconHandleToDestroy { set; get; }
}
private static byte[] ByteFromIcon(System.Drawing.Icon ic)
{
var icon = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(ic.Handle,
System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
icon.Freeze();
byte[] data;
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(icon));
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
data = ms.ToArray();
}
return data;
}
private static byte[] GetSmallIcon(string FileName, IconSize iconSize)
{
SHFILEINFO shinfo = new SHFILEINFO();
uint flags;
if (iconSize == IconSize.Small)
{
flags = SHGFI_ICON | SHGFI_SMALLICON;
}
else
{
flags = SHGFI_ICON | SHGFI_LARGEICON;
}
var res = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), flags);
if (res == 0)
{
throw (new System.IO.FileNotFoundException());
}
var ico = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon);
var bs = ByteFromIcon(ico);
ico.Dispose();
DestroyIcon(shinfo.hIcon);
return bs;
}
private static byte[] GetLargeIcon(string FileName)
{
SHFILEINFO shinfo = new SHFILEINFO();
uint SHGFI_SYSICONINDEX = 0x4000;
int FILE_ATTRIBUTE_NORMAL = 0x80;
uint flags;
flags = SHGFI_SYSICONINDEX;
var res = SHGetFileInfo(FileName, FILE_ATTRIBUTE_NORMAL, ref shinfo, Marshal.SizeOf(shinfo), flags);
if (res == 0)
{
throw (new System.IO.FileNotFoundException());
}
var iconIndex = shinfo.iIcon;
Guid iidImageList = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950");
IImageList iml;
int size = SHIL_EXTRALARGE;
var hres = SHGetImageList(size, ref iidImageList, out iml); // writes iml
IntPtr hIcon = IntPtr.Zero;
int ILD_TRANSPARENT = 1;
hres = iml.GetIcon(iconIndex, ILD_TRANSPARENT, ref hIcon);
var ico = System.Drawing.Icon.FromHandle(hIcon);
var bs = ByteFromIcon(ico);
ico.Dispose();
DestroyIcon(hIcon);
return bs;
}
}
and you can get four different sizes for the icon
I am attempting to write code to extract the contents of a CAB file, however I am having trouble using the SetupIterateCabinet routine.
Please see doc here http://msdn.microsoft.com/en-us/library/aa377404(v=vs.85).aspx
I can import it properly like this
private const uint SPFILENOTIFY_CABINETINFO = 0x00000010;
private const uint SPFILENOTIFY_FILEINCABINET = 0x00000011;
private const uint SPFILENOTIFY_NEEDNEWCABINET = 0x00000012;
private const uint SPFILENOTIFY_FILEEXTRACTED = 0x00000013;
private const uint SPFILENOTIFY_FILEOPDELAYED = 0x00000014;
private const uint NO_ERROR = 0;
private const uint FILEOP_ABORT = 0;
private const uint FILEOP_DOIT= 1;
private const uint FILEOP_SKIP= 2;
private const uint FILEOP_NEWPATH= 4;
static void Main(string[] args)
{
SetupIterateCabinet("c:\\SomeCab.cab", 0, new PSP_FILE_CALLBACK(CallBack), 0);
Console.ReadKey();
}
[DllImport("SetupApi.dll", CharSet = CharSet.Auto)]
public static extern bool SetupIterateCabinet(string cabinetFile,
uint reserved, PSP_FILE_CALLBACK callBack, uint context);
public delegate uint PSP_FILE_CALLBACK(uint context, uint notification,
IntPtr param1, IntPtr param2);
private static uint CallBack(uint context, uint notification, IntPtr param1,
IntPtr param2)
{
uint rtnValue = NO_ERROR;
switch (notification)
{
case SPFILENOTIFY_FILEINCABINET:
rtnValue = OnFileFound(context, notification, param1, param2);
break;
case SPFILENOTIFY_FILEEXTRACTED:
rtnValue = OnFileExtractComplete(param1);
break;
case SPFILENOTIFY_NEEDNEWCABINET:
rtnValue = NO_ERROR;
break;
}
return rtnValue;
}
private static uint OnFileExtractComplete(IntPtr param1)
{
Console.WriteLine("Complete");
return FILEOP_DOIT;
}
[StructLayout(LayoutKind.Sequential)]
struct _FILE_IN_CABINET_INFO {
IntPtr NameInCabinet;
int FileSize;
int Win32Error;
int DosDate;
int DosTime;
int DosAttribs;
StringBuilder FullTargetName;
};
static private uint OnFileFound(uint context, uint notification, IntPtr param1, IntPtr param2)
{
_FILE_IN_CABINET_INFO fc = new _FILE_IN_CABINET_INFO() ;
Marshal.PtrToStructure(param1, fc);
return 1;
}
However the problem comes when attempting to process the SPFILENOTIFY_FILEINCABINET event in the callback. According to the documentation this is a struct, that I need to put the name of where I want to have the file extracted to in. I am having trouble figuring out what the struct should look like and maybe how to convert the param to a struct.
I think you have a problem with the return values of your callback function. On SPFILENOTIFY_FILECABINET, you should be returning FILEOP_DOIT. Before returning you should be setting up the filename in the FILE_IN_CABINTE_INFO. Please check the codeproject post http://www.codeproject.com/Articles/7165/Iterate-and-Extract-Cabinet-File
I might add some code sample later. GTG now
EDIT:
Code sample below. I haven't tried it, but I believe it should work. I have tried to keep the structure similar to your code. This should show you how to define the FILE_IN_CABINET_INFO class and the correct values to be set and returned in the callback
public delegate uint PSP_FILE_CALLBACK(uint context, uint notification, IntPtr param1, IntPtr param2);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class FILE_IN_CABINET_INFO {
public String NameInCabinet;
public uint FileSize;
public uint Win32Error;
public ushort DosDate;
public ushort DosTime;
public ushort DosAttribs;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public System.String FullTargetName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class FILEPATHS {
public String Target;
public String Source;
public uint Win32Error;
public uint Flags;
}
public const uint SPFILENOTIFY_FILEINCABINET = 0x00000011; // The file has been extracted from the cabinet.
public const uint SPFILENOTIFY_NEEDNEWCABINET = 0x00000012; // file is encountered in the cabinet.
public const uint SPFILENOTIFY_FILEEXTRACTED = 0x00000013; // The current file is continued in the next cabinet.
public const uint NO_ERROR = 0;
public const uint FILEOP_ABORT = 0; // Abort cabinet processing.
public const uint FILEOP_DOIT = 1; // Extract the current file.
public const uint FILEOP_SKIP = 2; // Skip the current file.
[DllImport("SetupApi.dll", CharSet = CharSet.Auto)]
public static extern bool SetupIterateCabinet(string cabinetFile, uint reserved, PSP_FILE_CALLBACK callBack, uint context);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetLastError();
static void Main(string[] args) {
IterateCabinet(#"c:\SomeCab.cab");
}
public static void IterateCabinet(string filePath) {
PSP_FILE_CALLBACK callback = new PSP_FILE_CALLBACK(CallBack);
if (!SetupIterateCabinet(filePath, 0, callback, 0))
throw new Win32Exception((int)GetLastError());
}
static uint CallBack(uint context, uint notification, IntPtr param1, IntPtr param2) {
if (notification == SPFILENOTIFY_FILEINCABINET)
return OnFileFound(context, notification, param1, param2);
else if (notification == SPFILENOTIFY_FILEEXTRACTED)
return OnFileExtractComplete(param1);
else if (notification == SPFILENOTIFY_NEEDNEWCABINET)
return NO_ERROR;
return NO_ERROR;
}
static uint OnFileFound(uint context, uint notification, IntPtr param1, IntPtr param2) {
FILE_IN_CABINET_INFO fileInCabinetInfo = (FILE_IN_CABINET_INFO)Marshal.PtrToStructure(param1, typeof(FILE_IN_CABINET_INFO));
fileInCabinetInfo.FullTargetName = fileInCabinetInfo.NameInCabinet; // extract to current directory
return FILEOP_DOIT;
}
static uint OnFileExtractComplete(IntPtr param1) {
FILEPATHS filePaths = (FILEPATHS)Marshal.PtrToStructure(param1, typeof(FILEPATHS));
if (filePaths.Win32Error == NO_ERROR)
Console.WriteLine("File {0} extracted to {1} " + filePaths.Source, filePaths.Target);
else
Console.WriteLine("Errors occurred while extracting cab File {0} to {1} ", filePaths.Source, filePaths.Target);
return filePaths.Win32Error;
}
My HTC HD2 can't be rebooted from OS, just shut down. So I want to write a small program to do that.
Is it possible to programmatically reboot Windows Mobile 6.x device using C#?
You should use the documented ExitWindowsEx API. IOCTL should only be used on platforms lacking the ExitWindowsEx function call (Pocket PC 2000, 2002, and 2003). See the MSDN doc for more information.
[DllImport("aygshell.dll", SetLastError=""true"")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ExitWindowsEx([MarshalAs(UnmanagedType.U4)]uint dwFlags, [MarshalAs(UnmanagedType.U4)]uint dwReserved);
enum ExitWindowsAction : uint
{
EWX_LOGOFF = 0,
EWX_SHUTDOWN = 1,
EWX_REBOOT = 2,
EWX_FORCE = 4,
EWX_POWEROFF = 8
}
void rebootDevice()
{
ExitWindowsEx(ExitWindowsAction.EWX_REBOOT, 0);
}
SOFTRESET / HARDRESET
public class Reboot
{
public const uint FILE_DEVICE_HAL = 0x00000101;
public const uint METHOD_BUFFERED = 0;
public const uint FILE_ANY_ACCESS = 0;
public static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
[DllImport("Coredll.dll")]
public extern static uint KernelIoControl
(
uint dwIoControlCode,
IntPtr lpInBuf,
uint nInBufSize,
IntPtr lpOutBuf,
uint nOutBufSize,
ref uint lpBytesReturned
);
/// <summary>
/// Causes the CE device to soft/warm reset
/// </summary>
public static uint SoftReset()
{
uint bytesReturned = 0;
uint IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS);
SetCleanRebootFlag();
return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned);
}
[DllImport("coredll.dll")]
public extern static uint SetSystemPowerState
(
String psState,
Int32 StateFlags,
Int32 Options
);
const int POWER_FORCE = 4096;
const int POWER_STATE_RESET = 0x00800000;
public static uint ColdReset()
{
SetCleanRebootFlag();
return SetSystemPowerState(null, POWER_STATE_RESET, POWER_FORCE);
}
[DllImport("Coredll.dll")]
public extern static int KernelIoControl(int dwIoControlCode, IntPtr lpInBuf, int nInBufSize, IntPtr lpOutBuf, int nOutBufSize, ref int lpBytesReturned);
[DllImport("Coredll.dll")]
public extern static void SetCleanRebootFlag();
public static void HardReset()
{
int IOCTL_HAL_REBOOT = 0x101003C;
int bytesReturned = 0;
SetCleanRebootFlag();
KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned);
}
[DllImport("aygshell.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ExitWindowsEx([MarshalAs(UnmanagedType.U4)]uint dwFlags, [MarshalAs(UnmanagedType.U4)]uint dwReserved);
enum ExitWindowsAction : uint
{
EWX_LOGOFF = 0,
EWX_SHUTDOWN = 1,
EWX_REBOOT = 2,
EWX_FORCE = 4,
EWX_POWEROFF = 8
}
//
void rebootDevice()
{
ExitWindowsEx(ExitWindowsAction.EWX_REBOOT, 0);
}
I think this will help you: Hard Reset Windows Mobile Device..Still this method is not "clear c# code", because it uses Interop, but it works, so it can solve your problem.
For soft reset:
[DllImport("coredll.dll", SetLastError=true)]
private static extern bool KernelIoControl(int dwIoControlCode, byte[] inBuf, int inBufSize, byte[] outBuf, int outBufSize, ref int bytesReturned);
private const uint FILE_DEVICE_HAL = 0x00000101;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
private static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
public static void softReset()
{
uint bytesReturned = 0;
uint IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS);
KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned);
}
(tho i haven't used this method myself..see here)