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.

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