Cleanup of actions.
[wine.git] / dlls / msi / msi.c
blobf60deb299fb559240be23c664fbb4a9091faceb5
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002,2003 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 VOID MSI_CloseDatabase( VOID *arg )
150 MSIDATABASE *db = (MSIDATABASE *) arg;
152 free_cached_tables( db );
153 IStorage_Release( db->storage );
156 UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
158 HRESULT r = ERROR_FUNCTION_FAILED;
159 LPWSTR szwDBPath = NULL, szwPersist = NULL;
160 UINT len;
162 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
164 if( szDBPath )
166 len = MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, NULL, 0 );
167 szwDBPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
168 if( !szwDBPath )
169 goto end;
170 MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, szwDBPath, len );
173 if( HIWORD(szPersist) )
175 len = MultiByteToWideChar( CP_ACP, 0, szPersist, -1, NULL, 0 );
176 szwPersist = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
177 if( !szwPersist )
178 goto end;
179 MultiByteToWideChar( CP_ACP, 0, szPersist, -1, szwPersist, len );
181 else
182 szwPersist = (LPWSTR) szPersist;
184 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
186 end:
187 if( szwPersist )
188 HeapFree( GetProcessHeap(), 0, szwPersist );
189 if( szwDBPath )
190 HeapFree( GetProcessHeap(), 0, szwDBPath );
192 return r;
195 UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
197 IStorage *stg = NULL;
198 HRESULT r;
199 MSIHANDLE handle;
200 MSIDATABASE *db;
201 UINT ret;
202 LPWSTR szMode;
203 STATSTG stat;
205 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
207 if( !phDB )
208 return ERROR_INVALID_PARAMETER;
210 szMode = (LPWSTR) szPersist;
211 if( HIWORD( szPersist ) )
213 /* UINT len = lstrlenW( szPerist ) + 1; */
214 FIXME("don't support persist files yet\b");
215 return ERROR_INVALID_PARAMETER;
216 /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */
218 else if( szPersist == MSIDBOPEN_READONLY )
220 r = StgOpenStorage( szDBPath, NULL,
221 STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
223 else if( szPersist == MSIDBOPEN_CREATE )
225 r = StgCreateDocfile( szDBPath,
226 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
227 if( r == ERROR_SUCCESS )
229 IStorage_SetClass( stg, &CLSID_MsiDatabase );
230 r = init_string_table( stg );
233 else if( szPersist == MSIDBOPEN_TRANSACT )
235 r = StgOpenStorage( szDBPath, NULL,
236 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
238 else
240 ERR("unknown flag %p\n",szPersist);
241 return ERROR_INVALID_PARAMETER;
244 if( FAILED( r ) )
246 FIXME("open failed r = %08lx!\n",r);
247 return ERROR_FUNCTION_FAILED;
250 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
251 if( FAILED( r ) )
253 FIXME("Failed to stat storage\n");
254 ret = ERROR_FUNCTION_FAILED;
255 goto end;
258 if( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) )
260 ERR("storage GUID is not a MSI database GUID %s\n",
261 debugstr_guid(&stat.clsid) );
262 ret = ERROR_FUNCTION_FAILED;
263 goto end;
267 handle = alloc_msihandle( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
268 MSI_CloseDatabase, (void**) &db );
269 if( !handle )
271 FIXME("Failed to allocate a handle\n");
272 ret = ERROR_FUNCTION_FAILED;
273 goto end;
276 if( TRACE_ON( msi ) )
277 enum_stream_names( stg );
279 db->storage = stg;
280 db->mode = szMode;
281 /* db->strings = NULL;
282 db->first_table = NULL;
283 db->last_table = NULL; */
285 ret = load_string_table( db );
286 if( ret != ERROR_SUCCESS )
287 goto end;
289 *phDB = handle;
291 IStorage_AddRef( stg );
292 end:
293 if( stg )
294 IStorage_Release( stg );
296 return ret;
299 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
301 UINT len, ret;
302 LPWSTR szwProd = NULL;
304 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
306 if( szProduct )
308 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
309 szwProd = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
310 if( szwProd )
311 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProd, len );
314 ret = MsiOpenProductW( szwProd, phProduct );
316 if( szwProd )
317 HeapFree( GetProcessHeap(), 0, szwProd );
319 return ret;
322 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
324 static const WCHAR szKey[] = {
325 'S','o','f','t','w','a','r','e','\\',
326 'M','i','c','r','o','s','o','f','t','\\',
327 'W','i','n','d','o','w','s','\\',
328 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
329 'U','n','i','n','s','t','a','l','l',0 };
330 static const WCHAR szLocalPackage[] = {
331 'L','o','c','a','l','P','a','c','k','a','g','e', 0
333 LPWSTR path = NULL;
334 UINT r;
335 HKEY hKeyProduct = NULL, hKeyUninstall = NULL;
336 DWORD count, type;
338 TRACE("%s %p\n",debugstr_w(szProduct), phProduct);
340 r = RegOpenKeyW( HKEY_LOCAL_MACHINE, szKey, &hKeyUninstall );
341 if( r != ERROR_SUCCESS )
342 return ERROR_UNKNOWN_PRODUCT;
344 r = RegOpenKeyW( hKeyUninstall, szProduct, &hKeyProduct );
345 if( r != ERROR_SUCCESS )
347 r = ERROR_UNKNOWN_PRODUCT;
348 goto end;
351 /* find the size of the path */
352 type = count = 0;
353 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
354 NULL, &type, NULL, &count );
355 if( r != ERROR_SUCCESS )
357 r = ERROR_UNKNOWN_PRODUCT;
358 goto end;
361 /* now alloc and fetch the path of the database to open */
362 path = HeapAlloc( GetProcessHeap(), 0, count );
363 if( !path )
364 goto end;
366 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
367 NULL, &type, (LPBYTE) path, &count );
368 if( r != ERROR_SUCCESS )
370 r = ERROR_UNKNOWN_PRODUCT;
371 goto end;
374 r = MsiOpenPackageW( path, phProduct );
376 end:
377 if( path )
378 HeapFree( GetProcessHeap(), 0, path );
379 if( hKeyProduct )
380 RegCloseKey( hKeyProduct );
381 RegCloseKey( hKeyUninstall );
383 return r;
386 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage)
388 FIXME("%s %s %s 0x%08x\n",debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
389 return ERROR_CALL_NOT_IMPLEMENTED;
392 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage)
394 FIXME("%s %s %s 0x%08x\n",debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
395 return ERROR_CALL_NOT_IMPLEMENTED;
398 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
400 FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
401 debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage, dwPlatform, dwOptions);
402 return ERROR_CALL_NOT_IMPLEMENTED;
405 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
407 FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n",
408 debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage, dwPlatform, dwOptions);
409 return ERROR_CALL_NOT_IMPLEMENTED;
412 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
414 LPWSTR szwPath = NULL, szwCommand = NULL;
415 UINT r = ERROR_FUNCTION_FAILED; /* FIXME: check return code */
417 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
419 if( szPackagePath )
421 UINT len = MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, NULL, 0 );
422 szwPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
423 if( !szwPath )
424 goto end;
425 MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, szwPath, len );
428 if( szCommandLine )
430 UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 );
431 szwCommand = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
432 if( !szwCommand )
433 goto end;
434 MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommand, len );
437 r = MsiInstallProductW( szwPath, szwCommand );
439 end:
440 if( szwPath )
441 HeapFree( GetProcessHeap(), 0, szwPath );
443 if( szwCommand )
444 HeapFree( GetProcessHeap(), 0, szwCommand );
446 return r;
449 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
451 MSIHANDLE packagehandle;
452 UINT rc = ERROR_SUCCESS;
454 FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
456 rc = MsiVerifyPackageW(szPackagePath);
457 if (rc != ERROR_SUCCESS)
458 return rc;
460 rc = MsiOpenPackageW(szPackagePath,&packagehandle);
461 if (rc != ERROR_SUCCESS)
462 return rc;
464 ACTION_DoTopLevelINSTALL(packagehandle, szPackagePath, szCommandLine);
466 MsiCloseHandle(packagehandle);
467 return rc;
470 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
472 LPWSTR szwProduct = NULL;
473 UINT hr = ERROR_SUCCESS;
475 FIXME("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
477 if( szProduct )
479 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
480 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
481 if( !szwProduct )
482 goto end;
483 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
486 hr = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
488 end:
489 if( szwProduct )
490 HeapFree( GetProcessHeap(), 0, szwProduct );
492 return hr;
495 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
497 FIXME("%s %d %d\n",debugstr_w(szProduct), iInstallLevel, eInstallState);
498 return ERROR_CALL_NOT_IMPLEMENTED;
501 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
503 LPWSTR szwComponent = NULL, szwBuffer = NULL;
504 UINT hr = ERROR_INSTALL_FAILURE;
506 FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
508 if( szComponent )
510 UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
511 szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
512 if( !szwComponent )
513 goto end;
514 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
515 } else {
516 return ERROR_INVALID_PARAMETER;
520 szwBuffer = HeapAlloc( GetProcessHeap(), 0, GUID_SIZE * sizeof(WCHAR) );
521 if( !szwBuffer )
522 goto end;
525 hr = MsiGetProductCodeW( szwComponent, szwBuffer );
527 if( ERROR_SUCCESS == hr )
529 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
532 end:
533 if( szwComponent )
534 HeapFree( GetProcessHeap(), 0, szwComponent );
535 if( szwBuffer )
536 HeapFree( GetProcessHeap(), 0, szwBuffer );
538 return hr;
541 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
543 FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer));
544 if (NULL == szComponent) {
545 return ERROR_INVALID_PARAMETER;
547 return ERROR_CALL_NOT_IMPLEMENTED;
553 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, DWORD *pcchValueBuf)
555 LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
556 UINT hr = ERROR_INSTALL_FAILURE;
558 FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), szBuffer, pcchValueBuf);
560 if (NULL != szBuffer && NULL == pcchValueBuf) {
561 return ERROR_INVALID_PARAMETER;
563 if( szProduct )
565 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
566 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
567 if( !szwProduct )
568 goto end;
569 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
570 } else {
571 return ERROR_INVALID_PARAMETER;
574 if( szAttribute )
576 UINT len = MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, NULL, 0 );
577 szwAttribute = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
578 if( !szwAttribute )
579 goto end;
580 MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, szwAttribute, len );
581 } else {
582 return ERROR_INVALID_PARAMETER;
585 if( szBuffer )
587 szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
588 if( !szwBuffer )
589 goto end;
592 hr = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf );
594 if( ERROR_SUCCESS == hr )
596 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL);
599 end:
600 if( szwProduct )
601 HeapFree( GetProcessHeap(), 0, szwProduct );
602 if( szwAttribute )
603 HeapFree( GetProcessHeap(), 0, szwAttribute );
604 if( szwBuffer )
605 HeapFree( GetProcessHeap(), 0, szwBuffer );
607 return hr;
610 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szBuffer, DWORD *pcchValueBuf)
612 MSIHANDLE hProduct;
613 UINT hr;
615 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), szBuffer, pcchValueBuf);
617 if (NULL != szBuffer && NULL == pcchValueBuf) {
618 return ERROR_INVALID_PARAMETER;
620 if (NULL == szProduct || NULL == szAttribute) {
621 return ERROR_INVALID_PARAMETER;
624 hr = MsiOpenProductW(szProduct, &hProduct);
625 if (ERROR_SUCCESS != hr) return hr;
627 hr = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
628 MsiCloseHandle(hProduct);
629 return hr;
632 UINT WINAPI MsiDatabaseImportA(LPCSTR szFolderPath, LPCSTR szFilename)
634 FIXME("%s %s\n",debugstr_a(szFolderPath), debugstr_a(szFilename));
635 return ERROR_CALL_NOT_IMPLEMENTED;
638 UINT WINAPI MsiDatabaseImportW(LPCWSTR szFolderPath, LPCWSTR szFilename)
640 FIXME("%s %s\n",debugstr_w(szFolderPath), debugstr_w(szFilename));
641 return ERROR_CALL_NOT_IMPLEMENTED;
644 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, BOOL fAppend)
646 LPWSTR szwLogFile = NULL;
647 UINT hr = ERROR_INSTALL_FAILURE;
649 FIXME("%08lx %s %d\n", dwLogMode, debugstr_a(szLogFile), fAppend);
651 if( szLogFile )
653 UINT len = MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, NULL, 0 );
654 szwLogFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
655 if( !szwLogFile )
656 goto end;
657 MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, szwLogFile, len );
658 } else {
659 return ERROR_INVALID_PARAMETER;
662 hr = MsiEnableLogW( dwLogMode, szwLogFile, fAppend );
664 end:
665 if( szwLogFile )
666 HeapFree( GetProcessHeap(), 0, szwLogFile );
668 return hr;
671 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, BOOL fAppend)
673 HANDLE the_file = INVALID_HANDLE_VALUE;
674 TRACE("%08lx %s %d\n", dwLogMode, debugstr_w(szLogFile), fAppend);
675 strcpyW(gszLogFile,szLogFile);
676 if (!fAppend)
677 DeleteFileW(szLogFile);
678 the_file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
679 FILE_ATTRIBUTE_NORMAL, NULL);
680 if (the_file != INVALID_HANDLE_VALUE)
681 CloseHandle(the_file);
682 else
683 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
685 return ERROR_SUCCESS;
688 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
690 FIXME("%s\n", debugstr_a(szProduct));
691 return INSTALLSTATE_UNKNOWN;
694 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
696 FIXME("%s\n", debugstr_w(szProduct));
697 return INSTALLSTATE_UNKNOWN;
700 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
702 INSTALLUILEVEL old = gUILevel;
703 HWND oldwnd = gUIhwnd;
704 TRACE("%08x %p\n", dwUILevel, phWnd);
706 gUILevel = dwUILevel;
707 if (phWnd)
709 gUIhwnd = *phWnd;
710 *phWnd = oldwnd;
712 return old;
715 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
716 DWORD dwMessageFilter, LPVOID pvContext)
718 INSTALLUI_HANDLERA prev = gUIHandler;
720 TRACE("(%p %lx %p)\n",puiHandler,dwMessageFilter,pvContext);
721 gUIHandler = puiHandler;
722 gUIFilter = dwMessageFilter;
723 gUIContext = pvContext;
725 return prev;
728 UINT WINAPI MsiLoadStringA(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax, DWORD e)
730 /*FIXME("%08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e);*/
731 FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
732 return ERROR_CALL_NOT_IMPLEMENTED;
735 UINT WINAPI MsiLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax, DWORD e)
737 FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e);
739 int ret = LoadStringW(hInstance,uID,lpBuffer,nBufferMax);
740 FIXME("%s\n",debugstr_w(lpBuffer));
741 return ret;
743 return ERROR_CALL_NOT_IMPLEMENTED;
746 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
748 FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
749 return INSTALLSTATE_UNKNOWN;
752 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf)
754 FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
755 return INSTALLSTATE_UNKNOWN;
758 #include "winuser.h"
760 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
762 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),uType,wLanguageId,f);
764 MessageBoxExA(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
766 return ERROR_CALL_NOT_IMPLEMENTED;
769 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f)
771 /*FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);*/
772 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),uType,wLanguageId,f);
774 MessageBoxExW(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId);
776 return ERROR_CALL_NOT_IMPLEMENTED;
779 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
781 DWORD r;
782 WCHAR szwGuid[GUID_SIZE];
784 TRACE("%ld %p\n",index,lpguid);
786 if (NULL == lpguid) {
787 return ERROR_INVALID_PARAMETER;
789 r = MsiEnumProductsW(index, szwGuid);
790 if( r == ERROR_SUCCESS )
791 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
793 return r;
796 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
798 HKEY hkey = 0, hkeyFeatures = 0;
799 DWORD r;
800 WCHAR szKeyName[33];
802 TRACE("%ld %p\n",index,lpguid);
804 if (NULL == lpguid) {
805 return ERROR_INVALID_PARAMETER;
807 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
808 if( r != ERROR_SUCCESS )
809 goto end;
811 r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
812 if( r != ERROR_SUCCESS )
813 goto end;
815 r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE);
817 unsquash_guid(szKeyName, lpguid);
819 end:
821 if( hkeyFeatures )
822 RegCloseKey(hkeyFeatures);
823 if( hkey )
824 RegCloseKey(hkey);
826 return r;
829 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
830 LPSTR szFeature, LPSTR szParent)
832 DWORD r;
833 WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
834 LPWSTR szwProduct = NULL;
836 TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent);
838 if( szProduct )
840 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
841 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
842 if( szwProduct )
843 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
844 else
845 return ERROR_FUNCTION_FAILED;
848 r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
849 if( r == ERROR_SUCCESS )
851 WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
852 szFeature, GUID_SIZE, NULL, NULL);
853 WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
854 szParent, GUID_SIZE, NULL, NULL);
857 if( szwProduct )
858 HeapFree( GetProcessHeap(), 0, szwProduct);
860 return r;
863 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
864 LPWSTR szFeature, LPWSTR szParent)
866 HKEY hkey = 0, hkeyFeatures = 0, hkeyProduct = 0;
867 DWORD r, sz;
868 WCHAR szRegName[GUID_SIZE];
870 TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent);
872 if( !squash_guid(szProduct, szRegName) )
873 return ERROR_INVALID_PARAMETER;
875 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
876 if( r != ERROR_SUCCESS )
877 goto end;
879 r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures);
880 if( r != ERROR_SUCCESS )
881 goto end;
883 r = RegOpenKeyW(hkeyFeatures, szRegName, &hkeyProduct);
884 if( r != ERROR_SUCCESS )
885 goto end;
887 sz = GUID_SIZE;
888 r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
890 end:
891 if( hkeyProduct )
892 RegCloseKey(hkeyProduct);
893 if( hkeyFeatures )
894 RegCloseKey(hkeyFeatures);
895 if( hkey )
896 RegCloseKey(hkey);
898 return r;
901 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
903 DWORD r;
904 WCHAR szwGuid[GUID_SIZE];
906 TRACE("%ld %p\n",index,lpguid);
908 r = MsiEnumComponentsW(index, szwGuid);
909 if( r == ERROR_SUCCESS )
910 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
912 return r;
915 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
917 HKEY hkey = 0, hkeyComponents = 0;
918 DWORD r;
919 WCHAR szKeyName[33];
921 TRACE("%ld %p\n",index,lpguid);
923 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
924 if( r != ERROR_SUCCESS )
925 goto end;
927 r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
928 if( r != ERROR_SUCCESS )
929 goto end;
931 r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE);
933 unsquash_guid(szKeyName, lpguid);
935 end:
937 if( hkeyComponents )
938 RegCloseKey(hkeyComponents);
939 if( hkey )
940 RegCloseKey(hkey);
942 return r;
945 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
947 DWORD r;
948 WCHAR szwProduct[GUID_SIZE];
949 LPWSTR szwComponent = NULL;
951 TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct);
953 if( szComponent )
955 UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
956 szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
957 if( szwComponent )
958 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
959 else
960 return ERROR_FUNCTION_FAILED;
963 r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
964 if( r == ERROR_SUCCESS )
966 WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
967 szProduct, GUID_SIZE, NULL, NULL);
970 if( szwComponent )
971 HeapFree( GetProcessHeap(), 0, szwComponent);
973 return r;
976 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
978 HKEY hkey = 0, hkeyComponents = 0, hkeyComp = 0;
979 DWORD r, sz;
980 WCHAR szRegName[GUID_SIZE], szValName[GUID_SIZE];
982 TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct);
984 if( !squash_guid(szComponent, szRegName) )
985 return ERROR_INVALID_PARAMETER;
987 r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey);
988 if( r != ERROR_SUCCESS )
989 goto end;
991 r = RegOpenKeyW(hkey, szComponents, &hkeyComponents);
992 if( r != ERROR_SUCCESS )
993 goto end;
995 r = RegOpenKeyW(hkeyComponents, szRegName, &hkeyComp);
996 if( r != ERROR_SUCCESS )
997 goto end;
999 sz = GUID_SIZE;
1000 r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1001 if( r != ERROR_SUCCESS )
1002 goto end;
1004 unsquash_guid(szValName, szProduct);
1006 end:
1007 if( hkeyComp )
1008 RegCloseKey(hkeyComp);
1009 if( hkeyComponents )
1010 RegCloseKey(hkeyComponents);
1011 if( hkey )
1012 RegCloseKey(hkey);
1014 return r;
1017 UINT WINAPI MsiEnumComponentQualifiersA(
1018 LPSTR szComponent, DWORD iIndex, LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1020 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1021 return ERROR_CALL_NOT_IMPLEMENTED;
1024 UINT WINAPI MsiEnumComponentQualifiersW(
1025 LPWSTR szComponent, DWORD iIndex, LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf)
1027 FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf);
1028 return ERROR_CALL_NOT_IMPLEMENTED;
1031 UINT WINAPI MsiProvideAssemblyA(
1032 LPCSTR szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, DWORD* pcchPathBuf)
1034 FIXME("%s %s 0x%08lx 0x%08lx %p %p\n",
1035 debugstr_a(szAssemblyName), debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1036 return ERROR_CALL_NOT_IMPLEMENTED;
1039 UINT WINAPI MsiProvideAssemblyW(
1040 LPCWSTR szAssemblyName, LPCWSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD* pcchPathBuf)
1042 FIXME("%s %s 0x%08lx 0x%08lx %p %p\n",
1043 debugstr_w(szAssemblyName), debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf);
1044 return ERROR_CALL_NOT_IMPLEMENTED;
1047 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1049 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1050 return ERROR_CALL_NOT_IMPLEMENTED;
1053 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1055 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1056 return ERROR_CALL_NOT_IMPLEMENTED;
1059 HRESULT WINAPI MsiGetFileSignatureInformationA(
1060 LPCSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1062 FIXME("%s 0x%08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1063 return ERROR_CALL_NOT_IMPLEMENTED;
1066 HRESULT WINAPI MsiGetFileSignatureInformationW(
1067 LPCWSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData)
1069 FIXME("%s 0x%08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData);
1070 return ERROR_CALL_NOT_IMPLEMENTED;
1073 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1074 LPSTR szValue, DWORD *pccbValue )
1076 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1077 return ERROR_CALL_NOT_IMPLEMENTED;
1080 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1081 LPWSTR szValue, DWORD *pccbValue )
1083 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1084 return ERROR_CALL_NOT_IMPLEMENTED;
1087 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1089 FIXME("%s\n", debugstr_a(szPackage) );
1090 return ERROR_CALL_NOT_IMPLEMENTED;
1093 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1095 FIXME("%s\n", debugstr_w(szPackage) );
1096 return ERROR_CALL_NOT_IMPLEMENTED;
1099 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1100 LPSTR lpPathBuf, DWORD* pcchBuf)
1102 INSTALLSTATE rc;
1103 UINT len;
1104 LPWSTR szwProduct= NULL;
1105 LPWSTR szwComponent= NULL;
1106 LPWSTR lpwPathBuf= NULL;
1108 if( szProduct)
1110 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1111 szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1112 if( !szwProduct)
1113 return ERROR_OUTOFMEMORY;
1114 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1117 if( szComponent)
1119 len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1120 szwComponent= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1121 if( !szwComponent)
1122 return ERROR_OUTOFMEMORY;
1123 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1126 if (pcchBuf && *pcchBuf > 0)
1127 lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR));
1128 else
1129 lpwPathBuf = NULL;
1131 rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
1133 HeapFree( GetProcessHeap(), 0, szwProduct);
1134 HeapFree( GetProcessHeap(), 0, szwComponent);
1135 if (lpwPathBuf)
1137 WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, *pcchBuf,
1138 lpPathBuf, GUID_SIZE, NULL, NULL);
1139 HeapFree( GetProcessHeap(), 0, lpwPathBuf);
1142 return rc;
1145 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1146 LPWSTR lpPathBuf, DWORD* pcchBuf)
1148 FIXME("STUB: (%s %s %p %p)\n", debugstr_w(szProduct),
1149 debugstr_w(szComponent), lpPathBuf, pcchBuf);
1151 return INSTALLSTATE_UNKNOWN;
1154 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1156 INSTALLSTATE rc;
1157 UINT len;
1158 LPWSTR szwProduct= NULL;
1159 LPWSTR szwFeature= NULL;
1161 if( szProduct)
1163 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1164 szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1165 if( !szwProduct)
1166 return ERROR_OUTOFMEMORY;
1167 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1170 if( szFeature)
1172 len = MultiByteToWideChar( CP_ACP, 0, szFeature, -1, NULL, 0 );
1173 szwFeature= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1174 if( !szwFeature)
1175 return ERROR_OUTOFMEMORY;
1176 MultiByteToWideChar( CP_ACP, 0, szFeature, -1, szwFeature, len );
1179 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1181 HeapFree( GetProcessHeap(), 0, szwProduct);
1182 HeapFree( GetProcessHeap(), 0, szwFeature);
1184 return rc;
1187 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1189 FIXME("STUB: (%s %s)\n", debugstr_w(szProduct), debugstr_w(szFeature));
1190 return INSTALLSTATE_UNKNOWN;
1194 /******************************************************************
1195 * DllMain
1197 * @todo: maybe we can check here if MsiServer service is declared no ?
1199 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
1200 if (fdwReason == DLL_PROCESS_ATTACH) {
1201 DisableThreadLibraryCalls(hinstDLL);
1203 * UI Initialization
1205 gUILevel = INSTALLUILEVEL_BASIC;
1206 gUIhwnd = 0;
1207 gUIHandler = NULL;
1208 gUIFilter = 0;
1209 gUIContext = NULL;
1210 gszLogFile[0]=0;
1211 /* FIXME: Initialisation */
1212 } else if (fdwReason == DLL_PROCESS_DETACH) {
1213 /* FIXME: Cleanup */
1216 static const WCHAR szMSIServerSvc[] = { 'M','S','I','S','e','r','v','e','r',0 };
1217 static const WCHAR szNull[] = { 0 };
1218 if (!strcmpW(lpServiceName, szMSIServerSvc)) {
1219 hKey = CreateServiceW(hSCManager,
1220 szMSIServerSvc,
1221 szMSIServerSvc,
1222 SC_MANAGER_ALL_ACCESS,
1223 SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
1224 SERVICE_AUTO_START,
1225 SERVICE_ERROR_IGNORE,
1226 szNull,
1227 NULL,
1228 NULL,
1229 NULL,
1230 NULL,
1231 szNull);
1233 return TRUE;
1236 typedef struct {
1237 /* IUnknown fields */
1238 ICOM_VFIELD(IClassFactory);
1239 DWORD ref;
1240 } IClassFactoryImpl;
1242 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1243 ICOM_THIS(IClassFactoryImpl,iface);
1244 FIXME("(%p, %s, %p): stub\n",This,debugstr_guid(riid),ppobj);
1245 return E_NOINTERFACE;
1248 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface) {
1249 ICOM_THIS(IClassFactoryImpl,iface);
1250 return ++(This->ref);
1253 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) {
1254 ICOM_THIS(IClassFactoryImpl,iface);
1255 /* static class, won't be freed */
1256 return --(This->ref);
1259 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) {
1260 ICOM_THIS(IClassFactoryImpl,iface);
1261 FIXME ("(%p, %p, %s, %p): to implement\n", This, pOuter, debugstr_guid(riid), ppobj);
1262 return 0;
1265 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1266 ICOM_THIS(IClassFactoryImpl,iface);
1267 FIXME("(%p, %d): stub\n", This, dolock);
1268 return S_OK;
1271 static ICOM_VTABLE(IClassFactory) MsiCF_Vtbl = {
1272 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1273 MsiCF_QueryInterface,
1274 MsiCF_AddRef,
1275 MsiCF_Release,
1276 MsiCF_CreateInstance,
1277 MsiCF_LockServer
1280 static IClassFactoryImpl Msi_CF = {&MsiCF_Vtbl, 1 };
1282 /******************************************************************
1283 * DllGetClassObject (MSI.@)
1285 HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) {
1286 FIXME("(%s, %s, %p): almost a stub.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1287 if (IsEqualCLSID (rclsid, &CLSID_IMsiServer)) {
1288 *ppv = (LPVOID) &Msi_CF;
1289 IClassFactory_AddRef((IClassFactory*)*ppv);
1290 return S_OK;
1291 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage)) {
1292 *ppv = (LPVOID) &Msi_CF;
1293 IClassFactory_AddRef((IClassFactory*)*ppv);
1294 return S_OK;
1295 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX1)) {
1296 *ppv = (LPVOID) &Msi_CF;
1297 IClassFactory_AddRef((IClassFactory*)*ppv);
1298 return S_OK;
1299 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX2)) {
1300 *ppv = (LPVOID) &Msi_CF;
1301 IClassFactory_AddRef((IClassFactory*)*ppv);
1302 return S_OK;
1303 } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX3)) {
1304 *ppv = (LPVOID) &Msi_CF;
1305 IClassFactory_AddRef((IClassFactory*)*ppv);
1306 return S_OK;
1308 WARN("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1309 return CLASS_E_CLASSNOTAVAILABLE;
1312 /******************************************************************
1313 * DllGetVerison (MSI.@)
1315 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
1317 TRACE("%p\n",pdvi);
1319 if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1320 return E_INVALIDARG;
1322 pdvi->dwMajorVersion = MSI_MAJORVERSION;
1323 pdvi->dwMinorVersion = MSI_MINORVERSION;
1324 pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1325 pdvi->dwPlatformID = 1;
1327 return S_OK;
1330 /******************************************************************
1331 * DllCanUnloadNow (MSI.@)
1333 BOOL WINAPI MSI_DllCanUnloadNow(void)
1335 return S_FALSE;
1338 UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
1339 DWORD iProductIndex, LPSTR lpProductBuf)
1341 FIXME("STUB: (%s, %li %li %s)\n",lpUpgradeCode, dwReserved, iProductIndex,
1342 lpProductBuf);
1343 return ERROR_CALL_NOT_IMPLEMENTED;