aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Iis/ca/scawebappext.cpp
blob: cf3b9dd30823ffc7ba464045adb432b9db634f67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.

#include "precomp.h"

enum eWebAppExtensionQuery { wappextqExtension = 1, wappextqVerbs, wappextqExecutable, wappextqAttributes, wappextqApplication };

// prototypes for private helper functions
static HRESULT NewAppExt(
    __out SCA_WEB_APPLICATION_EXTENSION** ppswappext
    );
static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList(
    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList,
    __in SCA_WEB_APPLICATION_EXTENSION* pswappext
    );



HRESULT ScaWebAppExtensionsRead(
    __in LPCWSTR wzApplication,
    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
    __inout SCA_WEB_APPLICATION_EXTENSION** ppswappextList
    )
{
    HRESULT hr = S_OK;
    MSIHANDLE hRec;

    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;
    LPWSTR pwzData = NULL;

    // Reset back to the first record
    WcaFetchWrappedReset(hWebAppExtQuery);

    // get the application extension information
    while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hWebAppExtQuery, wappextqApplication, wzApplication, &hRec)))
    {
        hr = NewAppExt(&pswappext);
        ExitOnFailure(hr, "failed to create new web app extension");

        // get the extension
        hr = WcaGetRecordString(hRec, wappextqExtension, &pwzData);
        ExitOnFailure(hr, "Failed to get Web Application Extension");
        hr = ::StringCchCopyW(pswappext->wzExtension, countof(pswappext->wzExtension), pwzData);
        ExitOnFailure(hr, "Failed to copy extension string to webappext object");

        // application extension verbs
        hr = WcaGetRecordString(hRec, wappextqVerbs, &pwzData);
        ExitOnFailure(hr, "Failed to get Verbs for Application: '%ls'", wzApplication);
        hr = ::StringCchCopyW(pswappext->wzVerbs, countof(pswappext->wzVerbs), pwzData);
        ExitOnFailure(hr, "Failed to copy verbs string to webappext object");

        // extension executeable
        hr = WcaGetRecordString(hRec, wappextqExecutable, &pwzData);
        ExitOnFailure(hr, "Failed to get Executable for Application: '%ls'", wzApplication);
        hr = ::StringCchCopyW(pswappext->wzExecutable, countof(pswappext->wzExecutable), pwzData);
        ExitOnFailure(hr, "Failed to copy executable string to webappext object");

        hr = WcaGetRecordInteger(hRec, wappextqAttributes, &pswappext->iAttributes);
        if (S_FALSE == hr)
        {
            pswappext->iAttributes = 0;
            hr = S_OK;
        }
        ExitOnFailure(hr, "Failed to get App isolation");

        *ppswappextList = AddAppExtToList(*ppswappextList, pswappext);
        pswappext = NULL; // set the appext NULL so it doesn't accidentally get freed below
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }

LExit:
    // if anything was left over after an error clean it all up
    if (pswappext)
    {
        ScaWebAppExtensionsFreeList(pswappext);
    }

    ReleaseStr(pwzData);

    return hr;
}



HRESULT ScaWebAppExtensionsWrite(
    __in IMSAdminBase* piMetabase,
    __in LPCWSTR wzRootOfWeb,
    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
    )
{
    HRESULT hr = S_OK;

    LPWSTR wzAppExt = NULL;
    DWORD cchAppExt;
    WCHAR wzAppExtension[1024];
    WCHAR wzAppExtensions[65536];
    SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL;

    if (!pswappextList)
    {
        ExitFunction();
    }

    ::ZeroMemory(wzAppExtensions, sizeof(wzAppExtensions));
    wzAppExt = wzAppExtensions;
    cchAppExt = countof(wzAppExtensions);
    pswappext = pswappextList;

    while (pswappext)
    {
        // if all (represented by "*" or blank)
        if (0 == lstrcmpW(pswappext->wzExtension, L"*") || 0 == lstrlenW(pswappext->wzExtension))
        {
            hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L"*,%s,%d", pswappext->wzExecutable, pswappext->iAttributes);
            ExitOnFailure(hr, "Failed to format *,executable,attributes string");
        }
        else
        {
            hr = ::StringCchPrintfW(wzAppExtension, countof(wzAppExtension), L".%s,%s,%d", pswappext->wzExtension, pswappext->wzExecutable, pswappext->iAttributes);
            ExitOnFailure(hr, "Failed to format extension,executable,attributes string");
        }

        // if verbs were specified and not the keyword "all"
        if (pswappext->wzVerbs[0] && CSTR_EQUAL != CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pswappext->wzVerbs, -1, L"all", -1))
        {
            hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), L",");
            ExitOnFailure(hr, "Failed to concatenate comma to app extension string");
            hr = ::StringCchCatW(wzAppExtension, countof(wzAppExtension), pswappext->wzVerbs);
            ExitOnFailure(hr, "Failed to concatenate verb to app extension string");
        }

        hr = ::StringCchCopyW(wzAppExt, cchAppExt, wzAppExtension);
        ExitOnFailure(hr, "Failed to copy app extension string");
        wzAppExt += lstrlenW(wzAppExtension) + 1;
        cchAppExt -= lstrlenW(wzAppExtension) + 1;
        pswappext = pswappext->pswappextNext;
    }

    if (*wzAppExtensions)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SCRIPT_MAPS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzAppExtensions);
        ExitOnFailure(hr, "Failed to write AppExtension: '%ls'", wzAppExtension);
    }

LExit:
    return hr;
}


void ScaWebAppExtensionsFreeList(
    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList
    )
{
    SCA_WEB_APPLICATION_EXTENSION* pswappextDelete = pswappextList;
    while (pswappextList)
    {
        pswappextDelete = pswappextList;
        pswappextList = pswappextList->pswappextNext;

        MemFree(pswappextDelete);
    }
}



// private helper functions

static HRESULT NewAppExt(
    __out SCA_WEB_APPLICATION_EXTENSION** ppswappext
    )
{
    HRESULT hr = S_OK;
    SCA_WEB_APPLICATION_EXTENSION* pswappext = static_cast<SCA_WEB_APPLICATION_EXTENSION*>(MemAlloc(sizeof(SCA_WEB_APPLICATION_EXTENSION), TRUE));
    ExitOnNull(pswappext, hr, E_OUTOFMEMORY, "failed to allocate memory for new web app ext element");

    *ppswappext = pswappext;

LExit:
    return hr;
}


static SCA_WEB_APPLICATION_EXTENSION* AddAppExtToList(
    __in SCA_WEB_APPLICATION_EXTENSION* pswappextList,
    __in SCA_WEB_APPLICATION_EXTENSION* pswappext
    )
{
    if (pswappextList)
    {
        SCA_WEB_APPLICATION_EXTENSION* pswappextT = pswappextList;
        while (pswappextT->pswappextNext)
        {
            pswappextT = pswappextT->pswappextNext;
        }

        pswappextT->pswappextNext = pswappext;
    }
    else
    {
        pswappextList = pswappext;
    }

    return pswappextList;
}