Friday, December 02, 2011

Using Image File Execution Options (IEFO) to invoke a debugger automatically

A handy tip for invoking a debugger (or anything else) in place of a normal executable at image load time is to set the following registry key:
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<image name>\Debugger = <other image name> (REG_SZ)

For example, to invoke WinDBG when the OS loads notepad.exe:
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe\Debugger = "C:\Program Files\Debugging Tools for Windows (x86)\windbg.exe"

Very handy for short lived processes that are causing trouble, but you have no other means of attaching to them / etc!

Friday, September 23, 2011

Having trouble setting the height of a .NET Winform TextBox control?

Make sure multiline is set to true!

GetManifestResourceStream() returns NULL

If like me you're having problems accessing an embedded (assembly) resource using GetManifestResourceStream(), then read on:

GetManifestResourceStream was returning null even though I was pre-fixing the resource name with the namespace, i.e. NameSpace.Resource.ext.

The problem turned out to be the sub directory was missing from the name, in my example my resource lived under a folder (in the solution explorer) called Resources, so changing the qualified name to be:

NameSpace.Resources.Resource.ext fixed the issue.

Hope this helps someone else!

Friday, August 26, 2011

List of MSXML versions

For reference, here you can find a list of all versions of MSXML:

http://support.microsoft.com/kb/269238

.. and just in case Microsoft decide to once again change their site structure without providing adequate redirects here is the content for prosperity:

MSXML versions that have been released by Microsoft

