typedef void (*REQUEST)(HANDLE wr, HANDLE rd, int param);

typedef struct _drivesList {
   CHAR dname[32];
   HANDLE hthread;
   int position;
} drivesList, *p_drivesList;

typedef struct _threadParams {
   CHAR cmdline[256];
   REQUEST rq;
   int param;
} threadParams, *pthreadParams;


ULONG
lgOutput(HANDLE hwr, HANDLE hrd, int param)
{
   CHAR  tb[256];
	LVITEM lvstr={LVIF_TEXT, param, 5, 0, 0, NULL, sizeof(tb), 1, 0, 0};
   int res = 0;
   while(readString(hrd, tb, sizeof(tb)) > 0)
   {
      if(strstr(tb, "pmon=") == NULL)
      {
         fprintf(logf, "%s", tb);
         fflush(logf);
      }
      if(strstr(tb, "press Enter to continue") &&
         WaitForSingleObject(hMutex, 150000) == WAIT_OBJECT_0)
      {
         drvsReady++;
         ReleaseMutex(hMutex);
         while(wait_start)
            Sleep(50);
         WriteFile(hwr, "Go!\n", 4, &res, NULL);
         fflush(NULL);
      }
      if(strstr(tb, "KB/sec") &&
         WaitForSingleObject(hMutex, 150000) == WAIT_OBJECT_0)
      {
         if(strlen(resBuf))
            strcat(resBuf, " ");
         res = strtol(strchr(tb, ',') + 1, NULL, 10);
         sprintf(resBuf + strlen(resBuf), "%.3f", (double)res/1024.0);
         resInt += res;
         drvsReady++;
         ReleaseMutex(hMutex);
      }
      if(strstr(tb, "pmon=") != NULL)
      {
         lvstr.pszText = strstr(tb, "pmon=") + 5;
         if(strchr(lvstr.pszText, ' '))
            *strchr(lvstr.pszText, ' ') = 0;
         SendDlgItemMessage(hDialog, IDC_LIST1, LVM_SETITEMTEXT,
            param, (LPARAM)&lvstr);
      }
   }
   return 1;
}

/*****************************************************
 * FUNCTION NAME: RedirectPipe 
 * 
 * PURPOSE: 
 *    creates child process with redirected I/O and 
 *    gives pipe handles (plus param) to routine
 *    May be run in the same or new thread
 *    ptp - pointer to parameters struct
 * SPECIAL CONSIDERATIONS:
 *      
 *****************************************************/
ULONG __stdcall RedirectPipe(void *ptp)
{ 
   HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
   HANDLE hInputWriteTmp,hInputRead,hInputWrite;
   HANDLE hErrorWrite;
   PROCESS_INFORMATION pi;
   STARTUPINFO si;
   SECURITY_ATTRIBUTES sa;
   CHAR b[256];
   sa.nLength= sizeof(SECURITY_ATTRIBUTES);
   sa.lpSecurityDescriptor = NULL;
   sa.bInheritHandle = TRUE;

/* creating pipes for child process with redirected IO */
   if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
         return 1;
   if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
                           GetCurrentProcess(),&hErrorWrite,0,
                           TRUE,DUPLICATE_SAME_ACCESS))
         return 2;
   if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
         return 3;
   if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
                        GetCurrentProcess(),
                        &hOutputRead, /* Address of new handle. */
                        0,FALSE, /* Make it uninheritable. */
                        DUPLICATE_SAME_ACCESS))
         return 4;
   if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
                        GetCurrentProcess(),
                        &hInputWrite, /* Address of new handle. */
                        0,FALSE, /* Make it uninheritable. */
                        DUPLICATE_SAME_ACCESS))
         return 5;
   if (!CloseHandle(hOutputReadTmp))
      return 6;
   if (!CloseHandle(hInputWriteTmp))
      return 7;

/* run process and close unnecessary handles */
   ZeroMemory(&si,sizeof(STARTUPINFO));
   si.cb = sizeof(STARTUPINFO);
   si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
   si.hStdOutput = hOutputWrite;
   si.hStdInput  = hInputRead;
   si.hStdError  = hErrorWrite;
   si.wShowWindow = SW_HIDE;
   strcpy(b, ((pthreadParams)ptp)->cmdline);
   if (!CreateProcess(NULL,((pthreadParams)ptp)->cmdline,
                      NULL,NULL,TRUE,0,NULL,NULL,&si,&pi))
         return 13;
   if (!CloseHandle(pi.hThread))
      return 14;
   if (!CloseHandle(hOutputWrite))
      return 8;
   if (!CloseHandle(hInputRead ))
      return 9;
   if (!CloseHandle(hErrorWrite))
      return 10;


/* read output and (may be) control child */
   ((pthreadParams)ptp)->rq(hInputWrite, hOutputRead, ((pthreadParams)ptp)->param);

   WaitForSingleObject(pi.hProcess, 300000);
   if (!CloseHandle(pi.hProcess))
      return 15;

/* final close and free parameters */
   if (!CloseHandle(hOutputRead))
      return 11;
   if (!CloseHandle(hInputWrite))
      return 12;
      
   free(ptp);
   return 0;
}
