Source code of Windows XP (NT5)
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.

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