diff options
Diffstat (limited to 'src/ext/Iis/ca/scaapppool.cpp')
-rw-r--r-- | src/ext/Iis/ca/scaapppool.cpp | 594 |
1 files changed, 594 insertions, 0 deletions
diff --git a/src/ext/Iis/ca/scaapppool.cpp b/src/ext/Iis/ca/scaapppool.cpp new file mode 100644 index 00000000..781c55ca --- /dev/null +++ b/src/ext/Iis/ca/scaapppool.cpp | |||
@@ -0,0 +1,594 @@ | |||
1 | // 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. | ||
2 | |||
3 | #include "precomp.h" | ||
4 | |||
5 | /*------------------------------------------------------------------ | ||
6 | AppPool table: | ||
7 | |||
8 | Column Type Nullable Example Value | ||
9 | AppPool s72 No TestPool | ||
10 | Name s72 No "TestPool" | ||
11 | Component_ s72 No ComponentName | ||
12 | Attributes i2 No 8 (APATTR_OTHERUSER) | ||
13 | User_ s72 Yes UserKey | ||
14 | RecycleMinutes i2 Yes 500 | ||
15 | RecycleRequests i2 Yes 5000 | ||
16 | RecycleTimes s72 Yes "1:45,13:30,22:00" | ||
17 | IdleTimeout i2 Yes 15 | ||
18 | QueueLimit i2 Yes 500 | ||
19 | CPUMon s72 Yes "65,500,1" (65% CPU usage, 500 minutes, Shutdown Action) | ||
20 | MaxProc i2 Yes 5 | ||
21 | ManagedRuntimeVersion s72 Yes "v2.0" | ||
22 | ManagedPipelineMode s72 Yes "Integrated" | ||
23 | |||
24 | Notes: | ||
25 | RecycleTimes is a comma delimeted list of times. CPUMon is a | ||
26 | comma delimeted list of the following format: | ||
27 | <percent CPU usage>,<refress minutes>,<Action>. The values for | ||
28 | Action are 1 (Shutdown) and 0 (No Action). | ||
29 | |||
30 | ------------------------------------------------------------------*/ | ||
31 | |||
32 | enum eAppPoolQuery { apqAppPool = 1, apqName, apqComponent, apqAttributes, apqUser, apqRecycleMinutes, apqRecycleRequests, apqRecycleTimes, apqVirtualMemory, apqPrivateMemory, apqIdleTimeout, apqQueueLimit, apqCpuMon, apqMaxProc, apqManagedRuntimeVersion, apqManagedPipelineMode, apqInstalled, apqAction }; | ||
33 | |||
34 | enum eComponentAttrQuery { caqComponent = 1, caqAttributes }; | ||
35 | |||
36 | // prototypes | ||
37 | static HRESULT AppPoolExists( | ||
38 | __in IMSAdminBase* piMetabase, | ||
39 | __in LPCWSTR wzAppPool | ||
40 | ); | ||
41 | |||
42 | // functions | ||
43 | |||
44 | void ScaAppPoolFreeList( | ||
45 | __in SCA_APPPOOL* psapList | ||
46 | ) | ||
47 | { | ||
48 | SCA_APPPOOL* psapDelete = psapList; | ||
49 | while (psapList) | ||
50 | { | ||
51 | psapDelete = psapList; | ||
52 | psapList = psapList->psapNext; | ||
53 | |||
54 | MemFree(psapDelete); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | |||
59 | HRESULT ScaAppPoolRead( | ||
60 | __inout SCA_APPPOOL** ppsapList, | ||
61 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
62 | __inout LPWSTR *ppwzCustomActionData | ||
63 | ) | ||
64 | { | ||
65 | Assert(ppsapList); | ||
66 | |||
67 | HRESULT hr = S_OK; | ||
68 | |||
69 | MSIHANDLE hRec, hRecComp; | ||
70 | LPWSTR pwzData = NULL; | ||
71 | SCA_APPPOOL* psap = NULL; | ||
72 | WCA_WRAPQUERY_HANDLE hAppPoolQuery = NULL; | ||
73 | WCA_WRAPQUERY_HANDLE hComponentQuery = NULL; | ||
74 | |||
75 | hr = WcaBeginUnwrapQuery(&hAppPoolQuery, ppwzCustomActionData); | ||
76 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
77 | |||
78 | if (0 == WcaGetQueryRecords(hAppPoolQuery)) | ||
79 | { | ||
80 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaAppPoolRead() - required table not present"); | ||
81 | ExitFunction1(hr = S_FALSE); | ||
82 | } | ||
83 | |||
84 | hr = WcaBeginUnwrapQuery(&hComponentQuery, ppwzCustomActionData); | ||
85 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
86 | |||
87 | // loop through all the AppPools | ||
88 | while (S_OK == (hr = WcaFetchWrappedRecord(hAppPoolQuery, &hRec))) | ||
89 | { | ||
90 | // Add this record's information into the list of things to process. | ||
91 | hr = AddAppPoolToList(ppsapList); | ||
92 | ExitOnFailure(hr, "failed to add app pool to app pool list"); | ||
93 | |||
94 | psap = *ppsapList; | ||
95 | |||
96 | hr = WcaGetRecordString(hRec, apqComponent, &pwzData); | ||
97 | ExitOnFailure(hr, "failed to get AppPool.Component"); | ||
98 | |||
99 | if (pwzData && *pwzData) | ||
100 | { | ||
101 | psap->fHasComponent = TRUE; | ||
102 | |||
103 | hr = ::StringCchCopyW(psap->wzComponent, countof(psap->wzComponent), pwzData); | ||
104 | ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); | ||
105 | |||
106 | hr = WcaGetRecordInteger(hRec, apqInstalled, (int *)&psap->isInstalled); | ||
107 | ExitOnFailure(hr, "Failed to get Component installed state for app pool"); | ||
108 | |||
109 | hr = WcaGetRecordInteger(hRec, apqAction, (int *)&psap->isAction); | ||
110 | ExitOnFailure(hr, "Failed to get Component action state for app pool"); | ||
111 | |||
112 | WcaFetchWrappedReset(hComponentQuery); | ||
113 | hr = WcaFetchWrappedRecordWhereString(hComponentQuery, caqComponent, psap->wzComponent, &hRecComp); | ||
114 | ExitOnFailure(hr, "Failed to fetch Component.Attributes for Component '%ls'", psap->wzComponent); | ||
115 | |||
116 | hr = WcaGetRecordInteger(hRecComp, caqAttributes, &psap->iCompAttributes); | ||
117 | ExitOnFailure(hr, "failed to get Component.Attributes"); | ||
118 | } | ||
119 | |||
120 | hr = WcaGetRecordString(hRec, apqAppPool, &pwzData); | ||
121 | ExitOnFailure(hr, "failed to get AppPool.AppPool"); | ||
122 | hr = ::StringCchCopyW(psap->wzAppPool, countof(psap->wzAppPool), pwzData); | ||
123 | ExitOnFailure(hr, "failed to copy AppPool name: %ls", pwzData); | ||
124 | |||
125 | hr = WcaGetRecordString(hRec, apqName, &pwzData); | ||
126 | ExitOnFailure(hr, "failed to get AppPool.Name"); | ||
127 | hr = ::StringCchCopyW(psap->wzName, countof(psap->wzName), pwzData); | ||
128 | ExitOnFailure(hr, "failed to copy app pool name: %ls", pwzData); | ||
129 | hr = ::StringCchPrintfW(psap->wzKey, countof(psap->wzKey), L"/LM/W3SVC/AppPools/%s", pwzData); | ||
130 | ExitOnFailure(hr, "failed to format app pool key name"); | ||
131 | |||
132 | hr = WcaGetRecordInteger(hRec, apqAttributes, &psap->iAttributes); | ||
133 | ExitOnFailure(hr, "failed to get AppPool.Attributes"); | ||
134 | |||
135 | hr = WcaGetRecordString(hRec, apqUser, &pwzData); | ||
136 | ExitOnFailure(hr, "failed to get AppPool.User"); | ||
137 | hr = ScaGetUserDeferred(pwzData, hUserQuery, &psap->suUser); | ||
138 | ExitOnFailure(hr, "failed to get user: %ls", pwzData); | ||
139 | |||
140 | hr = WcaGetRecordInteger(hRec, apqRecycleRequests, &psap->iRecycleRequests); | ||
141 | ExitOnFailure(hr, "failed to get AppPool.RecycleRequests"); | ||
142 | |||
143 | hr = WcaGetRecordInteger(hRec, apqRecycleMinutes, &psap->iRecycleMinutes); | ||
144 | ExitOnFailure(hr, "failed to get AppPool.Minutes"); | ||
145 | |||
146 | hr = WcaGetRecordString(hRec, apqRecycleTimes, &pwzData); | ||
147 | ExitOnFailure(hr, "failed to get AppPool.RecycleTimes"); | ||
148 | hr = ::StringCchCopyW(psap->wzRecycleTimes, countof(psap->wzRecycleTimes), pwzData); | ||
149 | ExitOnFailure(hr, "failed to copy recycle value: %ls", pwzData); | ||
150 | |||
151 | hr = WcaGetRecordInteger(hRec, apqVirtualMemory, &psap->iVirtualMemory); | ||
152 | ExitOnFailure(hr, "failed to get AppPool.VirtualMemory"); | ||
153 | |||
154 | hr = WcaGetRecordInteger(hRec, apqPrivateMemory, &psap->iPrivateMemory); | ||
155 | ExitOnFailure(hr, "failed to get AppPool.PrivateMemory"); | ||
156 | |||
157 | hr = WcaGetRecordInteger(hRec, apqIdleTimeout, &psap->iIdleTimeout); | ||
158 | ExitOnFailure(hr, "failed to get AppPool.IdleTimeout"); | ||
159 | |||
160 | hr = WcaGetRecordInteger(hRec, apqQueueLimit, &psap->iQueueLimit); | ||
161 | ExitOnFailure(hr, "failed to get AppPool.QueueLimit"); | ||
162 | |||
163 | hr = WcaGetRecordString(hRec, apqCpuMon, &pwzData); | ||
164 | ExitOnFailure(hr, "failed to get AppPool.CPUMon"); | ||
165 | hr = ::StringCchCopyW(psap->wzCpuMon, countof(psap->wzCpuMon), pwzData); | ||
166 | ExitOnFailure(hr, "failed to copy cpu monitor value: %ls", pwzData); | ||
167 | |||
168 | hr = WcaGetRecordInteger(hRec, apqMaxProc, &psap->iMaxProcesses); | ||
169 | ExitOnFailure(hr, "failed to get AppPool.MaxProc"); | ||
170 | |||
171 | hr = WcaGetRecordString(hRec, apqManagedRuntimeVersion, &pwzData); | ||
172 | ExitOnFailure(hr, "failed to get AppPool.ManagedRuntimeVersion"); | ||
173 | hr = ::StringCchCopyW(psap->wzManagedRuntimeVersion, countof(psap->wzManagedRuntimeVersion), pwzData); | ||
174 | ExitOnFailure(hr, "failed to copy ManagedRuntimeVersion value: %ls", pwzData); | ||
175 | |||
176 | hr = WcaGetRecordString(hRec, apqManagedPipelineMode, &pwzData); | ||
177 | ExitOnFailure(hr, "failed to get AppPool.ManagedPipelineMode"); | ||
178 | hr = ::StringCchCopyW(psap->wzManagedPipelineMode, countof(psap->wzManagedPipelineMode), pwzData); | ||
179 | ExitOnFailure(hr, "failed to copy ManagedPipelineMode value: %ls", pwzData); | ||
180 | |||
181 | } | ||
182 | |||
183 | if (E_NOMOREITEMS == hr) | ||
184 | { | ||
185 | hr = S_OK; | ||
186 | } | ||
187 | ExitOnFailure(hr, "failure while processing AppPools"); | ||
188 | |||
189 | LExit: | ||
190 | WcaFinishUnwrapQuery(hAppPoolQuery); | ||
191 | WcaFinishUnwrapQuery(hComponentQuery); | ||
192 | |||
193 | ReleaseStr(pwzData); | ||
194 | return hr; | ||
195 | } | ||
196 | |||
197 | |||
198 | HRESULT ScaFindAppPool( | ||
199 | __in IMSAdminBase* piMetabase, | ||
200 | __in LPCWSTR wzAppPool, | ||
201 | __out_ecount(cchName) LPWSTR wzName, | ||
202 | __in DWORD cchName, | ||
203 | __in SCA_APPPOOL *psapList | ||
204 | ) | ||
205 | { | ||
206 | Assert(piMetabase && wzAppPool && *wzAppPool && wzName && *wzName); | ||
207 | |||
208 | HRESULT hr = S_OK; | ||
209 | |||
210 | // check memory first | ||
211 | SCA_APPPOOL* psap = psapList; | ||
212 | for (; psap; psap = psap->psapNext) | ||
213 | { | ||
214 | if (0 == lstrcmpW(psap->wzAppPool, wzAppPool)) | ||
215 | { | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | ExitOnNull(psap, hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Could not find the app pool: %ls", wzAppPool); | ||
220 | |||
221 | // copy the web app pool name | ||
222 | hr = ::StringCchCopyW(wzName, cchName, psap->wzName); | ||
223 | ExitOnFailure(hr, "failed to copy app pool name while finding app pool: %ls", psap->wzName); | ||
224 | |||
225 | // if it's not being installed now, check if it exists already | ||
226 | if (!psap->fHasComponent) | ||
227 | { | ||
228 | hr = AppPoolExists(piMetabase, psap->wzName); | ||
229 | ExitOnFailure(hr, "failed to check for existence of app pool: %ls", psap->wzName); | ||
230 | } | ||
231 | |||
232 | LExit: | ||
233 | return hr; | ||
234 | } | ||
235 | |||
236 | |||
237 | static HRESULT AppPoolExists( | ||
238 | __in IMSAdminBase* piMetabase, | ||
239 | __in LPCWSTR wzAppPool | ||
240 | ) | ||
241 | { | ||
242 | Assert(piMetabase && wzAppPool && *wzAppPool); | ||
243 | |||
244 | HRESULT hr = S_OK; | ||
245 | WCHAR wzSubKey[METADATA_MAX_NAME_LEN]; | ||
246 | |||
247 | for (DWORD dwIndex = 0; SUCCEEDED(hr); ++dwIndex) | ||
248 | { | ||
249 | hr = piMetabase->EnumKeys(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/AppPools", wzSubKey, dwIndex); | ||
250 | if (SUCCEEDED(hr) && 0 == lstrcmpW(wzSubKey, wzAppPool)) | ||
251 | { | ||
252 | hr = S_OK; | ||
253 | break; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | if (E_NOMOREITEMS == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
258 | { | ||
259 | hr = S_FALSE; | ||
260 | } | ||
261 | |||
262 | return hr; | ||
263 | } | ||
264 | |||
265 | |||
266 | HRESULT ScaAppPoolInstall( | ||
267 | __in IMSAdminBase* piMetabase, | ||
268 | __in SCA_APPPOOL* psapList | ||
269 | ) | ||
270 | { | ||
271 | Assert(piMetabase); | ||
272 | |||
273 | HRESULT hr = S_OK; | ||
274 | |||
275 | for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext) | ||
276 | { | ||
277 | // if we are installing the app pool | ||
278 | if (psap->fHasComponent && WcaIsInstalling(psap->isInstalled, psap->isAction)) | ||
279 | { | ||
280 | hr = ScaWriteAppPool(piMetabase, psap); | ||
281 | ExitOnFailure(hr, "failed to write AppPool '%ls' to metabase", psap->wzAppPool); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | LExit: | ||
286 | return hr; | ||
287 | } | ||
288 | |||
289 | |||
290 | HRESULT ScaAppPoolUninstall( | ||
291 | __in IMSAdminBase* piMetabase, | ||
292 | __in SCA_APPPOOL* psapList | ||
293 | ) | ||
294 | { | ||
295 | Assert(piMetabase); | ||
296 | |||
297 | HRESULT hr = S_OK; | ||
298 | |||
299 | for (SCA_APPPOOL* psap = psapList; psap; psap = psap->psapNext) | ||
300 | { | ||
301 | // if we are uninstalling the app pool | ||
302 | if (psap->fHasComponent && WcaIsUninstalling(psap->isInstalled, psap->isAction)) | ||
303 | { | ||
304 | hr = ScaRemoveAppPool(piMetabase, psap); | ||
305 | ExitOnFailure(hr, "Failed to remove AppPool '%ls' from metabase", psap->wzAppPool); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | LExit: | ||
310 | return hr; | ||
311 | } | ||
312 | |||
313 | |||
314 | HRESULT ScaWriteAppPool( | ||
315 | __in IMSAdminBase* piMetabase, | ||
316 | __in SCA_APPPOOL* psap | ||
317 | ) | ||
318 | { | ||
319 | Assert(piMetabase && psap); | ||
320 | |||
321 | HRESULT hr = S_OK; | ||
322 | DWORD dwIdentity = 0xFFFFFFFF; | ||
323 | BOOL fExists = FALSE; | ||
324 | LPWSTR pwzValue = NULL; | ||
325 | LPWSTR wz = NULL; | ||
326 | |||
327 | hr = AppPoolExists(piMetabase, psap->wzName); | ||
328 | ExitOnFailure(hr, "failed to check if app pool already exists"); | ||
329 | if (S_FALSE == hr) | ||
330 | { | ||
331 | // didn't find the AppPool key, so we need to create it | ||
332 | hr = ScaCreateMetabaseKey(piMetabase, psap->wzKey, L""); | ||
333 | ExitOnFailure(hr, "failed to create AppPool key: %ls", psap->wzKey); | ||
334 | |||
335 | // mark it as an AppPool | ||
336 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsApplicationPool"); | ||
337 | ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey); | ||
338 | |||
339 | // TODO: Make this an Attribute? | ||
340 | // set autostart value | ||
341 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_AUTO_START, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)1); | ||
342 | ExitOnFailure(hr, "failed to mark key as AppPool key: %ls", psap->wzKey); | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | fExists = TRUE; | ||
347 | } | ||
348 | |||
349 | // | ||
350 | // Set the AppPool Recycling Tab | ||
351 | // | ||
352 | if (MSI_NULL_INTEGER != psap->iRecycleMinutes) | ||
353 | { | ||
354 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_TIME, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iRecycleMinutes)); | ||
355 | ExitOnFailure(hr, "failed to set periodic restart time"); | ||
356 | } | ||
357 | |||
358 | if (MSI_NULL_INTEGER != psap->iRecycleRequests) | ||
359 | { | ||
360 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_REQUEST_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iRecycleRequests)); | ||
361 | ExitOnFailure(hr, "failed to set periodic restart request count"); | ||
362 | } | ||
363 | |||
364 | if (*psap->wzRecycleTimes) | ||
365 | { | ||
366 | // Add another NULL' onto pwz since it's a 'MULTISZ' | ||
367 | hr = StrAllocString(&pwzValue, psap->wzRecycleTimes, 0); | ||
368 | ExitOnFailure(hr, "failed to allocate string for MULTISZ"); | ||
369 | hr = StrAllocConcat(&pwzValue, L"\0", 1); | ||
370 | ExitOnFailure(hr, "failed to add second null to RecycleTime multisz"); | ||
371 | |||
372 | // Replace the commas with NULLs | ||
373 | wz = pwzValue; | ||
374 | while (NULL != (wz = wcschr(wz, L','))) | ||
375 | { | ||
376 | *wz = L'\0'; | ||
377 | ++wz; | ||
378 | } | ||
379 | |||
380 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_SCHEDULE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, (LPVOID)pwzValue); | ||
381 | ExitOnFailure(hr, "failed to set periodic restart schedule"); | ||
382 | } | ||
383 | |||
384 | if (MSI_NULL_INTEGER != psap->iVirtualMemory) | ||
385 | { | ||
386 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_MEMORY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iVirtualMemory)); | ||
387 | ExitOnFailure(hr, "failed to set periodic restart memory count"); | ||
388 | } | ||
389 | |||
390 | if (MSI_NULL_INTEGER != psap->iPrivateMemory) | ||
391 | { | ||
392 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_PERIODIC_RESTART_PRIVATE_MEMORY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iPrivateMemory)); | ||
393 | ExitOnFailure(hr, "failed to set periodic restart private memory count"); | ||
394 | } | ||
395 | |||
396 | |||
397 | // | ||
398 | // Set AppPool Performance Tab | ||
399 | // | ||
400 | if (MSI_NULL_INTEGER != psap->iIdleTimeout) | ||
401 | { | ||
402 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDLE_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iIdleTimeout)); | ||
403 | ExitOnFailure(hr, "failed to set idle timeout value"); | ||
404 | } | ||
405 | |||
406 | if (MSI_NULL_INTEGER != psap->iQueueLimit) | ||
407 | { | ||
408 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_UL_APPPOOL_QUEUE_LENGTH, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iQueueLimit)); | ||
409 | ExitOnFailure(hr, "failed to set request queue limit value"); | ||
410 | } | ||
411 | |||
412 | if (*psap->wzCpuMon) | ||
413 | { | ||
414 | hr = StrAllocString(&pwzValue, psap->wzCpuMon, 0); | ||
415 | ExitOnFailure(hr, "failed to allocate CPUMonitor string"); | ||
416 | |||
417 | DWORD dwPercent = 0; | ||
418 | DWORD dwRefreshMinutes = 0; | ||
419 | DWORD dwAction = 0; | ||
420 | |||
421 | dwPercent = wcstoul(pwzValue, &wz, 10); | ||
422 | if (100 < dwPercent) | ||
423 | { | ||
424 | ExitOnFailure(hr = E_INVALIDARG, "invalid maximum cpu percentage value: %d", dwPercent); | ||
425 | } | ||
426 | if (wz && L',' == *wz) | ||
427 | { | ||
428 | ++wz; | ||
429 | dwRefreshMinutes = wcstoul(wz, &wz, 10); | ||
430 | if (wz && L',' == *wz) | ||
431 | { | ||
432 | ++wz; | ||
433 | dwAction = wcstoul(wz, &wz, 10); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | if (dwPercent) | ||
438 | { | ||
439 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_LIMIT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)(dwPercent * 1000))); | ||
440 | ExitOnFailure(hr, "failed to set CPU percentage max"); | ||
441 | } | ||
442 | if (dwRefreshMinutes) | ||
443 | { | ||
444 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_RESET_INTERVAL, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwRefreshMinutes)); | ||
445 | ExitOnFailure(hr, "failed to set refresh CPU minutes"); | ||
446 | } | ||
447 | if (dwAction) | ||
448 | { | ||
449 | // 0 = No Action | ||
450 | // 1 = Shutdown | ||
451 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_CPU_ACTION, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwAction)); | ||
452 | ExitOnFailure(hr, "failed to set CPU action"); | ||
453 | } | ||
454 | } | ||
455 | |||
456 | if (MSI_NULL_INTEGER != psap->iMaxProcesses) | ||
457 | { | ||
458 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_MAX_PROCESS_COUNT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)psap->iMaxProcesses)); | ||
459 | ExitOnFailure(hr, "failed to set web garden maximum worker processes"); | ||
460 | } | ||
461 | |||
462 | // TODO: Health Tab if anyone wants it? | ||
463 | |||
464 | // | ||
465 | // Set the AppPool Identity tab | ||
466 | // | ||
467 | if (psap->iAttributes & APATTR_NETSERVICE) | ||
468 | { | ||
469 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE; | ||
470 | } | ||
471 | else if (psap->iAttributes & APATTR_LOCSERVICE) | ||
472 | { | ||
473 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE; | ||
474 | } | ||
475 | else if (psap->iAttributes & APATTR_LOCSYSTEM) | ||
476 | { | ||
477 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM; | ||
478 | } | ||
479 | else if (psap->iAttributes & APATTR_OTHERUSER) | ||
480 | { | ||
481 | if (!*psap->suUser.wzDomain || CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L".", -1)) | ||
482 | { | ||
483 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NetworkService", -1)) | ||
484 | { | ||
485 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE; | ||
486 | } | ||
487 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalService", -1)) | ||
488 | { | ||
489 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE; | ||
490 | } | ||
491 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"LocalSystem", -1)) | ||
492 | { | ||
493 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM; | ||
494 | } | ||
495 | else | ||
496 | { | ||
497 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER; | ||
498 | } | ||
499 | } | ||
500 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzDomain, -1, L"NT AUTHORITY", -1)) | ||
501 | { | ||
502 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"NETWORK SERVICE", -1)) | ||
503 | { | ||
504 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE; | ||
505 | } | ||
506 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SERVICE", -1)) | ||
507 | { | ||
508 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE; | ||
509 | } | ||
510 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, psap->suUser.wzName, -1, L"SYSTEM", -1)) | ||
511 | { | ||
512 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM; | ||
513 | } | ||
514 | else | ||
515 | { | ||
516 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER; | ||
517 | } | ||
518 | } | ||
519 | else | ||
520 | { | ||
521 | dwIdentity = MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | if (-1 != dwIdentity) | ||
526 | { | ||
527 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_APPPOOL_IDENTITY_TYPE, METADATA_INHERIT , IIS_MD_UT_SERVER, DWORD_METADATA, (LPVOID)((DWORD_PTR)dwIdentity)); | ||
528 | ExitOnFailure(hr, "failed to set app pool identity"); | ||
529 | |||
530 | if (MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER == dwIdentity) | ||
531 | { | ||
532 | if (*psap->suUser.wzDomain) | ||
533 | { | ||
534 | hr = StrAllocFormatted(&pwzValue, L"%s\\%s", psap->suUser.wzDomain, psap->suUser.wzName); | ||
535 | ExitOnFailure(hr, "failed to format user name: %ls domain: %ls", psap->suUser.wzName, psap->suUser.wzDomain); | ||
536 | } | ||
537 | else | ||
538 | { | ||
539 | hr = StrAllocFormatted(&pwzValue, L"%s", psap->suUser.wzName); | ||
540 | ExitOnFailure(hr, "failed to format user name: %ls", psap->suUser.wzName); | ||
541 | } | ||
542 | |||
543 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_USER_NAME, METADATA_INHERIT , IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pwzValue); | ||
544 | ExitOnFailure(hr, "failed to set app pool identity name"); | ||
545 | |||
546 | hr = ScaWriteMetabaseValue(piMetabase, psap->wzKey, NULL, MD_WAM_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psap->suUser.wzPassword); | ||
547 | ExitOnFailure(hr, "failed to set app pool identity password"); | ||
548 | } | ||
549 | } | ||
550 | |||
551 | LExit: | ||
552 | ReleaseStr(pwzValue); | ||
553 | |||
554 | return hr; | ||
555 | } | ||
556 | |||
557 | |||
558 | HRESULT ScaRemoveAppPool( | ||
559 | __in IMSAdminBase* piMetabase, | ||
560 | __in SCA_APPPOOL* psap | ||
561 | ) | ||
562 | { | ||
563 | Assert(piMetabase && psap); | ||
564 | |||
565 | HRESULT hr = S_OK; | ||
566 | |||
567 | // simply remove the root key and everything else is pulled at the same time | ||
568 | if (0 != lstrlenW(psap->wzKey)) | ||
569 | { | ||
570 | hr = ScaDeleteMetabaseKey(piMetabase, psap->wzKey, L""); | ||
571 | ExitOnFailure(hr, "failed to delete AppPool key: %ls", psap->wzKey); | ||
572 | } | ||
573 | |||
574 | // TODO: Maybe check to make sure any web sites that are using this AppPool are put back in the 'DefaultAppPool' | ||
575 | |||
576 | LExit: | ||
577 | return hr; | ||
578 | } | ||
579 | |||
580 | |||
581 | HRESULT AddAppPoolToList( | ||
582 | __in SCA_APPPOOL** ppsapList | ||
583 | ) | ||
584 | { | ||
585 | HRESULT hr = S_OK; | ||
586 | SCA_APPPOOL* psap = static_cast<SCA_APPPOOL*>(MemAlloc(sizeof(SCA_APPPOOL), TRUE)); | ||
587 | ExitOnNull(psap, hr, E_OUTOFMEMORY, "failed to allocate memory for new element in app pool list"); | ||
588 | |||
589 | psap->psapNext = *ppsapList; | ||
590 | *ppsapList = psap; | ||
591 | |||
592 | LExit: | ||
593 | return hr; | ||
594 | } | ||