Building Native Windows Applications with CLION, GCC and CygWin

As a software developer and architect, I’m always looking at options for my customers whether they’re around technologies, tools, hosting, security and tenancy model (being the last three mandatory in a “cloudy” world) among some other factors and considerations. To me crafting software it’s more than cracking code and ensure it compiles, it’s more about building smart solutions that will help people, as well as enjoying the building process. What really makes it enjoyable are two things (in my humble and personal opinion: First, what the challenge and requirements are;  Second, technology to use and lastly, the IDE).

In regards to points 2 & 3, I have to say that C++ is an awesome and powerful language and similarly to C, they both have been standard and platform independent since their very first versions, something that was achieved by Java and subsequently by .NET (and its Linux implementation, Mono for instance). So what’s all this introductory fuss about then? well… This post is about building a very simple native Windows application using non-Microsoft technologies:

Our source code Today is pretty straightforward, it’s classic Win32 development and if you’re like me and keen on learning how to do this kind of development without any frameworks, I can mention two books that helped me a lot when I was learning (They’re not recent or new though and the OS has changed a lot since the books were originally published – They are a relic, actually)

petzold Norton

The code and a screenshot of the application running are shown below

#include <windows.h> HINSTANCE hInst; const char g_szClassName[] = "bonafideideasWindowClass"; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ MSG Msg; HWND hwnd; WNDCLASSEX wc; wc.lpszMenuName = NULL; wc.hInstance = hInstance; wc.lpszClassName = g_szClassName; wc.cbSize = sizeof(WNDCLASSEX); wc.cbClsExtra = wc.cbWndExtra = 0; wc.style = CS_HREDRAW | CS_VREDRAW ; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wc.lpfnWndProc = [=](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -> LRESULT { HDC hdc; RECT rect; TEXTMETRIC tm; PAINTSTRUCT ps; switch(msg) { case WM_CLOSE: if (MessageBox(NULL, "Are you sure you want to quit?", "Confirmation", MB_ICONQUESTION | MB_YESNO) == IDYES) DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT ("Native Windows Development with CygWin and CLion."), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; }; if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed", "Error", MB_ICONEXCLAMATION | MB_OK); return 0; } hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "Simplest Windows Native App built with CLion", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 250, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed", "Error", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }

 

AppRunning

Now, let’s talk a bit of CLion… As previously mentioned it’s a cross-platform IDE (I’m writing a few things on Linux with it, actually).  It’s very similar to IntelliJ IDEA (Keep in mind it’s from the same company). The UI is easy to use and  functional (It’s not fair to compare to more mature products) and just to give you a glimpse

image

Besides providing with a good and decent Intellisense  support and fast parsing oh header files and libraries, good debugging experience and it also supports most of the new features in C++11 and C++14 Standards (This is because of using GCC as compiler).

image

Happy coding!,

Angel

Instrumenting SharePoint code via Performance Counters

Instrumentation is an important and integral part of every system because it allows (among some other things) to monitor the health of the system and/or components of it.  On a recent engagement, I had to architect a SharePoint solution that integrates with a core LOB system. The SharePoint solution comprises a few workflows that in turn do specific operations with the external system. Even when SEH, Tracing and Logging was implemented I needed something else, performance counters to provide IT staff with real-time information of the solution and in doing so, I leveraged one feature in the operating system as well as giving metrics on the performance of the solution.

