En Windows, CreateProcess en realidad no devuelve un código de error. En cambio, usa GetLastError para encontrar más detalles si CreateProcess falla, luego use FormatMessage para convertir el código de error de GetLastError en una descripción adecuada. (Los códigos de error de GetLastError también pueden ser decodificados usando this list)
En cuanto a la fuente de proc_open(), PHP está haciendo realmente el GetLastError() para que en el caso de un fallo, y el código de error se habilita el registro de el regreso de GetLastError() en lugar de CreateProcess (que devuelve un BOOL, poco probable que sea 3 :))
Tenga en cuenta que proc_open utiliza esto para volcar el mensaje:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "CreateProcess failed, error code - %u", dw);
... así que "-" tienes antes de que el 3 sea solo un guión, no un signo menos. Por lo tanto, obtiene el código de error 3, que de acuerdo con that list significa "El sistema no puede encontrar la ruta especificada".
Más een vir die username. – McGafter