/*********************************************************************** * VXD_Timer (WPROCS.405) */ void WINAPI VXD_Timer( CONTEXT86 *context ) { unsigned service = AX_reg(context); TRACE("[%04x] Virtual Timer\n", (UINT16)service); switch(service) { case 0x0000: /* version */ AX_reg(context) = VXD_WinVersion(); RESET_CFLAG(context); break; case 0x0100: /* clock tick time, in 840nsecs */ context->Eax = NtGetTickCount(); context->Edx = context->Eax >> 22; context->Eax <<= 10; /* not very precise */ break; case 0x0101: /* current Windows time, msecs */ case 0x0102: /* current VM time, msecs */ context->Eax = NtGetTickCount(); break; default: VXD_BARF( context, "VTD" ); } }
/*********************************************************************** * DeviceIo_VTDAPI */ static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPOVERLAPPED lpOverlapped) { BOOL retv = TRUE; switch (dwIoControlCode) { case 5: if (lpvOutBuffer && (cbOutBuffer>=4)) *(DWORD*)lpvOutBuffer = NtGetTickCount(); if (lpcbBytesReturned) *lpcbBytesReturned = 4; break; default: FIXME( "Control %ld not implemented\n", dwIoControlCode); retv = FALSE; break; } return retv; }
/***************************************************************************\ * SetLastDDEMLError * * Description: * Sets last error value and generates monitor events if monitoring. * * History: * 11-19-91 sanfords Created. \***************************************************************************/ VOID SetLastDDEMLError( PCL_INSTANCE_INFO pcii, DWORD error) { PEVENT_PACKET pep; if (pcii->MonitorFlags & MF_ERRORS && !(pcii->afCmd & APPCLASS_MONITOR)) { pep = (PEVENT_PACKET)DDEMLAlloc(sizeof(EVENT_PACKET) - sizeof(DWORD) + sizeof(MONERRSTRUCT)); if (pep != NULL) { pep->EventType = MF_ERRORS; pep->fSense = TRUE; pep->cbEventData = sizeof(MONERRSTRUCT); #define perrs ((MONERRSTRUCT *)&pep->Data) perrs->cb = sizeof(MONERRSTRUCT); perrs->wLastError = (WORD)error; perrs->dwTime = NtGetTickCount(); perrs->hTask = (HANDLE)pcii->tid; #undef perrs LeaveDDECrit; Event(pep); EnterDDECrit; } } #ifdef DEBUG if (error != 0 && error != DMLERR_NO_CONV_ESTABLISHED) { RIPMSG3(RIP_WARNING, "DDEML Error set=%x, Client Instance=%x, Process=%x.", error, pcii, GetCurrentProcessId()); } #endif pcii->LastError = error; }
/***************************************************************************\ * xxxMessageEvent * * Description: Called when a hooked DDE message is sent or posted. flags * specifies the applicable MF_ flag. This is called in the server side * context of the sender or poster which may or may not be a DDEML process. * pdmhd contains DDE data extracted and copied from the client side. * * History: * 12-1-91 sanfords Created. \***************************************************************************/ VOID xxxMessageEvent( PWND pwndTo, UINT message, WPARAM wParam, LPARAM lParam, DWORD flag, PDDEML_MSG_HOOK_DATA pdmhd) { PEVENT_PACKET pep; PWND pwndFrom; TL tlpep; PTHREADINFO pti; CheckCritIn(); pep = (PEVENT_PACKET)UserAllocPoolWithQuota(sizeof(EVENT_PACKET) - sizeof(DWORD) + sizeof(MONMSGSTRUCT), TAG_DDE8); if (pep == NULL) { return; } pep->EventType = flag; pep->fSense = TRUE; pep->cbEventData = sizeof(MONMSGSTRUCT); #define pmsgs ((MONMSGSTRUCT *)&pep->Data) pmsgs->cb = sizeof(MONMSGSTRUCT); pmsgs->hwndTo = PtoH(pwndTo); pmsgs->dwTime = NtGetTickCount(); pwndFrom = RevalidateHwnd((HWND)wParam); if (pwndFrom != NULL) { pmsgs->hTask = GETPTI(pwndFrom)->pEThread->Cid.UniqueThread; } else { pmsgs->hTask = 0; } pmsgs->wMsg = message; pmsgs->wParam = wParam; pmsgs->lParam = lParam; if (pdmhd != NULL) { pmsgs->dmhd = *pdmhd; } #undef pmsgs pti = PtiCurrent(); ThreadLockPool(pti, pep, &tlpep); xxxCsEvent(pep, sizeof(MONMSGSTRUCT)); ThreadUnlockAndFreePool(pti, &tlpep); }
BOOL TooltipAnimate(PTOOLTIPWND pttwnd) { int y, yMem, yReal, ny, iy, cx, cy; DWORD dwElapsed; HDC hdc; BOOL fRet = FALSE; if (pttwnd->pstr == NULL) return TRUE; hdc = GetTooltipDC(pttwnd); cx = pttwnd->rcWindow.right - pttwnd->rcWindow.left; cy = pttwnd->rcWindow.bottom - pttwnd->rcWindow.top; dwElapsed = NtGetTickCount() - pttwnd->dwAnimStart; iy = MultDiv(cy, dwElapsed, CMS_TOOLTIP); if (dwElapsed > CMS_TOOLTIP || iy == cy) { GreBitBlt(hdc, 0, 0, cx, cy, pttwnd->hdcMem, 0, 0, SRCCOPY | NOMIRRORBITMAP, 0); fRet = TRUE; goto Cleanup; } else if (pttwnd->iyAnim == iy) { goto Cleanup; } if (pttwnd->dwFlags & TTF_POSITIVE) { y = 0; ny = 0; } else { y = cy; ny = -1; } yReal = y + ny * iy; yMem = (pttwnd->dwFlags & TTF_POSITIVE) ? cy - iy : 0; pttwnd->iyAnim = iy; GreBitBlt(hdc, 0, yReal, cx, iy, pttwnd->hdcMem, 0, yMem, SRCCOPY | NOMIRRORBITMAP, 0); Cleanup: _ReleaseDC(hdc); return fRet; }
LRESULT xxxTooltipWndProc(PWND pwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; PTOOLTIPWND pttwnd; CheckLock(pwnd); VALIDATECLASSANDSIZE(pwnd, uMsg, wParam, lParam, FNID_TOOLTIP, WM_NCCREATE); pttwnd = (PTOOLTIPWND)pwnd; switch(uMsg) { case WM_TIMER: xxxTooltipHandleTimer(pttwnd, (UINT)wParam); break; case WM_PAINT: xxxBeginPaint(pwnd, &ps); TooltipRender(pttwnd, ps.hdc); xxxEndPaint(pwnd, &ps); break; case WM_PRINTCLIENT: TooltipRender(pttwnd, (HDC)wParam); break; case WM_ERASEBKGND: break; case WM_NCCREATE: InitTooltipDelay(pttwnd); InitTooltipAnimation(pttwnd); goto CallDWP; case WM_NCDESTROY: CleanupTooltipAnimation(pttwnd); GETPDESK(pttwnd)->dwDTFlags &= ~DF_TOOLTIP; goto CallDWP; case WM_WINDOWPOSCHANGED: if (((LPWINDOWPOS)lParam)->flags & SWP_SHOWWINDOW) { HDC hdc; int cx; int cy; if (!TestEffectUP(TOOLTIPANIMATION)) { SetTooltipTimer(pttwnd, TTT_HIDE, pttwnd->dwHideDelay); goto CallDWP; } hdc = NULL; cx = pttwnd->rcWindow.right - pttwnd->rcWindow.left; cy = pttwnd->rcWindow.bottom - pttwnd->rcWindow.top; /* * At this point we're sure that the window is showing and the size * has been changed and we're in the context of the desktop thread. */ if (TestALPHA(TOOLTIPFADE)) { hdc = CreateFade((PWND)pttwnd, NULL, CMS_TOOLTIP, FADE_SHOW | FADE_TOOLTIP); } else { if (CreateTooltipBitmap(pttwnd, cx, cy)) { hdc = pttwnd->hdcMem; } } if (hdc == NULL) { SetTooltipTimer(pttwnd, TTT_HIDE, 0); goto CallDWP; } xxxSendMessage((PWND)pttwnd, WM_PRINT, (WPARAM)hdc, PRF_CLIENT | PRF_NONCLIENT | PRF_CHILDREN | PRF_ERASEBKGND); /* * Start animation timer */ if (TestFadeFlags(FADE_TOOLTIP)) { StartFade(); SetTooltipTimer(pttwnd, TTT_HIDE, pttwnd->dwHideDelay); } else { pttwnd->dwAnimStart = NtGetTickCount(); SetTooltipTimer(pttwnd, TTT_ANIMATE, TT_ANIMATEDELAY); } } else if (((LPWINDOWPOS)lParam)->flags & SWP_HIDEWINDOW) { if (TestFadeFlags(FADE_TOOLTIP)) { StopFade(); } else { DestroyTooltipBitmap(pttwnd); } } goto CallDWP; default: CallDWP: return xxxDefWindowProc(pwnd, uMsg, wParam, lParam); } return 0; }
/***************************************************************************\ * DoCallback * * Description: * Performs a synchronous callback to the given instance's callback proc. * * History: * 11-12-91 sanfords Created. \***************************************************************************/ HDDEDATA DoCallback( PCL_INSTANCE_INFO pcii, WORD wType, WORD wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dw1, DWORD dw2) { HDDEDATA hDataRet; PCLIENTINFO pci; CheckDDECritIn; /* * Zombie conversations don't generate callbacks! */ if (hConv && TypeFromHandle(hConv) == HTYPE_ZOMBIE_CONVERSATION) { return(0); } pci = GetClientInfo(); pci->cInDDEMLCallback++; pcii->cInDDEMLCallback++; pci->hDdemlCallbackInst = pcii->hInstClient; LeaveDDECrit; CheckDDECritOut; hDataRet = (*pcii->pfnCallback)((UINT)wType, (UINT)wFmt, hConv, hsz1, hsz2, hData, dw1, dw2); EnterDDECrit; pcii->cInDDEMLCallback--; pci->cInDDEMLCallback--; if (!(pcii->afCmd & APPCLASS_MONITOR) && pcii->MonitorFlags & MF_CALLBACKS) { PEVENT_PACKET pep; pep = (PEVENT_PACKET)DDEMLAlloc(sizeof(EVENT_PACKET) - sizeof(DWORD) + sizeof(MONCBSTRUCT)); if (pep != NULL) { pep->EventType = MF_CALLBACKS; pep->fSense = TRUE; pep->cbEventData = sizeof(MONCBSTRUCT); #define pcbs ((MONCBSTRUCT *)&pep->Data) pcbs->cb = sizeof(MONCBSTRUCT); pcbs->dwTime = NtGetTickCount(); pcbs->hTask = (HANDLE)pcii->tid; pcbs->dwRet = (DWORD)hDataRet; pcbs->wType = wType; pcbs->wFmt = wFmt; pcbs->hConv = hConv; pcbs->hsz1 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1)); pcbs->hsz2 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz2)); pcbs->hData = hData; pcbs->dwData1 = dw1; pcbs->dwData2 = dw2; if (((wType == XTYP_CONNECT) || (wType == XTYP_WILDCONNECT)) && dw1) { RtlCopyMemory(&pcbs->cc, (PVOID)dw1, sizeof(CONVCONTEXT)); } LeaveDDECrit; if (wType & XCLASS_DATA) { if (hDataRet && hDataRet != CBR_BLOCK) { pcbs->cbData = DdeGetData(hDataRet, (LPBYTE)pcbs->Data, 32, 0); } } else if (hData) { pcbs->cbData = DdeGetData(hData, (LPBYTE)pcbs->Data, 32, 0); } Event(pep); EnterDDECrit; GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz1)); GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz2)); DDEMLFree(pep); #undef pcbs } } return (hDataRet); }
VOID VdmTraceEvent( USHORT Type, USHORT wData, USHORT lData, PKTRAP_FRAME TrapFrame ) /*++ Routine Description: Arguments: Return Value: None --*/ { PVDM_TIB VdmTib; NTSTATUS Status = STATUS_SUCCESS; KIRQL OldIrql; PVDM_TRACEENTRY pEntry; PVDM_TRACEINFO pInfo; LARGE_INTEGER CurTime, DiffTime; PAGED_CODE(); #if 0 // This code represents a security problem. Since it is only used // on special occasions, it won't be built into the standard build. // Individuals wishing to use it can build themselves a kernel with // it in. #if 0 // // Raise Irql to APC level... // KeRaiseIrql(APC_LEVEL, &OldIrql); // // VdmTib is in user mode memory // try { #endif if ((*(ULONG *)(FIXED_NTVDMSTATE_LINEAR) & VDM_TRACE_HISTORY)) { // // Get a pointer to the VdmTib // VdmTib = NtCurrentTeb()->Vdm; if (VdmTib->TraceInfo.pTraceTable) { pEntry = &VdmTib->TraceInfo.pTraceTable[VdmTib->TraceInfo.CurrentEntry]; pEntry->Type = Type; pEntry->wData = wData; pEntry->lData = lData; switch (VdmTib->TraceInfo.Flags & VDMTI_TIMER_MODE) { case VDMTI_TIMER_TICK: CurTime.LowPart = NtGetTickCount(); pEntry->Time = CurTime.LowPart - VdmTib->TraceInfo.TimeStamp.LowPart; VdmTib->TraceInfo.TimeStamp.LowPart = CurTime.LowPart; break; case VDMTI_TIMER_PERFCTR: pEntry->Time = 0; break; case VDMTI_TIMER_STAT: pEntry->Time = 0; break; } pEntry->eax = TrapFrame->Eax; pEntry->ebx = TrapFrame->Ebx; pEntry->ecx = TrapFrame->Ecx; pEntry->edx = TrapFrame->Edx; pEntry->esi = TrapFrame->Esi; pEntry->edi = TrapFrame->Edi; pEntry->ebp = TrapFrame->Ebp; pEntry->esp = TrapFrame->HardwareEsp; pEntry->eip = TrapFrame->Eip; pEntry->eflags = TrapFrame->EFlags; pEntry->cs = (USHORT) TrapFrame->SegCs; pEntry->ds = (USHORT) TrapFrame->SegDs; pEntry->es = (USHORT) TrapFrame->SegEs; pEntry->fs = (USHORT) TrapFrame->SegFs; pEntry->gs = (USHORT) TrapFrame->SegGs; pEntry->ss = (USHORT) TrapFrame->HardwareSegSs; if (++VdmTib->TraceInfo.CurrentEntry >= (VdmTib->TraceInfo.NumPages*4096/sizeof(VDM_TRACEENTRY))) { VdmTib->TraceInfo.CurrentEntry = 0; } } } #if 0 } except(EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); } KeLowerIrql(OldIrql); #endif #endif }
/*********************************************************************** * GetTickCount (KERNEL32.@) * * Returns the number of milliseconds, modulo 2^32, since the start * of the wineserver. */ DWORD WINAPI GetTickCount () { return (DWORD)NtGetTickCount (); }
/* IO_pp_init * * Read the ppdev entries from wine.conf, open the device and check * for nescessary IOCTRL * Report verbose about possible errors */ char IO_pp_init(void) { char name[80]; char buffer[1024]; HKEY hkey; char temp[256]; int i,idx=0,fd,res,userbase,nports=0; char * timeout; char ret=1; int lasterror; TRACE("\n"); if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\ppdev", &hkey ) != ERROR_SUCCESS) return 1; for (;;) { DWORD type, count = sizeof(buffer), name_len = sizeof(name); if (RegEnumValueA( hkey, idx, name, &name_len, NULL, &type, (LPBYTE)buffer, &count )!= ERROR_SUCCESS) break; idx++; if(nports >4) { FIXME("Make the PPDeviceList larger then 5 elements\n"); break; } TRACE("Device '%s' at virtual userbase '%s'\n", buffer,name); timeout = strchr(buffer,','); if (timeout) *timeout++=0; fd=open(buffer,O_RDWR); lasterror=errno; if (fd == -1) { WARN("Configuration: No access to %s Cause: %s\n",buffer,strerror(lasterror)); WARN("Rejecting configuration item\n"); if (lasterror == ENODEV) FIXME("Is the ppdev module loaded?\n"); continue; } userbase = strtol(name,(char **)NULL, 16); if ( errno == ERANGE) { WARN("Configuration: Invalid base %s for %s\n",name,buffer); WARN("Rejecting configuration item\n"); continue; } if (ioctl (fd,PPCLAIM,0)) { ERR("PPCLAIM rejected %s\n",buffer); ERR("Perhaps the device is already in use or non-existant\n"); continue; } if (nports > 0) { for (i=0; i<= nports; i++) { if (PPDeviceList[i].userbase == userbase) { WARN("Configuration: %s uses the same virtual ports as %s\n", buffer,PPDeviceList[0].devicename); WARN("Configuration: Rejecting configuration item"); userbase = 0; break; } } if (!userbase) continue; } /* Check for the minimum required IOCTLS */ if ((ioctl(fd,PPRDATA,&res))|| (ioctl(fd,PPRCONTROL,&res))|| (ioctl(fd,PPRCONTROL,&res))) { ERR("PPUSER IOCTL not available for parport device %s\n",temp); continue; } if (ioctl (fd,PPRELEASE,0)) { ERR("PPRELEASE rejected %s\n",buffer); ERR("Perhaps the device is already in use or non-existant\n"); continue; } PPDeviceList[nports].devicename = malloc(sizeof(buffer)+1); if (!PPDeviceList[nports].devicename) { ERR("No (more)space for devicename\n"); break; } strcpy(PPDeviceList[nports].devicename,buffer); PPDeviceList[nports].fd = fd; PPDeviceList[nports].userbase = userbase; PPDeviceList[nports].lastaccess=NtGetTickCount(); if (timeout) { PPDeviceList[nports].timeout = strtol(timeout,(char **)NULL, 10); if (errno == ERANGE) { WARN("Configuration:Invalid timeout %s in configuration for %s, Setting to 0\n", timeout,buffer); PPDeviceList[nports].timeout = 0; } } else PPDeviceList[nports].timeout = 0; nports++; } TRACE("found %d ports\n",nports); RegCloseKey( hkey ); PPDeviceNum= nports; if (nports > 1) /* sort in accending order for userbase for faster access*/ qsort (PPDeviceList,PPDeviceNum,sizeof(PPDeviceStruct),IO_pp_sort); if (nports) ret=0; for (idx= 0;idx<PPDeviceNum; idx++) TRACE("found device %s userbase %x fd %x timeout %d\n", PPDeviceList[idx].devicename, PPDeviceList[idx].userbase, PPDeviceList[idx].fd,PPDeviceList[idx].timeout); /* FIXME: register a timer callback perhaps every 30 second to release unused ports Set lastaccess = 0 as indicator when port was released */ return ret; }