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

541 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. sink.cxx
  5. Abstract:
  6. IIS Services IISADMIN Extension
  7. Unicode Metadata Sink.
  8. Author:
  9. Michael W. Thomas 16-Sep-97
  10. --*/
  11. #include <cominc.hxx>
  12. #include "w3ssl_config.hxx"
  13. //extern HANDLE hevtDone;
  14. #define REG_FP_LOAD_VALUE "NewFPWebCmdLine"
  15. #define REG_FP_UNLOAD_VALUE "DelFPWebCmdLine"
  16. CSvcExtImpIMDCOMSINK::CSvcExtImpIMDCOMSINK(
  17. IMDCOM * pcCom):
  18. m_dwRefCount(1),
  19. m_pcCom(pcCom)
  20. {
  21. }
  22. CSvcExtImpIMDCOMSINK::~CSvcExtImpIMDCOMSINK()
  23. {
  24. }
  25. HRESULT
  26. CSvcExtImpIMDCOMSINK::QueryInterface(
  27. REFIID riid,
  28. void **ppObject)
  29. {
  30. if ( ppObject == NULL )
  31. {
  32. return E_INVALIDARG;
  33. }
  34. *ppObject = NULL;
  35. if (riid==IID_IUnknown || riid==IID_IMDCOMSINK_W)
  36. {
  37. *ppObject = (IMDCOMSINKW *) this;
  38. }
  39. else
  40. {
  41. return E_NOINTERFACE;
  42. }
  43. AddRef();
  44. return NO_ERROR;
  45. }
  46. ULONG
  47. CSvcExtImpIMDCOMSINK::AddRef()
  48. {
  49. DWORD dwRefCount;
  50. dwRefCount = InterlockedIncrement((long *)&m_dwRefCount);
  51. return dwRefCount;
  52. }
  53. ULONG
  54. CSvcExtImpIMDCOMSINK::Release()
  55. {
  56. DWORD dwRefCount;
  57. dwRefCount = InterlockedDecrement((long *)&m_dwRefCount);
  58. if (dwRefCount == 0)
  59. {
  60. delete this;
  61. }
  62. return dwRefCount;
  63. }
  64. #define SCHEMA_PATH_PREFIX IIS_MD_ADSI_SCHEMA_PATH_W L"/"
  65. HRESULT STDMETHODCALLTYPE
  66. CSvcExtImpIMDCOMSINK::ComMDSinkNotify(
  67. METADATA_HANDLE ,
  68. DWORD dwMDNumElements,
  69. MD_CHANGE_OBJECT __RPC_FAR pcoChangeList[ ])
  70. {
  71. DWORD i;
  72. DWORD j;
  73. for (i = 0; i < dwMDNumElements; i++)
  74. {
  75. if (((pcoChangeList[i].dwMDChangeType | MD_CHANGE_TYPE_SET_DATA) != 0) &&
  76. //
  77. // If this is a schema change, then don't do anything
  78. //
  79. (_wcsnicmp(pcoChangeList[i].pszMDPath,
  80. SCHEMA_PATH_PREFIX,
  81. ((sizeof(SCHEMA_PATH_PREFIX) / sizeof(WCHAR)) - 1)) != 0))
  82. {
  83. for (j = 0; j < pcoChangeList[i].dwMDNumDataIDs; j++)
  84. {
  85. switch (pcoChangeList[i].pdwMDDataIDs[j])
  86. {
  87. case MD_FRONTPAGE_WEB:
  88. {
  89. RegisterFrontPage( pcoChangeList[i].pszMDPath );
  90. break;
  91. }
  92. case MD_SERVER_COMMAND:
  93. {
  94. ProcessCommand(pcoChangeList[i].pszMDPath, MD_SERVER_COMMAND, MD_SERVER_COMMAND_START );
  95. break;
  96. }
  97. case MD_APPPOOL_COMMAND:
  98. {
  99. ProcessCommand(pcoChangeList[i].pszMDPath, MD_APPPOOL_COMMAND, MD_APPPOOL_COMMAND_START);
  100. break;
  101. }
  102. case MD_GLOBAL_STANDARD_APP_MODE_ENABLED:
  103. {
  104. W3SSL_CONFIG::AdjustHTTPFilterImagePath();
  105. break;
  106. }
  107. default:
  108. ;
  109. //
  110. // No specific action for this command
  111. //
  112. }
  113. }
  114. }
  115. }
  116. return S_OK;
  117. }
  118. #define REG_KEY_W3SVC_VROOTS TEXT("SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters\\Virtual Roots")
  119. #define REG_KEY_MSFTPSVC_VROOTS TEXT("SYSTEM\\CurrentControlSet\\Services\\MSFTPSVC\\Parameters\\Virtual Roots")
  120. HRESULT STDMETHODCALLTYPE
  121. CSvcExtImpIMDCOMSINK::ComMDEventNotify(
  122. DWORD dwMDEvent)
  123. {
  124. DWORD err;
  125. if (dwMDEvent == MD_EVENT_MID_RESTORE)
  126. {
  127. //
  128. // Blow away registry VRoots so they won't be brought back to life
  129. //
  130. err = RegDeleteKey(HKEY_LOCAL_MACHINE, REG_KEY_W3SVC_VROOTS);
  131. if ( err != ERROR_SUCCESS )
  132. {
  133. DBGINFOW((DBG_CONTEXT,
  134. L"[ComMDEventNotify] (%x) Couldn't remove W3SVC VRoot key\n",
  135. err ));
  136. }
  137. err = RegDeleteKey(HKEY_LOCAL_MACHINE, REG_KEY_MSFTPSVC_VROOTS);
  138. if ( err != ERROR_SUCCESS )
  139. {
  140. DBGINFOW((DBG_CONTEXT,
  141. L"[ComMDEventNotify] (%x) Couldn't remove MSFTPSVC VRoot key\n",
  142. err ));
  143. }
  144. }
  145. //
  146. // Sync up the user accounts with those from the metabase
  147. //
  148. UpdateUsers( TRUE );
  149. return S_OK;
  150. }
  151. //
  152. // This must be in a non-Unicode file so that registry reads on Win95 work.
  153. //
  154. VOID
  155. CSvcExtImpIMDCOMSINK::RegisterFrontPage(
  156. LPWSTR pszPath)
  157. {
  158. HRESULT hr = S_OK;
  159. HKEY hkey = NULL;
  160. CHAR buff[255];
  161. CHAR cmd[512];
  162. CHAR achPath[512];
  163. LPSTR pszOp;
  164. DWORD cbBuff = sizeof( buff );
  165. DWORD dwType;
  166. DWORD dwValue = 0;
  167. DWORD dwRequiredDataLen;
  168. HRESULT hresReturn;
  169. METADATA_RECORD mdrData;
  170. MD_SET_DATA_RECORD_EXT(&mdrData,
  171. MD_FRONTPAGE_WEB,
  172. METADATA_NO_ATTRIBUTES,
  173. ALL_METADATA,
  174. DWORD_METADATA,
  175. sizeof(DWORD),
  176. (PBYTE)&dwValue)
  177. hresReturn = m_pcCom->ComMDGetMetaData(METADATA_MASTER_ROOT_HANDLE,
  178. pszPath,
  179. &mdrData,
  180. &dwRequiredDataLen);
  181. if (FAILED(hresReturn))
  182. {
  183. if (hresReturn != MD_ERROR_DATA_NOT_FOUND)
  184. {
  185. DBGINFOW((DBG_CONTEXT,
  186. L"[RegisterFrontPage] GetData Failed, return code = %X\n",
  187. hresReturn));
  188. }
  189. }
  190. else
  191. {
  192. DBGINFOW(( DBG_CONTEXT,
  193. L"[RegisterFrontPage] Value - %d, Path - %S\n",
  194. dwValue,
  195. pszPath ));
  196. //
  197. // PREFIX
  198. // ComMDGetMetaData should not return success without setting the data
  199. // value pointed to by dwValue. I'm not sure if PREFIX is incapable of
  200. // recognizing the extra level of indirection or if there is some path
  201. // that I missed in reviewing ComMDGetMetaData. I'm going to shut down
  202. // this warning, but I'll open an issue with the PREFIX guys.
  203. //
  204. /* INTRINSA suppress = uninitialized */
  205. pszOp = dwValue ? REG_FP_LOAD_VALUE : REG_FP_UNLOAD_VALUE;
  206. if ( !RegOpenKeyExA( HKEY_LOCAL_MACHINE,
  207. REG_FP_PATH,
  208. 0,
  209. KEY_READ,
  210. &hkey ) &&
  211. !RegQueryValueExA( hkey,
  212. pszOp,
  213. NULL,
  214. &dwType,
  215. (BYTE *) buff,
  216. &cbBuff ))
  217. {
  218. if ( WideCharToMultiByte( CP_ACP,
  219. 0,
  220. pszPath,
  221. -1,
  222. achPath,
  223. sizeof(achPath),
  224. NULL,
  225. NULL ) == 0 )
  226. {
  227. DBGINFOW((DBG_CONTEXT,
  228. L"Failed to convert path to Ansi, error = %d\n",
  229. GetLastError() ));
  230. }
  231. else
  232. {
  233. //
  234. // FrontPage cannot handle trailing slash, so remove it.
  235. // Need to restore as this is not a local copy of path.
  236. //
  237. DWORD dwPathLen = (DWORD)strlen(achPath);
  238. DBG_ASSERT(achPath[dwPathLen - 1] == '/');
  239. achPath[dwPathLen - 1] = '\0';
  240. if ( (strlen( buff ) + (dwPathLen - 1)) < sizeof( cmd ) )
  241. {
  242. STARTUPINFOA StartupInfo;
  243. PROCESS_INFORMATION ProcessInformation;
  244. BOOL CreateProcessStatus;
  245. hr = StringCbVPrintfA( cmd, sizeof(cmd), buff, achPath );
  246. if ( SUCCEEDED(hr) )
  247. {
  248. RtlZeroMemory(&StartupInfo,sizeof(StartupInfo));
  249. StartupInfo.cb = sizeof(StartupInfo);
  250. StartupInfo.dwFlags = 0;
  251. StartupInfo.wShowWindow = 0;
  252. CreateProcessStatus = CreateProcessA(
  253. NULL,
  254. cmd,
  255. NULL,
  256. NULL,
  257. FALSE,
  258. 0,
  259. NULL,
  260. NULL,
  261. &StartupInfo,
  262. &ProcessInformation );
  263. if ( CreateProcessStatus )
  264. {
  265. DBG_REQUIRE( CloseHandle(ProcessInformation.hProcess) );
  266. DBG_REQUIRE( CloseHandle(ProcessInformation.hThread) );
  267. }
  268. else
  269. {
  270. DBGPRINTF(( DBG_CONTEXT,
  271. "[RegisterFrontPage] CreateProcess returned %d for %s\n",
  272. GetLastError(),
  273. cmd ));
  274. }
  275. }
  276. else
  277. {
  278. DBGPRINTF(( DBG_CONTEXT,
  279. "[RegisterFrontPage] StringCbVPrintfA returned 0x%08x for %s\n",
  280. hr,
  281. cmd ));
  282. }
  283. }
  284. }
  285. }
  286. else
  287. {
  288. DBGINFOW((DBG_CONTEXT,
  289. L"[RegisterFrontPage] Failed to open reg or read value\n"));
  290. }
  291. if ( hkey )
  292. {
  293. RegCloseKey( hkey );
  294. }
  295. }
  296. }
  297. VOID
  298. CSvcExtImpIMDCOMSINK::ProcessCommand(
  299. LPWSTR pszPath,
  300. DWORD dwMetabaseProperty,
  301. DWORD dwStartValue)
  302. {
  303. WCHAR pszServiceName[METADATA_MAX_NAME_LEN];
  304. DWORD dwValue = 0;
  305. DWORD dwRequiredDataLen;
  306. HRESULT hresReturn;
  307. METADATA_RECORD mdrData;
  308. MD_SET_DATA_RECORD_EXT(&mdrData,
  309. dwMetabaseProperty,
  310. METADATA_NO_ATTRIBUTES,
  311. ALL_METADATA,
  312. DWORD_METADATA,
  313. sizeof(DWORD),
  314. (PBYTE)&dwValue)
  315. hresReturn = m_pcCom->ComMDGetMetaData(METADATA_MASTER_ROOT_HANDLE,
  316. pszPath,
  317. &mdrData,
  318. &dwRequiredDataLen);
  319. if (FAILED(hresReturn))
  320. {
  321. DBGINFOW((DBG_CONTEXT,
  322. L"[ProcessCommandInternal] GetData Failed, return code = %X\n",
  323. hresReturn));
  324. }
  325. else
  326. {
  327. //
  328. // PREFIX
  329. // ComMDGetMetaData should not return success without setting the data
  330. // value pointed to by dwValue. I'm not sure if PREFIX is incapable of
  331. // recognizing the extra level of indirection or if there is some path
  332. // that I missed in reviewing ComMDGetMetaData. I'm going to shut down
  333. // this warning, but I'll open an issue with the PREFIX guys.
  334. //
  335. /* INTRINSA suppress = uninitialized */
  336. if (dwValue == dwStartValue)
  337. {
  338. if (GetServiceNameFromPath(pszPath,
  339. pszServiceName))
  340. {
  341. StartIISService(pszServiceName);
  342. }
  343. }
  344. }
  345. }
  346. #define SERVICE_NAME_PREFIX L"/LM/"
  347. BOOL
  348. GetServiceNameFromPath(
  349. LPWSTR pszPath,
  350. LPWSTR pszServiceName)
  351. /*++
  352. Routine Description:
  353. Start an IIS service
  354. Arguments:
  355. pszPath - path spcifying which IIS service to start
  356. pszServiceName - updated with service name
  357. Return Value:
  358. TRUE - Success
  359. FALSE - Failure
  360. --*/
  361. {
  362. LPWSTR pszPathIndex;
  363. UINT cS;
  364. DBG_ASSERT(pszPath != NULL);
  365. DBG_ASSERT(pszServiceName != NULL);
  366. pszPathIndex = pszPath;
  367. if ((_wcsnicmp( pszPathIndex, \
  368. SERVICE_NAME_PREFIX,
  369. ((sizeof(SERVICE_NAME_PREFIX) / sizeof(WCHAR)) - 1)) == 0) &&
  370. (pszPath[(sizeof(SERVICE_NAME_PREFIX) / sizeof(WCHAR)) - 1] != (WCHAR)'\0'))
  371. {
  372. pszPathIndex += ((sizeof(SERVICE_NAME_PREFIX) / sizeof(WCHAR)) -1);
  373. //
  374. // copy to temp buffer until path delim
  375. //
  376. for ( cS = 0 ; cS < METADATA_MAX_NAME_LEN-1 &&
  377. (*pszPathIndex != (WCHAR)'/'); )
  378. {
  379. pszServiceName[cS++] = *pszPathIndex++;
  380. }
  381. pszServiceName[cS] = (WCHAR)'\0';
  382. return TRUE;
  383. }
  384. return FALSE;
  385. }
  386. VOID
  387. StartIISService(
  388. LPWSTR pszServiceName)
  389. /*++
  390. Routine Description:
  391. Start an IIS service
  392. Arguments:
  393. pszServiceName - specify which IIS service to start
  394. Return Value:
  395. TRUE - Success
  396. FALSE - Failure
  397. --*/
  398. {
  399. SC_HANDLE scManagerHandle;
  400. SC_HANDLE serviceHandle;
  401. DBG_ASSERT(pszServiceName != NULL);
  402. //
  403. // Start service WinNT-style
  404. //
  405. //
  406. // Open the service control manager
  407. //
  408. scManagerHandle = OpenSCManager( NULL, // local machine
  409. NULL, // ServicesActive database
  410. SC_MANAGER_ALL_ACCESS ); // all access
  411. if ( scManagerHandle != NULL )
  412. {
  413. //
  414. // Open the service
  415. //
  416. serviceHandle = OpenService( scManagerHandle,
  417. pszServiceName,
  418. SERVICE_START );
  419. if ( serviceHandle != NULL )
  420. {
  421. //
  422. // Make sure the service is running
  423. //
  424. if (!StartService( serviceHandle,
  425. 0,
  426. NULL) &&
  427. (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
  428. {
  429. DBGINFOW(( DBG_CONTEXT,
  430. L"[StartIISService] StartService(%s) Failed, Error = %X\n",
  431. pszServiceName,
  432. GetLastError()));
  433. }
  434. CloseServiceHandle( serviceHandle );
  435. }
  436. //
  437. // Close open handle
  438. //
  439. CloseServiceHandle( scManagerHandle);
  440. }
  441. }