VersionFile nameFile version number
1.0Msxml.dll4.71.1712.5
1.0aMsxml.dll4.72.2106.4
1.0 SP1Msxml.dll4.72.3110.0
2.0 Msxml.dll5.0.2014.0206
2.0aMsxml.dll5.0.2314.1000
2.0bMsxml.dll5.0.2614.3500
2.5 Beta 2Msxml.dll5.0.2919.38
2.5aMsxml.dll5.0.2919.6303
2.5Msxml.dll5.0.2920.0
2.5 SP1Msxml.dll8.0.5226
2.5 SP2Msxml.dll, Msxmlr.dll (the last DLL is a resource-only DLL)8.0.5718.1
2.5 SP3Msxml.dll, Msxmlr.dll (the last DLL is a resource-only DLL)8.00.6730.0
2.6 Web ReleaseMsxml2.dll7.50.4920.0
2.6 SP1Msxml2.dll, Msxml2a.dll, Msxml2r.dll (the last two DLLs are resource-only DLLs)8.1.7502.0
2.6 SP2Msxml2.dll, Msxml2a.dll, Msxml2r.dll (the last two DLLs are resource-only DLLs)8.2.8307.0
3.0 Web ReleaseMsxml3.dll, Msxml3a.dll, Msxml3r.dll (the last two DLLs are resource-only DLLs)7.50.5108.0
3.0Msxml3.dll, Msxml3a.dll, Msxml3r.dll (the last two DLLs are resource-only DLLs)8.0.7820.0
3.0 SP1Msxml3.dll, Msxml3a.dll, Msxml3r.dll (the last two DLLs are resource-only DLLs)8.10.8308.0
3.0 SP2Msxml3.dll, Msxml3a.dll, Msxml3r.dll (the last two DLLs are resource-only DLLs)8.20.8730.1
3.0 SP3Msxml3.dll, Msxml3a.dll (8.20.8730.1), Msxml3r.dll (8.20.8730.1) (the last two DLLs are resource-only DLLs)8.30.9926.0
3.0 SP4Msxml3.dll, Msxml3a.dll (8.20.8730.1), Msxml3r.dll (8.20.8730.1) (the last two DLLs are resource-only DLLs)8.40.9419.0
3.0 SP5Msxml3.dll, Msxml3a.dll (8.20.8730.1), Msxml3r.dll (8.20.8730.1) (the last two DLLs are resource-only DLLs)8.50.2162.0
3.0 SP7Msxml3.dll, Msxml3a.dll, Msxml3r.dll (the last two DLLs are resource-only DLLs)8.70.1104
3.0 Post SP7 MS06-061Msxml3.dll8.70.1113.0
3.0 Post SP8Msxml3.dll, Msxml3a.dll (8.20.8730.1), Msxml3r.dll (8.20.8730.1) (the last two DLLs are resource-only DLLs)8.80.1185.0
3.0 SP9Msxml3.dll, Msxml3a.dll (8.20.8730.1), Msxml3r.dll (8.20.8730.1) (the last two DLLs are resource-only DLLs)8.90.1002.0
3.0 Post SP9 MS06-061Msxml3.dll8.90.1101.0
3.0 SP10 (On Vista SP1)Msxml3.dll, Msxml3r.dll (8.20.8730.1) (the last DLL is resource-only DLL)8.100.1043.0
3.0 SP10 (On Vista SP2)Msxml3.dll, Msxml3r.dll (8.20.8730.1) (the last DLL is resource-only DLL)8.100.5000.0
3.0 Post SP10 KB973687Msxml3.dll8.100.5002.0
3.0 SP11Msxml3.dll, Msxml3r.dll (8.110.7600.16385) (the last DLL is resource-only DLL)8.110.7600.16385
3.0 Post SP11 MS10-051Msxml3.dll8.110.7600.16605
4.0Msxml4.dll, WinHTTP5.dll, Msxml4a.dll, Msxml4r.dll (the last two DLLs are resource-only DLLs)4.0.9004.0
4.0 SP1Msxml4.dll, WinHTTP5.dll, Msxml4a.dll, Msxml4r.dll (the last two DLLs are resource-only DLLs)4.10.9404.0
4.0 SP2Msxml4.dll, WinHTTP5.dll (5.0.2613.0), Msxml4a.dll (4.10.9404.0), Msxml4r.dll (4.10.9404.0) (the last two DLLs are resource-only DLLs)4.20.9818.0
4.0 Post SP2 MS06-061Msxml4.dll, Msxml4r.dll (4.10.9404.0) (the last DLL is a resource-only DLL)4.20.9839.0
4.0 Post SP2 MS06-071Msxml4.dll4.20.9841.0
4.0 Post SP2 MS07-042Msxml4.dll4.20.9848.0
4.0 SP3Msxml4.dll, Msxml4r.dll (4.30.2100.0) (the last DLL is a resource-only DLL)4.30.2100.0
5.0 (Office 2003)Msxml5.dll, Msxml5r.dll (5.0.2916.0) (the last DLL is a resource-only DLL)5.0.2916.0
5.0 (Office 2003 SP1)Msxml5.dll, Msxml5r.dll (5.10.2925.0) (the last DLL is a resource-only DLL)5.10.2925.0
5.0 (Office 2003 SP2)Msxml5.dll, Msxml5r.dll ( 5.10.2927.0) (the last DLL is a resource-only DLL) 5.10.2927.0
5.0 (Office 2003 Post SP2) MS06-061Msxml5.dll5.10.2930.0
5.0 (Office 2007)Msxml5.dll5.20.1076
5.0 (Office 2007 Post release) MS07-042Msxml5.dll5.20.1081.0
6.0Msxml6.dll, Msxml6r.dll (6.0.3883.0) (the last DLL is a resource-only DLL)6.0.3883.0
6.0 Post release MS06-061Msxml6.dll, Msxml6r.dll (6.0.3883.0) (the last DLL is a resource-only DLL)6.0.3888.0
6.0 Post release MS06-071Msxml6.dll6.0.3890.0
6.0 SP1Msxml6.dll6.10.1129.0
6.0 Post SP1 MS07-042Msxml6.dll6.10.1200.0
6.0 Post SP2 MS08-069Msxml6.dll6.20.1099.0
6.0 Post SP2 KB973687Msxml6.dll6.20.5002.0
6.0 SP3Msxml6.dll, Msxml6r.dll (the last DLL is a resource-only DLL)6.30.7600.16385
Notes
  • MSXML versions 1.x and 2.x are no longer supported by Microsoft.
  • MSXML 3.0 support follows the support policy of the OS into which it is built.
  • MSXML 4.0 is supported by Microsoft only if you are running Service Pack 3 (SP3).
  • MSXML 5.0 is supported by the Microsoft Office lifecycle policy.
  • MSXML 6.0 support follows the support policy of the OS into which it is built or onto which it is installed. 
  • This table includes the version of MSXML that is included in security updates that were released since October 10, 2006. For more information about the security updates, click the following article numbers to view the articles in the Microsoft Knowledge Base:
    924191 MS06-061: Vulnerabilities in Microsoft XML Core Services could allow remote code execution
    928088 MS06-071: Vulnerability in Microsoft XML Core Services could allow remote code execution
    936227 MS07-042: Vulnerability in Microsoft XML Core Services could allow remote code execution
    955218 MS08-069: Vulnerabilities in Microsoft XML Core Services could allow remote code execution
    2079403 MS10-051: Vulnerability in Microsoft XML Core Services Could allow remote code execution
  • 32-bit versions of MSXML 3.0 (Wmsxml3.dll.) on 64-bit Windows Server 2003 uses the same MSXML and file version numbers that are listed in this table.
  • If MSXML 4.0 SP2 (out-of-support in April 2010) is installed on a computer that is running Windows NT, Windows 2000 SP2 and earlier, Windows 2003 RTM, or Windows XP RTM, the WinHTTP5.dll file is installed.

