Copy wininet to branch
[reactos.git] / reactos / lib / msi / msi.c
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wine/debug.h"
32 #include "msi.h"
33 #include "msiquery.h"
34 #include "msipriv.h"
35 #include "objidl.h"
36 #include "wincrypt.h"
37 #include "wine/unicode.h"
38 #include "objbase.h"
39 #include "winver.h"
40 #include "winuser.h"
41
42 #include "initguid.h"
43
44 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf);
45
46
47 WINE_DEFAULT_DEBUG_CHANNEL(msi);
48
49 /*
50 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
51 * which is a problem because LPCTSTR isn't defined when compiling wine.
52 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
53 * and make sure to only use it in W functions.
54 */
55 #define LPCTSTR LPCWSTR
56
57 DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000,
58 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
59
60 /* the UI level */
61 INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
62 HWND gUIhwnd = 0;
63 INSTALLUI_HANDLERA gUIHandlerA = NULL;
64 INSTALLUI_HANDLERW gUIHandlerW = NULL;
65 DWORD gUIFilter = 0;
66 LPVOID gUIContext = NULL;
67 WCHAR gszLogFile[MAX_PATH];
68 HINSTANCE msi_hInstance;
69
70 /*
71 * .MSI file format
72 *
73 * A .msi file is a structured storage file.
74 * It should contain a number of streams.
75 */
76
77 VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
78 {
79 MSIDATABASE *db = (MSIDATABASE *) arg;
80 DWORD r;
81
82 free_cached_tables( db );
83 r = IStorage_Release( db->storage );
84 if( r )
85 ERR("database reference count was not zero (%ld)\n", r);
86 }
87
88 UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
89 {
90 IStorage *stg = NULL;
91 HRESULT r;
92 MSIDATABASE *db = NULL;
93 UINT ret = ERROR_FUNCTION_FAILED;
94 LPWSTR szMode;
95 STATSTG stat;
96
97 TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
98
99 if( !pdb )
100 return ERROR_INVALID_PARAMETER;
101
102 szMode = (LPWSTR) szPersist;
103 if( HIWORD( szPersist ) )
104 {
105 /* UINT len = lstrlenW( szPerist ) + 1; */
106 FIXME("don't support persist files yet\b");
107 return ERROR_INVALID_PARAMETER;
108 /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */
109 }
110 else if( szPersist == MSIDBOPEN_READONLY )
111 {
112 r = StgOpenStorage( szDBPath, NULL,
113 STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
114 }
115 else if( szPersist == MSIDBOPEN_CREATE )
116 {
117 r = StgCreateDocfile( szDBPath,
118 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
119 if( r == ERROR_SUCCESS )
120 {
121 IStorage_SetClass( stg, &CLSID_MsiDatabase );
122 r = init_string_table( stg );
123 }
124 }
125 else if( szPersist == MSIDBOPEN_TRANSACT )
126 {
127 r = StgOpenStorage( szDBPath, NULL,
128 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
129 }
130 else
131 {
132 ERR("unknown flag %p\n",szPersist);
133 return ERROR_INVALID_PARAMETER;
134 }
135
136 if( FAILED( r ) )
137 {
138 FIXME("open failed r = %08lx!\n",r);
139 return ERROR_FUNCTION_FAILED;
140 }
141
142 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
143 if( FAILED( r ) )
144 {
145 FIXME("Failed to stat storage\n");
146 goto end;
147 }
148
149 if( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) )
150 {
151 ERR("storage GUID is not a MSI database GUID %s\n",
152 debugstr_guid(&stat.clsid) );
153 goto end;
154 }
155
156
157 db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
158 MSI_CloseDatabase );
159 if( !db )
160 {
161 FIXME("Failed to allocate a handle\n");
162 goto end;
163 }
164
165 if( TRACE_ON( msi ) )
166 enum_stream_names( stg );
167
168 db->storage = stg;
169 db->mode = szMode;
170
171 ret = load_string_table( db );
172 if( ret != ERROR_SUCCESS )
173 goto end;
174
175 msiobj_addref( &db->hdr );
176 IStorage_AddRef( stg );
177 *pdb = db;
178
179 end:
180 if( db )
181 msiobj_release( &db->hdr );
182 if( stg )
183 IStorage_Release( stg );
184
185 return ret;
186 }
187
188 UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
189 {
190 MSIDATABASE *db;
191 UINT ret;
192
193 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
194
195 ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
196 if( ret == ERROR_SUCCESS )
197 {
198 *phDB = alloc_msihandle( &db->hdr );
199 msiobj_release( &db->hdr );
200 }
201
202 return ret;
203 }
204
205 UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
206 {
207 HRESULT r = ERROR_FUNCTION_FAILED;
208 LPWSTR szwDBPath = NULL, szwPersist = NULL;
209 UINT len;
210
211 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
212
213 if( szDBPath )
214 {
215 len = MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, NULL, 0 );
216 szwDBPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
217 if( !szwDBPath )
218 goto end;
219 MultiByteToWideChar( CP_ACP, 0, szDBPath, -1, szwDBPath, len );
220 }
221
222 if( HIWORD(szPersist) )
223 {
224 len = MultiByteToWideChar( CP_ACP, 0, szPersist, -1, NULL, 0 );
225 szwPersist = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
226 if( !szwPersist )
227 goto end;
228 MultiByteToWideChar( CP_ACP, 0, szPersist, -1, szwPersist, len );
229 }
230 else
231 szwPersist = (LPWSTR) szPersist;
232
233 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
234
235 end:
236 HeapFree( GetProcessHeap(), 0, szwPersist );
237 HeapFree( GetProcessHeap(), 0, szwDBPath );
238
239 return r;
240 }
241
242 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
243 {
244 UINT len, ret;
245 LPWSTR szwProd = NULL;
246
247 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
248
249 if( szProduct )
250 {
251 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
252 szwProd = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
253 if( szwProd )
254 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProd, len );
255 }
256
257 ret = MsiOpenProductW( szwProd, phProduct );
258
259 HeapFree( GetProcessHeap(), 0, szwProd );
260
261 return ret;
262 }
263
264 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
265 {
266 static const WCHAR szLocalPackage[] = {
267 'L','o','c','a','l','P','a','c','k','a','g','e', 0
268 };
269 LPWSTR path = NULL;
270 UINT r;
271 HKEY hKeyProduct = NULL;
272 DWORD count, type;
273
274 TRACE("%s %p\n",debugstr_w(szProduct), phProduct);
275
276 r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE);
277 if( r != ERROR_SUCCESS )
278 {
279 r = ERROR_UNKNOWN_PRODUCT;
280 goto end;
281 }
282
283 /* find the size of the path */
284 type = count = 0;
285 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
286 NULL, &type, NULL, &count );
287 if( r != ERROR_SUCCESS )
288 {
289 r = ERROR_UNKNOWN_PRODUCT;
290 goto end;
291 }
292
293 /* now alloc and fetch the path of the database to open */
294 path = HeapAlloc( GetProcessHeap(), 0, count );
295 if( !path )
296 goto end;
297
298 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
299 NULL, &type, (LPBYTE) path, &count );
300 if( r != ERROR_SUCCESS )
301 {
302 r = ERROR_UNKNOWN_PRODUCT;
303 goto end;
304 }
305
306 r = MsiOpenPackageW( path, phProduct );
307
308 end:
309 HeapFree( GetProcessHeap(), 0, path );
310 if( hKeyProduct )
311 RegCloseKey( hKeyProduct );
312
313 return r;
314 }
315
316 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
317 LPCSTR szTransforms, LANGID lgidLanguage)
318 {
319 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
320 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
321 return ERROR_CALL_NOT_IMPLEMENTED;
322 }
323
324 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
325 LPCWSTR szTransforms, LANGID lgidLanguage)
326 {
327 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
328 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
329 return ERROR_CALL_NOT_IMPLEMENTED;
330 }
331
332 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
333 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
334 {
335 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_a(szPackagePath),
336 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
337 lgidLanguage, dwPlatform, dwOptions);
338 return ERROR_CALL_NOT_IMPLEMENTED;
339 }
340
341 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
342 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
343 {
344 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_w(szPackagePath),
345 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
346 lgidLanguage, dwPlatform, dwOptions);
347 return ERROR_CALL_NOT_IMPLEMENTED;
348 }
349
350 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
351 {
352 LPWSTR szwPath = NULL, szwCommand = NULL;
353 UINT r = ERROR_FUNCTION_FAILED; /* FIXME: check return code */
354
355 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
356
357 if( szPackagePath )
358 {
359 UINT len = MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, NULL, 0 );
360 szwPath = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
361 if( !szwPath )
362 goto end;
363 MultiByteToWideChar( CP_ACP, 0, szPackagePath, -1, szwPath, len );
364 }
365
366 if( szCommandLine )
367 {
368 UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 );
369 szwCommand = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
370 if( !szwCommand )
371 goto end;
372 MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommand, len );
373 }
374
375 r = MsiInstallProductW( szwPath, szwCommand );
376
377 end:
378 HeapFree( GetProcessHeap(), 0, szwPath );
379 HeapFree( GetProcessHeap(), 0, szwCommand );
380
381 return r;
382 }
383
384 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
385 {
386 MSIPACKAGE *package = NULL;
387 UINT rc = ERROR_SUCCESS;
388 MSIHANDLE handle;
389
390 FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
391
392 rc = MsiVerifyPackageW(szPackagePath);
393 if (rc != ERROR_SUCCESS)
394 return rc;
395
396 rc = MSI_OpenPackageW(szPackagePath,&package);
397 if (rc != ERROR_SUCCESS)
398 return rc;
399
400 handle = alloc_msihandle( &package->hdr );
401
402 rc = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine);
403
404 MsiCloseHandle(handle);
405 msiobj_release( &package->hdr );
406 return rc;
407 }
408
409 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
410 {
411 FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode);
412 return ERROR_CALL_NOT_IMPLEMENTED;
413 }
414
415 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
416 {
417 FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode);
418 return ERROR_CALL_NOT_IMPLEMENTED;
419 }
420
421 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
422 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
423 {
424 FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
425 eInstallType, debugstr_a(szCommandLine));
426 return ERROR_CALL_NOT_IMPLEMENTED;
427 }
428
429 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
430 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
431 {
432 FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
433 eInstallType, debugstr_w(szCommandLine));
434 return ERROR_CALL_NOT_IMPLEMENTED;
435 }
436
437 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
438 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
439 {
440 MSIHANDLE handle;
441 MSIPACKAGE* package;
442 UINT rc;
443 HKEY hkey=0,hkey1=0;
444 DWORD sz;
445 static const WCHAR szSouceList[] = {
446 'S','o','u','r','c','e','L','i','s','t',0};
447 static const WCHAR szLUS[] = {
448 'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
449 WCHAR sourcepath[0x200];
450 static const WCHAR szInstalled[] = {
451 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
452 LPWSTR commandline;
453
454 FIXME("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
455 debugstr_w(szCommandLine));
456
457 if (eInstallState != INSTALLSTATE_LOCAL &&
458 eInstallState != INSTALLSTATE_DEFAULT)
459 {
460 FIXME("Not implemented for anything other than local installs\n");
461 return ERROR_CALL_NOT_IMPLEMENTED;
462 }
463
464 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
465 if (rc != ERROR_SUCCESS)
466 goto end;
467
468 rc = RegOpenKeyW(hkey,szSouceList,&hkey1);
469 if (rc != ERROR_SUCCESS)
470 goto end;
471
472 sz = sizeof(sourcepath);
473 rc = RegQueryValueExW(hkey1, szLUS, NULL, NULL,(LPBYTE)sourcepath, &sz);
474 if (rc != ERROR_SUCCESS)
475 goto end;
476
477 RegCloseKey(hkey1);
478 /*
479 * ok 1, we need to find the msi file for this product.
480 * 2, find the source dir for the files
481 * 3, do the configure/install.
482 * 4, cleanupany runonce entry.
483 */
484
485 rc = MsiOpenProductW(szProduct,&handle);
486 if (rc != ERROR_SUCCESS)
487 goto end;
488
489 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
490 if (!package)
491 {
492 rc = ERROR_INVALID_HANDLE;
493 goto end;
494 }
495
496 sz = strlenW(szInstalled);
497
498 if (szCommandLine)
499 sz += strlenW(szCommandLine);
500
501 commandline = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
502
503 if (szCommandLine)
504 strcpyW(commandline,szCommandLine);
505 else
506 commandline[0] = 0;
507
508 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
509 strcatW(commandline,szInstalled);
510
511 rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline);
512
513 msiobj_release( &package->hdr );
514
515 HeapFree(GetProcessHeap(),0,commandline);
516 end:
517 RegCloseKey(hkey);
518
519 return rc;
520 }
521
522 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
523 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
524 {
525 LPWSTR szwProduct = NULL;
526 LPWSTR szwCommandLine = NULL;
527 UINT hr = ERROR_FUNCTION_FAILED;
528
529 if( szProduct )
530 {
531 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
532 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
533 if( !szwProduct )
534 goto end;
535 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
536 }
537
538 if( szCommandLine)
539 {
540 UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 );
541 szwCommandLine= HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
542 if( !szwCommandLine)
543 goto end;
544 MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommandLine, len );
545 }
546
547 hr = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
548 szwCommandLine );
549 end:
550 HeapFree( GetProcessHeap(), 0, szwProduct );
551 HeapFree( GetProcessHeap(), 0, szwCommandLine);
552
553 return hr;
554 }
555
556 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
557 INSTALLSTATE eInstallState)
558 {
559 LPWSTR szwProduct = NULL;
560 UINT hr = ERROR_SUCCESS;
561
562 FIXME("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
563
564 if( szProduct )
565 {
566 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
567 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
568 if( !szwProduct )
569 goto end;
570 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
571 }
572
573 hr = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
574
575 end:
576 HeapFree( GetProcessHeap(), 0, szwProduct );
577
578 return hr;
579 }
580
581 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
582 INSTALLSTATE eInstallState)
583 {
584 FIXME("%s %d %d\n", debugstr_w(szProduct), iInstallLevel, eInstallState);
585
586 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState,
587 NULL);
588 }
589
590 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
591 {
592 LPWSTR szwComponent = NULL;
593 UINT hr = ERROR_INSTALL_FAILURE;
594 WCHAR szwBuffer[GUID_SIZE];
595
596 FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
597
598 if( szComponent )
599 {
600 UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
601 szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
602 if( !szwComponent )
603 goto end;
604 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
605 }
606 else
607 return ERROR_INVALID_PARAMETER;
608
609 hr = MsiGetProductCodeW( szwComponent, szwBuffer );
610
611 if( ERROR_SUCCESS == hr )
612 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
613
614 end:
615 HeapFree( GetProcessHeap(), 0, szwComponent );
616
617 return hr;
618 }
619
620 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
621 {
622 FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer));
623 if (NULL == szComponent)
624 return ERROR_INVALID_PARAMETER;
625 return ERROR_CALL_NOT_IMPLEMENTED;
626 }
627
628 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
629 LPSTR szBuffer, DWORD *pcchValueBuf)
630 {
631 LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
632 UINT hr = ERROR_INSTALL_FAILURE;
633
634 FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute),
635 szBuffer, pcchValueBuf);
636
637 if( NULL != szBuffer && NULL == pcchValueBuf )
638 return ERROR_INVALID_PARAMETER;
639 if( szProduct )
640 {
641 UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
642 szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
643 if( !szwProduct )
644 goto end;
645 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
646 }
647 else
648 return ERROR_INVALID_PARAMETER;
649
650 if( szAttribute )
651 {
652 UINT len = MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, NULL, 0 );
653 szwAttribute = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
654 if( !szwAttribute )
655 goto end;
656 MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, szwAttribute, len );
657 }
658 else
659 {
660 hr = ERROR_INVALID_PARAMETER;
661 goto end;
662 }
663
664 if( szBuffer )
665 {
666 szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
667 if( !szwBuffer )
668 goto end;
669 }
670
671 hr = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf );
672
673 if( ERROR_SUCCESS == hr )
674 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL);
675
676 end:
677 HeapFree( GetProcessHeap(), 0, szwProduct );
678 HeapFree( GetProcessHeap(), 0, szwAttribute );
679 HeapFree( GetProcessHeap(), 0, szwBuffer );
680
681 return hr;
682 }
683
684 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
685 LPWSTR szBuffer, DWORD *pcchValueBuf)
686 {
687 MSIHANDLE hProduct;
688 UINT hr;
689
690 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute),
691 szBuffer, pcchValueBuf);
692
693 if (NULL != szBuffer && NULL == pcchValueBuf)
694 return ERROR_INVALID_PARAMETER;
695 if (NULL == szProduct || NULL == szAttribute)
696 return ERROR_INVALID_PARAMETER;
697
698 hr = MsiOpenProductW(szProduct, &hProduct);
699 if (ERROR_SUCCESS != hr)
700 return hr;
701
702 hr = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
703 MsiCloseHandle(hProduct);
704 return hr;
705 }
706
707 UINT WINAPI MsiDatabaseImportA(LPCSTR szFolderPath, LPCSTR szFilename)
708 {
709 FIXME("%s %s\n",debugstr_a(szFolderPath), debugstr_a(szFilename));
710 return ERROR_CALL_NOT_IMPLEMENTED;
711 }
712
713 UINT WINAPI MsiDatabaseImportW(LPCWSTR szFolderPath, LPCWSTR szFilename)
714 {
715 FIXME("%s %s\n",debugstr_w(szFolderPath), debugstr_w(szFilename));
716 return ERROR_CALL_NOT_IMPLEMENTED;
717 }
718
719 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
720 {
721 LPWSTR szwLogFile = NULL;
722 UINT hr = ERROR_INSTALL_FAILURE;
723
724 FIXME("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes);
725
726 if( szLogFile )
727 {
728 UINT len = MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, NULL, 0 );
729 szwLogFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
730 if( !szwLogFile )
731 goto end;
732 MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, szwLogFile, len );
733 }
734 else
735 return ERROR_INVALID_PARAMETER;
736
737 hr = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
738
739 end:
740 HeapFree( GetProcessHeap(), 0, szwLogFile );
741
742 return hr;
743 }
744
745 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
746 {
747 HANDLE file = INVALID_HANDLE_VALUE;
748
749 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes);
750
751 strcpyW(gszLogFile,szLogFile);
752 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
753 DeleteFileW(szLogFile);
754 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
755 FILE_ATTRIBUTE_NORMAL, NULL);
756 if (file != INVALID_HANDLE_VALUE)
757 CloseHandle(file);
758 else
759 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
760
761 return ERROR_SUCCESS;
762 }
763
764 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
765 {
766 LPWSTR szwProduct;
767 UINT len;
768 INSTALLSTATE rc;
769
770 len = MultiByteToWideChar(CP_ACP,0,szProduct,-1,NULL,0);
771 szwProduct = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
772 MultiByteToWideChar(CP_ACP,0,szProduct,-1,szwProduct,len);
773 rc = MsiQueryProductStateW(szwProduct);
774 HeapFree(GetProcessHeap(),0,szwProduct);
775 return rc;
776 }
777
778 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
779 {
780 UINT rc;
781 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
782 HKEY hkey=0;
783 static const WCHAR szWindowsInstaller[] = {
784 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 };
785 DWORD sz;
786
787 TRACE("%s\n", debugstr_w(szProduct));
788
789 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
790 if (rc != ERROR_SUCCESS)
791 goto end;
792
793 RegCloseKey(hkey);
794
795 rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
796 if (rc != ERROR_SUCCESS)
797 goto end;
798
799 sz = sizeof(rrc);
800 rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz);
801 if (rc != ERROR_SUCCESS)
802 goto end;
803
804 switch (rrc)
805 {
806 case 1:
807 /* default */
808 rrc = INSTALLSTATE_DEFAULT;
809 break;
810 default:
811 FIXME("Unknown install state read from registry (%i)\n",rrc);
812 rrc = INSTALLSTATE_UNKNOWN;
813 break;
814 }
815 end:
816 RegCloseKey(hkey);
817 return rrc;
818 }
819
820 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
821 {
822 INSTALLUILEVEL old = gUILevel;
823 HWND oldwnd = gUIhwnd;
824
825 TRACE("%08x %p\n", dwUILevel, phWnd);
826
827 gUILevel = dwUILevel;
828 if (phWnd)
829 {
830 gUIhwnd = *phWnd;
831 *phWnd = oldwnd;
832 }
833 return old;
834 }
835
836 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
837 DWORD dwMessageFilter, LPVOID pvContext)
838 {
839 INSTALLUI_HANDLERA prev = gUIHandlerA;
840
841 TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext);
842 gUIHandlerA = puiHandler;
843 gUIFilter = dwMessageFilter;
844 gUIContext = pvContext;
845
846 return prev;
847 }
848
849 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
850 DWORD dwMessageFilter, LPVOID pvContext)
851 {
852 INSTALLUI_HANDLERW prev = gUIHandlerW;
853
854 TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext);
855 gUIHandlerW = puiHandler;
856 gUIFilter = dwMessageFilter;
857 gUIContext = pvContext;
858
859 return prev;
860 }
861
862 /******************************************************************
863 * MsiLoadStringW [MSI.@]
864 *
865 * Loads a string from MSI's string resources.
866 *
867 * PARAMS
868 *
869 * handle [I] only -1 is handled currently
870 * id [I] id of the string to be loaded
871 * lpBuffer [O] buffer for the string to be written to
872 * nBufferMax [I] maximum size of the buffer in characters
873 * lang [I] the preferred language for the string
874 *
875 * RETURNS
876 *
877 * If successful, this function returns the language id of the string loaded
878 * If the function fails, the function returns zero.
879 *
880 * NOTES
881 *
882 * The type of the first parameter is unknown. LoadString's prototype
883 * suggests that it might be a module handle. I have made it an MSI handle
884 * for starters, as -1 is an invalid MSI handle, but not an invalid module
885 * handle. Maybe strings can be stored in an MSI database somehow.
886 */
887 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
888 int nBufferMax, LANGID lang )
889 {
890 HRSRC hres;
891 HGLOBAL hResData;
892 LPWSTR p;
893 DWORD i, len;
894
895 TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
896
897 if( handle != -1 )
898 FIXME("don't know how to deal with handle = %08lx\n", handle);
899
900 if( !lang )
901 lang = GetUserDefaultLangID();
902
903 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
904 (LPWSTR)1, lang );
905 if( !hres )
906 return 0;
907 hResData = LoadResource( msi_hInstance, hres );
908 if( !hResData )
909 return 0;
910 p = LockResource( hResData );
911 if( !p )
912 return 0;
913
914 for (i = 0; i < (id&0xf); i++)
915 p += *p + 1;
916 len = *p;
917
918 if( nBufferMax <= len )
919 return 0;
920
921 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
922 lpBuffer[ len ] = 0;
923
924 TRACE("found -> %s\n", debugstr_w(lpBuffer));
925
926 return lang;
927 }
928
929 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
930 int nBufferMax, LANGID lang )
931 {
932 LPWSTR bufW;
933 LANGID r;
934 DWORD len;
935
936 bufW = HeapAlloc(GetProcessHeap(), 0, nBufferMax*sizeof(WCHAR));
937 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
938 if( r )
939 {
940 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
941 if( len <= nBufferMax )
942 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
943 lpBuffer, nBufferMax, NULL, NULL );
944 else
945 r = 0;
946 }
947 HeapFree(GetProcessHeap(), 0, bufW);
948 return r;
949 }
950
951 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
952 DWORD *pcchBuf)
953 {
954 FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
955 return INSTALLSTATE_UNKNOWN;
956 }
957
958 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf,
959 DWORD *pcchBuf)
960 {
961 FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
962 return INSTALLSTATE_UNKNOWN;
963 }
964
965 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
966 WORD wLanguageId, DWORD f)
967 {
968 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),
969 uType,wLanguageId,f);
970 return ERROR_CALL_NOT_IMPLEMENTED;
971 }
972
973 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
974 WORD wLanguageId, DWORD f)
975 {
976 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),
977 uType,wLanguageId,f);
978 return ERROR_CALL_NOT_IMPLEMENTED;
979 }
980
981 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
982 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
983 DWORD* pcchPathBuf )
984 {
985 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName),
986 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
987 pcchPathBuf);
988 return ERROR_CALL_NOT_IMPLEMENTED;
989 }
990
991 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
992 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
993 DWORD* pcchPathBuf )
994 {
995 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName),
996 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
997 pcchPathBuf);
998 return ERROR_CALL_NOT_IMPLEMENTED;
999 }
1000
1001 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
1002 LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1003 {
1004 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1005 return ERROR_CALL_NOT_IMPLEMENTED;
1006 }
1007
1008 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
1009 LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1010 {
1011 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1012 return ERROR_CALL_NOT_IMPLEMENTED;
1013 }
1014
1015 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
1016 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
1017 DWORD* pcbHashData)
1018 {
1019 FIXME("%s %08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
1020 ppcCertContext, pbHashData, pcbHashData);
1021 return ERROR_CALL_NOT_IMPLEMENTED;
1022 }
1023
1024 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
1025 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
1026 DWORD* pcbHashData)
1027 {
1028 FIXME("%s %08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
1029 ppcCertContext, pbHashData, pcbHashData);
1030 return ERROR_CALL_NOT_IMPLEMENTED;
1031 }
1032
1033 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1034 LPSTR szValue, DWORD *pccbValue )
1035 {
1036 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1037 return ERROR_CALL_NOT_IMPLEMENTED;
1038 }
1039
1040 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1041 LPWSTR szValue, DWORD *pccbValue )
1042 {
1043 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1044 return ERROR_CALL_NOT_IMPLEMENTED;
1045 }
1046
1047 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1048 {
1049 UINT r, len;
1050 LPWSTR szPack = NULL;
1051
1052 TRACE("%s\n", debugstr_a(szPackage) );
1053
1054 if( szPackage )
1055 {
1056 len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
1057 szPack = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1058 if( !szPack )
1059 return ERROR_OUTOFMEMORY;
1060 MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szPack, len );
1061 }
1062
1063 r = MsiVerifyPackageW( szPack );
1064
1065 HeapFree( GetProcessHeap(), 0, szPack );
1066
1067 return r;
1068 }
1069
1070 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1071 {
1072 MSIHANDLE handle;
1073 UINT r;
1074
1075 TRACE("%s\n", debugstr_w(szPackage) );
1076
1077 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1078 MsiCloseHandle( handle );
1079
1080 return r;
1081 }
1082
1083 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1084 LPSTR lpPathBuf, DWORD* pcchBuf)
1085 {
1086 LPWSTR szwProduct = NULL, szwComponent = NULL, lpwPathBuf= NULL;
1087 INSTALLSTATE rc;
1088 UINT len, incoming_len;
1089
1090 if( szProduct )
1091 {
1092 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1093 szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1094 if( !szwProduct)
1095 return ERROR_OUTOFMEMORY;
1096 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1097 }
1098
1099 if( szComponent )
1100 {
1101 len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 );
1102 szwComponent= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1103 if( !szwComponent )
1104 {
1105 HeapFree( GetProcessHeap(), 0, szwProduct);
1106 return ERROR_OUTOFMEMORY;
1107 }
1108 MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len );
1109 }
1110
1111 if( pcchBuf && *pcchBuf > 0 )
1112 lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR));
1113 else
1114 lpwPathBuf = NULL;
1115
1116 incoming_len = *pcchBuf;
1117 rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
1118
1119 HeapFree( GetProcessHeap(), 0, szwProduct);
1120 HeapFree( GetProcessHeap(), 0, szwComponent);
1121 if (lpwPathBuf)
1122 {
1123 if (rc != INSTALLSTATE_UNKNOWN)
1124 WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, incoming_len,
1125 lpPathBuf, incoming_len, NULL, NULL);
1126 HeapFree( GetProcessHeap(), 0, lpwPathBuf);
1127 }
1128
1129 return rc;
1130 }
1131
1132 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1133 LPWSTR lpPathBuf, DWORD* pcchBuf)
1134 {
1135 WCHAR squished_pc[GUID_SIZE];
1136 UINT rc;
1137 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
1138 HKEY hkey = 0;
1139 LPWSTR path = NULL;
1140 DWORD sz, type;
1141
1142 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1143 debugstr_w(szComponent), lpPathBuf, pcchBuf);
1144
1145 if( lpPathBuf && !pcchBuf )
1146 return INSTALLSTATE_INVALIDARG;
1147
1148 squash_guid(szProduct,squished_pc);
1149
1150 rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE);
1151 if( rc != ERROR_SUCCESS )
1152 goto end;
1153
1154 RegCloseKey(hkey);
1155
1156 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
1157 if( rc != ERROR_SUCCESS )
1158 goto end;
1159
1160 sz = 0;
1161 type = 0;
1162 rc = RegQueryValueExW( hkey, squished_pc, NULL, &type, NULL, &sz );
1163 if( rc != ERROR_SUCCESS )
1164 goto end;
1165 if( type != REG_SZ )
1166 goto end;
1167
1168 sz += sizeof(WCHAR);
1169 path = HeapAlloc( GetProcessHeap(), 0, sz );
1170 if( !path )
1171 goto end;
1172
1173 rc = RegQueryValueExW( hkey, squished_pc, NULL, NULL, (LPVOID) path, &sz );
1174 if( rc != ERROR_SUCCESS )
1175 goto end;
1176
1177 TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent),
1178 debugstr_w(szProduct), debugstr_w(path));
1179
1180 if (path[0]=='0')
1181 {
1182 FIXME("Registry entry.. check entry\n");
1183 rrc = INSTALLSTATE_LOCAL;
1184 }
1185 else
1186 {
1187 /* PROBABLY a file */
1188 if ( GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES )
1189 rrc = INSTALLSTATE_LOCAL;
1190 else
1191 rrc = INSTALLSTATE_ABSENT;
1192 }
1193
1194 if( pcchBuf )
1195 {
1196 sz = sz / sizeof(WCHAR);
1197 if( *pcchBuf >= sz )
1198 strcpyW( lpPathBuf, path );
1199 *pcchBuf = sz;
1200 }
1201
1202 end:
1203 HeapFree(GetProcessHeap(), 0, path );
1204 RegCloseKey(hkey);
1205 return rrc;
1206 }
1207
1208 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1209 {
1210 INSTALLSTATE rc;
1211 UINT len;
1212 LPWSTR szwProduct= NULL;
1213 LPWSTR szwFeature= NULL;
1214
1215 if( szProduct )
1216 {
1217 len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 );
1218 szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1219 if( !szwProduct)
1220 return ERROR_OUTOFMEMORY;
1221 MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len );
1222 }
1223
1224 if( szFeature )
1225 {
1226 len = MultiByteToWideChar( CP_ACP, 0, szFeature, -1, NULL, 0 );
1227 szwFeature= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1228 if( !szwFeature)
1229 {
1230 HeapFree( GetProcessHeap(), 0, szwProduct);
1231 return ERROR_OUTOFMEMORY;
1232 }
1233 MultiByteToWideChar( CP_ACP, 0, szFeature, -1, szwFeature, len );
1234 }
1235
1236 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1237
1238 HeapFree( GetProcessHeap(), 0, szwProduct);
1239 HeapFree( GetProcessHeap(), 0, szwFeature);
1240
1241 return rc;
1242 }
1243
1244 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1245 {
1246 FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1247 /*
1248 * Iterates all the features components and the features parents components
1249 */
1250 return INSTALLSTATE_LOCAL;
1251 }
1252
1253 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
1254 DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf)
1255 {
1256 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
1257 UINT len, ret = ERROR_OUTOFMEMORY;
1258
1259 if( szFilePath )
1260 {
1261 len = MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, NULL, 0 );
1262 szwFilePath = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1263 if( !szwFilePath )
1264 goto end;
1265 MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, szwFilePath, len );
1266 }
1267
1268 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1269 {
1270 lpwVersionBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR));
1271 if( !lpwVersionBuff )
1272 goto end;
1273 }
1274
1275 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1276 {
1277 lpwLangBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR));
1278 if( !lpwLangBuff )
1279 goto end;
1280 }
1281
1282 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
1283 lpwLangBuff, pcchLangBuf);
1284
1285 if( lpwVersionBuff )
1286 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
1287 lpVersionBuf, *pcchVersionBuf, NULL, NULL);
1288 if( lpwLangBuff )
1289 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
1290 lpLangBuf, *pcchLangBuf, NULL, NULL);
1291
1292 end:
1293 HeapFree(GetProcessHeap(), 0, szwFilePath);
1294 HeapFree(GetProcessHeap(), 0, lpwVersionBuff);
1295 HeapFree(GetProcessHeap(), 0, lpwLangBuff);
1296
1297 return ret;
1298 }
1299
1300 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
1301 DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf)
1302 {
1303 static const WCHAR szVersionResource[] = {'\\',0};
1304 static const WCHAR szVersionFormat[] = {
1305 '%','d','.','%','d','.','%','d','.','%','d',0};
1306 static const WCHAR szLangFormat[] = {'%','d',0};
1307 UINT ret = 0;
1308 DWORD dwVerLen;
1309 LPVOID lpVer = NULL;
1310 VS_FIXEDFILEINFO *ffi;
1311 UINT puLen;
1312 WCHAR tmp[32];
1313
1314 TRACE("%s %p %ld %p %ld\n", debugstr_w(szFilePath),
1315 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
1316 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
1317
1318 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
1319 if( !dwVerLen )
1320 return GetLastError();
1321
1322 lpVer = HeapAlloc(GetProcessHeap(), 0, dwVerLen);
1323 if( !lpVer )
1324 {
1325 ret = ERROR_OUTOFMEMORY;
1326 goto end;
1327 }
1328
1329 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
1330 {
1331 ret = GetLastError();
1332 goto end;
1333 }
1334 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1335 {
1336 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
1337 (puLen > 0) )
1338 {
1339 wsprintfW(tmp, szVersionFormat,
1340 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
1341 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
1342 lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
1343 *pcchVersionBuf = strlenW(lpVersionBuf);
1344 }
1345 else
1346 {
1347 *lpVersionBuf = 0;
1348 *pcchVersionBuf = 0;
1349 }
1350 }
1351
1352 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1353 {
1354 DWORD lang = GetUserDefaultLangID();
1355
1356 FIXME("Retrieve language from file\n");
1357 wsprintfW(tmp, szLangFormat, lang);
1358 lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
1359 *pcchLangBuf = strlenW(lpLangBuf);
1360 }
1361
1362 end:
1363 HeapFree(GetProcessHeap(), 0, lpVer);
1364 return ret;
1365 }
1366
1367
1368 /******************************************************************
1369 * DllMain
1370 */
1371 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1372 {
1373 switch(fdwReason)
1374 {
1375 case DLL_PROCESS_ATTACH:
1376 msi_hInstance = hinstDLL;
1377 DisableThreadLibraryCalls(hinstDLL);
1378 msi_dialog_register_class();
1379 break;
1380 case DLL_PROCESS_DETACH:
1381 msi_dialog_unregister_class();
1382 /* FIXME: Cleanup */
1383 break;
1384 }
1385 return TRUE;
1386 }
1387
1388 typedef struct tagIClassFactoryImpl
1389 {
1390 IClassFactoryVtbl *lpVtbl;
1391 } IClassFactoryImpl;
1392
1393 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
1394 REFIID riid,LPVOID *ppobj)
1395 {
1396 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1397 FIXME("%p %s %p\n",This,debugstr_guid(riid),ppobj);
1398 return E_NOINTERFACE;
1399 }
1400
1401 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
1402 {
1403 return 2;
1404 }
1405
1406 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
1407 {
1408 return 1;
1409 }
1410
1411 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
1412 LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
1413 {
1414 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1415
1416 FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
1417 return E_FAIL;
1418 }
1419
1420 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
1421 {
1422 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1423
1424 FIXME("%p %d\n", This, dolock);
1425 return S_OK;
1426 }
1427
1428 static IClassFactoryVtbl MsiCF_Vtbl =
1429 {
1430 MsiCF_QueryInterface,
1431 MsiCF_AddRef,
1432 MsiCF_Release,
1433 MsiCF_CreateInstance,
1434 MsiCF_LockServer
1435 };
1436
1437 static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl };
1438
1439 /******************************************************************
1440 * DllGetClassObject [MSI.@]
1441 */
1442 HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
1443 {
1444 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1445
1446 if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
1447 IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
1448 IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
1449 IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) ||
1450 IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
1451 {
1452 *ppv = (LPVOID) &Msi_CF;
1453 return S_OK;
1454 }
1455 return CLASS_E_CLASSNOTAVAILABLE;
1456 }
1457
1458 /******************************************************************
1459 * DllGetVersion [MSI.@]
1460 */
1461 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
1462 {
1463 TRACE("%p\n",pdvi);
1464
1465 if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1466 return E_INVALIDARG;
1467
1468 pdvi->dwMajorVersion = MSI_MAJORVERSION;
1469 pdvi->dwMinorVersion = MSI_MINORVERSION;
1470 pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1471 pdvi->dwPlatformID = 1;
1472
1473 return S_OK;
1474 }
1475
1476 /******************************************************************
1477 * DllCanUnloadNow [MSI.@]
1478 */
1479 BOOL WINAPI MSI_DllCanUnloadNow(void)
1480 {
1481 return S_FALSE;
1482 }
1483
1484 UINT WINAPI MsiGetFeatureUsageW(LPCWSTR szProduct, LPCWSTR szFeature,
1485 DWORD* pdwUseCount, WORD* pwDateUsed)
1486 {
1487 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
1488 pdwUseCount, pwDateUsed);
1489 return ERROR_CALL_NOT_IMPLEMENTED;
1490 }
1491
1492 UINT WINAPI MsiGetFeatureUsageA(LPCSTR szProduct, LPCSTR szFeature,
1493 DWORD* pdwUseCount, WORD* pwDateUsed)
1494 {
1495 FIXME("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
1496 pdwUseCount, pwDateUsed);
1497 return ERROR_CALL_NOT_IMPLEMENTED;
1498 }
1499
1500 INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature,
1501 DWORD dwInstallMode, DWORD dwReserved)
1502 {
1503 FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1504 dwInstallMode, dwReserved);
1505
1506 /*
1507 * Polls all the components of the feature to find install state and then
1508 * writes:
1509 * Software\\Microsoft\\Windows\\CurrentVersion\\
1510 * Installer\\Products\\<squishguid>\\<feature>
1511 * "Usage"=dword:........
1512 */
1513
1514 return INSTALLSTATE_LOCAL;
1515 }
1516
1517 INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature,
1518 DWORD dwInstallMode, DWORD dwReserved)
1519 {
1520 FIXME("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1521 dwInstallMode, dwReserved);
1522
1523 return INSTALLSTATE_LOCAL;
1524 }
1525
1526 INSTALLSTATE WINAPI MsiUseFeatureW(LPCWSTR szProduct, LPCWSTR szFeature)
1527 {
1528 FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1529
1530 return INSTALLSTATE_LOCAL;
1531 }
1532
1533 INSTALLSTATE WINAPI MsiUseFeatureA(LPCSTR szProduct, LPCSTR szFeature)
1534 {
1535 FIXME("%s %s\n", debugstr_a(szProduct), debugstr_a(szFeature));
1536
1537 return INSTALLSTATE_LOCAL;
1538 }
1539
1540 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
1541 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1542 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
1543 DWORD* pcchPathBuf)
1544 {
1545 FIXME("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
1546 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
1547 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1548
1549 return ERROR_INDEX_ABSENT;
1550 }
1551
1552 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
1553 DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf,
1554 DWORD* pcchOrgNameBuf, LPWSTR lpSerialBuf, DWORD* pcchSerialBuf)
1555 {
1556 FIXME("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
1557 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1558 pcchSerialBuf);
1559
1560 return USERINFOSTATE_UNKNOWN;
1561 }
1562
1563 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf,
1564 DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf,
1565 DWORD* pcchOrgNameBuf, LPSTR lpSerialBuf, DWORD* pcchSerialBuf)
1566 {
1567 FIXME("%s %p %p %p %p %p %p\n",debugstr_a(szProduct), lpUserNameBuf,
1568 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1569 pcchSerialBuf);
1570
1571 return USERINFOSTATE_UNKNOWN;
1572 }
1573
1574 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
1575 {
1576 FIXME("%s\n",debugstr_w(szProduct));
1577 return ERROR_CALL_NOT_IMPLEMENTED;
1578 }
1579
1580 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
1581 {
1582 FIXME("%s\n",debugstr_a(szProduct));
1583 return ERROR_CALL_NOT_IMPLEMENTED;
1584 }
1585
1586 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(void)
1587 {
1588 FIXME("\n");
1589 return ERROR_CALL_NOT_IMPLEMENTED;
1590 }
1591
1592 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
1593 LPSTR szProductCode, LPSTR szFeatureId,
1594 LPSTR szComponentCode )
1595 {
1596 FIXME("\n");
1597 return ERROR_CALL_NOT_IMPLEMENTED;
1598 }
1599
1600 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
1601 LPWSTR szProductCode, LPWSTR szFeatureId,
1602 LPWSTR szComponentCode )
1603 {
1604 FIXME("\n");
1605 return ERROR_CALL_NOT_IMPLEMENTED;
1606 }
1607
1608 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
1609 DWORD dwReinstallMode )
1610 {
1611 FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1612 dwReinstallMode);
1613 return ERROR_SUCCESS;
1614 }
1615
1616 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
1617 DWORD dwReinstallMode )
1618 {
1619 FIXME("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1620 dwReinstallMode);
1621 return ERROR_SUCCESS;
1622 }