Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2180 lines
68 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: Globals
  6. File: glob.cpp
  7. Owner: LeiJin
  8. Implementation of Glob class functions
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #include "iiscnfgp.h"
  13. #include "debugger.h"
  14. #include "appcnfg.h"
  15. #include "memchk.h"
  16. #include <iismsg.h>
  17. HRESULT ReadConfigFromMD(CIsapiReqInfo *pIReq, CAppConfig *pAppConfig, BOOL fLoadGlob);
  18. HRESULT MDUnRegisterProperties();
  19. HRESULT MDRegisterProperties(void);
  20. #define DEFAULTSTRSIZE 1024
  21. #define dwUnlimited 0xFFFFFFFF
  22. const DWORD dwMDDefaultTimeOut = 30000;
  23. enum eConfigType { eDLLConfig = 0, eAppConfig };
  24. CAspRegistryParams g_AspRegistryParams;
  25. extern LONG g_fProceedWithShutdownAppln;
  26. LONG g_fProceedWithShutdownGlob = 1;
  27. /*========================================================================================
  28. The following array definition is for D1 to D2 migration only. It contains the necessary
  29. information reads from D1 ASP settings in registry.
  30. =========================================================================================*/
  31. typedef struct _D1propinfo
  32. {
  33. CHAR *szName; // Name of the property in the registry
  34. DWORD dwType; // Type (e.g. REG_DWORD, REG_SZ, etc)
  35. DWORD cbData; // How long is the value
  36. VOID *pData;
  37. BOOL fSuccess; // Load from registry successful or not.
  38. } D1PROPINFO;
  39. #define NUM_D1PROP_NeedMigrated 18
  40. // This index should be match the index in D1PropInfo.
  41. enum D1PropIndex {
  42. D1Prop_NotExist = -1,
  43. D1Prop_BufferingOn = 0,
  44. D1Prop_LogErrorRequests,
  45. D1Prop_ScriptErrorsSentToBrowser,
  46. D1Prop_ScriptErrorMessage,
  47. D1Prop_ScriptFileCacheSize,
  48. D1Prop_ScriptEngineCacheMax,
  49. D1Prop_ScriptTimeout,
  50. D1Prop_SessionTimeout,
  51. // D1Prop_MemFreeFactor,
  52. // D1Prop_MinUsedBlocks,
  53. D1Prop_AllowSessionState,
  54. D1Prop_DefaultScriptLanguage,
  55. // D1Prop_StartConnectionPool,
  56. D1Prop_AllowOutOfProcCmpnts,
  57. D1Prop_EnableParentPaths,
  58. // IIS5.0 (from IIS4.0)
  59. D1Prop_EnableAspHtmlFallback,
  60. D1Prop_EnableChunkedEncoding,
  61. D1Prop_EnableTypelibCache,
  62. D1Prop_ErrorsToNtLog,
  63. D1Prop_ProcessorThreadMax,
  64. D1Prop_RequestQueueMax
  65. };
  66. // This flag is used only in setup time.
  67. BOOL g_fD1ConfigExist = FALSE;
  68. // The index is defined in D1PropIndex.
  69. D1PROPINFO D1PropInfo[] =
  70. {
  71. { "BufferingOn", REG_DWORD, 0, 0, FALSE},
  72. { "LogErrorRequests", REG_DWORD, 0, 0, FALSE},
  73. { "ScriptErrorsSentToBrowser", REG_DWORD, 0, 0, FALSE},
  74. { "ScriptErrorMessage", REG_SZ, 0, 0, FALSE},
  75. { "ScriptFileCacheSize", REG_DWORD, 0, 0, FALSE},
  76. { "ScriptEngineCacheMax", REG_DWORD, 0, 0, FALSE},
  77. { "ScriptTimeout", REG_DWORD, 0, 0, FALSE},
  78. { "SessionTimeout", REG_DWORD, 0, 0, FALSE},
  79. { "AllowSessionState", REG_DWORD, 0, 0, FALSE},
  80. { "DefaultScriptLanguage", REG_SZ, 0, 0, FALSE},
  81. { "AllowOutOfProcCmpnts", REG_DWORD, 0, 0, FALSE},
  82. { "EnableParentPaths", REG_DWORD, 0, 0, FALSE},
  83. // IIS5.0 (from IIS4.0)
  84. { "EnableAspHtmlFallback", REG_DWORD, 0, 0, FALSE},
  85. { "EnableChunkedEncoding", REG_DWORD, 0, 0, FALSE},
  86. { "EnableTypelibCache", REG_DWORD, 0, 0, FALSE},
  87. { "ErrorsToNTLog", REG_DWORD, 0, 0, FALSE},
  88. { "ProcessorThreadMax", REG_DWORD, 0, 0, FALSE},
  89. { "RequestQueueMax", REG_DWORD, 0, 0, FALSE}
  90. };
  91. /*
  92. * The following array contains all the info we need to create and load
  93. * all of the registry entries for denali. See the above PROPINFO structure for details on each of the fields.
  94. *
  95. * NOTE: There is an odd thing about initializers and unions. You must initialize a union with the value of
  96. * the type of the first element in the union. In the anonymous union in the PROPINFO structure, we have defined
  97. * the first type to be DWORD. Thus, for non-DWORD registry entries, the default value must be cast to a DWORD
  98. * before being initialized, or initialized using a more explicit mechanism.
  99. */
  100. /*
  101. * Info about our properties used by Metabase
  102. */
  103. typedef struct _MDpropinfo
  104. {
  105. INT id; // Identifier used in Glob if UserType is IIS_MD_UT_WAM,
  106. // Identifier used in AppConfig if UserType is ASP_MD_UT_APP.
  107. INT iD1PropIndex; // Index in D1PropInfo. if equals to -1, that it does not exist in D1.
  108. BOOL fAdminConfig; // Admin Configurable
  109. DWORD dwMDIdentifier; // Metabase identifier
  110. DWORD dwUserType; // IIS_MD_UT_WAM(data per Dll) or ASP_MD_UT_APP(data per App)
  111. DWORD dwType;
  112. DWORD cbData;
  113. union // Default Value
  114. {
  115. DWORD dwDefault; // Default value for DWORDs
  116. INT idDefault; // Default value for strings -- the id of the string in the resource
  117. BYTE *pbDefault; // Pointer to arbitrary default value
  118. };
  119. DWORD dwValueMin; // For DWORD registry entries, min value allowed
  120. DWORD dwValueMax; // For DWORD registry entries, max value allowed
  121. } MDPROPINFO;
  122. //Some default settings for ASP Metabase
  123. #define ASP_MD_DAttributes METADATA_INHERIT
  124. const MDPROPINFO rgMDPropInfo[] =
  125. {
  126. #define THREADGATING_DFLT 0L
  127. #define BUFFERING_DFLT 1L
  128. // ID D1PropIndex AdminConfig? Metabase ID UserType Data Type cbData Def, Min, Max
  129. // Glob Settings
  130. // -------------
  131. { IGlob_LogErrorRequests, D1Prop_LogErrorRequests, TRUE, MD_ASP_LOGERRORREQUESTS, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  132. { IGlob_ScriptFileCacheSize, D1Prop_ScriptFileCacheSize, TRUE, MD_ASP_SCRIPTFILECACHESIZE, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 500L, 0L, dwUnlimited},
  133. { IGlob_ScriptEngineCacheMax, D1Prop_ScriptEngineCacheMax, TRUE, MD_ASP_SCRIPTENGINECACHEMAX, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 250L, 0L, dwUnlimited},
  134. { IGlob_ExceptionCatchEnable, D1Prop_NotExist, TRUE, MD_ASP_EXCEPTIONCATCHENABLE, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  135. { IGlob_TrackThreadingModel, D1Prop_NotExist, TRUE, MD_ASP_TRACKTHREADINGMODEL, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
  136. { IGlob_AllowOutOfProcCmpnts, D1Prop_AllowOutOfProcCmpnts, FALSE, MD_ASP_ALLOWOUTOFPROCCMPNTS, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  137. // IIS5.0
  138. { IGlob_EnableAspHtmlFallback, D1Prop_EnableAspHtmlFallback, TRUE, MD_ASP_ENABLEASPHTMLFALLBACK, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
  139. { IGlob_EnableChunkedEncoding, D1Prop_EnableChunkedEncoding, TRUE, MD_ASP_ENABLECHUNKEDENCODING, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  140. { IGlob_EnableTypelibCache, D1Prop_EnableTypelibCache, TRUE, MD_ASP_ENABLETYPELIBCACHE, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  141. { IGlob_ErrorsToNtLog, D1Prop_ErrorsToNtLog, TRUE, MD_ASP_ERRORSTONTLOG, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
  142. { IGlob_ProcessorThreadMax, D1Prop_ProcessorThreadMax, TRUE, MD_ASP_PROCESSORTHREADMAX, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 25L, 0L, dwUnlimited},
  143. { IGlob_RequestQueueMax, D1Prop_RequestQueueMax, TRUE, MD_ASP_REQEUSTQUEUEMAX, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 3000L, 0L, dwUnlimited},
  144. // IIS6.0 & IIS5.1 - Persisted Template Cache
  145. { IGlob_PersistTemplateMaxFiles, D1Prop_NotExist, TRUE, MD_ASP_MAXDISKTEMPLATECACHEFILES, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 2000L, 0L, dwUnlimited},
  146. { IGlob_PersistTemplateDir, D1Prop_NotExist, TRUE, MD_ASP_DISKTEMPLATECACHEDIRECTORY, IIS_MD_UT_WAM, EXPANDSZ_METADATA, dwUnlimited, IDS_DEFAULTPERSISTDIR, 0L, dwUnlimited},
  147. // Application settings
  148. // --------------------
  149. { IApp_AllowSessionState, D1Prop_AllowSessionState, TRUE, MD_ASP_ALLOWSESSIONSTATE, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  150. { IApp_BufferingOn, D1Prop_BufferingOn, TRUE, MD_ASP_BUFFERINGON, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), BUFFERING_DFLT, 0L, 1L},
  151. { IApp_ScriptLanguage, D1Prop_DefaultScriptLanguage, TRUE, MD_ASP_SCRIPTLANGUAGE, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, IDS_SCRIPTLANGUAGE, 0L, dwUnlimited},
  152. { IApp_EnableParentPaths, D1Prop_EnableParentPaths, TRUE, MD_ASP_ENABLEPARENTPATHS, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
  153. { IApp_ScriptErrorMessage, D1Prop_ScriptErrorMessage, TRUE, MD_ASP_SCRIPTERRORMESSAGE, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, IDS_DEFAULTMSG_ERROR, 0L, dwUnlimited},
  154. { IApp_SessionTimeout, D1Prop_SessionTimeout, TRUE, MD_ASP_SESSIONTIMEOUT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 20L, 1L, dwUnlimited},
  155. { IApp_QueueTimeout, D1Prop_NotExist, TRUE, MD_ASP_QUEUETIMEOUT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), dwUnlimited, 1L, dwUnlimited},
  156. { IApp_CodePage, D1Prop_NotExist, TRUE, MD_ASP_CODEPAGE, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), CP_ACP, 0L, dwUnlimited},
  157. { IApp_ScriptTimeout, D1Prop_ScriptTimeout, TRUE, MD_ASP_SCRIPTTIMEOUT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 90L, 1L, dwUnlimited},
  158. { IApp_ScriptErrorsSenttoBrowser, D1Prop_ScriptErrorsSentToBrowser, TRUE, MD_ASP_SCRIPTERRORSSENTTOBROWSER, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  159. { IApp_AllowDebugging, D1Prop_NotExist, TRUE, MD_ASP_ENABLESERVERDEBUG, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
  160. { IApp_AllowClientDebug, D1Prop_NotExist, TRUE, MD_ASP_ENABLECLIENTDEBUG, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
  161. // IIS5.0
  162. { IApp_EnableApplicationRestart, D1Prop_NotExist, TRUE, MD_ASP_ENABLEAPPLICATIONRESTART, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  163. { IApp_QueueConnectionTestTime, D1Prop_NotExist, TRUE, MD_ASP_QUEUECONNECTIONTESTTIME, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 3L, 1L, dwUnlimited},
  164. { IApp_SessionMax, D1Prop_NotExist, TRUE, MD_ASP_SESSIONMAX, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), dwUnlimited, 1L, dwUnlimited},
  165. // IIS5.1 & IIS6.0
  166. { IApp_ExecuteInMTA, D1Prop_NotExist, TRUE, MD_ASP_EXECUTEINMTA, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1},
  167. { IApp_LCID, D1Prop_NotExist, TRUE, MD_ASP_LCID, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), LOCALE_SYSTEM_DEFAULT, 0L, dwUnlimited},
  168. // IIS6.0 Only - ServicesWithoutComponents
  169. { IApp_ServiceFlags, D1Prop_NotExist, TRUE, MD_ASP_SERVICE_FLAGS, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 7L},
  170. { IApp_PartitionGUID, D1Prop_NotExist, TRUE, MD_ASP_SERVICE_PARTITION_ID, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, 0xffffffff, 0L, dwUnlimited},
  171. { IApp_SxsName, D1Prop_NotExist, TRUE, MD_ASP_SERVICE_SXS_NAME, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, 0xffffffff, 0L, dwUnlimited},
  172. // IIS6.0 Only - Misc
  173. { IApp_KeepSessionIDSecure, D1Prop_NotExist, TRUE, MD_ASP_KEEPSESSIONIDSECURE, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
  174. { IApp_CalcLineNumber, D1Prop_NotExist, TRUE, MD_ASP_CALCLINENUMBER, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  175. { IApp_RunOnEndAsAnon, D1Prop_NotExist, TRUE, MD_ASP_RUN_ONEND_ANON, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
  176. { IApp_BufferLimit, D1Prop_NotExist, TRUE, MD_ASP_BUFFER_LIMIT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), DEFAULT_BUFFER_LIMIT, 0L, dwUnlimited},
  177. { IApp_RequestEntityLimit, D1Prop_NotExist, TRUE, MD_ASP_MAX_REQUEST_ENTITY_ALLOWED, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), DEFAULT_REQUEST_ENTITY_LIMIT, 0L, dwUnlimited}
  178. };
  179. const DWORD rgdwMDObsoleteIdentifiers[] =
  180. {MD_ASP_MEMFREEFACTOR,
  181. MD_ASP_MINUSEDBLOCKS
  182. };
  183. const UINT cPropsMax = sizeof(rgMDPropInfo) / sizeof(MDPROPINFO);
  184. /*===================================================================
  185. ReadAndRemoveOldD1PropsFromRegistry
  186. Reads whatever old D1 properties are in the registry and
  187. stores the values into D1PropInfo[] global array.
  188. Removes the old properties found from the registry.
  189. Returns:
  190. HRESULT - S_OK on success
  191. Side effects:
  192. Fills in values in Glob
  193. ===================================================================*/
  194. BOOL ReadAndRemoveOldD1PropsFromRegistry()
  195. {
  196. HKEY hkey = NULL;
  197. DWORD iValue;
  198. BYTE cTrys = 0;
  199. DWORD dwType;
  200. BYTE bData[DEFAULTSTRSIZE]; // Size???
  201. BYTE *lpRegString = NULL; // need to use dynamic allocation when we have ERROR_MORE_DATA
  202. DWORD cbData;
  203. HRESULT hr = S_OK;
  204. // Open the key for W3SVC\ASP\Parameters
  205. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\W3SVC\\ASP\\Parameters", 0, KEY_READ|KEY_WRITE, &hkey) != ERROR_SUCCESS)
  206. return(FALSE);
  207. // Load each of the values
  208. for (iValue = 0; iValue < NUM_D1PROP_NeedMigrated; iValue++)
  209. {
  210. LONG err;
  211. D1PROPINFO *pPropInfo;
  212. pPropInfo = &D1PropInfo[iValue];
  213. cbData = sizeof(bData);
  214. err = RegQueryValueExA(hkey, pPropInfo->szName, 0, &dwType, bData, &cbData);
  215. if (err == ERROR_MORE_DATA)
  216. {
  217. lpRegString = (BYTE *)GlobalAlloc(GPTR, cbData);
  218. if (lpRegString != NULL)
  219. {
  220. err = RegQueryValueExA(hkey, pPropInfo->szName, 0, &dwType, lpRegString, &cbData);
  221. }
  222. else
  223. {
  224. pPropInfo->fSuccess = FALSE;
  225. continue;
  226. }
  227. }
  228. // if get an error, or not the type we expect, then use the default
  229. if (err != ERROR_SUCCESS || dwType != pPropInfo->dwType)
  230. {
  231. pPropInfo->fSuccess = FALSE;
  232. //
  233. // Free up lpRegString
  234. //
  235. if (lpRegString)
  236. {
  237. GlobalFree(lpRegString);
  238. lpRegString = NULL;
  239. }
  240. continue;
  241. }
  242. // Success : Got the data, copy it into Glob
  243. // But first, if this is a DWORD type, make sure it is within allowed Max/Min range
  244. switch (pPropInfo->dwType)
  245. {
  246. case REG_DWORD:
  247. Assert(cbData == sizeof(DWORD));
  248. if (cbData == sizeof(DWORD))
  249. {
  250. pPropInfo->cbData = cbData;
  251. //
  252. // bData is atleast 4 bytes (DEFAULTSTRSIZE > 4 bytes) so bData is always valid even if Prefix tags it as using a
  253. // possibly uninited value as lpRegString may be used in its place. Ignore PREFIX warning.
  254. //
  255. pPropInfo->pData = (VOID *)UIntToPtr((*(DWORD *)bData));
  256. pPropInfo->fSuccess = TRUE;
  257. }
  258. //
  259. // So if its a DWORD then we are not going to need the lpRegString. Release it.
  260. //
  261. if (lpRegString)
  262. {
  263. GlobalFree(lpRegString) ;
  264. lpRegString = NULL;
  265. }
  266. break;
  267. case REG_SZ:
  268. if (lpRegString == NULL)
  269. { // The string fit into default allocation
  270. lpRegString = (BYTE *)GlobalAlloc(GPTR, cbData * sizeof(WCHAR));
  271. if (lpRegString == NULL)
  272. return FALSE;
  273. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)bData, -1, (LPWSTR)lpRegString, cbData);
  274. }
  275. pPropInfo->cbData = cbData * sizeof(WCHAR);
  276. pPropInfo->pData = (VOID *)lpRegString;
  277. pPropInfo->fSuccess = TRUE;
  278. lpRegString = NULL;
  279. break;
  280. }
  281. // remove the value from the registry
  282. RegDeleteValueA(hkey, pPropInfo->szName);
  283. }
  284. // remove some old properties that 'get lost' in the upgrade
  285. RegDeleteValueA(hkey, "CheckForNestedVroots");
  286. RegDeleteValueA(hkey, "EventLogDirection");
  287. RegDeleteValueA(hkey, "ScriptFileCacheTTL");
  288. RegDeleteValueA(hkey, "StartConnectionPool");
  289. RegDeleteValueA(hkey, "NumInitialThreads");
  290. RegDeleteValueA(hkey, "ThreadCreationThreshold");
  291. RegDeleteValueA(hkey, "MinUsedBlocks");
  292. RegDeleteValueA(hkey, "MemFreeFactor");
  293. RegDeleteValueA(hkey, "MemClsFreeFactor");
  294. RegDeleteValueA(hkey, "ThreadDeleteDelay");
  295. RegDeleteValueA(hkey, "ViperRequestQueueMax");
  296. RegCloseKey(hkey);
  297. // remove the W3SVC\ASP\Paramaters key
  298. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\W3SVC\\ASP", 0, KEY_READ|KEY_WRITE, &hkey) == ERROR_SUCCESS)
  299. {
  300. RegDeleteKeyA(hkey, "Parameters");
  301. RegCloseKey(hkey);
  302. }
  303. // remove the W3SVC\ASP key
  304. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\W3SVC", 0, KEY_READ|KEY_WRITE, &hkey) == ERROR_SUCCESS)
  305. {
  306. RegDeleteKeyA(hkey, "ASP");
  307. RegCloseKey(hkey);
  308. }
  309. return TRUE;
  310. }
  311. /*==================================================================
  312. MDRegisterProperties
  313. Register info about our properties in the metabase. This funtion is
  314. called during regsvr32, self-registration time.
  315. Returns:
  316. HRESULT - S_OK on success
  317. Side effects:
  318. Registers denali properties in the metabase
  319. ===================================================================*/
  320. HRESULT MDRegisterProperties(void)
  321. {
  322. HRESULT hr = S_OK;
  323. DWORD iValue;
  324. IMSAdminBase *pMetabase = NULL;
  325. METADATA_HANDLE hMetabase = NULL;
  326. METADATA_RECORD recMetaData;
  327. BYTE szDefaultString[2*DEFAULTSTRSIZE];
  328. HRESULT hrT = S_OK;
  329. BOOL fNeedMigrated;
  330. fNeedMigrated = ReadAndRemoveOldD1PropsFromRegistry();
  331. hr = CoInitialize(NULL);
  332. if (FAILED(hr))
  333. {
  334. return hr;
  335. }
  336. hr = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_SERVER, IID_IMSAdminBase, (void **)&pMetabase);
  337. if (FAILED(hr))
  338. {
  339. CoUninitialize();
  340. return hr;
  341. }
  342. // Open key to the Web service, and get a handle of \LM\w3svc
  343. hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)(L"\\LM\\W3SVC"),
  344. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  345. dwMDDefaultTimeOut, &hMetabase);
  346. if (FAILED(hr))
  347. {
  348. goto LExit;
  349. }
  350. //
  351. // Remove obsolete metabase settings
  352. // See rgdwMDObsoleteIdentifiers structure for detail list of properties
  353. //
  354. for (iValue = 0; iValue < sizeof(rgdwMDObsoleteIdentifiers)/sizeof(DWORD);
  355. iValue++)
  356. {
  357. hr = pMetabase->DeleteData( hMetabase,
  358. NULL,
  359. rgdwMDObsoleteIdentifiers[iValue],
  360. 0);
  361. if (FAILED(hr))
  362. {
  363. if (hr == MD_ERROR_DATA_NOT_FOUND)
  364. {
  365. hr = S_OK;
  366. }
  367. else
  368. {
  369. Assert(FALSE);
  370. }
  371. }
  372. }
  373. //
  374. // Set metabase properties
  375. //
  376. recMetaData.dwMDDataTag = 0; // this parameter is not used when setting data
  377. for (iValue = 0; iValue < cPropsMax; iValue++)
  378. {
  379. INT cch;
  380. BYTE aByte[4]; // Temporary buffer
  381. DWORD dwLen;
  382. D1PROPINFO *pD1PropInfo;
  383. recMetaData.dwMDIdentifier = rgMDPropInfo[iValue].dwMDIdentifier;
  384. recMetaData.dwMDAttributes = METADATA_INHERIT;
  385. recMetaData.dwMDUserType = rgMDPropInfo[iValue].dwUserType;
  386. recMetaData.dwMDDataType = rgMDPropInfo[iValue].dwType;
  387. dwLen = 0;
  388. recMetaData.dwMDDataLen = 0;
  389. recMetaData.pbMDData = (unsigned char *)aByte;
  390. HRESULT hrGetData = pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwLen);
  391. if (hrGetData == MD_ERROR_DATA_NOT_FOUND)
  392. {
  393. switch (rgMDPropInfo[iValue].dwType)
  394. {
  395. case DWORD_METADATA:
  396. if (fNeedMigrated && rgMDPropInfo[iValue].iD1PropIndex != D1Prop_NotExist )
  397. {
  398. pD1PropInfo = &D1PropInfo[rgMDPropInfo[iValue].iD1PropIndex];
  399. if (pD1PropInfo->fSuccess == TRUE)
  400. {
  401. recMetaData.dwMDDataLen = pD1PropInfo->cbData;
  402. recMetaData.pbMDData = (unsigned char *)&(pD1PropInfo->pData);
  403. break;
  404. }
  405. }
  406. // Did not migrated.
  407. recMetaData.dwMDDataLen = rgMDPropInfo[iValue].cbData;
  408. recMetaData.pbMDData = (unsigned char *)&(rgMDPropInfo[iValue].dwDefault);
  409. break;
  410. case EXPANDSZ_METADATA:
  411. case STRING_METADATA:
  412. if (fNeedMigrated && rgMDPropInfo[iValue].iD1PropIndex != D1Prop_NotExist )
  413. {
  414. pD1PropInfo = &D1PropInfo[rgMDPropInfo[iValue].iD1PropIndex];
  415. if (pD1PropInfo->fSuccess == TRUE)
  416. {
  417. recMetaData.dwMDDataLen = pD1PropInfo->cbData;
  418. recMetaData.pbMDData = (unsigned char *)(pD1PropInfo->pData);
  419. break;
  420. }
  421. }
  422. //
  423. // if its a string and its index is defined as 0xffffffff then just dont load the string and continue.
  424. //
  425. if (rgMDPropInfo[iValue].idDefault == 0xffffffff)
  426. continue;
  427. // Did not migrated
  428. cch = CwchLoadStringOfId(rgMDPropInfo[iValue].idDefault, (LPWSTR)szDefaultString, DEFAULTSTRSIZE);
  429. if (cch == 0)
  430. {
  431. DBGPRINTF((DBG_CONTEXT, "LoadString failed, id = %d\n", rgMDPropInfo[iValue].idDefault));
  432. recMetaData.dwMDDataLen = cch;
  433. recMetaData.pbMDData = NULL;
  434. }
  435. else
  436. {
  437. recMetaData.dwMDDataLen = (cch + 1)*sizeof(WCHAR);
  438. recMetaData.pbMDData = szDefaultString;
  439. }
  440. break;
  441. default:
  442. // So far, DWORD and STRING are the only 2 types.
  443. // Never reach this code path.
  444. Assert(FALSE);
  445. continue;
  446. }
  447. // not found - then set
  448. hr = pMetabase->SetData(hMetabase, NULL, &recMetaData);
  449. }
  450. else
  451. {
  452. // don't change if the data is already in the metabase
  453. hr = S_OK;
  454. }
  455. if (FAILED(hr))
  456. {
  457. DBGPRINTF((DBG_CONTEXT, "Metabase SetData failed, identifier = %08x.\n", rgMDPropInfo[iValue].dwMDIdentifier));
  458. }
  459. }
  460. hrT = pMetabase->CloseKey(hMetabase);
  461. if (fNeedMigrated)
  462. {
  463. if (D1PropInfo[D1Prop_DefaultScriptLanguage].pData != NULL)
  464. {
  465. GlobalFree(D1PropInfo[D1Prop_DefaultScriptLanguage].pData);
  466. }
  467. if (D1PropInfo[D1Prop_ScriptErrorMessage].pData != NULL)
  468. {
  469. GlobalFree(D1PropInfo[D1Prop_ScriptErrorMessage].pData);
  470. }
  471. }
  472. LExit:
  473. if (pMetabase)
  474. pMetabase->Release();
  475. CoUninitialize();
  476. return hr;
  477. }
  478. /*===================================================================
  479. SetConfigToDefaults
  480. Before loading values from the Metabase, set up default values
  481. in case anything goes wrong.
  482. Parameters:
  483. CAppConfig Application Config Object / per application
  484. fLoadGlob if fLoadGlob is TRUE, load glob data, otherwise, load data into AppConfig object.
  485. Returns:
  486. HRESULT - S_OK on success
  487. Side effects:
  488. ===================================================================*/
  489. HRESULT SetConfigToDefaults(CAppConfig *pAppConfig, BOOL fLoadGlob)
  490. {
  491. HRESULT hr = S_OK;
  492. DWORD dwMDUserType = 0;
  493. BYTE *szRegString = NULL;
  494. UINT iEntry = 0;
  495. if (fLoadGlob)
  496. {
  497. dwMDUserType = IIS_MD_UT_WAM;
  498. }
  499. else
  500. {
  501. dwMDUserType = ASP_MD_UT_APP;
  502. }
  503. for(iEntry = 0; iEntry < cPropsMax; iEntry++)
  504. {
  505. if (rgMDPropInfo[iEntry].dwUserType != dwMDUserType)
  506. continue;
  507. // After metabase has been read once, data with fAdminConfig = FALSE cant be changed on the fly.
  508. // so we dont bother to reset it
  509. if (fLoadGlob)
  510. {
  511. if (TRUE == Glob(fMDRead) && FALSE == rgMDPropInfo[iEntry].fAdminConfig)
  512. {
  513. continue;
  514. }
  515. }
  516. else
  517. {
  518. if (TRUE == pAppConfig->fInited() && FALSE == rgMDPropInfo[iEntry].fAdminConfig)
  519. {
  520. continue;
  521. }
  522. }
  523. switch (rgMDPropInfo[iEntry].dwType)
  524. {
  525. case DWORD_METADATA:
  526. if (fLoadGlob)
  527. gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)&rgMDPropInfo[iEntry].dwDefault);
  528. else
  529. hr = pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)&rgMDPropInfo[iEntry].dwDefault);
  530. break;
  531. case STRING_METADATA:
  532. case EXPANDSZ_METADATA:
  533. if (rgMDPropInfo[iEntry].idDefault == 0xffffffff)
  534. continue;
  535. szRegString = (BYTE *)GlobalAlloc(GPTR, DEFAULTSTRSIZE);
  536. if (szRegString == NULL) {
  537. hr = E_OUTOFMEMORY;
  538. break;
  539. }
  540. CchLoadStringOfId(rgMDPropInfo[iEntry].idDefault, (LPSTR)szRegString, DEFAULTSTRSIZE);
  541. if (rgMDPropInfo[iEntry].dwType == EXPANDSZ_METADATA) {
  542. BYTE *pszExpanded = (BYTE *)GlobalAlloc(GPTR, DEFAULTSTRSIZE);
  543. if (pszExpanded == NULL) {
  544. hr = E_OUTOFMEMORY;
  545. break;
  546. }
  547. INT result = ExpandEnvironmentStringsA((LPCSTR)szRegString,
  548. (LPSTR)pszExpanded,
  549. DEFAULTSTRSIZE);
  550. if ((result <= DEFAULTSTRSIZE) && (result > 0)) {
  551. GlobalFree(szRegString);
  552. szRegString = pszExpanded;
  553. }
  554. }
  555. if (fLoadGlob)
  556. gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
  557. else
  558. hr = pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
  559. break;
  560. default:
  561. Assert(FALSE);
  562. break;
  563. }
  564. }
  565. return hr;
  566. }
  567. /*===================================================================
  568. ReadConfigFromMD
  569. Read our properties from the registry. If our props are missing, the
  570. registry is messed up, try to re-register. If our props are there, but
  571. one or more values is missing, use the defaults.
  572. Parameters:
  573. CAppConfig Application Config Object / per application
  574. fLoadGlob if fLoadGlob is TRUE, load glob data, otherwise, load data into AppConfig object.
  575. Returns:
  576. HRESULT - S_OK on success
  577. Side effects:
  578. ===================================================================*/
  579. HRESULT ReadConfigFromMD
  580. (
  581. CIsapiReqInfo *pIReq,
  582. CAppConfig *pAppConfig,
  583. BOOL fLoadGlob
  584. )
  585. {
  586. HRESULT hr = S_OK;
  587. HRESULT hrT = S_OK;
  588. DWORD dwNumDataEntries = 0;
  589. DWORD cbRequired = 0;
  590. DWORD dwMDUserType = 0;
  591. DWORD cbBuffer;
  592. BYTE bBuffer[2000];
  593. BYTE *pBuffer = NULL;
  594. BYTE *szRegString = NULL;
  595. BOOL fAllocBuffer = FALSE;
  596. CHAR szMDOORange[DEFAULTSTRSIZE];
  597. TCHAR szMDGlobPath[] = _T("\\LM\\W3SVC");
  598. TCHAR *szMDPath = NULL;
  599. UINT iEntry = 0;
  600. METADATA_GETALL_RECORD *pMDGetAllRec;
  601. if (fLoadGlob)
  602. {
  603. // BUGs 88902, 105745:
  604. // If we are InProc, then use the "root" path for global values
  605. // If OutOfProc, then use the app path for global values
  606. if (pIReq->FInPool())
  607. szMDPath = szMDGlobPath;
  608. else
  609. szMDPath = pIReq->QueryPszApplnMDPath();
  610. dwMDUserType = IIS_MD_UT_WAM;
  611. }
  612. else
  613. {
  614. dwMDUserType = ASP_MD_UT_APP;
  615. szMDPath = pAppConfig->SzMDPath();
  616. }
  617. Assert(szMDPath != NULL);
  618. //
  619. // At this point szMDPath should never be NULL if it is then we bail out.
  620. //
  621. if (!szMDPath)
  622. {
  623. DBGPRINTF((DBG_CONTEXT,"ReadConfigFromMD: szMDPath is NULL\n"));
  624. return E_FAIL;
  625. }
  626. // PreLoad config data with default, in case anything failed.
  627. hr = SetConfigToDefaults(pAppConfig, fLoadGlob);
  628. if (FAILED(hr))
  629. {
  630. Assert(FALSE);
  631. DBGPRINTF((DBG_CONTEXT,"ReadConfigFromMD: Setting defaults failed with %x\n",hr));
  632. return hr;
  633. }
  634. // Set flags.
  635. //
  636. BOOL fConfigLoaded[cPropsMax];
  637. for (iEntry = 0; iEntry < cPropsMax; iEntry++) {
  638. fConfigLoaded[iEntry] = FALSE;
  639. }
  640. pBuffer = bBuffer;
  641. hr = pIReq->GetAspMDAllData(szMDPath,
  642. dwMDUserType,
  643. sizeof(bBuffer),
  644. (unsigned char *)pBuffer,
  645. &cbRequired,
  646. &dwNumDataEntries
  647. );
  648. if (hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
  649. pBuffer = (BYTE *)GlobalAlloc(GPTR, cbRequired);
  650. if (pBuffer == NULL)
  651. return E_OUTOFMEMORY;
  652. fAllocBuffer = TRUE;
  653. cbBuffer = cbRequired;
  654. hr = pIReq->GetAspMDAllData(szMDPath,
  655. dwMDUserType,
  656. cbRequired,
  657. (unsigned char *)pBuffer,
  658. &cbRequired,
  659. &dwNumDataEntries);
  660. }
  661. if (FAILED(hr)) {
  662. DBGPRINTF((DBG_CONTEXT,"ReadConfigFromMD: GetAspMDAllData failed with %x\n",hr));
  663. return hr;
  664. }
  665. else {
  666. INT cProps = 0;
  667. pMDGetAllRec = (METADATA_GETALL_RECORD *)pBuffer;
  668. for (UINT iValue = 0; iValue < dwNumDataEntries; iValue ++)
  669. {
  670. DWORD dwData;
  671. DWORD iTemp;
  672. DWORD cbStr;
  673. CHAR szMDOORangeFormat[DEFAULTSTRSIZE];
  674. // Init iEntry to be -1, -1 is invalid for rgMDPropInfo[] Array Index.
  675. iEntry = -1;
  676. for (iTemp = 0; iTemp < cPropsMax; iTemp++) {
  677. if (rgMDPropInfo[iTemp].dwMDIdentifier == pMDGetAllRec->dwMDIdentifier) {
  678. iEntry = iTemp;
  679. break;
  680. }
  681. }
  682. // Not found
  683. if (iEntry == -1) {
  684. pMDGetAllRec++;
  685. continue;
  686. }
  687. // Do found the entry in rgMDPropInfo, but datatype does not match.
  688. // Should never happen.
  689. if (rgMDPropInfo[iEntry].dwUserType != dwMDUserType) { // GetAllData should filter out the unwanted UserType.
  690. Assert(FALSE);
  691. pMDGetAllRec++;
  692. continue;
  693. }
  694. cProps++;
  695. // After metabase has been read once, data with fAdminConfig = FALSE cant be changed on the fly.
  696. // so we dont bother to reread it
  697. if (fLoadGlob) {
  698. if (TRUE == Glob(fMDRead) && FALSE == rgMDPropInfo[iEntry].fAdminConfig) {
  699. pMDGetAllRec++;
  700. continue;
  701. }
  702. }
  703. else {
  704. if (TRUE == pAppConfig->fInited() && FALSE == rgMDPropInfo[iEntry].fAdminConfig) {
  705. pMDGetAllRec++;
  706. continue;
  707. }
  708. }
  709. switch(pMDGetAllRec->dwMDDataType) {
  710. case DWORD_METADATA:
  711. Assert(pMDGetAllRec->dwMDDataLen == sizeof(DWORD));
  712. dwData = *(UNALIGNED64 DWORD *)(pBuffer + pMDGetAllRec->dwMDDataOffset);
  713. if (dwData > rgMDPropInfo[iEntry].dwValueMax) {
  714. szMDOORange[0] = '\0';
  715. CchLoadStringOfId(IDS_MDOORANGE_FORMAT, szMDOORangeFormat, DEFAULTSTRSIZE);
  716. sprintf(szMDOORange, szMDOORangeFormat,
  717. rgMDPropInfo[iEntry].dwMDIdentifier,
  718. rgMDPropInfo[iEntry].dwValueMax);
  719. MSG_Warning((LPCSTR)szMDOORange);
  720. dwData = rgMDPropInfo[iEntry].dwValueMax;
  721. }
  722. if (dwData < rgMDPropInfo[iEntry].dwValueMin) {
  723. szMDOORange[0] = '\0';
  724. CchLoadStringOfId(IDS_MDOORANGE_FORMAT, szMDOORangeFormat, DEFAULTSTRSIZE);
  725. sprintf(szMDOORange, szMDOORangeFormat,
  726. rgMDPropInfo[iEntry].dwMDIdentifier,
  727. rgMDPropInfo[iEntry].dwValueMin);
  728. MSG_Warning((LPCSTR)szMDOORange);
  729. dwData = rgMDPropInfo[iEntry].dwValueMin;
  730. }
  731. if (fLoadGlob)
  732. gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)&dwData);
  733. else
  734. pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)&dwData);
  735. fConfigLoaded[iEntry] = TRUE;
  736. break;
  737. case STRING_METADATA:
  738. case EXPANDSZ_METADATA:
  739. // bug fix 102010 DBCS fixes (& 99806)
  740. //cbStr = (pMDGetAllRec->dwMDDataLen) / sizeof(WCHAR);
  741. cbStr = pMDGetAllRec->dwMDDataLen;
  742. szRegString = (BYTE *)GlobalAlloc(GPTR, cbStr);
  743. if (szRegString == NULL) {
  744. hr = E_OUTOFMEMORY;
  745. break;
  746. }
  747. WideCharToMultiByte(CP_ACP, 0, (LPWSTR)(pBuffer + pMDGetAllRec->dwMDDataOffset), -1,
  748. (LPSTR)szRegString, cbStr, NULL, NULL);
  749. if (pMDGetAllRec->dwMDDataType == EXPANDSZ_METADATA) {
  750. BYTE *pszExpanded = (BYTE *)GlobalAlloc(GPTR, DEFAULTSTRSIZE);
  751. if (pszExpanded == NULL) {
  752. hr = E_OUTOFMEMORY;
  753. break;
  754. }
  755. INT result = ExpandEnvironmentStringsA((LPCSTR)szRegString,
  756. (LPSTR)pszExpanded,
  757. DEFAULTSTRSIZE);
  758. if ((result <= DEFAULTSTRSIZE) && (result > 0)) {
  759. GlobalFree(szRegString);
  760. szRegString = pszExpanded;
  761. }
  762. }
  763. if (fLoadGlob)
  764. gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
  765. else
  766. pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
  767. fConfigLoaded[iEntry] = TRUE;
  768. szRegString = NULL;
  769. break;
  770. default:
  771. Assert(FALSE);
  772. break;
  773. }
  774. pMDGetAllRec++;
  775. }
  776. }
  777. if (SUCCEEDED(hr) && !gGlob.m_fMDRead && fLoadGlob)
  778. gGlob.m_fMDRead = TRUE;
  779. if (fAllocBuffer == TRUE) {
  780. GlobalFree(pBuffer);
  781. }
  782. return hr;
  783. }
  784. /*==================================================================
  785. CMDGlobConfigSink::CMDGlobConfigSink
  786. Constructor
  787. ===================================================================*/
  788. CMDGlobConfigSink::CMDGlobConfigSink()
  789. {
  790. m_cRef = 1;
  791. InterlockedCompareExchange(&g_fProceedWithShutdownGlob,0,1);
  792. }
  793. /*==================================================================
  794. CMDGlobConfigSink::~CMDGlobConfigSink
  795. Destructor
  796. ===================================================================*/
  797. CMDGlobConfigSink::~CMDGlobConfigSink()
  798. {
  799. InterlockedCompareExchange(&g_fProceedWithShutdownGlob,1,0);
  800. }
  801. /*==================================================================
  802. CMDGlobConfigSink::QueryInterface
  803. Returns:
  804. HRESULT - S_OK on success
  805. Side effects:
  806. ===================================================================*/
  807. STDMETHODIMP CMDGlobConfigSink::QueryInterface(REFIID iid, void **ppv)
  808. {
  809. *ppv = NULL;
  810. if (iid == IID_IUnknown || iid == IID_IMSAdminBaseSink)
  811. *ppv = (IMSAdminBaseSink *)this;
  812. else
  813. return ResultFromScode(E_NOINTERFACE);
  814. ((IUnknown *)*ppv)->AddRef();
  815. return S_OK;
  816. }
  817. /*==================================================================
  818. CMDGlobConfigSink::AddRef
  819. Returns:
  820. ULONG - The new ref counter of object
  821. Side effects:
  822. ===================================================================*/
  823. STDMETHODIMP_(ULONG) CMDGlobConfigSink::AddRef(void)
  824. {
  825. LONG cRefs = InterlockedIncrement((long *)&m_cRef);
  826. return cRefs;
  827. }
  828. /*==================================================================
  829. CMDGlobConfigSink::Release
  830. Returns:
  831. ULONG - The new ref counter of object
  832. Side effects: Delete object if ref counter is zero.
  833. ===================================================================*/
  834. STDMETHODIMP_(ULONG) CMDGlobConfigSink::Release(void)
  835. {
  836. LONG cRefs = InterlockedDecrement((long *)&m_cRef);
  837. if (cRefs == 0)
  838. {
  839. delete this;
  840. }
  841. return cRefs;
  842. }
  843. /*==================================================================
  844. CMDGlobConfigSink::SinkNotify
  845. Returns:
  846. HRESULT - S_OK on success
  847. Side effects: Set fNeedUpdate to TRUE, and glob data will gets update next time a request coming in.
  848. ===================================================================*/
  849. STDMETHODIMP CMDGlobConfigSink::SinkNotify(
  850. DWORD dwMDNumElements,
  851. MD_CHANGE_OBJECT_W __RPC_FAR pcoChangeList[])
  852. {
  853. if (IsShutDownInProgress())
  854. return S_OK;
  855. UINT iEventNum = 0;
  856. DWORD iDataIDNum = 0;
  857. WCHAR wszMDPath[] = L"/LM/W3SVC/";
  858. UINT cSize = 0;
  859. cSize = wcslen(wszMDPath);
  860. for (iEventNum = 0; iEventNum < dwMDNumElements; iEventNum++)
  861. {
  862. if (0 == wcsnicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath, cSize + 1))
  863. {
  864. for (iDataIDNum = 0; iDataIDNum < pcoChangeList[iEventNum].dwMDNumDataIDs; iDataIDNum++)
  865. {
  866. if (pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] >= ASP_MD_SERVER_BASE
  867. && pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] <= MD_ASP_ID_LAST)
  868. {
  869. gGlob.NotifyNeedUpdate();
  870. return S_OK;
  871. }
  872. }
  873. }
  874. }
  875. return S_OK;
  876. }
  877. /*===================================================================
  878. MDUnRegisterProperties
  879. Remove info about our properties in the Metabase.
  880. Returns:
  881. HRESULT - S_OK on success
  882. Side effects:
  883. Removes denali properties in the Metabase
  884. // to settings per dll.
  885. ===================================================================*/
  886. HRESULT MDUnRegisterProperties(void)
  887. {
  888. HRESULT hr = S_OK;
  889. DWORD iValue;
  890. IMSAdminBase *pMetabase = NULL;
  891. METADATA_HANDLE hMetabase = NULL;
  892. BYTE szDefaultString[DEFAULTSTRSIZE];
  893. BOOL fMDSaveData = TRUE;
  894. HRESULT hrT = S_OK;
  895. hr = CoInitialize(NULL);
  896. if (FAILED(hr))
  897. {
  898. return hr;
  899. }
  900. hr = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_SERVER, IID_IMSAdminBase, (void **)&pMetabase);
  901. if (FAILED(hr))
  902. {
  903. CoUninitialize();
  904. return hr;
  905. }
  906. // Open key to the Web service, and get a handle of \LM\w3svc
  907. hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)L"\\LM\\W3SVC",
  908. METADATA_PERMISSION_WRITE, dwMDDefaultTimeOut, &hMetabase);
  909. if (FAILED(hr))
  910. {
  911. goto LExit;
  912. }
  913. for (iValue = 0; iValue < cPropsMax; iValue++)
  914. {
  915. hr = pMetabase->DeleteData( hMetabase,
  916. NULL,
  917. rgMDPropInfo[iValue].dwMDIdentifier,
  918. 0);
  919. if (FAILED(hr))
  920. {
  921. if (hr == MD_ERROR_DATA_NOT_FOUND)
  922. {
  923. hr = S_OK;
  924. }
  925. else
  926. {
  927. Assert(FALSE);
  928. }
  929. }
  930. }
  931. hrT = pMetabase->CloseKey(hMetabase);
  932. // Add data to W3SVC
  933. LExit:
  934. if (pMetabase)
  935. pMetabase->Release();
  936. CoUninitialize();
  937. return hr;
  938. }
  939. HRESULT GetMetabaseIF(IMSAdminBase **hMetabase)
  940. {
  941. IClassFactory *pcsfFactory = NULL;
  942. HRESULT hr;
  943. hr = CoGetClassObject(
  944. CLSID_MSAdminBase,
  945. CLSCTX_SERVER,
  946. NULL,
  947. IID_IClassFactory,
  948. (void **)&pcsfFactory);
  949. if (FAILED(hr)) {
  950. DBGPRINTF((DBG_CONTEXT,"MDInit: CoGetClassObject failed with %x\n",hr));
  951. return hr;
  952. }
  953. hr = pcsfFactory->CreateInstance(
  954. NULL,
  955. IID_IMSAdminBase,
  956. (void **) hMetabase);
  957. pcsfFactory->Release();
  958. if (FAILED(hr)) {
  959. DBGPRINTF((DBG_CONTEXT,"MDInit: CreateInstance failed with %x\n",hr));
  960. goto LExit;
  961. }
  962. Assert(*hMetabase != NULL);
  963. if (FAILED(hr))
  964. {
  965. (*hMetabase)->Release();
  966. (*hMetabase) = NULL;
  967. goto LExit;
  968. }
  969. LExit:
  970. return(hr);
  971. }
  972. /*===================================================================
  973. Cglob::CGlob
  974. Constructor. Fill glob with some default values.
  975. in:
  976. returns:
  977. Side effects:
  978. ===================================================================*/
  979. CGlob::CGlob()
  980. :
  981. m_pITypeLibDenali(NULL),
  982. m_pITypeLibTxn(NULL),
  983. m_dwNumberOfProcessors(1),
  984. m_fInited(FALSE),
  985. m_fMDRead(FALSE),
  986. m_fNeedUpdate(TRUE),
  987. m_dwScriptEngineCacheMax(120),
  988. m_dwScriptFileCacheSize(dwUnlimited),
  989. m_fLogErrorRequests(TRUE),
  990. m_fExceptionCatchEnable(TRUE),
  991. m_fAllowOutOfProcCmpnts(FALSE),
  992. m_fAllowDebugging(FALSE),
  993. m_fTrackThreadingModel(FALSE),
  994. m_dwMDSinkCookie(0),
  995. m_pMetabaseSink(NULL),
  996. m_pMetabase(NULL),
  997. m_fEnableAspHtmlFallBack(FALSE),
  998. m_fEnableTypelibCache(TRUE),
  999. m_fEnableChunkedEncoding(TRUE), // UNDONE: temp.
  1000. m_fDupIISLogToNTLog(FALSE),
  1001. m_dwRequestQueueMax(500), // default limit on # of requests
  1002. m_dwProcessorThreadMax(10),
  1003. m_dwPersistTemplateMaxFiles(1000),
  1004. m_pszPersistTemplateDir(NULL)
  1005. {
  1006. SYSTEM_INFO si;
  1007. // Find out how many processors are on this machine
  1008. GetSystemInfo(&si);
  1009. m_dwNumberOfProcessors = si.dwNumberOfProcessors;
  1010. if (m_dwNumberOfProcessors <= 0)
  1011. {
  1012. m_dwNumberOfProcessors = 1; // Just in case!
  1013. }
  1014. }
  1015. /*===================================================================
  1016. Cglob::SetGlobValue
  1017. Set global values.
  1018. in:
  1019. int index the index in the propinfo[]
  1020. BYTE* pData lp to the Data being copied/assigned in the glob.
  1021. returns:
  1022. BOOL TRUE/FALSE
  1023. Side effects:
  1024. Free old string memory and allocate new memory for string.
  1025. ===================================================================*/
  1026. HRESULT CGlob::SetGlobValue(unsigned int iValue, BYTE *pData)
  1027. {
  1028. Assert((iValue < IGlob_MAX) && (pData != NULL));
  1029. switch(iValue) {
  1030. case IGlob_LogErrorRequests:
  1031. InterlockedExchange((LPLONG)&m_fLogErrorRequests, *(LONG *)pData);
  1032. break;
  1033. case IGlob_ScriptFileCacheSize:
  1034. InterlockedExchange((LPLONG)&m_dwScriptFileCacheSize, *(LONG *)pData);
  1035. break;
  1036. case IGlob_ScriptEngineCacheMax:
  1037. InterlockedExchange((LPLONG)&m_dwScriptEngineCacheMax, *(LONG *)pData);
  1038. break;
  1039. case IGlob_ExceptionCatchEnable:
  1040. InterlockedExchange((LPLONG)&m_fExceptionCatchEnable, *(LONG *)pData);
  1041. break;
  1042. case IGlob_TrackThreadingModel:
  1043. InterlockedExchange((LPLONG)&m_fTrackThreadingModel, *(LONG *)pData);
  1044. break;
  1045. case IGlob_AllowOutOfProcCmpnts:
  1046. InterlockedExchange((LPLONG)&m_fAllowOutOfProcCmpnts, *(LONG *)pData);
  1047. break;
  1048. case IGlob_EnableAspHtmlFallback:
  1049. InterlockedExchange((LPLONG)&m_fEnableAspHtmlFallBack, *(LONG *)pData);
  1050. break;
  1051. case IGlob_EnableChunkedEncoding:
  1052. InterlockedExchange((LPLONG)&m_fEnableChunkedEncoding, *(LONG *)pData);
  1053. break;
  1054. case IGlob_EnableTypelibCache:
  1055. InterlockedExchange((LPLONG)&m_fEnableTypelibCache, *(LONG *)pData);
  1056. break;
  1057. case IGlob_ErrorsToNtLog:
  1058. InterlockedExchange((LPLONG)&m_fDupIISLogToNTLog, *(LONG *)pData);
  1059. break;
  1060. case IGlob_ProcessorThreadMax:
  1061. InterlockedExchange((LPLONG)&m_dwProcessorThreadMax, *(LONG *)pData);
  1062. break;
  1063. case IGlob_RequestQueueMax:
  1064. InterlockedExchange((LPLONG)&m_dwRequestQueueMax, *(LONG *)pData);
  1065. break;
  1066. case IGlob_PersistTemplateMaxFiles:
  1067. InterlockedExchange((LPLONG)&m_dwPersistTemplateMaxFiles, *(LONG *)pData);
  1068. break;
  1069. case IGlob_PersistTemplateDir:
  1070. GlobStringUseLock();
  1071. if (m_pszPersistTemplateDir != NULL) {
  1072. GlobalFree(m_pszPersistTemplateDir);
  1073. }
  1074. m_pszPersistTemplateDir = *(LPSTR *)pData;
  1075. GlobStringUseUnLock();
  1076. break;
  1077. default:
  1078. break;
  1079. }
  1080. return S_OK;
  1081. }
  1082. /*===================================================================
  1083. HRESULT CGlob::GlobInit
  1084. Get all interesting global values (mostly from registry)
  1085. Returns:
  1086. HRESULT - S_OK on success
  1087. Side effects:
  1088. fills in glob. May be slow
  1089. ===================================================================*/
  1090. HRESULT CGlob::GlobInit(void)
  1091. {
  1092. HRESULT hr = S_OK;
  1093. m_fInited = FALSE;
  1094. ErrInitCriticalSection(&m_cs, hr);
  1095. if (FAILED(hr))
  1096. return(hr);
  1097. hr = MDInit();
  1098. if (FAILED(hr))
  1099. return hr;
  1100. //Finish loading, any registry change from this moment requires Admin Configurable(TRUE) to take
  1101. //affect. Other registry changes need to have IIS be stopped and restarted.
  1102. m_fInited = TRUE;
  1103. m_fNeedUpdate = FALSE;
  1104. // get the registry based ASP parameters
  1105. g_AspRegistryParams.Init();
  1106. return(hr);
  1107. }
  1108. /*===================================================================
  1109. GlobUnInit
  1110. Free all GlobalString Values.
  1111. Returns:
  1112. HRESULT - S_OK on success
  1113. Side effects:
  1114. memory freed.
  1115. ===================================================================*/
  1116. HRESULT CGlob::GlobUnInit(void)
  1117. {
  1118. HRESULT hr = S_OK;
  1119. MDUnInit();
  1120. //
  1121. // Wait for COM to release the Global Sink
  1122. //
  1123. while (!g_fProceedWithShutdownGlob)
  1124. Sleep(100);
  1125. DeleteCriticalSection(&m_cs);
  1126. return(hr);
  1127. }
  1128. /*==================================================================
  1129. CGlob::MDInit
  1130. 1. Create Metabase interface.
  1131. 2. Load Glob configuration Settings from Metabase
  1132. 2. Register SinkNotify() callback function through Metabase connectionpoint interface.
  1133. Returns:
  1134. HRESULT - S_OK on success
  1135. Side effects: Register SinkNotify().
  1136. ===================================================================*/
  1137. HRESULT CGlob::MDInit(void)
  1138. {
  1139. HRESULT hr = S_OK;
  1140. IConnectionPointContainer *pConnPointContainer = NULL;
  1141. IConnectionPoint *pConnPoint = NULL;
  1142. if (FAILED(hr = GetMetabaseIF(&m_pMetabase))) {
  1143. goto LExit;
  1144. }
  1145. m_pMetabaseSink = new CMDGlobConfigSink();
  1146. if (!m_pMetabaseSink)
  1147. return E_OUTOFMEMORY;
  1148. m_dwMDSinkCookie = 0;
  1149. // Init the Glob structure with defaults. The metabase will actually be read later
  1150. hr = SetConfigToDefaults(NULL, TRUE);
  1151. if (SUCCEEDED(hr)) {
  1152. // Advise Metabase about SinkNotify().
  1153. hr = m_pMetabase->QueryInterface(IID_IConnectionPointContainer, (void **)&pConnPointContainer);
  1154. if (pConnPointContainer != NULL)
  1155. {
  1156. //Find the requested Connection Point. This AddRef's the return pointer.
  1157. hr = pConnPointContainer->FindConnectionPoint(IID_IMSAdminBaseSink, &pConnPoint);
  1158. pConnPointContainer->Release();
  1159. if (pConnPoint != NULL)
  1160. {
  1161. hr = pConnPoint->Advise((IUnknown *)m_pMetabaseSink, &m_dwMDSinkCookie);
  1162. pConnPoint->Release();
  1163. }
  1164. }
  1165. } else {
  1166. DBGPRINTF((DBG_CONTEXT,"MDInit: SetConfigToDefaults failed with %x\n",hr));
  1167. }
  1168. if (FAILED(hr)) //Advise failed
  1169. {
  1170. DBGPRINTF((DBG_CONTEXT,"MDInit: Advise failed with %x\n",hr));
  1171. m_pMetabase->Release();
  1172. m_pMetabase = NULL;
  1173. }
  1174. LExit:
  1175. return hr;
  1176. }
  1177. /*==================================================================
  1178. CGlob::MDUnInit
  1179. 1. UnRegister SinkNofity() from Metabase connectionpoint interface.
  1180. 2. delete m_pMetabaseSink.
  1181. 3. release interface pointer of m_pMetabase.
  1182. Returns:
  1183. HRESULT - S_OK on success
  1184. Side effects: release interface pointer of m_pMetabase
  1185. ===================================================================*/
  1186. HRESULT CGlob::MDUnInit(void)
  1187. {
  1188. HRESULT hr = S_OK;
  1189. IConnectionPointContainer *pConnPointContainer = NULL;
  1190. IConnectionPoint *pConnPoint = NULL;
  1191. IClassFactory *pcsfFactory = NULL;
  1192. if (m_pMetabase != NULL)
  1193. {
  1194. //Advise Metabase about SinkNotify().
  1195. hr = m_pMetabase->QueryInterface(IID_IConnectionPointContainer, (void **)&pConnPointContainer);
  1196. if (pConnPointContainer != NULL)
  1197. {
  1198. //Find the requested Connection Point. This AddRef's the return pointer.
  1199. hr = pConnPointContainer->FindConnectionPoint(IID_IMSAdminBaseSink, &pConnPoint);
  1200. pConnPointContainer->Release();
  1201. if (pConnPoint != NULL)
  1202. {
  1203. hr = pConnPoint->Unadvise(m_dwMDSinkCookie);
  1204. if (FAILED(hr))
  1205. {
  1206. DBGPRINTF((DBG_CONTEXT, "UnAdvise Glob Config Change Notify failed.\n"));
  1207. }
  1208. pConnPoint->Release();
  1209. m_dwMDSinkCookie = 0;
  1210. }
  1211. }
  1212. m_pMetabase->Release();
  1213. m_pMetabase = NULL;
  1214. }
  1215. if (m_pMetabaseSink)
  1216. {
  1217. m_pMetabaseSink->Release();
  1218. m_pMetabaseSink = NULL;
  1219. }
  1220. return hr;
  1221. }
  1222. /*==================================================================
  1223. CMDAppConfigSink::CMDAppConfigSink
  1224. Constructor
  1225. ===================================================================*/
  1226. CMDAppConfigSink::CMDAppConfigSink (CApplnMgr *pApplnMgr)
  1227. {
  1228. m_cRef = 1;
  1229. m_pApplnMgr = pApplnMgr;
  1230. InterlockedCompareExchange(&g_fProceedWithShutdownAppln,0,1);
  1231. }
  1232. /*==================================================================
  1233. CMDAppConfigSink::~CMDAppConfigSink
  1234. Destructor
  1235. ===================================================================*/
  1236. CMDAppConfigSink::~CMDAppConfigSink ()
  1237. {
  1238. InterlockedCompareExchange(&g_fProceedWithShutdownAppln,1,0);
  1239. }
  1240. /*==================================================================
  1241. CMDAppConfigSink::QueryInterface
  1242. Returns:
  1243. HRESULT - S_OK on success
  1244. Side effects:
  1245. ===================================================================*/
  1246. STDMETHODIMP CMDAppConfigSink::QueryInterface(REFIID iid, void **ppv)
  1247. {
  1248. *ppv = 0;
  1249. if (iid == IID_IUnknown || iid == IID_IMSAdminBaseSink)
  1250. *ppv = (IMSAdminBaseSink *)this;
  1251. else
  1252. return ResultFromScode(E_NOINTERFACE);
  1253. ((IUnknown *)*ppv)->AddRef();
  1254. return S_OK;
  1255. }
  1256. /*==================================================================
  1257. CMDAppConfigSink::AddRef
  1258. Returns:
  1259. ULONG - The new ref counter of object
  1260. Side effects:
  1261. ===================================================================*/
  1262. STDMETHODIMP_(ULONG) CMDAppConfigSink::AddRef(void)
  1263. {
  1264. LONG cRefs = InterlockedIncrement((long *)&m_cRef);
  1265. return cRefs;
  1266. }
  1267. /*==================================================================
  1268. CMDGlobConfigSink::Release
  1269. Returns:
  1270. ULONG - The new ref counter of object
  1271. Side effects: Delete object if ref counter is zero.
  1272. ===================================================================*/
  1273. STDMETHODIMP_(ULONG) CMDAppConfigSink::Release(void)
  1274. {
  1275. LONG cRefs = InterlockedDecrement((long *)&m_cRef);
  1276. if (cRefs == 0)
  1277. {
  1278. delete this;
  1279. }
  1280. return cRefs;
  1281. }
  1282. /*==================================================================
  1283. CMDAppConfigSink::SinkNotify
  1284. Returns:
  1285. HRESULT - S_OK on success
  1286. Side effects: Set fNeedUpdate to TRUE, and glob data will gets update next time a request coming in.
  1287. ===================================================================*/
  1288. STDMETHODIMP CMDAppConfigSink::SinkNotify(
  1289. DWORD dwMDNumElements,
  1290. MD_CHANGE_OBJECT_W __RPC_FAR pcoChangeList[])
  1291. {
  1292. if (IsShutDownInProgress())
  1293. return S_OK;
  1294. return m_pApplnMgr->NotifyAllMBListeners(dwMDNumElements,pcoChangeList);
  1295. }
  1296. /*===================================================================
  1297. CAppConfig::CAppConfig
  1298. Returns:
  1299. Nothing
  1300. Side Effects:
  1301. None.
  1302. ===================================================================*/
  1303. CAppConfig::CAppConfig()
  1304. :
  1305. m_dwScriptTimeout(45),
  1306. m_dwSessionTimeout(10),
  1307. m_dwQueueTimeout(0xffffffff),
  1308. m_fScriptErrorsSentToBrowser(TRUE),
  1309. m_fBufferingOn(TRUE),
  1310. m_fEnableParentPaths(TRUE),
  1311. m_fAllowSessionState(TRUE),
  1312. m_fAllowOutOfProcCmpnts(FALSE),
  1313. m_fAllowDebugging(FALSE),
  1314. m_fAllowClientDebug(FALSE),
  1315. m_fExecuteInMTA(FALSE),
  1316. m_fEnableApplicationRestart(TRUE),
  1317. m_dwQueueConnectionTestTime(3),
  1318. m_dwSessionMax(0xffffffff),
  1319. m_fInited(FALSE),
  1320. m_fRestartEnabledUpdated(FALSE),
  1321. m_uCodePage(CP_ACP),
  1322. m_fIsValidProglangCLSID(FALSE),
  1323. m_fIsValidPartitionGUID(FALSE),
  1324. m_fSxsEnabled(FALSE),
  1325. m_fTrackerEnabled(FALSE),
  1326. m_fUsePartition(FALSE),
  1327. m_fRunOnEndAsAnon(TRUE),
  1328. m_hAnonToken(INVALID_HANDLE_VALUE),
  1329. m_dwBufferLimit(DEFAULT_BUFFER_LIMIT),
  1330. m_dwRequestEntityLimit(DEFAULT_REQUEST_ENTITY_LIMIT),
  1331. m_cRefs(1)
  1332. {
  1333. m_uCodePage = GetACP();
  1334. for (UINT cMsg = 0; cMsg < APP_CONFIG_MESSAGEMAX; cMsg++)
  1335. m_szString[cMsg] = 0;
  1336. }
  1337. /*===================================================================
  1338. CAppConfig::Init
  1339. Init the CAppConfig. Only called once.
  1340. in:
  1341. CAppln pAppln The backpointer to Application.
  1342. Side effects:
  1343. Allocate CMDAppConfigSink. Register metabase sink. etc.
  1344. ===================================================================*/
  1345. HRESULT CAppConfig::Init
  1346. (
  1347. CIsapiReqInfo *pIReq,
  1348. CAppln *pAppln
  1349. )
  1350. {
  1351. HRESULT hr=S_OK;
  1352. //
  1353. // Initialize the Lock
  1354. //
  1355. ErrInitCriticalSection( &m_csLock, hr );
  1356. if (FAILED(hr))
  1357. return hr;
  1358. m_fCSInited = TRUE;
  1359. m_pAppln = pAppln;
  1360. //
  1361. // Read info into Glob structure
  1362. //
  1363. hr = ReadConfigFromMD(pIReq, this, FALSE);
  1364. if (SUCCEEDED(hr)) {
  1365. hr = g_ScriptManager.ProgLangIdOfLangName((LPCSTR)m_szString[IAppMsg_SCRIPTLANGUAGE],
  1366. &m_DefaultScriptEngineProgID);
  1367. // BUG 295239:
  1368. // If it failed, we still should create an application because the error message
  1369. // "New Application Failed" is too confusing for the user. This is not a fatal error
  1370. // because it is still (theoretically) possible to run scripts (those with explicit language
  1371. // attributes) Therefore, we reset the hr to S_OK.
  1372. m_fIsValidProglangCLSID = SUCCEEDED(hr);
  1373. hr = S_OK;
  1374. }
  1375. if (SUCCEEDED(hr) && m_szString[IAppMsg_PARTITIONGUID]) {
  1376. BSTR pbstrPartitionGUID = NULL;
  1377. hr = SysAllocStringFromSz(m_szString[IAppMsg_PARTITIONGUID], 0, &pbstrPartitionGUID, CP_ACP);
  1378. if (FAILED(hr)) {
  1379. Assert(0);
  1380. hr = S_OK;
  1381. }
  1382. else {
  1383. hr = CLSIDFromString(pbstrPartitionGUID, &m_PartitionGUID);
  1384. m_fIsValidPartitionGUID = SUCCEEDED(hr);
  1385. hr = S_OK;
  1386. }
  1387. if (pbstrPartitionGUID)
  1388. SysFreeString(pbstrPartitionGUID);
  1389. }
  1390. if (SUCCEEDED(hr) && fRunOnEndAsAnon()) {
  1391. if (pIReq->ServerSupportFunction(HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN,
  1392. pAppln->GetApplnPath(SOURCEPATHTYPE_VIRTUAL),
  1393. (DWORD *)&m_hAnonToken,
  1394. NULL) == FALSE) {
  1395. // if the SSF fails, just revert the handle to the INVALID_VALUE. We could fail
  1396. // here, but we don't really know if this will even be needed as there may not be
  1397. // a global.asa or if there is a global.asa, there might not be OnEnd functions.
  1398. m_hAnonToken = INVALID_HANDLE_VALUE;
  1399. }
  1400. }
  1401. m_fInited = TRUE;
  1402. m_fNeedUpdate = FALSE;
  1403. return hr;
  1404. }
  1405. /*===================================================================
  1406. CAppConfig::UnInit
  1407. UnInit the CAppConfig. Only called once.
  1408. in:
  1409. None.
  1410. Side effects:
  1411. DeAllocate CMDAppConfigSink. disconnect metabase sink. etc.
  1412. ===================================================================*/
  1413. HRESULT CAppConfig::UnInit(void)
  1414. {
  1415. for (int iStr = 0; iStr < APP_CONFIG_MESSAGEMAX; iStr++)
  1416. {
  1417. if (m_szString[iStr] != NULL)
  1418. {
  1419. GlobalFree(m_szString[iStr]);
  1420. m_szString[iStr] = NULL;
  1421. }
  1422. }
  1423. if (m_hAnonToken != INVALID_HANDLE_VALUE)
  1424. CloseHandle(m_hAnonToken);
  1425. return S_OK;
  1426. }
  1427. ULONG STDMETHODCALLTYPE CAppConfig::AddRef(void)
  1428. {
  1429. ULONG cRef = InterlockedIncrement ((LPLONG)&m_cRefs);
  1430. return cRef;
  1431. }
  1432. ULONG STDMETHODCALLTYPE CAppConfig::Release(void)
  1433. {
  1434. ULONG cRef = InterlockedDecrement ((LPLONG)&m_cRefs);
  1435. if (m_cRefs == 0)
  1436. delete this;
  1437. return cRef;
  1438. }
  1439. /*==================================================================
  1440. CAppConfig::SinkNotify
  1441. Returns:
  1442. HRESULT - S_OK on success
  1443. Side effects: Set fNeedUpdate to TRUE, and glob data will gets update next time a request coming in.
  1444. ===================================================================*/
  1445. STDMETHODIMP CAppConfig::SinkNotify(
  1446. DWORD dwMDNumElements,
  1447. MD_CHANGE_OBJECT_W __RPC_FAR pcoChangeList[])
  1448. {
  1449. if (IsShutDownInProgress())
  1450. return S_OK;
  1451. UINT iEventNum = 0;
  1452. DWORD iDataIDNum = 0;
  1453. WCHAR *wszMDPath = NULL;
  1454. BOOL fWszMDPathAllocd = FALSE;
  1455. UINT cSize = 0;
  1456. HRESULT hr = S_OK;
  1457. BOOL fRestartAppln = FALSE;
  1458. // Lock while we are in here to prevent the appconfig object from being
  1459. // cleaned up underneath of us
  1460. Lock();
  1461. #if UNICODE
  1462. wszMDPath = SzMDPath();
  1463. cSize = wcslen(wszMDPath);
  1464. // Tag on a trailing '/'because the directories in pszMDPath will have one
  1465. if (wszMDPath[cSize - 1] != L'/') {
  1466. wszMDPath = new WCHAR[cSize+2];
  1467. if (wszMDPath == NULL) {
  1468. hr = E_OUTOFMEMORY;
  1469. goto LExit;
  1470. }
  1471. fWszMDPathAllocd = TRUE;
  1472. wcscpy(wszMDPath, SzMDPath());
  1473. wszMDPath[cSize] = L'/';
  1474. wszMDPath[cSize + 1] = 0;
  1475. }
  1476. #else
  1477. CHAR * szMDPathT = SzMDPath();
  1478. Assert(szMDPathT != NULL);
  1479. DWORD cbStr = strlen(szMDPathT);
  1480. wszMDPath = new WCHAR[cbStr + 2]; // Allow for adding trailing '/' and '\0'
  1481. if (wszMDPath == NULL) {
  1482. hr = E_OUTOFMEMORY;
  1483. goto LExit;
  1484. }
  1485. fWszMDPathAllocd = TRUE;
  1486. cSize = MultiByteToWideChar(CP_ACP, 0, szMDPathT, cbStr, wszMDPath, cbStr + 2);
  1487. if (cSize == 0) {
  1488. hr = HRESULT_FROM_WIN32(GetLastError());
  1489. goto LExit;
  1490. }
  1491. wszMDPath[cSize] = 0;
  1492. wszMDPath[cSize + 1] = 0;
  1493. // Tag on a trailing '/'because the directories in pszMDPath will have one
  1494. if (wszMDPath[cSize - 1] != L'/') {
  1495. wszMDPath[cSize] = L'/';
  1496. }
  1497. #endif
  1498. for (iEventNum = 0; iEventNum < dwMDNumElements; iEventNum++)
  1499. {
  1500. DWORD dwMDChangeType = pcoChangeList[iEventNum].dwMDChangeType;
  1501. if ((dwMDChangeType == MD_CHANGE_TYPE_DELETE_OBJECT) || (dwMDChangeType == MD_CHANGE_TYPE_RENAME_OBJECT))
  1502. {
  1503. if (wcsicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath) == 0)
  1504. {
  1505. fRestartAppln = TRUE;
  1506. }
  1507. }
  1508. if (0 == wcsnicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath, min(cSize, wcslen((LPWSTR)pcoChangeList[iEventNum].pszMDPath))))
  1509. {
  1510. for (iDataIDNum = 0; iDataIDNum < pcoChangeList[iEventNum].dwMDNumDataIDs; iDataIDNum++)
  1511. {
  1512. if (pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] == MD_VR_PATH)
  1513. {
  1514. if (wcsicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath) == 0)
  1515. {
  1516. fRestartAppln = TRUE;
  1517. }
  1518. }
  1519. if (pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] >= ASP_MD_SERVER_BASE
  1520. && pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] <= MD_ASP_ID_LAST)
  1521. {
  1522. if (fNeedUpdate() == FALSE)
  1523. NotifyNeedUpdate();
  1524. if ((pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] == MD_ASP_ENABLEAPPLICATIONRESTART)
  1525. && (wcsicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath) == 0))
  1526. {
  1527. NotifyRestartEnabledUpdated();
  1528. goto LExit;
  1529. }
  1530. }
  1531. }
  1532. }
  1533. }
  1534. LExit:
  1535. UnLock();
  1536. if (fWszMDPathAllocd)
  1537. delete [] wszMDPath;
  1538. //
  1539. // The Restart() call an potentially delete the parent (no applications locked)
  1540. // If we restart just as we exit the thread then there is no race condition.
  1541. // The two cases where the race could still occur are covered with the locks on the ApplnMgr. The places are
  1542. // (1) NotifyRestartEnabledUpdate which can be used to restart only from AssignApplnToBrowserRequest which is protected by a g_ApplnMgr.Lock() critsec and
  1543. // (2) Another SinkNotify (which will be on another RPC thread and so protected by the same g_ApplnMgr.Lock() critsec
  1544. //
  1545. if (fRestartAppln)
  1546. m_pAppln->Restart(TRUE);
  1547. return hr;
  1548. }
  1549. /*===================================================================
  1550. CAppConfig::szMDPath
  1551. in:
  1552. None
  1553. returns:
  1554. LPTSTR: ptr to szmetabsekey
  1555. Side effects:
  1556. Get MetabaseKey
  1557. ===================================================================*/
  1558. LPTSTR CAppConfig::SzMDPath()
  1559. {
  1560. return m_pAppln->GetMetabaseKey();
  1561. }
  1562. /*===================================================================
  1563. CAppConfig::SetValue
  1564. in:
  1565. int index the index in the propinfo[]
  1566. BYTE* pData lp to the Data being copied/assigned in the glob.
  1567. returns:
  1568. BOOL TRUE/FALSE
  1569. Side effects:
  1570. Free old string memory and allocate new memory for string.
  1571. ===================================================================*/
  1572. HRESULT CAppConfig::SetValue(unsigned int iValue, BYTE *pData)
  1573. {
  1574. HRESULT hr = S_OK;
  1575. Assert((iValue < IApp_MAX) && (pData != NULL));
  1576. switch(iValue) {
  1577. case IApp_CodePage: {
  1578. LONG lCodePage = *(LONG *)pData;
  1579. if (lCodePage == 0)
  1580. lCodePage = GetACP();
  1581. InterlockedExchange((LPLONG)&m_uCodePage, lCodePage);
  1582. break;
  1583. }
  1584. case IApp_BufferingOn:
  1585. InterlockedExchange((LPLONG)&m_fBufferingOn, *(LONG *)pData);
  1586. break;
  1587. case IApp_ScriptErrorsSenttoBrowser:
  1588. InterlockedExchange((LPLONG)&m_fScriptErrorsSentToBrowser, *(LONG *)pData);
  1589. break;
  1590. case IApp_ScriptErrorMessage:
  1591. GlobStringUseLock();
  1592. if (m_szString[IAppMsg_SCRIPTERROR] != NULL) {
  1593. GlobalFree(m_szString[IAppMsg_SCRIPTERROR]);
  1594. }
  1595. m_szString[IAppMsg_SCRIPTERROR] = *(LPSTR *)pData;
  1596. GlobStringUseUnLock();
  1597. break;
  1598. case IApp_ScriptTimeout:
  1599. InterlockedExchange((LPLONG)&m_dwScriptTimeout, *(LONG *)pData);
  1600. break;
  1601. case IApp_SessionTimeout:
  1602. InterlockedExchange((LPLONG)&m_dwSessionTimeout, *(LONG *)pData);
  1603. break;
  1604. case IApp_QueueTimeout:
  1605. InterlockedExchange((LPLONG)&m_dwQueueTimeout, *(LONG *)pData);
  1606. break;
  1607. case IApp_EnableParentPaths:
  1608. InterlockedExchange((LPLONG)&m_fEnableParentPaths, !*(LONG *)pData);
  1609. break;
  1610. case IApp_AllowSessionState:
  1611. InterlockedExchange((LPLONG)&m_fAllowSessionState, *(LONG *)pData);
  1612. break;
  1613. case IApp_ScriptLanguage:
  1614. GlobStringUseLock();
  1615. if (m_szString[IAppMsg_SCRIPTLANGUAGE] != NULL) {
  1616. GlobalFree(m_szString[IAppMsg_SCRIPTLANGUAGE] );
  1617. }
  1618. m_szString[IAppMsg_SCRIPTLANGUAGE] = *(LPSTR *)pData;
  1619. if (m_szString[IAppMsg_SCRIPTLANGUAGE] != NULL) {
  1620. if('\0' == m_szString[IAppMsg_SCRIPTLANGUAGE][0]) {
  1621. WCHAR wszString[128];
  1622. CwchLoadStringOfId(IDS_SCRIPTLANGUAGE, wszString, 128);
  1623. MSG_Warning(MSG_APPL_WARNING_DEFAULT_SCRIPTLANGUAGE, m_pAppln->GetMetabaseKey(), wszString);
  1624. GlobalFree(m_szString[IAppMsg_SCRIPTLANGUAGE] );
  1625. m_szString[IAppMsg_SCRIPTLANGUAGE] = (LPSTR)GlobalAlloc(GPTR, 128);
  1626. CchLoadStringOfId(IDS_SCRIPTLANGUAGE, (LPSTR)m_szString[IAppMsg_SCRIPTLANGUAGE], 128);
  1627. }
  1628. }
  1629. hr = g_ScriptManager.ProgLangIdOfLangName((LPCSTR)m_szString[IAppMsg_SCRIPTLANGUAGE],
  1630. &m_DefaultScriptEngineProgID);
  1631. GlobStringUseUnLock();
  1632. break;
  1633. case IApp_AllowClientDebug:
  1634. InterlockedExchange((LPLONG)&m_fAllowClientDebug, *(LONG *)pData);
  1635. break;
  1636. case IApp_AllowDebugging:
  1637. InterlockedExchange((LPLONG)&m_fAllowDebugging, *(LONG *)pData);
  1638. break;
  1639. case IApp_EnableApplicationRestart:
  1640. InterlockedExchange((LPLONG)&m_fEnableApplicationRestart, *(LONG *)pData);
  1641. break;
  1642. case IApp_QueueConnectionTestTime:
  1643. InterlockedExchange((LPLONG)&m_dwQueueConnectionTestTime, *(LONG *)pData);
  1644. break;
  1645. case IApp_SessionMax:
  1646. InterlockedExchange((LPLONG)&m_dwSessionMax, *(LONG *)pData);
  1647. break;
  1648. case IApp_ExecuteInMTA:
  1649. InterlockedExchange((LPLONG)&m_fExecuteInMTA, *(LONG *)pData);
  1650. break;
  1651. case IApp_LCID:
  1652. InterlockedExchange((LPLONG)&m_uLCID, *(LONG *)pData);
  1653. break;
  1654. case IApp_KeepSessionIDSecure:
  1655. InterlockedExchange((LPLONG)&m_fKeepSessionIDSecure, *(LONG *)pData);
  1656. break;
  1657. case IApp_CalcLineNumber:
  1658. InterlockedExchange((LPLONG)&m_fCalcLineNumber, *(LONG *)pData);
  1659. break;
  1660. case IApp_ServiceFlags:
  1661. InterlockedExchange((LPLONG)&m_fTrackerEnabled, !!((*(LONG *)pData) & IFlag_SF_TrackerEnabled));
  1662. InterlockedExchange((LPLONG)&m_fSxsEnabled, !!((*(LONG *)pData) & IFlag_SF_SxsEnabled));
  1663. InterlockedExchange((LPLONG)&m_fUsePartition, !!((*(LONG *)pData) & IFlag_SF_UsePartition));
  1664. break;
  1665. case IApp_PartitionGUID:
  1666. GlobStringUseLock();
  1667. if (m_szString[IAppMsg_PARTITIONGUID] != NULL) {
  1668. GlobalFree(m_szString[IAppMsg_PARTITIONGUID] );
  1669. }
  1670. m_szString[IAppMsg_PARTITIONGUID] = *(LPSTR *)pData;
  1671. if (m_szString[IAppMsg_PARTITIONGUID] != NULL) {
  1672. if('\0' == m_szString[IAppMsg_PARTITIONGUID][0]) {
  1673. GlobalFree(m_szString[IAppMsg_PARTITIONGUID] );
  1674. m_szString[IAppMsg_PARTITIONGUID] = NULL;
  1675. }
  1676. }
  1677. GlobStringUseUnLock();
  1678. break;
  1679. case IApp_SxsName:
  1680. GlobStringUseLock();
  1681. if (m_szString[IAppMsg_SXSNAME] != NULL) {
  1682. GlobalFree(m_szString[IAppMsg_SXSNAME] );
  1683. }
  1684. m_szString[IAppMsg_SXSNAME] = *(LPSTR *)pData;
  1685. if (m_szString[IAppMsg_SXSNAME] != NULL) {
  1686. if('\0' == m_szString[IAppMsg_SXSNAME][0]) {
  1687. GlobalFree(m_szString[IAppMsg_SXSNAME] );
  1688. m_szString[IAppMsg_SXSNAME] = NULL;
  1689. }
  1690. }
  1691. GlobStringUseUnLock();
  1692. break;
  1693. case IApp_RunOnEndAsAnon:
  1694. InterlockedExchange((LPLONG)&m_fRunOnEndAsAnon, *(LONG *)pData);
  1695. break;
  1696. case IApp_BufferLimit:
  1697. InterlockedExchange((LPLONG)&m_dwBufferLimit, *(LONG *)pData);
  1698. break;
  1699. case IApp_RequestEntityLimit:
  1700. InterlockedExchange((LPLONG)&m_dwRequestEntityLimit, *(LONG *)pData);
  1701. break;
  1702. default:
  1703. break;
  1704. }
  1705. return hr;
  1706. }
  1707. /*===================================================================
  1708. CAppConfig::Update
  1709. Update settings in CAppConfig.
  1710. in:
  1711. returns:
  1712. HRESULT
  1713. Side effects:
  1714. Update CAppConfig settings.
  1715. ===================================================================*/
  1716. HRESULT CAppConfig::Update(CIsapiReqInfo *pIReq)
  1717. {
  1718. Glob(Lock);
  1719. if (m_fNeedUpdate == TRUE)
  1720. {
  1721. InterlockedExchange((LPLONG)&m_fNeedUpdate, 0);
  1722. m_fRestartEnabledUpdated = FALSE;
  1723. }
  1724. else
  1725. {
  1726. Glob(UnLock);
  1727. return S_OK;
  1728. }
  1729. Glob(UnLock);
  1730. return ReadConfigFromMD(pIReq, this, FALSE);
  1731. }
  1732. /*===================================================================
  1733. CAspRegistryParams::Init
  1734. Read the registry based ASP Parameters
  1735. in:
  1736. returns:
  1737. void
  1738. ===================================================================*/
  1739. void CAspRegistryParams::Init()
  1740. {
  1741. HKEY hkey = NULL;
  1742. DWORD dwType;
  1743. DWORD cbData;
  1744. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\ASP\\Parameters", 0, KEY_READ, &hkey) != ERROR_SUCCESS)
  1745. return;
  1746. // get DisableF5Attack
  1747. cbData = sizeof(DWORD);
  1748. m_fF5AttackValuePresent = RegQueryValueExA(hkey, "F5AttackDetectionEnabled", 0, &dwType, (LPBYTE)&m_dwF5AttackValue, &cbData) == NO_ERROR;
  1749. // get HangDetRequestThreshold
  1750. cbData = sizeof(DWORD);
  1751. m_fHangDetRequestThresholdPresent = RegQueryValueExA(hkey, "HangDetRequestThreshold", 0, &dwType, (LPBYTE)&m_dwHangDetRequestThreshold, &cbData) == NO_ERROR;
  1752. // get HangDetThreadHungThreshold
  1753. cbData = sizeof(DWORD);
  1754. m_fHangDetThreadHungThresholdPresent = RegQueryValueExA(hkey, "HangDetThreadHungThreshold", 0, &dwType, (LPBYTE)&m_dwHangDetThreadHungThreshold, &cbData) == NO_ERROR;
  1755. // get HangDetConsecIllStatesThreshold
  1756. cbData = sizeof(DWORD);
  1757. m_fHangDetConsecIllStatesThresholdPresent = RegQueryValueExA(hkey, "HangDetConsecIllStatesThreshold", 0, &dwType, (LPBYTE)&m_dwHangDetConsecIllStatesThreshold, &cbData) == NO_ERROR;
  1758. // get HangDetEnabled
  1759. cbData = sizeof(DWORD);
  1760. m_fHangDetEnabledPresent = RegQueryValueExA(hkey, "HangDetEnabled", 0, &dwType, (LPBYTE)&m_dwHangDetEnabled, &cbData) == NO_ERROR;
  1761. // get EnableChangeNotificationForUNC
  1762. cbData = sizeof(DWORD);
  1763. m_fChangeNotificationForUNCPresent = RegQueryValueExA(hkey, "EnableChangeNotificationForUNC", 0, &dwType, (LPBYTE)& m_dwChangeNotificationForUNC, &cbData) == NO_ERROR;
  1764. // get FileMonitoringEnabled
  1765. cbData = sizeof(DWORD);
  1766. m_fFileMonitoringEnabledPresent = RegQueryValueExA(hkey, "FileMonitoringEnabled", 0, &dwType, (LPBYTE)&m_dwFileMonitoringEnabled, &cbData) == NO_ERROR;
  1767. // get FileMonitoringTimeout
  1768. cbData = sizeof(DWORD);
  1769. m_fFileMonitoringTimeoutSecondsPresent = RegQueryValueExA(hkey, "FileMonitoringTimeoutSeconds", 0, &dwType, (LPBYTE)&m_dwFileMonitoringTimeoutSeconds, &cbData) == NO_ERROR;
  1770. // get MaxCSR
  1771. cbData = sizeof(DWORD);
  1772. m_fMaxCSRPresent = RegQueryValueExA(hkey, "MaxCSR", 0, &dwType, (LPBYTE)&m_dwMaxCSR, &cbData) == NO_ERROR;
  1773. // get MaxCPU
  1774. cbData = sizeof(DWORD);
  1775. m_fMaxCPUPresent = RegQueryValueExA(hkey, "MaxCPU", 0, &dwType, (LPBYTE)&m_dwMaxCPU, &cbData) == NO_ERROR;
  1776. // get DisableOOMRecycle
  1777. cbData = sizeof(DWORD);
  1778. m_fDisableOOMRecyclePresent = RegQueryValueExA(hkey, "DisableOOMRecycle", 0, &dwType, (LPBYTE)&m_dwDisableOOMRecycle, &cbData) == NO_ERROR;
  1779. // get DisableLazyContentPropagation
  1780. cbData = sizeof(DWORD);
  1781. m_fDisableLazyContentPropagationPresent = RegQueryValueExA(hkey, "DisableLazyContentPropagation", 0, &dwType, (LPBYTE)&m_dwDisableLazyContentPropagation, &cbData) == NO_ERROR;
  1782. // get ThreadMax
  1783. cbData = sizeof(DWORD);
  1784. m_fTotalThreadMaxPresent = RegQueryValueExA(hkey, "ThreadMax", 0, &dwType, (LPBYTE)&m_dwTotalThreadMax, &cbData) == NO_ERROR;
  1785. // get DisableComPlusCpuMetric
  1786. cbData = sizeof(DWORD);
  1787. m_fDisableComPlusCpuMetricPresent = RegQueryValueExA(hkey, "DisableComPlusCpuMetric", 0, &dwType, (LPBYTE)&m_dwDisableComPlusCpuMetric, &cbData) == NO_ERROR;
  1788. RegCloseKey(hkey);
  1789. }