Performance counters have been available in .NET since 1.0, however, it’s unusual to use them in a SharePoint solution. The way I approached this is described below:

  1. I usually use DI/IOC in my solutions (please note, not every solution benefits from this pattern though so implementing it might cause more headaches than expected results). Therefore, I defined my instrumentation capabilities in an interface IInstrumentationManager

    public interface IInstrumentationManager { /// <summary> /// Gets the perf counters. /// </summary> /// <value> /// The perf counters. /// </value> IPerfCounters PerfCounters { get; } /// <summary> /// Gets the logger. /// </summary> /// <value> /// The logger. /// </value> ILogger<ILogEntry> Logger { get; } }

  2. The performance counters are defined in IPerfCounters
    public interface IPerfCounters { /// <summary> /// Gets the created configuration. /// </summary> /// <value> /// The created configuration. /// </value> DateTime CreatedOn { get; } /// <summary> /// Gets the instance unique identifier. /// </summary> /// <value> /// The instance unique identifier. /// </value> Guid InstanceId { get; } /// <summary> /// Gets the <see cref="PerformanceCounter"/> with the specified counter name. /// </summary> /// <value> /// The <see cref="PerformanceCounter"/>. /// </value> /// <param name="counterName">Name of the counter.</param> /// <returns></returns> PerformanceCounter this[PerfCounter counterName] { get; } }

  3. Please note I have an indexer that uses an enum to access a specific performance counter.  The concrete class implements  IPerfcounters and IDisposable.
    public class PerfCounters : IPerfCounters, IDisposable { /// <summary> /// Gets the created configuration. /// </summary> /// <value> /// The created configuration. /// </value> public DateTime CreatedOn { get; private set; } /// <summary> /// Gets the instance unique identifier. /// </summary> /// <value> /// The instance unique identifier. /// </value> public Guid InstanceId { get; private set; } /// <summary> /// Gets the <see cref="PerformanceCounter" /> with the specified counter name. /// </summary> /// <value> /// The <see cref="PerformanceCounter" />. /// </value> /// <param name="counterName">Name of the counter.</param> /// <returns></returns> public PerformanceCounter this[PerfCounter counterName] { get { var retval = CountersAvailable.ContainsKey(counterName) ? CountersAvailable[counterName] : null; return retval; } } /// <summary> /// Gets or sets the counters available. /// </summary> /// <value> /// The counters available. /// </value> protected Dictionary<PerfCounter, PerformanceCounter> CountersAvailable { get; set; } /// <summary> /// Gets the counter data collection. /// </summary> /// <value> /// The counter data collection. /// </value> protected CounterCreationDataCollection CounterDataCollection { get; private set; } /// <summary> /// The disposed /// </summary> /// <value> /// <c>true</c> if this instance is disposed; otherwise, <c>false</c>. /// </value> protected bool IsDisposed { get; private set; } /// <summary> /// Gets or sets the configuration manager. /// </summary> /// <value> /// The configuration manager. /// </value> protected IConfigManager ConfigManager { get; set; } /// <summary> /// Gets or sets the impersonate helper. /// </summary> /// <value> /// The impersonate helper. /// </value> protected IImpersonateHelper ImpersonateHelper { get; set; } /// <summary> /// Initializes a new instance of the <see cref="PerfCounters" /> class. /// </summary> /// <param name="configMgr">The configuration MGR.</param> /// <param name="impersonateHelper">The impersonate helper.</param> public PerfCounters(IConfigManager configMgr, IImpersonateHelper impersonateHelper) { CreatedOn = DateTime.Now; ConfigManager = configMgr; InstanceId = Guid.NewGuid(); ImpersonateHelper = impersonateHelper; CounterDataCollection = new CounterCreationDataCollection(); CountersAvailable = new Dictionary<PerfCounter, PerformanceCounter>(); CreateOrInitializePerfCounters(); } /// <summary> /// Finalizes an instance of the <see cref="PerfCounters"/> class. /// </summary> ~PerfCounters() { Dispose(false); } /// <summary> /// Creates the original initialize perf counters. /// </summary> protected void CreateOrInitializePerfCounters() { NetworkCredential credential; var localAdmin = ConfigManager[Consts.LocalAdminKey]; if (!string.IsNullOrEmpty(localAdmin) && (credential = localAdmin.ConvertToNetworkCredential()) != null) ImpersonateHelper.Impersonate(CreatePerfCounters, credential); AddCountersToInstance(); } /// <summary> /// Creates the perf counters. /// </summary> private void CreatePerfCounters() { // Let's create Performance counter category if (!PerformanceCounterCategory.Exists(Consts.PerformanceCounterCategory)) { CounterDataCollection.AddRange(new[] { new CounterCreationData(Consts.TotalErrorCounter, string.Empty, PerformanceCounterType.NumberOfItems64), new CounterCreationData(Consts.TotalUnhandledErrorCounter, string.Empty, PerformanceCounterType.NumberOfItems64), new CounterCreationData(Consts.TotalTicketsProcessedCounter, string.Empty, PerformanceCounterType.NumberOfItems64), }); PerformanceCounterCategory.Create(Consts.PerformanceCounterCategory, Consts.PerformanceCounterCategory, PerformanceCounterCategoryType.MultiInstance, CounterDataCollection); } } /// <summary> /// Adds the counters to instance. /// </summary> private void AddCountersToInstance() { // Let's ensure category exists and create custom performance counters if (PerformanceCounterCategory.Exists(Consts.PerformanceCounterCategory)) { CountersAvailable.Add(PerfCounter.ErrorCount, new PerformanceCounter(Consts.PerformanceCounterCategory, Consts.TotalErrorCounter, Consts.PerformanceCounterCategory, false)); CountersAvailable.Add(PerfCounter.UnhandledExceptions, new PerformanceCounter(Consts.PerformanceCounterCategory, Consts.TotalUnhandledErrorCounter, Consts.PerformanceCounterCategory, false)); CountersAvailable.Add(PerfCounter.TotalTicketsProcessed, new PerformanceCounter(Consts.PerformanceCounterCategory, Consts.TotalTicketsProcessedCounter, Consts.PerformanceCounterCategory, false)); } } /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="isDisposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool isDisposing) { if (!IsDisposed) { if (isDisposing) { if (CountersAvailable != null && CountersAvailable.Count > 0) CountersAvailable.ToList().ForEach(x => { x.Value.Close(); x.Value.Dispose(); }); } IsDisposed = true; } } }

  4. Performance counters must be created and registered on the computer before they can be used, and in order to do that the user creating them must meet a certain criteria, this is usually done as a separate step in the deployment of the solution using the performance counters, however, I was able to do it by storing encrypted credentials of  user with right permissions on a SharePoint List, and this list entry was present then performance counters were created through impersonation of this user, if the list entry was missing nothing occurred.  The code responsible for impersonating user was passed in as a callback
    public class ImpersonateHelper : IImpersonateHelper { #region "Consts" private const int Logon32Interactive = 2; private const int Logon32ProviderDefault = 0; #endregion #region "Imported functions" /// <summary> /// Logons the user. /// </summary> /// <param name="lpszUsername">The LPSZ username.</param> /// <param name="lpszDomain">The LPSZ domain.</param> /// <param name="lpszPassword">The LPSZ password.</param> /// <param name="dwLogonType">Type of the dw logon.</param> /// <param name="dwLogonProvider">The dw logon provider.</param> /// <param name="phToken">The ph token.</param> /// <returns></returns> [DllImport("advapi32.dll", SetLastError = true)] private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); /// <summary> /// Closes the handle. /// </summary> /// <param name="handle">The handle.</param> /// <returns></returns> [DllImport("kernel32.dll", CharSet = CharSet.Auto)] private extern static bool CloseHandle(IntPtr handle); #endregion #region "Impersonate code" #endregion /// <summary> /// Impersonates the specified code to impersonate. /// </summary> /// <param name="codeToImpersonate">The code to impersonate.</param> /// <param name="credential">The credential.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public IExecutionResult Impersonate(Action codeToImpersonate, NetworkCredential credential) { var tokenHandle = IntPtr.Zero; var retval = new ExecutionResult() {Success = false}; if (codeToImpersonate != null && credential != null) { try { if (LogonUser(credential.UserName, credential.Domain, credential.Password, Logon32Interactive, Logon32ProviderDefault, ref tokenHandle)) { using (var newId = new WindowsIdentity(tokenHandle)) { using (var impersonatedUser = newId.Impersonate()) { codeToImpersonate.Invoke(); impersonatedUser.Undo(); } } retval.Success = true; } } catch (Exception ex) { retval.ErrorCondition = ex; } finally { CloseHandle(tokenHandle); } } return retval; } }

  5. Now, we’ve got so far out performance counters (creation and registration) but you might be wondering, where are we going to store it? Answer is very simple – in the  AppDomain. AppDomain is created when the CLR starts a new instance of any .NET application, at the same time developers can store information that’s not persisted once the application has been terminated, so it’s kind of a “property bag” in our application’s process memory.
    var defaultCounters = new PerfCounters(container.Resolve<IConfigManager>(), container.Resolve<IImpersonateHelper>()); RegisterPerfCounters(defaultCounters); container.RegisterInstance(typeof(IPerfCounters), defaultCounters); /// <summary> /// Registers the perf counters. // </summary> /// <typeparam name="T"></typeparam> /// <param name="instance">The instance.</param> /// <param name="instanceName">Name of the instance.</param> private void RegisterPerfCounters<T>(T instance, string instanceName = Consts.PerfCounterInstanceName) where T : IPerfCounters { if (AppDomain.CurrentDomain.GetData(instanceName) == null) AppDomain.CurrentDomain.SetData(instanceName, instance); }

  6. The InstrumentationManager then retrieves our IPerfCounters instance from the AppDomain through Unity
    public class InstrumentationManager : IInstrumentationManager { /// <summary> /// Gets the perf counters. /// </summary> /// <value> /// The perf counters. /// </value> /// <exception cref="System.NotImplementedException"></exception> public IPerfCounters PerfCounters { get { return AppDomain.CurrentDomain .GetData(Consts.PerfCounterInstanceName) as IPerfCounters; } } /// <summary> /// Gets the logger. /// </summary> /// <value> /// The logger. /// </value> /// <exception cref="System.NotImplementedException"></exception> public ILogger<ILogEntry> Logger { get { return GlobalService.Current.Container.Resolve<ILogger<ILogEntry>>(); } } }

  7. Then we increment or decrement our performance counter by accessing the right counter through an indexer that takes an enum
    var InstrumentationManager = GlobalService.Current .Container.Resolve<IInstrumentationManager>(); InstrumentationManager.PerfCounters[PerfCounter.TotalTicketsProcessed] .Increment();

When our solution is running, we can then open perfmon and see how it’s behaving

perfmon

Communication between user and kernel-mode

As a follow-up post on Windows Services and Minifilters, Today I’ll explain one way we can send notifications from kernel-mode to an user-mode application.  Let’s remember Windows provides fault tolerance protection in the form of rings, thus an offending code in one of the rings should not compromise the stability of the system. My metadata filesystem project has a minifilter driver that notifies a Windows service when an important event (event I’m interested in) has occurred. 

The basics to do this are:

  1. Minifilter driver creates a device by calling IoCreateDevice and also creates a symbolic link through IoCreateSymbolicLink

    NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) { NTSTATUS retval = STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING LinkName; PDEVICE_OBJECT EventDrvDeviceObject; UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(RegistryPath); KdPrint(("MetaFsDriver::DriverEntry - Entered.\n")); g_FilterDriverObject = DriverObject; // Create Dispatch Entry Points. for (int x = 0; x <= IRP_MJ_MAXIMUM_FUNCTION; ++x) DriverObject->MajorFunction[x] = MetaFsDispatchPassThrough; DriverObject->DriverUnload = MetaFsDriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = MetaFsDispatchCreate; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MetaFsDispatchDeviceControl; // Create device object RtlInitUnicodeString(&DeviceName, MetaFs_NT_DEVICE_NAME); retval = IoCreateDevice( DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &EventDrvDeviceObject); if (!NT_SUCCESS(retval)) { return retval; } KdPrint(("MetaFsDriver::DriverEntry - Device Created.\n")); // Create symbolic links RtlInitUnicodeString(&LinkName, MetaFs_WIN32_DEVICE_NAME); retval = IoCreateSymbolicLink(&LinkName, &DeviceName); if (!NT_SUCCESS(retval)) { IoDeleteDevice(EventDrvDeviceObject); return retval; } KdPrint(("MetaFsDriver::DriverEntry - Symbolic link created.\n")); // Set FastIO dispatch table DriverObject->FastIoDispatch = &g_FastIoDispatch; retval = IoRegisterFsRegistrationChange(DriverObject, MetaFsNotificationCallback); KdPrint(("MetaFsDriver::DriverEntry - Exited.\n")); return retval; }

    Since code above is running in kernel mode, it’s a bit tricky to send any output to Visual Studio output window, but fear not we can always make use of KdPrint to send messages to the kernel debugger, at the same time we also need to use DebugView to  capture this messages

    image

    Our minidriver details can be seen via DeviceTree

    image

  2. Once our minifilter driver is running and it’s created a symbolic link, the user mode application  (in our case, a Windows service) creates an event by calling CreateEvent and then uses DeviceIoControl to send the event handle to the driver. In order to send our control code, we use the name of the symbolic link that was created by minifilter driver.

    VOID InitializeCommunicationWithDriver() { HANDLE hFile; DWORD cbSize; if ((hFile = CreateFile(TARGET_DRIVER, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { if ((g_filterEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL)) != NULL) { if (DeviceIoControl(hFile, IOCTL_REGISTER_EVENT, &g_filterEventHandle, sizeof(g_filterEventHandle), NULL, NULL, &cbSize, NULL)) WriteEvent(EventInformation(EventType::INFORMATION_TYPE, L"Event successfully created....")); } CloseHandle(hFile); } }

  3. The call to CreateEvent creates a kernel mode KEVENT object and makes an entry into the application process’s handle table that points to the KEVENT. The HANDLE value returned to the application is essentially an index into the handle table. The handle isn’t directly useful to a WDM driver, though, for two reasons. First of all, there isn’t a documented kernel-mode interface for setting an event, given just a handle. Second, and most important, the handle is useful only in a thread that belongs to the same process. If driver code runs in an arbitrary thread (as it often does), it will be unable to reference the event by using the handle.

  4. It’s required to convert the handle to a pointer to the underlying KEVENT object. To handle a METHOD_BUFFERED control operation that the application uses to register an event with the driver

    HANDLE hEvent = *(PHANDLE) Irp->AssociatedIrp.SystemBuffer; PKEVENT pevent; NTSTATUS status = ObReferenceObjectByHandle(hEvent, EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode, (PVOID*) &pevent, NULL);

  5. ObReferenceObjectByHandle looks up hEvent in the handle table for the current process and stores the address of the associated kernel object in the pevent variable. If the RequestorMode in the IRP is UserMode, this function also verifies that hEvent really is a handle to something, that the something is an event object, and that the handle was opened in a way that includes the EVENT_MODIFY_STATE privilege.

  6. The Windows service can wait for the event to occur (This takes place in a separate thread created in ServiceMain)

    WaitForSingleObject(hEvent, INFINITE);

  7. The driver signals the event in the usual way
    KeSetEvent(pevent, EVENT_INCREMENT, FALSE);

  8. Eventually, the application cleans up by calling CloseHandle. The driver has a separate reference to the event object, which it must release by calling ObDereferenceObject. The object manager won’t destroy the event object until both these things occur.

That pretty much describes one way to communicate between user and kernel-mode. Two pieces of advice in regards to driver development:

  1. Wrap every entry point in your code
    1. DLL entry points
    2. Driver entry points
    3. Around all accesses to buffers passed to the driver
  2. Never trust a pointer
  3. Take care to protect data structures from thread conflicts
  4. Unload drivers properly and cancel any pending operations
  5. Test your drivers on a virtual machine, please!!!!

if you don’t do driver development the right way then you’ll see quite a few images like the one depicted below

image

Dynamically add event handlers to controls in a custom .NET control with C#

A few years back I came up with something called “FRF” (Forms Rendering Framework) which allowed me to render any UI (whether they are Web or Windows based) based on a template definition (Yes, this was long before Microsoft released XAML). Anyways, on one of my personal projects I had a requirement to dynamically create and host Windows controls inside native applications (property pages more specifically). The challenge here was being able to notify the container window (Property page) that something has been modified or changed in the contained user control and then being able to notify the property sheet’s window procedure of that change.  In my personal case, I had to monitor changes made to any textbox (TextChanged) inside the hosted control, the way I got it sorted is depicted below

private IEnumerable<Control> CreateHelper(ITemplateDefinition definition) { var retval = new List<Control>(); var flag = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public; var targetAsm = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(x => string.Equals(x.GetName().Name, " System.Windows.Forms", StringComparison.OrdinalIgnoreCase)); if (targetAsm != null) { definition.TemplateElements.ToList().ForEach(x => { try { var controlType = targetAsm.GetTypes() .FirstOrDefault(z => z.IsSubclassOf(typeof(Control)) && !z.IsAbstract && z.Name.ToUpperInvariant() .Contains(x.Class.ToUpperInvariant())); // Expected to have a default constructor without any parameters var control = controlType.GetConstructors(flag) .FirstOrDefault().Invoke(null) as Control; PropertySetter(control, x); // Does it have a TextChanged event? var ei = control.GetType().GetEvent("TextChanged"); if (ei != null) ei.AddEventHandler(control, new EventHandler((sender, args) => ChangeMonitor.HasChanges = true)); retval.Add(control); } catch (Exception ex) { Logger.LogError(ex); } }); } return retval; }

Pass information to .NET control from Native Code with Visual C++

As a follow up to this post on interoperability between .NET and native code, this post describes how we can host a .NET user control from an ActiveX control, but more importantly set properties that drive or change the behaviour of the .NET user control.

First of all, we need to define an interface with the properties that are required by the user control, but more importantly accessible to native code, and we declare it similarly we do with any other interface but we need to decorate it with a Guid attribute. In this case the control stores the path for a given file to do something, at the same time it’s important to note that if some operations are required to be done to the control then the control should return its HWND (as depicted below)

[Guid("EBD2C511-4EEB-488A-9BF1-EE14FB631C92")] public interface IMetaFsProps { /// <summary> /// Gets the control HWND. /// </summary> /// <returns>IntPtr.</returns> IntPtr GetControlHwnd(); /// <summary> /// Gets or sets the selected file. /// </summary> /// <value>The selected file.</value> string SelectedFile { get; set; } }

Then our .NET user control must implement the interface previously mentioned, but the user control class must also be decorated with a few attributes which are

[ClassInterface(ClassInterfaceType.None)] [ComSourceInterfaces(typeof(IMetaFsProps))] [Guid("917937B1-1AD8-4951-A417-3BED065089A0")] public partial class MyFileControl : UserControl, IMetaFsProps { /// <summary> /// Gets the control HWND. /// </summary> /// <returns></returns> public IntPtr GetControlHwnd() { return Handle; } /// <summary> /// Gets or sets the selected file. /// </summary> /// <value>The selected file.</value> public string SelectedFile { get; set; } }

 

In our Visual C++ COM object we instantiate and host the .NET user control as shown next

HRESULT MyNativeComponent::AddPages(IN LPFNADDPROPSHEETPAGE lpfnAddPage, IN LPARAM lParam) { HPROPSHEETPAGE hPage; PROPSHEETPAGE psp = {0}; auto retval = E_INVALIDARG; psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_DEFAULT; psp.hInstance = _AtlBaseModule.GetResourceInstance(); psp.pszTemplate = MAKEINTRESOURCE(IDD_EMPTYPAGE); psp.pszTitle = _T("My dialog's name goes here"); psp.pcRefParent = NULL; psp.lParam = reinterpret_cast<LPARAM>(new wstring(m_szFile.data())); psp.pfnDlgProc = [](HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)->LRESULT { switch (uiMsg) { case WM_INITDIALOG: CoInitialize(NULL); CComPtr<IDispatch> pUnk; CAxWindow container; auto psp = reinterpret_cast<PROPSHEETPAGE*>(lParam); shared_ptr<wstring> selectedFile(reinterpret_cast<wstring*>(psp->lParam)); container.Attach(hwnd); pUnk.CoCreateInstance(L"MyAssembly.MyFileControl", NULL); // We set the propery here!!! pUnk.PutPropertyByName(_bstr_t("SelectedFile"), &_variant_t(selectedFile->data())); container.AttachControl(pUnk, NULL); CoUninitialize(); pWndProc = (WNDPROC)SetWindowLongPtr(GetParent(hwnd), GWLP_WNDPROC, (LONG_PTR)&CustomWndProc); break; } return FALSE; }; if ((hPage = CreatePropertySheetPage(&psp)) != NULL) { if (!lpfnAddPage(hPage, lParam)) DestroyPropertySheetPage(hPage); retval = NOERROR; } return retval; }

Unit testing our Visual C++ code with Microsoft Unit Testing Framework

One of the things I love about unit testing (besides all of the well-known benefits) is the ability to test code without writing a tester or test harness application, but I can pretty much leverage what Microsoft have already built for us. Image below depicts an unit test I’ve written for this JNI .NET bridge or adapter to piggy back on existing libraries (adapters) provided by  Mulesoft 

image

More information here

Beware of where you call _CrtDumpMemoryLeaks

The Visual C++ compiler has a myriad of great features to build robust and high-quality software. A good example of this could be _CrtDumpMemoryLeaks function that allows to detect any memory leaks  that has occurred in the debug heap.  There is an entire section on debugging native code here.  The results produced by the function in question here (_CrtDumpMemoryLeaks) can be easily misinterpreted if the call to the function is not made in the right place, but let’s illustrate this with an example

1 #include "stdafx.h" 2 #include <iostream> 3 #include <string> 4 #include <memory> 5 #include <stdlib.h> 6 #include <crtdbg.h> 7 #define _CRTDBG_MAP_ALLOC 8 9 int _tmain(int argc, _TCHAR* argv[]) { 10 11 auto dodgyPtr = new int[5]; // Fail (delete is missing) 12 auto mySmartPtr = std::make_unique<int[]>(512); // Ok in "theory" 13 auto myString = std::string("This my test string"); // Ok in "theory" 14 15 _CrtDumpMemoryLeaks(); 16 17 return 0; 18 } 19

The produced output is and you’ll be like Disappointed smile why? if I’m using smart pointers and handling strings with std:: string class… Yes, I must admit it that I haven’t call delete operator but I knew I was leaking one pointer only but in modern C++ this should not happen!!!

1 Detected memory leaks! 2 Dumping objects -> 3 {202} normal block at 0x01046E08, 32 bytes long. 4 Data: <This my test str> 54 68 69 73 20 6D 79 20 74 65 73 74 20 73 74 72 5 {201} normal block at 0x01037748, 8 bytes long. 6 Data: <0 > 30 FB D8 00 00 00 00 00 7 {200} normal block at 0x010465C8, 2048 bytes long. 8 Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9 {199} normal block at 0x010411A8, 20 bytes long. 10 Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 11 Object dump complete. 12 The thread 0x29a4 has exited with code 0 (0x0). 13 The program '[11056] Temp.exe' has exited with code 0 (0x0). 14

Well, reason being is that the string and smart pointers are still “alive” when the call to _CrtDumpMemoryLeaks was made, therefore that memory allocation has not been freed because the destructor of the objects has not been invoked as yet. One of the nicest features in C++ is that the destruction of objects is deterministic, hence objects are destroyed once they go outside of scope. If we make minors changes to the code shown above we would then get a different result which is the correct one.

1 void AllocateMyObjectsInMemory() { 2 auto itemsInArray = 5; 3 auto dodgyPtr = new int[itemsInArray]; // Fail (remember to delete it) 4 auto mySmartPtr = std::make_unique<int[]>(512); // Ok 5 auto myString = std::string("This my test string"); // Ok 6 7 std::cout << "How many bytes am I leaking? " << 8 sizeof(int) * itemsInArray << std::endl; 9 } 10 11 int _tmain(int argc, _TCHAR* argv[]) { 12 13 AllocateMyObjectsInMemory(); 14 15 _CrtDumpMemoryLeaks(); 16 17 return 0; 18 } 19

And the newly produced output is accurate

1 Detected memory leaks! 2 Dumping objects -> 3 {199} normal block at 0x006311A8, 20 bytes long. 4 Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 5 Object dump complete. 6 The thread 0x1540 has exited with code 0 (0x0). 7 The program '[4632] Temp.exe' has exited with code 0 (0x0).

Why am I leaking 20 bytes? Well, an integer is 4 bytes * 5 (number of items in array)

image

Visual Studio also provides us with memory windows that allow us to view into the application’s memory space and it’s very useful when debugging

image

Easy and convenient way to convert Wide Characters to Multibyte with modern C++

One  of the most common tasks we developers have to do comes in the form of data conversion. A good example would be converting  void* (equivalent of Object in .NET) to a specific pointer of a different class through reinterpret_cast, this is however one example. Today’s post is about converting strings as Wide Characters to Multibyte using modern C++.

By modern C++, I mean using smart pointers instead of naked or raw pointers, string class and since it’s a functionality that will be used in different sections of code, it could be in the form of a function template or lambda, in this case, I’ll use a lambda as shown below

1 auto ConvertWstringToChar = [=](std::wstring& original) -> std::string { 2 std::string retval; 3 size_t cntConverted; 4 5 if (!original.empty()) { 6 wcstombs_s(&cntConverted, nullptr, NULL, original.c_str(), 7 original.size()); 8 9 auto buffer = std::make_unique<char[]>(cntConverted); 10 11 memset(buffer.get(), ' ', original.size()); 12 13 wcstombs_s(&cntConverted, buffer.get(), strlen(buffer.get()) + 1, 14 original.c_str(), original.size()); 15 16 retval.append(buffer.get()); 17 } 18 19 return retval; 20 }; 21 22 std::wstring test(L"This is my very funky string!!!!"); 23 auto converted = ConvertWstringToChar(test); 24 }

Some tools that every Visual C++ / .NET developer should have in their toolbox

Hi Community,

This post is about some of the tools I use when building stuff or diagnosing misbehaving applications, so I thought it’d come handy to have them, or learn about them [in case you don’t know them]

Regards,

Angel

Native Windows Service Example

Hi Community,

This blog post describes and explains the steps required to build a native Windows Service. One of the projects I’m currently working on is about a metadata filesystem for Windows (Similar to what WinFS was supposed to be but different in many aspects, mainly because users will have a greater level of customization and it will be template driven). One of the artefacts required (besides Minifilter driver and managed .NET assemblies it’s in the form of a Windows Service).

Building Windows Service in .NET is pretty straightforward, mainly because the project template in Visual Studio does pretty much all of the scaffolding for developers, however, in native code using Visual C++ that template is completely missing and it’s up to developers to do it by themselves.

In my use scenario, the rationale for having a Windows Service is to interact with Minifilter driver. Please bear in mind, most of the stuff we developers build run in User mode and drivers and such do it in Kernel mode, thus the need of having a Windows Service. User and Kernel mode are isolated one from the other, but there are ways to exchange information between the two (if required).

image

The source code for Windows Service is below (please disregard InitializeClr method).

1 #include "stdafx.h" 2 3 // Global variables 4 SERVICE_STATUS g_SvcStatus = {0}; 5 SERVICE_STATUS_HANDLE g_svcHandle = NULL; 6 HANDLE g_filterEventHandle = INVALID_HANDLE_VALUE; 7 HANDLE g_svcStopNotification = INVALID_HANDLE_VALUE; 8 9 10 11 12 /// <summary> 13 /// _tmains the specified argc. 14 /// </summary> 15 /// <param name="argc">The argc.</param> 16 /// <param name="argv">The argv.</param> 17 /// <returns>int.</returns> 18 int _tmain(int argc, _TCHAR* argv[]) { 19 auto retval = 0; 20 21 InitializeClr(); 22 23 SERVICE_TABLE_ENTRY ServiceTable[] = {{SERVICE_NAME, ServiceMain}}; 24 25 if (!StartServiceCtrlDispatcher(ServiceTable)) { 26 WriteEvent(EventInformation(EventType::ERROR_TYPE, L"Unable to start MetaFSAgent Service.")); 27 retval = GetLastError(); 28 } 29 30 return retval; 31 } 32 33 34 /// <summary> 35 /// Services the controller. 36 /// </summary> 37 /// <param name="ctlCode">The control code.</param> 38 VOID WINAPI ServiceController(DWORD ctlCode) { 39 switch (ctlCode) { 40 case SERVICE_CONTROL_STOP: 41 if (g_SvcStatus.dwCurrentState == SERVICE_RUNNING) { 42 ConfigureService(ConfigOption::STOP_SERVICE); 43 if (SetServiceStatus(g_svcHandle, &g_SvcStatus)) { 44 SetEvent(g_filterEventHandle); 45 SetEvent(g_svcStopNotification); 46 WriteEvent(EventInformation(EventType::INFORMATION_TYPE, L"MetaFS Agent Service stopped.\nVersion 1.0.0.0.\n\nChanges made to metadata on existing filesystem objects will not be monitored")); 47 } else WriteEvent(EventInformation(EventType::ERROR_TYPE, L"Unable to change status of MetaFSAgent Service (Stop Pending).")); 48 } 49 break; 50 } 51 } 52 53 /// <summary> 54 /// Services the main. 55 /// </summary> 56 /// <param name="argc">The argc.</param> 57 /// <param name="argv">The argv.</param> 58 VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { 59 HANDLE hThread; 60 61 if ((g_svcHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceController)) != NULL) { 62 ConfigureService(ConfigOption::START_SERVICE); 63 if (SetServiceStatus(g_svcHandle, &g_SvcStatus)) { 64 if ((g_svcStopNotification = CreateEvent(NULL, TRUE, FALSE, NULL)) != NULL) { 65 ConfigureService(ConfigOption::RUNNING_SERVICE); 66 if (SetServiceStatus(g_svcHandle, &g_SvcStatus)) { 67 InitializeCommunicationWithDriver(); 68 WriteEvent(EventInformation(EventType::INFORMATION_TYPE, L"MetaFS Agent Service started.\nVersion 1.0.0.0")); 69 hThread = CreateThread(NULL, NULL, AsyncFilterWorker, NULL, NULL, NULL); 70 WaitForSingleObject(hThread, INFINITE); 71 CloseHandle(g_svcStopNotification); 72 ConfigureService(ConfigOption::STOPPED_SERVICE); 73 SetServiceStatus(g_svcHandle, &g_SvcStatus); 74 CloseHandle(hThread); 75 } else WriteEvent(EventInformation(EventType::ERROR_TYPE, L"Unable to change status of MetaFSAgent Service (Running).")); 76 } else { 77 WriteEvent(EventInformation(EventType::ERROR_TYPE, L"Unable to CreateEvent(g_ServiceStopEvent) for MetaFSAgent Service.")); 78 ConfigureService(ConfigOption::STOP_SERVICE); 79 SetServiceStatus(g_svcHandle, &g_SvcStatus); 80 } 81 } else WriteEvent(EventInformation(EventType::ERROR_TYPE, L"Unable to change status of MetaFSAgent Service (Started).")); 82 } else WriteEvent(EventInformation(EventType::ERROR_TYPE, L"Unable to start MetaFSAgent Service.")); 83 } 84 85 /// <summary> 86 /// Asynchronouses the filter worker. 87 /// </summary> 88 /// <param name="lpParam">The lp parameter.</param> 89 /// <returns>DWORD.</returns> 90 DWORD WINAPI AsyncFilterWorker(LPVOID lpParam) { 91 while (WaitForSingleObject(g_svcStopNotification, INFINITE) != WAIT_OBJECT_0) { 92 // Has there been changes to the filesystem? 93 if (WaitForSingleObject(g_filterEventHandle, INFINITE) != WAIT_OBJECT_0) { 94 WriteEvent(EventInformation(EventType::INFORMATION_TYPE, L"Notification from driver...")); 95 SetEvent(g_filterEventHandle); 96 } 97 } 98 return ERROR_SUCCESS; 99 } 100 101 /// <summary> 102 /// Configures the service. 103 /// </summary> 104 /// <param name="option">The option.</param> 105 VOID ConfigureService(ConfigOption option) { 106 switch (option) { 107 case ConfigOption::START_SERVICE: 108 ZeroMemory(&g_SvcStatus, sizeof(g_SvcStatus)); 109 g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 110 g_SvcStatus.dwControlsAccepted = 0; 111 g_SvcStatus.dwCurrentState = SERVICE_START_PENDING; 112 g_SvcStatus.dwWin32ExitCode = 0; 113 g_SvcStatus.dwServiceSpecificExitCode = 0; 114 g_SvcStatus.dwCheckPoint = 0; 115 break; 116 117 case ConfigOption::STOP_SERVICE: 118 g_SvcStatus.dwControlsAccepted = 0; 119 g_SvcStatus.dwCurrentState = SERVICE_STOPPED; 120 g_SvcStatus.dwWin32ExitCode = GetLastError(); 121 g_SvcStatus.dwCheckPoint = 1; 122 break; 123 124 case ConfigOption::RUNNING_SERVICE: 125 g_SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; 126 g_SvcStatus.dwCurrentState = SERVICE_RUNNING; 127 g_SvcStatus.dwWin32ExitCode = 0; 128 g_SvcStatus.dwCheckPoint = 0; 129 break; 130 131 case ConfigOption::STOPPED_SERVICE: 132 g_SvcStatus.dwControlsAccepted = 0; 133 g_SvcStatus.dwCurrentState = SERVICE_STOPPED; 134 g_SvcStatus.dwWin32ExitCode = 0; 135 g_SvcStatus.dwCheckPoint = 3; 136 } 137 } 138 139 /// <summary> 140 /// Initializes the CLR. 141 /// </summary> 142 VOID InitializeClr() { 143 HINSTANCE hInstance; 144 145 SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); 146 147 if ((hInstance = LoadLibraryEx(INTEROP_LIBRARY, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) != NULL) { 148 ptrInitializeClr funcPtr = (ptrInitializeClr)GetProcAddress(hInstance, "InitializeClr"); 149 funcPtr(); 150 } 151 152 SetErrorMode(NULL); 153 154 FreeLibrary(hInstance); 155 } 156 157 /// <summary> 158 /// Initializes communication with driver 159 /// </summary> 160 VOID InitializeCommunicationWithDriver() { 161 HANDLE hFile; 162 DWORD cbSize; 163 164 if ((hFile = CreateFile(TARGET_DRIVER, GENERIC_READ | GENERIC_WRITE, 165 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { 166 if ((g_filterEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL)) != NULL) { 167 if (DeviceIoControl(hFile, IOCTL_REGISTER_EVENT, &g_filterEventHandle, sizeof(g_filterEventHandle), NULL, NULL, &cbSize, NULL)) 168 WriteEvent(EventInformation(EventType::INFORMATION_TYPE, L"Event successfully created....")); 169 } 170 CloseHandle(hFile); 171 } 172 } 173 174 /// <summary> 175 /// Writes the event. 176 /// </summary> 177 /// <param name="ei">The ei.</param> 178 VOID WriteEvent(const EventInformation& ei) { 179 HANDLE hEventLog; 180 LPWSTR messages[1] = {(WCHAR*)ei.Message.c_str()}; 181 182 if ((hEventLog = OpenEventLog(NULL, L"Application")) != NULL) { 183 ReportEvent(hEventLog, ei.Type, 0x1, 0x1, NULL, 1, NULL, (LPCWSTR*)messages, NULL); 184 CloseEventLog(hEventLog); 185 } 186 }

Regards,

Angel