mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-02 05:15:01 +00:00
wbemprox: Optimize a common Win32_Directory query.
This commit is contained in:
parent
a6dc4906de
commit
8e1aa4358a
1 changed files with 139 additions and 37 deletions
|
@ -839,37 +839,6 @@ static enum fill_status fill_compsys( struct table *table, const struct expr *co
|
|||
return status;
|
||||
}
|
||||
|
||||
static WCHAR *get_filesystem( const WCHAR *root )
|
||||
{
|
||||
static const WCHAR ntfsW[] = {'N','T','F','S',0};
|
||||
WCHAR buffer[MAX_PATH + 1];
|
||||
|
||||
if (GetVolumeInformationW( root, NULL, 0, NULL, NULL, NULL, buffer, MAX_PATH + 1 ))
|
||||
return heap_strdupW( buffer );
|
||||
return heap_strdupW( ntfsW );
|
||||
}
|
||||
|
||||
static UINT64 get_freespace( const WCHAR *dir, UINT64 *disksize )
|
||||
{
|
||||
WCHAR root[] = {'\\','\\','.','\\','A',':',0};
|
||||
ULARGE_INTEGER free;
|
||||
DISK_GEOMETRY_EX info;
|
||||
HANDLE handle;
|
||||
|
||||
free.QuadPart = 512 * 1024 * 1024;
|
||||
GetDiskFreeSpaceExW( dir, NULL, NULL, &free );
|
||||
|
||||
root[4] = dir[0];
|
||||
handle = CreateFileW( root, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (DeviceIoControl( handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &info, sizeof(info), NULL, NULL ))
|
||||
*disksize = info.DiskSize.QuadPart;
|
||||
CloseHandle( handle );
|
||||
}
|
||||
return free.QuadPart;
|
||||
}
|
||||
|
||||
struct dirstack
|
||||
{
|
||||
WCHAR **dirs;
|
||||
|
@ -899,10 +868,16 @@ static struct dirstack *alloc_dirstack( UINT size )
|
|||
return dirstack;
|
||||
}
|
||||
|
||||
static void free_dirstack( struct dirstack *dirstack )
|
||||
static void clear_dirstack( struct dirstack *dirstack )
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < dirstack->num_dirs; i++) heap_free( dirstack->dirs[i] );
|
||||
dirstack->num_dirs = 0;
|
||||
}
|
||||
|
||||
static void free_dirstack( struct dirstack *dirstack )
|
||||
{
|
||||
clear_dirstack( dirstack );
|
||||
heap_free( dirstack->dirs );
|
||||
heap_free( dirstack->len_dirs );
|
||||
heap_free( dirstack );
|
||||
|
@ -912,6 +887,8 @@ static BOOL push_dir( struct dirstack *dirstack, WCHAR *dir, UINT len )
|
|||
{
|
||||
UINT size, i = dirstack->num_dirs;
|
||||
|
||||
if (!dir) return FALSE;
|
||||
|
||||
if (i == dirstack->num_allocated)
|
||||
{
|
||||
WCHAR **tmp;
|
||||
|
@ -957,7 +934,7 @@ static WCHAR *build_glob( WCHAR drive, const WCHAR *path, UINT len )
|
|||
ret[i++] = drive;
|
||||
ret[i++] = ':';
|
||||
ret[i++] = '\\';
|
||||
if (path)
|
||||
if (path && len)
|
||||
{
|
||||
memcpy( ret + i, path, len * sizeof(WCHAR) );
|
||||
i += len;
|
||||
|
@ -968,7 +945,7 @@ static WCHAR *build_glob( WCHAR drive, const WCHAR *path, UINT len )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static WCHAR *build_dirname( WCHAR drive, const WCHAR *path )
|
||||
static WCHAR *build_name( WCHAR drive, const WCHAR *path )
|
||||
{
|
||||
UINT i = 0, len = 0;
|
||||
const WCHAR *p;
|
||||
|
@ -997,6 +974,90 @@ static WCHAR *build_dirname( WCHAR drive, const WCHAR *path )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static WCHAR *build_dirname( const WCHAR *path, UINT *ret_len )
|
||||
{
|
||||
const WCHAR *p = path, *start;
|
||||
UINT len, i;
|
||||
WCHAR *ret;
|
||||
|
||||
if (!isalphaW( p[0] ) || p[1] != ':' || p[2] != '\\' || p[3] != '\\' || !p[4]) return NULL;
|
||||
start = path + 4;
|
||||
len = strlenW( start );
|
||||
p = start + len - 1;
|
||||
if (*p == '\\') return NULL;
|
||||
|
||||
while (p >= start && *p != '\\') { len--; p--; };
|
||||
while (p >= start && *p == '\\') { len--; p--; };
|
||||
|
||||
if (!(ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
|
||||
for (i = 0, p = start; p < start + len; p++)
|
||||
{
|
||||
if (p[0] == '\\' && p[1] == '\\')
|
||||
{
|
||||
ret[i++] = '\\';
|
||||
p++;
|
||||
}
|
||||
else ret[i++] = *p;
|
||||
}
|
||||
ret[i] = 0;
|
||||
*ret_len = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL seen_dir( struct dirstack *dirstack, const WCHAR *path )
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < dirstack->num_dirs; i++) if (!strcmpW( dirstack->dirs[i], path )) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* optimize queries of the form WHERE Name='...' [OR Name='...']* */
|
||||
static UINT seed_dirs( struct dirstack *dirstack, const struct expr *cond, WCHAR root, UINT *count )
|
||||
{
|
||||
const struct expr *left = cond->u.expr.left, *right = cond->u.expr.right;
|
||||
|
||||
if (cond->type != EXPR_COMPLEX) return *count = 0;
|
||||
if (cond->u.expr.op == OP_EQ)
|
||||
{
|
||||
UINT len;
|
||||
WCHAR *path;
|
||||
const WCHAR *str = NULL;
|
||||
|
||||
if (left->type == EXPR_PROPVAL && right->type == EXPR_SVAL &&
|
||||
!strcmpW( left->u.propval->name, prop_nameW ) &&
|
||||
toupperW( right->u.sval[0] ) == toupperW( root ))
|
||||
{
|
||||
str = right->u.sval;
|
||||
}
|
||||
else if (left->type == EXPR_SVAL && right->type == EXPR_PROPVAL &&
|
||||
!strcmpW( right->u.propval->name, prop_nameW ) &&
|
||||
toupperW( left->u.sval[0] ) == toupperW( root ))
|
||||
{
|
||||
str = left->u.sval;
|
||||
}
|
||||
if (str && (path = build_dirname( str, &len )))
|
||||
{
|
||||
if (seen_dir( dirstack, path ))
|
||||
{
|
||||
heap_free( path );
|
||||
return ++*count;
|
||||
}
|
||||
else if (push_dir( dirstack, path, len )) return ++*count;
|
||||
heap_free( path );
|
||||
return *count = 0;
|
||||
}
|
||||
}
|
||||
else if (cond->u.expr.op == OP_OR)
|
||||
{
|
||||
UINT left_count = 0, right_count = 0;
|
||||
|
||||
if (!(seed_dirs( dirstack, left, root, &left_count ))) return *count = 0;
|
||||
if (!(seed_dirs( dirstack, right, root, &right_count ))) return *count = 0;
|
||||
return *count += left_count + right_count;
|
||||
}
|
||||
return *count = 0;
|
||||
}
|
||||
|
||||
static WCHAR *append_path( const WCHAR *path, const WCHAR *segment, UINT *len )
|
||||
{
|
||||
UINT len_path = 0, len_segment = strlenW( segment );
|
||||
|
@ -1005,7 +1066,7 @@ static WCHAR *append_path( const WCHAR *path, const WCHAR *segment, UINT *len )
|
|||
*len = 0;
|
||||
if (path) len_path = strlenW( path );
|
||||
if (!(ret = heap_alloc( (len_path + len_segment + 2) * sizeof(WCHAR) ))) return NULL;
|
||||
if (path)
|
||||
if (path && len_path)
|
||||
{
|
||||
memcpy( ret, path, len_path * sizeof(WCHAR) );
|
||||
ret[len_path] = '\\';
|
||||
|
@ -1021,7 +1082,7 @@ static enum fill_status fill_directory( struct table *table, const struct expr *
|
|||
{
|
||||
static const WCHAR dotW[] = {'.',0}, dotdotW[] = {'.','.',0};
|
||||
struct record_directory *rec;
|
||||
UINT i, len, row = 0, offset = 0, count = 4;
|
||||
UINT i, len, row = 0, offset = 0, count = 4, num_expected_rows;
|
||||
WCHAR *glob = NULL, *path = NULL, *new_path, root[] = {'A',':','\\',0};
|
||||
DWORD drives = GetLogicalDrives();
|
||||
WIN32_FIND_DATAW data;
|
||||
|
@ -1038,6 +1099,9 @@ static enum fill_status fill_directory( struct table *table, const struct expr *
|
|||
root[0] = 'A' + i;
|
||||
if (GetDriveTypeW( root ) != DRIVE_FIXED) continue;
|
||||
|
||||
num_expected_rows = 0;
|
||||
if (!seed_dirs( dirstack, cond, root[0], &num_expected_rows )) clear_dirstack( dirstack );
|
||||
|
||||
for (;;)
|
||||
{
|
||||
path = pop_dir( dirstack, &len );
|
||||
|
@ -1074,12 +1138,19 @@ static enum fill_status fill_directory( struct table *table, const struct expr *
|
|||
}
|
||||
rec = (struct record_directory *)(table->data + offset);
|
||||
rec->accessmask = FILE_ALL_ACCESS;
|
||||
rec->name = build_dirname( root[0], new_path );
|
||||
rec->name = build_name( root[0], new_path );
|
||||
if (!match_row( table, row, cond, &status ))
|
||||
{
|
||||
free_row_values( table, row );
|
||||
continue;
|
||||
}
|
||||
else if (num_expected_rows && row == num_expected_rows - 1)
|
||||
{
|
||||
row++;
|
||||
FindClose( handle );
|
||||
status = FILL_STATUS_FILTERED;
|
||||
goto done;
|
||||
}
|
||||
offset += sizeof(*rec);
|
||||
row++;
|
||||
}
|
||||
|
@ -1102,6 +1173,37 @@ done:
|
|||
return status;
|
||||
}
|
||||
|
||||
static WCHAR *get_filesystem( const WCHAR *root )
|
||||
{
|
||||
static const WCHAR ntfsW[] = {'N','T','F','S',0};
|
||||
WCHAR buffer[MAX_PATH + 1];
|
||||
|
||||
if (GetVolumeInformationW( root, NULL, 0, NULL, NULL, NULL, buffer, MAX_PATH + 1 ))
|
||||
return heap_strdupW( buffer );
|
||||
return heap_strdupW( ntfsW );
|
||||
}
|
||||
|
||||
static UINT64 get_freespace( const WCHAR *dir, UINT64 *disksize )
|
||||
{
|
||||
WCHAR root[] = {'\\','\\','.','\\','A',':',0};
|
||||
ULARGE_INTEGER free;
|
||||
DISK_GEOMETRY_EX info;
|
||||
HANDLE handle;
|
||||
|
||||
free.QuadPart = 512 * 1024 * 1024;
|
||||
GetDiskFreeSpaceExW( dir, NULL, NULL, &free );
|
||||
|
||||
root[4] = dir[0];
|
||||
handle = CreateFileW( root, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (DeviceIoControl( handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &info, sizeof(info), NULL, NULL ))
|
||||
*disksize = info.DiskSize.QuadPart;
|
||||
CloseHandle( handle );
|
||||
}
|
||||
return free.QuadPart;
|
||||
}
|
||||
|
||||
static enum fill_status fill_diskpartition( struct table *table, const struct expr *cond )
|
||||
{
|
||||
static const WCHAR fmtW[] =
|
||||
|
|
Loading…
Reference in a new issue