#include <windows.h>

#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <iostream>

typedef std::vector<std::string> arg_t;
typedef std::vector<std::string> commandline_t;

namespace {

void _report_error(DWORD err)
{
  TCHAR buf[BUFSIZ];
  FormatMessage(
      FORMAT_MESSAGE_FROM_SYSTEM,
      NULL,
      err,
      0,
      buf,
      BUFSIZ,
      NULL
      );
  std::cerr << "got error << " << buf << '\n';
}

std::string _expand_env(const std::string& str)
{
  if ( str.empty() ) return str;

  TCHAR buf[MAX_PATH];

  int ret = ExpandEnvironmentStrings(str.c_str(), buf, MAX_PATH);
  if ( ret == 0 )
  {
    _report_error(GetLastError());
    return "";
  }

  return buf;
}

int _main(const arg_t& args)
{
  std::string dir;
  commandline_t commandline;

  for (arg_t::const_iterator it = args.begin(); it != args.end(); ++it)
  {
    if (it->find("/D") == 0 || it->find("/d") == 0)
    {
      dir = *it;
      dir.erase(0,2);
    }
    else
    {
      commandline.push_back(*it);
    }
  }

  if ( commandline.empty() ) return 0;

  dir = _expand_env(dir);

  std::ostringstream oss;
  std::transform(
      commandline.begin(),
      commandline.end(),
      std::ostream_iterator<std::string>(oss, " "),
      _expand_env);
  std::string commandline_(oss.str());
  // 最後に空白が入ってしまうので除去して\0を代わりに入れる
  commandline_.replace(commandline_.length()-1, 1, 1, '\0');

  STARTUPINFO st_info;
  ZeroMemory(&st_info, sizeof(STARTUPINFO)); 
  st_info.cb = sizeof(STARTUPINFO);

  PROCESS_INFORMATION proc_info;

  BOOL ret = CreateProcess(
      NULL,   // application name
      &commandline_[0],
      NULL, NULL, // proc attr & thread attr
      FALSE,  // inherit handle?
      0,      // process start flags
      NULL,   // ENV
      dir.empty()?NULL:dir.c_str(), // startup directory
      &st_info, // startup info
      &proc_info  // [o] process_information
      );

  if ( !ret )
  {
    DWORD err(GetLastError());
    _report_error(err);
    return err;
  }

  std::cout << proc_info.dwProcessId << '\n';
  return 0;
}

}

int main(int argc, char** argv)
{
  arg_t args;
  std::copy(argv+1, argv+argc, std::back_inserter(args));
  return _main(args);
}
