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