The next meeting will be held on March 23rd, at Microsoft Offices.
This is the planned agenda:
17:00-17:30
Gathering
17:30-17:40 – MVP Summit impressions
17:40-18:55
Title: Developing connectivity based products (Bluetooth, Wireless-LAN and GPS) in complex environment – Alon Haze
Project management and Software development for Bluetooth, Wireless-LAN and GPS for the handsets market is challenging. The environment is built from demanding cellular customers with strict requirements for low cost, low power, small size and highly integrated products. The development process requires multi-disciplinary expertise that covers silicon design, Firmware, Software, Hardware, System and RF experts. Putting all connectivity IPs inside one chip and supporting the customers with the Hardware and Software integration into their phones is far from being simple
During the lecture I will discuss the above topics and the ways we manage them in Texas Instruments Israel
About Alon Haze
Alon is a Program Manager in Texas Instruments Israel. Alon joined Texas Instruments 11 years ago and was part of the team who started the connectivity business in TI. As part of his roles, Alon was a Software real-time embedded engineer, Software team leader and in the last 6 years he leads mobile Bluetooth, WLAN and GPS programs for the cellular market
18:55-19:15
Break
19:15-20:30
Introduction to programming software device drivers on Windows (or Device Driver programming 101) – Pavel Yosifovich
In this session we’ll see how to write a simple kernel driver using the Windows Driver Kit and establish a connection between a client application and the driver. We’ll consider installation of the driver, exposing device objects and more
About Pavel Yosifovich
Pavel is the CTO of Matrix Global and a senior instructor at Hi-Tech college. Prior to that, Pavel co-founded the startup Quiksee, where he was CTO, team leader and lead developer. He’s also a Microsoft MVP in Visual C++ and has more than 12 years of software development experience, specializing in Microsoft technologies
Please register to the event here.
Visual C++ 6 aficionados remember (fondly) the Class Wizard, most useful in MFC applications. The Class Wizard has gone away in later version of Visual Studio (2002, 2003, 2005, 2008), but is now making a smashing return in Visual Studio 2010 (Project menu –> Class Wizard or Ctrl+Shift+X).
This has the familiar options (relative to VC++ 6), such as adding/removing message handlers, command and update command handlers, creating new classes, member variables, etc. There are new options, such as creating custom message handlers and the ability to search.
In my experience, many developers back then were very dependent on the almighty Class Wizard, so the same warnings apply like any other wizard: use but do not abuse, and always, always – know what it does so you can do it yourself or undo it, if the need arises.
The famous CreateProcess function may fail with an access violation. For example, this innocent looking code causes a crash:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess(0, _T("notepad"), 0, 0, FALSE,
0, 0, 0, &si, &pi);
What’s wrong with this code? Apparently nothing.
The key here is that CreateProcess is not actually a function at all, but a macro that’s expanded to CreateProcessA or CreateProcessW depending a compile time constant (UNICODE).
If we open the docs, we find for the second argument: “The Unicode version of this function, CreateProcessW, can modify the contents of this string”.
The string I passed is a constant string, coming from a region marked as “read only” and this is why the access violation occurs. Changing CreateProcess to CreateProcessA avoids the crash. The reason is that the A function translates the string to unicode and calls the W function. The translated string is in a read/write buffer, so no problem there. This should generally be avoided because of the extra step A functions do.
In recent versions of Visual Studio the default libraries are unicode (as they should be, as the Windows 9x family of OSes is finally dead and buried). This is while a transition from (e.g.) Visual Studio 2003 to 2008 may cause old code to crash.
So, the general solution should be:
TCHAR name[] = _T("Notepad.exe");
CreateProcess(0, name, 0, 0, FALSE, 0, 0, 0, &si, &pi);
This still doesn’t answer the question: why? Why would CreateProcessW want to write back to the supplied string? What could it possibly write? It can’t write arbitrary stuff as the size of the buffer is unknown to the function and can cause access violation or memory corruption. But it does write something back (looks like the same string passed to it). For me, it’s still a mystery.
One of the well-known pitfalls of using events, is the holding of the subscriber instance by the publisher (if connecting to a delegate holding an instance method). If the subscriber forgets to unsubscribe, the instance cannot be garbage collected because the publisher holds a reference to it. Worse yet, the subscriber continues to receive event notifications even though it’s not interested.
One way to deal with this is presented in Jeffrey Richter’s book “CLR via C#”. The idea is based on a custom event implementation holding a list of WeakReference objects to the incoming subscribers delegates:
class Publisher {
private List<WeakReference> _subscribers = new List<WeakReference>();
public event EventHandler TheEvent {
add {
_subscribers.Add(new WeakReference(value));
}
remove {
//...
}
}
protected virtual void OnTheEvent() {
// raise the event
for(int i = _subscribers.Count - 1; i >= 0; i--) {
EventHandler eh = (EventHandler)_subscribers[i].Target;
if(eh == null) // delegate GC’d
_subscribers.RemoveAt(i);
else // raise the event
eh(this, EventArgs.Empty);
}
}
}
This approach has a fatal flaw: the WeakReference wraps the delegate object – not the subscriber instance itself! This means, that if a GC occurs, all the delegates in the list will be gone, disconnecting all subscribers, even those who are still very much alive.
To correct this, we need to use a WeakReference around the subscriber instance itself and not the delegate. Here’s some code that accomplishes this:
class Publisher {
private List<MethodInfo> _methods = new List<MethodInfo>();
private List<WeakReference> _instances = new List<WeakReference>();
public event EventHandler TheEvent {
add {
_methods.Add(value.Method);
if(value.Target != null)
_instances.Add(new WeakReference(value.Target));
else
_instances.Add(new WeakReference(value));
}
remove {
//...
}
}
public void Fire() {
for(int i = _methods.Count - 1; i >= 0; i--) {
object o = _instances[i].Target;
if(o != null) {
if(o.GetType() == typeof(WeakReference))
((EventHandler)o)(this, EventArgs.Empty);
else
_methods[i].Invoke(o, new object[] { this, EventArgs.Empty });
}
else {
_methods.RemoveAt(i);
_instances.RemoveAt(i);
}
}
}
}
Although this is somewhat involved, it solves the issue. It shouldn’t be too difficult to create some helper class to handle this in a generic way, to be used by any event publisher. (and the remove part must be completed…)
Another approach would be to abandon the event idea and use an interface for notifications. Wrapping an interface by a WeakReference is easy enough. The only downside – a subscriber must supply an object (cannot use static methods as callbacks) implementing the entire interface (even if only some methods are interesting).
It’s something I came across, which seems like a bug to me. A WPF element can use a style automatically if the style uses the TargetType property set to the type of that element and there is no x:Key value. That is, there is no need for a (e.g. textual) key (the type is the key), and there is no need to specify a Style property for elements of that type.
For some reason, the Separator type, commonly found in menus and toolbars, does not respect it, and requires an explicit Style setting with an appropriate key.
For example, this piece of XAML should make the separator a red line.
<Style TargetType="Separator">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Separator">
<Border Background="Red" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
For this menu:
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="_Open..." />
<Separator />
<MenuItem Header="E_xit" />
</MenuItem>
</Menu>
But it doesn’t. To make this work, I must add a style key and apply it:
<Style TargetType="Separator" x:Key="sep1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Separator">
<Border Background="Red" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="_Open..." />
<Separator Style="{StaticResource sep1}"/>
<MenuItem Header="E_xit" />
</MenuItem>
</Menu>
The result is:

