Module: wine Branch: master Commit: 98761037ab0bc6e9c68e2b9e1a25cab5b3abad3f URL: http://source.winehq.org/git/wine.git/?a=commit;h=98761037ab0bc6e9c68e2b9e1a... Author: Hans Leidekker <hans(a)codeweavers.com> Date: Fri Feb 12 10:32:35 2010 +0100 msi: Implement the UnregisterTypeLibraries standard action. --- dlls/msi/action.c | 70 ++++++++++++++++++++++++++++++++++---- dlls/msi/msipriv.h | 1 + dlls/msi/tests/install.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 8 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 31870bd..0f1877e 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -2862,8 +2862,6 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param) HMODULE module; HRESULT hr; - static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0}; - component = MSI_RecordGetString(row,3); comp = get_loaded_component(package,component); if (!comp) @@ -2967,6 +2965,68 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package) return rc; } +static UINT ITERATE_UnregisterTypeLibraries( MSIRECORD *row, LPVOID param ) +{ + MSIPACKAGE *package = param; + LPCWSTR component, guid; + MSICOMPONENT *comp; + GUID libid; + UINT version; + LCID language; + SYSKIND syskind; + HRESULT hr; + + component = MSI_RecordGetString( row, 3 ); + comp = get_loaded_component( package, component ); + if (!comp) + return ERROR_SUCCESS; + + if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_ABSENT )) + { + TRACE("Skipping, component is not scheduled for uninstall\n"); + + comp->Action = comp->Installed; + return ERROR_SUCCESS; + } + comp->Action = INSTALLSTATE_ABSENT; + + guid = MSI_RecordGetString( row, 1 ); + CLSIDFromString( (LPWSTR)guid, &libid ); + version = MSI_RecordGetInteger( row, 4 ); + language = MSI_RecordGetInteger( row, 2 ); + +#ifdef _WIN64 + syskind = SYS_WIN64; +#else + syskind = SYS_WIN32; +#endif + + hr = UnRegisterTypeLib( &libid, (version >> 8) & 0xffff, version & 0xff, language, syskind ); + if (FAILED(hr)) + { + WARN("Failed to unregister typelib: %08x\n", hr); + } + + return ERROR_SUCCESS; +} + +static UINT ACTION_UnregisterTypeLibraries( MSIPACKAGE *package ) +{ + UINT rc; + MSIQUERY *view; + static const WCHAR query[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + '`','T','y','p','e','L','i','b','`',0}; + + rc = MSI_DatabaseOpenViewW( package->db, query, &view ); + if (rc != ERROR_SUCCESS) + return ERROR_SUCCESS; + + rc = MSI_IterateRecords( view, NULL, ITERATE_UnregisterTypeLibraries, package ); + msiobj_release( &view->hdr ); + return rc; +} + static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param) { MSIPACKAGE *package = param; @@ -6452,12 +6512,6 @@ static UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package ) return msi_unimplemented_action_stub( package, "UnregisterProgIdInfo", table ); } -static UINT ACTION_UnregisterTypeLibraries( MSIPACKAGE *package ) -{ - static const WCHAR table[] = { 'T','y','p','e','L','i','b',0 }; - return msi_unimplemented_action_stub( package, "UnregisterTypeLibraries", table ); -} - typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*); static const struct diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index f81184b..8022afc 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -1075,6 +1075,7 @@ static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0}; static const WCHAR szProductID[] = {'P','r','o','d','u','c','t','I','D',0}; static const WCHAR szPIDTemplate[] = {'P','I','D','T','e','m','p','l','a','t','e',0}; static const WCHAR szPIDKEY[] = {'P','I','D','K','E','Y',0}; +static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0}; /* memory allocation macro functions */ static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1); diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 96b5117..83e7220 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -1320,6 +1320,50 @@ static const CHAR odbc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\ "Media\tDiskId\n" "1\t5\t\t\tDISK1\t\n"; +static const CHAR tl_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" + "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" + "File\tFile\n" + "typelib.dll\ttypelib\ttypelib.dll\t1000\t\t\t8192\t1\n"; + +static const CHAR tl_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n" + "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n" + "Feature\tFeature\n" + "typelib\t\t\ttypelib feature\t1\t2\tMSITESTDIR\t0\n"; + +static const CHAR tl_feature_comp_dat[] = "Feature_\tComponent_\n" + "s38\ts72\n" + "FeatureComponents\tFeature_\tComponent_\n" + "typelib\ttypelib\n"; + +static const CHAR tl_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" + "s72\tS38\ts72\ti2\tS255\tS72\n" + "Component\tComponent\n" + "typelib\t{BB4C26FD-89D8-4E49-AF1C-DB4DCB5BF1B0}\tMSITESTDIR\t0\t\ttypelib.dll\n"; + +static const CHAR tl_typelib_dat[] = "LibID\tLanguage\tComponent_\tVersion\tDescription\tDirectory_\tFeature_\tCost\n" + "s38\ti2\ts72\tI4\tL128\tS72\ts38\tI4\n" + "TypeLib\tLibID\tLanguage\tComponent_\n" + "{EAC5166A-9734-4D91-878F-1DD02304C66C}\t0\ttypelib\t1793\t\tMSITESTDIR\ttypelib\t\n"; + +static const CHAR tl_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" + "s72\tS255\tI2\n" + "InstallExecuteSequence\tAction\n" + "LaunchConditions\t\t100\n" + "CostInitialize\t\t800\n" + "FileCost\t\t900\n" + "CostFinalize\t\t1000\n" + "InstallValidate\t\t1400\n" + "InstallInitialize\t\t1500\n" + "ProcessComponents\t\t1600\n" + "RemoveFiles\t\t1700\n" + "InstallFiles\t\t2000\n" + "RegisterTypeLibraries\tREGISTER_TYPELIB=1\t3000\n" + "UnregisterTypeLibraries\t\t3100\n" + "RegisterProduct\t\t5100\n" + "PublishFeatures\t\t5200\n" + "PublishProduct\t\t5300\n" + "InstallFinalize\t\t6000\n"; + typedef struct _msi_table { const CHAR *filename; @@ -2131,6 +2175,19 @@ static const msi_table odbc_tables[] = ADD_TABLE(property) }; +static const msi_table tl_tables[] = +{ + ADD_TABLE(tl_component), + ADD_TABLE(directory), + ADD_TABLE(tl_feature), + ADD_TABLE(tl_feature_comp), + ADD_TABLE(tl_file), + ADD_TABLE(tl_typelib), + ADD_TABLE(tl_install_exec_seq), + ADD_TABLE(media), + ADD_TABLE(property) +}; + /* cabinet definitions */ /* make the max size large so there is only one cab file */ @@ -8022,6 +8079,31 @@ static void test_install_remove_odbc(void) delete_test_files(); } +static void test_register_typelib(void) +{ + UINT r; + + create_test_files(); + create_file("msitest\\typelib.dll", 1000); + create_database(msifile, tl_tables, sizeof(tl_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + r = MsiInstallProductA(msifile, "REGISTER_TYPELIB=1"); + todo_wine ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiInstallProductA(msifile, "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + ok(!delete_pf("msitest\\typelib.dll", TRUE), "file not removed\n"); + todo_wine ok(!delete_pf("msitest", FALSE), "directory not removed\n"); + + delete_test_files(); +} + START_TEST(install) { DWORD len; @@ -8121,6 +8203,7 @@ START_TEST(install) test_register_font(); test_validate_product_id(); test_install_remove_odbc(); + test_register_typelib(); DeleteFileA(log_file);