| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ANDROID_USB_NEW_DELETE_H__ |
| #define ANDROID_USB_NEW_DELETE_H__ |
| /** \file |
| This file consists implementations of our 'new' and 'delete' operators |
| */ |
| |
| #include "android_usb_pool_tags.h" |
| |
| /** \brief Checks if given pool type is one of NonPaged pool kinds. |
| |
| All numeric values for all NonPaged pool types are even numbers while all |
| numeric values for all PagedPool types are odd numbers (see definition of |
| POOL_TYPE enum). So this routine utilizes this to see whether given pool |
| type is one of NonPaged pool kinds. This routine can be called at any IRQL. |
| @param pool_type[in] Pool type |
| @return True if pool type is one of NonPaged pool types, false otherwise |
| */ |
| __forceinline bool IsPoolNonPaged(POOL_TYPE pool_type) { |
| return (0 == (pool_type & 0x1)); |
| } |
| |
| /** @name Operators new and delete |
| |
| In Kernel Mode development each memory allocation must specify type of the |
| pool from which memory should be allocated, usualy PagedPool or NonPagedPool. |
| Because of that "traditional" operator 'new' that takes only one parameter |
| (memory size) is not good so we modify that operator by adding two more |
| parameters: pool type and memory tag (last one is optional but highly |
| encouraged). To prevent from mistakes, traditional operator 'new' is also |
| defined. It will allocate requested number of bytes from NonPagedPool with |
| default memory tag but it will always assert on checked (debug) builds. |
| Since there is no infrastructure for C++ exceptions in Kernel Mode we are |
| not using them to report memory allocation error. So, on failure operators |
| 'new' are returning NULL instead of throwing an exception. |
| */ |
| ///@{ |
| |
| /** \brief Main operator new |
| |
| This is the main operator new that allocates specified number of bytes from |
| the specified pool and assigns a custom tag to the allocated memory. |
| Inherits IRQL restrictions for ExAllocatePoolWithTag (see the DDK doc). |
| @param size[in] Number of bytes to allocate. |
| @param pool_type[in] Type of the pool to allocate from. |
| @param pool_tag[in] A tag to attach to the allocated memory. Since utilities |
| that display tags use their ASCII representations it's advisable to |
| use tag values that are ASCII symbols, f.i. 'ATag'. Note that due to |
| inversion of bytes in stored ULONG value, to read 'ATag' in the tag |
| displaying utility, the actual value passed to operator 'new' must be |
| 'gaTA' |
| @return Pointer to allocated memory on success, NULL on error. |
| */ |
| __forceinline void* __cdecl operator new(size_t size, |
| POOL_TYPE pool_type, |
| ULONG pool_tag) { |
| ASSERT((pool_type < MaxPoolType) && (0 != size)); |
| // Enforce IRQL restriction check. |
| ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL)); |
| return size ? ExAllocatePoolWithTag(pool_type, |
| static_cast<ULONG>(size), |
| pool_tag) : |
| NULL; |
| } |
| |
| /** \brief |
| Short operator new that attaches a default tag to the allocated memory. |
| |
| This version of operator new allocates specified number of bytes from the |
| specified pool and assigns a default tag (GANDR_POOL_TAG_DEFAULT) to the |
| allocated memory. Inherits IRQL restrictions for ExAllocatePoolWithTag. |
| @param size[in] Number of bytes to allocate. |
| @param pool_type[in] Type of the pool to allocate from. |
| @return Pointer to allocated memory on success, NULL on error. |
| */ |
| __forceinline void* __cdecl operator new(size_t size, POOL_TYPE pool_type) { |
| ASSERT((pool_type < MaxPoolType) && (0 != size)); |
| // Enforce IRQL restriction check. |
| ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL)); |
| return size ? ExAllocatePoolWithTag(pool_type, |
| static_cast<ULONG>(size), |
| GANDR_POOL_TAG_DEFAULT) : |
| NULL; |
| } |
| |
| /** \brief Traditional operator new that should never be used. |
| |
| Using of this version of operator 'new' is prohibited in Kernel Mode |
| development. For the sake of safety it is implemented though to allocate |
| requested number of bytes from the NonPagedPool and attach default tag |
| to the allocated memory. It will assert on checked (debug) builds. |
| Inherits IRQL restrictions for ExAllocatePoolWithTag. |
| @param size[in] Number of bytes to allocate. |
| @return Pointer to memory allocated from NonPagedPool on success or NULL on |
| error. |
| */ |
| __forceinline void* __cdecl operator new(size_t size) { |
| ASSERTMSG("\n!!! Using of operator new(size_t size) is detected!\n" |
| "This is illegal in our driver C++ development environment to use " |
| "this version of operator 'new'. Please switch to\n" |
| "new(size_t size, POOL_TYPE pool_type) or " |
| "new(size_t size, POOL_TYPE pool_type, ULONG pool_tag) ASAP!!!\n", |
| false); |
| ASSERT(0 != size); |
| return size ? ExAllocatePoolWithTag(NonPagedPool, |
| static_cast<ULONG>(size), |
| GANDR_POOL_TAG_DEFAULT) : |
| NULL; |
| } |
| |
| /** \brief Operator delete. |
| |
| Frees memory allocated by 'new' operator. |
| @param pointer[in] Memory to free. If this parameter is NULL operator does |
| nothing but asserts on checked build. Inherits IRQL restrictions |
| for ExFreePool. |
| */ |
| __forceinline void __cdecl operator delete(void* pointer) { |
| ASSERT(NULL != pointer); |
| if (NULL != pointer) |
| ExFreePool(pointer); |
| } |
| |
| /** \brief Operator delete for arrays. |
| |
| Frees memory allocated by 'new' operator. |
| @param pointer[in] Memory to free. If this parameter is NULL operator does |
| nothing but asserts on checked build. Inherits IRQL restrictions |
| for ExFreePool. |
| */ |
| __forceinline void __cdecl operator delete[](void* pointer) { |
| ASSERT(NULL != pointer); |
| if (NULL != pointer) |
| ExFreePool(pointer); |
| } |
| |
| ///@} |
| |
| #endif // ANDROID_USB_NEW_DELETE_H__ |