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.

694 lines
16 KiB

  1. /*++
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name :
  4. wam.cpp
  5. Abstract:
  6. This module implements the exported routines for WAM object
  7. Author:
  8. David Kaplan ( DaveK ) 26-Feb-1997
  9. Wade Hilmo ( WadeH ) 08-Sep-2000
  10. Environment:
  11. User Mode - Win32
  12. Project:
  13. Wam DLL
  14. --*/
  15. //
  16. // Following are the notes from the original MSDEV generated file
  17. // Note: Proxy/Stub Information
  18. // To merge the proxy/stub code into the object DLL, add the file
  19. // dlldatax.c to the project. Make sure precompiled headers
  20. // are turned off for this file, and add _MERGE_PROXYSTUB to the
  21. // defines for the project.
  22. //
  23. // If you are not running WinNT4.0 or Win95 with DCOM, then you
  24. // need to remove the following define from dlldatax.c
  25. // #define _WIN32_WINNT 0x0400
  26. //
  27. // Further, if you are running MIDL without /Oicf switch, you also
  28. // need to remove the following define from dlldatax.c.
  29. // #define USE_STUBLESS_PROXY
  30. //
  31. // Modify the custom build rule for Wam.idl by adding the following
  32. // files to the Outputs.
  33. // Wam_p.c
  34. // dlldata.c
  35. // To build a separate proxy/stub DLL,
  36. // run nmake -f Wamps.mk in the project directory.
  37. // BEGIN mods
  38. // Post-wizard mods appear within BEGIN mods ... END mods
  39. // END mods
  40. #include "precomp.hxx"
  41. #include <w3isapi.h>
  42. #include <isapi_context.hxx>
  43. #include "wamobj.hxx"
  44. #include "IWam_i.c"
  45. #include "wamccf.hxx"
  46. #include <atlbase.h>
  47. // BEGIN mods
  48. #ifdef _ATL_STATIC_REGISTRY
  49. #include <statreg.h>
  50. #include <statreg.cpp>
  51. #endif
  52. #include <atlimpl.cpp>
  53. // END mods
  54. /************************************************************
  55. * Global Variables
  56. ************************************************************/
  57. const CHAR g_pszModuleName[] = "WAM";
  58. const CHAR g_pszWamRegLocation[] =
  59. "System\\CurrentControlSet\\Services\\W3Svc\\WAM";
  60. HMODULE WAM::sm_hIsapiModule;
  61. PFN_ISAPI_TERM_MODULE WAM::sm_pfnTermIsapiModule;
  62. PFN_ISAPI_PROCESS_REQUEST WAM::sm_pfnProcessIsapiRequest;
  63. PFN_ISAPI_PROCESS_COMPLETION WAM::sm_pfnProcessIsapiCompletion;
  64. #ifdef _MERGE_PROXYSTUB
  65. extern "C" HINSTANCE hProxyDll;
  66. #endif
  67. BEGIN_OBJECT_MAP(ObjectMap)
  68. OBJECT_ENTRY(CLSID_Wam, WAM)
  69. END_OBJECT_MAP()
  70. // BEGIN mods
  71. WAM_CCF_MODULE _WAMCCFModule;
  72. DECLARE_PLATFORM_TYPE();
  73. DECLARE_DEBUG_VARIABLE();
  74. DECLARE_DEBUG_PRINTS_OBJECT();
  75. // END mods
  76. /************************************************************
  77. * Type Definitions
  78. ************************************************************/
  79. // BUGBUG
  80. #undef INET_INFO_KEY
  81. #undef INET_INFO_PARAMETERS_KEY
  82. //
  83. // Configuration parameters registry key.
  84. //
  85. #define INET_INFO_KEY \
  86. "System\\CurrentControlSet\\Services\\iisw3adm"
  87. #define INET_INFO_PARAMETERS_KEY \
  88. INET_INFO_KEY "\\Parameters"
  89. const CHAR g_pszWpRegLocation[] =
  90. INET_INFO_PARAMETERS_KEY "\\WP";
  91. class DEBUG_WRAPPER {
  92. public:
  93. DEBUG_WRAPPER( IN LPCSTR pszModule )
  94. {
  95. #if DBG
  96. CREATE_DEBUG_PRINT_OBJECT( pszModule );
  97. #else
  98. UNREFERENCED_PARAMETER( pszModule );
  99. #endif
  100. LOAD_DEBUG_FLAGS_FROM_REG_STR( g_pszWpRegLocation, DEBUG_ERROR );
  101. }
  102. ~DEBUG_WRAPPER(void)
  103. { DELETE_DEBUG_PRINT_OBJECT(); }
  104. };
  105. class CWamModule _Module;
  106. /////////////////////////////////////////////////////////////////////////////
  107. // DLL Entry Point
  108. extern "C"
  109. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  110. {
  111. DWORD dwErr = NO_ERROR;
  112. #ifdef _MERGE_PROXYSTUB
  113. if (!PrxDllMain(hInstance, dwReason, lpReserved))
  114. return FALSE;
  115. #endif
  116. if (dwReason == DLL_PROCESS_ATTACH)
  117. {
  118. //
  119. // BEGIN mods
  120. //
  121. // From ATL generated
  122. _Module.Init(ObjectMap, hInstance);
  123. DisableThreadLibraryCalls(hInstance);
  124. // End of ATL generated
  125. _WAMCCFModule.Init();
  126. // END mods
  127. }
  128. else if (dwReason == DLL_PROCESS_DETACH)
  129. {
  130. if ( NULL != lpReserved )
  131. {
  132. //
  133. // Only cleanup if there is a FreeLibrary() call
  134. //
  135. return ( TRUE);
  136. }
  137. _WAMCCFModule.Term();
  138. _Module.Term();
  139. // BEGIN mods
  140. DELETE_DEBUG_PRINT_OBJECT();
  141. // END mods
  142. }
  143. return (dwErr == NO_ERROR);
  144. } // DllMain()
  145. /////////////////////////////////////////////////////////////////////////////
  146. // Used to determine whether the DLL can be unloaded by OLE
  147. STDAPI DllCanUnloadNow(void)
  148. {
  149. #ifdef _MERGE_PROXYSTUB
  150. if (PrxDllCanUnloadNow() != S_OK)
  151. return S_FALSE;
  152. #endif
  153. return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  154. }
  155. /////////////////////////////////////////////////////////////////////////////
  156. // Returns a class factory to create an object of the requested type
  157. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  158. {
  159. HRESULT hr;
  160. if (ppv == NULL) {
  161. return ( NULL);
  162. }
  163. *ppv = NULL; // reset the value before getting inside.
  164. if (ppv == NULL) {
  165. return ( E_POINTER);
  166. }
  167. *ppv = NULL; // set the incoming value to be invalid entry
  168. #ifdef _MERGE_PROXYSTUB
  169. if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
  170. return S_OK;
  171. #endif
  172. hr = _WAMCCFModule.GetClassObject(rclsid, riid, ppv);
  173. // BEGIN mods
  174. if (hr == CLASS_E_CLASSNOTAVAILABLE)
  175. {
  176. // If request for standard CF failed -> try custom
  177. hr = _Module.GetClassObject(CLSID_Wam, riid, ppv);
  178. }
  179. // END mods
  180. return ( hr);
  181. } // DllGetClassObject()
  182. /////////////////////////////////////////////////////////////////////////////
  183. // DllRegisterServer - Adds entries to the system registry
  184. STDAPI DllRegisterServer(void)
  185. {
  186. #ifdef _MERGE_PROXYSTUB
  187. HRESULT hRes = PrxDllRegisterServer();
  188. if (FAILED(hRes))
  189. return hRes;
  190. #endif
  191. // registers object, typelib and all interfaces in typelib
  192. return _Module.RegisterServer(TRUE);
  193. }
  194. /////////////////////////////////////////////////////////////////////////////
  195. // DllUnregisterServer - Removes entries from the system registry
  196. STDAPI DllUnregisterServer(void)
  197. {
  198. #ifdef _MERGE_PROXYSTUB
  199. PrxDllUnregisterServer();
  200. #endif
  201. _Module.UnregisterServer();
  202. return S_OK;
  203. }
  204. HRESULT
  205. WAM::WamProcessIsapiRequest(
  206. BYTE *pCoreData,
  207. DWORD cbCoreData,
  208. IIsapiCore *pIsapiCore,
  209. DWORD *pdwHseResult
  210. )
  211. /*++
  212. Routine Description:
  213. Processes an ISAPI request
  214. Arguments:
  215. pCoreData - The core data from the server for the request
  216. cbCoreData - The size of pCoreData
  217. pIsapiCore - The IIsapiCore interface pointer for this request
  218. pdwHseResult - Upon return, contains the return from HttpExtensionProc
  219. Return Value:
  220. HRESULT
  221. --*/
  222. {
  223. HRESULT hr = NOERROR;
  224. pIsapiCore->AddRef();
  225. hr = sm_pfnProcessIsapiRequest(
  226. pIsapiCore,
  227. (ISAPI_CORE_DATA*)pCoreData,
  228. pdwHseResult
  229. );
  230. pIsapiCore->Release();
  231. return hr;
  232. }
  233. HRESULT
  234. WAM::WamProcessIsapiCompletion(
  235. DWORD64 IsapiContext,
  236. DWORD cbCompletion,
  237. DWORD cbCompletionStatus
  238. )
  239. /*++
  240. Routine Description:
  241. Processes an ISAPI I/O completion
  242. Arguments:
  243. IsapiContext - The ISAPI_CONTEXT that identifies the request
  244. cbCompletion - The number of bytes associated with the completion
  245. cbCompletionStatus - The status code associated with the completion
  246. Return Value:
  247. HRESULT
  248. --*/
  249. {
  250. HRESULT hr = NOERROR;
  251. hr = sm_pfnProcessIsapiCompletion(
  252. IsapiContext,
  253. cbCompletion,
  254. cbCompletionStatus
  255. );
  256. return hr;
  257. }
  258. HRESULT
  259. WAM::WamInitProcess(
  260. BYTE *szIsapiModule,
  261. DWORD cbIsapiModule,
  262. DWORD *pdwProcessId,
  263. LPSTR szClsid,
  264. LPSTR szIsapiHandlerInstance,
  265. DWORD dwCallingProcess
  266. )
  267. /*++
  268. Routine Description:
  269. Initializes WAM for the host process. This includes loading
  270. w3isapi.dll and getting function pointers for the relevant stuff
  271. Arguments:
  272. szIsapiModule - The full path (UNICODE) of w3isapi.dll
  273. cbIsapiModule - The number of bytes in the above path
  274. pdwProcessId - Upon return, contains the process ID of the
  275. host process
  276. szClsid - The CLSID of the WAM object being initialized
  277. szIsapiHandlerInstance - The instance ID of the W3_ISAPI_HANDLER that's
  278. initializing this WAM.
  279. dwCallingProcess - The process ID of this function's caller
  280. Return Value:
  281. HRESULT
  282. --*/
  283. {
  284. HRESULT hr = NOERROR;
  285. PFN_ISAPI_INIT_MODULE pfnInit = NULL;
  286. //
  287. // First, set the process ID for the process hosting this object
  288. //
  289. *pdwProcessId = GetCurrentProcessId();
  290. //
  291. // Initialize IISUTIL
  292. //
  293. if ( !InitializeIISUtil() )
  294. {
  295. hr = HRESULT_FROM_WIN32( GetLastError() );
  296. DBGPRINTF(( DBG_CONTEXT,
  297. "Error initializing IISUTIL. hr = %x\n",
  298. hr ));
  299. goto ErrorExit;
  300. }
  301. //
  302. // Load and initialize the ISAPI module
  303. //
  304. sm_hIsapiModule = LoadLibraryW( (LPWSTR)szIsapiModule );
  305. if( sm_hIsapiModule == NULL )
  306. {
  307. hr = HRESULT_FROM_WIN32( GetLastError() );
  308. goto ErrorExit;
  309. }
  310. sm_pfnTermIsapiModule =
  311. (PFN_ISAPI_TERM_MODULE)GetProcAddress( sm_hIsapiModule,
  312. ISAPI_TERM_MODULE
  313. );
  314. sm_pfnProcessIsapiRequest =
  315. (PFN_ISAPI_PROCESS_REQUEST)GetProcAddress( sm_hIsapiModule,
  316. ISAPI_PROCESS_REQUEST
  317. );
  318. sm_pfnProcessIsapiCompletion =
  319. (PFN_ISAPI_PROCESS_COMPLETION)GetProcAddress( sm_hIsapiModule,
  320. ISAPI_PROCESS_COMPLETION
  321. );
  322. if( !sm_pfnTermIsapiModule ||
  323. !sm_pfnProcessIsapiRequest ||
  324. !sm_pfnProcessIsapiCompletion )
  325. {
  326. hr = E_FAIL;
  327. goto ErrorExit;
  328. }
  329. pfnInit =
  330. (PFN_ISAPI_INIT_MODULE)GetProcAddress( sm_hIsapiModule,
  331. ISAPI_INIT_MODULE
  332. );
  333. if( !pfnInit )
  334. {
  335. hr = E_FAIL;
  336. goto ErrorExit;
  337. }
  338. hr = pfnInit(
  339. szClsid,
  340. szIsapiHandlerInstance,
  341. dwCallingProcess
  342. );
  343. if( FAILED(hr) )
  344. {
  345. goto ErrorExit;
  346. }
  347. return hr;
  348. ErrorExit:
  349. DBG_ASSERT( FAILED( hr ) );
  350. return hr;
  351. }
  352. HRESULT
  353. WAM::WamUninitProcess(
  354. VOID
  355. )
  356. /*++
  357. Routine Description:
  358. Uninitializes WAM for the host process. This function ultimately
  359. causes TerminateExtension to get called for each loaded extension.
  360. Arguments:
  361. None
  362. Return Value:
  363. HRESULT
  364. --*/
  365. {
  366. HRESULT hr = NOERROR;
  367. DBG_ASSERT( sm_pfnTermIsapiModule );
  368. DBG_ASSERT( sm_hIsapiModule );
  369. if( sm_pfnTermIsapiModule )
  370. {
  371. sm_pfnTermIsapiModule();
  372. sm_pfnTermIsapiModule = NULL;
  373. }
  374. if( sm_hIsapiModule )
  375. {
  376. FreeLibrary( sm_hIsapiModule );
  377. sm_hIsapiModule = NULL;
  378. }
  379. TerminateIISUtil();
  380. return hr;
  381. }
  382. HRESULT
  383. WAM::WamMarshalAsyncReadBuffer(
  384. DWORD64 IsapiContext,
  385. BYTE *pBuffer,
  386. DWORD cbBuffer
  387. )
  388. /*++
  389. Routine Description:
  390. Receives a buffer to be passed to a request. This function will be
  391. called just prior to an I/O completion in the case where and OOP
  392. extension does an asynchronous ReadClient.
  393. Arguments:
  394. IsapiContext - The ISAPI_CONTEXT that identifies the request
  395. pBuffer - The data buffer
  396. cbBuffer - The size of pBuffer
  397. Return Value:
  398. HRESULT
  399. --*/
  400. {
  401. ISAPI_CONTEXT * pIsapiContext;
  402. VOID * pReadBuffer;
  403. DWORD cbReadBuffer;
  404. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( IsapiContext );
  405. DBG_ASSERT( pIsapiContext );
  406. DBG_ASSERT( pIsapiContext->QueryIoState() == AsyncReadPending );
  407. pReadBuffer = pIsapiContext->QueryAsyncIoBuffer();
  408. cbReadBuffer = pIsapiContext->QueryLastAsyncIo();
  409. DBG_ASSERT( pReadBuffer != NULL );
  410. DBG_ASSERT( cbBuffer <= cbReadBuffer );
  411. //
  412. // Ensure that we don't overrun the ISAPI_CONTEXT buffer
  413. //
  414. if ( cbBuffer > cbReadBuffer )
  415. {
  416. cbBuffer = cbReadBuffer;
  417. }
  418. memcpy( pReadBuffer, pBuffer, cbBuffer );
  419. pIsapiContext->SetAsyncIoBuffer( NULL );
  420. pIsapiContext->SetLastAsyncIo( 0 );
  421. return NO_ERROR;
  422. }
  423. HRESULT
  424. WAM::CallerHasAccess()
  425. /*++
  426. Routine Description:
  427. Get the COM call context and examine the calling thread to determine
  428. if the caller has sufficient access to make this call.
  429. Currently the check is just made that the caller is local system.
  430. Arguments:
  431. Return Value:
  432. HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) - If caller is denied.
  433. FAILED() if failed for some other reason.
  434. --*/
  435. {
  436. HRESULT hr;
  437. IServerSecurity * pServerSecurity = NULL;
  438. BOOL fImpersonated = FALSE;
  439. HANDLE hToken = NULL;
  440. STACK_BUFFER( TokenUserBuffer, 80 );
  441. DWORD dwRequiredSize;
  442. TOKEN_USER * pTokenUser;
  443. hr = CoGetCallContext( IID_IServerSecurity, (VOID **)&pServerSecurity );
  444. if( FAILED(hr) )
  445. {
  446. DBGERROR(( DBG_CONTEXT,
  447. "Failed to get IServerSecurity. %0x\n",
  448. hr ));
  449. goto exit;
  450. }
  451. hr = pServerSecurity->ImpersonateClient();
  452. if( FAILED(hr) )
  453. {
  454. DBGERROR(( DBG_CONTEXT,
  455. "Failed to ImpersonateClient. %0x\n",
  456. hr ));
  457. goto exit;
  458. }
  459. fImpersonated = TRUE;
  460. if( !OpenThreadToken( GetCurrentThread(),
  461. TOKEN_QUERY,
  462. TRUE,
  463. &hToken ) )
  464. {
  465. hr = HRESULT_FROM_WIN32( GetLastError() );
  466. DBGERROR(( DBG_CONTEXT,
  467. "Failed to OpenThreadToken gle=%d\n",
  468. GetLastError() ));
  469. goto exit;
  470. }
  471. if( !GetTokenInformation( hToken,
  472. TokenUser,
  473. TokenUserBuffer.QueryPtr(),
  474. TokenUserBuffer.QuerySize(),
  475. &dwRequiredSize ) )
  476. {
  477. if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  478. {
  479. hr = HRESULT_FROM_WIN32( GetLastError() );
  480. DBGERROR(( DBG_CONTEXT,
  481. "Failed to GetTokenInformation gle=%d\n",
  482. GetLastError() ));
  483. goto exit;
  484. }
  485. if( !TokenUserBuffer.Resize( dwRequiredSize ) )
  486. {
  487. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  488. goto exit;
  489. }
  490. if( !GetTokenInformation( hToken,
  491. TokenUser,
  492. TokenUserBuffer.QueryPtr(),
  493. TokenUserBuffer.QuerySize(),
  494. &dwRequiredSize ) )
  495. {
  496. hr = HRESULT_FROM_WIN32( GetLastError() );
  497. DBGERROR(( DBG_CONTEXT,
  498. "Failed to GetTokenInformation gle=%d\n",
  499. GetLastError() ));
  500. goto exit;
  501. }
  502. }
  503. pTokenUser = (TOKEN_USER *)TokenUserBuffer.QueryPtr();
  504. if( !IsWellKnownSid( pTokenUser->User.Sid,
  505. WinLocalSystemSid ) )
  506. {
  507. hr = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  508. DBGERROR(( DBG_CONTEXT,
  509. "Unknown user attempting to access\n" ));
  510. goto exit;
  511. }
  512. exit:
  513. if( hToken )
  514. {
  515. CloseHandle( hToken );
  516. }
  517. if( fImpersonated )
  518. {
  519. DBG_ASSERT( pServerSecurity );
  520. pServerSecurity->RevertToSelf();
  521. }
  522. if( pServerSecurity )
  523. {
  524. pServerSecurity->Release();
  525. }
  526. return hr;
  527. }