Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

789 lines
20 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. {
  184. Assert (ppszDst);
  185. HRESULT hr;
  186. DWORD cb = cchSrc * sizeof(WCHAR);
  187. hr = E_OUTOFMEMORY;
  188. *ppszDst = (PWSTR)CoTaskMemAlloc (cb + sizeof(WCHAR));
  189. if (*ppszDst)
  190. {
  191. hr = S_OK;
  192. wcsncpy (*ppszDst, pszSrc, cchSrc);
  193. (*ppszDst)[cchSrc] = 0;
  194. }
  195. TraceError ("HrCoTaskMemAllocAndDupSz", hr);
  196. return hr;
  197. }
  198. HRESULT
  199. HrCoTaskMemAllocAndDupSz (
  200. IN PCWSTR pszSrc,
  201. OUT PWSTR* ppszDst)
  202. {
  203. return HrCoTaskMemAllocAndDupSzLen (
  204. pszSrc,
  205. CchOfSzSafe(pszSrc),
  206. ppszDst);
  207. }
  208. //+---------------------------------------------------------------------------
  209. //
  210. // Function: HrFromLastWin32Error
  211. //
  212. // Purpose: Converts the GetLastError() Win32 call into a proper HRESULT.
  213. //
  214. // Arguments:
  215. // (none)
  216. //
  217. // Returns: Converted HRESULT value.
  218. //
  219. // Author: danielwe 24 Mar 1997
  220. //
  221. // Notes: This is not inline as it actually generates quite a bit of
  222. // code.
  223. // If GetLastError returns an error that looks like a SetupApi
  224. // error, this function will convert the error to an HRESULT
  225. // with FACILITY_SETUP instead of FACILITY_WIN32
  226. //
  227. NOTHROW
  228. HRESULT
  229. HrFromLastWin32Error ()
  230. {
  231. DWORD dwError = GetLastError();
  232. HRESULT hr;
  233. // This test is testing SetupApi errors only (this is
  234. // temporary because the new HRESULT_FROM_SETUPAPI macro will
  235. // do the entire conversion)
  236. if (dwError & (APPLICATION_ERROR_MASK | ERROR_SEVERITY_ERROR))
  237. {
  238. hr = HRESULT_FROM_SETUPAPI(dwError);
  239. }
  240. else
  241. {
  242. hr = HRESULT_FROM_WIN32(dwError);
  243. }
  244. return hr;
  245. }
  246. //+---------------------------------------------------------------------------
  247. //
  248. // Function: HrGetProcAddress
  249. //
  250. // Purpose: Loads a libray and returns the address of a procedure within
  251. // the library
  252. //
  253. // Arguments:
  254. // hModule [in] The handle to the library module instance
  255. // pszaFunction [in] Function to retrieve
  256. // ppfn [out] Address of szFunction
  257. //
  258. // Returns: S_OK if successful, Win32 converted error if failure.
  259. //
  260. // Author: billbe 10 June 1997
  261. //
  262. // Notes:
  263. //
  264. HRESULT
  265. HrGetProcAddress (
  266. HMODULE hModule,
  267. PCSTR pszaFunction,
  268. FARPROC* ppfn)
  269. {
  270. Assert(hModule);
  271. Assert(pszaFunction);
  272. Assert(ppfn);
  273. HRESULT hr = S_OK;
  274. *ppfn = GetProcAddress(hModule, pszaFunction);
  275. if (!*ppfn)
  276. {
  277. hr = HrFromLastWin32Error();
  278. TraceTag(ttidError, "HrGetProcAddress failed: szFunction: %s",
  279. pszaFunction);
  280. }
  281. TraceError("HrGetProcAddress", hr);
  282. return hr;
  283. }
  284. //+---------------------------------------------------------------------------
  285. //
  286. // Function: HrLoadLibAndGetProcs
  287. //
  288. // Purpose: Load a dynamic link library and the addresses of one or
  289. // more procedures within that library.
  290. //
  291. // Arguments:
  292. // pszLibPath [in] Path to the DLL to load.
  293. // cFunctions [in] Number of procedures to load.
  294. // apszaFunctionNames [in] Array of function names. (Must be 'cFunctions'
  295. // of them.)
  296. // phmod [out] Returned handle to the loaded module.
  297. // apfn [out] Array of returned pointers to the procedures
  298. // loaded. (Must be 'cFunctions' of them.)
  299. //
  300. // Returns: S_OK if all procedures were loaded, S_FALSE if only
  301. // some of them were, or a Win32 error code. If only
  302. // one procedure is to be loaded and it is not, S_FALSE will
  303. // not be returned, rather, the reason for why the single
  304. // procedure could not be loaded will be returned. This allows
  305. // HrLoadLibAndGetProc to be implemented using this function.
  306. //
  307. // Author: shaunco 19 Jan 1998
  308. //
  309. // Notes: phmod should be freed by the caller using FreeLibrary if
  310. // the return value is S_OK.
  311. //
  312. HRESULT
  313. HrLoadLibAndGetProcs (
  314. PCWSTR pszLibPath,
  315. UINT cFunctions,
  316. const PCSTR* apszaFunctionNames,
  317. HMODULE* phmod,
  318. FARPROC* apfn)
  319. {
  320. Assert (pszLibPath);
  321. Assert (cFunctions);
  322. Assert (apszaFunctionNames);
  323. Assert (phmod);
  324. Assert (apfn);
  325. HRESULT hr = S_OK;
  326. // Load the module and initialize the output parameters.
  327. //
  328. HMODULE hmod = LoadLibrary (pszLibPath);
  329. *phmod = hmod;
  330. ZeroMemory (apfn, cFunctions * sizeof(FARPROC));
  331. if (hmod)
  332. {
  333. // Get the proc address of each function.
  334. //
  335. for (UINT i = 0; i < cFunctions; i++)
  336. {
  337. apfn[i] = GetProcAddress (hmod, apszaFunctionNames[i]);
  338. if (!apfn[i])
  339. {
  340. // Couldn't load all functions. We'll be returning S_FALSE
  341. // (if their are more than one function.)
  342. //
  343. hr = S_FALSE;
  344. TraceTag (ttidError, "HrLoadLibAndGetProcs: GetProcAddress "
  345. "for '%s' failed.",
  346. apszaFunctionNames[i]);
  347. }
  348. }
  349. // If we're only loading one function, and it failed,
  350. // return the failure.
  351. //
  352. if ((1 == cFunctions) && !apfn[0])
  353. {
  354. hr = HrFromLastWin32Error ();
  355. FreeLibrary (hmod);
  356. }
  357. }
  358. else
  359. {
  360. hr = HrFromLastWin32Error ();
  361. TraceTag (ttidError, "HrLoadLibAndGetProcs: LoadLibrary (%S) failed.",
  362. pszLibPath);
  363. }
  364. TraceError ("HrLoadLibAndGetProcs", hr);
  365. return hr;
  366. }
  367. //+---------------------------------------------------------------------------
  368. //
  369. // Function: HrGetProcAddressesVa
  370. //
  371. // Purpose: Get proc-address of each function-name passed
  372. //
  373. // Arguments:
  374. // hModule [in] handle of DLL
  375. // arglist [in] list of var-args. the expected format is
  376. // "func-name", FARPROC*, ..., NULL
  377. //
  378. // Returns: S_OK on success, otherwise an error code
  379. //
  380. // Author: kumarp 29-December-97
  381. //
  382. // Notes:
  383. //
  384. HRESULT
  385. HrGetProcAddressesVa (
  386. HMODULE hModule,
  387. va_list arglist)
  388. {
  389. PCSTR szFunctionName;
  390. FARPROC* ppfn;
  391. HRESULT hr = S_OK;
  392. typedef FARPROC* PFARPROC;
  393. while (NULL != (szFunctionName = va_arg(arglist, CHAR*)))
  394. {
  395. ppfn = va_arg(arglist, PFARPROC);
  396. *ppfn = GetProcAddress(hModule, szFunctionName);
  397. if (!*ppfn)
  398. {
  399. hr = HrFromLastWin32Error();
  400. TraceTag(ttidError, "HrGetProcAddressesVa failed: szFunction: %s",
  401. szFunctionName);
  402. break;
  403. }
  404. }
  405. TraceError("HrGetProcAddressesVa", hr);
  406. return hr;
  407. }
  408. //+---------------------------------------------------------------------------
  409. //
  410. // Function: HrGetProcAddressesV
  411. //
  412. // Purpose: Get proc-address of each function-name passed
  413. //
  414. // Arguments:
  415. // hModule [in] handle of DLL
  416. // ... [in] list of var-args. the expected format is
  417. // "func-name", FARPROC*, ..., NULL
  418. //
  419. // Returns: S_OK on success, otherwise an error code
  420. //
  421. // Author: kumarp 29-December-97
  422. //
  423. // Notes:
  424. //
  425. HRESULT
  426. HrGetProcAddressesV (
  427. HMODULE hModule,
  428. ...)
  429. {
  430. HRESULT hr=S_OK;
  431. va_list arglist;
  432. va_start(arglist, hModule);
  433. hr = HrGetProcAddressesVa(hModule, arglist);
  434. va_end(arglist);
  435. TraceError("HrGetProcAddressesV", hr);
  436. return hr;
  437. }
  438. //+---------------------------------------------------------------------------
  439. //
  440. // Function: HrLoadLibAndGetProcsV
  441. //
  442. // Purpose: Get proc-address of each function-name passed
  443. //
  444. // Arguments:
  445. // pszLibPath [in] DLL to load
  446. // phModule [out] pointer to handle of DLL loaded
  447. // ... [in] list of var-args. the expected format is
  448. // "func-name", FARPROC*, ..., NULL
  449. //
  450. // Returns: S_OK on success, otherwise an error code
  451. //
  452. // Author: kumarp 29-December-97
  453. //
  454. // Notes:
  455. //
  456. HRESULT
  457. HrLoadLibAndGetProcsV (
  458. PCWSTR pszLibPath,
  459. HMODULE* phModule,
  460. ...)
  461. {
  462. Assert(pszLibPath);
  463. Assert(phModule);
  464. HRESULT hr = S_OK;
  465. // Attempt to load the library
  466. *phModule = LoadLibrary(pszLibPath);
  467. if (*phModule)
  468. {
  469. va_list arglist;
  470. va_start(arglist, phModule);
  471. hr = HrGetProcAddressesVa(*phModule, arglist);
  472. va_end(arglist);
  473. if (FAILED(hr))
  474. {
  475. // Free the library
  476. FreeLibrary(*phModule);
  477. }
  478. }
  479. else
  480. {
  481. hr = HrFromLastWin32Error();
  482. TraceTag(ttidError, "HrLoadLibAndGetProcsV failed: szLibPath: %S",
  483. pszLibPath);
  484. }
  485. // if we failed then we should set *phModule to NULL since we might
  486. // have successfully loaded it and failed getting the proc
  487. if (FAILED(hr))
  488. {
  489. *phModule = NULL;
  490. }
  491. TraceError("HrLoadLibAndGetProcsV", hr);
  492. return hr;
  493. }
  494. //+---------------------------------------------------------------------------
  495. //
  496. // Function: HrCreateEventWithWorldAccess
  497. //
  498. // Purpose: Creates a event with permissions to allow access to
  499. // everyone.
  500. //
  501. // Arguments:
  502. // pszName [in] Name for the event.
  503. // fManualReset [in] See Win32 docs.
  504. // fInitialState [in] See Win32 docs.
  505. // pfAlreadyExists [out] TRUE if the event already existed.
  506. // FALSE otherwise.
  507. // phEvent [out] The created event.
  508. //
  509. // Returns: S_OK on success. An error code otherwise.
  510. //
  511. // Author: BillBe 16 Nov 1998
  512. //
  513. // Notes:
  514. //
  515. HRESULT
  516. HrCreateEventWithWorldAccess(PCWSTR pszName, BOOL fManualReset,
  517. BOOL fInitialState, BOOL* pfAlreadyExists, HANDLE* phEvent)
  518. {
  519. Assert(pszName);
  520. Assert(phEvent);
  521. if (pfAlreadyExists)
  522. {
  523. *pfAlreadyExists = FALSE;
  524. }
  525. *phEvent = NULL;
  526. // Create the correct descriptor.
  527. PSECURITY_DESCRIPTOR pSd;
  528. HRESULT hr = HrAllocateSecurityDescriptorAllowAccessToWorld(&pSd);
  529. if (SUCCEEDED(hr))
  530. {
  531. SECURITY_ATTRIBUTES sa = {0};
  532. sa.nLength = sizeof(sa);
  533. sa.lpSecurityDescriptor = pSd;
  534. sa.bInheritHandle = FALSE;
  535. // Create Event
  536. //
  537. *phEvent = CreateEvent(&sa, fManualReset, fInitialState, pszName);
  538. hr = HrFromLastWin32Error();
  539. if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)
  540. {
  541. if (pfAlreadyExists)
  542. {
  543. *pfAlreadyExists = TRUE;
  544. }
  545. hr = S_OK;
  546. }
  547. MemFree(pSd);
  548. }
  549. TraceError("HrCreateEventWithWorldAccess", hr);
  550. return hr;
  551. }
  552. //+---------------------------------------------------------------------------
  553. //
  554. // Function: HrCreateMutexWithWorldAccess
  555. //
  556. // Purpose: Creates a mutex with permissions to allow access to
  557. // everyone.
  558. //
  559. // Arguments:
  560. // pszName [in] Name for the mutex.
  561. // fInitialOwner [in] See Win32 docs.
  562. // pfAlreadyExists [out] TRUE if the mutex already existed,
  563. // FALSE otherwise.
  564. // phMutex [out] The created mutex.
  565. //
  566. // Returns: S_OK on success. An error code otherwise.
  567. //
  568. // Author: BillBe 16 Nov 1998
  569. //
  570. // Notes:
  571. //
  572. HRESULT
  573. HrCreateMutexWithWorldAccess (
  574. PCWSTR pszName,
  575. BOOL fInitialOwner,
  576. BOOL* pfAlreadyExists,
  577. HANDLE* phMutex)
  578. {
  579. Assert(pszName);
  580. Assert(phMutex);
  581. if (pfAlreadyExists)
  582. {
  583. *pfAlreadyExists = FALSE;
  584. }
  585. *phMutex = NULL;
  586. // Create the correct descriptor.
  587. PSECURITY_DESCRIPTOR pSd;
  588. HRESULT hr = HrAllocateSecurityDescriptorAllowAccessToWorld(&pSd);
  589. if (S_OK == hr)
  590. {
  591. SECURITY_ATTRIBUTES sa = {0};
  592. sa.nLength = sizeof(sa);
  593. sa.lpSecurityDescriptor = pSd;
  594. sa.bInheritHandle = FALSE;
  595. // Create Mutex
  596. //
  597. *phMutex = CreateMutex(&sa, fInitialOwner, pszName);
  598. hr = HrFromLastWin32Error();
  599. if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)
  600. {
  601. if (pfAlreadyExists)
  602. {
  603. *pfAlreadyExists = TRUE;
  604. }
  605. hr = S_OK;
  606. }
  607. MemFree(pSd);
  608. }
  609. TraceError("HrCreateMutexWithWorldAccess", hr);
  610. return hr;
  611. }
  612. //+---------------------------------------------------------------------------
  613. // The standard parameterization of CoSetProxyBlanket. Call this instead
  614. // of CoSetProxyBlanket so you get the same security and authentication
  615. // settings as everyone else. This version saves code space at the call-site
  616. // because it pushes only one parameter instead of eight.
  617. // This does not return an error because it does not invalidate the use of
  618. // pUnk after it's called.
  619. //
  620. VOID
  621. NcSetProxyBlanket (
  622. IN IUnknown* pUnk)
  623. {
  624. HRESULT hr;
  625. hr = CoSetProxyBlanket (
  626. pUnk,
  627. RPC_C_AUTHN_WINNT, // use NT default security
  628. RPC_C_AUTHZ_NONE, // use NT default authentication
  629. NULL, // must be null if default
  630. RPC_C_AUTHN_LEVEL_CALL, // call
  631. RPC_C_IMP_LEVEL_IMPERSONATE,
  632. NULL, // use process token
  633. EOAC_NONE);
  634. if(SUCCEEDED(hr))
  635. {
  636. IUnknown * pUnkSet = NULL;
  637. hr = pUnk->QueryInterface(&pUnkSet);
  638. if(SUCCEEDED(hr))
  639. {
  640. hr = CoSetProxyBlanket (
  641. pUnkSet,
  642. RPC_C_AUTHN_WINNT, // use NT default security
  643. RPC_C_AUTHZ_NONE, // use NT default authentication
  644. NULL, // must be null if default
  645. RPC_C_AUTHN_LEVEL_CALL, // call
  646. RPC_C_IMP_LEVEL_IMPERSONATE,
  647. NULL, // use process token
  648. EOAC_NONE);
  649. ReleaseObj(pUnkSet);
  650. }
  651. }
  652. TraceHr(ttidError, FAL, hr, (E_NOINTERFACE == hr), "NcSetProxyBlanket");
  653. }
  654. //+---------------------------------------------------------------------------
  655. //
  656. // Function: HrCreateInstanceBase
  657. //
  658. // Purpose: Creates a COM object and sets default proxy settings.
  659. //
  660. // Arguments:
  661. // rclsid [in] See documentation for CoCreateInstance.
  662. // dwClsContext [in] ""
  663. // riid [in] ""
  664. // ppv [out] ""
  665. //
  666. // Returns: S_OK on success. An error code otherwise.
  667. //
  668. // Author: mbend 1 Mar 2000
  669. //
  670. // Notes: Call type safe version HrCreateInstance
  671. //
  672. HRESULT
  673. HrCreateInstanceBase (
  674. REFCLSID rclsid,
  675. DWORD dwClsContext,
  676. REFIID riid,
  677. LPVOID * ppv)
  678. {
  679. HRESULT hr = S_OK;
  680. hr = ::CoCreateInstance(rclsid, NULL, dwClsContext, riid, ppv);
  681. if(SUCCEEDED(hr) && (dwClsContext & CLSCTX_LOCAL_SERVER))
  682. {
  683. NcSetProxyBlanket(reinterpret_cast<IUnknown*>(*ppv));
  684. }
  685. TraceError("HrCreateInstanceBase", hr);
  686. return hr;
  687. }
  688. //+---------------------------------------------------------------------------
  689. //
  690. // Function: HrQIAndSetProxyBlanketBase
  691. //
  692. // Purpose: Performs QueryInterface and sets default proxy settings.
  693. //
  694. // Arguments:
  695. // pUnk [in] Interface pointer to perform QueryInterface on.
  696. // riid [in] See documentation of QueryInterface
  697. // ppv [out] ""
  698. //
  699. // Returns: S_OK on success. An error code otherwise.
  700. //
  701. // Author: mbend 1 Mar 2000
  702. //
  703. // Notes: Call type safe version HrQIAndSetProxyBlanket
  704. //
  705. HRESULT
  706. HrQIAndSetProxyBlanketBase(IUnknown * pUnk, REFIID riid, void ** ppv)
  707. {
  708. HRESULT hr = pUnk->QueryInterface(riid, ppv);
  709. if(SUCCEEDED(hr))
  710. {
  711. NcSetProxyBlanket(reinterpret_cast<IUnknown*>(*ppv));
  712. }
  713. TraceError("HrQIAndSetProxyBlanketBase", hr);
  714. return hr;
  715. }