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