mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
4.2 KiB
228 lines
4.2 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
asynchlp.c
|
|
|
|
Abstract:
|
|
|
|
This is the client windows suuport layer for async I/O requests.
|
|
|
|
Author:
|
|
|
|
Steven Zeck (stevez) 03/25/92
|
|
|
|
--*/
|
|
|
|
#include "windows.h"
|
|
#include "asynchlp.h"
|
|
|
|
// Some inline assembler for trival windows functions.
|
|
|
|
#define WinEnterCritical() _asm cli
|
|
#define WinExitCritical() _asm sti
|
|
#define int3() _asm int 3
|
|
|
|
extern HANDLE hInstanceDLL; // handle of DLL
|
|
PASYNC_REQUEST pRoot; // head of linked list of requests
|
|
PASYNC_REQUEST CurrentRequest; // current request, before yield
|
|
|
|
|
|
void _pascal _export _far
|
|
AsyncDone(
|
|
IN void _far * Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Mark an async request completed. This is called at interrupt time.
|
|
|
|
Arguments:
|
|
|
|
Context - Context of request that has been completed.
|
|
|
|
--*/
|
|
|
|
{
|
|
PASYNC_REQUEST _far * pAsyncLast, pAsyncCur;
|
|
|
|
// int3();
|
|
|
|
// Search the list of pending operations for the one done.
|
|
|
|
for (pAsyncLast = &pRoot, pAsyncCur = pRoot; pAsyncCur;
|
|
pAsyncLast = &pAsyncCur->pNext, pAsyncCur = pAsyncCur->pNext)
|
|
|
|
if (pAsyncCur->Context == Context)
|
|
{
|
|
pAsyncCur->fDone = TRUE;
|
|
|
|
// If the dialog has initialized itself, send a message to
|
|
// it to quit, which will return control to AsyncReadWrite().
|
|
|
|
if (pAsyncCur->hWnd)
|
|
PostMessage(pAsyncCur->hWnd, WM_USER, END_DIALOG, 0);
|
|
|
|
// remove the completed async block from the list
|
|
|
|
*pAsyncLast = pAsyncCur->pNext;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
unsigned int _far _pascal _export
|
|
BusyBox(
|
|
IN HWND hDialog,
|
|
IN unsigned Message,
|
|
IN unsigned int wParam,
|
|
IN LONG lParam
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the dialog procedure for the dialog which allows
|
|
the user to switch away from the application.
|
|
|
|
Arguments:
|
|
|
|
hDialog - handle of dialog block.
|
|
|
|
Message - windows message value.
|
|
|
|
wParam - parameter work, contains our private message token to quit.
|
|
|
|
lParam - unused.
|
|
|
|
Returns:
|
|
|
|
FALSE
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (Message){
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
// Fill in my window handle so I can receive the finished message.
|
|
|
|
WinEnterCritical();
|
|
|
|
if (!CurrentRequest->fDone)
|
|
CurrentRequest->hWnd = hDialog;
|
|
|
|
WinExitCritical();
|
|
|
|
if (CurrentRequest->fDone)
|
|
EndDialog(hDialog, 0);
|
|
|
|
break;
|
|
|
|
// I recieved the Quit message from the asyncDone function, so
|
|
// remove the dialog and return to AsyncSendReceive.
|
|
|
|
case WM_USER:
|
|
if (wParam == END_DIALOG)
|
|
EndDialog(hDialog, 0);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
unsigned short _pascal _far
|
|
AsyncInitialize (
|
|
OUT PASYNC_REQUEST AsyncBlock,
|
|
IN void _far * Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get an Async request ready to be initialed.
|
|
|
|
Arguments:
|
|
|
|
AsyncBlock - the async block that we are about to initialize.
|
|
|
|
Context - context value that is call with Async Done by the
|
|
transport at interrupt time.
|
|
|
|
Returns:
|
|
|
|
TRUE if initialization was OK, else FALSE for dead lock detected.
|
|
|
|
--*/
|
|
|
|
{
|
|
PASYNC_REQUEST AsyncItem;
|
|
HANDLE TaskSelf = GetCurrentTask();
|
|
|
|
// Scan the list of pending request to detect deadlock.
|
|
|
|
for ( AsyncItem = pRoot; AsyncItem; AsyncItem = AsyncItem->pNext)
|
|
if (AsyncItem->Owner == TaskSelf)
|
|
return(FALSE);
|
|
|
|
// int3();
|
|
|
|
// Link the request into list of active requests.
|
|
|
|
WinEnterCritical();
|
|
|
|
AsyncBlock->Owner = TaskSelf;
|
|
AsyncBlock->hWnd = 0;
|
|
AsyncBlock->fDone = FALSE;
|
|
AsyncBlock->TimeRequested = GetCurrentTime();
|
|
AsyncBlock->Context = Context;
|
|
|
|
CurrentRequest = AsyncBlock;
|
|
|
|
AsyncBlock->pNext = pRoot;
|
|
pRoot = AsyncBlock;
|
|
|
|
WinExitCritical();
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
void _pascal _far
|
|
AsyncWait (
|
|
OUT PASYNC_REQUEST AsyncBlock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Wait for an Async request to finish.
|
|
|
|
Arguments:
|
|
|
|
AsyncBlock - the async block that we want to wait for.
|
|
|
|
--*/
|
|
|
|
{
|
|
// The async request is now pending. If the operation doesn't
|
|
// complete soon, then put up a dialog box which tells the user
|
|
// that an RPC request is pending which will allow them to
|
|
// switch away.
|
|
|
|
while(! AsyncBlock->fDone)
|
|
{
|
|
|
|
// Yield();
|
|
|
|
if (GetCurrentTime() > AsyncBlock->TimeRequested + AsyncDelay)
|
|
DialogBox (hInstanceDLL, "BUSYBOX", GetFocus(), BusyBox);
|
|
}
|
|
}
|