static NTSTATUS NTAPI ConfigCallback(PVOID Context, PUNICODE_STRING PathName, INTERFACE_TYPE BusType, ULONG BusNumber, PKEY_VALUE_FULL_INFORMATION *BusInformation, CONFIGURATION_TYPE ControllerType, ULONG ControllerNumber, PKEY_VALUE_FULL_INFORMATION *ControllerInformation, CONFIGURATION_TYPE PeripheralType, ULONG PeripheralNumber, PKEY_VALUE_FULL_INFORMATION *PeripheralInformation) /* * FUNCTION: Callback to IoQueryDeviceDescription, which tells us about our controllers * ARGUMENTS: * Context: Unused * PathName: Unused * BusType: Type of the bus that our controller is on * BusNumber: Number of the bus that our controller is on * BusInformation: Unused * ControllerType: Unused * ControllerNumber: Number of the controller that we're adding * ControllerInformation: Full configuration information for our controller * PeripheralType: Unused * PeripheralNumber: Unused * PeripheralInformation: Full configuration information for each drive on our controller * RETURNS: * STATUS_SUCCESS in all cases * NOTES: * - The only documentation I've found about the contents of these structures is * from the various Microsoft floppy samples and from the DDK headers. They're * very vague, though, so I'm only mostly sure that this stuff is correct, as * the MS samples do things completely differently than I have done them. Seems * to work in my VMWare, though. * - Basically, the function gets all of the information (port, dma, irq) about the * controller, and then loops through all of the drives presented in PeripheralInformation. * - Each controller has a CONTROLLER_INFO created for it, and each drive has a DRIVE_INFO. * - Device objects are created for each drive (not controller), as that's the targeted * device in the eyes of the rest of the OS. Each DRIVE_INFO points to a single CONTROLLER_INFO. * - We only support up to four controllers in the whole system, each of which supports up to four * drives. */ { PKEY_VALUE_FULL_INFORMATION ControllerFullDescriptor = ControllerInformation[IoQueryDeviceConfigurationData]; PCM_FULL_RESOURCE_DESCRIPTOR ControllerResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)ControllerFullDescriptor + ControllerFullDescriptor->DataOffset); PKEY_VALUE_FULL_INFORMATION PeripheralFullDescriptor = PeripheralInformation[IoQueryDeviceConfigurationData]; PCM_FULL_RESOURCE_DESCRIPTOR PeripheralResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)PeripheralFullDescriptor + PeripheralFullDescriptor->DataOffset); PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PCM_FLOPPY_DEVICE_DATA FloppyDeviceData; UCHAR i; PAGED_CODE(); UNREFERENCED_PARAMETER(PeripheralType); UNREFERENCED_PARAMETER(PeripheralNumber); UNREFERENCED_PARAMETER(BusInformation); UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(ControllerType); UNREFERENCED_PARAMETER(PathName); TRACE_(FLOPPY, "ConfigCallback called with ControllerNumber %d\n", ControllerNumber); gControllerInfo[gNumberOfControllers].ControllerNumber = ControllerNumber; gControllerInfo[gNumberOfControllers].InterfaceType = BusType; gControllerInfo[gNumberOfControllers].BusNumber = BusNumber; /* Get controller interrupt level/vector, dma channel, and port base */ for(i = 0; i < ControllerResourceDescriptor->PartialResourceList.Count; i++) { KeInitializeEvent(&gControllerInfo[gNumberOfControllers].SynchEvent, NotificationEvent, FALSE); PartialDescriptor = &ControllerResourceDescriptor->PartialResourceList.PartialDescriptors[i]; if(PartialDescriptor->Type == CmResourceTypeInterrupt) { gControllerInfo[gNumberOfControllers].Level = PartialDescriptor->u.Interrupt.Level; gControllerInfo[gNumberOfControllers].Vector = PartialDescriptor->u.Interrupt.Vector; if(PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) gControllerInfo[gNumberOfControllers].InterruptMode = Latched; else gControllerInfo[gNumberOfControllers].InterruptMode = LevelSensitive; } else if(PartialDescriptor->Type == CmResourceTypePort) { PHYSICAL_ADDRESS TranslatedAddress; ULONG AddressSpace = 0x1; /* I/O Port Range */ if(!HalTranslateBusAddress(BusType, BusNumber, PartialDescriptor->u.Port.Start, &AddressSpace, &TranslatedAddress)) { WARN_(FLOPPY, "HalTranslateBusAddress failed; returning\n"); return STATUS_IO_DEVICE_ERROR; } if(AddressSpace == 0) gControllerInfo[gNumberOfControllers].BaseAddress = MmMapIoSpace(TranslatedAddress, FDC_PORT_BYTES, MmNonCached); else gControllerInfo[gNumberOfControllers].BaseAddress = (PUCHAR)(ULONG_PTR)TranslatedAddress.QuadPart; } else if(PartialDescriptor->Type == CmResourceTypeDma) gControllerInfo[gNumberOfControllers].Dma = PartialDescriptor->u.Dma.Channel; } /* Start with 0 drives, then go looking */ gControllerInfo[gNumberOfControllers].NumberOfDrives = 0; /* learn about drives attached to controller */ for(i = 0; i < PeripheralResourceDescriptor->PartialResourceList.Count; i++) { PDRIVE_INFO DriveInfo = &gControllerInfo[gNumberOfControllers].DriveInfo[i]; PartialDescriptor = &PeripheralResourceDescriptor->PartialResourceList.PartialDescriptors[i]; if(PartialDescriptor->Type != CmResourceTypeDeviceSpecific) continue; FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)(PartialDescriptor + 1); DriveInfo->ControllerInfo = &gControllerInfo[gNumberOfControllers]; DriveInfo->UnitNumber = i; DriveInfo->FloppyDeviceData.MaxDensity = FloppyDeviceData->MaxDensity; DriveInfo->FloppyDeviceData.MountDensity = FloppyDeviceData->MountDensity; DriveInfo->FloppyDeviceData.StepRateHeadUnloadTime = FloppyDeviceData->StepRateHeadUnloadTime; DriveInfo->FloppyDeviceData.HeadLoadTime = FloppyDeviceData->HeadLoadTime; DriveInfo->FloppyDeviceData.MotorOffTime = FloppyDeviceData->MotorOffTime; DriveInfo->FloppyDeviceData.SectorLengthCode = FloppyDeviceData->SectorLengthCode; DriveInfo->FloppyDeviceData.SectorPerTrack = FloppyDeviceData->SectorPerTrack; DriveInfo->FloppyDeviceData.ReadWriteGapLength = FloppyDeviceData->ReadWriteGapLength; DriveInfo->FloppyDeviceData.FormatGapLength = FloppyDeviceData->FormatGapLength; DriveInfo->FloppyDeviceData.FormatFillCharacter = FloppyDeviceData->FormatFillCharacter; DriveInfo->FloppyDeviceData.HeadSettleTime = FloppyDeviceData->HeadSettleTime; DriveInfo->FloppyDeviceData.MotorSettleTime = FloppyDeviceData->MotorSettleTime; DriveInfo->FloppyDeviceData.MaximumTrackValue = FloppyDeviceData->MaximumTrackValue; DriveInfo->FloppyDeviceData.DataTransferLength = FloppyDeviceData->DataTransferLength; /* Once it's all set up, acknowledge its existance in the controller info object */ gControllerInfo[gNumberOfControllers].NumberOfDrives++; } gControllerInfo[gNumberOfControllers].Populated = TRUE; gNumberOfControllers++; return STATUS_SUCCESS; }
static HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) { ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface); DMUS_PRIVATE_CHUNK Chunk; DWORD StreamSize, StreamCount, ListSize[1], ListCount[1]; LARGE_INTEGER liMove; /* used when skipping chunks */ TRACE("(%p, %p, %p)\n", This, pStream, pDesc); /* FIXME: should this be determined from stream? */ pDesc->dwValidData |= DMUS_OBJ_CLASS; pDesc->guidClass = CLSID_DirectMusicStyle; IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case FOURCC_RIFF: { IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID)); StreamSize = Chunk.dwSize - sizeof(FOURCC); StreamCount = 0; if (Chunk.fccID == DMUS_FOURCC_STYLE_FORM) { TRACE_(dmfile)(": style form\n"); do { IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case DMUS_FOURCC_GUID_CHUNK: { TRACE_(dmfile)(": GUID chunk\n"); pDesc->dwValidData |= DMUS_OBJ_OBJECT; IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL); break; } case DMUS_FOURCC_VERSION_CHUNK: { TRACE_(dmfile)(": version chunk\n"); pDesc->dwValidData |= DMUS_OBJ_VERSION; IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL); break; } case DMUS_FOURCC_CATEGORY_CHUNK: { TRACE_(dmfile)(": category chunk\n"); pDesc->dwValidData |= DMUS_OBJ_CATEGORY; IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL); break; } case FOURCC_LIST: { IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[0] = Chunk.dwSize - sizeof(FOURCC); ListCount[0] = 0; switch (Chunk.fccID) { /* evil M$ UNFO list, which can (!?) contain INFO elements */ case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes (though strings seem to be valid unicode) */ case mmioFOURCC('I','N','A','M'): case DMUS_FOURCC_UNAM_CHUNK: { TRACE_(dmfile)(": name chunk\n"); pDesc->dwValidData |= DMUS_OBJ_NAME; IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL); break; } case mmioFOURCC('I','A','R','T'): case DMUS_FOURCC_UART_CHUNK: { TRACE_(dmfile)(": artist chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','C','O','P'): case DMUS_FOURCC_UCOP_CHUNK: { TRACE_(dmfile)(": copyright chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','S','B','J'): case DMUS_FOURCC_USBJ_CHUNK: { TRACE_(dmfile)(": subject chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','C','M','T'): case DMUS_FOURCC_UCMT_CHUNK: { TRACE_(dmfile)(": comment chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); break; } default: { TRACE_(dmfile)(": unknown (skipping)\n"); liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize); } while (StreamCount < StreamSize); } else { TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); liMove.QuadPart = StreamSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ return E_FAIL; } TRACE_(dmfile)(": reading finished\n"); break; } default: { TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ return DMUS_E_INVALIDFILE; } } TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc)); return S_OK; }
static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) { /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/ HRESULT hr = E_FAIL; DMUS_PRIVATE_CHUNK Chunk; DWORD ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ DMUS_OBJECTDESC desc; DWORD dwSize = 0; DWORD cnt = 0; if (pChunk->fccID != DMUS_FOURCC_PART_LIST) { ERR_(dmfile)(": %s chunk should be a PART list\n", debugstr_fourcc (pChunk->fccID)); return E_FAIL; } ListSize[0] = pChunk->dwSize - sizeof(FOURCC); ListCount[0] = 0; do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case DMUS_FOURCC_PART_CHUNK: { TRACE_(dmfile)(": Part chunk (skipping for now)\n" ); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case DMUS_FOURCC_NOTE_CHUNK: { TRACE_(dmfile)(": Note chunk (skipping for now)\n"); IStream_Read (pStm, &dwSize, sizeof(DWORD), NULL); cnt = (Chunk.dwSize - sizeof(DWORD)); TRACE_(dmfile)(" - dwSize: %u\n", dwSize); TRACE_(dmfile)(" - cnt: %u (%u / %u)\n", cnt / dwSize, (DWORD)(Chunk.dwSize - sizeof(DWORD)), dwSize); if (cnt % dwSize != 0) { ERR("Invalid Array Size\n"); return E_FAIL; } cnt /= dwSize; /** skip for now */ liMove.QuadPart = cnt * dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case DMUS_FOURCC_CURVE_CHUNK: { TRACE_(dmfile)(": Curve chunk (skipping for now)\n"); IStream_Read (pStm, &dwSize, sizeof(DWORD), NULL); cnt = (Chunk.dwSize - sizeof(DWORD)); TRACE_(dmfile)(" - dwSize: %u\n", dwSize); TRACE_(dmfile)(" - cnt: %u (%u / %u)\n", cnt / dwSize, (DWORD)(Chunk.dwSize - sizeof(DWORD)), dwSize); if (cnt % dwSize != 0) { ERR("Invalid Array Size\n"); return E_FAIL; } cnt /= dwSize; /** skip for now */ liMove.QuadPart = cnt * dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case DMUS_FOURCC_MARKER_CHUNK: { TRACE_(dmfile)(": Marker chunk (skipping for now)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case DMUS_FOURCC_RESOLUTION_CHUNK: { TRACE_(dmfile)(": Resolution chunk (skipping for now)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case DMUS_FOURCC_ANTICIPATION_CHUNK: { TRACE_(dmfile)(": Anticipation chunk (skipping for now)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case FOURCC_LIST: { IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[1] = Chunk.dwSize - sizeof(FOURCC); ListCount[1] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &desc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { switch (Chunk.fccID) { default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } } TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]); } while (ListCount[1] < ListSize[1]); break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); return S_OK; }
NTSTATUS NTAPI SerialSetLineControl( IN PSERIAL_DEVICE_EXTENSION DeviceExtension, IN PSERIAL_LINE_CONTROL NewSettings) { PUCHAR ComPortBase; UCHAR Lcr = 0; NTSTATUS Status; ASSERT(DeviceExtension); ASSERT(NewSettings); TRACE_(SERIAL, "SerialSetLineControl(COM%lu, Settings { %lu %lu %lu })\n", DeviceExtension->ComPort, NewSettings->StopBits, NewSettings->Parity, NewSettings->WordLength); /* Verify parameters */ switch (NewSettings->WordLength) { case 5: Lcr |= SR_LCR_CS5; break; case 6: Lcr |= SR_LCR_CS6; break; case 7: Lcr |= SR_LCR_CS7; break; case 8: Lcr |= SR_LCR_CS8; break; default: return STATUS_INVALID_PARAMETER; } if (NewSettings->WordLength < 5 || NewSettings->WordLength > 8) return STATUS_INVALID_PARAMETER; switch (NewSettings->Parity) { case NO_PARITY: Lcr |= SR_LCR_PNO; break; case ODD_PARITY: Lcr |= SR_LCR_POD; break; case EVEN_PARITY: Lcr |= SR_LCR_PEV; break; case MARK_PARITY: Lcr |= SR_LCR_PMK; break; case SPACE_PARITY: Lcr |= SR_LCR_PSP; break; default: return STATUS_INVALID_PARAMETER; } switch (NewSettings->StopBits) { case STOP_BIT_1: Lcr |= SR_LCR_ST1; break; case STOP_BITS_1_5: if (NewSettings->WordLength != 5) return STATUS_INVALID_PARAMETER; Lcr |= SR_LCR_ST2; break; case STOP_BITS_2: if (NewSettings->WordLength < 6 || NewSettings->WordLength > 8) return STATUS_INVALID_PARAMETER; Lcr |= SR_LCR_ST2; break; default: return STATUS_INVALID_PARAMETER; } /* Update current parameters */ ComPortBase = ULongToPtr(DeviceExtension->BaseAddress); Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (!NT_SUCCESS(Status)) return Status; WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr); /* Read junk out of RBR */ READ_PORT_UCHAR(SER_RBR(ComPortBase)); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) DeviceExtension->SerialLineControl = *NewSettings; return Status; }
PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, const char *thread_name, pj_thread_proc *proc, void *arg, pj_size_t stack_size, unsigned flags, pj_thread_t **ptr_thread) { pj_thread_t *thread; TRACE_((THIS_FILE, "pj_thread_create()")); PJ_ASSERT_RETURN(pool && proc && ptr_thread, PJ_EINVAL); thread = pj_pool_zalloc(pool, sizeof(pj_thread_t)); if (!thread) return PJ_ENOMEM; PJ_UNUSED_ARG(stack_size); /* Thread name. */ if (!thread_name) thread_name = "thr%p"; if (strchr(thread_name, '%')) { pj_snprintf(thread->obj_name, PJ_MAX_OBJ_NAME, thread_name, thread); } else { strncpy(thread->obj_name, thread_name, PJ_MAX_OBJ_NAME); thread->obj_name[PJ_MAX_OBJ_NAME-1] = '\0'; } /* Init thread's semaphore. */ TRACE_((THIS_FILE, "...init semaphores...")); init_MUTEX_LOCKED(&thread->startstop_sem); init_MUTEX_LOCKED(&thread->suspend_sem); thread->flags = flags; if ((flags & PJ_THREAD_SUSPENDED) == 0) { up(&thread->suspend_sem); } /* Store the functions and argument. */ thread->func = proc; thread->arg = arg; /* Save return value. */ *ptr_thread = thread; /* Create the new thread by running a task through keventd. */ #if 0 /* Initialize the task queue struct. */ thread->tq.sync = 0; INIT_LIST_HEAD(&thread->tq.list); thread->tq.routine = kthread_launcher; thread->tq.data = thread; /* and schedule it for execution. */ schedule_task(&thread->tq); #endif kthread_launcher(thread); /* Wait until thread has reached the setup_thread routine. */ TRACE_((THIS_FILE, "...wait for the new thread...")); down(&thread->startstop_sem); TRACE_((THIS_FILE, "...main thread resumed...")); return PJ_SUCCESS; }
static HRESULT IDirectMusicBandImpl_IPersistStream_ParseBandForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) { ICOM_THIS_MULTI(IDirectMusicBandImpl, PersistStreamVtbl, iface); HRESULT hr = E_FAIL; DMUS_PRIVATE_CHUNK Chunk; DWORD StreamSize, StreamCount, ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ GUID tmp_guid; if (pChunk->fccID != DMUS_FOURCC_BAND_FORM) { ERR_(dmfile)(": %s chunk should be a BAND form\n", debugstr_fourcc (pChunk->fccID)); return E_FAIL; } StreamSize = pChunk->dwSize - sizeof(FOURCC); StreamCount = 0; do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, This->pDesc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { switch (Chunk.fccID) { case DMUS_FOURCC_GUID_CHUNK: { TRACE_(dmfile)(": GUID\n"); IStream_Read (pStm, &tmp_guid, sizeof(GUID), NULL); TRACE_(dmfile)(" - guid: %s\n", debugstr_dmguid(&tmp_guid)); break; } case FOURCC_LIST: { IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[0] = Chunk.dwSize - sizeof(FOURCC); ListCount[0] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, This->pDesc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { switch (Chunk.fccID) { default: { TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } } TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); break; } case DMUS_FOURCC_INSTRUMENTS_LIST: { TRACE_(dmfile)(": INSTRUMENTS list\n"); hr = IDirectMusicBandImpl_IPersistStream_ParseInstrumentsList (iface, &Chunk, pStm); if (FAILED(hr)) return hr; break; } default: { TRACE_(dmfile)(": unknown (skipping)\n"); liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } } TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize); } while (StreamCount < StreamSize); return S_OK; }
/* * Encode frame. */ static pj_status_t amr_codec_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct amr_data *amr_data = (struct amr_data*) codec->codec_data; unsigned char *bitstream; pj_int16_t *speech; unsigned nsamples, samples_per_frame; enum {MAX_FRAMES_PER_PACKET = 16}; pjmedia_frame frames[MAX_FRAMES_PER_PACKET]; pj_uint8_t *p; unsigned i, out_size = 0, nframes = 0; pj_size_t payload_len; unsigned dtx_cnt, sid_cnt; pj_status_t status; pj_assert(amr_data != NULL); PJ_ASSERT_RETURN(input && output, PJ_EINVAL); nsamples = input->size >> 1; samples_per_frame = amr_data->clock_rate * FRAME_LENGTH_MS / 1000; PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, PJMEDIA_CODEC_EPCMFRMINLEN); nframes = nsamples / samples_per_frame; PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET, PJMEDIA_CODEC_EFRMTOOSHORT); /* Encode the frames */ speech = (pj_int16_t*)input->buf; bitstream = (unsigned char*)output->buf; while (nsamples >= samples_per_frame) { int size; if (amr_data->enc_setting.amr_nb) { #ifdef USE_AMRNB size = Encoder_Interface_Encode (amr_data->encoder, amr_data->enc_mode, speech, bitstream, 0); #else size = 0; #endif } else { #ifdef USE_AMRWB size = E_IF_encode (amr_data->encoder, amr_data->enc_mode, speech, bitstream, 0); #else size = 0; #endif } if (size == 0) { output->size = 0; output->buf = NULL; output->type = PJMEDIA_FRAME_TYPE_NONE; TRACE_((THIS_FILE, "AMR encode() failed")); return PJMEDIA_CODEC_EFAILED; } nsamples -= samples_per_frame; speech += samples_per_frame; bitstream += size; out_size += size; TRACE_((THIS_FILE, "AMR encode(): mode=%d, size=%d", amr_data->enc_mode, out_size)); } /* Pack payload */ p = (pj_uint8_t*)output->buf + output_buf_len - out_size; pj_memmove(p, output->buf, out_size); dtx_cnt = sid_cnt = 0; for (i = 0; i < nframes; ++i) { pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*) &frames[i].bit_info; info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F); info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01); info->mode = (pj_int8_t)amr_data->enc_mode; info->start_bit = 0; frames[i].buf = p + 1; if (amr_data->enc_setting.amr_nb) { frames[i].size = (info->frame_type <= 8)? pjmedia_codec_amrnb_framelen[info->frame_type] : 0; } else { frames[i].size = (info->frame_type <= 9)? pjmedia_codec_amrwb_framelen[info->frame_type] : 0; } p += frames[i].size + 1; /* Count the number of SID and DTX frames */ if (info->frame_type == 15) /* DTX*/ ++dtx_cnt; else if (info->frame_type == 8) /* SID */ ++sid_cnt; } /* VA generates DTX frames as DTX+SID frames switching quickly and it * seems that the SID frames occur too often (assuming the purpose is * only for keeping NAT alive?). So let's modify the behavior a bit. * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD * milliseconds. */ if (sid_cnt + dtx_cnt == nframes) { pj_int32_t dtx_duration; dtx_duration = pj_timestamp_diff32(&amr_data->last_tx, &input->timestamp); if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || dtx_duration < (int)(PJMEDIA_CODEC_MAX_SILENCE_PERIOD* amr_data->clock_rate/1000)) { output->size = 0; output->type = PJMEDIA_FRAME_TYPE_NONE; output->timestamp = input->timestamp; return PJ_SUCCESS; } } payload_len = output_buf_len; status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting, output->buf, &payload_len); if (status != PJ_SUCCESS) { output->size = 0; output->buf = NULL; output->type = PJMEDIA_FRAME_TYPE_NONE; TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status)); return status; } output->size = payload_len; output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->timestamp = input->timestamp; amr_data->last_tx = input->timestamp; return PJ_SUCCESS; }
/********************************************************************** * K32WOWCallback16Ex (KERNEL32.55) */ BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags, DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode ) { /* * Arguments must be prepared in the correct order by the caller * (both for PASCAL and CDECL calling convention), so we simply * copy them to the 16-bit stack ... */ char *stack = (char *)CURRENT_STACK16 - cbArgs; memcpy( stack, pArgs, cbArgs ); if (dwFlags & (WCB16_REGS|WCB16_REGS_LONG)) { CONTEXT *context = (CONTEXT *)pdwRetCode; if (TRACE_ON(relay)) { DWORD count = cbArgs / sizeof(WORD); WORD * wstack = (WORD *)stack; TRACE_(relay)( "\1CallTo16(func=%04x:%04x", context->SegCs, LOWORD(context->Eip) ); while (count) TRACE_(relay)( ",%04x", wstack[--count] ); TRACE_(relay)( ") ss:sp=%04x:%04x ax=%04x bx=%04x cx=%04x dx=%04x si=%04x di=%04x bp=%04x ds=%04x es=%04x\n", SELECTOROF(NtCurrentTeb()->WOW32Reserved), OFFSETOF(NtCurrentTeb()->WOW32Reserved), (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx, (WORD)context->Edx, (WORD)context->Esi, (WORD)context->Edi, (WORD)context->Ebp, (WORD)context->SegDs, (WORD)context->SegEs ); SYSLEVEL_CheckNotLevel( 2 ); } if (context->EFlags & 0x00020000) /* v86 mode */ { EXCEPTION_REGISTRATION_RECORD frame; frame.Handler = vm86_handler; errno = 0; __wine_push_frame( &frame ); __wine_enter_vm86( context ); __wine_pop_frame( &frame ); if (errno != 0) /* enter_vm86 will fail with ENOSYS on x64 kernels */ { WARN("__wine_enter_vm86 failed (errno=%d)\n", errno); if (errno == ENOSYS) SetLastError(ERROR_NOT_SUPPORTED); else SetLastError(ERROR_GEN_FAILURE); return FALSE; } } else { /* push return address */ if (dwFlags & WCB16_REGS_LONG) { stack -= sizeof(DWORD); *((DWORD *)stack) = HIWORD(call16_ret_addr); stack -= sizeof(DWORD); *((DWORD *)stack) = LOWORD(call16_ret_addr); cbArgs += 2 * sizeof(DWORD); } else { stack -= sizeof(SEGPTR); *((SEGPTR *)stack) = call16_ret_addr; cbArgs += sizeof(SEGPTR); } /* * Start call by checking for pending events. * Note that wine_call_to_16_regs overwrites context stack * pointer so we may modify it here without a problem. */ if (get_vm86_teb_info()->dpmi_vif) { context->SegSs = wine_get_ds(); context->Esp = (DWORD)stack; insert_event_check( context ); cbArgs += (DWORD)stack - context->Esp; } _EnterWin16Lock(); wine_call_to_16_regs( context, cbArgs, call16_handler ); _LeaveWin16Lock(); } if (TRACE_ON(relay)) { TRACE_(relay)( "\1RetFrom16() ss:sp=%04x:%04x ax=%04x bx=%04x cx=%04x dx=%04x bp=%04x sp=%04x\n", SELECTOROF(NtCurrentTeb()->WOW32Reserved), OFFSETOF(NtCurrentTeb()->WOW32Reserved), (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx, (WORD)context->Edx, (WORD)context->Ebp, (WORD)context->Esp ); SYSLEVEL_CheckNotLevel( 2 ); } } else { DWORD ret; if (TRACE_ON(relay)) { DWORD count = cbArgs / sizeof(WORD); WORD * wstack = (WORD *)stack; TRACE_(relay)( "\1CallTo16(func=%04x:%04x,ds=%04x", HIWORD(vpfn16), LOWORD(vpfn16), SELECTOROF(NtCurrentTeb()->WOW32Reserved) ); while (count) TRACE_(relay)( ",%04x", wstack[--count] ); TRACE_(relay)( ") ss:sp=%04x:%04x\n", SELECTOROF(NtCurrentTeb()->WOW32Reserved), OFFSETOF(NtCurrentTeb()->WOW32Reserved) ); SYSLEVEL_CheckNotLevel( 2 ); } /* push return address */ stack -= sizeof(SEGPTR); *((SEGPTR *)stack) = call16_ret_addr; cbArgs += sizeof(SEGPTR); /* * Actually, we should take care whether the called routine cleans up * its stack or not. Fortunately, our wine_call_to_16 core doesn't rely on * the callee to do so; after the routine has returned, the 16-bit * stack pointer is always reset to the position it had before. */ _EnterWin16Lock(); ret = wine_call_to_16( (FARPROC16)vpfn16, cbArgs, call16_handler ); if (pdwRetCode) *pdwRetCode = ret; _LeaveWin16Lock(); if (TRACE_ON(relay)) { TRACE_(relay)( "\1RetFrom16() ss:sp=%04x:%04x retval=%08x\n", SELECTOROF(NtCurrentTeb()->WOW32Reserved), OFFSETOF(NtCurrentTeb()->WOW32Reserved), ret ); SYSLEVEL_CheckNotLevel( 2 ); } } return TRUE; /* success */ }
static NTSTATUS NTAPI ClassDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { //PCLASS_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status = STATUS_NOT_SUPPORTED; TRACE_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL\n"); if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) return ForwardIrpAndForget(DeviceObject, Irp); //DeviceExtension = (PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: case IOCTL_KEYBOARD_QUERY_INDICATORS: case IOCTL_KEYBOARD_QUERY_TYPEMATIC: { /* FIXME: We hope that all devices will return the same result. * Ask only the first one */ PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead; if (Head->Flink != Head) { /* We have at least one device */ PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry); IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->DeviceObject, Irp); } break; } case IOCTL_KEYBOARD_SET_INDICATORS: case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */ { /* Send it to all associated Port devices */ PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead; PLIST_ENTRY Entry = Head->Flink; Status = STATUS_SUCCESS; while (Entry != Head) { PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Entry, PORT_DEVICE_EXTENSION, ListEntry); NTSTATUS IntermediateStatus; IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; IntermediateStatus = ForwardIrpAndWait(DevExt->DeviceObject, Irp); if (!NT_SUCCESS(IntermediateStatus)) Status = IntermediateStatus; Entry = Entry->Flink; } break; } default: WARN_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n", IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode); ASSERT(FALSE); break; } Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
static int perform_test(inv_test_param_t *param) { pj_str_t uri; pjsip_dialog *dlg; pjmedia_sdp_session *sdp; pjsip_tx_data *tdata; pj_status_t status; PJ_LOG(3,(THIS_FILE, " %s", param->title)); pj_bzero(&inv_test, sizeof(inv_test)); pj_memcpy(&inv_test.param, param, sizeof(*param)); job_cnt = 0; uri = pj_str(CONTACT); /* * Create UAC */ status = pjsip_dlg_create_uac(pjsip_ua_instance(), &uri, &uri, &uri, &uri, &dlg); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -10); if (inv_test.param.oa[0] == OFFERER_UAC) sdp = create_sdp(dlg->pool, oa_sdp[0].offer); else sdp = NULL; status = pjsip_inv_create_uac(dlg, sdp, inv_test.param.inv_option, &inv_test.uac); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -20); TRACE_((THIS_FILE, " Sending INVITE %s offer", (sdp ? "with" : "without"))); /* * Make call! */ status = pjsip_inv_invite(inv_test.uac, &tdata); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30); status = pjsip_inv_send_msg(inv_test.uac, tdata); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30); /* * Wait until test completes */ while (!inv_test.complete) { pj_time_val delay = {0, 20}; pjsip_endpt_handle_events(endpt, &delay); while (job_cnt) { job_t j; j = jobs[0]; pj_array_erase(jobs, sizeof(jobs[0]), job_cnt, 0); --job_cnt; run_job(&j); } } flush_events(100); /* * Hangup */ TRACE_((THIS_FILE, " Disconnecting call")); status = pjsip_inv_end_session(inv_test.uas, PJSIP_SC_DECLINE, 0, &tdata); pj_assert(status == PJ_SUCCESS); status = pjsip_inv_send_msg(inv_test.uas, tdata); pj_assert(status == PJ_SUCCESS); flush_events(500); return 0; }
static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) { ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface); HRESULT hr = E_FAIL; DMUS_PRIVATE_CHUNK Chunk; DWORD StreamSize, StreamCount, ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ IDirectMusicBand* pBand = NULL; if (pChunk->fccID != DMUS_FOURCC_STYLE_FORM) { ERR_(dmfile)(": %s chunk should be a STYLE form\n", debugstr_fourcc (pChunk->fccID)); return E_FAIL; } StreamSize = pChunk->dwSize - sizeof(FOURCC); StreamCount = 0; do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, This->pDesc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { switch (Chunk.fccID) { case DMUS_FOURCC_STYLE_CHUNK: { TRACE_(dmfile)(": Style chunk\n"); IStream_Read (pStm, &This->style, sizeof(DMUS_IO_STYLE), NULL); /** TODO dump DMUS_IO_TIMESIG style.timeSig */ TRACE_(dmfile)(" - dblTempo: %g\n", This->style.dblTempo); break; } case FOURCC_RIFF: { /** * should be embedded Bands into style */ IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[0] = Chunk.dwSize - sizeof(FOURCC); ListCount[0] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_BAND_FORM: { LPSTREAM pClonedStream = NULL; LPDMUS_PRIVATE_STYLE_BAND pNewBand; TRACE_(dmfile)(": BAND RIFF\n"); IStream_Clone (pStm, &pClonedStream); liMove.QuadPart = 0; liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD)); IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL); hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand); if (FAILED(hr)) { ERR(": could not load track\n"); return hr; } IStream_Release (pClonedStream); pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_BAND)); if (NULL == pNewBand) { ERR(": no more memory\n"); return E_OUTOFMEMORY; } pNewBand->pBand = pBand; IDirectMusicBand_AddRef(pBand); list_add_tail (&This->Bands, &pNewBand->entry); IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release it as it's inserted */ /** now safely move the cursor */ liMove.QuadPart = ListSize[0]; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = ListSize[0]; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } case FOURCC_LIST: { IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[0] = Chunk.dwSize - sizeof(FOURCC); ListCount[0] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, This->pDesc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { switch (Chunk.fccID) { default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } } TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); break; } case DMUS_FOURCC_PART_LIST: { TRACE_(dmfile)(": PART list\n"); hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartList (iface, &Chunk, pStm); if (FAILED(hr)) return hr; break; } case DMUS_FOURCC_PATTERN_LIST: { TRACE_(dmfile)(": PATTERN list\n"); hr = IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (iface, &Chunk, pStm); if (FAILED(hr)) return hr; break; } default: { TRACE_(dmfile)(": unknown (skipping)\n"); liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } } TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize); } while (StreamCount < StreamSize); return S_OK; }
static cairo_int_status_t _cairo_spans_compositor_fill (const cairo_compositor_t *_compositor, cairo_composite_rectangles_t *extents, const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor; cairo_int_status_t status; TRACE((stderr, "%s op=%d, antialias=%d\n", __FUNCTION__, extents->op, antialias)); status = CAIRO_INT_STATUS_UNSUPPORTED; if (_cairo_path_fixed_fill_is_rectilinear (path)) { cairo_boxes_t boxes; TRACE((stderr, "%s - rectilinear\n", __FUNCTION__)); _cairo_boxes_init (&boxes); if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask)) _cairo_boxes_limit (&boxes, extents->clip->boxes, extents->clip->num_boxes); status = _cairo_path_fixed_fill_rectilinear_to_boxes (path, fill_rule, antialias, &boxes); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) status = clip_and_composite_boxes (compositor, extents, &boxes); _cairo_boxes_fini (&boxes); } if (status == CAIRO_INT_STATUS_UNSUPPORTED) { cairo_polygon_t polygon; TRACE((stderr, "%s - polygon\n", __FUNCTION__)); if (! _cairo_rectangle_contains_rectangle (&extents->unbounded, &extents->mask)) { TRACE((stderr, "%s - clipping to bounds\n", __FUNCTION__)); if (extents->clip->num_boxes == 1) { _cairo_polygon_init (&polygon, extents->clip->boxes, 1); } else { cairo_box_t limits; _cairo_box_from_rectangle (&limits, &extents->unbounded); _cairo_polygon_init (&polygon, &limits, 1); } } else { _cairo_polygon_init (&polygon, NULL, 0); } status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon); TRACE_ (_cairo_debug_print_polygon (stderr, &polygon)); polygon.num_limits = 0; if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) { TRACE((stderr, "%s - polygon intersect with %d clip boxes\n", __FUNCTION__, extents->clip->num_boxes)); status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule, extents->clip->boxes, extents->clip->num_boxes); } TRACE_ (_cairo_debug_print_polygon (stderr, &polygon)); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { cairo_clip_t *saved_clip = extents->clip; if (extents->is_bounded) { TRACE((stderr, "%s - polygon discard clip boxes\n", __FUNCTION__)); extents->clip = _cairo_clip_copy_path (extents->clip); extents->clip = _cairo_clip_intersect_box(extents->clip, &polygon.extents); } status = clip_and_composite_polygon (compositor, extents, &polygon, fill_rule, antialias); if (extents->is_bounded) { _cairo_clip_destroy (extents->clip); extents->clip = saved_clip; } } _cairo_polygon_fini (&polygon); TRACE((stderr, "%s - polygon status=%d\n", __FUNCTION__, status)); } return status; }
static cairo_int_status_t _cairo_spans_compositor_stroke (const cairo_compositor_t *_compositor, cairo_composite_rectangles_t *extents, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias) { const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor; cairo_int_status_t status; TRACE ((stderr, "%s\n", __FUNCTION__)); TRACE_ (_cairo_debug_print_path (stderr, path)); TRACE_ (_cairo_debug_print_clip (stderr, extents->clip)); status = CAIRO_INT_STATUS_UNSUPPORTED; if (_cairo_path_fixed_stroke_is_rectilinear (path)) { cairo_boxes_t boxes; _cairo_boxes_init (&boxes); if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask)) _cairo_boxes_limit (&boxes, extents->clip->boxes, extents->clip->num_boxes); status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path, style, ctm, antialias, &boxes); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) status = clip_and_composite_boxes (compositor, extents, &boxes); _cairo_boxes_fini (&boxes); } if (status == CAIRO_INT_STATUS_UNSUPPORTED) { cairo_polygon_t polygon; cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING; if (! _cairo_rectangle_contains_rectangle (&extents->unbounded, &extents->mask)) { if (extents->clip->num_boxes == 1) { _cairo_polygon_init (&polygon, extents->clip->boxes, 1); } else { cairo_box_t limits; _cairo_box_from_rectangle (&limits, &extents->unbounded); _cairo_polygon_init (&polygon, &limits, 1); } } else { _cairo_polygon_init (&polygon, NULL, 0); } status = _cairo_path_fixed_stroke_to_polygon (path, style, ctm, ctm_inverse, tolerance, &polygon); TRACE_ (_cairo_debug_print_polygon (stderr, &polygon)); polygon.num_limits = 0; if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) { status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule, extents->clip->boxes, extents->clip->num_boxes); } if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { cairo_clip_t *saved_clip = extents->clip; if (extents->is_bounded) { extents->clip = _cairo_clip_copy_path (extents->clip); extents->clip = _cairo_clip_intersect_box(extents->clip, &polygon.extents); } status = clip_and_composite_polygon (compositor, extents, &polygon, fill_rule, antialias); if (extents->is_bounded) { _cairo_clip_destroy (extents->clip); extents->clip = saved_clip; } } _cairo_polygon_fini (&polygon); } return status; }
static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo) /* * FUNCTION: Initialize a newly-found controller * ARGUMENTS: * ControllerInfo: pointer to the controller to be initialized * RETURNS: * STATUS_SUCCESS if the controller is successfully initialized * STATUS_IO_DEVICE_ERROR otherwise */ { int i; UCHAR HeadLoadTime; UCHAR HeadUnloadTime; UCHAR StepRateTime; UCHAR ControllerVersion; PAGED_CODE(); ASSERT(ControllerInfo); TRACE_(FLOPPY, "InitController called with Controller 0x%p\n", ControllerInfo); /* Get controller in a known state */ HwConfigure(ControllerInfo, FALSE, TRUE, TRUE, 0, 0); /* Get the controller version */ ControllerVersion = HwGetVersion(ControllerInfo); KeClearEvent(&ControllerInfo->SynchEvent); /* Reset the controller */ if(HwReset(ControllerInfo) != STATUS_SUCCESS) { WARN_(FLOPPY, "InitController: unable to reset controller\n"); return STATUS_IO_DEVICE_ERROR; } INFO_(FLOPPY, "InitController: waiting for initial interrupt\n"); /* Wait for an interrupt */ WaitForControllerInterrupt(ControllerInfo); /* Reset means you have to clear each of the four interrupts (one per drive) */ for(i = 0; i < MAX_DRIVES_PER_CONTROLLER; i++) { INFO_(FLOPPY, "InitController: Sensing interrupt %d\n", i); if(HwSenseInterruptStatus(ControllerInfo) != STATUS_SUCCESS) { WARN_(FLOPPY, "InitController: Unable to clear interrupt 0x%x\n", i); return STATUS_IO_DEVICE_ERROR; } } INFO_(FLOPPY, "InitController: done sensing interrupts\n"); /* Next, see if we have the right version to do implied seek */ if(ControllerVersion == VERSION_ENHANCED) { /* If so, set that up -- all defaults below except first TRUE for EIS */ if(HwConfigure(ControllerInfo, TRUE, TRUE, TRUE, 0, 0) != STATUS_SUCCESS) { WARN_(FLOPPY, "InitController: unable to set up implied seek\n"); ControllerInfo->ImpliedSeeks = FALSE; } else { INFO_(FLOPPY, "InitController: implied seeks set!\n"); ControllerInfo->ImpliedSeeks = TRUE; } /* * FIXME: Figure out the answer to the below * * I must admit that I'm really confused about the Model 30 issue. At least one * important bit (the disk change bit in the DIR) is flipped if this is a Model 30 * controller. However, at least one other floppy driver believes that there are only * two computers that are guaranteed to have a Model 30 controller: * - IBM Thinkpad 750 * - IBM PS2e * * ...and another driver only lists a config option for "thinkpad", that flips * the change line. A third driver doesn't mention the Model 30 issue at all. * * What I can't tell is whether or not the average, run-of-the-mill computer now has * a Model 30 controller. For the time being, I'm going to wire this to FALSE, * and just not support the computers mentioned above, while I try to figure out * how ubiquitous these newfangled 30 thingies are. */ //ControllerInfo->Model30 = TRUE; ControllerInfo->Model30 = FALSE; } else { INFO_(FLOPPY, "InitController: enhanced version not supported; disabling implied seeks\n"); ControllerInfo->ImpliedSeeks = FALSE; ControllerInfo->Model30 = FALSE; } /* Specify */ WARN_(FLOPPY, "FIXME: Figure out speed\n"); HeadLoadTime = SPECIFY_HLT_500K; HeadUnloadTime = SPECIFY_HUT_500K; StepRateTime = SPECIFY_SRT_500K; INFO_(FLOPPY, "InitController: setting data rate\n"); /* Set data rate */ if(HwSetDataRate(ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS) { WARN_(FLOPPY, "InitController: unable to set data rate\n"); return STATUS_IO_DEVICE_ERROR; } INFO_(FLOPPY, "InitController: issuing specify command to controller\n"); /* Don't disable DMA --> enable dma (dumb & confusing) */ if(HwSpecify(ControllerInfo, HeadLoadTime, HeadUnloadTime, StepRateTime, FALSE) != STATUS_SUCCESS) { WARN_(FLOPPY, "InitController: unable to specify options\n"); return STATUS_IO_DEVICE_ERROR; } /* Init the stop stuff */ KeInitializeDpc(&ControllerInfo->MotorStopDpc, MotorStopDpcFunc, ControllerInfo); KeInitializeTimer(&ControllerInfo->MotorTimer); KeInitializeEvent(&ControllerInfo->MotorStoppedEvent, NotificationEvent, FALSE); ControllerInfo->StopDpcQueued = FALSE; /* * Recalibrate each drive on the controller (depends on StartMotor, which depends on the timer stuff above) * We don't even know if there is a disk in the drive, so this may not work, but that's OK. */ for(i = 0; i < ControllerInfo->NumberOfDrives; i++) { INFO_(FLOPPY, "InitController: recalibrating drive 0x%x on controller 0x%p\n", i, ControllerInfo); Recalibrate(&ControllerInfo->DriveInfo[i]); } INFO_(FLOPPY, "InitController: done initializing; returning STATUS_SUCCESS\n"); return STATUS_SUCCESS; }
static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) { IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; struct wined3d_context *context; RECT src_rect, dst_rect; BOOL render_to_fbo; unsigned int sync; int retval; #ifdef VBOX_WITH_WDDM /* quickly sort out invalid swapchains */ if (!This->hDC) { WARN("Invalid swapchain"); return WINED3D_OK; } #endif IWineD3DSwapChain_SetDestWindowOverride(iface, hDestWindowOverride); context = context_acquire(This->device, This->backBuffer[0], CTXUSAGE_RESOURCELOAD); if (!context->valid) { context_release(context); WARN("Invalid context, skipping present.\n"); return WINED3D_OK; } /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */ if (This->device->bCursorVisible && This->device->cursorTexture) { IWineD3DSurfaceImpl cursor; RECT destRect = { This->device->xScreenSpace - This->device->xHotSpot, This->device->yScreenSpace - This->device->yHotSpot, This->device->xScreenSpace + This->device->cursorWidth - This->device->xHotSpot, This->device->yScreenSpace + This->device->cursorHeight - This->device->yHotSpot, }; TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor); /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by * the application because we are only supposed to copy the information out. Using a fake surface * allows to use the Blitting engine and avoid copying the whole texture -> render target blitting code. */ memset(&cursor, 0, sizeof(cursor)); cursor.lpVtbl = &IWineD3DSurface_Vtbl; cursor.resource.ref = 1; cursor.resource.device = This->device; cursor.resource.pool = WINED3DPOOL_SCRATCH; cursor.resource.format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, context->gl_info); cursor.resource.resourceType = WINED3DRTYPE_SURFACE; cursor.texture_name = This->device->cursorTexture; cursor.texture_target = GL_TEXTURE_2D; cursor.texture_level = 0; cursor.currentDesc.Width = This->device->cursorWidth; cursor.currentDesc.Height = This->device->cursorHeight; /* The cursor must have pow2 sizes */ cursor.pow2Width = cursor.currentDesc.Width; cursor.pow2Height = cursor.currentDesc.Height; /* The surface is in the texture */ cursor.Flags |= SFLAG_INTEXTURE; /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0, * which is exactly what we want :-) */ if (This->presentParms.Windowed) { #ifdef VBOX_WITH_WDDM /* @todo: can we actualy be here? */ #endif MapWindowPoints(NULL, This->win_handle, (LPPOINT)&destRect, 2); } IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *)&cursor, NULL, WINEDDBLT_KEYSRC, NULL, WINED3DTEXF_POINT); } if (This->device->logo_surface) { /* Blit the logo into the upper left corner of the drawable. */ IWineD3DSurface_BltFast(This->backBuffer[0], 0, 0, This->device->logo_surface, NULL, WINEDDBLTFAST_SRCCOLORKEY); } #ifdef VBOX_WITH_WDDM TRACE("Presenting HDC %p.\n", context->currentSwapchain->hDC); #else TRACE("Presenting HDC %p.\n", context->hdc); #endif render_to_fbo = This->render_to_fbo; if (pSourceRect) { src_rect = *pSourceRect; if (!render_to_fbo && (src_rect.left || src_rect.top || src_rect.right != This->presentParms.BackBufferWidth || src_rect.bottom != This->presentParms.BackBufferHeight)) { render_to_fbo = TRUE; } } else { src_rect.left = 0; src_rect.top = 0; src_rect.right = This->presentParms.BackBufferWidth; src_rect.bottom = This->presentParms.BackBufferHeight; } if (pDestRect) dst_rect = *pDestRect; #ifndef VBOX_WITH_WDDM else GetClientRect(This->win_handle, &dst_rect); if (!render_to_fbo && (dst_rect.left || dst_rect.top || dst_rect.right != This->presentParms.BackBufferWidth || dst_rect.bottom != This->presentParms.BackBufferHeight)) { render_to_fbo = TRUE; } #else else { dst_rect.left = 0; dst_rect.top = 0; dst_rect.right = This->presentParms.BackBufferWidth; dst_rect.bottom = This->presentParms.BackBufferHeight; } #endif /* Rendering to a window of different size, presenting partial rectangles, * or rendering to a different window needs help from FBO_blit or a textured * draw. Render the swapchain to a FBO in the future. * * Note that FBO_blit from the backbuffer to the frontbuffer cannot solve * all these issues - this fails if the window is smaller than the backbuffer. */ if (!This->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { IWineD3DSurface_LoadLocation(This->backBuffer[0], SFLAG_INTEXTURE, NULL); IWineD3DSurface_ModifyLocation(This->backBuffer[0], SFLAG_INDRAWABLE, FALSE); This->render_to_fbo = TRUE; /* Force the context manager to update the render target configuration next draw. */ context->current_rt = NULL; } if(This->render_to_fbo) { /* This codepath should only be hit with the COPY swapeffect. Otherwise a backbuffer- * window size mismatch is impossible(fullscreen) and src and dst rectangles are * not allowed(they need the COPY swapeffect) * * The DISCARD swap effect is ok as well since any backbuffer content is allowed after * the swap */ if(This->presentParms.SwapEffect == WINED3DSWAPEFFECT_FLIP ) { FIXME("Render-to-fbo with WINED3DSWAPEFFECT_FLIP\n"); } swapchain_blit(This, context, &src_rect, &dst_rect); } #ifdef VBOX_WITH_WDDM if (This->device->numContexts > 1) wglFinish(); #else if (This->num_contexts > 1) wglFinish(); #endif #if defined(VBOX_WITH_WDDM) && defined(DEBUG) { HWND wnd = WindowFromDC(context->currentSwapchain->hDC); Assert(wnd == context->currentSwapchain->win_handle); } #endif #ifdef VBOX_WITH_WDDM /* We're directly using wglMakeCurrent calls skipping GDI layer, which causes GDI SwapBuffers to fail trying to * call glFinish, which doesn't have any context set. So we use wglSwapLayerBuffers directly as well. */ pwglSwapLayerBuffers(context->currentSwapchain->hDC, WGL_SWAP_MAIN_PLANE); #else # ifdef VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT pwglSwapLayerBuffers(context->hdc, WGL_SWAP_MAIN_PLANE); # else SwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */ # endif #endif TRACE("SwapBuffers called, Starting new frame\n"); /* FPS support */ if (TRACE_ON(fps)) { DWORD time = GetTickCount(); This->frames++; /* every 1.5 seconds */ if (time - This->prev_time > 1500) { TRACE_(fps)("%p @ approx %.2ffps\n", This, 1000.0*This->frames/(time - This->prev_time)); This->prev_time = time; This->frames = 0; } } #if defined(FRAME_DEBUGGING) { if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) { if (!isOn) { isOn = TRUE; FIXME("Enabling D3D Trace\n"); __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1); #if defined(SHOW_FRAME_MAKEUP) FIXME("Singe Frame snapshots Starting\n"); isDumpingFrames = TRUE; ENTER_GL(); glClear(GL_COLOR_BUFFER_BIT); LEAVE_GL(); #endif #if defined(SINGLE_FRAME_DEBUGGING) } else { #if defined(SHOW_FRAME_MAKEUP) FIXME("Singe Frame snapshots Finishing\n"); isDumpingFrames = FALSE; #endif FIXME("Singe Frame trace complete\n"); DeleteFileA("C:\\D3DTRACE"); __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); #endif } } else { if (isOn) { isOn = FALSE; #if defined(SHOW_FRAME_MAKEUP) FIXME("Single Frame snapshots Finishing\n"); isDumpingFrames = FALSE; #endif FIXME("Disabling D3D Trace\n"); __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); } } } #endif /* This is disabled, but the code left in for debug purposes. * * Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip, * we can clear it with some ugly color to make bad drawing visible and ease debugging. * The Debug runtime does the same on Windows. However, a few games do not redraw the * screen properly, like Max Payne 2, which leaves a few pixels undefined. * * Tests show that the content of the back buffer after a discard flip is indeed not * reliable, so no game can depend on the exact content. However, it resembles the * old contents in some way, for example by showing fragments at other locations. In * general, the color theme is still intact. So Max payne, which draws rather dark scenes * gets a dark background image. If we clear it with a bright ugly color, the game's * bug shows up much more than it does on Windows, and the players see single pixels * with wrong colors. * (The Max Payne bug has been confirmed on Windows with the debug runtime) */ if (FALSE && This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) { TRACE("Clearing the color buffer with cyan color\n"); IWineD3DDevice_Clear((IWineD3DDevice *)This->device, 0, NULL, WINED3DCLEAR_TARGET, 0xff00ffff, 1.0f, 0); } if(!This->render_to_fbo && ( ((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags & SFLAG_INSYSMEM || ((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_INSYSMEM ) ) { /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying * Doesn't work with render_to_fbo because we're not flipping */ IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer; IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0]; if(front->resource.size == back->resource.size) { DWORD fbflags; flip_surface(front, back); /* Tell the front buffer surface that is has been modified. However, * the other locations were preserved during that, so keep the flags. * This serves to update the emulated overlay, if any */ fbflags = front->Flags; IWineD3DSurface_ModifyLocation(This->frontBuffer, SFLAG_INDRAWABLE, TRUE); front->Flags = fbflags; } else { IWineD3DSurface_ModifyLocation((IWineD3DSurface *) front, SFLAG_INDRAWABLE, TRUE); IWineD3DSurface_ModifyLocation((IWineD3DSurface *) back, SFLAG_INDRAWABLE, TRUE); } } else { IWineD3DSurface_ModifyLocation(This->frontBuffer, SFLAG_INDRAWABLE, TRUE); /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM * and INTEXTURE copies can keep their old content if they have any defined content. * If the swapeffect is COPY, the content remains the same. If it is FLIP however, * the texture / sysmem copy needs to be reloaded from the drawable */ if(This->presentParms.SwapEffect == WINED3DSWAPEFFECT_FLIP) { IWineD3DSurface_ModifyLocation(This->backBuffer[0], SFLAG_INDRAWABLE, TRUE); } } if (This->device->stencilBufferTarget) { if (This->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || ((IWineD3DSurfaceImpl *)This->device->stencilBufferTarget)->Flags & SFLAG_DISCARD) { surface_modify_ds_location(This->device->stencilBufferTarget, SFLAG_DS_DISCARDED); } } if (This->presentParms.PresentationInterval != WINED3DPRESENT_INTERVAL_IMMEDIATE && context->gl_info->supported[SGI_VIDEO_SYNC]) { retval = GL_EXTCALL(glXGetVideoSyncSGI(&sync)); if(retval != 0) { ERR("glXGetVideoSyncSGI failed(retval = %d\n", retval); } switch(This->presentParms.PresentationInterval) { case WINED3DPRESENT_INTERVAL_DEFAULT: case WINED3DPRESENT_INTERVAL_ONE: if(sync <= This->vSyncCounter) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(1, 0, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; case WINED3DPRESENT_INTERVAL_TWO: if(sync <= This->vSyncCounter + 1) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(2, This->vSyncCounter & 0x1, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; case WINED3DPRESENT_INTERVAL_THREE: if(sync <= This->vSyncCounter + 2) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(3, This->vSyncCounter % 0x3, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; case WINED3DPRESENT_INTERVAL_FOUR: if(sync <= This->vSyncCounter + 3) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(4, This->vSyncCounter & 0x3, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; default: FIXME("Unknown presentation interval %08x\n", This->presentParms.PresentationInterval); } } context_release(context); TRACE("returning\n"); return WINED3D_OK; }
PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, int sock_cnt, pj_sock_t sock[], const pj_str_t *srv1, int port1, const pj_str_t *srv2, int port2, pj_sockaddr_in mapped_addr[]) { unsigned srv_cnt; pj_sockaddr_in srv_addr[2]; int i, send_cnt = 0, nfds; pj_pool_t *pool; struct query_rec { struct { pj_uint32_t mapped_addr; pj_uint32_t mapped_port; } srv[2]; } *rec; void *out_msg; pj_size_t out_msg_len; int wait_resp = 0; pj_status_t status; PJ_CHECK_STACK(); TRACE_((THIS_FILE, "Entering pjstun_get_mapped_addr()")); /* Create pool. */ pool = pj_pool_create(pf, "stun%p", 400, 400, NULL); if (!pool) return PJ_ENOMEM; /* Allocate client records */ rec = (struct query_rec*) pj_pool_calloc(pool, sock_cnt, sizeof(*rec)); if (!rec) { status = PJ_ENOMEM; goto on_error; } TRACE_((THIS_FILE, " Memory allocated.")); /* Create the outgoing BIND REQUEST message template */ status = pjstun_create_bind_req( pool, &out_msg, &out_msg_len, pj_rand(), pj_rand()); if (status != PJ_SUCCESS) goto on_error; TRACE_((THIS_FILE, " Binding request created.")); /* Resolve servers. */ status = pj_sockaddr_in_init(&srv_addr[0], srv1, (pj_uint16_t)port1); if (status != PJ_SUCCESS) goto on_error; srv_cnt = 1; if (srv2 && port2) { status = pj_sockaddr_in_init(&srv_addr[1], srv2, (pj_uint16_t)port2); if (status != PJ_SUCCESS) goto on_error; if (srv_addr[1].sin_addr.s_addr != srv_addr[0].sin_addr.s_addr && srv_addr[1].sin_port != srv_addr[0].sin_port) { srv_cnt++; } } TRACE_((THIS_FILE, " Server initialized, using %d server(s)", srv_cnt)); /* Init mapped addresses to zero */ pj_memset(mapped_addr, 0, sock_cnt * sizeof(pj_sockaddr_in)); /* We need these many responses */ wait_resp = sock_cnt * srv_cnt; TRACE_((THIS_FILE, " Done initialization.")); #if defined(PJ_SELECT_NEEDS_NFDS) && PJ_SELECT_NEEDS_NFDS!=0 nfds = -1; for (i=0; i<sock_cnt; ++i) { if (sock[i] > nfds) { nfds = sock[i]; } } #else nfds = PJ_IOQUEUE_MAX_HANDLES-1; #endif /* Main retransmission loop. */ for (send_cnt=0; send_cnt<MAX_REQUEST; ++send_cnt) { pj_time_val next_tx, now; pj_fd_set_t r; int select_rc; PJ_FD_ZERO(&r); /* Send messages to servers that has not given us response. */ for (i=0; i<sock_cnt && status==PJ_SUCCESS; ++i) { unsigned j; for (j=0; j<srv_cnt && status==PJ_SUCCESS; ++j) { pjstun_msg_hdr *msg_hdr = (pjstun_msg_hdr*) out_msg; pj_ssize_t sent_len; if (rec[i].srv[j].mapped_port != 0) continue; /* Modify message so that we can distinguish response. */ msg_hdr->tsx[2] = pj_htonl(i); msg_hdr->tsx[3] = pj_htonl(j); /* Send! */ sent_len = out_msg_len; status = pj_sock_sendto(sock[i], out_msg, &sent_len, 0, (pj_sockaddr_t*)&srv_addr[j], sizeof(pj_sockaddr_in)); } } /* All requests sent. * The loop below will wait for responses until all responses have * been received (i.e. wait_resp==0) or timeout occurs, which then * we'll go to the next retransmission iteration. */ TRACE_((THIS_FILE, " Request(s) sent, counter=%d", send_cnt)); /* Calculate time of next retransmission. */ pj_gettimeofday(&next_tx); next_tx.sec += (stun_timer[send_cnt]/1000); next_tx.msec += (stun_timer[send_cnt]%1000); pj_time_val_normalize(&next_tx); for (pj_gettimeofday(&now), select_rc=1; status==PJ_SUCCESS && select_rc>=1 && wait_resp>0 && PJ_TIME_VAL_LT(now, next_tx); pj_gettimeofday(&now)) { pj_time_val timeout; timeout = next_tx; PJ_TIME_VAL_SUB(timeout, now); for (i=0; i<sock_cnt; ++i) { PJ_FD_SET(sock[i], &r); } select_rc = pj_sock_select(nfds+1, &r, NULL, NULL, &timeout); TRACE_((THIS_FILE, " select() rc=%d", select_rc)); if (select_rc < 1) continue; for (i=0; i<sock_cnt; ++i) { int sock_idx, srv_idx; pj_ssize_t len; pjstun_msg msg; pj_sockaddr_in addr; int addrlen = sizeof(addr); pjstun_mapped_addr_attr *attr; char recv_buf[128]; if (!PJ_FD_ISSET(sock[i], &r)) continue; len = sizeof(recv_buf); status = pj_sock_recvfrom( sock[i], recv_buf, &len, 0, (pj_sockaddr_t*)&addr, &addrlen); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; PJ_LOG(4,(THIS_FILE, "recvfrom() error ignored: %s", pj_strerror(status, errmsg,sizeof(errmsg)).ptr)); /* Ignore non-PJ_SUCCESS status. * It possible that other SIP entity is currently * sending SIP request to us, and because SIP message * is larger than STUN, we could get EMSGSIZE when * we call recvfrom(). */ status = PJ_SUCCESS; continue; } status = pjstun_parse_msg(recv_buf, len, &msg); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; PJ_LOG(4,(THIS_FILE, "STUN parsing error ignored: %s", pj_strerror(status, errmsg,sizeof(errmsg)).ptr)); /* Also ignore non-successful parsing. This may not * be STUN response at all. See the comment above. */ status = PJ_SUCCESS; continue; } sock_idx = pj_ntohl(msg.hdr->tsx[2]); srv_idx = pj_ntohl(msg.hdr->tsx[3]); if (sock_idx<0 || sock_idx>=sock_cnt || sock_idx!=i || srv_idx<0 || srv_idx>=2) { status = PJLIB_UTIL_ESTUNININDEX; continue; } if (pj_ntohs(msg.hdr->type) != PJSTUN_BINDING_RESPONSE) { status = PJLIB_UTIL_ESTUNNOBINDRES; continue; } if (rec[sock_idx].srv[srv_idx].mapped_port != 0) { /* Already got response */ continue; } /* From this part, we consider the packet as a valid STUN * response for our request. */ --wait_resp; if (pjstun_msg_find_attr(&msg, PJSTUN_ATTR_ERROR_CODE) != NULL) { status = PJLIB_UTIL_ESTUNRECVERRATTR; continue; } attr = (pjstun_mapped_addr_attr*) pjstun_msg_find_attr(&msg, PJSTUN_ATTR_MAPPED_ADDR); if (!attr) { attr = (pjstun_mapped_addr_attr*) pjstun_msg_find_attr(&msg, PJSTUN_ATTR_XOR_MAPPED_ADDR); if (!attr || attr->family != 1) { status = PJLIB_UTIL_ESTUNNOMAP; continue; } } rec[sock_idx].srv[srv_idx].mapped_addr = attr->addr; rec[sock_idx].srv[srv_idx].mapped_port = attr->port; if (pj_ntohs(attr->hdr.type) == PJSTUN_ATTR_XOR_MAPPED_ADDR) { rec[sock_idx].srv[srv_idx].mapped_addr ^= pj_htonl(STUN_MAGIC); rec[sock_idx].srv[srv_idx].mapped_port ^= pj_htons(STUN_MAGIC >> 16); } } } /* The best scenario is if all requests have been replied. * Then we don't need to go to the next retransmission iteration. */ if (wait_resp <= 0) break; }
static HRESULT IDirectMusicBandImpl_IPersistStream_ParseInstrument (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) { ICOM_THIS_MULTI(IDirectMusicBandImpl, PersistStreamVtbl, iface); DMUS_PRIVATE_CHUNK Chunk; DWORD ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ HRESULT hr; DMUS_IO_INSTRUMENT inst; LPDMUS_PRIVATE_INSTRUMENT pNewInstrument; IDirectMusicObject* pObject = NULL; if (pChunk->fccID != DMUS_FOURCC_INSTRUMENT_LIST) { ERR_(dmfile)(": %s chunk should be an INSTRUMENT list\n", debugstr_fourcc (pChunk->fccID)); return E_FAIL; } ListSize[0] = pChunk->dwSize - sizeof(FOURCC); ListCount[0] = 0; do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case DMUS_FOURCC_INSTRUMENT_CHUNK: { TRACE_(dmfile)(": Instrument chunk\n"); if (Chunk.dwSize != sizeof(DMUS_IO_INSTRUMENT)) return E_FAIL; IStream_Read (pStm, &inst, sizeof(DMUS_IO_INSTRUMENT), NULL); TRACE_(dmfile)(" - dwPatch: %lu\n", inst.dwPatch); TRACE_(dmfile)(" - dwAssignPatch: %lu\n", inst.dwAssignPatch); TRACE_(dmfile)(" - dwNoteRanges[0]: %lu\n", inst.dwNoteRanges[0]); TRACE_(dmfile)(" - dwNoteRanges[1]: %lu\n", inst.dwNoteRanges[1]); TRACE_(dmfile)(" - dwNoteRanges[2]: %lu\n", inst.dwNoteRanges[2]); TRACE_(dmfile)(" - dwNoteRanges[3]: %lu\n", inst.dwNoteRanges[3]); TRACE_(dmfile)(" - dwPChannel: %lu\n", inst.dwPChannel); TRACE_(dmfile)(" - dwFlags: %lu\n", inst.dwFlags); TRACE_(dmfile)(" - bPan: %u\n", inst.bPan); TRACE_(dmfile)(" - bVolume: %u\n", inst.bVolume); TRACE_(dmfile)(" - nTranspose: %d\n", inst.nTranspose); TRACE_(dmfile)(" - dwChannelPriority: %lu\n", inst.dwChannelPriority); TRACE_(dmfile)(" - nPitchBendRange: %d\n", inst.nPitchBendRange); break; } case FOURCC_LIST: { IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[1] = Chunk.dwSize - sizeof(FOURCC); ListCount[1] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_REF_LIST: { FIXME_(dmfile)(": DMRF (DM References) list\n"); hr = IDirectMusicUtils_IPersistStream_ParseReference (iface, &Chunk, pStm, &pObject); if (FAILED(hr)) { ERR(": could not load Reference\n"); return hr; } break; } default: { TRACE_(dmfile)(": unknown (skipping)\n"); liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); /* * @TODO insert pNewInstrument into This */ pNewInstrument = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_INSTRUMENT)); if (NULL == pNewInstrument) { ERR(": no more memory\n"); return E_OUTOFMEMORY; } memcpy(&pNewInstrument->pInstrument, &inst, sizeof(DMUS_IO_INSTRUMENT)); pNewInstrument->ppReferenceCollection = NULL; if (NULL != pObject) { IDirectMusicCollection* pCol = NULL; hr = IDirectMusicObject_QueryInterface (pObject, &IID_IDirectMusicCollection, (void**) &pCol); if (FAILED(hr)) { ERR(": failed to get IDirectMusicCollection Interface from DMObject\n"); return hr; } pNewInstrument->ppReferenceCollection = pCol; IDirectMusicObject_Release(pObject); } list_add_tail (&This->Instruments, &pNewInstrument->entry); return S_OK; }
/* Parse a multipart part. "pct" is parent content-type */ static pjsip_multipart_part *parse_multipart_part(pj_pool_t *pool, char *start, pj_size_t len, const pjsip_media_type *pct) { pjsip_multipart_part *part = pjsip_multipart_create_part(pool); char *p = start, *end = start+len, *end_hdr = NULL, *start_body = NULL; pjsip_ctype_hdr *ctype_hdr = NULL; TRACE_((THIS_FILE, "Parsing part: begin--\n%.*s\n--end", (int)len, start)); /* Find the end of header area, by looking at an empty line */ for (;;) { while (p!=end && *p!='\n') ++p; if (p==end) { start_body = end; break; } if ((p==start) || (p==start+1 && *(p-1)=='\r')) { /* Empty header section */ end_hdr = start; start_body = ++p; break; } else if (p==end-1) { /* Empty body section */ end_hdr = end; start_body = ++p; } else if ((p>=start+1 && *(p-1)=='\n') || (p>=start+2 && *(p-1)=='\r' && *(p-2)=='\n')) { /* Found it */ end_hdr = (*(p-1)=='\r') ? (p-1) : p; start_body = ++p; break; } else { ++p; } } /* Parse the headers */ if (end_hdr-start > 0) { pjsip_hdr *hdr; pj_status_t status; status = pjsip_parse_headers(pool, start, end_hdr-start, &part->hdr, 0); if (status != PJ_SUCCESS) { PJ_PERROR(2,(THIS_FILE, status, "Warning: error parsing multipart" " header")); } /* Find Content-Type header */ hdr = part->hdr.next; while (hdr != &part->hdr) { TRACE_((THIS_FILE, "Header parsed: %.*s", (int)hdr->name.slen, hdr->name.ptr)); if (hdr->type == PJSIP_H_CONTENT_TYPE) { ctype_hdr = (pjsip_ctype_hdr*)hdr; } hdr = hdr->next; } } /* Assign the body */ part->body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body); if (ctype_hdr) { pjsip_media_type_cp(pool, &part->body->content_type, &ctype_hdr->media); } else if (pct && pj_stricmp2(&pct->subtype, "digest")==0) { part->body->content_type.type = pj_str("message"); part->body->content_type.subtype = pj_str("rfc822"); } else { part->body->content_type.type = pj_str("text"); part->body->content_type.subtype = pj_str("plain"); } if (start_body < end) { part->body->data = start_body; part->body->len = end - start_body; } else { part->body->data = (void*)""; part->body->len = 0; } TRACE_((THIS_FILE, "Body parsed: \"%.*s\"", (int)part->body->len, part->body->data)); part->body->print_body = &pjsip_print_text_body; part->body->clone_data = &pjsip_clone_text_data; return part; }
/* * Open codec. */ static pj_status_t amr_codec_open( pjmedia_codec *codec, pjmedia_codec_param *attr ) { struct amr_data *amr_data = (struct amr_data*) codec->codec_data; pjmedia_codec_amr_pack_setting *setting; unsigned i; pj_uint8_t octet_align = 0; pj_int8_t enc_mode; const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11}; unsigned idx; PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL); PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP); idx = (attr->info.clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB); enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps); pj_assert(enc_mode >= 0 && (unsigned)enc_mode < amr_bitrates_size[idx]); /* Check octet-align */ for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) { if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_FMTP_OCTET_ALIGN) == 0) { octet_align = (pj_uint8_t) (pj_strtoul(&attr->setting.dec_fmtp.param[i].val)); break; } } /* Check mode-set */ for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) { const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8}; if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_FMTP_MODE_SET) == 0) { const char *p; pj_size_t l; pj_int8_t diff = 99; /* Encoding mode is chosen based on local default mode setting: * - if local default mode is included in the mode-set, use it * - otherwise, find the closest mode to local default mode; * if there are two closest modes, prefer to use the higher * one, e.g: local default mode is 4, the mode-set param * contains '2,3,5,6', then 5 will be chosen. */ p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val); l = pj_strlen(&attr->setting.enc_fmtp.param[i].val); while (l--) { if (*p>='0' && (unsigned)*p<=('0'+amr_bitrates_size[idx]-1)) { pj_int8_t tmp = *p - '0' - enc_mode; if (PJ_ABS(diff) > PJ_ABS(tmp) || (PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff)) { diff = tmp; if (diff == 0) break; } } ++p; } PJ_ASSERT_RETURN(diff != 99, PJMEDIA_CODEC_EFAILED); enc_mode = enc_mode + diff; break; } } amr_data->clock_rate = attr->info.clock_rate; amr_data->vad_enabled = (attr->setting.vad != 0); amr_data->plc_enabled = (attr->setting.plc != 0); amr_data->enc_mode = enc_mode; if (idx == IDX_AMR_NB) { #ifdef USE_AMRNB amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled); #endif } else { #ifdef USE_AMRWB amr_data->encoder = E_IF_init(); #endif } if (amr_data->encoder == NULL) { TRACE_((THIS_FILE, "Encoder initialization failed")); amr_codec_close(codec); return PJMEDIA_CODEC_EFAILED; } setting = &amr_data->enc_setting; pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting)); setting->amr_nb = (idx == IDX_AMR_NB? 1: 0); setting->reorder = 0; setting->octet_aligned = octet_align; setting->cmr = 15; if (idx == IDX_AMR_NB) { #ifdef USE_AMRNB amr_data->decoder = Decoder_Interface_init(); #endif } else { #ifdef USE_AMRWB amr_data->decoder = D_IF_init(); #endif } if (amr_data->decoder == NULL) { TRACE_((THIS_FILE, "Decoder initialization failed")); amr_codec_close(codec); return PJMEDIA_CODEC_EFAILED; } setting = &amr_data->dec_setting; pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting)); setting->amr_nb = (idx == IDX_AMR_NB? 1: 0); setting->reorder = 0; setting->octet_aligned = octet_align; TRACE_((THIS_FILE, "AMR codec allocated: clockrate=%d vad=%d, plc=%d," " bitrate=%d", amr_data->clock_rate, amr_data->vad_enabled, amr_data->plc_enabled, amr_bitrates[idx][amr_data->enc_mode])); return PJ_SUCCESS; }
/* Public function to parse multipart message bodies into its parts */ PJ_DEF(pjsip_msg_body*) pjsip_multipart_parse(pj_pool_t *pool, char *buf, pj_size_t len, const pjsip_media_type *ctype, unsigned options) { pj_str_t boundary, delim; char *curptr, *endptr; const pjsip_param *ctype_param; const pj_str_t STR_BOUNDARY = { "boundary", 8 }; pjsip_msg_body *body = NULL; PJ_ASSERT_RETURN(pool && buf && len && ctype && !options, NULL); TRACE_((THIS_FILE, "Started parsing multipart body")); /* Get the boundary value in the ctype */ boundary.ptr = NULL; boundary.slen = 0; ctype_param = pjsip_param_find(&ctype->param, &STR_BOUNDARY); if (ctype_param) { boundary = ctype_param->value; if (boundary.slen>2 && *boundary.ptr=='"') { /* Remove quote */ boundary.ptr++; boundary.slen -= 2; } TRACE_((THIS_FILE, "Boundary is specified: '%.*s'", (int)boundary.slen, boundary.ptr)); } if (!boundary.slen) { /* Boundary not found or not specified. Try to be clever, get * the boundary from the body. */ char *p=buf, *end=buf+len; PJ_LOG(4,(THIS_FILE, "Warning: boundary parameter not found or " "not specified when parsing multipart body")); /* Find the first "--". This "--" must be right after a CRLF, unless * it really appears at the start of the buffer. */ for (;;) { while (p!=end && *p!='-') ++p; if (p!=end && *(p+1)=='-' && ((p>buf && *(p-1)=='\n') || (p==buf))) { p+=2; break; } else { ++p; } } if (p==end) { /* Unable to determine boundary. Maybe this is not a multipart * message? */ PJ_LOG(4,(THIS_FILE, "Error: multipart boundary not specified and" " unable to calculate from the body")); return NULL; } boundary.ptr = p; while (p!=end && !pj_isspace(*p)) ++p; boundary.slen = p - boundary.ptr; TRACE_((THIS_FILE, "Boundary is calculated: '%.*s'", (int)boundary.slen, boundary.ptr)); } /* Build the delimiter: * delimiter = "--" boundary */ delim.slen = boundary.slen+2; delim.ptr = (char*)pj_pool_alloc(pool, (int)delim.slen); delim.ptr[0] = '-'; delim.ptr[1] = '-'; pj_memcpy(delim.ptr+2, boundary.ptr, boundary.slen); /* Start parsing the body, skip until the first delimiter. */ curptr = buf; endptr = buf + len; { pj_str_t body; body.ptr = buf; body.slen = len; curptr = pj_strstr(&body, &delim); if (!curptr) return NULL; } body = pjsip_multipart_create(pool, ctype, &boundary); for (;;) { char *start_body, *end_body; pjsip_multipart_part *part; /* Eat the boundary */ curptr += delim.slen; if (*curptr=='-' && curptr<endptr-1 && *(curptr+1)=='-') { /* Found the closing delimiter */ curptr += 2; break; } /* Optional whitespace after delimiter */ while (curptr!=endptr && IS_SPACE(*curptr)) ++curptr; /* Mandatory CRLF */ if (*curptr=='\r') ++curptr; if (*curptr!='\n') { /* Expecting a newline here */ return NULL; } ++curptr; /* We now in the start of the body */ start_body = curptr; /* Find the next delimiter */ { pj_str_t subbody; subbody.ptr = curptr; subbody.slen = endptr - curptr; curptr = pj_strstr(&subbody, &delim); if (!curptr) { /* We're really expecting end delimiter to be found. */ return NULL; } } end_body = curptr; /* The newline preceeding the delimiter is conceptually part of * the delimiter, so trim it from the body. */ if (*(end_body-1) == '\n') --end_body; if (*(end_body-1) == '\r') --end_body; /* Now that we have determined the part's boundary, parse it * to get the header and body part of the part. */ part = parse_multipart_part(pool, start_body, end_body - start_body, ctype); if (part) { pjsip_multipart_add_part(pool, body, part); } } return body; }
NTSTATUS NTAPI SerialDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION Stack; ULONG IoControlCode; PSERIAL_DEVICE_EXTENSION DeviceExtension; ULONG LengthIn, LengthOut; ULONG_PTR Information = 0; PVOID BufferIn, BufferOut; PUCHAR ComPortBase; NTSTATUS Status; TRACE_(SERIAL, "IRP_MJ_DEVICE_CONTROL dispatch\n"); Stack = IoGetCurrentIrpStackLocation(Irp); LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength; LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength; DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ComPortBase = ULongToPtr(DeviceExtension->BaseAddress); IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode; SerialGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut); /* FIXME: need to probe buffers */ /* FIXME: see http://www.osronline.com/ddkx/serial/serref_61bm.htm */ switch (IoControlCode) { case IOCTL_SERIAL_CLEAR_STATS: { TRACE_(SERIAL, "IOCTL_SERIAL_CLEAR_STATS\n"); KeSynchronizeExecution( DeviceExtension->Interrupt, (PKSYNCHRONIZE_ROUTINE)SerialClearPerfStats, DeviceExtension); Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_CLR_DTR: { TRACE_(SERIAL, "IOCTL_SERIAL_CLR_DTR\n"); /* FIXME: If the handshake flow control of the device is configured to * automatically use DTR, return STATUS_INVALID_PARAMETER */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR &= ~SR_MCR_DTR; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } break; } case IOCTL_SERIAL_CLR_RTS: { TRACE_(SERIAL, "IOCTL_SERIAL_CLR_RTS\n"); /* FIXME: If the handshake flow control of the device is configured to * automatically use RTS, return STATUS_INVALID_PARAMETER */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR &= ~SR_MCR_RTS; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } break; } case IOCTL_SERIAL_CONFIG_SIZE: { /* Obsolete on Microsoft Windows 2000+ */ PULONG pConfigSize; TRACE_(SERIAL, "IOCTL_SERIAL_CONFIG_SIZE\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pConfigSize = (PULONG)BufferOut; *pConfigSize = 0; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_BAUD_RATE: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_BAUD_RATE\n"); if (LengthOut < sizeof(SERIAL_BAUD_RATE)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { ((PSERIAL_BAUD_RATE)BufferOut)->BaudRate = DeviceExtension->BaudRate; Information = sizeof(SERIAL_BAUD_RATE); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_CHARS: { /* FIXME */ PSERIAL_CHARS pSerialChars; ERR_(SERIAL, "IOCTL_SERIAL_GET_CHARS not implemented.\n"); if (LengthOut < sizeof(SERIAL_CHARS)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pSerialChars = (PSERIAL_CHARS)BufferOut; pSerialChars->EofChar = 0; pSerialChars->ErrorChar = 0; pSerialChars->BreakChar = 0; pSerialChars->EventChar = 0; pSerialChars->XonChar = 0; pSerialChars->XoffChar = 0; Information = sizeof(SERIAL_CHARS); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_COMMSTATUS: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_COMMSTATUS\n"); if (LengthOut < sizeof(SERIAL_STATUS)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = SerialGetCommStatus((PSERIAL_STATUS)BufferOut, DeviceExtension); Information = sizeof(SERIAL_STATUS); } break; } case IOCTL_SERIAL_GET_DTRRTS: { PULONG pDtrRts; TRACE_(SERIAL, "IOCTL_SERIAL_GET_DTRRTS\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pDtrRts = (PULONG)BufferOut; *pDtrRts = 0; if (DeviceExtension->MCR & SR_MCR_DTR) *pDtrRts |= SERIAL_DTR_STATE; if (DeviceExtension->MCR & SR_MCR_RTS) *pDtrRts |= SERIAL_RTS_STATE; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_HANDFLOW: { /* FIXME */ PSERIAL_HANDFLOW pSerialHandflow; ERR_(SERIAL, "IOCTL_SERIAL_GET_HANDFLOW not implemented.\n"); if (LengthOut < sizeof(SERIAL_HANDFLOW)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pSerialHandflow = (PSERIAL_HANDFLOW)BufferOut; pSerialHandflow->ControlHandShake = 0; pSerialHandflow->FlowReplace = 0; pSerialHandflow->XonLimit = 0; pSerialHandflow->XoffLimit = 0; Information = sizeof(SERIAL_HANDFLOW); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_LINE_CONTROL: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_LINE_CONTROL\n"); if (LengthOut < sizeof(SERIAL_LINE_CONTROL)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { *((PSERIAL_LINE_CONTROL)BufferOut) = DeviceExtension->SerialLineControl; Information = sizeof(SERIAL_LINE_CONTROL); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_MODEM_CONTROL: { PULONG pMCR; TRACE_(SERIAL, "IOCTL_SERIAL_GET_MODEM_CONTROL\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pMCR = (PULONG)BufferOut; *pMCR = DeviceExtension->MCR; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_MODEMSTATUS: { PULONG pMSR; TRACE_(SERIAL, "IOCTL_SERIAL_GET_MODEMSTATUS\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pMSR = (PULONG)BufferOut; *pMSR = DeviceExtension->MSR; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_PROPERTIES: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_PROPERTIES\n"); if (LengthOut < sizeof(SERIAL_COMMPROP)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = SerialGetCommProp((PSERIAL_COMMPROP)BufferOut, DeviceExtension); Information = sizeof(SERIAL_COMMPROP); } break; } case IOCTL_SERIAL_GET_STATS: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_STATS\n"); if (LengthOut < sizeof(SERIALPERF_STATS)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { KeSynchronizeExecution(DeviceExtension->Interrupt, (PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp); Information = sizeof(SERIALPERF_STATS); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_TIMEOUTS: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_TIMEOUTS\n"); if (LengthOut != sizeof(SERIAL_TIMEOUTS) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { *(PSERIAL_TIMEOUTS)BufferOut = DeviceExtension->SerialTimeOuts; Information = sizeof(SERIAL_TIMEOUTS); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_WAIT_MASK: { PULONG pWaitMask; TRACE_(SERIAL, "IOCTL_SERIAL_GET_WAIT_MASK\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pWaitMask = (PULONG)BufferOut; *pWaitMask = DeviceExtension->WaitMask; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_IMMEDIATE_CHAR: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_IMMEDIATE_CHAR not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_LSRMST_INSERT: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_LSRMST_INSERT not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_PURGE: { KIRQL Irql; TRACE_(SERIAL, "IOCTL_SERIAL_PURGE\n"); /* FIXME: SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT * should stop current request */ if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { ULONG PurgeMask = *(PULONG)BufferIn; Status = STATUS_SUCCESS; /* FIXME: use SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT flags */ if (PurgeMask & SERIAL_PURGE_RXCLEAR) { KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql); DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0; if (DeviceExtension->UartType >= Uart16550A) { /* Clear also Uart FIFO */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_RCVR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql); } if (PurgeMask & SERIAL_PURGE_TXCLEAR) { KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql); DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0; if (DeviceExtension->UartType >= Uart16550A) { /* Clear also Uart FIFO */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_XMIT); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql); } } break; } case IOCTL_SERIAL_RESET_DEVICE: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_RESET_DEVICE not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_BAUD_RATE: { PULONG pNewBaudRate; TRACE_(SERIAL, "IOCTL_SERIAL_SET_BAUD_RATE\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { pNewBaudRate = (PULONG)BufferIn; Status = SerialSetBaudRate(DeviceExtension, *pNewBaudRate); } break; } case IOCTL_SERIAL_SET_BREAK_OFF: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_BREAK_OFF not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_BREAK_ON: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_BREAK_ON not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_CHARS: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_CHARS not implemented.\n"); Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_DTR: { /* FIXME: If the handshake flow control of the device is configured to * automatically use DTR, return STATUS_INVALID_PARAMETER */ TRACE_(SERIAL, "IOCTL_SERIAL_SET_DTR\n"); if (!(DeviceExtension->MCR & SR_MCR_DTR)) { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR |= SR_MCR_DTR; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } else Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_FIFO_CONTROL: { TRACE_(SERIAL, "IOCTL_SERIAL_SET_FIFO_CONTROL\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff)); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } break; } case IOCTL_SERIAL_SET_HANDFLOW: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_HANDFLOW not implemented.\n"); Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_LINE_CONTROL: { TRACE_(SERIAL, "IOCTL_SERIAL_SET_LINE_CONTROL\n"); if (LengthIn < sizeof(SERIAL_LINE_CONTROL)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else Status = SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)BufferIn); break; } case IOCTL_SERIAL_SET_MODEM_CONTROL: { PULONG pMCR; TRACE_(SERIAL, "IOCTL_SERIAL_SET_MODEM_CONTROL\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { pMCR = (PULONG)BufferIn; DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff); WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } break; } case IOCTL_SERIAL_SET_QUEUE_SIZE: { if (LengthIn < sizeof(SERIAL_QUEUE_SIZE )) return STATUS_BUFFER_TOO_SMALL; else if (BufferIn == NULL) return STATUS_INVALID_PARAMETER; else { KIRQL Irql; PSERIAL_QUEUE_SIZE NewQueueSize = (PSERIAL_QUEUE_SIZE)BufferIn; Status = STATUS_SUCCESS; if (NewQueueSize->InSize > DeviceExtension->InputBuffer.Length) { KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql); Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, NewQueueSize->InSize); KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql); } if (NT_SUCCESS(Status) && NewQueueSize->OutSize > DeviceExtension->OutputBuffer.Length) { KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql); Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, NewQueueSize->OutSize); KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql); } } break; } case IOCTL_SERIAL_SET_RTS: { /* FIXME: If the handshake flow control of the device is configured to * automatically use DTR, return STATUS_INVALID_PARAMETER */ TRACE_(SERIAL, "IOCTL_SERIAL_SET_RTS\n"); if (!(DeviceExtension->MCR & SR_MCR_RTS)) { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR |= SR_MCR_RTS; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } else Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_TIMEOUTS: { TRACE_(SERIAL, "IOCTL_SERIAL_SET_TIMEOUTS\n"); if (LengthIn != sizeof(SERIAL_TIMEOUTS) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { DeviceExtension->SerialTimeOuts = *(PSERIAL_TIMEOUTS)BufferIn; Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_SET_WAIT_MASK: { PULONG pWaitMask = (PULONG)BufferIn; TRACE_(SERIAL, "IOCTL_SERIAL_SET_WAIT_MASK\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else if (DeviceExtension->WaitOnMaskIrp) /* FIXME: Race condition ; field may be currently in modification */ { WARN_(SERIAL, "An IRP is already currently processed\n"); Status = STATUS_INVALID_PARAMETER; } else { DeviceExtension->WaitMask = *pWaitMask; Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_SET_XOFF: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_XOFF not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_XON: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_XON not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_WAIT_ON_MASK: { PIRP WaitingIrp; TRACE_(SERIAL, "IOCTL_SERIAL_WAIT_ON_MASK\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { IoMarkIrpPending(Irp); WaitingIrp = InterlockedCompareExchangePointer( &DeviceExtension->WaitOnMaskIrp, Irp, NULL); /* Check if an Irp is already pending */ if (WaitingIrp != NULL) { /* Unable to have a 2nd pending IRP for this IOCTL */ WARN_(SERIAL, "Unable to pend a second IRP for IOCTL_SERIAL_WAIT_ON_MASK\n"); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return STATUS_PENDING; } break; } case IOCTL_SERIAL_XOFF_COUNTER: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_XOFF_COUNTER not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } default: { /* Pass Irp to lower driver */ TRACE_(SERIAL, "Unknown IOCTL code 0x%x\n", Stack->Parameters.DeviceIoControl.IoControlCode); IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DeviceExtension->LowerDevice, Irp); } } Irp->IoStatus.Status = Status; if (Status == STATUS_PENDING) { IoMarkIrpPending(Irp); } else { Irp->IoStatus.Information = Information; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return Status; }
static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) { struct wined3d_surface *back_buffer = swapchain->back_buffers[0]; const struct wined3d_fb_state *fb = &swapchain->device->fb; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; RECT src_rect, dst_rect; BOOL render_to_fbo; context = context_acquire(swapchain->device, back_buffer); if (!context->valid) { context_release(context); WARN("Invalid context, skipping present.\n"); return; } gl_info = context->gl_info; /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */ if (swapchain->device->bCursorVisible && swapchain->device->cursorTexture && !swapchain->device->hardwareCursor) { struct wined3d_surface cursor; RECT destRect = { swapchain->device->xScreenSpace - swapchain->device->xHotSpot, swapchain->device->yScreenSpace - swapchain->device->yHotSpot, swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot, swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot, }; TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor); /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by * the application because we are only supposed to copy the information out. Using a fake surface * allows us to use the Blitting engine and avoid copying the whole texture -> render target blitting code. */ memset(&cursor, 0, sizeof(cursor)); cursor.resource.ref = 1; cursor.resource.device = swapchain->device; cursor.resource.pool = WINED3D_POOL_SCRATCH; cursor.resource.format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM); cursor.resource.type = WINED3D_RTYPE_SURFACE; cursor.texture_name = swapchain->device->cursorTexture; cursor.texture_target = GL_TEXTURE_2D; cursor.texture_level = 0; cursor.resource.width = swapchain->device->cursorWidth; cursor.resource.height = swapchain->device->cursorHeight; /* The cursor must have pow2 sizes */ cursor.pow2Width = cursor.resource.width; cursor.pow2Height = cursor.resource.height; /* The surface is in the texture */ cursor.flags |= SFLAG_INTEXTURE; /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0, * which is exactly what we want :-) */ if (swapchain->desc.windowed) MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2); wined3d_surface_blt(back_buffer, &destRect, &cursor, NULL, WINEDDBLT_KEYSRC, NULL, WINED3D_TEXF_POINT); } if (swapchain->device->logo_surface) { struct wined3d_surface *src_surface = swapchain->device->logo_surface; RECT rect = {0, 0, src_surface->resource.width, src_surface->resource.height}; /* Blit the logo into the upper left corner of the drawable. */ wined3d_surface_blt(back_buffer, &rect, src_surface, &rect, WINEDDBLT_KEYSRC, NULL, WINED3D_TEXF_POINT); } TRACE("Presenting HDC %p.\n", context->hdc); render_to_fbo = swapchain->render_to_fbo; if (src_rect_in) { src_rect = *src_rect_in; if (!render_to_fbo && (src_rect.left || src_rect.top || src_rect.right != swapchain->desc.backbuffer_width || src_rect.bottom != swapchain->desc.backbuffer_height)) { render_to_fbo = TRUE; } } else { src_rect.left = 0; src_rect.top = 0; src_rect.right = swapchain->desc.backbuffer_width; src_rect.bottom = swapchain->desc.backbuffer_height; } if (dst_rect_in) dst_rect = *dst_rect_in; else GetClientRect(swapchain->win_handle, &dst_rect); if (!render_to_fbo && (dst_rect.left || dst_rect.top || dst_rect.right != swapchain->desc.backbuffer_width || dst_rect.bottom != swapchain->desc.backbuffer_height)) render_to_fbo = TRUE; /* Rendering to a window of different size, presenting partial rectangles, * or rendering to a different window needs help from FBO_blit or a textured * draw. Render the swapchain to a FBO in the future. * * Note that FBO_blit from the backbuffer to the frontbuffer cannot solve * all these issues - this fails if the window is smaller than the backbuffer. */ if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { surface_load_location(back_buffer, SFLAG_INTEXTURE, NULL); surface_modify_location(back_buffer, SFLAG_INDRAWABLE, FALSE); swapchain->render_to_fbo = TRUE; swapchain_update_draw_bindings(swapchain); } else { surface_load_location(back_buffer, back_buffer->draw_binding, NULL); } if (swapchain->render_to_fbo) { /* This codepath should only be hit with the COPY swapeffect. Otherwise a backbuffer- * window size mismatch is impossible(fullscreen) and src and dst rectangles are * not allowed(they need the COPY swapeffect) * * The DISCARD swap effect is ok as well since any backbuffer content is allowed after * the swap. */ if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) FIXME("Render-to-fbo with WINED3D_SWAP_EFFECT_FLIP\n"); swapchain_blit(swapchain, context, &src_rect, &dst_rect); } if (swapchain->num_contexts > 1) glFinish(); SwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */ TRACE("SwapBuffers called, Starting new frame\n"); /* FPS support */ if (TRACE_ON(fps)) { DWORD time = GetTickCount(); ++swapchain->frames; /* every 1.5 seconds */ if (time - swapchain->prev_time > 1500) { TRACE_(fps)("%p @ approx %.2ffps\n", swapchain, 1000.0 * swapchain->frames / (time - swapchain->prev_time)); swapchain->prev_time = time; swapchain->frames = 0; } } /* This is disabled, but the code left in for debug purposes. * * Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip, * we can clear it with some ugly color to make bad drawing visible and ease debugging. * The Debug runtime does the same on Windows. However, a few games do not redraw the * screen properly, like Max Payne 2, which leaves a few pixels undefined. * * Tests show that the content of the back buffer after a discard flip is indeed not * reliable, so no game can depend on the exact content. However, it resembles the * old contents in some way, for example by showing fragments at other locations. In * general, the color theme is still intact. So Max payne, which draws rather dark scenes * gets a dark background image. If we clear it with a bright ugly color, the game's * bug shows up much more than it does on Windows, and the players see single pixels * with wrong colors. * (The Max Payne bug has been confirmed on Windows with the debug runtime) */ if (FALSE && swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_DISCARD) { static const struct wined3d_color cyan = {0.0f, 1.0f, 1.0f, 1.0f}; TRACE("Clearing the color buffer with cyan color\n"); wined3d_device_clear(swapchain->device, 0, NULL, WINED3DCLEAR_TARGET, &cyan, 1.0f, 0); } if (!swapchain->render_to_fbo && ((swapchain->front_buffer->flags & SFLAG_INSYSMEM) || (back_buffer->flags & SFLAG_INSYSMEM))) { /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying * Doesn't work with render_to_fbo because we're not flipping */ struct wined3d_surface *front = swapchain->front_buffer; if (front->resource.size == back_buffer->resource.size) { DWORD fbflags; flip_surface(front, back_buffer); /* Tell the front buffer surface that is has been modified. However, * the other locations were preserved during that, so keep the flags. * This serves to update the emulated overlay, if any. */ fbflags = front->flags; surface_modify_location(front, SFLAG_INDRAWABLE, TRUE); front->flags = fbflags; } else { surface_modify_location(front, SFLAG_INDRAWABLE, TRUE); surface_modify_location(back_buffer, SFLAG_INDRAWABLE, TRUE); } } else { surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE); /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM * and INTEXTURE copies can keep their old content if they have any defined content. * If the swapeffect is COPY, the content remains the same. If it is FLIP however, * the texture / sysmem copy needs to be reloaded from the drawable */ if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) surface_modify_location(back_buffer, back_buffer->draw_binding, TRUE); } if (fb->depth_stencil) { if (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || fb->depth_stencil->flags & SFLAG_DISCARD) { surface_modify_ds_location(fb->depth_stencil, SFLAG_DISCARDED, fb->depth_stencil->resource.width, fb->depth_stencil->resource.height); if (fb->depth_stencil == swapchain->device->onscreen_depth_stencil) { wined3d_surface_decref(swapchain->device->onscreen_depth_stencil); swapchain->device->onscreen_depth_stencil = NULL; } } } context_release(context); }
/* The very task entry. */ static void kthread_launcher(void *arg) { TRACE_((THIS_FILE, "...launching thread!...")); kernel_thread(&thread_proc, arg, 0); }
static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) { struct wined3d_surface *front, *back; front = swapchain->front_buffer; back = swapchain->back_buffers[0]; /* Flip the DC. */ { HDC tmp; tmp = front->hDC; front->hDC = back->hDC; back->hDC = tmp; } /* Flip the DIBsection. */ { HBITMAP tmp; tmp = front->dib.DIBsection; front->dib.DIBsection = back->dib.DIBsection; back->dib.DIBsection = tmp; } /* Flip the surface data. */ { void *tmp; tmp = front->dib.bitmap_data; front->dib.bitmap_data = back->dib.bitmap_data; back->dib.bitmap_data = tmp; tmp = front->resource.allocatedMemory; front->resource.allocatedMemory = back->resource.allocatedMemory; back->resource.allocatedMemory = tmp; if (front->resource.heapMemory) ERR("GDI Surface %p has heap memory allocated.\n", front); if (back->resource.heapMemory) ERR("GDI Surface %p has heap memory allocated.\n", back); } /* FPS support */ if (TRACE_ON(fps)) { static LONG prev_time, frames; DWORD time = GetTickCount(); ++frames; /* every 1.5 seconds */ if (time - prev_time > 1500) { TRACE_(fps)("@ approx %.2ffps\n", 1000.0 * frames / (time - prev_time)); prev_time = time; frames = 0; } } x11_copy_to_screen(swapchain, NULL); }
static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) { struct wined3d_surface *back_buffer = surface_from_resource( wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)); const struct wined3d_fb_state *fb = &swapchain->device->fb; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; struct wined3d_surface *front; RECT src_rect, dst_rect; BOOL render_to_fbo; context = context_acquire(swapchain->device, back_buffer); if (!context->valid) { context_release(context); WARN("Invalid context, skipping present.\n"); return; } gl_info = context->gl_info; if (swapchain->device->logo_texture) { struct wined3d_surface *src_surface = surface_from_resource( wined3d_texture_get_sub_resource(swapchain->device->logo_texture, 0)); RECT rect = {0, 0, src_surface->resource.width, src_surface->resource.height}; /* Blit the logo into the upper left corner of the drawable. */ wined3d_surface_blt(back_buffer, &rect, src_surface, &rect, WINEDDBLT_ALPHATEST, NULL, WINED3D_TEXF_POINT); } if (swapchain->device->bCursorVisible && swapchain->device->cursor_texture && !swapchain->device->hardwareCursor) { struct wined3d_surface *cursor = surface_from_resource( wined3d_texture_get_sub_resource(swapchain->device->cursor_texture, 0)); RECT destRect = { swapchain->device->xScreenSpace - swapchain->device->xHotSpot, swapchain->device->yScreenSpace - swapchain->device->yHotSpot, swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot, swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot, }; TRACE("Rendering the software cursor.\n"); if (swapchain->desc.windowed) MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2); wined3d_surface_blt(back_buffer, &destRect, cursor, NULL, WINEDDBLT_ALPHATEST, NULL, WINED3D_TEXF_POINT); } TRACE("Presenting HDC %p.\n", context->hdc); render_to_fbo = swapchain->render_to_fbo; if (src_rect_in) { src_rect = *src_rect_in; if (!render_to_fbo && (src_rect.left || src_rect.top || src_rect.right != swapchain->desc.backbuffer_width || src_rect.bottom != swapchain->desc.backbuffer_height)) { render_to_fbo = TRUE; } } else { src_rect.left = 0; src_rect.top = 0; src_rect.right = swapchain->desc.backbuffer_width; src_rect.bottom = swapchain->desc.backbuffer_height; } if (dst_rect_in) dst_rect = *dst_rect_in; else GetClientRect(swapchain->win_handle, &dst_rect); if (!render_to_fbo && (dst_rect.left || dst_rect.top || dst_rect.right != swapchain->desc.backbuffer_width || dst_rect.bottom != swapchain->desc.backbuffer_height)) render_to_fbo = TRUE; /* Rendering to a window of different size, presenting partial rectangles, * or rendering to a different window needs help from FBO_blit or a textured * draw. Render the swapchain to a FBO in the future. * * Note that FBO_blit from the backbuffer to the frontbuffer cannot solve * all these issues - this fails if the window is smaller than the backbuffer. */ if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { surface_load_location(back_buffer, WINED3D_LOCATION_TEXTURE_RGB); surface_invalidate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); swapchain->render_to_fbo = TRUE; swapchain_update_draw_bindings(swapchain); } else { surface_load_location(back_buffer, back_buffer->container->resource.draw_binding); } if (swapchain->render_to_fbo) { static unsigned int once; if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP && !once++) FIXME("WINED3D_SWAP_EFFECT_FLIP not implemented.\n"); swapchain_blit(swapchain, context, &src_rect, &dst_rect); } if (swapchain->num_contexts > 1) gl_info->gl_ops.gl.p_glFinish(); /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */ gl_info->gl_ops.wgl.p_wglSwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */ TRACE("SwapBuffers called, Starting new frame\n"); /* FPS support */ if (TRACE_ON(fps)) { DWORD time = GetTickCount(); ++swapchain->frames; /* every 1.5 seconds */ if (time - swapchain->prev_time > 1500) { TRACE_(fps)("%p @ approx %.2ffps\n", swapchain, 1000.0 * swapchain->frames / (time - swapchain->prev_time)); swapchain->prev_time = time; swapchain->frames = 0; } } front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); if (!swapchain->render_to_fbo && ((front->locations & WINED3D_LOCATION_SYSMEM) || (back_buffer->locations & WINED3D_LOCATION_SYSMEM))) { /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying * Doesn't work with render_to_fbo because we're not flipping */ if (front->resource.size == back_buffer->resource.size) { flip_surface(front, back_buffer); /* Tell the front buffer surface that is has been modified. However, * the other locations were preserved during that, so keep the flags. * This serves to update the emulated overlay, if any. */ surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); } else { surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); surface_validate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); surface_invalidate_location(back_buffer, ~WINED3D_LOCATION_DRAWABLE); } } else { surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM * and INTEXTURE copies can keep their old content if they have any defined content. * If the swapeffect is COPY, the content remains the same. If it is FLIP however, * the texture / sysmem copy needs to be reloaded from the drawable */ if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) { surface_validate_location(back_buffer, back_buffer->container->resource.draw_binding); surface_invalidate_location(back_buffer, ~back_buffer->container->resource.draw_binding); } } if (fb->depth_stencil) { struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(fb->depth_stencil); if (ds && (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || ds->flags & SFLAG_DISCARD)) { surface_modify_ds_location(ds, WINED3D_LOCATION_DISCARDED, fb->depth_stencil->width, fb->depth_stencil->height); if (ds == swapchain->device->onscreen_depth_stencil) { wined3d_surface_decref(swapchain->device->onscreen_depth_stencil); swapchain->device->onscreen_depth_stencil = NULL; } } } context_release(context); }
/* Resolve the IP address of local machine */ PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr) { unsigned i, count, cand_cnt; enum { CAND_CNT = 8, /* Weighting to be applied to found addresses */ WEIGHT_HOSTNAME = 1, /* hostname IP is not always valid! */ WEIGHT_DEF_ROUTE = 2, WEIGHT_INTERFACE = 1, WEIGHT_LOOPBACK = -5, WEIGHT_LINK_LOCAL = -4, WEIGHT_DISABLED = -50, MIN_WEIGHT = WEIGHT_DISABLED+1 /* minimum weight to use */ }; /* candidates: */ pj_sockaddr cand_addr[CAND_CNT]; int cand_weight[CAND_CNT]; int selected_cand; char strip[PJ_INET6_ADDRSTRLEN+10]; /* Special IPv4 addresses. */ struct spec_ipv4_t { pj_uint32_t addr; pj_uint32_t mask; int weight; } spec_ipv4[] = { /* 127.0.0.0/8, loopback addr will be used if there is no other * addresses. */ { 0x7f000000, 0xFF000000, WEIGHT_LOOPBACK }, /* 0.0.0.0/8, special IP that doesn't seem to be practically useful */ { 0x00000000, 0xFF000000, WEIGHT_DISABLED }, /* 169.254.0.0/16, a zeroconf/link-local address, which has higher * priority than loopback and will be used if there is no other * valid addresses. */ { 0xa9fe0000, 0xFFFF0000, WEIGHT_LINK_LOCAL } }; /* Special IPv6 addresses */ struct spec_ipv6_t { pj_uint8_t addr[16]; pj_uint8_t mask[16]; int weight; } spec_ipv6[] = { /* Loopback address, ::1/128 */ { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, WEIGHT_LOOPBACK }, /* Link local, fe80::/10 */ { {0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0xff,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, WEIGHT_LINK_LOCAL }, /* Disabled, ::/128 */ { {0x0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, WEIGHT_DISABLED } }; pj_addrinfo ai; pj_status_t status; /* May not be used if TRACE_ is disabled */ PJ_UNUSED_ARG(strip); #ifdef _MSC_VER /* Get rid of "uninitialized he variable" with MS compilers */ pj_bzero(&ai, sizeof(ai)); #endif cand_cnt = 0; pj_bzero(cand_addr, sizeof(cand_addr)); pj_bzero(cand_weight, sizeof(cand_weight)); for (i=0; i<PJ_ARRAY_SIZE(cand_addr); ++i) { cand_addr[i].addr.sa_family = (pj_uint16_t)af; PJ_SOCKADDR_RESET_LEN(&cand_addr[i]); } addr->addr.sa_family = (pj_uint16_t)af; PJ_SOCKADDR_RESET_LEN(addr); #if defined(PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION) && \ PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION != 0 /* Get hostname's IP address */ count = 1; status = pj_getaddrinfo(af, pj_gethostname(), &count, &ai); if (status == PJ_SUCCESS) { pj_assert(ai.ai_addr.addr.sa_family == (pj_uint16_t)af); pj_sockaddr_copy_addr(&cand_addr[cand_cnt], &ai.ai_addr); pj_sockaddr_set_port(&cand_addr[cand_cnt], 0); cand_weight[cand_cnt] += WEIGHT_HOSTNAME; ++cand_cnt; TRACE_((THIS_FILE, "hostname IP is %s", pj_sockaddr_print(&ai.ai_addr, strip, sizeof(strip), 0))); } #else PJ_UNUSED_ARG(ai); PJ_UNUSED_ARG(count); #endif /* Get default interface (interface for default route) */ if (cand_cnt < PJ_ARRAY_SIZE(cand_addr)) { status = pj_getdefaultipinterface(af, addr); if (status == PJ_SUCCESS) { TRACE_((THIS_FILE, "default IP is %s", pj_sockaddr_print(addr, strip, sizeof(strip), 0))); pj_sockaddr_set_port(addr, 0); for (i=0; i<cand_cnt; ++i) { if (pj_sockaddr_cmp(&cand_addr[i], addr)==0) break; } cand_weight[i] += WEIGHT_DEF_ROUTE; if (i >= cand_cnt) { pj_sockaddr_copy_addr(&cand_addr[i], addr); ++cand_cnt; } } } /* Enumerate IP interfaces */ if (cand_cnt < PJ_ARRAY_SIZE(cand_addr)) { unsigned start_if = cand_cnt; unsigned count = PJ_ARRAY_SIZE(cand_addr) - start_if; status = pj_enum_ip_interface(af, &count, &cand_addr[start_if]); if (status == PJ_SUCCESS && count) { /* Clear the port number */ for (i=0; i<count; ++i) pj_sockaddr_set_port(&cand_addr[start_if+i], 0); /* For each candidate that we found so far (that is the hostname * address and default interface address, check if they're found * in the interface list. If found, add the weight, and if not, * decrease the weight. */ for (i=0; i<cand_cnt; ++i) { unsigned j; for (j=0; j<count; ++j) { if (pj_sockaddr_cmp(&cand_addr[i], &cand_addr[start_if+j])==0) break; } if (j == count) { /* Not found */ cand_weight[i] -= WEIGHT_INTERFACE; } else { cand_weight[i] += WEIGHT_INTERFACE; } } /* Add remaining interface to candidate list. */ for (i=0; i<count; ++i) { unsigned j; for (j=0; j<cand_cnt; ++j) { if (pj_sockaddr_cmp(&cand_addr[start_if+i], &cand_addr[j])==0) break; } if (j == cand_cnt) { pj_sockaddr_copy_addr(&cand_addr[cand_cnt], &cand_addr[start_if+i]); cand_weight[cand_cnt] += WEIGHT_INTERFACE; ++cand_cnt; } } } } /* Apply weight adjustment for special IPv4/IPv6 addresses * See http://trac.pjsip.org/repos/ticket/1046 */ if (af == PJ_AF_INET) { for (i=0; i<cand_cnt; ++i) { unsigned j; for (j=0; j<PJ_ARRAY_SIZE(spec_ipv4); ++j) { pj_uint32_t a = pj_ntohl(cand_addr[i].ipv4.sin_addr.s_addr); pj_uint32_t pa = spec_ipv4[j].addr; pj_uint32_t pm = spec_ipv4[j].mask; if ((a & pm) == pa) { cand_weight[i] += spec_ipv4[j].weight; break; } } } } else if (af == PJ_AF_INET6) { for (i=0; i<PJ_ARRAY_SIZE(spec_ipv6); ++i) { unsigned j; for (j=0; j<cand_cnt; ++j) { pj_uint8_t *a = cand_addr[j].ipv6.sin6_addr.s6_addr; pj_uint8_t am[16]; pj_uint8_t *pa = spec_ipv6[i].addr; pj_uint8_t *pm = spec_ipv6[i].mask; unsigned k; for (k=0; k<16; ++k) { am[k] = (pj_uint8_t)((a[k] & pm[k]) & 0xFF); } if (pj_memcmp(am, pa, 16)==0) { cand_weight[j] += spec_ipv6[i].weight; } } } } else { return PJ_EAFNOTSUP; } /* Enumerate candidates to get the best IP address to choose */ selected_cand = -1; for (i=0; i<cand_cnt; ++i) { TRACE_((THIS_FILE, "Checking candidate IP %s, weight=%d", pj_sockaddr_print(&cand_addr[i], strip, sizeof(strip), 0), cand_weight[i])); if (cand_weight[i] < MIN_WEIGHT) { continue; } if (selected_cand == -1) selected_cand = i; else if (cand_weight[i] > cand_weight[selected_cand]) selected_cand = i; } /* If else fails, returns loopback interface as the last resort */ if (selected_cand == -1) { if (af==PJ_AF_INET) { addr->ipv4.sin_addr.s_addr = pj_htonl (0x7f000001); } else { pj_in6_addr *s6_addr; s6_addr = (pj_in6_addr*) pj_sockaddr_get_addr(addr); pj_bzero(s6_addr, sizeof(pj_in6_addr)); s6_addr->s6_addr[15] = 1; } TRACE_((THIS_FILE, "Loopback IP %s returned", pj_sockaddr_print(addr, strip, sizeof(strip), 0))); } else { pj_sockaddr_copy_addr(addr, &cand_addr[selected_cand]); TRACE_((THIS_FILE, "Candidate %s selected", pj_sockaddr_print(addr, strip, sizeof(strip), 0))); } return PJ_SUCCESS; }
static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm, LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif) { /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/ HRESULT hr = E_FAIL; DMUS_PRIVATE_CHUNK Chunk; DWORD ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ LPDMUS_PRIVATE_STYLE_PARTREF_ITEM pNewItem = NULL; if (pChunk->fccID != DMUS_FOURCC_PARTREF_LIST) { ERR_(dmfile)(": %s chunk should be a PARTREF list\n", debugstr_fourcc (pChunk->fccID)); return E_FAIL; } ListSize[0] = pChunk->dwSize - sizeof(FOURCC); ListCount[0] = 0; do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case DMUS_FOURCC_PARTREF_CHUNK: { TRACE_(dmfile)(": PartRef chunk\n"); pNewItem = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_PARTREF_ITEM)); if (!pNewItem) { ERR(": no more memory\n"); return E_OUTOFMEMORY; } hr = IStream_Read (pStm, &pNewItem->part_ref, sizeof(DMUS_IO_PARTREF), NULL); /*TRACE_(dmfile)(" - sizeof %lu\n", sizeof(DMUS_IO_PARTREF));*/ list_add_tail (&pNewMotif->Items, &pNewItem->entry); DM_STRUCT_INIT(&pNewItem->desc); break; } case FOURCC_LIST: { IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[1] = Chunk.dwSize - sizeof(FOURCC); ListCount[1] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); if (!pNewItem) { ERR(": pNewItem not yet allocated, chunk order bad?\n"); return E_OUTOFMEMORY; } hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &pNewItem->desc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { switch (Chunk.fccID) { default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } } TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]); } while (ListCount[1] < ListSize[1]); break; } default: { TRACE_(dmfile)(": unknown chunk (skipping)\n"); liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); return S_OK; }
/* Test with recursive mutex. */ static int recursive_mutex_test(pj_pool_t *pool) { pj_status_t rc; pj_mutex_t *mutex; PJ_LOG(3,("", "...testing recursive mutex")); /* Create mutex. */ TRACE_(("", "....create mutex")); rc = pj_mutex_create( pool, "", PJ_MUTEX_RECURSE, &mutex); if (rc != PJ_SUCCESS) { app_perror("...error: pj_mutex_create", rc); return -10; } /* Normal lock/unlock cycle. */ TRACE_(("", "....lock mutex")); rc = pj_mutex_lock(mutex); if (rc != PJ_SUCCESS) { app_perror("...error: pj_mutex_lock", rc); return -20; } TRACE_(("", "....unlock mutex")); rc = pj_mutex_unlock(mutex); if (rc != PJ_SUCCESS) { app_perror("...error: pj_mutex_unlock", rc); return -30; } /* Lock again. */ TRACE_(("", "....lock mutex")); rc = pj_mutex_lock(mutex); if (rc != PJ_SUCCESS) return -40; /* Try-lock should NOT fail. . */ TRACE_(("", "....trylock mutex")); rc = pj_mutex_trylock(mutex); if (rc != PJ_SUCCESS) { app_perror("...error: recursive mutex is not recursive!", rc); return -40; } /* Locking again should not fail. */ TRACE_(("", "....lock mutex")); rc = pj_mutex_lock(mutex); if (rc != PJ_SUCCESS) { app_perror("...error: recursive mutex is not recursive!", rc); return -45; } /* Unlock several times and done. */ TRACE_(("", "....unlock mutex 3x")); rc = pj_mutex_unlock(mutex); if (rc != PJ_SUCCESS) return -50; rc = pj_mutex_unlock(mutex); if (rc != PJ_SUCCESS) return -51; rc = pj_mutex_unlock(mutex); if (rc != PJ_SUCCESS) return -52; TRACE_(("", "....destroy mutex")); rc = pj_mutex_destroy(mutex); if (rc != PJ_SUCCESS) return -60; TRACE_(("", "....done")); return PJ_SUCCESS; }
static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) { ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface); HRESULT hr = E_FAIL; DMUS_PRIVATE_CHUNK Chunk; DWORD ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ DMUS_OBJECTDESC desc; IDirectMusicBand* pBand = NULL; LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif = NULL; DM_STRUCT_INIT(&desc); if (pChunk->fccID != DMUS_FOURCC_PATTERN_LIST) { ERR_(dmfile)(": %s chunk should be a PATTERN list\n", debugstr_fourcc (pChunk->fccID)); return E_FAIL; } ListSize[0] = pChunk->dwSize - sizeof(FOURCC); ListCount[0] = 0; do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case DMUS_FOURCC_PATTERN_CHUNK: { TRACE_(dmfile)(": Pattern chunk\n"); /** alloc new motif entry */ pNewMotif = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_MOTIF)); if (NULL == pNewMotif) { ERR(": no more memory\n"); return E_OUTOFMEMORY; } list_add_tail (&This->Motifs, &pNewMotif->entry); IStream_Read (pStm, &pNewMotif->pattern, Chunk.dwSize, NULL); /** TODO trace pattern */ /** reset all data, as a new pattern begin */ DM_STRUCT_INIT(&pNewMotif->desc); list_init (&pNewMotif->Items); break; } case DMUS_FOURCC_RHYTHM_CHUNK: { TRACE_(dmfile)(": Rhythm chunk\n"); IStream_Read (pStm, &pNewMotif->dwRhythm, sizeof(DWORD), NULL); TRACE_(dmfile)(" - dwRhythm: %u\n", pNewMotif->dwRhythm); /** TODO understand why some Chunks have size > 4 */ liMove.QuadPart = Chunk.dwSize - sizeof(DWORD); IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case DMUS_FOURCC_MOTIFSETTINGS_CHUNK: { TRACE_(dmfile)(": MotifSettings chunk (skipping for now)\n"); IStream_Read (pStm, &pNewMotif->settings, Chunk.dwSize, NULL); /** TODO trace settings */ break; } case FOURCC_RIFF: { /** * should be embedded Bands into pattern */ IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[1] = Chunk.dwSize - sizeof(FOURCC); ListCount[1] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_BAND_FORM: { LPSTREAM pClonedStream = NULL; TRACE_(dmfile)(": BAND RIFF\n"); IStream_Clone (pStm, &pClonedStream); liMove.QuadPart = 0; liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD)); IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL); hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand); if (FAILED(hr)) { ERR(": could not load track\n"); return hr; } IStream_Release (pClonedStream); pNewMotif->pBand = pBand; IDirectMusicBand_AddRef(pBand); IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release it as it's inserted */ /** now safe move the cursor */ liMove.QuadPart = ListSize[1]; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = ListSize[1]; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } case FOURCC_LIST: { IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[1] = Chunk.dwSize - sizeof(FOURCC); ListCount[1] = 0; switch (Chunk.fccID) { case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &pNewMotif->desc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { switch (Chunk.fccID) { default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } } TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]); } while (ListCount[1] < ListSize[1]); break; } case DMUS_FOURCC_PARTREF_LIST: { TRACE_(dmfile)(": PartRef list\n"); hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (iface, &Chunk, pStm, pNewMotif); if (FAILED(hr)) return hr; break; } default: { TRACE_(dmfile)(": unknown (skipping)\n"); liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); return S_OK; }
NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo) /* * FUNCTION: Reset the drive's change flag (as reflected in the DIR) * ARGUMENTS: * DriveInfo: the drive to reset * RETURNS: * STATUS_SUCCESS if the changeline is cleared * STATUS_NO_MEDIA_IN_DEVICE if the changeline cannot be cleared * STATUS_IO_DEVICE_ERROR if the controller cannot be communicated with * NOTES: * - Change reset procedure: recalibrate, seek 1, seek 0 * - If the line is still set after that, there's clearly no disk in the * drive, so we return STATUS_NO_MEDIA_IN_DEVICE * - PAGED_CODE because we wait */ { BOOLEAN DiskChanged; PAGED_CODE(); ASSERT(DriveInfo); TRACE_(FLOPPY, "ResetChangeFlag called\n"); /* Try to recalibrate. We don't care if it works. */ Recalibrate(DriveInfo); /* clear spurious interrupts in prep for seeks */ KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent); /* must re-start the drive because Recalibrate() stops it */ StartMotor(DriveInfo); /* Seek to 1 */ if(HwSeek(DriveInfo, 1) != STATUS_SUCCESS) { WARN_(FLOPPY, "ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n"); StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } WaitForControllerInterrupt(DriveInfo->ControllerInfo); if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS) { WARN_(FLOPPY, "ResetChangeFlag(): HwSenseInterruptStatus failed; bailing out\n"); StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } /* Seek back to 0 */ if(HwSeek(DriveInfo, 0) != STATUS_SUCCESS) { WARN_(FLOPPY, "ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n"); StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } WaitForControllerInterrupt(DriveInfo->ControllerInfo); if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS) { WARN_(FLOPPY, "ResetChangeFlag(): HwSenseInterruptStatus #2 failed; bailing\n"); StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } /* Check the change bit */ if(HwDiskChanged(DriveInfo, &DiskChanged) != STATUS_SUCCESS) { WARN_(FLOPPY, "ResetChangeFlag(): HwDiskChanged failed; returning STATUS_IO_DEVICE_ERROR\n"); StopMotor(DriveInfo->ControllerInfo); return STATUS_IO_DEVICE_ERROR; } StopMotor(DriveInfo->ControllerInfo); /* if the change flag is still set, there's probably no media in the drive. */ if(DiskChanged) return STATUS_NO_MEDIA_IN_DEVICE; /* else we're done! */ return STATUS_SUCCESS; }