Handling WM_DEVICECHANGE message in C#; how to handle LPARAM?

J

Jason Seeley

Hi, I'm trying to handle the WM_DEVICECHANGE message, and have the
actual message triggering my WndProc and coming on through. The
problem I'm having, however, is determining whether I care about the
drive that has triggered the message. All of that is contained within
the LPARAM pointer (DEV_BROADCAST_HDR *). However, I have no idea how
I'm supposed to take the LParam value and turn it into something I can
use in my managed program.

These are the structures I care about, but when I use m.LParam, I
don't know how to get from there to an object I can use.

struct _DEV_BROADCAST_HEADER { /* */
DWORD dbcd_size;
DWORD dbcd_devicetype;
DWORD dbcd_reserved;
};

struct _DEV_BROADCAST_VOLUME { /* */
DWORD dbcv_size;
DWORD dbcv_devicetype;
DWORD dbcv_reserved;
DWORD dbcv_unitmask;
WORD dbcv_flags;
};


If anyone has any suggestions or pointers, please let me know.

Thanks --
Jason
 
G

Guest

In C++ there are functions HIWORD LOWORD..

Check the C++ Doc for your message to see what is in HiWord and LoWord.

I have not yet figureed this out definitivel
but depending on Hi/Low word one of these combinations below usually gets me what I nee
maybe someone can explain this better to both of us

GetLoWord( m.WParam.ToInt32() )

/// <summary
/// Method: Lets the HiWord from an integer value, good for interpretin
/// LParam, WParam et
/// </summary
/// <param name="aValue"></param
/// <returns></returns
public static int GetHiWord(int aValue)
{
//TODO: figure this out properly for LPara
int x = (aValue >> 16)
int x1 = (aValue >> 16) & 0xffff;
int x2 = (aValue >> 16) & 0x0000;
return (aValue >> 16);
}
/// <summary
/// Method: Lets the LoWord from an integer value, good for interpretin
/// LParam, WParam et
/// </summary
/// <param name="aValue"></param
/// <returns></returns
public static int GetLoWord(int aValue)
{
return aValue & 0xffff;
}
 
J

Jason Seeley

In C++ there are functions HIWORD LOWORD...

Check the C++ Doc for your message to see what is in HiWord and LoWord..

I have not yet figureed this out definitively
but depending on Hi/Low word one of these combinations below usually gets me what I need
maybe someone can explain this better to both of us!

GetLoWord( m.WParam.ToInt32() );

/// <summary>
/// Method: Lets the HiWord from an integer value, good for interpreting
/// LParam, WParam etc
/// </summary>
/// <param name="aValue"></param>
/// <returns></returns>
public static int GetHiWord(int aValue)
{
//TODO: figure this out properly for LParam
int x = (aValue >> 16);
int x1 = (aValue >> 16) & 0xffff;
int x2 = (aValue >> 16) & 0x0000;
return (aValue >> 16);
}
/// <summary>
/// Method: Lets the LoWord from an integer value, good for interpreting
/// LParam, WParam etc
/// </summary>
/// <param name="aValue"></param>
/// <returns></returns>
public static int GetLoWord(int aValue)
{
return aValue & 0xffff;
}

In this particular case, LPARAM contains a pointer to a
DEV_BROADCAST_HDR structure, so I don't think that HIWORD and LOWORD
are going to do it for me. For the immediate solution, I'm going to
create a C++ DLL that I can pass the LPARAM value to in order to have
it do the pointer work and return the values that I want out of the
thing. I consider that a 'hack' solution, though, so I'm hoping there
is a better way.

Thanks --
Jason
 
G

Guest

In that case did you try creating the Structure and then Casting the Message with the Lparam to the new Structure?

_DEV_BROADCAST_HEADER newHeader = (_DEV_BROADCAST_HEADER)message.Lparam

or it might be like this with a cast to int first.

_DEV_BROADCAST_HEADER newHeader = (_DEV_BROADCAST_HEADER)(int)message.Lparam

I am not that familar with this, but I do remember having to do casting like this in some code...
 
J

Jason Seeley

In that case did you try creating the Structure and then Casting the Message with the Lparam to the new Structure??

_DEV_BROADCAST_HEADER newHeader = (_DEV_BROADCAST_HEADER)message.Lparam;

or it might be like this with a cast to int first..

_DEV_BROADCAST_HEADER newHeader = (_DEV_BROADCAST_HEADER)(int)message.Lparam;

I am not that familar with this, but I do remember having to do casting like this in some code...

No, that doesn't work, because I am in managed (not unsafe) code, and
the header is a pointer to a structure, not just a single int value.
The compiler complains that it doesn't know how to explicitly convert
from an IntPtr to a DEV_BROADCAST_HEADER, and in order for me to write
something that would define that cast, I would need to write some
unsafe code. Maybe that's the solution, but I haven't messed with
unsafe code, and I was looking for a quick answer today (I can
probably come back to it in a couple of weeks when time isn't so
tight).

I've got it working by passing the IntPtr to a C++ DLL, and letting
the C++ DLL do all of the pointer manipulation. There's got to be a
way to use the LParam as something else, but I am guessing that it
will either involve making my project 'unsafe' or through some casting
magic that I haven't discovered yet. The thing that makes me doubt
that it will work within the realms of safe casting is that it is a
pointer to a structure, and that structure is unsafe, and therefore
does not contain any type information.

Thanks --
Jason
 
Y

Ying-Shen Yu[MSFT]

Hi Jason,

You cat get the structure data using Marshal class , since the data is
actually allocated on the unmanaged heap so we need declare the structure
in managed code and copy the data into it manually. Here is an sample for
this:
<code>
[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_VOLUME
{
public int dbcv_size;
public int dbcv_devicetype;
public int dbcv_reserved;
public int dbcv_unitmask;
}
protected override void WndProc(ref Message m)
{
//you may find these definitions in dbt.h and winuser.h
const int WM_DEVICECHANGE = 0x0219;
const int DBT_DEVICEARRIVAL = 0x8000; // system detected a new device
const int DBT_DEVTYP_VOLUME = 0x00000002; // logical volume

//we detect the media arrival event
if (m.Msg == WM_DEVICECHANGE && m.WParam.ToInt32() == DBT_DEVICEARRIVAL)
{
int devType = Marshal.ReadInt32(m.LParam,4);
if(devType == DBT_DEVTYP_VOLUME)
{
DEV_BROADCAST_VOLUME vol;
vol = (DEV_BROADCAST_VOLUME)
Marshal.PtrToStructure(m.LParam,typeof(DEV_BROADCAST_VOLUME));
MessageBox.Show(vol.dbcv_unitmask.ToString("x"));
}
}
base.WndProc (ref m);
}
</code>
Does this answer your question?
If you still have questions on this issue, please reply in this newsgroup.
Thanks!

Best regards,

Ying-Shen Yu [MSFT]
Microsoft community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top