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
30 #include "wine/debug.h"
36 #include "wine/unicode.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 };
66 INSTALLUILEVEL gUILevel
;
68 INSTALLUI_HANDLERA gUIHandler
;
71 WCHAR gszLogFile
[MAX_PATH
];
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
)
96 out
[n
++] = in
[17+i
*2];
97 out
[n
++] = in
[16+i
*2];
102 out
[n
++] = in
[17+i
*2];
103 out
[n
++] = in
[16+i
*2];
110 BOOL
squash_guid(LPCWSTR in
, LPWSTR out
)
130 out
[17+i
*2] = in
[n
++];
131 out
[16+i
*2] = in
[n
++];
137 out
[17+i
*2] = in
[n
++];
138 out
[16+i
*2] = in
[n
++];
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
;
162 TRACE("%s %s %p\n", debugstr_a(szDBPath
), debugstr_a(szPersist
), phDB
);
166 len
= MultiByteToWideChar( CP_ACP
, 0, szDBPath
, -1, NULL
, 0 );
167 szwDBPath
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
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
) );
179 MultiByteToWideChar( CP_ACP
, 0, szPersist
, -1, szwPersist
, len
);
182 szwPersist
= (LPWSTR
) szPersist
;
184 r
= MsiOpenDatabaseW( szwDBPath
, szwPersist
, phDB
);
188 HeapFree( GetProcessHeap(), 0, szwPersist
);
190 HeapFree( GetProcessHeap(), 0, szwDBPath
);
195 UINT WINAPI
MsiOpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIHANDLE
*phDB
)
197 IStorage
*stg
= NULL
;
205 TRACE("%s %s %p\n",debugstr_w(szDBPath
),debugstr_w(szPersist
), 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
);
240 ERR("unknown flag %p\n",szPersist
);
241 return ERROR_INVALID_PARAMETER
;
246 FIXME("open failed r = %08lx!\n",r
);
247 return ERROR_FUNCTION_FAILED
;
250 r
= IStorage_Stat( stg
, &stat
, STATFLAG_NONAME
);
253 FIXME("Failed to stat storage\n");
254 ret
= ERROR_FUNCTION_FAILED
;
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
;
267 handle
= alloc_msihandle( MSIHANDLETYPE_DATABASE
, sizeof (MSIDATABASE
),
268 MSI_CloseDatabase
, (void**) &db
);
271 FIXME("Failed to allocate a handle\n");
272 ret
= ERROR_FUNCTION_FAILED
;
276 if( TRACE_ON( msi
) )
277 enum_stream_names( stg
);
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
)
291 IStorage_AddRef( stg
);
294 IStorage_Release( stg
);
299 UINT WINAPI
MsiOpenProductA(LPCSTR szProduct
, MSIHANDLE
*phProduct
)
302 LPWSTR szwProd
= NULL
;
304 TRACE("%s %p\n",debugstr_a(szProduct
), phProduct
);
308 len
= MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, NULL
, 0 );
309 szwProd
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof (WCHAR
) );
311 MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, szwProd
, len
);
314 ret
= MsiOpenProductW( szwProd
, phProduct
);
317 HeapFree( GetProcessHeap(), 0, szwProd
);
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
335 HKEY hKeyProduct
= NULL
, hKeyUninstall
= NULL
;
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
;
351 /* find the size of the path */
353 r
= RegQueryValueExW( hKeyProduct
, szLocalPackage
,
354 NULL
, &type
, NULL
, &count
);
355 if( r
!= ERROR_SUCCESS
)
357 r
= ERROR_UNKNOWN_PRODUCT
;
361 /* now alloc and fetch the path of the database to open */
362 path
= HeapAlloc( GetProcessHeap(), 0, count
);
366 r
= RegQueryValueExW( hKeyProduct
, szLocalPackage
,
367 NULL
, &type
, (LPBYTE
) path
, &count
);
368 if( r
!= ERROR_SUCCESS
)
370 r
= ERROR_UNKNOWN_PRODUCT
;
374 r
= MsiOpenPackageW( path
, phProduct
);
378 HeapFree( GetProcessHeap(), 0, path
);
380 RegCloseKey( hKeyProduct
);
381 RegCloseKey( hKeyUninstall
);
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
));
421 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szPackagePath
, -1, NULL
, 0 );
422 szwPath
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
425 MultiByteToWideChar( CP_ACP
, 0, szPackagePath
, -1, szwPath
, len
);
430 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szCommandLine
, -1, NULL
, 0 );
431 szwCommand
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
434 MultiByteToWideChar( CP_ACP
, 0, szCommandLine
, -1, szwCommand
, len
);
437 r
= MsiInstallProductW( szwPath
, szwCommand
);
441 HeapFree( GetProcessHeap(), 0, szwPath
);
444 HeapFree( GetProcessHeap(), 0, szwCommand
);
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
)
460 rc
= MsiOpenPackageW(szPackagePath
,&packagehandle
);
461 if (rc
!= ERROR_SUCCESS
)
464 ACTION_DoTopLevelINSTALL(packagehandle
, szPackagePath
, szCommandLine
);
466 MsiCloseHandle(packagehandle
);
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
);
479 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, NULL
, 0 );
480 szwProduct
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
483 MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, szwProduct
, len
);
486 hr
= MsiConfigureProductW( szwProduct
, iInstallLevel
, eInstallState
);
490 HeapFree( GetProcessHeap(), 0, szwProduct
);
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
));
510 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szComponent
, -1, NULL
, 0 );
511 szwComponent
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
514 MultiByteToWideChar( CP_ACP
, 0, szComponent
, -1, szwComponent
, len
);
516 return ERROR_INVALID_PARAMETER
;
520 szwBuffer
= HeapAlloc( GetProcessHeap(), 0, GUID_SIZE
* sizeof(WCHAR
) );
525 hr
= MsiGetProductCodeW( szwComponent
, szwBuffer
);
527 if( ERROR_SUCCESS
== hr
)
529 WideCharToMultiByte(CP_ACP
, 0, szwBuffer
, -1, szBuffer
, GUID_SIZE
, NULL
, NULL
);
534 HeapFree( GetProcessHeap(), 0, szwComponent
);
536 HeapFree( GetProcessHeap(), 0, szwBuffer
);
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
;
565 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, NULL
, 0 );
566 szwProduct
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
569 MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, szwProduct
, len
);
571 return ERROR_INVALID_PARAMETER
;
576 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szAttribute
, -1, NULL
, 0 );
577 szwAttribute
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
580 MultiByteToWideChar( CP_ACP
, 0, szAttribute
, -1, szwAttribute
, len
);
582 return ERROR_INVALID_PARAMETER
;
587 szwBuffer
= HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf
) * sizeof(WCHAR
) );
592 hr
= MsiGetProductInfoW( szwProduct
, szwAttribute
, szwBuffer
, pcchValueBuf
);
594 if( ERROR_SUCCESS
== hr
)
596 WideCharToMultiByte(CP_ACP
, 0, szwBuffer
, -1, szBuffer
, *pcchValueBuf
, NULL
, NULL
);
601 HeapFree( GetProcessHeap(), 0, szwProduct
);
603 HeapFree( GetProcessHeap(), 0, szwAttribute
);
605 HeapFree( GetProcessHeap(), 0, szwBuffer
);
610 UINT WINAPI
MsiGetProductInfoW(LPCWSTR szProduct
, LPCWSTR szAttribute
, LPWSTR szBuffer
, DWORD
*pcchValueBuf
)
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
);
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
);
653 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szLogFile
, -1, NULL
, 0 );
654 szwLogFile
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
657 MultiByteToWideChar( CP_ACP
, 0, szLogFile
, -1, szwLogFile
, len
);
659 return ERROR_INVALID_PARAMETER
;
662 hr
= MsiEnableLogW( dwLogMode
, szwLogFile
, fAppend
);
666 HeapFree( GetProcessHeap(), 0, szwLogFile
);
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
);
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
);
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
;
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
;
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));
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
;
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
)
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
);
796 UINT WINAPI
MsiEnumProductsW(DWORD index
, LPWSTR lpguid
)
798 HKEY hkey
= 0, hkeyFeatures
= 0;
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
)
811 r
= RegOpenKeyW(hkey
, szFeatures
, &hkeyFeatures
);
812 if( r
!= ERROR_SUCCESS
)
815 r
= RegEnumKeyW(hkeyFeatures
, index
, szKeyName
, GUID_SIZE
);
817 unsquash_guid(szKeyName
, lpguid
);
822 RegCloseKey(hkeyFeatures
);
829 UINT WINAPI
MsiEnumFeaturesA(LPCSTR szProduct
, DWORD index
,
830 LPSTR szFeature
, LPSTR szParent
)
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
);
840 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, NULL
, 0 );
841 szwProduct
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof (WCHAR
) );
843 MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, szwProduct
, len
);
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
);
858 HeapFree( GetProcessHeap(), 0, szwProduct
);
863 UINT WINAPI
MsiEnumFeaturesW(LPCWSTR szProduct
, DWORD index
,
864 LPWSTR szFeature
, LPWSTR szParent
)
866 HKEY hkey
= 0, hkeyFeatures
= 0, hkeyProduct
= 0;
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
)
879 r
= RegOpenKeyW(hkey
, szFeatures
, &hkeyFeatures
);
880 if( r
!= ERROR_SUCCESS
)
883 r
= RegOpenKeyW(hkeyFeatures
, szRegName
, &hkeyProduct
);
884 if( r
!= ERROR_SUCCESS
)
888 r
= RegEnumValueW(hkeyProduct
, index
, szFeature
, &sz
, NULL
, NULL
, NULL
, NULL
);
892 RegCloseKey(hkeyProduct
);
894 RegCloseKey(hkeyFeatures
);
901 UINT WINAPI
MsiEnumComponentsA(DWORD index
, LPSTR lpguid
)
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
);
915 UINT WINAPI
MsiEnumComponentsW(DWORD index
, LPWSTR lpguid
)
917 HKEY hkey
= 0, hkeyComponents
= 0;
921 TRACE("%ld %p\n",index
,lpguid
);
923 r
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, szInstaller
, &hkey
);
924 if( r
!= ERROR_SUCCESS
)
927 r
= RegOpenKeyW(hkey
, szComponents
, &hkeyComponents
);
928 if( r
!= ERROR_SUCCESS
)
931 r
= RegEnumKeyW(hkeyComponents
, index
, szKeyName
, GUID_SIZE
);
933 unsquash_guid(szKeyName
, lpguid
);
938 RegCloseKey(hkeyComponents
);
945 UINT WINAPI
MsiEnumClientsA(LPCSTR szComponent
, DWORD index
, LPSTR szProduct
)
948 WCHAR szwProduct
[GUID_SIZE
];
949 LPWSTR szwComponent
= NULL
;
951 TRACE("%s %ld %p\n",debugstr_a(szComponent
),index
,szProduct
);
955 UINT len
= MultiByteToWideChar( CP_ACP
, 0, szComponent
, -1, NULL
, 0 );
956 szwComponent
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof (WCHAR
) );
958 MultiByteToWideChar( CP_ACP
, 0, szComponent
, -1, szwComponent
, len
);
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
);
971 HeapFree( GetProcessHeap(), 0, szwComponent
);
976 UINT WINAPI
MsiEnumClientsW(LPCWSTR szComponent
, DWORD index
, LPWSTR szProduct
)
978 HKEY hkey
= 0, hkeyComponents
= 0, hkeyComp
= 0;
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
)
991 r
= RegOpenKeyW(hkey
, szComponents
, &hkeyComponents
);
992 if( r
!= ERROR_SUCCESS
)
995 r
= RegOpenKeyW(hkeyComponents
, szRegName
, &hkeyComp
);
996 if( r
!= ERROR_SUCCESS
)
1000 r
= RegEnumValueW(hkeyComp
, index
, szValName
, &sz
, NULL
, NULL
, NULL
, NULL
);
1001 if( r
!= ERROR_SUCCESS
)
1004 unsquash_guid(szValName
, szProduct
);
1008 RegCloseKey(hkeyComp
);
1009 if( hkeyComponents
)
1010 RegCloseKey(hkeyComponents
);
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
)
1104 LPWSTR szwProduct
= NULL
;
1105 LPWSTR szwComponent
= NULL
;
1106 LPWSTR lpwPathBuf
= NULL
;
1110 len
= MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, NULL
, 0 );
1111 szwProduct
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
1113 return ERROR_OUTOFMEMORY
;
1114 MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, szwProduct
, len
);
1119 len
= MultiByteToWideChar( CP_ACP
, 0, szComponent
, -1, NULL
, 0 );
1120 szwComponent
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
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
));
1131 rc
= MsiGetComponentPathW(szwProduct
, szwComponent
, lpwPathBuf
, pcchBuf
);
1133 HeapFree( GetProcessHeap(), 0, szwProduct
);
1134 HeapFree( GetProcessHeap(), 0, szwComponent
);
1137 WideCharToMultiByte(CP_ACP
, 0, lpwPathBuf
, *pcchBuf
,
1138 lpPathBuf
, GUID_SIZE
, NULL
, NULL
);
1139 HeapFree( GetProcessHeap(), 0, lpwPathBuf
);
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
)
1158 LPWSTR szwProduct
= NULL
;
1159 LPWSTR szwFeature
= NULL
;
1163 len
= MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, NULL
, 0 );
1164 szwProduct
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
1166 return ERROR_OUTOFMEMORY
;
1167 MultiByteToWideChar( CP_ACP
, 0, szProduct
, -1, szwProduct
, len
);
1172 len
= MultiByteToWideChar( CP_ACP
, 0, szFeature
, -1, NULL
, 0 );
1173 szwFeature
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
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
);
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 /******************************************************************
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
);
1205 gUILevel
= INSTALLUILEVEL_BASIC
;
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,
1222 SC_MANAGER_ALL_ACCESS,
1223 SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
1225 SERVICE_ERROR_IGNORE,
1237 /* IUnknown fields */
1238 ICOM_VFIELD(IClassFactory
);
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
);
1265 static HRESULT WINAPI
MsiCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
1266 ICOM_THIS(IClassFactoryImpl
,iface
);
1267 FIXME("(%p, %d): stub\n", This
, dolock
);
1271 static ICOM_VTABLE(IClassFactory
) MsiCF_Vtbl
= {
1272 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1273 MsiCF_QueryInterface
,
1276 MsiCF_CreateInstance
,
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
);
1291 } else if (IsEqualCLSID (rclsid
, &CLSID_IMsiServerMessage
)) {
1292 *ppv
= (LPVOID
) &Msi_CF
;
1293 IClassFactory_AddRef((IClassFactory
*)*ppv
);
1295 } else if (IsEqualCLSID (rclsid
, &CLSID_IMsiServerX1
)) {
1296 *ppv
= (LPVOID
) &Msi_CF
;
1297 IClassFactory_AddRef((IClassFactory
*)*ppv
);
1299 } else if (IsEqualCLSID (rclsid
, &CLSID_IMsiServerX2
)) {
1300 *ppv
= (LPVOID
) &Msi_CF
;
1301 IClassFactory_AddRef((IClassFactory
*)*ppv
);
1303 } else if (IsEqualCLSID (rclsid
, &CLSID_IMsiServerX3
)) {
1304 *ppv
= (LPVOID
) &Msi_CF
;
1305 IClassFactory_AddRef((IClassFactory
*)*ppv
);
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
)
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;
1330 /******************************************************************
1331 * DllCanUnloadNow (MSI.@)
1333 BOOL WINAPI
MSI_DllCanUnloadNow(void)
1338 UINT WINAPI
MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode
, DWORD dwReserved
,
1339 DWORD iProductIndex
, LPSTR lpProductBuf
)
1341 FIXME("STUB: (%s, %li %li %s)\n",lpUpgradeCode
, dwReserved
, iProductIndex
,
1343 return ERROR_CALL_NOT_IMPLEMENTED
;