/* Expands the value in src into a path without property names and only * containing long path names into dst. Replaces at most len characters of dst, * and always NULL-terminates dst if dst is not NULL and len >= 1. * May modify src. * Assumes src and dst are non-overlapping. * FIXME: return code probably needed: * - what does AppSearch return if the table values are invalid? * - what if dst is too small? */ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst, size_t len) { WCHAR *ptr, *deformatted; if (!src || !dst || !len) { if (dst) *dst = '\0'; return; } dst[0] = '\0'; /* Ignore the short portion of the path */ if ((ptr = strchrW(src, '|'))) ptr++; else ptr = src; deformat_string(package, ptr, &deformatted); if (!deformatted || strlenW(deformatted) > len - 1) { msi_free(deformatted); return; } lstrcpyW(dst, deformatted); dst[lstrlenW(deformatted)] = '\0'; msi_free(deformatted); }
static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATURE *sig) { static const WCHAR query[] = { 's','e','l','e','c','t',' ','*',' ', 'f','r','o','m',' ', 'R','e','g','L','o','c','a','t','o','r',' ', 'w','h','e','r','e',' ', 'S','i','g','n','a','t','u','r','e','_',' ','=',' ', '\'','%','s','\'',0}; LPWSTR keyPath = NULL, valueName = NULL; LPWSTR deformatted = NULL; LPWSTR ptr = NULL, end; int root, type; HKEY rootKey, key = NULL; DWORD sz = 0, regType; LPBYTE value = NULL; MSIRECORD *row; UINT rc; TRACE("%s\n", debugstr_w(sig->Name)); *appValue = NULL; row = MSI_QueryGetRecord( package->db, query, sig->Name ); if (!row) { TRACE("failed to query RegLocator for %s\n", debugstr_w(sig->Name)); return ERROR_SUCCESS; } root = MSI_RecordGetInteger(row,2); keyPath = msi_dup_record_field(row,3); valueName = msi_dup_record_field(row,4); type = MSI_RecordGetInteger(row,5); deformat_string(package, keyPath, &deformatted); switch (root) { case msidbRegistryRootClassesRoot: rootKey = HKEY_CLASSES_ROOT; break; case msidbRegistryRootCurrentUser: rootKey = HKEY_CURRENT_USER; break; case msidbRegistryRootLocalMachine: rootKey = HKEY_LOCAL_MACHINE; break; case msidbRegistryRootUsers: rootKey = HKEY_USERS; break; default: WARN("Unknown root key %d\n", root); goto end; } rc = RegOpenKeyW(rootKey, deformatted, &key); if (rc) { TRACE("RegOpenKeyW returned %d\n", rc); goto end; } rc = RegQueryValueExW(key, valueName, NULL, NULL, NULL, &sz); if (rc) { TRACE("RegQueryValueExW returned %d\n", rc); goto end; } /* FIXME: sanity-check sz before allocating (is there an upper-limit * on the value of a property?) */ value = msi_alloc( sz ); rc = RegQueryValueExW(key, valueName, NULL, ®Type, value, &sz); if (rc) { TRACE("RegQueryValueExW returned %d\n", rc); goto end; } /* bail out if the registry key is empty */ if (sz == 0) goto end; if ((regType == REG_SZ || regType == REG_EXPAND_SZ) && (ptr = strchrW((LPWSTR)value, '"')) && (end = strchrW(++ptr, '"'))) *end = '\0'; else ptr = (LPWSTR)value; switch (type & 0x0f) { case msidbLocatorTypeDirectory: rc = ACTION_SearchDirectory(package, sig, ptr, 0, appValue); break; case msidbLocatorTypeFileName: *appValue = app_search_file(ptr, sig); break; case msidbLocatorTypeRawValue: ACTION_ConvertRegValue(regType, value, sz, appValue); break; default: FIXME("unimplemented for type %d (key path %s, value %s)\n", type, debugstr_w(keyPath), debugstr_w(valueName)); } end: msi_free( value ); RegCloseKey( key ); msi_free( keyPath ); msi_free( valueName ); msi_free( deformatted ); msiobj_release(&row->hdr); return ERROR_SUCCESS; }
static UINT search_reg( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig ) { static const WCHAR query[] = { 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 'R','e','g','L','o','c','a','t','o','r',' ','W','H','E','R','E',' ', 'S','i','g','n','a','t','u','r','e','_',' ','=',' ', '\'','%','s','\'',0}; const WCHAR *keyPath, *valueName; WCHAR *deformatted = NULL, *ptr = NULL, *end; int root, type; REGSAM access = KEY_READ; HKEY rootKey, key = NULL; DWORD sz = 0, regType; LPBYTE value = NULL; MSIRECORD *row; UINT rc; TRACE("%s\n", debugstr_w(sig->Name)); *appValue = NULL; row = MSI_QueryGetRecord( package->db, query, sig->Name ); if (!row) { TRACE("failed to query RegLocator for %s\n", debugstr_w(sig->Name)); return ERROR_SUCCESS; } root = MSI_RecordGetInteger(row, 2); keyPath = MSI_RecordGetString(row, 3); valueName = MSI_RecordGetString(row, 4); type = MSI_RecordGetInteger(row, 5); deformat_string(package, keyPath, &deformatted); switch (root) { case msidbRegistryRootClassesRoot: rootKey = HKEY_CLASSES_ROOT; break; case msidbRegistryRootCurrentUser: rootKey = HKEY_CURRENT_USER; break; case msidbRegistryRootLocalMachine: rootKey = HKEY_LOCAL_MACHINE; if (type & msidbLocatorType64bit) access |= KEY_WOW64_64KEY; else access |= KEY_WOW64_32KEY; break; case msidbRegistryRootUsers: rootKey = HKEY_USERS; break; default: WARN("Unknown root key %d\n", root); goto end; } rc = RegOpenKeyExW( rootKey, deformatted, 0, access, &key ); if (rc) { TRACE("RegOpenKeyExW returned %d\n", rc); goto end; } msi_free(deformatted); deformat_string(package, valueName, &deformatted); rc = RegQueryValueExW(key, deformatted, NULL, NULL, NULL, &sz); if (rc) { TRACE("RegQueryValueExW returned %d\n", rc); goto end; } /* FIXME: sanity-check sz before allocating (is there an upper-limit * on the value of a property?) */ value = msi_alloc( sz ); rc = RegQueryValueExW(key, deformatted, NULL, ®Type, value, &sz); if (rc) { TRACE("RegQueryValueExW returned %d\n", rc); goto end; } /* bail out if the registry key is empty */ if (sz == 0) goto end; /* expand if needed */ if (regType == REG_EXPAND_SZ) { sz = ExpandEnvironmentStringsW((LPCWSTR)value, NULL, 0); if (sz) { LPWSTR buf = msi_alloc(sz * sizeof(WCHAR)); ExpandEnvironmentStringsW((LPCWSTR)value, buf, sz); msi_free(value); value = (LPBYTE)buf; } } if ((regType == REG_SZ || regType == REG_EXPAND_SZ) && (ptr = strchrW((LPWSTR)value, '"')) && (end = strchrW(++ptr, '"'))) *end = '\0'; else ptr = (LPWSTR)value; switch (type & 0x0f) { case msidbLocatorTypeDirectory: search_directory( package, sig, ptr, 0, appValue ); break; case msidbLocatorTypeFileName: *appValue = search_file( package, ptr, sig ); break; case msidbLocatorTypeRawValue: convert_reg_value( regType, value, sz, appValue ); break; default: FIXME("unimplemented for type %d (key path %s, value %s)\n", type, debugstr_w(keyPath), debugstr_w(valueName)); } end: msi_free( value ); RegCloseKey( key ); msi_free( deformatted ); msiobj_release(&row->hdr); return ERROR_SUCCESS; }