1 /* 2 * DLL for testing type 1 custom actions 3 * 4 * Copyright 2017 Zebediah Figura 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <stdio.h> 23 24 #include <windef.h> 25 #include <winbase.h> 26 #define COBJMACROS 27 #include <objbase.h> 28 #include <unknwn.h> 29 #include <msi.h> 30 #include <msiquery.h> 31 32 static void ok_(MSIHANDLE hinst, int todo, const char *file, int line, int condition, const char *msg, ...) 33 { 34 static char buffer[2000]; 35 MSIHANDLE record; 36 va_list valist; 37 38 va_start(valist, msg); 39 vsprintf(buffer, msg, valist); 40 va_end(valist); 41 42 record = MsiCreateRecord(5); 43 MsiRecordSetInteger(record, 1, todo); 44 MsiRecordSetStringA(record, 2, file); 45 MsiRecordSetInteger(record, 3, line); 46 MsiRecordSetInteger(record, 4, condition); 47 MsiRecordSetStringA(record, 5, buffer); 48 MsiProcessMessage(hinst, INSTALLMESSAGE_USER, record); 49 MsiCloseHandle(record); 50 } 51 #define ok(hinst, condition, ...) ok_(hinst, 0, __FILE__, __LINE__, condition, __VA_ARGS__) 52 #define todo_wine_ok(hinst, condition, ...) ok_(hinst, 1, __FILE__, __LINE__, condition, __VA_ARGS__) 53 54 55 /* Main test. Anything that doesn't depend on a specific install configuration 56 * or have undesired side effects should go here. */ 57 UINT WINAPI main_test(MSIHANDLE hinst) 58 { 59 UINT res; 60 IUnknown *unk = NULL; 61 HRESULT hres; 62 63 /* Test for an MTA apartment */ 64 hres = CoCreateInstance(&CLSID_Picture_Metafile, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); 65 todo_wine_ok(hinst, hres == S_OK, "CoCreateInstance failed with %08x\n", hres); 66 67 if (unk) IUnknown_Release(unk); 68 69 /* Test MsiGetDatabaseState() */ 70 res = MsiGetDatabaseState(hinst); 71 todo_wine_ok(hinst, res == MSIDBSTATE_ERROR, "expected MSIDBSTATE_ERROR, got %u\n", res); 72 73 return ERROR_SUCCESS; 74 } 75 76 UINT WINAPI test_retval(MSIHANDLE hinst) 77 { 78 char prop[10]; 79 DWORD len = sizeof(prop); 80 UINT retval; 81 82 MsiGetPropertyA(hinst, "TEST_RETVAL", prop, &len); 83 sscanf(prop, "%u", &retval); 84 return retval; 85 } 86 87 static void append_file(MSIHANDLE hinst, const char *filename, const char *text) 88 { 89 DWORD size; 90 HANDLE file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 91 ok(hinst, file != INVALID_HANDLE_VALUE, "CreateFile failed, error %u\n", GetLastError()); 92 93 SetFilePointer(file, 0, NULL, FILE_END); 94 WriteFile(file, text, strlen(text), &size, NULL); 95 CloseHandle(file); 96 } 97 98 UINT WINAPI da_immediate(MSIHANDLE hinst) 99 { 100 char prop[300]; 101 DWORD len = sizeof(prop); 102 103 MsiGetPropertyA(hinst, "TESTPATH", prop, &len); 104 105 append_file(hinst, prop, "one"); 106 107 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_SCHEDULED), "shouldn't be scheduled\n"); 108 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_ROLLBACK), "shouldn't be rollback\n"); 109 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_COMMIT), "shouldn't be commit\n"); 110 111 return ERROR_SUCCESS; 112 } 113 114 UINT WINAPI da_deferred(MSIHANDLE hinst) 115 { 116 char prop[300]; 117 DWORD len = sizeof(prop); 118 LANGID lang; 119 UINT r; 120 121 /* Test that we were in fact deferred */ 122 r = MsiGetPropertyA(hinst, "CustomActionData", prop, &len); 123 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r); 124 ok(hinst, prop[0], "CustomActionData was empty\n"); 125 126 append_file(hinst, prop, "two"); 127 128 /* Test available properties */ 129 len = sizeof(prop); 130 r = MsiGetPropertyA(hinst, "ProductCode", prop, &len); 131 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r); 132 ok(hinst, prop[0], "got %s\n", prop); 133 134 len = sizeof(prop); 135 r = MsiGetPropertyA(hinst, "UserSID", prop, &len); 136 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r); 137 ok(hinst, prop[0], "got %s\n", prop); 138 139 len = sizeof(prop); 140 r = MsiGetPropertyA(hinst, "TESTPATH", prop, &len); 141 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r); 142 todo_wine_ok(hinst, !prop[0], "got %s\n", prop); 143 144 /* Test modes */ 145 ok(hinst, MsiGetMode(hinst, MSIRUNMODE_SCHEDULED), "should be scheduled\n"); 146 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_ROLLBACK), "shouldn't be rollback\n"); 147 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_COMMIT), "shouldn't be commit\n"); 148 149 lang = MsiGetLanguage(hinst); 150 ok(hinst, lang != ERROR_INVALID_HANDLE, "MsiGetLanguage failed\n"); 151 152 return ERROR_SUCCESS; 153 } 154