@djhayman:
Unfortunately "best" is open to many different interpretations, and some programmers think that it is best for the people who use their library not to worry about initialisation and cleanup, and this is done in DllMain. In some ways you can understand this because if a library has some form of persistant state and the developer forgets to signal to that library that it is shutting down, then that persistant state may become corrupt.
Well anyway, I agree with you, the executable knows better about the state of the program. It is also documented in the DllMain documentation that when the process is terminating, all threads besides the one you are currently in has been terminated. It is also documented that you shouldn't do anything too complex in DllMain, like communicate with other threads. But people don't read, people don't listen, they just do what they want and then get confused when the program crashes.
@Neil:
What motivated you to ask that question? Since what you get back from CreateThreadpool is a pointer to a user mode structure, can you give any guarantee that, after you close the thread pool, it doesn't clean up the memory right away? Accessing anything after you said you don't want to use it any more is a bug.