In one MSDN article, I read the following:
HMONITOR and the Device Context
Each physical display is represented by a monitor handle of type HMONITOR.
However, another article seems to contradict that statement:
GetPhysicalMonitorsFromHMONITOR function
A single HMONITOR handle can be associated with more than one physical monitor.
So my question is: under what circumstances will an HMONITOR be associated with multiple physical monitors?
An HMONITOR can be associated with multiple physical/virtual monitors like this:
multi-monitors share a same HMONITOR
When select 'Duplicate these displys' instead of 'Extend these displays', two physical/virtual monitors can share one HMONITOR, or in other word, they are totally overlapped. In this case, you may get two IDDCX_MONITORs(physical or virtual monitors) but only one HMONITOR.
Actually, I'm finding way of mapping between IDDCX_MONITORs and HMONITORs:Map a IDDCX_MONITOR to a HMONITOR
Related
Just as the title says, I am writing a networking program where I open a handle to a network driver using CreateFile, and I have been experimenting with the NO_BUFFERING flag.
Most documentation won't even mention this being used with communication devices, and the ones that do (AKA the MSDN reference, etc), simply mention that you can.
Does anyone have any idea how this may affect communication with the device?
It is a device driver implementation detail, options you specify in the CreateFile() call are passed in the IRP_MJ_REQUEST request. The one I linked is the one for file systems, it is very fancy one. Click through the IrpSp->Parameters.Create.Options link to IoCreateFileSpecifyDeviceObjectHint()'s Options argument to see FILE_NO_INTERMEDIATE_BUFFERING.
The documentation for the IRP_MJ_REQUEST for serial ports is here. Very simple one, no arguments at all :) In general, the winapi to device driver interface for communication ports is a very straight-forward. There's an (almost) direct mapping between the documented winapi function and its underlying IOCTL. The winapi function doesn't do much beyond basic error checking, then quickly passes the job to the driver.
So there isn't any way to pass the FILE_FLAG_NO_BUFFERING option you specify so it simply doesn't get used.
Otherwise the logical conclusion, serial port I/O is interrupt driven, the driver must buffer in order to not lose bytes and keep an acceptable transfer rate. You can technically tinker with the buffer sizes through SetupComm() but, as documented, it is only a recommendation with pretty high odds that the driver simply ignores very low values.
We have some HID devices (touch digitizers) that communicate with an internal R&D tool. This tool parses the raw feature reports from the devices to draw the touch reports along with some additional data that are present in the raw feature report but filtered out by the HID driver of Windows 7 (eg, pressure data is not present in WM_TOUCH messages).
However, we have started working with some devices that may have different firmware variants, and thus that do not share the same ordering or bytelength of the fields and I need to modify our R&D tool so that it will adapt transparently to all the devices.
The devices come from the same manufacturer (ourselves) and share the same device info, so using these fields to differentiate between the different firmwares is not an option. What I would like to do is to get the HID feature report descriptor sent by the device and update dynamically our feature report parsing method based on this information.
However, I didn't manage to find the correct method to call in order to get this descriptor when browsing the Windows API. What I have found so far is the Raw Input page on MSDN, but I'm not sure what to do next. Can I find the required information in the RID_DEVICE_HID structure ? Or do I need to call a completely different API ?
Thanks in advance for your help!
Ok, finally I've got something (almost completely) functional. As inferred by mcoill, I used the HidP_xxx() family of functions, but it needs a little bit of data preparation first.
I based my solution on this example code that targets USB joysticks and adapted it to touch digitizer devices.
If someone else also gets confused by the online doc, here are the required steps involved in the process:
registering the application for a Raw Input device at launch.
This is done by calling the function RegisterRawInputDevice(&Rid, 1, sizeof(Rid)), where Rid is a RAWINPUTDEVICE with the following properties set (in order to get a touch digitizer) :
Rid.usUsage = 0x04;
Rid.usUsagePage = 0x0d;
Rid.dwFlags = RIDEV_INPUT_SINK;
registering a callback OnInput(LPARAM lParam) for the events WM_INPUT since the Rid device will generate this type of events;
the OnInput(LPARAM lParam) method will get the data from this event in two steps:
// Parse the raw input header to read its size.
UINT bufferSize;
GetRawInputData(HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));
// Allocate memory for the raw input data and retrieve it
PRAWINPUT = (PRAWINPUT)HeapAlloc(GetProcessHeap(), 0, bufferSize);
GetRawInputData(HRAWINPUT)lParam, RID_INPUT, rawInput /* NOT NULL */, &bufferSize, sizeof(RAWINPUTHEADER));
it then calls a parsing method that creates the HIDP_PREPARSED_DATA structure required by the lookup functions:
// Again, read the data size, allocate then retrieve
GetRawInputDeviceInfo(rawInput->header.hDevice, RIDI_PREPARSEDDATA, NULL, &bufferSize);
PHIDP_PREPARSED_DATA preparsedData = (PHIDP_PREPARSED_DATA)HeapAlloc(heap, 0, bufferSize);
GetRawInputDeviceInfo(rawInput->header.hDevice, RIDI_PREPARSEDDATA, preparsedData, &bufferSize);
The preparsed data is split into capabilities:
// Create a structure that will hold the values
HidP_GetCaps(preparsedData, &caps);
USHORT capsLength = caps.NumberInputValueCaps;
PHIDP_VALUE_CAPS valueCaps = (PHIDP_VALUE_CAPS)HeapAlloc(heap, 0, capsLength*sizeof(HIDP_VALUE_CAPS));
HidP_GetValueCaps(HidP_Input, valueCaps, &capsLength, preparsedData);
And capabilities can be asked for their value:
// Read sample value
HidP_GetUsageValue(HidP_Input, valueCaps[i].UsagePage, 0, valueCaps[i].Range.UsageMin, &value, preparsedData, (PCHAR)rawInput->data.hid.bRawData, rawInput->data.hid.dwSizeHid);
Wouldn't HidP_GetPReparsedData(...), HidP_GetValueCaps(HidP_Feature, ...) and their ilk give you enough information without having to get the raw feature report?
HIDClass Support Routines on MSDN
I wanted to figure out what the syscalls behind GetWindowText are. I wrote a simple program to call GetWindowText with a handle to a window in a different process.
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(0,"Attach debugger and set bp","on GetWindowTextA",0);
HWND winmine = FindWindow(NULL,"Minesweeper");
if(winmine != NULL)
{
char buf[255] = "";
GetWindowTextA(winmine, buf, 254);
MessageBox(0,buf,"Found",0);
}
else
{
MessageBox(0,"?","Found nothing",0);
}
return 0;
}
I attached a debugger and stepped through the GetWindowTextA call, manually stepping through everything except these API calls (in order):
GetWindowThreadProcessId (in GetWindowLong)
InterlockedIncrement
WCSToMBEx (which is basically WideCharToMultiByte)
InterlockedDecrement
None of these API calls seem to be able to read a string in memory not owned by the calling process. I used a usermode debugger so I certainly didn't end up in kernelmode while stepping without realizing it. This means that GetWindowText got the window name without performing a context switch. Which seems to imply that the text for every window that exists is accessible without a context switch.. and that can't be right because there's no way Windows keeps a copy of the text for every single window/control on the system, on every single process.
I have read this article. It mentions that window names are stored in quote "a special place", but does not explain how this "special place" can be accessed from a different process without a syscall/context switching.
So I'm looking for any explanations as to how this is done. Any information you can provide is greatly appreciated.
GetWindowText got the window name without performing a context switch. Which seems to imply that the text for every window that exists is accessible without a context switch.
This info is stored in memory that is shared between all the processes that use user32.dll. You may try to search virtual space of your process for unicode names of other processes' windows.
It gets mapped into the process address space during user32.dll loading. There are some kernel structures/sections involved: win32k!gSharedInfo, win32k!ghSectionShared, win32k!gpsi and others (which I don't know of).
Actually, the lower 16 bits of HWND represents index into window info array with base address *(&user32!gSharedInfo + 1). The first field of this window info is the kernel address of another structure which contains all the shared window information. Subtracting the difference between kernel address of the section and its user-space mapping (which is stored in TEB!Win32ClientInfo) you can get relevant info.
user32!ValidateHwnd is the function that converts window handle into this address which can be used by inner user32 functions like user32!DefWindowProcWorker.
Pseudocode of GetWindowTextW looks like (excluding error-handling):
GetWindowTextW(HWND hwnd, wchar_t* buf, int size)
{
inner_hwnd = ValidateHwnd(hwnd);
if (TestWindowProcess(inner_hwnd))
SendMessageWorker(inner_hwnd, WM_GETTEXT, size, buf, FALSE);
else
DefWindowProcWorker(inner_hwnd, WM_GETTEXT, size, buf, FALSE);
}
DefWindowProcWorker which is called in your case with WM_GETTEXT will just parse the structure referenced by inner_hwnd and copy window's name into buf.
it seems that the text for EDITTEXT controls are not stored in this manner
I never knew all the info that was stored in there though it seems like a good choice to not pollute processes' virtual space with all kinds of user/gdi params. Besides, lower integrity processes should not be able to get higher integrity processes sensitive information.
because there's no way Windows keeps a copy of the text for every single window
The text most certainly exists, just not as a copy. The text for a window is stored in the virtual memory of the process that owns the window. Might be in RAM, not terribly likely if the process has been dormant for a while, definitely on disk in the paging file. Which doesn't stop GetWindowText() from making a copy. On-the-fly, when you call it.
GetWindowText() is limited, it is documented to only being capable of copying the caption text of a window, so it probably uses the desktop heap for the session to retrieve the text. Not otherwise a restriction to a winapi function like SendMessage(), you can use WM_GETTEXT to obtain a gigabyte from an Edit control. That certainly crosses the process boundary.
As an operating system function, SendMessage can of course break all the rules that apply to normal processes. The OS has no trouble addressing the VM of an arbitrary process. Rules that are routinely broken, your debugger does it as well. With functions that you can use to also break the rules, ReadProcessMemory() and WriteProcessMemory().
We are writing a program that must be able to push setting to specific monitors, requiring us to have unique identifiers for each display device. So far, the best I can get is querying a handle to the DEVMODE struct returned by EnumDisplayDevices and seeing if the returned DISPLAY_DEVICE name contains either "DISPLAY1" or "DISPLAY2" (we only support up to two monitors with this software, and the deviceName field of the DISPLAY_DEVICE struct is in the form of \.\DISPLAYx where x is a natural number, minimum of 1).
My problem is, if someone applies settings from one terminal to another and says, in effect, "get all my settings from DISPLAY1 and all of my settings from my DISPLAY2 and apply them to another terminal's DISPLAY1 and DISPLAY2," will it apply the settings to the monitors connected to the corresponding ports? As far as I can tell, if there is only 1 monitor connected, that monitor is assigned the name \.\DISPLAY1, and if there are two connected, the display device connected via DVI is \.\DISPLAY1 and the device on VGA is \.\DISPLAY2.
I've tried unplugging the monitors one at a time, reconnecting them in different orders, rebooting, rebooting with only one connected, then connecting a second, etc etc, and it seems to always assign them this way. I can't seem to make it assign them to the opposite names. If this is the case, then we should be OK.
Alternatively, if anyone knows of a way to programmatically determine which port to which a monitor is connected (DVI or VGA etc) using MSDN calls, that would be even more helpful. I've exhausted basically every option I can think of in solving this problem.
Basically, I'm asking, am I correct in my assumptions as to how Windows 7 assigns names to the displays? If not, how is it done? Is there a way to change it? If so, how? Is there a way to determine the port to which a monitor is connected?
By the way, this application is written in C++ utilizing Qt, if that matters at all.
Thank you.
-Alex aka LeapDayWilliam
I think what you're looking for is some code to help you associate a monitor's canonical name with its physical location. You were looking for a solution where you'd be able to make this determination by looking at the device names of the monitor, but this isn't an accurate or reliable way to do it. From my experience there's no rhyme or reason to the numbering scheme for the monitor device names. What you really need is a way to determine which monitor is physically located where.
Here is some very basic code to print out the X,Y coordinates of the virtual pixel location for the monitor you're interested in. You'll notice that if you have two (or more) monitors the X value of those monitors will increase based on the width of the monitor to the left. You can calculate a monitor's physical location based on this information.
BOOL CALLBACK enumMonitorCallback(
__in HMONITOR hMonitor,
__in HDC hdcMonitor,
__in LPRECT lprcMonitor,
__in LPARAM dwData
)
{
printf("Monitor: %p (X,Y): (%d,%d) (Width, Height): (%d,%d) \n", hMonitor, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top);
return TRUE;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
BOOL res = EnumDisplayMonitors(NULL, NULL, enumMonitorCallback, NULL);
getchar();
return nRetCode;
}
My machine has two monitors. I get this output:
Monitor: 0x00C005E1 (X,Y): (0,0) (Width, Height): (1280,1024)
Monitor: 0x00020001 (X,Y): (1280,0) (Width, Height): (1280,1024)
Which tells me that monitor with handle 0x00020001 is located to the right of the first monitor and is offset by the resolution of that monitor (1280px).
I hope that helps.
I want to update a list of storage devices as the user inserts USB keys, adds external disks and mounts disk images. IOKit's IOServiceAddInterestNotification looks like the way to go, but the obvious use of registering general interest in kIOMediaClass only gives you notifications for unmounting of volumes and then only sometimes.
What's the right way to do this?
The following calls in DiskArbitration.h do exactly what I want:
DARegisterDiskAppearedCallback
DARegisterDiskDisappearedCallback
DARegisterDiskDescriptionChangedCallback
These cover insertion, removal (even of unmountable volumes)
metadata change events.
P.S. Don't forget to add your DASession to a runloop
or you won't get any callbacks.
I want to update a list of storage devices as the user inserts USB keys, adds external disks and mounts disk images.
I can get you two out of three with this piece of code, which I imagine wouldn't require a lot more work to give you the third.
File: USBNotificationExample.c
Description: This sample demonstrates how to use IOKitLib and IOUSBLib to set up asynchronous
callbacks when a USB device is attached to or removed from the system.
It also shows how to associate arbitrary data with each device instance.
http://opensource.apple.com/source/IOUSBFamily/IOUSBFamily-385.4.1/Examples/Another%20USB%20Notification%20Example/USBNotificationExample.c
I've personally used (a slightly modified copy of this code) for a long time, to monitor the connection of USB HDDs.
As you can see from this small sample, it may easily prove adaptable to monitor mounted drives. Or it may not. YMMV.
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
// IOUSBDevice and its subclasses
and when it matches
void DeviceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
IOCFPlugInInterface **plugInInterface=NULL;
SInt32 score;
HRESULT res;
while ( (usbDevice = IOIteratorNext(iterator)) )
{
io_name_t deviceName;
CFStringRef deviceNameAsCFString;
MyPrivateData *privateDataRef = NULL;
UInt32 locationID;
printf("Device 0x%08x added.\n", usbDevice);
and so forth, and so on.
Would watching /Volumes for changes do what you need?
If you happen to be working at the Cocoa level, you can also register to receive the following notifications from NSWorkspace:
NSWorkspaceDidMountNotification
NSWorkspaceDidRenameVolumeNotification
NSWorkspaceWillUnmountNotification
NSWorkspaceDidUnmountNotification