Sync to Wine-20050830:
[reactos.git] / reactos / lib / msi / msi.c
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wine/debug.h"
32 #include "msi.h"
33 #include "msiquery.h"
34 #include "msipriv.h"
35 #include "wincrypt.h"
36 #include "winver.h"
37 #include "winuser.h"
38 #include "wine/unicode.h"
39 #include "action.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42
43 /*
44 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
45 * which is a problem because LPCTSTR isn't defined when compiling wine.
46 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
47 * and make sure to only use it in W functions.
48 */
49 #define LPCTSTR LPCWSTR
50
51 /* the UI level */
52 INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
53 HWND gUIhwnd = 0;
54 INSTALLUI_HANDLERA gUIHandlerA = NULL;
55 INSTALLUI_HANDLERW gUIHandlerW = NULL;
56 DWORD gUIFilter = 0;
57 LPVOID gUIContext = NULL;
58 WCHAR gszLogFile[MAX_PATH];
59 HINSTANCE msi_hInstance;
60
61 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
62
63 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
64 {
65 UINT r;
66 LPWSTR szwProd = NULL;
67
68 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
69
70 if( szProduct )
71 {
72 szwProd = strdupAtoW( szProduct );
73 if( !szwProd )
74 return ERROR_OUTOFMEMORY;
75 }
76
77 r = MsiOpenProductW( szwProd, phProduct );
78
79 HeapFree( GetProcessHeap(), 0, szwProd );
80
81 return r;
82 }
83
84 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
85 {
86 LPWSTR path = NULL;
87 UINT r;
88 HKEY hKeyProduct = NULL;
89 DWORD count, type;
90
91 TRACE("%s %p\n",debugstr_w(szProduct), phProduct);
92
93 r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE);
94 if( r != ERROR_SUCCESS )
95 {
96 r = ERROR_UNKNOWN_PRODUCT;
97 goto end;
98 }
99
100 /* find the size of the path */
101 type = count = 0;
102 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
103 NULL, &type, NULL, &count );
104 if( r != ERROR_SUCCESS )
105 {
106 r = ERROR_UNKNOWN_PRODUCT;
107 goto end;
108 }
109
110 /* now alloc and fetch the path of the database to open */
111 path = HeapAlloc( GetProcessHeap(), 0, count );
112 if( !path )
113 goto end;
114
115 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
116 NULL, &type, (LPBYTE) path, &count );
117 if( r != ERROR_SUCCESS )
118 {
119 r = ERROR_UNKNOWN_PRODUCT;
120 goto end;
121 }
122
123 r = MsiOpenPackageW( path, phProduct );
124
125 end:
126 HeapFree( GetProcessHeap(), 0, path );
127 if( hKeyProduct )
128 RegCloseKey( hKeyProduct );
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 HeapFree( GetProcessHeap(), 0, szwPath );
192 HeapFree( GetProcessHeap(), 0, szwCommand );
193
194 return r;
195 }
196
197 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
198 {
199 MSIPACKAGE *package = NULL;
200 UINT r;
201 MSIHANDLE handle;
202 WCHAR path[MAX_PATH];
203 WCHAR filename[MAX_PATH];
204 static const WCHAR szMSI[] = {'M','S','I',0};
205
206 FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
207
208 r = MsiVerifyPackageW(szPackagePath);
209 if (r != ERROR_SUCCESS)
210 return r;
211
212 /* copy the msi file to a temp file to pervent locking a CD
213 * with a multi disc install
214 */
215 GetTempPathW(MAX_PATH, path);
216 GetTempFileNameW(path, szMSI, 0, filename);
217
218 CopyFileW(szPackagePath, filename, FALSE);
219
220 TRACE("Opening relocated package %s\n",debugstr_w(filename));
221 r = MSI_OpenPackageW(filename, &package);
222 if (r != ERROR_SUCCESS)
223 {
224 DeleteFileW(filename);
225 return r;
226 }
227
228 handle = alloc_msihandle( &package->hdr );
229
230 r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine,
231 filename);
232
233 MsiCloseHandle(handle);
234 msiobj_release( &package->hdr );
235
236 DeleteFileW(filename);
237 return r;
238 }
239
240 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
241 {
242 FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode);
243 return ERROR_CALL_NOT_IMPLEMENTED;
244 }
245
246 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
247 {
248 FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode);
249 return ERROR_CALL_NOT_IMPLEMENTED;
250 }
251
252 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
253 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
254 {
255 FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
256 eInstallType, debugstr_a(szCommandLine));
257 return ERROR_CALL_NOT_IMPLEMENTED;
258 }
259
260 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
261 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
262 {
263 FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
264 eInstallType, debugstr_w(szCommandLine));
265 return ERROR_CALL_NOT_IMPLEMENTED;
266 }
267
268 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
269 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
270 {
271 MSIHANDLE handle = -1;
272 MSIPACKAGE* package;
273 UINT rc;
274 DWORD sz;
275 WCHAR sourcepath[MAX_PATH];
276 WCHAR filename[MAX_PATH];
277 static const WCHAR szInstalled[] = {
278 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
279 LPWSTR commandline;
280
281 FIXME("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
282 debugstr_w(szCommandLine));
283
284 if (eInstallState != INSTALLSTATE_LOCAL &&
285 eInstallState != INSTALLSTATE_DEFAULT)
286 {
287 FIXME("Not implemented for anything other than local installs\n");
288 return ERROR_CALL_NOT_IMPLEMENTED;
289 }
290
291 sz = sizeof(sourcepath);
292 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
293 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
294 &sz);
295
296 sz = sizeof(filename);
297 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
298 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
299
300 strcatW(sourcepath,filename);
301
302 /*
303 * ok 1, we need to find the msi file for this product.
304 * 2, find the source dir for the files
305 * 3, do the configure/install.
306 * 4, cleanupany runonce entry.
307 */
308
309 rc = MsiOpenProductW(szProduct,&handle);
310 if (rc != ERROR_SUCCESS)
311 goto end;
312
313 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
314 if (!package)
315 {
316 rc = ERROR_INVALID_HANDLE;
317 goto end;
318 }
319
320 sz = lstrlenW(szInstalled);
321
322 if (szCommandLine)
323 sz += lstrlenW(szCommandLine);
324
325 commandline = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
326
327 if (szCommandLine)
328 lstrcpyW(commandline,szCommandLine);
329 else
330 commandline[0] = 0;
331
332 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
333 lstrcatW(commandline,szInstalled);
334
335 rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline, sourcepath);
336
337 msiobj_release( &package->hdr );
338
339 HeapFree(GetProcessHeap(),0,commandline);
340 end:
341 if (handle != -1)
342 MsiCloseHandle(handle);
343
344 return rc;
345 }
346
347 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
348 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
349 {
350 LPWSTR szwProduct = NULL;
351 LPWSTR szwCommandLine = NULL;
352 UINT r = ERROR_OUTOFMEMORY;
353
354 if( szProduct )
355 {
356 szwProduct = strdupAtoW( szProduct );
357 if( !szwProduct )
358 goto end;
359 }
360
361 if( szCommandLine)
362 {
363 szwCommandLine = strdupAtoW( szCommandLine );
364 if( !szwCommandLine)
365 goto end;
366 }
367
368 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
369 szwCommandLine );
370 end:
371 HeapFree( GetProcessHeap(), 0, szwProduct );
372 HeapFree( GetProcessHeap(), 0, szwCommandLine);
373
374 return r;
375 }
376
377 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
378 INSTALLSTATE eInstallState)
379 {
380 LPWSTR szwProduct = NULL;
381 UINT r;
382
383 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
384
385 if( szProduct )
386 {
387 szwProduct = strdupAtoW( szProduct );
388 if( !szwProduct )
389 return ERROR_OUTOFMEMORY;
390 }
391
392 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
393 HeapFree( GetProcessHeap(), 0, szwProduct );
394
395 return r;
396 }
397
398 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
399 INSTALLSTATE eInstallState)
400 {
401 FIXME("%s %d %d\n", debugstr_w(szProduct), iInstallLevel, eInstallState);
402
403 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
404 }
405
406 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
407 {
408 LPWSTR szwComponent = NULL;
409 UINT r;
410 WCHAR szwBuffer[GUID_SIZE];
411
412 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
413
414 if( szComponent )
415 {
416 szwComponent = strdupAtoW( szComponent );
417 if( !szwComponent )
418 return ERROR_OUTOFMEMORY;
419 }
420
421 r = MsiGetProductCodeW( szwComponent, szwBuffer );
422
423 if( ERROR_SUCCESS == r )
424 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
425
426 HeapFree( GetProcessHeap(), 0, szwComponent );
427
428 return r;
429 }
430
431 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
432 {
433 UINT rc;
434 HKEY hkey;
435 WCHAR szSquished[GUID_SIZE];
436 DWORD sz = GUID_SIZE;
437 static const WCHAR szPermKey[] =
438 { '0','0','0','0','0','0','0','0','0','0','0','0',
439 '0','0','0','0','0','0','0', '0','0','0','0','0',
440 '0','0','0','0','0','0','0','0',0};
441
442 TRACE("%s %p\n",debugstr_w(szComponent), szBuffer);
443
444 if (NULL == szComponent)
445 return ERROR_INVALID_PARAMETER;
446
447 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
448 if (rc != ERROR_SUCCESS)
449 return ERROR_UNKNOWN_COMPONENT;
450
451 rc = RegEnumValueW(hkey, 0, szSquished, &sz, NULL, NULL, NULL, NULL);
452 if (rc == ERROR_SUCCESS && strcmpW(szSquished,szPermKey)==0)
453 {
454 sz = GUID_SIZE;
455 rc = RegEnumValueW(hkey, 1, szSquished, &sz, NULL, NULL, NULL, NULL);
456 }
457
458 RegCloseKey(hkey);
459
460 if (rc != ERROR_SUCCESS)
461 return ERROR_INSTALL_FAILURE;
462
463 unsquash_guid(szSquished, szBuffer);
464 return ERROR_SUCCESS;
465 }
466
467 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
468 LPSTR szBuffer, DWORD *pcchValueBuf)
469 {
470 LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
471 UINT r = ERROR_OUTOFMEMORY;
472 DWORD pcchwValueBuf = 0;
473
474 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
475 szBuffer, pcchValueBuf);
476
477 if( szProduct )
478 {
479 szwProduct = strdupAtoW( szProduct );
480 if( !szwProduct )
481 goto end;
482 }
483
484 if( szAttribute )
485 {
486 szwAttribute = strdupAtoW( szAttribute );
487 if( !szwAttribute )
488 goto end;
489 }
490
491 if( szBuffer )
492 {
493 szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
494 pcchwValueBuf = *pcchValueBuf;
495 if( !szwBuffer )
496 goto end;
497 }
498
499 r = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer,
500 &pcchwValueBuf );
501
502 if( ERROR_SUCCESS == r )
503 *pcchValueBuf = WideCharToMultiByte(CP_ACP, 0, szwBuffer, pcchwValueBuf,
504 szBuffer, *pcchValueBuf, NULL, NULL);
505
506 end:
507 HeapFree( GetProcessHeap(), 0, szwProduct );
508 HeapFree( GetProcessHeap(), 0, szwAttribute );
509 HeapFree( GetProcessHeap(), 0, szwBuffer );
510
511 return r;
512 }
513
514 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
515 LPWSTR szBuffer, DWORD *pcchValueBuf)
516 {
517 MSIHANDLE hProduct;
518 UINT r;
519 static const WCHAR szProductVersion[] =
520 {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
521 static const WCHAR szProductLanguage[] =
522 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
523
524 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute),
525 szBuffer, pcchValueBuf);
526
527 if (NULL != szBuffer && NULL == pcchValueBuf)
528 return ERROR_INVALID_PARAMETER;
529 if (NULL == szProduct || NULL == szAttribute)
530 return ERROR_INVALID_PARAMETER;
531
532 /* check for special properties */
533 if (strcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW)==0)
534 {
535 HKEY hkey;
536 WCHAR squished[GUID_SIZE];
537 WCHAR package[200];
538 DWORD sz = sizeof(squished);
539
540 r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
541 if (r != ERROR_SUCCESS)
542 return ERROR_UNKNOWN_PRODUCT;
543
544 r = RegQueryValueExW(hkey, INSTALLPROPERTY_PACKAGECODEW, NULL, NULL,
545 (LPBYTE)squished, &sz);
546 if (r != ERROR_SUCCESS)
547 {
548 RegCloseKey(hkey);
549 return ERROR_UNKNOWN_PRODUCT;
550 }
551
552 unsquash_guid(squished, package);
553 *pcchValueBuf = strlenW(package);
554 if (strlenW(package) > *pcchValueBuf)
555 {
556 RegCloseKey(hkey);
557 return ERROR_MORE_DATA;
558 }
559 else
560 strcpyW(szBuffer, package);
561
562 RegCloseKey(hkey);
563 r = ERROR_SUCCESS;
564 }
565 else if (strcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW)==0)
566 {
567 r = MsiOpenProductW(szProduct, &hProduct);
568 if (ERROR_SUCCESS != r)
569 return r;
570
571 r = MsiGetPropertyW(hProduct, szProductVersion, szBuffer, pcchValueBuf);
572 MsiCloseHandle(hProduct);
573 }
574 else if (strcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW)==0)
575 {
576 FIXME("0 (zero) if advertised or per user , 1(one) if per machine.\n");
577 if (szBuffer)
578 {
579 szBuffer[0] = '1';
580 szBuffer[1] = 0;
581 }
582 if (pcchValueBuf)
583 *pcchValueBuf = 1;
584 r = ERROR_SUCCESS;
585 }
586 else if (strcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW)==0)
587 {
588 r = MsiOpenProductW(szProduct, &hProduct);
589 if (ERROR_SUCCESS != r)
590 return r;
591
592 r = MsiGetPropertyW(hProduct, szProductLanguage, szBuffer, pcchValueBuf);
593 MsiCloseHandle(hProduct);
594 }
595 else
596 {
597 r = MsiOpenProductW(szProduct, &hProduct);
598 if (ERROR_SUCCESS != r)
599 return r;
600
601 r = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
602 MsiCloseHandle(hProduct);
603 }
604
605 return r;
606 }
607
608 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
609 {
610 LPWSTR szwLogFile = NULL;
611 UINT r;
612
613 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes);
614
615 if( szLogFile )
616 {
617 szwLogFile = strdupAtoW( szLogFile );
618 if( !szwLogFile )
619 return ERROR_OUTOFMEMORY;
620 }
621 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
622 HeapFree( GetProcessHeap(), 0, szwLogFile );
623 return r;
624 }
625
626 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
627 {
628 HANDLE file = INVALID_HANDLE_VALUE;
629
630 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes);
631
632 lstrcpyW(gszLogFile,szLogFile);
633 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
634 DeleteFileW(szLogFile);
635 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
636 FILE_ATTRIBUTE_NORMAL, NULL);
637 if (file != INVALID_HANDLE_VALUE)
638 CloseHandle(file);
639 else
640 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
641
642 return ERROR_SUCCESS;
643 }
644
645 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
646 {
647 LPWSTR szwProduct = NULL;
648 INSTALLSTATE r;
649
650 if( szProduct )
651 {
652 szwProduct = strdupAtoW( szProduct );
653 if( !szwProduct )
654 return ERROR_OUTOFMEMORY;
655 }
656 r = MsiQueryProductStateW( szwProduct );
657 HeapFree( GetProcessHeap(), 0, szwProduct );
658 return r;
659 }
660
661 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
662 {
663 UINT rc;
664 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
665 HKEY hkey = 0;
666 static const WCHAR szWindowsInstaller[] = {
667 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 };
668 DWORD sz;
669
670 TRACE("%s\n", debugstr_w(szProduct));
671
672 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
673 if (rc != ERROR_SUCCESS)
674 goto end;
675
676 RegCloseKey(hkey);
677
678 rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
679 if (rc != ERROR_SUCCESS)
680 goto end;
681
682 sz = sizeof(rrc);
683 rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz);
684 if (rc != ERROR_SUCCESS)
685 goto end;
686
687 switch (rrc)
688 {
689 case 1:
690 /* default */
691 rrc = INSTALLSTATE_DEFAULT;
692 break;
693 default:
694 FIXME("Unknown install state read from registry (%i)\n",rrc);
695 rrc = INSTALLSTATE_UNKNOWN;
696 break;
697 }
698 end:
699 RegCloseKey(hkey);
700 return rrc;
701 }
702
703 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
704 {
705 INSTALLUILEVEL old = gUILevel;
706 HWND oldwnd = gUIhwnd;
707
708 TRACE("%08x %p\n", dwUILevel, phWnd);
709
710 gUILevel = dwUILevel;
711 if (phWnd)
712 {
713 gUIhwnd = *phWnd;
714 *phWnd = oldwnd;
715 }
716 return old;
717 }
718
719 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
720 DWORD dwMessageFilter, LPVOID pvContext)
721 {
722 INSTALLUI_HANDLERA prev = gUIHandlerA;
723
724 TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext);
725 gUIHandlerA = puiHandler;
726 gUIFilter = dwMessageFilter;
727 gUIContext = pvContext;
728
729 return prev;
730 }
731
732 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
733 DWORD dwMessageFilter, LPVOID pvContext)
734 {
735 INSTALLUI_HANDLERW prev = gUIHandlerW;
736
737 TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext);
738 gUIHandlerW = puiHandler;
739 gUIFilter = dwMessageFilter;
740 gUIContext = pvContext;
741
742 return prev;
743 }
744
745 /******************************************************************
746 * MsiLoadStringW [MSI.@]
747 *
748 * Loads a string from MSI's string resources.
749 *
750 * PARAMS
751 *
752 * handle [I] only -1 is handled currently
753 * id [I] id of the string to be loaded
754 * lpBuffer [O] buffer for the string to be written to
755 * nBufferMax [I] maximum size of the buffer in characters
756 * lang [I] the preferred language for the string
757 *
758 * RETURNS
759 *
760 * If successful, this function returns the language id of the string loaded
761 * If the function fails, the function returns zero.
762 *
763 * NOTES
764 *
765 * The type of the first parameter is unknown. LoadString's prototype
766 * suggests that it might be a module handle. I have made it an MSI handle
767 * for starters, as -1 is an invalid MSI handle, but not an invalid module
768 * handle. Maybe strings can be stored in an MSI database somehow.
769 */
770 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
771 int nBufferMax, LANGID lang )
772 {
773 HRSRC hres;
774 HGLOBAL hResData;
775 LPWSTR p;
776 DWORD i, len;
777
778 TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
779
780 if( handle != -1 )
781 FIXME("don't know how to deal with handle = %08lx\n", handle);
782
783 if( !lang )
784 lang = GetUserDefaultLangID();
785
786 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
787 (LPWSTR)1, lang );
788 if( !hres )
789 return 0;
790 hResData = LoadResource( msi_hInstance, hres );
791 if( !hResData )
792 return 0;
793 p = LockResource( hResData );
794 if( !p )
795 return 0;
796
797 for (i = 0; i < (id&0xf); i++)
798 p += *p + 1;
799 len = *p;
800
801 if( nBufferMax <= len )
802 return 0;
803
804 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
805 lpBuffer[ len ] = 0;
806
807 TRACE("found -> %s\n", debugstr_w(lpBuffer));
808
809 return lang;
810 }
811
812 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
813 int nBufferMax, LANGID lang )
814 {
815 LPWSTR bufW;
816 LANGID r;
817 DWORD len;
818
819 bufW = HeapAlloc(GetProcessHeap(), 0, nBufferMax*sizeof(WCHAR));
820 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
821 if( r )
822 {
823 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
824 if( len <= nBufferMax )
825 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
826 lpBuffer, nBufferMax, NULL, NULL );
827 else
828 r = 0;
829 }
830 HeapFree(GetProcessHeap(), 0, bufW);
831 return r;
832 }
833
834 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
835 DWORD *pcchBuf)
836 {
837 FIXME("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
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 ERROR_CALL_NOT_IMPLEMENTED;
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 ERROR_CALL_NOT_IMPLEMENTED;
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 HeapFree( GetProcessHeap(), 0, 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 HeapFree( GetProcessHeap(), 0, szwProduct);
984 return ERROR_OUTOFMEMORY;
985 }
986 }
987
988 if( pcchBuf && *pcchBuf > 0 )
989 {
990 lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *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 HeapFree( GetProcessHeap(), 0, szwProduct);
1002 HeapFree( GetProcessHeap(), 0, 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 HeapFree( GetProcessHeap(), 0, 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( lpPathBuf && !pcchBuf )
1028 return INSTALLSTATE_INVALIDARG;
1029
1030 squash_guid(szProduct,squished_pc);
1031
1032 rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE);
1033 if( rc != ERROR_SUCCESS )
1034 goto end;
1035
1036 RegCloseKey(hkey);
1037
1038 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
1039 if( rc != ERROR_SUCCESS )
1040 goto end;
1041
1042 sz = 0;
1043 type = 0;
1044 rc = RegQueryValueExW( hkey, squished_pc, NULL, &type, NULL, &sz );
1045 if( rc != ERROR_SUCCESS )
1046 goto end;
1047 if( type != REG_SZ )
1048 goto end;
1049
1050 sz += sizeof(WCHAR);
1051 path = HeapAlloc( GetProcessHeap(), 0, sz );
1052 if( !path )
1053 goto end;
1054
1055 rc = RegQueryValueExW( hkey, squished_pc, NULL, NULL, (LPVOID) path, &sz );
1056 if( rc != ERROR_SUCCESS )
1057 goto end;
1058
1059 TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent),
1060 debugstr_w(szProduct), debugstr_w(path));
1061
1062 if (path[0]=='0')
1063 {
1064 FIXME("Registry entry.. check entry\n");
1065 rrc = INSTALLSTATE_LOCAL;
1066 }
1067 else
1068 {
1069 /* PROBABLY a file */
1070 if ( GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES )
1071 rrc = INSTALLSTATE_LOCAL;
1072 else
1073 rrc = INSTALLSTATE_ABSENT;
1074 }
1075
1076 if( pcchBuf )
1077 {
1078 sz = sz / sizeof(WCHAR);
1079 if( *pcchBuf >= sz )
1080 lstrcpyW( lpPathBuf, path );
1081 *pcchBuf = sz;
1082 }
1083
1084 end:
1085 HeapFree(GetProcessHeap(), 0, path );
1086 RegCloseKey(hkey);
1087 return rrc;
1088 }
1089
1090 /******************************************************************
1091 * MsiQueryFeatureStateA [MSI.@]
1092 */
1093 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1094 {
1095 INSTALLSTATE rc;
1096 LPWSTR szwProduct= NULL;
1097 LPWSTR szwFeature= NULL;
1098
1099 if( szProduct )
1100 {
1101 szwProduct = strdupAtoW( szProduct );
1102 if( !szwProduct)
1103 return ERROR_OUTOFMEMORY;
1104 }
1105
1106 if( szFeature )
1107 {
1108 szwFeature = strdupAtoW( szFeature );
1109 if( !szwFeature)
1110 {
1111 HeapFree( GetProcessHeap(), 0, szwProduct);
1112 return ERROR_OUTOFMEMORY;
1113 }
1114 }
1115
1116 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1117
1118 HeapFree( GetProcessHeap(), 0, szwProduct);
1119 HeapFree( GetProcessHeap(), 0, szwFeature);
1120
1121 return rc;
1122 }
1123
1124 /******************************************************************
1125 * MsiQueryFeatureStateW [MSI.@]
1126 *
1127 * This does not verify that the Feature is functional. So i am only going to
1128 * check the existence of the key in the registry. This should tell me if it is
1129 * installed.
1130 */
1131 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1132 {
1133 UINT rc;
1134 DWORD sz = 0;
1135 HKEY hkey;
1136
1137 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
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 else
1149 return INSTALLSTATE_ABSENT;
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 = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR));
1171 if( !lpwVersionBuff )
1172 goto end;
1173 }
1174
1175 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1176 {
1177 lpwLangBuff = HeapAlloc(GetProcessHeap(), 0, *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 HeapFree(GetProcessHeap(), 0, szwFilePath);
1194 HeapFree(GetProcessHeap(), 0, lpwVersionBuff);
1195 HeapFree(GetProcessHeap(), 0, 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 const 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 = HeapAlloc(GetProcessHeap(), 0, 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 HeapFree(GetProcessHeap(), 0, 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 return 2;
1307 }
1308
1309 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
1310 {
1311 return 1;
1312 }
1313
1314 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
1315 LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
1316 {
1317 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1318
1319 FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
1320 return E_FAIL;
1321 }
1322
1323 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
1324 {
1325 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1326
1327 FIXME("%p %d\n", This, dolock);
1328 return S_OK;
1329 }
1330
1331 static const IClassFactoryVtbl MsiCF_Vtbl =
1332 {
1333 MsiCF_QueryInterface,
1334 MsiCF_AddRef,
1335 MsiCF_Release,
1336 MsiCF_CreateInstance,
1337 MsiCF_LockServer
1338 };
1339
1340 static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl };
1341
1342 /******************************************************************
1343 * DllGetClassObject [MSI.@]
1344 */
1345 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
1346 {
1347 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1348
1349 if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
1350 IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
1351 IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
1352 IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) ||
1353 IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
1354 {
1355 *ppv = (LPVOID) &Msi_CF;
1356 return S_OK;
1357 }
1358 return CLASS_E_CLASSNOTAVAILABLE;
1359 }
1360
1361 /******************************************************************
1362 * DllGetVersion [MSI.@]
1363 */
1364 HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi)
1365 {
1366 TRACE("%p\n",pdvi);
1367
1368 if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1369 return E_INVALIDARG;
1370
1371 pdvi->dwMajorVersion = MSI_MAJORVERSION;
1372 pdvi->dwMinorVersion = MSI_MINORVERSION;
1373 pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1374 pdvi->dwPlatformID = 1;
1375
1376 return S_OK;
1377 }
1378
1379 /******************************************************************
1380 * DllCanUnloadNow [MSI.@]
1381 */
1382 HRESULT WINAPI DllCanUnloadNow(void)
1383 {
1384 return S_FALSE;
1385 }
1386
1387 UINT WINAPI MsiGetFeatureUsageW(LPCWSTR szProduct, LPCWSTR szFeature,
1388 DWORD* pdwUseCount, WORD* pwDateUsed)
1389 {
1390 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
1391 pdwUseCount, pwDateUsed);
1392 return ERROR_CALL_NOT_IMPLEMENTED;
1393 }
1394
1395 UINT WINAPI MsiGetFeatureUsageA(LPCSTR szProduct, LPCSTR szFeature,
1396 DWORD* pdwUseCount, WORD* pwDateUsed)
1397 {
1398 FIXME("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
1399 pdwUseCount, pwDateUsed);
1400 return ERROR_CALL_NOT_IMPLEMENTED;
1401 }
1402
1403 INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature,
1404 DWORD dwInstallMode, DWORD dwReserved)
1405 {
1406 FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1407 dwInstallMode, dwReserved);
1408
1409 /*
1410 * Polls all the components of the feature to find install state and then
1411 * writes:
1412 * Software\\Microsoft\\Windows\\CurrentVersion\\
1413 * Installer\\Products\\<squishguid>\\<feature>
1414 * "Usage"=dword:........
1415 */
1416
1417 return INSTALLSTATE_LOCAL;
1418 }
1419
1420 /***********************************************************************
1421 * MsiUseFeatureExA [MSI.@]
1422 */
1423 INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature,
1424 DWORD dwInstallMode, DWORD dwReserved)
1425 {
1426 FIXME("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1427 dwInstallMode, dwReserved);
1428
1429 return INSTALLSTATE_LOCAL;
1430 }
1431
1432 INSTALLSTATE WINAPI MsiUseFeatureW(LPCWSTR szProduct, LPCWSTR szFeature)
1433 {
1434 FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1435
1436 return INSTALLSTATE_LOCAL;
1437 }
1438
1439 INSTALLSTATE WINAPI MsiUseFeatureA(LPCSTR szProduct, LPCSTR szFeature)
1440 {
1441 FIXME("%s %s\n", debugstr_a(szProduct), debugstr_a(szFeature));
1442
1443 return INSTALLSTATE_LOCAL;
1444 }
1445
1446 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
1447 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1448 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
1449 DWORD* pcchPathBuf)
1450 {
1451 HKEY hkey;
1452 UINT rc;
1453 LPWSTR info;
1454 DWORD sz;
1455 LPWSTR product = NULL;
1456 LPWSTR component = NULL;
1457 LPWSTR ptr;
1458 GUID clsid;
1459
1460 TRACE("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
1461 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
1462 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1463
1464 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
1465 if (rc != ERROR_SUCCESS)
1466 return ERROR_INDEX_ABSENT;
1467
1468 sz = 0;
1469 rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, NULL, &sz);
1470 if (sz <= 0)
1471 {
1472 RegCloseKey(hkey);
1473 return ERROR_INDEX_ABSENT;
1474 }
1475
1476 info = HeapAlloc(GetProcessHeap(),0,sz);
1477 rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, (LPBYTE)info, &sz);
1478 if (rc != ERROR_SUCCESS)
1479 {
1480 RegCloseKey(hkey);
1481 HeapFree(GetProcessHeap(),0,info);
1482 return ERROR_INDEX_ABSENT;
1483 }
1484
1485 /* find the component */
1486 ptr = strchrW(&info[20],'>');
1487 if (ptr)
1488 ptr++;
1489 else
1490 {
1491 RegCloseKey(hkey);
1492 HeapFree(GetProcessHeap(),0,info);
1493 return ERROR_INDEX_ABSENT;
1494 }
1495
1496 if (!szProduct)
1497 {
1498 decode_base85_guid(info,&clsid);
1499 StringFromCLSID(&clsid, &product);
1500 }
1501 decode_base85_guid(ptr,&clsid);
1502 StringFromCLSID(&clsid, &component);
1503
1504 if (!szProduct)
1505 rc = MsiGetComponentPathW(product, component, lpPathBuf, pcchPathBuf);
1506 else
1507 rc = MsiGetComponentPathW(szProduct, component, lpPathBuf, pcchPathBuf);
1508
1509 RegCloseKey(hkey);
1510 HeapFree(GetProcessHeap(),0,info);
1511 HeapFree(GetProcessHeap(),0,product);
1512 HeapFree(GetProcessHeap(),0,component);
1513
1514 if (rc == INSTALLSTATE_LOCAL)
1515 return ERROR_SUCCESS;
1516 else
1517 return ERROR_FILE_NOT_FOUND;
1518 }
1519
1520 /***********************************************************************
1521 * MsiProvideQualifiedComponentW [MSI.@]
1522 */
1523 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
1524 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
1525 DWORD* pcchPathBuf)
1526 {
1527 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
1528 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
1529 }
1530
1531 /***********************************************************************
1532 * MsiProvideQualifiedComponentA [MSI.@]
1533 */
1534 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
1535 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
1536 DWORD* pcchPathBuf)
1537 {
1538 LPWSTR szwComponent, szwQualifier, lpwPathBuf;
1539 DWORD pcchwPathBuf;
1540 UINT rc;
1541
1542 TRACE("%s %s %li %p %p\n",szComponent, szQualifier,
1543 dwInstallMode, lpPathBuf, pcchPathBuf);
1544
1545 szwComponent= strdupAtoW( szComponent);
1546 szwQualifier= strdupAtoW( szQualifier);
1547
1548 lpwPathBuf = HeapAlloc(GetProcessHeap(),0,*pcchPathBuf * sizeof(WCHAR));
1549
1550 pcchwPathBuf = *pcchPathBuf;
1551
1552 rc = MsiProvideQualifiedComponentW(szwComponent, szwQualifier,
1553 dwInstallMode, lpwPathBuf, &pcchwPathBuf);
1554
1555 HeapFree(GetProcessHeap(),0,szwComponent);
1556 HeapFree(GetProcessHeap(),0,szwQualifier);
1557 *pcchPathBuf = WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, pcchwPathBuf,
1558 lpPathBuf, *pcchPathBuf, NULL, NULL);
1559
1560 HeapFree(GetProcessHeap(),0,lpwPathBuf);
1561 return rc;
1562 }
1563
1564 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
1565 DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf,
1566 DWORD* pcchOrgNameBuf, LPWSTR lpSerialBuf, DWORD* pcchSerialBuf)
1567 {
1568 HKEY hkey;
1569 DWORD sz;
1570 UINT rc = ERROR_SUCCESS,rc2 = ERROR_SUCCESS;
1571
1572 TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
1573 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1574 pcchSerialBuf);
1575
1576 rc = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
1577 if (rc != ERROR_SUCCESS)
1578 return USERINFOSTATE_UNKNOWN;
1579
1580 if (lpUserNameBuf)
1581 {
1582 sz = *lpUserNameBuf * sizeof(WCHAR);
1583 rc = RegQueryValueExW( hkey, INSTALLPROPERTY_REGOWNERW, NULL,
1584 NULL, (LPBYTE)lpUserNameBuf,
1585 &sz);
1586 }
1587 if (!lpUserNameBuf && pcchUserNameBuf)
1588 {
1589 sz = 0;
1590 rc = RegQueryValueExW( hkey, INSTALLPROPERTY_REGOWNERW, NULL,
1591 NULL, NULL, &sz);
1592 }
1593
1594 if (pcchUserNameBuf)
1595 *pcchUserNameBuf = sz / sizeof(WCHAR);
1596
1597 if (lpOrgNameBuf)
1598 {
1599 sz = *pcchOrgNameBuf * sizeof(WCHAR);
1600 rc2 = RegQueryValueExW( hkey, INSTALLPROPERTY_REGCOMPANYW, NULL,
1601 NULL, (LPBYTE)lpOrgNameBuf, &sz);
1602 }
1603 if (!lpOrgNameBuf && pcchOrgNameBuf)
1604 {
1605 sz = 0;
1606 rc2 = RegQueryValueExW( hkey, INSTALLPROPERTY_REGCOMPANYW, NULL,
1607 NULL, NULL, &sz);
1608 }
1609
1610 if (pcchOrgNameBuf)
1611 *pcchOrgNameBuf = sz / sizeof(WCHAR);
1612
1613 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA &&
1614 rc2 != ERROR_SUCCESS && rc2 != ERROR_MORE_DATA)
1615 {
1616 RegCloseKey(hkey);
1617 return USERINFOSTATE_ABSENT;
1618 }
1619
1620 if (lpSerialBuf)
1621 {
1622 sz = *pcchSerialBuf * sizeof(WCHAR);
1623 RegQueryValueExW( hkey, INSTALLPROPERTY_PRODUCTIDW, NULL, NULL,
1624 (LPBYTE)lpSerialBuf, &sz);
1625 }
1626 if (!lpSerialBuf && pcchSerialBuf)
1627 {
1628 sz = 0;
1629 rc = RegQueryValueExW( hkey, INSTALLPROPERTY_PRODUCTIDW, NULL,
1630 NULL, NULL, &sz);
1631 }
1632 if (pcchSerialBuf)
1633 *pcchSerialBuf = sz / sizeof(WCHAR);
1634
1635 RegCloseKey(hkey);
1636 return USERINFOSTATE_PRESENT;
1637 }
1638
1639 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf,
1640 DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf,
1641 DWORD* pcchOrgNameBuf, LPSTR lpSerialBuf, DWORD* pcchSerialBuf)
1642 {
1643 FIXME("%s %p %p %p %p %p %p\n",debugstr_a(szProduct), lpUserNameBuf,
1644 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1645 pcchSerialBuf);
1646
1647 return USERINFOSTATE_UNKNOWN;
1648 }
1649
1650 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
1651 {
1652 MSIHANDLE handle;
1653 UINT rc;
1654 MSIPACKAGE *package;
1655 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1656
1657 TRACE("(%s)\n",debugstr_w(szProduct));
1658
1659 rc = MsiOpenProductW(szProduct,&handle);
1660 if (rc != ERROR_SUCCESS)
1661 return ERROR_INVALID_PARAMETER;
1662
1663 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1664 rc = ACTION_PerformUIAction(package, szFirstRun);
1665 msiobj_release( &package->hdr );
1666
1667 MsiCloseHandle(handle);
1668
1669 return rc;
1670 }
1671
1672 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
1673 {
1674 MSIHANDLE handle;
1675 UINT rc;
1676 MSIPACKAGE *package;
1677 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1678
1679 TRACE("(%s)\n",debugstr_a(szProduct));
1680
1681 rc = MsiOpenProductA(szProduct,&handle);
1682 if (rc != ERROR_SUCCESS)
1683 return ERROR_INVALID_PARAMETER;
1684
1685 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1686 rc = ACTION_PerformUIAction(package, szFirstRun);
1687 msiobj_release( &package->hdr );
1688
1689 MsiCloseHandle(handle);
1690
1691 return rc;
1692 }
1693
1694 UINT WINAPI MsiConfigureFeatureW(LPWSTR szProduct, LPWSTR szFeature, INSTALLSTATE eInstallState)
1695 {
1696 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
1697 return ERROR_SUCCESS;
1698 }
1699
1700
1701
1702 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
1703 {
1704 WCHAR path[MAX_PATH];
1705
1706 if(dwReserved) {
1707 FIXME("Don't know how to handle argument %ld\n", dwReserved);
1708 return ERROR_CALL_NOT_IMPLEMENTED;
1709 }
1710
1711 if(!GetWindowsDirectoryW(path, MAX_PATH)) {
1712 FIXME("GetWindowsDirectory failed unexpected! Error %ld\n",
1713 GetLastError());
1714 return ERROR_CALL_NOT_IMPLEMENTED;
1715 }
1716
1717 strcatW(path, installerW);
1718
1719 CreateDirectoryW(path, NULL);
1720
1721 return 0;
1722 }
1723
1724 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
1725 LPSTR szProductCode, LPSTR szFeatureId,
1726 LPSTR szComponentCode )
1727 {
1728 FIXME("\n");
1729 return ERROR_CALL_NOT_IMPLEMENTED;
1730 }
1731
1732 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
1733 LPWSTR szProductCode, LPWSTR szFeatureId,
1734 LPWSTR szComponentCode )
1735 {
1736 FIXME("\n");
1737 return ERROR_CALL_NOT_IMPLEMENTED;
1738 }
1739
1740 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
1741 DWORD dwReinstallMode )
1742 {
1743 FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1744 dwReinstallMode);
1745 return ERROR_SUCCESS;
1746 }
1747
1748 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
1749 DWORD dwReinstallMode )
1750 {
1751 FIXME("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1752 dwReinstallMode);
1753 return ERROR_SUCCESS;
1754 }