Sync to Wine-20050524:
[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 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf);
42
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msi);
45
46 /*
47 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
48 * which is a problem because LPCTSTR isn't defined when compiling wine.
49 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
50 * and make sure to only use it in W functions.
51 */
52 #define LPCTSTR LPCWSTR
53
54 /* the UI level */
55 INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
56 HWND gUIhwnd = 0;
57 INSTALLUI_HANDLERA gUIHandlerA = NULL;
58 INSTALLUI_HANDLERW gUIHandlerW = NULL;
59 DWORD gUIFilter = 0;
60 LPVOID gUIContext = NULL;
61 WCHAR gszLogFile[MAX_PATH];
62 HINSTANCE msi_hInstance;
63
64 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
65
66 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
67 {
68 UINT r;
69 LPWSTR szwProd = NULL;
70
71 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
72
73 if( szProduct )
74 {
75 szwProd = strdupAtoW( szProduct );
76 if( !szwProd )
77 return ERROR_OUTOFMEMORY;
78 }
79
80 r = MsiOpenProductW( szwProd, phProduct );
81
82 HeapFree( GetProcessHeap(), 0, szwProd );
83
84 return r;
85 }
86
87 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
88 {
89 static const WCHAR szLocalPackage[] = {
90 'L','o','c','a','l','P','a','c','k','a','g','e', 0
91 };
92 LPWSTR path = NULL;
93 UINT r;
94 HKEY hKeyProduct = NULL;
95 DWORD count, type;
96
97 TRACE("%s %p\n",debugstr_w(szProduct), phProduct);
98
99 r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE);
100 if( r != ERROR_SUCCESS )
101 {
102 r = ERROR_UNKNOWN_PRODUCT;
103 goto end;
104 }
105
106 /* find the size of the path */
107 type = count = 0;
108 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
109 NULL, &type, NULL, &count );
110 if( r != ERROR_SUCCESS )
111 {
112 r = ERROR_UNKNOWN_PRODUCT;
113 goto end;
114 }
115
116 /* now alloc and fetch the path of the database to open */
117 path = HeapAlloc( GetProcessHeap(), 0, count );
118 if( !path )
119 goto end;
120
121 r = RegQueryValueExW( hKeyProduct, szLocalPackage,
122 NULL, &type, (LPBYTE) path, &count );
123 if( r != ERROR_SUCCESS )
124 {
125 r = ERROR_UNKNOWN_PRODUCT;
126 goto end;
127 }
128
129 r = MsiOpenPackageW( path, phProduct );
130
131 end:
132 HeapFree( GetProcessHeap(), 0, path );
133 if( hKeyProduct )
134 RegCloseKey( hKeyProduct );
135
136 return r;
137 }
138
139 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
140 LPCSTR szTransforms, LANGID lgidLanguage)
141 {
142 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
143 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
144 return ERROR_CALL_NOT_IMPLEMENTED;
145 }
146
147 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
148 LPCWSTR szTransforms, LANGID lgidLanguage)
149 {
150 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
151 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
152 return ERROR_CALL_NOT_IMPLEMENTED;
153 }
154
155 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
156 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
157 {
158 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_a(szPackagePath),
159 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
160 lgidLanguage, dwPlatform, dwOptions);
161 return ERROR_CALL_NOT_IMPLEMENTED;
162 }
163
164 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
165 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
166 {
167 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_w(szPackagePath),
168 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
169 lgidLanguage, dwPlatform, dwOptions);
170 return ERROR_CALL_NOT_IMPLEMENTED;
171 }
172
173 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
174 {
175 LPWSTR szwPath = NULL, szwCommand = NULL;
176 UINT r = ERROR_OUTOFMEMORY;
177
178 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
179
180 if( szPackagePath )
181 {
182 szwPath = strdupAtoW( szPackagePath );
183 if( !szwPath )
184 goto end;
185 }
186
187 if( szCommandLine )
188 {
189 szwCommand = strdupAtoW( szCommandLine );
190 if( !szwCommand )
191 goto end;
192 }
193
194 r = MsiInstallProductW( szwPath, szwCommand );
195
196 end:
197 HeapFree( GetProcessHeap(), 0, szwPath );
198 HeapFree( GetProcessHeap(), 0, szwCommand );
199
200 return r;
201 }
202
203 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
204 {
205 MSIPACKAGE *package = NULL;
206 UINT r;
207 MSIHANDLE handle;
208
209 FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
210
211 r = MsiVerifyPackageW(szPackagePath);
212 if (r != ERROR_SUCCESS)
213 return r;
214
215 r = MSI_OpenPackageW(szPackagePath,&package);
216 if (r != ERROR_SUCCESS)
217 return r;
218
219 handle = alloc_msihandle( &package->hdr );
220
221 r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine);
222
223 MsiCloseHandle(handle);
224 msiobj_release( &package->hdr );
225 return r;
226 }
227
228 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
229 {
230 FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode);
231 return ERROR_CALL_NOT_IMPLEMENTED;
232 }
233
234 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
235 {
236 FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode);
237 return ERROR_CALL_NOT_IMPLEMENTED;
238 }
239
240 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
241 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
242 {
243 FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
244 eInstallType, debugstr_a(szCommandLine));
245 return ERROR_CALL_NOT_IMPLEMENTED;
246 }
247
248 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
249 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
250 {
251 FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
252 eInstallType, debugstr_w(szCommandLine));
253 return ERROR_CALL_NOT_IMPLEMENTED;
254 }
255
256 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
257 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
258 {
259 MSIHANDLE handle = -1;
260 MSIPACKAGE* package;
261 UINT rc;
262 HKEY hkey=0,hkey1=0;
263 DWORD sz;
264 static const WCHAR szSouceList[] = {
265 'S','o','u','r','c','e','L','i','s','t',0};
266 static const WCHAR szLUS[] = {
267 'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
268 WCHAR sourcepath[0x200];
269 static const WCHAR szInstalled[] = {
270 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
271 LPWSTR commandline;
272
273 FIXME("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
274 debugstr_w(szCommandLine));
275
276 if (eInstallState != INSTALLSTATE_LOCAL &&
277 eInstallState != INSTALLSTATE_DEFAULT)
278 {
279 FIXME("Not implemented for anything other than local installs\n");
280 return ERROR_CALL_NOT_IMPLEMENTED;
281 }
282
283 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
284 if (rc != ERROR_SUCCESS)
285 goto end;
286
287 rc = RegOpenKeyW(hkey,szSouceList,&hkey1);
288 if (rc != ERROR_SUCCESS)
289 goto end;
290
291 sz = sizeof(sourcepath);
292 rc = RegQueryValueExW(hkey1, szLUS, NULL, NULL,(LPBYTE)sourcepath, &sz);
293 if (rc != ERROR_SUCCESS)
294 goto end;
295
296 RegCloseKey(hkey1);
297 /*
298 * ok 1, we need to find the msi file for this product.
299 * 2, find the source dir for the files
300 * 3, do the configure/install.
301 * 4, cleanupany runonce entry.
302 */
303
304 rc = MsiOpenProductW(szProduct,&handle);
305 if (rc != ERROR_SUCCESS)
306 goto end;
307
308 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
309 if (!package)
310 {
311 rc = ERROR_INVALID_HANDLE;
312 goto end;
313 }
314
315 sz = lstrlenW(szInstalled);
316
317 if (szCommandLine)
318 sz += lstrlenW(szCommandLine);
319
320 commandline = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
321
322 if (szCommandLine)
323 lstrcpyW(commandline,szCommandLine);
324 else
325 commandline[0] = 0;
326
327 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
328 lstrcatW(commandline,szInstalled);
329
330 rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline);
331
332 msiobj_release( &package->hdr );
333
334 HeapFree(GetProcessHeap(),0,commandline);
335 end:
336 RegCloseKey(hkey);
337 if (handle != -1)
338 MsiCloseHandle(handle);
339
340 return rc;
341 }
342
343 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
344 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
345 {
346 LPWSTR szwProduct = NULL;
347 LPWSTR szwCommandLine = NULL;
348 UINT r = ERROR_OUTOFMEMORY;
349
350 if( szProduct )
351 {
352 szwProduct = strdupAtoW( szProduct );
353 if( !szwProduct )
354 goto end;
355 }
356
357 if( szCommandLine)
358 {
359 szwCommandLine = strdupAtoW( szCommandLine );
360 if( !szwCommandLine)
361 goto end;
362 }
363
364 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
365 szwCommandLine );
366 end:
367 HeapFree( GetProcessHeap(), 0, szwProduct );
368 HeapFree( GetProcessHeap(), 0, szwCommandLine);
369
370 return r;
371 }
372
373 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
374 INSTALLSTATE eInstallState)
375 {
376 LPWSTR szwProduct = NULL;
377 UINT r;
378
379 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
380
381 if( szProduct )
382 {
383 szwProduct = strdupAtoW( szProduct );
384 if( !szwProduct )
385 return ERROR_OUTOFMEMORY;
386 }
387
388 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
389 HeapFree( GetProcessHeap(), 0, szwProduct );
390
391 return r;
392 }
393
394 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
395 INSTALLSTATE eInstallState)
396 {
397 FIXME("%s %d %d\n", debugstr_w(szProduct), iInstallLevel, eInstallState);
398
399 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
400 }
401
402 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
403 {
404 LPWSTR szwComponent = NULL;
405 UINT r;
406 WCHAR szwBuffer[GUID_SIZE];
407
408 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
409
410 if( szComponent )
411 {
412 szwComponent = strdupAtoW( szComponent );
413 if( !szwComponent )
414 return ERROR_OUTOFMEMORY;
415 }
416
417 r = MsiGetProductCodeW( szwComponent, szwBuffer );
418
419 if( ERROR_SUCCESS == r )
420 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
421
422 HeapFree( GetProcessHeap(), 0, szwComponent );
423
424 return r;
425 }
426
427 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
428 {
429 UINT rc;
430 HKEY hkey;
431 WCHAR szSquished[GUID_SIZE];
432 DWORD sz = GUID_SIZE;
433 static const WCHAR szPermKey[] =
434 { '0','0','0','0','0','0','0','0','0','0','0','0',
435 '0','0','0','0','0','0','0', '0','0','0','0','0',
436 '0','0','0','0','0','0','0','0',0};
437
438 TRACE("%s %p\n",debugstr_w(szComponent), szBuffer);
439
440 if (NULL == szComponent)
441 return ERROR_INVALID_PARAMETER;
442
443 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
444 if (rc != ERROR_SUCCESS)
445 return ERROR_UNKNOWN_COMPONENT;
446
447 rc = RegEnumValueW(hkey, 0, szSquished, &sz, NULL, NULL, NULL, NULL);
448 if (rc == ERROR_SUCCESS && strcmpW(szSquished,szPermKey)==0)
449 {
450 sz = GUID_SIZE;
451 rc = RegEnumValueW(hkey, 1, szSquished, &sz, NULL, NULL, NULL, NULL);
452 }
453
454 RegCloseKey(hkey);
455
456 if (rc != ERROR_SUCCESS)
457 return ERROR_INSTALL_FAILURE;
458
459 unsquash_guid(szSquished, szBuffer);
460 return ERROR_SUCCESS;
461 }
462
463 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
464 LPSTR szBuffer, DWORD *pcchValueBuf)
465 {
466 LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
467 UINT r = ERROR_OUTOFMEMORY;
468
469 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
470 szBuffer, pcchValueBuf);
471
472 if( szProduct )
473 {
474 szwProduct = strdupAtoW( szProduct );
475 if( !szwProduct )
476 goto end;
477 }
478
479 if( szAttribute )
480 {
481 szwAttribute = strdupAtoW( szAttribute );
482 if( !szwAttribute )
483 goto end;
484 }
485
486 if( szBuffer )
487 {
488 szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) );
489 if( !szwBuffer )
490 goto end;
491 }
492
493 r = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf );
494
495 if( ERROR_SUCCESS == r )
496 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL);
497
498 end:
499 HeapFree( GetProcessHeap(), 0, szwProduct );
500 HeapFree( GetProcessHeap(), 0, szwAttribute );
501 HeapFree( GetProcessHeap(), 0, szwBuffer );
502
503 return r;
504 }
505
506 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
507 LPWSTR szBuffer, DWORD *pcchValueBuf)
508 {
509 MSIHANDLE hProduct;
510 UINT r;
511 static const WCHAR szPackageCode[] =
512 {'P','a','c','k','a','g','e','C','o','d','e',0};
513 static const WCHAR szVersionString[] =
514 {'V','e','r','s','i','o','n','S','t','r','i','n','g',0};
515 static const WCHAR szProductVersion[] =
516 {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
517 static const WCHAR szAssignmentType[] =
518 {'A','s','s','i','g','n','m','e','n','t','T','y','p','e',0};
519
520 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute),
521 szBuffer, pcchValueBuf);
522
523 if (NULL != szBuffer && NULL == pcchValueBuf)
524 return ERROR_INVALID_PARAMETER;
525 if (NULL == szProduct || NULL == szAttribute)
526 return ERROR_INVALID_PARAMETER;
527
528 /* check for special properties */
529 if (strcmpW(szAttribute, szPackageCode)==0)
530 {
531 HKEY hkey;
532 WCHAR squished[GUID_SIZE];
533 WCHAR package[200];
534 DWORD sz = sizeof(squished);
535
536 r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
537 if (r != ERROR_SUCCESS)
538 return ERROR_UNKNOWN_PRODUCT;
539
540 r = RegQueryValueExW(hkey, szPackageCode, NULL, NULL,
541 (LPBYTE)squished, &sz);
542 if (r != ERROR_SUCCESS)
543 {
544 RegCloseKey(hkey);
545 return ERROR_UNKNOWN_PRODUCT;
546 }
547
548 unsquash_guid(squished, package);
549 *pcchValueBuf = strlenW(package);
550 if (strlenW(package) > *pcchValueBuf)
551 {
552 RegCloseKey(hkey);
553 return ERROR_MORE_DATA;
554 }
555 else
556 strcpyW(szBuffer, package);
557
558 RegCloseKey(hkey);
559 r = ERROR_SUCCESS;
560 }
561 else if (strcmpW(szAttribute, szVersionString)==0)
562 {
563 r = MsiOpenProductW(szProduct, &hProduct);
564 if (ERROR_SUCCESS != r)
565 return r;
566
567 r = MsiGetPropertyW(hProduct, szProductVersion, szBuffer, pcchValueBuf);
568 MsiCloseHandle(hProduct);
569 }
570 else if (strcmpW(szAttribute, szAssignmentType)==0)
571 {
572 FIXME("0 (zero) if advertised, 1(one) if per machine.\n");
573 if (szBuffer)
574 szBuffer[0] = 1;
575 r = ERROR_SUCCESS;
576 }
577 else
578 {
579 r = MsiOpenProductW(szProduct, &hProduct);
580 if (ERROR_SUCCESS != r)
581 return r;
582
583 r = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
584 MsiCloseHandle(hProduct);
585 }
586
587 return r;
588 }
589
590 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
591 {
592 LPWSTR szwLogFile = NULL;
593 UINT r;
594
595 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes);
596
597 if( szLogFile )
598 {
599 szwLogFile = strdupAtoW( szLogFile );
600 if( !szwLogFile )
601 return ERROR_OUTOFMEMORY;
602 }
603 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
604 HeapFree( GetProcessHeap(), 0, szwLogFile );
605 return r;
606 }
607
608 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
609 {
610 HANDLE file = INVALID_HANDLE_VALUE;
611
612 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes);
613
614 lstrcpyW(gszLogFile,szLogFile);
615 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
616 DeleteFileW(szLogFile);
617 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
618 FILE_ATTRIBUTE_NORMAL, NULL);
619 if (file != INVALID_HANDLE_VALUE)
620 CloseHandle(file);
621 else
622 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
623
624 return ERROR_SUCCESS;
625 }
626
627 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
628 {
629 LPWSTR szwProduct = NULL;
630 INSTALLSTATE r;
631
632 if( szProduct )
633 {
634 szwProduct = strdupAtoW( szProduct );
635 if( !szwProduct )
636 return ERROR_OUTOFMEMORY;
637 }
638 r = MsiQueryProductStateW( szwProduct );
639 HeapFree( GetProcessHeap(), 0, szwProduct );
640 return r;
641 }
642
643 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
644 {
645 UINT rc;
646 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
647 HKEY hkey = 0;
648 static const WCHAR szWindowsInstaller[] = {
649 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 };
650 DWORD sz;
651
652 TRACE("%s\n", debugstr_w(szProduct));
653
654 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
655 if (rc != ERROR_SUCCESS)
656 goto end;
657
658 RegCloseKey(hkey);
659
660 rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
661 if (rc != ERROR_SUCCESS)
662 goto end;
663
664 sz = sizeof(rrc);
665 rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz);
666 if (rc != ERROR_SUCCESS)
667 goto end;
668
669 switch (rrc)
670 {
671 case 1:
672 /* default */
673 rrc = INSTALLSTATE_DEFAULT;
674 break;
675 default:
676 FIXME("Unknown install state read from registry (%i)\n",rrc);
677 rrc = INSTALLSTATE_UNKNOWN;
678 break;
679 }
680 end:
681 RegCloseKey(hkey);
682 return rrc;
683 }
684
685 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
686 {
687 INSTALLUILEVEL old = gUILevel;
688 HWND oldwnd = gUIhwnd;
689
690 TRACE("%08x %p\n", dwUILevel, phWnd);
691
692 gUILevel = dwUILevel;
693 if (phWnd)
694 {
695 gUIhwnd = *phWnd;
696 *phWnd = oldwnd;
697 }
698 return old;
699 }
700
701 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
702 DWORD dwMessageFilter, LPVOID pvContext)
703 {
704 INSTALLUI_HANDLERA prev = gUIHandlerA;
705
706 TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext);
707 gUIHandlerA = puiHandler;
708 gUIFilter = dwMessageFilter;
709 gUIContext = pvContext;
710
711 return prev;
712 }
713
714 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
715 DWORD dwMessageFilter, LPVOID pvContext)
716 {
717 INSTALLUI_HANDLERW prev = gUIHandlerW;
718
719 TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext);
720 gUIHandlerW = puiHandler;
721 gUIFilter = dwMessageFilter;
722 gUIContext = pvContext;
723
724 return prev;
725 }
726
727 /******************************************************************
728 * MsiLoadStringW [MSI.@]
729 *
730 * Loads a string from MSI's string resources.
731 *
732 * PARAMS
733 *
734 * handle [I] only -1 is handled currently
735 * id [I] id of the string to be loaded
736 * lpBuffer [O] buffer for the string to be written to
737 * nBufferMax [I] maximum size of the buffer in characters
738 * lang [I] the preferred language for the string
739 *
740 * RETURNS
741 *
742 * If successful, this function returns the language id of the string loaded
743 * If the function fails, the function returns zero.
744 *
745 * NOTES
746 *
747 * The type of the first parameter is unknown. LoadString's prototype
748 * suggests that it might be a module handle. I have made it an MSI handle
749 * for starters, as -1 is an invalid MSI handle, but not an invalid module
750 * handle. Maybe strings can be stored in an MSI database somehow.
751 */
752 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
753 int nBufferMax, LANGID lang )
754 {
755 HRSRC hres;
756 HGLOBAL hResData;
757 LPWSTR p;
758 DWORD i, len;
759
760 TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
761
762 if( handle != -1 )
763 FIXME("don't know how to deal with handle = %08lx\n", handle);
764
765 if( !lang )
766 lang = GetUserDefaultLangID();
767
768 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
769 (LPWSTR)1, lang );
770 if( !hres )
771 return 0;
772 hResData = LoadResource( msi_hInstance, hres );
773 if( !hResData )
774 return 0;
775 p = LockResource( hResData );
776 if( !p )
777 return 0;
778
779 for (i = 0; i < (id&0xf); i++)
780 p += *p + 1;
781 len = *p;
782
783 if( nBufferMax <= len )
784 return 0;
785
786 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
787 lpBuffer[ len ] = 0;
788
789 TRACE("found -> %s\n", debugstr_w(lpBuffer));
790
791 return lang;
792 }
793
794 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
795 int nBufferMax, LANGID lang )
796 {
797 LPWSTR bufW;
798 LANGID r;
799 DWORD len;
800
801 bufW = HeapAlloc(GetProcessHeap(), 0, nBufferMax*sizeof(WCHAR));
802 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
803 if( r )
804 {
805 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
806 if( len <= nBufferMax )
807 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
808 lpBuffer, nBufferMax, NULL, NULL );
809 else
810 r = 0;
811 }
812 HeapFree(GetProcessHeap(), 0, bufW);
813 return r;
814 }
815
816 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
817 DWORD *pcchBuf)
818 {
819 FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
820 return INSTALLSTATE_UNKNOWN;
821 }
822
823 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf,
824 DWORD *pcchBuf)
825 {
826 FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
827 return INSTALLSTATE_UNKNOWN;
828 }
829
830 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
831 WORD wLanguageId, DWORD f)
832 {
833 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),
834 uType,wLanguageId,f);
835 return ERROR_CALL_NOT_IMPLEMENTED;
836 }
837
838 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
839 WORD wLanguageId, DWORD f)
840 {
841 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),
842 uType,wLanguageId,f);
843 return ERROR_CALL_NOT_IMPLEMENTED;
844 }
845
846 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
847 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
848 DWORD* pcchPathBuf )
849 {
850 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName),
851 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
852 pcchPathBuf);
853 return ERROR_CALL_NOT_IMPLEMENTED;
854 }
855
856 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
857 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
858 DWORD* pcchPathBuf )
859 {
860 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName),
861 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
862 pcchPathBuf);
863 return ERROR_CALL_NOT_IMPLEMENTED;
864 }
865
866 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
867 LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
868 {
869 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
870 return ERROR_CALL_NOT_IMPLEMENTED;
871 }
872
873 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
874 LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
875 {
876 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
877 return ERROR_CALL_NOT_IMPLEMENTED;
878 }
879
880 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
881 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
882 DWORD* pcbHashData)
883 {
884 FIXME("%s %08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
885 ppcCertContext, pbHashData, pcbHashData);
886 return ERROR_CALL_NOT_IMPLEMENTED;
887 }
888
889 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
890 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
891 DWORD* pcbHashData)
892 {
893 FIXME("%s %08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
894 ppcCertContext, pbHashData, pcbHashData);
895 return ERROR_CALL_NOT_IMPLEMENTED;
896 }
897
898 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
899 LPSTR szValue, DWORD *pccbValue )
900 {
901 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
902 return ERROR_CALL_NOT_IMPLEMENTED;
903 }
904
905 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
906 LPWSTR szValue, DWORD *pccbValue )
907 {
908 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
909 return ERROR_CALL_NOT_IMPLEMENTED;
910 }
911
912 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
913 {
914 UINT r;
915 LPWSTR szPack = NULL;
916
917 TRACE("%s\n", debugstr_a(szPackage) );
918
919 if( szPackage )
920 {
921 szPack = strdupAtoW( szPackage );
922 if( !szPack )
923 return ERROR_OUTOFMEMORY;
924 }
925
926 r = MsiVerifyPackageW( szPack );
927
928 HeapFree( GetProcessHeap(), 0, szPack );
929
930 return r;
931 }
932
933 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
934 {
935 MSIHANDLE handle;
936 UINT r;
937
938 TRACE("%s\n", debugstr_w(szPackage) );
939
940 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
941 MsiCloseHandle( handle );
942
943 return r;
944 }
945
946 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
947 LPSTR lpPathBuf, DWORD* pcchBuf)
948 {
949 LPWSTR szwProduct = NULL, szwComponent = NULL, lpwPathBuf= NULL;
950 INSTALLSTATE rc;
951 UINT incoming_len;
952
953 if( szProduct )
954 {
955 szwProduct = strdupAtoW( szProduct );
956 if( !szwProduct)
957 return ERROR_OUTOFMEMORY;
958 }
959
960 if( szComponent )
961 {
962 szwComponent = strdupAtoW( szComponent );
963 if( !szwComponent )
964 {
965 HeapFree( GetProcessHeap(), 0, szwProduct);
966 return ERROR_OUTOFMEMORY;
967 }
968 }
969
970 if( pcchBuf && *pcchBuf > 0 )
971 lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR));
972 else
973 lpwPathBuf = NULL;
974
975 incoming_len = *pcchBuf;
976 rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
977
978 HeapFree( GetProcessHeap(), 0, szwProduct);
979 HeapFree( GetProcessHeap(), 0, szwComponent);
980 if (lpwPathBuf)
981 {
982 if (rc != INSTALLSTATE_UNKNOWN)
983 WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, incoming_len,
984 lpPathBuf, incoming_len, NULL, NULL);
985 HeapFree( GetProcessHeap(), 0, lpwPathBuf);
986 }
987
988 return rc;
989 }
990
991 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
992 LPWSTR lpPathBuf, DWORD* pcchBuf)
993 {
994 WCHAR squished_pc[GUID_SIZE];
995 UINT rc;
996 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
997 HKEY hkey = 0;
998 LPWSTR path = NULL;
999 DWORD sz, type;
1000
1001 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1002 debugstr_w(szComponent), lpPathBuf, pcchBuf);
1003
1004 if( lpPathBuf && !pcchBuf )
1005 return INSTALLSTATE_INVALIDARG;
1006
1007 squash_guid(szProduct,squished_pc);
1008
1009 rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE);
1010 if( rc != ERROR_SUCCESS )
1011 goto end;
1012
1013 RegCloseKey(hkey);
1014
1015 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
1016 if( rc != ERROR_SUCCESS )
1017 goto end;
1018
1019 sz = 0;
1020 type = 0;
1021 rc = RegQueryValueExW( hkey, squished_pc, NULL, &type, NULL, &sz );
1022 if( rc != ERROR_SUCCESS )
1023 goto end;
1024 if( type != REG_SZ )
1025 goto end;
1026
1027 sz += sizeof(WCHAR);
1028 path = HeapAlloc( GetProcessHeap(), 0, sz );
1029 if( !path )
1030 goto end;
1031
1032 rc = RegQueryValueExW( hkey, squished_pc, NULL, NULL, (LPVOID) path, &sz );
1033 if( rc != ERROR_SUCCESS )
1034 goto end;
1035
1036 TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent),
1037 debugstr_w(szProduct), debugstr_w(path));
1038
1039 if (path[0]=='0')
1040 {
1041 FIXME("Registry entry.. check entry\n");
1042 rrc = INSTALLSTATE_LOCAL;
1043 }
1044 else
1045 {
1046 /* PROBABLY a file */
1047 if ( GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES )
1048 rrc = INSTALLSTATE_LOCAL;
1049 else
1050 rrc = INSTALLSTATE_ABSENT;
1051 }
1052
1053 if( pcchBuf )
1054 {
1055 sz = sz / sizeof(WCHAR);
1056 if( *pcchBuf >= sz )
1057 lstrcpyW( lpPathBuf, path );
1058 *pcchBuf = sz;
1059 }
1060
1061 end:
1062 HeapFree(GetProcessHeap(), 0, path );
1063 RegCloseKey(hkey);
1064 return rrc;
1065 }
1066
1067 /******************************************************************
1068 * MsiQueryFeatureStateA [MSI.@]
1069 */
1070 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1071 {
1072 INSTALLSTATE rc;
1073 LPWSTR szwProduct= NULL;
1074 LPWSTR szwFeature= NULL;
1075
1076 if( szProduct )
1077 {
1078 szwProduct = strdupAtoW( szProduct );
1079 if( !szwProduct)
1080 return ERROR_OUTOFMEMORY;
1081 }
1082
1083 if( szFeature )
1084 {
1085 szwFeature = strdupAtoW( szFeature );
1086 if( !szwFeature)
1087 {
1088 HeapFree( GetProcessHeap(), 0, szwProduct);
1089 return ERROR_OUTOFMEMORY;
1090 }
1091 }
1092
1093 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1094
1095 HeapFree( GetProcessHeap(), 0, szwProduct);
1096 HeapFree( GetProcessHeap(), 0, szwFeature);
1097
1098 return rc;
1099 }
1100
1101 /******************************************************************
1102 * MsiQueryFeatureStateW [MSI.@]
1103 *
1104 * This does not verify that the Feature is functional. So i am only going to
1105 * check the existence of the key in the registry. This should tell me if it is
1106 * installed.
1107 */
1108 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1109 {
1110 UINT rc;
1111 DWORD sz = 0;
1112 HKEY hkey;
1113
1114 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1115
1116 rc = MSIREG_OpenFeaturesKey(szProduct, &hkey, FALSE);
1117 if (rc != ERROR_SUCCESS)
1118 return INSTALLSTATE_UNKNOWN;
1119
1120 rc = RegQueryValueExW( hkey, szFeature, NULL, NULL, NULL, &sz);
1121 RegCloseKey(hkey);
1122
1123 if (rc == ERROR_SUCCESS)
1124 return INSTALLSTATE_LOCAL;
1125 else
1126 return INSTALLSTATE_ABSENT;
1127 }
1128
1129 /******************************************************************
1130 * MsiGetFileVersionA [MSI.@]
1131 */
1132 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
1133 DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf)
1134 {
1135 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
1136 UINT ret = ERROR_OUTOFMEMORY;
1137
1138 if( szFilePath )
1139 {
1140 szwFilePath = strdupAtoW( szFilePath );
1141 if( !szwFilePath )
1142 goto end;
1143 }
1144
1145 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1146 {
1147 lpwVersionBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR));
1148 if( !lpwVersionBuff )
1149 goto end;
1150 }
1151
1152 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1153 {
1154 lpwLangBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR));
1155 if( !lpwLangBuff )
1156 goto end;
1157 }
1158
1159 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
1160 lpwLangBuff, pcchLangBuf);
1161
1162 if( lpwVersionBuff )
1163 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
1164 lpVersionBuf, *pcchVersionBuf, NULL, NULL);
1165 if( lpwLangBuff )
1166 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
1167 lpLangBuf, *pcchLangBuf, NULL, NULL);
1168
1169 end:
1170 HeapFree(GetProcessHeap(), 0, szwFilePath);
1171 HeapFree(GetProcessHeap(), 0, lpwVersionBuff);
1172 HeapFree(GetProcessHeap(), 0, lpwLangBuff);
1173
1174 return ret;
1175 }
1176
1177 /******************************************************************
1178 * MsiGetFileVersionW [MSI.@]
1179 */
1180 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
1181 DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf)
1182 {
1183 static const WCHAR szVersionResource[] = {'\\',0};
1184 static const WCHAR szVersionFormat[] = {
1185 '%','d','.','%','d','.','%','d','.','%','d',0};
1186 static const WCHAR szLangFormat[] = {'%','d',0};
1187 UINT ret = 0;
1188 DWORD dwVerLen;
1189 LPVOID lpVer = NULL;
1190 VS_FIXEDFILEINFO *ffi;
1191 UINT puLen;
1192 WCHAR tmp[32];
1193
1194 TRACE("%s %p %ld %p %ld\n", debugstr_w(szFilePath),
1195 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
1196 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
1197
1198 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
1199 if( !dwVerLen )
1200 return GetLastError();
1201
1202 lpVer = HeapAlloc(GetProcessHeap(), 0, dwVerLen);
1203 if( !lpVer )
1204 {
1205 ret = ERROR_OUTOFMEMORY;
1206 goto end;
1207 }
1208
1209 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
1210 {
1211 ret = GetLastError();
1212 goto end;
1213 }
1214 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1215 {
1216 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
1217 (puLen > 0) )
1218 {
1219 wsprintfW(tmp, szVersionFormat,
1220 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
1221 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
1222 lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
1223 *pcchVersionBuf = lstrlenW(lpVersionBuf);
1224 }
1225 else
1226 {
1227 *lpVersionBuf = 0;
1228 *pcchVersionBuf = 0;
1229 }
1230 }
1231
1232 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1233 {
1234 DWORD lang = GetUserDefaultLangID();
1235
1236 FIXME("Retrieve language from file\n");
1237 wsprintfW(tmp, szLangFormat, lang);
1238 lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
1239 *pcchLangBuf = lstrlenW(lpLangBuf);
1240 }
1241
1242 end:
1243 HeapFree(GetProcessHeap(), 0, lpVer);
1244 return ret;
1245 }
1246
1247
1248 /******************************************************************
1249 * DllMain
1250 */
1251 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1252 {
1253 switch(fdwReason)
1254 {
1255 case DLL_PROCESS_ATTACH:
1256 msi_hInstance = hinstDLL;
1257 DisableThreadLibraryCalls(hinstDLL);
1258 msi_dialog_register_class();
1259 break;
1260 case DLL_PROCESS_DETACH:
1261 msi_dialog_unregister_class();
1262 /* FIXME: Cleanup */
1263 break;
1264 }
1265 return TRUE;
1266 }
1267
1268 typedef struct tagIClassFactoryImpl
1269 {
1270 IClassFactoryVtbl *lpVtbl;
1271 } IClassFactoryImpl;
1272
1273 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
1274 REFIID riid,LPVOID *ppobj)
1275 {
1276 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1277 FIXME("%p %s %p\n",This,debugstr_guid(riid),ppobj);
1278 return E_NOINTERFACE;
1279 }
1280
1281 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
1282 {
1283 return 2;
1284 }
1285
1286 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
1287 {
1288 return 1;
1289 }
1290
1291 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
1292 LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
1293 {
1294 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1295
1296 FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
1297 return E_FAIL;
1298 }
1299
1300 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
1301 {
1302 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1303
1304 FIXME("%p %d\n", This, dolock);
1305 return S_OK;
1306 }
1307
1308 static IClassFactoryVtbl MsiCF_Vtbl =
1309 {
1310 MsiCF_QueryInterface,
1311 MsiCF_AddRef,
1312 MsiCF_Release,
1313 MsiCF_CreateInstance,
1314 MsiCF_LockServer
1315 };
1316
1317 static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl };
1318
1319 /******************************************************************
1320 * DllGetClassObject [MSI.@]
1321 */
1322 HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
1323 {
1324 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1325
1326 if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
1327 IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
1328 IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
1329 IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) ||
1330 IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
1331 {
1332 *ppv = (LPVOID) &Msi_CF;
1333 return S_OK;
1334 }
1335 return CLASS_E_CLASSNOTAVAILABLE;
1336 }
1337
1338 /******************************************************************
1339 * DllGetVersion [MSI.@]
1340 */
1341 HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi)
1342 {
1343 TRACE("%p\n",pdvi);
1344
1345 if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1346 return E_INVALIDARG;
1347
1348 pdvi->dwMajorVersion = MSI_MAJORVERSION;
1349 pdvi->dwMinorVersion = MSI_MINORVERSION;
1350 pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1351 pdvi->dwPlatformID = 1;
1352
1353 return S_OK;
1354 }
1355
1356 /******************************************************************
1357 * DllCanUnloadNow [MSI.@]
1358 */
1359 BOOL WINAPI MSI_DllCanUnloadNow(void)
1360 {
1361 return S_FALSE;
1362 }
1363
1364 UINT WINAPI MsiGetFeatureUsageW(LPCWSTR szProduct, LPCWSTR szFeature,
1365 DWORD* pdwUseCount, WORD* pwDateUsed)
1366 {
1367 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
1368 pdwUseCount, pwDateUsed);
1369 return ERROR_CALL_NOT_IMPLEMENTED;
1370 }
1371
1372 UINT WINAPI MsiGetFeatureUsageA(LPCSTR szProduct, LPCSTR szFeature,
1373 DWORD* pdwUseCount, WORD* pwDateUsed)
1374 {
1375 FIXME("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
1376 pdwUseCount, pwDateUsed);
1377 return ERROR_CALL_NOT_IMPLEMENTED;
1378 }
1379
1380 INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature,
1381 DWORD dwInstallMode, DWORD dwReserved)
1382 {
1383 FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1384 dwInstallMode, dwReserved);
1385
1386 /*
1387 * Polls all the components of the feature to find install state and then
1388 * writes:
1389 * Software\\Microsoft\\Windows\\CurrentVersion\\
1390 * Installer\\Products\\<squishguid>\\<feature>
1391 * "Usage"=dword:........
1392 */
1393
1394 return INSTALLSTATE_LOCAL;
1395 }
1396
1397 /***********************************************************************
1398 * MsiUseFeatureExA [MSI.@]
1399 */
1400 INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature,
1401 DWORD dwInstallMode, DWORD dwReserved)
1402 {
1403 FIXME("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1404 dwInstallMode, dwReserved);
1405
1406 return INSTALLSTATE_LOCAL;
1407 }
1408
1409 INSTALLSTATE WINAPI MsiUseFeatureW(LPCWSTR szProduct, LPCWSTR szFeature)
1410 {
1411 FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1412
1413 return INSTALLSTATE_LOCAL;
1414 }
1415
1416 INSTALLSTATE WINAPI MsiUseFeatureA(LPCSTR szProduct, LPCSTR szFeature)
1417 {
1418 FIXME("%s %s\n", debugstr_a(szProduct), debugstr_a(szFeature));
1419
1420 return INSTALLSTATE_LOCAL;
1421 }
1422
1423 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
1424 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1425 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
1426 DWORD* pcchPathBuf)
1427 {
1428 HKEY hkey;
1429 UINT rc;
1430 LPWSTR info;
1431 DWORD sz;
1432 LPWSTR product = NULL;
1433 LPWSTR component = NULL;
1434 LPWSTR ptr;
1435 GUID clsid;
1436
1437 TRACE("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
1438 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
1439 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1440
1441 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
1442 if (rc != ERROR_SUCCESS)
1443 return ERROR_INDEX_ABSENT;
1444
1445 sz = 0;
1446 rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, NULL, &sz);
1447 if (sz <= 0)
1448 {
1449 RegCloseKey(hkey);
1450 return ERROR_INDEX_ABSENT;
1451 }
1452
1453 info = HeapAlloc(GetProcessHeap(),0,sz);
1454 rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, (LPBYTE)info, &sz);
1455 if (rc != ERROR_SUCCESS)
1456 {
1457 RegCloseKey(hkey);
1458 HeapFree(GetProcessHeap(),0,info);
1459 return ERROR_INDEX_ABSENT;
1460 }
1461
1462 /* find the component */
1463 ptr = strchrW(&info[20],'>');
1464 if (ptr)
1465 ptr++;
1466 else
1467 {
1468 RegCloseKey(hkey);
1469 HeapFree(GetProcessHeap(),0,info);
1470 return ERROR_INDEX_ABSENT;
1471 }
1472
1473 if (!szProduct)
1474 {
1475 decode_base85_guid(info,&clsid);
1476 StringFromCLSID(&clsid, &product);
1477 }
1478 decode_base85_guid(ptr,&clsid);
1479 StringFromCLSID(&clsid, &component);
1480
1481 if (!szProduct)
1482 rc = MsiGetComponentPathW(product, component, lpPathBuf, pcchPathBuf);
1483 else
1484 rc = MsiGetComponentPathW(szProduct, component, lpPathBuf, pcchPathBuf);
1485
1486 RegCloseKey(hkey);
1487 HeapFree(GetProcessHeap(),0,info);
1488 HeapFree(GetProcessHeap(),0,product);
1489 HeapFree(GetProcessHeap(),0,component);
1490
1491 if (rc == INSTALLSTATE_LOCAL)
1492 return ERROR_SUCCESS;
1493 else
1494 return ERROR_FILE_NOT_FOUND;
1495 }
1496
1497 /***********************************************************************
1498 * MsiProvideQualifiedComponentW [MSI.@]
1499 */
1500 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
1501 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
1502 DWORD* pcchPathBuf)
1503 {
1504 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
1505 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
1506 }
1507
1508 /***********************************************************************
1509 * MsiProvideQualifiedComponentA [MSI.@]
1510 */
1511 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
1512 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
1513 DWORD* pcchPathBuf)
1514 {
1515 LPWSTR szwComponent, szwQualifier, lpwPathBuf;
1516 DWORD pcchwPathBuf;
1517 UINT rc;
1518
1519 TRACE("%s %s %li %p %p\n",szComponent, szQualifier,
1520 dwInstallMode, lpPathBuf, pcchPathBuf);
1521
1522 szwComponent= strdupAtoW( szComponent);
1523 szwQualifier= strdupAtoW( szQualifier);
1524
1525 lpwPathBuf = HeapAlloc(GetProcessHeap(),0,*pcchPathBuf * sizeof(WCHAR));
1526
1527 pcchwPathBuf = *pcchPathBuf;
1528
1529 rc = MsiProvideQualifiedComponentW(szwComponent, szwQualifier,
1530 dwInstallMode, lpwPathBuf, &pcchwPathBuf);
1531
1532 HeapFree(GetProcessHeap(),0,szwComponent);
1533 HeapFree(GetProcessHeap(),0,szwQualifier);
1534 *pcchPathBuf = WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, pcchwPathBuf,
1535 lpPathBuf, *pcchPathBuf, NULL, NULL);
1536
1537 HeapFree(GetProcessHeap(),0,lpwPathBuf);
1538 return rc;
1539 }
1540
1541 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
1542 DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf,
1543 DWORD* pcchOrgNameBuf, LPWSTR lpSerialBuf, DWORD* pcchSerialBuf)
1544 {
1545 HKEY hkey;
1546 DWORD sz;
1547 UINT rc = ERROR_SUCCESS,rc2 = ERROR_SUCCESS;
1548 static const WCHAR szOwner[] = {'R','e','g','O','w','n','e','r',0};
1549 static const WCHAR szCompany[] = {'R','e','g','C','o','m','p','a','n','y',0};
1550 static const WCHAR szSerial[] = {'P','r','o','d','u','c','t','I','D',0};
1551
1552 TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
1553 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1554 pcchSerialBuf);
1555
1556 rc = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
1557 if (rc != ERROR_SUCCESS)
1558 return USERINFOSTATE_UNKNOWN;
1559
1560 if (lpUserNameBuf)
1561 {
1562 sz = *lpUserNameBuf * sizeof(WCHAR);
1563 rc = RegQueryValueExW( hkey, szOwner, NULL, NULL, (LPBYTE)lpUserNameBuf,
1564 &sz);
1565 }
1566 if (!lpUserNameBuf && pcchUserNameBuf)
1567 {
1568 sz = 0;
1569 rc = RegQueryValueExW( hkey, szOwner, NULL, NULL, NULL, &sz);
1570 }
1571
1572 if (pcchUserNameBuf)
1573 *pcchUserNameBuf = sz / sizeof(WCHAR);
1574
1575 if (lpOrgNameBuf)
1576 {
1577 sz = *pcchOrgNameBuf * sizeof(WCHAR);
1578 rc2 = RegQueryValueExW( hkey, szCompany, NULL, NULL,
1579 (LPBYTE)lpOrgNameBuf, &sz);
1580 }
1581 if (!lpOrgNameBuf && pcchOrgNameBuf)
1582 {
1583 sz = 0;
1584 rc2 = RegQueryValueExW( hkey, szCompany, NULL, NULL, NULL, &sz);
1585 }
1586
1587 if (pcchOrgNameBuf)
1588 *pcchOrgNameBuf = sz / sizeof(WCHAR);
1589
1590 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA &&
1591 rc2 != ERROR_SUCCESS && rc2 != ERROR_MORE_DATA)
1592 {
1593 RegCloseKey(hkey);
1594 return USERINFOSTATE_ABSENT;
1595 }
1596
1597 if (lpSerialBuf)
1598 {
1599 sz = *pcchSerialBuf * sizeof(WCHAR);
1600 RegQueryValueExW( hkey, szSerial, NULL, NULL, (LPBYTE)lpSerialBuf,
1601 &sz);
1602 }
1603 if (!lpSerialBuf && pcchSerialBuf)
1604 {
1605 sz = 0;
1606 rc = RegQueryValueExW( hkey, szSerial, NULL, NULL, NULL, &sz);
1607 }
1608 if (pcchSerialBuf)
1609 *pcchSerialBuf = sz / sizeof(WCHAR);
1610
1611 RegCloseKey(hkey);
1612 return USERINFOSTATE_PRESENT;
1613 }
1614
1615 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf,
1616 DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf,
1617 DWORD* pcchOrgNameBuf, LPSTR lpSerialBuf, DWORD* pcchSerialBuf)
1618 {
1619 FIXME("%s %p %p %p %p %p %p\n",debugstr_a(szProduct), lpUserNameBuf,
1620 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1621 pcchSerialBuf);
1622
1623 return USERINFOSTATE_UNKNOWN;
1624 }
1625
1626 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
1627 {
1628 MSIHANDLE handle;
1629 UINT rc;
1630 MSIPACKAGE *package;
1631 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1632
1633 TRACE("(%s)\n",debugstr_w(szProduct));
1634
1635 rc = MsiOpenProductW(szProduct,&handle);
1636 if (rc != ERROR_SUCCESS)
1637 return ERROR_INVALID_PARAMETER;
1638
1639 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1640 rc = ACTION_PerformUIAction(package, szFirstRun);
1641 msiobj_release( &package->hdr );
1642
1643 MsiCloseHandle(handle);
1644
1645 return rc;
1646 }
1647
1648 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
1649 {
1650 MSIHANDLE handle;
1651 UINT rc;
1652 MSIPACKAGE *package;
1653 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1654
1655 TRACE("(%s)\n",debugstr_a(szProduct));
1656
1657 rc = MsiOpenProductA(szProduct,&handle);
1658 if (rc != ERROR_SUCCESS)
1659 return ERROR_INVALID_PARAMETER;
1660
1661 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1662 rc = ACTION_PerformUIAction(package, szFirstRun);
1663 msiobj_release( &package->hdr );
1664
1665 MsiCloseHandle(handle);
1666
1667 return rc;
1668 }
1669
1670 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
1671 {
1672 WCHAR path[MAX_PATH];
1673
1674 if(dwReserved) {
1675 FIXME("Don't know how to handle argument %ld\n", dwReserved);
1676 return ERROR_CALL_NOT_IMPLEMENTED;
1677 }
1678
1679 if(!GetWindowsDirectoryW(path, MAX_PATH)) {
1680 FIXME("GetWindowsDirectory failed unexpected! Error %ld\n",
1681 GetLastError());
1682 return ERROR_CALL_NOT_IMPLEMENTED;
1683 }
1684
1685 strcatW(path, installerW);
1686
1687 CreateDirectoryW(path, NULL);
1688
1689 return 0;
1690 }
1691
1692 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
1693 LPSTR szProductCode, LPSTR szFeatureId,
1694 LPSTR szComponentCode )
1695 {
1696 FIXME("\n");
1697 return ERROR_CALL_NOT_IMPLEMENTED;
1698 }
1699
1700 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
1701 LPWSTR szProductCode, LPWSTR szFeatureId,
1702 LPWSTR szComponentCode )
1703 {
1704 FIXME("\n");
1705 return ERROR_CALL_NOT_IMPLEMENTED;
1706 }
1707
1708 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
1709 DWORD dwReinstallMode )
1710 {
1711 FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1712 dwReinstallMode);
1713 return ERROR_SUCCESS;
1714 }
1715
1716 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
1717 DWORD dwReinstallMode )
1718 {
1719 FIXME("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1720 dwReinstallMode);
1721 return ERROR_SUCCESS;
1722 }