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.

2448 lines
65 KiB

  1. //---------------------------------------------------------------------
  2. // Copyright (C)1998 Microsoft Corporation, All Rights Reserved.
  3. //
  4. // registry.cpp
  5. //
  6. //---------------------------------------------------------------------
  7. #define UNICODE
  8. #define INITGUID
  9. #include <sysinc.h>
  10. #include <malloc.h>
  11. #include <winsock2.h>
  12. #include <olectl.h> // for: SELFREG_E_CLASS
  13. #include <iadmw.h> // COM Interface header
  14. #include <iiscnfg.h> // MD_ & IIS_MD_ #defines
  15. #include <httpfilt.h>
  16. #include <httpext.h>
  17. #include <ecblist.h>
  18. #include <registry.h>
  19. #include <filter.h>
  20. #include <iwamreg.h>
  21. #include <align.h>
  22. #include <util.hxx>
  23. #include <osfpcket.hxx>
  24. #include <iads.h>
  25. #include <adshlp.h>
  26. #include <resource.h>
  27. #include <iiisext.h>
  28. #include <iisext_i.c>
  29. // uncomment to debug setup problems
  30. /*
  31. #ifndef DBG_REG
  32. #define DBG_REG 1
  33. #endif // DBG_REG
  34. #define DBG_ERROR 1
  35. */
  36. // this defines control whether we will compile for the IIS security
  37. // console or for the lockdown list.
  38. #define IIS_SEC_CONSOLE 1
  39. //#define IIS_LOCKDOWN_LIST
  40. //----------------------------------------------------------------
  41. // Globals:
  42. //----------------------------------------------------------------
  43. const rpcconn_tunnel_settings EchoRTS =
  44. {
  45. {
  46. OSF_RPC_V20_VERS,
  47. OSF_RPC_V20_VERS_MINOR,
  48. rpc_rts,
  49. PFC_FIRST_FRAG | PFC_LAST_FRAG,
  50. {
  51. NDR_LOCAL_CHAR_DREP | NDR_LOCAL_INT_DREP,
  52. NDR_LOCAL_FP_DREP,
  53. 0,
  54. 0
  55. },
  56. FIELD_OFFSET(rpcconn_tunnel_settings, Cmd) + ConstPadN(FIELD_OFFSET(rpcconn_tunnel_settings, Cmd), 4),
  57. 0,
  58. 0
  59. },
  60. RTS_FLAG_ECHO,
  61. 0
  62. };
  63. const BYTE *GetEchoRTS (
  64. OUT ULONG *EchoRTSSize
  65. )
  66. {
  67. *EchoRTSSize = FIELD_OFFSET(rpcconn_tunnel_settings, Cmd)
  68. + ConstPadN(FIELD_OFFSET(rpcconn_tunnel_settings, Cmd), 4);
  69. return (const BYTE *)&EchoRTS;
  70. }
  71. HMODULE g_hInst = NULL;
  72. //----------------------------------------------------------------
  73. // AnsiToUnicode()
  74. //
  75. // Convert an ANSI string to a UNICODE string.
  76. //----------------------------------------------------------------
  77. DWORD AnsiToUnicode( IN UCHAR *pszString,
  78. IN ULONG ulStringLen,
  79. OUT WCHAR *pwsString )
  80. {
  81. if (!pszString)
  82. {
  83. if (!pwsString)
  84. {
  85. return NO_ERROR;
  86. }
  87. else
  88. {
  89. pwsString[0] = 0;
  90. return NO_ERROR;
  91. }
  92. }
  93. if (!MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED,
  94. (char*)pszString, 1+ulStringLen,
  95. pwsString, 1+ulStringLen ))
  96. {
  97. return ERROR_NO_UNICODE_TRANSLATION;
  98. }
  99. return NO_ERROR;
  100. }
  101. //---------------------------------------------------------------------
  102. // RegSetKeyAndValueIfDontExist()
  103. //
  104. // Private helper function for SetupRegistry() that checks if a key exists,
  105. // and if not, creates a key, sets a value, then closes the key. If key
  106. // exists, it is not touched.
  107. //
  108. // Parameters:
  109. // pwsKey WCHAR* The name of the key
  110. // pwsSubkey WCHAR* The name of a subkey
  111. // pwsValueName WCHAR* The value name.
  112. // pwsValue WCHAR* The data value to store
  113. // dwType The type for the new registry value.
  114. // dwDataSize The size for non-REG_SZ registry entry types.
  115. //
  116. // Return:
  117. // BOOL TRUE if successful, FALSE otherwise.
  118. //---------------------------------------------------------------------
  119. BOOL RegSetKeyAndValueIfDontExist( const WCHAR *pwsKey,
  120. const WCHAR *pwsSubKey,
  121. const WCHAR *pwsValueName,
  122. const WCHAR *pwsValue,
  123. const DWORD dwType = REG_SZ,
  124. DWORD dwDataSize = 0 )
  125. {
  126. HKEY hKey;
  127. DWORD dwSize = 0;
  128. WCHAR *pwsCompleteKey;
  129. DWORD dwTypeFound;
  130. long Error;
  131. if (pwsKey)
  132. dwSize = wcslen(pwsKey);
  133. if (pwsSubKey)
  134. dwSize += wcslen(pwsSubKey);
  135. dwSize = (1+1+dwSize)*sizeof(WCHAR); // Extra +1 for the backslash...
  136. pwsCompleteKey = (WCHAR*)_alloca(dwSize);
  137. wcscpy(pwsCompleteKey,pwsKey);
  138. if (NULL!=pwsSubKey)
  139. {
  140. wcscat(pwsCompleteKey, TEXT("\\"));
  141. wcscat(pwsCompleteKey, pwsSubKey);
  142. }
  143. if ((Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  144. pwsCompleteKey,
  145. 0,
  146. KEY_WRITE | KEY_QUERY_VALUE,
  147. &hKey) ) == ERROR_SUCCESS )
  148. {
  149. if (( Error = RegQueryValueEx(
  150. hKey,
  151. pwsValueName,
  152. 0,
  153. &dwTypeFound,
  154. NULL,
  155. NULL
  156. ) ) == ERROR_SUCCESS )
  157. {
  158. RegCloseKey(hKey);
  159. return TRUE;
  160. }
  161. // the key exists, but the value does not. Fall through to
  162. // create it
  163. }
  164. else
  165. {
  166. if (ERROR_SUCCESS != RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  167. pwsCompleteKey,
  168. 0,
  169. NULL,
  170. REG_OPTION_NON_VOLATILE,
  171. KEY_WRITE, NULL, &hKey, NULL))
  172. {
  173. return FALSE;
  174. }
  175. }
  176. if (pwsValue)
  177. {
  178. if ((dwType == REG_SZ)||(dwType == REG_EXPAND_SZ))
  179. dwDataSize = (1+wcslen(pwsValue))*sizeof(WCHAR);
  180. RegSetValueEx( hKey,
  181. pwsValueName, 0, dwType, (BYTE *)pwsValue, dwDataSize );
  182. }
  183. else
  184. {
  185. RegSetValueEx( hKey,
  186. pwsValueName, 0, dwType, (BYTE *)pwsValue, 0 );
  187. }
  188. RegCloseKey(hKey);
  189. return TRUE;
  190. }
  191. const WCHAR * const EVENT_LOG_SOURCE_NAME = L"RPC Proxy";
  192. const WCHAR * const EVENT_LOG_KEY_NAME = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\RPC Proxy";
  193. const ULONG EVENT_LOG_CATEGORY_COUNT = 1;
  194. HRESULT
  195. RegisterEventLog()
  196. {
  197. HKEY EventLogKey = NULL;
  198. DWORD Disposition;
  199. LONG Result =
  200. RegCreateKeyEx(
  201. HKEY_LOCAL_MACHINE, // handle to open key
  202. EVENT_LOG_KEY_NAME, // subkey name
  203. 0, // reserved
  204. NULL, // class string
  205. 0, // special options
  206. KEY_ALL_ACCESS, // desired security access
  207. NULL, // inheritance
  208. &EventLogKey, // key handle
  209. &Disposition // disposition value buffer
  210. );
  211. if ( Result )
  212. {
  213. #if DBG
  214. DbgPrint("RPCProxy: Can't create Eventlog key: %X\n", GetLastError());
  215. #endif // DBG
  216. return HRESULT_FROM_WIN32( Result );
  217. }
  218. DWORD Value = EVENT_LOG_CATEGORY_COUNT;
  219. Result =
  220. RegSetValueEx(
  221. EventLogKey, // handle to key
  222. L"CategoryCount", // value name
  223. 0, // reserved
  224. REG_DWORD, // value type
  225. (BYTE*)&Value, // value data
  226. sizeof(Value) // size of value data
  227. );
  228. if ( Result )
  229. {
  230. #if DBG
  231. DbgPrint("RPCProxy: Can't set CategoryCount value: %X\n", GetLastError());
  232. #endif // DBG
  233. goto error;
  234. }
  235. const WCHAR MessageFileName[] = L"%SystemRoot%\\system32\\rpcproxy\\rpcproxy.dll";
  236. const DWORD MessageFileNameSize = sizeof( MessageFileName );
  237. Result =
  238. RegSetValueEx(
  239. EventLogKey, // handle to key
  240. L"CategoryMessageFile", // value name
  241. 0, // reserved
  242. REG_EXPAND_SZ, // value type
  243. (const BYTE*)MessageFileName, // value data
  244. MessageFileNameSize // size of value data
  245. );
  246. if ( Result )
  247. {
  248. #if DBG
  249. DbgPrint("RPCProxy: Can't set CategoryMessageFile value: %X\n", GetLastError());
  250. #endif // DBG
  251. goto error;
  252. }
  253. Result =
  254. RegSetValueEx(
  255. EventLogKey, // handle to key
  256. L"EventMessageFile", // value name
  257. 0, // reserved
  258. REG_EXPAND_SZ, // value type
  259. (const BYTE*)MessageFileName, // value data
  260. MessageFileNameSize // size of value data
  261. );
  262. if ( Result )
  263. {
  264. #if DBG
  265. DbgPrint("RPCProxy: Can't set EventMessageFile value: %X\n", GetLastError());
  266. #endif // DBG
  267. goto error;
  268. }
  269. Value = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
  270. Result =
  271. RegSetValueEx(
  272. EventLogKey, // handle to key
  273. L"TypesSupported", // value name
  274. 0, // reserved
  275. REG_DWORD, // value type
  276. (BYTE*)&Value, // value data
  277. sizeof(Value) // size of value data
  278. );
  279. if ( Result )
  280. {
  281. #if DBG
  282. DbgPrint("RPCProxy: Can't set TypesSupported value: %X\n", GetLastError());
  283. #endif // DBG
  284. goto error;
  285. }
  286. RegCloseKey( EventLogKey );
  287. EventLogKey = NULL;
  288. return S_OK;
  289. error:
  290. if ( EventLogKey )
  291. {
  292. RegCloseKey( EventLogKey );
  293. EventLogKey = NULL;
  294. }
  295. if ( REG_CREATED_NEW_KEY == Disposition )
  296. {
  297. RegDeleteKey(
  298. HKEY_LOCAL_MACHINE,
  299. EVENT_LOG_KEY_NAME );
  300. }
  301. return HRESULT_FROM_WIN32( Result );
  302. }
  303. HRESULT
  304. UnRegisterEventLog()
  305. {
  306. RegDeleteKey(
  307. HKEY_LOCAL_MACHINE,
  308. EVENT_LOG_KEY_NAME );
  309. return S_OK;
  310. }
  311. HRESULT
  312. RPCProxyGetStartupInfo(
  313. LPSTARTUPINFOA lpStartupInfo )
  314. {
  315. __try
  316. {
  317. GetStartupInfoA( lpStartupInfo );
  318. }
  319. __except( EXCEPTION_EXECUTE_HANDLER )
  320. {
  321. return E_OUTOFMEMORY;
  322. }
  323. return S_OK;
  324. }
  325. BOOL
  326. RegisterOutOfProc(void)
  327. {
  328. //
  329. // Runs a child process
  330. //
  331. STARTUPINFOA StartupInfo;
  332. HRESULT Hr = RPCProxyGetStartupInfo( &StartupInfo );
  333. if ( FAILED( Hr ) )
  334. {
  335. SetLastError( Hr );
  336. return FALSE;
  337. }
  338. PROCESS_INFORMATION ProcessInfo;
  339. CHAR sApplicationPath[MAX_PATH];
  340. CHAR *pApplicationName = NULL;
  341. CHAR sCmdLine[MAX_PATH];
  342. DWORD dwLen = MAX_PATH;
  343. DWORD dwCount;
  344. dwCount = SearchPathA(NULL, // Search Path, NULL is PATH
  345. "regsvr32.exe", // Application
  346. NULL, // Extension (already specified)
  347. dwLen, // Length (char's) of sApplicationPath
  348. sApplicationPath, // Path + Name for application
  349. &pApplicationName ); // File part of sApplicationPath
  350. if (dwCount == 0)
  351. {
  352. return FALSE;
  353. }
  354. if (dwCount > dwLen)
  355. {
  356. SetLastError( ERROR_BUFFER_OVERFLOW );
  357. return FALSE;
  358. }
  359. strcpy(sCmdLine, "regsvr32 /s rpcproxy.dll");
  360. BOOL RetVal = CreateProcessA(
  361. sApplicationPath, // name of executable module
  362. sCmdLine, // command line string
  363. NULL, // SD
  364. NULL, // SD
  365. FALSE, // handle inheritance option
  366. CREATE_NO_WINDOW, // creation flags
  367. NULL, // new environment block
  368. NULL, // current directory name
  369. &StartupInfo, // startup information
  370. &ProcessInfo // process information
  371. );
  372. if ( !RetVal )
  373. return FALSE;
  374. WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
  375. DWORD Status;
  376. GetExitCodeProcess( ProcessInfo.hProcess, &Status );
  377. CloseHandle( ProcessInfo.hProcess );
  378. CloseHandle( ProcessInfo.hThread );
  379. if ( ERROR_SUCCESS == Status )
  380. return TRUE;
  381. SetLastError( Status );
  382. return FALSE;
  383. }
  384. //---------------------------------------------------------------------
  385. // SetupRegistry()
  386. //
  387. // Add RPC proxy specific registry entries to contol its operation.
  388. //
  389. // \HKEY_LOCAL_MACHINE
  390. // \Software
  391. // \Microsoft
  392. // \Rpc
  393. // \RpcProxy
  394. // \Enabled:REG_DWORD:0x00000001
  395. // \ValidPorts:REG_SZ:<hostname>:1-5000
  396. //
  397. //---------------------------------------------------------------------
  398. HRESULT SetupRegistry()
  399. {
  400. DWORD dwEnabled = 0x01;
  401. DWORD dwSize;
  402. DWORD dwStatus;
  403. WCHAR *pwsValidPorts = 0;
  404. char szHostName[MAX_TCPIP_HOST_NAME];
  405. HRESULT hr;
  406. // Note that gethostname() is an ANSI (non-unicode) function:
  407. if (SOCKET_ERROR == gethostname(szHostName,sizeof(szHostName)))
  408. {
  409. dwStatus = WSAGetLastError();
  410. return SELFREG_E_CLASS;
  411. }
  412. dwSize = 1 + _mbstrlen(szHostName);
  413. pwsValidPorts = (WCHAR*)MemAllocate( sizeof(WCHAR)
  414. * (dwSize + wcslen(REG_PORT_RANGE)) );
  415. if (!pwsValidPorts)
  416. {
  417. return E_OUTOFMEMORY;
  418. }
  419. dwStatus = AnsiToUnicode((unsigned char*)szHostName,dwSize,pwsValidPorts);
  420. if (dwStatus != NO_ERROR)
  421. {
  422. MemFree(pwsValidPorts);
  423. return SELFREG_E_CLASS;
  424. }
  425. wcscat(pwsValidPorts,REG_PORT_RANGE);
  426. if ( !RegSetKeyAndValueIfDontExist( REG_RPC_PATH,
  427. REG_RPCPROXY,
  428. REG_ENABLED,
  429. (unsigned short *)&dwEnabled,
  430. REG_DWORD,
  431. sizeof(DWORD))
  432. || !RegSetKeyAndValueIfDontExist( REG_RPC_PATH,
  433. REG_RPCPROXY,
  434. REG_VALID_PORTS,
  435. pwsValidPorts,
  436. REG_SZ) )
  437. {
  438. MemFree(pwsValidPorts);
  439. return SELFREG_E_CLASS;
  440. }
  441. MemFree(pwsValidPorts);
  442. hr = RegisterEventLog ();
  443. return hr;
  444. }
  445. //---------------------------------------------------------------------
  446. // CleanupRegistry()
  447. //
  448. // Delete the RpcProxy specific registry entries.
  449. //---------------------------------------------------------------------
  450. HRESULT CleanupRegistry()
  451. {
  452. HRESULT hr;
  453. LONG lStatus;
  454. DWORD dwLength = sizeof(WCHAR) + sizeof(REG_RPC_PATH)
  455. + sizeof(REG_RPCPROXY);
  456. WCHAR *pwsSubKey;
  457. pwsSubKey = (WCHAR*)_alloca(sizeof(WCHAR)*dwLength);
  458. wcscpy(pwsSubKey,REG_RPC_PATH);
  459. wcscat(pwsSubKey,TEXT("\\"));
  460. wcscat(pwsSubKey,REG_RPCPROXY);
  461. lStatus = RegDeleteKey( HKEY_LOCAL_MACHINE,
  462. pwsSubKey );
  463. (void) UnRegisterEventLog ();
  464. return S_OK;
  465. }
  466. //---------------------------------------------------------------------
  467. // GetMetaBaseString()
  468. //
  469. // Retrieve a string value from the metabase.
  470. //---------------------------------------------------------------------
  471. HRESULT GetMetaBaseString( IN IMSAdminBase *pIMeta,
  472. IN METADATA_HANDLE hMetaBase,
  473. IN WCHAR *pwsKeyPath,
  474. IN DWORD dwIdent,
  475. OUT WCHAR *pwsBuffer,
  476. IN OUT DWORD *pdwBufferSize )
  477. {
  478. HRESULT hr;
  479. DWORD dwSize;
  480. METADATA_RECORD *pmbRecord;
  481. dwSize = sizeof(METADATA_RECORD);
  482. pmbRecord = (METADATA_RECORD*)MemAllocate(dwSize);
  483. if (!pmbRecord)
  484. {
  485. return ERROR_OUTOFMEMORY;
  486. }
  487. memset(pmbRecord,0,dwSize);
  488. pmbRecord->dwMDIdentifier = dwIdent;
  489. pmbRecord->dwMDAttributes = 0; // METADATA_INHERIT;
  490. pmbRecord->dwMDUserType = IIS_MD_UT_SERVER;
  491. pmbRecord->dwMDDataType = STRING_METADATA;
  492. pmbRecord->dwMDDataLen = *pdwBufferSize;
  493. pmbRecord->pbMDData = (BYTE*)pwsBuffer;
  494. hr = pIMeta->GetData( hMetaBase,
  495. pwsKeyPath,
  496. pmbRecord,
  497. &dwSize );
  498. #ifdef DBG_REG
  499. if (FAILED(hr))
  500. {
  501. DbgPrint("pIMeta->GetData(): Failed: 0x%x\n",hr);
  502. }
  503. #endif
  504. MemFree(pmbRecord);
  505. return hr;
  506. }
  507. //---------------------------------------------------------------------
  508. // SetMetaBaseString()
  509. //
  510. // Store a string value into the metabase.
  511. //---------------------------------------------------------------------
  512. HRESULT SetMetaBaseString( IMSAdminBase *pIMeta,
  513. METADATA_HANDLE hMetaBase,
  514. WCHAR *pwsKeyPath,
  515. DWORD dwIdent,
  516. WCHAR *pwsBuffer,
  517. DWORD dwAttributes,
  518. DWORD dwUserType )
  519. {
  520. HRESULT hr;
  521. METADATA_RECORD MbRecord;
  522. memset(&MbRecord,0,sizeof(MbRecord));
  523. MbRecord.dwMDIdentifier = dwIdent;
  524. MbRecord.dwMDAttributes = dwAttributes;
  525. MbRecord.dwMDUserType = dwUserType;
  526. MbRecord.dwMDDataType = STRING_METADATA;
  527. MbRecord.dwMDDataLen = sizeof(WCHAR) * (1 + wcslen(pwsBuffer));
  528. MbRecord.pbMDData = (BYTE*)pwsBuffer;
  529. hr = pIMeta->SetData( hMetaBase,
  530. pwsKeyPath,
  531. &MbRecord );
  532. return hr;
  533. }
  534. #if IIS_LOCKDOWN_LIST
  535. HRESULT
  536. AddDllToIISList(
  537. SAFEARRAY* Array )
  538. {
  539. //
  540. // Add the ISAPI to the IIS list.
  541. //
  542. HRESULT Hr;
  543. WCHAR ExtensionPath[ MAX_PATH ];
  544. DWORD dwRet =
  545. GetModuleFileNameW(
  546. g_hInst,
  547. ExtensionPath,
  548. MAX_PATH );
  549. if ( !dwRet )
  550. return HRESULT_FROM_WIN32( GetLastError() );
  551. // Search for the DLL. If its already in the list, do nothing
  552. Hr = SafeArrayLock( Array );
  553. if ( FAILED( Hr ) )
  554. return Hr;
  555. for ( unsigned int i = Array->rgsabound[0].lLbound;
  556. i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements; i++ )
  557. {
  558. VARIANT & IElem = ((VARIANT*)Array->pvData)[i];
  559. if ( _wcsicmp( (WCHAR*)IElem.bstrVal, ExtensionPath ) == 0 )
  560. {
  561. SafeArrayUnlock( Array );
  562. return S_OK;
  563. }
  564. }
  565. // Need to add the DLL
  566. SAFEARRAYBOUND SafeBounds;
  567. SafeBounds.lLbound = Array->rgsabound[0].lLbound;
  568. SafeBounds.cElements = Array->rgsabound[0].cElements+1;
  569. SafeArrayUnlock( Array );
  570. Hr = SafeArrayRedim( Array, &SafeBounds );
  571. if ( FAILED( Hr ) )
  572. return Hr;
  573. VARIANT bstrvar;
  574. VariantInit( &bstrvar );
  575. bstrvar.vt = VT_BSTR;
  576. bstrvar.bstrVal = SysAllocString( ExtensionPath );
  577. long Index = SafeBounds.lLbound + SafeBounds.cElements - 1;
  578. Hr = SafeArrayPutElement( Array, &Index, (void*)&bstrvar );
  579. VariantClear( &bstrvar );
  580. if ( FAILED( Hr ) )
  581. return Hr;
  582. return S_OK;
  583. }
  584. HRESULT
  585. RemoveDllFromIISList(
  586. SAFEARRAY *Array )
  587. {
  588. // Remove the DLL from the IIS list
  589. HRESULT Hr;
  590. WCHAR ExtensionPath[ MAX_PATH ];
  591. DWORD dwRet =
  592. GetModuleFileNameW(
  593. g_hInst,
  594. ExtensionPath,
  595. MAX_PATH );
  596. if ( !dwRet )
  597. return HRESULT_FROM_WIN32( GetLastError() );
  598. Hr = SafeArrayLock( Array );
  599. if ( FAILED( Hr ) )
  600. return Hr;
  601. ULONG NewSize = 0;
  602. SIZE_T j = Array->rgsabound[0].lLbound;
  603. SIZE_T k = Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  604. while( j < k )
  605. {
  606. VARIANT & JElem = ((VARIANT*)Array->pvData)[j];
  607. // This element is fine, keep it
  608. if ( 0 != _wcsicmp( (WCHAR*)JElem.bstrVal, ExtensionPath ) )
  609. {
  610. NewSize++;
  611. j++;
  612. }
  613. else
  614. {
  615. // find a suitable element to replace the bad element with
  616. while( j < --k )
  617. {
  618. VARIANT & KElem = ((VARIANT*)Array->pvData)[k];
  619. if ( 0 != _wcsicmp( (WCHAR*)KElem.bstrVal, ExtensionPath ) )
  620. {
  621. // found element. move it
  622. VARIANT temp = JElem;
  623. JElem = KElem;
  624. KElem = temp;
  625. break;
  626. }
  627. }
  628. }
  629. }
  630. SAFEARRAYBOUND ArrayBounds;
  631. ArrayBounds = Array->rgsabound[0];
  632. ArrayBounds.cElements = NewSize;
  633. SafeArrayUnlock( Array );
  634. Hr = SafeArrayRedim( Array, &ArrayBounds );
  635. if ( FAILED( Hr ) )
  636. return Hr;
  637. return S_OK;
  638. }
  639. #endif // #if #if IIS_LOCKDOWN_LIST
  640. #if IIS_SEC_CONSOLE
  641. HRESULT
  642. EnableRpcProxyExtension (
  643. void
  644. )
  645. /*++
  646. Routine Description:
  647. Enables the rpc proxy extension in the list of IIS ISAPI extensions.
  648. Arguments:
  649. Return Value:
  650. Standard HRESULT
  651. --*/
  652. {
  653. HRESULT hr;
  654. WCHAR* wszRootWeb6 = L"IIS://LOCALHOST/W3SVC";
  655. IISWebService * pWeb = NULL;
  656. VARIANT var1,var2;
  657. BSTR ExtensionPath = NULL;
  658. BSTR ExtensionGroup = NULL;
  659. BSTR ExtensionDescription = NULL;
  660. WCHAR FilterPath[ MAX_PATH + 1 ];
  661. WCHAR ExtensionNameBuffer[ MAX_PATH ];
  662. DWORD dwRet;
  663. hr = ADsGetObject(wszRootWeb6, IID_IISWebService, (void**)&pWeb);
  664. if (SUCCEEDED(hr) && NULL != pWeb)
  665. {
  666. VariantInit(&var1);
  667. VariantInit(&var2);
  668. var1.vt = VT_BOOL;
  669. var1.boolVal = VARIANT_TRUE;
  670. var2.vt = VT_BOOL;
  671. var2.boolVal = VARIANT_TRUE;
  672. dwRet = GetModuleFileNameW(
  673. g_hInst,
  674. FilterPath,
  675. MAX_PATH );
  676. if ( (dwRet > 0) && (dwRet != MAX_PATH))
  677. {
  678. FilterPath[MAX_PATH] = '\0';
  679. ASSERT(GetLastError() == NO_ERROR);
  680. }
  681. else
  682. {
  683. ASSERT(GetLastError() != NO_ERROR);
  684. hr = HRESULT_FROM_WIN32( GetLastError() );
  685. goto CleanupAndExit;
  686. }
  687. if (! LoadStringW(g_hInst, // handle to resource module
  688. IDS_EXTENSION_NAME, // resource identifier
  689. ExtensionNameBuffer, // resource buffer
  690. MAX_PATH ) ) // size of buffer
  691. {
  692. hr = HRESULT_FROM_WIN32( GetLastError() );
  693. goto CleanupAndExit;
  694. }
  695. ExtensionPath = SysAllocString(FilterPath);
  696. if (ExtensionPath == NULL)
  697. {
  698. hr = E_OUTOFMEMORY;
  699. goto CleanupAndExit;
  700. }
  701. ExtensionGroup = SysAllocString(L"RPCProxy");
  702. if (ExtensionGroup == NULL)
  703. {
  704. hr = E_OUTOFMEMORY;
  705. goto CleanupAndExit;
  706. }
  707. ExtensionDescription = SysAllocString(ExtensionNameBuffer);
  708. if (ExtensionDescription == NULL)
  709. {
  710. hr = E_OUTOFMEMORY;
  711. goto CleanupAndExit;
  712. }
  713. // During an upgrade the extension will already exist, so the API will fail.
  714. hr = pWeb->AddExtensionFile(ExtensionPath, var1, ExtensionGroup, var2, ExtensionDescription);
  715. if (SUCCEEDED(hr))
  716. {
  717. hr = pWeb->AddDependency(ExtensionPath, ExtensionGroup);
  718. if (SUCCEEDED(hr))
  719. {
  720. hr = S_OK;
  721. }
  722. }
  723. else
  724. {
  725. if (HRESULT_CODE(hr) == ERROR_DUP_NAME)
  726. {
  727. hr = S_OK;
  728. }
  729. else
  730. {
  731. #ifdef DBG_ERROR
  732. DbgPrint("pWeb->AddExtensionFile failed: %X\r\n", hr);
  733. #endif
  734. // fall through with hr
  735. }
  736. }
  737. VariantClear(&var1);
  738. VariantClear(&var2);
  739. pWeb->Release();
  740. }
  741. else
  742. {
  743. #ifdef DBG_ERROR
  744. DbgPrint("FAIL:no object: %X\r\n", hr);
  745. #endif
  746. // fall through with hr
  747. }
  748. CleanupAndExit:
  749. if (ExtensionPath != NULL)
  750. SysFreeString(ExtensionPath);
  751. if (ExtensionGroup != NULL)
  752. SysFreeString(ExtensionGroup);
  753. if (ExtensionDescription != NULL)
  754. SysFreeString(ExtensionDescription);
  755. return hr;
  756. }
  757. HRESULT
  758. DisableRpcProxyExtension (
  759. void
  760. )
  761. /*++
  762. Routine Description:
  763. Disables the rpc proxy extension in the list of IIS ISAPI extensions.
  764. Arguments:
  765. Return Value:
  766. Standard HRESULT
  767. --*/
  768. {
  769. BSTR ExtensionPath = NULL;
  770. HRESULT hr;
  771. WCHAR* wszRootWeb6 = L"IIS://LOCALHOST/W3SVC";
  772. IISWebService * pWeb = NULL;
  773. DWORD dwRet;
  774. WCHAR FilterPath[ MAX_PATH + 1 ];
  775. hr = ADsGetObject(wszRootWeb6, IID_IISWebService, (void**)&pWeb);
  776. if (SUCCEEDED(hr) && NULL != pWeb)
  777. {
  778. dwRet = GetModuleFileNameW(
  779. g_hInst,
  780. FilterPath,
  781. MAX_PATH );
  782. if ( (dwRet > 0) && (dwRet != MAX_PATH))
  783. {
  784. FilterPath[MAX_PATH] = '\0';
  785. ASSERT(GetLastError() == NO_ERROR);
  786. }
  787. else
  788. {
  789. ASSERT(GetLastError() != NO_ERROR);
  790. hr = HRESULT_FROM_WIN32( GetLastError() );
  791. goto CleanupAndExit;
  792. }
  793. ExtensionPath = SysAllocString(FilterPath);
  794. if (ExtensionPath == NULL)
  795. {
  796. hr = E_OUTOFMEMORY;
  797. goto CleanupAndExit;
  798. }
  799. // Call DeleteExtensionFileRecord for each of the DLLs you are removing
  800. // from the system. This removes entries from WSERL.
  801. hr = pWeb->DeleteExtensionFileRecord(ExtensionPath);
  802. if (SUCCEEDED(hr))
  803. {
  804. // Call RemoveApplication (pYourAppName) - this removes your entry from
  805. // ApplicationDependencies
  806. hr = pWeb->RemoveApplication(ExtensionPath);
  807. // fall through with the hr
  808. }
  809. else
  810. {
  811. #ifdef DBG_ERROR
  812. DbgPrint("pWeb->DeleteExtensionFileRecord failed: %X\r\n", hr);
  813. #endif
  814. // fall through with the hr
  815. }
  816. }
  817. else
  818. {
  819. // fall through with the hr
  820. }
  821. CleanupAndExit:
  822. if (ExtensionPath != NULL)
  823. SysFreeString(ExtensionPath);
  824. return hr;
  825. }
  826. #endif // #if IIS_SEC_CONSOLE
  827. #if IIS_LOCKDOWN_LIST
  828. HRESULT
  829. ModifyLockdownList( bool Add )
  830. {
  831. // Toplevel function to modify the IIS lockdown list.
  832. // If Add is 1, then the ISAPI is added. If Add is 0, then the ISAPI is removed.
  833. HRESULT Hr;
  834. IADs *Service = NULL;
  835. SAFEARRAY* Array = NULL;
  836. bool ArrayLocked = false;
  837. VARIANT var;
  838. VariantInit( &var );
  839. Hr = ADsGetObject( BSTR( L"IIS://LocalHost/W3SVC" ), __uuidof( IADs ), (void**)&Service );
  840. if ( FAILED( Hr ) )
  841. return Hr;
  842. Hr = Service->Get( BSTR( L"IsapiRestrictionList" ), &var );
  843. if ( FAILED(Hr) )
  844. {
  845. // This property doesn't exist on IIS5 or IIS5.1 don't install it
  846. Hr = S_OK;
  847. goto cleanup;
  848. }
  849. Array = var.parray;
  850. Hr = SafeArrayLock( Array );
  851. if ( FAILED( Hr ) )
  852. goto cleanup;
  853. ArrayLocked = true;
  854. if ( !Array->rgsabound[0].cElements )
  855. {
  856. // The array has no elements which means no restrictions.
  857. Hr = S_OK;
  858. goto cleanup;
  859. }
  860. VARIANT & FirstElem = ((VARIANT*)Array->pvData)[ Array->rgsabound[0].lLbound ];
  861. if ( _wcsicmp(L"0", (WCHAR*)FirstElem.bstrVal ) == 0 )
  862. {
  863. //
  864. // According to the IIS6 spec, a 0 means that all ISAPIs are denied except
  865. // those that are explicitly listed.
  866. //
  867. // If installing: add to the list.
  868. // If uninstalling: remove from the list
  869. //
  870. SafeArrayUnlock( Array );
  871. ArrayLocked = false;
  872. if ( Add )
  873. Hr = AddDllToIISList( Array );
  874. else
  875. Hr = RemoveDllFromIISList( Array );
  876. if ( FAILED( Hr ) )
  877. goto cleanup;
  878. }
  879. else if ( _wcsicmp( L"1", (WCHAR*)FirstElem.bstrVal ) == 0 )
  880. {
  881. //
  882. // According to the IIS6 spec, a 1 means that all ISAPIs are allowed except
  883. // those that are explicitly denied.
  884. //
  885. // If installing: remove from the list
  886. // If uninstalling: Do nothing
  887. //
  888. SafeArrayUnlock( Array );
  889. ArrayLocked = false;
  890. if ( Add )
  891. {
  892. Hr = RemoveDllFromIISList( Array );
  893. if ( FAILED( Hr ) )
  894. goto cleanup;
  895. }
  896. }
  897. else
  898. {
  899. Hr = E_FAIL;
  900. goto cleanup;
  901. }
  902. Hr = Service->Put( BSTR( L"IsapiRestrictionList" ), var );
  903. if ( FAILED( Hr ) )
  904. goto cleanup;
  905. Hr = Service->SetInfo();
  906. if ( FAILED( Hr ) )
  907. goto cleanup;
  908. Hr = S_OK;
  909. cleanup:
  910. if ( Array && ArrayLocked )
  911. SafeArrayUnlock( Array );
  912. if ( Service )
  913. Service->Release();
  914. VariantClear( &var );
  915. return Hr;
  916. }
  917. HRESULT
  918. AddToLockdownListDisplayPutString(
  919. SAFEARRAY *Array,
  920. unsigned long Position,
  921. const WCHAR *String )
  922. {
  923. HRESULT Hr;
  924. VARIANT Var;
  925. VariantInit( &Var );
  926. Var.vt = VT_BSTR;
  927. Var.bstrVal = SysAllocString( String );
  928. if ( !Var.bstrVal )
  929. return E_OUTOFMEMORY;
  930. long Index = (unsigned long)Position;
  931. Hr = SafeArrayPutElement( Array, &Index, (void*)&Var );
  932. VariantClear( &Var );
  933. return Hr;
  934. }
  935. HRESULT
  936. AddToLockdownListDisplay( SAFEARRAY *Array )
  937. {
  938. HRESULT Hr;
  939. WCHAR FilterPath[ MAX_PATH ];
  940. DWORD dwRet =
  941. GetModuleFileNameW(
  942. g_hInst,
  943. FilterPath,
  944. MAX_PATH );
  945. if ( !dwRet )
  946. return HRESULT_FROM_WIN32( GetLastError() );
  947. WCHAR ExtensionName[ MAX_PATH ];
  948. if (! LoadStringW(g_hInst, // handle to resource module
  949. IDS_EXTENSION_NAME, // resource identifier
  950. ExtensionName, // resource buffer
  951. MAX_PATH ) ) // size of buffer
  952. return HRESULT_FROM_WIN32( GetLastError() );
  953. //
  954. // Check to see if the ISAPI is already in the list. If it is, don't modify
  955. // list.
  956. //
  957. Hr = SafeArrayLock( Array );
  958. if ( FAILED( Hr ) )
  959. return Hr;
  960. for( unsigned long i = Array->rgsabound[0].lLbound;
  961. i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  962. i++ )
  963. {
  964. VARIANT & CurrentElement = ((VARIANT*)Array->pvData)[ i ];
  965. BSTR BSTRString = CurrentElement.bstrVal;
  966. if ( _wcsicmp( (WCHAR*)BSTRString, FilterPath ) == 0 )
  967. {
  968. // ISAPI is already in the list, don't do anything
  969. SafeArrayUnlock( Array );
  970. return S_OK;
  971. }
  972. }
  973. SAFEARRAYBOUND SafeArrayBound = Array->rgsabound[0];
  974. unsigned long OldSize = SafeArrayBound.cElements;
  975. SafeArrayBound.cElements += 3;
  976. SafeArrayUnlock( Array );
  977. Hr = SafeArrayRedim( Array, &SafeArrayBound );
  978. if ( FAILED( Hr ) )
  979. return Hr;
  980. Hr = AddToLockdownListDisplayPutString( Array, OldSize, L"1" );
  981. if ( FAILED( Hr ) )
  982. return Hr;
  983. Hr = AddToLockdownListDisplayPutString( Array, OldSize + 1, FilterPath );
  984. if ( FAILED( Hr ) )
  985. return Hr;
  986. Hr = AddToLockdownListDisplayPutString( Array, OldSize + 2, ExtensionName );
  987. if ( FAILED( Hr ) )
  988. return Hr;
  989. return S_OK;
  990. }
  991. HRESULT
  992. SafeArrayRemoveSlice(
  993. SAFEARRAY *Array,
  994. unsigned long lBound,
  995. unsigned long uBound )
  996. {
  997. // Remove a slice of an array.
  998. SIZE_T ElementsToRemove = uBound - lBound + 1;
  999. HRESULT Hr = SafeArrayLock( Array );
  1000. if ( FAILED( Hr ) )
  1001. return Hr;
  1002. if ( uBound + 1 < Array->rgsabound[0].cElements )
  1003. {
  1004. // At least one element exists above this element
  1005. // Step 1, move slice to temp storage
  1006. VARIANT *Temp = (VARIANT*)_alloca( sizeof(VARIANT) * ElementsToRemove );
  1007. memcpy( Temp, &((VARIANT*)Array->pvData)[ lBound ], sizeof(VARIANT)*ElementsToRemove );
  1008. // Step 2, collapse hole left by slice
  1009. memmove( &((VARIANT*)Array->pvData)[ lBound ],
  1010. &((VARIANT*)Array->pvData)[ uBound + 1 ],
  1011. sizeof(VARIANT) * ( Array->rgsabound[0].cElements - ( uBound + 1 ) ) );
  1012. // Step 3, move slice to end of array
  1013. memcpy( &((VARIANT*)Array->pvData)[ Array->rgsabound[0].cElements - ElementsToRemove ],
  1014. Temp,
  1015. sizeof(VARIANT)*ElementsToRemove );
  1016. }
  1017. SAFEARRAYBOUND SafeArrayBound = Array->rgsabound[0];
  1018. SafeArrayBound.cElements -= (ULONG)ElementsToRemove;
  1019. SafeArrayUnlock( Array );
  1020. return SafeArrayRedim( Array, &SafeArrayBound );
  1021. }
  1022. HRESULT
  1023. RemoveFromLockdownListDisplay(
  1024. SAFEARRAY *Array )
  1025. {
  1026. HRESULT Hr;
  1027. WCHAR FilterPath[ MAX_PATH ];
  1028. DWORD dwRet =
  1029. GetModuleFileNameW(
  1030. g_hInst,
  1031. FilterPath,
  1032. MAX_PATH );
  1033. if ( !dwRet )
  1034. return HRESULT_FROM_WIN32( GetLastError() );
  1035. Hr = SafeArrayLock( Array );
  1036. if ( FAILED( Hr ) )
  1037. return Hr;
  1038. for( unsigned int i = Array->rgsabound[0].lLbound;
  1039. i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  1040. i++ )
  1041. {
  1042. VARIANT & CurrentElement = ((VARIANT*)Array->pvData)[ i ];
  1043. BSTR BSTRString = CurrentElement.bstrVal;
  1044. if ( _wcsicmp( (WCHAR*)BSTRString, FilterPath ) == 0 )
  1045. {
  1046. // ISAPI is in the list, remove it
  1047. Hr = SafeArrayUnlock( Array );
  1048. if ( FAILED( Hr ) )
  1049. return Hr;
  1050. Hr = SafeArrayRemoveSlice(
  1051. Array,
  1052. (i == 0) ? 0 : i - 1,
  1053. min( i + 1, Array->rgsabound[0].cElements - 1 ) );
  1054. return Hr;
  1055. }
  1056. }
  1057. // ISAPI wasn't found. Nothing to do.
  1058. SafeArrayUnlock( Array );
  1059. return S_OK;
  1060. }
  1061. HRESULT
  1062. ModifyLockdownListDisplay( bool Add )
  1063. {
  1064. HRESULT Hr;
  1065. SAFEARRAY* Array = NULL;
  1066. IADs *Service = NULL;
  1067. VARIANT var;
  1068. VariantInit( &var );
  1069. Hr = ADsGetObject( BSTR( L"IIS://LocalHost/W3SVC" ), __uuidof( IADs ), (void**)&Service );
  1070. if ( FAILED( Hr ) )
  1071. {
  1072. #ifdef DBG_REG
  1073. DbgPrint("RpcProxy: ADsGetObject(): Failed: 0x%x (%d)\n",
  1074. Hr, Hr );
  1075. #endif
  1076. return Hr;
  1077. }
  1078. Hr = Service->Get( BSTR( L"RestrictionListCustomDesc" ), &var );
  1079. if ( FAILED(Hr) )
  1080. {
  1081. #ifdef DBG_REG
  1082. DbgPrint("RpcProxy: Service->Get(): Failed: 0x%x (%d)\n",
  1083. Hr, Hr );
  1084. #endif
  1085. // This property doesn't exist on IIS5 or IIS5.1 don't install or uninstall it
  1086. Hr = S_OK;
  1087. goto cleanup;
  1088. }
  1089. Array = var.parray;
  1090. if ( Add )
  1091. Hr = AddToLockdownListDisplay( Array );
  1092. else
  1093. Hr = RemoveFromLockdownListDisplay( Array );
  1094. if ( FAILED( Hr ) )
  1095. {
  1096. #ifdef DBG_REG
  1097. DbgPrint("RpcProxy: AddToLockdownListDisplay/RemoveFromLockdownListDisplay(): Failed: 0x%x (%d)\n",
  1098. Hr, Hr );
  1099. #endif
  1100. goto cleanup;
  1101. }
  1102. Hr = Service->Put( BSTR( L"RestrictionListCustomDesc" ), var );
  1103. if ( FAILED( Hr ) )
  1104. {
  1105. #ifdef DBG_REG
  1106. DbgPrint("RpcProxy: Service->Put(): Failed: 0x%x (%d)\n",
  1107. Hr, Hr );
  1108. #endif
  1109. goto cleanup;
  1110. }
  1111. Hr = Service->SetInfo();
  1112. if ( FAILED( Hr ) )
  1113. {
  1114. #ifdef DBG_REG
  1115. DbgPrint("RpcProxy: Service->SetInfo(): Failed: 0x%x (%d)\n",
  1116. Hr, Hr );
  1117. #endif
  1118. goto cleanup;
  1119. }
  1120. cleanup:
  1121. VariantClear( &var );
  1122. if ( Service )
  1123. Service->Release();
  1124. return Hr;
  1125. }
  1126. #endif // #if IIS_LOCKDOWN_LIST
  1127. //---------------------------------------------------------------------
  1128. // GetMetaBaseDword()
  1129. //
  1130. // Get a DWORD value from the metabase.
  1131. //---------------------------------------------------------------------
  1132. HRESULT GetMetaBaseDword( IMSAdminBase *pIMeta,
  1133. METADATA_HANDLE hMetaBase,
  1134. WCHAR *pwsKeyPath,
  1135. DWORD dwIdent,
  1136. DWORD *pdwValue )
  1137. {
  1138. HRESULT hr;
  1139. DWORD dwSize;
  1140. METADATA_RECORD MbRecord;
  1141. memset(&MbRecord,0,sizeof(MbRecord));
  1142. *pdwValue = 0;
  1143. MbRecord.dwMDIdentifier = dwIdent;
  1144. MbRecord.dwMDAttributes = 0;
  1145. MbRecord.dwMDUserType = IIS_MD_UT_SERVER;
  1146. MbRecord.dwMDDataType = DWORD_METADATA;
  1147. MbRecord.dwMDDataLen = sizeof(DWORD);
  1148. MbRecord.pbMDData = (unsigned char *)pdwValue;
  1149. hr = pIMeta->GetData( hMetaBase,
  1150. pwsKeyPath,
  1151. &MbRecord,
  1152. &dwSize );
  1153. return hr;
  1154. }
  1155. //---------------------------------------------------------------------
  1156. // SetMetaBaseDword()
  1157. //
  1158. // Store a DWORD value into the metabase.
  1159. //---------------------------------------------------------------------
  1160. HRESULT SetMetaBaseDword( IMSAdminBase *pIMeta,
  1161. METADATA_HANDLE hMetaBase,
  1162. WCHAR *pwsKeyPath,
  1163. DWORD dwIdent,
  1164. DWORD dwValue,
  1165. DWORD dwAttributes,
  1166. DWORD dwUserType )
  1167. {
  1168. HRESULT hr;
  1169. DWORD dwSize;
  1170. METADATA_RECORD MbRecord;
  1171. memset(&MbRecord,0,sizeof(MbRecord));
  1172. MbRecord.dwMDIdentifier = dwIdent;
  1173. MbRecord.dwMDAttributes = dwAttributes;
  1174. MbRecord.dwMDUserType = dwUserType;
  1175. MbRecord.dwMDDataType = DWORD_METADATA;
  1176. MbRecord.dwMDDataLen = sizeof(DWORD);
  1177. MbRecord.pbMDData = (unsigned char *)&dwValue;
  1178. hr = pIMeta->SetData( hMetaBase,
  1179. pwsKeyPath,
  1180. &MbRecord );
  1181. return hr;
  1182. }
  1183. RPC_STATUS
  1184. GetIISConnectionTimeout (
  1185. OUT ULONG *ConnectionTimeout
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. Retrieve the connection timeout for IIS:
  1190. W3Svc/1/ROOT/Rpc/ConnectionTimeout
  1191. Arguments:
  1192. ConnectionTimeout - the connection timeout in seconds. Undefined
  1193. on failure
  1194. Return Value:
  1195. RPC_S_OK or RPC_S_* for error
  1196. --*/
  1197. {
  1198. HRESULT hr = 0;
  1199. DWORD dwValue = 0;
  1200. DWORD dwSize = 0;
  1201. IMSAdminBase *pIMeta = NULL;
  1202. BOOL CoInitSucceeded = FALSE;
  1203. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  1204. if (FAILED(hr))
  1205. {
  1206. #ifdef DBG_ERROR
  1207. DbgPrint("GetIISConnectionTimeout: CoInitializeEx failed: Error: %X\n", hr);
  1208. #endif
  1209. goto MapErrorAndExit;
  1210. }
  1211. CoInitSucceeded = TRUE;
  1212. hr = CoCreateInstance( CLSID_MSAdminBase,
  1213. NULL,
  1214. CLSCTX_ALL,
  1215. IID_IMSAdminBase,
  1216. (void **)&pIMeta );
  1217. if (FAILED(hr))
  1218. {
  1219. #ifdef DBG_REG
  1220. DbgPrint("CoCreateInstance(): Failed: 0x%x\n",hr);
  1221. #endif
  1222. goto MapErrorAndExit;
  1223. }
  1224. //
  1225. // Get: /W3Svc/1/ROOT/rpc/ConnectionTimeout
  1226. //
  1227. hr = GetMetaBaseDword( pIMeta,
  1228. METADATA_MASTER_ROOT_HANDLE,
  1229. TEXT("/lm/w3svc/1/ROOT/Rpc"),
  1230. MD_CONNECTION_TIMEOUT,
  1231. ConnectionTimeout);
  1232. if (FAILED(hr))
  1233. {
  1234. #ifdef DBG_REG
  1235. DbgPrint("GetMetaBaseDword: Failed: 0x%x\n",hr);
  1236. #endif
  1237. // couldn't read at the site level - try the root
  1238. //
  1239. // Get: /W3Svc/ConnectionTimeout
  1240. //
  1241. hr = GetMetaBaseDword( pIMeta,
  1242. METADATA_MASTER_ROOT_HANDLE,
  1243. TEXT("/lm/w3svc"),
  1244. MD_CONNECTION_TIMEOUT,
  1245. ConnectionTimeout);
  1246. if (FAILED(hr))
  1247. {
  1248. #ifdef DBG_REG
  1249. DbgPrint("GetMetaBaseDword: Failed: 0x%x\n",hr);
  1250. #endif
  1251. }
  1252. }
  1253. MapErrorAndExit:
  1254. if (pIMeta != NULL)
  1255. pIMeta->Release();
  1256. if (CoInitSucceeded)
  1257. CoUninitialize();
  1258. if (FAILED(hr))
  1259. return RPC_S_OUT_OF_MEMORY;
  1260. else
  1261. return RPC_S_OK;
  1262. }
  1263. //---------------------------------------------------------------------
  1264. // SetupMetaBase()
  1265. //
  1266. // Setup entries in the metabase for both the filter and ISAPI parts
  1267. // of the RPC proxy. Note that these entries used to be in the registry.
  1268. //
  1269. // W3Svc/Filters/FilterLoadOrder "...,RpcProxy"
  1270. // W3Svc/Filters/RpcProxy/FilterImagePath "%SystemRoot%\System32\RpcProxy"
  1271. // W3Svc/Filters/RpcProxy/KeyType "IIsFilter"
  1272. // W3Svc/Filters/RpcProxy/FilterDescription "Microsoft RPC Proxy Filter, v1.0"
  1273. //
  1274. // W3Svc/1/ROOT/Rpc/KeyType "IIsWebVirtualDir"
  1275. // W3Svc/1/ROOT/Rpc/VrPath "%SystemRoot%\System32\RpcProxy"
  1276. // W3Svc/1/ROOT/Rpc/AccessPerm 0x205
  1277. // W3Svc/1/ROOT/Rpc/Win32Error 0x0
  1278. // W3Svc/1/ROOT/Rpc/DirectoryBrowsing 0x4000001E
  1279. // W3Svc/1/ROOT/Rpc/AppIsolated 0x0
  1280. // W3Svc/1/ROOT/Rpc/AppRoot "/LM/W3SVC/1/Root/rpc"
  1281. // W3Svc/1/ROOT/Rpc/AppWamClsid "{BF285648-0C5C-11D2-A476-0000F8080B50}"
  1282. // W3Svc/1/ROOT/Rpc/AppFriendlyName "rpc"
  1283. //
  1284. //---------------------------------------------------------------------
  1285. HRESULT SetupMetaBase()
  1286. {
  1287. HRESULT hr = 0;
  1288. DWORD dwValue = 0;
  1289. DWORD dwSize = 0;
  1290. DWORD dwBufferSize = sizeof(WCHAR) * ORIGINAL_BUFFER_SIZE;
  1291. WCHAR *pwsBuffer = (WCHAR*)MemAllocate(dwBufferSize);
  1292. WCHAR *pwsSystemRoot = _wgetenv(SYSTEM_ROOT);
  1293. WCHAR wsPath[METADATA_MAX_NAME_LEN];
  1294. IMSAdminBase *pIMeta;
  1295. METADATA_HANDLE hMetaBase;
  1296. //
  1297. // Name of this DLL (and where it is):
  1298. //
  1299. // WCHAR wszModule[256];
  1300. //
  1301. // if (!GetModuleFileName( g_hInst, wszModule,
  1302. // sizeof(wszModule)/sizeof(WCHAR)))
  1303. // {
  1304. // return SELFREG_E_CLASS;
  1305. // }
  1306. if (!pwsBuffer)
  1307. {
  1308. return E_OUTOFMEMORY;
  1309. }
  1310. hr = CoCreateInstance( CLSID_MSAdminBase,
  1311. NULL,
  1312. CLSCTX_ALL,
  1313. IID_IMSAdminBase,
  1314. (void **)&pIMeta );
  1315. if (FAILED(hr))
  1316. {
  1317. #ifdef DBG_REG
  1318. DbgPrint("CoCreateInstance(): Failed: 0x%x\n",hr);
  1319. #endif
  1320. MemFree(pwsBuffer);
  1321. return hr;
  1322. }
  1323. // Get a handle to the Web service:
  1324. hr = pIMeta->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  1325. LOCAL_MACHINE_W3SVC,
  1326. (METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE),
  1327. 20,
  1328. &hMetaBase );
  1329. if (FAILED(hr))
  1330. {
  1331. #ifdef DBG_REG
  1332. DbgPrint("pIMeta->OpenKey(): Failed: 0x%x\n",hr);
  1333. #endif
  1334. MemFree(pwsBuffer);
  1335. pIMeta->Release();
  1336. return hr;
  1337. }
  1338. //
  1339. // IIS Filter: FilterLoadOrder
  1340. //
  1341. dwSize = dwBufferSize;
  1342. hr = GetMetaBaseString( pIMeta,
  1343. hMetaBase,
  1344. MD_KEY_FILTERS, // See iiscnfg.h
  1345. MD_FILTER_LOAD_ORDER, // See iiscnfg.h
  1346. pwsBuffer,
  1347. &dwSize );
  1348. if (FAILED(hr) && (hr != MD_ERROR_DATA_NOT_FOUND))
  1349. {
  1350. #ifdef DBG_REG
  1351. DbgPrint("GetMetaBaseString(): Failed: 0x%x\n",hr);
  1352. #endif
  1353. MemFree(pwsBuffer);
  1354. pIMeta->Release();
  1355. return hr;
  1356. }
  1357. if (hr == MD_ERROR_DATA_NOT_FOUND)
  1358. pwsBuffer[0] = '\0';
  1359. // Check whether too much of the buffer has been used up.
  1360. pwsBuffer[ORIGINAL_BUFFER_SIZE-1] = '\0';
  1361. if (wcslen(pwsBuffer) > MAX_USED_BUFFER_SIZE)
  1362. {
  1363. ASSERT(0);
  1364. MemFree(pwsBuffer);
  1365. pIMeta->Release();
  1366. return E_UNEXPECTED;
  1367. }
  1368. if (!wcsstr(pwsBuffer,RPCPROXY))
  1369. {
  1370. // RpcProxy is not in FilterLoadOrder, so add it (if there were
  1371. // previous elements).
  1372. if (hr != MD_ERROR_DATA_NOT_FOUND)
  1373. {
  1374. wcscat(pwsBuffer,TEXT(","));
  1375. }
  1376. wcscat(pwsBuffer,RPCPROXY);
  1377. hr = SetMetaBaseString( pIMeta,
  1378. hMetaBase,
  1379. MD_KEY_FILTERS,
  1380. MD_FILTER_LOAD_ORDER,
  1381. pwsBuffer,
  1382. 0,
  1383. IIS_MD_UT_SERVER );
  1384. }
  1385. if (FAILED(hr))
  1386. {
  1387. MemFree(pwsBuffer);
  1388. pIMeta->Release();
  1389. return hr;
  1390. }
  1391. //
  1392. // IIS Filter: RpcProxy/FilterImagePath
  1393. //
  1394. hr = pIMeta->AddKey( hMetaBase, MD_KEY_FILTERS_RPCPROXY );
  1395. if ( (FAILED(hr)) && (hr != 0x800700b7))
  1396. {
  1397. MemFree(pwsBuffer);
  1398. pIMeta->Release();
  1399. return hr;
  1400. }
  1401. wcscpy(pwsBuffer,pwsSystemRoot);
  1402. wcscat(pwsBuffer,RPCPROXY_PATH);
  1403. wcscat(pwsBuffer,TEXT("\\"));
  1404. wcscat(pwsBuffer,RPCPROXY_DLL);
  1405. hr = SetMetaBaseString( pIMeta,
  1406. hMetaBase,
  1407. MD_KEY_FILTERS_RPCPROXY,
  1408. MD_FILTER_IMAGE_PATH,
  1409. pwsBuffer,
  1410. 0,
  1411. IIS_MD_UT_SERVER );
  1412. if (FAILED(hr))
  1413. {
  1414. MemFree(pwsBuffer);
  1415. pIMeta->Release();
  1416. return hr;
  1417. }
  1418. //
  1419. // IIS Filter: Filters/RpcProxy/KeyType
  1420. //
  1421. wcscpy(pwsBuffer,IISFILTER);
  1422. hr = SetMetaBaseString( pIMeta,
  1423. hMetaBase,
  1424. MD_KEY_FILTERS_RPCPROXY,
  1425. MD_KEY_TYPE,
  1426. pwsBuffer,
  1427. 0,
  1428. IIS_MD_UT_SERVER );
  1429. if (FAILED(hr))
  1430. {
  1431. MemFree(pwsBuffer);
  1432. pIMeta->Release();
  1433. return hr;
  1434. }
  1435. wcscpy(pwsBuffer, FILTER_DESCRIPTION_W);
  1436. hr = SetMetaBaseString( pIMeta,
  1437. hMetaBase,
  1438. MD_KEY_FILTERS_RPCPROXY,
  1439. MD_FILTER_DESCRIPTION,
  1440. pwsBuffer,
  1441. 0,
  1442. IIS_MD_UT_SERVER );
  1443. if (FAILED(hr))
  1444. {
  1445. MemFree(pwsBuffer);
  1446. pIMeta->Release();
  1447. return hr;
  1448. }
  1449. // We do not write the events we subscribe for to the metabase. We have
  1450. // already advertised our presence and in IIS 5 mode IIS will load us,
  1451. // ask for the events, and write them for us in the metabase
  1452. //
  1453. // Set: /W3Svc/1/ROOT/rpc/AccessPerm
  1454. //
  1455. dwValue = ACCESS_PERM_FLAGS;
  1456. hr = SetMetaBaseDword( pIMeta,
  1457. hMetaBase,
  1458. MD_KEY_ROOT_RPC,
  1459. MD_ACCESS_PERM,
  1460. dwValue,
  1461. METADATA_INHERIT,
  1462. IIS_MD_UT_FILE );
  1463. if (FAILED(hr))
  1464. {
  1465. MemFree(pwsBuffer);
  1466. pIMeta->Release();
  1467. return hr;
  1468. }
  1469. //
  1470. // Disable entity body preload for this ISAPI
  1471. //
  1472. dwValue = 0;
  1473. hr = SetMetaBaseDword( pIMeta,
  1474. hMetaBase,
  1475. MD_KEY_ROOT_RPC,
  1476. MD_UPLOAD_READAHEAD_SIZE,
  1477. dwValue,
  1478. METADATA_INHERIT,
  1479. IIS_MD_UT_FILE );
  1480. if (FAILED(hr))
  1481. {
  1482. MemFree(pwsBuffer);
  1483. pIMeta->Release();
  1484. return hr;
  1485. }
  1486. //
  1487. // Set: /W3Svc/1/ROOT/rpc/Win32Error
  1488. //
  1489. dwValue = 0;
  1490. hr = SetMetaBaseDword( pIMeta,
  1491. hMetaBase,
  1492. MD_KEY_ROOT_RPC,
  1493. MD_WIN32_ERROR,
  1494. dwValue,
  1495. METADATA_INHERIT,
  1496. IIS_MD_UT_SERVER );
  1497. if (FAILED(hr))
  1498. {
  1499. MemFree(pwsBuffer);
  1500. pIMeta->Release();
  1501. return hr;
  1502. }
  1503. //
  1504. // Set: /W3Svc/1/ROOT/rpc/DirectroyBrowsing
  1505. //
  1506. dwValue = DIRECTORY_BROWSING_FLAGS;
  1507. hr = SetMetaBaseDword( pIMeta,
  1508. hMetaBase,
  1509. MD_KEY_ROOT_RPC,
  1510. MD_DIRECTORY_BROWSING,
  1511. dwValue,
  1512. METADATA_INHERIT,
  1513. IIS_MD_UT_FILE );
  1514. if (FAILED(hr))
  1515. {
  1516. pIMeta->Release();
  1517. CoUninitialize();
  1518. return hr;
  1519. }
  1520. //
  1521. // Set: /W3Svc/1/ROOT/rpc/KeyType
  1522. //
  1523. wcscpy(pwsBuffer,IIS_WEB_VIRTUAL_DIR);
  1524. hr = SetMetaBaseString( pIMeta,
  1525. hMetaBase,
  1526. MD_KEY_ROOT_RPC,
  1527. MD_KEY_TYPE,
  1528. pwsBuffer,
  1529. 0,
  1530. IIS_MD_UT_SERVER );
  1531. if (FAILED(hr))
  1532. {
  1533. MemFree(pwsBuffer);
  1534. pIMeta->Release();
  1535. return hr;
  1536. }
  1537. //
  1538. // Set: /W3Svc/1/ROOT/rpc/VrPath
  1539. //
  1540. wcscpy(pwsBuffer,pwsSystemRoot);
  1541. wcscat(pwsBuffer,RPCPROXY_PATH);
  1542. hr = SetMetaBaseString( pIMeta,
  1543. hMetaBase,
  1544. MD_KEY_ROOT_RPC,
  1545. MD_VR_PATH,
  1546. pwsBuffer,
  1547. METADATA_INHERIT,
  1548. IIS_MD_UT_FILE );
  1549. if (FAILED(hr))
  1550. {
  1551. MemFree(pwsBuffer);
  1552. pIMeta->Release();
  1553. return hr;
  1554. }
  1555. #if FALSE
  1556. //
  1557. // Set: /W3Svc/1/ROOT/rpc/AppIsolated
  1558. //
  1559. dwValue = 0;
  1560. hr = SetMetaBaseDword( pIMeta,
  1561. hMetaBase,
  1562. MD_KEY_ROOT_RPC,
  1563. MD_APP_ISOLATED,
  1564. dwValue,
  1565. METADATA_INHERIT,
  1566. IIS_MD_UT_WAM );
  1567. if (FAILED(hr))
  1568. {
  1569. MemFree(pwsBuffer);
  1570. pIMeta->Release();
  1571. return hr;
  1572. }
  1573. //
  1574. // Set: /W3Svc/1/ROOT/rpc/AppRoot
  1575. //
  1576. wcscpy(pwsBuffer,APP_ROOT_PATH);
  1577. hr = SetMetaBaseString( pIMeta,
  1578. hMetaBase,
  1579. MD_KEY_ROOT_RPC,
  1580. MD_APP_ROOT,
  1581. pwsBuffer,
  1582. METADATA_INHERIT,
  1583. IIS_MD_UT_FILE );
  1584. if (FAILED(hr))
  1585. {
  1586. MemFree(pwsBuffer);
  1587. pIMeta->Release();
  1588. return hr;
  1589. }
  1590. //
  1591. // Set: /W3Svc/1/ROOT/rpc/AppWamClsid
  1592. //
  1593. wcscpy(pwsBuffer,APP_WAM_CLSID);
  1594. hr = SetMetaBaseString( pIMeta,
  1595. hMetaBase,
  1596. MD_KEY_ROOT_RPC,
  1597. MD_APP_WAM_CLSID,
  1598. pwsBuffer,
  1599. METADATA_INHERIT,
  1600. IIS_MD_UT_WAM );
  1601. if (FAILED(hr))
  1602. {
  1603. MemFree(pwsBuffer);
  1604. pIMeta->Release();
  1605. return hr;
  1606. }
  1607. //
  1608. // Set: /W3Svc/1/ROOT/rpc/AppFriendlyName
  1609. //
  1610. wcscpy(pwsBuffer,APP_FRIENDLY_NAME);
  1611. hr = SetMetaBaseString( pIMeta,
  1612. hMetaBase,
  1613. MD_KEY_ROOT_RPC,
  1614. MD_APP_FRIENDLY_NAME,
  1615. pwsBuffer,
  1616. METADATA_INHERIT,
  1617. IIS_MD_UT_WAM );
  1618. if (FAILED(hr))
  1619. {
  1620. MemFree(pwsBuffer);
  1621. pIMeta->Release();
  1622. return hr;
  1623. }
  1624. #endif
  1625. //
  1626. // Release the handle and buffer:
  1627. //
  1628. MemFree(pwsBuffer);
  1629. pIMeta->CloseKey(hMetaBase);
  1630. pIMeta->Release();
  1631. CoUninitialize();
  1632. return 0;
  1633. }
  1634. //---------------------------------------------------------------------
  1635. // CleanupMetaBase()
  1636. //
  1637. //---------------------------------------------------------------------
  1638. HRESULT CleanupMetaBase()
  1639. {
  1640. HRESULT hr = 0;
  1641. DWORD dwSize = 0;
  1642. WCHAR *pwsRpcProxy;
  1643. WCHAR *pws;
  1644. DWORD dwBufferSize = sizeof(WCHAR) * ORIGINAL_BUFFER_SIZE;
  1645. WCHAR *pwsBuffer = (WCHAR*)MemAllocate(dwBufferSize);
  1646. // CComPtr <IMSAdminBase> pIMeta;
  1647. IMSAdminBase *pIMeta;
  1648. METADATA_HANDLE hMetaBase;
  1649. if (!pwsBuffer)
  1650. {
  1651. return ERROR_OUTOFMEMORY;
  1652. }
  1653. hr = CoCreateInstance( CLSID_MSAdminBase,
  1654. NULL,
  1655. CLSCTX_ALL,
  1656. IID_IMSAdminBase,
  1657. (void **)&pIMeta );
  1658. if (FAILED(hr))
  1659. {
  1660. MemFree(pwsBuffer);
  1661. return hr;
  1662. }
  1663. //
  1664. // Get a handle to the Web service:
  1665. //
  1666. hr = pIMeta->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  1667. TEXT("/LM/W3SVC"),
  1668. (METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE),
  1669. 20,
  1670. &hMetaBase );
  1671. if (FAILED(hr))
  1672. {
  1673. MemFree(pwsBuffer);
  1674. pIMeta->Release();
  1675. return hr;
  1676. }
  1677. //
  1678. // Remove the RpcProxy reference from the FilterLoadOrder value:
  1679. //
  1680. dwSize = dwBufferSize;
  1681. hr = GetMetaBaseString( pIMeta,
  1682. hMetaBase,
  1683. MD_KEY_FILTERS,
  1684. MD_FILTER_LOAD_ORDER,
  1685. pwsBuffer,
  1686. &dwSize );
  1687. if (!FAILED(hr))
  1688. {
  1689. // Check whether too much of the buffer has been used up.
  1690. pwsBuffer[ORIGINAL_BUFFER_SIZE-1] = '\0';
  1691. if (wcslen(pwsBuffer) > MAX_USED_BUFFER_SIZE)
  1692. {
  1693. ASSERT(0);
  1694. MemFree(pwsBuffer);
  1695. pIMeta->Release();
  1696. return E_UNEXPECTED;
  1697. }
  1698. if (pwsRpcProxy=wcsstr(pwsBuffer,RPCPROXY))
  1699. {
  1700. // "RpcProxy" is in FilterLoadOrder, so remove it:
  1701. // Check to see if RpcProxy is at the start of the list:
  1702. if (pwsRpcProxy != pwsBuffer)
  1703. {
  1704. pwsRpcProxy--; // Want to remove the comma before...
  1705. dwSize = sizeof(RPCPROXY);
  1706. }
  1707. else
  1708. {
  1709. dwSize = sizeof(RPCPROXY) - 1;
  1710. }
  1711. pws = pwsRpcProxy + dwSize;
  1712. memcpy(pwsRpcProxy,pws,sizeof(WCHAR)*(1+wcslen(pws)));
  1713. hr = SetMetaBaseString( pIMeta,
  1714. hMetaBase,
  1715. MD_KEY_FILTERS,
  1716. MD_FILTER_LOAD_ORDER,
  1717. pwsBuffer,
  1718. 0,
  1719. IIS_MD_UT_SERVER );
  1720. }
  1721. }
  1722. //
  1723. // Delete: /W3Svc/Filters/RpcProxy
  1724. //
  1725. hr = pIMeta->DeleteKey( hMetaBase,
  1726. MD_KEY_FILTERS_RPCPROXY );
  1727. //
  1728. // Delete: /W3Svc/1/ROOT/Rpc
  1729. //
  1730. hr = pIMeta->DeleteKey( hMetaBase,
  1731. MD_KEY_FILTERS_RPCPROXY );
  1732. //
  1733. // Release the handle and buffer:
  1734. //
  1735. MemFree(pwsBuffer);
  1736. pIMeta->CloseKey(hMetaBase);
  1737. pIMeta->Release();
  1738. return S_OK;
  1739. }
  1740. const WCHAR InetInfoName[] = L"inetinfo.exe";
  1741. const ULONG InetInfoNameLength = sizeof(InetInfoName) / sizeof(WCHAR) - 1; // in characters without terminating NULL
  1742. BOOL
  1743. UpdateIsIISInCompatibilityMode (
  1744. void
  1745. )
  1746. /*++
  1747. Routine Description:
  1748. Reads the compatibility mode state. It used to read it from the metabase,
  1749. but after repeated problems in compatibility mode, WadeH suggested a simpler approach -
  1750. check whether we run in inetinfo. If yet, we're in compatibility mode.
  1751. Arguments:
  1752. Return Value:
  1753. non-zero if the variable is correctly updated. 0 otherwise
  1754. --*/
  1755. {
  1756. WCHAR ExtensionPath[ MAX_PATH + 1 ];
  1757. ULONG ModuleFileNameLength; // in characters without terminating NULL
  1758. DWORD dwRet = GetModuleFileNameW(
  1759. GetModuleHandle(NULL),
  1760. ExtensionPath,
  1761. MAX_PATH );
  1762. if ( (dwRet > 0) && (dwRet != MAX_PATH))
  1763. {
  1764. ExtensionPath[MAX_PATH] = '\0';
  1765. ASSERT(GetLastError() == NO_ERROR);
  1766. }
  1767. else
  1768. {
  1769. ASSERT(GetLastError() != NO_ERROR);
  1770. return FALSE;
  1771. }
  1772. ModuleFileNameLength = wcslen(ExtensionPath);
  1773. if (ModuleFileNameLength < InetInfoNameLength)
  1774. {
  1775. fIsIISInCompatibilityMode = FALSE;
  1776. }
  1777. if (_wcsicmp(ExtensionPath + ModuleFileNameLength - InetInfoNameLength, InetInfoName) == 0)
  1778. {
  1779. fIsIISInCompatibilityMode = TRUE;
  1780. }
  1781. else
  1782. {
  1783. fIsIISInCompatibilityMode = FALSE;
  1784. }
  1785. return TRUE;
  1786. }
  1787. //---------------------------------------------------------------------
  1788. // DllRegisterServer()
  1789. //
  1790. // Setup the Registry and MetaBase for the RPC proxy.
  1791. //---------------------------------------------------------------------
  1792. const char ChildProcessVar[] = "__RPCPROXY_CHILD_PROCESS";
  1793. const char ChildProcessVarValue[] = "__FROM_SETUP";
  1794. HRESULT DllRegisterServer()
  1795. {
  1796. HRESULT hr;
  1797. WORD wVersion = MAKEWORD(1,1);
  1798. WSADATA wsaData;
  1799. char EnvironmentVarBuffer[MAX_PATH];
  1800. DWORD Temp;
  1801. BOOL Result;
  1802. DWORD LastError;
  1803. #ifdef DBG_REG
  1804. DbgPrint("RpcProxy: DllRegisterServer(): Start\n");
  1805. #endif
  1806. // check if we are have already been called from the RPCProxy DllRegister routine
  1807. Temp = GetEnvironmentVariableA(ChildProcessVar, EnvironmentVarBuffer, MAX_PATH);
  1808. #ifdef DBG_REG
  1809. DbgPrint("RpcProxy: Result of looking for environment variable - %d\n", Temp);
  1810. #endif
  1811. // GetEnvironmentVariable does not count the terminating NULL.
  1812. if (Temp < sizeof(ChildProcessVarValue) - 1)
  1813. {
  1814. #ifdef DBG_REG
  1815. DbgPrint("RpcProxy: Not a child process - spawning one\n");
  1816. #endif
  1817. // we didn't find the variable. Add it and spawn ourselves to register out of proc
  1818. Result = SetEnvironmentVariableA (ChildProcessVar, ChildProcessVarValue);
  1819. if (Result == FALSE)
  1820. return E_OUTOFMEMORY;
  1821. Result = RegisterOutOfProc();
  1822. if (Result == FALSE)
  1823. {
  1824. // capture the last error before we call SetEnvironmentVariable
  1825. LastError = GetLastError();
  1826. }
  1827. // before processing the result, remove the environment variable. If this fails, there
  1828. // isn't much we can do. Fortunately, failure to delete is completely benign
  1829. (void) SetEnvironmentVariableA (ChildProcessVar, NULL);
  1830. if (Result == FALSE)
  1831. {
  1832. return HRESULT_FROM_WIN32(LastError);
  1833. }
  1834. return S_OK;
  1835. }
  1836. if (WSAStartup(wVersion,&wsaData))
  1837. {
  1838. return SELFREG_E_CLASS;
  1839. }
  1840. hr = CoInitializeEx(0,COINIT_MULTITHREADED);
  1841. if (FAILED(hr))
  1842. {
  1843. hr = CoInitializeEx(0,COINIT_APARTMENTTHREADED);
  1844. if (FAILED(hr))
  1845. {
  1846. #ifdef DBG_REG
  1847. DbgPrint("RpcProxy: CoInitialize(): Failed: 0x%x\n", hr );
  1848. #endif
  1849. return hr;
  1850. }
  1851. }
  1852. hr = SetupRegistry();
  1853. if (FAILED(hr))
  1854. {
  1855. #ifdef DBG_REG
  1856. DbgPrint("RpcProxy: SetupRegistry(): Failed: 0x%x (%d)\n",
  1857. hr, hr );
  1858. #endif
  1859. goto CleanupAndExit;
  1860. }
  1861. hr = SetupMetaBase();
  1862. if (FAILED(hr))
  1863. {
  1864. #ifdef DBG_REG
  1865. DbgPrint("RpcProxy: SetupMetaBase(): Failed: 0x%x (%d)\n",
  1866. hr, hr );
  1867. #endif
  1868. goto CleanupAndExit;
  1869. }
  1870. #if IIS_LOCKDOWN_LIST
  1871. hr = ModifyLockdownList( true );
  1872. #endif // #if IIS_LOCKDOWN_LIST
  1873. #if IIS_SEC_CONSOLE
  1874. hr = EnableRpcProxyExtension();
  1875. #endif // #if IIS_SEC_CONSOLE
  1876. if ( FAILED( hr ) )
  1877. {
  1878. #ifdef DBG_REG
  1879. DbgPrint("RpcProxy: ModifyLockdownList(): Failed: 0x%x (%d)\n",
  1880. hr, hr );
  1881. #endif
  1882. goto CleanupAndExit;
  1883. }
  1884. #if IIS_LOCKDOWN_LIST
  1885. hr = ModifyLockdownListDisplay( true );
  1886. #ifdef DBG_REG
  1887. if ( FAILED( hr ) )
  1888. {
  1889. DbgPrint("RpcProxy: ModifyLockdownListDisplay(): Failed: 0x%x (%d)\n",
  1890. hr, hr );
  1891. }
  1892. #endif
  1893. #endif // #if IIS_LOCKDOWN_LIST
  1894. CleanupAndExit:
  1895. CoUninitialize();
  1896. #ifdef DBG_REG
  1897. DbgPrint("RpcProxy: DllRegisterServer(): End: hr: 0x%x\n",hr);
  1898. #endif
  1899. return hr;
  1900. }
  1901. //---------------------------------------------------------------------
  1902. // DllUnregisterServer()
  1903. //
  1904. // Uninstall Registry and MetaBase values used by the RPC proxy.
  1905. //
  1906. // Modified to mostly return S_Ok, even if a problem occurs. This is
  1907. // done so that the uninstall will complete even if there is a problem
  1908. // in the un-register.
  1909. //---------------------------------------------------------------------
  1910. HRESULT DllUnregisterServer()
  1911. {
  1912. HRESULT hr;
  1913. WORD wVersion = MAKEWORD(1,1);
  1914. WSADATA wsaData;
  1915. #ifdef DBG_REG
  1916. DbgPrint("RpcProxy: DllUnregisterServer(): Start\n");
  1917. #endif
  1918. if (WSAStartup(wVersion,&wsaData))
  1919. {
  1920. return SELFREG_E_CLASS;
  1921. }
  1922. hr = CoInitializeEx(0,COINIT_MULTITHREADED);
  1923. if (FAILED(hr))
  1924. {
  1925. hr = CoInitializeEx(0,COINIT_APARTMENTTHREADED);
  1926. if (FAILED(hr))
  1927. {
  1928. #ifdef DBG_REG
  1929. DbgPrint("RpcProxy: CoInitializeEx() Failed: 0x%x\n",hr);
  1930. #endif
  1931. return S_OK;
  1932. }
  1933. }
  1934. #if IIS_SEC_CONSOLE
  1935. hr = DisableRpcProxyExtension();
  1936. #endif // #if IIS_SEC_CONSOLE
  1937. #if IIS_LOCKDOWN_LIST
  1938. hr = ModifyLockdownList( false );
  1939. #endif // #if IIS_LOCKDOWN_LIST
  1940. if (FAILED(hr))
  1941. {
  1942. #ifdef DBG_REG
  1943. DbgPrint("RpcProxy: ModifyLockdownList() Failed: 0x%x (%d)\n",hr,hr);
  1944. #endif
  1945. return S_OK;
  1946. }
  1947. #if IIS_LOCKDOWN_LIST
  1948. hr = ModifyLockdownListDisplay( false );
  1949. if (FAILED(hr))
  1950. {
  1951. #ifdef DBG_REG
  1952. DbgPrint("RpcProxy: ModifyLockdownListDisplay() Failed: 0x%x (%d)\n",hr,hr);
  1953. #endif
  1954. return S_OK;
  1955. }
  1956. #endif // #if IIS_LOCKDOWN_LIST
  1957. hr = CleanupRegistry();
  1958. if (FAILED(hr))
  1959. {
  1960. #ifdef DBG_REG
  1961. DbgPrint("RpcProxy: CleanupRegistry() Failed: 0x%x (%d)\n",hr,hr);
  1962. #endif
  1963. return S_OK;
  1964. }
  1965. hr = CleanupMetaBase();
  1966. #ifdef DBG_REG
  1967. if (FAILED(hr))
  1968. {
  1969. DbgPrint("RpcProxy: CleanupMetaBase() Failed: 0x%x (%d)\n",hr,hr);
  1970. }
  1971. #endif
  1972. CoUninitialize();
  1973. #ifdef DBG_REG
  1974. DbgPrint("RpcProxy: DllUnregisterServer(): Start\n");
  1975. #endif
  1976. return S_OK;
  1977. }
  1978. //--------------------------------------------------------------------
  1979. // DllMain()
  1980. //
  1981. //--------------------------------------------------------------------
  1982. BOOL WINAPI DllMain( HINSTANCE hInst,
  1983. ULONG ulReason,
  1984. LPVOID pvReserved )
  1985. {
  1986. BOOL fInitialized = TRUE;
  1987. switch (ulReason)
  1988. {
  1989. case DLL_PROCESS_ATTACH:
  1990. if (!DisableThreadLibraryCalls(hInst))
  1991. {
  1992. fInitialized = FALSE;
  1993. }
  1994. else
  1995. {
  1996. g_hInst = hInst;
  1997. }
  1998. break;
  1999. case DLL_PROCESS_DETACH:
  2000. FreeServerInfo(&g_pServerInfo);
  2001. break;
  2002. case DLL_THREAD_ATTACH:
  2003. // Not used. Disabled.
  2004. break;
  2005. case DLL_THREAD_DETACH:
  2006. // Not used. Disabled.
  2007. break;
  2008. }
  2009. return fInitialized;
  2010. }