ReactOS 0.4.15-dev-5666-gc548b97
appsearch.c
Go to the documentation of this file.
1/*
2 * Implementation of the AppSearch action of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2005 Juan Lang
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20#include <stdarg.h>
21
22#define COBJMACROS
23
24#include "windef.h"
25#include "winbase.h"
26#include "winreg.h"
27#include "msi.h"
28#include "msiquery.h"
29#include "msidefs.h"
30#include "winver.h"
31#include "shlwapi.h"
32#include "wine/debug.h"
33#include "msipriv.h"
34
36
37typedef struct tagMSISIGNATURE
38{
39 LPCWSTR Name; /* NOT owned by this structure */
51
53{
54 const WCHAR *ptr;
55 int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
56
57 x1 = wcstol(verStr, NULL, 10);
58 ptr = wcschr(verStr, '.');
59 if (ptr)
60 {
61 x2 = wcstol(ptr + 1, NULL, 10);
62 ptr = wcschr(ptr + 1, '.');
63 }
64 if (ptr)
65 {
66 x3 = wcstol(ptr + 1, NULL, 10);
67 ptr = wcschr(ptr + 1, '.');
68 }
69 if (ptr)
70 x4 = wcstol(ptr + 1, NULL, 10);
71 /* FIXME: byte-order dependent? */
72 *ms = x1 << 16 | x2;
73 if (ls) *ls = x3 << 16 | x4;
74}
75
76/* Fills in sig with the values from the Signature table, where name is the
77 * signature to find. Upon return, sig->File will be NULL if the record is not
78 * found, and not NULL if it is found.
79 * Warning: clears all fields in sig!
80 * Returns ERROR_SUCCESS upon success (where not finding the record counts as
81 * success), something else on error.
82 */
83static UINT get_signature( MSIPACKAGE *package, MSISIGNATURE *sig, const WCHAR *name )
84{
85 WCHAR *minVersion, *maxVersion, *p;
87 DWORD time;
88
89 TRACE("package %p, sig %p\n", package, sig);
90
91 memset(sig, 0, sizeof(*sig));
92 sig->Name = name;
93 row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `Signature` WHERE `Signature` = '%s'", name );
94 if (!row)
95 {
96 TRACE("failed to query signature for %s\n", debugstr_w(name));
97 return ERROR_SUCCESS;
98 }
99
100 /* get properties */
101 sig->File = msi_dup_record_field(row,2);
102 if ((p = wcschr(sig->File, '|')))
103 {
104 p++;
105 memmove(sig->File, p, (lstrlenW(p) + 1) * sizeof(WCHAR));
106 }
107
108 minVersion = msi_dup_record_field(row,3);
109 if (minVersion)
110 {
111 msi_parse_version_string( minVersion, &sig->MinVersionMS, &sig->MinVersionLS );
112 msi_free( minVersion );
113 }
114 maxVersion = msi_dup_record_field(row,4);
115 if (maxVersion)
116 {
117 msi_parse_version_string( maxVersion, &sig->MaxVersionMS, &sig->MaxVersionLS );
118 msi_free( maxVersion );
119 }
121 if (sig->MinSize == MSI_NULL_INTEGER)
122 sig->MinSize = 0;
124 if (sig->MaxSize == MSI_NULL_INTEGER)
125 sig->MaxSize = 0;
128 if (time != MSI_NULL_INTEGER)
131 if (time != MSI_NULL_INTEGER)
133
134 TRACE("Found file name %s for Signature_ %s;\n",
136 TRACE("MinVersion is %d.%d.%d.%d\n", HIWORD(sig->MinVersionMS),
138 LOWORD(sig->MinVersionLS));
139 TRACE("MaxVersion is %d.%d.%d.%d\n", HIWORD(sig->MaxVersionMS),
141 LOWORD(sig->MaxVersionLS));
142 TRACE("MinSize is %lu, MaxSize is %lu\n", sig->MinSize, sig->MaxSize);
143 TRACE("Languages is %s\n", debugstr_w(sig->Languages));
144
145 msiobj_release( &row->hdr );
146
147 return ERROR_SUCCESS;
148}
149
150/* Frees any memory allocated in sig */
151static void free_signature( MSISIGNATURE *sig )
152{
153 msi_free(sig->File);
154 msi_free(sig->Languages);
155}
156
158{
160 DWORD attr;
161 UINT size;
162 LPWSTR val = NULL;
164
165 if (!sig->File)
166 {
169
170 attr = msi_get_file_attributes( package, path );
172 return strdupW(path);
173
174 return NULL;
175 }
176
177 attr = msi_get_file_attributes( package, path );
179 return NULL;
180
181 size = msi_get_file_version_info( package, path, 0, NULL );
182 if (!size)
183 return strdupW(path);
184
186 if (!buffer)
187 return NULL;
188
190 if (!size)
191 goto done;
192
193 if (!VerQueryValueW(buffer, L"\\", (LPVOID)&info, &size) || !info)
194 goto done;
195
196 if (sig->MinVersionLS || sig->MinVersionMS)
197 {
198 if (info->dwFileVersionMS < sig->MinVersionMS)
199 goto done;
200
201 if (info->dwFileVersionMS == sig->MinVersionMS &&
202 info->dwFileVersionLS < sig->MinVersionLS)
203 goto done;
204 }
205
206 if (sig->MaxVersionLS || sig->MaxVersionMS)
207 {
208 if (info->dwFileVersionMS > sig->MaxVersionMS)
209 goto done;
210
211 if (info->dwFileVersionMS == sig->MaxVersionMS &&
212 info->dwFileVersionLS > sig->MaxVersionLS)
213 goto done;
214 }
215
216 val = strdupW(path);
217
218done:
220 return val;
221}
222
223static UINT search_components( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
224{
225 MSIRECORD *row, *rec;
226 LPCWSTR signature, guid;
227 BOOL sigpresent = TRUE;
228 BOOL isdir;
229 UINT type;
232 LPWSTR ptr;
233 DWORD attr;
234
235 TRACE("%s\n", debugstr_w(sig->Name));
236
237 *appValue = NULL;
238
239 row = MSI_QueryGetRecord(package->db, L"SELECT * FROM `CompLocator` WHERE `Signature_` = '%s'", sig->Name);
240 if (!row)
241 {
242 TRACE("failed to query CompLocator for %s\n", debugstr_w(sig->Name));
243 return ERROR_SUCCESS;
244 }
245
246 signature = MSI_RecordGetString(row, 1);
249
250 rec = MSI_QueryGetRecord(package->db, L"SELECT * FROM `Signature` WHERE `Signature` = '%s'", signature);
251 if (!rec)
252 sigpresent = FALSE;
253
254 *path = '\0';
256 if (!*path)
257 goto done;
258
259 attr = msi_get_file_attributes( package, path );
261 goto done;
262
263 isdir = (attr & FILE_ATTRIBUTE_DIRECTORY);
264
265 if (type != msidbLocatorTypeDirectory && sigpresent && !isdir)
266 {
267 *appValue = search_file( package, path, sig );
268 }
269 else if (!sigpresent && (type != msidbLocatorTypeDirectory || isdir))
270 {
272 {
273 ptr = wcsrchr(path, '\\');
274 *(ptr + 1) = '\0';
275 }
276 else
278
279 *appValue = strdupW(path);
280 }
281 else if (sigpresent)
282 {
285
286 attr = msi_get_file_attributes( package, path );
288 *appValue = strdupW(path);
289 }
290
291done:
292 if (rec) msiobj_release(&rec->hdr);
293 msiobj_release(&row->hdr);
294 return ERROR_SUCCESS;
295}
296
297static void convert_reg_value( DWORD regType, const BYTE *value, DWORD sz, WCHAR **appValue )
298{
299 LPWSTR ptr;
300 DWORD i;
301
302 switch (regType)
303 {
304 case REG_SZ:
305 if (*(LPCWSTR)value == '#')
306 {
307 /* escape leading pound with another */
308 *appValue = msi_alloc(sz + sizeof(WCHAR));
309 (*appValue)[0] = '#';
310 lstrcpyW(*appValue + 1, (LPCWSTR)value);
311 }
312 else
313 {
314 *appValue = msi_alloc(sz);
315 lstrcpyW(*appValue, (LPCWSTR)value);
316 }
317 break;
318 case REG_DWORD:
319 /* 7 chars for digits, 1 for NULL, 1 for #, and 1 for sign
320 * char if needed
321 */
322 *appValue = msi_alloc(10 * sizeof(WCHAR));
323 swprintf(*appValue, 10, L"#%d", *(const DWORD *)value);
324 break;
325 case REG_EXPAND_SZ:
327 *appValue = msi_alloc(sz * sizeof(WCHAR));
328 ExpandEnvironmentStringsW((LPCWSTR)value, *appValue, sz);
329 break;
330 case REG_BINARY:
331 /* #x<nibbles>\0 */
332 *appValue = msi_alloc((sz * 2 + 3) * sizeof(WCHAR));
333 lstrcpyW(*appValue, L"#x");
334 ptr = *appValue + lstrlenW(L"#x");
335 for (i = 0; i < sz; i++, ptr += 2)
336 swprintf(ptr, 3, L"%02X", value[i]);
337 break;
338 default:
339 WARN( "unimplemented for values of type %lu\n", regType );
340 *appValue = NULL;
341 }
342}
343
344static UINT search_directory( MSIPACKAGE *, MSISIGNATURE *, const WCHAR *, int, WCHAR ** );
345
346static UINT search_reg( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
347{
348 const WCHAR *keyPath, *valueName;
349 WCHAR *deformatted = NULL, *ptr = NULL, *end;
350 int root, type;
352 HKEY rootKey, key = NULL;
353 DWORD sz = 0, regType;
354 LPBYTE value = NULL;
355 MSIRECORD *row;
356 UINT rc;
357
358 TRACE("%s\n", debugstr_w(sig->Name));
359
360 *appValue = NULL;
361
362 row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `RegLocator` WHERE `Signature_` = '%s'", sig->Name );
363 if (!row)
364 {
365 TRACE("failed to query RegLocator for %s\n", debugstr_w(sig->Name));
366 return ERROR_SUCCESS;
367 }
368
370 keyPath = MSI_RecordGetString(row, 3);
371 valueName = MSI_RecordGetString(row, 4);
373
374 deformat_string(package, keyPath, &deformatted);
375
376 switch (root)
377 {
379 rootKey = HKEY_CLASSES_ROOT;
380 break;
382 rootKey = HKEY_CURRENT_USER;
383 break;
385 rootKey = HKEY_LOCAL_MACHINE;
387 else access |= KEY_WOW64_32KEY;
388 break;
390 rootKey = HKEY_USERS;
391 break;
392 default:
393 WARN("Unknown root key %d\n", root);
394 goto end;
395 }
396
397 rc = RegOpenKeyExW( rootKey, deformatted, 0, access, &key );
398 if (rc)
399 {
400 TRACE("RegOpenKeyExW returned %d\n", rc);
401 goto end;
402 }
403
404 msi_free(deformatted);
405 deformat_string(package, valueName, &deformatted);
406
407 rc = RegQueryValueExW(key, deformatted, NULL, NULL, NULL, &sz);
408 if (rc)
409 {
410 TRACE("RegQueryValueExW returned %d\n", rc);
411 goto end;
412 }
413 /* FIXME: sanity-check sz before allocating (is there an upper-limit
414 * on the value of a property?)
415 */
416 value = msi_alloc( sz );
417 rc = RegQueryValueExW(key, deformatted, NULL, &regType, value, &sz);
418 if (rc)
419 {
420 TRACE("RegQueryValueExW returned %d\n", rc);
421 goto end;
422 }
423
424 /* bail out if the registry key is empty */
425 if (sz == 0)
426 goto end;
427
428 /* expand if needed */
429 if (regType == REG_EXPAND_SZ)
430 {
432 if (sz)
433 {
434 LPWSTR buf = msi_alloc(sz * sizeof(WCHAR));
437 value = (LPBYTE)buf;
438 }
439 }
440
441 if ((regType == REG_SZ || regType == REG_EXPAND_SZ) &&
442 (ptr = wcschr((LPWSTR)value, '"')) && (end = wcschr(++ptr, '"')))
443 *end = '\0';
444 else
445 ptr = (LPWSTR)value;
446
447 switch (type & 0x0f)
448 {
450 search_directory( package, sig, ptr, 0, appValue );
451 break;
453 *appValue = search_file( package, ptr, sig );
454 break;
456 convert_reg_value( regType, value, sz, appValue );
457 break;
458 default:
459 FIXME("unimplemented for type %d (key path %s, value %s)\n",
460 type, debugstr_w(keyPath), debugstr_w(valueName));
461 }
462end:
463 msi_free( value );
464 RegCloseKey( key );
465 msi_free( deformatted );
466
467 msiobj_release(&row->hdr);
468 return ERROR_SUCCESS;
469}
470
472{
473 LPWSTR beg, end;
474 int i = 1;
475
476 if (field == 0)
477 return strdupW(buf);
478
479 beg = buf;
480 while ((end = wcschr(beg, ',')) && i < field)
481 {
482 beg = end + 1;
483 while (*beg == ' ')
484 beg++;
485
486 i++;
487 }
488
489 end = wcschr(beg, ',');
490 if (!end)
491 end = beg + lstrlenW(beg);
492
493 *end = '\0';
494 return strdupW(beg);
495}
496
497static UINT search_ini( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
498{
499 MSIRECORD *row;
500 LPWSTR fileName, section, key;
501 int field, type;
503
504 TRACE("%s\n", debugstr_w(sig->Name));
505
506 *appValue = NULL;
507
508 row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `IniLocator` WHERE `Signature_` = '%s'", sig->Name );
509 if (!row)
510 {
511 TRACE("failed to query IniLocator for %s\n", debugstr_w(sig->Name));
512 return ERROR_SUCCESS;
513 }
514
515 fileName = msi_dup_record_field(row, 2);
520 if (field == MSI_NULL_INTEGER)
521 field = 0;
522 if (type == MSI_NULL_INTEGER)
523 type = 0;
524
526 if (buf[0])
527 {
528 switch (type & 0x0f)
529 {
531 search_directory( package, sig, buf, 0, appValue );
532 break;
534 *appValue = search_file( package, buf, sig );
535 break;
537 *appValue = get_ini_field(buf, field);
538 break;
539 }
540 }
541
542 msi_free(fileName);
544 msi_free(key);
545
546 msiobj_release(&row->hdr);
547
548 return ERROR_SUCCESS;
549}
550
551/* Expands the value in src into a path without property names and only
552 * containing long path names into dst. Replaces at most len characters of dst,
553 * and always NULL-terminates dst if dst is not NULL and len >= 1.
554 * May modify src.
555 * Assumes src and dst are non-overlapping.
556 * FIXME: return code probably needed:
557 * - what does AppSearch return if the table values are invalid?
558 * - what if dst is too small?
559 */
560static void expand_any_path( MSIPACKAGE *package, WCHAR *src, WCHAR *dst, size_t len )
561{
562 WCHAR *ptr, *deformatted;
563
564 if (!src || !dst || !len)
565 {
566 if (dst) *dst = '\0';
567 return;
568 }
569
570 dst[0] = '\0';
571
572 /* Ignore the short portion of the path */
573 if ((ptr = wcschr(src, '|')))
574 ptr++;
575 else
576 ptr = src;
577
578 deformat_string(package, ptr, &deformatted);
579 if (!deformatted || lstrlenW(deformatted) > len - 1)
580 {
581 msi_free(deformatted);
582 return;
583 }
584
585 lstrcpyW(dst, deformatted);
586 dst[lstrlenW(deformatted)] = '\0';
587 msi_free(deformatted);
588}
589
590static LANGID *parse_languages( const WCHAR *languages, DWORD *num_ids )
591{
592 UINT i, count = 1;
593 WCHAR *str = strdupW( languages ), *p, *q;
594 LANGID *ret;
595
596 if (!str) return NULL;
597 for (p = q = str; (q = wcschr( q, ',' )); q++) count++;
598
599 if (!(ret = msi_alloc( count * sizeof(LANGID) )))
600 {
601 msi_free( str );
602 return NULL;
603 }
604 i = 0;
605 while (*p)
606 {
607 q = wcschr( p, ',' );
608 if (q) *q = 0;
609 ret[i] = wcstol( p, NULL, 10 );
610 if (!q) break;
611 p = q + 1;
612 i++;
613 }
614 msi_free( str );
615 *num_ids = count;
616 return ret;
617}
618
619static BOOL match_languages( const void *version, const WCHAR *languages )
620{
621 struct lang
622 {
623 USHORT id;
625 } *lang;
626 UINT len, j;
627 DWORD num_ids, i;
628 BOOL found = FALSE;
629 LANGID *ids;
630
631 if (!languages || !languages[0]) return TRUE;
632 if (!VerQueryValueW( version, L"\\VarFileInfo\\Translation", (void **)&lang, &len )) return FALSE;
633 if (!(ids = parse_languages( languages, &num_ids ))) return FALSE;
634
635 for (i = 0; i < num_ids; i++)
636 {
637 found = FALSE;
638 for (j = 0; j < len / sizeof(struct lang); j++)
639 {
640 if (!ids[i] || ids[i] == lang[j].id) found = TRUE;
641 }
642 if (!found) goto done;
643 }
644
645done:
646 msi_free( ids );
647 return found;
648}
649
650/* Sets *matches to whether the file (whose path is filePath) matches the
651 * versions set in sig.
652 * Return ERROR_SUCCESS in case of success (whether or not the file matches),
653 * something else if an install-halting error occurs.
654 */
655static UINT file_version_matches( MSIPACKAGE *package, const MSISIGNATURE *sig, const WCHAR *filePath,
656 BOOL *matches )
657{
658 UINT len;
659 void *version;
661 DWORD size = msi_get_file_version_info( package, filePath, 0, NULL );
662
663 *matches = FALSE;
664
665 if (!size) return ERROR_SUCCESS;
666 if (!(version = msi_alloc( size ))) return ERROR_OUTOFMEMORY;
667
668 if (msi_get_file_version_info( package, filePath, size, version ))
669 VerQueryValueW( version, L"\\", (void **)&info, &len );
670
671 if (info)
672 {
673 TRACE("comparing file version %d.%d.%d.%d:\n",
674 HIWORD(info->dwFileVersionMS),
675 LOWORD(info->dwFileVersionMS),
676 HIWORD(info->dwFileVersionLS),
677 LOWORD(info->dwFileVersionLS));
678 if (info->dwFileVersionMS < sig->MinVersionMS
679 || (info->dwFileVersionMS == sig->MinVersionMS &&
680 info->dwFileVersionLS < sig->MinVersionLS))
681 {
682 TRACE("less than minimum version %d.%d.%d.%d\n",
683 HIWORD(sig->MinVersionMS),
684 LOWORD(sig->MinVersionMS),
685 HIWORD(sig->MinVersionLS),
686 LOWORD(sig->MinVersionLS));
687 }
688 else if ((sig->MaxVersionMS || sig->MaxVersionLS) &&
689 (info->dwFileVersionMS > sig->MaxVersionMS ||
690 (info->dwFileVersionMS == sig->MaxVersionMS &&
691 info->dwFileVersionLS > sig->MaxVersionLS)))
692 {
693 TRACE("greater than maximum version %d.%d.%d.%d\n",
694 HIWORD(sig->MaxVersionMS),
695 LOWORD(sig->MaxVersionMS),
696 HIWORD(sig->MaxVersionLS),
697 LOWORD(sig->MaxVersionLS));
698 }
699 else if (!match_languages( version, sig->Languages ))
700 {
701 TRACE("languages %s not supported\n", debugstr_w( sig->Languages ));
702 }
703 else *matches = TRUE;
704 }
705 msi_free( version );
706 return ERROR_SUCCESS;
707}
708
709/* Sets *matches to whether the file in findData matches that in sig.
710 * fullFilePath is assumed to be the full path of the file specified in
711 * findData, which may be necessary to compare the version.
712 * Return ERROR_SUCCESS in case of success (whether or not the file matches),
713 * something else if an install-halting error occurs.
714 */
715static UINT file_matches_sig( MSIPACKAGE *package, const MSISIGNATURE *sig, const WIN32_FIND_DATAW *findData,
716 const WCHAR *fullFilePath, BOOL *matches )
717{
718 UINT rc = ERROR_SUCCESS;
719
720 *matches = TRUE;
721 /* assumes the caller has already ensured the filenames match, so check
722 * the other fields..
723 */
725 {
726 if (findData->ftCreationTime.dwHighDateTime <
727 sig->MinTime.dwHighDateTime ||
728 (findData->ftCreationTime.dwHighDateTime == sig->MinTime.dwHighDateTime
729 && findData->ftCreationTime.dwLowDateTime <
731 *matches = FALSE;
732 }
733 if (*matches && (sig->MaxTime.dwLowDateTime || sig->MaxTime.dwHighDateTime))
734 {
735 if (findData->ftCreationTime.dwHighDateTime >
736 sig->MaxTime.dwHighDateTime ||
737 (findData->ftCreationTime.dwHighDateTime == sig->MaxTime.dwHighDateTime
738 && findData->ftCreationTime.dwLowDateTime >
740 *matches = FALSE;
741 }
742 if (*matches && sig->MinSize && findData->nFileSizeLow < sig->MinSize)
743 *matches = FALSE;
744 if (*matches && sig->MaxSize && findData->nFileSizeLow > sig->MaxSize)
745 *matches = FALSE;
746 if (*matches && (sig->MinVersionMS || sig->MinVersionLS ||
747 sig->MaxVersionMS || sig->MaxVersionLS))
748 rc = file_version_matches( package, sig, fullFilePath, matches );
749 return rc;
750}
751
752/* Recursively searches the directory dir for files that match the signature
753 * sig, up to (depth + 1) levels deep. That is, if depth is 0, it searches dir
754 * (and only dir). If depth is 1, searches dir and its immediate
755 * subdirectories.
756 * Assumes sig->File is not NULL.
757 * Returns ERROR_SUCCESS on success (which may include non-critical errors),
758 * something else on failures which should halt the install.
759 */
760static UINT recurse_search_directory( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig, const WCHAR *dir,
761 int depth )
762{
763 HANDLE hFind;
764 WIN32_FIND_DATAW findData;
765 UINT rc = ERROR_SUCCESS;
766 size_t dirLen = lstrlenW(dir), fileLen = lstrlenW(sig->File);
767 WCHAR subpath[MAX_PATH];
768 WCHAR *buf;
769 DWORD len;
770
771 TRACE("Searching directory %s for file %s, depth %d\n", debugstr_w(dir), debugstr_w(sig->File), depth);
772
773 if (depth < 0)
774 return ERROR_SUCCESS;
775
776 *appValue = NULL;
777 /* We need the buffer in both paths below, so go ahead and allocate it
778 * here. Add two because we might need to add a backslash if the dir name
779 * isn't backslash-terminated.
780 */
781 len = dirLen + max(fileLen, lstrlenW(L"*.*")) + 2;
782 buf = msi_alloc(len * sizeof(WCHAR));
783 if (!buf)
784 return ERROR_OUTOFMEMORY;
785
786 lstrcpyW(buf, dir);
788 lstrcatW(buf, sig->File);
789
790 hFind = msi_find_first_file( package, buf, &findData );
791 if (hFind != INVALID_HANDLE_VALUE)
792 {
793 if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
794 {
796
797 rc = file_matches_sig( package, sig, &findData, buf, &matches );
798 if (rc == ERROR_SUCCESS && matches)
799 {
800 TRACE("found file, returning %s\n", debugstr_w(buf));
801 *appValue = buf;
802 }
803 }
804 FindClose(hFind);
805 }
806
807 if (rc == ERROR_SUCCESS && !*appValue)
808 {
809 lstrcpyW(buf, dir);
811 lstrcatW(buf, L"*.*");
812
813 hFind = msi_find_first_file( package, buf, &findData );
814 if (hFind != INVALID_HANDLE_VALUE)
815 {
816 if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
817 wcscmp( findData.cFileName, L"." ) &&
818 wcscmp( findData.cFileName, L".." ))
819 {
820 lstrcpyW(subpath, dir);
821 PathAppendW(subpath, findData.cFileName);
822 rc = recurse_search_directory( package, appValue, sig, subpath, depth - 1 );
823 }
824
825 while (rc == ERROR_SUCCESS && !*appValue && msi_find_next_file( package, hFind, &findData ))
826 {
827 if (!wcscmp( findData.cFileName, L"." ) ||
828 !wcscmp( findData.cFileName, L".." ))
829 continue;
830
831 lstrcpyW(subpath, dir);
832 PathAppendW(subpath, findData.cFileName);
833 if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
834 rc = recurse_search_directory( package, appValue, sig, subpath, depth - 1 );
835 }
836
837 FindClose(hFind);
838 }
839 }
840
841 if (*appValue != buf)
842 msi_free(buf);
843
844 return rc;
845}
846
847static UINT check_directory( MSIPACKAGE *package, const WCHAR *dir, WCHAR **appValue )
848{
850
852 {
853 TRACE("directory exists, returning %s\n", debugstr_w(dir));
854 *appValue = strdupW(dir);
855 }
856
857 return ERROR_SUCCESS;
858}
859
860static BOOL is_full_path( const WCHAR *path )
861{
862 WCHAR first = towupper(path[0]);
863 BOOL ret;
864
865 if (first >= 'A' && first <= 'Z' && path[1] == ':')
866 ret = TRUE;
867 else if (path[0] == '\\' && path[1] == '\\')
868 ret = TRUE;
869 else
870 ret = FALSE;
871 return ret;
872}
873
874static UINT search_directory( MSIPACKAGE *package, MSISIGNATURE *sig, const WCHAR *path, int depth, WCHAR **appValue )
875{
876 UINT rc;
877 DWORD attr;
878 LPWSTR val = NULL;
879
880 TRACE("%p, %p, %s, %d, %p\n", package, sig, debugstr_w(path), depth, appValue);
881
882 if (is_full_path( path ))
883 {
884 if (sig->File)
885 rc = recurse_search_directory( package, &val, sig, path, depth );
886 else
887 {
888 /* Recursively searching a directory makes no sense when the
889 * directory to search is the thing you're trying to find.
890 */
891 rc = check_directory( package, path, &val );
892 }
893 }
894 else
895 {
896 WCHAR pathWithDrive[MAX_PATH] = { 'C',':','\\',0 };
897 DWORD drives = GetLogicalDrives();
898 int i;
899
900 rc = ERROR_SUCCESS;
901 for (i = 0; rc == ERROR_SUCCESS && !val && i < 26; i++)
902 {
903 if (!(drives & (1 << i)))
904 continue;
905
906 pathWithDrive[0] = 'A' + i;
907 if (GetDriveTypeW(pathWithDrive) != DRIVE_FIXED)
908 continue;
909
910 lstrcpynW(pathWithDrive + 3, path, ARRAY_SIZE(pathWithDrive) - 3);
911
912 if (sig->File)
913 rc = recurse_search_directory( package, &val, sig, pathWithDrive, depth );
914 else
915 rc = check_directory( package, pathWithDrive, &val );
916 }
917 }
918
919 attr = msi_get_file_attributes( package, val );
921 val && val[lstrlenW(val) - 1] != '\\')
922 {
923 val = msi_realloc(val, (lstrlenW(val) + 2) * sizeof(WCHAR));
924 if (!val)
926 else
928 }
929
930 *appValue = val;
931
932 TRACE("returning %d\n", rc);
933 return rc;
934}
935
936static UINT search_sig_name( MSIPACKAGE *, const WCHAR *, MSISIGNATURE *, WCHAR ** );
937
938static UINT search_dr( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
939{
941 LPCWSTR parentName;
943 WCHAR expanded[MAX_PATH];
944 MSIRECORD *row;
945 int depth;
946 DWORD sz, attr;
947 UINT rc;
948
949 TRACE("%s\n", debugstr_w(sig->Name));
950
951 *appValue = NULL;
952
953 row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `DrLocator` WHERE `Signature_` = '%s'", sig->Name );
954 if (!row)
955 {
956 TRACE("failed to query DrLocator for %s\n", debugstr_w(sig->Name));
957 return ERROR_SUCCESS;
958 }
959
960 /* check whether parent is set */
961 parentName = MSI_RecordGetString(row, 2);
962 if (parentName)
963 {
964 MSISIGNATURE parentSig;
965
966 search_sig_name( package, parentName, &parentSig, &parent );
967 free_signature( &parentSig );
968 if (!parent)
969 {
970 msiobj_release(&row->hdr);
971 return ERROR_SUCCESS;
972 }
973 }
974
975 sz = MAX_PATH;
976 MSI_RecordGetStringW(row, 3, path, &sz);
977
978 if (MSI_RecordIsNull(row,4))
979 depth = 0;
980 else
982
983 if (sz)
984 expand_any_path( package, path, expanded, MAX_PATH );
985 else
986 lstrcpyW(expanded, path);
987
988 if (parent)
989 {
990 attr = msi_get_file_attributes( package, parent );
993 {
996 }
997
999 lstrcatW(path, expanded);
1000 }
1001 else if (sz) lstrcpyW(path, expanded);
1002
1004
1005 rc = search_directory( package, sig, path, depth, appValue );
1006
1008 msiobj_release(&row->hdr);
1009 TRACE("returning %d\n", rc);
1010 return rc;
1011}
1012
1013static UINT search_sig_name( MSIPACKAGE *package, const WCHAR *sigName, MSISIGNATURE *sig, WCHAR **appValue )
1014{
1015 UINT rc;
1016
1017 *appValue = NULL;
1018 rc = get_signature( package, sig, sigName );
1019 if (rc == ERROR_SUCCESS)
1020 {
1021 rc = search_components( package, appValue, sig );
1022 if (rc == ERROR_SUCCESS && !*appValue)
1023 {
1024 rc = search_reg( package, appValue, sig );
1025 if (rc == ERROR_SUCCESS && !*appValue)
1026 {
1027 rc = search_ini( package, appValue, sig );
1028 if (rc == ERROR_SUCCESS && !*appValue)
1029 rc = search_dr( package, appValue, sig );
1030 }
1031 }
1032 }
1033 return rc;
1034}
1035
1037{
1038 MSIPACKAGE *package = param;
1039 LPCWSTR propName, sigName;
1040 LPWSTR value = NULL;
1041 MSISIGNATURE sig;
1042 MSIRECORD *uirow;
1043 UINT r;
1044
1045 /* get property and signature */
1046 propName = MSI_RecordGetString(row, 1);
1047 sigName = MSI_RecordGetString(row, 2);
1048
1049 TRACE("%s %s\n", debugstr_w(propName), debugstr_w(sigName));
1050
1051 r = search_sig_name( package, sigName, &sig, &value );
1052 if (value)
1053 {
1054 r = msi_set_property( package->db, propName, value, -1 );
1055 if (r == ERROR_SUCCESS && !wcscmp( propName, L"SourceDir" ))
1056 msi_reset_source_folders( package );
1057
1058 msi_free(value);
1059 }
1060 free_signature( &sig );
1061
1062 uirow = MSI_CreateRecord( 2 );
1063 MSI_RecordSetStringW( uirow, 1, propName );
1064 MSI_RecordSetStringW( uirow, 2, sigName );
1066 msiobj_release( &uirow->hdr );
1067
1068 return r;
1069}
1070
1072{
1073 MSIQUERY *view;
1074 UINT r;
1075
1076 if (msi_action_is_unique(package, L"AppSearch"))
1077 {
1078 TRACE("Skipping AppSearch action: already done in UI sequence\n");
1079 return ERROR_SUCCESS;
1080 }
1081 else
1082 msi_register_unique_action(package, L"AppSearch");
1083
1084 r = MSI_OpenQuery( package->db, &view, L"SELECT * FROM `AppSearch`" );
1085 if (r != ERROR_SUCCESS)
1086 return ERROR_SUCCESS;
1087
1089 msiobj_release( &view->hdr );
1090 return r;
1091}
1092
1094{
1095 MSIPACKAGE *package = param;
1096 LPCWSTR signature;
1097 LPWSTR value = NULL;
1098 MSISIGNATURE sig;
1100
1101 signature = MSI_RecordGetString(row, 1);
1102
1103 TRACE("%s\n", debugstr_w(signature));
1104
1105 search_sig_name( package, signature, &sig, &value );
1106 if (value)
1107 {
1108 TRACE("Found signature %s\n", debugstr_w(signature));
1109 msi_set_property( package->db, L"CCP_Success", L"1", -1 );
1110 msi_free(value);
1112 }
1113
1114 free_signature(&sig);
1115 return r;
1116}
1117
1119{
1120 MSIQUERY *view;
1121 UINT r;
1122
1123 if (msi_action_is_unique(package, L"CCPSearch"))
1124 {
1125 TRACE("Skipping AppSearch action: already done in UI sequence\n");
1126 return ERROR_SUCCESS;
1127 }
1128 else
1129 msi_register_unique_action(package, L"CCPSearch");
1130
1131 r = MSI_OpenQuery(package->db, &view, L"SELECT * FROM `CCPSearch`");
1132 if (r != ERROR_SUCCESS)
1133 return ERROR_SUCCESS;
1134
1136 msiobj_release(&view->hdr);
1137 return r;
1138}
unsigned int dir
Definition: maze.c:112
static BOOL match_languages(const void *version, const WCHAR *languages)
Definition: appsearch.c:619
static UINT ITERATE_AppSearch(MSIRECORD *row, LPVOID param)
Definition: appsearch.c:1036
static UINT search_sig_name(MSIPACKAGE *, const WCHAR *, MSISIGNATURE *, WCHAR **)
Definition: appsearch.c:1013
static LANGID * parse_languages(const WCHAR *languages, DWORD *num_ids)
Definition: appsearch.c:590
UINT ACTION_AppSearch(MSIPACKAGE *package)
Definition: appsearch.c:1071
static void free_signature(MSISIGNATURE *sig)
Definition: appsearch.c:151
static UINT check_directory(MSIPACKAGE *package, const WCHAR *dir, WCHAR **appValue)
Definition: appsearch.c:847
static UINT search_components(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:223
static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param)
Definition: appsearch.c:1093
UINT ACTION_CCPSearch(MSIPACKAGE *package)
Definition: appsearch.c:1118
static UINT search_reg(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:346
static UINT search_dr(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:938
static BOOL is_full_path(const WCHAR *path)
Definition: appsearch.c:860
static UINT recurse_search_directory(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig, const WCHAR *dir, int depth)
Definition: appsearch.c:760
void msi_parse_version_string(LPCWSTR verStr, PDWORD ms, PDWORD ls)
Definition: appsearch.c:52
static UINT file_matches_sig(MSIPACKAGE *package, const MSISIGNATURE *sig, const WIN32_FIND_DATAW *findData, const WCHAR *fullFilePath, BOOL *matches)
Definition: appsearch.c:715
struct tagMSISIGNATURE MSISIGNATURE
static UINT search_ini(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:497
static WCHAR * search_file(MSIPACKAGE *package, WCHAR *path, MSISIGNATURE *sig)
Definition: appsearch.c:157
static void expand_any_path(MSIPACKAGE *package, WCHAR *src, WCHAR *dst, size_t len)
Definition: appsearch.c:560
static UINT get_signature(MSIPACKAGE *package, MSISIGNATURE *sig, const WCHAR *name)
Definition: appsearch.c:83
static UINT search_directory(MSIPACKAGE *, MSISIGNATURE *, const WCHAR *, int, WCHAR **)
Definition: appsearch.c:874
static UINT file_version_matches(MSIPACKAGE *package, const MSISIGNATURE *sig, const WCHAR *filePath, BOOL *matches)
Definition: appsearch.c:655
static LPWSTR get_ini_field(LPWSTR buf, int field)
Definition: appsearch.c:471
static void convert_reg_value(DWORD regType, const BYTE *value, DWORD sz, WCHAR **appValue)
Definition: appsearch.c:297
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
void ls(int argc, const char *argv[])
Definition: cmds.c:1136
#define ARRAY_SIZE(a)
Definition: main.h:24
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define RegCloseKey(hKey)
Definition: registry.h:47
struct _root root
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static void free_signature(struct d3dcompiler_shader_signature *sig)
Definition: reflection.c:230
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3356
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4121
#define wcschr
Definition: compat.h:17
#define wcsrchr
Definition: compat.h:16
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define MAX_PATH
Definition: compat.h:34
#define lstrcpyW
Definition: compat.h:749
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI DosDateTimeToFileTime(IN WORD wFatDate, IN WORD wFatTime, OUT LPFILETIME lpFileTime)
Definition: time.c:75
INT WINAPI GetPrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len, LPCWSTR filename)
Definition: profile.c:1142
UINT msi_register_unique_action(MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:113
BOOL msi_action_is_unique(const MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:131
DWORD msi_get_file_version_info(MSIPACKAGE *package, const WCHAR *path, DWORD buflen, BYTE *buffer)
Definition: files.c:151
HANDLE msi_find_first_file(MSIPACKAGE *package, const WCHAR *filename, WIN32_FIND_DATAW *data)
Definition: files.c:115
DWORD msi_get_file_attributes(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:106
BOOL msi_find_next_file(MSIPACKAGE *package, HANDLE handle, WIN32_FIND_DATAW *data)
Definition: files.c:124
DWORD deformat_string(MSIPACKAGE *package, const WCHAR *fmt, WCHAR **data)
Definition: format.c:1016
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf, LPDWORD pcchBuf)
Definition: msi.c:2438
LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:294
BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
Definition: path.c:629
BOOL WINAPI PathAppendW(LPWSTR lpszPath, LPCWSTR lpszAppend)
Definition: path.c:126
BOOL WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:1049
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
#define swprintf
Definition: precomp.h:40
r parent
Definition: btrfs.c:3010
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLenum src
Definition: glext.h:6340
GLuint * ids
Definition: glext.h:5907
GLuint buffer
Definition: glext.h:5915
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define debugstr_w
Definition: kernel32.h:32
#define REG_SZ
Definition: layer.c:22
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
const GUID * guid
__u16 time
Definition: mkdosfs.c:8
#define matches(FN)
Definition: match.h:70
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PVOID ptr
Definition: dispmode.c:27
@ INSTALLMESSAGE_ACTIONDATA
Definition: msi.h:103
@ msidbLocatorType64bit
Definition: msidefs.h:190
@ msidbLocatorTypeRawValue
Definition: msidefs.h:189
@ msidbLocatorTypeDirectory
Definition: msidefs.h:187
@ msidbLocatorTypeFileName
Definition: msidefs.h:188
@ msidbRegistryRootClassesRoot
Definition: msidefs.h:179
@ msidbRegistryRootUsers
Definition: msidefs.h:182
@ msidbRegistryRootLocalMachine
Definition: msidefs.h:181
@ msidbRegistryRootCurrentUser
Definition: msidefs.h:180
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1154
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN
Definition: record.c:1002
UINT msi_set_property(MSIDATABASE *, const WCHAR *, const WCHAR *, int) DECLSPEC_HIDDEN
Definition: package.c:2100
MSIRECORD *WINAPIV MSI_QueryGetRecord(MSIDATABASE *db, LPCWSTR query,...) DECLSPEC_HIDDEN
Definition: msiquery.c:201
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID) DECLSPEC_HIDDEN
Definition: msiquery.c:163
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
static void msi_free(void *mem)
Definition: msipriv.h:1159
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
void msi_reset_source_folders(MSIPACKAGE *package) DECLSPEC_HIDDEN
Definition: package.c:2089
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:433
INT MSI_ProcessMessage(MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD *) DECLSPEC_HIDDEN
Definition: package.c:1914
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:321
UINT WINAPIV MSI_OpenQuery(MSIDATABASE *, MSIQUERY **, LPCWSTR,...) DECLSPEC_HIDDEN
Definition: msiquery.c:138
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
#define MSI_NULL_INTEGER
Definition: msiquery.h:32
unsigned int UINT
Definition: ndis.h:50
#define REG_BINARY
Definition: nt_native.h:1496
#define KEY_READ
Definition: nt_native.h:1023
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define L(x)
Definition: ntvdm.h:50
#define LOWORD(l)
Definition: pedump.c:82
DWORD * PDWORD
Definition: pedump.c:68
unsigned short USHORT
Definition: pedump.c:61
const WCHAR * str
#define REG_DWORD
Definition: sdbapi.c:596
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
Definition: cookie.c:202
Definition: parser.c:44
Definition: copy.c:22
Definition: name.c:39
Definition: parser.c:56
MSIDATABASE * db
Definition: msipriv.h:394
MSIOBJECTHDR hdr
Definition: msipriv.h:151
LPCWSTR Name
Definition: appsearch.c:39
FILETIME MinTime
Definition: appsearch.c:47
FILETIME MaxTime
Definition: appsearch.c:48
DWORD MaxVersionMS
Definition: appsearch.c:43
DWORD MinVersionMS
Definition: appsearch.c:41
DWORD MinVersionLS
Definition: appsearch.c:42
LPWSTR Languages
Definition: appsearch.c:49
DWORD MaxVersionLS
Definition: appsearch.c:44
#define max(a, b)
Definition: svc.c:63
#define towupper(c)
Definition: wctype.h:99
WORD LANGID
Definition: typedefs.h:81
unsigned char * LPBYTE
Definition: typedefs.h:53
#define HIWORD(l)
Definition: typedefs.h:247
Definition: pdh_main.c:94
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
static const WCHAR lang[]
Definition: wbemdisp.c:287
int ret
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetLogicalDrives(void)
Definition: disk.c:110
#define DRIVE_FIXED
Definition: winbase.h:252
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define HKEY_USERS
Definition: winreg.h:13
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193