MSXML versions that are included with other Microsoft products and software updates

Replaced MSXML security update - MS02-008

Article numberMsxml versionFile nameFile version number
3182022.6 SP2 (including hotfix)Msxml2.dll, Msxml2a.dll, Msxml2r.dll (the last two DLLs are resource-only DLLs)8.20.8307.0
3172443.0 SP2 (including hotfix)Msxml3.dll8.20.9415.0
3172444.0 (including hotfix)Msxml4.dll, WinHTTP5.dll, Msxml4a.dll, Msxml4r.dll (the last two DLLs are resource-only DLLs)4.00.9406.0

MSXML versions that are included with Microsoft Internet Explorer

Microsoft Internet Explorer versionMicrosoft XML version (file version)
4.01.0 (4.71.1712.5)
4.0a1.0a (4.72.2106.4)
4.01 (SP1)2.0a (5.0.2014.0206)
5.0a2.0a (5.0.2314.1000)
5.0b2.0b (5.0.2614.3500)
5.012.5a (5.0.2919.6303)
5.01 SP12.5 SP1 (8.0.5226)
5.52.5 SP1 (8.0.5226)
5.5 SP22.5 Post-SP2 (8.00.6611.0)
6.03.0 SP2 (8.20.8730.1)
6.0 SP13.0 SP3 (8.30.9926.0)

MSXML versions that are included with MDAC

MDAC version (products)Microsoft XML version (file version)
MDAC 2.5 (Windows 2000)2.5 (5.0.2920.0)
MDAC 2.5 SP1 (Windows 2000 SP1)2.5 SP1 (8.0.5226)
MDAC 2.5 SP2 (Windows 2000 SP2)2.5 SP2 (8.0.5718.1)
MDAC 2.5 SP3 (Windows 2000 SP3)2.5 SP3 (8.00.6730.0)
MDAC 2.6 (SQL Server 2000)2.6 (8.0.6518.1)
MDAC 2.6 SP1 (SQL Server 2000 SP1)2.6 SP1 (8.1.7502.0)
MDAC 2.6 SP2 (SQL Server 2000 SP2)2.6 SP2 (8.2.8307.0)
MDAC 2.7 (Windows XP)3.0 SP2 (8.20.8730.1)
MDAC 2.7 SP1 (Windows XP SP1)3.0 SP3 (8.30.9926.0)
MDAC 2.8 (Windows Server 2003)3.0 SP4 (8.40.9419.0)
MDAC 2.8 SP13.0 SP7 (8.70.1104.0)

MSXML versions that are included with other Microsoft products

This is not a complete list of MSXML versions that are included with other Microsoft products.
Other productsMicrosoft XML version (file version)
Microsoft Security Essentials (Client)4.0
BizTalk Server 20044.0
Microsoft Office Project Server 20034.0
Encarta 2003, 2004, 2005, and Student/Encarta 20064.0
Works Suite 2006, Works Suite 2005, Works Suite 2004, Works Suite 20034.0
Live Communications Server4.0, 6.0
Application Compatibility Toolkit4.0, 6.0
URGE 6.0
Microsoft .NET Framework 3.06.0
Microsoft Visual Studio 20056.0
Microsoft SQL Server 20056.0
Microsoft SQL Server 20086.0
Student/Encarta 20076.0
Zune software version 1.06.0
Windows SharePoint Services 3.06.0

