Fixed-Size Memory Pool with alignment
first of all you hold Next Block Index in allocated block. but you not use it . Next Block Index (which is implicit pointer to next free block) used only in free block. as result you not need Next Block Index and Padding in allocated block. the Object Data must begin at begin of block. this give serious optimization by memory size and simplify code. 

also instead index (implicit pointer) better use explicit pointer to next free block (or 0 if no more free blocks). this yet more simplify code.

next your code is not thread safe and not design to allocate/free in concurrent from multiple threads. however this is very easy can be implemented.

finally CalculatePadding simply wrong. impossible calculate align of object by it size. different objects with same size, can have different align.

first we need implement structure describes an entry in a block linked list:

struct LE 
{
    LE* next;

    static void Push(LE* head, LE* entry)
    {
        LE *_next = head-&gt;next, *next;

        for( ; ; _next = next)
        {
            entry-&gt;next = _next;

            next = (LE*)InterlockedCompareExchangePointerRelease(
                (void**)&amp;head-&gt;next, entry, _next);

            if (next == _next)
            {
                return;
            }
        }
    }

    static LE* Pop(LE* head)
    {
        LE* _entry = head-&gt;next, *entry;

        for ( ;_entry;_entry = entry)
        {
            entry = (LE*)InterlockedCompareExchangePointerAcquire(
                (void**)&amp;head-&gt;next, _entry-&gt;next, _entry);

            if (entry == _entry)
            {
                return entry;
            }
        }
        return 0;
    }
};


we put this LE at begin of every free block. this will pointer to next free block (or 0 if this is the last free block). instead of index. with this we can allocate block by LE::Pop and free block by LE::Push.

#define DEBUG_CHECK 1

class FixedSizeMemoryPool
{
    LE m_head;
    void* m_buf;
    void (__stdcall * m_Free)(void*);
#if DEBUG_CHECK
    ULONG m_count;
#endif

public:

    FixedSizeMemoryPool() { m_buf = 0; }

    ~FixedSizeMemoryPool();

    void* Alloc()
    {
        return LE::Pop(&amp;m_head);
    }

    void Free(void* data)
    {
        LE::Push(&amp;m_head, reinterpret_cast&lt;LE*&gt;(data));
    }

    bool Create(ULONG objectSize, ULONG nObjects, 
        void* (__stdcall* XxxAllocate)(ULONG), 
        void (__stdcall * XxxFree)(void*));
};

FixedSizeMemoryPool::~FixedSizeMemoryPool()
{
    if (m_buf) 
    {
#if DEBUG_CHECK
        ULONG count = m_count;

        if (LE* next = m_head.next)
        {
            do 
            {
                --count;
            } while (next = next-&gt;next);
        }

        if (count)
        {
            __debugbreak();
        }
#endif
        m_Free(m_buf);
    }
}

bool FixedSizeMemoryPool::Create(ULONG objectSize, ULONG nObjects, 
                                 void* (__stdcall* XxxAllocate)(ULONG),
                                 void (__stdcall * XxxFree)(void*))
{
    if (!objectSize || !nObjects || objectSize &gt; MAXLONG)
    {
        return false;
    }

    if (objectSize &lt; sizeof(LE))
    {
        // we need space for LE in block
        objectSize = sizeof(LE);
    }

    // must be aligned how minimum as LE
    objectSize = (objectSize + alignof(LE) - 1) &amp; ~(alignof(LE) - 1);

    ULONGLONG size = (ULONGLONG)objectSize * (ULONGLONG)nObjects;

    if (size &gt; MAXULONG)
    {
        return false;
    }

    union {
        void* buf;
        char* pb;
        LE* entry;
    };

    if (buf = XxxAllocate((ULONG)size))
    {
#if DEBUG_CHECK
        m_count = nObjects;
#endif
        m_buf = buf;
        m_Free = XxxFree;
        LE* next = 0;
        do 
        {
            entry-&gt;next = next, next = entry;
        } while (pb += objectSize, --nObjects);

        m_head.next = next;

        return true;
    }

    return false;
}


note that client of FixedSizeMemoryPool must provide itself routines for allocate/free block of memory, where pool will be implemented. this give ability implement different memory types. also if objects(pool blocks) require special align (more than default allocation align), user implement this in allocate routine. say if we not need extended alignment for object, we can use 

void* __stdcall XxxAlocate(ULONG s)
{
    return new char[s];
}

void __stdcall XxxFree(void* data)
{
    delete [] data;
}


if we need extended alignment - say want 64byte align for blocks in pool:

void* __stdcall XxxAlocate(ULONG s)
{
    return _aligned_malloc(s, 64);
}

void __stdcall XxxFree(void* data)
{
    _aligned_free(data);
}


and of course size of object (block) must be multiple of object(block) align