sxs.c 6.72 KB
Newer Older
EA Durbin's avatar
EA Durbin committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * sxs main
 *
 * Copyright 2007 EA Durbin
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdarg.h>
22
#include <stdlib.h>
EA Durbin's avatar
EA Durbin committed
23 24 25 26

#include "windef.h"
#include "winbase.h"

27 28 29
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(sxs);
EA Durbin's avatar
EA Durbin committed
30

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
typedef struct _SXS_GUID_INFORMATION_CLR
{
    DWORD cbSize;
    DWORD dwFlags;
    PCWSTR pcwszRuntimeVersion;
    PCWSTR pcwszTypeName;
    PCWSTR pcwszAssemblyIdentity;
} SXS_GUID_INFORMATION_CLR, *PSXS_GUID_INFORMATION_CLR;

#define SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE 0x1
#define SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS     0x2

#define SXS_LOOKUP_CLR_GUID_USE_ACTCTX     0x00000001
#define SXS_LOOKUP_CLR_GUID_FIND_SURROGATE 0x00010000
#define SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS 0x00020000
46
#define SXS_LOOKUP_CLR_GUID_FIND_ANY       (SXS_LOOKUP_CLR_GUID_FIND_SURROGATE | SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS)
47 48 49 50

struct comclassredirect_data
{
    ULONG size;
51
    ULONG flags;
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
    DWORD model;
    GUID  clsid;
    GUID  alias;
    GUID  clsid2;
    GUID  tlbid;
    ULONG name_len;
    ULONG name_offset;
    ULONG progid_len;
    ULONG progid_offset;
    ULONG clrdata_len;
    ULONG clrdata_offset;
    DWORD miscstatus;
    DWORD miscstatuscontent;
    DWORD miscstatusthumbnail;
    DWORD miscstatusicon;
    DWORD miscstatusdocprint;
};

struct clrclass_data
{
    ULONG size;
    DWORD res[2];
    ULONG module_len;
    ULONG module_offset;
    ULONG name_len;
    ULONG name_offset;
    ULONG version_len;
    ULONG version_offset;
    DWORD res2[2];
};

83 84 85 86 87 88 89 90 91 92 93
struct clrsurrogate_data
{
    ULONG size;
    DWORD res;
    GUID  clsid;
    ULONG version_offset;
    ULONG version_len;
    ULONG name_offset;
    ULONG name_len;
};

94 95 96 97
BOOL WINAPI SxsLookupClrGuid(DWORD flags, GUID *clsid, HANDLE actctx, void *buffer, SIZE_T buffer_len,
                             SIZE_T *buffer_len_required)
{
    ACTCTX_SECTION_KEYED_DATA guid_info = { sizeof(ACTCTX_SECTION_KEYED_DATA) };
98
    ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *assembly_info = NULL;
99
    SIZE_T bytes_assembly_info;
100
    unsigned int len_version = 0, len_name, len_identity;
101 102
    const void *ptr_name, *ptr_version, *ptr_identity;
    SXS_GUID_INFORMATION_CLR *ret = buffer;
103
    BOOL retval = FALSE;
104
    char *ret_strings;
105
    ULONG_PTR cookie;
106

107
    TRACE("%#lx, %s, %p, %p, %Ix, %p.\n", flags, wine_dbgstr_guid(clsid), actctx,
108 109
          buffer, buffer_len, buffer_len_required);

110 111 112 113 114 115 116 117
    if (flags & SXS_LOOKUP_CLR_GUID_USE_ACTCTX)
    {
        if (!ActivateActCtx(actctx, &cookie))
        {
            WARN("Failed to activate context.\n");
            return FALSE;
        }
    }
118

119 120
    if (flags & SXS_LOOKUP_CLR_GUID_FIND_SURROGATE)
    {
121 122 123
        if ((retval = FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
                ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES, clsid, &guid_info)))
        {
124
            flags &= ~SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS;
125
        }
126 127 128 129
    }

    if (!retval && (flags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS))
    {
130 131 132
        if ((retval = FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
                ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, clsid, &guid_info)))
        {
133
            flags &= ~SXS_LOOKUP_CLR_GUID_FIND_SURROGATE;
134
        }
135 136 137
    }

    if (!retval)
138 139
    {
        SetLastError(ERROR_NOT_FOUND);
140
        goto out;
141 142
    }

143
    retval = QueryActCtxW(0, guid_info.hActCtx, &guid_info.ulAssemblyRosterIndex,
144
            AssemblyDetailedInformationInActivationContext, NULL, 0, &bytes_assembly_info);
145
    if (!retval && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
146
    {
147
        goto out;
148
    }
149

150
    assembly_info = malloc(bytes_assembly_info);
151
    if (!(retval = QueryActCtxW(0, guid_info.hActCtx, &guid_info.ulAssemblyRosterIndex,
152
            AssemblyDetailedInformationInActivationContext, assembly_info,
153
            bytes_assembly_info, &bytes_assembly_info)))
154
    {
155
        goto out;
156 157
    }

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
    if (flags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS)
    {
        const struct comclassredirect_data *redirect_data = guid_info.lpData;
        const struct clrclass_data *class_data;

        class_data = (void *)((char *)redirect_data + redirect_data->clrdata_offset);
        ptr_name = (char *)class_data + class_data->name_offset;
        ptr_version = (char *)class_data + class_data->version_offset;
        len_name = class_data->name_len + sizeof(WCHAR);
        if (class_data->version_len)
            len_version = class_data->version_len + sizeof(WCHAR);
    }
    else
    {
        const struct clrsurrogate_data *surrogate = guid_info.lpData;
        ptr_name = (char *)surrogate + surrogate->name_offset;
        ptr_version = (char *)surrogate + surrogate->version_offset;
        len_name = surrogate->name_len + sizeof(WCHAR);
        if (surrogate->version_len)
            len_version = surrogate->version_len + sizeof(WCHAR);
    }
179 180 181 182

    ptr_identity = assembly_info->lpAssemblyEncodedAssemblyIdentity;
    len_identity = assembly_info->ulEncodedAssemblyIdentityLength + sizeof(WCHAR);

183
    *buffer_len_required = sizeof(*ret) + len_identity + len_version + len_name;
184 185 186
    if (!buffer || buffer_len < *buffer_len_required)
    {
        SetLastError(ERROR_INSUFFICIENT_BUFFER);
187 188
        retval = FALSE;
        goto out;
189 190
    }

191 192 193
    ret->cbSize = sizeof(*ret);
    ret->dwFlags = flags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS ? SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS :
            SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE;
194 195

    /* Copy strings into buffer */
196
    ret_strings = (char *)ret + sizeof(*ret);
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215

    memcpy(ret_strings, ptr_identity, len_identity);
    ret->pcwszAssemblyIdentity = (WCHAR *)ret_strings;
    ret_strings += len_identity;

    memcpy(ret_strings, ptr_name, len_name);
    ret->pcwszTypeName = (WCHAR *)ret_strings;
    ret_strings += len_name;

    if (len_version > 0)
    {
        memcpy(ret_strings, ptr_version, len_version);
        ret->pcwszRuntimeVersion = (WCHAR *)ret_strings;
    }
    else
        ret->pcwszRuntimeVersion = NULL;

    SetLastError(0);

216
out:
217
    ReleaseActCtx(guid_info.hActCtx);
218 219 220 221

    if (flags & SXS_LOOKUP_CLR_GUID_USE_ACTCTX)
        DeactivateActCtx(0, cookie);

222
    free(assembly_info);
223
    return retval;
224
}