So you specify each vertex point twice (v.x, v.y, 1) and (v.x, v.y, 0). The z-coordinate isn't really a z at all, it just flags if the point should be a regular point (1.0) or point projected infinitely away from the light (0.0).
The (x, y) coord in the matrix is the position of the light. So say the light is at (l.x, l.y) and you pass the point (v.x, v.y, 1.0). The homogenous coord you'd get back would be (v.x, v.y, 0.0, 1.0) or basically the "regular" coord that you put in (ignoring the weird, not-really-a-z-value). If you put in (v.x, v.y, 0.0) you'd get (v.x - l.x, v.y - l.y, 0.0, 0.0) In other words, a point at infinity in the direction from the light to the vertex. The w = 0.0 trick is actually in the OpenGL spec and is required to be supported by the hardware, which is good to know it's not just a hack that happens to work.
Anyways, nowadays I'd probably try batching all of the shadow geometry stuff on the CPU. It was a neat trick on OpenGL ES 1.x, but it effectively requires a draw call per shadow casting object (I did the entire static environment as 1 though). It saved on a bit of code, but I think having so many draw calls was more expensive than it needed to be. /me shrugs It worked on an iPhone 1 though.