Recently, I’ve given several sessions on “What’s new in C# 4.0?” in an MS Open House and the Nes Tziona User group.
For those unable to attend, or just want some refreshing, I’ve created 3 videos on the main C# 4 features (“Optional and named arguments”, “dynamically typed objects” and “generic variance”). You can watch those on the Hi-Tech TV web site.
Enjoy!
The upcoming new C++ standard, dubbed C++0x (hopefully, x will be a single (decimal) digit (9)) is quite intriguing, with many new features to the language and the supporting standard library. Here’s a video of a lecture given by the inventor and original implementor of C++, Bjarne Stroustrup.
Very interesting, not just from the point of view of features, but design-wise and decision-wise as well.
בשעה טובה מחר, יום רביעי, ה-4 לנובמבר בשעה 17:30 תתקיים הפגישה הראשונה של קבוצת משתמשים חדשה, Windows Platform Developer , בהנהלת אלון פליס ואנוכי. הקבוצה תיפגש מידי חודש ביום רביעי הראשון בחודש.
הקבוצה עוסקת בחלקים היותר פנימיים של Windows ושל טכנולוגיות הקשורות ל-Windows. דוגמאות לנושאים שיופיעו בעתיד הם:
- ++C כולל הסטנדרט החדש
- Windows Internals
- Kernel Programming
- .NET Interop
- Advanced Debugging
ועוד.
המפגש הראשון יעסוק ב-Windows 7. פירוט נוסף ניתן למצוא כאן.
Sometimes we need some new functionality from a basic control. One way to go about it is to create a custom control and add that functionality. However, sometimes creating a new control is an overkill, especially when no new behaviour is actually needed. Perhaps some new way of presenting or drawing the control is all that’s needed.
The problem is that we may want more properties on the control, but we don’t want or need to actually extend it (i.e. derive from it).
For example, suppose we want to create a button with one of several images depending on its state: enabled, disabled or focused.
Deriving from Button seems too excessive: the images are not changing anything from a behaviour perspective. However, I would like to have new properties, such as NormalImage, DisabledImage and FocusedImage.
Adding properties to an existing class in WPF is possible through attached properties. Attached properties are contextual; they are defined by one class, but may be used by any other class.
Continuing the example, I can look for some already define attached properties that match my intentions. More often than not, I won’t find any.
To facilitate my image button, I can create a new class, define the attached properties by calling DependencyProperty.RegisterAttached and simply look for them in the appropriate class (the Button in this case, when used with a style).
Here’s an example: (you can add an attached property easily using Visual Studio with the propa code snippet – just type propa and hit Tab twice)
public sealed class ImageStates : DependencyObject {
public static ImageSource GetNormalImage(DependencyObject obj) {
return (ImageSource)obj.GetValue(NormalImageProperty);
}
public static void SetNormalImage(DependencyObject obj, ImageSource value) {
obj.SetValue(NormalImageProperty, value);
}
public static readonly DependencyProperty NormalImageProperty =
DependencyProperty.RegisterAttached("NormalImage", typeof(ImageSource), typeof(ImageStates), new UIPropertyMetadata(null));
public static ImageSource GetDisabledImage(DependencyObject obj) {
return (ImageSource)obj.GetValue(DisabledImageProperty);
}
public static void SetDisabledImage(DependencyObject obj, ImageSource value) {
obj.SetValue(DisabledImageProperty, value);
}
public static readonly DependencyProperty DisabledImageProperty =
DependencyProperty.RegisterAttached("DisabledImage", typeof(ImageSource), typeof(ImageStates), new UIPropertyMetadata(null));
public static ImageSource GetFocusedImage(DependencyObject obj) {
return (ImageSource)obj.GetValue(FocusedImageProperty);
}
public static void SetFocusedImage(DependencyObject obj, ImageSource value) {
obj.SetValue(FocusedImageProperty, value);
}
public static readonly DependencyProperty FocusedImageProperty =
DependencyProperty.RegisterAttached("FocusedImage", typeof(ImageSource), typeof(ImageStates), new UIPropertyMetadata(null));
}
I’ve created 3 attached properties in some class acting as a simple logical container for these properties.
Now, I can create some buttons like so:
<StackPanel>
<Button Margin="4" local:ImageStates.NormalImage="book_open.png"
local:ImageStates.DisabledImage="book_red.png"
local:ImageStates.FocusedImage="book_open2.png" />
<Button Margin="4" local:ImageStates.NormalImage="book_open.png" IsEnabled="False"
local:ImageStates.DisabledImage="book_red.png"
local:ImageStates.FocusedImage="book_open2.png" />
<Button Margin="4" local:ImageStates.NormalImage="book_open.png"
local:ImageStates.DisabledImage="book_red.png"
local:ImageStates.FocusedImage="book_open2.png" />
</StackPanel>
The attached properties are used in the correct “context”. These properties are not part of Button, but now are used by it (actually by the style and template that’s applied). The application of the templates can be done like so: (a bit crude)
<Application.Resources>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Stretch="None" Source="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=(local:ImageStates.NormalImage)}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Stretch="None" Source="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=(local:ImageStates.FocusedImage)}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Stretch="None" Opacity=".5" Source="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=(local:ImageStates.DisabledImage)}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
Here’s a screenshot of the result (top button is focused, middle is disabled):
The attached ZIP is the complete project. Power to Attached Properties!
Yesterday, I delivered a session titled “What’s new in C# 4.0?” after a session by Guy Burstein on “First look at Visual Studio 2010”.
Thank you all for attending. I apologise for not using all the feedbacks to select winners for the books – sorry, guys! I’ll pay attention next time (probably lack of food).
Some notes that came up during the session:
1. The misbehavior on the DynamicXmlElement class was due to a small oversight: I wrote this code when only one element existed:
case 1:
result = elements.First();
break;
which returns the element as is (which is an XElement, not what we want). It should have been:
case 1:
result = new DynamicXmlElement(elements.First());
break;
So it continues to be a DynamicXmlElement object. Again, lack of food.
2. The other question I left somewhat open, is regarding caching in the ExpandoObject example. Well, no caching is possible – no special layer there, the code must run each time and do the right thing.
The code samples will be available soon in the usual location as Guy described.
Early in the ads for .NET 4.0, there were rumours about two types dealing with numeric stuff, BigInteger and Complex. In the Beta 1 phase, BigInteger has appeared (I’ve briefly blogged about it), but Complex was nowhere to be found.
With the advent of .NET 4.0 Beta 2, I was happy to find the emergence of the Complex type in the System.Numerics namespace (and these numeric types have been moved to their own System.Numerics.Dll assembly).
Complex is, of course, represents a complex number, with a Real part and an Imaginary part. It hosts all the usual expected properties and methods, including operator overloading and conversions.
One mishap, I believe, is the existence of a Magnitude property, returning the length of the complex number as measured from the origin, but no MagnitudeSquared property, which is an optimization – as sometimes this is what is needed and the overhead of performing a square root for the Magnitude property is unnecessary (Magnitude is calculated with the super famous pythagorean theorem, requiring a costly square root operation).
Hopefully, this property will be added in the .NET 4.0 RTM.
Local kernel debugging is the ability to view kernel data structures in a live system (i.e. not connecting to a target system through a null cable modem or USB or other alternatives), and is supported since Windows XP. This is a great way to explore windows on its darker side (the kernel and related subsystems) with all its mysteries and secrets.
With Windows XP, starting local kernel debugging is pretty easy. Just fire up WinDbg (or kd for that matter), select from the menu File->Kernel Debug, navigate to the “Local” tab, click OK and start exploring.
In Windows Vista and up, trying to do the same thing produces the following message box:
“---------------------------
WinDbg:6.11.0001.404 AMD64
---------------------------
The system does not support local kernel debugging.
Local kernel debugging requires Windows XP, Administrative
privileges, and is not supported by WOW64.
Only a single local kernel debugging session can run at a time.
Local kernel debugging is disabled by default in Windows Vista, you must run 'bcdedit -debug on' and reboot to enable it.”
The bold section is the important part. On Vista and up (not just Vista, as may be suggested by the error message), this is disabled by default, and requires change in the Boot Configuration Database (BCD) and reboot. Doesn’t seem to difficult to do; however, setting this option disables the ability to do user mode debugging (e.g. with Visual Studio)… not nice.
The life saver here is Mark Russinovich from the famous SysInternals site and tools (now part of Microsoft). He wrote the livekd tool, that simulates a “blue screen” and creates a dump file, then opens it with your favourite kernel debugger (WinDbg or kd). For example, issuing Livekd –w (assuming WinDbg is in the default search path, or livekd is copied to the Debugging Tools For Windows folder and you’re running with admin privileges), this launches WinDbg and allows local kernel debugging.
Livekd was not working properly on newer systems (x64) but finally a new version was released, fixing that issue, allowing local kernel debugging on x64 systems on Vista and up.
When defining dependency properties in a WPF (e.g. in a user control or custom control), you can supply a default value for that property. However, if you’re not careful, you’ll get a nasty exception at runtime, with no obvious cause.
For example, consider this simple dependency property:
public double SomeLength {
get { return (double)GetValue(SomeLengthProperty); }
set { SetValue(SomeLengthProperty, value); }
}
public static readonly DependencyProperty SomeLengthProperty =
DependencyProperty.Register("SomeLength", typeof(double),
typeof(SomeControl), new UIPropertyMetadata(0));
When running the application hosting the control declaring this property, you’ll get a nasty XamlParseException. Looking at the InnerException, you’ll see something like:
{"Exception has been thrown by the target of an invocation."}
Great. Probably some reflection exception. Let’s look at its InnerException:
{"The type initializer for 'CustomControls.SomeControl' threw an exception."}
That’s a bit more helpful. It must be the DependencyProperty.Register method (called from the static constructor a.k.a. type initializer).
So, what’s going on here? Experienced WPF developers may spot this immediately. The problem is the default value of 0. What’s wrong with that? Can’t a double be zero? It can, but what’s missing is the value zero in a double look: 0.0 or (double)0.
Why is this happening? Simply because the argument Register expects is of type object. Passing a value type causes boxing. No surprise here. But when unboxing occurs – an exception is triggered, because a 0 (int) cannot be unboxed to a double without an intermediate cast (which, of course, is not supplied, as everything is too dynamic for that).
So, the moral of the story is: keep your default values with the exact type declared in the dependency property.
Here’s an elegant (in my opinion) way to kill Visual Studio 2008 immediately without leaving any trace.
Here’s what you need to do:
1. Open up VS 2008 and create a new project of type C# WPF Application.
2. Open Window1.xaml and make sure you get a split view of XAML and preview.
3. The top level layout panel is a Grid (by default). Add two rows, and in one place a button. Also name the window (e.g. “win”). The markup should be something like this:
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" x:Name="win">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button Content="Click me if you can!" FontSize="20" />
</Grid>
</Window>
You should see the button filling the first row of the grid. Now for the fun part:
Add a Rectangle to the second row of the grid and set its fill property to use a VisualBrush binded to the window itself. Should be something like:
<Rectangle Grid.Row="1">
<Rectangle.Fill>
<VisualBrush Visual=“{Binding ElementName=win}" />
</Rectangle.Fill>
</Rectangle>
As soon as you close that tag on the VisualBrush – BAM! VS disappears…
What happened here?
The VisualBrush used the window to paint the rectangle, but that means the window has changed again, so the rectangle needs to repaint and so on and so forth… I guess the poor WPF designer just couldn’t handle it…
And some people say WPF is not fun…
For all you debuggers out there, you’ve got a classic case of adplus –crash and a good dump debugging with WinDbg. Enjoy!
When Windows media player (WMP) is open, any attempt to open it again simply reactivates the existing WMP window. WMP is running as a single instance. It uses a relatively well known methods for this, creating a named mutex on startup and seeing if it already exists (by calling GetLastError and comparing with ERROR_ALREADY_EXISTS). WMP uses a mutex called "Microsoft_WMP_70_CheckForOtherInstanceMutex" and this name seems to be consistent between WMP versions (at least starting from Windows XP).
Mark Russinovich showed this mutex in the latest addition of Windows Internals. Let’s run an instance of WMP and look at process explorer’s lower pane when configured to show handles:
The session prefix indicates this object was created in the logged in user’s session (session 1 in Vista and up).
We can manually close the handle using Process Explorer again. Just right click the handle and select “Close Handle”. After this – you can open another WMP – that new WMP will try to create that named mutex – and will succeed.
Closing a handle like this may be catastrophic – the process doesn’t know the handle was closed “behind its back”, so any use of this handle will fail. Even worse, a new handle in that process may be created pointing to another object altogether, without the process realizing it. In this particular case, it’s benign.
What if you wanted to automate this, so that you could open multiple instances of WMP and play several video/audio files at the same time? Or pause one, play another, etc.? I think this has its uses.
How would we go about doing it? How can we close the correct handle like Process Explorer does?
Maybe we can call OpenMutex with the above name and close the handle twice… this won’t work, as after the first CloseHandle, the handle becomes invalid and the next CloseHandle simply fails.
What we need is to get to the handle inside the WMP process and close it from there. Easier said than done…
There are basically two ways we can go:
1. Write a driver, that can access the EPROCESS kernel structure, find the handle table for that process, locate the handle and close it. Theoretically possible, but many issues involved: EPROCESS is undocumented, except through the kernel debugger – not much fun to work with; installing a driver required user consent if UAC is active – not so user friendly; driver by its own nature is much dangerous to use (blue screen possible), …
2. Inject code into the WMP process that will scan the handle table from user mode, locate the handle and close it. Sounds better, easier; just one caveat: no Windows API allows scanning handles and getting the name of the object their pointing at.
So, we’ll go with option 2. Injecting code into a process is fairly well documented, e.g. by calling CreateRemoteThread pointed at LoadLibrary (because kernel32 is loaded at the same virtual address in every process) where our DLL is loaded into the other process and does the deed in its DllMain. The complete details can be found in Jeffrey Richter’s book Windows Via C/C++ (5th edition), or look at the source code accompanying this post.
Getting our code to execute under a WMP process is possible. The only thing remaining is handle enumeration. Although there is no official Windows API to do this, there is a native API (inside ntdll.dll) called NtQueryObject. It’s partially documented in the Windows SDK and in the Windows Driver Kit (WDK) (under ZwQueryObject) – there is a lot of symmetry in the APIs from ntdll and the executive. This function allows getting information given a handle. So, we can scan the handles, starting from 4 (the first legal handle value) up to some limit and look for an object with the aforementioned name. When we find it – just CloseHandle it and we’re done.
Here’s the prototype for NtQueryObject that we need:
typedef enum _OBJECT_INFORMATION_CLASS {
ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation,
ObjectAllInformation, ObjectDataInformation
} OBJECT_INFORMATION_CLASS;
typedef struct _UNICODE_STRING {
SHORT Length;
SHORT MaxLength;
PWSTR String;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
WCHAR NameBuffer[1];
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
extern "C" NTSYSAPI LONG NTAPI NtQueryObject(
__in_opt HANDLE Handle,
__in OBJECT_INFORMATION_CLASS ObjectInformationClass,
__out_bcount_opt(Length) PVOID ObjectInformation,
__in ULONG Length,
__out_opt PULONG ReturnLength
);
We need to use ObjectNameInformation (which is undocumented).
Here’s the way we can find the correct handle and close it:
OBJECT_NAME_INFORMATION* ninfo = (OBJECT_NAME_INFORMATION*)::malloc(1024);
// run through all handles until we find it
for(int h = 4; h <= 0x120; h += 4) {
LONG status = NtQueryObject((HANDLE)h,
ObjectNameInformation, ninfo, 900, NULL);
if(status == 0) {
PWSTR name = ::wcsrchr(ninfo->NameBuffer, L'\\');
if(name != NULL && ::lstrcmpW(name + 1, mutexName) == 0) {
// found it!
::CloseHandle((HANDLE)h);
break;
}
}
}
::free(ninfo);
mutexName is the name we’re after.
Attached is the source code and the executable. The DLL is stored as a resource in the EXE, and extracted at runtime to a temp folder. This trick makes it easy to distribute – only one file is required.
Enjoy Media Player multi instancing!
More Posts
Next page »