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.

795 lines
21 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N C B A S E . C P P
  7. //
  8. // Contents: Basic common code.
  9. //
  10. // Notes: Pollute this under penalty of death.
  11. //
  12. // Author: shaunco 20 Sep 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "ncbase.h"
  18. #include "ncdebug.h"
  19. #include "ncperms.h"
  20. #include "ncstring.h"
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Function: AddRefObj
  24. //
  25. // Purpose: AddRef's the object pointed to by punk by calling
  26. // punk->AddRef();
  27. //
  28. // Arguments:
  29. // punk [in] Object to be AddRef'd. Can be NULL.
  30. //
  31. // Returns: Result of AddRef call.
  32. //
  33. // Author: danielwe 25 Feb 1997
  34. //
  35. // Notes: Using this function to AddRef an object will reduce
  36. // our code size.
  37. //
  38. NOTHROW
  39. ULONG
  40. AddRefObj (
  41. IUnknown* punk)
  42. {
  43. return (punk) ? punk->AddRef () : 0;
  44. }
  45. //+---------------------------------------------------------------------------
  46. //
  47. // Function: ReleaseObj
  48. //
  49. // Purpose: Releases the object pointed to by punk by calling
  50. // punk->Release();
  51. //
  52. // Arguments:
  53. // punk [in] Object to be released. Can be NULL.
  54. //
  55. // Returns: Result of Release call.
  56. //
  57. // Author: danielwe 25 Feb 1997
  58. //
  59. // Notes: Using this function to release a (possibly NULL) object will
  60. // reduce our code size.
  61. //
  62. NOTHROW
  63. ULONG
  64. ReleaseObj (
  65. IUnknown* punk)
  66. {
  67. return (punk) ? punk->Release () : 0;
  68. }
  69. //+--------------------------------------------------------------------------
  70. //
  71. // Function: DwWin32ErrorFromHr
  72. //
  73. // Purpose: Converts the HRESULT to a Win32 error or SetupApi error.
  74. //
  75. // Arguments:
  76. // hr [in] The HRESULT to convert
  77. //
  78. // Returns: Converted DWORD value.
  79. //
  80. // Author: billbe 22 Apr 1997
  81. //
  82. // Notes:
  83. //
  84. NOTHROW
  85. DWORD
  86. DwWin32ErrorFromHr (
  87. HRESULT hr)
  88. {
  89. DWORD dw = ERROR_SUCCESS;
  90. // All success codes convert to ERROR_SUCCESS so we only need to handle
  91. // failures.
  92. if (FAILED(hr))
  93. {
  94. DWORD dwFacility = HRESULT_FACILITY(hr);
  95. if (FACILITY_SETUPAPI == dwFacility)
  96. {
  97. // reconstruct the SetupApi error using the correct masks
  98. dw = HRESULT_CODE(hr) | APPLICATION_ERROR_MASK |
  99. ERROR_SEVERITY_ERROR;
  100. // Check to make sure dw maps to a known SetupApi error
  101. AssertSz(FDwordWithinRange(ERROR_EXPECTED_SECTION_NAME,
  102. dw, ERROR_GENERAL_SYNTAX) ||
  103. FDwordWithinRange(ERROR_WRONG_INF_STYLE,
  104. dw, ERROR_NO_BACKUP) ||
  105. FDwordWithinRange(ERROR_NO_ASSOCIATED_CLASS,
  106. dw, ERROR_SET_SYSTEM_RESTORE_POINT),
  107. "The mapped SetupApi error is not known "
  108. "(or is new)!!!");
  109. }
  110. else if (FACILITY_WIN32 == dwFacility)
  111. {
  112. dw = HRESULT_CODE(hr);
  113. }
  114. else if (FACILITY_ITF == dwFacility)
  115. {
  116. dw = ERROR_GEN_FAILURE;
  117. }
  118. else
  119. {
  120. // cannot convert it
  121. AssertSz(FALSE, "Facility was not SETUP or WIN32!");
  122. dw = hr;
  123. }
  124. }
  125. return dw;
  126. }
  127. //+---------------------------------------------------------------------------
  128. //
  129. // Function: HrCoTaskMemAlloc
  130. //
  131. // Purpose: Call CoTaskMemAlloc but return an HRESULT.
  132. //
  133. // Arguments:
  134. // cb [in] Count of bytes to allocate.
  135. // ppv [out] Returned pointer to bytes.
  136. //
  137. // Returns: S_OK or E_OUTOFMEMORY.
  138. //
  139. // Author: shaunco 31 May 1997
  140. //
  141. // Notes:
  142. //
  143. HRESULT
  144. HrCoTaskMemAlloc (
  145. ULONG cb,
  146. VOID** ppv)
  147. {
  148. HRESULT hr = S_OK;
  149. *ppv = CoTaskMemAlloc (cb);
  150. if (!*ppv)
  151. {
  152. hr = E_OUTOFMEMORY;
  153. }
  154. TraceError ("HrCoTaskMemAlloc", hr);
  155. return hr;
  156. }
  157. //+---------------------------------------------------------------------------
  158. //
  159. // Function: HrCoTaskMemAllocAndDupSzLen
  160. //
  161. // Purpose: Allocate memory using CoTaskMemAlloc and copy a string
  162. // into it. This is used by the implementation of COM interfaces
  163. // that return strings.
  164. //
  165. // Arguments:
  166. // pszSrc [in] Pointer to source string.
  167. // cchSrc [in] Number of characters to copy from source string.
  168. // ppszDst [out] Address of pointer to destination string.
  169. //
  170. // Returns: S_OK or E_OUTOFMEMORY
  171. //
  172. // Author: shaunco 14 Jan 1999
  173. //
  174. // Notes: NULL input pointers are allocated as empty strings
  175. // deliberately.
  176. // The returned string is guaranteed to be NULL terminated.
  177. //
  178. HRESULT
  179. HrCoTaskMemAllocAndDupSzLen (
  180. IN PCWSTR pszSrc,
  181. IN ULONG cchSrc,
  182. OUT PWSTR* ppszDst,
  183. IN ULONG cchMaxDest)
  184. {
  185. Assert (ppszDst);
  186. HRESULT hr;
  187. DWORD cbCopy = min(cchSrc, cchMaxDest);
  188. DWORD cb = cbCopy * sizeof(WCHAR);
  189. hr = E_OUTOFMEMORY;
  190. *ppszDst = (PWSTR)CoTaskMemAlloc (cb + sizeof(WCHAR));
  191. if (*ppszDst)
  192. {
  193. hr = S_OK;
  194. wcsncpy (*ppszDst, pszSrc, cbCopy);
  195. (*ppszDst)[cbCopy] = 0;
  196. }
  197. TraceError ("HrCoTaskMemAllocAndDupSz", hr);
  198. return hr;
  199. }
  200. HRESULT
  201. HrCoTaskMemAllocAndDupSz (
  202. IN PCWSTR pszSrc,
  203. OUT PWSTR* ppszDst,
  204. IN ULONG cchMaxDest)
  205. {
  206. return HrCoTaskMemAllocAndDupSzLen (
  207. pszSrc,
  208. CchOfSzSafe(pszSrc),
  209. ppszDst,
  210. cchMaxDest);
  211. }
  212. //+---------------------------------------------------------------------------
  213. //
  214. // Function: HrFromLastWin32Error
  215. //
  216. // Purpose: Converts the GetLastError() Win32 call into a proper HRESULT.
  217. //
  218. // Arguments:
  219. // (none)
  220. //
  221. // Returns: Converted HRESULT value.
  222. //
  223. // Author: danielwe 24 Mar 1997
  224. //
  225. // Notes: This is not inline as it actually generates quite a bit of
  226. // code.
  227. // If GetLastError returns an error that looks like a SetupApi
  228. // error, this function will convert the error to an HRESULT
  229. // with FACILITY_SETUP instead of FACILITY_WIN32
  230. //
  231. NOTHROW
  232. HRESULT
  233. HrFromLastWin32Error ()
  234. {
  235. DWORD dwError = GetLastError();
  236. HRESULT hr;
  237. // This test is testing SetupApi errors only (this is
  238. // temporary because the new HRESULT_FROM_SETUPAPI macro will
  239. // do the entire conversion)
  240. if (dwError & (APPLICATION_ERROR_MASK | ERROR_SEVERITY_ERROR))
  241. {
  242. hr = HRESULT_FROM_SETUPAPI(dwError);
  243. }
  244. else
  245. {
  246. hr = HRESULT_FROM_WIN32(dwError);
  247. }
  248. return hr;
  249. }
  250. //+---------------------------------------------------------------------------
  251. //
  252. // Function: HrGetProcAddress
  253. //
  254. // Purpose: Loads a libray and returns the address of a procedure within
  255. // the library
  256. //
  257. // Arguments:
  258. // hModule [in] The handle to the library module instance
  259. // pszaFunction [in] Function to retrieve
  260. // ppfn [out] Address of szFunction
  261. //
  262. // Returns: S_OK if successful, Win32 converted error if failure.
  263. //
  264. // Author: billbe 10 June 1997
  265. //
  266. // Notes:
  267. //
  268. HRESULT
  269. HrGetProcAddress (
  270. HMODULE hModule,
  271. PCSTR pszaFunction,
  272. FARPROC* ppfn)
  273. {
  274. Assert(hModule);
  275. Assert(pszaFunction);
  276. Assert(ppfn);
  277. HRESULT hr = S_OK;
  278. *ppfn = GetProcAddress(hModule, pszaFunction);
  279. if (!*ppfn)
  280. {
  281. hr = HrFromLastWin32Error();
  282. TraceTag(ttidError, "HrGetProcAddress failed: szFunction: %s",
  283. pszaFunction);
  284. }
  285. TraceError("HrGetProcAddress", hr);
  286. return hr;
  287. }
  288. //+---------------------------------------------------------------------------
  289. //
  290. // Function: HrLoadLibAndGetProcs
  291. //
  292. // Purpose: Load a dynamic link library and the addresses of one or
  293. // more procedures within that library.
  294. //
  295. // Arguments:
  296. // pszLibPath [in] Path to the DLL to load.
  297. // cFunctions [in] Number of procedures to load.
  298. // apszaFunctionNames [in] Array of function names. (Must be 'cFunctions'
  299. // of them.)
  300. // phmod [out] Returned handle to the loaded module.
  301. // apfn [out] Array of returned pointers to the procedures
  302. // loaded. (Must be 'cFunctions' of them.)
  303. //
  304. // Returns: S_OK if all procedures were loaded, S_FALSE if only
  305. // some of them were, or a Win32 error code. If only
  306. // one procedure is to be loaded and it is not, S_FALSE will
  307. // not be returned, rather, the reason for why the single
  308. // procedure could not be loaded will be returned. This allows
  309. // HrLoadLibAndGetProc to be implemented using this function.
  310. //
  311. // Author: shaunco 19 Jan 1998
  312. //
  313. // Notes: phmod should be freed by the caller using FreeLibrary if
  314. // the return value is S_OK.
  315. //
  316. HRESULT
  317. HrLoadLibAndGetProcs (
  318. PCWSTR pszLibPath,
  319. UINT cFunctions,
  320. const PCSTR* apszaFunctionNames,
  321. HMODULE* phmod,
  322. FARPROC* apfn)
  323. {
  324. Assert (pszLibPath);
  325. Assert (cFunctions);
  326. Assert (apszaFunctionNames);
  327. Assert (phmod);
  328. Assert (apfn);
  329. HRESULT hr = S_OK;
  330. // Load the module and initialize the output parameters.
  331. //
  332. HMODULE hmod = LoadLibrary (pszLibPath);
  333. *phmod = hmod;
  334. ZeroMemory (apfn, cFunctions * sizeof(FARPROC));
  335. if (hmod)
  336. {
  337. // Get the proc address of each function.
  338. //
  339. for (UINT i = 0; i < cFunctions; i++)
  340. {
  341. apfn[i] = GetProcAddress (hmod, apszaFunctionNames[i]);
  342. if (!apfn[i])
  343. {
  344. // Couldn't load all functions. We'll be returning S_FALSE
  345. // (if their are more than one function.)
  346. //
  347. hr = S_FALSE;
  348. TraceTag (ttidError, "HrLoadLibAndGetProcs: GetProcAddress "
  349. "for '%s' failed.",
  350. apszaFunctionNames[i]);
  351. }
  352. }
  353. // If we're only loading one function, and it failed,
  354. // return the failure.
  355. //
  356. if ((1 == cFunctions) && !apfn[0])
  357. {
  358. hr = HrFromLastWin32Error ();
  359. FreeLibrary (hmod);
  360. }
  361. }
  362. else
  363. {
  364. hr = HrFromLastWin32Error ();
  365. TraceTag (ttidError, "HrLoadLibAndGetProcs: LoadLibrary (%S) failed.",
  366. pszLibPath);
  367. }
  368. TraceError ("HrLoadLibAndGetProcs", hr);
  369. return hr;
  370. }
  371. //+---------------------------------------------------------------------------
  372. //
  373. // Function: HrGetProcAddressesVa
  374. //
  375. // Purpose: Get proc-address of each function-name passed
  376. //
  377. // Arguments:
  378. // hModule [in] handle of DLL
  379. // arglist [in] list of var-args. the expected format is
  380. // "func-name", FARPROC*, ..., NULL
  381. //
  382. // Returns: S_OK on success, otherwise an error code
  383. //
  384. // Author: kumarp 29-December-97
  385. //
  386. // Notes:
  387. //
  388. HRESULT
  389. HrGetProcAddressesVa (
  390. HMODULE hModule,
  391. va_list arglist)
  392. {
  393. PCSTR szFunctionName;
  394. FARPROC* ppfn;
  395. HRESULT hr = S_OK;
  396. typedef FARPROC* PFARPROC;
  397. while (NULL != (szFunctionName = va_arg(arglist, CHAR*)))
  398. {
  399. ppfn = va_arg(arglist, PFARPROC);
  400. *ppfn = GetProcAddress(hModule, szFunctionName);
  401. if (!*ppfn)
  402. {
  403. hr = HrFromLastWin32Error();
  404. TraceTag(ttidError, "HrGetProcAddressesVa failed: szFunction: %s",
  405. szFunctionName);
  406. break;
  407. }
  408. }
  409. TraceError("HrGetProcAddressesVa", hr);
  410. return hr;
  411. }
  412. //+---------------------------------------------------------------------------
  413. //
  414. // Function: HrGetProcAddressesV
  415. //
  416. // Purpose: Get proc-address of each function-name passed
  417. //
  418. // Arguments:
  419. // hModule [in] handle of DLL
  420. // ... [in] list of var-args. the expected format is
  421. // "func-name", FARPROC*, ..., NULL
  422. //
  423. // Returns: S_OK on success, otherwise an error code
  424. //
  425. // Author: kumarp 29-December-97
  426. //
  427. // Notes:
  428. //
  429. HRESULT
  430. HrGetProcAddressesV (
  431. HMODULE hModule,
  432. ...)
  433. {
  434. HRESULT hr=S_OK;
  435. va_list arglist;
  436. va_start(arglist, hModule);
  437. hr = HrGetProcAddressesVa(hModule, arglist);
  438. va_end(arglist);
  439. TraceError("HrGetProcAddressesV", hr);
  440. return hr;
  441. }
  442. //+---------------------------------------------------------------------------
  443. //
  444. // Function: HrLoadLibAndGetProcsV
  445. //
  446. // Purpose: Get proc-address of each function-name passed
  447. //
  448. // Arguments:
  449. // pszLibPath [in] DLL to load
  450. // phModule [out] pointer to handle of DLL loaded
  451. // ... [in] list of var-args. the expected format is
  452. // "func-name", FARPROC*, ..., NULL
  453. //
  454. // Returns: S_OK on success, otherwise an error code
  455. //
  456. // Author: kumarp 29-December-97
  457. //
  458. // Notes:
  459. //
  460. HRESULT
  461. HrLoadLibAndGetProcsV (
  462. PCWSTR pszLibPath,
  463. HMODULE* phModule,
  464. ...)
  465. {
  466. Assert(pszLibPath);
  467. Assert(phModule);
  468. HRESULT hr = S_OK;
  469. // Attempt to load the library
  470. *phModule = LoadLibrary(pszLibPath);
  471. if (*phModule)
  472. {
  473. va_list arglist;
  474. va_start(arglist, phModule);
  475. hr = HrGetProcAddressesVa(*phModule, arglist);
  476. va_end(arglist);
  477. if (FAILED(hr))
  478. {
  479. // Free the library
  480. FreeLibrary(*phModule);
  481. }
  482. }
  483. else
  484. {
  485. hr = HrFromLastWin32Error();
  486. TraceTag(ttidError, "HrLoadLibAndGetProcsV failed: szLibPath: %S",
  487. pszLibPath);
  488. }
  489. // if we failed then we should set *phModule to NULL since we might
  490. // have successfully loaded it and failed getting the proc
  491. if (FAILED(hr))
  492. {
  493. *phModule = NULL;
  494. }
  495. TraceError("HrLoadLibAndGetProcsV", hr);
  496. return hr;
  497. }
  498. //+---------------------------------------------------------------------------
  499. //
  500. // Function: HrCreateEventWithWorldAccess
  501. //
  502. // Purpose: Creates a event with permissions to allow access to
  503. // everyone.
  504. //
  505. // Arguments:
  506. // pszName [in] Name for the event.
  507. // fManualReset [in] See Win32 docs.
  508. // fInitialState [in] See Win32 docs.
  509. // pfAlreadyExists [out] TRUE if the event already existed.
  510. // FALSE otherwise.
  511. // phEvent [out] The created event.
  512. //
  513. // Returns: S_OK on success. An error code otherwise.
  514. //
  515. // Author: BillBe 16 Nov 1998
  516. //
  517. // Notes:
  518. //
  519. HRESULT
  520. HrCreateEventWithWorldAccess(PCWSTR pszName, BOOL fManualReset,
  521. BOOL fInitialState, BOOL* pfAlreadyExists, HANDLE* phEvent)
  522. {
  523. Assert(pszName);
  524. Assert(phEvent);
  525. if (pfAlreadyExists)
  526. {
  527. *pfAlreadyExists = FALSE;
  528. }
  529. *phEvent = NULL;
  530. // Create the correct descriptor.
  531. PSECURITY_DESCRIPTOR pSd;
  532. HRESULT hr = HrAllocateSecurityDescriptorAllowAccessToWorld(&pSd);
  533. if (SUCCEEDED(hr))
  534. {
  535. SECURITY_ATTRIBUTES sa = {0};
  536. sa.nLength = sizeof(sa);
  537. sa.lpSecurityDescriptor = pSd;
  538. sa.bInheritHandle = FALSE;
  539. // Create Event
  540. //
  541. *phEvent = CreateEvent(&sa, fManualReset, fInitialState, pszName);
  542. hr = HrFromLastWin32Error();
  543. if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)
  544. {
  545. if (pfAlreadyExists)
  546. {
  547. *pfAlreadyExists = TRUE;
  548. }
  549. hr = S_OK;
  550. }
  551. MemFree(pSd);
  552. }
  553. TraceError("HrCreateEventWithWorldAccess", hr);
  554. return hr;
  555. }
  556. //+---------------------------------------------------------------------------
  557. //
  558. // Function: HrCreateMutexWithWorldAccess
  559. //
  560. // Purpose: Creates a mutex with permissions to allow access to
  561. // everyone.
  562. //
  563. // Arguments:
  564. // pszName [in] Name for the mutex.
  565. // fInitialOwner [in] See Win32 docs.
  566. // pfAlreadyExists [out] TRUE if the mutex already existed,
  567. // FALSE otherwise.
  568. // phMutex [out] The created mutex.
  569. //
  570. // Returns: S_OK on success. An error code otherwise.
  571. //
  572. // Author: BillBe 16 Nov 1998
  573. //
  574. // Notes:
  575. //
  576. HRESULT
  577. HrCreateMutexWithWorldAccess (
  578. PCWSTR pszName,
  579. BOOL fInitialOwner,
  580. BOOL* pfAlreadyExists,
  581. HANDLE* phMutex)
  582. {
  583. Assert(pszName);
  584. Assert(phMutex);
  585. if (pfAlreadyExists)
  586. {
  587. *pfAlreadyExists = FALSE;
  588. }
  589. *phMutex = NULL;
  590. // Create the correct descriptor.
  591. PSECURITY_DESCRIPTOR pSd;
  592. HRESULT hr = HrAllocateSecurityDescriptorAllowAccessToWorld(&pSd);
  593. if (S_OK == hr)
  594. {
  595. SECURITY_ATTRIBUTES sa = {0};
  596. sa.nLength = sizeof(sa);
  597. sa.lpSecurityDescriptor = pSd;
  598. sa.bInheritHandle = FALSE;
  599. // Create Mutex
  600. //
  601. *phMutex = CreateMutex(&sa, fInitialOwner, pszName);
  602. hr = HrFromLastWin32Error();
  603. if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)
  604. {
  605. if (pfAlreadyExists)
  606. {
  607. *pfAlreadyExists = TRUE;
  608. }
  609. hr = S_OK;
  610. }
  611. MemFree(pSd);
  612. }
  613. TraceError("HrCreateMutexWithWorldAccess", hr);
  614. return hr;
  615. }
  616. //+---------------------------------------------------------------------------
  617. // The standard parameterization of CoSetProxyBlanket. Call this instead
  618. // of CoSetProxyBlanket so you get the same security and authentication
  619. // settings as everyone else. This version saves code space at the call-site
  620. // because it pushes only one parameter instead of eight.
  621. // This does not return an error because it does not invalidate the use of
  622. // pUnk after it's called.
  623. //
  624. VOID
  625. NcSetProxyBlanket (
  626. IN IUnknown* pUnk)
  627. {
  628. HRESULT hr;
  629. hr = CoSetProxyBlanket (
  630. pUnk,
  631. RPC_C_AUTHN_WINNT, // use NT default security
  632. RPC_C_AUTHZ_NONE, // use NT default authentication
  633. NULL, // must be null if default
  634. RPC_C_AUTHN_LEVEL_CALL, // call
  635. RPC_C_IMP_LEVEL_IMPERSONATE,
  636. NULL, // use process token
  637. EOAC_NONE);
  638. if(SUCCEEDED(hr))
  639. {
  640. IUnknown * pUnkSet = NULL;
  641. hr = pUnk->QueryInterface(&pUnkSet);
  642. if(SUCCEEDED(hr))
  643. {
  644. hr = CoSetProxyBlanket (
  645. pUnkSet,
  646. RPC_C_AUTHN_WINNT, // use NT default security
  647. RPC_C_AUTHZ_NONE, // use NT default authentication
  648. NULL, // must be null if default
  649. RPC_C_AUTHN_LEVEL_CALL, // call
  650. RPC_C_IMP_LEVEL_IMPERSONATE,
  651. NULL, // use process token
  652. EOAC_NONE);
  653. ReleaseObj(pUnkSet);
  654. }
  655. }
  656. TraceHr(ttidError, FAL, hr, (E_NOINTERFACE == hr), "NcSetProxyBlanket");
  657. }
  658. //+---------------------------------------------------------------------------
  659. //
  660. // Function: HrCreateInstanceBase
  661. //
  662. // Purpose: Creates a COM object and sets default proxy settings.
  663. //
  664. // Arguments:
  665. // rclsid [in] See documentation for CoCreateInstance.
  666. // dwClsContext [in] ""
  667. // riid [in] ""
  668. // ppv [out] ""
  669. //
  670. // Returns: S_OK on success. An error code otherwise.
  671. //
  672. // Author: mbend 1 Mar 2000
  673. //
  674. // Notes: Call type safe version HrCreateInstance
  675. //
  676. HRESULT
  677. HrCreateInstanceBase (
  678. REFCLSID rclsid,
  679. DWORD dwClsContext,
  680. REFIID riid,
  681. LPVOID * ppv)
  682. {
  683. HRESULT hr = S_OK;
  684. hr = ::CoCreateInstance(rclsid, NULL, dwClsContext, riid, ppv);
  685. if(SUCCEEDED(hr) && (dwClsContext & CLSCTX_LOCAL_SERVER))
  686. {
  687. NcSetProxyBlanket(reinterpret_cast<IUnknown*>(*ppv));
  688. }
  689. TraceError("HrCreateInstanceBase", hr);
  690. return hr;
  691. }
  692. //+---------------------------------------------------------------------------
  693. //
  694. // Function: HrQIAndSetProxyBlanketBase
  695. //
  696. // Purpose: Performs QueryInterface and sets default proxy settings.
  697. //
  698. // Arguments:
  699. // pUnk [in] Interface pointer to perform QueryInterface on.
  700. // riid [in] See documentation of QueryInterface
  701. // ppv [out] ""
  702. //
  703. // Returns: S_OK on success. An error code otherwise.
  704. //
  705. // Author: mbend 1 Mar 2000
  706. //
  707. // Notes: Call type safe version HrQIAndSetProxyBlanket
  708. //
  709. HRESULT
  710. HrQIAndSetProxyBlanketBase(IUnknown * pUnk, REFIID riid, void ** ppv)
  711. {
  712. HRESULT hr = pUnk->QueryInterface(riid, ppv);
  713. if(SUCCEEDED(hr))
  714. {
  715. NcSetProxyBlanket(reinterpret_cast<IUnknown*>(*ppv));
  716. }
  717. TraceError("HrQIAndSetProxyBlanketBase", hr);
  718. return hr;
  719. }