diff --git a/reactos/include/wine/msidefs.h b/reactos/include/wine/msidefs.h index 45d4f20969b..f266b32172c 100644 --- a/reactos/include/wine/msidefs.h +++ b/reactos/include/wine/msidefs.h @@ -103,6 +103,49 @@ enum msidbComponentAttributes msidbComponentAttributes64bit = 0x00000100 }; +/* + * Windows SDK braindamage alert + * + * PID_DICTIONARY and PID_CODEPAGE are defined by propidl.h too + * PID_SECURITY is defined in propidl.h with a different value! + * So these need to be undefined first. + */ +#ifdef PID_DICTIONARY +#undef PID_DICTIONARY +#endif + +#ifdef PID_CODEPAGE +#undef PID_CODEPAGE +#endif + +#ifdef PID_SECURITY +#undef PID_SECURITY +#endif + +#define PID_DICTIONARY 0 +#define PID_CODEPAGE 1 +#define PID_TITLE 2 +#define PID_SUBJECT 3 +#define PID_AUTHOR 4 +#define PID_KEYWORDS 5 +#define PID_COMMENTS 6 +#define PID_TEMPLATE 7 +#define PID_LASTAUTHOR 8 +#define PID_REVNUMBER 9 +#define PID_EDITTINE 10 +#define PID_LASTPRINTED 11 +#define PID_CREATE_DTM 12 +#define PID_LASTSAVE_DTM 13 +#define PID_PAGECOUNT 14 +#define PID_WORDCOUNT 15 +#define PID_CHARCOUNT 16 +#define PID_THUMBNAIL 17 +#define PID_APPNAME 18 +#define PID_SECURITY 19 +#define PID_MSIVERSION PID_PAGECOUNT +#define PID_MSISOURCE PID_WORDCOUNT +#define PID_MSIRESTRICT PID_CHARCOUNT + #ifdef __cplusplus } #endif diff --git a/reactos/lib/msi/Makefile.in b/reactos/lib/msi/Makefile.in index 14ad0ed4a12..85c1eee55e3 100644 --- a/reactos/lib/msi/Makefile.in +++ b/reactos/lib/msi/Makefile.in @@ -11,6 +11,7 @@ C_SRCS = \ appsearch.c \ create.c \ custom.c \ + database.c \ delete.c \ dialog.c \ distinct.c \ diff --git a/reactos/lib/msi/action.c b/reactos/lib/msi/action.c index aef211a0cb6..ae48e3bcf75 100644 --- a/reactos/lib/msi/action.c +++ b/reactos/lib/msi/action.c @@ -61,7 +61,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); */ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran); static UINT ACTION_ProcessUISequence(MSIPACKAGE *package); -static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq); +static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI); static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, LPWSTR *FilePath); @@ -508,8 +508,8 @@ int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path) memset(&package->files[index],0,sizeof(MSIFILE)); - package->files[index].File = dupstrW(name); - package->files[index].TargetPath = dupstrW(path); + package->files[index].File = strdupW(name); + package->files[index].TargetPath = strdupW(path); package->files[index].Temporary = TRUE; TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File)); @@ -677,7 +677,7 @@ static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * recor package->ActionFormat = load_dynamic_stringW(row,3); HeapFree(GetProcessHeap(),0,package->LastAction); - package->LastAction = dupstrW(action); + package->LastAction = strdupW(action); msiobj_release(&row->hdr); MSI_ViewClose(view); @@ -864,6 +864,7 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, DWORD sz; WCHAR buffer[10]; UINT rc; + BOOL ui = FALSE; static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0}; static const WCHAR szAction[] = {'A','C','T','I','O','N',0}; static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0}; @@ -875,8 +876,8 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, { LPWSTR p, check, path; - package->PackagePath = dupstrW(szPackagePath); - path = dupstrW(szPackagePath); + package->PackagePath = strdupW(szPackagePath); + path = strdupW(szPackagePath); p = strrchrW(path,'\\'); if (p) { @@ -921,7 +922,7 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, while (*ptr == ' ') ptr++; len = ptr2-ptr; prop = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR)); - strncpyW(prop,ptr,len); + memcpy(prop,ptr,len*sizeof(WCHAR)); prop[len]=0; ptr2++; @@ -941,7 +942,7 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, len -= 2; } val = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR)); - strncpyW(val,ptr2,len); + memcpy(val,ptr2,len*sizeof(WCHAR)); val[len] = 0; if (strlenW(prop) > 0) @@ -963,6 +964,7 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED) { rc = ACTION_ProcessUISequence(package); + ui = TRUE; if (rc == ERROR_SUCCESS) rc = ACTION_ProcessExecSequence(package,TRUE); } @@ -980,13 +982,13 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, /* process the ending type action */ if (rc == ERROR_SUCCESS) - ACTION_PerformActionSequence(package,-1); + ACTION_PerformActionSequence(package,-1,ui); else if (rc == ERROR_INSTALL_USEREXIT) - ACTION_PerformActionSequence(package,-2); + ACTION_PerformActionSequence(package,-2,ui); else if (rc == ERROR_FUNCTION_FAILED) - ACTION_PerformActionSequence(package,-3); + ACTION_PerformActionSequence(package,-3,ui); else if (rc == ERROR_INSTALL_SUSPEND) - ACTION_PerformActionSequence(package,-4); + ACTION_PerformActionSequence(package,-4,ui); /* finish up running custom actions */ ACTION_FinishCustomActions(package); @@ -994,7 +996,7 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, return rc; } -static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq) +static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI) { MSIQUERY * view; UINT rc; @@ -1007,7 +1009,16 @@ static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq) 'S','e','q','u','e','n','c','e',' ', 'W','H','E','R','E',' ', 'S','e','q','u','e','n','c','e',' ', '=',' ','%','i',0}; - rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq); + static const WCHAR UISeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e', + ' ', 'W','H','E','R','E',' ', 'S','e','q','u','e','n','c','e', + ' ', '=',' ','%','i',0}; + + if (UI) + rc = MSI_OpenQuery(package->db, &view, UISeqQuery, seq); + else + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq); if (rc == ERROR_SUCCESS) { @@ -1058,7 +1069,10 @@ static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq) goto end; } - rc = ACTION_PerformAction(package,buffer); + if (UI) + rc = ACTION_PerformUIAction(package,buffer); + else + rc = ACTION_PerformAction(package,buffer); msiobj_release(&row->hdr); end: MSI_ViewClose(view); @@ -1921,7 +1935,7 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) memset(&package->folders[index],0,sizeof(MSIFOLDER)); - package->folders[index].Directory = dupstrW(dir); + package->folders[index].Directory = strdupW(dir); rc = MSI_OpenQuery(package->db, &view, Query, dir); if (rc != ERROR_SUCCESS) @@ -1980,13 +1994,13 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) { TRACE(" TargetDefault = %s\n",debugstr_w(targetdir)); HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault); - package->folders[index].TargetDefault = dupstrW(targetdir); + package->folders[index].TargetDefault = strdupW(targetdir); } if (srcdir) - package->folders[index].SourceDefault = dupstrW(srcdir); + package->folders[index].SourceDefault = strdupW(srcdir); else if (targetdir) - package->folders[index].SourceDefault = dupstrW(targetdir); + package->folders[index].SourceDefault = strdupW(targetdir); HeapFree(GetProcessHeap(), 0, ptargetdir); parent = load_dynamic_stringW(row,2); @@ -2084,13 +2098,13 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, if (!source && package->folders[i].ResolvedTarget) { - path = dupstrW(package->folders[i].ResolvedTarget); + path = strdupW(package->folders[i].ResolvedTarget); TRACE(" already resolved to %s\n",debugstr_w(path)); return path; } else if (source && package->folders[i].ResolvedSource) { - path = dupstrW(package->folders[i].ResolvedSource); + path = strdupW(package->folders[i].ResolvedSource); return path; } else if (!source && package->folders[i].Property) @@ -2114,7 +2128,7 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, { TRACE(" TargetDefault = %s\n",debugstr_w(package->folders[i].TargetDefault)); path = build_directory_name(3, p, package->folders[i].TargetDefault, NULL); - package->folders[i].ResolvedTarget = dupstrW(path); + package->folders[i].ResolvedTarget = strdupW(path); TRACE(" resolved into %s\n",debugstr_w(path)); if (set_prop) MSI_SetPropertyW(package,name,path); @@ -2122,7 +2136,7 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, else { path = build_directory_name(3, p, package->folders[i].SourceDefault, NULL); - package->folders[i].ResolvedSource = dupstrW(path); + package->folders[i].ResolvedSource = strdupW(path); } HeapFree(GetProcessHeap(),0,p); } @@ -3119,7 +3133,7 @@ inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key, { if (package->files[index].State >= 2) { - *file_source = dupstrW(package->files[index].TargetPath); + *file_source = strdupW(package->files[index].TargetPath); return ERROR_SUCCESS; } else @@ -3231,7 +3245,7 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) if (MSI_RecordIsNull(row,5)) { LPWSTR p; - dest_path = dupstrW(file_source); + dest_path = strdupW(file_source); p = strrchrW(dest_path,'\\'); if (p) *p=0; @@ -3523,7 +3537,8 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package) value_data = parse_value(package, value, &type, &size); else { - value_data = NULL; + static const WCHAR szEmpty[] = {0}; + value_data = (LPSTR)strdupW(szEmpty); size = 0; type = REG_SZ; } @@ -3759,7 +3774,7 @@ static LPWSTR resolve_keypath( MSIPACKAGE* package, INT if (j>=0) { - LPWSTR p = dupstrW(package->files[j].TargetPath); + LPWSTR p = strdupW(package->files[j].TargetPath); return p; } } @@ -4005,6 +4020,61 @@ end: return rc; } +typedef struct { + CLSID clsid; + LPWSTR source; + + LPWSTR path; + ITypeLib *ptLib; +} typelib_struct; + +BOOL CALLBACK Typelib_EnumResNameProc( HMODULE hModule, LPCWSTR lpszType, + LPWSTR lpszName, LONG_PTR lParam) +{ + TLIBATTR *attr; + typelib_struct *tl_struct = (typelib_struct*) lParam; + static const WCHAR fmt[] = {'%','s','\\','%','i',0}; + int sz; + HRESULT res; + + if (!IS_INTRESOURCE(lpszName)) + { + ERR("Not Int Resource Name %s\n",debugstr_w(lpszName)); + return TRUE; + } + + sz = strlenW(tl_struct->source)+4; + sz *= sizeof(WCHAR); + + tl_struct->path = HeapAlloc(GetProcessHeap(),0,sz); + sprintfW(tl_struct->path,fmt,tl_struct->source, lpszName); + + TRACE("trying %s\n", debugstr_w(tl_struct->path)); + res = LoadTypeLib(tl_struct->path,&tl_struct->ptLib); + if (!SUCCEEDED(res)) + { + HeapFree(GetProcessHeap(),0,tl_struct->path); + tl_struct->path = NULL; + + return TRUE; + } + + ITypeLib_GetLibAttr(tl_struct->ptLib, &attr); + if (IsEqualGUID(&(tl_struct->clsid),&(attr->guid))) + { + ITypeLib_ReleaseTLibAttr(tl_struct->ptLib, attr); + return FALSE; + } + + HeapFree(GetProcessHeap(),0,tl_struct->path); + tl_struct->path = NULL; + + ITypeLib_ReleaseTLibAttr(tl_struct->ptLib, attr); + ITypeLib_Release(tl_struct->ptLib); + + return TRUE; +} + static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package) { /* @@ -4019,8 +4089,6 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package) static const WCHAR Query[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 'T','y','p','e','L','i','b',0}; - ITypeLib *ptLib; - HRESULT res; if (!package) return ERROR_INVALID_HANDLE; @@ -4042,6 +4110,10 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package) WCHAR component[0x100]; DWORD sz; INT index; + LPWSTR guid; + typelib_struct tl_struct; + HMODULE module; + static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0}; rc = MSI_ViewFetch(view,&row); if (rc != ERROR_SUCCESS) @@ -4082,46 +4154,59 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package) continue; } - res = LoadTypeLib(package->files[index].TargetPath,&ptLib); - if (SUCCEEDED(res)) + guid = load_dynamic_stringW(row,1); + module = LoadLibraryExW(package->files[index].TargetPath, NULL, + LOAD_LIBRARY_AS_DATAFILE); + if (module != NULL) { - LPWSTR help; - WCHAR helpid[0x100]; + CLSIDFromString(guid, &tl_struct.clsid); + tl_struct.source = strdupW(package->files[index].TargetPath); + tl_struct.path = NULL; - sz = 0x100; - MSI_RecordGetStringW(row,6,helpid,&sz); + EnumResourceNamesW(module, szTYPELIB, Typelib_EnumResNameProc, + (LONG_PTR)&tl_struct); - help = resolve_folder(package,helpid,FALSE,FALSE,NULL); - res = RegisterTypeLib(ptLib,package->files[index].TargetPath,help); - HeapFree(GetProcessHeap(),0,help); - - if (!SUCCEEDED(res)) - ERR("Failed to register type library %s\n", - debugstr_w(package->files[index].TargetPath)); - else + if (tl_struct.path != NULL) { - /* Yes the row has more fields than I need, but #1 is - correct and the only one I need. Why make a new row? */ + LPWSTR help; + WCHAR helpid[0x100]; + HRESULT res; - ui_actiondata(package,szRegisterTypeLibraries,row); + sz = 0x100; + MSI_RecordGetStringW(row,6,helpid,&sz); + + help = resolve_folder(package,helpid,FALSE,FALSE,NULL); + res = RegisterTypeLib(tl_struct.ptLib,tl_struct.path,help); + HeapFree(GetProcessHeap(),0,help); + + if (!SUCCEEDED(res)) + ERR("Failed to register type library %s\n", + debugstr_w(tl_struct.path)); + else + { + ui_actiondata(package,szRegisterTypeLibraries,row); - TRACE("Registered %s\n", - debugstr_w(package->files[index].TargetPath)); - } + TRACE("Registered %s\n", debugstr_w(tl_struct.path)); + } - if (ptLib) - ITypeLib_Release(ptLib); + ITypeLib_Release(tl_struct.ptLib); + HeapFree(GetProcessHeap(),0,tl_struct.path); + } + else + ERR("Failed to load type library %s\n", + debugstr_w(tl_struct.source)); + + FreeLibrary(module); + HeapFree(GetProcessHeap(),0,tl_struct.source); } else - ERR("Failed to load type library %s\n", - debugstr_w(package->files[index].TargetPath)); - + ERR("Could not load file! %s\n", + debugstr_w(package->files[index].TargetPath)); msiobj_release(&row->hdr); } MSI_ViewClose(view); msiobj_release(&view->hdr); return rc; - } static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) @@ -4362,7 +4447,7 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package) HeapFree(GetProcessHeap(),0,argument); size += (strlenW(package->files[index].TargetPath))*sizeof(WCHAR); - argument = (LPWSTR)HeapAlloc(GetProcessHeap(),0,size+sizeof(WCHAR)); + argument = HeapAlloc(GetProcessHeap(),0,size+sizeof(WCHAR)); strcpyW(argument,package->files[index].TargetPath); if (deformated) { @@ -4882,7 +4967,7 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package) { LPWSTR keypath; FIXME("poorly handled shortcut format, advertised shortcut\n"); - keypath = dupstrW(package->components[index].FullKeypath); + keypath = strdupW(package->components[index].FullKeypath); IShellLinkW_SetPath(sl,keypath); HeapFree(GetProcessHeap(),0,keypath); } diff --git a/reactos/lib/msi/action.h b/reactos/lib/msi/action.h index 1ac1430c32e..af718bee464 100644 --- a/reactos/lib/msi/action.h +++ b/reactos/lib/msi/action.h @@ -116,39 +116,3 @@ int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component ); int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature ); int get_loaded_file(MSIPACKAGE* package, LPCWSTR file); int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path); - - - -inline static char *strdupWtoA( const WCHAR *str ) -{ - char *ret = NULL; - if (str) - { - DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL -); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) - WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); - } - return ret; -} - -inline static WCHAR *strdupAtoW( const char *str ) -{ - WCHAR *ret = NULL; - if (str) - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); - } - return ret; -} - -inline static LPWSTR dupstrW(LPCWSTR src) -{ - LPWSTR dest; - if (!src) return NULL; - dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR)); - strcpyW(dest, src); - return dest; -} diff --git a/reactos/lib/msi/appsearch.c b/reactos/lib/msi/appsearch.c index 8918d7f4588..ca9fc65a305 100644 --- a/reactos/lib/msi/appsearch.c +++ b/reactos/lib/msi/appsearch.c @@ -406,7 +406,7 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst, /* Sets *matches to whether the file (whose path is filePath) matches the * versions set in sig. * Return ERROR_SUCCESS in case of success (whether or not the file matches), - * something else if a install-halting error occurs. + * something else if an install-halting error occurs. */ static UINT ACTION_FileVersionMatches(MSISIGNATURE *sig, LPCWSTR filePath, BOOL *matches) @@ -481,7 +481,7 @@ static UINT ACTION_FileVersionMatches(MSISIGNATURE *sig, LPCWSTR filePath, * fullFilePath is assumed to be the full path of the file specified in * findData, which may be necessary to compare the version. * Return ERROR_SUCCESS in case of success (whether or not the file matches), - * something else if a install-halting error occurs. + * something else if an install-halting error occurs. */ static UINT ACTION_FileMatchesSig(MSISIGNATURE *sig, LPWIN32_FIND_DATAW findData, LPCWSTR fullFilePath, BOOL *matches) @@ -672,8 +672,8 @@ static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig, pathWithDrive[0] = 'A' + i; if (GetDriveTypeW(pathWithDrive) == DRIVE_FIXED) { - strncpyW(pathWithDrive + 3, expanded, - sizeof(pathWithDrive) / sizeof(pathWithDrive[0]) - 3); + lstrcpynW(pathWithDrive + 3, expanded, + sizeof(pathWithDrive) / sizeof(pathWithDrive[0]) - 3); if (sig->File) rc = ACTION_RecurseSearchDirectory(package, &found, sig, pathWithDrive, depth); diff --git a/reactos/lib/msi/cond.tab.c b/reactos/lib/msi/cond.tab.c index 31fa5f736a6..56af92f32e5 100644 --- a/reactos/lib/msi/cond.tab.c +++ b/reactos/lib/msi/cond.tab.c @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 1.875b. */ +/* A Bison parser, made by GNU Bison 1.875c. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. @@ -253,18 +253,25 @@ typedef union YYSTYPE { #if ! defined (yyoverflow) || YYERROR_VERBOSE +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + /* The parser invokes alloca or malloc; define the necessary symbols. */ -# if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# endif # else -# ifndef YYSTACK_USE_ALLOCA -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca -# else -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# endif +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca # endif # endif # endif @@ -277,15 +284,15 @@ typedef union YYSTYPE { # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ - || (YYSTYPE_IS_TRIVIAL))) + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc @@ -306,7 +313,7 @@ union yyalloc /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY -# if 1 < __GNUC__ +# if defined (__GNUC__) && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else @@ -454,14 +461,14 @@ static const unsigned short yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "COND_SPACE", "COND_EOF", "COND_OR", - "COND_AND", "COND_NOT", "COND_LT", "COND_GT", "COND_EQ", "COND_LPAR", - "COND_RPAR", "COND_TILDA", "COND_PERCENT", "COND_DOLLARS", - "COND_QUESTION", "COND_AMPER", "COND_EXCLAM", "COND_IDENT", - "COND_NUMBER", "COND_LITER", "COND_ERROR", "$accept", "condition", - "expression", "boolean_term", "boolean_factor", "term", "comp_op_i", - "comp_op_s", "comp_op_m1", "comp_op_m2", "value_i", "value_s", - "literal", "symbol_i", "symbol_s", "identifier", "integer", 0 + "$end", "error", "$undefined", "COND_SPACE", "COND_EOF", "COND_OR", + "COND_AND", "COND_NOT", "COND_LT", "COND_GT", "COND_EQ", "COND_LPAR", + "COND_RPAR", "COND_TILDA", "COND_PERCENT", "COND_DOLLARS", + "COND_QUESTION", "COND_AMPER", "COND_EXCLAM", "COND_IDENT", + "COND_NUMBER", "COND_LITER", "COND_ERROR", "$accept", "condition", + "expression", "boolean_term", "boolean_factor", "term", "comp_op_i", + "comp_op_s", "comp_op_m1", "comp_op_m2", "value_i", "value_s", "literal", + "symbol_i", "symbol_s", "identifier", "integer", 0 }; #endif @@ -624,7 +631,7 @@ static const unsigned char yystos[] = #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 +#define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily @@ -659,11 +666,11 @@ while (0) are run). */ #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - Current.first_line = Rhs[1].first_line; \ - Current.first_column = Rhs[1].first_column; \ - Current.last_line = Rhs[N].last_line; \ - Current.last_column = Rhs[N].last_column; +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + ((Current).first_line = (Rhs)[1].first_line, \ + (Current).first_column = (Rhs)[1].first_column, \ + (Current).last_line = (Rhs)[N].last_line, \ + (Current).last_column = (Rhs)[N].last_column) #endif /* YYLEX -- calling `yylex' with the right arguments. */ @@ -707,7 +714,7 @@ do { \ /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (cinluded). | +| TOP (included). | `------------------------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) @@ -786,7 +793,7 @@ int yydebug; SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ -#if YYMAXDEPTH == 0 +#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 # undef YYMAXDEPTH #endif @@ -1714,8 +1721,8 @@ yyreduce: } -/* Line 999 of yacc.c. */ -#line 1719 "cond.tab.c" +/* Line 1000 of yacc.c. */ +#line 1726 "cond.tab.c" yyvsp -= yylen; yyssp -= yylen; @@ -1818,25 +1825,27 @@ yyerrlab: /* If just tried and failed to reuse lookahead token after an error, discard it. */ - /* Return failure if at end of input. */ - if (yychar == YYEOF) + if (yychar <= YYEOF) { - /* Pop the error token. */ - YYPOPSTACK; - /* Pop the rest of the stack. */ - while (yyss < yyssp) - { - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[*yyssp], yyvsp); - YYPOPSTACK; - } - YYABORT; + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + } } + else + { + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); + yychar = YYEMPTY; - YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); - yydestruct (yytoken, &yylval); - yychar = YYEMPTY; - + } } /* Else will try to reuse lookahead token after shifting the error @@ -1844,9 +1853,27 @@ yyerrlab: goto yyerrlab1; -/*----------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action. | -`----------------------------------------------------*/ +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; +#endif + + yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ @@ -1870,9 +1897,8 @@ yyerrlab1: YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); yydestruct (yystos[yystate], yyvsp); - yyvsp--; - yystate = *--yyssp; - + YYPOPSTACK; + yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } @@ -2123,7 +2149,7 @@ static LPWSTR COND_GetString( struct cond_str *str ) ret = HeapAlloc( GetProcessHeap(), 0, (str->len+1) * sizeof (WCHAR) ); if( ret ) { - strncpyW( ret, str->data, str->len ); + memcpy( ret, str->data, str->len * sizeof(WCHAR)); ret[str->len]=0; } TRACE("Got identifier %s\n",debugstr_w(ret)); diff --git a/reactos/lib/msi/cond.tab.h b/reactos/lib/msi/cond.tab.h index 4870215530d..f37273b3993 100644 --- a/reactos/lib/msi/cond.tab.h +++ b/reactos/lib/msi/cond.tab.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 1.875b. */ +/* A Bison parser, made by GNU Bison 1.875c. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. @@ -86,7 +86,7 @@ typedef union YYSTYPE { comp_m1 fn_comp_m1; comp_m2 fn_comp_m2; } YYSTYPE; -/* Line 1252 of yacc.c. */ +/* Line 1275 of yacc.c. */ #line 91 "cond.tab.h" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 diff --git a/reactos/lib/msi/cond.y b/reactos/lib/msi/cond.y index 2221fb156ba..8be1d2e6c04 100644 --- a/reactos/lib/msi/cond.y +++ b/reactos/lib/msi/cond.y @@ -701,7 +701,7 @@ static LPWSTR COND_GetString( struct cond_str *str ) ret = HeapAlloc( GetProcessHeap(), 0, (str->len+1) * sizeof (WCHAR) ); if( ret ) { - strncpyW( ret, str->data, str->len ); + memcpy( ret, str->data, str->len * sizeof(WCHAR)); ret[str->len]=0; } TRACE("Got identifier %s\n",debugstr_w(ret)); diff --git a/reactos/lib/msi/custom.c b/reactos/lib/msi/custom.c index 3f5686a7ea2..b9e70cf9d6e 100644 --- a/reactos/lib/msi/custom.c +++ b/reactos/lib/msi/custom.c @@ -145,7 +145,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) else newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR)); - newbuf[count] = dupstrW(action); + newbuf[count] = strdupW(action); package->CommitAction = newbuf; } else @@ -160,7 +160,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) else newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR)); - newbuf[count] = dupstrW(action); + newbuf[count] = strdupW(action); package->DeferredAction = newbuf; } @@ -326,7 +326,7 @@ static void file_running_action(MSIPACKAGE* package, HANDLE Handle, newbuf[count].handle = Handle; newbuf[count].process = process; - newbuf[count].name = dupstrW(name); + newbuf[count].name = strdupW(name); package->RunningAction = newbuf; } @@ -508,8 +508,8 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) ); msiobj_addref( &package->hdr ); info->package = package; - info->target = dupstrW(target); - info->source = dupstrW(tmp_file); + info->target = strdupW(target); + info->source = strdupW(tmp_file); ThreadHandle = CreateThread(NULL,0,DllThread,(LPVOID)info,0,&ThreadId); @@ -542,7 +542,7 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, if (deformated) len += strlenW(deformated); - cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); + cmd = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); strcpyW(cmd,tmp_file); if (deformated) @@ -595,7 +595,7 @@ static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, len += strlenW(deformated); len += 2; - cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR)); + cmd = HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR)); strcpyW(cmd, package->files[index].TargetPath); if (deformated) @@ -692,7 +692,7 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, if (deformated) len += strlenW(deformated); - cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); + cmd = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); strcpyW(cmd,prop); if (deformated) diff --git a/reactos/lib/msi/database.c b/reactos/lib/msi/database.c new file mode 100644 index 00000000000..6d7bd1b9e5b --- /dev/null +++ b/reactos/lib/msi/database.c @@ -0,0 +1,345 @@ +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define COBJMACROS +#define NONAMELESSUNION + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winnls.h" +#include "wine/debug.h" +#include "msi.h" +#include "msiquery.h" +#include "msipriv.h" +#include "objidl.h" +#include "objbase.h" + +#include "initguid.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + +/* + * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR, + * which is a problem because LPCTSTR isn't defined when compiling wine. + * To work around this problem, we need to define LPCTSTR as LPCWSTR here, + * and make sure to only use it in W functions. + */ +#define LPCTSTR LPCWSTR + +DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); + +/* + * .MSI file format + * + * An .msi file is a structured storage file. + * It contains a number of streams. + * A stream for each table in the database. + * Two streams for the string table in the database. + * Any binary data in a table is a reference to a stream. + */ + +VOID MSI_CloseDatabase( MSIOBJECTHDR *arg ) +{ + MSIDATABASE *db = (MSIDATABASE *) arg; + DWORD r; + + free_cached_tables( db ); + r = IStorage_Release( db->storage ); + if( r ) + ERR("database reference count was not zero (%ld)\n", r); +} + +UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb) +{ + IStorage *stg = NULL; + HRESULT r; + MSIDATABASE *db = NULL; + UINT ret = ERROR_FUNCTION_FAILED; + LPWSTR szMode; + STATSTG stat; + + TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) ); + + if( !pdb ) + return ERROR_INVALID_PARAMETER; + + szMode = (LPWSTR) szPersist; + if( HIWORD( szPersist ) ) + { + /* UINT len = lstrlenW( szPerist ) + 1; */ + FIXME("don't support persist files yet\b"); + return ERROR_INVALID_PARAMETER; + /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */ + } + else if( szPersist == MSIDBOPEN_READONLY ) + { + r = StgOpenStorage( szDBPath, NULL, + STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg); + } + else if( szPersist == MSIDBOPEN_CREATE ) + { + r = StgCreateDocfile( szDBPath, + STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg); + if( r == ERROR_SUCCESS ) + { + IStorage_SetClass( stg, &CLSID_MsiDatabase ); + r = init_string_table( stg ); + } + } + else if( szPersist == MSIDBOPEN_TRANSACT ) + { + r = StgOpenStorage( szDBPath, NULL, + STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg); + } + else + { + ERR("unknown flag %p\n",szPersist); + return ERROR_INVALID_PARAMETER; + } + + if( FAILED( r ) ) + { + FIXME("open failed r = %08lx!\n",r); + return ERROR_FUNCTION_FAILED; + } + + r = IStorage_Stat( stg, &stat, STATFLAG_NONAME ); + if( FAILED( r ) ) + { + FIXME("Failed to stat storage\n"); + goto end; + } + + if( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) ) + { + ERR("storage GUID is not a MSI database GUID %s\n", + debugstr_guid(&stat.clsid) ); + goto end; + } + + + db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE), + MSI_CloseDatabase ); + if( !db ) + { + FIXME("Failed to allocate a handle\n"); + goto end; + } + + if( TRACE_ON( msi ) ) + enum_stream_names( stg ); + + db->storage = stg; + db->mode = szMode; + + ret = load_string_table( db ); + if( ret != ERROR_SUCCESS ) + goto end; + + msiobj_addref( &db->hdr ); + IStorage_AddRef( stg ); + *pdb = db; + +end: + if( db ) + msiobj_release( &db->hdr ); + if( stg ) + IStorage_Release( stg ); + + return ret; +} + +UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB) +{ + MSIDATABASE *db; + UINT ret; + + TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB); + + ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db ); + if( ret == ERROR_SUCCESS ) + { + *phDB = alloc_msihandle( &db->hdr ); + msiobj_release( &db->hdr ); + } + + return ret; +} + +UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB) +{ + HRESULT r = ERROR_FUNCTION_FAILED; + LPWSTR szwDBPath = NULL, szwPersist = NULL; + + TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB); + + if( szDBPath ) + { + szwDBPath = strdupAtoW( szDBPath ); + if( !szwDBPath ) + goto end; + } + + if( HIWORD(szPersist) ) + { + szwPersist = strdupAtoW( szPersist ); + if( !szwPersist ) + goto end; + } + else + szwPersist = (LPWSTR) szPersist; + + r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB ); + +end: + HeapFree( GetProcessHeap(), 0, szwPersist ); + HeapFree( GetProcessHeap(), 0, szwDBPath ); + + return r; +} + +UINT MSI_DatabaseImport( MSIDATABASE *db, LPCWSTR folder, LPCWSTR file ) +{ + FIXME("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) ); + + if( folder == NULL || file == NULL ) + return ERROR_INVALID_PARAMETER; + + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, LPCWSTR szFolder, LPCWSTR szFilename) +{ + MSIDATABASE *db; + UINT r; + + TRACE("%lx %s %s\n",handle,debugstr_w(szFolder), debugstr_w(szFilename)); + + db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); + if( !db ) + return ERROR_INVALID_HANDLE; + r = MSI_DatabaseImport( db, szFolder, szFilename ); + msiobj_release( &db->hdr ); + return r; +} + +UINT WINAPI MsiDatabaseImportA( MSIHANDLE handle, + LPCSTR szFolder, LPCSTR szFilename ) +{ + LPWSTR path = NULL, file = NULL; + UINT r = ERROR_OUTOFMEMORY; + + TRACE("%lx %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename)); + + if( szFolder ) + { + path = strdupAtoW( szFolder ); + if( !path ) + goto end; + } + + if( szFilename ) + { + file = strdupAtoW( szFilename ); + if( !file ) + goto end; + } + + r = MsiDatabaseImportW( handle, path, file ); + +end: + HeapFree( GetProcessHeap(), 0, path ); + HeapFree( GetProcessHeap(), 0, file ); + + return r; +} + +UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table, + LPCWSTR folder, LPCWSTR file ) +{ + FIXME("%p %s %s %s\n", db, debugstr_w(table), + debugstr_w(folder), debugstr_w(file) ); + + if( folder == NULL || file == NULL ) + return ERROR_INVALID_PARAMETER; + + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiDatabaseExportW( MSIHANDLE handle, LPCWSTR szTable, + LPCWSTR szFolder, LPCWSTR szFilename ) +{ + MSIDATABASE *db; + UINT r; + + TRACE("%lx %s %s %s\n", handle, debugstr_w(szTable), + debugstr_w(szFolder), debugstr_w(szFilename)); + + db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); + if( !db ) + return ERROR_INVALID_HANDLE; + r = MSI_DatabaseExport( db, szTable, szFolder, szFilename ); + msiobj_release( &db->hdr ); + return r; +} + +UINT WINAPI MsiDatabaseExportA( MSIHANDLE handle, LPCSTR szTable, + LPCSTR szFolder, LPCSTR szFilename ) +{ + LPWSTR path = NULL, file = NULL, table = NULL; + UINT r = ERROR_OUTOFMEMORY; + + TRACE("%lx %s %s %s\n", handle, debugstr_a(szTable), + debugstr_a(szFolder), debugstr_a(szFilename)); + + if( szTable ) + { + table = strdupAtoW( szTable ); + if( !table ) + goto end; + } + + if( szFolder ) + { + path = strdupAtoW( szFolder ); + if( !path ) + goto end; + } + + if( szFilename ) + { + file = strdupAtoW( szFilename ); + if( !file ) + goto end; + } + + r = MsiDatabaseImportW( handle, path, file ); + +end: + HeapFree( GetProcessHeap(), 0, table ); + HeapFree( GetProcessHeap(), 0, path ); + HeapFree( GetProcessHeap(), 0, file ); + + return r; +} diff --git a/reactos/lib/msi/dialog.c b/reactos/lib/msi/dialog.c index ccd01a43c1c..19ab2d5d402 100644 --- a/reactos/lib/msi/dialog.c +++ b/reactos/lib/msi/dialog.c @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define COBJMACROS + #include #include "windef.h" @@ -28,6 +30,8 @@ #include "msi.h" #include "msipriv.h" #include "msidefs.h" +#include "ocidl.h" +#include "olectl.h" #include "wine/debug.h" #include "wine/unicode.h" @@ -55,6 +59,7 @@ struct msi_control_tag HWND hwnd; msi_handler handler; LPWSTR property; + IPicture *pic; WCHAR name[1]; }; @@ -131,7 +136,7 @@ static LPWSTR msi_dialog_get_style( LPCWSTR *text ) ret = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); if( !ret ) return ret; - strncpyW( ret, p, len ); + memcpy( ret, p, len*sizeof(WCHAR) ); ret[len-1] = 0; return ret; } @@ -226,17 +231,16 @@ static UINT msi_dialog_build_font_list( msi_dialog *dialog ) return r; } -static msi_control *msi_dialog_add_control( msi_dialog *dialog, - MSIRECORD *rec, LPCWSTR szCls, DWORD style ) +static msi_control *msi_dialog_create_window( msi_dialog *dialog, + MSIRECORD *rec, LPCWSTR szCls, LPCWSTR name, LPCWSTR text, + DWORD style, HWND parent ) { - DWORD x, y, width, height, attributes; - LPCWSTR text, name; + DWORD x, y, width, height; LPWSTR font = NULL, title = NULL; - msi_control *control = NULL; + msi_control *control; style |= WS_CHILD | WS_GROUP; - name = MSI_RecordGetString( rec, 2 ); control = HeapAlloc( GetProcessHeap(), 0, sizeof *control + strlenW(name)*sizeof(WCHAR) ); strcpyW( control->name, name ); @@ -244,39 +248,57 @@ static msi_control *msi_dialog_add_control( msi_dialog *dialog, dialog->control_list = control; control->handler = NULL; control->property = NULL; + control->pic = NULL; x = MSI_RecordGetInteger( rec, 4 ); y = MSI_RecordGetInteger( rec, 5 ); width = MSI_RecordGetInteger( rec, 6 ); height = MSI_RecordGetInteger( rec, 7 ); - attributes = MSI_RecordGetInteger( rec, 8 ); - text = MSI_RecordGetString( rec, 10 ); - - TRACE("Dialog %s control %s\n", debugstr_w(dialog->name), debugstr_w(text)); x = msi_dialog_scale_unit( dialog, x ); y = msi_dialog_scale_unit( dialog, y ); width = msi_dialog_scale_unit( dialog, width ); height = msi_dialog_scale_unit( dialog, height ); - if( attributes & 1 ) - style |= WS_VISIBLE; - if( ~attributes & 2 ) - style |= WS_DISABLED; if( text ) { font = msi_dialog_get_style( &text ); deformat_string( dialog->package, text, &title ); } + control->hwnd = CreateWindowW( szCls, title, style, - x, y, width, height, dialog->hwnd, NULL, NULL, NULL ); + x, y, width, height, parent, NULL, NULL, NULL ); + + TRACE("Dialog %s control %s hwnd %p\n", + debugstr_w(dialog->name), debugstr_w(text), control->hwnd ); + msi_dialog_set_font( dialog, control->hwnd, font ? font : dialog->default_font ); + HeapFree( GetProcessHeap(), 0, font ); HeapFree( GetProcessHeap(), 0, title ); + return control; } +/* everything except radio buttons */ +static msi_control *msi_dialog_add_control( msi_dialog *dialog, + MSIRECORD *rec, LPCWSTR szCls, DWORD style ) +{ + DWORD attributes; + LPCWSTR text, name; + + name = MSI_RecordGetString( rec, 2 ); + attributes = MSI_RecordGetInteger( rec, 8 ); + text = MSI_RecordGetString( rec, 10 ); + if( attributes & 1 ) + style |= WS_VISIBLE; + if( ~attributes & 2 ) + style |= WS_DISABLED; + return msi_dialog_create_window( dialog, rec, szCls, name, text, + style, dialog->hwnd ); +} + static UINT msi_dialog_text_control( msi_dialog *dialog, MSIRECORD *rec ) { TRACE("%p %p\n", dialog, rec); @@ -309,7 +331,7 @@ static UINT msi_dialog_checkbox_control( msi_dialog *dialog, MSIRECORD *rec ) control->handler = msi_dialog_checkbox_handler; prop = MSI_RecordGetString( rec, 9 ); if( prop ) - control->property = dupstrW( prop ); + control->property = strdupW( prop ); msi_dialog_checkbox_sync_state( dialog, control ); return ERROR_SUCCESS; @@ -327,7 +349,7 @@ static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec ) { const static WCHAR szEdit[] = { 'E','D','I','T',0 }; - TRACE("%p %p\n", dialog, rec); + FIXME("%p %p\n", dialog, rec); msi_dialog_add_control( dialog, rec, szEdit, WS_BORDER | ES_MULTILINE | WS_VSCROLL | ES_READONLY | ES_AUTOVSCROLL ); @@ -335,12 +357,64 @@ static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec ) return ERROR_SUCCESS; } +static UINT msi_load_bitmap( MSIDATABASE *db, LPCWSTR name, IPicture **pic ) +{ + const static WCHAR query[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ','B','i','n','a','r','y',' ', + 'w','h','e','r','e',' ', + '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0 + }; + MSIQUERY *view = NULL; + MSIRECORD *rec = NULL; + IStream *stm = NULL; + UINT r; + + r = MSI_OpenQuery( db, &view, query, name ); + if( r != ERROR_SUCCESS ) + return r; + + MSI_ViewExecute( view, NULL ); + MSI_ViewFetch( view, &rec ); + MSI_ViewClose( view ); + msiobj_release( &view->hdr ); + + if( !rec ) + return ERROR_FUNCTION_FAILED; + + r = MSI_RecordGetIStream( rec, 2, &stm ); + msiobj_release( &rec->hdr ); + if( r != ERROR_SUCCESS ) + return r; + + r = OleLoadPicture( stm, 0, TRUE, &IID_IPicture, (LPVOID*) pic ); + IStream_Release( stm ); + if( FAILED( r ) ) + return ERROR_FUNCTION_FAILED; + + return ERROR_SUCCESS; +} + static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec ) { - TRACE("%p %p\n", dialog, rec); + IPicture *pic = NULL; + msi_control *control; + OLE_HANDLE hBitmap = 0; + LPCWSTR text; + UINT r; - msi_dialog_add_control( dialog, rec, szStatic, + control = msi_dialog_add_control( dialog, rec, szStatic, SS_BITMAP | SS_LEFT | SS_CENTERIMAGE ); + text = MSI_RecordGetString( rec, 10 ); + r = msi_load_bitmap( dialog->package->db, text, &pic ); + if( r == ERROR_SUCCESS ) + { + r = IPicture_get_Handle( pic, &hBitmap ); + if( SUCCEEDED( r ) ) + SendMessageW( control->hwnd, STM_SETIMAGE, IMAGE_BITMAP, hBitmap ); + control->pic = pic; + } + return ERROR_SUCCESS; } @@ -364,7 +438,7 @@ static UINT msi_dialog_edit_control( msi_dialog *dialog, MSIRECORD *rec ) control->handler = msi_dialog_edit_handler; prop = MSI_RecordGetString( rec, 9 ); if( prop ) - control->property = dupstrW( prop ); + control->property = strdupW( prop ); val = load_dynamic_property( dialog->package, control->property, NULL ); SetWindowTextW( control->hwnd, val ); HeapFree( GetProcessHeap(), 0, val ); @@ -377,63 +451,31 @@ static UINT msi_dialog_pathedit_control( msi_dialog *dialog, MSIRECORD *rec ) return msi_dialog_edit_control( dialog, rec ); } +/* radio buttons are a bit different from normal controls */ static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param ) { radio_button_group_descr *group = (radio_button_group_descr *)param; msi_dialog *dialog = group->dialog; msi_control *control; - LPCWSTR prop; - DWORD x, y, width, height, style; + LPCWSTR prop, text, name; + DWORD style; DWORD attributes = group->attributes; - LPCWSTR text, name; - LPWSTR font = NULL, title = NULL; style = WS_CHILD | BS_AUTORADIOBUTTON | BS_MULTILINE; name = MSI_RecordGetString( rec, 3 ); - control = HeapAlloc( GetProcessHeap(), 0, - sizeof *control + strlenW(name)*sizeof(WCHAR) ); - strcpyW( control->name, name ); - control->next = dialog->control_list; - dialog->control_list = control; - - x = MSI_RecordGetInteger( rec, 4 ); - y = MSI_RecordGetInteger( rec, 5 ); - width = MSI_RecordGetInteger( rec, 6 ); - height = MSI_RecordGetInteger( rec, 7 ); text = MSI_RecordGetString( rec, 8 ); - - x = msi_dialog_scale_unit( dialog, x ); - y = msi_dialog_scale_unit( dialog, y ); - width = msi_dialog_scale_unit( dialog, width ); - height = msi_dialog_scale_unit( dialog, height ); - if( attributes & 1 ) style |= WS_VISIBLE; if( ~attributes & 2 ) style |= WS_DISABLED; - if( text ) - { - font = msi_dialog_get_style( &text ); - deformat_string( dialog->package, text, &title ); - } - - control->hwnd = CreateWindowW( szButton, title, style, x, y, width, height, - group->parent->hwnd, NULL, NULL, NULL ); - - TRACE("Dialog %s control %s hwnd %p\n", debugstr_w(dialog->name), debugstr_w(text), control->hwnd); - - msi_dialog_set_font( dialog, control->hwnd, - font ? font : dialog->default_font ); - - HeapFree( GetProcessHeap(), 0, font ); - HeapFree( GetProcessHeap(), 0, title ); - + control = msi_dialog_create_window( dialog, rec, szButton, name, text, + style, group->parent->hwnd ); control->handler = msi_dialog_radiogroup_handler; prop = MSI_RecordGetString( rec, 1 ); if( prop ) - control->property = dupstrW( prop ); + control->property = strdupW( prop ); return ERROR_SUCCESS; } @@ -467,7 +509,7 @@ static UINT msi_dialog_radiogroup_control( msi_dialog *dialog, MSIRECORD *rec ) } if( prop ) - control->property = dupstrW( prop ); + control->property = strdupW( prop ); /* query the Radio Button table for all control in this group */ r = MSI_OpenQuery( package->db, &view, query, prop ); @@ -1078,6 +1120,8 @@ void msi_dialog_destroy( msi_dialog *dialog ) dialog->control_list = t->next; /* leave dialog->hwnd - destroying parent destroys child windows */ HeapFree( GetProcessHeap(), 0, t->property ); + if( t->pic ) + IPicture_Release( t->pic ); HeapFree( GetProcessHeap(), 0, t ); } diff --git a/reactos/lib/msi/format.c b/reactos/lib/msi/format.c index 7e5b6dc2574..d85fd27c58b 100644 --- a/reactos/lib/msi/format.c +++ b/reactos/lib/msi/format.c @@ -114,7 +114,7 @@ static LPWSTR deformat_file(MSIPACKAGE* package, LPCWSTR key, DWORD* sz) index = get_loaded_file(package,key); if (index >=0) { - value = dupstrW(package->files[index].TargetPath); + value = strdupW(package->files[index].TargetPath); *sz = (strlenW(value)) * sizeof(WCHAR); } @@ -137,7 +137,7 @@ static LPWSTR deformat_environment(MSIPACKAGE* package, LPCWSTR key, } else { - ERR("Unknown environment variable\n"); + ERR("Unknown environment variable %s\n", debugstr_w(key)); *chunk = 0; value = NULL; } @@ -252,7 +252,7 @@ static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining, *key = HeapAlloc(GetProcessHeap(),0,i*sizeof(WCHAR)); /* do not have the [] in the key */ i -= 1; - strncpyW(*key,&(*mark)[1],i); + memcpy(*key,&(*mark)[1],i*sizeof(WCHAR)); (*key)[i] = 0; TRACE("Found Key %s\n",debugstr_w(*key)); @@ -358,11 +358,12 @@ static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, value = deformat_index(record,key,&chunk); else { - chunk = (strlenW(key) + 2)*sizeof(WCHAR); + DWORD keylen = strlenW(key); + chunk = (keylen + 2)*sizeof(WCHAR); value = HeapAlloc(GetProcessHeap(),0,chunk); value[0] = '['; - memcpy(&value[1],key,strlenW(key)*sizeof(WCHAR)); - value[strlenW(key)+1] = ']'; + memcpy(&value[1],key,keylen*sizeof(WCHAR)); + value[1+keylen] = ']'; } } else diff --git a/reactos/lib/msi/msi.c b/reactos/lib/msi/msi.c index 7534f04f6d2..aabcd522e77 100644 --- a/reactos/lib/msi/msi.c +++ b/reactos/lib/msi/msi.c @@ -32,15 +32,10 @@ #include "msi.h" #include "msiquery.h" #include "msipriv.h" -#include "objidl.h" #include "wincrypt.h" -#include "wine/unicode.h" -#include "objbase.h" #include "winver.h" #include "winuser.h" -#include "initguid.h" - UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf); @@ -54,9 +49,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); */ #define LPCTSTR LPCWSTR -DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000, - 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); - /* the UI level */ INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC; HWND gUIhwnd = 0; @@ -67,198 +59,25 @@ LPVOID gUIContext = NULL; WCHAR gszLogFile[MAX_PATH]; HINSTANCE msi_hInstance; -/* - * .MSI file format - * - * A .msi file is a structured storage file. - * It should contain a number of streams. - */ - -VOID MSI_CloseDatabase( MSIOBJECTHDR *arg ) -{ - MSIDATABASE *db = (MSIDATABASE *) arg; - DWORD r; - - free_cached_tables( db ); - r = IStorage_Release( db->storage ); - if( r ) - ERR("database reference count was not zero (%ld)\n", r); -} - -UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb) -{ - IStorage *stg = NULL; - HRESULT r; - MSIDATABASE *db = NULL; - UINT ret = ERROR_FUNCTION_FAILED; - LPWSTR szMode; - STATSTG stat; - - TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) ); - - if( !pdb ) - return ERROR_INVALID_PARAMETER; - - szMode = (LPWSTR) szPersist; - if( HIWORD( szPersist ) ) - { - /* UINT len = lstrlenW( szPerist ) + 1; */ - FIXME("don't support persist files yet\b"); - return ERROR_INVALID_PARAMETER; - /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */ - } - else if( szPersist == MSIDBOPEN_READONLY ) - { - r = StgOpenStorage( szDBPath, NULL, - STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg); - } - else if( szPersist == MSIDBOPEN_CREATE ) - { - r = StgCreateDocfile( szDBPath, - STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg); - if( r == ERROR_SUCCESS ) - { - IStorage_SetClass( stg, &CLSID_MsiDatabase ); - r = init_string_table( stg ); - } - } - else if( szPersist == MSIDBOPEN_TRANSACT ) - { - r = StgOpenStorage( szDBPath, NULL, - STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg); - } - else - { - ERR("unknown flag %p\n",szPersist); - return ERROR_INVALID_PARAMETER; - } - - if( FAILED( r ) ) - { - FIXME("open failed r = %08lx!\n",r); - return ERROR_FUNCTION_FAILED; - } - - r = IStorage_Stat( stg, &stat, STATFLAG_NONAME ); - if( FAILED( r ) ) - { - FIXME("Failed to stat storage\n"); - goto end; - } - - if( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) ) - { - ERR("storage GUID is not a MSI database GUID %s\n", - debugstr_guid(&stat.clsid) ); - goto end; - } - - - db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE), - MSI_CloseDatabase ); - if( !db ) - { - FIXME("Failed to allocate a handle\n"); - goto end; - } - - if( TRACE_ON( msi ) ) - enum_stream_names( stg ); - - db->storage = stg; - db->mode = szMode; - - ret = load_string_table( db ); - if( ret != ERROR_SUCCESS ) - goto end; - - msiobj_addref( &db->hdr ); - IStorage_AddRef( stg ); - *pdb = db; - -end: - if( db ) - msiobj_release( &db->hdr ); - if( stg ) - IStorage_Release( stg ); - - return ret; -} - -UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB) -{ - MSIDATABASE *db; - UINT ret; - - TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB); - - ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db ); - if( ret == ERROR_SUCCESS ) - { - *phDB = alloc_msihandle( &db->hdr ); - msiobj_release( &db->hdr ); - } - - return ret; -} - -UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB) -{ - HRESULT r = ERROR_FUNCTION_FAILED; - LPWSTR szwDBPath = NULL, szwPersist = NULL; - UINT len; - - TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB); - - if( szDBPath ) - { - len = MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, NULL, 0 ); - szwDBPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - if( !szwDBPath ) - goto end; - MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, szwDBPath, len ); - } - - if( HIWORD(szPersist) ) - { - len = MultiByteToWideChar( CP_ACP, 0, szPersist, -1, NULL, 0 ); - szwPersist = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - if( !szwPersist ) - goto end; - MultiByteToWideChar( CP_ACP, 0, szPersist, -1, szwPersist, len ); - } - else - szwPersist = (LPWSTR) szPersist; - - r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB ); - -end: - HeapFree( GetProcessHeap(), 0, szwPersist ); - HeapFree( GetProcessHeap(), 0, szwDBPath ); - - return r; -} - UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct) { - UINT len, ret; + UINT r; LPWSTR szwProd = NULL; TRACE("%s %p\n",debugstr_a(szProduct), phProduct); if( szProduct ) { - len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProd = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); - if( szwProd ) - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProd, len ); + szwProd = strdupAtoW( szProduct ); + if( !szwProd ) + return ERROR_OUTOFMEMORY; } - ret = MsiOpenProductW( szwProd, phProduct ); + r = MsiOpenProductW( szwProd, phProduct ); HeapFree( GetProcessHeap(), 0, szwProd ); - return ret; + return r; } UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct) @@ -350,28 +169,24 @@ UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfileP UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine) { LPWSTR szwPath = NULL, szwCommand = NULL; - UINT r = ERROR_FUNCTION_FAILED; /* FIXME: check return code */ + UINT r = ERROR_OUTOFMEMORY; TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine)); if( szPackagePath ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, NULL, 0 ); - szwPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwPath = strdupAtoW( szPackagePath ); if( !szwPath ) goto end; - MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, szwPath, len ); } if( szCommandLine ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 ); - szwCommand = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwCommand = strdupAtoW( szCommandLine ); if( !szwCommand ) goto end; - MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommand, len ); } - + r = MsiInstallProductW( szwPath, szwCommand ); end: @@ -384,26 +199,26 @@ end: UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine) { MSIPACKAGE *package = NULL; - UINT rc = ERROR_SUCCESS; + UINT r; MSIHANDLE handle; FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine)); - rc = MsiVerifyPackageW(szPackagePath); - if (rc != ERROR_SUCCESS) - return rc; + r = MsiVerifyPackageW(szPackagePath); + if (r != ERROR_SUCCESS) + return r; - rc = MSI_OpenPackageW(szPackagePath,&package); - if (rc != ERROR_SUCCESS) - return rc; + r = MSI_OpenPackageW(szPackagePath,&package); + if (r != ERROR_SUCCESS) + return r; handle = alloc_msihandle( &package->hdr ); - rc = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine); + r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine); MsiCloseHandle(handle); msiobj_release( &package->hdr ); - return rc; + return r; } UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode) @@ -437,7 +252,7 @@ UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage, UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState, LPCWSTR szCommandLine) { - MSIHANDLE handle; + MSIHANDLE handle; MSIPACKAGE* package; UINT rc; HKEY hkey=0,hkey1=0; @@ -454,7 +269,7 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, FIXME("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState, debugstr_w(szCommandLine)); - if (eInstallState != INSTALLSTATE_LOCAL && + if (eInstallState != INSTALLSTATE_LOCAL && eInstallState != INSTALLSTATE_DEFAULT) { FIXME("Not implemented for anything other than local installs\n"); @@ -479,7 +294,7 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, * ok 1, we need to find the msi file for this product. * 2, find the source dir for the files * 3, do the configure/install. - * 4, cleanupany runonce entry. + * 4, cleanupany runonce entry. */ rc = MsiOpenProductW(szProduct,&handle); @@ -492,21 +307,21 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, rc = ERROR_INVALID_HANDLE; goto end; } - - sz = strlenW(szInstalled); + + sz = lstrlenW(szInstalled); if (szCommandLine) - sz += strlenW(szCommandLine); + sz += lstrlenW(szCommandLine); commandline = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR)); - if (szCommandLine) - strcpyW(commandline,szCommandLine); + if (szCommandLine) + lstrcpyW(commandline,szCommandLine); else commandline[0] = 0; if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN) - strcatW(commandline,szInstalled); + lstrcatW(commandline,szInstalled); rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline); @@ -524,102 +339,89 @@ UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel, { LPWSTR szwProduct = NULL; LPWSTR szwCommandLine = NULL; - UINT hr = ERROR_FUNCTION_FAILED; + UINT r = ERROR_OUTOFMEMORY; if( szProduct ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwProduct = strdupAtoW( szProduct ); if( !szwProduct ) goto end; - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); } if( szCommandLine) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 ); - szwCommandLine= HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwCommandLine = strdupAtoW( szCommandLine ); if( !szwCommandLine) goto end; - MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommandLine, len ); } - hr = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState, + r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState, szwCommandLine ); end: HeapFree( GetProcessHeap(), 0, szwProduct ); HeapFree( GetProcessHeap(), 0, szwCommandLine); - return hr; + return r; } -UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, +UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState) { LPWSTR szwProduct = NULL; - UINT hr = ERROR_SUCCESS; + UINT r; - FIXME("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState); + TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState); if( szProduct ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwProduct = strdupAtoW( szProduct ); if( !szwProduct ) - goto end; - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); + return ERROR_OUTOFMEMORY; } - hr = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState ); - -end: + r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState ); HeapFree( GetProcessHeap(), 0, szwProduct ); - return hr; + return r; } -UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, +UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState) { FIXME("%s %d %d\n", debugstr_w(szProduct), iInstallLevel, eInstallState); - return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, - NULL); + return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL); } UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer) { LPWSTR szwComponent = NULL; - UINT hr = ERROR_INSTALL_FAILURE; + UINT r; WCHAR szwBuffer[GUID_SIZE]; - FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer)); + TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer)); if( szComponent ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 ); - szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwComponent = strdupAtoW( szComponent ); if( !szwComponent ) - goto end; - MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len ); + return ERROR_OUTOFMEMORY; } - else - return ERROR_INVALID_PARAMETER; - hr = MsiGetProductCodeW( szwComponent, szwBuffer ); + r = MsiGetProductCodeW( szwComponent, szwBuffer ); - if( ERROR_SUCCESS == hr ) + if( ERROR_SUCCESS == r ) WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL); -end: HeapFree( GetProcessHeap(), 0, szwComponent ); - return hr; + return r; } UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer) { - FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer)); + FIXME("%s %p\n",debugstr_w(szComponent), szBuffer); + if (NULL == szComponent) return ERROR_INVALID_PARAMETER; return ERROR_CALL_NOT_IMPLEMENTED; @@ -629,36 +431,23 @@ UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, DWORD *pcchValueBuf) { LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL; - UINT hr = ERROR_INSTALL_FAILURE; + UINT r = ERROR_OUTOFMEMORY; - FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), + TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute), szBuffer, pcchValueBuf); - if( NULL != szBuffer && NULL == pcchValueBuf ) - return ERROR_INVALID_PARAMETER; if( szProduct ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwProduct = strdupAtoW( szProduct ); if( !szwProduct ) goto end; - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); } - else - return ERROR_INVALID_PARAMETER; if( szAttribute ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, NULL, 0 ); - szwAttribute = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwAttribute = strdupAtoW( szAttribute ); if( !szwAttribute ) goto end; - MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, szwAttribute, len ); - } - else - { - hr = ERROR_INVALID_PARAMETER; - goto end; } if( szBuffer ) @@ -668,9 +457,9 @@ UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, goto end; } - hr = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf ); + r = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf ); - if( ERROR_SUCCESS == hr ) + if( ERROR_SUCCESS == r ) WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL); end: @@ -678,15 +467,15 @@ end: HeapFree( GetProcessHeap(), 0, szwAttribute ); HeapFree( GetProcessHeap(), 0, szwBuffer ); - return hr; + return r; } UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szBuffer, DWORD *pcchValueBuf) { MSIHANDLE hProduct; - UINT hr; - + UINT r; + FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), szBuffer, pcchValueBuf); @@ -695,51 +484,31 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, if (NULL == szProduct || NULL == szAttribute) return ERROR_INVALID_PARAMETER; - hr = MsiOpenProductW(szProduct, &hProduct); - if (ERROR_SUCCESS != hr) - return hr; + r = MsiOpenProductW(szProduct, &hProduct); + if (ERROR_SUCCESS != r) + return r; - hr = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf); + r = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf); MsiCloseHandle(hProduct); - return hr; -} - -UINT WINAPI MsiDatabaseImportA(LPCSTR szFolderPath, LPCSTR szFilename) -{ - FIXME("%s %s\n",debugstr_a(szFolderPath), debugstr_a(szFilename)); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -UINT WINAPI MsiDatabaseImportW(LPCWSTR szFolderPath, LPCWSTR szFilename) -{ - FIXME("%s %s\n",debugstr_w(szFolderPath), debugstr_w(szFilename)); - return ERROR_CALL_NOT_IMPLEMENTED; + return r; } UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes) { LPWSTR szwLogFile = NULL; - UINT hr = ERROR_INSTALL_FAILURE; + UINT r; - FIXME("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes); + TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes); if( szLogFile ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, NULL, 0 ); - szwLogFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + szwLogFile = strdupAtoW( szLogFile ); if( !szwLogFile ) - goto end; - MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, szwLogFile, len ); + return ERROR_OUTOFMEMORY; } - else - return ERROR_INVALID_PARAMETER; - - hr = MsiEnableLogW( dwLogMode, szwLogFile, attributes ); - -end: + r = MsiEnableLogW( dwLogMode, szwLogFile, attributes ); HeapFree( GetProcessHeap(), 0, szwLogFile ); - - return hr; + return r; } UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes) @@ -748,7 +517,7 @@ UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes) TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes); - strcpyW(gszLogFile,szLogFile); + lstrcpyW(gszLogFile,szLogFile); if (!(attributes & INSTALLLOGATTRIBUTES_APPEND)) DeleteFileW(szLogFile); file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, @@ -763,23 +532,25 @@ UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes) INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct) { - LPWSTR szwProduct; - UINT len; - INSTALLSTATE rc; + LPWSTR szwProduct = NULL; + INSTALLSTATE r; - len = MultiByteToWideChar(CP_ACP,0,szProduct,-1,NULL,0); - szwProduct = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP,0,szProduct,-1,szwProduct,len); - rc = MsiQueryProductStateW(szwProduct); - HeapFree(GetProcessHeap(),0,szwProduct); - return rc; + if( szProduct ) + { + szwProduct = strdupAtoW( szProduct ); + if( !szwProduct ) + return ERROR_OUTOFMEMORY; + } + r = MsiQueryProductStateW( szwProduct ); + HeapFree( GetProcessHeap(), 0, szwProduct ); + return r; } INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct) { UINT rc; INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN; - HKEY hkey=0; + HKEY hkey = 0; static const WCHAR szWindowsInstaller[] = { 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 }; DWORD sz; @@ -833,7 +604,7 @@ INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd) return old; } -INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, +INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, DWORD dwMessageFilter, LPVOID pvContext) { INSTALLUI_HANDLERA prev = gUIHandlerA; @@ -980,7 +751,7 @@ UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uT UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, - DWORD* pcchPathBuf ) + DWORD* pcchPathBuf ) { FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName), debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, @@ -992,7 +763,7 @@ UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD* pcchPathBuf ) { - FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName), + FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName), debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf); return ERROR_CALL_NOT_IMPLEMENTED; @@ -1046,18 +817,16 @@ UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty, UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage ) { - UINT r, len; + UINT r; LPWSTR szPack = NULL; TRACE("%s\n", debugstr_a(szPackage) ); if( szPackage ) { - len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 ); - szPack = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + szPack = strdupAtoW( szPackage ); if( !szPack ) return ERROR_OUTOFMEMORY; - MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szPack, len ); } r = MsiVerifyPackageW( szPack ); @@ -1085,27 +854,23 @@ INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent, { LPWSTR szwProduct = NULL, szwComponent = NULL, lpwPathBuf= NULL; INSTALLSTATE rc; - UINT len, incoming_len; + UINT incoming_len; if( szProduct ) { - len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + szwProduct = strdupAtoW( szProduct ); if( !szwProduct) return ERROR_OUTOFMEMORY; - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); } if( szComponent ) { - len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 ); - szwComponent= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + szwComponent = strdupAtoW( szComponent ); if( !szwComponent ) { HeapFree( GetProcessHeap(), 0, szwProduct); return ERROR_OUTOFMEMORY; } - MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len ); } if( pcchBuf && *pcchBuf > 0 ) @@ -1180,7 +945,7 @@ INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent, if (path[0]=='0') { FIXME("Registry entry.. check entry\n"); - rrc = INSTALLSTATE_LOCAL; + rrc = INSTALLSTATE_LOCAL; } else { @@ -1195,7 +960,7 @@ INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent, { sz = sz / sizeof(WCHAR); if( *pcchBuf >= sz ) - strcpyW( lpPathBuf, path ); + lstrcpyW( lpPathBuf, path ); *pcchBuf = sz; } @@ -1208,29 +973,24 @@ end: INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature) { INSTALLSTATE rc; - UINT len; LPWSTR szwProduct= NULL; LPWSTR szwFeature= NULL; if( szProduct ) { - len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + szwProduct = strdupAtoW( szProduct ); if( !szwProduct) return ERROR_OUTOFMEMORY; - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); } if( szFeature ) { - len = MultiByteToWideChar( CP_ACP, 0, szFeature, -1, NULL, 0 ); - szwFeature= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + szwFeature = strdupAtoW( szFeature ); if( !szwFeature) { HeapFree( GetProcessHeap(), 0, szwProduct); return ERROR_OUTOFMEMORY; } - MultiByteToWideChar( CP_ACP, 0, szFeature, -1, szwFeature, len ); } rc = MsiQueryFeatureStateW(szwProduct, szwFeature); @@ -1254,17 +1014,15 @@ UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf) { LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL; - UINT len, ret = ERROR_OUTOFMEMORY; - + UINT ret = ERROR_OUTOFMEMORY; + if( szFilePath ) { - len = MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, NULL, 0 ); - szwFilePath = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + szwFilePath = strdupAtoW( szFilePath ); if( !szwFilePath ) goto end; - MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, szwFilePath, len ); } - + if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) { lpwVersionBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR)); @@ -1278,22 +1036,22 @@ UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, if( !lpwLangBuff ) goto end; } - + ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, lpwLangBuff, pcchLangBuf); - + if( lpwVersionBuff ) WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, lpVersionBuf, *pcchVersionBuf, NULL, NULL); if( lpwLangBuff ) WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, lpLangBuf, *pcchLangBuf, NULL, NULL); - + end: HeapFree(GetProcessHeap(), 0, szwFilePath); HeapFree(GetProcessHeap(), 0, lpwVersionBuff); HeapFree(GetProcessHeap(), 0, lpwLangBuff); - + return ret; } @@ -1340,7 +1098,7 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS)); lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf); - *pcchVersionBuf = strlenW(lpVersionBuf); + *pcchVersionBuf = lstrlenW(lpVersionBuf); } else { @@ -1356,7 +1114,7 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, FIXME("Retrieve language from file\n"); wsprintfW(tmp, szLangFormat, lang); lstrcpynW(lpLangBuf, tmp, *pcchLangBuf); - *pcchLangBuf = strlenW(lpLangBuf); + *pcchLangBuf = lstrlenW(lpLangBuf); } end: @@ -1461,15 +1219,15 @@ HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi) { TRACE("%p\n",pdvi); - + if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) return E_INVALIDARG; - + pdvi->dwMajorVersion = MSI_MAJORVERSION; pdvi->dwMinorVersion = MSI_MINORVERSION; pdvi->dwBuildNumber = MSI_BUILDNUMBER; pdvi->dwPlatformID = 1; - + return S_OK; } @@ -1497,7 +1255,7 @@ UINT WINAPI MsiGetFeatureUsageA(LPCSTR szProduct, LPCSTR szFeature, return ERROR_CALL_NOT_IMPLEMENTED; } -INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature, +INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature, DWORD dwInstallMode, DWORD dwReserved) { FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature), @@ -1509,37 +1267,37 @@ INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature, * Software\\Microsoft\\Windows\\CurrentVersion\\ * Installer\\Products\\\\ * "Usage"=dword:........ - */ - - return INSTALLSTATE_LOCAL; + */ + + return INSTALLSTATE_LOCAL; } -INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature, +INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature, DWORD dwInstallMode, DWORD dwReserved) { FIXME("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature), dwInstallMode, dwReserved); - - return INSTALLSTATE_LOCAL; + + return INSTALLSTATE_LOCAL; } INSTALLSTATE WINAPI MsiUseFeatureW(LPCWSTR szProduct, LPCWSTR szFeature) { FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); - - return INSTALLSTATE_LOCAL; + + return INSTALLSTATE_LOCAL; } INSTALLSTATE WINAPI MsiUseFeatureA(LPCSTR szProduct, LPCSTR szFeature) { FIXME("%s %s\n", debugstr_a(szProduct), debugstr_a(szFeature)); - - return INSTALLSTATE_LOCAL; + + return INSTALLSTATE_LOCAL; } -UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent, +UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent, LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct, - DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf, + DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf, DWORD* pcchPathBuf) { FIXME("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent), @@ -1549,26 +1307,26 @@ UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent, return ERROR_INDEX_ABSENT; } -USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf, - DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf, +USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf, + DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf, DWORD* pcchOrgNameBuf, LPWSTR lpSerialBuf, DWORD* pcchSerialBuf) { FIXME("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf, pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, pcchSerialBuf); - - return USERINFOSTATE_UNKNOWN; + + return USERINFOSTATE_UNKNOWN; } -USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf, - DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf, +USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf, + DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf, DWORD* pcchOrgNameBuf, LPSTR lpSerialBuf, DWORD* pcchSerialBuf) { FIXME("%s %p %p %p %p %p %p\n",debugstr_a(szProduct), lpUserNameBuf, pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, pcchSerialBuf); - - return USERINFOSTATE_UNKNOWN; + + return USERINFOSTATE_UNKNOWN; } UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct) @@ -1583,9 +1341,9 @@ UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct) return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiCreateAndVerifyInstallerDirectory(void) +UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved) { - FIXME("\n"); + FIXME("%ld\n", dwReserved); return ERROR_CALL_NOT_IMPLEMENTED; } @@ -1605,7 +1363,7 @@ UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget, return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, +UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, DWORD dwReinstallMode ) { FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature), @@ -1613,7 +1371,7 @@ UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, return ERROR_SUCCESS; } -UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature, +UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature, DWORD dwReinstallMode ) { FIXME("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature), diff --git a/reactos/lib/msi/msi.rc b/reactos/lib/msi/msi.rc index af6906c8883..ce777aa13ef 100644 --- a/reactos/lib/msi/msi.rc +++ b/reactos/lib/msi/msi.rc @@ -31,4 +31,5 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #include "msi_En.rc" #include "msi_Es.rc" #include "msi_Fr.rc" +#include "msi_Nl.rc" #include "msi_Pt.rc" diff --git a/reactos/lib/msi/msi.spec b/reactos/lib/msi/msi.spec index a5a7d44068b..4bf2712ecb1 100644 --- a/reactos/lib/msi/msi.spec +++ b/reactos/lib/msi/msi.spec @@ -24,8 +24,8 @@ 24 stdcall MsiDatabaseGenerateTransformW(long long wstr long long) 25 stdcall MsiDatabaseGetPrimaryKeysA(long str ptr) 26 stdcall MsiDatabaseGetPrimaryKeysW(long wstr ptr) -27 stdcall MsiDatabaseImportA(str str) -28 stdcall MsiDatabaseImportW(wstr wstr) +27 stdcall MsiDatabaseImportA(str str long) +28 stdcall MsiDatabaseImportW(wstr wstr long) 29 stub MsiDatabaseMergeA 30 stub MsiDatabaseMergeW 31 stdcall MsiDatabaseOpenViewA(long str ptr) @@ -219,7 +219,7 @@ 219 stub MsiGetFileHashW 220 stub MsiEnumComponentCostsA 221 stub MsiEnumComponentCostsW -222 stdcall MsiCreateAndVerifyInstallerDirectory() +222 stdcall MsiCreateAndVerifyInstallerDirectory(long) 223 stdcall MsiGetFileSignatureInformationA(str long ptr ptr ptr) 224 stdcall MsiGetFileSignatureInformationW(wstr long ptr ptr ptr) 225 stdcall MsiProvideAssemblyA(str str long long str ptr) diff --git a/reactos/lib/msi/msi_Es.rc b/reactos/lib/msi/msi_Es.rc index 3270f479eea..3d36ff7cde8 100644 --- a/reactos/lib/msi/msi_Es.rc +++ b/reactos/lib/msi/msi_Es.rc @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE { diff --git a/reactos/lib/msi/msi_Nl.rc b/reactos/lib/msi/msi_Nl.rc new file mode 100644 index 00000000000..aff08e7bf90 --- /dev/null +++ b/reactos/lib/msi/msi_Nl.rc @@ -0,0 +1,33 @@ +/* + * Durch resources for MSI + * + * Copyright 2005 Hans Leidekker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + 5 "Pad %s niet gevonden" + 9 "Plaats disk %s" + 10 "Ongeldige parameters" + 11 "Voer de map in die %s bevat" + 12 "De installatiebron van het feature ontbreekt" + 13 "De netwerkschijf met het feature ontbreekt" + 14 "Feature van:" + 15 "Kies de map die %s bevat" +} diff --git a/reactos/lib/msi/msipriv.h b/reactos/lib/msi/msipriv.h index eed3e545517..290de68e075 100644 --- a/reactos/lib/msi/msipriv.h +++ b/reactos/lib/msi/msipriv.h @@ -29,6 +29,7 @@ #include "msiquery.h" #include "objbase.h" #include "objidl.h" +#include "wine/unicode.h" #define MSI_DATASIZEMASK 0x00ff #define MSITYPE_VALID 0x0100 @@ -170,12 +171,6 @@ typedef struct tagMSIVIEWOPS } MSIVIEWOPS; -typedef struct tagMSISUMMARYINFO -{ - MSIOBJECTHDR hdr; - IPropertyStorage *propstg; -} MSISUMMARYINFO; - struct tagMSIVIEW { MSIOBJECTHDR hdr; @@ -307,6 +302,7 @@ extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR); /* record internals */ extern UINT MSI_RecordSetIStream( MSIRECORD *, unsigned int, IStream *); +extern UINT MSI_RecordGetIStream( MSIRECORD *, unsigned int, IStream **); extern const WCHAR *MSI_RecordGetString( MSIRECORD *, unsigned int ); extern MSIRECORD *MSI_CreateRecord( unsigned int ); extern UINT MSI_RecordSetInteger( MSIRECORD *, unsigned int, int ); @@ -386,4 +382,38 @@ extern DWORD gUIFilter; extern LPVOID gUIContext; extern WCHAR gszLogFile[MAX_PATH]; +inline static char *strdupWtoA( LPCWSTR str ) +{ + LPSTR ret = NULL; + if (str) + { + DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL +); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) + WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); + } + return ret; +} + +inline static LPWSTR strdupAtoW( LPCSTR str ) +{ + LPWSTR ret = NULL; + if (str) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); + } + return ret; +} + +inline static LPWSTR strdupW( LPCWSTR src ) +{ + LPWSTR dest; + if (!src) return NULL; + dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR)); + strcpyW(dest, src); + return dest; +} + #endif /* __WINE_MSI_PRIVATE__ */ diff --git a/reactos/lib/msi/msiquery.c b/reactos/lib/msi/msiquery.c index cfe1ecfab64..eb50d0991cc 100644 --- a/reactos/lib/msi/msiquery.c +++ b/reactos/lib/msi/msiquery.c @@ -86,11 +86,9 @@ UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb, if( szQuery ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szQuery, -1, NULL, 0 ); - szwQuery = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + szwQuery = strdupAtoW( szQuery ); if( !szwQuery ) return ERROR_FUNCTION_FAILED; - MultiByteToWideChar( CP_ACP, 0, szQuery, -1, szwQuery, len ); } else szwQuery = NULL; @@ -672,16 +670,15 @@ UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb, LPCSTR table, MSIHANDLE* phRec) { LPWSTR szwTable = NULL; - DWORD len; UINT r; TRACE("%ld %s %p\n", hdb, debugstr_a(table), phRec); if( table ) { - len = MultiByteToWideChar( CP_ACP, 0, table, -1, NULL, 0 ); - szwTable = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, table, -1, szwTable, len ); + szwTable = strdupAtoW( table ); + if( !szwTable ) + return ERROR_OUTOFMEMORY; } r = MsiDatabaseGetPrimaryKeysW( hdb, szwTable, phRec ); HeapFree( GetProcessHeap(), 0, szwTable ); diff --git a/reactos/lib/msi/package.c b/reactos/lib/msi/package.c index 60f939e6472..938de885d70 100644 --- a/reactos/lib/msi/package.c +++ b/reactos/lib/msi/package.c @@ -469,14 +469,13 @@ UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) { LPWSTR szwPack = NULL; - UINT len, ret; + UINT ret; if( szPackage ) { - len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 ); - szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); - if( szwPack ) - MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len ); + szwPack = strdupAtoW( szPackage ); + if( !szwPack ) + return ERROR_OUTOFMEMORY; } ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); @@ -638,29 +637,20 @@ UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue) { LPWSTR szwName = NULL, szwValue = NULL; UINT hr = ERROR_INSTALL_FAILURE; - UINT len; - if (0 == hInstall) { - return ERROR_INVALID_HANDLE; - } - if (NULL == szName) { - return ERROR_INVALID_PARAMETER; - } - if (NULL == szValue) { - return ERROR_INVALID_PARAMETER; + if( szName ) + { + szwName = strdupAtoW( szName ); + if( !szwName ) + goto end; } - len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 ); - szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - if( !szwName ) - goto end; - MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len ); - - len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 ); - szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - if( !szwValue) - goto end; - MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len ); + if( szValue ) + { + szwValue = strdupAtoW( szValue ); + if( !szwValue) + goto end; + } hr = MsiSetPropertyW( hInstall, szwName, szwValue); @@ -703,7 +693,7 @@ UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue) } else { - strcpyW(Query,Insert); + strcpyW(Query,Insert); row = MSI_CreateRecord(2); MSI_RecordSetStringW(row,1,szName); @@ -732,8 +722,13 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue MSIPACKAGE *package; UINT ret; + if (NULL == szName) + return ERROR_INVALID_PARAMETER; + if (NULL == szValue) + return ERROR_INVALID_PARAMETER; + package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); - if( !package) + if( !package ) return ERROR_INVALID_HANDLE; ret = MSI_SetPropertyW( package, szName, szValue); msiobj_release( &package->hdr ); @@ -808,17 +803,18 @@ UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf) { MSIRECORD *row; - UINT rc, len; - LPWSTR szwName; + UINT rc; + LPWSTR szwName = NULL; if (*pchValueBuf > 0) szValueBuf[0] = 0; - len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 ); - szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - if (!szwName) - return ERROR_NOT_ENOUGH_MEMORY; - MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len ); + if( szName ) + { + szwName = strdupAtoW( szName ); + if (!szwName) + return ERROR_NOT_ENOUGH_MEMORY; + } rc = MSI_GetPropertyRow(package, szwName, &row); if (rc == ERROR_SUCCESS) diff --git a/reactos/lib/msi/preview.c b/reactos/lib/msi/preview.c index 5df8ef0e796..540d65174b6 100644 --- a/reactos/lib/msi/preview.c +++ b/reactos/lib/msi/preview.c @@ -132,16 +132,16 @@ UINT WINAPI MsiPreviewDialogW( MSIHANDLE hPreview, LPCWSTR szDialogName ) UINT WINAPI MsiPreviewDialogA( MSIHANDLE hPreview, LPCSTR szDialogName ) { - UINT r, len; + UINT r; LPWSTR strW = NULL; TRACE("%ld %s\n", hPreview, debugstr_a(szDialogName)); if( szDialogName ) { - len = MultiByteToWideChar( CP_ACP, 0, szDialogName, -1, NULL, 0 ); - strW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, szDialogName, -1, strW, len ); + strW = strdupAtoW( szDialogName ); + if( !strW ) + return ERROR_OUTOFMEMORY; } r = MsiPreviewDialogW( hPreview, strW ); HeapFree( GetProcessHeap(), 0, strW ); diff --git a/reactos/lib/msi/record.c b/reactos/lib/msi/record.c index 99722e347c1..a06b0a58658 100644 --- a/reactos/lib/msi/record.c +++ b/reactos/lib/msi/record.c @@ -448,7 +448,6 @@ UINT WINAPI MsiRecordDataSize(MSIHANDLE handle, unsigned int iField) UINT MSI_RecordSetStringA( MSIRECORD *rec, unsigned int iField, LPCSTR szValue ) { LPWSTR str; - UINT len; TRACE("%p %d %s\n", rec, iField, debugstr_a(szValue)); @@ -458,9 +457,7 @@ UINT MSI_RecordSetStringA( MSIRECORD *rec, unsigned int iField, LPCSTR szValue ) MSI_FreeField( &rec->fields[iField] ); if( szValue && szValue[0] ) { - len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 ); - str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, szValue, -1, str, len ); + str = strdupAtoW( szValue ); rec->fields[iField].type = MSIFIELD_WSTR; rec->fields[iField].u.szwVal = str; } @@ -493,7 +490,6 @@ UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, unsigned int iField, LPCSTR s UINT MSI_RecordSetStringW( MSIRECORD *rec, unsigned int iField, LPCWSTR szValue ) { LPWSTR str; - UINT len; TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue)); @@ -504,10 +500,7 @@ UINT MSI_RecordSetStringW( MSIRECORD *rec, unsigned int iField, LPCWSTR szValue if( szValue && szValue[0] ) { - len = lstrlenW(szValue) + 1; - str = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR)); - lstrcpyW( str, szValue ); - + str = strdupW( szValue ); rec->fields[iField].type = MSIFIELD_WSTR; rec->fields[iField].u.szwVal = str; } @@ -633,15 +626,15 @@ UINT MSI_RecordSetStreamW(MSIRECORD *rec, unsigned int iField, LPCWSTR szFilenam UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, unsigned int iField, LPCSTR szFilename) { LPWSTR wstr = NULL; - UINT ret, len; + UINT ret; TRACE("%ld %d %s\n", hRecord, iField, debugstr_a(szFilename)); if( szFilename ) { - len = MultiByteToWideChar(CP_ACP,0,szFilename,-1,NULL,0); - wstr = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP,0,szFilename,-1,wstr,len); + wstr = strdupAtoW( szFilename ); + if( !wstr ) + return ERROR_OUTOFMEMORY; } ret = MsiRecordSetStreamW(hRecord, iField, wstr); HeapFree(GetProcessHeap(),0,wstr); @@ -751,3 +744,19 @@ UINT MSI_RecordSetIStream( MSIRECORD *rec, unsigned int iField, IStream *stm ) return ERROR_SUCCESS; } + +UINT MSI_RecordGetIStream( MSIRECORD *rec, unsigned int iField, IStream **pstm) +{ + TRACE("%p %d %p\n", rec, iField, pstm); + + if( iField > rec->count ) + return ERROR_INVALID_FIELD; + + if( rec->fields[iField].type != MSIFIELD_STREAM ) + return ERROR_INVALID_FIELD; + + *pstm = rec->fields[iField].u.stream; + IStream_AddRef( *pstm ); + + return ERROR_SUCCESS; +} diff --git a/reactos/lib/msi/registry.c b/reactos/lib/msi/registry.c index ad3fa1c7985..c6de5692a96 100644 --- a/reactos/lib/msi/registry.c +++ b/reactos/lib/msi/registry.c @@ -134,6 +134,8 @@ static const WCHAR szInstaller_UpgradeCodes_fmt[] = { 'U','p','g','r','a','d','e','C','o','d','e','s','\\', '%','s',0}; +#define SQUISH_GUID_SIZE 33 + BOOL unsquash_guid(LPCWSTR in, LPWSTR out) { DWORD i,n=0; @@ -496,16 +498,16 @@ UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct, WCHAR feature[MAX_FEATURE_CHARS+1]; WCHAR component[MAX_FEATURE_CHARS+1]; LPWSTR str = NULL; - UINT r, len; + UINT r; TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct, szFeature, szComponent, pUsed); if( szDescriptor ) { - len = MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, NULL, 0 ); - str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, str, len ); + str = strdupAtoW( szDescriptor ); + if( !str ) + return ERROR_OUTOFMEMORY; } r = MsiDecomposeDescriptorW( str, product, feature, component, pUsed ); @@ -542,7 +544,7 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid) { HKEY hkeyFeatures = 0; DWORD r; - WCHAR szKeyName[33]; + WCHAR szKeyName[SQUISH_GUID_SIZE]; TRACE("%ld %p\n",index,lpguid); @@ -551,16 +553,12 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid) r = MSIREG_OpenFeatures(&hkeyFeatures); if( r != ERROR_SUCCESS ) - goto end; + return ERROR_NO_MORE_ITEMS; - r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE); - - unsquash_guid(szKeyName, lpguid); - -end: - - if( hkeyFeatures ) - RegCloseKey(hkeyFeatures); + r = RegEnumKeyW(hkeyFeatures, index, szKeyName, SQUISH_GUID_SIZE); + if( r == ERROR_SUCCESS ) + unsquash_guid(szKeyName, lpguid); + RegCloseKey(hkeyFeatures); return r; } @@ -576,12 +574,9 @@ UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, if( szProduct ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); - if( szwProduct ) - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); - else - return ERROR_FUNCTION_FAILED; + szwProduct = strdupAtoW( szProduct ); + if( !szwProduct ) + return ERROR_OUTOFMEMORY; } r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent); @@ -608,14 +603,11 @@ UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE); if( r != ERROR_SUCCESS ) - goto end; + return ERROR_NO_MORE_ITEMS; sz = GUID_SIZE; r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL); - -end: - if( hkeyProduct ) - RegCloseKey(hkeyProduct); + RegCloseKey(hkeyProduct); return r; } @@ -638,22 +630,18 @@ UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid) { HKEY hkeyComponents = 0; DWORD r; - WCHAR szKeyName[33]; + WCHAR szKeyName[SQUISH_GUID_SIZE]; TRACE("%ld %p\n",index,lpguid); r = MSIREG_OpenComponents(&hkeyComponents); if( r != ERROR_SUCCESS ) - goto end; + return ERROR_NO_MORE_ITEMS; - r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE); - - unsquash_guid(szKeyName, lpguid); - -end: - - if( hkeyComponents ) - RegCloseKey(hkeyComponents); + r = RegEnumKeyW(hkeyComponents, index, szKeyName, SQUISH_GUID_SIZE); + if( r == ERROR_SUCCESS ) + unsquash_guid(szKeyName, lpguid); + RegCloseKey(hkeyComponents); return r; } @@ -668,12 +656,9 @@ UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct) if( szComponent ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 ); - szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); - if( szwComponent ) - MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len ); - else - return ERROR_FUNCTION_FAILED; + szwComponent = strdupAtoW( szComponent ); + if( !szwComponent ) + return ERROR_OUTOFMEMORY; } r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct); @@ -692,24 +677,20 @@ UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct) { HKEY hkeyComp = 0; DWORD r, sz; - WCHAR szValName[GUID_SIZE]; + WCHAR szValName[SQUISH_GUID_SIZE]; TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct); r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE); if( r != ERROR_SUCCESS ) - goto end; + return ERROR_NO_MORE_ITEMS; - sz = GUID_SIZE; + sz = SQUISH_GUID_SIZE; r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL); - if( r != ERROR_SUCCESS ) - goto end; + if( r == ERROR_SUCCESS ) + unsquash_guid(szValName, szProduct); - unsquash_guid(szValName, szProduct); - -end: - if( hkeyComp ) - RegCloseKey(hkeyComp); + RegCloseKey(hkeyComp); return r; } @@ -737,9 +718,9 @@ UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex, UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved, DWORD iProductIndex, LPWSTR lpProductBuf) { - UINT rc; + UINT r; HKEY hkey; - WCHAR szKeyName[33]; + WCHAR szKeyName[SQUISH_GUID_SIZE]; TRACE("%s %lu %lu %p\n", debugstr_w(szUpgradeCode), dwReserved, iProductIndex, lpProductBuf); @@ -748,54 +729,43 @@ UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved, return ERROR_INVALID_PARAMETER; if (NULL == lpProductBuf) return ERROR_INVALID_PARAMETER; - rc = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE); - if (rc != ERROR_SUCCESS) - { - rc = ERROR_NO_MORE_ITEMS; - goto end; - } - rc = RegEnumKeyW(hkey, iProductIndex, szKeyName, - sizeof(szKeyName) / sizeof(szKeyName[0])); + r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE); + if (r != ERROR_SUCCESS) + return ERROR_NO_MORE_ITEMS; - unsquash_guid(szKeyName, lpProductBuf); + r = RegEnumKeyW(hkey, iProductIndex, szKeyName, SQUISH_GUID_SIZE); + if( r == ERROR_SUCCESS ) + unsquash_guid(szKeyName, lpProductBuf); RegCloseKey(hkey); -end: - return rc; + return r; } UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved, DWORD iProductIndex, LPSTR lpProductBuf) { - UINT rc; - int len; - LPWSTR szUpgradeCodeW = NULL; + LPWSTR szwUpgradeCode = NULL; + WCHAR productW[GUID_SIZE]; + UINT r; TRACE("%s %lu %lu %p\n", debugstr_a(szUpgradeCode), dwReserved, iProductIndex, lpProductBuf); - if (!szUpgradeCode) - return ERROR_INVALID_PARAMETER; - len = MultiByteToWideChar(CP_ACP, 0, szUpgradeCode, -1, NULL, 0); - szUpgradeCodeW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, - len * sizeof(WCHAR)); - if (szUpgradeCodeW) + + if (szUpgradeCode) { - WCHAR productW[39]; - - MultiByteToWideChar(CP_ACP, 0, szUpgradeCode, -1, szUpgradeCodeW, len); - rc = MsiEnumRelatedProductsW(szUpgradeCodeW, dwReserved, - iProductIndex, productW); - if (rc == ERROR_SUCCESS) - { - LPWSTR ptr; - - for (ptr = productW; *ptr; ) - *lpProductBuf++ = *ptr++; - } - HeapFree(GetProcessHeap(), 0, szUpgradeCodeW); + szwUpgradeCode = strdupAtoW( szUpgradeCode ); + if( !szwUpgradeCode ) + return ERROR_OUTOFMEMORY; } - else - rc = ERROR_OUTOFMEMORY; - return rc; + + r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved, + iProductIndex, productW ); + if (r == ERROR_SUCCESS) + { + WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE, + lpProductBuf, GUID_SIZE, NULL, NULL ); + } + HeapFree(GetProcessHeap(), 0, szwUpgradeCode); + return r; } diff --git a/reactos/lib/msi/suminfo.c b/reactos/lib/msi/suminfo.c index 16e4516b9ae..74f00dc64ad 100644 --- a/reactos/lib/msi/suminfo.c +++ b/reactos/lib/msi/suminfo.c @@ -1,7 +1,7 @@ /* * Implementation of the Microsoft Installer (msi.dll) * - * Copyright 2002 Mike McCormack for CodeWeavers + * Copyright 2002, 2005 Mike McCormack for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,61 +33,406 @@ #include "wine/debug.h" #include "msi.h" #include "msiquery.h" +#include "msidefs.h" #include "msipriv.h" #include "objidl.h" WINE_DEFAULT_DEBUG_CHANNEL(msi); +#define MSI_MAX_PROPS 19 + +#include "pshpack1.h" + +typedef struct { + WORD wByteOrder; + WORD wFormat; + DWORD dwOSVer; + CLSID clsID; + DWORD reserved; +} PROPERTYSETHEADER; + +typedef struct { + FMTID fmtid; + DWORD dwOffset; +} FORMATIDOFFSET; + +typedef struct { + DWORD cbSection; + DWORD cProperties; +} PROPERTYSECTIONHEADER; + +typedef struct { + DWORD propid; + DWORD dwOffset; +} PROPERTYIDOFFSET; + +typedef struct { + DWORD type; + union { + INT i4; + SHORT i2; + FILETIME ft; + struct { + DWORD len; + BYTE str[1]; + } str; + } u; +} PROPERTY_DATA; + +#include "poppack.h" + +typedef struct { + BOOL unicode; + union { + LPSTR a; + LPWSTR w; + } str; +} awstring; + +typedef struct tagMSISUMMARYINFO +{ + MSIOBJECTHDR hdr; + MSIDATABASE *db; + DWORD update_count; + PROPVARIANT property[MSI_MAX_PROPS]; +} MSISUMMARYINFO; + static const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y', 'I','n','f','o','r','m','a','t','i','o','n',0 }; -static void MSI_CloseSummaryInfo( MSIOBJECTHDR *arg ) +static void free_prop( PROPVARIANT *prop ) { - MSISUMMARYINFO *suminfo = (MSISUMMARYINFO *) arg; - IPropertyStorage_Release( suminfo->propstg ); + if (prop->vt == VT_LPSTR ) + HeapFree( GetProcessHeap(), 0, prop->u.pszVal ); + prop->vt = VT_EMPTY; } -UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, - LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo) +static void MSI_CloseSummaryInfo( MSIOBJECTHDR *arg ) { - LPWSTR szwDatabase = NULL; - UINT ret; + MSISUMMARYINFO *si = (MSISUMMARYINFO *) arg; + DWORD i; - TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase), - uiUpdateCount, phSummaryInfo); + for( i = 0; i < MSI_MAX_PROPS; i++ ) + free_prop( &si->property[i] ); + msiobj_release( &si->db->hdr ); +} - if( szDatabase ) +static UINT get_type( UINT uiProperty ) +{ + switch( uiProperty ) { - UINT len = MultiByteToWideChar( CP_ACP, 0, szDatabase, -1, NULL, 0 ); - szwDatabase = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - if( !szwDatabase ) - return ERROR_FUNCTION_FAILED; - MultiByteToWideChar( CP_ACP, 0, szDatabase, -1, szwDatabase, len ); + case PID_CODEPAGE: + return VT_I2; + + case PID_SUBJECT: + case PID_AUTHOR: + case PID_KEYWORDS: + case PID_COMMENTS: + case PID_TEMPLATE: + case PID_LASTAUTHOR: + case PID_REVNUMBER: + case PID_APPNAME: + case PID_TITLE: + return VT_LPSTR; + + case PID_LASTPRINTED: + case PID_CREATE_DTM: + case PID_LASTSAVE_DTM: + return VT_FILETIME; + + case PID_WORDCOUNT: + case PID_CHARCOUNT: + case PID_SECURITY: + case PID_PAGECOUNT: + return VT_I4; + } + return VT_EMPTY; +} + +static UINT get_property_count( PROPVARIANT *property ) +{ + UINT i, n = 0; + + if( !property ) + return n; + for( i = 0; i < MSI_MAX_PROPS; i++ ) + if( property[i].vt != VT_EMPTY ) + n++; + return n; +} + +/* FIXME: doesn't deal with endian conversion */ +static void read_properties_from_data( PROPVARIANT *prop, + PROPERTYIDOFFSET *idofs, DWORD count, LPBYTE data, DWORD sz ) +{ + UINT type; + DWORD i; + int size; + PROPERTY_DATA *propdata; + PROPVARIANT *property; + + /* now set all the properties */ + for( i = 0; i < count; i++ ) + { + type = get_type( idofs[i].propid ); + if( type == VT_EMPTY ) + { + ERR("propid %ld has unknown type\n", idofs[i].propid); + break; + } + + propdata = (PROPERTY_DATA*) &data[idofs[i].dwOffset]; + + /* check the type is the same as we expect */ + if( type != propdata->type ) + { + ERR("wrong type\n"); + break; + } + + /* check we don't run off the end of the data */ + size = sz - idofs[i].dwOffset - sizeof(DWORD); + if( sizeof(DWORD) > size || + ( type == VT_FILETIME && sizeof(FILETIME) > size ) || + ( type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) ) + { + ERR("not enough data\n"); + break; + } + + property = &prop[ idofs[i].propid ]; + property->vt = type; + + if( type == VT_LPSTR ) + { + LPSTR str = HeapAlloc( GetProcessHeap(), 0, propdata->u.str.len ); + memcpy( str, propdata->u.str.str, propdata->u.str.len ); + str[ propdata->u.str.len - 1 ] = 0; + property->u.pszVal = str; + } + else if( type == VT_FILETIME ) + property->u.filetime = propdata->u.ft; + else if( type == VT_I2 ) + property->u.iVal = propdata->u.i2; + else if( type == VT_I4 ) + property->u.lVal = propdata->u.i4; + } +} + +static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm ) +{ + UINT ret = ERROR_FUNCTION_FAILED; + PROPERTYSETHEADER set_hdr; + FORMATIDOFFSET format_hdr; + PROPERTYSECTIONHEADER section_hdr; + PROPERTYIDOFFSET idofs[MSI_MAX_PROPS]; + LPBYTE data = NULL; + LARGE_INTEGER ofs; + ULONG count, sz; + HRESULT r; + + TRACE("%p %p\n", si, stm); + + /* read the header */ + sz = sizeof set_hdr; + r = IStream_Read( stm, &set_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + if( set_hdr.wByteOrder != 0xfffe ) + { + ERR("property set not big-endian %04X\n", set_hdr.wByteOrder); + return ret; } - ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, phSummaryInfo); + sz = sizeof format_hdr; + r = IStream_Read( stm, &format_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; - HeapFree( GetProcessHeap(), 0, szwDatabase ); + /* check the format id is correct */ + if( !IsEqualGUID( &FMTID_SummaryInformation, &format_hdr.fmtid ) ) + return ret; + /* seek to the location of the section */ + ofs.QuadPart = format_hdr.dwOffset; + r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, NULL ); + if( FAILED(r) ) + return ret; + + /* read the section itself */ + sz = sizeof section_hdr; + r = IStream_Read( stm, §ion_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + if( section_hdr.cProperties > MSI_MAX_PROPS ) + { + ERR("too many properties %ld\n", section_hdr.cProperties); + return ret; + } + + /* read the offsets */ + sz = sizeof idofs[0] * section_hdr.cProperties; + r = IStream_Read( stm, idofs, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + /* read all the data in one go */ + sz = section_hdr.cbSection; + data = HeapAlloc( GetProcessHeap(), 0, sz ); + if( !data ) + return ret; + r = IStream_Read( stm, data, sz, &count ); + if( SUCCEEDED(r) && count == sz ) + { + read_properties_from_data( si->property, idofs, + section_hdr.cProperties, data, sz ); + } + + HeapFree( GetProcessHeap(), 0, data ); return ret; } -UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase, - LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo) +static DWORD write_dword( LPBYTE data, DWORD ofs, DWORD val ) { + if( data ) + { + data[ofs++] = val&0xff; + data[ofs++] = (val>>8)&0xff; + data[ofs++] = (val>>16)&0xff; + data[ofs++] = (val>>24)&0xff; + } + return 4; +} + +static DWORD write_filetime( LPBYTE data, DWORD ofs, LPFILETIME ft ) +{ + write_dword( data, ofs, ft->dwLowDateTime ); + write_dword( data, ofs + 4, ft->dwHighDateTime ); + return 8; +} + +static DWORD write_string( LPBYTE data, DWORD ofs, LPCSTR str ) +{ + DWORD len = lstrlenA( str ) + 1; + write_dword( data, ofs, len ); + if( data ) + lstrcpyA( &data[ofs + 4], str ); + return (7 + len) & ~3; +} + +static UINT write_property_to_data( PROPVARIANT *prop, LPBYTE data ) +{ + DWORD sz = 0; + + if( prop->vt == VT_EMPTY ) + return sz; + + /* add the type */ + sz += write_dword( data, sz, prop->vt ); + switch( prop->vt ) + { + case VT_I2: + sz += write_dword( data, sz, prop->u.iVal ); + break; + case VT_I4: + sz += write_dword( data, sz, prop->u.lVal ); + break; + case VT_FILETIME: + sz += write_filetime( data, sz, &prop->u.filetime ); + break; + case VT_LPSTR: + sz += write_string( data, sz, prop->u.pszVal ); + break; + } + return sz; +} + +static UINT save_summary_info( MSISUMMARYINFO * si, IStream *stm ) +{ + UINT ret = ERROR_FUNCTION_FAILED; + PROPERTYSETHEADER set_hdr; + FORMATIDOFFSET format_hdr; + PROPERTYSECTIONHEADER section_hdr; + PROPERTYIDOFFSET idofs[MSI_MAX_PROPS]; + LPBYTE data = NULL; + ULONG count, sz; HRESULT r; - MSIHANDLE handle; - MSISUMMARYINFO *suminfo; - MSIDATABASE *db; + int i, n; + + /* write the header */ + sz = sizeof set_hdr; + memset( &set_hdr, 0, sz ); + set_hdr.wByteOrder = 0xfffe; + set_hdr.wFormat = 0; + set_hdr.dwOSVer = 0x00020005; /* build 5, platform id 2 */ + /* set_hdr.clsID is {00000000-0000-0000-0000-000000000000} */ + set_hdr.reserved = 1; + r = IStream_Write( stm, &set_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + /* write the format header */ + sz = sizeof format_hdr; + memcpy( &format_hdr.fmtid, &FMTID_SummaryInformation, sizeof (FMTID) ); + format_hdr.dwOffset = sizeof format_hdr + sizeof set_hdr; + r = IStream_Write( stm, &format_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + /* add up how much space the data will take and calculate the offsets */ + section_hdr.cbSection = sizeof section_hdr; + section_hdr.cbSection += (get_property_count( si->property ) * sizeof idofs[0]); + section_hdr.cProperties = 0; + n = 0; + for( i = 0; i < MSI_MAX_PROPS; i++ ) + { + sz = write_property_to_data( &si->property[i], NULL ); + if( !sz ) + continue; + idofs[ section_hdr.cProperties ].propid = i; + idofs[ section_hdr.cProperties ].dwOffset = section_hdr.cbSection; + section_hdr.cProperties++; + section_hdr.cbSection += sz; + } + + data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, section_hdr.cbSection ); + + sz = 0; + memcpy( &data[sz], §ion_hdr, sizeof section_hdr ); + sz += sizeof section_hdr; + + memcpy( &data[sz], idofs, section_hdr.cProperties * sizeof idofs[0] ); + sz += section_hdr.cProperties * sizeof idofs[0]; + + /* write out the data */ + for( i = 0; i < MSI_MAX_PROPS; i++ ) + sz += write_property_to_data( &si->property[i], &data[sz] ); + + r = IStream_Write( stm, data, sz, &count ); + HeapFree( GetProcessHeap(), 0, data ); + if( FAILED(r) || count != sz ) + return ret; + + return ERROR_SUCCESS; +} + +UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase, + LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle ) +{ UINT ret = ERROR_SUCCESS; - IPropertySetStorage *psstg = NULL; - IPropertyStorage *ps = NULL; + IStream *stm = NULL; + MSISUMMARYINFO *si; + MSIHANDLE handle; + MSIDATABASE *db; DWORD grfMode; + HRESULT r; TRACE("%ld %s %d %p\n", hDatabase, debugstr_w(szDatabase), - uiUpdateCount, phSummaryInfo); + uiUpdateCount, pHandle); - if( !phSummaryInfo ) + if( !pHandle ) return ERROR_INVALID_PARAMETER; if( szDatabase ) @@ -105,207 +450,302 @@ UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase, return ERROR_INVALID_PARAMETER; } - r = IStorage_QueryInterface( db->storage, - &IID_IPropertySetStorage, (LPVOID)&psstg); - if( FAILED( r ) ) - { - ERR("IStorage -> IPropertySetStorage failed\n"); - ret = ERROR_FUNCTION_FAILED; - goto end; - } - - grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE; - r = IPropertySetStorage_Open( psstg, &FMTID_SummaryInformation, grfMode, &ps ); - if( FAILED( r ) ) - { - ERR("failed to get IPropertyStorage r=%08lx\n",r); - ret = ERROR_FUNCTION_FAILED; - goto end; - } - - suminfo = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO, + si = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO, sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo ); - if( !suminfo ) + if( !si ) { ret = ERROR_FUNCTION_FAILED; goto end; } - IPropertyStorage_AddRef(ps); - suminfo->propstg = ps; - handle = alloc_msihandle( &suminfo->hdr ); + msiobj_addref( &db->hdr ); + si->db = db; + memset( &si->property, 0, sizeof si->property ); + si->update_count = uiUpdateCount; + + /* read the stream... if we fail, we'll start with an empty property set */ + grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE; + r = IStorage_OpenStream( si->db->storage, szSumInfo, 0, grfMode, 0, &stm ); + if( SUCCEEDED(r) ) + { + load_summary_info( si, stm ); + IStream_Release( stm ); + } + + handle = alloc_msihandle( &si->hdr ); if( handle ) - *phSummaryInfo = handle; + *pHandle = handle; else ret = ERROR_FUNCTION_FAILED; - msiobj_release( &suminfo->hdr ); + msiobj_release( &si->hdr ); end: - if( ps ) - IPropertyStorage_Release(ps); - if( psstg ) - IPropertySetStorage_Release(psstg); if( db ) msiobj_release(&db->hdr); return ret; } +UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, + LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle) +{ + LPWSTR szwDatabase = NULL; + UINT ret; + + TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase), + uiUpdateCount, pHandle); + + if( szDatabase ) + { + szwDatabase = strdupAtoW( szDatabase ); + if( !szwDatabase ) + return ERROR_FUNCTION_FAILED; + } + + ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, pHandle); + + HeapFree( GetProcessHeap(), 0, szwDatabase ); + + return ret; +} + UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount) { - MSISUMMARYINFO *suminfo; + MSISUMMARYINFO *si; - FIXME("%ld %p\n",hSummaryInfo, pCount); + TRACE("%ld %p\n",hSummaryInfo, pCount); - suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); - if( !suminfo ) + si = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) return ERROR_INVALID_HANDLE; - msiobj_release( &suminfo->hdr ); - return ERROR_CALL_NOT_IMPLEMENTED; + if( pCount ) + *pCount = get_property_count( si->property ); + msiobj_release( &si->hdr ); + + return ERROR_SUCCESS; +} + +static UINT get_prop( MSIHANDLE handle, UINT uiProperty, UINT *puiDataType, + INT *piValue, FILETIME *pftValue, awstring *str, DWORD *pcchValueBuf) +{ + MSISUMMARYINFO *si; + PROPVARIANT *prop; + UINT type; + + TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType, + piValue, pftValue, str, pcchValueBuf); + + type = get_type( uiProperty ); + if( puiDataType ) + *puiDataType = type; + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) + return ERROR_INVALID_HANDLE; + + prop = &si->property[uiProperty]; + if( prop->vt != type ) + goto end; + + switch( type ) + { + case VT_I2: + if( piValue ) + *piValue = prop->u.iVal; + break; + case VT_I4: + if( piValue ) + *piValue = prop->u.lVal; + break; + case VT_LPSTR: + if( pcchValueBuf ) + { + DWORD len = 0; + + if( str->unicode ) + { + len = MultiByteToWideChar( CP_ACP, 0, prop->u.pszVal, -1, + str->str.w, *pcchValueBuf ); + } + else + { + len = lstrlenA( prop->u.pszVal ); + if( str->str.a ) + lstrcpynA(str->str.a, prop->u.pszVal, *pcchValueBuf ); + } + *pcchValueBuf = len; + } + break; + case VT_FILETIME: + if( pftValue ) + memcpy(pftValue, &prop->u.filetime, sizeof (FILETIME) ); + break; + case VT_EMPTY: + break; + default: + FIXME("Unknown property variant type\n"); + break; + } +end: + msiobj_release( &si->hdr ); + return ERROR_SUCCESS; } UINT WINAPI MsiSummaryInfoGetPropertyA( - MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue, + MSIHANDLE handle, UINT uiProperty, UINT *puiDataType, INT *piValue, FILETIME *pftValue, LPSTR szValueBuf, DWORD *pcchValueBuf) { - MSISUMMARYINFO *suminfo; - HRESULT r; - PROPSPEC spec; - PROPVARIANT var; - UINT rc = ERROR_SUCCESS; + awstring str; - TRACE("%ld %d %p %p %p %p %p\n", - hSummaryInfo, uiProperty, puiDataType, piValue, - pftValue, szValueBuf, pcchValueBuf); + TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType, + piValue, pftValue, szValueBuf, pcchValueBuf ); - suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); - if( !suminfo ) - return ERROR_INVALID_HANDLE; + str.unicode = FALSE; + str.str.a = szValueBuf; - spec.ulKind = PRSPEC_PROPID; - spec.u.propid = uiProperty; - - r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var); - if( FAILED(r) ) - { - rc = ERROR_FUNCTION_FAILED; - goto end; - } - - if( puiDataType ) - *puiDataType = var.vt; - - switch( var.vt ) - { - case VT_I4: - if( piValue ) - *piValue = var.u.lVal; - break; - case VT_LPSTR: - if( pcchValueBuf && szValueBuf ) - { - lstrcpynA(szValueBuf, var.u.pszVal, *pcchValueBuf ); - *pcchValueBuf = lstrlenA( var.u.pszVal ); - } - break; - case VT_FILETIME: - if( pftValue ) - memcpy(pftValue, &var.u.filetime, sizeof (FILETIME) ); - break; - case VT_EMPTY: - break; - default: - FIXME("Unknown property variant type\n"); - break; - } - -end: - msiobj_release( &suminfo->hdr ); - return rc; + return get_prop( handle, uiProperty, puiDataType, piValue, + pftValue, &str, pcchValueBuf ); } UINT WINAPI MsiSummaryInfoGetPropertyW( - MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue, + MSIHANDLE handle, UINT uiProperty, UINT *puiDataType, INT *piValue, FILETIME *pftValue, LPWSTR szValueBuf, DWORD *pcchValueBuf) { - MSISUMMARYINFO *suminfo; - HRESULT r; - PROPSPEC spec; - PROPVARIANT var; - UINT rc = ERROR_SUCCESS; + awstring str; - TRACE("%ld %d %p %p %p %p %p\n", - hSummaryInfo, uiProperty, puiDataType, piValue, - pftValue, szValueBuf, pcchValueBuf); + TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType, + piValue, pftValue, szValueBuf, pcchValueBuf ); - suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); - if( !suminfo ) + str.unicode = TRUE; + str.str.w = szValueBuf; + + return get_prop( handle, uiProperty, puiDataType, piValue, + pftValue, &str, pcchValueBuf ); +} + +static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType, + INT iValue, FILETIME* pftValue, awstring *str ) +{ + MSISUMMARYINFO *si; + PROPVARIANT *prop; + UINT type, len, ret = ERROR_SUCCESS; + + TRACE("%ld %u %u %i %p %p\n", handle, uiProperty, uiDataType, + iValue, pftValue, str ); + + type = get_type( uiProperty ); + if( type == VT_EMPTY || type != uiDataType ) + return ERROR_DATATYPE_MISMATCH; + + if( uiDataType == VT_LPSTR && !str->str.w ) + return ERROR_INVALID_PARAMETER; + + if( uiDataType == VT_FILETIME && !pftValue ) + return ERROR_INVALID_PARAMETER; + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) return ERROR_INVALID_HANDLE; - spec.ulKind = PRSPEC_PROPID; - spec.u.propid = uiProperty; + prop = &si->property[uiProperty]; - r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var); - if( FAILED(r) ) + if( prop->vt == VT_EMPTY ) { - rc = ERROR_FUNCTION_FAILED; - goto end; + if( !si->update_count ) + { + ret = ERROR_FUNCTION_FAILED; + goto end; + } + si->update_count--; } + else if( prop->vt != type ) + goto end; - if( puiDataType ) - *puiDataType = var.vt; - - switch( var.vt ) + free_prop( prop ); + prop->vt = type; + switch( type ) { case VT_I4: - if( piValue ) - *piValue = var.u.lVal; + prop->u.lVal = iValue; break; - case VT_LPSTR: - if( pcchValueBuf && szValueBuf ) - { - MultiByteToWideChar(CP_ACP, 0, var.u.pszVal, -1, szValueBuf, - *pcchValueBuf ); - *pcchValueBuf = lstrlenA( var.u.pszVal ); - } + case VT_I2: + prop->u.iVal = iValue; break; case VT_FILETIME: - if( pftValue ) - memcpy(pftValue, &var.u.filetime, sizeof (FILETIME) ); + memcpy( &prop->u.filetime, pftValue, sizeof prop->u.filetime ); break; - case VT_EMPTY: - break; - default: - FIXME("Unknown property variant type\n"); + case VT_LPSTR: + if( str->unicode ) + { + len = WideCharToMultiByte( CP_ACP, 0, str->str.w, -1, + NULL, 0, NULL, NULL ); + prop->u.pszVal = HeapAlloc( GetProcessHeap(), 0, len ); + WideCharToMultiByte( CP_ACP, 0, str->str.w, -1, + prop->u.pszVal, len, NULL, NULL ); + } + else + { + len = lstrlenA( str->str.a ) + 1; + prop->u.pszVal = HeapAlloc( GetProcessHeap(), 0, len ); + lstrcpyA( prop->u.pszVal, str->str.a ); + } break; } end: - msiobj_release( &suminfo->hdr ); - return rc; + msiobj_release( &si->hdr ); + return ret; } -UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty, - UINT uiDataType, INT iValue, - FILETIME* pftValue, LPSTR szValue ) +UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE handle, UINT uiProperty, + UINT uiDataType, INT iValue, FILETIME* pftValue, LPWSTR szValue ) { - FIXME("%ld %u %u %i %p %s\n", hSummaryInfo, uiProperty, - uiDataType, iValue, pftValue, debugstr_a(szValue) ); - return ERROR_CALL_NOT_IMPLEMENTED; + awstring str; + + TRACE("%ld %u %u %i %p %s\n", handle, uiProperty, uiDataType, + iValue, pftValue, debugstr_w(szValue) ); + + str.unicode = TRUE; + str.str.w = szValue; + return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str ); } -UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE hSummaryInfo, UINT uiProperty, - UINT uiDataType, INT iValue, - FILETIME* pftValue, LPWSTR szValue ) +UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE handle, UINT uiProperty, + UINT uiDataType, INT iValue, FILETIME* pftValue, LPSTR szValue ) { - FIXME("%ld %u %u %i %p %s\n", hSummaryInfo, uiProperty, - uiDataType, iValue, pftValue, debugstr_w(szValue) ); - return ERROR_CALL_NOT_IMPLEMENTED; + awstring str; + + TRACE("%ld %u %u %i %p %s\n", handle, uiProperty, uiDataType, + iValue, pftValue, debugstr_a(szValue) ); + + str.unicode = FALSE; + str.str.a = szValue; + return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str ); } -UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE hSummaryInfo ) +UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle ) { - FIXME("%ld\n", hSummaryInfo ); - return ERROR_CALL_NOT_IMPLEMENTED; + IStream *stm = NULL; + MSISUMMARYINFO *si; + DWORD grfMode; + HRESULT r; + UINT ret = ERROR_FUNCTION_FAILED; + + TRACE("%ld\n", handle ); + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) + return ERROR_INVALID_HANDLE; + + grfMode = STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE; + r = IStorage_CreateStream( si->db->storage, szSumInfo, grfMode, 0, 0, &stm ); + if( SUCCEEDED(r) ) + { + ret = save_summary_info( si, stm ); + IStream_Release( stm ); + } + msiobj_release( &si->hdr ); + + return ret; } diff --git a/reactos/lib/msi/table.c b/reactos/lib/msi/table.c index 63ee0db24ac..cf0718b19c7 100644 --- a/reactos/lib/msi/table.c +++ b/reactos/lib/msi/table.c @@ -834,15 +834,6 @@ err: return ret; } -static LPWSTR strdupW( LPCWSTR str ) -{ - UINT len = lstrlenW( str ) + 1; - LPWSTR ret = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) ); - if( ret ) - lstrcpyW( ret, str ); - return ret; -} - /* information for default tables */ static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 }; static const WCHAR szTable[] = { 'T','a','b','l','e',0 };