245 lines
6.8 KiB
C
245 lines
6.8 KiB
C
|
/*
|
||
|
+-------------------------------------------------------------------------+
|
||
|
| File Copying Routines |
|
||
|
+-------------------------------------------------------------------------+
|
||
|
| (c) Copyright 1993-1994 |
|
||
|
| Microsoft Corp. |
|
||
|
| All rights reserved |
|
||
|
| |
|
||
|
| Program : [FastCopy.c] |
|
||
|
| Programmer : Arthur Hanson |
|
||
|
| Original Program Date : [Jul 27, 1993] |
|
||
|
| Last Update : [Jun 18, 1994] |
|
||
|
| |
|
||
|
| Version: 1.00 |
|
||
|
| |
|
||
|
| Use multiple threads to whack data from one file to another |
|
||
|
| |
|
||
|
| Modifications: |
|
||
|
| 18-Oct-1990 w-barry Removed 'dead' code. |
|
||
|
| 21-Nov-1990 w-barry Updated API's to the Win32 set. |
|
||
|
| |
|
||
|
+-------------------------------------------------------------------------+
|
||
|
*/
|
||
|
|
||
|
#define INCL_DOSPROCESS
|
||
|
#define INCL_DOSSEMAPHORES
|
||
|
|
||
|
#include "globals.h"
|
||
|
#include <stdio.h>
|
||
|
#include <process.h>
|
||
|
#include <windows.h>
|
||
|
#include <malloc.h>
|
||
|
#include "mem.h"
|
||
|
#include "debug.h"
|
||
|
#include "utils.h"
|
||
|
#include "convapi.h"
|
||
|
|
||
|
#define BUFSIZE 0xFE00 // full segment minus sector
|
||
|
#define STACKSIZE 256 // stack size for child thread
|
||
|
|
||
|
typedef struct BUF BUF;
|
||
|
|
||
|
struct BUF {
|
||
|
BOOL flag;
|
||
|
DWORD cbBuf;
|
||
|
BUF *fpbufNext;
|
||
|
BYTE ach[BUFSIZE];
|
||
|
};
|
||
|
|
||
|
#define LAST TRUE
|
||
|
#define NOTLAST FALSE
|
||
|
|
||
|
static HANDLE hevQNotEmpty;
|
||
|
static CRITICAL_SECTION hcrtQLock;
|
||
|
static BUF *fpbufHead = NULL;
|
||
|
static BUF *fpbufTail = NULL;
|
||
|
static HANDLE hfSrc, hfDst;
|
||
|
static HANDLE hThread;
|
||
|
static BOOLEAN fAbort;
|
||
|
|
||
|
// forward type definitions
|
||
|
|
||
|
LPTSTR writer( void );
|
||
|
DWORD reader( void );
|
||
|
BUF *dequeue( void );
|
||
|
void enqueue( BUF *fpbuf );
|
||
|
TCHAR *fastcopy( HANDLE hfSrcParm, HANDLE hfDstParm );
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| writer()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
LPTSTR writer ( void ) {
|
||
|
BUF *fpbuf;
|
||
|
DWORD cbBytesOut;
|
||
|
BOOL f = !LAST;
|
||
|
LPTSTR npsz = NULL;
|
||
|
ULONG BytesCopied = 0;
|
||
|
|
||
|
TCHAR buffer[MAX_PATH];
|
||
|
|
||
|
Status_Bytes(lToStr(BytesCopied));
|
||
|
|
||
|
while (f != LAST && npsz == NULL) {
|
||
|
fpbuf = dequeue ();
|
||
|
|
||
|
if (fpbuf) {
|
||
|
if ((f = fpbuf->flag) != LAST) {
|
||
|
if (!WriteFile(hfDst, fpbuf->ach, fpbuf->cbBuf, &cbBytesOut, NULL)) {
|
||
|
npsz = Lids(IDS_L_4);
|
||
|
#ifdef DEBUG
|
||
|
dprintf(TEXT("ERROR: WriteFile\n"));
|
||
|
#endif
|
||
|
} else {
|
||
|
BytesCopied += cbBytesOut;
|
||
|
Status_Bytes(lToStr(BytesCopied));
|
||
|
|
||
|
|
||
|
if (cbBytesOut != (DWORD)fpbuf->cbBuf) {
|
||
|
npsz = Lids(IDS_L_5);
|
||
|
#ifdef DEBUG
|
||
|
dprintf(TEXT("ERROR: WriteFile: out-of-space\n"));
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
npsz = *(LPTSTR *)fpbuf->ach;
|
||
|
|
||
|
FreeMemory(fpbuf);
|
||
|
|
||
|
} else {
|
||
|
wsprintf (buffer, Lids(IDS_L_4), fpbuf);
|
||
|
#ifdef DEBUG
|
||
|
dprintf(TEXT("ERROR: WriteFile - FileBuffer is NULL\n"));
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (f != LAST)
|
||
|
fAbort = TRUE;
|
||
|
|
||
|
WaitForSingleObject(hThread, (DWORD)-1);
|
||
|
CloseHandle(hThread);
|
||
|
CloseHandle(hevQNotEmpty);
|
||
|
DeleteCriticalSection(&hcrtQLock);
|
||
|
|
||
|
return (npsz);
|
||
|
} // writer
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| reader()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
DWORD reader( void ) {
|
||
|
BUF *fpbuf;
|
||
|
BOOL f = !LAST;
|
||
|
|
||
|
while (!fAbort && f != LAST) {
|
||
|
if ((fpbuf = AllocMemory(sizeof(BUF))) == NULL) {
|
||
|
#ifdef DEBUG
|
||
|
dprintf(TEXT("ERROR: MemoryAlloc error %ld\n"), GetLastError());
|
||
|
#endif
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
f = fpbuf->flag = NOTLAST;
|
||
|
if (!ReadFile(hfSrc, fpbuf->ach, BUFSIZE, &fpbuf->cbBuf, NULL) || fpbuf->cbBuf == 0) {
|
||
|
f = fpbuf->flag = LAST;
|
||
|
*(LPTSTR *)(fpbuf->ach) = NULL;
|
||
|
}
|
||
|
|
||
|
enqueue (fpbuf);
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
} // reader
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| dequeue()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
BUF *dequeue( void ) {
|
||
|
BUF *fpbuf;
|
||
|
|
||
|
while (TRUE) {
|
||
|
if (fpbufHead != NULL) {
|
||
|
EnterCriticalSection(&hcrtQLock);
|
||
|
fpbufHead = (fpbuf = fpbufHead)->fpbufNext;
|
||
|
|
||
|
if (fpbufTail == fpbuf)
|
||
|
fpbufTail = NULL;
|
||
|
|
||
|
LeaveCriticalSection(&hcrtQLock);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// the head pointer is null so the list is empty. Block on eventsem
|
||
|
// until enqueue posts (ie. adds to queue)
|
||
|
WaitForSingleObject(hevQNotEmpty, (DWORD)-1);
|
||
|
}
|
||
|
|
||
|
return fpbuf;
|
||
|
} // dequeue
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| enqueue()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
void enqueue( BUF *fpbuf ) {
|
||
|
fpbuf->fpbufNext = NULL;
|
||
|
|
||
|
EnterCriticalSection(&hcrtQLock);
|
||
|
|
||
|
if (fpbufTail == NULL)
|
||
|
fpbufHead = fpbuf;
|
||
|
else
|
||
|
fpbufTail->fpbufNext = fpbuf;
|
||
|
|
||
|
fpbufTail = fpbuf;
|
||
|
LeaveCriticalSection(&hcrtQLock);
|
||
|
|
||
|
SetEvent(hevQNotEmpty);
|
||
|
} // enqueue
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| fastcopy()
|
||
|
|
|
||
|
| hfSrcParm file handle to read from
|
||
|
| hfDstParm file handle to write to
|
||
|
|
|
||
|
| returns NULL if successful
|
||
|
| pointer to error string otherwise
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
TCHAR *fastcopy (HANDLE hfSrcParm, HANDLE hfDstParm) {
|
||
|
DWORD dwReader;
|
||
|
|
||
|
hfSrc = hfSrcParm;
|
||
|
hfDst = hfDstParm;
|
||
|
|
||
|
|
||
|
hevQNotEmpty = CreateEvent(NULL, (BOOL)FALSE, (BOOL)FALSE, NULL);
|
||
|
if (hevQNotEmpty == INVALID_HANDLE_VALUE)
|
||
|
return NULL;
|
||
|
|
||
|
InitializeCriticalSection(&hcrtQLock);
|
||
|
|
||
|
fAbort = FALSE;
|
||
|
hThread = CreateThread(0, STACKSIZE, (LPTHREAD_START_ROUTINE)reader, 0, 0, &dwReader);
|
||
|
if (hThread == INVALID_HANDLE_VALUE) {
|
||
|
#ifdef DEBUG
|
||
|
dprintf(TEXT("ERROR: Can't create thread - FileCopy\n"));
|
||
|
#endif
|
||
|
return Lids(IDS_L_6);
|
||
|
}
|
||
|
|
||
|
return(writer());
|
||
|
} // fastcopy
|
||
|
|
||
|
|