Update MSI to current Wine version.
[reactos.git] / reactos / dll / win32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25
26 #include "stdio.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winreg.h"
30 #include "winnls.h"
31 #include "shlwapi.h"
32 #include "wine/debug.h"
33 #include "msi.h"
34 #include "msiquery.h"
35 #include "msipriv.h"
36 #include "wincrypt.h"
37 #include "winver.h"
38 #include "winuser.h"
39 #include "shlobj.h"
40 #include "shobjidl.h"
41 #include "objidl.h"
42 #include "wine/unicode.h"
43 #include "action.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(msi);
46
47 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
48
49 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
50 {
51 UINT r;
52 LPWSTR szwProd = NULL;
53
54 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
55
56 if( szProduct )
57 {
58 szwProd = strdupAtoW( szProduct );
59 if( !szwProd )
60 return ERROR_OUTOFMEMORY;
61 }
62
63 r = MsiOpenProductW( szwProd, phProduct );
64
65 msi_free( szwProd );
66
67 return r;
68 }
69
70 static UINT MSI_OpenProductW( LPCWSTR szProduct, MSIPACKAGE **ppackage )
71 {
72 LPWSTR path = NULL;
73 UINT r;
74 HKEY hKeyProduct = NULL;
75 DWORD count, type;
76
77 TRACE("%s %p\n", debugstr_w(szProduct), ppackage );
78
79 r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE);
80 if( r != ERROR_SUCCESS )
81 {
82 r = ERROR_UNKNOWN_PRODUCT;
83 goto end;
84 }
85
86 /* find the size of the path */
87 type = count = 0;
88 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
89 NULL, &type, NULL, &count );
90 if( r != ERROR_SUCCESS )
91 {
92 r = ERROR_UNKNOWN_PRODUCT;
93 goto end;
94 }
95
96 /* now alloc and fetch the path of the database to open */
97 path = msi_alloc( count );
98 if( !path )
99 goto end;
100
101 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
102 NULL, &type, (LPBYTE) path, &count );
103 if( r != ERROR_SUCCESS )
104 {
105 r = ERROR_UNKNOWN_PRODUCT;
106 goto end;
107 }
108
109 r = MSI_OpenPackageW( path, ppackage );
110
111 end:
112 msi_free( path );
113 if( hKeyProduct )
114 RegCloseKey( hKeyProduct );
115
116 return r;
117 }
118
119 UINT WINAPI MsiOpenProductW( LPCWSTR szProduct, MSIHANDLE *phProduct )
120 {
121 MSIPACKAGE *package = NULL;
122 UINT r;
123
124 r = MSI_OpenProductW( szProduct, &package );
125 if( r == ERROR_SUCCESS )
126 {
127 *phProduct = alloc_msihandle( &package->hdr );
128 if (! *phProduct)
129 r = ERROR_NOT_ENOUGH_MEMORY;
130 msiobj_release( &package->hdr );
131 }
132 return r;
133 }
134
135 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
136 LPCSTR szTransforms, LANGID lgidLanguage)
137 {
138 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
139 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
140 return ERROR_CALL_NOT_IMPLEMENTED;
141 }
142
143 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
144 LPCWSTR szTransforms, LANGID lgidLanguage)
145 {
146 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
147 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
148 return ERROR_CALL_NOT_IMPLEMENTED;
149 }
150
151 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
152 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
153 {
154 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_a(szPackagePath),
155 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
156 lgidLanguage, dwPlatform, dwOptions);
157 return ERROR_CALL_NOT_IMPLEMENTED;
158 }
159
160 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
161 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
162 {
163 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_w(szPackagePath),
164 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
165 lgidLanguage, dwPlatform, dwOptions);
166 return ERROR_CALL_NOT_IMPLEMENTED;
167 }
168
169 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
170 {
171 LPWSTR szwPath = NULL, szwCommand = NULL;
172 UINT r = ERROR_OUTOFMEMORY;
173
174 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
175
176 if( szPackagePath )
177 {
178 szwPath = strdupAtoW( szPackagePath );
179 if( !szwPath )
180 goto end;
181 }
182
183 if( szCommandLine )
184 {
185 szwCommand = strdupAtoW( szCommandLine );
186 if( !szwCommand )
187 goto end;
188 }
189
190 r = MsiInstallProductW( szwPath, szwCommand );
191
192 end:
193 msi_free( szwPath );
194 msi_free( szwCommand );
195
196 return r;
197 }
198
199 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
200 {
201 MSIPACKAGE *package = NULL;
202 UINT r;
203
204 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
205
206 r = MSI_OpenPackageW( szPackagePath, &package );
207 if (r == ERROR_SUCCESS)
208 {
209 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
210 msiobj_release( &package->hdr );
211 }
212
213 return r;
214 }
215
216 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
217 {
218 FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode);
219 return ERROR_CALL_NOT_IMPLEMENTED;
220 }
221
222 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
223 {
224 FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode);
225 return ERROR_CALL_NOT_IMPLEMENTED;
226 }
227
228 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
229 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
230 {
231 FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
232 eInstallType, debugstr_a(szCommandLine));
233 return ERROR_CALL_NOT_IMPLEMENTED;
234 }
235
236 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
237 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
238 {
239 FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
240 eInstallType, debugstr_w(szCommandLine));
241 return ERROR_CALL_NOT_IMPLEMENTED;
242 }
243
244 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
245 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
246 {
247 MSIPACKAGE* package = NULL;
248 UINT r;
249 DWORD sz;
250 WCHAR sourcepath[MAX_PATH];
251 WCHAR filename[MAX_PATH];
252 static const WCHAR szInstalled[] = {
253 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
254 LPWSTR commandline;
255
256 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
257 debugstr_w(szCommandLine));
258
259 if (eInstallState != INSTALLSTATE_LOCAL &&
260 eInstallState != INSTALLSTATE_DEFAULT)
261 {
262 FIXME("Not implemented for anything other than local installs\n");
263 return ERROR_CALL_NOT_IMPLEMENTED;
264 }
265
266 sz = sizeof(sourcepath);
267 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
268 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
269 &sz);
270
271 sz = sizeof(filename);
272 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
273 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
274
275 lstrcatW(sourcepath,filename);
276
277 /*
278 * ok 1, we need to find the msi file for this product.
279 * 2, find the source dir for the files
280 * 3, do the configure/install.
281 * 4, cleanupany runonce entry.
282 */
283
284 r = MSI_OpenProductW( szProduct, &package );
285 if (r != ERROR_SUCCESS)
286 return r;
287
288 sz = lstrlenW(szInstalled) + 1;
289
290 if (szCommandLine)
291 sz += lstrlenW(szCommandLine);
292
293 commandline = msi_alloc(sz * sizeof(WCHAR));
294 if (!commandline )
295 {
296 r = ERROR_OUTOFMEMORY;
297 goto end;
298 }
299
300 commandline[0] = 0;
301 if (szCommandLine)
302 lstrcpyW(commandline,szCommandLine);
303
304 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
305 lstrcatW(commandline,szInstalled);
306
307 r = MSI_InstallPackage( package, sourcepath, commandline );
308
309 msi_free(commandline);
310
311 end:
312 msiobj_release( &package->hdr );
313
314 return r;
315 }
316
317 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
318 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
319 {
320 LPWSTR szwProduct = NULL;
321 LPWSTR szwCommandLine = NULL;
322 UINT r = ERROR_OUTOFMEMORY;
323
324 if( szProduct )
325 {
326 szwProduct = strdupAtoW( szProduct );
327 if( !szwProduct )
328 goto end;
329 }
330
331 if( szCommandLine)
332 {
333 szwCommandLine = strdupAtoW( szCommandLine );
334 if( !szwCommandLine)
335 goto end;
336 }
337
338 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
339 szwCommandLine );
340 end:
341 msi_free( szwProduct );
342 msi_free( szwCommandLine);
343
344 return r;
345 }
346
347 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
348 INSTALLSTATE eInstallState)
349 {
350 LPWSTR szwProduct = NULL;
351 UINT r;
352
353 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
354
355 if( szProduct )
356 {
357 szwProduct = strdupAtoW( szProduct );
358 if( !szwProduct )
359 return ERROR_OUTOFMEMORY;
360 }
361
362 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
363 msi_free( szwProduct );
364
365 return r;
366 }
367
368 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
369 INSTALLSTATE eInstallState)
370 {
371 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
372 }
373
374 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
375 {
376 LPWSTR szwComponent = NULL;
377 UINT r;
378 WCHAR szwBuffer[GUID_SIZE];
379
380 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
381
382 if( szComponent )
383 {
384 szwComponent = strdupAtoW( szComponent );
385 if( !szwComponent )
386 return ERROR_OUTOFMEMORY;
387 }
388
389 r = MsiGetProductCodeW( szwComponent, szwBuffer );
390
391 if( ERROR_SUCCESS == r )
392 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
393
394 msi_free( szwComponent );
395
396 return r;
397 }
398
399 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
400 {
401 UINT rc;
402 HKEY hkey;
403 WCHAR szSquished[GUID_SIZE];
404 DWORD sz = GUID_SIZE;
405 static const WCHAR szPermKey[] =
406 { '0','0','0','0','0','0','0','0','0','0','0','0',
407 '0','0','0','0','0','0','0','0','0','0','0','0',
408 '0','0','0','0','0','0','0','0',0};
409
410 TRACE("%s %p\n",debugstr_w(szComponent), szBuffer);
411
412 if (NULL == szComponent)
413 return ERROR_INVALID_PARAMETER;
414
415 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
416 if (rc != ERROR_SUCCESS)
417 return ERROR_UNKNOWN_COMPONENT;
418
419 rc = RegEnumValueW(hkey, 0, szSquished, &sz, NULL, NULL, NULL, NULL);
420 if (rc == ERROR_SUCCESS && strcmpW(szSquished,szPermKey)==0)
421 {
422 sz = GUID_SIZE;
423 rc = RegEnumValueW(hkey, 1, szSquished, &sz, NULL, NULL, NULL, NULL);
424 }
425
426 RegCloseKey(hkey);
427
428 if (rc != ERROR_SUCCESS)
429 return ERROR_INSTALL_FAILURE;
430
431 unsquash_guid(szSquished, szBuffer);
432 return ERROR_SUCCESS;
433 }
434
435 UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
436 awstring *szValue, DWORD *pcchValueBuf)
437 {
438 UINT r;
439 HKEY hkey;
440 LPWSTR val = NULL;
441
442 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
443 debugstr_w(szAttribute), szValue, pcchValueBuf);
444
445 /*
446 * FIXME: Values seem scattered/duplicated in the registry. Is there a system?
447 */
448
449 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
450 return ERROR_INVALID_PARAMETER;
451
452 /* check for special properties */
453 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
454 {
455 LPWSTR regval;
456 WCHAR packagecode[35];
457
458 r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
459 if (r != ERROR_SUCCESS)
460 return ERROR_UNKNOWN_PRODUCT;
461
462 regval = msi_reg_get_val_str( hkey, szAttribute );
463 if (regval)
464 {
465 if (unsquash_guid(regval, packagecode))
466 val = strdupW(packagecode);
467 msi_free(regval);
468 }
469
470 RegCloseKey(hkey);
471 }
472 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
473 {
474 static const WCHAR one[] = { '1',0 };
475 /*
476 * FIXME: should be in the Product key (user or system?)
477 * but isn't written yet...
478 */
479 val = strdupW( one );
480 }
481 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
482 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW))
483 {
484 static const WCHAR fmt[] = { '%','u',0 };
485 WCHAR szVal[16];
486 DWORD regval;
487
488 r = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
489 if (r != ERROR_SUCCESS)
490 return ERROR_UNKNOWN_PRODUCT;
491
492 if (msi_reg_get_val_dword( hkey, szAttribute, &regval))
493 {
494 sprintfW(szVal, fmt, regval);
495 val = strdupW( szVal );
496 }
497
498 RegCloseKey(hkey);
499 }
500 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW))
501 {
502 r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
503 if (r != ERROR_SUCCESS)
504 return ERROR_UNKNOWN_PRODUCT;
505
506 val = msi_reg_get_val_str( hkey, szAttribute );
507
508 RegCloseKey(hkey);
509 }
510 else
511 {
512 static const WCHAR szDisplayVersion[] = {
513 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0 };
514
515 FIXME("%s\n", debugstr_w(szAttribute));
516 /* FIXME: some attribute values not tested... */
517
518 if (!lstrcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
519 szAttribute = szDisplayVersion;
520
521 r = MSIREG_OpenUninstallKey( szProduct, &hkey, FALSE );
522 if (r != ERROR_SUCCESS)
523 return ERROR_UNKNOWN_PRODUCT;
524
525 val = msi_reg_get_val_str( hkey, szAttribute );
526
527 RegCloseKey(hkey);
528 }
529
530 TRACE("returning %s\n", debugstr_w(val));
531
532 if (!val)
533 return ERROR_UNKNOWN_PROPERTY;
534
535 r = msi_strcpy_to_awstring( val, szValue, pcchValueBuf );
536
537 msi_free(val);
538
539 return r;
540 }
541
542 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
543 LPSTR szBuffer, DWORD *pcchValueBuf)
544 {
545 LPWSTR szwProduct, szwAttribute = NULL;
546 UINT r = ERROR_OUTOFMEMORY;
547 awstring buffer;
548
549 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
550 szBuffer, pcchValueBuf);
551
552 szwProduct = strdupAtoW( szProduct );
553 if( szProduct && !szwProduct )
554 goto end;
555
556 szwAttribute = strdupAtoW( szAttribute );
557 if( szAttribute && !szwAttribute )
558 goto end;
559
560 buffer.unicode = FALSE;
561 buffer.str.a = szBuffer;
562
563 r = MSI_GetProductInfo( szwProduct, szwAttribute,
564 &buffer, pcchValueBuf );
565
566 end:
567 msi_free( szwProduct );
568 msi_free( szwAttribute );
569
570 return r;
571 }
572
573 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
574 LPWSTR szBuffer, DWORD *pcchValueBuf)
575 {
576 awstring buffer;
577
578 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
579 szBuffer, pcchValueBuf);
580
581 buffer.unicode = TRUE;
582 buffer.str.w = szBuffer;
583
584 return MSI_GetProductInfo( szProduct, szAttribute,
585 &buffer, pcchValueBuf );
586 }
587
588 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
589 {
590 LPWSTR szwLogFile = NULL;
591 UINT r;
592
593 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes);
594
595 if( szLogFile )
596 {
597 szwLogFile = strdupAtoW( szLogFile );
598 if( !szwLogFile )
599 return ERROR_OUTOFMEMORY;
600 }
601 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
602 msi_free( szwLogFile );
603 return r;
604 }
605
606 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
607 {
608 HANDLE file = INVALID_HANDLE_VALUE;
609
610 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes);
611
612 if (szLogFile)
613 {
614 lstrcpyW(gszLogFile,szLogFile);
615 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
616 DeleteFileW(szLogFile);
617 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
618 FILE_ATTRIBUTE_NORMAL, NULL);
619 if (file != INVALID_HANDLE_VALUE)
620 CloseHandle(file);
621 else
622 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
623 }
624 else
625 gszLogFile[0] = '\0';
626
627 return ERROR_SUCCESS;
628 }
629
630 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
631 {
632 LPWSTR szwProduct = NULL;
633 INSTALLSTATE r;
634
635 if( szProduct )
636 {
637 szwProduct = strdupAtoW( szProduct );
638 if( !szwProduct )
639 return ERROR_OUTOFMEMORY;
640 }
641 r = MsiQueryProductStateW( szwProduct );
642 msi_free( szwProduct );
643 return r;
644 }
645
646 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
647 {
648 UINT rc;
649 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
650 HKEY hkey = 0;
651 static const WCHAR szWindowsInstaller[] = {
652 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 };
653 DWORD sz;
654
655 TRACE("%s\n", debugstr_w(szProduct));
656
657 if (!szProduct)
658 return INSTALLSTATE_INVALIDARG;
659
660 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
661 if (rc != ERROR_SUCCESS)
662 goto end;
663
664 RegCloseKey(hkey);
665
666 rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
667 if (rc != ERROR_SUCCESS)
668 goto end;
669
670 sz = sizeof(rrc);
671 rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz);
672 if (rc != ERROR_SUCCESS)
673 goto end;
674
675 switch (rrc)
676 {
677 case 1:
678 /* default */
679 rrc = INSTALLSTATE_DEFAULT;
680 break;
681 default:
682 FIXME("Unknown install state read from registry (%i)\n",rrc);
683 rrc = INSTALLSTATE_UNKNOWN;
684 break;
685 }
686 end:
687 RegCloseKey(hkey);
688 return rrc;
689 }
690
691 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
692 {
693 INSTALLUILEVEL old = gUILevel;
694 HWND oldwnd = gUIhwnd;
695
696 TRACE("%08x %p\n", dwUILevel, phWnd);
697
698 gUILevel = dwUILevel;
699 if (phWnd)
700 {
701 gUIhwnd = *phWnd;
702 *phWnd = oldwnd;
703 }
704 return old;
705 }
706
707 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
708 DWORD dwMessageFilter, LPVOID pvContext)
709 {
710 INSTALLUI_HANDLERA prev = gUIHandlerA;
711
712 TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext);
713 gUIHandlerA = puiHandler;
714 gUIFilter = dwMessageFilter;
715 gUIContext = pvContext;
716
717 return prev;
718 }
719
720 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
721 DWORD dwMessageFilter, LPVOID pvContext)
722 {
723 INSTALLUI_HANDLERW prev = gUIHandlerW;
724
725 TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext);
726 gUIHandlerW = puiHandler;
727 gUIFilter = dwMessageFilter;
728 gUIContext = pvContext;
729
730 return prev;
731 }
732
733 /******************************************************************
734 * MsiLoadStringW [MSI.@]
735 *
736 * Loads a string from MSI's string resources.
737 *
738 * PARAMS
739 *
740 * handle [I] only -1 is handled currently
741 * id [I] id of the string to be loaded
742 * lpBuffer [O] buffer for the string to be written to
743 * nBufferMax [I] maximum size of the buffer in characters
744 * lang [I] the preferred language for the string
745 *
746 * RETURNS
747 *
748 * If successful, this function returns the language id of the string loaded
749 * If the function fails, the function returns zero.
750 *
751 * NOTES
752 *
753 * The type of the first parameter is unknown. LoadString's prototype
754 * suggests that it might be a module handle. I have made it an MSI handle
755 * for starters, as -1 is an invalid MSI handle, but not an invalid module
756 * handle. Maybe strings can be stored in an MSI database somehow.
757 */
758 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
759 int nBufferMax, LANGID lang )
760 {
761 HRSRC hres;
762 HGLOBAL hResData;
763 LPWSTR p;
764 DWORD i, len;
765
766 TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
767
768 if( handle != -1 )
769 FIXME("don't know how to deal with handle = %08lx\n", handle);
770
771 if( !lang )
772 lang = GetUserDefaultLangID();
773
774 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
775 (LPWSTR)1, lang );
776 if( !hres )
777 return 0;
778 hResData = LoadResource( msi_hInstance, hres );
779 if( !hResData )
780 return 0;
781 p = LockResource( hResData );
782 if( !p )
783 return 0;
784
785 for (i = 0; i < (id&0xf); i++)
786 p += *p + 1;
787 len = *p;
788
789 if( nBufferMax <= len )
790 return 0;
791
792 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
793 lpBuffer[ len ] = 0;
794
795 TRACE("found -> %s\n", debugstr_w(lpBuffer));
796
797 return lang;
798 }
799
800 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
801 int nBufferMax, LANGID lang )
802 {
803 LPWSTR bufW;
804 LANGID r;
805 DWORD len;
806
807 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
808 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
809 if( r )
810 {
811 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
812 if( len <= nBufferMax )
813 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
814 lpBuffer, nBufferMax, NULL, NULL );
815 else
816 r = 0;
817 }
818 msi_free(bufW);
819 return r;
820 }
821
822 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
823 DWORD *pcchBuf)
824 {
825 char szProduct[GUID_SIZE];
826
827 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
828
829 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
830 return INSTALLSTATE_UNKNOWN;
831
832 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
833 }
834
835 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
836 DWORD *pcchBuf)
837 {
838 WCHAR szProduct[GUID_SIZE];
839
840 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
841
842 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
843 return INSTALLSTATE_UNKNOWN;
844
845 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
846 }
847
848 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
849 WORD wLanguageId, DWORD f)
850 {
851 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),
852 uType,wLanguageId,f);
853 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
854 }
855
856 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
857 WORD wLanguageId, DWORD f)
858 {
859 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),
860 uType,wLanguageId,f);
861 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
862 }
863
864 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
865 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
866 DWORD* pcchPathBuf )
867 {
868 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName),
869 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
870 pcchPathBuf);
871 return ERROR_CALL_NOT_IMPLEMENTED;
872 }
873
874 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
875 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
876 DWORD* pcchPathBuf )
877 {
878 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName),
879 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
880 pcchPathBuf);
881 return ERROR_CALL_NOT_IMPLEMENTED;
882 }
883
884 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
885 LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
886 {
887 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
888 return ERROR_CALL_NOT_IMPLEMENTED;
889 }
890
891 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
892 LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
893 {
894 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
895 return ERROR_CALL_NOT_IMPLEMENTED;
896 }
897
898 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
899 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
900 DWORD* pcbHashData)
901 {
902 FIXME("%s %08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
903 ppcCertContext, pbHashData, pcbHashData);
904 return ERROR_CALL_NOT_IMPLEMENTED;
905 }
906
907 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
908 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
909 DWORD* pcbHashData)
910 {
911 FIXME("%s %08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
912 ppcCertContext, pbHashData, pcbHashData);
913 return ERROR_CALL_NOT_IMPLEMENTED;
914 }
915
916 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
917 LPSTR szValue, DWORD *pccbValue )
918 {
919 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
920 return ERROR_CALL_NOT_IMPLEMENTED;
921 }
922
923 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
924 LPWSTR szValue, DWORD *pccbValue )
925 {
926 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
927 return ERROR_CALL_NOT_IMPLEMENTED;
928 }
929
930 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
931 {
932 UINT r;
933 LPWSTR szPack = NULL;
934
935 TRACE("%s\n", debugstr_a(szPackage) );
936
937 if( szPackage )
938 {
939 szPack = strdupAtoW( szPackage );
940 if( !szPack )
941 return ERROR_OUTOFMEMORY;
942 }
943
944 r = MsiVerifyPackageW( szPack );
945
946 msi_free( szPack );
947
948 return r;
949 }
950
951 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
952 {
953 MSIHANDLE handle;
954 UINT r;
955
956 TRACE("%s\n", debugstr_w(szPackage) );
957
958 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
959 MsiCloseHandle( handle );
960
961 return r;
962 }
963
964 INSTALLSTATE WINAPI MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
965 awstring* lpPathBuf, DWORD* pcchBuf)
966 {
967 WCHAR squished_pc[GUID_SIZE], squished_comp[GUID_SIZE];
968 UINT rc;
969 HKEY hkey = 0;
970 LPWSTR path = NULL;
971 INSTALLSTATE r;
972
973 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
974 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
975
976 if( !szProduct || !szComponent )
977 return INSTALLSTATE_INVALIDARG;
978 if( lpPathBuf->str.w && !pcchBuf )
979 return INSTALLSTATE_INVALIDARG;
980
981 if (!squash_guid( szProduct, squished_pc ) ||
982 !squash_guid( szComponent, squished_comp ))
983 return INSTALLSTATE_INVALIDARG;
984
985 rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE);
986 if( rc != ERROR_SUCCESS )
987 return INSTALLSTATE_UNKNOWN;
988
989 RegCloseKey(hkey);
990
991 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
992 if( rc != ERROR_SUCCESS )
993 return INSTALLSTATE_UNKNOWN;
994
995 path = msi_reg_get_val_str( hkey, squished_pc );
996 RegCloseKey(hkey);
997
998 TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent),
999 debugstr_w(szProduct), debugstr_w(path));
1000
1001 if (!path)
1002 return INSTALLSTATE_UNKNOWN;
1003
1004 if (path[0])
1005 r = INSTALLSTATE_LOCAL;
1006 else
1007 r = INSTALLSTATE_NOTUSED;
1008
1009 msi_strcpy_to_awstring( path, lpPathBuf, pcchBuf );
1010
1011 msi_free( path );
1012 return r;
1013 }
1014
1015 /******************************************************************
1016 * MsiGetComponentPathW [MSI.@]
1017 */
1018 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1019 LPWSTR lpPathBuf, DWORD* pcchBuf)
1020 {
1021 awstring path;
1022
1023 path.unicode = TRUE;
1024 path.str.w = lpPathBuf;
1025
1026 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
1027 }
1028
1029 /******************************************************************
1030 * MsiGetComponentPathA [MSI.@]
1031 */
1032 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1033 LPSTR lpPathBuf, DWORD* pcchBuf)
1034 {
1035 LPWSTR szwProduct, szwComponent = NULL;
1036 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
1037 awstring path;
1038
1039 szwProduct = strdupAtoW( szProduct );
1040 if( szProduct && !szwProduct)
1041 goto end;
1042
1043 szwComponent = strdupAtoW( szComponent );
1044 if( szComponent && !szwComponent )
1045 goto end;
1046
1047 path.unicode = FALSE;
1048 path.str.a = lpPathBuf;
1049
1050 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
1051
1052 end:
1053 msi_free( szwProduct );
1054 msi_free( szwComponent );
1055
1056 return r;
1057 }
1058
1059 /******************************************************************
1060 * MsiQueryFeatureStateA [MSI.@]
1061 */
1062 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1063 {
1064 LPWSTR szwProduct = NULL, szwFeature= NULL;
1065 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
1066
1067 szwProduct = strdupAtoW( szProduct );
1068 if ( szProduct && !szwProduct )
1069 goto end;
1070
1071 szwFeature = strdupAtoW( szFeature );
1072 if ( szFeature && !szwFeature )
1073 goto end;
1074
1075 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1076
1077 end:
1078 msi_free( szwProduct);
1079 msi_free( szwFeature);
1080
1081 return rc;
1082 }
1083
1084 /******************************************************************
1085 * MsiQueryFeatureStateW [MSI.@]
1086 *
1087 * Checks the state of a feature
1088 *
1089 * PARAMS
1090 * szProduct [I] Product's GUID string
1091 * szFeature [I] Feature's GUID string
1092 *
1093 * RETURNS
1094 * INSTALLSTATE_LOCAL Feature is installed and useable
1095 * INSTALLSTATE_ABSENT Feature is absent
1096 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
1097 * INSTALLSTATE_UNKNOWN An error occurred
1098 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
1099 *
1100 */
1101 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1102 {
1103 WCHAR squishProduct[33], comp[GUID_SIZE];
1104 GUID guid;
1105 LPWSTR components, p, parent_feature;
1106 UINT rc;
1107 HKEY hkey;
1108 INSTALLSTATE r;
1109 BOOL missing = FALSE;
1110
1111 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1112
1113 if (!szProduct || !szFeature)
1114 return INSTALLSTATE_INVALIDARG;
1115
1116 if (!squash_guid( szProduct, squishProduct ))
1117 return INSTALLSTATE_INVALIDARG;
1118
1119 /* check that it's installed at all */
1120 rc = MSIREG_OpenUserFeaturesKey(szProduct, &hkey, FALSE);
1121 if (rc != ERROR_SUCCESS)
1122 return INSTALLSTATE_UNKNOWN;
1123
1124 parent_feature = msi_reg_get_val_str( hkey, szFeature );
1125 RegCloseKey(hkey);
1126
1127 if (!parent_feature)
1128 return INSTALLSTATE_UNKNOWN;
1129
1130 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
1131 msi_free(parent_feature);
1132 if (r == INSTALLSTATE_ABSENT)
1133 return r;
1134
1135 /* now check if it's complete or advertised */
1136 rc = MSIREG_OpenFeaturesKey(szProduct, &hkey, FALSE);
1137 if (rc != ERROR_SUCCESS)
1138 return INSTALLSTATE_UNKNOWN;
1139
1140 components = msi_reg_get_val_str( hkey, szFeature );
1141 RegCloseKey(hkey);
1142
1143 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
1144
1145 if (!components)
1146 {
1147 ERR("components missing %s %s\n",
1148 debugstr_w(szProduct), debugstr_w(szFeature));
1149 return INSTALLSTATE_UNKNOWN;
1150 }
1151
1152 for( p = components; *p != 2 ; p += 20)
1153 {
1154 if (!decode_base85_guid( p, &guid ))
1155 {
1156 ERR("%s\n", debugstr_w(p));
1157 break;
1158 }
1159 StringFromGUID2(&guid, comp, GUID_SIZE);
1160 r = MsiGetComponentPathW(szProduct, comp, NULL, 0);
1161 TRACE("component %s state %d\n", debugstr_guid(&guid), r);
1162 switch (r)
1163 {
1164 case INSTALLSTATE_NOTUSED:
1165 case INSTALLSTATE_LOCAL:
1166 case INSTALLSTATE_SOURCE:
1167 break;
1168 default:
1169 missing = TRUE;
1170 }
1171 }
1172
1173 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
1174 msi_free(components);
1175
1176 if (missing)
1177 return INSTALLSTATE_ADVERTISED;
1178
1179 return INSTALLSTATE_LOCAL;
1180 }
1181
1182 /******************************************************************
1183 * MsiGetFileVersionA [MSI.@]
1184 */
1185 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
1186 DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf)
1187 {
1188 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
1189 UINT ret = ERROR_OUTOFMEMORY;
1190
1191 if( szFilePath )
1192 {
1193 szwFilePath = strdupAtoW( szFilePath );
1194 if( !szwFilePath )
1195 goto end;
1196 }
1197
1198 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1199 {
1200 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
1201 if( !lpwVersionBuff )
1202 goto end;
1203 }
1204
1205 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1206 {
1207 lpwLangBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
1208 if( !lpwLangBuff )
1209 goto end;
1210 }
1211
1212 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
1213 lpwLangBuff, pcchLangBuf);
1214
1215 if( lpwVersionBuff )
1216 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
1217 lpVersionBuf, *pcchVersionBuf, NULL, NULL);
1218 if( lpwLangBuff )
1219 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
1220 lpLangBuf, *pcchLangBuf, NULL, NULL);
1221
1222 end:
1223 msi_free(szwFilePath);
1224 msi_free(lpwVersionBuff);
1225 msi_free(lpwLangBuff);
1226
1227 return ret;
1228 }
1229
1230 /******************************************************************
1231 * MsiGetFileVersionW [MSI.@]
1232 */
1233 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
1234 DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf)
1235 {
1236 static WCHAR szVersionResource[] = {'\\',0};
1237 static const WCHAR szVersionFormat[] = {
1238 '%','d','.','%','d','.','%','d','.','%','d',0};
1239 static const WCHAR szLangFormat[] = {'%','d',0};
1240 UINT ret = 0;
1241 DWORD dwVerLen;
1242 LPVOID lpVer = NULL;
1243 VS_FIXEDFILEINFO *ffi;
1244 UINT puLen;
1245 WCHAR tmp[32];
1246
1247 TRACE("%s %p %ld %p %ld\n", debugstr_w(szFilePath),
1248 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
1249 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
1250
1251 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
1252 if( !dwVerLen )
1253 return GetLastError();
1254
1255 lpVer = msi_alloc(dwVerLen);
1256 if( !lpVer )
1257 {
1258 ret = ERROR_OUTOFMEMORY;
1259 goto end;
1260 }
1261
1262 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
1263 {
1264 ret = GetLastError();
1265 goto end;
1266 }
1267 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1268 {
1269 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
1270 (puLen > 0) )
1271 {
1272 wsprintfW(tmp, szVersionFormat,
1273 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
1274 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
1275 lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
1276 *pcchVersionBuf = lstrlenW(lpVersionBuf);
1277 }
1278 else
1279 {
1280 *lpVersionBuf = 0;
1281 *pcchVersionBuf = 0;
1282 }
1283 }
1284
1285 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1286 {
1287 DWORD lang = GetUserDefaultLangID();
1288
1289 FIXME("Retrieve language from file\n");
1290 wsprintfW(tmp, szLangFormat, lang);
1291 lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
1292 *pcchLangBuf = lstrlenW(lpLangBuf);
1293 }
1294
1295 end:
1296 msi_free(lpVer);
1297 return ret;
1298 }
1299
1300 /***********************************************************************
1301 * MsiGetFeatureUsageW [MSI.@]
1302 */
1303 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
1304 DWORD* pdwUseCount, WORD* pwDateUsed )
1305 {
1306 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
1307 pdwUseCount, pwDateUsed);
1308 return ERROR_CALL_NOT_IMPLEMENTED;
1309 }
1310
1311 /***********************************************************************
1312 * MsiGetFeatureUsageA [MSI.@]
1313 */
1314 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
1315 DWORD* pdwUseCount, WORD* pwDateUsed )
1316 {
1317 LPWSTR prod = NULL, feat = NULL;
1318 UINT ret = ERROR_OUTOFMEMORY;
1319
1320 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
1321 pdwUseCount, pwDateUsed);
1322
1323 prod = strdupAtoW( szProduct );
1324 if (szProduct && !prod)
1325 goto end;
1326
1327 feat = strdupAtoW( szFeature );
1328 if (szFeature && !feat)
1329 goto end;
1330
1331 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
1332
1333 end:
1334 msi_free( prod );
1335 msi_free( feat );
1336
1337 return ret;
1338 }
1339
1340 /***********************************************************************
1341 * MsiUseFeatureExW [MSI.@]
1342 */
1343 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
1344 DWORD dwInstallMode, DWORD dwReserved )
1345 {
1346 INSTALLSTATE state;
1347
1348 TRACE("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1349 dwInstallMode, dwReserved);
1350
1351 state = MsiQueryFeatureStateW( szProduct, szFeature );
1352
1353 if (dwReserved)
1354 return INSTALLSTATE_INVALIDARG;
1355
1356 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
1357 {
1358 FIXME("mark product %s feature %s as used\n",
1359 debugstr_w(szProduct), debugstr_w(szFeature) );
1360 }
1361
1362 return state;
1363 }
1364
1365 /***********************************************************************
1366 * MsiUseFeatureExA [MSI.@]
1367 */
1368 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
1369 DWORD dwInstallMode, DWORD dwReserved )
1370 {
1371 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
1372 LPWSTR prod = NULL, feat = NULL;
1373
1374 TRACE("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1375 dwInstallMode, dwReserved);
1376
1377 prod = strdupAtoW( szProduct );
1378 if (szProduct && !prod)
1379 goto end;
1380
1381 feat = strdupAtoW( szFeature );
1382 if (szFeature && !feat)
1383 goto end;
1384
1385 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
1386
1387 end:
1388 msi_free( prod );
1389 msi_free( feat );
1390
1391 return ret;
1392 }
1393
1394 /***********************************************************************
1395 * MsiUseFeatureW [MSI.@]
1396 */
1397 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
1398 {
1399 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
1400 }
1401
1402 /***********************************************************************
1403 * MsiUseFeatureA [MSI.@]
1404 */
1405 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
1406 {
1407 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
1408 }
1409
1410 /***********************************************************************
1411 * MSI_ProvideQualifiedComponentEx [internal]
1412 */
1413 UINT WINAPI MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
1414 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1415 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
1416 DWORD* pcchPathBuf)
1417 {
1418 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
1419 feature[MAX_FEATURE_CHARS+1];
1420 LPWSTR info;
1421 HKEY hkey;
1422 DWORD sz;
1423 UINT rc;
1424
1425 TRACE("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
1426 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
1427 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1428
1429 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
1430 if (rc != ERROR_SUCCESS)
1431 return ERROR_INDEX_ABSENT;
1432
1433 info = msi_reg_get_val_str( hkey, szQualifier );
1434 RegCloseKey(hkey);
1435
1436 if (!info)
1437 return ERROR_INDEX_ABSENT;
1438
1439 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
1440
1441 if (!szProduct)
1442 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
1443 else
1444 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
1445
1446 msi_free( info );
1447
1448 if (rc != INSTALLSTATE_LOCAL)
1449 return ERROR_FILE_NOT_FOUND;
1450
1451 return ERROR_SUCCESS;
1452 }
1453
1454 /***********************************************************************
1455 * MsiProvideQualifiedComponentExW [MSI.@]
1456 */
1457 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
1458 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1459 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
1460 DWORD* pcchPathBuf)
1461 {
1462 awstring path;
1463
1464 path.unicode = TRUE;
1465 path.str.w = lpPathBuf;
1466
1467 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
1468 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
1469 }
1470
1471 /***********************************************************************
1472 * MsiProvideQualifiedComponentExA [MSI.@]
1473 */
1474 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
1475 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR szProduct,
1476 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
1477 DWORD* pcchPathBuf)
1478 {
1479 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
1480 UINT r = ERROR_OUTOFMEMORY;
1481 awstring path;
1482
1483 TRACE("%s %s %lu %s %lu %lu %p %p\n", debugstr_a(szComponent),
1484 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
1485 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1486
1487 szwComponent = strdupAtoW( szComponent );
1488 if (szComponent && !szwComponent)
1489 goto end;
1490
1491 szwQualifier = strdupAtoW( szQualifier );
1492 if (szQualifier && !szwQualifier)
1493 goto end;
1494
1495 szwProduct = strdupAtoW( szProduct );
1496 if (szProduct && !szwProduct)
1497 goto end;
1498
1499 path.unicode = FALSE;
1500 path.str.a = lpPathBuf;
1501
1502 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
1503 dwInstallMode, szwProduct, Unused1,
1504 Unused2, &path, pcchPathBuf);
1505 end:
1506 msi_free(szwProduct);
1507 msi_free(szwComponent);
1508 msi_free(szwQualifier);
1509
1510 return r;
1511 }
1512
1513 /***********************************************************************
1514 * MsiProvideQualifiedComponentW [MSI.@]
1515 */
1516 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
1517 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
1518 DWORD* pcchPathBuf)
1519 {
1520 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
1521 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
1522 }
1523
1524 /***********************************************************************
1525 * MsiProvideQualifiedComponentA [MSI.@]
1526 */
1527 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
1528 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
1529 DWORD* pcchPathBuf)
1530 {
1531 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
1532 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
1533 }
1534
1535 /***********************************************************************
1536 * MSI_GetUserInfo [internal]
1537 */
1538 USERINFOSTATE WINAPI MSI_GetUserInfo(LPCWSTR szProduct,
1539 awstring *lpUserNameBuf, DWORD* pcchUserNameBuf,
1540 awstring *lpOrgNameBuf, DWORD* pcchOrgNameBuf,
1541 awstring *lpSerialBuf, DWORD* pcchSerialBuf)
1542 {
1543 HKEY hkey;
1544 LPWSTR user, org, serial;
1545 UINT r;
1546 USERINFOSTATE state;
1547
1548 TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
1549 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1550 pcchSerialBuf);
1551
1552 if (!szProduct)
1553 return USERINFOSTATE_INVALIDARG;
1554
1555 r = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
1556 if (r != ERROR_SUCCESS)
1557 return USERINFOSTATE_UNKNOWN;
1558
1559 user = msi_reg_get_val_str( hkey, INSTALLPROPERTY_REGOWNERW );
1560 org = msi_reg_get_val_str( hkey, INSTALLPROPERTY_REGCOMPANYW );
1561 serial = msi_reg_get_val_str( hkey, INSTALLPROPERTY_PRODUCTIDW );
1562
1563 RegCloseKey(hkey);
1564
1565 state = USERINFOSTATE_PRESENT;
1566
1567 r = msi_strcpy_to_awstring( user, lpUserNameBuf, pcchUserNameBuf );
1568 if (r == ERROR_MORE_DATA)
1569 state = USERINFOSTATE_MOREDATA;
1570 r = msi_strcpy_to_awstring( org, lpOrgNameBuf, pcchOrgNameBuf );
1571 if (r == ERROR_MORE_DATA)
1572 state = USERINFOSTATE_MOREDATA;
1573 r = msi_strcpy_to_awstring( serial, lpSerialBuf, pcchSerialBuf );
1574 if (r == ERROR_MORE_DATA)
1575 state = USERINFOSTATE_MOREDATA;
1576
1577 msi_free( user );
1578 msi_free( org );
1579 msi_free( serial );
1580
1581 return state;
1582 }
1583
1584 /***********************************************************************
1585 * MsiGetUserInfoW [MSI.@]
1586 */
1587 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
1588 LPWSTR lpUserNameBuf, DWORD* pcchUserNameBuf,
1589 LPWSTR lpOrgNameBuf, DWORD* pcchOrgNameBuf,
1590 LPWSTR lpSerialBuf, DWORD* pcchSerialBuf)
1591 {
1592 awstring user, org, serial;
1593
1594 user.unicode = TRUE;
1595 user.str.w = lpUserNameBuf;
1596 org.unicode = TRUE;
1597 org.str.w = lpOrgNameBuf;
1598 serial.unicode = TRUE;
1599 serial.str.w = lpSerialBuf;
1600
1601 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
1602 &org, pcchOrgNameBuf,
1603 &serial, pcchSerialBuf );
1604 }
1605
1606 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
1607 LPSTR lpUserNameBuf, DWORD* pcchUserNameBuf,
1608 LPSTR lpOrgNameBuf, DWORD* pcchOrgNameBuf,
1609 LPSTR lpSerialBuf, DWORD* pcchSerialBuf)
1610 {
1611 awstring user, org, serial;
1612 LPWSTR prod;
1613 UINT r;
1614
1615 prod = strdupAtoW( szProduct );
1616 if (szProduct && !prod)
1617 return ERROR_OUTOFMEMORY;
1618
1619 user.unicode = FALSE;
1620 user.str.a = lpUserNameBuf;
1621 org.unicode = FALSE;
1622 org.str.a = lpOrgNameBuf;
1623 serial.unicode = FALSE;
1624 serial.str.a = lpSerialBuf;
1625
1626 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
1627 &org, pcchOrgNameBuf,
1628 &serial, pcchSerialBuf );
1629
1630 msi_free( prod );
1631
1632 return r;
1633 }
1634
1635 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
1636 {
1637 MSIHANDLE handle;
1638 UINT rc;
1639 MSIPACKAGE *package;
1640 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1641
1642 TRACE("(%s)\n",debugstr_w(szProduct));
1643
1644 rc = MsiOpenProductW(szProduct,&handle);
1645 if (rc != ERROR_SUCCESS)
1646 return ERROR_INVALID_PARAMETER;
1647
1648 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1649 rc = ACTION_PerformUIAction(package, szFirstRun);
1650 msiobj_release( &package->hdr );
1651
1652 MsiCloseHandle(handle);
1653
1654 return rc;
1655 }
1656
1657 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
1658 {
1659 MSIHANDLE handle;
1660 UINT rc;
1661 MSIPACKAGE *package;
1662 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1663
1664 TRACE("(%s)\n",debugstr_a(szProduct));
1665
1666 rc = MsiOpenProductA(szProduct,&handle);
1667 if (rc != ERROR_SUCCESS)
1668 return ERROR_INVALID_PARAMETER;
1669
1670 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1671 rc = ACTION_PerformUIAction(package, szFirstRun);
1672 msiobj_release( &package->hdr );
1673
1674 MsiCloseHandle(handle);
1675
1676 return rc;
1677 }
1678
1679 /***********************************************************************
1680 * MsiConfigureFeatureA [MSI.@]
1681 */
1682 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
1683 {
1684 LPWSTR prod, feat = NULL;
1685 UINT r = ERROR_OUTOFMEMORY;
1686
1687 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
1688
1689 prod = strdupAtoW( szProduct );
1690 if (szProduct && !prod)
1691 goto end;
1692
1693 feat = strdupAtoW( szFeature );
1694 if (szFeature && !feat)
1695 goto end;
1696
1697 r = MsiConfigureFeatureW(prod, feat, eInstallState);
1698
1699 end:
1700 msi_free(feat);
1701 msi_free(prod);
1702
1703 return r;
1704 }
1705
1706 /***********************************************************************
1707 * MsiConfigureFeatureW [MSI.@]
1708 */
1709 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
1710 {
1711 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
1712 MSIPACKAGE *package = NULL;
1713 UINT r;
1714 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
1715 DWORD sz;
1716
1717 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
1718
1719 if (!szProduct || !szFeature)
1720 return ERROR_INVALID_PARAMETER;
1721
1722 switch (eInstallState)
1723 {
1724 case INSTALLSTATE_DEFAULT:
1725 /* FIXME: how do we figure out the default location? */
1726 eInstallState = INSTALLSTATE_LOCAL;
1727 break;
1728 case INSTALLSTATE_LOCAL:
1729 case INSTALLSTATE_SOURCE:
1730 case INSTALLSTATE_ABSENT:
1731 case INSTALLSTATE_ADVERTISED:
1732 break;
1733 default:
1734 return ERROR_INVALID_PARAMETER;
1735 }
1736
1737 r = MSI_OpenProductW( szProduct, &package );
1738 if (r != ERROR_SUCCESS)
1739 return r;
1740
1741 sz = sizeof(sourcepath);
1742 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1743 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
1744
1745 sz = sizeof(filename);
1746 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1747 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
1748
1749 lstrcatW( sourcepath, filename );
1750
1751 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
1752
1753 r = ACTION_PerformUIAction( package, szCostInit );
1754 if (r != ERROR_SUCCESS)
1755 goto end;
1756
1757 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
1758 if (r != ERROR_SUCCESS)
1759 goto end;
1760
1761 r = MSI_InstallPackage( package, sourcepath, NULL );
1762
1763 end:
1764 msiobj_release( &package->hdr );
1765
1766 return r;
1767 }
1768
1769 /***********************************************************************
1770 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
1771 *
1772 * Notes: undocumented
1773 */
1774 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
1775 {
1776 WCHAR path[MAX_PATH];
1777
1778 TRACE("%ld\n", dwReserved);
1779
1780 if (dwReserved)
1781 {
1782 FIXME("dwReserved=%ld\n", dwReserved);
1783 return ERROR_INVALID_PARAMETER;
1784 }
1785
1786 if (!GetWindowsDirectoryW(path, MAX_PATH))
1787 return ERROR_FUNCTION_FAILED;
1788
1789 lstrcatW(path, installerW);
1790
1791 if (!CreateDirectoryW(path, NULL))
1792 return ERROR_FUNCTION_FAILED;
1793
1794 return ERROR_SUCCESS;
1795 }
1796
1797 /***********************************************************************
1798 * MsiGetShortcutTargetA [MSI.@]
1799 */
1800 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
1801 LPSTR szProductCode, LPSTR szFeatureId,
1802 LPSTR szComponentCode )
1803 {
1804 LPWSTR target;
1805 const int len = MAX_FEATURE_CHARS+1;
1806 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
1807 UINT r;
1808
1809 target = strdupAtoW( szShortcutTarget );
1810 if (szShortcutTarget && !target )
1811 return ERROR_OUTOFMEMORY;
1812 product[0] = 0;
1813 feature[0] = 0;
1814 component[0] = 0;
1815 r = MsiGetShortcutTargetW( target, product, feature, component );
1816 msi_free( target );
1817 if (r == ERROR_SUCCESS)
1818 {
1819 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
1820 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
1821 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
1822 }
1823 return r;
1824 }
1825
1826 /***********************************************************************
1827 * MsiGetShortcutTargetW [MSI.@]
1828 */
1829 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
1830 LPWSTR szProductCode, LPWSTR szFeatureId,
1831 LPWSTR szComponentCode )
1832 {
1833 IShellLinkDataList *dl = NULL;
1834 IPersistFile *pf = NULL;
1835 LPEXP_DARWIN_LINK darwin = NULL;
1836 HRESULT r, init;
1837
1838 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
1839 szProductCode, szFeatureId, szComponentCode );
1840
1841 init = CoInitialize(NULL);
1842
1843 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
1844 &IID_IPersistFile, (LPVOID*) &pf );
1845 if( SUCCEEDED( r ) )
1846 {
1847 r = IPersistFile_Load( pf, szShortcutTarget,
1848 STGM_READ | STGM_SHARE_DENY_WRITE );
1849 if( SUCCEEDED( r ) )
1850 {
1851 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
1852 (LPVOID*) &dl );
1853 if( SUCCEEDED( r ) )
1854 {
1855 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
1856 (LPVOID) &darwin );
1857 IShellLinkDataList_Release( dl );
1858 }
1859 }
1860 IPersistFile_Release( pf );
1861 }
1862
1863 if (SUCCEEDED(init))
1864 CoUninitialize();
1865
1866 TRACE("darwin = %p\n", darwin);
1867
1868 if (darwin)
1869 {
1870 DWORD sz;
1871 UINT ret;
1872
1873 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
1874 szProductCode, szFeatureId, szComponentCode, &sz );
1875 LocalFree( darwin );
1876 return ret;
1877 }
1878
1879 return ERROR_FUNCTION_FAILED;
1880 }
1881
1882 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
1883 DWORD dwReinstallMode )
1884 {
1885 MSIPACKAGE* package = NULL;
1886 UINT r;
1887 WCHAR sourcepath[MAX_PATH];
1888 WCHAR filename[MAX_PATH];
1889 static const WCHAR szLogVerbose[] = {
1890 ' ','L','O','G','V','E','R','B','O','S','E',0 };
1891 static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
1892 static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
1893 static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
1894 static const WCHAR szOne[] = {'1',0};
1895 WCHAR reinstallmode[11];
1896 LPWSTR ptr;
1897 DWORD sz;
1898
1899 FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1900 dwReinstallMode);
1901
1902 ptr = reinstallmode;
1903
1904 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
1905 *ptr++ = 'p';
1906 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
1907 *ptr++ = 'o';
1908 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
1909 *ptr++ = 'w';
1910 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
1911 *ptr++ = 'd';
1912 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
1913 *ptr++ = 'c';
1914 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
1915 *ptr++ = 'a';
1916 if (dwReinstallMode & REINSTALLMODE_USERDATA)
1917 *ptr++ = 'u';
1918 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
1919 *ptr++ = 'm';
1920 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
1921 *ptr++ = 's';
1922 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
1923 *ptr++ = 'v';
1924 *ptr = 0;
1925
1926 sz = sizeof(sourcepath);
1927 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1928 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
1929
1930 sz = sizeof(filename);
1931 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1932 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
1933
1934 lstrcatW( sourcepath, filename );
1935
1936 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
1937 r = MSI_OpenPackageW( sourcepath, &package );
1938 else
1939 r = MSI_OpenProductW( szProduct, &package );
1940
1941 if (r != ERROR_SUCCESS)
1942 return r;
1943
1944 MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
1945 MSI_SetPropertyW( package, szInstalled, szOne );
1946 MSI_SetPropertyW( package, szLogVerbose, szOne );
1947 MSI_SetPropertyW( package, szReinstall, szFeature );
1948
1949 r = MSI_InstallPackage( package, sourcepath, NULL );
1950
1951 msiobj_release( &package->hdr );
1952
1953 return r;
1954 }
1955
1956 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
1957 DWORD dwReinstallMode )
1958 {
1959 LPWSTR wszProduct;
1960 LPWSTR wszFeature;
1961 UINT rc;
1962
1963 TRACE("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1964 dwReinstallMode);
1965
1966 wszProduct = strdupAtoW(szProduct);
1967 wszFeature = strdupAtoW(szFeature);
1968
1969 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
1970
1971 msi_free(wszProduct);
1972 msi_free(wszFeature);
1973 return rc;
1974 }
1975
1976 typedef struct
1977 {
1978 unsigned int i[2];
1979 unsigned int buf[4];
1980 unsigned char in[64];
1981 unsigned char digest[16];
1982 } MD5_CTX;
1983
1984 extern VOID WINAPI MD5Init( MD5_CTX *);
1985 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
1986 extern VOID WINAPI MD5Final( MD5_CTX *);
1987
1988 /***********************************************************************
1989 * MsiGetFileHashW [MSI.@]
1990 */
1991 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
1992 PMSIFILEHASHINFO pHash )
1993 {
1994 HANDLE handle, mapping;
1995 void *p;
1996 DWORD length;
1997 UINT r = ERROR_FUNCTION_FAILED;
1998
1999 TRACE("%s %08lx %p\n", debugstr_w(szFilePath), dwOptions, pHash );
2000
2001 if (dwOptions)
2002 return ERROR_INVALID_PARAMETER;
2003 if (!pHash)
2004 return ERROR_INVALID_PARAMETER;
2005 if (pHash->dwFileHashInfoSize < sizeof *pHash)
2006 return ERROR_INVALID_PARAMETER;
2007
2008 handle = CreateFileW( szFilePath, GENERIC_READ,
2009 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
2010 if (handle == INVALID_HANDLE_VALUE)
2011 return ERROR_FILE_NOT_FOUND;
2012
2013 length = GetFileSize( handle, NULL );
2014
2015 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
2016 if (mapping)
2017 {
2018 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
2019 if (p)
2020 {
2021 MD5_CTX ctx;
2022
2023 MD5Init( &ctx );
2024 MD5Update( &ctx, p, length );
2025 MD5Final( &ctx );
2026 UnmapViewOfFile( p );
2027
2028 memcpy( pHash->dwData, &ctx.digest, sizeof pHash->dwData );
2029 r = ERROR_SUCCESS;
2030 }
2031 CloseHandle( mapping );
2032 }
2033 CloseHandle( handle );
2034
2035 return r;
2036 }
2037
2038 /***********************************************************************
2039 * MsiGetFileHashA [MSI.@]
2040 */
2041 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
2042 PMSIFILEHASHINFO pHash )
2043 {
2044 LPWSTR file;
2045 UINT r;
2046
2047 TRACE("%s %08lx %p\n", debugstr_a(szFilePath), dwOptions, pHash );
2048
2049 file = strdupAtoW( szFilePath );
2050 if (szFilePath && !file)
2051 return ERROR_OUTOFMEMORY;
2052
2053 r = MsiGetFileHashW( file, dwOptions, pHash );
2054 msi_free( file );
2055 return r;
2056 }
2057
2058 /***********************************************************************
2059 * MsiAdvertiseScriptW [MSI.@]
2060 */
2061 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
2062 PHKEY phRegData, BOOL fRemoveItems )
2063 {
2064 FIXME("%s %08lx %p %d\n",
2065 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
2066 return ERROR_CALL_NOT_IMPLEMENTED;
2067 }
2068
2069 /***********************************************************************
2070 * MsiAdvertiseScriptA [MSI.@]
2071 */
2072 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
2073 PHKEY phRegData, BOOL fRemoveItems )
2074 {
2075 FIXME("%s %08lx %p %d\n",
2076 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
2077 return ERROR_CALL_NOT_IMPLEMENTED;
2078 }