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.

1919 lines
60 KiB

  1. /*
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. CMDhcp.cpp
  5. Abstract:
  6. Implementation of CMdhcp.
  7. Author:
  8. */
  9. #include "stdafx.h"
  10. #include <winsock2.h>
  11. #include "mdhcp.h"
  12. #include "CMDhcp.h"
  13. #include "lease.h"
  14. #include "local.h"
  15. // template for collections
  16. #include "collect.h"
  17. // From rendezvous control code:
  18. // sets the first bit to indicate error
  19. // sets the win32 facility code
  20. // this is used instead of the HRESULT_FROM_WIN32 macro
  21. // because that clears the customer flag
  22. inline long
  23. HRESULT_FROM_ERROR_CODE(IN long ErrorCode)
  24. {
  25. return ( 0x80070000 | (0xa000ffff & ErrorCode) );
  26. }
  27. /////////////////////////////////////////////////////////////////////////////
  28. // Helper functions.
  29. /////////////////////////////////////////////////////////////////////////////
  30. HRESULT CMDhcp::CreateWrappers(
  31. DWORD dwScopeCount, // the number of scopes we were given
  32. MCAST_SCOPE_ENTRY * pScopeList, // array of scope structs
  33. IMcastScope *** pppWrappers, // here we will put an array of if ptrs
  34. BOOL fLocal // true = scopes are locally generated
  35. )
  36. {
  37. LOG((MSP_TRACE, "CMDhcp::CreateWrappers enter"));
  38. HRESULT hr;
  39. // Allocate the array of interface pointers.
  40. typedef IMcastScope * ScopeIfPtr;
  41. *pppWrappers = new ScopeIfPtr[dwScopeCount];
  42. if ( (*pppWrappers) == NULL )
  43. {
  44. LOG((MSP_ERROR,
  45. "can't create allocate array of interface pointers"));
  46. return E_OUTOFMEMORY;
  47. }
  48. // For each scope in the list of scopes returned by the C API
  49. for (DWORD i = 0; i < dwScopeCount; i++)
  50. {
  51. // create the com object.
  52. CComObject<CMDhcpScope> * pMDhcpScope;
  53. hr = CComObject<CMDhcpScope>::CreateInstance(&pMDhcpScope);
  54. if ( (FAILED(hr)) || (NULL == pMDhcpScope) )
  55. {
  56. LOG((MSP_ERROR, "can't create MDhcpScope Object (%d/%d): %08x",
  57. i, dwScopeCount, hr));
  58. // get rid of all previously created COM objects
  59. for (DWORD j = 0; j < i; j++) (*pppWrappers)[j]->Release();
  60. delete (*pppWrappers);
  61. return hr;
  62. }
  63. // Get the IMcastScope interface.
  64. hr = pMDhcpScope->_InternalQueryInterface(
  65. IID_IMcastScope,
  66. (void **) (& (*pppWrappers)[i])
  67. );
  68. if ( FAILED(hr) )
  69. {
  70. LOG((MSP_ERROR, "CreateWrappers:QueryInterface (%d/%d) failed: %08x",
  71. i, dwScopeCount, hr));
  72. // get rid of all previously created COM objects
  73. for (DWORD j = 0; j < i; j++) (*pppWrappers)[j]->Release();
  74. delete (*pppWrappers);
  75. delete pMDhcpScope; // don't know if it addrefed or not
  76. return hr;
  77. }
  78. // Set the object's info based on the struct. From now on the
  79. // object will be read-only.
  80. hr = pMDhcpScope->Initialize(pScopeList[i], fLocal);
  81. if ( FAILED(hr) )
  82. {
  83. LOG((MSP_ERROR, "CreateWrappers:Initialize (%d/%d) failed: %08x",
  84. i, dwScopeCount, hr));
  85. // get rid of all previously created COM objects
  86. for (DWORD j = 0; j < i; j++) (*pppWrappers)[j]->Release();
  87. delete (*pppWrappers);
  88. pMDhcpScope->Release(); // we know it addrefed in the QI
  89. return hr;
  90. }
  91. }
  92. LOG((MSP_TRACE, "CMDhcp::CreateWrappers exit"));
  93. return S_OK;
  94. }
  95. /////////////////////////////////////////////////////////////////////////////
  96. // Get a list of scopes from the C API.
  97. HRESULT CMDhcp::GetScopeList(
  98. DWORD * pdwScopeCount,
  99. MCAST_SCOPE_ENTRY ** ppScopeList,
  100. BOOL * pfLocal
  101. )
  102. {
  103. LOG((MSP_TRACE, "CMDhcp::GetScopeList enter"));
  104. _ASSERTE( ! IsBadWritePtr(pdwScopeCount, sizeof(DWORD) ) );
  105. _ASSERTE( ! IsBadWritePtr(ppScopeList, sizeof(MCAST_SCOPE_ENTRY *) ) );
  106. HRESULT hr;
  107. DWORD dwScopeLen = 0; // size in bytes of returned scopes structure
  108. DWORD dwCode; // return code
  109. *pfLocal = FALSE; // try mdhcp first
  110. dwCode = LocalEnumerateScopes(NULL, // only want to know how many we have
  111. &dwScopeLen, // # of bytes should be zero
  112. pdwScopeCount, // # of scopes placed here
  113. pfLocal);
  114. // This must succeed for us to continue.
  115. if (dwCode != ERROR_SUCCESS)
  116. {
  117. hr = HRESULT_FROM_ERROR_CODE(dwCode);
  118. LOG((MSP_ERROR, "GetScopeList: First C API call failed "
  119. "(code: %d hresult: %08x)", dwCode, hr));
  120. return hr;
  121. }
  122. do
  123. {
  124. // If there are no scopes to choose from, let's not enumerate them.
  125. // We also need at least the length fields from the first
  126. // UNICODE_STRING.
  127. if ( (dwScopeLen < sizeof(MCAST_SCOPE_ENTRY)) || (*pdwScopeCount < 1) )
  128. {
  129. LOG((MSP_ERROR, "GetScopeList: don't have enough scopes (%d;%d)",
  130. dwScopeLen, *pdwScopeCount));
  131. return E_FAIL;
  132. }
  133. // Now that we know how many there are, allocate an array to hold the
  134. // scope structs returned by the C method.
  135. // The API acts very strangely here. We have to give it dwScopeLen
  136. // bytes as one big chunk. The first dwScopeCount * sizeof(MCAST_SCOPE_ENTRY)
  137. // bytes contain dwScopeCount MCAST_SCOPE_ENTRY structures. Each of these
  138. // structures has a pointer to a wide string. The first of these points
  139. // to the first byte after all the MCAST_SCOPE_ENTRY structures! In this way
  140. // they avoid doing so many mallocs. We therefore have to
  141. // copy each string in the COM wrapper for each scope, and then delete
  142. // this buffer (ppScopeList) all at once after all the wrapping is complete.
  143. *ppScopeList = (MCAST_SCOPE_ENTRY *) new CHAR[dwScopeLen];
  144. if (*ppScopeList == NULL)
  145. {
  146. LOG((MSP_ERROR, "GetScopeList: not enough memory to allocate scope"
  147. " list (size = %d)", dwScopeLen));
  148. return E_OUTOFMEMORY;
  149. }
  150. // *pdwScopeCount still specifies the number of scopes we can get.
  151. // Now ask for all the scopes.
  152. dwCode = LocalEnumerateScopes(*ppScopeList,
  153. &dwScopeLen,
  154. pdwScopeCount,
  155. pfLocal);
  156. // If things changed in this bried time, just try again.
  157. if (dwCode == ERROR_MORE_DATA)
  158. {
  159. LOG((MSP_INFO, "GetScopeList: got more scopes than we were told "
  160. "existed (we though there were %d) -- retrying",
  161. *pdwScopeCount));
  162. delete (*ppScopeList);
  163. }
  164. }
  165. while (dwCode == ERROR_MORE_DATA);
  166. if (dwCode != ERROR_SUCCESS)
  167. {
  168. hr = HRESULT_FROM_ERROR_CODE(dwCode);
  169. LOG((MSP_ERROR, "GetScopeList: Second C API call failed "
  170. "(code: %d hresult: %08x)", dwCode, hr));
  171. delete (*ppScopeList);
  172. return hr;
  173. }
  174. LOG((MSP_TRACE, "CMDhcp::GetScopeList exit"));
  175. return S_OK;
  176. }
  177. /////////////////////////////////////////////////////////////////////////////
  178. // This is a private helper method that creates a CMDhcpLeaseInfo object and
  179. // uses it to wrap a lease info structure and request ID into an
  180. // IMcastLeaseInfo interface.
  181. HRESULT CMDhcp::WrapMDhcpLeaseInfo(
  182. BOOL fGotTtl,
  183. long lTtl,
  184. BOOL fLocal,
  185. MCAST_LEASE_INFO * pLeaseInfo,
  186. MCAST_CLIENT_UID * pRequestID,
  187. IMcastLeaseInfo ** ppInterface
  188. )
  189. {
  190. LOG((MSP_TRACE, "CMDhcp::WrapMDhcpLeaseInfo enter"));
  191. // We don't check pLeaseInfo or pRequestID -- they'll be comprehensively
  192. // checked in the Wrap call below.
  193. if ( IsBadWritePtr(ppInterface, sizeof(IMcastLeaseInfo *) ) )
  194. {
  195. LOG((MSP_ERROR, "WrapMDhcpLeaseInfo: invalid pointer: %x",
  196. ppInterface));
  197. return E_POINTER;
  198. }
  199. HRESULT hr;
  200. // create the com object.
  201. CComObject<CMDhcpLeaseInfo> * pMDhcpLeaseInfo;
  202. hr = CComObject<CMDhcpLeaseInfo>::CreateInstance(&pMDhcpLeaseInfo);
  203. if ( (FAILED(hr)) || (pMDhcpLeaseInfo == NULL) )
  204. {
  205. LOG((MSP_ERROR, "can't create MDhcpLeaseInfo Object."));
  206. return hr;
  207. }
  208. // Get the IMcastLeaseInfo interface.
  209. hr = pMDhcpLeaseInfo->_InternalQueryInterface(
  210. IID_IMcastLeaseInfo,
  211. (void **)ppInterface
  212. );
  213. if ( FAILED(hr) )
  214. {
  215. LOG((MSP_ERROR, "WrapMDhcpLeaseInfo:QueryInterface failed: %x", hr));
  216. delete pMDhcpLeaseInfo;
  217. return hr;
  218. }
  219. // Wrap the object in the interface.
  220. hr = pMDhcpLeaseInfo->Wrap(pLeaseInfo, pRequestID, fGotTtl, lTtl);
  221. if ( FAILED(hr) )
  222. {
  223. LOG((MSP_ERROR, "WrapMDhcpLeaseInfo:Wrap failed: %x", hr));
  224. (*ppInterface)->Release();
  225. return hr;
  226. }
  227. hr = pMDhcpLeaseInfo->SetLocal(fLocal);
  228. if ( FAILED(hr) )
  229. {
  230. LOG((MSP_ERROR, "WrapMDhcpLeaseInfo: SetLocal failed: %x", hr));
  231. (*ppInterface)->Release();
  232. return hr;
  233. }
  234. LOG((MSP_TRACE, "CMDhcp::WrapMDhcpLeaseInfo exit"));
  235. return S_OK;
  236. }
  237. /////////////////////////////////////////////////////////////////////////////
  238. // This is a private helper method that munges the arguments into structs
  239. // at the beginning of a Request call.
  240. HRESULT CMDhcp::PrepareArgumentsRequest(
  241. IN IMcastScope * pScope,
  242. IN DATE LeaseStartTime,
  243. IN DATE LeaseStopTime,
  244. IN long lNumAddresses,
  245. OUT MCAST_CLIENT_UID * pRequestIDStruct,
  246. OUT MCAST_SCOPE_CTX * pScopeCtxStruct,
  247. OUT MCAST_LEASE_INFO ** ppLeaseStruct,
  248. OUT BOOL * pfLocal,
  249. OUT long * plTtl
  250. )
  251. {
  252. LOG((MSP_TRACE, "CMDhcp::PrepareArgumentsRequest enter"));
  253. _ASSERTE ( ! IsBadReadPtr(pScope, sizeof(IMcastScope) ) );
  254. _ASSERTE ( ! IsBadWritePtr(pRequestIDStruct, sizeof(MCAST_CLIENT_UID) ) );
  255. _ASSERTE ( ! IsBadWritePtr(pScopeCtxStruct, sizeof(MCAST_SCOPE_CTX) ) );
  256. _ASSERTE ( ! IsBadWritePtr(ppLeaseStruct, sizeof(MCAST_LEASE_INFO *) ) );
  257. _ASSERTE ( ! IsBadWritePtr(pfLocal, sizeof(BOOL) ) );
  258. _ASSERTE ( ! IsBadWritePtr(plTtl, sizeof(long) ) );
  259. HRESULT hr;
  260. //
  261. // The start time must be less than the stop time.
  262. //
  263. if ( LeaseStartTime > LeaseStopTime )
  264. {
  265. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest - "
  266. "start time is greater than stop time - exit E_INVALIDARG"));
  267. return E_INVALIDARG;
  268. }
  269. //
  270. // lNumAddresses must be stuffed into a WORD for the C API -- check to see if
  271. // it's in range.
  272. //
  273. if ( ( lNumAddresses < 0 ) || ( lNumAddresses > USHRT_MAX ) )
  274. {
  275. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest - "
  276. "invalid number of addresses - exit E_INVALIDARG"));
  277. return E_INVALIDARG;
  278. }
  279. //
  280. // dynamic_cast to get an object pointer from the passed-in interface
  281. // pointer. This will cause an exception if the user tries to use their
  282. // own implementation of IMcastScope, which is quite unlikely.
  283. //
  284. CMDhcpScope * pCScope = dynamic_cast<CMDhcpScope *>(pScope);
  285. if (pCScope == NULL)
  286. {
  287. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest - "
  288. "Unsupported CMDhcpScope object"));
  289. return E_POINTER;
  290. }
  291. //
  292. // Find out if this scope uses local alloc.
  293. //
  294. hr = pCScope->GetLocal(pfLocal);
  295. if (FAILED(hr))
  296. {
  297. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest: "
  298. "GetLocal failed %08x", hr));
  299. return hr;
  300. }
  301. //
  302. // Find out the ttl to stuff in leases from this scope.
  303. //
  304. hr = pCScope->get_TTL( plTtl );
  305. if ( FAILED(hr) )
  306. {
  307. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest: "
  308. "get_TTL failed %08x", hr));
  309. return hr;
  310. }
  311. //
  312. // Get the normal scope info.
  313. // ScopeID is stored in network byte order but the get_ method
  314. // returns it in host byte order for the benefit of apps.
  315. //
  316. long lScopeID;
  317. hr = pScope->get_ScopeID( &lScopeID );
  318. if ( FAILED(hr) )
  319. {
  320. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest - "
  321. "can't get scope ID from scope object - exit 0x%08x", hr));
  322. return hr;
  323. }
  324. pScopeCtxStruct->ScopeID.IpAddrV4 = htonl(lScopeID);
  325. hr = pScope->get_ServerID(
  326. (long *) &(pScopeCtxStruct->ServerID.IpAddrV4) );
  327. if ( FAILED(hr) )
  328. {
  329. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest - "
  330. "can't get server ID from scope object - exit 0x%08x", hr));
  331. return hr;
  332. }
  333. hr = pScope->get_InterfaceID(
  334. (long *) &(pScopeCtxStruct->Interface.IpAddrV4) );
  335. if ( FAILED(hr) )
  336. {
  337. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest - "
  338. "can't get interface ID from scope object - exit 0x%08x", hr));
  339. return hr;
  340. }
  341. //
  342. // Allocate space for the client UID.
  343. //
  344. pRequestIDStruct->ClientUIDLength = MCAST_CLIENT_ID_LEN;
  345. pRequestIDStruct->ClientUID = new BYTE[ MCAST_CLIENT_ID_LEN ];
  346. if ( pRequestIDStruct->ClientUID == NULL )
  347. {
  348. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest: out of memory in "
  349. "buffer allocation"));
  350. return E_OUTOFMEMORY;
  351. }
  352. //
  353. // Generate a random client UID.
  354. //
  355. DWORD dwResult = McastGenUID( pRequestIDStruct );
  356. if ( dwResult != ERROR_SUCCESS )
  357. {
  358. hr = HRESULT_FROM_ERROR_CODE( dwResult );
  359. LOG((MSP_TRACE, "CMDhcp::PrepareArgumentsRequest: "
  360. "McastGenUID failed (dw = %d; hr = 0x%08x)", dwResult, hr));
  361. return hr;
  362. }
  363. LOG((MSP_TRACE, "CMDhcp::PrepareArgumentsRequest: before MCAST_LEASE_INFO "
  364. "alloc; we are asking for %d addresses", lNumAddresses));
  365. //
  366. // Allocate the lease info structure.
  367. // The caller will delete it after the API call.
  368. // This is a REQUEST, so we do not specify any particular addresses
  369. // in the array -- we do not need space for them.
  370. //
  371. //
  372. (*ppLeaseStruct) = new MCAST_LEASE_INFO;
  373. if ( (*ppLeaseStruct) == NULL )
  374. {
  375. LOG((MSP_ERROR, "CMDhcp::PrepareArgumentsRequest: out of memory in "
  376. "MCAST_LEASE_INFO allocation"));
  377. delete (pRequestIDStruct->ClientUID);
  378. return E_OUTOFMEMORY;
  379. }
  380. //
  381. // Fill in the times.
  382. //
  383. hr = DateToLeaseTime(LeaseStartTime,
  384. &((*ppLeaseStruct)->LeaseStartTime));
  385. if ( FAILED(hr) )
  386. {
  387. delete (pRequestIDStruct->ClientUID);
  388. delete (*ppLeaseStruct);
  389. return hr;
  390. }
  391. hr = DateToLeaseTime(LeaseStopTime,
  392. &((*ppLeaseStruct)->LeaseEndTime));
  393. if ( FAILED(hr) )
  394. {
  395. delete (pRequestIDStruct->ClientUID);
  396. delete (*ppLeaseStruct);
  397. return hr;
  398. }
  399. //
  400. // Fill in the address info fields.
  401. //
  402. (*ppLeaseStruct)->ServerAddress.IpAddrV4 = 0;
  403. (*ppLeaseStruct)->AddrCount = (WORD) lNumAddresses; // checked above
  404. //
  405. // This is a REQUEST, so we do not specify any particular addresses
  406. // in the array -- we make the array NULL.
  407. //
  408. (*ppLeaseStruct)->pAddrBuf = NULL;
  409. LOG((MSP_TRACE, "CMDhcp::PrepareArgumentsRequest exit"));
  410. return S_OK;
  411. }
  412. /////////////////////////////////////////////////////////////////////////////
  413. // This is a private helper method that munges the arguments into structs
  414. // at the beginning of a Renew or Release call.
  415. HRESULT CMDhcp::PrepareArgumentsNonRequest(
  416. IN IMcastLeaseInfo * pLease,
  417. OUT MCAST_CLIENT_UID * pRequestIDStruct,
  418. OUT MCAST_LEASE_INFO ** ppLeaseStruct,
  419. OUT BOOL * pfLocal,
  420. OUT BOOL * pfGotTtl,
  421. OUT long * plTtl
  422. )
  423. {
  424. LOG((MSP_TRACE, "CMDhcp::PrepareArgumentsNonRequest enter"));
  425. if ( IsBadReadPtr(pLease, sizeof(IMcastLeaseInfo) ) )
  426. {
  427. LOG((MSP_ERROR, "PrepareArgumentsNonRequest: bad pLease pointer argument"));
  428. return E_POINTER;
  429. }
  430. _ASSERTE ( ! IsBadWritePtr(pRequestIDStruct, sizeof(MCAST_CLIENT_UID) ) );
  431. _ASSERTE ( ! IsBadWritePtr(ppLeaseStruct, sizeof(MCAST_LEASE_INFO *) ) );
  432. _ASSERTE ( ! IsBadWritePtr(pfLocal, sizeof(BOOL) ) );
  433. _ASSERTE ( ! IsBadWritePtr(pfGotTtl, sizeof(BOOL) ) );
  434. _ASSERTE ( ! IsBadWritePtr(plTtl, sizeof(long) ) );
  435. HRESULT hr;
  436. // We approach things in a completely different way here, compared
  437. // to the other PrepareArguments method -- we use
  438. // dynamic_cast to get an object pointer from the passed-in interface
  439. // pointer. This will cause an exception if the user tries to use their
  440. // own implementation of IMcastRequestID, which is quite unlikely.
  441. CMDhcpLeaseInfo * pCLease = dynamic_cast<CMDhcpLeaseInfo *>(pLease);
  442. if (pCLease == NULL)
  443. {
  444. LOG((MSP_ERROR, "PrepareArgumentsNonRequest: Unsupported CMDhcpLeaseInfo object"));
  445. return E_POINTER;
  446. }
  447. //
  448. // Find out if this lease was obtained using local alloc.
  449. //
  450. hr = pCLease->GetLocal(pfLocal);
  451. if (FAILED(hr))
  452. {
  453. LOG((MSP_ERROR, "PrepareArgumentsNonRequest: "
  454. "GetLocal failed %08x", hr));
  455. return hr;
  456. }
  457. //
  458. // If the lease had a TTL set, then retrieve it for use in a
  459. // resulting response. Else just say we don't have a ttl.
  460. //
  461. hr = pCLease->get_TTL( plTtl );
  462. *pfGotTtl = SUCCEEDED(hr);
  463. //
  464. // Get our request ID from the lease info object.
  465. //
  466. pRequestIDStruct->ClientUIDLength = MCAST_CLIENT_ID_LEN;
  467. pRequestIDStruct->ClientUID = new BYTE[ MCAST_CLIENT_ID_LEN ];
  468. if (pRequestIDStruct->ClientUID == NULL)
  469. {
  470. LOG((MSP_ERROR, "PrepareArgumentsNonRequest: out of memory in "
  471. "buffer allocation"));
  472. return E_OUTOFMEMORY;
  473. }
  474. hr = pCLease->GetRequestIDBuffer(pRequestIDStruct->ClientUIDLength,
  475. pRequestIDStruct->ClientUID);
  476. if ( FAILED(hr) )
  477. {
  478. LOG((MSP_ERROR, "PrepareArgumentsNonRequest: RequestID "
  479. "GetBuffer failed %08x", hr));
  480. delete (pRequestIDStruct->ClientUID);
  481. return hr;
  482. }
  483. //
  484. // Get the rest of the stuff, which belongs in the straight lease info
  485. // structure, from the lease info object.
  486. //
  487. // this does a new for us
  488. hr = pCLease->GetStruct(ppLeaseStruct);
  489. if ( FAILED(hr) )
  490. {
  491. LOG((MSP_ERROR, "PrepareArgumentsNonRequest - "
  492. "failed to grab pLeaseStruct - 0x%08x", hr));
  493. delete (pRequestIDStruct->ClientUID);
  494. return hr;
  495. }
  496. LOG((MSP_TRACE, "CMDhcp::PrepareArgumentsNonRequest exit"));
  497. return S_OK;
  498. }
  499. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  500. //
  501. // VerifyAndGetArrayBounds
  502. //
  503. // Helper function for variant/safearrays
  504. //
  505. // Array
  506. // IN Variant that contains a safearray
  507. //
  508. // ppsa
  509. // OUT safearray returned here
  510. //
  511. // pllBound
  512. // OUT array lower bound returned here
  513. //
  514. // pluBound
  515. // OUT array upper bound returned here
  516. //
  517. // RETURNS
  518. //
  519. // verifies that Array contains an array, and returns the array, upper
  520. // and lower bounds.
  521. //
  522. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  523. static HRESULT
  524. VerifyAndGetArrayBounds(
  525. VARIANT Array,
  526. SAFEARRAY ** ppsa,
  527. long * pllBound,
  528. long * pluBound
  529. )
  530. {
  531. LOG((MSP_TRACE, "VerifyAndGetArrayBounds: enter"));
  532. UINT uDims;
  533. HRESULT hr = S_OK;
  534. //
  535. // see if the variant & safearray are valid
  536. //
  537. try
  538. {
  539. if (!(V_ISARRAY(&Array)))
  540. {
  541. if ( Array.vt == VT_NULL )
  542. {
  543. //
  544. // null is usually valid
  545. //
  546. *ppsa = NULL;
  547. LOG((MSP_INFO, "Returning NULL array"));
  548. return S_FALSE;
  549. }
  550. LOG((MSP_ERROR, "Array - not an array"));
  551. return E_INVALIDARG;
  552. }
  553. if ( Array.parray == NULL )
  554. {
  555. //
  556. // null is usually valide
  557. //
  558. *ppsa = NULL;
  559. LOG((MSP_INFO, "Returning NULL array"));
  560. return S_FALSE;
  561. }
  562. *ppsa = V_ARRAY(&Array);
  563. uDims = SafeArrayGetDim( *ppsa );
  564. }
  565. catch(...)
  566. {
  567. hr = E_POINTER;
  568. }
  569. if (!SUCCEEDED(hr))
  570. {
  571. LOG((MSP_ERROR, "Array - invalid array"));
  572. return hr;
  573. }
  574. //
  575. // verify array
  576. //
  577. if ( uDims != 1 )
  578. {
  579. if ( uDims == 0 )
  580. {
  581. LOG((MSP_ERROR, "Array - has 0 dim"));
  582. return E_INVALIDARG;
  583. }
  584. else
  585. {
  586. LOG((MSP_WARN, "Array - has > 1 dim - will only use 1"));
  587. }
  588. }
  589. //
  590. // Get array bounds
  591. //
  592. SafeArrayGetUBound(
  593. *ppsa,
  594. 1,
  595. pluBound
  596. );
  597. SafeArrayGetLBound(
  598. *ppsa,
  599. 1,
  600. pllBound
  601. );
  602. LOG((MSP_TRACE, "VerifyAndGetArrayBounds: exit"));
  603. return S_OK;
  604. }
  605. //////////////////////////////////////////////////////////////////////////////
  606. // CMDhcp::FinalContruct
  607. //
  608. // Parameters
  609. // none
  610. //
  611. // Return Values
  612. // S_OK Success
  613. // E_OUTOFMEMORY Not enough memory to create free thread marshaler
  614. // E_FAIL We are running the wrong version of dhcpcsvc.dll
  615. //
  616. // Description
  617. // This is called on construction. It creates the free threaded marshaler
  618. // and checks if the C API's DLL is the same version that we were compiled
  619. // with.
  620. //////////////////////////////////////////////////////////////////////////////
  621. HRESULT CMDhcp::FinalConstruct(void)
  622. {
  623. LOG((MSP_TRACE, "CMDhcp::FinalConstruct - enter"));
  624. HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
  625. & m_pFTM );
  626. if ( FAILED(hr) )
  627. {
  628. LOG((MSP_ERROR, "CMDhcp::FinalConstruct - "
  629. "failed to create FTM - exit 0x%08x", hr));
  630. //
  631. // Now, FinalRelease will get called, and then CoCreate will return
  632. // failure.
  633. //
  634. return hr;
  635. }
  636. // Munil uses this as an IN/OUT parameter.
  637. DWORD dwVersion = MCAST_API_CURRENT_VERSION; // defined in mdhccapi.h
  638. DWORD dwCode;
  639. dwCode = McastApiStartup(&dwVersion);
  640. // dwVersion now contains the actual version of the C API, but we don't
  641. // really care what it is.
  642. if (dwCode == ERROR_SUCCESS)
  643. {
  644. m_fApiIsInitialized = TRUE;
  645. LOG((MSP_TRACE, "CMDhcp::FinalConstruct - C API version "
  646. "is >= our version - exit S_OK"));
  647. return S_OK;
  648. }
  649. else
  650. {
  651. LOG((MSP_ERROR, "CMDhcp::FinalConstruct - C API version "
  652. "is < our version - exit E_FAIL"));
  653. //
  654. // Now, FinalRelease will get called, and then CoCreate will return
  655. // failure.
  656. //
  657. return E_FAIL;
  658. }
  659. }
  660. //////////////////////////////////////////////////////////////////////////////
  661. //
  662. // CMDhcp::FinalRelease
  663. //
  664. // Parameters
  665. // none
  666. //
  667. // Return Values
  668. // none
  669. //
  670. // Description
  671. // This is called on destruction. It releases the free threaded marshaler
  672. // and cleans up the C API instance. Note that it is also called if
  673. // FinalConstruct failed.
  674. //
  675. //////////////////////////////////////////////////////////////////////////////
  676. void CMDhcp::FinalRelease(void)
  677. {
  678. LOG((MSP_TRACE, "CMDhcp::FinalRelease - enter"));
  679. if ( m_pFTM )
  680. {
  681. m_pFTM->Release();
  682. }
  683. if ( m_fApiIsInitialized )
  684. {
  685. McastApiCleanup();
  686. }
  687. LOG((MSP_TRACE, "CMDhcp::FinalRelease - exit"));
  688. }
  689. //////////////////////////////////////////////////////////////////////////////
  690. //////////////////////////////////////////////////////////////////////////////
  691. // IMcastAddressAllocation
  692. //
  693. // This is the main interface for the MDHCP address allocation. An
  694. // application will call CoCreateInstance on this interface to create the
  695. // MDHCP client interface object.
  696. //////////////////////////////////////////////////////////////////////////////
  697. //////////////////////////////////////////////////////////////////////////////
  698. //////////////////////////////////////////////////////////////////////////////
  699. // IMcastAddressAllocation::get_Scopes
  700. //
  701. // Parameters
  702. // pVariant [out] Pointer to a VARIANT that will receive an OLE-standard
  703. // Collection of available multicast scopes. Each scope
  704. // is an IDispatch pointer to an object that implements
  705. // IMcastScope.
  706. //
  707. // Return Values
  708. // S_OK Success
  709. // E_POINTER The caller passed in an invalid pointer argument
  710. // E_FAIL There are no scopes available
  711. // E_OUTOFMEMORY Not enough memory to create the required objects
  712. // other From MDhcpEnumerateScopes (win32 call)
  713. //
  714. // Description
  715. // This method is primarily for VB and other scripting languages; C++
  716. // programmers use EnumerateScopes instead.
  717. /////////////////////////////////////////////////////////////////////////////
  718. STDMETHODIMP CMDhcp::get_Scopes(
  719. VARIANT * pVariant
  720. )
  721. {
  722. LOG((MSP_TRACE, "CMDhcp::get_Scopes enter"));
  723. // Check argument.
  724. if ( IsBadWritePtr(pVariant, sizeof(VARIANT) ) )
  725. {
  726. LOG((MSP_ERROR, "get_Scopes: invalid pointer passed in "
  727. "(%08x)", pVariant));
  728. return E_POINTER;
  729. }
  730. DWORD i;
  731. DWORD dwScopeCount = 0;
  732. MCAST_SCOPE_ENTRY * pScopeList = NULL;
  733. HRESULT hr;
  734. BOOL fLocal;
  735. //
  736. // Grab the scopes from the C API.
  737. //
  738. hr = GetScopeList(&dwScopeCount, &pScopeList, &fLocal);
  739. if (FAILED(hr))
  740. {
  741. LOG((MSP_ERROR, "get_Scopes: GetScopeList failed "
  742. "(hr = %08x)", hr));
  743. return hr;
  744. }
  745. //
  746. // Now we wrap the array in COM wrappers.
  747. //
  748. IMcastScope ** ppWrappers = NULL;
  749. // this does a new into ppWrappers
  750. // as well as dwScopeCount individual object instantiations
  751. hr = CreateWrappers(dwScopeCount,
  752. pScopeList,
  753. &ppWrappers,
  754. fLocal);
  755. // At this point we've got a bunch of COM objects that contain
  756. // individual scopes, and so we no longer need the array of
  757. // scopes. Even if CreateWrappers failed we must get rid of
  758. // the array of scopes.
  759. delete pScopeList;
  760. if (FAILED(hr))
  761. {
  762. LOG((MSP_ERROR, "get_Scopes: CreateWrappers failed "
  763. "(hr = %08x)", hr));
  764. return hr;
  765. }
  766. //
  767. // create the collection object - see collect.h
  768. //
  769. typedef CTapiIfCollection< IMcastScope * > ScopeCollection;
  770. CComObject<ScopeCollection> * p;
  771. hr = CComObject<ScopeCollection>::CreateInstance( &p );
  772. if ( (FAILED(hr)) || (p == NULL) )
  773. {
  774. LOG((MSP_ERROR, "get_Scopes: Could not create CTapiIfCollection "
  775. "object - return %lx", hr ));
  776. for (DWORD i = 0 ; i < dwScopeCount; i++) delete ppWrappers[i];
  777. delete ppWrappers;
  778. return hr;
  779. }
  780. //
  781. // get the Collection's IDispatch interface
  782. //
  783. IDispatch * pDisp;
  784. hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
  785. if ( FAILED(hr) )
  786. {
  787. // Query interface failed so we don't know that if it addreffed
  788. // or not.
  789. LOG((MSP_ERROR, "get_Scopes: QI for IDispatch failed on "
  790. "ScopeCollection - %lx", hr ));
  791. delete p;
  792. //
  793. // PREFIXBUG 433295 - VLD
  794. // ppWrappers was allocated into CreateWrappers() method
  795. // we should deallocate it
  796. //
  797. for (DWORD i = 0 ; i < dwScopeCount; i++) delete ppWrappers[i];
  798. delete ppWrappers;
  799. return hr;
  800. }
  801. // initialize it using an iterator -- pointers to the beginning and
  802. // the ending element plus one.
  803. hr = p->Initialize( dwScopeCount,
  804. ppWrappers,
  805. ppWrappers + dwScopeCount );
  806. // ZoltanS fixed:
  807. // We started off by creating and calling QI on each object in
  808. // CreateWrappers. Then we passed the array of pointers to objects to
  809. // the Initialize method of the collection object. This method
  810. // called QI on each object to get each object's IDispatch pointer.
  811. // So now we are at refcount 2. We now Release() each object and get
  812. // back to refcount 1 on each object. Of course we must even do this
  813. // if the initialize failed (in that case to delete them outright).
  814. for (i = 0; i < dwScopeCount; i++)
  815. {
  816. ppWrappers[i]->Release();
  817. }
  818. // The array of pointers must now be deleted -- we now store the
  819. // objects in the collection instead. (or nowhere if initialize failed)
  820. delete ppWrappers;
  821. if (FAILED(hr))
  822. {
  823. // Initialize has failed -- we assume it did nothing, so we must
  824. // release all the COM objects ourselves
  825. LOG((MSP_ERROR, "get_Scopes: Could not initialize "
  826. "ScopeCollection object - return %lx", hr ));
  827. p->Release();
  828. return hr;
  829. }
  830. //
  831. // put the IDispatch interface pointer into the variant
  832. //
  833. LOG((MSP_INFO, "placing IDispatch value %08x in variant", pDisp));
  834. VariantInit(pVariant);
  835. pVariant->vt = VT_DISPATCH;
  836. pVariant->pdispVal = pDisp;
  837. LOG((MSP_TRACE, "CMDhcp::get_Scopes exit - return %lx", hr ));
  838. return hr;
  839. }
  840. //////////////////////////////////////////////////////////////////////////////
  841. // IMcastAddressAllocation::EnumerateScopes
  842. //
  843. // Parameters
  844. // ppEnumMcastScope [out] Returns a pointer to a new IEnumMcastScope
  845. // object. IEnumMcastScope is a standard
  846. // enumerator interface that enumerates
  847. // IMcastScope objects.
  848. //
  849. // Return Values
  850. // S_OK Success
  851. // E_POINTER The caller passed in an invalid pointer argument
  852. // E_FAIL There are no scopes available
  853. // E_OUTOFMEMORY Not enough memory to create the required objects
  854. // other From MDhcpEnumerateScopes (win32 call)
  855. //
  856. // Description
  857. // This method is primarily for C++ programmers; VB and other scripting
  858. // languages use get_Scopes instead.
  859. /////////////////////////////////////////////////////////////////////////////
  860. STDMETHODIMP CMDhcp::EnumerateScopes(
  861. IEnumMcastScope ** ppEnumMcastScope
  862. )
  863. {
  864. LOG((MSP_TRACE, "CMDhcp::EnumerateScopes enter"));
  865. if ( IsBadWritePtr(ppEnumMcastScope, sizeof(IEnumMcastScope *) ) )
  866. {
  867. LOG((MSP_ERROR, "EnumerateScopes: bad pointer argument "
  868. "(%08x)", ppEnumMcastScope));
  869. return E_POINTER;
  870. }
  871. DWORD dwScopeCount = 0;
  872. MCAST_SCOPE_ENTRY * pScopeList = NULL;
  873. HRESULT hr;
  874. BOOL fLocal;
  875. //
  876. // Grab the scopes from the C API.
  877. //
  878. hr = GetScopeList(&dwScopeCount, &pScopeList, &fLocal);
  879. if (FAILED(hr))
  880. {
  881. LOG((MSP_ERROR, "EnumerateScopes: GetScopeList failed "
  882. "(hr = %08x)", hr));
  883. return hr;
  884. }
  885. //
  886. // Now we wrap the array in COM wrappers.
  887. //
  888. IMcastScope ** ppWrappers = NULL;
  889. // this does a new into ppWrappers
  890. hr = CreateWrappers(dwScopeCount,
  891. pScopeList,
  892. &ppWrappers,
  893. fLocal);
  894. // At this point we've got a bunch of COM objects that contain
  895. // individual scopes, and so we no longer need the array of
  896. // scopes. Even if CreateWrappers failed we must get rid of
  897. // the array of scopes.
  898. delete pScopeList;
  899. if (FAILED(hr))
  900. {
  901. LOG((MSP_ERROR, "EnumerateScopes: CreateWrappers failed "
  902. "(hr = %08x)", hr));
  903. return hr;
  904. }
  905. //
  906. // Now we create and set up the enumerator.
  907. //
  908. typedef _CopyInterface<IMcastScope> CCopy;
  909. typedef CSafeComEnum<IEnumMcastScope, &IID_IEnumMcastScope,
  910. IMcastScope *, CCopy> CEnumerator;
  911. CComObject<CEnumerator> *pEnum = NULL;
  912. hr = CComObject<CEnumerator>::CreateInstance(&pEnum);
  913. if ((FAILED(hr)) || (pEnum == NULL))
  914. {
  915. LOG((MSP_ERROR, "Couldn't create enumerator object: %08x", hr));
  916. delete ppWrappers;
  917. return hr;
  918. }
  919. // Get the IEnumMcastScope interface.
  920. hr = pEnum->_InternalQueryInterface(
  921. IID_IEnumMcastScope,
  922. (void **)ppEnumMcastScope
  923. );
  924. if (FAILED(hr))
  925. {
  926. LOG((MSP_ERROR, "QI on enumerator object failed: %08x", hr));
  927. delete ppWrappers;
  928. delete pEnum;
  929. return hr;
  930. }
  931. // This takes ownership of the wrapper list so we will no longer
  932. // delete the wrapper list if this succeeds.
  933. hr = pEnum->Init(ppWrappers, ppWrappers + dwScopeCount, NULL,
  934. AtlFlagTakeOwnership);
  935. if (FAILED(hr))
  936. {
  937. LOG((MSP_ERROR, "Init enumerator object failed: %08x", hr));
  938. delete ppWrappers;
  939. pEnum->Release();
  940. return hr;
  941. }
  942. LOG((MSP_TRACE, "CMDhcp::EnumerateScopes exit"));
  943. return S_OK;
  944. }
  945. //////////////////////////////////////////////////////////////////////////////
  946. // IMcastAddressAllocation::RequestAddress
  947. //
  948. // Parameters
  949. // pScope [in] This identifies the multicast scope from which
  950. // the application wants to be given an address.
  951. // The application first calls get_Scopes or
  952. // EnumerateScopes to obtain a list of available
  953. // scopes.
  954. // LeaseStartTime [in] Requested time for the lease on these addresses
  955. // to start / begin. The start time that is
  956. // actually granted may be different.
  957. // LeaseStopTime [in] Requested time for the lease on these addresses
  958. // to stop / end. The stop time that is actually
  959. // granted may be different.
  960. // NumAddresses [in] The number of addresses requested. Fewer
  961. // addresses may actually be granted. NOTE:
  962. // although these COM interfaces and their
  963. // implementation support allocation of multiple
  964. // addresses at a time, this is not currently
  965. // supported by the underlying Win32 calls. You
  966. // may need to use a loop instead.
  967. // ppLeaseResponse [out] Pointer to an interface pointer that will be set
  968. // to point to a new IMcastLeaseInfo object. This
  969. // interface can then be used to discover the
  970. // actual attributes of the granted lease. See
  971. // below for a description of IMcastScope.
  972. //
  973. // Return Values
  974. // S_OK Success
  975. // E_POINTER The caller passed in an invalid pointer argument
  976. // E_OUTOFMEMORY Not enough memory to create the required objects
  977. // E_INVALIDARG Requested too many addresses, format conversion
  978. // failed for the start time or stop time, or the stop
  979. // time is less than the start time
  980. // other From MdhcpRequestAddress (win32 call)
  981. //
  982. // Description
  983. // Call this method to obtain a new lease for one or more multicast
  984. // addresses. You will first need to call EnumerateScopes or get_Scopes,
  985. // as well as CreateMDhcpRequestID.
  986. /////////////////////////////////////////////////////////////////////////////
  987. STDMETHODIMP CMDhcp::RequestAddress(IMcastScope * pScope,
  988. DATE LeaseStartTime,
  989. DATE LeaseStopTime,
  990. long NumAddresses,
  991. IMcastLeaseInfo ** ppLeaseResponse)
  992. {
  993. LOG((MSP_TRACE, "CMDhcp::RequestAddress enter: asking for %d addresses",
  994. NumAddresses));
  995. if ( IsBadReadPtr( pScope, sizeof(IMcastScope) ) )
  996. {
  997. LOG((MSP_ERROR, "CMDhcp::RequestAddress - "
  998. "bad scope pointer - exit E_POINTER"));
  999. return E_POINTER;
  1000. }
  1001. // no need to check ppLeaseResponse -- WrapMDhcpLeaseInfo handles it
  1002. MCAST_CLIENT_UID requestID;
  1003. MCAST_SCOPE_CTX scopeCtx;
  1004. MCAST_LEASE_INFO * pLeaseRequest;
  1005. HRESULT hr;
  1006. BOOL fLocal;
  1007. long lTtl;
  1008. // Munge input arguments into three structs for passing to the C API.
  1009. // pLeaseRequest and requestID->ClientUID are allocated. We must delete them when
  1010. // we're done.
  1011. hr = PrepareArgumentsRequest(pScope, // goes into scopeCtx
  1012. LeaseStartTime, // goes into leaseRequest
  1013. LeaseStopTime, // goes into leaseRequest
  1014. NumAddresses, // goes into leaseRequest
  1015. &requestID, // we generate it
  1016. &scopeCtx,
  1017. &pLeaseRequest,
  1018. &fLocal,
  1019. &lTtl
  1020. );
  1021. if ( FAILED(hr) )
  1022. {
  1023. LOG((MSP_ERROR, "CMDHcp::RequestAddress - "
  1024. "PrepareArgumentsRequest failed - exit 0x%08x", hr));
  1025. return hr;
  1026. }
  1027. MCAST_LEASE_INFO * pLeaseResponse = (MCAST_LEASE_INFO *) new BYTE
  1028. [ sizeof(MCAST_LEASE_INFO) + sizeof(DWORD) * NumAddresses ];
  1029. if (pLeaseResponse == NULL)
  1030. {
  1031. LOG((MSP_ERROR, "RequestAddress: out of memory in response alloc"));
  1032. delete requestID.ClientUID;
  1033. delete pLeaseRequest;
  1034. return E_OUTOFMEMORY;
  1035. }
  1036. DWORD dwCode;
  1037. dwCode = LocalRequestAddress(fLocal,
  1038. &requestID,
  1039. &scopeCtx,
  1040. pLeaseRequest,
  1041. pLeaseResponse);
  1042. // No matter what, we no longer need this.
  1043. delete pLeaseRequest;
  1044. if (dwCode != ERROR_SUCCESS)
  1045. {
  1046. LOG((MSP_ERROR, "RequestAddress: C API call failed "
  1047. "(code = %d)", dwCode));
  1048. delete requestID.ClientUID;
  1049. delete pLeaseResponse;
  1050. return HRESULT_FROM_ERROR_CODE(dwCode);
  1051. }
  1052. // Wrap the lease response, along with the requestID, in an interface
  1053. // and return it.
  1054. // The wrapper assumes ownership of the lease structure and
  1055. // requestID.clientuid.
  1056. hr = WrapMDhcpLeaseInfo(TRUE,
  1057. lTtl,
  1058. fLocal,
  1059. pLeaseResponse,
  1060. &requestID,
  1061. ppLeaseResponse);
  1062. if ( FAILED(hr) )
  1063. {
  1064. LOG((MSP_ERROR, "RequestAddress: WrapMDhcpLeaseInfo failed "
  1065. "(hr = %08x)", hr));
  1066. delete pLeaseResponse;
  1067. delete requestID.ClientUID;
  1068. return hr;
  1069. }
  1070. return S_OK;
  1071. }
  1072. //////////////////////////////////////////////////////////////////////////////
  1073. // IMcastAddressAllocation::RenewAddress
  1074. //
  1075. // Parameters
  1076. // pRenewRequest [in] Pointer to an IMcastLeaseInfo object specifying
  1077. // the attributes of the requested renewal, such
  1078. // as which address(es) to renew. This is
  1079. // obtained by calling CreateLeaseInfo.
  1080. // ppRenewResponse [out] Pointer to an interface pointer that will be set
  1081. // to point to a new IMcastLeaseInfo object. This
  1082. // interface can then be used to discover the
  1083. // attributes of the renewed lease. See below for
  1084. // a description of IMcastScope.
  1085. //
  1086. // Return Values
  1087. // S_OK Success
  1088. // E_OUTOFMEMORY Not enough memory to create the required objects
  1089. // E_POINTER The caller passed in an invalid pointer argument
  1090. // E_INVALIDARG Start time is greater than stop time
  1091. // other From MdhcpRenewAddress (win32 call)
  1092. //
  1093. // Description
  1094. // To renew a lease, call CreateLeaseInfo to specify the parameters of
  1095. // the renewal request, and then call this method to make the request.
  1096. /////////////////////////////////////////////////////////////////////////////
  1097. STDMETHODIMP CMDhcp::RenewAddress(
  1098. long lReserved, // unused
  1099. IMcastLeaseInfo * pRenewRequest,
  1100. IMcastLeaseInfo ** ppRenewResponse
  1101. )
  1102. {
  1103. LOG((MSP_TRACE, "CMDhcp::RenewAddress enter"));
  1104. // no need to check pRequestID or pRenewRequest --
  1105. // PrepareArgumentsNonRequest handles that.
  1106. // ppRenewResponse check handled by WrapMDhcpLeaseInfo
  1107. MCAST_CLIENT_UID requestID;
  1108. MCAST_LEASE_INFO * pRenewRequestStruct;
  1109. HRESULT hr;
  1110. BOOL fLocal;
  1111. BOOL fGotTtl;
  1112. long lTtl;
  1113. // Munge input arguments into three structs for passing to the C API.
  1114. // pLeaseRequest and requestID->ClientUID are allocated. We must delete them when
  1115. // we're done.
  1116. hr = PrepareArgumentsNonRequest(pRenewRequest,
  1117. &requestID,
  1118. &pRenewRequestStruct,
  1119. &fLocal,
  1120. &fGotTtl,
  1121. &lTtl);
  1122. if ( FAILED(hr) )
  1123. {
  1124. LOG((MSP_ERROR, "RenewAddress: PrepareArgumentsNonRequest failed "
  1125. "(hr = %08x)", hr));
  1126. return hr;
  1127. }
  1128. //
  1129. // Check that the start time is less than the stop time
  1130. //
  1131. if ( pRenewRequestStruct->LeaseStartTime >
  1132. pRenewRequestStruct->LeaseEndTime )
  1133. {
  1134. LOG((MSP_ERROR, "PrepareArgumentsNonRequest - "
  1135. "start time %d is greater than stop time %d - exit E_INVALIDARG",
  1136. pRenewRequestStruct->LeaseStartTime,
  1137. pRenewRequestStruct->LeaseEndTime));
  1138. delete requestID.ClientUID;
  1139. delete pRenewRequestStruct;
  1140. return E_INVALIDARG;
  1141. }
  1142. MCAST_LEASE_INFO * pRenewResponse = (MCAST_LEASE_INFO *) new BYTE
  1143. [ sizeof(MCAST_LEASE_INFO) +
  1144. sizeof(DWORD) * pRenewRequestStruct->AddrCount ];
  1145. if ( pRenewResponse == NULL )
  1146. {
  1147. LOG((MSP_ERROR, "RenewAddress: out of memory in response alloc"));
  1148. delete requestID.ClientUID;
  1149. delete pRenewRequestStruct;
  1150. return E_OUTOFMEMORY;
  1151. }
  1152. DWORD dwCode = LocalRenewAddress(fLocal,
  1153. &requestID,
  1154. pRenewRequestStruct,
  1155. pRenewResponse);
  1156. //
  1157. // We have performed the renew request so we no longer need the struct
  1158. // for the request, even if the request failed.
  1159. //
  1160. delete pRenewRequestStruct;
  1161. if ( dwCode != ERROR_SUCCESS )
  1162. {
  1163. LOG((MSP_ERROR, "RenewAddress: C API call failed "
  1164. "(code = %d)", dwCode));
  1165. delete requestID.ClientUID;
  1166. delete pRenewResponse;
  1167. return HRESULT_FROM_ERROR_CODE(dwCode);
  1168. }
  1169. //
  1170. // Wrap pRenewResponse and the requestID in an interface and return it.
  1171. // the wrapper takes ownership of the requestID.clientUID and the
  1172. // response struct
  1173. //
  1174. hr = WrapMDhcpLeaseInfo(fGotTtl,
  1175. lTtl,
  1176. fLocal,
  1177. pRenewResponse,
  1178. &requestID,
  1179. ppRenewResponse);
  1180. if ( FAILED(hr) )
  1181. {
  1182. LOG((MSP_ERROR, "RenewAddress: WrapMDhcpLeaseInfo failed "
  1183. "(hr = %08x)", hr));
  1184. delete requestID.ClientUID;
  1185. delete pRenewResponse;
  1186. return hr;
  1187. }
  1188. LOG((MSP_TRACE, "CMDhcp::RenewAddress exit"));
  1189. return S_OK;
  1190. }
  1191. //////////////////////////////////////////////////////////////////////////////
  1192. // IMcastAddressAllocation::ReleaseAddress
  1193. //
  1194. // Parameters
  1195. // pReleaseRequest [in] Pointer to an IMcastLeaseInfo object specifying
  1196. // the which address(es) to release. This is
  1197. // returned from a previous RequestAddress call or
  1198. // obtained by calling CreateLeaseInfo.
  1199. //
  1200. // Return Values
  1201. // S_OK Success
  1202. // E_POINTER The caller passed in an invalid pointer argument
  1203. // E_OUTOFMEMORY Not enough memory to make the request
  1204. // other From MdhcpReleaseAddress (win32 call)
  1205. //
  1206. // Description
  1207. // Use this method to release a lease that was obtained previously.
  1208. /////////////////////////////////////////////////////////////////////////////
  1209. STDMETHODIMP CMDhcp::ReleaseAddress(
  1210. IMcastLeaseInfo * pReleaseRequest
  1211. )
  1212. {
  1213. LOG((MSP_TRACE, "CMDhcp::ReleaseAddress enter"));
  1214. // no need to check pReleaseRequest --
  1215. // PrepareArgumentsNonRequest handles that.
  1216. MCAST_CLIENT_UID requestID;
  1217. MCAST_LEASE_INFO * pReleaseRequestStruct;
  1218. HRESULT hr;
  1219. BOOL fLocal;
  1220. BOOL fGotTtl; // unused after call
  1221. long lTtl; // unused after call
  1222. hr = PrepareArgumentsNonRequest(pReleaseRequest,
  1223. &requestID,
  1224. &pReleaseRequestStruct,
  1225. &fLocal,
  1226. &fGotTtl,
  1227. &lTtl
  1228. );
  1229. if ( FAILED(hr) )
  1230. {
  1231. LOG((MSP_ERROR, "ReleaseAddress: PrepareArgumentsNonRequest failed "
  1232. "(hr = %08x)", hr));
  1233. return hr;
  1234. }
  1235. DWORD dwCode;
  1236. dwCode = LocalReleaseAddress(fLocal,
  1237. &requestID,
  1238. pReleaseRequestStruct);
  1239. //
  1240. // These were allocated by PrepareArgumentsNonRequest and there is no one
  1241. // to own them now -- we delete them. This is true even if the
  1242. // LocalReleaseAddress call failed.
  1243. //
  1244. delete pReleaseRequestStruct;
  1245. delete requestID.ClientUID;
  1246. if ( dwCode != ERROR_SUCCESS )
  1247. {
  1248. LOG((MSP_ERROR, "ReleaseAddress: C API call failed "
  1249. "(code = %d)", dwCode));
  1250. return HRESULT_FROM_ERROR_CODE(dwCode);
  1251. }
  1252. LOG((MSP_TRACE, "CMDhcp::ReleaseAddress exit"));
  1253. return S_OK;
  1254. }
  1255. //////////////////////////////////////////////////////////////////////////////
  1256. // IMcastAddressAllocation::CreateLeaseInfo
  1257. //
  1258. // Parameters
  1259. // LeaseStartTime [in] The start time of the lease.
  1260. // LeaseStopTime [in] The stop time of the lease.
  1261. // dwNumAddresses [in] The number of addresses associated with the
  1262. // lease.
  1263. // ppAddresses [in] An array of LPWSTRs of size dwNumAddresses. Each
  1264. // LPWSTR (Unicode string pointer) is an IPv4
  1265. // address in "dot-quad" notation; e.g.
  1266. // "123.234.12.17".
  1267. // pRequestID [in] An LPWSTR (Unicode string pointer) specifying
  1268. // the request ID for the original request.
  1269. // pServerAddress [in] An LPWSTR (Unicode string pointer) specifying
  1270. // the address of the server that granted the
  1271. // original request. This address is an IPv4
  1272. // address in "dot quad" notation; e.g.
  1273. // "123.234.12.17".
  1274. // ppReleaseRequest [out] Returns a pointer to the IMcastLeaseInfo
  1275. // interface on the newly created lease
  1276. // information object.
  1277. //
  1278. // Return Values
  1279. // S_OK Success
  1280. // E_POINTER The caller passed in an invalid pointer argument
  1281. // E_OUTOFMEMORY Not enough memory to create the required objects
  1282. // E_INVALIDARG An error occured during the date format conversion
  1283. //
  1284. // Description
  1285. // Use this method to create a lease information object for a subsequent
  1286. // RenewAddress or ReleaseAddress call. This method is primarily for C++
  1287. // programmers; VB and other scripting languages use
  1288. // CreateLeaseInfoFromVariant instead.
  1289. // The dwNumAddresses, ppAddresses, pRequestID, and pServerAddress
  1290. // parameters are normally obtained by calling the corresponding
  1291. // IMcastLeaseInfo methods on the lease info object corresponding to the
  1292. // original request. These values should be saved in persistent storage
  1293. // between executions of the application program. If you are renewing or
  1294. // releasing a lease that was requested during the same run of the
  1295. // application, you have no reason to use CreateLeaseInfo; just pass the
  1296. // existing IMcastLeaseInfo pointer to RenewAddress or ReleaseAddress.
  1297. //////////////////////////////////////////////////////////////////////////////
  1298. #include <atlwin.cpp>
  1299. STDMETHODIMP CMDhcp::CreateLeaseInfo(
  1300. DATE LeaseStartTime,
  1301. DATE LeaseStopTime,
  1302. DWORD dwNumAddresses,
  1303. LPWSTR * ppAddresses,
  1304. LPWSTR pRequestID,
  1305. LPWSTR pServerAddress,
  1306. IMcastLeaseInfo ** ppReleaseRequest
  1307. )
  1308. {
  1309. LOG((MSP_TRACE, "CMDhcp::CreateLeaseInfo enter"));
  1310. if ( IsBadWritePtr(ppReleaseRequest, sizeof(IMcastLeaseInfo *) ) )
  1311. {
  1312. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfo - "
  1313. "invalid lease return pointer: 0x%08x - exit E_POINTER",
  1314. ppReleaseRequest));
  1315. return E_POINTER;
  1316. }
  1317. if ( IsBadStringPtr(pRequestID, (UINT) -1 ) )
  1318. {
  1319. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfo - "
  1320. "invalid RequestID pointer: 0x%08x - exit E_POINTER",
  1321. pRequestID));
  1322. return E_POINTER;
  1323. }
  1324. if ( ( dwNumAddresses < 1 ) || ( dwNumAddresses > USHRT_MAX ) )
  1325. {
  1326. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfo - "
  1327. "invalid number of addresses: %d - exit E_INVALIDARG",
  1328. dwNumAddresses));
  1329. return E_INVALIDARG;
  1330. }
  1331. if (IsBadReadPtr(ppAddresses, sizeof(LPWSTR) * dwNumAddresses) )
  1332. {
  1333. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfo - "
  1334. "invalid addresses array pointer: 0x%08x - exit E_POINTER",
  1335. ppAddresses));
  1336. return E_POINTER;
  1337. }
  1338. if ( IsBadStringPtr(pServerAddress, (UINT) -1 ) )
  1339. {
  1340. LOG((MSP_ERROR, "CreateLeaseInfo: invalid Server Address pointer: %08x",
  1341. pRequestID));
  1342. return E_POINTER;
  1343. }
  1344. HRESULT hr;
  1345. // create the com object.
  1346. CComObject<CMDhcpLeaseInfo> * pMDhcpLeaseInfo;
  1347. hr = CComObject<CMDhcpLeaseInfo>::CreateInstance(&pMDhcpLeaseInfo);
  1348. if ( (FAILED(hr)) || (pMDhcpLeaseInfo == NULL) )
  1349. {
  1350. LOG((MSP_ERROR, "CreateLeaseInfo: can't create MDhcpLeaseInfo Object."));
  1351. return hr;
  1352. }
  1353. // Get the IMcastLeaseInfo interface.
  1354. hr = pMDhcpLeaseInfo->_InternalQueryInterface(
  1355. IID_IMcastLeaseInfo,
  1356. (void **)ppReleaseRequest
  1357. );
  1358. if ( FAILED(hr) )
  1359. {
  1360. LOG((MSP_ERROR, "CreateLeaseInfo: QueryInterface failed: %x", hr));
  1361. delete pMDhcpLeaseInfo;
  1362. return hr;
  1363. }
  1364. // Fill in the object with the stuff the user wanted.
  1365. hr = pMDhcpLeaseInfo->Initialize(LeaseStartTime,
  1366. LeaseStopTime,
  1367. dwNumAddresses,
  1368. ppAddresses,
  1369. pRequestID,
  1370. pServerAddress);
  1371. if ( FAILED(hr) )
  1372. {
  1373. LOG((MSP_ERROR, "CreateLeaseInfo: Initialize failed: %x", hr));
  1374. delete pMDhcpLeaseInfo;
  1375. return hr;
  1376. }
  1377. LOG((MSP_TRACE, "CMDhcp::CreateLeaseInfo exit"));
  1378. return S_OK;
  1379. }
  1380. //////////////////////////////////////////////////////////////////////////////
  1381. // IMcastAddressAllocation::CreateLeaseInfoFromVariant
  1382. //
  1383. // Parameters
  1384. // LeaseStartTime [in] The start time of the lease.
  1385. // LeaseStopTime [in] The stop time of the lease.
  1386. // vAddresses [in] A VARIANT containing a SafeArray of BSTRs. Each
  1387. // BSTR (size-tagged Unicode string pointer) is
  1388. // an IPv4 address in "dot-quad" notation; e.g.
  1389. // "123.234.12.17".
  1390. // pRequestID [in] A BSTR (size-tagged Unicode string pointer)
  1391. // specifying the request ID for the original
  1392. // request.
  1393. // pServerAddress [in] A BSTR (size-tagged Unicode string pointer)
  1394. // specifying the address of the server that
  1395. // granted the original request. This address is
  1396. // an IPv4 address in "dot quad" notation; e.g.
  1397. // "123.234.12.17".
  1398. // ppReleaseRequest [out] Returns a pointer to the IMcastLeaseInfo
  1399. // interface on the newly created lease
  1400. // information object.
  1401. //
  1402. // Return Values
  1403. // S_OK Success
  1404. // E_POINTER The caller passed in an invalid pointer argument
  1405. // E_OUTOFMEMORY Not enough memory to create the required objects
  1406. // E_INVALIDARG An error occured during the date format conversion
  1407. //
  1408. // Description
  1409. // Use this method to create a lease information object for a subsequent
  1410. // RenewAddress or ReleaseAddress call. This method is primarily for VB
  1411. // and other scripting languages; C++ programmers should use
  1412. // CreateLeaseInfo instead.
  1413. // The dwNumAddresses, ppAddresses, pRequestID, and pServerAddress
  1414. // parameters are normally obtained by calling the corresponding
  1415. // IMcastLeaseInfo methods on the lease info object corresponding to the
  1416. // original request. These values should be saved in persistent storage
  1417. // between executions of the application program. If you are renewing or
  1418. // releasing a lease that was requested during the same run of the
  1419. // application, you have no reason to use CreateLeaseInfoFromVariant; just
  1420. // pass the existing IMcastLeaseInfo pointer to RenewAddress or
  1421. // ReleaseAddress.
  1422. /////////////////////////////////////////////////////////////////////////////
  1423. STDMETHODIMP CMDhcp::CreateLeaseInfoFromVariant(
  1424. DATE LeaseStartTime,
  1425. DATE LeaseStopTime,
  1426. VARIANT vAddresses,
  1427. BSTR pRequestID,
  1428. BSTR pServerAddress,
  1429. IMcastLeaseInfo ** ppReleaseRequest
  1430. )
  1431. {
  1432. LOG((MSP_TRACE, "CMDhcp::CreateLeaseInfoFromVariant enter"));
  1433. // We will check the pointers in CreateLeaseInfo.
  1434. HRESULT hr;
  1435. // Get from the variant:
  1436. DWORD dwNumAddresses;
  1437. LPWSTR * ppAddresses;
  1438. SAFEARRAY * psaAddresses = NULL; // SafeArray with the addresses
  1439. long lLowerBound = 0; // lower bound of safearray
  1440. long lUpperBound = 0; // upper bound of safearray
  1441. hr = VerifyAndGetArrayBounds(
  1442. vAddresses,
  1443. &psaAddresses,
  1444. &lLowerBound,
  1445. &lUpperBound);
  1446. if (FAILED(hr))
  1447. {
  1448. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfoFromVariant: invalid "
  1449. "VARIANT"));
  1450. return E_INVALIDARG;
  1451. }
  1452. // This is how many addresses we *expect* (may have fewer).
  1453. long lAddrCount = lUpperBound - lLowerBound + 1;
  1454. if (lAddrCount < 1)
  1455. {
  1456. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfoFromVariant: too few "
  1457. "addresses (check #1) (%d)", lAddrCount));
  1458. return E_INVALIDARG;
  1459. }
  1460. // We allocate as many as we are told to expect, but some of this
  1461. // space may end up getting "wasted" if there are fewer valid ones
  1462. // after all.
  1463. ppAddresses = new LPWSTR[lAddrCount];
  1464. if (ppAddresses == NULL)
  1465. {
  1466. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfoFromVariant: "
  1467. "out of memory in array allocation"));
  1468. return E_OUTOFMEMORY;
  1469. }
  1470. long lCurrSrc; // the current element in the safearray (source)
  1471. long lCurrDest = 0; // the current element in the struct's array (destination)
  1472. // Get the addresses from the SafeArray and put them in our array.
  1473. for (lCurrSrc = lLowerBound; lCurrSrc <= lUpperBound; lCurrSrc++)
  1474. {
  1475. hr = SafeArrayGetElement(
  1476. psaAddresses,
  1477. &lCurrSrc,
  1478. & ( ppAddresses[lCurrDest] )
  1479. );
  1480. if ( FAILED(hr) )
  1481. {
  1482. LOG((MSP_INFO, "CMDhcp::CreateLeaseInfoFromVariant: "
  1483. "failed to get safearray element %d"
  1484. " - skipping (array range %d-%d)",
  1485. lCurrSrc, lLowerBound, lUpperBound));
  1486. }
  1487. else if ( ppAddresses[lCurrDest] == 0 )
  1488. {
  1489. LOG((MSP_INFO, "CMDhcp::CreateLeaseInfoFromVariant: "
  1490. "got ZERO address from safearray "
  1491. "element %d - skipping (array range %d-%d)",
  1492. lCurrSrc, lLowerBound, lUpperBound));
  1493. }
  1494. else
  1495. {
  1496. // We got an element.
  1497. lCurrDest++;
  1498. }
  1499. }
  1500. // note the number of addresses we actually placed in the array
  1501. dwNumAddresses = (DWORD) lCurrDest;
  1502. if (dwNumAddresses < 1)
  1503. {
  1504. LOG((MSP_ERROR, "CMDhcp::CreateLeaseInfoFromVariant: "
  1505. "too few addresses (check #2)"
  1506. "(%d)", lAddrCount));
  1507. delete ppAddresses;
  1508. return E_INVALIDARG;
  1509. }
  1510. hr = CreateLeaseInfo(LeaseStartTime,
  1511. LeaseStopTime,
  1512. dwNumAddresses,
  1513. ppAddresses,
  1514. pRequestID,
  1515. pServerAddress,
  1516. ppReleaseRequest
  1517. );
  1518. // No matter what, we no longer need this.
  1519. delete ppAddresses;
  1520. if (FAILED(hr))
  1521. {
  1522. LOG((MSP_TRACE, "CMDhcp::CreateLeaseInfoFromVariant : "
  1523. "CreateLeaseInfo returned %08x", hr));
  1524. return hr;
  1525. }
  1526. LOG((MSP_TRACE, "CMDhcp::CreateLeaseInfoFromVariant exit"));
  1527. return S_OK;
  1528. }
  1529. // eof