Implement MsiVerifyPackage, cosmetic fixes.
[wine/multimedia.git] / dlls / msi / msi.c
blob7f49276ffc41245b51b6421a8c251705140af6ae
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002,2003,2004 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSUNION
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "winnls.h"
29 #include "shlwapi.h"
30 #include "wine/debug.h"
31 #include "msi.h"
32 #include "msiquery.h"
33 #include "msipriv.h"
34 #include "objidl.h"
35 #include "wincrypt.h"
36 #include "wine/unicode.h"
37 #include "objbase.h"
39 #include "initguid.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
44 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
45 * which is a problem because LPCTSTR isn't defined when compiling wine.
46 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
47 * and make sure to only use it in W functions.
49 #define LPCTSTR LPCWSTR
51 DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000, 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
53 static const WCHAR szInstaller[] = {
54 'S','o','f','t','w','a','r','e','\\',
55 'M','i','c','r','o','s','o','f','t','\\',
56 'W','i','n','d','o','w','s','\\',
57 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
58 'I','n','s','t','a','l','l','e','r',0 };
60 static const WCHAR szFeatures[] = {
61 'F','e','a','t','u','r','e','s',0 };
62 static const WCHAR szComponents[] = {
63 'C','o','m','p','o','n','e','n','t','s',0 };
65 /* the UI level */
66 INSTALLUILEVEL gUILevel;
67 HWND gUIhwnd;
68 INSTALLUI_HANDLERA gUIHandler;
69 DWORD gUIFilter;
70 LPVOID gUIContext;
71 WCHAR gszLogFile[MAX_PATH];
74 * .MSI file format
76 * A .msi file is a structured storage file.
77 * It should contain a number of streams.
80 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
82 DWORD i,n=0;
84 out[n++]='{';
85 for(i=0; i<8; i++)
86 out[n++] = in[7-i];
87 out[n++]='-';
88 for(i=0; i<4; i++)
89 out[n++] = in[11-i];
90 out[n++]='-';
91 for(i=0; i<4; i++)
92 out[n++] = in[15-i];
93 out[n++]='-';
94 for(i=0; i<2; i++)
96 out[n++] = in[17+i*2];
97 out[n++] = in[16+i*2];
99 out[n++]='-';
100 for( ; i<8; i++)
102 out[n++] = in[17+i*2];
103 out[n++] = in[16+i*2];
105 out[n++]='}';
106 out[n]=0;
107 return TRUE;
110 BOOL squash_guid(LPCWSTR in, LPWSTR out)
112 DWORD i,n=0;
114 if(in[n++] != '{')
115 return FALSE;
116 for(i=0; i<8; i++)
117 out[7-i] = in[n++];
118 if(in[n++] != '-')
119 return FALSE;
120 for(i=0; i<4; i++)
121 out[11-i] = in[n++];
122 if(in[n++] != '-')
123 return FALSE;
124 for(i=0; i<4; i++)
125 out[15-i] = in[n++];
126 if(in[n++] != '-')
127 return FALSE;
128 for(i=0; i<2; i++)
130 out[17+i*2] = in[n++];
131 out[16+i*2] = in[n++];
133 if(in[n++] != '-')
134 return FALSE;
135 for( ; i<8; i++)
137 out[17+i*2] = in[n++];
138 out[16+i*2] = in[n++];
140 out[32]=0;
141 if(in[n++] != '}')
142 return FALSE;
143 if(in[n])
144 return FALSE;
145 return TRUE;
148 /* tables for encoding and decoding base85 */
149 static const unsigned char table_dec85[0x80] = {
150 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
151 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
152 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
153 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
154 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
155 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
156 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
157 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
160 static const char table_enc85[] =
161 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
162 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
163 "yz{}~";
166 * Converts a base85 encoded guid into a GUID pointer
167 * Base85 encoded GUIDs should be 20 characters long.
169 * returns TRUE if successful, FALSE if not
171 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
173 DWORD i, val = 0, base = 1, *p;
175 p = (DWORD*) guid;
176 for( i=0; i<20; i++ )
178 if( (i%5) == 0 )
180 val = 0;
181 base = 1;
183 val += table_dec85[str[i]] * base;
184 if( str[i] >= 0x80 )
185 return FALSE;
186 if( table_dec85[str[i]] == 0xff )
187 return FALSE;
188 if( (i%5) == 4 )
189 p[i/5] = val;
190 base *= 85;
192 return TRUE;
196 * Encodes a base85 guid given a GUID pointer
197 * Caller should provide a 21 character buffer for the encoded string.
199 * returns TRUE if successful, FALSE if not
201 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
203 unsigned int x, *p, i;
205 p = (unsigned int*) guid;
206 for( i=0; i<4; i++ )
208 x = p[i];
209 *str++ = table_enc85[x%85];
210 x = x/85;
211 *str++ = table_enc85[x%85];
212 x = x/85;
213 *str++ = table_enc85[x%85];
214 x = x/85;
215 *str++ = table_enc85[x%85];
216 x = x/85;
217 *str++ = table_enc85[x%85];
219 *str = 0;
221 return TRUE;
225 VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
227 MSIDATABASE *db = (MSIDATABASE *) arg;
229 free_cached_tables( db );
230 IStorage_Release( db->storage );
233 UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
235 IStorage *stg = NULL;
236 HRESULT r;
237 MSIDATABASE *db = NULL;
238 UINT ret = ERROR_FUNCTION_FAILED;
239 LPWSTR szMode;
240 STATSTG stat;
242 TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
244 if( !pdb )
245 return ERROR_INVALID_PARAMETER;
247 szMode = (LPWSTR) szPersist;
248 if( HIWORD( szPersist ) )
250 /* UINT len = lstrlenW( szPerist ) + 1; */
251 FIXME("don't support persist files yet\b");
252 return ERROR_INVALID_PARAMETER;
253 /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */
255 else if( szPersist == MSIDBOPEN_READONLY )
257 r = StgOpenStorage( szDBPath, NULL,
258 STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
260 else if( szPersist == MSIDBOPEN_CREATE )
262 r = StgCreateDocfile( szDBPath,
263 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
264 if( r == ERROR_SUCCESS )
266 IStorage_SetClass( stg, &CLSID_MsiDatabase );
267 r = init_string_table( stg );
270 else if( szPersist == MSIDBOPEN_TRANSACT )
272 r = StgOpenStorage( szDBPath, NULL,
273 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
275 else
277 ERR("unknown flag %p\n",szPersist);
278 return ERROR_INVALID_PARAMETER;
281 if( FAILED( r ) )
283 FIXME("open failed r = %08lx!\n",r);
284 return ERROR_FUNCTION_FAILED;
287 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
288 if( FAILED( r ) )
290 FIXME("Failed to stat storage\n");
291 goto end;
294 if( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) )
296 ERR("storage GUID is not a MSI database GUID %s\n",
297 debugstr_guid(&stat.clsid) );
298 goto end;
302 db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
303 MSI_CloseDatabase );
304 if( !db )
306 FIXME("Failed to allocate a handle\n");
307 goto end;
310 if( TRACE_ON( msi ) )
311 enum_stream_names( stg );
313 db->storage = stg;
314 db->mode = szMode;
316 ret = load_string_table( db );
317 if( ret != ERROR_SUCCESS )
318 goto end;
320 msiobj_addref( &db->hdr );
321 IStorage_AddRef( stg );
322 *pdb = db;
324 end:
325 if( db )
326 msiobj_release( &db->hdr );
327 if( stg )
328 IStorage_Release( stg );
330 return ret;
333 UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
335 MSIDATABASE *db;
336 UINT ret;
338 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
340 ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
341 if( ret == ERROR_SUCCESS )
343 *phDB = alloc_msihandle( &db->hdr );
344 msiobj_release( &db->hdr );
347 return ret;
350 UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
352 HRESULT r = ERROR_FUNCTION_FAILED;
353 LPWSTR szwDBPath = NULL, szwPersist = NULL;
354 UINT len;
356 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
358 if( szDBPath )
360 len = MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, NULL, 0 );
361 szwDBPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
362 if( !szwDBPath )
363 goto end;
364 MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, szwDBPath, len );
367 if( HIWORD(szPersist) )
369 len = MultiByteToWideChar( CP_ACP, 0, szPersist, -1, NULL, 0 );
370 szwPersist = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
371 if( !szwPersist )
372 goto end;
373 MultiByteToWideChar( CP_ACP, 0, szPersist, -1, szwPersist, len );
375 else
376 szwPersist = (LPWSTR) szPersist;
378 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
380 end:
381 if( szwPersist )
382 HeapFree( GetProcessHeap(), 0, szwPersist );
383 if( szwDBPath )
384 HeapFree( GetProcessHeap(), 0, szwDBPath );
386 return r;
389 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
391 UINT len, ret;
392 LPWSTR szwProd = NULL;
394 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
396 if( szProduct )
398 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
399 szwProd = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
400 if( szwProd )
401 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProd, len );
404 ret = MsiOpenProductW( szwProd, phProduct );
406 if( szwProd )
407 HeapFree( GetProcessHeap(), 0, szwProd );
409 return ret;
412 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
414 static const WCHAR szKey[] = {
415 'S','o','f','t','w','a','r','e','\\',
416 'M','i','c','r','o','s','o','f','t','\\',
417 'W','i','n','d','o','w','s','\\',
418 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
419 'U','n','i','n','s','t','a','l','l',0 };
420 static const WCHAR szLocalPackage[] = {
421 'L','o','c','a','l','P','a','c','k','a','g','e', 0
423 LPWSTR path = NULL;
424 UINT r;
425 HKEY hKeyProduct = NULL, hKeyUninstall = NULL;
426 DWORD count, type;
428 TRACE("%s %p\n",debugstr_w(szProduct), phProduct);
430 r = RegOpenKeyW( HKEY_LOCAL_MACHINE, szKey, &hKeyUninstall );
431 if( r != ERROR_SUCCESS )
432 return ERROR_UNKNOWN_PRODUCT;
434 r = RegOpenKeyW( hKeyUninstall, szProduct, &hKeyProduct );
435 if( r != ERROR_SUCCESS )
437 r = ERROR_UNKNOWN_PRODUCT;
438 goto end;
441 /* find the size of the path */
442 type = count = 0;
443 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
444 NULL, &type, NULL, &count );
445 if( r != ERROR_SUCCESS )
447 r = ERROR_UNKNOWN_PRODUCT;
448 goto end;
451 /* now alloc and fetch the path of the database to open */
452 path = HeapAlloc( GetProcessHeap(), 0, count );
453 if( !path )
454 goto end;
456 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
457 NULL, &type, (LPBYTE) path, &count );
458 if( r != ERROR_SUCCESS )
460 r = ERROR_UNKNOWN_PRODUCT;
461 goto end;
464 r = MsiOpenPackageW( path, phProduct );
466 end:
467 if( path )
468 HeapFree( GetProcessHeap(), 0, path );
469 if( hKeyProduct )
470 RegCloseKey( hKeyProduct );
471 RegCloseKey( hKeyUninstall );
473 return r;
476 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage)
478 FIXME("%s %s %s 0x%08x\n",debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
479 return ERROR_CALL_NOT_IMPLEMENTED;
482 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage)
484 FIXME("%s %s %s 0x%08x\n",debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
485 return ERROR_CALL_NOT_IMPLEMENTED;
488 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
490 FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
491 debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage, dwPlatform, dwOptions);
492 return ERROR_CALL_NOT_IMPLEMENTED;
495 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
497 FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
498 debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage, dwPlatform, dwOptions);
499 return ERROR_CALL_NOT_IMPLEMENTED;
502 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
504 LPWSTR szwPath = NULL, szwCommand = NULL;
505 UINT r = ERROR_FUNCTION_FAILED; /* FIXME: check return code */
507 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
509 if( szPackagePath )
511 UINT len = MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, NULL, 0 );
512 szwPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
513 if( !szwPath )
514 goto end;
515 MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, szwPath, len );
518 if( szCommandLine )
520 UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 );
521 szwCommand = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
522 if( !szwCommand )
523 goto end;
524 MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommand, len );
527 r = MsiInstallProductW( szwPath, szwCommand );
529 end:
530 if( szwPath )
531 HeapFree( GetProcessHeap(), 0, szwPath );
533 if( szwCommand )
534 HeapFree( GetProcessHeap(), 0, szwCommand );
536 return r;
539 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
541 MSIPACKAGE *package = NULL;
542 UINT rc = ERROR_SUCCESS;
543 MSIHANDLE handle;
545 FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
547 rc = MsiVerifyPackageW(szPackagePath);
548 if (rc != ERROR_SUCCESS)
549 return rc;
551 rc = MSI_OpenPackageW(szPackagePath,&package);
552 if (rc != ERROR_SUCCESS)
553 return rc;
555 handle = alloc_msihandle( &package->hdr );
557 rc = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine);
559 MsiCloseHandle(handle);
560 msiobj_release( &package->hdr );
561 return rc;
564 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
566 LPWSTR szwProduct = NULL;
567 UINT hr = ERROR_SUCCESS;
569 FIXME("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
571 if( szProduct )
573 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
574 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
575 if( !szwProduct )
576 goto end;
577 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
580 hr = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
582 end:
583 if( szwProduct )
584 HeapFree( GetProcessHeap(), 0, szwProduct );
586 return hr;
589 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
591 FIXME("%s %d %d\n",debugstr_w(szProduct), iInstallLevel, eInstallState);
592 return ERROR_CALL_NOT_IMPLEMENTED;
595 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
597 LPWSTR szwComponent = NULL, szwBuffer = NULL;
598 UINT hr = ERROR_INSTALL_FAILURE;
600 FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
602 if( szComponent )
604 UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
605 szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
606 if( !szwComponent )
607 goto end;
608 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
609 } else {
610 return ERROR_INVALID_PARAMETER;
614 szwBuffer = HeapAlloc( GetProcessHeap(), 0, GUID_SIZE * sizeof(WCHAR) );
615 if( !szwBuffer )
616 goto end;
619 hr = MsiGetProductCodeW( szwComponent, szwBuffer );
621 if( ERROR_SUCCESS == hr )
623 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
626 end:
627 if( szwComponent )
628 HeapFree( GetProcessHeap(), 0, szwComponent );
629 if( szwBuffer )
630 HeapFree( GetProcessHeap(), 0, szwBuffer );
632 return hr;
635 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
637 FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer));
638 if (NULL == szComponent) {
639 return ERROR_INVALID_PARAMETER;
641 return ERROR_CALL_NOT_IMPLEMENTED;
647 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, DWORD *pcchValueBuf)
649 LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
650 UINT hr = ERROR_INSTALL_FAILURE;
652 FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), szBuffer, pcchValueBuf);
654 if (NULL != szBuffer && NULL == pcchValueBuf) {
655 return ERROR_INVALID_PARAMETER;
657 if( szProduct )
659 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
660 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
661 if( !szwProduct )
662 goto end;
663 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
664 } else {
665 return ERROR_INVALID_PARAMETER;
668 if( szAttribute )
670 UINT len = MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, NULL, 0 );
671 szwAttribute = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
672 if( !szwAttribute )
673 goto end;
674 MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, szwAttribute, len );
675 } else {
676 return ERROR_INVALID_PARAMETER;
679 if( szBuffer )
681 szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
682 if( !szwBuffer )
683 goto end;
686 hr = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf );
688 if( ERROR_SUCCESS == hr )
690 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL);
693 end:
694 if( szwProduct )
695 HeapFree( GetProcessHeap(), 0, szwProduct );
696 if( szwAttribute )
697 HeapFree( GetProcessHeap(), 0, szwAttribute );
698 if( szwBuffer )
699 HeapFree( GetProcessHeap(), 0, szwBuffer );
701 return hr;
704 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szBuffer, DWORD *pcchValueBuf)
706 MSIHANDLE hProduct;
707 UINT hr;
709 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), szBuffer, pcchValueBuf);
711 if (NULL != szBuffer && NULL == pcchValueBuf) {
712 return ERROR_INVALID_PARAMETER;
714 if (NULL == szProduct || NULL == szAttribute) {
715 return ERROR_INVALID_PARAMETER;
718 hr = MsiOpenProductW(szProduct, &hProduct);
719 if (ERROR_SUCCESS != hr) return hr;
721 hr = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
722 MsiCloseHandle(hProduct);
723 return hr;
726 UINT WINAPI MsiDatabaseImportA(LPCSTR szFolderPath, LPCSTR szFilename)
728 FIXME("%s %s\n",debugstr_a(szFolderPath), debugstr_a(szFilename));
729 return ERROR_CALL_NOT_IMPLEMENTED;
732 UINT WINAPI MsiDatabaseImportW(LPCWSTR szFolderPath, LPCWSTR szFilename)
734 FIXME("%s %s\n",debugstr_w(szFolderPath), debugstr_w(szFilename));
735 return ERROR_CALL_NOT_IMPLEMENTED;
738 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, BOOL fAppend)
740 LPWSTR szwLogFile = NULL;
741 UINT hr = ERROR_INSTALL_FAILURE;
743 FIXME("%08lx %s %d\n", dwLogMode, debugstr_a(szLogFile), fAppend);
745 if( szLogFile )
747 UINT len = MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, NULL, 0 );
748 szwLogFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
749 if( !szwLogFile )
750 goto end;
751 MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, szwLogFile, len );
752 } else {
753 return ERROR_INVALID_PARAMETER;
756 hr = MsiEnableLogW( dwLogMode, szwLogFile, fAppend );
758 end:
759 if( szwLogFile )
760 HeapFree( GetProcessHeap(), 0, szwLogFile );
762 return hr;
765 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, BOOL fAppend)
767 HANDLE the_file = INVALID_HANDLE_VALUE;
768 TRACE("%08lx %s %d\n", dwLogMode, debugstr_w(szLogFile), fAppend);
769 strcpyW(gszLogFile,szLogFile);
770 if (!fAppend)
771 DeleteFileW(szLogFile);
772 the_file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
773 FILE_ATTRIBUTE_NORMAL, NULL);
774 if (the_file != INVALID_HANDLE_VALUE)
775 CloseHandle(the_file);
776 else
777 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
779 return ERROR_SUCCESS;
782 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
784 FIXME("%s\n", debugstr_a(szProduct));
785 return INSTALLSTATE_UNKNOWN;
788 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
790 FIXME("%s\n", debugstr_w(szProduct));
791 return INSTALLSTATE_UNKNOWN;
794 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
796 INSTALLUILEVEL old = gUILevel;
797 HWND oldwnd = gUIhwnd;
798 TRACE("%08x %p\n", dwUILevel, phWnd);
800 gUILevel = dwUILevel;
801 if (phWnd)
803 gUIhwnd = *phWnd;
804 *phWnd = oldwnd;
806 return old;
809 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
810 DWORD dwMessageFilter, LPVOID pvContext)
812 INSTALLUI_HANDLERA prev = gUIHandler;
814 TRACE("(%p %lx %p)\n",puiHandler,dwMessageFilter,pvContext);
815 gUIHandler = puiHandler;
816 gUIFilter = dwMessageFilter;
817 gUIContext = pvContext;
819 return prev;
822 UINT WINAPI MsiLoadStringA(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax, DWORD e)
824 /*FIXME("%08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e);*/
825 FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
826 return ERROR_CALL_NOT_IMPLEMENTED;
829 UINT WINAPI MsiLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax, DWORD e)
831 FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
833 int ret = LoadStringW(hInstance,uID,lpBuffer,nBufferMax);
834 FIXME("%s\n",debugstr_w(lpBuffer));
835 return ret;
837 return ERROR_CALL_NOT_IMPLEMENTED;
840 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
842 FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
843 return INSTALLSTATE_UNKNOWN;
846 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
848 FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
849 return INSTALLSTATE_UNKNOWN;
852 #include "winuser.h"
854 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
856 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),uType,wLanguageId,f);
858 MessageBoxExA(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
860 return ERROR_CALL_NOT_IMPLEMENTED;
863 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
865 /*FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);*/
866 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),uType,wLanguageId,f);
868 MessageBoxExW(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
870 return ERROR_CALL_NOT_IMPLEMENTED;
873 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
875 DWORD r;
876 WCHAR szwGuid[GUID_SIZE];
878 TRACE("%ld %p\n",index,lpguid);
880 if (NULL == lpguid) {
881 return ERROR_INVALID_PARAMETER;
883 r = MsiEnumProductsW(index, szwGuid);
884 if( r == ERROR_SUCCESS )
885 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
887 return r;
890 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
892 HKEY hkey = 0, hkeyFeatures = 0;
893 DWORD r;
894 WCHAR szKeyName[33];
896 TRACE("%ld %p\n",index,lpguid);
898 if (NULL == lpguid) {
899 return ERROR_INVALID_PARAMETER;
901 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
902 if( r != ERROR_SUCCESS )
903 goto end;
905 r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
906 if( r != ERROR_SUCCESS )
907 goto end;
909 r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE);
911 unsquash_guid(szKeyName, lpguid);
913 end:
915 if( hkeyFeatures )
916 RegCloseKey(hkeyFeatures);
917 if( hkey )
918 RegCloseKey(hkey);
920 return r;
923 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
924 LPSTR szFeature, LPSTR szParent)
926 DWORD r;
927 WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
928 LPWSTR szwProduct = NULL;
930 TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent);
932 if( szProduct )
934 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
935 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
936 if( szwProduct )
937 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
938 else
939 return ERROR_FUNCTION_FAILED;
942 r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
943 if( r == ERROR_SUCCESS )
945 WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
946 szFeature, GUID_SIZE, NULL, NULL);
947 WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
948 szParent, GUID_SIZE, NULL, NULL);
951 if( szwProduct )
952 HeapFree( GetProcessHeap(), 0, szwProduct);
954 return r;
957 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
958 LPWSTR szFeature, LPWSTR szParent)
960 HKEY hkey = 0, hkeyFeatures = 0, hkeyProduct = 0;
961 DWORD r, sz;
962 WCHAR szRegName[GUID_SIZE];
964 TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent);
966 if( !squash_guid(szProduct, szRegName) )
967 return ERROR_INVALID_PARAMETER;
969 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
970 if( r != ERROR_SUCCESS )
971 goto end;
973 r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
974 if( r != ERROR_SUCCESS )
975 goto end;
977 r = RegOpenKeyW(hkeyFeatures, szRegName, &hkeyProduct);
978 if( r != ERROR_SUCCESS )
979 goto end;
981 sz = GUID_SIZE;
982 r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
984 end:
985 if( hkeyProduct )
986 RegCloseKey(hkeyProduct);
987 if( hkeyFeatures )
988 RegCloseKey(hkeyFeatures);
989 if( hkey )
990 RegCloseKey(hkey);
992 return r;
995 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
997 DWORD r;
998 WCHAR szwGuid[GUID_SIZE];
1000 TRACE("%ld %p\n",index,lpguid);
1002 r = MsiEnumComponentsW(index, szwGuid);
1003 if( r == ERROR_SUCCESS )
1004 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1006 return r;
1009 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1011 HKEY hkey = 0, hkeyComponents = 0;
1012 DWORD r;
1013 WCHAR szKeyName[33];
1015 TRACE("%ld %p\n",index,lpguid);
1017 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
1018 if( r != ERROR_SUCCESS )
1019 goto end;
1021 r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
1022 if( r != ERROR_SUCCESS )
1023 goto end;
1025 r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE);
1027 unsquash_guid(szKeyName, lpguid);
1029 end:
1031 if( hkeyComponents )
1032 RegCloseKey(hkeyComponents);
1033 if( hkey )
1034 RegCloseKey(hkey);
1036 return r;
1039 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1041 DWORD r;
1042 WCHAR szwProduct[GUID_SIZE];
1043 LPWSTR szwComponent = NULL;
1045 TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct);
1047 if( szComponent )
1049 UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1050 szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
1051 if( szwComponent )
1052 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1053 else
1054 return ERROR_FUNCTION_FAILED;
1057 r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1058 if( r == ERROR_SUCCESS )
1060 WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1061 szProduct, GUID_SIZE, NULL, NULL);
1064 if( szwComponent )
1065 HeapFree( GetProcessHeap(), 0, szwComponent);
1067 return r;
1070 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1072 HKEY hkey = 0, hkeyComponents = 0, hkeyComp = 0;
1073 DWORD r, sz;
1074 WCHAR szRegName[GUID_SIZE], szValName[GUID_SIZE];
1076 TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct);
1078 if( !squash_guid(szComponent, szRegName) )
1079 return ERROR_INVALID_PARAMETER;
1081 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
1082 if( r != ERROR_SUCCESS )
1083 goto end;
1085 r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
1086 if( r != ERROR_SUCCESS )
1087 goto end;
1089 r = RegOpenKeyW(hkeyComponents, szRegName, &hkeyComp);
1090 if( r != ERROR_SUCCESS )
1091 goto end;
1093 sz = GUID_SIZE;
1094 r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1095 if( r != ERROR_SUCCESS )
1096 goto end;
1098 unsquash_guid(szValName, szProduct);
1100 end:
1101 if( hkeyComp )
1102 RegCloseKey(hkeyComp);
1103 if( hkeyComponents )
1104 RegCloseKey(hkeyComponents);
1105 if( hkey )
1106 RegCloseKey(hkey);
1108 return r;
1111 UINT WINAPI MsiEnumComponentQualifiersA(
1112 LPSTR szComponent, DWORD iIndex, LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1114 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1115 return ERROR_CALL_NOT_IMPLEMENTED;
1118 UINT WINAPI MsiEnumComponentQualifiersW(
1119 LPWSTR szComponent, DWORD iIndex, LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1121 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1122 return ERROR_CALL_NOT_IMPLEMENTED;
1125 UINT WINAPI MsiProvideAssemblyA(
1126 LPCSTR szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, DWORD* pcchPathBuf)
1128 FIXME("%s %s 0x%08lx 0x%08lx %p %p\n",
1129 debugstr_a(szAssemblyName), debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1130 return ERROR_CALL_NOT_IMPLEMENTED;
1133 UINT WINAPI MsiProvideAssemblyW(
1134 LPCWSTR szAssemblyName, LPCWSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD* pcchPathBuf)
1136 FIXME("%s %s 0x%08lx 0x%08lx %p %p\n",
1137 debugstr_w(szAssemblyName), debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1138 return ERROR_CALL_NOT_IMPLEMENTED;
1141 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1143 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1144 return ERROR_CALL_NOT_IMPLEMENTED;
1147 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1149 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1150 return ERROR_CALL_NOT_IMPLEMENTED;
1153 HRESULT WINAPI MsiGetFileSignatureInformationA(
1154 LPCSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1156 FIXME("%s 0x%08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1157 return ERROR_CALL_NOT_IMPLEMENTED;
1160 HRESULT WINAPI MsiGetFileSignatureInformationW(
1161 LPCWSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1163 FIXME("%s 0x%08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1164 return ERROR_CALL_NOT_IMPLEMENTED;
1167 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1168 LPSTR szValue, DWORD *pccbValue )
1170 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1171 return ERROR_CALL_NOT_IMPLEMENTED;
1174 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1175 LPWSTR szValue, DWORD *pccbValue )
1177 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1178 return ERROR_CALL_NOT_IMPLEMENTED;
1181 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1183 UINT r, len;
1184 LPWSTR szPack = NULL;
1186 TRACE("%s\n", debugstr_a(szPackage) );
1188 if( szPackage )
1190 len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
1191 szPack = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1192 if( !szPack )
1193 return ERROR_OUTOFMEMORY;
1194 MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szPack, len );
1197 r = MsiVerifyPackageW( szPack );
1199 HeapFree( GetProcessHeap(), 0, szPack );
1201 return r;
1204 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1206 MSIHANDLE handle;
1207 UINT r;
1209 TRACE("%s\n", debugstr_w(szPackage) );
1211 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1212 MsiCloseHandle( handle );
1214 return r;
1217 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1218 LPSTR lpPathBuf, DWORD* pcchBuf)
1220 INSTALLSTATE rc;
1221 UINT len;
1222 LPWSTR szwProduct= NULL;
1223 LPWSTR szwComponent= NULL;
1224 LPWSTR lpwPathBuf= NULL;
1226 if( szProduct)
1228 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1229 szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1230 if( !szwProduct)
1231 return ERROR_OUTOFMEMORY;
1232 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1235 if( szComponent)
1237 len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1238 szwComponent= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1239 if( !szwComponent)
1240 return ERROR_OUTOFMEMORY;
1241 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1244 if (pcchBuf && *pcchBuf > 0)
1245 lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR));
1246 else
1247 lpwPathBuf = NULL;
1249 rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
1251 HeapFree( GetProcessHeap(), 0, szwProduct);
1252 HeapFree( GetProcessHeap(), 0, szwComponent);
1253 if (lpwPathBuf)
1255 WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, *pcchBuf,
1256 lpPathBuf, GUID_SIZE, NULL, NULL);
1257 HeapFree( GetProcessHeap(), 0, lpwPathBuf);
1260 return rc;
1263 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1264 LPWSTR lpPathBuf, DWORD* pcchBuf)
1266 FIXME("STUB: (%s %s %p %p)\n", debugstr_w(szProduct),
1267 debugstr_w(szComponent), lpPathBuf, pcchBuf);
1269 return INSTALLSTATE_UNKNOWN;
1272 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1274 INSTALLSTATE rc;
1275 UINT len;
1276 LPWSTR szwProduct= NULL;
1277 LPWSTR szwFeature= NULL;
1279 if( szProduct)
1281 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1282 szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1283 if( !szwProduct)
1284 return ERROR_OUTOFMEMORY;
1285 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1288 if( szFeature)
1290 len = MultiByteToWideChar( CP_ACP, 0, szFeature, -1, NULL, 0 );
1291 szwFeature= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1292 if( !szwFeature)
1293 return ERROR_OUTOFMEMORY;
1294 MultiByteToWideChar( CP_ACP, 0, szFeature, -1, szwFeature, len );
1297 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1299 HeapFree( GetProcessHeap(), 0, szwProduct);
1300 HeapFree( GetProcessHeap(), 0, szwFeature);
1302 return rc;
1305 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1307 FIXME("STUB: (%s %s)\n", debugstr_w(szProduct), debugstr_w(szFeature));
1308 return INSTALLSTATE_UNKNOWN;
1312 /******************************************************************
1313 * DllMain
1315 * @todo: maybe we can check here if MsiServer service is declared no ?
1317 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
1318 if (fdwReason == DLL_PROCESS_ATTACH) {
1319 DisableThreadLibraryCalls(hinstDLL);
1321 * UI Initialization
1323 gUILevel = INSTALLUILEVEL_BASIC;
1324 gUIhwnd = 0;
1325 gUIHandler = NULL;
1326 gUIFilter = 0;
1327 gUIContext = NULL;
1328 gszLogFile[0]=0;
1329 /* FIXME: Initialisation */
1330 } else if (fdwReason == DLL_PROCESS_DETACH) {
1331 /* FIXME: Cleanup */
1334 static const WCHAR szMSIServerSvc[] = { 'M','S','I','S','e','r','v','e','r',0 };
1335 static const WCHAR szNull[] = { 0 };
1336 if (!strcmpW(lpServiceName, szMSIServerSvc)) {
1337 hKey = CreateServiceW(hSCManager,
1338 szMSIServerSvc,
1339 szMSIServerSvc,
1340 SC_MANAGER_ALL_ACCESS,
1341 SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
1342 SERVICE_AUTO_START,
1343 SERVICE_ERROR_IGNORE,
1344 szNull,
1345 NULL,
1346 NULL,
1347 NULL,
1348 NULL,
1349 szNull);
1351 return TRUE;
1354 typedef struct {
1355 /* IUnknown fields */
1356 ICOM_VFIELD(IClassFactory);
1357 DWORD ref;
1358 } IClassFactoryImpl;
1360 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1361 ICOM_THIS(IClassFactoryImpl,iface);
1362 FIXME("(%p, %s, %p): stub\n",This,debugstr_guid(riid),ppobj);
1363 return E_NOINTERFACE;
1366 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface) {
1367 ICOM_THIS(IClassFactoryImpl,iface);
1368 return ++(This->ref);
1371 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) {
1372 ICOM_THIS(IClassFactoryImpl,iface);
1373 /* static class, won't be freed */
1374 return --(This->ref);
1377 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) {
1378 ICOM_THIS(IClassFactoryImpl,iface);
1379 FIXME ("(%p, %p, %s, %p): to implement\n", This, pOuter, debugstr_guid(riid), ppobj);
1380 return 0;
1383 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1384 ICOM_THIS(IClassFactoryImpl,iface);
1385 FIXME("(%p, %d): stub\n", This, dolock);
1386 return S_OK;
1389 static ICOM_VTABLE(IClassFactory) MsiCF_Vtbl = {
1390 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1391 MsiCF_QueryInterface,
1392 MsiCF_AddRef,
1393 MsiCF_Release,
1394 MsiCF_CreateInstance,
1395 MsiCF_LockServer
1398 static IClassFactoryImpl Msi_CF = {&MsiCF_Vtbl, 1 };
1400 /******************************************************************
1401 * DllGetClassObject (MSI.@)
1403 HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) {
1404 FIXME("(%s, %s, %p): almost a stub.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1405 if (IsEqualCLSID (rclsid, &CLSID_IMsiServer)) {
1406 *ppv = (LPVOID) &Msi_CF;
1407 IClassFactory_AddRef((IClassFactory*)*ppv);
1408 return S_OK;
1409 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage)) {
1410 *ppv = (LPVOID) &Msi_CF;
1411 IClassFactory_AddRef((IClassFactory*)*ppv);
1412 return S_OK;
1413 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX1)) {
1414 *ppv = (LPVOID) &Msi_CF;
1415 IClassFactory_AddRef((IClassFactory*)*ppv);
1416 return S_OK;
1417 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX2)) {
1418 *ppv = (LPVOID) &Msi_CF;
1419 IClassFactory_AddRef((IClassFactory*)*ppv);
1420 return S_OK;
1421 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX3)) {
1422 *ppv = (LPVOID) &Msi_CF;
1423 IClassFactory_AddRef((IClassFactory*)*ppv);
1424 return S_OK;
1426 WARN("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1427 return CLASS_E_CLASSNOTAVAILABLE;
1430 /******************************************************************
1431 * DllGetVerison (MSI.@)
1433 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
1435 TRACE("%p\n",pdvi);
1437 if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1438 return E_INVALIDARG;
1440 pdvi->dwMajorVersion = MSI_MAJORVERSION;
1441 pdvi->dwMinorVersion = MSI_MINORVERSION;
1442 pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1443 pdvi->dwPlatformID = 1;
1445 return S_OK;
1448 /******************************************************************
1449 * DllCanUnloadNow (MSI.@)
1451 BOOL WINAPI MSI_DllCanUnloadNow(void)
1453 return S_FALSE;
1456 UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
1457 DWORD iProductIndex, LPSTR lpProductBuf)
1459 FIXME("STUB: (%s, %li %li %s)\n",lpUpgradeCode, dwReserved, iProductIndex,
1460 lpProductBuf);
1461 return ERROR_CALL_NOT_IMPLEMENTED;