As Rebecca1 says: follow the paths! Can you identify which branches of the code have been tested, which have not? This is usually done on an 'instrumented' version of the AUT which will report each branch and each code line your tests take as they execute. The areas not covered are where you need to think about creating new tests for. It is not possible to get 100% coverage, because some error conditions are really hard to have occur on demand.
You could think about doing code reviews, ala, Michael Fagan.
For whatever it is worth you may think of white box vs. black box testing as a paradigm shift. As a black box tester you were approaching the code from the outside based on the functions that you expect the code to perform. As a white box tester you will approach the code from the inside based on what has been coded. While this helps you find bugs related to the technical implementation you may not find bugs related to failing to meet the specifications.
Typically white box testing focuses on smaller units of code (modules, functions, and small code assemblies) rather than on larger integraded code assemblies or full systems. Typically you have an editor-like view of the code that is executed, as in the case of JUnit testing frameworks (or any of a myriad of derived frameworks for Java and/or other languages).
The automated testing referred to by bbondi can be hands-off running of a full assembly. This is done by analyzing the branch conditions, and by monitoring that each section of code has been in use at least once during a testing session. This kind of logic is useful to find dead-end logic, or logic that cannot be reached. Sometimes there are logic constructs that are mutually exclusive so the dependent code simply cannot be reached. This is not uncommon for code that is based on a copy of previous code with customization for new requirements.
Code reviews should be a preventive technique and the primary value is to make sure that the code appears easy enough to maintain. You can also see if the code addresses all the requirements, but I think it would be difficult to ascertain if that code would work correctly.
As for the impossibility of getting 100% coverage I suggest that unit testing is actually where the front-end validations can be bypassed and where I can inject exceptions to confirm that the code is able to intercept errors.