Note If the MSXML parser is updated on a computer that has Microsoft Application Center 2000 installed, you must reinstall Application Center 2000. For more information, click the following article number to view the article in the Microsoft Knowledge Base:
289510 Application Center 2000 installs a special version of MSXML 3.0

Anyone looking for the Platform SDK Feb 2003 (aka the last Platform SDK to support Visual C++ 6)?

Here it is:

http://groups.google.com/group/microsoft.public.platformsdk.sdk_install/msg/087b0178f5d8159e?&hl=en

Thursday, August 25, 2011

More fun with C++/CLI DLLs and native MFC Extension DLLs!

I've recently been busy working on an ActiveX DLL written in C++/CLI, I chose C++/CLI (instead of C#) because we have "legacy" code in native C++ DLLs, some of which contain MFC exported classes (i.e. MFC Extension DLLs). As such there would have been a horrible amount of "glue" code to get this working in C# so the C++/CLI was the best choice for this sort of project.

Everything seems to have been going very well, until I noticed regasm hanging up on Vista during interop registration, the debug version of the DLL doesn't exhibit the problem, only the release version.

So I fired up WinDbg and setup the Windows symbol server path and launched regasm through the debugger. The stack trace revealed an invalid pointer usage inside AfxTermExtensionModule inside MFC42U. After some research I learned the way that MFC extension DLLs work internally (via CDynLinkLibrary), and some further digging produced this:-

http://support.microsoft.com/kb/154126

My next point of call was the DllMain entry points for the 4 MFC extension DLLs I'm making use of, which revealed that the CDynLinkLibrary instantiation was being carried out inside DllMain()'s DLL_PROCESS_ATTACH switch branch. Following the advice from the Microsoft link above, it becomes obvious that we do indeed need to create a separate exported function for the CDynLinkLibrary instantiation, this way we can call it and wire into the link library chain of our own DLL.

Severe headache, but at least I found a solution!

Finalize and Dispose in C#

I came across this succinct (well as succinct as you can be when discussing this topic) and comprehensive description of Dispose and Finalize semantics and thought I'd re-post it for reference (the author mentions specific C# functions, but the underlying mechanism applies to all .NET languages):-

(credits go to itowlson @ codeproject)

Finalize is the backstop method, called by the garbage collector when it reclaims an object. Dispose is the "deterministic cleanup" method, called by applications to release valuable native resources (window handles, database connections, etc.) when they are no longer needed, rather than leaving them held indefinitely until the GC gets round to the object.

As the user of an object, you always use Dispose. Finalize is for the GC. As the implementer of a class, if you hold managed resources that ought to be disposed, you implement Dispose. If you hold native resources, you implement both Dispose and Finalize, and both call a common method that releases the native resources. These idioms are typically combined through a private Dispose(bool disposing) method, which Dispose calls with true, and Finalize calls with false. This method always frees native resources, then checks the disposing parameter, and if it is true it disposes managed resources and calls GC.SuppressFinalize.

Wednesday, August 24, 2011

Visual Studio embedded manfiest targetting 9.0.21022.8 CRT even though 9.0.30729.1 (SP1) is in the redist

Something else noticed whilst developing my C++/CLI ActiveX control.

I'm using the CRT (v9.0) and for deployment I'm shipping the DLLs as private assemblies (i.e. 'xcopy deployment'). However what I noticed is that the embedded manifest inside my DLL was pointing toward version 9.0.210228.8 of the CRT, when the actual DLLs in the redist folder (which I'm using for packaging) are the SP1 version of the CRT (v9.0.30729.1).

Problem is, if the target installation PC doesn't already have the SP1 Visual C++ 2008 Redistributable SP1 package installed, then the runtime probe will fallback to my private assembly, however, because my private assembly version is 9.0.30729.1 but the manifest is asking for 9.0.210228.8 then we get a load failure.

Solution is to add a #define into the source (stdafx.h) to tell Visual Studio to generate a manifest which points to the current vclibs installed for the development environment (i.e. 9.0.30729.1):-
#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

Tuesday, August 23, 2011

C++/CLI ActiveX automatic registration

I've been working on an ActiveX control written in C++/CLI recently and I thought I'd share the COM registration function ([ComRegisterFunction()] attribute) I've written (which is called by regasm.exe when you're registering the assembly for COM Interop).

