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.

1028 lines
28 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. handle.cxx
  5. Abstract:
  6. Contains functions to allocate and deallocate handle values for various
  7. Windows Internet Extensions DLL 'objects'
  8. Functions in this module generate pseudo-handle values and free them when
  9. no longer required. Each handle value is generated from its position within
  10. a (2K) bitmap (== 16K handles max.). We also maintain an array that is used
  11. to map the generated handle to the address of the handle object that it
  12. represents
  13. Contents:
  14. HandleInitialize
  15. HandleTerminate
  16. AllocateHandle
  17. FreeHandle
  18. MapHandleToAddress
  19. DereferenceObject
  20. (BitToIndex)
  21. Author:
  22. Richard L Firth (rfirth) 31-Oct-1994
  23. Revision History:
  24. 11-Jan-1996 rfirth
  25. Use fixed memory instead of moveable (Win95 has a bug w/ LocalUnlock)
  26. 31-Oct-1994 rfirth
  27. Created
  28. --*/
  29. #include <wininetp.h>
  30. //
  31. // manifests
  32. //
  33. #define BASE_HANDLE_VALUE 0x00cc0000
  34. #define HANDLE_INCREMENT 4
  35. #define BITS_PER_BYTE 8
  36. #define BITS_IN_DWORD (sizeof(DWORD) * BITS_PER_BYTE)
  37. #define FULL_DWORD ((DWORD)-1)
  38. #define MAXIMUM_HANDLE_NUMBER (64 K)
  39. #define MAXIMUM_HANDLE_COUNT ((MAXIMUM_HANDLE_NUMBER / HANDLE_INCREMENT) - 1)
  40. #define MAXIMUM_DWORD_INDEX ((MAXIMUM_HANDLE_COUNT + BITS_IN_DWORD - 1) / BITS_IN_DWORD)
  41. #define MINIMUM_HANDLE_VALUE (BASE_HANDLE_VALUE + HANDLE_INCREMENT)
  42. #define MAXIMUM_HANDLE_VALUE (BASE_HANDLE_VALUE + MAXIMUM_HANDLE_NUMBER - HANDLE_INCREMENT)
  43. #define INITIAL_MAP_LENGTH 16 // 512 handles == 2048 bytes
  44. #define HANDLE_MAP_INCREMENT 16
  45. // Warning: In order for 64-bit compatibility, the range of handle
  46. // values must be restricted to quantities representable by 32-bits.
  47. // If maximum handle value >= 4GB the implementation has to change
  48. // use 64-bit integral types internally.
  49. //
  50. // macros
  51. //
  52. #define NEXT_HANDLE_VALUE(d, i) (BASE_HANDLE_VALUE + ((d) * BITS_IN_DWORD + ((i) + 1)) * HANDLE_INCREMENT)
  53. //
  54. // private prototypes
  55. //
  56. PRIVATE
  57. inline
  58. DWORD
  59. BitToIndex(
  60. IN DWORD Bit
  61. );
  62. //
  63. // private data
  64. //
  65. PRIVATE CRITICAL_SECTION HandleMapCritSec; // protects access to following variables
  66. PRIVATE LPDWORD HandleMap = NULL; // bitmap of allocated handles
  67. PRIVATE DWORD HandleMapLength; // number of DWORDs in HandleMap
  68. PRIVATE DWORD NextHandleMapDword = 0; // first bitmap DWORD to check
  69. PRIVATE DWORD NextHandleMapBit = 1; // map of first bit to check
  70. PRIVATE DWORD NextHandleMapBitIndex = 0; // position of first bit in first DWORD
  71. PRIVATE DWORD NextHandleValue = MINIMUM_HANDLE_VALUE;
  72. PRIVATE DWORD NextHandleIndex = 0;
  73. PRIVATE BOOL Initialized = FALSE;
  74. PRIVATE LPVOID * MapArray = NULL;
  75. PRIVATE DWORD MapArrayLength = 0;
  76. //
  77. // functions
  78. //
  79. DWORD
  80. HandleInitialize(
  81. VOID
  82. )
  83. /*++
  84. Routine Description:
  85. Performs initialization required by functions in this module
  86. Arguments:
  87. None.
  88. Return Value:
  89. DWORD
  90. Success - ERROR_SUCCESS
  91. Failure - return code from LocalAlloc
  92. --*/
  93. {
  94. DEBUG_ENTER((DBG_HANDLE,
  95. Dword,
  96. "HandleInitialize",
  97. NULL
  98. ));
  99. InitializeCriticalSection(&HandleMapCritSec);
  100. HandleMapLength = INITIAL_MAP_LENGTH;
  101. DWORD error;
  102. //
  103. // ResizeBuffer() doesn't use LMEM_ZEROINIT
  104. //
  105. HandleMap = (LPDWORD)ALLOCATE_MEMORY(LMEM_ZEROINIT,
  106. HandleMapLength * sizeof(DWORD)
  107. );
  108. if (HandleMap != NULL) {
  109. MapArrayLength = INITIAL_MAP_LENGTH * BITS_IN_DWORD;
  110. MapArray = (LPVOID *)ALLOCATE_MEMORY(LMEM_ZEROINIT,
  111. MapArrayLength * sizeof(LPVOID)
  112. );
  113. if (MapArray != NULL) {
  114. Initialized = TRUE;
  115. error = ERROR_SUCCESS;
  116. }
  117. }
  118. if (!HandleMap || !MapArray) {
  119. error = GetLastError();
  120. HandleTerminate();
  121. }
  122. DEBUG_LEAVE(error);
  123. return error;
  124. }
  125. VOID
  126. HandleTerminate(
  127. VOID
  128. )
  129. /*++
  130. Routine Description:
  131. Obverse of HandleInitialize - frees any system resources allocated by
  132. HandleInitialize
  133. Arguments:
  134. None.
  135. Return Value:
  136. None.
  137. --*/
  138. {
  139. DEBUG_ENTER((DBG_HANDLE,
  140. None,
  141. "HandleTerminate",
  142. NULL
  143. ));
  144. if (Initialized) {
  145. //
  146. // there shouldn't be any other threads active when this function is
  147. // called but we'll grab the critical section anyway, just to make sure
  148. //
  149. EnterCriticalSection(&HandleMapCritSec);
  150. //
  151. // free up the memory occupied by the handle bitmap and map array
  152. //
  153. if (HandleMap != NULL) {
  154. HandleMap = (LPDWORD)FREE_MEMORY((HLOCAL)HandleMap);
  155. }
  156. INET_ASSERT(HandleMap == NULL);
  157. if (MapArray != NULL) {
  158. MapArray = (LPVOID *)FREE_MEMORY((HLOCAL)MapArray);
  159. }
  160. INET_ASSERT(MapArray == NULL);
  161. //
  162. // no longer initialized
  163. //
  164. Initialized = FALSE;
  165. //
  166. // and reset the variables
  167. //
  168. HandleMapLength = 0;
  169. NextHandleMapDword = 0;
  170. NextHandleMapBit = 1;
  171. NextHandleMapBitIndex = 0;
  172. NextHandleValue = MINIMUM_HANDLE_VALUE;
  173. NextHandleIndex = 0;
  174. MapArrayLength = 0;
  175. LeaveCriticalSection(&HandleMapCritSec);
  176. //
  177. // delete the critical section
  178. //
  179. DeleteCriticalSection(&HandleMapCritSec);
  180. }
  181. DEBUG_LEAVE(0);
  182. }
  183. DWORD
  184. AllocateHandle(
  185. IN LPVOID Address,
  186. OUT LPHINTERNET lpHandle
  187. )
  188. /*++
  189. Routine Description:
  190. Generic handle allocator function which generates a unique handle value for
  191. any object. The handle value is simply a number, slightly massaged to give a
  192. value that can be easily differentiated from other Win32 handle ranges (for
  193. debugging purposes mainly, and also to protect against illegal use of
  194. handles (such as treating as a pointer and dereferencing it)).
  195. The range of handles are kept in a bitmap, composed of DWORDs. The next
  196. allocated handle is simply the index of the next free bit in the map. The
  197. map is extended if we run out of handles (up to 16K-1 handles (== 2K bytes)).
  198. If the map needs to be extended we don't go to the trouble to reduce it
  199. again. For the sake of 2K bytes max (currently), its not worth the effort.
  200. This function does not rely on knowing the type of object for which the
  201. handle is being generated, and only requires serialization via a critical
  202. section.
  203. This function can increase the values of these variables:
  204. NextHandleMapDword
  205. NextHandleMapBit
  206. NextHandleMapBitIndex
  207. NextHandleValue
  208. NextHandleIndex
  209. Arguments:
  210. Address - the (object address) value which will be associated with the
  211. returned handle
  212. lpHandle - place to return the allocated handle
  213. Return Value:
  214. DWORD
  215. Success - ERROR_SUCCESS
  216. Failure - ERROR_INTERNET_OUT_OF_HANDLES
  217. 16K-1 (currently) handles are outstanding!
  218. ERROR_NOT_ENOUGH_MEMORY etc.
  219. problems with Win32 memory/heap management?
  220. --*/
  221. {
  222. DEBUG_ENTER((DBG_HANDLE,
  223. Dword,
  224. "AllocateHandle",
  225. "%#x, %#x",
  226. Address,
  227. lpHandle
  228. ));
  229. DWORD error;
  230. //
  231. // can't associate a NULL address with the generated handle
  232. //
  233. INET_ASSERT(Address != NULL);
  234. //
  235. // default returned handle
  236. //
  237. *lpHandle = NULL;
  238. //
  239. // in case this function is being called before we have initialized this
  240. // module, or after we have terminated it, return an error
  241. //
  242. if (!Initialized) {
  243. error = ERROR_INTERNET_SHUTDOWN;
  244. goto quit;
  245. }
  246. error = ERROR_INTERNET_OUT_OF_HANDLES;
  247. EnterCriticalSection(&HandleMapCritSec);
  248. if (HandleMap == NULL) {
  249. //
  250. // don't ever expect this?
  251. //
  252. INET_ASSERT(FALSE);
  253. error = ERROR_INTERNET_INTERNAL_ERROR;
  254. goto unlock_exit;
  255. }
  256. while (NextHandleMapDword != MAXIMUM_DWORD_INDEX) {
  257. //
  258. // if we reached the end of the map the last time, we must reallocate
  259. //
  260. if (NextHandleMapDword == HandleMapLength) {
  261. HLOCAL newHandleMap;
  262. newHandleMap = REALLOCATE_MEMORY((HLOCAL)HandleMap,
  263. (HandleMapLength + HANDLE_MAP_INCREMENT)
  264. * sizeof(DWORD),
  265. LMEM_MOVEABLE | LMEM_ZEROINIT
  266. );
  267. HLOCAL newMapArray;
  268. newMapArray = REALLOCATE_MEMORY((HLOCAL)MapArray,
  269. (HandleMapLength + HANDLE_MAP_INCREMENT)
  270. * BITS_IN_DWORD
  271. * sizeof(LPVOID),
  272. LMEM_MOVEABLE | LMEM_ZEROINIT
  273. );
  274. if ((newHandleMap != NULL) && (newMapArray != NULL)) {
  275. HandleMapLength += HANDLE_MAP_INCREMENT;
  276. HandleMap = (LPDWORD)newHandleMap;
  277. MapArrayLength += HANDLE_MAP_INCREMENT * BITS_IN_DWORD;
  278. MapArray = (LPVOID *)newMapArray;
  279. DEBUG_PRINT(HANDLE,
  280. INFO,
  281. ("re-allocated %d DWORDs: HandleMap = %#x MapArray = %#x\n",
  282. HandleMapLength,
  283. HandleMap,
  284. MapArray
  285. ));
  286. } else {
  287. error = GetLastError();
  288. DEBUG_PRINT(HANDLE,
  289. ERROR,
  290. ("REALLOCATE_MEMORY() returns %d\n",
  291. error
  292. ));
  293. break;
  294. }
  295. } else if (NextHandleValue <= MAXIMUM_HANDLE_VALUE) {
  296. HandleMap[NextHandleMapDword] |= NextHandleMapBit;
  297. //
  298. // first handle value returned is 0x00cc0004
  299. //
  300. DEBUG_PRINT(HANDLE,
  301. INFO,
  302. ("handle = %#x, index = %d\n",
  303. NextHandleValue,
  304. NextHandleIndex
  305. ));
  306. *lpHandle = (HINTERNET)(DWORD_PTR)NextHandleValue;
  307. //
  308. // store it in the map array at the specified index
  309. //
  310. INET_ASSERT(MapArray[NextHandleIndex] == NULL);
  311. MapArray[NextHandleIndex] = Address;
  312. error = ERROR_SUCCESS;
  313. //
  314. // find the next available bit for the next caller. Search up
  315. // to the end of the currently allocated map. If we don't find
  316. // it, the next caller will attempt to allocate a new DWORD
  317. // (unless a lower handle gets freed meantime)
  318. //
  319. while (NextHandleMapDword < HandleMapLength) {
  320. if (HandleMap[NextHandleMapDword] != FULL_DWORD) {
  321. while (HandleMap[NextHandleMapDword] & NextHandleMapBit) {
  322. NextHandleMapBit <<= 1;
  323. ++NextHandleMapBitIndex;
  324. NextHandleValue += HANDLE_INCREMENT;
  325. ++NextHandleIndex;
  326. }
  327. } else {
  328. NextHandleMapBit = 0;
  329. }
  330. if (NextHandleMapBit != 0) {
  331. break;
  332. } else {
  333. //
  334. // reached the end of a DWORD. Start the next
  335. //
  336. ++NextHandleMapDword;
  337. NextHandleMapBit = 1;
  338. NextHandleMapBitIndex = 0;
  339. //
  340. // recalculate the next handle value
  341. //
  342. NextHandleValue = NEXT_HANDLE_VALUE(NextHandleMapDword,
  343. NextHandleMapBitIndex
  344. );
  345. //
  346. // and map array index
  347. //
  348. NextHandleIndex = NextHandleMapDword * BITS_IN_DWORD;
  349. }
  350. }
  351. break;
  352. } else {
  353. //
  354. // reached maximum handle value - return error
  355. //
  356. break;
  357. }
  358. }
  359. unlock_exit:
  360. LeaveCriticalSection(&HandleMapCritSec);
  361. quit:
  362. DEBUG_LEAVE(error);
  363. return error;
  364. }
  365. DWORD
  366. FreeHandle(
  367. IN HINTERNET Handle
  368. )
  369. /*++
  370. Routine Description:
  371. The obverse function to AllocateHandle. Frees up a previously allocated
  372. handle value. If this handle has a lower index than the currently selected
  373. next index (Dword and Bit) then the next index is modified
  374. This function can reduce the values of these variables:
  375. NextHandleMapDword
  376. NextHandleMapBit
  377. NextHandleMapBitIndex
  378. NextHandleValue
  379. NextHandleIndex
  380. Arguments:
  381. Handle - handle value previously allocated via AllocateHandle
  382. Return Value:
  383. DWORD
  384. Success - ERROR_SUCCESS
  385. Failure - ERROR_INVALID_HANDLE
  386. We don't think this handle was generated by AllocateHandle
  387. or the corresponding bit in the map is already 0
  388. --*/
  389. {
  390. DEBUG_ENTER((DBG_HANDLE,
  391. Dword,
  392. "FreeHandle",
  393. "%#x",
  394. Handle
  395. ));
  396. DWORD error;
  397. //
  398. // ensure that we are in the correct state
  399. //
  400. if (!Initialized) {
  401. error = ERROR_INTERNET_SHUTDOWN;
  402. goto quit;
  403. }
  404. error = ERROR_INVALID_HANDLE;
  405. //
  406. // error if 0x00cc0000 > Handle > 0x00ccfffc
  407. //
  408. if ((PtrToUlong(Handle) < MINIMUM_HANDLE_VALUE)
  409. || (PtrToUlong(Handle) > MAXIMUM_HANDLE_VALUE)) {
  410. goto quit;
  411. }
  412. //
  413. // get the map DWORD index and bit mask from the handle
  414. //
  415. DWORD index;
  416. index = (PtrToUlong(Handle) - MINIMUM_HANDLE_VALUE) / (BITS_IN_DWORD * HANDLE_INCREMENT);
  417. DWORD bit;
  418. bit = 1 << (((PtrToUlong(Handle) - MINIMUM_HANDLE_VALUE) / HANDLE_INCREMENT) & (BITS_IN_DWORD - 1));
  419. DWORD mapIndex;
  420. mapIndex = (PtrToUlong(Handle) - MINIMUM_HANDLE_VALUE) / HANDLE_INCREMENT;
  421. EnterCriticalSection(&HandleMapCritSec);
  422. //
  423. // the index may be in range, but greater than the currently allocated
  424. // map length, in which case its an error
  425. //
  426. if (index < HandleMapLength) {
  427. if (HandleMap != NULL) {
  428. if (HandleMap[index] & bit) {
  429. BOOL recalc = FALSE;
  430. DEBUG_PRINT(HANDLE,
  431. INFO,
  432. ("handle = %#x, index = %d, address = %#x\n",
  433. Handle,
  434. mapIndex,
  435. MapArray[mapIndex]
  436. ));
  437. HandleMap[index] &= ~bit;
  438. MapArray[mapIndex] = NULL;
  439. error = ERROR_SUCCESS;
  440. //
  441. // if we have cleared a bit lower in the bitmap than the current
  442. // index and bit indicators, then reset the indicators to the
  443. // new position
  444. //
  445. if (index < NextHandleMapDword) {
  446. //
  447. // new DWORD is lower than current: change all variables
  448. // to those for this handle
  449. //
  450. NextHandleMapDword = index;
  451. recalc = TRUE;
  452. } else if ((index == NextHandleMapDword) && (bit < NextHandleMapBit)) {
  453. //
  454. // same DWORD index, lower bit position
  455. //
  456. recalc = TRUE;
  457. }
  458. if (recalc) {
  459. NextHandleMapBit = bit;
  460. NextHandleMapBitIndex = BitToIndex(bit);
  461. //
  462. // recalculate the next handle value
  463. //
  464. NextHandleValue = NEXT_HANDLE_VALUE(NextHandleMapDword,
  465. NextHandleMapBitIndex
  466. );
  467. //
  468. // and map array index
  469. //
  470. NextHandleIndex = (NextHandleMapDword * BITS_IN_DWORD)
  471. + NextHandleMapBitIndex;
  472. }
  473. } else {
  474. DEBUG_PRINT(HANDLE,
  475. ERROR,
  476. ("Handle = %#x. HandleMap[%d].%#x not set\n",
  477. Handle,
  478. index,
  479. bit
  480. ));
  481. }
  482. } else {
  483. //
  484. // don't ever expect this to happen
  485. //
  486. error = ERROR_INTERNET_INTERNAL_ERROR;
  487. INET_ASSERT(FALSE);
  488. }
  489. } else {
  490. DEBUG_PRINT(HANDLE,
  491. ERROR,
  492. ("Handle = %#x, index = %d, HandleMapLength = %d\n",
  493. Handle,
  494. index,
  495. HandleMapLength
  496. ));
  497. }
  498. LeaveCriticalSection(&HandleMapCritSec);
  499. quit:
  500. DEBUG_LEAVE(error);
  501. return error;
  502. }
  503. DWORD
  504. MapHandleToAddress(
  505. IN HINTERNET Handle,
  506. OUT LPVOID * lpAddress,
  507. IN BOOL Invalidate
  508. )
  509. /*++
  510. Routine Description:
  511. Given a handle, retrieve its associated address from the map array. The
  512. handle object represented by Handle is referenced
  513. Assumes: 1. only HINTERNETs visible at the API are presented to this
  514. function. Even though we AllocateHandle() for arbitrary
  515. objects (e.g. gopher views) we never map their addresses
  516. Arguments:
  517. Handle - handle value generated by AllocateHandle()
  518. lpAddress - place to store mapped address. If the handle has been closed
  519. and unmapped, NULL is returned. If the handle is still
  520. mapped, even though it has been invalidated, its address will
  521. be returned, and its reference count incremented
  522. Invalidate - TRUE if we are invalidating this handle
  523. Return Value:
  524. LPVOID
  525. Success - ERROR_SUCCESS
  526. Failure - ERROR_INVALID_HANDLE
  527. if *lpAddress == NULL then the handle has been closed and
  528. unmapped, else it is still mapped, but invalidated. In
  529. this case, we incremented the reference count
  530. --*/
  531. {
  532. DEBUG_ENTER((DBG_HANDLE,
  533. Dword,
  534. "MapHandleToAddress",
  535. "%#x, %#x, %B",
  536. Handle,
  537. lpAddress,
  538. Invalidate
  539. ));
  540. LPVOID address = NULL;
  541. DWORD error = ERROR_INVALID_HANDLE;
  542. //
  543. // error if 0x00cc0000 > Handle > 0x00ccfffc
  544. //
  545. if ((PtrToUlong(Handle) >= MINIMUM_HANDLE_VALUE)
  546. && (PtrToUlong(Handle) <= MAXIMUM_HANDLE_VALUE)
  547. && !InDllCleanup) {
  548. DWORD index = (PtrToUlong(Handle) - MINIMUM_HANDLE_VALUE) / HANDLE_INCREMENT;
  549. //
  550. // the caller could have supplied a value which has the correct range
  551. // but may not yet have been generated, causing us to index past the
  552. // end of the array
  553. //
  554. if (index < MapArrayLength) {
  555. //
  556. // we have to acquire the critical section in case another thread
  557. // is reallocating the array
  558. //
  559. EnterCriticalSection(&HandleMapCritSec);
  560. address = MapArray[index];
  561. DEBUG_PRINT(HANDLE,
  562. INFO,
  563. ("Handle %#x mapped to address %#x\n",
  564. Handle,
  565. address
  566. ));
  567. if (address != NULL) {
  568. //
  569. // although we store addresses of arbitrary structures (e.g.
  570. // FTP_SESSION_INFO), we are only calling this function to map
  571. // pseudo-handles to object addresses at the API. Therefore it
  572. // should be safe to assume that the pointer references a handle
  573. // object
  574. // However, there's nothing to stop an app passing in a random
  575. // handle value that just happens to map to an FTP or gopher
  576. // session or gopher view, and since we don't want to treat that
  577. // as a handle object, we must make this test full-time
  578. //
  579. if (((HANDLE_OBJECT *)address)->IsValid(TypeWildHandle) == ERROR_SUCCESS) {
  580. //
  581. // this is also a very good time to increment the reference
  582. // count. We are using the fact that we are serialized on the
  583. // handle map critical section here. If Reference() returns
  584. // ERROR_INVALID_HANDLE then the handle object has been
  585. // invalidated, but its reference count will have been
  586. // incremented. The caller should perform as little work as
  587. // necessary and get out.
  588. //
  589. // If Refrerence() returns ERROR_ACCESS_DENIED, then the object
  590. // is being destroyed (refcount already went to zero).
  591. //
  592. // If the reference count is incremented to 1 then there is
  593. // another thread waiting to finish deleting this handle. It
  594. // is virtually deleted, and if we return its address, the
  595. // caller will have a deleted object
  596. //
  597. if (((HANDLE_OBJECT *)address)->ReferenceCount() == 0) {
  598. DEBUG_PRINT(HANDLE,
  599. ERROR,
  600. ("handle %#x [%#x] about to be deleted\n",
  601. Handle,
  602. address
  603. ));
  604. address = NULL;
  605. } else {
  606. error = ((HANDLE_OBJECT *)address)->Reference();
  607. if (error == ERROR_SUCCESS) {
  608. if (Invalidate) {
  609. //
  610. // we were called from a handle close API.
  611. // Subsequent API calls will discover that the
  612. // handle is already invalidated and will quit
  613. //
  614. ((HANDLE_OBJECT *)address)->Invalidate();
  615. }
  616. } else if (error == ERROR_ACCESS_DENIED) {
  617. //
  618. // if we get ERROR_ACCESS_DENIED, this means that the object is
  619. // being destructed, so we *have* to return NULL.
  620. //
  621. DEBUG_PRINT(HANDLE,
  622. ERROR,
  623. ("Reference() failed - handle %#x [%#x] about to be deleted\n",
  624. Handle,
  625. address
  626. ));
  627. address = NULL;
  628. } else {
  629. DEBUG_PRINT(HANDLE,
  630. ERROR,
  631. ("Reference() returns %d\n",
  632. error
  633. ));
  634. //
  635. // if invalid and reference count already zero, we
  636. // didn't increment ref count: handle already being
  637. // deleted
  638. //
  639. if (((HANDLE_OBJECT *)address)->ReferenceCount() == 0) {
  640. address = NULL;
  641. }
  642. }
  643. }
  644. } else {
  645. //
  646. // we still want to know about it in debug version
  647. //
  648. DEBUG_PRINT(HANDLE,
  649. ERROR,
  650. ("invalid handle object: %#x [%#x]\n",
  651. Handle,
  652. address
  653. ));
  654. IF_DEBUG(INVALID_HANDLES) {
  655. //INET_ASSERT(FALSE);
  656. }
  657. }
  658. } else {
  659. //
  660. // lets also catch this one (NULL address)
  661. //
  662. DEBUG_PRINT(HANDLE,
  663. ERROR,
  664. ("NULL handle: %#x\n",
  665. Handle
  666. ));
  667. IF_DEBUG(INVALID_HANDLES) {
  668. //INET_ASSERT(FALSE);
  669. }
  670. }
  671. LeaveCriticalSection(&HandleMapCritSec);
  672. }
  673. } else if (InDllCleanup) {
  674. error = ERROR_INTERNET_SHUTDOWN;
  675. } else {
  676. DEBUG_PRINT(HANDLE,
  677. ERROR,
  678. ("bad handle value: %#x\n",
  679. Handle
  680. ));
  681. IF_DEBUG(INVALID_HANDLES) {
  682. //INET_ASSERT(FALSE);
  683. }
  684. }
  685. *lpAddress = address;
  686. DEBUG_LEAVE(error);
  687. return error;
  688. }
  689. DWORD
  690. DereferenceObject(
  691. IN LPVOID lpObject
  692. )
  693. /*++
  694. Routine Description:
  695. Undoes the reference added to the handle object by MapHandleToAddress(). May
  696. result in the handle object being deleted
  697. Arguments:
  698. lpObject - address of object to dereference. This MUST be the mapped
  699. object address as returned by MapHandleToAddress()
  700. Return Value:
  701. DWORD
  702. Success - ERROR_SUCCESS
  703. The handle object was destroyed
  704. Failure - ERROR_INVALID_HANDLE
  705. The object was not a valid handle
  706. ERROR_INTERNET_HANDLE_EXISTS
  707. The handle is still alive
  708. --*/
  709. {
  710. DEBUG_ENTER((DBG_HANDLE,
  711. Dword,
  712. "DereferenceObject",
  713. "%#x",
  714. lpObject
  715. ));
  716. INET_ASSERT(lpObject != NULL);
  717. HANDLE_OBJECT * object = (HANDLE_OBJECT *)lpObject;
  718. DWORD error = object->IsValid(TypeWildHandle);
  719. if (error == ERROR_SUCCESS) {
  720. if (!object->Dereference()) {
  721. error = ERROR_INTERNET_HANDLE_EXISTS;
  722. }
  723. } else {
  724. //
  725. // IsValid() should never return an error if the reference counts
  726. // are correct
  727. //
  728. INET_ASSERT(FALSE);
  729. }
  730. DEBUG_LEAVE(error);
  731. return error;
  732. }
  733. PRIVATE
  734. inline
  735. DWORD
  736. BitToIndex(
  737. IN DWORD Bit
  738. )
  739. /*++
  740. Routine Description:
  741. Returns the index of the first bit set in a DWORD
  742. Arguments:
  743. Bit - bitmap
  744. Return Value:
  745. DWORD - 0..(BITS_IN_DWORD - 1) if bit found, else BITS_IN_DWORD
  746. --*/
  747. {
  748. if (Bit == 0) {
  749. return BITS_IN_DWORD;
  750. } else {
  751. DWORD index;
  752. DWORD testBit;
  753. for (index = 0, testBit = 1; !(Bit & testBit); ++index, testBit <<= 1) {
  754. ;
  755. }
  756. return index;
  757. }
  758. }