You can get a list of all exported functions just by reading the PE headers. But, that won't give you any function names, or expected arguments lists (*), and it won't give you any functions that are internal to the DLL.
In the general case, the only thing you can do is start with exported functions, disassemble from there, follow
jmps, and mark everything that's
called as a new function and process it in the same way that you process the exported stuff. This is basically what IDA does.
As C0000022L mentioned, this is in no way trivial, especially with C++ methods that are never called directly, but only through vtable pointers, which is why even IDA gets this kind of stuff mostly right, but not completely right.
Ida has another feature though, named FLIRT - it has a database that has signatures of standard library functions for many different compilers. Which is why it can, often, identify standard library function names. But as far as i know, this is a second pass thing; first IDA identifies functions by being called from somewhere, then tries to assign names to those functions using FLIRT. Of course, this helps with standard library functions ONLY, and building this kind of database certainly needs a lot of work as well.
(*) If you're lucky, functions will be exported by name, and if you're very lucky, and the DLL was written in C++, the function name will include the signature. So there are cases when the export list is valuable. But this isn't the generic case, when a function might just be exported by ordinal.