It does the following:

Creates the necessary keys to register as an ActiveX control.
Adds in the codebase keys so there is no need to pass the /codebase flag to regasm.exe.

Please note, if you're not including oleidl.h as part of your include hierarchy (which I am as I'm using the Windows SDK), then you'll need to define the following constants:
// Ref: http://msdn.microsoft.com/en-us/library/ms678497.aspx

const int OLEMISC_RECOMPOSEONRESIZE = 1;
const int OLEMISC_CANTLINKINSIDE = 16;
const int OLEMISC_INSIDEOUT = 128;
const int OLEMISC_ACTIVATEWHENVISIBLE = 256;
const int OLEMISC_SETCLIENTSITEFIRST = 131072;
Credit is given to the authors of the CSActiveX control upon which this code was originally based.
//
// we need to add some extra registry keys on top of the regasm.exe generated
// keys. this is because we are an ActiveX control (not just a plain COM control)
// and as such require certain keys and values to be present.
//
// we also add in the codebase entries (instead of passing /codebase to regasm.exe)
// this is so we avoid the overkill warnings that regasm.exe generates.
//
// as such to register this .NET assembly as a fully fledged ActiveX control
// we need to run:
//
// regasm.exe /tlb
//
void FTEngine::Register( Type^ t )
{
  try
  {
    // Open the CLSID key of the control
    RegistryKey^ keyCLSID = Registry::ClassesRoot->OpenSubKey( "CLSID\\" +
                             t->GUID.ToString("B"), true );

    //////////////////////////////////////////////////////////////////////////
    // Set "InprocServer32" to register a 32-bit in-process server.
    // InprocServer32 =
    // Ref: http://msdn.microsoft.com/en-us/library/ms683844.aspx
    //
    RegistryKey^ subkey = keyCLSID->OpenSubKey( "InprocServer32", true );
    if( subkey )
    {
      // .NET runtime engine (mscoree.dll) for .NET assemblies
      subkey->SetValue( nullptr, Environment::SystemDirectory + "\\mscoree.dll" );

      // setup codebase flag as we're not in the GAC
      subkey->SetValue( "CodeBase", Assembly::GetExecutingAssembly()->CodeBase );

      // setup the version specific codebase flag
      Version^ ver = Assembly::GetExecutingAssembly()->GetName()->Version;
      subkey = subkey->OpenSubKey( String::Format( "{0}.{1}.{2}.{3}",
                                   ver->Major, ver->Minor, ver->Build,
                                   ver->Revision ), true );

      if( subkey )
      {
        // setup codebase flag as we're not in the GAC
        subkey->SetValue( "CodeBase",
                          Assembly::GetExecutingAssembly()->CodeBase );
      }
   }

   //////////////////////////////////////////////////////////////////////////
   // Create "Control" to identify it as an ActiveX Control.
   // Ref: http://msdn.microsoft.com/en-us/library/ms680056.aspx
   //
   keyCLSID->CreateSubKey( "Control" );

   //////////////////////////////////////////////////////////////////////////
   // Create "MiscStatus" to specify how to create/display an object.
   // MiscStatus =
   // Ref: http://msdn.microsoft.com/en-us/library/ms683733.aspx
   //
    subkey = keyCLSID->CreateSubKey( "MiscStatus" );

    int nMiscStatus = OLEMISC_RECOMPOSEONRESIZE +
                        OLEMISC_CANTLINKINSIDE + OLEMISC_INSIDEOUT +
                        OLEMISC_ACTIVATEWHENVISIBLE + OLEMISC_SETCLIENTSITEFIRST;

   subkey->SetValue( "", nMiscStatus.ToString(), RegistryValueKind::String );

   //////////////////////////////////////////////////////////////////////////
   // Create "ToolBoxBitmap32" to identify the module name and the resource
   // ID for a 16 x 16 bitmap as the toolbar button face.
   // ToolBoxBitmap32 = .,
   // Ref: http://msdn.microsoft.com/en-us/library/ms687316.aspx
   //
   subkey = keyCLSID->CreateSubKey( "ToolBoxBitmap32" );

   // If you want different icons for each control in the assembly you
   // can modify this section to specify a different icon each time.
   // Each specified icon must be embedded as a win32 resource in the
   // assembly; the default one is at the index 101, but you can use
   // additional ones.
   subkey->SetValue( "",
                     Assembly::GetExecutingAssembly()->Location + ", 101",
                     RegistryValueKind::String );

   //////////////////////////////////////////////////////////////////////////
   // Create "TypeLib" to specify the typelib GUID associated with the class.
   //
   subkey = keyCLSID->CreateSubKey("TypeLib");

   Guid libId = Marshal::GetTypeLibGuidForAssembly( t->Assembly );
   subkey->SetValue( "",
                     libId.ToString("B"),
                     RegistryValueKind::String );  


   //////////////////////////////////////////////////////////////////////////
   // Create "Version" to specify the version of the control.
   // Ref: http://msdn.microsoft.com/en-us/library/ms686568.aspx
   //
   subkey = keyCLSID->CreateSubKey( "Version" );

   int nMajor, nMinor;
   Marshal::GetTypeLibVersionForAssembly( t->Assembly, nMajor, nMinor);
   subkey->SetValue( "",
                     String::Format( "{0}.{1}", nMajor, nMinor ) );
   }
 catch( Exception^ ex )
 {
   LogException( ex );
   throw;
 }
}

