home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
PMF202.ZIP
/
PMFLOPPY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-09
|
21KB
|
663 lines
/*
pmfloppy.c
main program
PM based disk utility. Use separate threads for disk actions to
prevent slowing up PM too much. Use huge memory allocation for
single pass reads.
Copyright G. Bryant, 1990
Change Log
8-Jun-90 Correct array bounds violation in FreeThread
9-Jun-90 Correct the EXPORTS statement in pmfloppy.def
*/
#define INCL_PM
#define INCL_BASE
#define INCL_DOSERRORS
#define INCL_DOSPROCESS
#define INCL_DOSDEVIOCTL
#define INCL_DOSSESMGR
#define INCL_GPILCIDS
#define INCL_WINSWITCHLIST
#include <os2.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <process.h>
#include "pmfloppy.h"
#include "DskIm.h"
// prototypes for current file
MRESULT EXPENTRY ClientWndProc(HWND, USHORT, MPARAM, MPARAM);
MRESULT Panic(PCH, USHORT);
MRESULT DisplayStatus(HWND, HPS, USHORT);
MRESULT DisplayDone(HWND , HPS, USHORT);
VOID FreeThread(USHORT);
VOID DisplayImageStat(HWND, HPS);
VOID PutBox(PSZ, PSZ);
// prototypes from copydlgs.c
extern MRESULT EXPENTRY ReadDlgProc(HWND, USHORT, MPARAM, MPARAM);
extern MRESULT EXPENTRY WriteDlgProc(HWND, USHORT, MPARAM, MPARAM);
extern MRESULT EXPENTRY AboutDlgProc(HWND, USHORT, MPARAM, MPARAM);
extern MRESULT EXPENTRY DeleteDlgProc(HWND, USHORT, MPARAM, MPARAM);
extern MRESULT EXPENTRY LoadDlgProc(HWND, USHORT, MPARAM, MPARAM);
extern MRESULT EXPENTRY SaveDlgProc(HWND, USHORT, MPARAM, MPARAM);
extern MRESULT EXPENTRY CompDlgProc(HWND, USHORT, MPARAM, MPARAM);
// prototypes from dskcpy.c
extern VOID FAR readsource(USHORT);
extern VOID FAR writetarget(USHORT);
extern VOID FAR LoadImage(USHORT);
extern VOID FAR SaveImage(USHORT);
extern VOID FAR CompImages(USHORT);
/* GLOBAL VARIABLES */
// PM vbls
HAB hab;
HMQ hmq;
HWND hWndFrame ;
static CHAR szClientClass[]="PMFloppy";
ULONG ctldata = FCF_STANDARD & ~FCF_TASKLIST;
HWND hWndClient;
HWND hwndDeskTop;
QMSG qmsg;
LONG CharHeight;
LONG CharWidth;
// User response vbls
DskImage ImageBuffers[NUM_IMAGES];
USHORT BufferNum; // only use in foreground thread
USHORT CompNum; // only use in foreground thread
// Thread variables
ThreadContext tcThBufs[NUM_THREADS];
int cdecl main(void)
{
SWCNTRL swctl;
HSWITCH hswitch;
PID pid;
hab = WinInitialize(0);
hmq = WinCreateMsgQueue(hab, 0);
hwndDeskTop = WinQueryDesktopWindow(hab, NULL);
if (!WinRegisterClass(hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0))
return(0);
hWndFrame = WinCreateStdWindow(HWND_DESKTOP,
WS_VISIBLE,
&ctldata,
szClientClass,
"Floppy Disk Utility",
0L,
0,
IDR_PMFLOPPY,
&hWndClient);
if (hWndFrame != NULL)
{
WinQueryWindowProcess(hWndFrame, &pid, NULL);
swctl.hwnd = hWndFrame;
swctl.hwndIcon = NULL;
swctl.hprog = NULL;
swctl.idProcess = pid;
swctl.idSession = 0;
swctl.uchVisibility = SWL_VISIBLE;
swctl.fbJump = SWL_JUMPABLE;
swctl.szSwtitle[0] = '\0';
hswitch = WinAddSwitchEntry(&swctl);
while ( WinGetMsg(hab, &qmsg, NULL, 0, 0) )
WinDispatchMsg(hab, &qmsg);
WinDestroyWindow(hWndFrame);
}
WinDestroyMsgQueue(hmq);
WinTerminate(hab);
DosExit(EXIT_PROCESS, 0);
} /* main */
// ClientWndProc - main window processing
//
// note: UM messages are User-defined (in pmfloppy.h).
// all UM messages use mp2 to indicate the drive the message concerns,
// and mp1 is data specific to that message. Then UM_xxxMSG is a
// generic msg. It is currently only used for DONE messages. If I
// need more, set up some magic numbers and pass them through mp1.
//
MRESULT EXPENTRY ClientWndProc(HWND hwnd
, USHORT id
, MPARAM mp1
, MPARAM mp2) {
HPS hPS;
HWND hMenu;
CHAR szTxtBuf[MAXMSGLEN];
int far *stkptr;
FONTMETRICS fm;
USHORT curBuff;
USHORT gotSource;
BOOL DriveActive;
USHORT curTh;
RECTL rctPaint;
switch (id) {
case WM_CREATE:
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
ImageBuffers[curBuff].BufferName[0] = '\0';
for (curTh=0;curTh < NUM_THREADS;curTh++) {
tcThBufs[curTh].ThID = 0;
tcThBufs[curTh].ImageNumber = NUM_IMAGES+1;
tcThBufs[curTh].CompNumber = NUM_IMAGES+1;
}
hPS = WinGetPS(hwnd);
GpiQueryFontMetrics(hPS, (long)sizeof(fm), &fm);
CharHeight = fm.lMaxBaselineExt;
CharWidth = fm.lMaxCharInc;
WinReleasePS(hPS);
break;
case WM_PAINT:
hPS = WinGetPS(hwnd);
GpiErase(hPS);
WinQueryUpdateRect(hwnd,&rctPaint);
DisplayImageStat(hwnd, hPS);
WinValidateRect(hwnd, &rctPaint, FALSE);
WinReleasePS(hPS);
break;
case WM_COMMAND:
switch (COMMANDMSG(&id)->cmd) {
case IDM_READ:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,ReadDlgProc,0,READ_DLG,NULL)) {
// send off thread to read
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS) {
tcThBufs[curTh].ImageNumber = BufferNum;
DosAllocSeg(STACK_SIZE, &(tcThBufs[curTh].selStk), 0);
stkptr = (int far *)MAKEP(tcThBufs[curTh].selStk, STACK_SIZE);
*(--stkptr) = curTh;
if (DosCreateThread(readsource,
&(tcThBufs[curTh].ThID),
(PBYTE)stkptr)) {
PutBox("Drive Read","DosCreateThread failed.");
DosFreeSeg(tcThBufs[curTh].selStk);
return FALSE;
} /* if can't create the thread. */
}
else {
PutBox("Drive Read","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_WRITE:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,WriteDlgProc,0,WRITE_DLG,NULL)) {
// send off thread to write
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS) {
tcThBufs[curTh].ImageNumber = BufferNum;
DosAllocSeg(STACK_SIZE, &(tcThBufs[curTh].selStk), 0);
stkptr = (int far *)MAKEP(tcThBufs[curTh].selStk, STACK_SIZE);
*(--stkptr) = curTh;
if (DosCreateThread(writetarget,
&(tcThBufs[curTh].ThID),
(PBYTE)stkptr)) {
PutBox("Drive Write","DosCreateThread failed.");
DosFreeSeg(tcThBufs[curTh].selStk);
return FALSE;
} /* if can't create the thread. */
}
else {
PutBox("Drive Write","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_ABOUT:
WinDlgBox(HWND_DESKTOP,hWndFrame,AboutDlgProc,0,ABOUT_DLG,NULL);
break;
case IDM_DELETE:
WinDlgBox(HWND_DESKTOP,hWndFrame,DeleteDlgProc,0,DELETE_DLG,NULL);
hPS = WinGetPS(hwnd);
GpiErase(hPS);
DisplayImageStat(hwnd, hPS);
WinReleasePS(hPS);
break;
case IDM_LOAD:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,LoadDlgProc,0,LOAD_DLG,NULL)) {
// send off thread to load
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS) {
tcThBufs[curTh].ImageNumber = BufferNum;
DosAllocSeg(STACK_SIZE, &(tcThBufs[curTh].selStk), 0);
stkptr = (int far *)MAKEP(tcThBufs[curTh].selStk, STACK_SIZE);
*(--stkptr) = curTh;
if (DosCreateThread(LoadImage,
&(tcThBufs[curTh].ThID),
(PBYTE)stkptr)) {
PutBox("Image Load","DosCreateThread failed.");
DosFreeSeg(tcThBufs[curTh].selStk);
return FALSE;
} /* if can't create the thread. */
}
else {
PutBox("Image Load","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_SAVE:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,SaveDlgProc,0,SAVE_DLG,NULL)) {
// send off thread to save
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS) {
tcThBufs[curTh].ImageNumber = BufferNum;
DosAllocSeg(STACK_SIZE, &(tcThBufs[curTh].selStk), 0);
stkptr = (int far *)MAKEP(tcThBufs[curTh].selStk, STACK_SIZE);
*(--stkptr) = curTh;
if (DosCreateThread(SaveImage,
&(tcThBufs[curTh].ThID),
(PBYTE)stkptr)) {
PutBox("Image Save","DosCreateThread failed.");
DosFreeSeg(tcThBufs[curTh].selStk);
return FALSE;
} /* if can't create the thread. */
}
else {
PutBox("Image Save","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_COMP:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,CompDlgProc,0,COMP_DLG,NULL)) {
// send off thread to compare
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS) {
tcThBufs[curTh].ImageNumber = BufferNum;
tcThBufs[curTh].CompNumber = CompNum;
DosAllocSeg(STACK_SIZE, &(tcThBufs[curTh].selStk), 0);
stkptr = (int far *)MAKEP(tcThBufs[curTh].selStk, STACK_SIZE);
*(--stkptr) = curTh;
if (DosCreateThread(CompImages,
&(tcThBufs[curTh].ThID),
(PBYTE)stkptr)) {
PutBox("Image Compare","DosCreateThread failed.");
DosFreeSeg(tcThBufs[curTh].selStk);
return FALSE;
} /* if can't create the thread. */
}
else {
PutBox("Image Compare","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_EXIT:
WinPostMsg(hWndFrame, WM_CLOSE, NULL, NULL);
break;
}
break;
case WM_INITMENU:
//set the allowable menu choices.
hMenu = WinWindowFromID(hWndFrame,FID_MENU);
// If we don't have anything to write, disable the write, save, and
// delete menus
gotSource = 0;
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++) {
if (ImageBuffers[curBuff].Percent == 100) gotSource++;
}
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_WRITE,TRUE),
MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_SAVE,TRUE),
MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_DELETE,TRUE),
MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_COMP,TRUE),
MPFROM2SHORT(MIA_DISABLED,(gotSource > 1) ? 0 : MIA_DISABLED));
break;
case UM_STATUS:
curTh = SHORT1FROMMP(mp1);
hPS = WinGetPS(hwnd);
DisplayStatus(hwnd, hPS, curTh);
WinReleasePS(hPS);
break;
case UM_DONE:
curTh = SHORT1FROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
hPS = WinGetPS(hwnd);
WinAlarm(HWND_DESKTOP,WA_NOTE);
DisplayDone(hwnd, hPS,curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case UM_ERROR:
curTh = SHORT1FROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
switch (ImageBuffers[curBuff].Busy) {
case BUSY_READ:
sprintf(szTxtBuf,"Read Error on drive %c", ImageBuffers[curBuff].DriveID[0]);
break;
case BUSY_WRITE:
sprintf(szTxtBuf,"Write Error on drive %c", ImageBuffers[curBuff].DriveID[0]);
break;
case BUSY_LOAD:
sprintf(szTxtBuf,"Load Error on drive %s", ImageBuffers[curBuff].FileName);
break;
case BUSY_SAVE:
sprintf(szTxtBuf,"Save Error on file %s", ImageBuffers[curBuff].FileName);
break;
}
Panic(szTxtBuf, tcThBufs[curTh].ErrorCode);
hPS = WinGetPS(hwnd);
DisplayStatus(hwnd, hPS, curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case UM_COMPOK:
curTh = SHORT1FROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
WinAlarm(HWND_DESKTOP,WA_NOTE);
PutBox("Image Compare","Images are identical!");
hPS = WinGetPS(hwnd);
DisplayDone(hwnd, hPS,curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case UM_COMPERR:
curTh = SHORT1FROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
WinAlarm(HWND_DESKTOP,WA_WARNING);
PutBox("Image Compare","Images are different");
hPS = WinGetPS(hwnd);
DisplayDone(hwnd, hPS,curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case WM_CLOSE:
DriveActive = FALSE;
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
if (ImageBuffers[curBuff].Busy) DriveActive = TRUE;
if (DriveActive) {
if (MBID_OK != WinMessageBox(HWND_DESKTOP,
hWndFrame,
"are you sure you want to quit?",
"A Drive is still running - ",
0,
MB_OKCANCEL | MB_QUERY))
break;
}
// else just fall through to default to get to the default proc
default:
return(WinDefWindowProc(hwnd, id, mp1, mp2));
} /* switch id */
return 0L;
} /* clientwndproc */
// Panic -- Put up a message box with an error message.
//
// Inputs: pszCaption -- Caption text for message box
//
// Returns: 1L, for error signalling from window procedures.
MRESULT Panic(PCH pszCaption,USHORT ErrorNum)
{
HWND hwndCurFocus;
CHAR buf[1024];
USHORT cbBuf;
if (ErrorNum == DSKIM_ERROR_WRONG_FORMAT)
sprintf(buf, "Error - target disk has incorrect format");
else if (ErrorNum == DSKIM_ERROR_WRONG_FILE)
sprintf(buf, "Error - file is not in correct format");
else if (DosGetMessage(NULL, 0, buf, 1024, ErrorNum, "oso001.msg", &cbBuf))
{
sprintf(buf, "SYS%04d: error text unavailable", ErrorNum);
cbBuf = 31;
}
buf[cbBuf] = (char)0;
hwndCurFocus = WinQueryFocus(HWND_DESKTOP, FALSE);
WinAlarm(HWND_DESKTOP, WA_ERROR);
PutBox(pszCaption,buf);
return(1L);
} // panic
// DisplayStatus - Display the status for the drive in the PS
//
// in: usPct Percent done
// Drive drive letter
// hwnd window handle to display on
// op operation (eg read, write)
//
MRESULT DisplayStatus(HWND hwnd, HPS hPS, USHORT curTh) {
RECTL rctStart;
CHAR szTxtBuf[MAXMSGLEN];
CHAR op[10];
CHAR Object[6];
CHAR Device[80];
USHORT curBuff;
USHORT compBuff;
curBuff = tcThBufs[curTh].ImageNumber;
compBuff = tcThBufs[curTh].CompNumber;
switch (ImageBuffers[curBuff].Busy) {
case BUSY_READ:
strcpy(op,"reading");
strcpy(Object,"Drive");
Device[0] = ImageBuffers[curBuff].DriveID[0];
Device[1] = '\0';
break;
case BUSY_WRITE:
strcpy(op,"writing");
strcpy(Object,"Drive");
Device[0] = ImageBuffers[curBuff].DriveID[0];
Device[1] = '\0';
break;
case BUSY_LOAD:
strcpy(op,"loading");
strcpy(Object,"file");
strcpy(Device,ImageBuffers[curBuff].FileName);
break;
case BUSY_SAVE:
strcpy(op,"saving");
strcpy(Object,"file");
strcpy(Device,ImageBuffers[curBuff].FileName);
break;
case BUSY_COMP:
strcpy(op,"comparing");
strcpy(Object,"image");
strcpy(Device,ImageBuffers[compBuff].BufferName);
break;
}
rctStart.xLeft = 5L;
rctStart.xRight = 5L + (CharWidth * MAXMSGLEN);
rctStart.yBottom = (curBuff * CharHeight) + 5;
rctStart.yTop = rctStart.yBottom + CharHeight;
sprintf(szTxtBuf,
"Image %s %s %s %s (%d%% complete)",
ImageBuffers[curBuff].BufferName,
op,
Object,
Device,
ImageBuffers[curBuff].Percent);
WinDrawText(hPS, -1, szTxtBuf, &rctStart, CLR_NEUTRAL, CLR_BACKGROUND,
DT_LEFT | DT_ERASERECT);
WinValidateRect(hwnd, &rctStart, FALSE);
return 0;
}
// DisplayDone - Display an operation complete
//
// in: Drive drive letter
// hwnd window handle to display on
// op operation (eg read, write)
//
MRESULT DisplayDone(HWND hwnd, HPS hPS, USHORT curBuff) {
RECTL rctStart;
CHAR szTxtBuf[MAXMSGLEN];
rctStart.xLeft = 5L;
rctStart.xRight = 5L + (CharWidth * MAXMSGLEN);
rctStart.yBottom = (curBuff * CharHeight) + 5;
rctStart.yTop = rctStart.yBottom + CharHeight;
sprintf(szTxtBuf, "Image %s is full", ImageBuffers[curBuff].BufferName);
WinDrawText(hPS, -1, szTxtBuf, &rctStart, CLR_NEUTRAL, CLR_BACKGROUND,
DT_LEFT | DT_ERASERECT);
WinValidateRect(hwnd, &rctStart, FALSE);
return 0;
}
// FreeThread - clean up after a child thread
//
// in: curTh - Thread to clean up
//
// Note: there doesn't seem to be an easy way to determine when a thread is
// gone. all the wait routines just work on processes. So we cheat and
// check the priority until we get a failure. Like all busy waits,
// this is incredibly idiotic, but until we get a "twait" function, I
// can't think of a better way.
//
VOID FreeThread(USHORT curTh) {
USHORT curBuff;
USHORT compBuff;
USHORT Prty;
// sit here until the thread is gone
while (DosGetPrty(PRTYS_THREAD,
&Prty,
tcThBufs[curTh].ThID) != ERROR_INVALID_THREADID) ;
curBuff = tcThBufs[curTh].ImageNumber;
compBuff = tcThBufs[curTh].CompNumber;
tcThBufs[curTh].ThID = 0;
tcThBufs[curTh].ImageNumber = NUM_IMAGES+1;
tcThBufs[curTh].CompNumber = NUM_IMAGES+1;
tcThBufs[curTh].ErrorCode = 0;
DosFreeSeg(tcThBufs[curTh].selStk);
ImageBuffers[curBuff].Busy = FALSE;
if (compBuff < NUM_IMAGES) ImageBuffers[compBuff].Busy = FALSE;
}
VOID DisplayImageStat(HWND hwnd, HPS hPS) {
RECTL rctStart;
RECTL rctPaint;
USHORT curBuff;
WinQueryWindowRect(hwnd,&rctPaint);
if (ImageBuffers[0].BufferName[0] == '\0') {
rctStart.xLeft = 5L;
rctStart.xRight = 5L + (CharWidth * 16);
rctStart.yBottom = 5L;
rctStart.yTop = rctStart.yBottom + CharHeight;
WinDrawText(hPS,
-1,
"No images in use",
&rctStart,
CLR_NEUTRAL,
CLR_BACKGROUND,
DT_LEFT | DT_ERASERECT);
}
else {
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
if (ImageBuffers[curBuff].BufferName[0] != '\0') {
if (ImageBuffers[curBuff].Busy) DisplayStatus(hwnd, hPS, curBuff);
else DisplayDone(hwnd,hPS, curBuff);
}
}
}
//
// Put the messages in an application modal message box
//
VOID PutBox(PSZ msg1, PSZ msg2) {
WinMessageBox(HWND_DESKTOP,
hWndFrame,
msg2,
msg1,
0,
MB_OK | MB_ICONEXCLAMATION);
return;
} // PutBox