ReactOS  0.4.15-dev-4914-g2220e56
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 
37 typedef 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  */
83 static UINT get_signature( MSIPACKAGE *package, MSISIGNATURE *sig, const WCHAR *name )
84 {
85  WCHAR *minVersion, *maxVersion, *p;
86  MSIRECORD *row;
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  }
120  sig->MinSize = MSI_RecordGetInteger(row,5);
121  if (sig->MinSize == MSI_NULL_INTEGER)
122  sig->MinSize = 0;
123  sig->MaxSize = MSI_RecordGetInteger(row,6);
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",
135  debugstr_w(sig->File), debugstr_w(name));
136  TRACE("MinVersion is %d.%d.%d.%d\n", HIWORD(sig->MinVersionMS),
137  LOWORD(sig->MinVersionMS), HIWORD(sig->MinVersionLS),
138  LOWORD(sig->MinVersionLS));
139  TRACE("MaxVersion is %d.%d.%d.%d\n", HIWORD(sig->MaxVersionMS),
140  LOWORD(sig->MaxVersionMS), HIWORD(sig->MaxVersionLS),
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 */
151 static void free_signature( MSISIGNATURE *sig )
152 {
153  msi_free(sig->File);
154  msi_free(sig->Languages);
155 }
156 
157 static WCHAR *search_file( MSIPACKAGE *package, WCHAR *path, MSISIGNATURE *sig )
158 {
160  DWORD attr;
161  UINT size;
162  LPWSTR val = NULL;
163  LPBYTE buffer;
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 
185  buffer = msi_alloc(size);
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 
218 done:
219  msi_free(buffer);
220  return val;
221 }
222 
223 static 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;
231  DWORD size = MAX_PATH;
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 
291 done:
292  if (rec) msiobj_release(&rec->hdr);
293  msiobj_release(&row->hdr);
294  return ERROR_SUCCESS;
295 }
296 
297 static 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 
344 static UINT search_directory( MSIPACKAGE *, MSISIGNATURE *, const WCHAR *, int, WCHAR ** );
345 
346 static 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));
436  msi_free(value);
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  }
462 end:
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 
497 static UINT search_ini( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
498 {
499  MSIRECORD *row;
500  LPWSTR fileName, section, key;
501  int field, type;
502  WCHAR buf[MAX_PATH];
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);
543  msi_free(section);
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  */
560 static 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 
590 static 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 
619 static 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 
645 done:
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  */
655 static 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  */
715 static 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  */
724  if (sig->MinTime.dwLowDateTime || sig->MinTime.dwHighDateTime)
725  {
726  if (findData->ftCreationTime.dwHighDateTime <
727  sig->MinTime.dwHighDateTime ||
728  (findData->ftCreationTime.dwHighDateTime == sig->MinTime.dwHighDateTime
729  && findData->ftCreationTime.dwLowDateTime <
730  sig->MinTime.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 >
739  sig->MaxTime.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  */
760 static 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  {
795  BOOL matches;
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 
847 static UINT check_directory( MSIPACKAGE *package, const WCHAR *dir, WCHAR **appValue )
848 {
849  DWORD attr = msi_get_file_attributes( package, dir );
850 
852  {
853  TRACE("directory exists, returning %s\n", debugstr_w(dir));
854  *appValue = strdupW(dir);
855  }
856 
857  return ERROR_SUCCESS;
858 }
859 
860 static 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 
874 static 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)
925  rc = ERROR_OUTOFMEMORY;
926  else
928  }
929 
930  *appValue = val;
931 
932  TRACE("returning %d\n", rc);
933  return rc;
934 }
935 
936 static UINT search_sig_name( MSIPACKAGE *, const WCHAR *, MSISIGNATURE *, WCHAR ** );
937 
938 static UINT search_dr( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
939 {
940  LPWSTR parent = NULL;
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 );
991  if (attr != INVALID_FILE_ATTRIBUTES &&
993  {
996  }
997 
998  lstrcpyW(path, parent);
999  lstrcatW(path, expanded);
1000  }
1001  else if (sz) lstrcpyW(path, expanded);
1002 
1004 
1005  rc = search_directory( package, sig, path, depth, appValue );
1006 
1007  msi_free(parent);
1008  msiobj_release(&row->hdr);
1009  TRACE("returning %d\n", rc);
1010  return rc;
1011 }
1012 
1013 static 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;
1099  UINT r = ERROR_SUCCESS;
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 }
#define HKEY_USERS
Definition: winreg.h:13
FILETIME MaxTime
Definition: appsearch.c:48
struct tagMSISIGNATURE MSISIGNATURE
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define max(a, b)
Definition: svc.c:63
BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
Definition: path.c:629
Definition: pdh_main.c:93
INT WINAPI GetPrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len, LPCWSTR filename)
Definition: profile.c:1142
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
#define matches(FN)
Definition: match.h:70
static BOOL is_full_path(const WCHAR *path)
Definition: appsearch.c:860
#define ERROR_SUCCESS
Definition: deptool.c:10
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define REG_BINARY
Definition: nt_native.h:1496
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
static UINT search_components(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:223
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
MSIOBJECTHDR hdr
Definition: msipriv.h:151
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static UINT file_matches_sig(MSIPACKAGE *package, const MSISIGNATURE *sig, const WIN32_FIND_DATAW *findData, const WCHAR *fullFilePath, BOOL *matches)
Definition: appsearch.c:715
#define HKEY_CURRENT_USER
Definition: winreg.h:11
GLuint GLuint GLsizei count
Definition: gl.h:1545
struct _root root
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:112
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
UINT ACTION_AppSearch(MSIPACKAGE *package)
Definition: appsearch.c:1071
LPWSTR Languages
Definition: appsearch.c:49
static UINT check_directory(MSIPACKAGE *package, const WCHAR *dir, WCHAR **appValue)
Definition: appsearch.c:847
BOOL msi_action_is_unique(const MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:131
static UINT search_sig_name(MSIPACKAGE *, const WCHAR *, MSISIGNATURE *, WCHAR **)
Definition: appsearch.c:1013
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
GLuint buffer
Definition: glext.h:5915
#define MSI_NULL_INTEGER
Definition: msiquery.h:32
static void msi_free(void *mem)
Definition: msipriv.h:1159
WORD LANGID
Definition: typedefs.h:81
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
__u16 time
Definition: mkdosfs.c:366
Definition: parser.c:55
static BOOL match_languages(const void *version, const WCHAR *languages)
Definition: appsearch.c:619
#define lstrlenW
Definition: compat.h:609
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1154
static IMAGE_SECTION_HEADER section
Definition: loader.c:152
#define lstrcpynW
Definition: compat.h:597
static void convert_reg_value(DWORD regType, const BYTE *value, DWORD sz, WCHAR **appValue)
Definition: appsearch.c:297
UINT WINAPIV MSI_OpenQuery(MSIDATABASE *, MSIQUERY **, LPCWSTR,...) DECLSPEC_HIDDEN
Definition: msiquery.c:138
BOOL WINAPI PathAppendW(LPWSTR lpszPath, LPCWSTR lpszAppend)
Definition: path.c:126
void ls(int argc, const char *argv[])
Definition: cmds.c:1136
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint * ids
Definition: glext.h:5907
DWORD dwHighDateTime
Definition: mapidefs.h:66
const GUID * guid
#define L(x)
Definition: ntvdm.h:50
static void free_signature(MSISIGNATURE *sig)
Definition: appsearch.c:151
unsigned char * LPBYTE
Definition: typedefs.h:53
#define FALSE
Definition: types.h:117
LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:294
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:321
static struct _test_info info[]
Definition: SetCursorPos.c:19
#define debugstr_w
Definition: kernel32.h:32
INT MSI_ProcessMessage(MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD *) DECLSPEC_HIDDEN
Definition: package.c:1858
#define FIXME(fmt,...)
Definition: debug.h:111
static PVOID ptr
Definition: dispmode.c:27
int codepage
Definition: win_iconv.c:156
const WCHAR * str
WINE_DEFAULT_DEBUG_CHANNEL(msi)
static const WCHAR version[]
Definition: asmname.c:66
DWORD msi_get_file_version_info(MSIPACKAGE *package, const WCHAR *path, DWORD buflen, BYTE *buffer)
Definition: files.c:151
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:433
unsigned int dir
Definition: maze.c:112
void msi_parse_version_string(LPCWSTR verStr, PDWORD ms, PDWORD ls)
Definition: appsearch.c:52
static UINT get_signature(MSIPACKAGE *package, MSISIGNATURE *sig, const WCHAR *name)
Definition: appsearch.c:83
GLuint GLfloat * val
Definition: glext.h:7180
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
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
MSIRECORD *WINAPIV MSI_QueryGetRecord(MSIDATABASE *db, LPCWSTR query,...) DECLSPEC_HIDDEN
Definition: msiquery.c:201
static const WCHAR lang[]
Definition: wbemdisp.c:287
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
DWORD deformat_string(MSIPACKAGE *package, const WCHAR *fmt, WCHAR **data)
Definition: format.c:1016
BOOL msi_find_next_file(MSIPACKAGE *package, HANDLE handle, WIN32_FIND_DATAW *data)
Definition: files.c:124
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf, LPDWORD pcchBuf)
Definition: msi.c:2438
LPCWSTR Name
Definition: appsearch.c:39
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4120
r parent
Definition: btrfs.c:2979
__wchar_t WCHAR
Definition: xmlstorage.h:180
BOOL WINAPI DosDateTimeToFileTime(IN WORD wFatDate, IN WORD wFatTime, OUT LPFILETIME lpFileTime)
Definition: time.c:75
Definition: parser.c:43
UINT ACTION_CCPSearch(MSIPACKAGE *package)
Definition: appsearch.c:1118
GLfloat param
Definition: glext.h:5796
#define MAX_PATH
Definition: compat.h:34
static UINT recurse_search_directory(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig, const WCHAR *dir, int depth)
Definition: appsearch.c:760
unsigned long DWORD
Definition: ntddk_ex.h:95
static UINT search_directory(MSIPACKAGE *, MSISIGNATURE *, const WCHAR *, int, WCHAR **)
Definition: appsearch.c:874
MSIDATABASE * db
Definition: msipriv.h:394
Definition: cookie.c:201
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
static UINT file_version_matches(MSIPACKAGE *package, const MSISIGNATURE *sig, const WCHAR *filePath, BOOL *matches)
Definition: appsearch.c:655
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
GLuint GLuint end
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
int ret
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
__u8 attr
Definition: mkdosfs.c:359
DWORD msi_get_file_attributes(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:106
HKEY key
Definition: reg.c:28
GLenum GLsizei len
Definition: glext.h:6722
GLenum src
Definition: glext.h:6340
#define wcsrchr
Definition: compat.h:16
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
int _cdecl swprintf(const WCHAR *,...)
unsigned char BYTE
Definition: xxhash.c:193
DWORD MinVersionMS
Definition: appsearch.c:41
static UINT search_ini(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:497
#define DRIVE_FIXED
Definition: winbase.h:249
DWORD WINAPI GetLogicalDrives(VOID)
Definition: disk.c:110
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define lstrcpyW
Definition: compat.h:608
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
unsigned short USHORT
Definition: pedump.c:61
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
#define ARRAY_SIZE(a)
Definition: main.h:24
static LANGID * parse_languages(const WCHAR *languages, DWORD *num_ids)
Definition: appsearch.c:590
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN
Definition: record.c:1002
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
GLenum GLenum dst
Definition: glext.h:6340
ACCESS_MASK REGSAM
Definition: winreg.h:69
FILETIME MinTime
Definition: appsearch.c:47
DWORD MaxVersionLS
Definition: appsearch.c:44
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
UINT msi_set_property(MSIDATABASE *, const WCHAR *, const WCHAR *, int) DECLSPEC_HIDDEN
Definition: package.c:2044
DWORD * PDWORD
Definition: pedump.c:68
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
DWORD MinVersionLS
Definition: appsearch.c:42
Definition: name.c:38
static void expand_any_path(MSIPACKAGE *package, WCHAR *src, WCHAR *dst, size_t len)
Definition: appsearch.c:560
static WCHAR * search_file(MSIPACKAGE *package, WCHAR *path, MSISIGNATURE *sig)
Definition: appsearch.c:157
static UINT search_dr(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:938
static LPWSTR get_ini_field(LPWSTR buf, int field)
Definition: appsearch.c:471
static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param)
Definition: appsearch.c:1093
static UINT search_reg(MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig)
Definition: appsearch.c:346
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
#define HIWORD(l)
Definition: typedefs.h:247
GLenum GLuint id
Definition: glext.h:5579
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3356
static IOleDocumentView * view
Definition: activex.c:1749
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define towupper(c)
Definition: wctype.h:99
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID) DECLSPEC_HIDDEN
Definition: msiquery.c:163
#define memset(x, y, z)
Definition: compat.h:39
#define REG_DWORD
Definition: sdbapi.c:596
static UINT ITERATE_AppSearch(MSIRECORD *row, LPVOID param)
Definition: appsearch.c:1036
#define LOWORD(l)
Definition: pedump.c:82
DWORD MaxVersionMS
Definition: appsearch.c:43
#define RegCloseKey(hKey)
Definition: registry.h:47
HANDLE msi_find_first_file(MSIPACKAGE *package, const WCHAR *filename, WIN32_FIND_DATAW *data)
Definition: files.c:115
DWORD dwLowDateTime
Definition: mapidefs.h:65
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
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
Definition: copy.c:22
UINT msi_register_unique_action(MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:113
BOOL WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:1049
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
GLuint const GLchar * name
Definition: glext.h:6031
void msi_reset_source_folders(MSIPACKAGE *package) DECLSPEC_HIDDEN
Definition: package.c:2033