About Windows Installer, the .NET Framework, and Visual Studio.
If you want to open a .msp file with the Windows Installer APIs, you must pass MSIDBOPEN_PATCHFILE to the MsiOpenDatabase function, or ERROR_OPEN_FAILED (110) is returned. Below is the definition of both MSIDBOPEN_PATCHFILE and MSIDBOPEN_READONLY from msiquery.h in the Windows Installer SDK.
#define MSIDBOPEN_READONLY (LPCTSTR)0#define MSIDBOPEN_PATCHFILE 32/sizeof(*MSIDBOPEN_READONLY)
LPCTSTR is defined as LPCWSTR when UNICODE is defined, which is defined as wchar_t*. Since sizeof(wchar_t) is 2, the value of MSIDBOPEN_PATCHFILE is 16 when UNICODE is defined. If you pass this to either the MsiOpenDatabaseA function or the MsiOpenDatabaseW function ERROR_OPEN_FAILED is still returned. The value must always be defined as 32.
For the automation method Installer.OpenDatabase the second parameter must be set to msiOpenDatabaseModePatchFile to open a patch, which is always defined as 32.
Most developers probably haven't run into this problem yet because of support for Windows 95, 98, and Me, where Unicode is not natively supported and it's typically undesirable to have to ship and support two bootstrap applications. Since Windows NT, 2000, XP, 2003, and future platforms support both ANSI and Unicode it makes sense to compile bootstrap applications for ANSI or MBCS. But when you choose to or need to support only Unicode, be sure to pass 32 as the szPersist parameter to MsiOpenDatabase.
PMSIDATABASE hDatabase = NULL;UINT uiError = MsiOpenDatabase(TEXT("Patch.msp"), (LPCTSTR)32, &hDatabase);