1119 lines
34 KiB
C
1119 lines
34 KiB
C
/* MMIOTest.c
|
||
*
|
||
* Test the MMIO library.
|
||
*/
|
||
|
||
#include "mmiot32.h" // (Win32)
|
||
|
||
|
||
/* constants */
|
||
#define MMIOM_ANSWER (MMIOM_USER + 1) // get answer to the universe
|
||
|
||
|
||
/* globals */
|
||
char gszAppName[] = "MMIOTest"; // for title bar etc.
|
||
HANDLE ghInst; // program instance handle
|
||
|
||
|
||
/* prototypes */
|
||
void PASCAL AppPaint(HWND hwnd, HDC hdc);
|
||
BOOL FAR PASCAL AppAbout(HWND hDlg, UINT uMessage,
|
||
DWORD dwParam, LONG lParam);
|
||
BOOL PASCAL AppInit(HANDLE hInst, HANDLE hPrev);
|
||
LONG FAR PASCAL AppWndProc(HWND hwnd, UINT uMessage,
|
||
DWORD dwParam, LONG lParam);
|
||
int WINAPI WinMain(HANDLE hInst, HANDLE hPrev, LPSTR lpszCmdLine, int iCmdShow);
|
||
|
||
void NEAR PASCAL Test1(HWND hwnd);
|
||
void NEAR PASCAL TestHelloWorld(HMMIO hmmio, LONG lBufSize);
|
||
MMIOPROC RCDIOProc;
|
||
void NEAR PASCAL Test2(HWND hwnd);
|
||
void NEAR PASCAL Test2Helper(BOOL fMemFile);
|
||
void NEAR PASCAL FillBufferedFile(HMMIO hmmio, LONG lLongs);
|
||
void NEAR PASCAL Test3(HWND hwnd);
|
||
void NEAR PASCAL TestRIFF(HMMIO hmmio, BOOL fReadable);
|
||
LPSTR NEAR PASCAL lstrrchr(LPSTR szSrc, char ch);
|
||
#ifdef OMIT
|
||
void NEAR PASCAL lmemset(void far *pDst, BYTE bSrc, long cDst);
|
||
#endif //OMIT
|
||
|
||
|
||
/* AppPaint(hwnd, hdc)
|
||
*
|
||
* This function is called whenever the application windows needs to be
|
||
* redrawn.
|
||
*/
|
||
void PASCAL
|
||
AppPaint(
|
||
HWND hwnd, // window painting into
|
||
HDC hdc) // display context to paint to
|
||
{
|
||
}
|
||
|
||
|
||
/* AppAbout(hDlg, uMessage, dwParam, lParam)
|
||
*
|
||
* This function handles messages belonging to the "About" dialog box.
|
||
* The only message that it looks for is WM_COMMAND, indicating the use
|
||
* has pressed the "OK" button. When this happens, it takes down
|
||
* the dialog box.
|
||
*/
|
||
BOOL FAR PASCAL // TRUE iff message has been processed
|
||
AppAbout(
|
||
HWND hDlg, // window handle of "about" dialog box
|
||
UINT uMessage, // message number
|
||
DWORD dwParam, // message-dependent parameter
|
||
LONG lParam) // message-dependent parameter
|
||
{
|
||
switch (uMessage)
|
||
{
|
||
case WM_COMMAND:
|
||
if (dwParam == IDOK)
|
||
EndDialog(hDlg, TRUE);
|
||
break;
|
||
case WM_INITDIALOG:
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
/* AppInit(hInst, hPrev)
|
||
*
|
||
* This is called when the application is first loaded into memory.
|
||
* It performs all initialization that doesn't need to be done once
|
||
* per instance.
|
||
*/
|
||
BOOL PASCAL // returns TRUE iff successful
|
||
AppInit(
|
||
HANDLE hInst, // instance handle of current instance
|
||
HANDLE hPrev) // instance handle of previous instance
|
||
{
|
||
WNDCLASS wndclass;
|
||
|
||
#if DBG
|
||
#if BOGUS //Laurie
|
||
wpfGetDebugLevel(gszAppName);
|
||
#endif
|
||
#endif
|
||
|
||
if (!hPrev)
|
||
{
|
||
/* Register a class for the main application window */
|
||
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
wndclass.hIcon = LoadIcon(hInst, "AppIcon");
|
||
wndclass.lpszMenuName = "AppMenu";
|
||
wndclass.lpszClassName = gszAppName;
|
||
/* wndclass.hbrBackground = (HBRUSH) COLOR_WINDOW + 1; */
|
||
wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
|
||
wndclass.hInstance = hInst; // (Win32)
|
||
wndclass.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW;
|
||
wndclass.lpfnWndProc = (WNDPROC)AppWndProc;
|
||
wndclass.cbWndExtra = 0;
|
||
wndclass.cbClsExtra = 0;
|
||
|
||
if (!RegisterClass(&wndclass))
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/* WinMain(hInst, hPrev, lpszCmdLine, cmdShow)
|
||
*
|
||
* The main procedure for the App. After initializing, it just goes
|
||
* into a message-processing loop until it gets a WM_QUIT message
|
||
* (meaning the app was closed).
|
||
*/
|
||
int WINAPI // returns exit code specified in WM_QUIT
|
||
WinMain(
|
||
HANDLE hInst, // instance handle of current instance
|
||
HANDLE hPrev, // instance handle of previous instance
|
||
LPSTR lpszCmdLine, // null-terminated command line
|
||
int iCmdShow) // how window should be initially displayed
|
||
{
|
||
MSG msg; // message from queue
|
||
HWND hwnd; // handle to app's window
|
||
|
||
/* save instance handle for dialog boxes */
|
||
ghInst = hInst;
|
||
|
||
/* call initialization procedure */
|
||
if (!AppInit(hInst, hPrev))
|
||
return FALSE;
|
||
|
||
/* create the application's window */
|
||
hwnd = CreateWindow
|
||
(
|
||
gszAppName, // window class
|
||
gszAppName, // window caption
|
||
WS_OVERLAPPEDWINDOW, // window style
|
||
CW_USEDEFAULT, 0, // initial position
|
||
CW_USEDEFAULT, 0, // initial size
|
||
NULL, // parent window handle
|
||
NULL, // window menu handle
|
||
hInst, // program instance handle
|
||
NULL // create parameters
|
||
);
|
||
ShowWindow(hwnd, iCmdShow);
|
||
|
||
/* get messages from event queue and dispatch them */
|
||
while (GetMessage(&msg, NULL, 0, 0))
|
||
{
|
||
TranslateMessage(&msg);
|
||
DispatchMessage(&msg);
|
||
}
|
||
|
||
return msg.wParam; /* Note: wParam is a DWORD in NT */
|
||
}
|
||
|
||
|
||
/* AppWndProc(hwnd, uMessage, dwParam, lParam)
|
||
*
|
||
* The window proc for the app's main window. This processes all
|
||
* of the parent window's messages.
|
||
*/
|
||
LONG FAR PASCAL // returns 0 iff processed message
|
||
AppWndProc(
|
||
HWND hwnd, // window's handle
|
||
UINT uMessage, // message number
|
||
DWORD dwParam, // message-dependent parameter
|
||
LONG lParam) // message-dependent parameter
|
||
{
|
||
#ifdef WIN16
|
||
FARPROC fpfn;
|
||
#endif
|
||
PAINTSTRUCT ps;
|
||
BOOL fAllTests = FALSE;
|
||
|
||
switch (uMessage)
|
||
{
|
||
|
||
case WM_COMMAND:
|
||
|
||
switch (dwParam)
|
||
{
|
||
|
||
case IDM_ABOUT:
|
||
|
||
/* request to display "About" dialog box */
|
||
#ifdef WIN16
|
||
fpfn = MakeProcInstance((FARPROC) AppAbout, ghInst);
|
||
DialogBox(ghInst, MAKEINTRESOURCE(ABOUTBOX),
|
||
hwnd, fpfn);
|
||
FreeProcInstance(fpfn);
|
||
#else
|
||
DialogBox(ghInst, MAKEINTRESOURCE(ABOUTBOX),
|
||
hwnd, (DLGPROC)AppAbout);
|
||
#endif
|
||
break;
|
||
|
||
case IDM_EXIT:
|
||
|
||
/* request to exit this program */
|
||
PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
|
||
break;
|
||
|
||
case IDM_ALLTESTS:
|
||
|
||
fAllTests = TRUE;
|
||
/* fall through */
|
||
|
||
case IDM_TEST1:
|
||
|
||
dprintf("\n--------------- Test1 ---------------\n");
|
||
Test1(hwnd);
|
||
dprintf("Done Test1.\n");
|
||
if (!fAllTests)
|
||
break;
|
||
|
||
case IDM_TEST2:
|
||
|
||
dprintf("\n--------------- Test2 ---------------\n");
|
||
Test2(hwnd);
|
||
dprintf("Done Test2.\n");
|
||
if (!fAllTests)
|
||
break;
|
||
|
||
case IDM_TEST3:
|
||
|
||
dprintf("\n--------------- Test3 ---------------\n");
|
||
Test3(hwnd);
|
||
dprintf("Done Test3.\n");
|
||
if (!fAllTests)
|
||
break;
|
||
|
||
dprintf("Done All Tests.\n");
|
||
break;
|
||
}
|
||
return 0L;
|
||
|
||
case WM_DESTROY:
|
||
|
||
/* exit this program */
|
||
PostQuitMessage(0);
|
||
break;
|
||
|
||
case WM_PAINT:
|
||
|
||
/* set up a paint structure, and call AppPaint() */
|
||
BeginPaint(hwnd, &ps);
|
||
AppPaint(hwnd, ps.hdc);
|
||
EndPaint(hwnd, &ps);
|
||
return 0;
|
||
}
|
||
|
||
return (LONG)DefWindowProc(hwnd, uMessage, dwParam, lParam);
|
||
}
|
||
|
||
|
||
void NEAR PASCAL
|
||
Test1(HWND hwnd)
|
||
{
|
||
HMMIO hmmio;
|
||
char achMemFile[100];
|
||
MMIOINFO mmioinfo;
|
||
HMMIO hmmioMF; // memory file handle
|
||
long lBufSize;
|
||
int fh;
|
||
FARPROC farproc; // Added to make it compile. LKG
|
||
|
||
|
||
dprintf("HelloWorld tests...\n");
|
||
|
||
/* open "hello.txt" unbuffered -- assume it contains
|
||
* "hello world\r\n" (13 bytes) -- and run the TestHelloWorld test
|
||
*/
|
||
WinEval((hmmio = mmioOpen("hello.txt", NULL, 0)) != NULL);
|
||
dprintf("TestHelloWorld() with no buffer\n");
|
||
TestHelloWorld(hmmio, 0);
|
||
|
||
for (lBufSize = 1; lBufSize <= 15; lBufSize++)
|
||
{
|
||
/* re-run test for various buffer sizes */
|
||
WinEval(mmioSetBuffer(hmmio, NULL, lBufSize, 0) == 0);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_SET) == 0L);
|
||
dprintf("TestHelloWorld() with %ld-byte buffer\n",
|
||
lBufSize);
|
||
TestHelloWorld(hmmio, lBufSize);
|
||
}
|
||
|
||
/* copy file into a memory block, set up memory block
|
||
* as a memory file, and re-run the test
|
||
*/
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_SET) == 0L);
|
||
WinEval(mmioRead(hmmio, achMemFile, 13L) == 13L);
|
||
memset(&mmioinfo, 0, sizeof(mmioinfo));
|
||
mmioinfo.fccIOProc = FOURCC_MEM;
|
||
mmioinfo.pchBuffer = achMemFile;
|
||
mmioinfo.cchBuffer = 13L;
|
||
WinEval((hmmioMF = mmioOpen(NULL, &mmioinfo, 0)) != NULL);
|
||
dprintf("TestHelloWorld() with memory file\n");
|
||
TestHelloWorld(hmmioMF, 13L);
|
||
|
||
/* close the open files */
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
WinEval(mmioClose(hmmioMF, 0) == 0);
|
||
|
||
/* open file and pass file handle to mmioOpen() */
|
||
WinEval((fh = _lopen("hello.txt", READ)) >= 0);
|
||
memset(&mmioinfo, 0, sizeof(mmioinfo));
|
||
mmioinfo.adwInfo[0] = fh;
|
||
WinEval((hmmio = mmioOpen((LPSTR) NULL, &mmioinfo, MMIO_ALLOCBUF))
|
||
!= NULL);
|
||
dprintf("TestHelloWorld() with file handle passed to mmioOpen()\n");
|
||
TestHelloWorld(hmmio, 0);
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
|
||
/* "hello.txt" is stored as an RCDATA resource named "Hello" --
|
||
* use this to try out the custom I/O procedure stuff
|
||
*/
|
||
dprintf("register Win3 RCDATA custom I/O procedure\n");
|
||
#define FOURCC_RCD mmioFOURCC('R', 'C', 'D', ' ')
|
||
WinEval( (farproc = (FARPROC) RCDIOProc) != NULL );
|
||
|
||
/* installing it twice should just mean it has to be removed twice */
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_FINDPROC) == NULL);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, (LPMMIOPROC) farproc,
|
||
MMIO_INSTALLPROC) == (LPMMIOPROC) farproc);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_FINDPROC) == (LPMMIOPROC) farproc);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, (LPMMIOPROC) farproc,
|
||
MMIO_INSTALLPROC) == (LPMMIOPROC) farproc);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_FINDPROC) == (LPMMIOPROC) farproc);
|
||
|
||
/* run the test without an I/O buffer */
|
||
dprintf("TestHelloWorld() unbuffered, with custom I/O procedure\n");
|
||
WinEval((hmmio = mmioOpen("mmiotest.rcd+Hello", NULL, 0)) != NULL); // changed ! to + LKG
|
||
TestHelloWorld(hmmio, 0);
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
|
||
/* run the test with a standard-size I/O buffer */
|
||
dprintf("TestHelloWorld() buffered, with custom I/O procedure\n");
|
||
WinEval((hmmio = mmioOpen("mmiotest.rcd+Hello", NULL, MMIO_ALLOCBUF))
|
||
!= NULL);
|
||
TestHelloWorld(hmmio, MMIO_DEFAULTBUFFER);
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
|
||
/* remove the custom I/O procedure (it was installed twice above) */
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_FINDPROC) == (LPMMIOPROC) farproc);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_REMOVEPROC) == (LPMMIOPROC) farproc);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_FINDPROC) == (LPMMIOPROC) farproc);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_REMOVEPROC) == (LPMMIOPROC) farproc);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_FINDPROC) == NULL);
|
||
WinEval(mmioInstallIOProc(FOURCC_RCD, NULL,
|
||
MMIO_REMOVEPROC) == NULL);
|
||
|
||
/* make sure the I/O procedure got removed */
|
||
WinEval(mmioOpen("mmiotest.rcd+Hello", NULL, 0) == NULL);
|
||
}
|
||
|
||
|
||
void NEAR PASCAL
|
||
TestHelloWorld(HMMIO hmmio, LONG lBufSize)
|
||
{
|
||
MMIOINFO mmioinfo;
|
||
char ach[100];
|
||
long lOffset;
|
||
static NPSTR szHello = "hello world\r\n"; // contents of file
|
||
long lAnswer;
|
||
|
||
strcpy(ach, "Recognisable garbage!");
|
||
|
||
/* send the I/O procedure a custom message */
|
||
lAnswer = mmioSendMessage(hmmio, MMIOM_ANSWER, 20L, 22L);
|
||
dprintf("answer %ld, ", lAnswer);
|
||
|
||
/* expect to be at offset 0 now */
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 0L);
|
||
|
||
if (lBufSize > 0)
|
||
{
|
||
/* access buffer directly starting at "hello" */
|
||
WinEval(mmioGetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
WinEval(mmioAdvance(hmmio, &mmioinfo, MMIO_READ) == 0);
|
||
WinEval(lstrncmp(mmioinfo.pchNext, szHello,
|
||
min((int) lBufSize, 13)) == 0);
|
||
if (lBufSize >= 2)
|
||
{
|
||
WinAssert((mmioinfo.pchEndWrite - mmioinfo.pchNext)
|
||
>= 2);
|
||
mmioinfo.pchNext += 2;
|
||
}
|
||
WinEval(mmioSetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
|
||
/* expect to be at offset 2 now */
|
||
if (lBufSize >= 2)
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 2L);
|
||
|
||
/* access buffer directly starting at "world" */
|
||
WinEval(mmioSeek(hmmio, 6L, SEEK_SET) == 6L);
|
||
WinEval(mmioGetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
WinEval(mmioAdvance(hmmio, &mmioinfo, MMIO_READ) == 0);
|
||
WinEval(lstrncmp(mmioinfo.pchNext, szHello + 6,
|
||
min((int) lBufSize, 13 - 6)) == 0);
|
||
WinEval(mmioSetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
|
||
/* expect to still be at offset 6 */
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 6L);
|
||
}
|
||
|
||
/* go to offset 2 */
|
||
WinEval(mmioSeek(hmmio, 2L, SEEK_SET) == 2L);
|
||
|
||
/* read "llo" */
|
||
strcpy(ach, "Recognisable garbage!");
|
||
WinEval(mmioRead(hmmio, ach, 3) == 3);
|
||
WinEval(lstrncmp(ach, "llo", 3) == 0);
|
||
|
||
/* read " wor" */
|
||
WinEval(mmioRead(hmmio, ach, 4) == 4);
|
||
|
||
if (lstrncmp(ach, " wor", 4) != 0)
|
||
{ printf("ach = <%s>, expected < wor>", ach);
|
||
}
|
||
|
||
WinEval(lstrncmp(ach, " wor", 4) == 0);
|
||
|
||
/* expect to be at offset 9 now */
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 9L);
|
||
|
||
/* read "ld\r\n" -- ask for 7 bytes, but only expect 4 */
|
||
WinEval(mmioRead(hmmio, ach, 7) == 4);
|
||
WinEval(lstrncmp(ach, "ld\r\n", 4) == 0);
|
||
|
||
/* expect to be at end of file now */
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 13L);
|
||
|
||
/* test seeking and reading for each offset in the file */
|
||
dprintf("reading from offset");
|
||
for (lOffset = 0; lOffset <= 11; lOffset++)
|
||
{
|
||
dprintf(" %ld", lOffset);
|
||
WinEval(mmioSeek(hmmio, lOffset, SEEK_SET) == lOffset);
|
||
WinEval(mmioRead(hmmio, ach, 2) == 2);
|
||
WinEval(lstrncmp(ach, "hello world\r\n" + lOffset, 2) == 0);
|
||
}
|
||
dprintf(".\n");
|
||
|
||
/* check more seeking */
|
||
OutputDebugString("SEEK_SET\n");
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_SET) == 0L);
|
||
WinEval(mmioSeek(hmmio, 13L, SEEK_SET) == 13L);
|
||
OutputDebugString("SEEK_CUR\n");
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 13L);
|
||
WinEval(mmioSeek(hmmio, -2L, SEEK_CUR) == 11L);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 11L);
|
||
WinEval(mmioSeek(hmmio, -11L, SEEK_CUR) == 0L);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 0L);
|
||
OutputDebugString("SEEK_END\n");
|
||
WinEval(mmioSeek(hmmio, 11L, SEEK_END) == 2L);
|
||
OutputDebugString("SEEK_CUR\n");
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 2L);
|
||
|
||
/* measure the length of the file */
|
||
OutputDebugString("SEEK_END\n");
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_END) == 13L);
|
||
} /* TestHelloWorld */
|
||
|
||
|
||
/* 'RCD' I/O Procedure
|
||
*
|
||
* I/O procedure that will open e.g. "foo.rcd+bar" but it's a con.
|
||
* It will chech that what's between the . and + is rcd, it will
|
||
* check that bar is in fact "hello" and that foo is "mmiotest"
|
||
* It then has a spoof "file" containing "hello world\r\n"
|
||
*/
|
||
|
||
typedef struct _MMIORCDINFO // How RCD IOProc uses MMIO.adwInfo[]
|
||
{
|
||
int fh; // DOS file handle
|
||
long lOffset; // offset of start of resource
|
||
long lSize; // size of resource (bytes)
|
||
} MMIORCDINFO;
|
||
|
||
LONG FAR PASCAL
|
||
RCDIOProc(
|
||
LPSTR lpmmioStr, // I/O status block (cast to LPSTR)
|
||
UINT uMsg, // message number
|
||
LONG lParam1,
|
||
LONG lParam2) // message-specific parameters
|
||
{
|
||
LPMMIOINFO pmmio = (LPMMIOINFO) lpmmioStr;
|
||
MMIORCDINFO FAR *pInfo = (MMIORCDINFO FAR *) pmmio->adwInfo;
|
||
LPSTR szFileName = (LPSTR) lParam1;
|
||
HANDLE hModule; // handle to module
|
||
HANDLE hResInfo; // handle to resource information
|
||
LONG lBytesLeft; // bytes left in res. after current pos.
|
||
WORD wBytesAsk; // bytes asked to read
|
||
WORD wBytes; // bytes actually read
|
||
LONG lBytesTotal; // accum. bytes actually read
|
||
LPSTR pchPlus; // pointer to '+'
|
||
LPSTR pchDot; // pointer to '.rcd'
|
||
LONG lNewOffset;
|
||
|
||
static LPSTR lpData = "hello world\r\n"; // actual data
|
||
|
||
switch (uMsg)
|
||
{
|
||
|
||
case MMIOM_OPEN:
|
||
|
||
if (0 != stricmp(szFileName,"mmiotest.rcd+hello"))
|
||
return MMIOERR_CANNOTOPEN;
|
||
|
||
pInfo->lSize = strlen(lpData);
|
||
|
||
pInfo->lOffset = 0;
|
||
|
||
pmmio->lDiskOffset = 0L;
|
||
|
||
return 0L;
|
||
|
||
case MMIOM_CLOSE:
|
||
|
||
return 0L;
|
||
|
||
case MMIOM_READ:
|
||
|
||
/* lParam2 = number of bytes to read */
|
||
/* lParam1 = address to deliver them to */
|
||
lBytesLeft = pInfo->lSize - pmmio->lDiskOffset;
|
||
if (lParam2 > lBytesLeft)
|
||
lParam2 = lBytesLeft;
|
||
|
||
// memcpy((LPSTR)lParam1, lpData[pmmio->lDiskOffset], lParam2); but it trapped!
|
||
{ int i;
|
||
for (i=0; i<lParam2; ++i) {
|
||
((LPSTR)lParam1)[i] = lpData[pmmio->lDiskOffset++];
|
||
}
|
||
}
|
||
|
||
return lParam2;
|
||
|
||
case MMIOM_WRITE:
|
||
|
||
/* Windows resources are read-only */
|
||
return -1;
|
||
|
||
case MMIOM_SEEK:
|
||
|
||
/* calculate <lNewOffset>, the new offset (relative to the
|
||
* beginning of the resource)
|
||
*/
|
||
switch ((int) lParam2)
|
||
{
|
||
|
||
case SEEK_SET:
|
||
|
||
lNewOffset = lParam1;
|
||
break;
|
||
|
||
case SEEK_CUR:
|
||
|
||
lNewOffset = pmmio->lDiskOffset + lParam1;
|
||
break;
|
||
|
||
case SEEK_END:
|
||
|
||
lNewOffset = pInfo->lSize - lParam1;
|
||
break;
|
||
}
|
||
|
||
if (lNewOffset<0)
|
||
{ dprintf("Seek to before start of rcd");
|
||
return -1;
|
||
}
|
||
if (lNewOffset>pInfo->lSize)
|
||
{ dprintf("Seek to after end of rcd");
|
||
return -1;
|
||
}
|
||
|
||
|
||
pmmio->lDiskOffset = lNewOffset;
|
||
return lNewOffset;
|
||
|
||
case MMIOM_ANSWER:
|
||
|
||
/* this I/O procedure knows the answer to the universe */
|
||
return lParam1 + lParam2;
|
||
|
||
}
|
||
|
||
return 0L;
|
||
}
|
||
|
||
|
||
void NEAR PASCAL
|
||
Test2(
|
||
HWND hwnd)
|
||
{
|
||
dprintf("Test2 using a DOS file...\n");
|
||
Test2Helper(FALSE);
|
||
dprintf("Test2 using a memory file...\n");
|
||
Test2Helper(TRUE);
|
||
}
|
||
|
||
|
||
void NEAR PASCAL
|
||
Test2Helper(
|
||
BOOL fMemFile)
|
||
{
|
||
HMMIO hmmio;
|
||
HPSTR pchCallerData = NULL;
|
||
long lBytesToRead;
|
||
long lOffset;
|
||
long lBufSize;
|
||
long lMemFileBufSize;
|
||
BOOL fBuffered;
|
||
MMIOINFO mmioinfo;
|
||
|
||
dprintf("creating 540000-byte file\n");
|
||
if (fMemFile)
|
||
{
|
||
/* create a memory file */
|
||
memset(&mmioinfo, 0, sizeof(mmioinfo));
|
||
mmioinfo.fccIOProc = FOURCC_MEM;
|
||
mmioinfo.pchBuffer = NULL;
|
||
mmioinfo.cchBuffer = 12344L; // initial size
|
||
mmioinfo.adwInfo[0] = 76543L; // grow by this much
|
||
WinEval((hmmio = mmioOpen(NULL, &mmioinfo,
|
||
MMIO_CREATE | MMIO_READWRITE)) != NULL);
|
||
}
|
||
else
|
||
{
|
||
/* open "test2.tmp" for reading and writing */
|
||
WinEval((hmmio = mmioOpen("test2.tmp", NULL,
|
||
MMIO_CREATE | MMIO_READWRITE | MMIO_ALLOCBUF)) != NULL);
|
||
}
|
||
|
||
/* create a file that's big enough so we do the following reads:
|
||
* 40000, 60000, 80000, 100000, 120000, 140000 (sum 540000)
|
||
*/
|
||
FillBufferedFile(hmmio, 540000L / 4L);
|
||
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 540000L);
|
||
|
||
dprintf("create huge a buffer that's not segment boundary aligned\n");
|
||
/* we'll read stuff into the buffer at offset 12345, to try out
|
||
* reading into the buffer across segment offsets
|
||
*/
|
||
if ((pchCallerData = GAllocPtr(140000L + 12345L)) == NULL)
|
||
{
|
||
dprintf("test program problem: can't allocate caller buffer\n");
|
||
WinAssert(FALSE);
|
||
}
|
||
|
||
lMemFileBufSize = 540000L;
|
||
for (fBuffered = fMemFile; fBuffered <= TRUE; fBuffered++)
|
||
{
|
||
/* seek back */
|
||
dprintf("seek back, do 40000-140000 byte %s reads,"
|
||
" and check file contents\n",
|
||
(LPSTR) (fBuffered ? "buffered" : "unbuffered"));
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_SET) == 0L);
|
||
|
||
/* read the file in varying large and huge reads, and at the
|
||
* same time verify that the file was written to correctly
|
||
*/
|
||
for (lOffset = 0L, lBytesToRead = 40000L, lBufSize = 100000L;
|
||
lBytesToRead <= 140000L;
|
||
lOffset += lBytesToRead, lBytesToRead += 20000L,
|
||
lBufSize -= 10000L)
|
||
{
|
||
long lLongs;
|
||
long huge * pl;
|
||
long lOffsetCheck;
|
||
MMIOINFO mmioinfo;
|
||
|
||
if (fMemFile)
|
||
{
|
||
/* juggle the memory file buffer around, but
|
||
* don't truncate the data
|
||
*/
|
||
if (lMemFileBufSize == 540000L)
|
||
lMemFileBufSize = 678901L;
|
||
else
|
||
lMemFileBufSize = 540000L;
|
||
WinEval(mmioSetBuffer(hmmio, NULL,
|
||
lMemFileBufSize, 0) == 0);
|
||
}
|
||
else
|
||
if (fBuffered)
|
||
{
|
||
/* just to be nasty, let's play around with the
|
||
* buffer size while all this is going on
|
||
*/
|
||
WinEval(mmioSetBuffer(hmmio, NULL, lBufSize, 0)
|
||
== 0);
|
||
WinEval(mmioGetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
WinEval(mmioAdvance(hmmio, &mmioinfo, MMIO_READ)
|
||
== 0);
|
||
WinEval(mmioSetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
}
|
||
else
|
||
{
|
||
/* no buffer */
|
||
WinEval(mmioSetBuffer(hmmio, NULL, 0, 0)
|
||
== 0);
|
||
}
|
||
|
||
/* read the next <lBytesToRead> */
|
||
WinEval(mmioRead(hmmio, pchCallerData + 12345L,
|
||
lBytesToRead) == lBytesToRead);
|
||
|
||
lLongs = lBytesToRead / 4L, pl =
|
||
(long huge *) (pchCallerData + 12345L);
|
||
lOffsetCheck = lOffset;
|
||
while (lLongs-- > 0)
|
||
{
|
||
WinEval(*pl++ == lOffsetCheck);
|
||
lOffsetCheck += 4;
|
||
}
|
||
}
|
||
|
||
WinAssert(mmioSeek(hmmio, 0L, SEEK_CUR) == 540000L);
|
||
WinAssert(mmioSeek(hmmio, 0L, SEEK_END) == 540000L);
|
||
WinEval(mmioRead(hmmio, pchCallerData + 12345L, 17L) == 0L);
|
||
}
|
||
|
||
if (pchCallerData != NULL)
|
||
GFreePtr(pchCallerData);
|
||
|
||
/* close "test2.tmp" */
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
|
||
if (!fMemFile)
|
||
{
|
||
dprintf("delete the test file using MMIO_DELETE\n");
|
||
WinEval(mmioOpen("test2.tmp", NULL, MMIO_DELETE)
|
||
== (HANDLE) TRUE);
|
||
}
|
||
}
|
||
|
||
|
||
void NEAR PASCAL
|
||
FillBufferedFile(
|
||
HMMIO hmmio,
|
||
LONG lLongs)
|
||
{
|
||
MMIOINFO mmioinfo;
|
||
long lOffset = 0;
|
||
|
||
/* fill buffered file <hmmio> with <lLongs> binary long integers,
|
||
* where offset X (such that X % 4 == 0) contains long integer X
|
||
*/
|
||
|
||
/* begin direct access of the I/O buffer */
|
||
WinEval(mmioGetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
|
||
for( ; ; )
|
||
{
|
||
long lAvail; // bytes available in buffer
|
||
|
||
lAvail = mmioinfo.pchEndWrite - mmioinfo.pchNext;
|
||
for( ; ; )
|
||
{
|
||
if ((lAvail -= sizeof(lOffset)) < 0)
|
||
break;
|
||
if (lLongs-- <= 0)
|
||
goto EXIT_FUNCTION;
|
||
*((long *) mmioinfo.pchNext) = lOffset;
|
||
mmioinfo.pchNext = (long)mmioinfo.pchNext + sizeof(long); // bypass compiler bug
|
||
lOffset += sizeof(lOffset);
|
||
}
|
||
|
||
/* flush the I/O buffer */
|
||
mmioinfo.dwFlags |= MMIO_DIRTY;
|
||
WinEval(mmioAdvance(hmmio, &mmioinfo, MMIO_WRITE) == 0);
|
||
WinAssert((mmioinfo.pchNext + sizeof(lOffset))
|
||
<= mmioinfo.pchEndWrite);
|
||
}
|
||
|
||
EXIT_FUNCTION:
|
||
|
||
/* end direct access of the I/O buffer */
|
||
mmioinfo.dwFlags |= MMIO_DIRTY;
|
||
WinEval(mmioSetInfo(hmmio, &mmioinfo, 0) == 0);
|
||
|
||
/* make sure we're where we think we should be */
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == lOffset);
|
||
}
|
||
|
||
|
||
void NEAR PASCAL
|
||
Test3(
|
||
HWND hwnd)
|
||
{
|
||
HMMIO hmmio;
|
||
DWORD dwFlags;
|
||
MMIOINFO mmioinfo;
|
||
|
||
for (dwFlags = 0; dwFlags <= MMIO_ALLOCBUF; dwFlags += MMIO_ALLOCBUF)
|
||
{
|
||
WinEval((hmmio = mmioOpen("test3.tmp", NULL,
|
||
dwFlags | MMIO_CREATE | MMIO_WRITE)) != NULL);
|
||
dprintf("TestRIFF(), %s, MMIO_WRITE: ",
|
||
(LPSTR) (dwFlags == 0 ? "unbuffered" : "buffered"));
|
||
TestRIFF(hmmio, FALSE);
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
|
||
WinEval((hmmio = mmioOpen("test3.tmp", NULL,
|
||
dwFlags | MMIO_CREATE | MMIO_READWRITE)) != NULL);
|
||
dprintf("TestRIFF(), %s, MMIO_READWRITE: ",
|
||
(LPSTR) (dwFlags == 0 ? "unbuffered" : "buffered"));
|
||
TestRIFF(hmmio, TRUE);
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
}
|
||
|
||
/* create a memory file */
|
||
memset(&mmioinfo, 0, sizeof(mmioinfo));
|
||
mmioinfo.fccIOProc = FOURCC_MEM;
|
||
mmioinfo.pchBuffer = NULL;
|
||
mmioinfo.cchBuffer = 1L; // initial size
|
||
mmioinfo.adwInfo[0] = 1L; // grow by this much
|
||
WinEval((hmmio = mmioOpen(NULL, &mmioinfo,
|
||
MMIO_CREATE | MMIO_READWRITE)) != NULL);
|
||
dprintf("TestRIFF() with memory file: ");
|
||
TestRIFF(hmmio, TRUE);
|
||
WinEval(mmioClose(hmmio, 0) == 0);
|
||
|
||
dprintf("delete the test file using MMIO_DELETE\n");
|
||
WinEval(mmioOpen("test3.tmp", NULL, MMIO_DELETE) == (HANDLE) TRUE);
|
||
}
|
||
|
||
|
||
/* Output from TestRIFF():
|
||
*
|
||
* 00000000 RIFF (0001E32A) 'foo '
|
||
* 0000000C abc1 (00000001)
|
||
* 00000016 abc2 (00000002)
|
||
* 00000020 abc3 (00000003)
|
||
* 0000002C abc4 (00000004)
|
||
* 00000038 abc5 (00000005)
|
||
* 00000046 abc6 (00000006)
|
||
* 00000054 abc7 (00000007)
|
||
* 00000064 LIST (0000007E) 'data'
|
||
* 00000070 num1 (00000001)
|
||
* 0000007A num2 (00000002)
|
||
* 00000084 num3 (00000003)
|
||
* 00000090 num4 (00000004)
|
||
* 0000009C num5 (00000005)
|
||
* 000000AA num6 (00000006)
|
||
* 000000B8 num7 (00000007)
|
||
* 000000C8 num8 (00000008)
|
||
* 000000D8 num9 (00000009)
|
||
* 000000EA xyz (0001E240)
|
||
* 0001E332
|
||
*/
|
||
|
||
void NEAR PASCAL
|
||
TestRIFF(
|
||
HMMIO hmmio,
|
||
BOOL fReadable)
|
||
{
|
||
MMCKINFO ckRIFF;
|
||
MMCKINFO ckLIST;
|
||
MMCKINFO ck;
|
||
HPSTR pchBuf, pchStart;
|
||
int huge * pi;
|
||
int i;
|
||
|
||
#define FOURCC_FOO mmioFOURCC('f', 'o', 'o', ' ')
|
||
#define FOURCC_ABC mmioFOURCC('a', 'b', 'c', ' ')
|
||
#define FOURCC_DATA mmioFOURCC('d', 'a', 't', 'a')
|
||
#define FOURCC_NUM mmioFOURCC('n', 'u', 'm', ' ')
|
||
#define FOURCC_XYZ mmioFOURCC('x', 'y', 'z', ' ')
|
||
|
||
dprintf("write file");
|
||
|
||
/* create 'RIFF' chunk, formtype ' */
|
||
ckRIFF.cksize = 0L;
|
||
ckRIFF.fccType = FOURCC_FOO;
|
||
WinEval(mmioCreateChunk(hmmio, &ckRIFF, MMIO_CREATERIFF) == 0);
|
||
|
||
/* create chunks 'abc1' ... 'abc7' -- the data for the i-th chunk
|
||
* is the first i uppercase letters of the alphabet
|
||
*/
|
||
for (i = 1; i <= 7; i++)
|
||
{
|
||
MMCKINFO ck;
|
||
|
||
ck.ckid = FOURCC_ABC;
|
||
((NPSTR) (&ck.ckid))[3] = (CHAR)'0' + (CHAR)i;
|
||
ck.cksize = 8 + i;
|
||
WinEval(mmioCreateChunk(hmmio, &ck, 0) == 0);
|
||
WinEval(mmioWrite(hmmio, "ABCDEFG", (LONG) i) == (LONG) i);
|
||
WinEval(mmioAscend(hmmio, &ck, 0) == 0);
|
||
}
|
||
|
||
/* create a LIST chunk with list type 'data' */
|
||
ckLIST.cksize = 0L;
|
||
ckLIST.fccType = FOURCC_DATA;
|
||
WinEval(mmioCreateChunk(hmmio, &ckLIST, MMIO_CREATELIST) == 0);
|
||
|
||
/* create chunks 'num1' ... 'num9' -- the data for the i-th chunk
|
||
* is the first i positive numbers
|
||
*/
|
||
for (i = 1; i <= 9; i++)
|
||
{
|
||
ck.ckid = FOURCC_NUM;
|
||
((NPSTR) (&ck.ckid))[3] = (CHAR)'0' + (CHAR)i;
|
||
ck.cksize = 77; // make medAscend() work for a living
|
||
WinEval(mmioCreateChunk(hmmio, &ck, 0) == 0);
|
||
WinEval(mmioWrite(hmmio, "123456789", (LONG) i) == (LONG) i);
|
||
WinEval(mmioAscend(hmmio, &ck, 0) == 0);
|
||
}
|
||
|
||
/* ascend from the LIST chunk */
|
||
WinEval(mmioAscend(hmmio, &ckLIST, 0) == 0);
|
||
|
||
/* write 'xyz' chunk to contain 123456 bytes that are filled with
|
||
* short integers 0 to 123456/2 - 1; make the buffer misaligned
|
||
* by 32768 bytes
|
||
*/
|
||
|
||
if ((pchBuf = GAllocPtr(123456L + 32768L)) == NULL)
|
||
{
|
||
dprintf("test program problem: out of memory\n");
|
||
WinAssert(FALSE);
|
||
}
|
||
pchStart = pchBuf + 32768L;
|
||
|
||
for (pi = (int huge *) pchStart, i = 0; i < (int) (123456L / sizeof(int)); // (Win32)
|
||
pi++, i++)
|
||
*pi = i;
|
||
|
||
ck.ckid = FOURCC_XYZ;
|
||
WinEval(mmioCreateChunk(hmmio, &ck, 0) == 0);
|
||
WinEval(mmioWrite(hmmio, pchStart, 123456L) == 123456L);
|
||
WinEval(mmioAscend(hmmio, &ck, 0) == 0);
|
||
|
||
/* ascend from the RIFF chunk */
|
||
WinEval(mmioAscend(hmmio, &ckRIFF, 0) == 0);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 0x0001E332L);
|
||
|
||
/* destroy data in <pchStart>, <ck>, etc. to ensure a
|
||
* valid test
|
||
*/
|
||
#ifdef OMIT
|
||
lmemset(pchStart, 12, 123456L);
|
||
#else
|
||
memset(pchStart, 12, 123456L);
|
||
#endif //OMIT
|
||
memset(&ckRIFF, 34, sizeof(ckRIFF));
|
||
memset(&ckLIST, 56, sizeof(ckLIST));
|
||
memset(&ck, 78, sizeof(ck));
|
||
|
||
if (fReadable)
|
||
{
|
||
dprintf(", read file");
|
||
|
||
/* seek back */
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_SET) == 0L);
|
||
|
||
/* descend into RIFF chunk */
|
||
WinEval(mmioDescend(hmmio, &ckRIFF, NULL, 0) == 0);
|
||
WinAssert(ckRIFF.ckid == FOURCC_RIFF);
|
||
WinAssert(ckRIFF.cksize == 0x0001E32AL);
|
||
WinAssert(ckRIFF.fccType == FOURCC_FOO);
|
||
WinAssert(ckRIFF.dwDataOffset == 0x00000000L + 8L);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 0x0000000CL);
|
||
|
||
/* find all the 'abc' chunks */
|
||
for (i = 1; i <= 7; i++)
|
||
{
|
||
MMCKINFO ck;
|
||
char ach[10];
|
||
|
||
/* seek back to start of RIFF chunk data */
|
||
WinEval(mmioSeek(hmmio, 12L, SEEK_SET) == 12L);
|
||
ck.ckid = FOURCC_ABC;
|
||
((NPSTR) (&ck.ckid))[3] = (CHAR)'0' + (CHAR)i;
|
||
WinEval(mmioDescend(hmmio, &ck, &ckRIFF,
|
||
MMIO_FINDCHUNK) == 0);
|
||
WinAssert(ck.cksize == (UINT)i);
|
||
WinAssert(ck.fccType == 0);
|
||
WinEval(mmioRead(hmmio, ach, (LONG) i) == (LONG) i);
|
||
WinEval(lstrncmp(ach, "ABCDEFG", i) == 0);
|
||
if (i != 7)
|
||
WinEval(mmioAscend(hmmio, &ck, 0) == 0);
|
||
}
|
||
|
||
/* we're down two levels -- ascend to end of RIFF chunk */
|
||
WinEval(mmioAscend(hmmio, &ckRIFF, 0) == 0);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 0x0001E332L);
|
||
|
||
/* seek back to start of RIFF chunk data */
|
||
WinEval(mmioSeek(hmmio, 12L, SEEK_SET) == 12L);
|
||
|
||
/* make sure we cannot find 'num1' chunk */
|
||
ck.ckid = mmioFOURCC('n', 'u', 'm', '1');
|
||
WinEval(mmioDescend(hmmio, &ck, &ckRIFF, MMIO_FINDCHUNK)
|
||
== MMIOERR_CHUNKNOTFOUND);
|
||
|
||
/* seek back to start of RIFF chunk data */
|
||
WinEval(mmioSeek(hmmio, 12L, SEEK_SET) == 12L);
|
||
|
||
/* make sure we can find 'data' list */
|
||
ckLIST.fccType = FOURCC_DATA;
|
||
WinEval(mmioDescend(hmmio, &ckLIST, &ckRIFF, MMIO_FINDLIST)
|
||
== 0);
|
||
WinAssert(ckLIST.ckid == FOURCC_LIST);
|
||
WinAssert(ckLIST.fccType == FOURCC_DATA);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 0x00000064L + 12L);
|
||
|
||
/* descend into each of the 'num' chunks */
|
||
for (i = 1; i <= 9; i++)
|
||
{
|
||
FOURCC fcc;
|
||
MMCKINFO ck;
|
||
char ach[10];
|
||
|
||
fcc = FOURCC_ABC;
|
||
((NPSTR) (&fcc))[3] = (CHAR)'0' + (CHAR)i;
|
||
WinEval(mmioDescend(hmmio, &ck, &ckLIST, 0) == 0);
|
||
WinAssert(ck.cksize == (UINT)i);
|
||
WinAssert(ck.fccType == 0);
|
||
WinEval(mmioRead(hmmio, ach, (LONG) i) == (LONG) i);
|
||
WinEval(lstrncmp(ach, "123456789", i) == 0);
|
||
WinEval(mmioAscend(hmmio, &ck, 0) == 0);
|
||
}
|
||
|
||
/* make sure we cannot go any further */
|
||
WinEval(mmioDescend(hmmio, &ck, &ckLIST, 0)
|
||
== MMIOERR_CHUNKNOTFOUND);
|
||
|
||
/* seek back to start of RIFF chunk data */
|
||
WinEval(mmioSeek(hmmio, 12L, SEEK_SET) == 12L);
|
||
|
||
/* seek to the 'xyz' chunk */
|
||
ck.ckid = FOURCC_XYZ;
|
||
WinEval(mmioDescend(hmmio, &ck, &ckRIFF, MMIO_FINDCHUNK) == 0);
|
||
WinAssert(ck.ckid == FOURCC_XYZ);
|
||
WinAssert(ck.fccType == 0);
|
||
WinEval(mmioRead(hmmio, pchStart, 123456L) == 123456L);
|
||
WinEval(mmioAscend(hmmio, &ck, 0) == 0);
|
||
|
||
/* ascend from the RIFF chunk */
|
||
WinEval(mmioAscend(hmmio, &ckRIFF, 0) == 0);
|
||
WinEval(mmioSeek(hmmio, 0L, SEEK_CUR) == 0x0001E332L);
|
||
|
||
/* check the contents of the 'xyz' chunk */
|
||
for (pi = (int huge *) pchStart, i = 0; i < (int) (123456L / sizeof(int)); // (Win32)
|
||
pi++, i++)
|
||
{
|
||
WinAssert(*pi == i);
|
||
}
|
||
}
|
||
|
||
GFreePtr(pchBuf);
|
||
|
||
dprintf(", done.\n");
|
||
}
|
||
|
||
|
||
/* sz = lstrrchr(szSrc, ch)
|
||
*
|
||
* Find the last occurence <sz> (NULL if not found) of <p ch> in <p szSrc>.
|
||
*/
|
||
LPSTR NEAR PASCAL
|
||
lstrrchr(
|
||
LPSTR szSrc,
|
||
char ch)
|
||
{
|
||
LPSTR szLast = NULL;
|
||
|
||
do
|
||
{
|
||
if (*szSrc == ch)
|
||
szLast = szSrc;
|
||
} while (*szSrc++ != 0);
|
||
|
||
return szLast;
|
||
}
|
||
|
||
#ifdef OMIT
|
||
/* lmemset(pDst, bSrc, cDst)
|
||
*
|
||
* Set all <cDest> bytes in memory block <pDst> to a byte value <bSrc>.
|
||
*/
|
||
void NEAR PASCAL
|
||
lmemset(
|
||
void far *pDst,
|
||
BYTE bSrc,
|
||
long cDst)
|
||
{
|
||
while (cDst-- > 0)
|
||
*((BYTE huge *) pDst)++ = bSrc;
|
||
}
|
||
#endif //OMIT
|
||
|