/*++ Copyright (c) 1994 Microsoft Corporation Module Name: handle.cxx Abstract: Contains functions to allocate and deallocate handle values Contents: HandleInitialize HandleTerminate AllocateHandle FreeHandle MapHandleToAddress DereferenceObject Author: Richard L Firth (rfirth) 31-Oct-1994 Revision History: 12-Mar-2001 rajeevd Gutted 11-Jan-1996 rfirth Use fixed memory instead of moveable (Win95 has a bug w/ LocalUnlock) 31-Oct-1994 rfirth Created --*/ #include // // private prototypes // DEBUG_ONLY (PRIVATE void LogHandleClassSizes(); ) // // functions // DWORD HandleInitialize (VOID) { DEBUG_ONLY (LogHandleClassSizes(); ) return ERROR_SUCCESS; } VOID HandleTerminate(VOID) { // nothing to do } DWORD AllocateHandle (IN LPVOID Address,OUT LPHINTERNET lpHandle) { HINTERNET Handle = (HINTERNET) Address; *lpHandle = Handle; return ERROR_SUCCESS; } DWORD FreeHandle(IN HINTERNET Handle) { return ERROR_SUCCESS; } DWORD MapHandleToAddress( IN HINTERNET Handle, OUT LPVOID * lpAddress, IN BOOL Invalidate ) /*++ Routine Description: The handle object represented by Handle is referenced Assumes: 1. only HINTERNETs visible at the API are presented to this function. Arguments: Handle - handle value generated by AllocateHandle() lpAddress - place to store mapped address. If the handle has been closed and unmapped, NULL is returned. If the handle is still mapped, even though it has been invalidated, its address will be returned, and its reference count incremented Invalidate - TRUE if we are invalidating this handle Return Value: LPVOID Success - ERROR_SUCCESS Failure - ERROR_INVALID_HANDLE if *lpAddress == NULL then the handle has been closed and unmapped, else it is still mapped, but invalidated. In this case, we incremented the reference count --*/ { DEBUG_ENTER((DBG_HANDLE, Dword, "MapHandleToAddress", "%#x, %#x, %B", Handle, lpAddress, Invalidate )); DWORD error; // Cast the handle to an address and validate LPVOID address = (LPVOID) Handle; if (address) { error = ((HANDLE_OBJECT *)address)->IsValid(TypeWildHandle); } else { error = ERROR_INVALID_HANDLE; } if (error != ERROR_SUCCESS) { DEBUG_PRINT(HANDLE, ERROR, ("invalid handle object: %#x [%#x]\n", Handle, address )); error = ERROR_INVALID_HANDLE; address = NULL; goto quit; } // Attempt to increment the reference count on the handle. error = ((HANDLE_OBJECT *)address)->Reference(); DEBUG_PRINT(HANDLE, ERROR, ("Reference() returns %d\n", error)); switch (error) { case ERROR_SUCCESS: // handle was refcounted but is not tombstoned if (Invalidate) { // we were called from a handle close API. // Subsequent API calls will discover that the // handle is already invalidated and will quit ((HANDLE_OBJECT *)address)->Invalidate(); } break; case ERROR_INVALID_HANDLE: // handle was refcounted but was tombstoned. break; default: INET_ASSERT (false); // intentional fall through case ERROR_ACCESS_DENIED: // handle is being destroyed DEBUG_PRINT(HANDLE, ERROR, ("Reference() failed - handle %#x [%#x] about to be deleted\n", Handle, address )); error = ERROR_INVALID_HANDLE; address = NULL; break; } quit: *lpAddress = address; DEBUG_LEAVE(error); return error; } DWORD DereferenceObject( IN LPVOID lpObject ) /*++ Routine Description: Undoes the reference added to the handle object by MapHandleToAddress(). May result in the handle object being deleted Arguments: lpObject - address of object to dereference. This MUST be the mapped object address as returned by MapHandleToAddress() Return Value: DWORD Success - ERROR_SUCCESS The handle object was destroyed Failure - ERROR_INVALID_HANDLE The object was not a valid handle --*/ { DEBUG_ENTER((DBG_HANDLE, Dword, "DereferenceObject", "%#x", lpObject )); INET_ASSERT(lpObject != NULL); HANDLE_OBJECT * object = (HANDLE_OBJECT *)lpObject; DWORD error = object->IsValid(TypeWildHandle); // Serialize with MapHandleToAddress if (error == ERROR_SUCCESS) { object->Dereference(); } else { // // IsValid() should never return an error if the reference counts // are correct // INET_ASSERT(FALSE); } DEBUG_LEAVE(error); return error; } #if INET_DEBUG PRIVATE void LogHandleClassSizes() { DEBUG_PRINT(HANDLE, INFO, ("sizeof(HANDLE_OBJECT) = %d bytes\n", sizeof(HANDLE_OBJECT) )); DEBUG_PRINT(HANDLE, INFO, ("sizeof(INTERNET_HANDLE_OBJECT) = %d bytes\n", sizeof(INTERNET_HANDLE_OBJECT) )); DEBUG_PRINT(HANDLE, INFO, ("sizeof(INTERNET_CONNECT_HANDLE_OBJECT) = %d bytes\n", sizeof(INTERNET_CONNECT_HANDLE_OBJECT) )); DEBUG_PRINT(HANDLE, INFO, ("sizeof(HTTP_REQUEST_HANDLE_OBJECT) = %d bytes\n", sizeof(HTTP_REQUEST_HANDLE_OBJECT) )); } #endif