Custom attributes are not consistent!

error LNK2022: metadata operation failed (80131195) : Custom attributes are not consistent: (0x0c00007d).
This is caused by specifying a managed attribute on the implementation of a C++/CLI function (i.e .cpp file), but not on the definition (i.e .h file).

Change your code so just the header file contains the attribute.

Javascript can't pass by reference into ActiveX/COM component

Useful information:
JScript / Javascript can't pass values by reference into a COM component, whereas VBScript can...

Thursday, July 28, 2011

Visual Studio (all editions including Express) on 64bit Windows may cause headaches when using "Register for COM Interop"

Just experienced a wasted 60 minutes trying to figure out why a C# project I've created (which is registered for COM Interop / CCW) couldn't be created from my test harness .vbs file (via CreateObject).

Background: I installed Visual C# 2010 Express on a 64bit Windows 7 platform, created my demo C# 'COM project', told VS to 'Register for COM Interop' - it all built without fail. However when I try and call into the COM object via a test.vbs file COM was complaining!

After some investigation (the /regfile switch on regasm.exe helped me out) I noticed that VS was using the 32bit version of regasm.exe which was subsequently writing the registry entries under the 'virtualised' WOW64 hierarchy (i.e. HKEY_LOCAL_MACHINE\Software\Wow6432Node) . Thus when I execute my .vbs (which internally uses the 64bit cscript.exe) then it couldn't find the COM object as registered (as it was only registered for the 32bit world).

Solution is to manually run the 64bit regasm.exe so the registry entries are put into the normal (and correct) place. Then your COM object will be visible to the 64bit world!

See here:-
http://support.microsoft.com/kb/956933

Wednesday, February 02, 2011

Want tabs in Visual Studio 6 / VC6? = wndtabs

Still stuck using Visual Studio 6 / Visual C++ 6 IDE? (for whatever reason!)

Want all your source files to be represented as tabs like in the later Visual Studio IDEs (i.e. 2005 / 2008 / etc.) , plus a few other toys?

Give http://www.wndtabs.com/ a try and make your life easier.

Wednesday, January 19, 2011

Get filename and line number in pragma message

Ever wanted to get proper "double clickable" file name and line number output from your #pragma message() statements?

Use the following defines (for example in stdafx.h):

#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : "

Then use __LOC__ in your #pragma message() statements:

#pragma message(__LOC__"This code will be completed in Phase 2")

At which point you should see the following compiler output:

C:\honda\2.5g\PC\runtime\SILinkProcess\SiLink_helpers.cpp(567) : This code will be completed in Phase 2

Very handy!