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